diff options
Diffstat (limited to 'contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h')
-rw-r--r-- | contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h | 228 |
1 files changed, 137 insertions, 91 deletions
diff --git a/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h b/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h index 1544c498ef66..29913fd84c58 100644 --- a/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h +++ b/contrib/llvm-project/clang/include/clang/AST/ExprConcepts.h @@ -14,19 +14,21 @@ #ifndef LLVM_CLANG_AST_EXPRCONCEPTS_H #define LLVM_CLANG_AST_EXPRCONCEPTS_H -#include "clang/AST/ASTContext.h" #include "clang/AST/ASTConcept.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclarationName.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/STLFunctionalExtras.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TrailingObjects.h" -#include <utility> #include <string> +#include <utility> namespace clang { class ASTStmtReader; @@ -37,74 +39,91 @@ class ASTStmtWriter; /// /// According to C++2a [expr.prim.id]p3 an id-expression that denotes the /// specialization of a concept results in a prvalue of type bool. -class ConceptSpecializationExpr final : public Expr, public ConceptReference, - private llvm::TrailingObjects<ConceptSpecializationExpr, - TemplateArgument> { +class ConceptSpecializationExpr final : public Expr { + friend class ASTReader; friend class ASTStmtReader; - friend TrailingObjects; -public: - using SubstitutionDiagnostic = std::pair<SourceLocation, std::string>; -protected: - /// \brief The number of template arguments in the tail-allocated list of - /// converted template arguments. - unsigned NumTemplateArgs; +private: + ConceptReference *ConceptRef; + + /// \brief The Implicit Concept Specialization Decl, which holds the template + /// arguments for this specialization. + ImplicitConceptSpecializationDecl *SpecDecl; /// \brief Information about the satisfaction of the named concept with the /// given arguments. If this expression is value dependent, this is to be /// ignored. ASTConstraintSatisfaction *Satisfaction; - ConceptSpecializationExpr(const ASTContext &C, NestedNameSpecifierLoc NNS, - SourceLocation TemplateKWLoc, - DeclarationNameInfo ConceptNameInfo, - NamedDecl *FoundDecl, ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - ArrayRef<TemplateArgument> ConvertedArgs, + ConceptSpecializationExpr(const ASTContext &C, ConceptReference *ConceptRef, + ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction); - ConceptSpecializationExpr(const ASTContext &C, ConceptDecl *NamedConcept, - ArrayRef<TemplateArgument> ConvertedArgs, + ConceptSpecializationExpr(const ASTContext &C, ConceptReference *ConceptRef, + ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction, bool Dependent, bool ContainsUnexpandedParameterPack); - - ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs); + ConceptSpecializationExpr(EmptyShell Empty); public: - static ConceptSpecializationExpr * - Create(const ASTContext &C, NestedNameSpecifierLoc NNS, - SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, - NamedDecl *FoundDecl, ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - ArrayRef<TemplateArgument> ConvertedArgs, + Create(const ASTContext &C, ConceptReference *ConceptRef, + ImplicitConceptSpecializationDecl *SpecDecl, const ConstraintSatisfaction *Satisfaction); static ConceptSpecializationExpr * - Create(const ASTContext &C, ConceptDecl *NamedConcept, - ArrayRef<TemplateArgument> ConvertedArgs, - const ConstraintSatisfaction *Satisfaction, - bool Dependent, + Create(const ASTContext &C, ConceptReference *ConceptRef, + ImplicitConceptSpecializationDecl *SpecDecl, + const ConstraintSatisfaction *Satisfaction, bool Dependent, bool ContainsUnexpandedParameterPack); - static ConceptSpecializationExpr * - Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs); - ArrayRef<TemplateArgument> getTemplateArguments() const { - return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(), - NumTemplateArgs); + return SpecDecl->getTemplateArguments(); + } + + ConceptReference *getConceptReference() const { return ConceptRef; } + + ConceptDecl *getNamedConcept() const { return ConceptRef->getNamedConcept(); } + + // FIXME: Several of the following functions can be removed. Instead the + // caller can directly work with the ConceptReference. + bool hasExplicitTemplateArgs() const { + return ConceptRef->hasExplicitTemplateArgs(); + } + + SourceLocation getConceptNameLoc() const { + return ConceptRef->getConceptNameLoc(); + } + const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { + return ConceptRef->getTemplateArgsAsWritten(); + } + + const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { + return ConceptRef->getNestedNameSpecifierLoc(); + } + + SourceLocation getTemplateKWLoc() const { + return ConceptRef->getTemplateKWLoc(); } - /// \brief Set new template arguments for this concept specialization. - void setTemplateArguments(ArrayRef<TemplateArgument> Converted); + NamedDecl *getFoundDecl() const { return ConceptRef->getFoundDecl(); } + + const DeclarationNameInfo &getConceptNameInfo() const { + return ConceptRef->getConceptNameInfo(); + } + + const ImplicitConceptSpecializationDecl *getSpecializationDecl() const { + assert(SpecDecl && "Template Argument Decl not initialized"); + return SpecDecl; + } /// \brief Whether or not the concept with the given arguments was satisfied /// when the expression was created. /// The expression must not be dependent. bool isSatisfied() const { - assert(!isValueDependent() - && "isSatisfied called on a dependent ConceptSpecializationExpr"); + assert(!isValueDependent() && + "isSatisfied called on a dependent ConceptSpecializationExpr"); return Satisfaction->IsSatisfied; } @@ -112,8 +131,8 @@ public: /// satisfaction of the named concept. /// The expression must not be dependent. const ASTConstraintSatisfaction &getSatisfaction() const { - assert(!isValueDependent() - && "getSatisfaction called on dependent ConceptSpecializationExpr"); + assert(!isValueDependent() && + "getSatisfaction called on dependent ConceptSpecializationExpr"); return *Satisfaction; } @@ -122,15 +141,15 @@ public: } SourceLocation getBeginLoc() const LLVM_READONLY { - return ConceptName.getBeginLoc(); + return ConceptRef->getBeginLoc(); } SourceLocation getEndLoc() const LLVM_READONLY { - // If the ConceptSpecializationExpr is the ImmediatelyDeclaredConstraint - // of a TypeConstraint written syntactically as a constrained-parameter, - // there may not be a template argument list. - return ArgsAsWritten->RAngleLoc.isValid() ? ArgsAsWritten->RAngleLoc - : ConceptName.getEndLoc(); + return ConceptRef->getEndLoc(); + } + + SourceLocation getExprLoc() const LLVM_READONLY { + return ConceptRef->getLocation(); } // Iterators @@ -154,8 +173,11 @@ public: private: const RequirementKind Kind; // FIXME: use RequirementDependence to model dependence? + LLVM_PREFERRED_TYPE(bool) bool Dependent : 1; + LLVM_PREFERRED_TYPE(bool) bool ContainsUnexpandedParameterPack : 1; + LLVM_PREFERRED_TYPE(bool) bool Satisfied : 1; public: struct SubstitutionDiagnostic { @@ -275,12 +297,12 @@ public: friend ASTStmtWriter; /// \brief No return type requirement was specified. - ReturnTypeRequirement() : TypeConstraintInfo(nullptr, 0) {} + ReturnTypeRequirement() : TypeConstraintInfo(nullptr, false) {} /// \brief A return type requirement was specified but it was a /// substitution failure. ReturnTypeRequirement(SubstitutionDiagnostic *SubstDiag) : - TypeConstraintInfo(SubstDiag, 0) {} + TypeConstraintInfo(SubstDiag, false) {} /// \brief A 'type constraint' style return type requirement. /// \param TPL an invented template parameter list containing a single @@ -405,57 +427,61 @@ public: /// \brief A requires-expression requirement which is satisfied when a general /// constraint expression is satisfied ('nested' requirements). class NestedRequirement : public Requirement { - llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> Value; + Expr *Constraint = nullptr; const ASTConstraintSatisfaction *Satisfaction = nullptr; + bool HasInvalidConstraint = false; + StringRef InvalidConstraintEntity; public: friend ASTStmtReader; friend ASTStmtWriter; - NestedRequirement(SubstitutionDiagnostic *SubstDiag) : - Requirement(RK_Nested, /*Dependent=*/false, - /*ContainsUnexpandedParameterPack*/false, - /*Satisfied=*/false), Value(SubstDiag) {} - - NestedRequirement(Expr *Constraint) : - Requirement(RK_Nested, /*Dependent=*/true, - Constraint->containsUnexpandedParameterPack()), - Value(Constraint) { + NestedRequirement(Expr *Constraint) + : Requirement(RK_Nested, /*IsDependent=*/true, + Constraint->containsUnexpandedParameterPack()), + Constraint(Constraint) { assert(Constraint->isInstantiationDependent() && "Nested requirement with non-dependent constraint must be " "constructed with a ConstraintSatisfaction object"); } NestedRequirement(ASTContext &C, Expr *Constraint, - const ConstraintSatisfaction &Satisfaction) : - Requirement(RK_Nested, Constraint->isInstantiationDependent(), - Constraint->containsUnexpandedParameterPack(), - Satisfaction.IsSatisfied), - Value(Constraint), - Satisfaction(ASTConstraintSatisfaction::Create(C, Satisfaction)) {} - - bool isSubstitutionFailure() const { - return Value.is<SubstitutionDiagnostic *>(); - } - - SubstitutionDiagnostic *getSubstitutionDiagnostic() const { - assert(isSubstitutionFailure() && - "getSubstitutionDiagnostic() may not be called when there was no " - "substitution failure."); - return Value.get<SubstitutionDiagnostic *>(); + const ConstraintSatisfaction &Satisfaction) + : Requirement(RK_Nested, Constraint->isInstantiationDependent(), + Constraint->containsUnexpandedParameterPack(), + Satisfaction.IsSatisfied), + Constraint(Constraint), + Satisfaction(ASTConstraintSatisfaction::Create(C, Satisfaction)) {} + + NestedRequirement(StringRef InvalidConstraintEntity, + const ASTConstraintSatisfaction *Satisfaction) + : Requirement(RK_Nested, + /*IsDependent=*/false, + /*ContainsUnexpandedParameterPack*/ false, + Satisfaction->IsSatisfied), + Satisfaction(Satisfaction), HasInvalidConstraint(true), + InvalidConstraintEntity(InvalidConstraintEntity) {} + + NestedRequirement(ASTContext &C, StringRef InvalidConstraintEntity, + const ConstraintSatisfaction &Satisfaction) + : NestedRequirement(InvalidConstraintEntity, + ASTConstraintSatisfaction::Create(C, Satisfaction)) {} + + bool hasInvalidConstraint() const { return HasInvalidConstraint; } + + StringRef getInvalidConstraintEntity() { + assert(hasInvalidConstraint()); + return InvalidConstraintEntity; } Expr *getConstraintExpr() const { - assert(!isSubstitutionFailure() && "getConstraintExpr() may not be called " - "on nested requirements with " - "substitution failures."); - return Value.get<Expr *>(); + assert(!hasInvalidConstraint() && + "getConstraintExpr() may not be called " + "on nested requirements with invalid constraint."); + return Constraint; } const ASTConstraintSatisfaction &getConstraintSatisfaction() const { - assert(!isSubstitutionFailure() && "getConstraintSatisfaction() may not be " - "called on nested requirements with " - "substitution failures."); return *Satisfaction; } @@ -464,6 +490,13 @@ public: } }; +using EntityPrinter = llvm::function_ref<void(llvm::raw_ostream &)>; + +/// \brief create a Requirement::SubstitutionDiagnostic with only a +/// SubstitutedEntity and DiagLoc using Sema's allocator. +Requirement::SubstitutionDiagnostic * +createSubstDiagAt(Sema &S, SourceLocation Location, EntityPrinter Printer); + } // namespace concepts /// C++2a [expr.prim.req]: @@ -481,6 +514,8 @@ class RequiresExpr final : public Expr, unsigned NumLocalParameters; unsigned NumRequirements; RequiresExprBodyDecl *Body; + SourceLocation LParenLoc; + SourceLocation RParenLoc; SourceLocation RBraceLoc; unsigned numTrailingObjects(OverloadToken<ParmVarDecl *>) const { @@ -492,19 +527,22 @@ class RequiresExpr final : public Expr, } RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, - RequiresExprBodyDecl *Body, + RequiresExprBodyDecl *Body, SourceLocation LParenLoc, ArrayRef<ParmVarDecl *> LocalParameters, + SourceLocation RParenLoc, ArrayRef<concepts::Requirement *> Requirements, SourceLocation RBraceLoc); RequiresExpr(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters, unsigned NumRequirements); public: - static RequiresExpr * - Create(ASTContext &C, SourceLocation RequiresKWLoc, - RequiresExprBodyDecl *Body, ArrayRef<ParmVarDecl *> LocalParameters, - ArrayRef<concepts::Requirement *> Requirements, - SourceLocation RBraceLoc); + static RequiresExpr *Create(ASTContext &C, SourceLocation RequiresKWLoc, + RequiresExprBodyDecl *Body, + SourceLocation LParenLoc, + ArrayRef<ParmVarDecl *> LocalParameters, + SourceLocation RParenLoc, + ArrayRef<concepts::Requirement *> Requirements, + SourceLocation RBraceLoc); static RequiresExpr * Create(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters, unsigned NumRequirements); @@ -527,10 +565,18 @@ public: return RequiresExprBits.IsSatisfied; } + void setSatisfied(bool IsSatisfied) { + assert(!isValueDependent() && + "setSatisfied called on a dependent RequiresExpr"); + RequiresExprBits.IsSatisfied = IsSatisfied; + } + SourceLocation getRequiresKWLoc() const { return RequiresExprBits.RequiresKWLoc; } + SourceLocation getLParenLoc() const { return LParenLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } SourceLocation getRBraceLoc() const { return RBraceLoc; } static bool classof(const Stmt *T) { |