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