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