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/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"
27 #include <algorithm>
28 #include <string>
29 #include <utility>
30
31 using namespace clang;
32
ConceptSpecializationExpr(const ASTContext & C,NestedNameSpecifierLoc NNS,SourceLocation TemplateKWLoc,DeclarationNameInfo ConceptNameInfo,NamedDecl * FoundDecl,ConceptDecl * NamedConcept,const ASTTemplateArgumentListInfo * ArgsAsWritten,ImplicitConceptSpecializationDecl * SpecDecl,const ConstraintSatisfaction * Satisfaction)33 ConceptSpecializationExpr::ConceptSpecializationExpr(
34 const ASTContext &C, NestedNameSpecifierLoc NNS,
35 SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
36 NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
37 const ASTTemplateArgumentListInfo *ArgsAsWritten,
38 ImplicitConceptSpecializationDecl *SpecDecl,
39 const ConstraintSatisfaction *Satisfaction)
40 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
41 ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl,
42 NamedConcept, ArgsAsWritten),
43 SpecDecl(SpecDecl),
44 Satisfaction(Satisfaction
45 ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
46 : nullptr) {
47 setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction));
48
49 // Currently guaranteed by the fact concepts can only be at namespace-scope.
50 assert(!NestedNameSpec ||
51 (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() &&
52 !NestedNameSpec.getNestedNameSpecifier()
53 ->containsUnexpandedParameterPack()));
54 assert((!isValueDependent() || isInstantiationDependent()) &&
55 "should not be value-dependent");
56 }
57
ConceptSpecializationExpr(EmptyShell Empty)58 ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty)
59 : Expr(ConceptSpecializationExprClass, Empty) {}
60
Create(const ASTContext & C,ConceptDecl * NamedConcept,ImplicitConceptSpecializationDecl * SpecDecl,const ConstraintSatisfaction * Satisfaction,bool Dependent,bool ContainsUnexpandedParameterPack)61 ConceptSpecializationExpr *ConceptSpecializationExpr::Create(
62 const ASTContext &C, ConceptDecl *NamedConcept,
63 ImplicitConceptSpecializationDecl *SpecDecl,
64 const ConstraintSatisfaction *Satisfaction, bool Dependent,
65 bool ContainsUnexpandedParameterPack) {
66 return Create(C, NamedConcept, /*ArgsAsWritten*/ nullptr, SpecDecl, Satisfaction,
67 Dependent, ContainsUnexpandedParameterPack);
68 }
69
Create(const ASTContext & C,NestedNameSpecifierLoc NNS,SourceLocation TemplateKWLoc,DeclarationNameInfo ConceptNameInfo,NamedDecl * FoundDecl,ConceptDecl * NamedConcept,const ASTTemplateArgumentListInfo * ArgsAsWritten,ImplicitConceptSpecializationDecl * SpecDecl,const ConstraintSatisfaction * Satisfaction)70 ConceptSpecializationExpr *ConceptSpecializationExpr::Create(
71 const ASTContext &C, NestedNameSpecifierLoc NNS,
72 SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
73 NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
74 const ASTTemplateArgumentListInfo *ArgsAsWritten,
75 ImplicitConceptSpecializationDecl *SpecDecl,
76 const ConstraintSatisfaction *Satisfaction) {
77 return new (C) ConceptSpecializationExpr(
78 C, NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept,
79 ArgsAsWritten, SpecDecl, Satisfaction);
80 }
81
ConceptSpecializationExpr(const ASTContext & C,ConceptDecl * NamedConcept,const ASTTemplateArgumentListInfo * ArgsAsWritten,ImplicitConceptSpecializationDecl * SpecDecl,const ConstraintSatisfaction * Satisfaction,bool Dependent,bool ContainsUnexpandedParameterPack)82 ConceptSpecializationExpr::ConceptSpecializationExpr(
83 const ASTContext &C, ConceptDecl *NamedConcept,
84 const ASTTemplateArgumentListInfo *ArgsAsWritten,
85 ImplicitConceptSpecializationDecl *SpecDecl,
86 const ConstraintSatisfaction *Satisfaction, bool Dependent,
87 bool ContainsUnexpandedParameterPack)
88 : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
89 ConceptReference(NestedNameSpecifierLoc(), SourceLocation(),
90 DeclarationNameInfo(), NamedConcept, NamedConcept,
91 ArgsAsWritten),
92 SpecDecl(SpecDecl),
93 Satisfaction(Satisfaction
94 ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
95 : nullptr) {
96 ExprDependence D = ExprDependence::None;
97 if (!Satisfaction)
98 D |= ExprDependence::Value;
99 if (Dependent)
100 D |= ExprDependence::Instantiation;
101 if (ContainsUnexpandedParameterPack)
102 D |= ExprDependence::UnexpandedPack;
103 setDependence(D);
104 }
105
Create(const ASTContext & C,ConceptDecl * NamedConcept,const ASTTemplateArgumentListInfo * ArgsAsWritten,ImplicitConceptSpecializationDecl * SpecDecl,const ConstraintSatisfaction * Satisfaction,bool Dependent,bool ContainsUnexpandedParameterPack)106 ConceptSpecializationExpr *ConceptSpecializationExpr::Create(
107 const ASTContext &C, ConceptDecl *NamedConcept,
108 const ASTTemplateArgumentListInfo *ArgsAsWritten,
109 ImplicitConceptSpecializationDecl *SpecDecl,
110 const ConstraintSatisfaction *Satisfaction, bool Dependent,
111 bool ContainsUnexpandedParameterPack) {
112 return new (C) ConceptSpecializationExpr(C, NamedConcept, ArgsAsWritten,
113 SpecDecl, Satisfaction, Dependent,
114 ContainsUnexpandedParameterPack);
115 }
116
117 const TypeConstraint *
getTypeConstraint() const118 concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {
119 assert(isTypeConstraint());
120 auto TPL =
121 TypeConstraintInfo.getPointer().get<TemplateParameterList *>();
122 return cast<TemplateTypeParmDecl>(TPL->getParam(0))
123 ->getTypeConstraint();
124 }
125
RequiresExpr(ASTContext & C,SourceLocation RequiresKWLoc,RequiresExprBodyDecl * Body,ArrayRef<ParmVarDecl * > LocalParameters,ArrayRef<concepts::Requirement * > Requirements,SourceLocation RBraceLoc)126 RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
127 RequiresExprBodyDecl *Body,
128 ArrayRef<ParmVarDecl *> LocalParameters,
129 ArrayRef<concepts::Requirement *> Requirements,
130 SourceLocation RBraceLoc)
131 : Expr(RequiresExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
132 NumLocalParameters(LocalParameters.size()),
133 NumRequirements(Requirements.size()), Body(Body), RBraceLoc(RBraceLoc) {
134 RequiresExprBits.IsSatisfied = false;
135 RequiresExprBits.RequiresKWLoc = RequiresKWLoc;
136 bool Dependent = false;
137 bool ContainsUnexpandedParameterPack = false;
138 for (ParmVarDecl *P : LocalParameters) {
139 Dependent |= P->getType()->isInstantiationDependentType();
140 ContainsUnexpandedParameterPack |=
141 P->getType()->containsUnexpandedParameterPack();
142 }
143 RequiresExprBits.IsSatisfied = true;
144 for (concepts::Requirement *R : Requirements) {
145 Dependent |= R->isDependent();
146 ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();
147 if (!Dependent) {
148 RequiresExprBits.IsSatisfied = R->isSatisfied();
149 if (!RequiresExprBits.IsSatisfied)
150 break;
151 }
152 }
153 std::copy(LocalParameters.begin(), LocalParameters.end(),
154 getTrailingObjects<ParmVarDecl *>());
155 std::copy(Requirements.begin(), Requirements.end(),
156 getTrailingObjects<concepts::Requirement *>());
157 RequiresExprBits.IsSatisfied |= Dependent;
158 // FIXME: move the computing dependency logic to ComputeDependence.h
159 if (ContainsUnexpandedParameterPack)
160 setDependence(getDependence() | ExprDependence::UnexpandedPack);
161 // FIXME: this is incorrect for cases where we have a non-dependent
162 // requirement, but its parameters are instantiation-dependent. RequiresExpr
163 // should be instantiation-dependent if it has instantiation-dependent
164 // parameters.
165 if (Dependent)
166 setDependence(getDependence() | ExprDependence::ValueInstantiation);
167 }
168
RequiresExpr(ASTContext & C,EmptyShell Empty,unsigned NumLocalParameters,unsigned NumRequirements)169 RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
170 unsigned NumLocalParameters,
171 unsigned NumRequirements)
172 : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
173 NumRequirements(NumRequirements) { }
174
175 RequiresExpr *
Create(ASTContext & C,SourceLocation RequiresKWLoc,RequiresExprBodyDecl * Body,ArrayRef<ParmVarDecl * > LocalParameters,ArrayRef<concepts::Requirement * > Requirements,SourceLocation RBraceLoc)176 RequiresExpr::Create(ASTContext &C, SourceLocation RequiresKWLoc,
177 RequiresExprBodyDecl *Body,
178 ArrayRef<ParmVarDecl *> LocalParameters,
179 ArrayRef<concepts::Requirement *> Requirements,
180 SourceLocation RBraceLoc) {
181 void *Mem =
182 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
183 LocalParameters.size(), Requirements.size()),
184 alignof(RequiresExpr));
185 return new (Mem) RequiresExpr(C, RequiresKWLoc, Body, LocalParameters,
186 Requirements, RBraceLoc);
187 }
188
189 RequiresExpr *
Create(ASTContext & C,EmptyShell Empty,unsigned NumLocalParameters,unsigned NumRequirements)190 RequiresExpr::Create(ASTContext &C, EmptyShell Empty,
191 unsigned NumLocalParameters, unsigned NumRequirements) {
192 void *Mem =
193 C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
194 NumLocalParameters, NumRequirements),
195 alignof(RequiresExpr));
196 return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);
197 }
198