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/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"
31 using namespace clang
;
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
)
47 setTemplateArguments(ConvertedArgs
);
48 setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction
));
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");
59 ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty
,
60 unsigned NumTemplateArgs
)
61 : Expr(ConceptSpecializationExprClass
, Empty
),
62 NumTemplateArgs(NumTemplateArgs
) {}
64 void ConceptSpecializationExpr::setTemplateArguments(
65 ArrayRef
<TemplateArgument
> Converted
) {
66 assert(Converted
.size() == NumTemplateArgs
);
67 std::uninitialized_copy(Converted
.begin(), Converted
.end(),
68 getTrailingObjects
<TemplateArgument
>());
71 ConceptSpecializationExpr
*
72 ConceptSpecializationExpr::Create(const ASTContext
&C
,
73 NestedNameSpecifierLoc NNS
,
74 SourceLocation TemplateKWLoc
,
75 DeclarationNameInfo ConceptNameInfo
,
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
);
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
,
98 NumTemplateArgs(ConvertedArgs
.size()),
99 Satisfaction(Satisfaction
100 ? ASTConstraintSatisfaction::Create(C
, *Satisfaction
)
102 setTemplateArguments(ConvertedArgs
);
103 ExprDependence D
= ExprDependence::None
;
105 D
|= ExprDependence::Value
;
107 D
|= ExprDependence::Instantiation
;
108 if (ContainsUnexpandedParameterPack
)
109 D
|= ExprDependence::UnexpandedPack
;
113 ConceptSpecializationExpr
*
114 ConceptSpecializationExpr::Create(const ASTContext
&C
,
115 ConceptDecl
*NamedConcept
,
116 ArrayRef
<TemplateArgument
> ConvertedArgs
,
117 const ConstraintSatisfaction
*Satisfaction
,
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
);
127 ConceptSpecializationExpr
*
128 ConceptSpecializationExpr::Create(ASTContext
&C
, EmptyShell Empty
,
129 unsigned NumTemplateArgs
) {
130 void *Buffer
= C
.Allocate(totalSizeToAlloc
<TemplateArgument
>(
132 return new (Buffer
) ConceptSpecializationExpr(Empty
, NumTemplateArgs
);
135 const TypeConstraint
*
136 concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {
137 assert(isTypeConstraint());
139 TypeConstraintInfo
.getPointer().get
<TemplateParameterList
*>();
140 return cast
<TemplateTypeParmDecl
>(TPL
->getParam(0))
141 ->getTypeConstraint();
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();
161 RequiresExprBits
.IsSatisfied
= true;
162 for (concepts::Requirement
*R
: Requirements
) {
163 Dependent
|= R
->isDependent();
164 ContainsUnexpandedParameterPack
|= R
->containsUnexpandedParameterPack();
166 RequiresExprBits
.IsSatisfied
= R
->isSatisfied();
167 if (!RequiresExprBits
.IsSatisfied
)
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
184 setDependence(getDependence() | ExprDependence::ValueInstantiation
);
187 RequiresExpr::RequiresExpr(ASTContext
&C
, EmptyShell Empty
,
188 unsigned NumLocalParameters
,
189 unsigned NumRequirements
)
190 : Expr(RequiresExprClass
, Empty
), NumLocalParameters(NumLocalParameters
),
191 NumRequirements(NumRequirements
) { }
194 RequiresExpr::Create(ASTContext
&C
, SourceLocation RequiresKWLoc
,
195 RequiresExprBodyDecl
*Body
,
196 ArrayRef
<ParmVarDecl
*> LocalParameters
,
197 ArrayRef
<concepts::Requirement
*> Requirements
,
198 SourceLocation RBraceLoc
) {
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
);
208 RequiresExpr::Create(ASTContext
&C
, EmptyShell Empty
,
209 unsigned NumLocalParameters
, unsigned NumRequirements
) {
211 C
.Allocate(totalSizeToAlloc
<ParmVarDecl
*, concepts::Requirement
*>(
212 NumLocalParameters
, NumRequirements
),
213 alignof(RequiresExpr
));
214 return new (Mem
) RequiresExpr(C
, Empty
, NumLocalParameters
, NumRequirements
);