1 //===- ExprCXX.cpp - (C++) Expression AST Node Implementation -------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the subclesses of Expr class declared in ExprCXX.h
11 //===----------------------------------------------------------------------===//
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"
29 using namespace clang;
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) :
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)
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");
71 ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty,
72 unsigned NumTemplateArgs)
73 : Expr(ConceptSpecializationExprClass, Empty), ConceptReference(),
74 NumTemplateArgs(NumTemplateArgs) { }
76 void ConceptSpecializationExpr::setTemplateArguments(
77 ArrayRef<TemplateArgument> Converted) {
78 assert(Converted.size() == NumTemplateArgs);
79 std::uninitialized_copy(Converted.begin(), Converted.end(),
80 getTrailingObjects<TemplateArgument>());
83 ConceptSpecializationExpr *
84 ConceptSpecializationExpr::Create(const ASTContext &C,
85 NestedNameSpecifierLoc NNS,
86 SourceLocation TemplateKWLoc,
87 DeclarationNameInfo ConceptNameInfo,
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);
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) :
117 setTemplateArguments(ConvertedArgs);
120 ConceptSpecializationExpr *
121 ConceptSpecializationExpr::Create(const ASTContext &C,
122 ConceptDecl *NamedConcept,
123 ArrayRef<TemplateArgument> ConvertedArgs,
124 const ConstraintSatisfaction *Satisfaction,
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);
134 ConceptSpecializationExpr *
135 ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty,
136 unsigned NumTemplateArgs) {
137 void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
139 return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs);
142 const TypeConstraint *
143 concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {
144 assert(isTypeConstraint());
146 TypeConstraintInfo.getPointer().get<TemplateParameterList *>();
147 return cast<TemplateTypeParmDecl>(TPL->getParam(0))
148 ->getTypeConstraint();
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();
170 RequiresExprBits.IsSatisfied = true;
171 for (concepts::Requirement *R : Requirements) {
172 Dependent |= R->isDependent();
173 ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();
175 RequiresExprBits.IsSatisfied = R->isSatisfied();
176 if (!RequiresExprBits.IsSatisfied)
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);
190 RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
191 unsigned NumLocalParameters,
192 unsigned NumRequirements)
193 : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
194 NumRequirements(NumRequirements) { }
197 RequiresExpr::Create(ASTContext &C, SourceLocation RequiresKWLoc,
198 RequiresExprBodyDecl *Body,
199 ArrayRef<ParmVarDecl *> LocalParameters,
200 ArrayRef<concepts::Requirement *> Requirements,
201 SourceLocation RBraceLoc) {
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);
211 RequiresExpr::Create(ASTContext &C, EmptyShell Empty,
212 unsigned NumLocalParameters, unsigned NumRequirements) {
214 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
215 NumLocalParameters, NumRequirements),
216 alignof(RequiresExpr));
217 return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);