155e4f9d5SDimitry Andric //===- ExprConcepts.h - C++2a Concepts expressions --------------*- C++ -*-===// 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 /// \file 1055e4f9d5SDimitry Andric /// Defines Expressions and AST nodes for C++2a concepts. 1155e4f9d5SDimitry Andric // 1255e4f9d5SDimitry Andric //===----------------------------------------------------------------------===// 1355e4f9d5SDimitry Andric 1455e4f9d5SDimitry Andric #ifndef LLVM_CLANG_AST_EXPRCONCEPTS_H 1555e4f9d5SDimitry Andric #define LLVM_CLANG_AST_EXPRCONCEPTS_H 1655e4f9d5SDimitry Andric 1755e4f9d5SDimitry Andric #include "clang/AST/ASTConcept.h" 188a4dda33SDimitry Andric #include "clang/AST/ASTContext.h" 1955e4f9d5SDimitry Andric #include "clang/AST/Decl.h" 2055e4f9d5SDimitry Andric #include "clang/AST/DeclTemplate.h" 218a4dda33SDimitry Andric #include "clang/AST/DeclarationName.h" 2255e4f9d5SDimitry Andric #include "clang/AST/Expr.h" 2355e4f9d5SDimitry Andric #include "clang/AST/NestedNameSpecifier.h" 2455e4f9d5SDimitry Andric #include "clang/AST/TemplateBase.h" 2555e4f9d5SDimitry Andric #include "clang/AST/Type.h" 2655e4f9d5SDimitry Andric #include "clang/Basic/SourceLocation.h" 278a4dda33SDimitry Andric #include "llvm/ADT/STLFunctionalExtras.h" 28bdd1243dSDimitry Andric #include "llvm/Support/ErrorHandling.h" 2955e4f9d5SDimitry Andric #include "llvm/Support/TrailingObjects.h" 3055e4f9d5SDimitry Andric #include <string> 318a4dda33SDimitry Andric #include <utility> 3255e4f9d5SDimitry Andric 3355e4f9d5SDimitry Andric namespace clang { 3455e4f9d5SDimitry Andric class ASTStmtReader; 3555e4f9d5SDimitry Andric class ASTStmtWriter; 3655e4f9d5SDimitry Andric 3755e4f9d5SDimitry Andric /// \brief Represents the specialization of a concept - evaluates to a prvalue 3855e4f9d5SDimitry Andric /// of type bool. 3955e4f9d5SDimitry Andric /// 4055e4f9d5SDimitry Andric /// According to C++2a [expr.prim.id]p3 an id-expression that denotes the 4155e4f9d5SDimitry Andric /// specialization of a concept results in a prvalue of type bool. 42*5f757f3fSDimitry Andric class ConceptSpecializationExpr final : public Expr { 43bdd1243dSDimitry Andric friend class ASTReader; 4455e4f9d5SDimitry Andric friend class ASTStmtReader; 45bdd1243dSDimitry Andric 46*5f757f3fSDimitry Andric private: 47*5f757f3fSDimitry Andric ConceptReference *ConceptRef; 4855e4f9d5SDimitry Andric 49bdd1243dSDimitry Andric /// \brief The Implicit Concept Specialization Decl, which holds the template 50bdd1243dSDimitry Andric /// arguments for this specialization. 51bdd1243dSDimitry Andric ImplicitConceptSpecializationDecl *SpecDecl; 5255e4f9d5SDimitry Andric 5355e4f9d5SDimitry Andric /// \brief Information about the satisfaction of the named concept with the 5455e4f9d5SDimitry Andric /// given arguments. If this expression is value dependent, this is to be 5555e4f9d5SDimitry Andric /// ignored. 5655e4f9d5SDimitry Andric ASTConstraintSatisfaction *Satisfaction; 5755e4f9d5SDimitry Andric 58*5f757f3fSDimitry Andric ConceptSpecializationExpr(const ASTContext &C, ConceptReference *ConceptRef, 59bdd1243dSDimitry Andric ImplicitConceptSpecializationDecl *SpecDecl, 6055e4f9d5SDimitry Andric const ConstraintSatisfaction *Satisfaction); 6155e4f9d5SDimitry Andric 62*5f757f3fSDimitry Andric ConceptSpecializationExpr(const ASTContext &C, ConceptReference *ConceptRef, 63bdd1243dSDimitry Andric ImplicitConceptSpecializationDecl *SpecDecl, 6413138422SDimitry Andric const ConstraintSatisfaction *Satisfaction, 6513138422SDimitry Andric bool Dependent, 6613138422SDimitry Andric bool ContainsUnexpandedParameterPack); 67bdd1243dSDimitry Andric ConceptSpecializationExpr(EmptyShell Empty); 6855e4f9d5SDimitry Andric 6955e4f9d5SDimitry Andric public: 7055e4f9d5SDimitry Andric static ConceptSpecializationExpr * 71*5f757f3fSDimitry Andric Create(const ASTContext &C, ConceptReference *ConceptRef, 72bdd1243dSDimitry Andric ImplicitConceptSpecializationDecl *SpecDecl, 7355e4f9d5SDimitry Andric const ConstraintSatisfaction *Satisfaction); 7455e4f9d5SDimitry Andric 7555e4f9d5SDimitry Andric static ConceptSpecializationExpr * 76*5f757f3fSDimitry Andric Create(const ASTContext &C, ConceptReference *ConceptRef, 772efbaac7SDimitry Andric ImplicitConceptSpecializationDecl *SpecDecl, 782efbaac7SDimitry Andric const ConstraintSatisfaction *Satisfaction, bool Dependent, 792efbaac7SDimitry Andric bool ContainsUnexpandedParameterPack); 802efbaac7SDimitry Andric getTemplateArguments()8155e4f9d5SDimitry Andric ArrayRef<TemplateArgument> getTemplateArguments() const { 82bdd1243dSDimitry Andric return SpecDecl->getTemplateArguments(); 8355e4f9d5SDimitry Andric } 8455e4f9d5SDimitry Andric getConceptReference()85*5f757f3fSDimitry Andric ConceptReference *getConceptReference() const { return ConceptRef; } 86*5f757f3fSDimitry Andric getNamedConcept()87*5f757f3fSDimitry Andric ConceptDecl *getNamedConcept() const { return ConceptRef->getNamedConcept(); } 88*5f757f3fSDimitry Andric 89*5f757f3fSDimitry Andric // FIXME: Several of the following functions can be removed. Instead the 90*5f757f3fSDimitry Andric // caller can directly work with the ConceptReference. hasExplicitTemplateArgs()91*5f757f3fSDimitry Andric bool hasExplicitTemplateArgs() const { 92*5f757f3fSDimitry Andric return ConceptRef->hasExplicitTemplateArgs(); 93*5f757f3fSDimitry Andric } 94*5f757f3fSDimitry Andric getConceptNameLoc()95*5f757f3fSDimitry Andric SourceLocation getConceptNameLoc() const { 96*5f757f3fSDimitry Andric return ConceptRef->getConceptNameLoc(); 97*5f757f3fSDimitry Andric } getTemplateArgsAsWritten()98*5f757f3fSDimitry Andric const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { 99*5f757f3fSDimitry Andric return ConceptRef->getTemplateArgsAsWritten(); 100*5f757f3fSDimitry Andric } 101*5f757f3fSDimitry Andric getNestedNameSpecifierLoc()102*5f757f3fSDimitry Andric const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { 103*5f757f3fSDimitry Andric return ConceptRef->getNestedNameSpecifierLoc(); 104*5f757f3fSDimitry Andric } 105*5f757f3fSDimitry Andric getTemplateKWLoc()106*5f757f3fSDimitry Andric SourceLocation getTemplateKWLoc() const { 107*5f757f3fSDimitry Andric return ConceptRef->getTemplateKWLoc(); 108*5f757f3fSDimitry Andric } 109*5f757f3fSDimitry Andric getFoundDecl()110*5f757f3fSDimitry Andric NamedDecl *getFoundDecl() const { return ConceptRef->getFoundDecl(); } 111*5f757f3fSDimitry Andric getConceptNameInfo()112*5f757f3fSDimitry Andric const DeclarationNameInfo &getConceptNameInfo() const { 113*5f757f3fSDimitry Andric return ConceptRef->getConceptNameInfo(); 114*5f757f3fSDimitry Andric } 115*5f757f3fSDimitry Andric getSpecializationDecl()116bdd1243dSDimitry Andric const ImplicitConceptSpecializationDecl *getSpecializationDecl() const { 117bdd1243dSDimitry Andric assert(SpecDecl && "Template Argument Decl not initialized"); 118bdd1243dSDimitry Andric return SpecDecl; 119bdd1243dSDimitry Andric } 12055e4f9d5SDimitry Andric 12155e4f9d5SDimitry Andric /// \brief Whether or not the concept with the given arguments was satisfied 12255e4f9d5SDimitry Andric /// when the expression was created. 12355e4f9d5SDimitry Andric /// The expression must not be dependent. isSatisfied()12455e4f9d5SDimitry Andric bool isSatisfied() const { 125bdd1243dSDimitry Andric assert(!isValueDependent() && 126bdd1243dSDimitry Andric "isSatisfied called on a dependent ConceptSpecializationExpr"); 12755e4f9d5SDimitry Andric return Satisfaction->IsSatisfied; 12855e4f9d5SDimitry Andric } 12955e4f9d5SDimitry Andric 13055e4f9d5SDimitry Andric /// \brief Get elaborated satisfaction info about the template arguments' 13155e4f9d5SDimitry Andric /// satisfaction of the named concept. 13255e4f9d5SDimitry Andric /// The expression must not be dependent. getSatisfaction()13355e4f9d5SDimitry Andric const ASTConstraintSatisfaction &getSatisfaction() const { 134bdd1243dSDimitry Andric assert(!isValueDependent() && 135bdd1243dSDimitry Andric "getSatisfaction called on dependent ConceptSpecializationExpr"); 13655e4f9d5SDimitry Andric return *Satisfaction; 13755e4f9d5SDimitry Andric } 13855e4f9d5SDimitry Andric classof(const Stmt * T)13955e4f9d5SDimitry Andric static bool classof(const Stmt *T) { 14055e4f9d5SDimitry Andric return T->getStmtClass() == ConceptSpecializationExprClass; 14155e4f9d5SDimitry Andric } 14255e4f9d5SDimitry Andric getBeginLoc()14355e4f9d5SDimitry Andric SourceLocation getBeginLoc() const LLVM_READONLY { 144*5f757f3fSDimitry Andric return ConceptRef->getBeginLoc(); 14555e4f9d5SDimitry Andric } 14655e4f9d5SDimitry Andric getEndLoc()14755e4f9d5SDimitry Andric SourceLocation getEndLoc() const LLVM_READONLY { 148*5f757f3fSDimitry Andric return ConceptRef->getEndLoc(); 149*5f757f3fSDimitry Andric } 150*5f757f3fSDimitry Andric getExprLoc()151*5f757f3fSDimitry Andric SourceLocation getExprLoc() const LLVM_READONLY { 152*5f757f3fSDimitry Andric return ConceptRef->getLocation(); 15355e4f9d5SDimitry Andric } 15455e4f9d5SDimitry Andric 15555e4f9d5SDimitry Andric // Iterators children()15655e4f9d5SDimitry Andric child_range children() { 15755e4f9d5SDimitry Andric return child_range(child_iterator(), child_iterator()); 15855e4f9d5SDimitry Andric } children()15955e4f9d5SDimitry Andric const_child_range children() const { 16055e4f9d5SDimitry Andric return const_child_range(const_child_iterator(), const_child_iterator()); 16155e4f9d5SDimitry Andric } 16255e4f9d5SDimitry Andric }; 16355e4f9d5SDimitry Andric 16455e4f9d5SDimitry Andric namespace concepts { 16555e4f9d5SDimitry Andric 16655e4f9d5SDimitry Andric /// \brief A static requirement that can be used in a requires-expression to 16755e4f9d5SDimitry Andric /// check properties of types and expression. 16855e4f9d5SDimitry Andric class Requirement { 16955e4f9d5SDimitry Andric public: 17055e4f9d5SDimitry Andric // Note - simple and compound requirements are both represented by the same 17155e4f9d5SDimitry Andric // class (ExprRequirement). 17255e4f9d5SDimitry Andric enum RequirementKind { RK_Type, RK_Simple, RK_Compound, RK_Nested }; 17355e4f9d5SDimitry Andric private: 17455e4f9d5SDimitry Andric const RequirementKind Kind; 1755ffd83dbSDimitry Andric // FIXME: use RequirementDependence to model dependence? 176*5f757f3fSDimitry Andric LLVM_PREFERRED_TYPE(bool) 17755e4f9d5SDimitry Andric bool Dependent : 1; 178*5f757f3fSDimitry Andric LLVM_PREFERRED_TYPE(bool) 17955e4f9d5SDimitry Andric bool ContainsUnexpandedParameterPack : 1; 180*5f757f3fSDimitry Andric LLVM_PREFERRED_TYPE(bool) 18155e4f9d5SDimitry Andric bool Satisfied : 1; 18255e4f9d5SDimitry Andric public: 18355e4f9d5SDimitry Andric struct SubstitutionDiagnostic { 18455e4f9d5SDimitry Andric StringRef SubstitutedEntity; 18555e4f9d5SDimitry Andric // FIXME: Store diagnostics semantically and not as prerendered strings. 18655e4f9d5SDimitry Andric // Fixing this probably requires serialization of PartialDiagnostic 18755e4f9d5SDimitry Andric // objects. 18855e4f9d5SDimitry Andric SourceLocation DiagLoc; 18955e4f9d5SDimitry Andric StringRef DiagMessage; 19055e4f9d5SDimitry Andric }; 19155e4f9d5SDimitry Andric 19255e4f9d5SDimitry Andric Requirement(RequirementKind Kind, bool IsDependent, 19355e4f9d5SDimitry Andric bool ContainsUnexpandedParameterPack, bool IsSatisfied = true) : Kind(Kind)19455e4f9d5SDimitry Andric Kind(Kind), Dependent(IsDependent), 19555e4f9d5SDimitry Andric ContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack), 19655e4f9d5SDimitry Andric Satisfied(IsSatisfied) {} 19755e4f9d5SDimitry Andric getKind()19855e4f9d5SDimitry Andric RequirementKind getKind() const { return Kind; } 19955e4f9d5SDimitry Andric isSatisfied()20055e4f9d5SDimitry Andric bool isSatisfied() const { 20155e4f9d5SDimitry Andric assert(!Dependent && 20255e4f9d5SDimitry Andric "isSatisfied can only be called on non-dependent requirements."); 20355e4f9d5SDimitry Andric return Satisfied; 20455e4f9d5SDimitry Andric } 20555e4f9d5SDimitry Andric setSatisfied(bool IsSatisfied)20655e4f9d5SDimitry Andric void setSatisfied(bool IsSatisfied) { 20755e4f9d5SDimitry Andric assert(!Dependent && 20855e4f9d5SDimitry Andric "setSatisfied can only be called on non-dependent requirements."); 20955e4f9d5SDimitry Andric Satisfied = IsSatisfied; 21055e4f9d5SDimitry Andric } 21155e4f9d5SDimitry Andric setDependent(bool IsDependent)21255e4f9d5SDimitry Andric void setDependent(bool IsDependent) { Dependent = IsDependent; } isDependent()21355e4f9d5SDimitry Andric bool isDependent() const { return Dependent; } 21455e4f9d5SDimitry Andric setContainsUnexpandedParameterPack(bool Contains)21555e4f9d5SDimitry Andric void setContainsUnexpandedParameterPack(bool Contains) { 21655e4f9d5SDimitry Andric ContainsUnexpandedParameterPack = Contains; 21755e4f9d5SDimitry Andric } containsUnexpandedParameterPack()21855e4f9d5SDimitry Andric bool containsUnexpandedParameterPack() const { 21955e4f9d5SDimitry Andric return ContainsUnexpandedParameterPack; 22055e4f9d5SDimitry Andric } 22155e4f9d5SDimitry Andric }; 22255e4f9d5SDimitry Andric 22355e4f9d5SDimitry Andric /// \brief A requires-expression requirement which queries the existence of a 22455e4f9d5SDimitry Andric /// type name or type template specialization ('type' requirements). 22555e4f9d5SDimitry Andric class TypeRequirement : public Requirement { 22655e4f9d5SDimitry Andric public: 22755e4f9d5SDimitry Andric enum SatisfactionStatus { 22855e4f9d5SDimitry Andric SS_Dependent, 22955e4f9d5SDimitry Andric SS_SubstitutionFailure, 23055e4f9d5SDimitry Andric SS_Satisfied 23155e4f9d5SDimitry Andric }; 23255e4f9d5SDimitry Andric private: 23355e4f9d5SDimitry Andric llvm::PointerUnion<SubstitutionDiagnostic *, TypeSourceInfo *> Value; 23455e4f9d5SDimitry Andric SatisfactionStatus Status; 23555e4f9d5SDimitry Andric public: 23655e4f9d5SDimitry Andric friend ASTStmtReader; 23755e4f9d5SDimitry Andric friend ASTStmtWriter; 23855e4f9d5SDimitry Andric 23955e4f9d5SDimitry Andric /// \brief Construct a type requirement from a type. If the given type is not 24055e4f9d5SDimitry Andric /// dependent, this indicates that the type exists and the requirement will be 24155e4f9d5SDimitry Andric /// satisfied. Otherwise, the SubstitutionDiagnostic constructor is to be 24255e4f9d5SDimitry Andric /// used. 24355e4f9d5SDimitry Andric TypeRequirement(TypeSourceInfo *T); 24455e4f9d5SDimitry Andric 24555e4f9d5SDimitry Andric /// \brief Construct a type requirement when the nested name specifier is 24655e4f9d5SDimitry Andric /// invalid due to a bad substitution. The requirement is unsatisfied. TypeRequirement(SubstitutionDiagnostic * Diagnostic)24755e4f9d5SDimitry Andric TypeRequirement(SubstitutionDiagnostic *Diagnostic) : 24855e4f9d5SDimitry Andric Requirement(RK_Type, false, false, false), Value(Diagnostic), 24955e4f9d5SDimitry Andric Status(SS_SubstitutionFailure) {} 25055e4f9d5SDimitry Andric getSatisfactionStatus()25155e4f9d5SDimitry Andric SatisfactionStatus getSatisfactionStatus() const { return Status; } setSatisfactionStatus(SatisfactionStatus Status)25255e4f9d5SDimitry Andric void setSatisfactionStatus(SatisfactionStatus Status) { 25355e4f9d5SDimitry Andric this->Status = Status; 25455e4f9d5SDimitry Andric } 25555e4f9d5SDimitry Andric isSubstitutionFailure()25655e4f9d5SDimitry Andric bool isSubstitutionFailure() const { 25755e4f9d5SDimitry Andric return Status == SS_SubstitutionFailure; 25855e4f9d5SDimitry Andric } 25955e4f9d5SDimitry Andric getSubstitutionDiagnostic()26055e4f9d5SDimitry Andric SubstitutionDiagnostic *getSubstitutionDiagnostic() const { 26155e4f9d5SDimitry Andric assert(Status == SS_SubstitutionFailure && 26255e4f9d5SDimitry Andric "Attempted to get substitution diagnostic when there has been no " 26355e4f9d5SDimitry Andric "substitution failure."); 26455e4f9d5SDimitry Andric return Value.get<SubstitutionDiagnostic *>(); 26555e4f9d5SDimitry Andric } 26655e4f9d5SDimitry Andric getType()26755e4f9d5SDimitry Andric TypeSourceInfo *getType() const { 26855e4f9d5SDimitry Andric assert(!isSubstitutionFailure() && 26955e4f9d5SDimitry Andric "Attempted to get type when there has been a substitution failure."); 27055e4f9d5SDimitry Andric return Value.get<TypeSourceInfo *>(); 27155e4f9d5SDimitry Andric } 27255e4f9d5SDimitry Andric classof(const Requirement * R)27355e4f9d5SDimitry Andric static bool classof(const Requirement *R) { 27455e4f9d5SDimitry Andric return R->getKind() == RK_Type; 27555e4f9d5SDimitry Andric } 27655e4f9d5SDimitry Andric }; 27755e4f9d5SDimitry Andric 27855e4f9d5SDimitry Andric /// \brief A requires-expression requirement which queries the validity and 27955e4f9d5SDimitry Andric /// properties of an expression ('simple' and 'compound' requirements). 28055e4f9d5SDimitry Andric class ExprRequirement : public Requirement { 28155e4f9d5SDimitry Andric public: 28255e4f9d5SDimitry Andric enum SatisfactionStatus { 28355e4f9d5SDimitry Andric SS_Dependent, 28455e4f9d5SDimitry Andric SS_ExprSubstitutionFailure, 28555e4f9d5SDimitry Andric SS_NoexceptNotMet, 28655e4f9d5SDimitry Andric SS_TypeRequirementSubstitutionFailure, 28755e4f9d5SDimitry Andric SS_ConstraintsNotSatisfied, 28855e4f9d5SDimitry Andric SS_Satisfied 28955e4f9d5SDimitry Andric }; 29055e4f9d5SDimitry Andric class ReturnTypeRequirement { 29155e4f9d5SDimitry Andric llvm::PointerIntPair< 29255e4f9d5SDimitry Andric llvm::PointerUnion<TemplateParameterList *, SubstitutionDiagnostic *>, 29355e4f9d5SDimitry Andric 1, bool> 29455e4f9d5SDimitry Andric TypeConstraintInfo; 29555e4f9d5SDimitry Andric public: 29655e4f9d5SDimitry Andric friend ASTStmtReader; 29755e4f9d5SDimitry Andric friend ASTStmtWriter; 29855e4f9d5SDimitry Andric 29955e4f9d5SDimitry Andric /// \brief No return type requirement was specified. ReturnTypeRequirement()30004eeddc0SDimitry Andric ReturnTypeRequirement() : TypeConstraintInfo(nullptr, false) {} 30155e4f9d5SDimitry Andric 30255e4f9d5SDimitry Andric /// \brief A return type requirement was specified but it was a 30355e4f9d5SDimitry Andric /// substitution failure. ReturnTypeRequirement(SubstitutionDiagnostic * SubstDiag)30455e4f9d5SDimitry Andric ReturnTypeRequirement(SubstitutionDiagnostic *SubstDiag) : 30504eeddc0SDimitry Andric TypeConstraintInfo(SubstDiag, false) {} 30655e4f9d5SDimitry Andric 30755e4f9d5SDimitry Andric /// \brief A 'type constraint' style return type requirement. 30855e4f9d5SDimitry Andric /// \param TPL an invented template parameter list containing a single 30955e4f9d5SDimitry Andric /// type parameter with a type-constraint. 31055e4f9d5SDimitry Andric // TODO: Can we maybe not save the whole template parameter list and just 31155e4f9d5SDimitry Andric // the type constraint? Saving the whole TPL makes it easier to handle in 31255e4f9d5SDimitry Andric // serialization but is less elegant. 31355e4f9d5SDimitry Andric ReturnTypeRequirement(TemplateParameterList *TPL); 31455e4f9d5SDimitry Andric isDependent()31555e4f9d5SDimitry Andric bool isDependent() const { 31655e4f9d5SDimitry Andric return TypeConstraintInfo.getInt(); 31755e4f9d5SDimitry Andric } 31855e4f9d5SDimitry Andric containsUnexpandedParameterPack()31955e4f9d5SDimitry Andric bool containsUnexpandedParameterPack() const { 32055e4f9d5SDimitry Andric if (!isTypeConstraint()) 32155e4f9d5SDimitry Andric return false; 32255e4f9d5SDimitry Andric return getTypeConstraintTemplateParameterList() 32355e4f9d5SDimitry Andric ->containsUnexpandedParameterPack(); 32455e4f9d5SDimitry Andric } 32555e4f9d5SDimitry Andric isEmpty()32655e4f9d5SDimitry Andric bool isEmpty() const { 32755e4f9d5SDimitry Andric return TypeConstraintInfo.getPointer().isNull(); 32855e4f9d5SDimitry Andric } 32955e4f9d5SDimitry Andric isSubstitutionFailure()33055e4f9d5SDimitry Andric bool isSubstitutionFailure() const { 33155e4f9d5SDimitry Andric return !isEmpty() && 33255e4f9d5SDimitry Andric TypeConstraintInfo.getPointer().is<SubstitutionDiagnostic *>(); 33355e4f9d5SDimitry Andric } 33455e4f9d5SDimitry Andric isTypeConstraint()33555e4f9d5SDimitry Andric bool isTypeConstraint() const { 33655e4f9d5SDimitry Andric return !isEmpty() && 33755e4f9d5SDimitry Andric TypeConstraintInfo.getPointer().is<TemplateParameterList *>(); 33855e4f9d5SDimitry Andric } 33955e4f9d5SDimitry Andric getSubstitutionDiagnostic()34055e4f9d5SDimitry Andric SubstitutionDiagnostic *getSubstitutionDiagnostic() const { 34155e4f9d5SDimitry Andric assert(isSubstitutionFailure()); 34255e4f9d5SDimitry Andric return TypeConstraintInfo.getPointer().get<SubstitutionDiagnostic *>(); 34355e4f9d5SDimitry Andric } 34455e4f9d5SDimitry Andric 34555e4f9d5SDimitry Andric const TypeConstraint *getTypeConstraint() const; 34655e4f9d5SDimitry Andric getTypeConstraintTemplateParameterList()34755e4f9d5SDimitry Andric TemplateParameterList *getTypeConstraintTemplateParameterList() const { 34855e4f9d5SDimitry Andric assert(isTypeConstraint()); 34955e4f9d5SDimitry Andric return TypeConstraintInfo.getPointer().get<TemplateParameterList *>(); 35055e4f9d5SDimitry Andric } 35155e4f9d5SDimitry Andric }; 35255e4f9d5SDimitry Andric private: 35355e4f9d5SDimitry Andric llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> Value; 35455e4f9d5SDimitry Andric SourceLocation NoexceptLoc; // May be empty if noexcept wasn't specified. 35555e4f9d5SDimitry Andric ReturnTypeRequirement TypeReq; 35655e4f9d5SDimitry Andric ConceptSpecializationExpr *SubstitutedConstraintExpr; 35755e4f9d5SDimitry Andric SatisfactionStatus Status; 35855e4f9d5SDimitry Andric public: 35955e4f9d5SDimitry Andric friend ASTStmtReader; 36055e4f9d5SDimitry Andric friend ASTStmtWriter; 36155e4f9d5SDimitry Andric 36255e4f9d5SDimitry Andric /// \brief Construct a compound requirement. 36355e4f9d5SDimitry Andric /// \param E the expression which is checked by this requirement. 36455e4f9d5SDimitry Andric /// \param IsSimple whether this was a simple requirement in source. 36555e4f9d5SDimitry Andric /// \param NoexceptLoc the location of the noexcept keyword, if it was 36655e4f9d5SDimitry Andric /// specified, otherwise an empty location. 36755e4f9d5SDimitry Andric /// \param Req the requirement for the type of the checked expression. 36855e4f9d5SDimitry Andric /// \param Status the satisfaction status of this requirement. 36955e4f9d5SDimitry Andric ExprRequirement( 37055e4f9d5SDimitry Andric Expr *E, bool IsSimple, SourceLocation NoexceptLoc, 37155e4f9d5SDimitry Andric ReturnTypeRequirement Req, SatisfactionStatus Status, 37255e4f9d5SDimitry Andric ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr); 37355e4f9d5SDimitry Andric 37455e4f9d5SDimitry Andric /// \brief Construct a compound requirement whose expression was a 37555e4f9d5SDimitry Andric /// substitution failure. The requirement is not satisfied. 37655e4f9d5SDimitry Andric /// \param E the diagnostic emitted while instantiating the original 37755e4f9d5SDimitry Andric /// expression. 37855e4f9d5SDimitry Andric /// \param IsSimple whether this was a simple requirement in source. 37955e4f9d5SDimitry Andric /// \param NoexceptLoc the location of the noexcept keyword, if it was 38055e4f9d5SDimitry Andric /// specified, otherwise an empty location. 38155e4f9d5SDimitry Andric /// \param Req the requirement for the type of the checked expression (omit 38255e4f9d5SDimitry Andric /// if no requirement was specified). 38355e4f9d5SDimitry Andric ExprRequirement(SubstitutionDiagnostic *E, bool IsSimple, 38455e4f9d5SDimitry Andric SourceLocation NoexceptLoc, ReturnTypeRequirement Req = {}); 38555e4f9d5SDimitry Andric isSimple()38655e4f9d5SDimitry Andric bool isSimple() const { return getKind() == RK_Simple; } isCompound()38755e4f9d5SDimitry Andric bool isCompound() const { return getKind() == RK_Compound; } 38855e4f9d5SDimitry Andric hasNoexceptRequirement()38955e4f9d5SDimitry Andric bool hasNoexceptRequirement() const { return NoexceptLoc.isValid(); } getNoexceptLoc()39055e4f9d5SDimitry Andric SourceLocation getNoexceptLoc() const { return NoexceptLoc; } 39155e4f9d5SDimitry Andric getSatisfactionStatus()39255e4f9d5SDimitry Andric SatisfactionStatus getSatisfactionStatus() const { return Status; } 39355e4f9d5SDimitry Andric isExprSubstitutionFailure()39455e4f9d5SDimitry Andric bool isExprSubstitutionFailure() const { 39555e4f9d5SDimitry Andric return Status == SS_ExprSubstitutionFailure; 39655e4f9d5SDimitry Andric } 39755e4f9d5SDimitry Andric getReturnTypeRequirement()39855e4f9d5SDimitry Andric const ReturnTypeRequirement &getReturnTypeRequirement() const { 39955e4f9d5SDimitry Andric return TypeReq; 40055e4f9d5SDimitry Andric } 40155e4f9d5SDimitry Andric 40255e4f9d5SDimitry Andric ConceptSpecializationExpr * getReturnTypeRequirementSubstitutedConstraintExpr()40355e4f9d5SDimitry Andric getReturnTypeRequirementSubstitutedConstraintExpr() const { 40455e4f9d5SDimitry Andric assert(Status >= SS_TypeRequirementSubstitutionFailure); 40555e4f9d5SDimitry Andric return SubstitutedConstraintExpr; 40655e4f9d5SDimitry Andric } 40755e4f9d5SDimitry Andric getExprSubstitutionDiagnostic()40855e4f9d5SDimitry Andric SubstitutionDiagnostic *getExprSubstitutionDiagnostic() const { 40955e4f9d5SDimitry Andric assert(isExprSubstitutionFailure() && 41055e4f9d5SDimitry Andric "Attempted to get expression substitution diagnostic when there has " 41155e4f9d5SDimitry Andric "been no expression substitution failure"); 41255e4f9d5SDimitry Andric return Value.get<SubstitutionDiagnostic *>(); 41355e4f9d5SDimitry Andric } 41455e4f9d5SDimitry Andric getExpr()41555e4f9d5SDimitry Andric Expr *getExpr() const { 41655e4f9d5SDimitry Andric assert(!isExprSubstitutionFailure() && 41755e4f9d5SDimitry Andric "ExprRequirement has no expression because there has been a " 41855e4f9d5SDimitry Andric "substitution failure."); 41955e4f9d5SDimitry Andric return Value.get<Expr *>(); 42055e4f9d5SDimitry Andric } 42155e4f9d5SDimitry Andric classof(const Requirement * R)42255e4f9d5SDimitry Andric static bool classof(const Requirement *R) { 42355e4f9d5SDimitry Andric return R->getKind() == RK_Compound || R->getKind() == RK_Simple; 42455e4f9d5SDimitry Andric } 42555e4f9d5SDimitry Andric }; 42655e4f9d5SDimitry Andric 42755e4f9d5SDimitry Andric /// \brief A requires-expression requirement which is satisfied when a general 42855e4f9d5SDimitry Andric /// constraint expression is satisfied ('nested' requirements). 42955e4f9d5SDimitry Andric class NestedRequirement : public Requirement { 430bdd1243dSDimitry Andric Expr *Constraint = nullptr; 43155e4f9d5SDimitry Andric const ASTConstraintSatisfaction *Satisfaction = nullptr; 432bdd1243dSDimitry Andric bool HasInvalidConstraint = false; 433bdd1243dSDimitry Andric StringRef InvalidConstraintEntity; 43455e4f9d5SDimitry Andric 43555e4f9d5SDimitry Andric public: 43655e4f9d5SDimitry Andric friend ASTStmtReader; 43755e4f9d5SDimitry Andric friend ASTStmtWriter; 43855e4f9d5SDimitry Andric NestedRequirement(Expr * Constraint)439bdd1243dSDimitry Andric NestedRequirement(Expr *Constraint) 440bdd1243dSDimitry Andric : Requirement(RK_Nested, /*IsDependent=*/true, 44155e4f9d5SDimitry Andric Constraint->containsUnexpandedParameterPack()), 442bdd1243dSDimitry Andric Constraint(Constraint) { 44355e4f9d5SDimitry Andric assert(Constraint->isInstantiationDependent() && 44455e4f9d5SDimitry Andric "Nested requirement with non-dependent constraint must be " 44555e4f9d5SDimitry Andric "constructed with a ConstraintSatisfaction object"); 44655e4f9d5SDimitry Andric } 44755e4f9d5SDimitry Andric NestedRequirement(ASTContext & C,Expr * Constraint,const ConstraintSatisfaction & Satisfaction)44855e4f9d5SDimitry Andric NestedRequirement(ASTContext &C, Expr *Constraint, 449bdd1243dSDimitry Andric const ConstraintSatisfaction &Satisfaction) 450bdd1243dSDimitry Andric : Requirement(RK_Nested, Constraint->isInstantiationDependent(), 45155e4f9d5SDimitry Andric Constraint->containsUnexpandedParameterPack(), 45255e4f9d5SDimitry Andric Satisfaction.IsSatisfied), 453bdd1243dSDimitry Andric Constraint(Constraint), 45455e4f9d5SDimitry Andric Satisfaction(ASTConstraintSatisfaction::Create(C, Satisfaction)) {} 45555e4f9d5SDimitry Andric NestedRequirement(StringRef InvalidConstraintEntity,const ASTConstraintSatisfaction * Satisfaction)456bdd1243dSDimitry Andric NestedRequirement(StringRef InvalidConstraintEntity, 457bdd1243dSDimitry Andric const ASTConstraintSatisfaction *Satisfaction) 458bdd1243dSDimitry Andric : Requirement(RK_Nested, 459bdd1243dSDimitry Andric /*IsDependent=*/false, 460bdd1243dSDimitry Andric /*ContainsUnexpandedParameterPack*/ false, 461bdd1243dSDimitry Andric Satisfaction->IsSatisfied), 462bdd1243dSDimitry Andric Satisfaction(Satisfaction), HasInvalidConstraint(true), 463bdd1243dSDimitry Andric InvalidConstraintEntity(InvalidConstraintEntity) {} 46455e4f9d5SDimitry Andric NestedRequirement(ASTContext & C,StringRef InvalidConstraintEntity,const ConstraintSatisfaction & Satisfaction)465bdd1243dSDimitry Andric NestedRequirement(ASTContext &C, StringRef InvalidConstraintEntity, 466bdd1243dSDimitry Andric const ConstraintSatisfaction &Satisfaction) 467bdd1243dSDimitry Andric : NestedRequirement(InvalidConstraintEntity, 468bdd1243dSDimitry Andric ASTConstraintSatisfaction::Create(C, Satisfaction)) {} 469bdd1243dSDimitry Andric hasInvalidConstraint()470bdd1243dSDimitry Andric bool hasInvalidConstraint() const { return HasInvalidConstraint; } 471bdd1243dSDimitry Andric getInvalidConstraintEntity()472bdd1243dSDimitry Andric StringRef getInvalidConstraintEntity() { 473bdd1243dSDimitry Andric assert(hasInvalidConstraint()); 474bdd1243dSDimitry Andric return InvalidConstraintEntity; 47555e4f9d5SDimitry Andric } 47655e4f9d5SDimitry Andric getConstraintExpr()47755e4f9d5SDimitry Andric Expr *getConstraintExpr() const { 478bdd1243dSDimitry Andric assert(!hasInvalidConstraint() && 479bdd1243dSDimitry Andric "getConstraintExpr() may not be called " 480bdd1243dSDimitry Andric "on nested requirements with invalid constraint."); 481bdd1243dSDimitry Andric return Constraint; 48255e4f9d5SDimitry Andric } 48355e4f9d5SDimitry Andric getConstraintSatisfaction()48455e4f9d5SDimitry Andric const ASTConstraintSatisfaction &getConstraintSatisfaction() const { 48555e4f9d5SDimitry Andric return *Satisfaction; 48655e4f9d5SDimitry Andric } 48755e4f9d5SDimitry Andric classof(const Requirement * R)48855e4f9d5SDimitry Andric static bool classof(const Requirement *R) { 48955e4f9d5SDimitry Andric return R->getKind() == RK_Nested; 49055e4f9d5SDimitry Andric } 49155e4f9d5SDimitry Andric }; 49255e4f9d5SDimitry Andric 4938a4dda33SDimitry Andric using EntityPrinter = llvm::function_ref<void(llvm::raw_ostream &)>; 4948a4dda33SDimitry Andric 4958a4dda33SDimitry Andric /// \brief create a Requirement::SubstitutionDiagnostic with only a 4968a4dda33SDimitry Andric /// SubstitutedEntity and DiagLoc using Sema's allocator. 4978a4dda33SDimitry Andric Requirement::SubstitutionDiagnostic * 4988a4dda33SDimitry Andric createSubstDiagAt(Sema &S, SourceLocation Location, EntityPrinter Printer); 4998a4dda33SDimitry Andric 50055e4f9d5SDimitry Andric } // namespace concepts 50155e4f9d5SDimitry Andric 50255e4f9d5SDimitry Andric /// C++2a [expr.prim.req]: 50355e4f9d5SDimitry Andric /// A requires-expression provides a concise way to express requirements on 50455e4f9d5SDimitry Andric /// template arguments. A requirement is one that can be checked by name 50555e4f9d5SDimitry Andric /// lookup (6.4) or by checking properties of types and expressions. 50655e4f9d5SDimitry Andric /// [...] 50755e4f9d5SDimitry Andric /// A requires-expression is a prvalue of type bool [...] 50855e4f9d5SDimitry Andric class RequiresExpr final : public Expr, 50955e4f9d5SDimitry Andric llvm::TrailingObjects<RequiresExpr, ParmVarDecl *, 51055e4f9d5SDimitry Andric concepts::Requirement *> { 51155e4f9d5SDimitry Andric friend TrailingObjects; 51255e4f9d5SDimitry Andric friend class ASTStmtReader; 51355e4f9d5SDimitry Andric 51455e4f9d5SDimitry Andric unsigned NumLocalParameters; 51555e4f9d5SDimitry Andric unsigned NumRequirements; 51655e4f9d5SDimitry Andric RequiresExprBodyDecl *Body; 517*5f757f3fSDimitry Andric SourceLocation LParenLoc; 518*5f757f3fSDimitry Andric SourceLocation RParenLoc; 51955e4f9d5SDimitry Andric SourceLocation RBraceLoc; 52055e4f9d5SDimitry Andric numTrailingObjects(OverloadToken<ParmVarDecl * >)52155e4f9d5SDimitry Andric unsigned numTrailingObjects(OverloadToken<ParmVarDecl *>) const { 52255e4f9d5SDimitry Andric return NumLocalParameters; 52355e4f9d5SDimitry Andric } 52455e4f9d5SDimitry Andric numTrailingObjects(OverloadToken<concepts::Requirement * >)52555e4f9d5SDimitry Andric unsigned numTrailingObjects(OverloadToken<concepts::Requirement *>) const { 52655e4f9d5SDimitry Andric return NumRequirements; 52755e4f9d5SDimitry Andric } 52855e4f9d5SDimitry Andric 52955e4f9d5SDimitry Andric RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, 530*5f757f3fSDimitry Andric RequiresExprBodyDecl *Body, SourceLocation LParenLoc, 53155e4f9d5SDimitry Andric ArrayRef<ParmVarDecl *> LocalParameters, 532*5f757f3fSDimitry Andric SourceLocation RParenLoc, 53355e4f9d5SDimitry Andric ArrayRef<concepts::Requirement *> Requirements, 53455e4f9d5SDimitry Andric SourceLocation RBraceLoc); 53555e4f9d5SDimitry Andric RequiresExpr(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters, 53655e4f9d5SDimitry Andric unsigned NumRequirements); 53755e4f9d5SDimitry Andric 53855e4f9d5SDimitry Andric public: 539*5f757f3fSDimitry Andric static RequiresExpr *Create(ASTContext &C, SourceLocation RequiresKWLoc, 540*5f757f3fSDimitry Andric RequiresExprBodyDecl *Body, 541*5f757f3fSDimitry Andric SourceLocation LParenLoc, 542*5f757f3fSDimitry Andric ArrayRef<ParmVarDecl *> LocalParameters, 543*5f757f3fSDimitry Andric SourceLocation RParenLoc, 54455e4f9d5SDimitry Andric ArrayRef<concepts::Requirement *> Requirements, 54555e4f9d5SDimitry Andric SourceLocation RBraceLoc); 54655e4f9d5SDimitry Andric static RequiresExpr * 54755e4f9d5SDimitry Andric Create(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters, 54855e4f9d5SDimitry Andric unsigned NumRequirements); 54955e4f9d5SDimitry Andric getLocalParameters()55055e4f9d5SDimitry Andric ArrayRef<ParmVarDecl *> getLocalParameters() const { 55155e4f9d5SDimitry Andric return {getTrailingObjects<ParmVarDecl *>(), NumLocalParameters}; 55255e4f9d5SDimitry Andric } 55355e4f9d5SDimitry Andric getBody()55455e4f9d5SDimitry Andric RequiresExprBodyDecl *getBody() const { return Body; } 55555e4f9d5SDimitry Andric getRequirements()55655e4f9d5SDimitry Andric ArrayRef<concepts::Requirement *> getRequirements() const { 55755e4f9d5SDimitry Andric return {getTrailingObjects<concepts::Requirement *>(), NumRequirements}; 55855e4f9d5SDimitry Andric } 55955e4f9d5SDimitry Andric 56055e4f9d5SDimitry Andric /// \brief Whether or not the requires clause is satisfied. 56155e4f9d5SDimitry Andric /// The expression must not be dependent. isSatisfied()56255e4f9d5SDimitry Andric bool isSatisfied() const { 56355e4f9d5SDimitry Andric assert(!isValueDependent() 56455e4f9d5SDimitry Andric && "isSatisfied called on a dependent RequiresExpr"); 56555e4f9d5SDimitry Andric return RequiresExprBits.IsSatisfied; 56655e4f9d5SDimitry Andric } 56755e4f9d5SDimitry Andric setSatisfied(bool IsSatisfied)568bdd1243dSDimitry Andric void setSatisfied(bool IsSatisfied) { 569bdd1243dSDimitry Andric assert(!isValueDependent() && 570bdd1243dSDimitry Andric "setSatisfied called on a dependent RequiresExpr"); 571bdd1243dSDimitry Andric RequiresExprBits.IsSatisfied = IsSatisfied; 572bdd1243dSDimitry Andric } 573bdd1243dSDimitry Andric getRequiresKWLoc()57455e4f9d5SDimitry Andric SourceLocation getRequiresKWLoc() const { 57555e4f9d5SDimitry Andric return RequiresExprBits.RequiresKWLoc; 57655e4f9d5SDimitry Andric } 57755e4f9d5SDimitry Andric getLParenLoc()578*5f757f3fSDimitry Andric SourceLocation getLParenLoc() const { return LParenLoc; } getRParenLoc()579*5f757f3fSDimitry Andric SourceLocation getRParenLoc() const { return RParenLoc; } getRBraceLoc()58055e4f9d5SDimitry Andric SourceLocation getRBraceLoc() const { return RBraceLoc; } 58155e4f9d5SDimitry Andric classof(const Stmt * T)58255e4f9d5SDimitry Andric static bool classof(const Stmt *T) { 58355e4f9d5SDimitry Andric return T->getStmtClass() == RequiresExprClass; 58455e4f9d5SDimitry Andric } 58555e4f9d5SDimitry Andric getBeginLoc()58655e4f9d5SDimitry Andric SourceLocation getBeginLoc() const LLVM_READONLY { 58755e4f9d5SDimitry Andric return RequiresExprBits.RequiresKWLoc; 58855e4f9d5SDimitry Andric } getEndLoc()58955e4f9d5SDimitry Andric SourceLocation getEndLoc() const LLVM_READONLY { 59055e4f9d5SDimitry Andric return RBraceLoc; 59155e4f9d5SDimitry Andric } 59255e4f9d5SDimitry Andric 59355e4f9d5SDimitry Andric // Iterators children()59455e4f9d5SDimitry Andric child_range children() { 59555e4f9d5SDimitry Andric return child_range(child_iterator(), child_iterator()); 59655e4f9d5SDimitry Andric } children()59755e4f9d5SDimitry Andric const_child_range children() const { 59855e4f9d5SDimitry Andric return const_child_range(const_child_iterator(), const_child_iterator()); 59955e4f9d5SDimitry Andric } 60055e4f9d5SDimitry Andric }; 60155e4f9d5SDimitry Andric 60255e4f9d5SDimitry Andric } // namespace clang 60355e4f9d5SDimitry Andric 60455e4f9d5SDimitry Andric #endif // LLVM_CLANG_AST_EXPRCONCEPTS_H 605