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
, ConceptReference
*Loc
,
35 ImplicitConceptSpecializationDecl
*SpecDecl
,
36 const ConstraintSatisfaction
*Satisfaction
)
37 : Expr(ConceptSpecializationExprClass
, C
.BoolTy
, VK_PRValue
, OK_Ordinary
),
38 ConceptRef(Loc
), SpecDecl(SpecDecl
),
39 Satisfaction(Satisfaction
40 ? ASTConstraintSatisfaction::Create(C
, *Satisfaction
)
42 setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction
));
44 // Currently guaranteed by the fact concepts can only be at namespace-scope.
45 assert(!Loc
->getNestedNameSpecifierLoc() ||
46 (!Loc
->getNestedNameSpecifierLoc()
47 .getNestedNameSpecifier()
48 ->isInstantiationDependent() &&
49 !Loc
->getNestedNameSpecifierLoc()
50 .getNestedNameSpecifier()
51 ->containsUnexpandedParameterPack()));
52 assert((!isValueDependent() || isInstantiationDependent()) &&
53 "should not be value-dependent");
56 ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty
)
57 : Expr(ConceptSpecializationExprClass
, Empty
) {}
59 ConceptSpecializationExpr
*
60 ConceptSpecializationExpr::Create(const ASTContext
&C
, ConceptReference
*Loc
,
61 ImplicitConceptSpecializationDecl
*SpecDecl
,
62 const ConstraintSatisfaction
*Satisfaction
) {
63 return new (C
) ConceptSpecializationExpr(C
, Loc
, SpecDecl
, Satisfaction
);
66 ConceptSpecializationExpr::ConceptSpecializationExpr(
67 const ASTContext
&C
, ConceptReference
*Loc
,
68 ImplicitConceptSpecializationDecl
*SpecDecl
,
69 const ConstraintSatisfaction
*Satisfaction
, bool Dependent
,
70 bool ContainsUnexpandedParameterPack
)
71 : Expr(ConceptSpecializationExprClass
, C
.BoolTy
, VK_PRValue
, OK_Ordinary
),
72 ConceptRef(Loc
), SpecDecl(SpecDecl
),
73 Satisfaction(Satisfaction
74 ? ASTConstraintSatisfaction::Create(C
, *Satisfaction
)
76 ExprDependence D
= ExprDependence::None
;
78 D
|= ExprDependence::Value
;
80 D
|= ExprDependence::Instantiation
;
81 if (ContainsUnexpandedParameterPack
)
82 D
|= ExprDependence::UnexpandedPack
;
86 ConceptSpecializationExpr
*
87 ConceptSpecializationExpr::Create(const ASTContext
&C
, ConceptReference
*Loc
,
88 ImplicitConceptSpecializationDecl
*SpecDecl
,
89 const ConstraintSatisfaction
*Satisfaction
,
91 bool ContainsUnexpandedParameterPack
) {
93 ConceptSpecializationExpr(C
, Loc
, SpecDecl
, Satisfaction
, Dependent
,
94 ContainsUnexpandedParameterPack
);
97 const TypeConstraint
*
98 concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {
99 assert(isTypeConstraint());
101 TypeConstraintInfo
.getPointer().get
<TemplateParameterList
*>();
102 return cast
<TemplateTypeParmDecl
>(TPL
->getParam(0))
103 ->getTypeConstraint();
106 // Search through the requirements, and see if any have a RecoveryExpr in it,
107 // which means this RequiresExpr ALSO needs to be invalid.
108 static bool RequirementContainsError(concepts::Requirement
*R
) {
109 if (auto *ExprReq
= dyn_cast
<concepts::ExprRequirement
>(R
))
110 return ExprReq
->getExpr() && ExprReq
->getExpr()->containsErrors();
112 if (auto *NestedReq
= dyn_cast
<concepts::NestedRequirement
>(R
))
113 return !NestedReq
->hasInvalidConstraint() &&
114 NestedReq
->getConstraintExpr() &&
115 NestedReq
->getConstraintExpr()->containsErrors();
119 RequiresExpr::RequiresExpr(ASTContext
&C
, SourceLocation RequiresKWLoc
,
120 RequiresExprBodyDecl
*Body
, SourceLocation LParenLoc
,
121 ArrayRef
<ParmVarDecl
*> LocalParameters
,
122 SourceLocation RParenLoc
,
123 ArrayRef
<concepts::Requirement
*> Requirements
,
124 SourceLocation RBraceLoc
)
125 : Expr(RequiresExprClass
, C
.BoolTy
, VK_PRValue
, OK_Ordinary
),
126 NumLocalParameters(LocalParameters
.size()),
127 NumRequirements(Requirements
.size()), Body(Body
), LParenLoc(LParenLoc
),
128 RParenLoc(RParenLoc
), RBraceLoc(RBraceLoc
) {
129 RequiresExprBits
.IsSatisfied
= false;
130 RequiresExprBits
.RequiresKWLoc
= RequiresKWLoc
;
131 bool Dependent
= false;
132 bool ContainsUnexpandedParameterPack
= false;
133 for (ParmVarDecl
*P
: LocalParameters
) {
134 Dependent
|= P
->getType()->isInstantiationDependentType();
135 ContainsUnexpandedParameterPack
|=
136 P
->getType()->containsUnexpandedParameterPack();
138 RequiresExprBits
.IsSatisfied
= true;
139 for (concepts::Requirement
*R
: Requirements
) {
140 Dependent
|= R
->isDependent();
141 ContainsUnexpandedParameterPack
|= R
->containsUnexpandedParameterPack();
143 RequiresExprBits
.IsSatisfied
= R
->isSatisfied();
144 if (!RequiresExprBits
.IsSatisfied
)
148 if (RequirementContainsError(R
))
149 setDependence(getDependence() | ExprDependence::Error
);
151 std::copy(LocalParameters
.begin(), LocalParameters
.end(),
152 getTrailingObjects
<ParmVarDecl
*>());
153 std::copy(Requirements
.begin(), Requirements
.end(),
154 getTrailingObjects
<concepts::Requirement
*>());
155 RequiresExprBits
.IsSatisfied
|= Dependent
;
156 // FIXME: move the computing dependency logic to ComputeDependence.h
157 if (ContainsUnexpandedParameterPack
)
158 setDependence(getDependence() | ExprDependence::UnexpandedPack
);
159 // FIXME: this is incorrect for cases where we have a non-dependent
160 // requirement, but its parameters are instantiation-dependent. RequiresExpr
161 // should be instantiation-dependent if it has instantiation-dependent
164 setDependence(getDependence() | ExprDependence::ValueInstantiation
);
167 RequiresExpr::RequiresExpr(ASTContext
&C
, EmptyShell Empty
,
168 unsigned NumLocalParameters
,
169 unsigned NumRequirements
)
170 : Expr(RequiresExprClass
, Empty
), NumLocalParameters(NumLocalParameters
),
171 NumRequirements(NumRequirements
) { }
173 RequiresExpr
*RequiresExpr::Create(
174 ASTContext
&C
, SourceLocation RequiresKWLoc
, RequiresExprBodyDecl
*Body
,
175 SourceLocation LParenLoc
, ArrayRef
<ParmVarDecl
*> LocalParameters
,
176 SourceLocation RParenLoc
, ArrayRef
<concepts::Requirement
*> Requirements
,
177 SourceLocation RBraceLoc
) {
179 C
.Allocate(totalSizeToAlloc
<ParmVarDecl
*, concepts::Requirement
*>(
180 LocalParameters
.size(), Requirements
.size()),
181 alignof(RequiresExpr
));
183 RequiresExpr(C
, RequiresKWLoc
, Body
, LParenLoc
, LocalParameters
,
184 RParenLoc
, Requirements
, RBraceLoc
);
188 RequiresExpr::Create(ASTContext
&C
, EmptyShell Empty
,
189 unsigned NumLocalParameters
, unsigned NumRequirements
) {
191 C
.Allocate(totalSizeToAlloc
<ParmVarDecl
*, concepts::Requirement
*>(
192 NumLocalParameters
, NumRequirements
),
193 alignof(RequiresExpr
));
194 return new (Mem
) RequiresExpr(C
, Empty
, NumLocalParameters
, NumRequirements
);