1*13fbcb42Sjoerg //===- ExprCXX.cpp - (C++) Expression AST Node Implementation -------------===//
2*13fbcb42Sjoerg //
3*13fbcb42Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*13fbcb42Sjoerg // See https://llvm.org/LICENSE.txt for license information.
5*13fbcb42Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*13fbcb42Sjoerg //
7*13fbcb42Sjoerg //===----------------------------------------------------------------------===//
8*13fbcb42Sjoerg //
9*13fbcb42Sjoerg // This file implements the subclesses of Expr class declared in ExprCXX.h
10*13fbcb42Sjoerg //
11*13fbcb42Sjoerg //===----------------------------------------------------------------------===//
12*13fbcb42Sjoerg
13*13fbcb42Sjoerg #include "clang/AST/ExprConcepts.h"
14*13fbcb42Sjoerg #include "clang/AST/ASTConcept.h"
15*13fbcb42Sjoerg #include "clang/AST/ASTContext.h"
16*13fbcb42Sjoerg #include "clang/AST/ComputeDependence.h"
17*13fbcb42Sjoerg #include "clang/AST/Decl.h"
18*13fbcb42Sjoerg #include "clang/AST/DeclTemplate.h"
19*13fbcb42Sjoerg #include "clang/AST/DeclarationName.h"
20*13fbcb42Sjoerg #include "clang/AST/DependenceFlags.h"
21*13fbcb42Sjoerg #include "clang/AST/Expr.h"
22*13fbcb42Sjoerg #include "clang/AST/NestedNameSpecifier.h"
23*13fbcb42Sjoerg #include "clang/AST/TemplateBase.h"
24*13fbcb42Sjoerg #include "clang/AST/Type.h"
25*13fbcb42Sjoerg #include "clang/Basic/SourceLocation.h"
26*13fbcb42Sjoerg #include "llvm/Support/TrailingObjects.h"
27*13fbcb42Sjoerg #include <algorithm>
28*13fbcb42Sjoerg #include <string>
29*13fbcb42Sjoerg #include <utility>
30*13fbcb42Sjoerg
31*13fbcb42Sjoerg using namespace clang;
32*13fbcb42Sjoerg
ConceptSpecializationExpr(const ASTContext & C,NestedNameSpecifierLoc NNS,SourceLocation TemplateKWLoc,DeclarationNameInfo ConceptNameInfo,NamedDecl * FoundDecl,ConceptDecl * NamedConcept,const ASTTemplateArgumentListInfo * ArgsAsWritten,ArrayRef<TemplateArgument> ConvertedArgs,const ConstraintSatisfaction * Satisfaction)33*13fbcb42Sjoerg ConceptSpecializationExpr::ConceptSpecializationExpr(
34*13fbcb42Sjoerg const ASTContext &C, NestedNameSpecifierLoc NNS,
35*13fbcb42Sjoerg SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
36*13fbcb42Sjoerg NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
37*13fbcb42Sjoerg const ASTTemplateArgumentListInfo *ArgsAsWritten,
38*13fbcb42Sjoerg ArrayRef<TemplateArgument> ConvertedArgs,
39*13fbcb42Sjoerg const ConstraintSatisfaction *Satisfaction)
40*13fbcb42Sjoerg : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary),
41*13fbcb42Sjoerg ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl,
42*13fbcb42Sjoerg NamedConcept, ArgsAsWritten),
43*13fbcb42Sjoerg NumTemplateArgs(ConvertedArgs.size()),
44*13fbcb42Sjoerg Satisfaction(Satisfaction
45*13fbcb42Sjoerg ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
46*13fbcb42Sjoerg : nullptr) {
47*13fbcb42Sjoerg setTemplateArguments(ConvertedArgs);
48*13fbcb42Sjoerg setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction));
49*13fbcb42Sjoerg
50*13fbcb42Sjoerg // Currently guaranteed by the fact concepts can only be at namespace-scope.
51*13fbcb42Sjoerg assert(!NestedNameSpec ||
52*13fbcb42Sjoerg (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() &&
53*13fbcb42Sjoerg !NestedNameSpec.getNestedNameSpecifier()
54*13fbcb42Sjoerg ->containsUnexpandedParameterPack()));
55*13fbcb42Sjoerg assert((!isValueDependent() || isInstantiationDependent()) &&
56*13fbcb42Sjoerg "should not be value-dependent");
57*13fbcb42Sjoerg }
58*13fbcb42Sjoerg
ConceptSpecializationExpr(EmptyShell Empty,unsigned NumTemplateArgs)59*13fbcb42Sjoerg ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty,
60*13fbcb42Sjoerg unsigned NumTemplateArgs)
61*13fbcb42Sjoerg : Expr(ConceptSpecializationExprClass, Empty), ConceptReference(),
62*13fbcb42Sjoerg NumTemplateArgs(NumTemplateArgs) { }
63*13fbcb42Sjoerg
setTemplateArguments(ArrayRef<TemplateArgument> Converted)64*13fbcb42Sjoerg void ConceptSpecializationExpr::setTemplateArguments(
65*13fbcb42Sjoerg ArrayRef<TemplateArgument> Converted) {
66*13fbcb42Sjoerg assert(Converted.size() == NumTemplateArgs);
67*13fbcb42Sjoerg std::uninitialized_copy(Converted.begin(), Converted.end(),
68*13fbcb42Sjoerg getTrailingObjects<TemplateArgument>());
69*13fbcb42Sjoerg }
70*13fbcb42Sjoerg
71*13fbcb42Sjoerg ConceptSpecializationExpr *
Create(const ASTContext & C,NestedNameSpecifierLoc NNS,SourceLocation TemplateKWLoc,DeclarationNameInfo ConceptNameInfo,NamedDecl * FoundDecl,ConceptDecl * NamedConcept,const ASTTemplateArgumentListInfo * ArgsAsWritten,ArrayRef<TemplateArgument> ConvertedArgs,const ConstraintSatisfaction * Satisfaction)72*13fbcb42Sjoerg ConceptSpecializationExpr::Create(const ASTContext &C,
73*13fbcb42Sjoerg NestedNameSpecifierLoc NNS,
74*13fbcb42Sjoerg SourceLocation TemplateKWLoc,
75*13fbcb42Sjoerg DeclarationNameInfo ConceptNameInfo,
76*13fbcb42Sjoerg NamedDecl *FoundDecl,
77*13fbcb42Sjoerg ConceptDecl *NamedConcept,
78*13fbcb42Sjoerg const ASTTemplateArgumentListInfo *ArgsAsWritten,
79*13fbcb42Sjoerg ArrayRef<TemplateArgument> ConvertedArgs,
80*13fbcb42Sjoerg const ConstraintSatisfaction *Satisfaction) {
81*13fbcb42Sjoerg void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
82*13fbcb42Sjoerg ConvertedArgs.size()));
83*13fbcb42Sjoerg return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc,
84*13fbcb42Sjoerg ConceptNameInfo, FoundDecl,
85*13fbcb42Sjoerg NamedConcept, ArgsAsWritten,
86*13fbcb42Sjoerg ConvertedArgs, Satisfaction);
87*13fbcb42Sjoerg }
88*13fbcb42Sjoerg
ConceptSpecializationExpr(const ASTContext & C,ConceptDecl * NamedConcept,ArrayRef<TemplateArgument> ConvertedArgs,const ConstraintSatisfaction * Satisfaction,bool Dependent,bool ContainsUnexpandedParameterPack)89*13fbcb42Sjoerg ConceptSpecializationExpr::ConceptSpecializationExpr(
90*13fbcb42Sjoerg const ASTContext &C, ConceptDecl *NamedConcept,
91*13fbcb42Sjoerg ArrayRef<TemplateArgument> ConvertedArgs,
92*13fbcb42Sjoerg const ConstraintSatisfaction *Satisfaction, bool Dependent,
93*13fbcb42Sjoerg bool ContainsUnexpandedParameterPack)
94*13fbcb42Sjoerg : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary),
95*13fbcb42Sjoerg ConceptReference(NestedNameSpecifierLoc(), SourceLocation(),
96*13fbcb42Sjoerg DeclarationNameInfo(), NamedConcept, NamedConcept,
97*13fbcb42Sjoerg nullptr),
98*13fbcb42Sjoerg NumTemplateArgs(ConvertedArgs.size()),
99*13fbcb42Sjoerg Satisfaction(Satisfaction
100*13fbcb42Sjoerg ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
101*13fbcb42Sjoerg : nullptr) {
102*13fbcb42Sjoerg setTemplateArguments(ConvertedArgs);
103*13fbcb42Sjoerg ExprDependence D = ExprDependence::None;
104*13fbcb42Sjoerg if (!Satisfaction)
105*13fbcb42Sjoerg D |= ExprDependence::Value;
106*13fbcb42Sjoerg if (Dependent)
107*13fbcb42Sjoerg D |= ExprDependence::Instantiation;
108*13fbcb42Sjoerg if (ContainsUnexpandedParameterPack)
109*13fbcb42Sjoerg D |= ExprDependence::UnexpandedPack;
110*13fbcb42Sjoerg setDependence(D);
111*13fbcb42Sjoerg }
112*13fbcb42Sjoerg
113*13fbcb42Sjoerg ConceptSpecializationExpr *
Create(const ASTContext & C,ConceptDecl * NamedConcept,ArrayRef<TemplateArgument> ConvertedArgs,const ConstraintSatisfaction * Satisfaction,bool Dependent,bool ContainsUnexpandedParameterPack)114*13fbcb42Sjoerg ConceptSpecializationExpr::Create(const ASTContext &C,
115*13fbcb42Sjoerg ConceptDecl *NamedConcept,
116*13fbcb42Sjoerg ArrayRef<TemplateArgument> ConvertedArgs,
117*13fbcb42Sjoerg const ConstraintSatisfaction *Satisfaction,
118*13fbcb42Sjoerg bool Dependent,
119*13fbcb42Sjoerg bool ContainsUnexpandedParameterPack) {
120*13fbcb42Sjoerg void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
121*13fbcb42Sjoerg ConvertedArgs.size()));
122*13fbcb42Sjoerg return new (Buffer) ConceptSpecializationExpr(
123*13fbcb42Sjoerg C, NamedConcept, ConvertedArgs, Satisfaction, Dependent,
124*13fbcb42Sjoerg ContainsUnexpandedParameterPack);
125*13fbcb42Sjoerg }
126*13fbcb42Sjoerg
127*13fbcb42Sjoerg ConceptSpecializationExpr *
Create(ASTContext & C,EmptyShell Empty,unsigned NumTemplateArgs)128*13fbcb42Sjoerg ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty,
129*13fbcb42Sjoerg unsigned NumTemplateArgs) {
130*13fbcb42Sjoerg void *Buffer = C.Allocate(totalSizeToAlloc<TemplateArgument>(
131*13fbcb42Sjoerg NumTemplateArgs));
132*13fbcb42Sjoerg return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs);
133*13fbcb42Sjoerg }
134*13fbcb42Sjoerg
135*13fbcb42Sjoerg const TypeConstraint *
getTypeConstraint() const136*13fbcb42Sjoerg concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {
137*13fbcb42Sjoerg assert(isTypeConstraint());
138*13fbcb42Sjoerg auto TPL =
139*13fbcb42Sjoerg TypeConstraintInfo.getPointer().get<TemplateParameterList *>();
140*13fbcb42Sjoerg return cast<TemplateTypeParmDecl>(TPL->getParam(0))
141*13fbcb42Sjoerg ->getTypeConstraint();
142*13fbcb42Sjoerg }
143*13fbcb42Sjoerg
RequiresExpr(ASTContext & C,SourceLocation RequiresKWLoc,RequiresExprBodyDecl * Body,ArrayRef<ParmVarDecl * > LocalParameters,ArrayRef<concepts::Requirement * > Requirements,SourceLocation RBraceLoc)144*13fbcb42Sjoerg RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
145*13fbcb42Sjoerg RequiresExprBodyDecl *Body,
146*13fbcb42Sjoerg ArrayRef<ParmVarDecl *> LocalParameters,
147*13fbcb42Sjoerg ArrayRef<concepts::Requirement *> Requirements,
148*13fbcb42Sjoerg SourceLocation RBraceLoc)
149*13fbcb42Sjoerg : Expr(RequiresExprClass, C.BoolTy, VK_RValue, OK_Ordinary),
150*13fbcb42Sjoerg NumLocalParameters(LocalParameters.size()),
151*13fbcb42Sjoerg NumRequirements(Requirements.size()), Body(Body), RBraceLoc(RBraceLoc) {
152*13fbcb42Sjoerg RequiresExprBits.IsSatisfied = false;
153*13fbcb42Sjoerg RequiresExprBits.RequiresKWLoc = RequiresKWLoc;
154*13fbcb42Sjoerg bool Dependent = false;
155*13fbcb42Sjoerg bool ContainsUnexpandedParameterPack = false;
156*13fbcb42Sjoerg for (ParmVarDecl *P : LocalParameters) {
157*13fbcb42Sjoerg Dependent |= P->getType()->isInstantiationDependentType();
158*13fbcb42Sjoerg ContainsUnexpandedParameterPack |=
159*13fbcb42Sjoerg P->getType()->containsUnexpandedParameterPack();
160*13fbcb42Sjoerg }
161*13fbcb42Sjoerg RequiresExprBits.IsSatisfied = true;
162*13fbcb42Sjoerg for (concepts::Requirement *R : Requirements) {
163*13fbcb42Sjoerg Dependent |= R->isDependent();
164*13fbcb42Sjoerg ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();
165*13fbcb42Sjoerg if (!Dependent) {
166*13fbcb42Sjoerg RequiresExprBits.IsSatisfied = R->isSatisfied();
167*13fbcb42Sjoerg if (!RequiresExprBits.IsSatisfied)
168*13fbcb42Sjoerg break;
169*13fbcb42Sjoerg }
170*13fbcb42Sjoerg }
171*13fbcb42Sjoerg std::copy(LocalParameters.begin(), LocalParameters.end(),
172*13fbcb42Sjoerg getTrailingObjects<ParmVarDecl *>());
173*13fbcb42Sjoerg std::copy(Requirements.begin(), Requirements.end(),
174*13fbcb42Sjoerg getTrailingObjects<concepts::Requirement *>());
175*13fbcb42Sjoerg RequiresExprBits.IsSatisfied |= Dependent;
176*13fbcb42Sjoerg // FIXME: move the computing dependency logic to ComputeDependence.h
177*13fbcb42Sjoerg if (ContainsUnexpandedParameterPack)
178*13fbcb42Sjoerg setDependence(getDependence() | ExprDependence::UnexpandedPack);
179*13fbcb42Sjoerg // FIXME: this is incorrect for cases where we have a non-dependent
180*13fbcb42Sjoerg // requirement, but its parameters are instantiation-dependent. RequiresExpr
181*13fbcb42Sjoerg // should be instantiation-dependent if it has instantiation-dependent
182*13fbcb42Sjoerg // parameters.
183*13fbcb42Sjoerg if (Dependent)
184*13fbcb42Sjoerg setDependence(getDependence() | ExprDependence::ValueInstantiation);
185*13fbcb42Sjoerg }
186*13fbcb42Sjoerg
RequiresExpr(ASTContext & C,EmptyShell Empty,unsigned NumLocalParameters,unsigned NumRequirements)187*13fbcb42Sjoerg RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
188*13fbcb42Sjoerg unsigned NumLocalParameters,
189*13fbcb42Sjoerg unsigned NumRequirements)
190*13fbcb42Sjoerg : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
191*13fbcb42Sjoerg NumRequirements(NumRequirements) { }
192*13fbcb42Sjoerg
193*13fbcb42Sjoerg RequiresExpr *
Create(ASTContext & C,SourceLocation RequiresKWLoc,RequiresExprBodyDecl * Body,ArrayRef<ParmVarDecl * > LocalParameters,ArrayRef<concepts::Requirement * > Requirements,SourceLocation RBraceLoc)194*13fbcb42Sjoerg RequiresExpr::Create(ASTContext &C, SourceLocation RequiresKWLoc,
195*13fbcb42Sjoerg RequiresExprBodyDecl *Body,
196*13fbcb42Sjoerg ArrayRef<ParmVarDecl *> LocalParameters,
197*13fbcb42Sjoerg ArrayRef<concepts::Requirement *> Requirements,
198*13fbcb42Sjoerg SourceLocation RBraceLoc) {
199*13fbcb42Sjoerg void *Mem =
200*13fbcb42Sjoerg C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
201*13fbcb42Sjoerg LocalParameters.size(), Requirements.size()),
202*13fbcb42Sjoerg alignof(RequiresExpr));
203*13fbcb42Sjoerg return new (Mem) RequiresExpr(C, RequiresKWLoc, Body, LocalParameters,
204*13fbcb42Sjoerg Requirements, RBraceLoc);
205*13fbcb42Sjoerg }
206*13fbcb42Sjoerg
207*13fbcb42Sjoerg RequiresExpr *
Create(ASTContext & C,EmptyShell Empty,unsigned NumLocalParameters,unsigned NumRequirements)208*13fbcb42Sjoerg RequiresExpr::Create(ASTContext &C, EmptyShell Empty,
209*13fbcb42Sjoerg unsigned NumLocalParameters, unsigned NumRequirements) {
210*13fbcb42Sjoerg void *Mem =
211*13fbcb42Sjoerg C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
212*13fbcb42Sjoerg NumLocalParameters, NumRequirements),
213*13fbcb42Sjoerg alignof(RequiresExpr));
214*13fbcb42Sjoerg return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);
215*13fbcb42Sjoerg }
216