1 //===- ExprCXX.cpp - (C++) Expression AST Node Implementation -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the subclesses of Expr class declared in ExprCXX.h 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/AST/ExprConcepts.h" 14 #include "clang/AST/ASTConcept.h" 15 #include "clang/AST/ASTContext.h" 16 #include "clang/AST/ComputeDependence.h" 17 #include "clang/AST/Decl.h" 18 #include "clang/AST/DeclTemplate.h" 19 #include "clang/AST/DeclarationName.h" 20 #include "clang/AST/DependenceFlags.h" 21 #include "clang/AST/Expr.h" 22 #include "clang/AST/NestedNameSpecifier.h" 23 #include "clang/AST/TemplateBase.h" 24 #include "clang/AST/Type.h" 25 #include "clang/Basic/SourceLocation.h" 26 27 using namespace clang; 28 29 ConceptSpecializationExpr::ConceptSpecializationExpr( 30 const ASTContext &C, ConceptReference *Loc, 31 ImplicitConceptSpecializationDecl *SpecDecl, 32 const ConstraintSatisfaction *Satisfaction) 33 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary), 34 ConceptRef(Loc), SpecDecl(SpecDecl), 35 Satisfaction(Satisfaction 36 ? ASTConstraintSatisfaction::Create(C, *Satisfaction) 37 : nullptr) { 38 setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction)); 39 40 // Currently guaranteed by the fact concepts can only be at namespace-scope. 41 assert(!Loc->getNestedNameSpecifierLoc() || 42 (!Loc->getNestedNameSpecifierLoc() 43 .getNestedNameSpecifier() 44 ->isInstantiationDependent() && 45 !Loc->getNestedNameSpecifierLoc() 46 .getNestedNameSpecifier() 47 ->containsUnexpandedParameterPack())); 48 assert((!isValueDependent() || isInstantiationDependent()) && 49 "should not be value-dependent"); 50 } 51 52 ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty) 53 : Expr(ConceptSpecializationExprClass, Empty) {} 54 55 ConceptSpecializationExpr * 56 ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc, 57 ImplicitConceptSpecializationDecl *SpecDecl, 58 const ConstraintSatisfaction *Satisfaction) { 59 return new (C) ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction); 60 } 61 62 ConceptSpecializationExpr::ConceptSpecializationExpr( 63 const ASTContext &C, ConceptReference *Loc, 64 ImplicitConceptSpecializationDecl *SpecDecl, 65 const ConstraintSatisfaction *Satisfaction, bool Dependent, 66 bool ContainsUnexpandedParameterPack) 67 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary), 68 ConceptRef(Loc), SpecDecl(SpecDecl), 69 Satisfaction(Satisfaction 70 ? ASTConstraintSatisfaction::Create(C, *Satisfaction) 71 : nullptr) { 72 ExprDependence D = ExprDependence::None; 73 if (!Satisfaction) 74 D |= ExprDependence::Value; 75 if (Dependent) 76 D |= ExprDependence::Instantiation; 77 if (ContainsUnexpandedParameterPack) 78 D |= ExprDependence::UnexpandedPack; 79 setDependence(D); 80 } 81 82 ConceptSpecializationExpr * 83 ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc, 84 ImplicitConceptSpecializationDecl *SpecDecl, 85 const ConstraintSatisfaction *Satisfaction, 86 bool Dependent, 87 bool ContainsUnexpandedParameterPack) { 88 return new (C) 89 ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction, Dependent, 90 ContainsUnexpandedParameterPack); 91 } 92 93 const TypeConstraint * 94 concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const { 95 assert(isTypeConstraint()); 96 auto TPL = cast<TemplateParameterList *>(TypeConstraintInfo.getPointer()); 97 return cast<TemplateTypeParmDecl>(TPL->getParam(0)) 98 ->getTypeConstraint(); 99 } 100 101 // Search through the requirements, and see if any have a RecoveryExpr in it, 102 // which means this RequiresExpr ALSO needs to be invalid. 103 static bool RequirementContainsError(concepts::Requirement *R) { 104 if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(R)) 105 return ExprReq->getExpr() && ExprReq->getExpr()->containsErrors(); 106 107 if (auto *NestedReq = dyn_cast<concepts::NestedRequirement>(R)) 108 return !NestedReq->hasInvalidConstraint() && 109 NestedReq->getConstraintExpr() && 110 NestedReq->getConstraintExpr()->containsErrors(); 111 return false; 112 } 113 114 RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, 115 RequiresExprBodyDecl *Body, SourceLocation LParenLoc, 116 ArrayRef<ParmVarDecl *> LocalParameters, 117 SourceLocation RParenLoc, 118 ArrayRef<concepts::Requirement *> Requirements, 119 SourceLocation RBraceLoc) 120 : Expr(RequiresExprClass, C.BoolTy, VK_PRValue, OK_Ordinary), 121 NumLocalParameters(LocalParameters.size()), 122 NumRequirements(Requirements.size()), Body(Body), LParenLoc(LParenLoc), 123 RParenLoc(RParenLoc), RBraceLoc(RBraceLoc) { 124 RequiresExprBits.IsSatisfied = false; 125 RequiresExprBits.RequiresKWLoc = RequiresKWLoc; 126 bool Dependent = false; 127 bool ContainsUnexpandedParameterPack = false; 128 for (ParmVarDecl *P : LocalParameters) { 129 Dependent |= P->getType()->isInstantiationDependentType(); 130 ContainsUnexpandedParameterPack |= 131 P->getType()->containsUnexpandedParameterPack(); 132 } 133 RequiresExprBits.IsSatisfied = true; 134 for (concepts::Requirement *R : Requirements) { 135 Dependent |= R->isDependent(); 136 ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack(); 137 if (!Dependent) { 138 RequiresExprBits.IsSatisfied = R->isSatisfied(); 139 if (!RequiresExprBits.IsSatisfied) 140 break; 141 } 142 143 if (RequirementContainsError(R)) 144 setDependence(getDependence() | ExprDependence::Error); 145 } 146 llvm::copy(LocalParameters, getTrailingObjects<ParmVarDecl *>()); 147 llvm::copy(Requirements, getTrailingObjects<concepts::Requirement *>()); 148 RequiresExprBits.IsSatisfied |= Dependent; 149 // FIXME: move the computing dependency logic to ComputeDependence.h 150 if (ContainsUnexpandedParameterPack) 151 setDependence(getDependence() | ExprDependence::UnexpandedPack); 152 // FIXME: this is incorrect for cases where we have a non-dependent 153 // requirement, but its parameters are instantiation-dependent. RequiresExpr 154 // should be instantiation-dependent if it has instantiation-dependent 155 // parameters. 156 if (Dependent) 157 setDependence(getDependence() | ExprDependence::ValueInstantiation); 158 } 159 160 RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty, 161 unsigned NumLocalParameters, 162 unsigned NumRequirements) 163 : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters), 164 NumRequirements(NumRequirements) { } 165 166 RequiresExpr *RequiresExpr::Create( 167 ASTContext &C, SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body, 168 SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters, 169 SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements, 170 SourceLocation RBraceLoc) { 171 void *Mem = 172 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>( 173 LocalParameters.size(), Requirements.size()), 174 alignof(RequiresExpr)); 175 return new (Mem) 176 RequiresExpr(C, RequiresKWLoc, Body, LParenLoc, LocalParameters, 177 RParenLoc, Requirements, RBraceLoc); 178 } 179 180 RequiresExpr * 181 RequiresExpr::Create(ASTContext &C, EmptyShell Empty, 182 unsigned NumLocalParameters, unsigned NumRequirements) { 183 void *Mem = 184 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>( 185 NumLocalParameters, NumRequirements), 186 alignof(RequiresExpr)); 187 return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements); 188 } 189