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 #include "llvm/Support/TrailingObjects.h" 27 #include <algorithm> 28 #include <string> 29 #include <utility> 30 31 using namespace clang; 32 33 ConceptSpecializationExpr::ConceptSpecializationExpr( 34 const ASTContext &C, NestedNameSpecifierLoc NNS, 35 SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, 36 NamedDecl *FoundDecl, ConceptDecl *NamedConcept, 37 const ASTTemplateArgumentListInfo *ArgsAsWritten, 38 ArrayRef<TemplateArgument> ConvertedArgs, 39 const ConstraintSatisfaction *Satisfaction) 40 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary), 41 ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl, 42 NamedConcept, ArgsAsWritten), 43 NumTemplateArgs(ConvertedArgs.size()), 44 Satisfaction(Satisfaction 45 ? ASTConstraintSatisfaction::Create(C, *Satisfaction) 46 : nullptr) { 47 setTemplateArguments(ConvertedArgs); 48 setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction)); 49 50 // Currently guaranteed by the fact concepts can only be at namespace-scope. 51 assert(!NestedNameSpec || 52 (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() && 53 !NestedNameSpec.getNestedNameSpecifier() 54 ->containsUnexpandedParameterPack())); 55 assert((!isValueDependent() || isInstantiationDependent()) && 56 "should not be value-dependent"); 57 } 58 59 ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty, 60 unsigned NumTemplateArgs) 61 : Expr(ConceptSpecializationExprClass, Empty), 62 NumTemplateArgs(NumTemplateArgs) {} 63 64 void ConceptSpecializationExpr::setTemplateArguments( 65 ArrayRef<TemplateArgument> Converted) { 66 assert(Converted.size() == NumTemplateArgs); 67 std::uninitialized_copy(Converted.begin(), Converted.end(), 68 getTrailingObjects<TemplateArgument>()); 69 } 70 71 ConceptSpecializationExpr * 72 ConceptSpecializationExpr::Create(const ASTContext &C, 73 NestedNameSpecifierLoc NNS, 74 SourceLocation TemplateKWLoc, 75 DeclarationNameInfo ConceptNameInfo, 76 NamedDecl *FoundDecl, 77 ConceptDecl *NamedConcept, 78 const ASTTemplateArgumentListInfo *ArgsAsWritten, 79 ArrayRef<TemplateArgument> ConvertedArgs, 80 const ConstraintSatisfaction *Satisfaction) { 81 void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>( 82 ConvertedArgs.size())); 83 return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc, 84 ConceptNameInfo, FoundDecl, 85 NamedConcept, ArgsAsWritten, 86 ConvertedArgs, Satisfaction); 87 } 88 89 ConceptSpecializationExpr::ConceptSpecializationExpr( 90 const ASTContext &C, ConceptDecl *NamedConcept, 91 ArrayRef<TemplateArgument> ConvertedArgs, 92 const ConstraintSatisfaction *Satisfaction, bool Dependent, 93 bool ContainsUnexpandedParameterPack) 94 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary), 95 ConceptReference(NestedNameSpecifierLoc(), SourceLocation(), 96 DeclarationNameInfo(), NamedConcept, NamedConcept, 97 nullptr), 98 NumTemplateArgs(ConvertedArgs.size()), 99 Satisfaction(Satisfaction 100 ? ASTConstraintSatisfaction::Create(C, *Satisfaction) 101 : nullptr) { 102 setTemplateArguments(ConvertedArgs); 103 ExprDependence D = ExprDependence::None; 104 if (!Satisfaction) 105 D |= ExprDependence::Value; 106 if (Dependent) 107 D |= ExprDependence::Instantiation; 108 if (ContainsUnexpandedParameterPack) 109 D |= ExprDependence::UnexpandedPack; 110 setDependence(D); 111 } 112 113 ConceptSpecializationExpr * 114 ConceptSpecializationExpr::Create(const ASTContext &C, 115 ConceptDecl *NamedConcept, 116 ArrayRef<TemplateArgument> ConvertedArgs, 117 const ConstraintSatisfaction *Satisfaction, 118 bool Dependent, 119 bool ContainsUnexpandedParameterPack) { 120 void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>( 121 ConvertedArgs.size())); 122 return new (Buffer) ConceptSpecializationExpr( 123 C, NamedConcept, ConvertedArgs, Satisfaction, Dependent, 124 ContainsUnexpandedParameterPack); 125 } 126 127 ConceptSpecializationExpr * 128 ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty, 129 unsigned NumTemplateArgs) { 130 void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>( 131 NumTemplateArgs)); 132 return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs); 133 } 134 135 const TypeConstraint * 136 concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const { 137 assert(isTypeConstraint()); 138 auto TPL = 139 TypeConstraintInfo.getPointer().get<TemplateParameterList *>(); 140 return cast<TemplateTypeParmDecl>(TPL->getParam(0)) 141 ->getTypeConstraint(); 142 } 143 144 RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, 145 RequiresExprBodyDecl *Body, 146 ArrayRef<ParmVarDecl *> LocalParameters, 147 ArrayRef<concepts::Requirement *> Requirements, 148 SourceLocation RBraceLoc) 149 : Expr(RequiresExprClass, C.BoolTy, VK_PRValue, OK_Ordinary), 150 NumLocalParameters(LocalParameters.size()), 151 NumRequirements(Requirements.size()), Body(Body), RBraceLoc(RBraceLoc) { 152 RequiresExprBits.IsSatisfied = false; 153 RequiresExprBits.RequiresKWLoc = RequiresKWLoc; 154 bool Dependent = false; 155 bool ContainsUnexpandedParameterPack = false; 156 for (ParmVarDecl *P : LocalParameters) { 157 Dependent |= P->getType()->isInstantiationDependentType(); 158 ContainsUnexpandedParameterPack |= 159 P->getType()->containsUnexpandedParameterPack(); 160 } 161 RequiresExprBits.IsSatisfied = true; 162 for (concepts::Requirement *R : Requirements) { 163 Dependent |= R->isDependent(); 164 ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack(); 165 if (!Dependent) { 166 RequiresExprBits.IsSatisfied = R->isSatisfied(); 167 if (!RequiresExprBits.IsSatisfied) 168 break; 169 } 170 } 171 std::copy(LocalParameters.begin(), LocalParameters.end(), 172 getTrailingObjects<ParmVarDecl *>()); 173 std::copy(Requirements.begin(), Requirements.end(), 174 getTrailingObjects<concepts::Requirement *>()); 175 RequiresExprBits.IsSatisfied |= Dependent; 176 // FIXME: move the computing dependency logic to ComputeDependence.h 177 if (ContainsUnexpandedParameterPack) 178 setDependence(getDependence() | ExprDependence::UnexpandedPack); 179 // FIXME: this is incorrect for cases where we have a non-dependent 180 // requirement, but its parameters are instantiation-dependent. RequiresExpr 181 // should be instantiation-dependent if it has instantiation-dependent 182 // parameters. 183 if (Dependent) 184 setDependence(getDependence() | ExprDependence::ValueInstantiation); 185 } 186 187 RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty, 188 unsigned NumLocalParameters, 189 unsigned NumRequirements) 190 : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters), 191 NumRequirements(NumRequirements) { } 192 193 RequiresExpr * 194 RequiresExpr::Create(ASTContext &C, SourceLocation RequiresKWLoc, 195 RequiresExprBodyDecl *Body, 196 ArrayRef<ParmVarDecl *> LocalParameters, 197 ArrayRef<concepts::Requirement *> Requirements, 198 SourceLocation RBraceLoc) { 199 void *Mem = 200 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>( 201 LocalParameters.size(), Requirements.size()), 202 alignof(RequiresExpr)); 203 return new (Mem) RequiresExpr(C, RequiresKWLoc, Body, LocalParameters, 204 Requirements, RBraceLoc); 205 } 206 207 RequiresExpr * 208 RequiresExpr::Create(ASTContext &C, EmptyShell Empty, 209 unsigned NumLocalParameters, unsigned NumRequirements) { 210 void *Mem = 211 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>( 212 NumLocalParameters, NumRequirements), 213 alignof(RequiresExpr)); 214 return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements); 215 } 216