xref: /freebsd-src/contrib/llvm-project/clang/lib/AST/ExprConcepts.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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