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 } 50 51 ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty, 52 unsigned NumTemplateArgs) 53 : Expr(ConceptSpecializationExprClass, Empty), ConceptReference(), 54 NumTemplateArgs(NumTemplateArgs) { } 55 56 void ConceptSpecializationExpr::setTemplateArguments( 57 ArrayRef<TemplateArgument> Converted) { 58 assert(Converted.size() == NumTemplateArgs); 59 std::uninitialized_copy(Converted.begin(), Converted.end(), 60 getTrailingObjects<TemplateArgument>()); 61 bool IsInstantiationDependent = false; 62 bool ContainsUnexpandedParameterPack = false; 63 for (const TemplateArgument& Arg : Converted) { 64 if (Arg.isInstantiationDependent()) 65 IsInstantiationDependent = true; 66 if (Arg.containsUnexpandedParameterPack()) 67 ContainsUnexpandedParameterPack = true; 68 if (ContainsUnexpandedParameterPack && IsInstantiationDependent) 69 break; 70 } 71 72 // Currently guaranteed by the fact concepts can only be at namespace-scope. 73 assert(!NestedNameSpec || 74 (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() && 75 !NestedNameSpec.getNestedNameSpecifier() 76 ->containsUnexpandedParameterPack())); 77 setInstantiationDependent(IsInstantiationDependent); 78 setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack); 79 assert((!isValueDependent() || isInstantiationDependent()) && 80 "should not be value-dependent"); 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 * 102 ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty, 103 unsigned NumTemplateArgs) { 104 void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>( 105 NumTemplateArgs)); 106 return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs); 107 } 108 109 const TypeConstraint * 110 concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const { 111 assert(isTypeConstraint()); 112 auto TPL = 113 TypeConstraintInfo.getPointer().get<TemplateParameterList *>(); 114 return cast<TemplateTypeParmDecl>(TPL->getParam(0)) 115 ->getTypeConstraint(); 116 } 117 118 RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, 119 RequiresExprBodyDecl *Body, 120 ArrayRef<ParmVarDecl *> LocalParameters, 121 ArrayRef<concepts::Requirement *> Requirements, 122 SourceLocation RBraceLoc) 123 : Expr(RequiresExprClass, C.BoolTy, VK_RValue, OK_Ordinary, 124 /*TD=*/false, /*VD=*/false, /*ID=*/false, 125 /*ContainsUnexpandedParameterPack=*/false), 126 NumLocalParameters(LocalParameters.size()), 127 NumRequirements(Requirements.size()), Body(Body), RBraceLoc(RBraceLoc) { 128 RequiresExprBits.IsSatisfied = false; 129 RequiresExprBits.RequiresKWLoc = RequiresKWLoc; 130 bool Dependent = false; 131 bool ContainsUnexpandedParameterPack = false; 132 for (ParmVarDecl *P : LocalParameters) { 133 Dependent |= P->getType()->isInstantiationDependentType(); 134 ContainsUnexpandedParameterPack |= 135 P->getType()->containsUnexpandedParameterPack(); 136 } 137 RequiresExprBits.IsSatisfied = true; 138 for (concepts::Requirement *R : Requirements) { 139 Dependent |= R->isDependent(); 140 ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack(); 141 if (!Dependent) { 142 RequiresExprBits.IsSatisfied = R->isSatisfied(); 143 if (!RequiresExprBits.IsSatisfied) 144 break; 145 } 146 } 147 std::copy(LocalParameters.begin(), LocalParameters.end(), 148 getTrailingObjects<ParmVarDecl *>()); 149 std::copy(Requirements.begin(), Requirements.end(), 150 getTrailingObjects<concepts::Requirement *>()); 151 RequiresExprBits.IsSatisfied |= Dependent; 152 setValueDependent(Dependent); 153 setInstantiationDependent(Dependent); 154 setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack); 155 } 156 157 RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty, 158 unsigned NumLocalParameters, 159 unsigned NumRequirements) 160 : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters), 161 NumRequirements(NumRequirements) { } 162 163 RequiresExpr * 164 RequiresExpr::Create(ASTContext &C, SourceLocation RequiresKWLoc, 165 RequiresExprBodyDecl *Body, 166 ArrayRef<ParmVarDecl *> LocalParameters, 167 ArrayRef<concepts::Requirement *> Requirements, 168 SourceLocation RBraceLoc) { 169 void *Mem = 170 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>( 171 LocalParameters.size(), Requirements.size()), 172 alignof(RequiresExpr)); 173 return new (Mem) RequiresExpr(C, RequiresKWLoc, Body, LocalParameters, 174 Requirements, RBraceLoc); 175 } 176 177 RequiresExpr * 178 RequiresExpr::Create(ASTContext &C, EmptyShell Empty, 179 unsigned NumLocalParameters, unsigned NumRequirements) { 180 void *Mem = 181 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>( 182 NumLocalParameters, NumRequirements), 183 alignof(RequiresExpr)); 184 return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements); 185 } 186