155e4f9d5SDimitry Andric //===- ExprCXX.cpp - (C++) Expression AST Node Implementation -------------===//
255e4f9d5SDimitry Andric //
355e4f9d5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
455e4f9d5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
555e4f9d5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
655e4f9d5SDimitry Andric //
755e4f9d5SDimitry Andric //===----------------------------------------------------------------------===//
855e4f9d5SDimitry Andric //
955e4f9d5SDimitry Andric // This file implements the subclesses of Expr class declared in ExprCXX.h
1055e4f9d5SDimitry Andric //
1155e4f9d5SDimitry Andric //===----------------------------------------------------------------------===//
1255e4f9d5SDimitry Andric
1355e4f9d5SDimitry Andric #include "clang/AST/ExprConcepts.h"
1455e4f9d5SDimitry Andric #include "clang/AST/ASTConcept.h"
155ffd83dbSDimitry Andric #include "clang/AST/ASTContext.h"
165ffd83dbSDimitry Andric #include "clang/AST/ComputeDependence.h"
1755e4f9d5SDimitry Andric #include "clang/AST/Decl.h"
1855e4f9d5SDimitry Andric #include "clang/AST/DeclTemplate.h"
195ffd83dbSDimitry Andric #include "clang/AST/DeclarationName.h"
205ffd83dbSDimitry Andric #include "clang/AST/DependenceFlags.h"
2155e4f9d5SDimitry Andric #include "clang/AST/Expr.h"
2255e4f9d5SDimitry Andric #include "clang/AST/NestedNameSpecifier.h"
2355e4f9d5SDimitry Andric #include "clang/AST/TemplateBase.h"
2455e4f9d5SDimitry Andric #include "clang/AST/Type.h"
2555e4f9d5SDimitry Andric #include "clang/Basic/SourceLocation.h"
2655e4f9d5SDimitry Andric #include "llvm/Support/TrailingObjects.h"
2755e4f9d5SDimitry Andric #include <algorithm>
2855e4f9d5SDimitry Andric #include <string>
295ffd83dbSDimitry Andric #include <utility>
3055e4f9d5SDimitry Andric
3155e4f9d5SDimitry Andric using namespace clang;
3255e4f9d5SDimitry Andric
ConceptSpecializationExpr(const ASTContext & C,ConceptReference * Loc,ImplicitConceptSpecializationDecl * SpecDecl,const ConstraintSatisfaction * Satisfaction)335ffd83dbSDimitry Andric ConceptSpecializationExpr::ConceptSpecializationExpr(
34*5f757f3fSDimitry Andric const ASTContext &C, ConceptReference *Loc,
35bdd1243dSDimitry Andric ImplicitConceptSpecializationDecl *SpecDecl,
3655e4f9d5SDimitry Andric const ConstraintSatisfaction *Satisfaction)
37fe6060f1SDimitry Andric : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
38*5f757f3fSDimitry Andric ConceptRef(Loc), SpecDecl(SpecDecl),
395ffd83dbSDimitry Andric Satisfaction(Satisfaction
405ffd83dbSDimitry Andric ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
415ffd83dbSDimitry Andric : nullptr) {
425ffd83dbSDimitry Andric setDependence(computeDependence(this, /*ValueDependent=*/!Satisfaction));
4355e4f9d5SDimitry Andric
4455e4f9d5SDimitry Andric // Currently guaranteed by the fact concepts can only be at namespace-scope.
45*5f757f3fSDimitry Andric assert(!Loc->getNestedNameSpecifierLoc() ||
46*5f757f3fSDimitry Andric (!Loc->getNestedNameSpecifierLoc()
47*5f757f3fSDimitry Andric .getNestedNameSpecifier()
48*5f757f3fSDimitry Andric ->isInstantiationDependent() &&
49*5f757f3fSDimitry Andric !Loc->getNestedNameSpecifierLoc()
50*5f757f3fSDimitry Andric .getNestedNameSpecifier()
5155e4f9d5SDimitry Andric ->containsUnexpandedParameterPack()));
5255e4f9d5SDimitry Andric assert((!isValueDependent() || isInstantiationDependent()) &&
5355e4f9d5SDimitry Andric "should not be value-dependent");
5455e4f9d5SDimitry Andric }
5555e4f9d5SDimitry Andric
ConceptSpecializationExpr(EmptyShell Empty)56bdd1243dSDimitry Andric ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty)
57bdd1243dSDimitry Andric : Expr(ConceptSpecializationExprClass, Empty) {}
5813138422SDimitry Andric
59*5f757f3fSDimitry Andric ConceptSpecializationExpr *
Create(const ASTContext & C,ConceptReference * Loc,ImplicitConceptSpecializationDecl * SpecDecl,const ConstraintSatisfaction * Satisfaction)60*5f757f3fSDimitry Andric ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc,
61bdd1243dSDimitry Andric ImplicitConceptSpecializationDecl *SpecDecl,
6255e4f9d5SDimitry Andric const ConstraintSatisfaction *Satisfaction) {
63*5f757f3fSDimitry Andric return new (C) ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction);
6455e4f9d5SDimitry Andric }
6555e4f9d5SDimitry Andric
ConceptSpecializationExpr(const ASTContext & C,ConceptReference * Loc,ImplicitConceptSpecializationDecl * SpecDecl,const ConstraintSatisfaction * Satisfaction,bool Dependent,bool ContainsUnexpandedParameterPack)6613138422SDimitry Andric ConceptSpecializationExpr::ConceptSpecializationExpr(
67*5f757f3fSDimitry Andric const ASTContext &C, ConceptReference *Loc,
68bdd1243dSDimitry Andric ImplicitConceptSpecializationDecl *SpecDecl,
6913138422SDimitry Andric const ConstraintSatisfaction *Satisfaction, bool Dependent,
7013138422SDimitry Andric bool ContainsUnexpandedParameterPack)
71fe6060f1SDimitry Andric : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
72*5f757f3fSDimitry Andric ConceptRef(Loc), SpecDecl(SpecDecl),
735ffd83dbSDimitry Andric Satisfaction(Satisfaction
745ffd83dbSDimitry Andric ? ASTConstraintSatisfaction::Create(C, *Satisfaction)
755ffd83dbSDimitry Andric : nullptr) {
765ffd83dbSDimitry Andric ExprDependence D = ExprDependence::None;
775ffd83dbSDimitry Andric if (!Satisfaction)
785ffd83dbSDimitry Andric D |= ExprDependence::Value;
795ffd83dbSDimitry Andric if (Dependent)
805ffd83dbSDimitry Andric D |= ExprDependence::Instantiation;
815ffd83dbSDimitry Andric if (ContainsUnexpandedParameterPack)
825ffd83dbSDimitry Andric D |= ExprDependence::UnexpandedPack;
835ffd83dbSDimitry Andric setDependence(D);
8413138422SDimitry Andric }
8513138422SDimitry Andric
86*5f757f3fSDimitry Andric ConceptSpecializationExpr *
Create(const ASTContext & C,ConceptReference * Loc,ImplicitConceptSpecializationDecl * SpecDecl,const ConstraintSatisfaction * Satisfaction,bool Dependent,bool ContainsUnexpandedParameterPack)87*5f757f3fSDimitry Andric ConceptSpecializationExpr::Create(const ASTContext &C, ConceptReference *Loc,
88bdd1243dSDimitry Andric ImplicitConceptSpecializationDecl *SpecDecl,
89*5f757f3fSDimitry Andric const ConstraintSatisfaction *Satisfaction,
90*5f757f3fSDimitry Andric bool Dependent,
9113138422SDimitry Andric bool ContainsUnexpandedParameterPack) {
92*5f757f3fSDimitry Andric return new (C)
93*5f757f3fSDimitry Andric ConceptSpecializationExpr(C, Loc, SpecDecl, Satisfaction, Dependent,
942efbaac7SDimitry Andric ContainsUnexpandedParameterPack);
9555e4f9d5SDimitry Andric }
9655e4f9d5SDimitry Andric
9755e4f9d5SDimitry Andric const TypeConstraint *
getTypeConstraint() const9855e4f9d5SDimitry Andric concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const {
9955e4f9d5SDimitry Andric assert(isTypeConstraint());
10055e4f9d5SDimitry Andric auto TPL =
10155e4f9d5SDimitry Andric TypeConstraintInfo.getPointer().get<TemplateParameterList *>();
10255e4f9d5SDimitry Andric return cast<TemplateTypeParmDecl>(TPL->getParam(0))
10355e4f9d5SDimitry Andric ->getTypeConstraint();
10455e4f9d5SDimitry Andric }
10555e4f9d5SDimitry Andric
10606c3fb27SDimitry Andric // Search through the requirements, and see if any have a RecoveryExpr in it,
10706c3fb27SDimitry Andric // which means this RequiresExpr ALSO needs to be invalid.
RequirementContainsError(concepts::Requirement * R)10806c3fb27SDimitry Andric static bool RequirementContainsError(concepts::Requirement *R) {
10906c3fb27SDimitry Andric if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(R))
11006c3fb27SDimitry Andric return ExprReq->getExpr() && ExprReq->getExpr()->containsErrors();
11106c3fb27SDimitry Andric
11206c3fb27SDimitry Andric if (auto *NestedReq = dyn_cast<concepts::NestedRequirement>(R))
11306c3fb27SDimitry Andric return !NestedReq->hasInvalidConstraint() &&
11406c3fb27SDimitry Andric NestedReq->getConstraintExpr() &&
11506c3fb27SDimitry Andric NestedReq->getConstraintExpr()->containsErrors();
11606c3fb27SDimitry Andric return false;
11706c3fb27SDimitry Andric }
11806c3fb27SDimitry Andric
RequiresExpr(ASTContext & C,SourceLocation RequiresKWLoc,RequiresExprBodyDecl * Body,SourceLocation LParenLoc,ArrayRef<ParmVarDecl * > LocalParameters,SourceLocation RParenLoc,ArrayRef<concepts::Requirement * > Requirements,SourceLocation RBraceLoc)11955e4f9d5SDimitry Andric RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
120*5f757f3fSDimitry Andric RequiresExprBodyDecl *Body, SourceLocation LParenLoc,
12155e4f9d5SDimitry Andric ArrayRef<ParmVarDecl *> LocalParameters,
122*5f757f3fSDimitry Andric SourceLocation RParenLoc,
12355e4f9d5SDimitry Andric ArrayRef<concepts::Requirement *> Requirements,
12455e4f9d5SDimitry Andric SourceLocation RBraceLoc)
125fe6060f1SDimitry Andric : Expr(RequiresExprClass, C.BoolTy, VK_PRValue, OK_Ordinary),
12655e4f9d5SDimitry Andric NumLocalParameters(LocalParameters.size()),
127*5f757f3fSDimitry Andric NumRequirements(Requirements.size()), Body(Body), LParenLoc(LParenLoc),
128*5f757f3fSDimitry Andric RParenLoc(RParenLoc), RBraceLoc(RBraceLoc) {
12955e4f9d5SDimitry Andric RequiresExprBits.IsSatisfied = false;
13055e4f9d5SDimitry Andric RequiresExprBits.RequiresKWLoc = RequiresKWLoc;
13155e4f9d5SDimitry Andric bool Dependent = false;
13255e4f9d5SDimitry Andric bool ContainsUnexpandedParameterPack = false;
13355e4f9d5SDimitry Andric for (ParmVarDecl *P : LocalParameters) {
13455e4f9d5SDimitry Andric Dependent |= P->getType()->isInstantiationDependentType();
13555e4f9d5SDimitry Andric ContainsUnexpandedParameterPack |=
13655e4f9d5SDimitry Andric P->getType()->containsUnexpandedParameterPack();
13755e4f9d5SDimitry Andric }
13855e4f9d5SDimitry Andric RequiresExprBits.IsSatisfied = true;
13955e4f9d5SDimitry Andric for (concepts::Requirement *R : Requirements) {
14055e4f9d5SDimitry Andric Dependent |= R->isDependent();
14155e4f9d5SDimitry Andric ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack();
14255e4f9d5SDimitry Andric if (!Dependent) {
14355e4f9d5SDimitry Andric RequiresExprBits.IsSatisfied = R->isSatisfied();
14455e4f9d5SDimitry Andric if (!RequiresExprBits.IsSatisfied)
14555e4f9d5SDimitry Andric break;
14655e4f9d5SDimitry Andric }
14706c3fb27SDimitry Andric
14806c3fb27SDimitry Andric if (RequirementContainsError(R))
14906c3fb27SDimitry Andric setDependence(getDependence() | ExprDependence::Error);
15055e4f9d5SDimitry Andric }
15155e4f9d5SDimitry Andric std::copy(LocalParameters.begin(), LocalParameters.end(),
15255e4f9d5SDimitry Andric getTrailingObjects<ParmVarDecl *>());
15355e4f9d5SDimitry Andric std::copy(Requirements.begin(), Requirements.end(),
15455e4f9d5SDimitry Andric getTrailingObjects<concepts::Requirement *>());
15555e4f9d5SDimitry Andric RequiresExprBits.IsSatisfied |= Dependent;
1565ffd83dbSDimitry Andric // FIXME: move the computing dependency logic to ComputeDependence.h
1575ffd83dbSDimitry Andric if (ContainsUnexpandedParameterPack)
1585ffd83dbSDimitry Andric setDependence(getDependence() | ExprDependence::UnexpandedPack);
1595ffd83dbSDimitry Andric // FIXME: this is incorrect for cases where we have a non-dependent
1605ffd83dbSDimitry Andric // requirement, but its parameters are instantiation-dependent. RequiresExpr
1615ffd83dbSDimitry Andric // should be instantiation-dependent if it has instantiation-dependent
1625ffd83dbSDimitry Andric // parameters.
1635ffd83dbSDimitry Andric if (Dependent)
1645ffd83dbSDimitry Andric setDependence(getDependence() | ExprDependence::ValueInstantiation);
16555e4f9d5SDimitry Andric }
16655e4f9d5SDimitry Andric
RequiresExpr(ASTContext & C,EmptyShell Empty,unsigned NumLocalParameters,unsigned NumRequirements)16755e4f9d5SDimitry Andric RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty,
16855e4f9d5SDimitry Andric unsigned NumLocalParameters,
16955e4f9d5SDimitry Andric unsigned NumRequirements)
17055e4f9d5SDimitry Andric : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters),
17155e4f9d5SDimitry Andric NumRequirements(NumRequirements) { }
17255e4f9d5SDimitry Andric
Create(ASTContext & C,SourceLocation RequiresKWLoc,RequiresExprBodyDecl * Body,SourceLocation LParenLoc,ArrayRef<ParmVarDecl * > LocalParameters,SourceLocation RParenLoc,ArrayRef<concepts::Requirement * > Requirements,SourceLocation RBraceLoc)173*5f757f3fSDimitry Andric RequiresExpr *RequiresExpr::Create(
174*5f757f3fSDimitry Andric ASTContext &C, SourceLocation RequiresKWLoc, RequiresExprBodyDecl *Body,
175*5f757f3fSDimitry Andric SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters,
176*5f757f3fSDimitry Andric SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements,
17755e4f9d5SDimitry Andric SourceLocation RBraceLoc) {
17855e4f9d5SDimitry Andric void *Mem =
17955e4f9d5SDimitry Andric C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
18055e4f9d5SDimitry Andric LocalParameters.size(), Requirements.size()),
18155e4f9d5SDimitry Andric alignof(RequiresExpr));
182*5f757f3fSDimitry Andric return new (Mem)
183*5f757f3fSDimitry Andric RequiresExpr(C, RequiresKWLoc, Body, LParenLoc, LocalParameters,
184*5f757f3fSDimitry Andric RParenLoc, Requirements, RBraceLoc);
18555e4f9d5SDimitry Andric }
18655e4f9d5SDimitry Andric
18755e4f9d5SDimitry Andric RequiresExpr *
Create(ASTContext & C,EmptyShell Empty,unsigned NumLocalParameters,unsigned NumRequirements)18855e4f9d5SDimitry Andric RequiresExpr::Create(ASTContext &C, EmptyShell Empty,
18955e4f9d5SDimitry Andric unsigned NumLocalParameters, unsigned NumRequirements) {
19055e4f9d5SDimitry Andric void *Mem =
19155e4f9d5SDimitry Andric C.Allocate(totalSizeToAlloc<ParmVarDecl *, concepts::Requirement *>(
19255e4f9d5SDimitry Andric NumLocalParameters, NumRequirements),
19355e4f9d5SDimitry Andric alignof(RequiresExpr));
19455e4f9d5SDimitry Andric return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements);
19555e4f9d5SDimitry Andric }
196