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