From baa84d8cde940278d6fb37917ac0d64c127b528f Mon Sep 17 00:00:00 2001 From: Saar Raz Date: Sat, 18 Jan 2020 14:58:01 +0200 Subject: [PATCH] Revert "[Concepts] Requires Expressions" This reverts commit 027931899763409e2c61a84bdee6057b5e838ffa. There have been some failing tests on some platforms, reverting while investigating. --- clang/include/clang/AST/ASTConcept.h | 1 - clang/include/clang/AST/DeclCXX.h | 31 - clang/include/clang/AST/ExprCXX.h | 94 +++ clang/include/clang/AST/ExprConcepts.h | 537 ------------------ clang/include/clang/AST/RecursiveASTVisitor.h | 25 - clang/include/clang/AST/Stmt.h | 12 - clang/include/clang/AST/StmtVisitor.h | 1 - clang/include/clang/Basic/DeclNodes.td | 1 - .../clang/Basic/DiagnosticParseKinds.td | 27 - .../clang/Basic/DiagnosticSemaKinds.td | 66 +-- clang/include/clang/Basic/StmtNodes.td | 1 - clang/include/clang/Parse/Parser.h | 3 +- clang/include/clang/Sema/DeclSpec.h | 9 +- clang/include/clang/Sema/Sema.h | 84 +-- clang/include/clang/Sema/SemaConcept.h | 7 - .../include/clang/Serialization/ASTBitCodes.h | 4 - clang/lib/AST/CMakeLists.txt | 1 - clang/lib/AST/DeclBase.cpp | 2 - clang/lib/AST/DeclCXX.cpp | 10 - clang/lib/AST/Expr.cpp | 1 - clang/lib/AST/ExprCXX.cpp | 79 ++- clang/lib/AST/ExprClassification.cpp | 1 - clang/lib/AST/ExprConcepts.cpp | 185 ------ clang/lib/AST/ExprConstant.cpp | 5 - clang/lib/AST/ItaniumMangle.cpp | 2 - clang/lib/AST/Stmt.cpp | 1 - clang/lib/AST/StmtPrinter.cpp | 54 -- clang/lib/AST/StmtProfile.cpp | 43 -- clang/lib/CodeGen/CGDecl.cpp | 1 - clang/lib/CodeGen/CGExprScalar.cpp | 4 - clang/lib/Frontend/FrontendActions.cpp | 4 - clang/lib/Frontend/InitPreprocessor.cpp | 3 - clang/lib/Parse/ParseDecl.cpp | 20 +- clang/lib/Parse/ParseExpr.cpp | 4 - clang/lib/Parse/ParseExprCXX.cpp | 326 +---------- clang/lib/Sema/Sema.cpp | 3 +- clang/lib/Sema/SemaConcept.cpp | 207 +------ clang/lib/Sema/SemaDecl.cpp | 2 - clang/lib/Sema/SemaExceptionSpec.cpp | 1 - clang/lib/Sema/SemaExpr.cpp | 13 +- clang/lib/Sema/SemaExprCXX.cpp | 213 ------- clang/lib/Sema/SemaLookup.cpp | 4 +- clang/lib/Sema/SemaTemplate.cpp | 127 ++--- clang/lib/Sema/SemaTemplateInstantiate.cpp | 250 +------- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 6 - clang/lib/Sema/SemaType.cpp | 6 - clang/lib/Sema/TreeTransform.h | 220 +------ clang/lib/Serialization/ASTCommon.cpp | 1 - clang/lib/Serialization/ASTReaderDecl.cpp | 7 - clang/lib/Serialization/ASTReaderStmt.cpp | 162 +----- clang/lib/Serialization/ASTWriter.cpp | 1 - clang/lib/Serialization/ASTWriterDecl.cpp | 5 - clang/lib/Serialization/ASTWriterStmt.cpp | 105 +--- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 1 - .../expr.prim.req/compound-requirement.cpp | 175 ------ .../expr.prim/expr.prim.req/equivalence.cpp | 125 ---- .../expr.prim.req/nested-requirement.cpp | 46 -- .../CXX/expr/expr.prim/expr.prim.req/p3.cpp | 37 -- .../expr.prim/expr.prim.req/requires-expr.cpp | 68 --- .../expr.prim.req/simple-requirement.cpp | 106 ---- .../expr.prim.req/type-requirement.cpp | 194 ------- clang/test/PCH/cxx2a-requires-expr.cpp | 20 - .../Parser/cxx2a-concepts-requires-expr.cpp | 141 ----- .../instantiate-requires-expr.cpp | 216 ------- clang/tools/libclang/CIndex.cpp | 1 - clang/tools/libclang/CXCursor.cpp | 1 - 66 files changed, 302 insertions(+), 3811 deletions(-) delete mode 100644 clang/include/clang/AST/ExprConcepts.h delete mode 100644 clang/lib/AST/ExprConcepts.cpp delete mode 100644 clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp delete mode 100644 clang/test/CXX/expr/expr.prim/expr.prim.req/equivalence.cpp delete mode 100644 clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp delete mode 100644 clang/test/CXX/expr/expr.prim/expr.prim.req/p3.cpp delete mode 100644 clang/test/CXX/expr/expr.prim/expr.prim.req/requires-expr.cpp delete mode 100644 clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp delete mode 100644 clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp delete mode 100644 clang/test/PCH/cxx2a-requires-expr.cpp delete mode 100644 clang/test/Parser/cxx2a-concepts-requires-expr.cpp delete mode 100644 clang/test/SemaTemplate/instantiate-requires-expr.cpp diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h index 84a611c14e0b2..896d857d8c96c 100644 --- a/clang/include/clang/AST/ASTConcept.h +++ b/clang/include/clang/AST/ASTConcept.h @@ -22,7 +22,6 @@ #include namespace clang { class ConceptDecl; -class ConceptSpecializationExpr; /// \brief The result of a constraint satisfaction check, containing the /// necessary information to diagnose an unsatisfied constraint. diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 2e8e31dbf4c7b..b716ea453a5a0 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -1893,37 +1893,6 @@ class CXXDeductionGuideDecl : public FunctionDecl { static bool classofKind(Kind K) { return K == CXXDeductionGuide; } }; -/// \brief Represents the body of a requires-expression. -/// -/// This decl exists merely to serve as the DeclContext for the local -/// parameters of the requires expression as well as other declarations inside -/// it. -/// -/// \code -/// template requires requires (T t) { {t++} -> regular; } -/// \endcode -/// -/// In this example, a RequiresExpr object will be generated for the expression, -/// and a RequiresExprBodyDecl will be created to hold the parameter t and the -/// template argument list imposed by the compound requirement. -class RequiresExprBodyDecl : public Decl, public DeclContext { - RequiresExprBodyDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc) - : Decl(RequiresExprBody, DC, StartLoc), DeclContext(RequiresExprBody) {} - -public: - friend class ASTDeclReader; - friend class ASTDeclWriter; - - static RequiresExprBodyDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc); - - static RequiresExprBodyDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == RequiresExprBody; } -}; - /// Represents a static or instance method of a struct/union/class. /// /// In the terminology of the C++ Standard, these are the (static and diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index cea360d12e91e..2c29409e0ca57 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_EXPRCXX_H #define LLVM_CLANG_AST_EXPRCXX_H +#include "clang/AST/ASTConcept.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" @@ -4835,6 +4836,99 @@ class BuiltinBitCastExpr final } }; +/// \brief Represents the specialization of a concept - evaluates to a prvalue +/// of type bool. +/// +/// 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 { + friend class ASTStmtReader; + friend TrailingObjects; +public: + using SubstitutionDiagnostic = std::pair; + +protected: + /// \brief The number of template arguments in the tail-allocated list of + /// converted template arguments. + unsigned NumTemplateArgs; + + /// \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 ConvertedArgs, + const ConstraintSatisfaction *Satisfaction); + + ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs); + +public: + + static ConceptSpecializationExpr * + Create(const ASTContext &C, NestedNameSpecifierLoc NNS, + SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, + NamedDecl *FoundDecl, ConceptDecl *NamedConcept, + const ASTTemplateArgumentListInfo *ArgsAsWritten, + ArrayRef ConvertedArgs, + const ConstraintSatisfaction *Satisfaction); + + static ConceptSpecializationExpr * + Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs); + + ArrayRef getTemplateArguments() const { + return ArrayRef(getTrailingObjects(), + NumTemplateArgs); + } + + /// \brief Set new template arguments for this concept specialization. + void setTemplateArguments(ArrayRef Converted); + + /// \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"); + return Satisfaction->IsSatisfied; + } + + /// \brief Get elaborated satisfaction info about the template arguments' + /// satisfaction of the named concept. + /// The expression must not be dependent. + const ASTConstraintSatisfaction &getSatisfaction() const { + assert(!isValueDependent() + && "getSatisfaction called on dependent ConceptSpecializationExpr"); + return *Satisfaction; + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ConceptSpecializationExprClass; + } + + SourceLocation getBeginLoc() const LLVM_READONLY { + return ConceptName.getBeginLoc(); + } + + SourceLocation getEndLoc() const LLVM_READONLY { + return ArgsAsWritten->RAngleLoc; + } + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + } // namespace clang #endif // LLVM_CLANG_AST_EXPRCXX_H diff --git a/clang/include/clang/AST/ExprConcepts.h b/clang/include/clang/AST/ExprConcepts.h deleted file mode 100644 index 8d0de0b6e99c1..0000000000000 --- a/clang/include/clang/AST/ExprConcepts.h +++ /dev/null @@ -1,537 +0,0 @@ -//===- ExprConcepts.h - C++2a Concepts expressions --------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file -/// Defines Expressions and AST nodes for C++2a concepts. -// -//===----------------------------------------------------------------------===// - -#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/Decl.h" -#include "clang/AST/DeclarationName.h" -#include "clang/AST/DeclTemplate.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/Support/TrailingObjects.h" -#include -#include - -namespace clang { -class ASTStmtReader; -class ASTStmtWriter; - -/// \brief Represents the specialization of a concept - evaluates to a prvalue -/// of type bool. -/// -/// 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 { - friend class ASTStmtReader; - friend TrailingObjects; -public: - using SubstitutionDiagnostic = std::pair; - -protected: - /// \brief The number of template arguments in the tail-allocated list of - /// converted template arguments. - unsigned NumTemplateArgs; - - /// \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 ConvertedArgs, - const ConstraintSatisfaction *Satisfaction); - - ConceptSpecializationExpr(EmptyShell Empty, unsigned NumTemplateArgs); - -public: - - static ConceptSpecializationExpr * - Create(const ASTContext &C, NestedNameSpecifierLoc NNS, - SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, - NamedDecl *FoundDecl, ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - ArrayRef ConvertedArgs, - const ConstraintSatisfaction *Satisfaction); - - static ConceptSpecializationExpr * - Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs); - - ArrayRef getTemplateArguments() const { - return ArrayRef(getTrailingObjects(), - NumTemplateArgs); - } - - /// \brief Set new template arguments for this concept specialization. - void setTemplateArguments(ArrayRef Converted); - - /// \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"); - return Satisfaction->IsSatisfied; - } - - /// \brief Get elaborated satisfaction info about the template arguments' - /// satisfaction of the named concept. - /// The expression must not be dependent. - const ASTConstraintSatisfaction &getSatisfaction() const { - assert(!isValueDependent() - && "getSatisfaction called on dependent ConceptSpecializationExpr"); - return *Satisfaction; - } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == ConceptSpecializationExprClass; - } - - SourceLocation getBeginLoc() const LLVM_READONLY { - return ConceptName.getBeginLoc(); - } - - SourceLocation getEndLoc() const LLVM_READONLY { - return ArgsAsWritten->RAngleLoc; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } - const_child_range children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); - } -}; - -namespace concepts { - -/// \brief A static requirement that can be used in a requires-expression to -/// check properties of types and expression. -class Requirement { -public: - // Note - simple and compound requirements are both represented by the same - // class (ExprRequirement). - enum RequirementKind { RK_Type, RK_Simple, RK_Compound, RK_Nested }; -private: - const RequirementKind Kind; - bool Dependent : 1; - bool ContainsUnexpandedParameterPack : 1; - bool Satisfied : 1; -public: - struct SubstitutionDiagnostic { - StringRef SubstitutedEntity; - // FIXME: Store diagnostics semantically and not as prerendered strings. - // Fixing this probably requires serialization of PartialDiagnostic - // objects. - SourceLocation DiagLoc; - StringRef DiagMessage; - }; - - Requirement(RequirementKind Kind, bool IsDependent, - bool ContainsUnexpandedParameterPack, bool IsSatisfied = true) : - Kind(Kind), Dependent(IsDependent), - ContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack), - Satisfied(IsSatisfied) {} - - RequirementKind getKind() const { return Kind; } - - bool isSatisfied() const { - assert(!Dependent && - "isSatisfied can only be called on non-dependent requirements."); - return Satisfied; - } - - void setSatisfied(bool IsSatisfied) { - assert(!Dependent && - "setSatisfied can only be called on non-dependent requirements."); - Satisfied = IsSatisfied; - } - - void setDependent(bool IsDependent) { Dependent = IsDependent; } - bool isDependent() const { return Dependent; } - - void setContainsUnexpandedParameterPack(bool Contains) { - ContainsUnexpandedParameterPack = Contains; - } - bool containsUnexpandedParameterPack() const { - return ContainsUnexpandedParameterPack; - } -}; - -/// \brief A requires-expression requirement which queries the existence of a -/// type name or type template specialization ('type' requirements). -class TypeRequirement : public Requirement { -public: - enum SatisfactionStatus { - SS_Dependent, - SS_SubstitutionFailure, - SS_Satisfied - }; -private: - llvm::PointerUnion Value; - SatisfactionStatus Status; -public: - friend ASTStmtReader; - friend ASTStmtWriter; - - /// \brief Construct a type requirement from a type. If the given type is not - /// dependent, this indicates that the type exists and the requirement will be - /// satisfied. Otherwise, the SubstitutionDiagnostic constructor is to be - /// used. - TypeRequirement(TypeSourceInfo *T); - - /// \brief Construct a type requirement when the nested name specifier is - /// invalid due to a bad substitution. The requirement is unsatisfied. - TypeRequirement(SubstitutionDiagnostic *Diagnostic) : - Requirement(RK_Type, false, false, false), Value(Diagnostic), - Status(SS_SubstitutionFailure) {} - - SatisfactionStatus getSatisfactionStatus() const { return Status; } - void setSatisfactionStatus(SatisfactionStatus Status) { - this->Status = Status; - } - - bool isSubstitutionFailure() const { - return Status == SS_SubstitutionFailure; - } - - SubstitutionDiagnostic *getSubstitutionDiagnostic() const { - assert(Status == SS_SubstitutionFailure && - "Attempted to get substitution diagnostic when there has been no " - "substitution failure."); - return Value.get(); - } - - TypeSourceInfo *getType() const { - assert(!isSubstitutionFailure() && - "Attempted to get type when there has been a substitution failure."); - return Value.get(); - } - - static bool classof(const Requirement *R) { - return R->getKind() == RK_Type; - } -}; - -/// \brief A requires-expression requirement which queries the validity and -/// properties of an expression ('simple' and 'compound' requirements). -class ExprRequirement : public Requirement { -public: - enum SatisfactionStatus { - SS_Dependent, - SS_ExprSubstitutionFailure, - SS_NoexceptNotMet, - SS_TypeRequirementSubstitutionFailure, - SS_ConstraintsNotSatisfied, - SS_Satisfied - }; - class ReturnTypeRequirement { - llvm::PointerIntPair< - llvm::PointerUnion, - 2, int> - TypeConstraintInfo; - public: - friend ASTStmtReader; - friend ASTStmtWriter; - - /// \brief No return type requirement was specified. - ReturnTypeRequirement() : TypeConstraintInfo(nullptr, 0) {} - - /// \brief A return type requirement was specified but it was a - /// substitution failure. - ReturnTypeRequirement(SubstitutionDiagnostic *SubstDiag) : - TypeConstraintInfo(SubstDiag, 0) {} - - /// \brief A 'type constraint' style return type requirement. - /// \param TPL an invented template parameter list containing a single - /// type parameter with a type-constraint. - // TODO: Can we maybe not save the whole template parameter list and just - // the type constraint? Saving the whole TPL makes it easier to handle in - // serialization but is less elegant. - ReturnTypeRequirement(TemplateParameterList *TPL); - - bool isDependent() const { - return TypeConstraintInfo.getInt() & 1; - } - - bool containsUnexpandedParameterPack() const { - return TypeConstraintInfo.getInt() & 2; - } - - bool isEmpty() const { - return TypeConstraintInfo.getPointer().isNull(); - } - - bool isSubstitutionFailure() const { - return !isEmpty() && - TypeConstraintInfo.getPointer().is(); - } - - bool isTypeConstraint() const { - return !isEmpty() && - TypeConstraintInfo.getPointer().is(); - } - - SubstitutionDiagnostic *getSubstitutionDiagnostic() const { - assert(isSubstitutionFailure()); - return TypeConstraintInfo.getPointer().get(); - } - - const TypeConstraint *getTypeConstraint() const; - - TemplateParameterList *getTypeConstraintTemplateParameterList() const { - assert(isTypeConstraint()); - return TypeConstraintInfo.getPointer().get(); - } - }; -private: - llvm::PointerUnion Value; - SourceLocation NoexceptLoc; // May be empty if noexcept wasn't specified. - ReturnTypeRequirement TypeReq; - ConceptSpecializationExpr *SubstitutedConstraintExpr; - SatisfactionStatus Status; -public: - friend ASTStmtReader; - friend ASTStmtWriter; - - /// \brief Construct a compound requirement. - /// \param E the expression which is checked by this requirement. - /// \param IsSimple whether this was a simple requirement in source. - /// \param NoexceptLoc the location of the noexcept keyword, if it was - /// specified, otherwise an empty location. - /// \param Req the requirement for the type of the checked expression. - /// \param Status the satisfaction status of this requirement. - ExprRequirement( - Expr *E, bool IsSimple, SourceLocation NoexceptLoc, - ReturnTypeRequirement Req, SatisfactionStatus Status, - ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr); - - /// \brief Construct a compound requirement whose expression was a - /// substitution failure. The requirement is not satisfied. - /// \param E the diagnostic emitted while instantiating the original - /// expression. - /// \param IsSimple whether this was a simple requirement in source. - /// \param NoexceptLoc the location of the noexcept keyword, if it was - /// specified, otherwise an empty location. - /// \param Req the requirement for the type of the checked expression (omit - /// if no requirement was specified). - ExprRequirement(SubstitutionDiagnostic *E, bool IsSimple, - SourceLocation NoexceptLoc, ReturnTypeRequirement Req = {}); - - bool isSimple() const { return getKind() == RK_Simple; } - bool isCompound() const { return getKind() == RK_Compound; } - - bool hasNoexceptRequirement() const { return NoexceptLoc.isValid(); } - SourceLocation getNoexceptLoc() const { return NoexceptLoc; } - - SatisfactionStatus getSatisfactionStatus() const { return Status; } - - bool isExprSubstitutionFailure() const { - return Status == SS_ExprSubstitutionFailure; - } - - const ReturnTypeRequirement &getReturnTypeRequirement() const { - return TypeReq; - } - - ConceptSpecializationExpr * - getReturnTypeRequirementSubstitutedConstraintExpr() const { - assert(Status >= SS_TypeRequirementSubstitutionFailure); - return SubstitutedConstraintExpr; - } - - SubstitutionDiagnostic *getExprSubstitutionDiagnostic() const { - assert(isExprSubstitutionFailure() && - "Attempted to get expression substitution diagnostic when there has " - "been no expression substitution failure"); - return Value.get(); - } - - Expr *getExpr() const { - assert(!isExprSubstitutionFailure() && - "ExprRequirement has no expression because there has been a " - "substitution failure."); - return Value.get(); - } - - static bool classof(const Requirement *R) { - return R->getKind() == RK_Compound || R->getKind() == RK_Simple; - } -}; - -/// \brief A requires-expression requirement which is satisfied when a general -/// constraint expression is satisfied ('nested' requirements). -class NestedRequirement : public Requirement { - llvm::PointerUnion Value; - const ASTConstraintSatisfaction *Satisfaction = nullptr; - -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) { - 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 *getSubstitutionDiagnostic() const { - assert(isSubstitutionFailure() && - "getSubstitutionDiagnostic() may not be called when there was no " - "substitution failure."); - return Value.get(); - } - - Expr *getConstraintExpr() const { - assert(!isSubstitutionFailure() && "getConstraintExpr() may not be called " - "on nested requirements with " - "substitution failures."); - return Value.get(); - } - - const ASTConstraintSatisfaction &getConstraintSatisfaction() const { - assert(!isSubstitutionFailure() && "getConstraintSatisfaction() may not be " - "called on nested requirements with " - "substitution failures."); - return *Satisfaction; - } - - static bool classof(const Requirement *R) { - return R->getKind() == RK_Nested; - } -}; - -} // namespace concepts - -/// C++2a [expr.prim.req]: -/// A requires-expression provides a concise way to express requirements on -/// template arguments. A requirement is one that can be checked by name -/// lookup (6.4) or by checking properties of types and expressions. -/// [...] -/// A requires-expression is a prvalue of type bool [...] -class RequiresExpr final : public Expr, - llvm::TrailingObjects { - friend TrailingObjects; - friend class ASTStmtReader; - - unsigned NumLocalParameters; - unsigned NumRequirements; - RequiresExprBodyDecl *Body; - SourceLocation RBraceLoc; - - unsigned numTrailingObjects(OverloadToken) const { - return NumLocalParameters; - } - - unsigned numTrailingObjects(OverloadToken) const { - return NumRequirements; - } - - RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, - RequiresExprBodyDecl *Body, - ArrayRef LocalParameters, - ArrayRef Requirements, - SourceLocation RBraceLoc); - RequiresExpr(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters, - unsigned NumRequirements); - -public: - static RequiresExpr * - Create(ASTContext &C, SourceLocation RequiresKWLoc, - RequiresExprBodyDecl *Body, ArrayRef LocalParameters, - ArrayRef Requirements, - SourceLocation RBraceLoc); - static RequiresExpr * - Create(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters, - unsigned NumRequirements); - - ArrayRef getLocalParameters() const { - return {getTrailingObjects(), NumLocalParameters}; - } - - RequiresExprBodyDecl *getBody() const { return Body; } - - ArrayRef getRequirements() const { - return {getTrailingObjects(), NumRequirements}; - } - - /// \brief Whether or not the requires clause is satisfied. - /// The expression must not be dependent. - bool isSatisfied() const { - assert(!isValueDependent() - && "isSatisfied called on a dependent RequiresExpr"); - return RequiresExprBits.IsSatisfied; - } - - SourceLocation getRequiresKWLoc() const { - return RequiresExprBits.RequiresKWLoc; - } - - SourceLocation getRBraceLoc() const { return RBraceLoc; } - - static bool classof(const Stmt *T) { - return T->getStmtClass() == RequiresExprClass; - } - - SourceLocation getBeginLoc() const LLVM_READONLY { - return RequiresExprBits.RequiresKWLoc; - } - SourceLocation getEndLoc() const LLVM_READONLY { - return RBraceLoc; - } - - // Iterators - child_range children() { - return child_range(child_iterator(), child_iterator()); - } - const_child_range children() const { - return const_child_range(const_child_iterator(), const_child_iterator()); - } -}; - -} // namespace clang - -#endif // LLVM_CLANG_AST_EXPRCONCEPTS_H \ No newline at end of file diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 4633122aba48e..f8ab8e451d8c3 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -23,7 +23,6 @@ #include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" -#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" @@ -2139,8 +2138,6 @@ DEF_TRAVERSE_DECL(ParmVarDecl, { TRY_TO(TraverseStmt(D->getDefaultArg())); }) -DEF_TRAVERSE_DECL(RequiresExprBodyDecl, {}) - #undef DEF_TRAVERSE_DECL // ----------------- Stmt traversal ----------------- @@ -2712,28 +2709,6 @@ DEF_TRAVERSE_STMT(ConceptSpecializationExpr, { TRY_TO(TraverseConceptReference(*S)); }) -DEF_TRAVERSE_STMT(RequiresExpr, { - TRY_TO(TraverseDecl(S->getBody())); - for (ParmVarDecl *Parm : S->getLocalParameters()) - TRY_TO(TraverseDecl(Parm)); - for (concepts::Requirement *Req : S->getRequirements()) - if (auto *TypeReq = dyn_cast(Req)) { - if (!TypeReq->isSubstitutionFailure()) - TRY_TO(TraverseTypeLoc(TypeReq->getType()->getTypeLoc())); - } else if (auto *ExprReq = dyn_cast(Req)) { - if (!ExprReq->isExprSubstitutionFailure()) - TRY_TO(TraverseStmt(ExprReq->getExpr())); - auto &RetReq = ExprReq->getReturnTypeRequirement(); - if (RetReq.isTypeConstraint()) - TRY_TO(TraverseTemplateParameterListHelper( - RetReq.getTypeConstraintTemplateParameterList())); - } else { - auto *NestedReq = cast(Req); - if (!NestedReq->isSubstitutionFailure()) - TRY_TO(TraverseStmt(NestedReq->getConstraintExpr())); - } -}) - // These literals (all of them) do not need any action. DEF_TRAVERSE_STMT(IntegerLiteral, {}) DEF_TRAVERSE_STMT(FixedPointLiteral, {}) diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index 253b76941991c..eaacb1a5b252e 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -910,17 +910,6 @@ class alignas(void *) Stmt { SourceLocation NameLoc; }; - class RequiresExprBitfields { - friend class ASTStmtReader; - friend class ASTStmtWriter; - friend class RequiresExpr; - - unsigned : NumExprBits; - - unsigned IsSatisfied : 1; - SourceLocation RequiresKWLoc; - }; - //===--- C++ Coroutines TS bitfields classes ---===// class CoawaitExprBitfields { @@ -1019,7 +1008,6 @@ class alignas(void *) Stmt { UnresolvedMemberExprBitfields UnresolvedMemberExprBits; CXXNoexceptExprBitfields CXXNoexceptExprBits; SubstNonTypeTemplateParmExprBitfields SubstNonTypeTemplateParmExprBits; - RequiresExprBitfields RequiresExprBits; // C++ Coroutines TS expressions CoawaitExprBitfields CoawaitBits; diff --git a/clang/include/clang/AST/StmtVisitor.h b/clang/include/clang/AST/StmtVisitor.h index 3e5155199eace..d3be93d228ccb 100644 --- a/clang/include/clang/AST/StmtVisitor.h +++ b/clang/include/clang/AST/StmtVisitor.h @@ -13,7 +13,6 @@ #ifndef LLVM_CLANG_AST_STMTVISITOR_H #define LLVM_CLANG_AST_STMTVISITOR_H -#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td index d5bbc604819f8..c2c23237285b2 100644 --- a/clang/include/clang/Basic/DeclNodes.td +++ b/clang/include/clang/Basic/DeclNodes.td @@ -100,6 +100,5 @@ def OMPThreadPrivate : DeclNode; def OMPAllocate : DeclNode; def OMPRequires : DeclNode; def Empty : DeclNode; -def RequiresExprBody : DeclNode, DeclContext; def LifetimeExtendedTemporary : DeclNode; diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 105ed7bf6c84d..41f788e7d9bdd 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -744,33 +744,6 @@ def err_friend_explicit_instantiation : Error< def err_explicit_instantiation_enum : Error< "enumerations cannot be explicitly instantiated">; def err_expected_template_parameter : Error<"expected template parameter">; -def note_ill_formed_requires_expression_outside_template : Note< - "requires expression outside a template declaration may not contain invalid " - "types or expressions">; -def err_empty_requires_expr : Error< - "a requires expression must contain at least one requirement">; -def err_requires_expr_parameter_list_ellipsis : Error< - "varargs not allowed in requires expression">; -def err_requires_expr_type_req_illegal_identifier : Error< - "expected identifier or template-id in type requirement">; -def err_requires_expr_type_req_template_args_on_non_template : Error< - "template arguments provided for non-template '%0'">; -def err_expected_semi_requirement : Error< - "expected ';' at end of requirement">; -def err_requires_expr_missing_arrow : Error< - "expected '->' before expression type requirement">; -def err_requires_expr_expected_type_constraint : Error< - "expected concept name with optional arguments">; -def err_requires_expr_simple_requirement_noexcept : Error< - "'noexcept' can only be used in a compound requirement (with '{' '}' around " - "the expression)">; -def err_requires_expr_simple_requirement_unexpected_tok : Error< - "unexpected %0 after expression; did you intend to use a compound " - "requirement (with '{' '}' around the expression)?">; -def warn_requires_expr_in_simple_requirement : Warning< - "this requires expression will only be checked for syntactic validity; did " - "you intend to place it in a nested requirement? (add another 'requires' " - "before the expression)">, InGroup>; def err_missing_dependent_template_keyword : Error< "use 'template' keyword to treat '%0' as a dependent template name">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index a4d0427108587..ffa326932a1cd 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2102,21 +2102,12 @@ def err_auto_not_allowed : Error< "|in template argument|in typedef|in type alias|in function return type" "|in conversion function type|here|in lambda parameter" "|in type allocated by 'new'|in K&R-style function parameter" - "|in template parameter|in friend declaration" - "|in requires expression parameter}1">; -def err_auto_not_allowed_in_return_type_requirement : Error< - "%select{'auto'|'decltype(auto)'|'__auto_type'}0 not allowed in expression " - "type requirement">; + "|in template parameter|in friend declaration}1">; def err_dependent_deduced_tst : Error< "typename specifier refers to " "%select{class template|function template|variable template|alias template|" "template template parameter|template}0 member in %1; " "argument deduction not allowed here">; -def err_deduced_tst : Error< - "typename specifier refers to " - "%select{class template|function template|variable template|alias template|" - "template template parameter|template}0; argument deduction not allowed " - "here">; def err_auto_not_allowed_var_inst : Error< "'auto' variable template instantiation is not allowed">; def err_auto_var_requires_init : Error< @@ -2599,56 +2590,19 @@ def note_constraints_not_satisfied : Note< def note_substituted_constraint_expr_is_ill_formed : Note< "because substituted constraint expression is ill-formed%0">; def note_atomic_constraint_evaluated_to_false : Note< - "%select{and|because}0 '%1' evaluated to false">; + "%select{and |because }0'%1' evaluated to false">; def note_concept_specialization_constraint_evaluated_to_false : Note< - "%select{and|because}0 '%1' evaluated to false">; + "%select{and |because }0'%1' evaluated to false">; def note_single_arg_concept_specialization_constraint_evaluated_to_false : Note< - "%select{and|because}0 %1 does not satisfy %2">; + "%select{and |because }0%1 does not satisfy %2">; def note_atomic_constraint_evaluated_to_false_elaborated : Note< - "%select{and|because}0 '%1' (%2 %3 %4) evaluated to false">; + "%select{and |because }0'%1' (%2 %3 %4) evaluated to false">; def err_constrained_virtual_method : Error< "virtual function cannot have a requires clause">; def err_trailing_requires_clause_on_deduction_guide : Error< "deduction guide cannot have a requires clause">; def err_reference_to_function_with_unsatisfied_constraints : Error< "invalid reference to function %0: constraints not satisfied">; -def note_requires_expr_ill_formed_expr : Note< - "expression is invalid: %0">; -def note_requires_expr_no_implicit_conversion : Note< - "no implicit conversion exists between expression type %0 and expected type " - "%1">; -def err_requires_expr_local_parameter_default_argument : Error< - "default arguments not allowed for parameters of a requires expression">; -def err_requires_expr_parameter_referenced_in_evaluated_context : Error< - "constraint variable %0 cannot be used in an evaluated context">; -def note_expr_requirement_expr_substitution_error : Note< - "%select{and|because}0 '%1' would be invalid: %2">; -def note_expr_requirement_expr_unknown_substitution_error : Note< - "%select{and|because}0 '%1' would be invalid">; -def note_expr_requirement_noexcept_not_met : Note< - "%select{and|because}0 '%1' may throw an exception">; -def note_expr_requirement_type_requirement_substitution_error : Note< - "%select{and|because}0 '%1' would be invalid: %2">; -def note_expr_requirement_type_requirement_unknown_substitution_error : Note< - "%select{and|because}0 '%1' would be invalid">; -def note_expr_requirement_constraints_not_satisfied : Note< - "%select{and|because}0 type constraint '%1' was not satisfied:">; -def note_expr_requirement_constraints_not_satisfied_simple : Note< - "%select{and|because}0 %1 does not satisfy %2:">; -def note_type_requirement_substitution_error : Note< - "%select{and|because}0 '%1' would be invalid: %2">; -def note_type_requirement_unknown_substitution_error : Note< - "%select{and|because}0 '%1' would be invalid">; -def err_type_requirement_non_type_template : Error< - "'%0' refers to a %select{class template|function template|" - "variable template|alias template|template template parameter|template}1, " - "not a type template">; -def err_type_requirement_no_such_type : Error< - "'%0' does not name a type">; -def note_nested_requirement_substitution_error : Note< - "%select{and|because}0 '%1' would be invalid: %2">; -def note_nested_requirement_unknown_substitution_error : Note< - "%select{and|because}0 '%1' would be invalid">; def note_ambiguous_atomic_constraints : Note< "similar constraint expressions not considered equivalent; constraint " "expressions cannot be considered equivalent unless they originate from the " @@ -4634,8 +4588,6 @@ def note_template_type_alias_instantiation_here : Note< "in instantiation of template type alias %0 requested here">; def note_template_exception_spec_instantiation_here : Note< "in instantiation of exception specification for %0 requested here">; -def note_template_requirement_instantiation_here : Note< - "in instantiation of requirement here">; def warn_var_template_missing : Warning<"instantiation of variable %q0 " "required here, but no definition is available">, InGroup; @@ -4671,8 +4623,6 @@ def note_template_default_arg_checking : Note< "while checking a default template argument used here">; def note_concept_specialization_here : Note< "while checking the satisfaction of concept '%0' requested here">; -def note_nested_requirement_here : Note< - "while checking the satisfaction of nested requirement requested here">; def note_checking_constraints_for_template_id_here : Note< "while checking constraint satisfaction for template '%0' required here">; def note_checking_constraints_for_var_spec_id_here : Note< @@ -4806,12 +4756,8 @@ def err_typename_nested_not_found_requirement : Error< "declaration">; def err_typename_nested_not_type : Error< "typename specifier refers to non-type member %0 in %1">; -def err_typename_not_type : Error< - "typename specifier refers to non-type %0">; -def note_typename_member_refers_here : Note< - "referenced member %0 is declared here">; def note_typename_refers_here : Note< - "referenced %0 is declared here">; + "referenced member %0 is declared here">; def err_typename_missing : Error< "missing 'typename' prior to dependent type name '%0%1'">; def err_typename_missing_template : Error< diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td index 41923cddc4930..294993298a18a 100644 --- a/clang/include/clang/Basic/StmtNodes.td +++ b/clang/include/clang/Basic/StmtNodes.td @@ -164,7 +164,6 @@ def CoyieldExpr : StmtNode; // C++2a Concepts expressions def ConceptSpecializationExpr : StmtNode; -def RequiresExpr : StmtNode; // Obj-C Expressions. def ObjCStringLiteral : StmtNode; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 41f46861d0895..182024ea51080 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -1933,7 +1933,6 @@ class Parser : public CodeCompletionHandler { //===--------------------------------------------------------------------===// // C++ Concepts - ExprResult ParseRequiresExpression(); void ParseTrailingRequiresClause(Declarator &D); //===--------------------------------------------------------------------===// @@ -2772,7 +2771,7 @@ class Parser : public CodeCompletionHandler { Declarator &D, SmallVectorImpl &ParamInfo); void ParseParameterDeclarationClause( - DeclaratorContext DeclaratorContext, + Declarator &D, ParsedAttributes &attrs, SmallVectorImpl &ParamInfo, SourceLocation &EllipsisLoc); diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 1222549161e4d..aceec9cbe1c9e 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1757,8 +1757,7 @@ enum class DeclaratorContext { TemplateArgContext, // Any template argument (in template argument list). TemplateTypeArgContext, // Template type argument (in default argument). AliasDeclContext, // C++11 alias-declaration. - AliasTemplateContext, // C++11 alias-declaration template. - RequiresExprContext // C++2a requires-expression. + AliasTemplateContext // C++11 alias-declaration template. }; @@ -1982,7 +1981,6 @@ class Declarator { case DeclaratorContext::TemplateTypeArgContext: case DeclaratorContext::TrailingReturnContext: case DeclaratorContext::TrailingReturnVarContext: - case DeclaratorContext::RequiresExprContext: return true; } llvm_unreachable("unknown context kind!"); @@ -2005,7 +2003,6 @@ class Declarator { case DeclaratorContext::TemplateParamContext: case DeclaratorContext::CXXCatchContext: case DeclaratorContext::ObjCCatchContext: - case DeclaratorContext::RequiresExprContext: return true; case DeclaratorContext::TypeNameContext: @@ -2042,7 +2039,6 @@ class Declarator { case DeclaratorContext::MemberContext: case DeclaratorContext::PrototypeContext: case DeclaratorContext::TemplateParamContext: - case DeclaratorContext::RequiresExprContext: // Maybe one day... return false; @@ -2120,7 +2116,6 @@ class Declarator { case DeclaratorContext::TemplateArgContext: case DeclaratorContext::TemplateTypeArgContext: case DeclaratorContext::TrailingReturnContext: - case DeclaratorContext::RequiresExprContext: return false; } llvm_unreachable("unknown context kind!"); @@ -2342,7 +2337,6 @@ class Declarator { case DeclaratorContext::TemplateTypeArgContext: case DeclaratorContext::TrailingReturnContext: case DeclaratorContext::TrailingReturnVarContext: - case DeclaratorContext::RequiresExprContext: return false; } llvm_unreachable("unknown context kind!"); @@ -2376,7 +2370,6 @@ class Declarator { case DeclaratorContext::TrailingReturnContext: case DeclaratorContext::TrailingReturnVarContext: case DeclaratorContext::TemplateTypeArgContext: - case DeclaratorContext::RequiresExprContext: return false; case DeclaratorContext::BlockContext: diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 2fb758bc75d61..4d76c877d31b5 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -21,7 +21,6 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" -#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExternalASTSource.h" @@ -6283,17 +6282,13 @@ class Sema final { /// \brief Emit diagnostics explaining why a constraint expression was deemed /// unsatisfied. - /// \param First whether this is the first time an unsatisfied constraint is - /// diagnosed for this error. void - DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, - bool First = true); + DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction); /// \brief Emit diagnostics explaining why a constraint expression was deemed /// unsatisfied. void - DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction, - bool First = true); + DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction& Satisfaction); /// \brief Emit diagnostics explaining why a constraint expression was deemed /// unsatisfied because it was ill-formed. @@ -7267,17 +7262,7 @@ class Sema final { SourceLocation KeywordLoc, NestedNameSpecifierLoc QualifierLoc, const IdentifierInfo &II, - SourceLocation IILoc, - TypeSourceInfo **TSI, - bool DeducedTSTContext); - - QualType CheckTypenameType(ElaboratedTypeKeyword Keyword, - SourceLocation KeywordLoc, - NestedNameSpecifierLoc QualifierLoc, - const IdentifierInfo &II, - SourceLocation IILoc, - bool DeducedTSTContext = true); - + SourceLocation IILoc); TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T, SourceLocation Loc, @@ -7297,52 +7282,11 @@ class Sema final { const TemplateArgument *Args, unsigned NumArgs); - //===--------------------------------------------------------------------===// - // C++ Concepts - //===--------------------------------------------------------------------===// + // Concepts Decl *ActOnConceptDefinition( Scope *S, MultiTemplateParamsArg TemplateParameterLists, IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr); - RequiresExprBodyDecl * - ActOnStartRequiresExpr(SourceLocation RequiresKWLoc, - ArrayRef LocalParameters, - Scope *BodyScope); - void ActOnFinishRequiresExpr(); - concepts::Requirement *ActOnSimpleRequirement(Expr *E); - concepts::Requirement *ActOnTypeRequirement( - SourceLocation TypenameKWLoc, CXXScopeSpec &SS, SourceLocation NameLoc, - IdentifierInfo *TypeName, TemplateIdAnnotation *TemplateId); - concepts::Requirement *ActOnCompoundRequirement(Expr *E, - SourceLocation NoexceptLoc); - concepts::Requirement * - ActOnCompoundRequirement( - Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS, - TemplateIdAnnotation *TypeConstraint, unsigned Depth); - concepts::Requirement *ActOnNestedRequirement(Expr *Constraint); - concepts::ExprRequirement * - BuildExprRequirement( - Expr *E, bool IsSatisfied, SourceLocation NoexceptLoc, - concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement); - concepts::ExprRequirement * - BuildExprRequirement( - concepts::Requirement::SubstitutionDiagnostic *ExprSubstDiag, - bool IsSatisfied, SourceLocation NoexceptLoc, - concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement); - concepts::TypeRequirement *BuildTypeRequirement(TypeSourceInfo *Type); - concepts::TypeRequirement * - BuildTypeRequirement( - concepts::Requirement::SubstitutionDiagnostic *SubstDiag); - concepts::NestedRequirement *BuildNestedRequirement(Expr *E); - concepts::NestedRequirement * - BuildNestedRequirement( - concepts::Requirement::SubstitutionDiagnostic *SubstDiag); - ExprResult ActOnRequiresExpr(SourceLocation RequiresKWLoc, - RequiresExprBodyDecl *Body, - ArrayRef LocalParameters, - ArrayRef Requirements, - SourceLocation ClosingBraceLoc); - //===--------------------------------------------------------------------===// // C++ Variadic Templates (C++0x [temp.variadic]) //===--------------------------------------------------------------------===// @@ -7989,13 +7933,6 @@ class Sema final { /// template which was deferred until it was needed. ExceptionSpecInstantiation, - /// We are instantiating a requirement of a requires expression. - RequirementInstantiation, - - /// We are checking the satisfaction of a nested requirement of a requires - /// expression. - NestedRequirementConstraintsCheck, - /// We are declaring an implicit special member function. DeclaringSpecialMember, @@ -8317,19 +8254,6 @@ class Sema final { ParameterMappingSubstitution, NamedDecl *Template, SourceRange InstantiationRange); - /// \brief Note that we are substituting template arguments into a part of - /// a requirement of a requires expression. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - concepts::Requirement *Req, - sema::TemplateDeductionInfo &DeductionInfo, - SourceRange InstantiationRange = SourceRange()); - - /// \brief Note that we are checking the satisfaction of the constraint - /// expression inside of a nested requirement. - InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, - concepts::NestedRequirement *Req, ConstraintsCheck, - SourceRange InstantiationRange = SourceRange()); - /// Note that we have finished instantiating this template. void Clear(); diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h index 7fc42a4816ec0..acd1e604211a1 100644 --- a/clang/include/clang/Sema/SemaConcept.h +++ b/clang/include/clang/Sema/SemaConcept.h @@ -13,17 +13,10 @@ #ifndef LLVM_CLANG_SEMA_SEMACONCEPT_H #define LLVM_CLANG_SEMA_SEMACONCEPT_H -#include "clang/AST/ASTConcept.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" -#include -#include - namespace clang { class Sema; diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 44a12c875da7d..1bfcbda8c9f1e 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -1403,9 +1403,6 @@ namespace serialization { /// An LifetimeExtendedTemporaryDecl record. DECL_LIFETIME_EXTENDED_TEMPORARY, - /// A RequiresExprBodyDecl record. - DECL_REQUIRES_EXPR_BODY, - /// An ObjCTypeParamDecl record. DECL_OBJC_TYPE_PARAM, @@ -1788,7 +1785,6 @@ namespace serialization { EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr EXPR_CXX_FOLD, // CXXFoldExpr EXPR_CONCEPT_SPECIALIZATION,// ConceptSpecializationExpr - EXPR_REQUIRES, // RequiresExpr // CUDA EXPR_CUDA_KERNEL_CALL, // CUDAKernelCallExpr diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index e79c245d2f8c4..bd9b0934591c5 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -46,7 +46,6 @@ add_clang_library(clangAST DeclTemplate.cpp Expr.cpp ExprClassification.cpp - ExprConcepts.cpp ExprConstant.cpp ExprCXX.cpp ExprObjC.cpp diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index cb4d61cac2c71..6ee767ccecf7d 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -804,7 +804,6 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case OMPCapturedExpr: case Empty: case LifetimeExtendedTemporary: - case RequiresExprBody: // Never looked up by name. return 0; } @@ -1178,7 +1177,6 @@ DeclContext *DeclContext::getPrimaryContext() { case Decl::Captured: case Decl::OMPDeclareReduction: case Decl::OMPDeclareMapper: - case Decl::RequiresExprBody: // There is only one DeclContext for these entities. return this; diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 48e310e858b26..2ead1e70ea0d6 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1968,16 +1968,6 @@ CXXDeductionGuideDecl *CXXDeductionGuideDecl::CreateDeserialized(ASTContext &C, QualType(), nullptr, SourceLocation()); } -RequiresExprBodyDecl *RequiresExprBodyDecl::Create( - ASTContext &C, DeclContext *DC, SourceLocation StartLoc) { - return new (C, DC) RequiresExprBodyDecl(C, DC, StartLoc); -} - -RequiresExprBodyDecl *RequiresExprBodyDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { - return new (C, ID) RequiresExprBodyDecl(C, nullptr, SourceLocation()); -} - void CXXMethodDecl::anchor() {} bool CXXMethodDecl::isStatic() const { diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 8351989587662..73ddbc62482dd 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -3457,7 +3457,6 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case OpaqueValueExprClass: case SourceLocExprClass: case ConceptSpecializationExprClass: - case RequiresExprClass: // These never have a side-effect. return false; diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index e4bd218ae2d36..422227d787b10 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -17,7 +17,6 @@ #include "clang/AST/DeclAccessPair.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/LambdaCapture.h" @@ -1765,3 +1764,81 @@ CUDAKernelCallExpr *CUDAKernelCallExpr::CreateEmpty(const ASTContext &Ctx, alignof(CUDAKernelCallExpr)); return new (Mem) CUDAKernelCallExpr(NumArgs, Empty); } + +ConceptSpecializationExpr::ConceptSpecializationExpr(const ASTContext &C, + NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, + DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, + ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten, + ArrayRef ConvertedArgs, + const ConstraintSatisfaction *Satisfaction) + : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary, + /*TypeDependent=*/false, + // All the flags below are set in setTemplateArguments. + /*ValueDependent=*/!Satisfaction, /*InstantiationDependent=*/false, + /*ContainsUnexpandedParameterPacks=*/false), + ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl, + NamedConcept, ArgsAsWritten), + NumTemplateArgs(ConvertedArgs.size()), + Satisfaction(Satisfaction ? + ASTConstraintSatisfaction::Create(C, *Satisfaction) : + nullptr) { + setTemplateArguments(ConvertedArgs); +} + +ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty, + unsigned NumTemplateArgs) + : Expr(ConceptSpecializationExprClass, Empty), ConceptReference(), + NumTemplateArgs(NumTemplateArgs) { } + +void ConceptSpecializationExpr::setTemplateArguments( + ArrayRef Converted) { + assert(Converted.size() == NumTemplateArgs); + std::uninitialized_copy(Converted.begin(), Converted.end(), + getTrailingObjects()); + bool IsInstantiationDependent = false; + bool ContainsUnexpandedParameterPack = false; + for (const TemplateArgument& Arg : Converted) { + if (Arg.isInstantiationDependent()) + IsInstantiationDependent = true; + if (Arg.containsUnexpandedParameterPack()) + ContainsUnexpandedParameterPack = true; + if (ContainsUnexpandedParameterPack && IsInstantiationDependent) + break; + } + + // Currently guaranteed by the fact concepts can only be at namespace-scope. + assert(!NestedNameSpec || + (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() && + !NestedNameSpec.getNestedNameSpecifier() + ->containsUnexpandedParameterPack())); + setInstantiationDependent(IsInstantiationDependent); + setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack); + assert((!isValueDependent() || isInstantiationDependent()) && + "should not be value-dependent"); +} + +ConceptSpecializationExpr * +ConceptSpecializationExpr::Create(const ASTContext &C, + NestedNameSpecifierLoc NNS, + SourceLocation TemplateKWLoc, + DeclarationNameInfo ConceptNameInfo, + NamedDecl *FoundDecl, + ConceptDecl *NamedConcept, + const ASTTemplateArgumentListInfo *ArgsAsWritten, + ArrayRef ConvertedArgs, + const ConstraintSatisfaction *Satisfaction) { + void *Buffer = C.Allocate(totalSizeToAlloc( + ConvertedArgs.size())); + return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc, + ConceptNameInfo, FoundDecl, + NamedConcept, ArgsAsWritten, + ConvertedArgs, Satisfaction); +} + +ConceptSpecializationExpr * +ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty, + unsigned NumTemplateArgs) { + void *Buffer = C.Allocate(totalSizeToAlloc( + NumTemplateArgs)); + return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs); +} diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp index d201af31f521e..9dbf6fe9e0f06 100644 --- a/clang/lib/AST/ExprClassification.cpp +++ b/clang/lib/AST/ExprClassification.cpp @@ -193,7 +193,6 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { case Expr::DesignatedInitUpdateExprClass: case Expr::SourceLocExprClass: case Expr::ConceptSpecializationExprClass: - case Expr::RequiresExprClass: return Cl::CL_PRValue; case Expr::ConstantExprClass: diff --git a/clang/lib/AST/ExprConcepts.cpp b/clang/lib/AST/ExprConcepts.cpp deleted file mode 100644 index 76d57ed5d5b1f..0000000000000 --- a/clang/lib/AST/ExprConcepts.cpp +++ /dev/null @@ -1,185 +0,0 @@ -//===- ExprCXX.cpp - (C++) Expression AST Node Implementation -------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file implements the subclesses of Expr class declared in ExprCXX.h -// -//===----------------------------------------------------------------------===// - -#include "clang/AST/ExprConcepts.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/ASTConcept.h" -#include "clang/AST/Decl.h" -#include "clang/AST/DeclarationName.h" -#include "clang/AST/DeclTemplate.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/Support/TrailingObjects.h" -#include -#include -#include - -using namespace clang; - -ConceptSpecializationExpr::ConceptSpecializationExpr(const ASTContext &C, - NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, - DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, - ConceptDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten, - ArrayRef ConvertedArgs, - const ConstraintSatisfaction *Satisfaction) - : Expr(ConceptSpecializationExprClass, C.BoolTy, VK_RValue, OK_Ordinary, - /*TypeDependent=*/false, - // All the flags below are set in setTemplateArguments. - /*ValueDependent=*/!Satisfaction, /*InstantiationDependent=*/false, - /*ContainsUnexpandedParameterPacks=*/false), - ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl, - NamedConcept, ArgsAsWritten), - NumTemplateArgs(ConvertedArgs.size()), - Satisfaction(Satisfaction ? - ASTConstraintSatisfaction::Create(C, *Satisfaction) : - nullptr) { - setTemplateArguments(ConvertedArgs); -} - -ConceptSpecializationExpr::ConceptSpecializationExpr(EmptyShell Empty, - unsigned NumTemplateArgs) - : Expr(ConceptSpecializationExprClass, Empty), ConceptReference(), - NumTemplateArgs(NumTemplateArgs) { } - -void ConceptSpecializationExpr::setTemplateArguments( - ArrayRef Converted) { - assert(Converted.size() == NumTemplateArgs); - std::uninitialized_copy(Converted.begin(), Converted.end(), - getTrailingObjects()); - bool IsInstantiationDependent = false; - bool ContainsUnexpandedParameterPack = false; - for (const TemplateArgument& Arg : Converted) { - if (Arg.isInstantiationDependent()) - IsInstantiationDependent = true; - if (Arg.containsUnexpandedParameterPack()) - ContainsUnexpandedParameterPack = true; - if (ContainsUnexpandedParameterPack && IsInstantiationDependent) - break; - } - - // Currently guaranteed by the fact concepts can only be at namespace-scope. - assert(!NestedNameSpec || - (!NestedNameSpec.getNestedNameSpecifier()->isInstantiationDependent() && - !NestedNameSpec.getNestedNameSpecifier() - ->containsUnexpandedParameterPack())); - setInstantiationDependent(IsInstantiationDependent); - setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack); - assert((!isValueDependent() || isInstantiationDependent()) && - "should not be value-dependent"); -} - -ConceptSpecializationExpr * -ConceptSpecializationExpr::Create(const ASTContext &C, - NestedNameSpecifierLoc NNS, - SourceLocation TemplateKWLoc, - DeclarationNameInfo ConceptNameInfo, - NamedDecl *FoundDecl, - ConceptDecl *NamedConcept, - const ASTTemplateArgumentListInfo *ArgsAsWritten, - ArrayRef ConvertedArgs, - const ConstraintSatisfaction *Satisfaction) { - void *Buffer = C.Allocate(totalSizeToAlloc( - ConvertedArgs.size())); - return new (Buffer) ConceptSpecializationExpr(C, NNS, TemplateKWLoc, - ConceptNameInfo, FoundDecl, - NamedConcept, ArgsAsWritten, - ConvertedArgs, Satisfaction); -} - -ConceptSpecializationExpr * -ConceptSpecializationExpr::Create(ASTContext &C, EmptyShell Empty, - unsigned NumTemplateArgs) { - void *Buffer = C.Allocate(totalSizeToAlloc( - NumTemplateArgs)); - return new (Buffer) ConceptSpecializationExpr(Empty, NumTemplateArgs); -} - -const TypeConstraint * -concepts::ExprRequirement::ReturnTypeRequirement::getTypeConstraint() const { - assert(isTypeConstraint()); - auto TPL = - TypeConstraintInfo.getPointer().get(); - return cast(TPL->getParam(0)) - ->getTypeConstraint(); -} - -RequiresExpr::RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc, - RequiresExprBodyDecl *Body, - ArrayRef LocalParameters, - ArrayRef Requirements, - SourceLocation RBraceLoc) - : Expr(RequiresExprClass, C.BoolTy, VK_RValue, OK_Ordinary, - /*TD=*/false, /*VD=*/false, /*ID=*/false, - /*ContainsUnexpandedParameterPack=*/false), - NumLocalParameters(LocalParameters.size()), - NumRequirements(Requirements.size()), Body(Body), RBraceLoc(RBraceLoc) { - RequiresExprBits.IsSatisfied = false; - RequiresExprBits.RequiresKWLoc = RequiresKWLoc; - bool Dependent = false; - bool ContainsUnexpandedParameterPack = false; - for (ParmVarDecl *P : LocalParameters) { - Dependent |= P->getType()->isInstantiationDependentType(); - ContainsUnexpandedParameterPack |= - P->getType()->containsUnexpandedParameterPack(); - } - RequiresExprBits.IsSatisfied = true; - for (concepts::Requirement *R : Requirements) { - Dependent |= R->isDependent(); - ContainsUnexpandedParameterPack |= R->containsUnexpandedParameterPack(); - if (!Dependent) { - RequiresExprBits.IsSatisfied = R->isSatisfied(); - if (!RequiresExprBits.IsSatisfied) - break; - } - } - std::copy(LocalParameters.begin(), LocalParameters.end(), - getTrailingObjects()); - std::copy(Requirements.begin(), Requirements.end(), - getTrailingObjects()); - RequiresExprBits.IsSatisfied |= Dependent; - setValueDependent(Dependent); - setInstantiationDependent(Dependent); - setContainsUnexpandedParameterPack(ContainsUnexpandedParameterPack); -} - -RequiresExpr::RequiresExpr(ASTContext &C, EmptyShell Empty, - unsigned NumLocalParameters, - unsigned NumRequirements) - : Expr(RequiresExprClass, Empty), NumLocalParameters(NumLocalParameters), - NumRequirements(NumRequirements) { } - -RequiresExpr * -RequiresExpr::Create(ASTContext &C, SourceLocation RequiresKWLoc, - RequiresExprBodyDecl *Body, - ArrayRef LocalParameters, - ArrayRef Requirements, - SourceLocation RBraceLoc) { - void *Mem = - C.Allocate(totalSizeToAlloc( - LocalParameters.size(), Requirements.size()), - alignof(RequiresExpr)); - return new (Mem) RequiresExpr(C, RequiresKWLoc, Body, LocalParameters, - Requirements, RBraceLoc); -} - -RequiresExpr * -RequiresExpr::Create(ASTContext &C, EmptyShell Empty, - unsigned NumLocalParameters, unsigned NumRequirements) { - void *Mem = - C.Allocate(totalSizeToAlloc( - NumLocalParameters, NumRequirements), - alignof(RequiresExpr)); - return new (Mem) RequiresExpr(C, Empty, NumLocalParameters, NumRequirements); -} diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index c79973507323d..c4b27b5d1daa2 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -9912,7 +9912,6 @@ class IntExprEvaluator bool VisitSizeOfPackExpr(const SizeOfPackExpr *E); bool VisitSourceLocExpr(const SourceLocExpr *E); bool VisitConceptSpecializationExpr(const ConceptSpecializationExpr *E); - bool VisitRequiresExpr(const RequiresExpr *E); // FIXME: Missing: array subscript of vector, member of vector }; @@ -12525,9 +12524,6 @@ bool IntExprEvaluator::VisitConceptSpecializationExpr( return Success(E->isSatisfied(), E); } -bool IntExprEvaluator::VisitRequiresExpr(const RequiresExpr *E) { - return Success(E->isSatisfied(), E); -} bool FixedPointExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { switch (E->getOpcode()) { @@ -14186,7 +14182,6 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) { case Expr::CXXScalarValueInitExprClass: case Expr::TypeTraitExprClass: case Expr::ConceptSpecializationExprClass: - case Expr::RequiresExprClass: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: case Expr::CXXNoexceptExprClass: diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 5d485e000750b..0d567edac5216 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -22,7 +22,6 @@ #include "clang/AST/DeclOpenMP.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" -#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/TypeLoc.h" @@ -3669,7 +3668,6 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) { case Expr::ConvertVectorExprClass: case Expr::StmtExprClass: case Expr::TypeTraitExprClass: - case Expr::RequiresExprClass: case Expr::ArrayTypeTraitExprClass: case Expr::ExpressionTraitExprClass: case Expr::VAArgExprClass: diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 7409ae7ddc9e7..b6e4d8aff21e9 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -16,7 +16,6 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclGroup.h" #include "clang/AST/Expr.h" -#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 45fd8ceae8d36..c14bb886bb11a 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -2269,60 +2269,6 @@ void StmtPrinter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) { Policy); } -void StmtPrinter::VisitRequiresExpr(RequiresExpr *E) { - OS << "requires "; - auto LocalParameters = E->getLocalParameters(); - if (!LocalParameters.empty()) { - OS << "("; - for (ParmVarDecl *LocalParam : LocalParameters) { - PrintRawDecl(LocalParam); - if (LocalParam != LocalParameters.back()) - OS << ", "; - } - - OS << ") "; - } - OS << "{ "; - auto Requirements = E->getRequirements(); - for (concepts::Requirement *Req : Requirements) { - if (auto *TypeReq = dyn_cast(Req)) { - if (TypeReq->isSubstitutionFailure()) - OS << "<>"; - else - TypeReq->getType()->getType().print(OS, Policy); - } else if (auto *ExprReq = dyn_cast(Req)) { - if (ExprReq->isCompound()) - OS << "{ "; - if (ExprReq->isExprSubstitutionFailure()) - OS << "<>"; - else - PrintExpr(ExprReq->getExpr()); - if (ExprReq->isCompound()) { - OS << " }"; - if (ExprReq->getNoexceptLoc().isValid()) - OS << " noexcept"; - const auto &RetReq = ExprReq->getReturnTypeRequirement(); - if (!RetReq.isEmpty()) { - OS << " -> "; - if (RetReq.isSubstitutionFailure()) - OS << "<>"; - else if (RetReq.isTypeConstraint()) - RetReq.getTypeConstraint()->print(OS, Policy); - } - } - } else { - auto *NestedReq = cast(Req); - OS << "requires "; - if (NestedReq->isSubstitutionFailure()) - OS << "<>"; - else - PrintExpr(NestedReq->getConstraintExpr()); - } - OS << "; "; - } - OS << "}"; -} - // C++ Coroutines TS void StmtPrinter::VisitCoroutineBodyStmt(CoroutineBodyStmt *S) { diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 382ea5c8d7ef0..c0b0f3b0b064c 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -1340,49 +1340,6 @@ void StmtProfiler::VisitConceptSpecializationExpr( VisitTemplateArgument(Arg); } -void StmtProfiler::VisitRequiresExpr(const RequiresExpr *S) { - VisitExpr(S); - ID.AddInteger(S->getLocalParameters().size()); - for (ParmVarDecl *LocalParam : S->getLocalParameters()) - VisitDecl(LocalParam); - ID.AddInteger(S->getRequirements().size()); - for (concepts::Requirement *Req : S->getRequirements()) { - if (auto *TypeReq = dyn_cast(Req)) { - ID.AddInteger(concepts::Requirement::RK_Type); - ID.AddBoolean(TypeReq->isSubstitutionFailure()); - if (!TypeReq->isSubstitutionFailure()) - VisitType(TypeReq->getType()->getType()); - } else if (auto *ExprReq = dyn_cast(Req)) { - ID.AddInteger(concepts::Requirement::RK_Compound); - ID.AddBoolean(ExprReq->isExprSubstitutionFailure()); - if (!ExprReq->isExprSubstitutionFailure()) - Visit(ExprReq->getExpr()); - // C++2a [expr.prim.req.compound]p1 Example: - // [...] The compound-requirement in C1 requires that x++ is a valid - // expression. It is equivalent to the simple-requirement x++; [...] - // We therefore do not profile isSimple() here. - ID.AddBoolean(ExprReq->getNoexceptLoc().isValid()); - const concepts::ExprRequirement::ReturnTypeRequirement &RetReq = - ExprReq->getReturnTypeRequirement(); - if (RetReq.isEmpty()) { - ID.AddInteger(0); - } else if (RetReq.isTypeConstraint()) { - ID.AddInteger(1); - Visit(RetReq.getTypeConstraint()->getImmediatelyDeclaredConstraint()); - } else { - assert(RetReq.isSubstitutionFailure()); - ID.AddInteger(2); - } - } else { - ID.AddInteger(concepts::Requirement::RK_Nested); - auto *NestedReq = cast(Req); - ID.AddBoolean(NestedReq->isSubstitutionFailure()); - if (!NestedReq->isSubstitutionFailure()) - Visit(NestedReq->getConstraintExpr()); - } - } -} - static Stmt::StmtClass DecodeOperatorCall(const CXXOperatorCallExpr *S, UnaryOperatorKind &UnaryOp, BinaryOperatorKind &BinaryOp) { diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 60f1dba7c768a..5aac7a8d54c77 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -111,7 +111,6 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::Empty: case Decl::Concept: case Decl::LifetimeExtendedTemporary: - case Decl::RequiresExprBody: // None of these decls require codegen support. return; diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index de5c3a03fb68d..3f23fe11e4f58 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -680,10 +680,6 @@ class ScalarExprEmitter return Builder.getInt1(E->isSatisfied()); } - Value *VisitRequiresExpr(const RequiresExpr *E) { - return Builder.getInt1(E->isSatisfied()); - } - Value *VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) { return llvm::ConstantInt::get(Builder.getInt32Ty(), E->getValue()); } diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 935c64a0fa13f..8574d0a7e8132 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -429,10 +429,6 @@ class DefaultTemplateInstCallback : public TemplateInstantiationCallback { return "ConstraintNormalization"; case CodeSynthesisContext::ParameterMappingSubstitution: return "ParameterMappingSubstitution"; - case CodeSynthesisContext::RequirementInstantiation: - return "RequirementInstantiation"; - case CodeSynthesisContext::NestedRequirementConstraintsCheck: - return "NestedRequirementConstraintsCheck"; } return ""; } diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 42e6fd88515af..2c7e3a56c0436 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -385,9 +385,6 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, else Builder.defineMacro("__cplusplus", "199711L"); - if (LangOpts.ConceptsTS) - Builder.defineMacro("__cpp_concepts", "201707L"); - // C++1z [cpp.predefined]p1: // An integer literal of type std::size_t whose value is the alignment // guaranteed by a call to operator new(std::size_t) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 178cb1b661c73..192c0e99e5a5d 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -6366,7 +6366,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, ProhibitAttributes(FnAttrs); } else { if (Tok.isNot(tok::r_paren)) - ParseParameterDeclarationClause(D.getContext(), FirstArgAttrs, ParamInfo, + ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo, EllipsisLoc); else if (RequiresArg) Diag(Tok, diag::err_argument_required_after_attribute); @@ -6584,9 +6584,9 @@ void Parser::ParseFunctionDeclaratorIdentifierList( /// after the opening parenthesis. This function will not parse a K&R-style /// identifier list. /// -/// DeclContext is the context of the declarator being parsed. If FirstArgAttrs -/// is non-null, then the caller parsed those attributes immediately after the -/// open paren - they should be considered to be part of the first parameter. +/// D is the declarator being parsed. If FirstArgAttrs is non-null, then the +/// caller parsed those arguments immediately after the open paren - they should +/// be considered to be part of the first parameter. /// /// After returning, ParamInfo will hold the parsed parameters. EllipsisLoc will /// be the location of the ellipsis, if any was parsed. @@ -6612,7 +6612,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList( /// [C++11] attribute-specifier-seq parameter-declaration /// void Parser::ParseParameterDeclarationClause( - DeclaratorContext DeclaratorContext, + Declarator &D, ParsedAttributes &FirstArgAttrs, SmallVectorImpl &ParamInfo, SourceLocation &EllipsisLoc) { @@ -6661,11 +6661,9 @@ void Parser::ParseParameterDeclarationClause( // "LambdaExprParameterContext", because we must accept either // 'declarator' or 'abstract-declarator' here. Declarator ParmDeclarator( - DS, DeclaratorContext == DeclaratorContext::RequiresExprContext - ? DeclaratorContext::RequiresExprContext - : DeclaratorContext == DeclaratorContext::LambdaExprContext - ? DeclaratorContext::LambdaExprParameterContext - : DeclaratorContext::PrototypeContext); + DS, D.getContext() == DeclaratorContext::LambdaExprContext + ? DeclaratorContext::LambdaExprParameterContext + : DeclaratorContext::PrototypeContext); ParseDeclarator(ParmDeclarator); // Parse GNU attributes, if present. @@ -6719,7 +6717,7 @@ void Parser::ParseParameterDeclarationClause( SourceLocation EqualLoc = Tok.getLocation(); // Parse the default argument - if (DeclaratorContext == DeclaratorContext::MemberContext) { + if (D.getContext() == DeclaratorContext::MemberContext) { // If we're inside a class definition, cache the tokens // corresponding to the default argument. We'll actually parse // them when we see the end of the class definition. diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index df8388926db10..32dacbcc9646c 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -756,7 +756,6 @@ class CastExpressionIdValidator final : public CorrectionCandidateCallback { /// [C++11] user-defined-literal /// '(' expression ')' /// [C11] generic-selection -/// [C++2a] requires-expression /// '__func__' [C99 6.4.2.2] /// [GNU] '__FUNCTION__' /// [MS] '__FUNCDNAME__' @@ -1602,9 +1601,6 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, *NotPrimaryExpression = true; return ParseCXXDeleteExpression(false, Tok.getLocation()); - case tok::kw_requires: // [C++2a] requires-expression - return ParseRequiresExpression(); - case tok::kw_noexcept: { // [C++0x] 'noexcept' '(' expression ')' if (NotPrimaryExpression) *NotPrimaryExpression = true; diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 036eabb94dd7e..7d477d271dc2c 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -11,9 +11,7 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" #include "clang/AST/DeclTemplate.h" -#include "clang/AST/ExprCXX.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" @@ -1301,9 +1299,9 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( Actions.RecordParsingTemplateParameterDepth( CurTemplateDepthTracker.getOriginalDepth()); - ParseParameterDeclarationClause(D.getContext(), Attr, ParamInfo, - EllipsisLoc); - // For a generic lambda, each 'auto' within the parameter declaration + ParseParameterDeclarationClause(D, Attr, ParamInfo, EllipsisLoc); + + // For a generic lambda, each 'auto' within the parameter declaration // clause creates a template type parameter, so increment the depth. // If we've parsed any explicit template parameters, then the depth will // have already been incremented. So we make sure that at most a single @@ -3257,324 +3255,6 @@ Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) { return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, Operand.get()); } -/// ParseRequiresExpression - Parse a C++2a requires-expression. -/// C++2a [expr.prim.req]p1 -/// A requires-expression provides a concise way to express requirements on -/// template arguments. A requirement is one that can be checked by name -/// lookup (6.4) or by checking properties of types and expressions. -/// -/// requires-expression: -/// 'requires' requirement-parameter-list[opt] requirement-body -/// -/// requirement-parameter-list: -/// '(' parameter-declaration-clause[opt] ')' -/// -/// requirement-body: -/// '{' requirement-seq '}' -/// -/// requirement-seq: -/// requirement -/// requirement-seq requirement -/// -/// requirement: -/// simple-requirement -/// type-requirement -/// compound-requirement -/// nested-requirement -ExprResult Parser::ParseRequiresExpression() { - assert(Tok.is(tok::kw_requires) && "Expected 'requires' keyword"); - SourceLocation RequiresKWLoc = ConsumeToken(); // Consume 'requires' - - llvm::SmallVector LocalParameterDecls; - if (Tok.is(tok::l_paren)) { - // requirement parameter list is present. - ParseScope LocalParametersScope(this, Scope::FunctionPrototypeScope | - Scope::DeclScope); - BalancedDelimiterTracker Parens(*this, tok::l_paren); - Parens.consumeOpen(); - if (!Tok.is(tok::r_paren)) { - ParsedAttributes FirstArgAttrs(getAttrFactory()); - SourceLocation EllipsisLoc; - llvm::SmallVector LocalParameters; - DiagnosticErrorTrap Trap(Diags); - ParseParameterDeclarationClause(DeclaratorContext::RequiresExprContext, - FirstArgAttrs, LocalParameters, - EllipsisLoc); - if (EllipsisLoc.isValid()) - Diag(EllipsisLoc, diag::err_requires_expr_parameter_list_ellipsis); - for (auto &ParamInfo : LocalParameters) - LocalParameterDecls.push_back(cast(ParamInfo.Param)); - if (Trap.hasErrorOccurred()) - SkipUntil(tok::r_paren, StopBeforeMatch); - } - Parens.consumeClose(); - } - - BalancedDelimiterTracker Braces(*this, tok::l_brace); - if (Braces.expectAndConsume()) - return ExprError(); - - // Start of requirement list - llvm::SmallVector Requirements; - - // C++2a [expr.prim.req]p2 - // Expressions appearing within a requirement-body are unevaluated operands. - EnterExpressionEvaluationContext Ctx( - Actions, Sema::ExpressionEvaluationContext::Unevaluated); - - ParseScope BodyScope(this, Scope::DeclScope); - RequiresExprBodyDecl *Body = Actions.ActOnStartRequiresExpr( - RequiresKWLoc, LocalParameterDecls, getCurScope()); - - if (Tok.is(tok::r_brace)) { - // Grammar does not allow an empty body. - // requirement-body: - // { requirement-seq } - // requirement-seq: - // requirement - // requirement-seq requirement - Diag(Tok, diag::err_empty_requires_expr); - // Continue anyway and produce a requires expr with no requirements. - } else { - while (!Tok.is(tok::r_brace)) { - switch (Tok.getKind()) { - case tok::l_brace: { - // Compound requirement - // C++ [expr.prim.req.compound] - // compound-requirement: - // '{' expression '}' 'noexcept'[opt] - // return-type-requirement[opt] ';' - // return-type-requirement: - // trailing-return-type - // '->' cv-qualifier-seq[opt] constrained-parameter - // cv-qualifier-seq[opt] abstract-declarator[opt] - BalancedDelimiterTracker ExprBraces(*this, tok::l_brace); - ExprBraces.consumeOpen(); - ExprResult Expression = - Actions.CorrectDelayedTyposInExpr(ParseExpression()); - if (!Expression.isUsable()) { - ExprBraces.skipToEnd(); - SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch); - break; - } - if (ExprBraces.consumeClose()) - ExprBraces.skipToEnd(); - - concepts::Requirement *Req = nullptr; - SourceLocation NoexceptLoc; - TryConsumeToken(tok::kw_noexcept, NoexceptLoc); - if (Tok.is(tok::semi)) { - Req = Actions.ActOnCompoundRequirement(Expression.get(), NoexceptLoc); - if (Req) - Requirements.push_back(Req); - break; - } - if (!TryConsumeToken(tok::arrow)) - // User probably forgot the arrow, remind them and try to continue. - Diag(Tok, diag::err_requires_expr_missing_arrow) - << FixItHint::CreateInsertion(Tok.getLocation(), "->"); - // Try to parse a 'type-constraint' - CXXScopeSpec SS; - if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), - /*EnteringContext=*/false, - /*MayBePseudoDestructor=*/nullptr, - // If this is not a type-constraint, - // then this scope-spec is part of - // the typename of a non-type - // template parameter - /*IsTypename=*/true, - /*LastII=*/nullptr, - // We won't find concepts in - // non-namespaces anyway, so might as - // well parse this correctly for - // possible type names. - /*OnlyNamespace=*/false, - /*SuppressDiagnostic=*/true)) { - SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch); - break; - } - if (TryAnnotateTypeConstraint()) { - SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch); - break; - } - if (!isTypeConstraintAnnotation()) { - Diag(Tok, diag::err_requires_expr_expected_type_constraint); - SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch); - break; - } - if (Tok.is(tok::annot_cxxscope)) - ConsumeAnnotationToken(); - - Req = Actions.ActOnCompoundRequirement( - Expression.get(), NoexceptLoc, SS, takeTemplateIdAnnotation(Tok), - TemplateParameterDepth); - ConsumeAnnotationToken(); - if (Req) - Requirements.push_back(Req); - break; - } - default: { - bool PossibleRequiresExprInSimpleRequirement = false; - if (Tok.is(tok::kw_requires)) { - auto IsNestedRequirement = [&] { - RevertingTentativeParsingAction TPA(*this); - ConsumeToken(); // 'requires' - if (Tok.is(tok::l_brace)) - // This is a requires expression - // requires (T t) { - // requires { t++; }; - // ... ^ - // } - return false; - if (Tok.is(tok::l_paren)) { - // This might be the parameter list of a requires expression - ConsumeParen(); - auto Res = TryParseParameterDeclarationClause(); - if (Res != TPResult::False) { - // Skip to the closing parenthesis - // FIXME: Don't traverse these tokens twice (here and in - // TryParseParameterDeclarationClause). - unsigned Depth = 1; - while (Depth != 0) { - if (Tok.is(tok::l_paren)) - Depth++; - else if (Tok.is(tok::r_paren)) - Depth--; - ConsumeAnyToken(); - } - // requires (T t) { - // requires () ? - // ... ^ - // - OR - - // requires (int x) ? - // ... ^ - // } - if (Tok.is(tok::l_brace)) - // requires (...) { - // ^ - a requires expression as a - // simple-requirement. - return false; - } - } - return true; - }; - if (IsNestedRequirement()) { - ConsumeToken(); - // Nested requirement - // C++ [expr.prim.req.nested] - // nested-requirement: - // 'requires' constraint-expression ';' - ExprResult ConstraintExpr = - Actions.CorrectDelayedTyposInExpr(ParseConstraintExpression()); - if (ConstraintExpr.isInvalid() || !ConstraintExpr.isUsable()) { - SkipUntil(tok::semi, tok::r_brace, - SkipUntilFlags::StopBeforeMatch); - break; - } - if (auto *Req = - Actions.ActOnNestedRequirement(ConstraintExpr.get())) - Requirements.push_back(Req); - else { - SkipUntil(tok::semi, tok::r_brace, - SkipUntilFlags::StopBeforeMatch); - break; - } - break; - } else - PossibleRequiresExprInSimpleRequirement = true; - } else if (Tok.is(tok::kw_typename)) { - // This might be 'typename T::value_type;' (a type requirement) or - // 'typename T::value_type{};' (a simple requirement). - TentativeParsingAction TPA(*this); - - // We need to consume the typename to allow 'requires { typename a; }' - SourceLocation TypenameKWLoc = ConsumeToken(); - if (TryAnnotateCXXScopeToken()) { - SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch); - break; - } - CXXScopeSpec SS; - if (Tok.is(tok::annot_cxxscope)) { - Actions.RestoreNestedNameSpecifierAnnotation( - Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS); - ConsumeAnnotationToken(); - } - - if (Tok.isOneOf(tok::identifier, tok::annot_template_id) && - !NextToken().isOneOf(tok::l_brace, tok::l_paren)) { - TPA.Commit(); - SourceLocation NameLoc = Tok.getLocation(); - IdentifierInfo *II = nullptr; - TemplateIdAnnotation *TemplateId = nullptr; - if (Tok.is(tok::identifier)) { - II = Tok.getIdentifierInfo(); - ConsumeToken(); - } else { - TemplateId = takeTemplateIdAnnotation(Tok); - ConsumeAnnotationToken(); - } - - if (auto *Req = Actions.ActOnTypeRequirement(TypenameKWLoc, SS, - NameLoc, II, - TemplateId)) { - Requirements.push_back(Req); - } - break; - } - TPA.Revert(); - } - // Simple requirement - // C++ [expr.prim.req.simple] - // simple-requirement: - // expression ';' - SourceLocation StartLoc = Tok.getLocation(); - ExprResult Expression = - Actions.CorrectDelayedTyposInExpr(ParseExpression()); - if (!Expression.isUsable()) { - SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch); - break; - } - if (!Expression.isInvalid() && PossibleRequiresExprInSimpleRequirement) - Diag(StartLoc, diag::warn_requires_expr_in_simple_requirement) - << FixItHint::CreateInsertion(StartLoc, "requires"); - if (auto *Req = Actions.ActOnSimpleRequirement(Expression.get())) - Requirements.push_back(Req); - else { - SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch); - break; - } - // User may have tried to put some compound requirement stuff here - if (Tok.is(tok::kw_noexcept)) { - Diag(Tok, diag::err_requires_expr_simple_requirement_noexcept) - << FixItHint::CreateInsertion(StartLoc, "{") - << FixItHint::CreateInsertion(Tok.getLocation(), "}"); - SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch); - break; - } - break; - } - } - if (ExpectAndConsumeSemi(diag::err_expected_semi_requirement)) { - SkipUntil(tok::semi, tok::r_brace, SkipUntilFlags::StopBeforeMatch); - TryConsumeToken(tok::semi); - break; - } - } - if (Requirements.empty()) { - // Don't emit an empty requires expr here to avoid confusing the user with - // other diagnostics quoting an empty requires expression they never - // wrote. - Braces.consumeClose(); - Actions.ActOnFinishRequiresExpr(); - return ExprError(); - } - } - Braces.consumeClose(); - Actions.ActOnFinishRequiresExpr(); - return Actions.ActOnRequiresExpr(RequiresKWLoc, Body, LocalParameterDecls, - Requirements, Braces.getCloseLocation()); -} - static TypeTrait TypeTraitFromTokKind(tok::TokenKind kind) { switch (kind) { default: llvm_unreachable("Not a known type trait"); diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index f8da1cb89b9d9..2cd158a8b43c1 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -1261,8 +1261,7 @@ DeclContext *Sema::getFunctionLevelDeclContext() { DeclContext *DC = CurContext; while (true) { - if (isa(DC) || isa(DC) || isa(DC) || - isa(DC)) { + if (isa(DC) || isa(DC) || isa(DC)) { DC = DC->getParent(); } else if (isa(DC) && cast(DC)->getOverloadedOperator() == OO_Call && diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index a5f505784fc56..018ac2d7dc9d1 100755 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -17,10 +17,7 @@ #include "clang/Sema/SemaDiagnostic.h" #include "clang/Sema/TemplateDeduction.h" #include "clang/Sema/Template.h" -#include "clang/Sema/Overload.h" -#include "clang/Sema/Initialization.h" -#include "clang/Sema/SemaInternal.h" -#include "clang/AST/ExprConcepts.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/Basic/OperatorPrecedence.h" #include "llvm/ADT/DenseMap.h" @@ -339,118 +336,6 @@ bool Sema::EnsureTemplateArgumentListConstraints( return false; } -static void diagnoseUnsatisfiedRequirement(Sema &S, - concepts::ExprRequirement *Req, - bool First) { - assert(!Req->isSatisfied() - && "Diagnose() can only be used on an unsatisfied requirement"); - switch (Req->getSatisfactionStatus()) { - case concepts::ExprRequirement::SS_Dependent: - llvm_unreachable("Diagnosing a dependent requirement"); - break; - case concepts::ExprRequirement::SS_ExprSubstitutionFailure: { - auto *SubstDiag = Req->getExprSubstitutionDiagnostic(); - if (!SubstDiag->DiagMessage.empty()) - S.Diag(SubstDiag->DiagLoc, - diag::note_expr_requirement_expr_substitution_error) - << (int)First << SubstDiag->SubstitutedEntity - << SubstDiag->DiagMessage; - else - S.Diag(SubstDiag->DiagLoc, - diag::note_expr_requirement_expr_unknown_substitution_error) - << (int)First << SubstDiag->SubstitutedEntity; - break; - } - case concepts::ExprRequirement::SS_NoexceptNotMet: - S.Diag(Req->getNoexceptLoc(), - diag::note_expr_requirement_noexcept_not_met) - << (int)First << Req->getExpr(); - break; - case concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure: { - auto *SubstDiag = - Req->getReturnTypeRequirement().getSubstitutionDiagnostic(); - if (!SubstDiag->DiagMessage.empty()) - S.Diag(SubstDiag->DiagLoc, - diag::note_expr_requirement_type_requirement_substitution_error) - << (int)First << SubstDiag->SubstitutedEntity - << SubstDiag->DiagMessage; - else - S.Diag(SubstDiag->DiagLoc, - diag::note_expr_requirement_type_requirement_unknown_substitution_error) - << (int)First << SubstDiag->SubstitutedEntity; - break; - } - case concepts::ExprRequirement::SS_ConstraintsNotSatisfied: { - ConceptSpecializationExpr *ConstraintExpr = - Req->getReturnTypeRequirementSubstitutedConstraintExpr(); - if (ConstraintExpr->getTemplateArgsAsWritten()->NumTemplateArgs == 1) - // A simple case - expr type is the type being constrained and the concept - // was not provided arguments. - S.Diag(ConstraintExpr->getBeginLoc(), - diag::note_expr_requirement_constraints_not_satisfied_simple) - << (int)First << S.BuildDecltypeType(Req->getExpr(), - Req->getExpr()->getBeginLoc()) - << ConstraintExpr->getNamedConcept(); - else - S.Diag(ConstraintExpr->getBeginLoc(), - diag::note_expr_requirement_constraints_not_satisfied) - << (int)First << ConstraintExpr; - S.DiagnoseUnsatisfiedConstraint(ConstraintExpr->getSatisfaction()); - break; - } - case concepts::ExprRequirement::SS_Satisfied: - llvm_unreachable("We checked this above"); - } -} - -static void diagnoseUnsatisfiedRequirement(Sema &S, - concepts::TypeRequirement *Req, - bool First) { - assert(!Req->isSatisfied() - && "Diagnose() can only be used on an unsatisfied requirement"); - switch (Req->getSatisfactionStatus()) { - case concepts::TypeRequirement::SS_Dependent: - llvm_unreachable("Diagnosing a dependent requirement"); - return; - case concepts::TypeRequirement::SS_SubstitutionFailure: { - auto *SubstDiag = Req->getSubstitutionDiagnostic(); - if (!SubstDiag->DiagMessage.empty()) - S.Diag(SubstDiag->DiagLoc, - diag::note_type_requirement_substitution_error) << (int)First - << SubstDiag->SubstitutedEntity << SubstDiag->DiagMessage; - else - S.Diag(SubstDiag->DiagLoc, - diag::note_type_requirement_unknown_substitution_error) - << (int)First << SubstDiag->SubstitutedEntity; - return; - } - default: - llvm_unreachable("Unknown satisfaction status"); - return; - } -} - -static void diagnoseUnsatisfiedRequirement(Sema &S, - concepts::NestedRequirement *Req, - bool First) { - if (Req->isSubstitutionFailure()) { - concepts::Requirement::SubstitutionDiagnostic *SubstDiag = - Req->getSubstitutionDiagnostic(); - if (!SubstDiag->DiagMessage.empty()) - S.Diag(SubstDiag->DiagLoc, - diag::note_nested_requirement_substitution_error) - << (int)First << SubstDiag->SubstitutedEntity - << SubstDiag->DiagMessage; - else - S.Diag(SubstDiag->DiagLoc, - diag::note_nested_requirement_unknown_substitution_error) - << (int)First << SubstDiag->SubstitutedEntity; - return; - } - S.DiagnoseUnsatisfiedConstraint(Req->getConstraintSatisfaction(), First); -} - - static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, Expr *SubstExpr, bool First = true) { @@ -527,19 +412,6 @@ static void diagnoseWellFormedUnsatisfiedConstraintExpr(Sema &S, } S.DiagnoseUnsatisfiedConstraint(CSE->getSatisfaction()); return; - } else if (auto *RE = dyn_cast(SubstExpr)) { - for (concepts::Requirement *Req : RE->getRequirements()) - if (!Req->isDependent() && !Req->isSatisfied()) { - if (auto *E = dyn_cast(Req)) - diagnoseUnsatisfiedRequirement(S, E, First); - else if (auto *T = dyn_cast(Req)) - diagnoseUnsatisfiedRequirement(S, T, First); - else - diagnoseUnsatisfiedRequirement( - S, cast(Req), First); - break; - } - return; } S.Diag(SubstExpr->getSourceRange().getBegin(), @@ -562,11 +434,11 @@ static void diagnoseUnsatisfiedConstraintExpr( Record.template get(), First); } -void -Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction, - bool First) { +void Sema::DiagnoseUnsatisfiedConstraint( + const ConstraintSatisfaction& Satisfaction) { assert(!Satisfaction.IsSatisfied && "Attempted to diagnose a satisfied constraint"); + bool First = true; for (auto &Pair : Satisfaction.Details) { diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First); First = false; @@ -574,10 +446,10 @@ Sema::DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction& Satisfaction, } void Sema::DiagnoseUnsatisfiedConstraint( - const ASTConstraintSatisfaction &Satisfaction, - bool First) { + const ASTConstraintSatisfaction &Satisfaction) { assert(!Satisfaction.IsSatisfied && "Attempted to diagnose a satisfied constraint"); + bool First = true; for (auto &Pair : Satisfaction) { diagnoseUnsatisfiedConstraintExpr(*this, Pair.first, Pair.second, First); First = false; @@ -954,70 +826,3 @@ bool Sema::MaybeEmitAmbiguousAtomicConstraintsDiagnostic(NamedDecl *D1, << AmbiguousAtomic2->getSourceRange(); return true; } - -concepts::ExprRequirement::ExprRequirement( - Expr *E, bool IsSimple, SourceLocation NoexceptLoc, - ReturnTypeRequirement Req, SatisfactionStatus Status, - ConceptSpecializationExpr *SubstitutedConstraintExpr) : - Requirement(IsSimple ? RK_Simple : RK_Compound, Status == SS_Dependent, - Status == SS_Dependent && - (E->containsUnexpandedParameterPack() || - Req.containsUnexpandedParameterPack()), - Status == SS_Satisfied), Value(E), NoexceptLoc(NoexceptLoc), - TypeReq(Req), SubstitutedConstraintExpr(SubstitutedConstraintExpr), - Status(Status) { - assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && - "Simple requirement must not have a return type requirement or a " - "noexcept specification"); - assert((Status > SS_TypeRequirementSubstitutionFailure && Req.isTypeConstraint()) == - (SubstitutedConstraintExpr != nullptr)); -} - -concepts::ExprRequirement::ExprRequirement( - SubstitutionDiagnostic *ExprSubstDiag, bool IsSimple, - SourceLocation NoexceptLoc, ReturnTypeRequirement Req) : - Requirement(IsSimple ? RK_Simple : RK_Compound, Req.isDependent(), - Req.containsUnexpandedParameterPack(), /*IsSatisfied=*/false), - Value(ExprSubstDiag), NoexceptLoc(NoexceptLoc), TypeReq(Req), - Status(SS_ExprSubstitutionFailure) { - assert((!IsSimple || (Req.isEmpty() && NoexceptLoc.isInvalid())) && - "Simple requirement must not have a return type requirement or a " - "noexcept specification"); -} - -concepts::ExprRequirement::ReturnTypeRequirement:: -ReturnTypeRequirement(TemplateParameterList *TPL) : - TypeConstraintInfo(TPL, 0) { - assert(TPL->size() == 1); - const TypeConstraint *TC = - cast(TPL->getParam(0))->getTypeConstraint(); - assert(TC && - "TPL must have a template type parameter with a type constraint"); - auto *Constraint = - cast_or_null( - TC->getImmediatelyDeclaredConstraint()); - bool ContainsUnexpandedParameterPack = - Constraint->containsUnexpandedParameterPack(); - bool Dependent = false; - if (Constraint->getTemplateArgsAsWritten()) { - for (auto &ArgLoc : - Constraint->getTemplateArgsAsWritten()->arguments().drop_front(1)) { - if (ArgLoc.getArgument().isDependent()) { - Dependent = true; - break; - } - } - } - TypeConstraintInfo.setInt((Dependent ? 1 : 0) | - (ContainsUnexpandedParameterPack ? 2 : 0)); -} - -concepts::TypeRequirement::TypeRequirement(TypeSourceInfo *T) : - Requirement(RK_Type, T->getType()->isDependentType(), - T->getType()->containsUnexpandedParameterPack(), - // We reach this ctor with either dependent types (in which - // IsSatisfied doesn't matter) or with non-dependent type in - // which the existence of the type indicates satisfaction. - /*IsSatisfied=*/true - ), Value(T), - Status(T->getType()->isDependentType() ? SS_Dependent : SS_Satisfied) {} diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 372f3d1585977..507e4a6cd4365 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6468,8 +6468,6 @@ static bool shouldConsiderLinkage(const VarDecl *VD) { return true; if (DC->isRecord()) return false; - if (isa(DC)) - return false; llvm_unreachable("Unexpected context"); } diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index 193eaa3e01f93..5aedbe7644e4b 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -1386,7 +1386,6 @@ CanThrowResult Sema::canThrow(const Stmt *S) { case Expr::StringLiteralClass: case Expr::SourceLocExprClass: case Expr::ConceptSpecializationExprClass: - case Expr::RequiresExprClass: // These expressions can never throw. return CT_Cannot; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index ea4b93ee6a5a4..5f4071924d3f1 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -350,17 +350,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, } } - if (isa(D) && isa(D->getDeclContext()) && - !isUnevaluatedContext()) { - // C++ [expr.prim.req.nested] p3 - // A local parameter shall only appear as an unevaluated operand - // (Clause 8) within the constraint-expression. - Diag(Loc, diag::err_requires_expr_parameter_referenced_in_evaluated_context) - << D; - Diag(D->getLocation(), diag::note_entity_declared_at) << D; - return true; - } - return false; } @@ -1915,7 +1904,7 @@ Sema::BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, bool RefersToCapturedVariable = isa(D) && NeedToCaptureVariable(cast(D), NameInfo.getLoc()); - + DeclRefExpr *E = DeclRefExpr::Create( Context, NNS, TemplateKWLoc, D, RefersToCapturedVariable, NameInfo, Ty, VK, FoundD, TemplateArgs, getNonOdrUseReasonInCurrentContext(D)); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 192c237b6c1ce..938420d85c65d 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -11,7 +11,6 @@ /// //===----------------------------------------------------------------------===// -#include "clang/Sema/Template.h" #include "clang/Sema/SemaInternal.h" #include "TreeTransform.h" #include "TypeLocBuilder.h" @@ -8332,215 +8331,3 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc, return CheckMicrosoftIfExistsSymbol(S, SS, TargetNameInfo); } - -concepts::Requirement *Sema::ActOnSimpleRequirement(Expr *E) { - return BuildExprRequirement(E, /*IsSimple=*/true, - /*NoexceptLoc=*/SourceLocation(), - /*ReturnTypeRequirement=*/{}); -} - -concepts::Requirement * -Sema::ActOnTypeRequirement(SourceLocation TypenameKWLoc, CXXScopeSpec &SS, - SourceLocation NameLoc, IdentifierInfo *TypeName, - TemplateIdAnnotation *TemplateId) { - assert(((!TypeName && TemplateId) || (TypeName && !TemplateId)) && - "Exactly one of TypeName and TemplateId must be specified."); - TypeSourceInfo *TSI = nullptr; - if (TypeName) { - QualType T = CheckTypenameType(ETK_Typename, TypenameKWLoc, - SS.getWithLocInContext(Context), *TypeName, - NameLoc, &TSI, /*DeducedTypeContext=*/false); - if (T.isNull()) - return nullptr; - } else { - ASTTemplateArgsPtr ArgsPtr(TemplateId->getTemplateArgs(), - TemplateId->NumArgs); - TypeResult T = ActOnTypenameType(CurScope, TypenameKWLoc, SS, - TemplateId->TemplateKWLoc, - TemplateId->Template, TemplateId->Name, - TemplateId->TemplateNameLoc, - TemplateId->LAngleLoc, ArgsPtr, - TemplateId->RAngleLoc); - if (T.isInvalid()) - return nullptr; - if (GetTypeFromParser(T.get(), &TSI).isNull()) - return nullptr; - } - return BuildTypeRequirement(TSI); -} - -concepts::Requirement * -Sema::ActOnCompoundRequirement(Expr *E, SourceLocation NoexceptLoc) { - return BuildExprRequirement(E, /*IsSimple=*/false, NoexceptLoc, - /*ReturnTypeRequirement=*/{}); -} - -concepts::Requirement * -Sema::ActOnCompoundRequirement( - Expr *E, SourceLocation NoexceptLoc, CXXScopeSpec &SS, - TemplateIdAnnotation *TypeConstraint, unsigned Depth) { - // C++2a [expr.prim.req.compound] p1.3.3 - // [..] the expression is deduced against an invented function template - // F [...] F is a void function template with a single type template - // parameter T declared with the constrained-parameter. Form a new - // cv-qualifier-seq cv by taking the union of const and volatile specifiers - // around the constrained-parameter. F has a single parameter whose - // type-specifier is cv T followed by the abstract-declarator. [...] - // - // The cv part is done in the calling function - we get the concept with - // arguments and the abstract declarator with the correct CV qualification and - // have to synthesize T and the single parameter of F. - auto &II = Context.Idents.get("expr-type"); - auto *TParam = TemplateTypeParmDecl::Create(Context, CurContext, - SourceLocation(), - SourceLocation(), Depth, - /*Index=*/0, &II, - /*Typename=*/true, - /*ParameterPack=*/false, - /*HasTypeConstraint=*/true); - - if (ActOnTypeConstraint(SS, TypeConstraint, TParam, - /*EllpsisLoc=*/SourceLocation())) - // Just produce a requirement with no type requirements. - return BuildExprRequirement(E, /*IsSimple=*/false, NoexceptLoc, {}); - - auto *TPL = TemplateParameterList::Create(Context, SourceLocation(), - SourceLocation(), - ArrayRef(TParam), - SourceLocation(), - /*RequiresClause=*/nullptr); - return BuildExprRequirement( - E, /*IsSimple=*/false, NoexceptLoc, - concepts::ExprRequirement::ReturnTypeRequirement(TPL)); -} - -concepts::ExprRequirement * -Sema::BuildExprRequirement( - Expr *E, bool IsSimple, SourceLocation NoexceptLoc, - concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement) { - auto Status = concepts::ExprRequirement::SS_Satisfied; - ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr; - if (E->isInstantiationDependent() || ReturnTypeRequirement.isDependent()) - Status = concepts::ExprRequirement::SS_Dependent; - else if (NoexceptLoc.isValid() && canThrow(E) == CanThrowResult::CT_Can) - Status = concepts::ExprRequirement::SS_NoexceptNotMet; - else if (ReturnTypeRequirement.isSubstitutionFailure()) - Status = concepts::ExprRequirement::SS_TypeRequirementSubstitutionFailure; - else if (ReturnTypeRequirement.isTypeConstraint()) { - // C++2a [expr.prim.req]p1.3.3 - // The immediately-declared constraint ([temp]) of decltype((E)) shall - // be satisfied. - TemplateParameterList *TPL = - ReturnTypeRequirement.getTypeConstraintTemplateParameterList(); - QualType MatchedType = - BuildDecltypeType(E, E->getBeginLoc()).getCanonicalType(); - llvm::SmallVector Args; - Args.push_back(TemplateArgument(MatchedType)); - TemplateArgumentList TAL(TemplateArgumentList::OnStack, Args); - MultiLevelTemplateArgumentList MLTAL(TAL); - for (unsigned I = 0; I < TPL->getDepth(); ++I) - MLTAL.addOuterRetainedLevel(); - Expr *IDC = - cast(TPL->getParam(0))->getTypeConstraint() - ->getImmediatelyDeclaredConstraint(); - ExprResult Constraint = SubstExpr(IDC, MLTAL); - assert(!Constraint.isInvalid() && - "Substitution cannot fail as it is simply putting a type template " - "argument into a concept specialization expression's parameter."); - - SubstitutedConstraintExpr = - cast(Constraint.get()); - if (!SubstitutedConstraintExpr->isSatisfied()) - Status = concepts::ExprRequirement::SS_ConstraintsNotSatisfied; - } - return new (Context) concepts::ExprRequirement(E, IsSimple, NoexceptLoc, - ReturnTypeRequirement, Status, - SubstitutedConstraintExpr); -} - -concepts::ExprRequirement * -Sema::BuildExprRequirement( - concepts::Requirement::SubstitutionDiagnostic *ExprSubstitutionDiagnostic, - bool IsSimple, SourceLocation NoexceptLoc, - concepts::ExprRequirement::ReturnTypeRequirement ReturnTypeRequirement) { - return new (Context) concepts::ExprRequirement(ExprSubstitutionDiagnostic, - IsSimple, NoexceptLoc, - ReturnTypeRequirement); -} - -concepts::TypeRequirement * -Sema::BuildTypeRequirement(TypeSourceInfo *Type) { - return new (Context) concepts::TypeRequirement(Type); -} - -concepts::TypeRequirement * -Sema::BuildTypeRequirement( - concepts::Requirement::SubstitutionDiagnostic *SubstDiag) { - return new (Context) concepts::TypeRequirement(SubstDiag); -} - -concepts::Requirement *Sema::ActOnNestedRequirement(Expr *Constraint) { - return BuildNestedRequirement(Constraint); -} - -concepts::NestedRequirement * -Sema::BuildNestedRequirement(Expr *Constraint) { - ConstraintSatisfaction Satisfaction; - if (!Constraint->isInstantiationDependent() && - CheckConstraintSatisfaction(Constraint, Satisfaction)) - return nullptr; - return new (Context) concepts::NestedRequirement(Context, Constraint, - Satisfaction); -} - -concepts::NestedRequirement * -Sema::BuildNestedRequirement( - concepts::Requirement::SubstitutionDiagnostic *SubstDiag) { - return new (Context) concepts::NestedRequirement(SubstDiag); -} - -RequiresExprBodyDecl * -Sema::ActOnStartRequiresExpr(SourceLocation RequiresKWLoc, - ArrayRef LocalParameters, - Scope *BodyScope) { - assert(BodyScope); - - RequiresExprBodyDecl *Body = RequiresExprBodyDecl::Create(Context, CurContext, - RequiresKWLoc); - - PushDeclContext(BodyScope, Body); - - for (ParmVarDecl *Param : LocalParameters) { - if (Param->hasDefaultArg()) - // C++2a [expr.prim.req] p4 - // [...] A local parameter of a requires-expression shall not have a - // default argument. [...] - Diag(Param->getDefaultArgRange().getBegin(), - diag::err_requires_expr_local_parameter_default_argument); - // Ignore default argument and move on - - Param->setDeclContext(Body); - // If this has an identifier, add it to the scope stack. - if (Param->getIdentifier()) { - CheckShadow(BodyScope, Param); - PushOnScopeChains(Param, BodyScope); - } - } - return Body; -} - -void Sema::ActOnFinishRequiresExpr() { - assert(CurContext && "DeclContext imbalance!"); - CurContext = CurContext->getLexicalParent(); - assert(CurContext && "Popped translation unit!"); -} - -ExprResult -Sema::ActOnRequiresExpr(SourceLocation RequiresKWLoc, - RequiresExprBodyDecl *Body, - ArrayRef LocalParameters, - ArrayRef Requirements, - SourceLocation ClosingBraceLoc) { - return RequiresExpr::Create(Context, RequiresKWLoc, Body, LocalParameters, - Requirements, ClosingBraceLoc); -} diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 8d96404a5c27d..0ed51de0cc131 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -1575,9 +1575,7 @@ llvm::DenseSet &Sema::getLookupModules() { unsigned N = CodeSynthesisContexts.size(); for (unsigned I = CodeSynthesisContextLookupModules.size(); I != N; ++I) { - Module *M = CodeSynthesisContexts[I].Entity ? - getDefiningModule(*this, CodeSynthesisContexts[I].Entity) : - nullptr; + Module *M = getDefiningModule(*this, CodeSynthesisContexts[I].Entity); if (M && !LookupModulesCache.insert(M).second) M = nullptr; CodeSynthesisContextLookupModules.push_back(M); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 661a66246a53b..8a50a9e1538ff 100755 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -10010,12 +10010,24 @@ Sema::ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, << FixItHint::CreateRemoval(TypenameLoc); NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); - TypeSourceInfo *TSI = nullptr; QualType T = CheckTypenameType(TypenameLoc.isValid()? ETK_Typename : ETK_None, - TypenameLoc, QualifierLoc, II, IdLoc, &TSI, - /*DeducedTSTContext=*/true); + TypenameLoc, QualifierLoc, II, IdLoc); if (T.isNull()) return true; + + TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T); + if (isa(T)) { + DependentNameTypeLoc TL = TSI->getTypeLoc().castAs(); + TL.setElaboratedKeywordLoc(TypenameLoc); + TL.setQualifierLoc(QualifierLoc); + TL.setNameLoc(IdLoc); + } else { + ElaboratedTypeLoc TL = TSI->getTypeLoc().castAs(); + TL.setElaboratedKeywordLoc(TypenameLoc); + TL.setQualifierLoc(QualifierLoc); + TL.getNamedTypeLoc().castAs().setNameLoc(IdLoc); + } + return CreateParsedType(T, TSI); } @@ -10152,35 +10164,6 @@ static bool isEnableIf(NestedNameSpecifierLoc NNS, const IdentifierInfo &II, return true; } -QualType -Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, - SourceLocation KeywordLoc, - NestedNameSpecifierLoc QualifierLoc, - const IdentifierInfo &II, - SourceLocation IILoc, - TypeSourceInfo **TSI, - bool DeducedTSTContext) { - QualType T = CheckTypenameType(Keyword, KeywordLoc, QualifierLoc, II, IILoc, - DeducedTSTContext); - if (T.isNull()) - return QualType(); - - *TSI = Context.CreateTypeSourceInfo(T); - if (isa(T)) { - DependentNameTypeLoc TL = - (*TSI)->getTypeLoc().castAs(); - TL.setElaboratedKeywordLoc(KeywordLoc); - TL.setQualifierLoc(QualifierLoc); - TL.setNameLoc(IILoc); - } else { - ElaboratedTypeLoc TL = (*TSI)->getTypeLoc().castAs(); - TL.setElaboratedKeywordLoc(KeywordLoc); - TL.setQualifierLoc(QualifierLoc); - TL.getNamedTypeLoc().castAs().setNameLoc(IILoc); - } - return T; -} - /// Build the type that describes a C++ typename specifier, /// e.g., "typename T::type". QualType @@ -10188,38 +10171,32 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, SourceLocation KeywordLoc, NestedNameSpecifierLoc QualifierLoc, const IdentifierInfo &II, - SourceLocation IILoc, bool DeducedTSTContext) { + SourceLocation IILoc) { CXXScopeSpec SS; SS.Adopt(QualifierLoc); - DeclContext *Ctx = nullptr; - if (QualifierLoc) { - Ctx = computeDeclContext(SS); - if (!Ctx) { - // If the nested-name-specifier is dependent and couldn't be - // resolved to a type, build a typename type. - assert(QualifierLoc.getNestedNameSpecifier()->isDependent()); - return Context.getDependentNameType(Keyword, - QualifierLoc.getNestedNameSpecifier(), - &II); - } - - // If the nested-name-specifier refers to the current instantiation, - // the "typename" keyword itself is superfluous. In C++03, the - // program is actually ill-formed. However, DR 382 (in C++0x CD1) - // allows such extraneous "typename" keywords, and we retroactively - // apply this DR to C++03 code with only a warning. In any case we continue. - - if (RequireCompleteDeclContext(SS, Ctx)) - return QualType(); + DeclContext *Ctx = computeDeclContext(SS); + if (!Ctx) { + // If the nested-name-specifier is dependent and couldn't be + // resolved to a type, build a typename type. + assert(QualifierLoc.getNestedNameSpecifier()->isDependent()); + return Context.getDependentNameType(Keyword, + QualifierLoc.getNestedNameSpecifier(), + &II); } + // If the nested-name-specifier refers to the current instantiation, + // the "typename" keyword itself is superfluous. In C++03, the + // program is actually ill-formed. However, DR 382 (in C++0x CD1) + // allows such extraneous "typename" keywords, and we retroactively + // apply this DR to C++03 code with only a warning. In any case we continue. + + if (RequireCompleteDeclContext(SS, Ctx)) + return QualType(); + DeclarationName Name(&II); LookupResult Result(*this, Name, IILoc, LookupOrdinaryName); - if (Ctx) - LookupQualifiedName(Result, Ctx, SS); - else - LookupName(Result, CurScope); + LookupQualifiedName(Result, Ctx, SS); unsigned DiagID = 0; Decl *Referenced = nullptr; switch (Result.getResultKind()) { @@ -10228,7 +10205,7 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, // a more specific diagnostic. SourceRange CondRange; Expr *Cond = nullptr; - if (Ctx && isEnableIf(QualifierLoc, II, CondRange, Cond)) { + if (isEnableIf(QualifierLoc, II, CondRange, Cond)) { // If we have a condition, narrow it down to the specific failed // condition. if (Cond) { @@ -10244,14 +10221,12 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, return QualType(); } - Diag(CondRange.getBegin(), - diag::err_typename_nested_not_found_enable_if) + Diag(CondRange.getBegin(), diag::err_typename_nested_not_found_enable_if) << Ctx << CondRange; return QualType(); } - DiagID = Ctx ? diag::err_typename_nested_not_found - : diag::err_unknown_typename; + DiagID = diag::err_typename_nested_not_found; break; } @@ -10317,19 +10292,6 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, // is a placeholder for a deduced class type [...]. if (getLangOpts().CPlusPlus17) { if (auto *TD = getAsTypeTemplateDecl(Result.getFoundDecl())) { - if (!DeducedTSTContext) { - QualType T(QualifierLoc - ? QualifierLoc.getNestedNameSpecifier()->getAsType() - : nullptr, 0); - if (!T.isNull()) - Diag(IILoc, diag::err_dependent_deduced_tst) - << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)) << T; - else - Diag(IILoc, diag::err_deduced_tst) - << (int)getTemplateNameKindForDiagnostics(TemplateName(TD)); - Diag(TD->getLocation(), diag::note_template_decl_here); - return QualType(); - } return Context.getElaboratedType( Keyword, QualifierLoc.getNestedNameSpecifier(), Context.getDeducedTemplateSpecializationType(TemplateName(TD), @@ -10337,14 +10299,12 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, } } - DiagID = Ctx ? diag::err_typename_nested_not_type - : diag::err_typename_not_type; + DiagID = diag::err_typename_nested_not_type; Referenced = Result.getFoundDecl(); break; case LookupResult::FoundOverloaded: - DiagID = Ctx ? diag::err_typename_nested_not_type - : diag::err_typename_not_type; + DiagID = diag::err_typename_nested_not_type; Referenced = *Result.begin(); break; @@ -10356,14 +10316,9 @@ Sema::CheckTypenameType(ElaboratedTypeKeyword Keyword, // type. Emit an appropriate diagnostic and return an error. SourceRange FullRange(KeywordLoc.isValid() ? KeywordLoc : SS.getBeginLoc(), IILoc); - if (Ctx) - Diag(IILoc, DiagID) << FullRange << Name << Ctx; - else - Diag(IILoc, DiagID) << FullRange << Name; + Diag(IILoc, DiagID) << FullRange << Name << Ctx; if (Referenced) - Diag(Referenced->getLocation(), - Ctx ? diag::note_typename_member_refers_here - : diag::note_typename_refers_here) + Diag(Referenced->getLocation(), diag::note_typename_refers_here) << Name; return QualType(); } diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 39bc28d62305b..af41e231134d0 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -26,7 +26,6 @@ #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" #include "clang/Sema/TemplateInstCallback.h" -#include "clang/Sema/SemaConcept.h" #include "llvm/Support/TimeProfiler.h" using namespace clang; @@ -200,10 +199,8 @@ bool Sema::CodeSynthesisContext::isInstantiationRecord() const { case DeducedTemplateArgumentSubstitution: case PriorTemplateArgumentSubstitution: case ConstraintsCheck: - case NestedRequirementConstraintsCheck: return true; - case RequirementInstantiation: case DefaultTemplateArgumentChecking: case DeclaringSpecialMember: case DeclaringImplicitEqualityComparison: @@ -250,7 +247,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate( Inst.InstantiationRange = InstantiationRange; SemaRef.pushCodeSynthesisContext(Inst); - AlreadyInstantiating = !Inst.Entity ? false : + AlreadyInstantiating = !SemaRef.InstantiatingSpecializations .insert(std::make_pair(Inst.Entity->getCanonicalDecl(), Inst.Kind)) .second; @@ -367,26 +364,6 @@ Sema::InstantiatingTemplate::InstantiatingTemplate( PointOfInstantiation, InstantiationRange, Param, Template, TemplateArgs) {} -Sema::InstantiatingTemplate::InstantiatingTemplate( - Sema &SemaRef, SourceLocation PointOfInstantiation, - concepts::Requirement *Req, sema::TemplateDeductionInfo &DeductionInfo, - SourceRange InstantiationRange) - : InstantiatingTemplate( - SemaRef, CodeSynthesisContext::RequirementInstantiation, - PointOfInstantiation, InstantiationRange, /*Entity=*/nullptr, - /*Template=*/nullptr, /*TemplateArgs=*/None, &DeductionInfo) {} - - -Sema::InstantiatingTemplate::InstantiatingTemplate( - Sema &SemaRef, SourceLocation PointOfInstantiation, - concepts::NestedRequirement *Req, ConstraintsCheck, - SourceRange InstantiationRange) - : InstantiatingTemplate( - SemaRef, CodeSynthesisContext::NestedRequirementConstraintsCheck, - PointOfInstantiation, InstantiationRange, /*Entity=*/nullptr, - /*Template=*/nullptr, /*TemplateArgs=*/None) {} - - Sema::InstantiatingTemplate::InstantiatingTemplate( Sema &SemaRef, SourceLocation PointOfInstantiation, ConstraintsCheck, NamedDecl *Template, @@ -469,9 +446,8 @@ void Sema::InstantiatingTemplate::Clear() { if (!Invalid) { if (!AlreadyInstantiating) { auto &Active = SemaRef.CodeSynthesisContexts.back(); - if (Active.Entity) - SemaRef.InstantiatingSpecializations.erase( - std::make_pair(Active.Entity, Active.Kind)); + SemaRef.InstantiatingSpecializations.erase( + std::make_pair(Active.Entity, Active.Kind)); } atTemplateEnd(SemaRef.TemplateInstCallbacks, SemaRef, @@ -708,18 +684,6 @@ void Sema::PrintInstantiationStack() { << Active->InstantiationRange; break; - case CodeSynthesisContext::RequirementInstantiation: - Diags.Report(Active->PointOfInstantiation, - diag::note_template_requirement_instantiation_here) - << Active->InstantiationRange; - break; - - case CodeSynthesisContext::NestedRequirementConstraintsCheck: - Diags.Report(Active->PointOfInstantiation, - diag::note_nested_requirement_here) - << Active->InstantiationRange; - break; - case CodeSynthesisContext::DeclaringSpecialMember: Diags.Report(Active->PointOfInstantiation, diag::note_in_declaration_of_implicit_special_member) @@ -824,7 +788,6 @@ Optional Sema::isSFINAEContext() const { case CodeSynthesisContext::ConstraintsCheck: case CodeSynthesisContext::ParameterMappingSubstitution: case CodeSynthesisContext::ConstraintNormalization: - case CodeSynthesisContext::NestedRequirementConstraintsCheck: // This is a template instantiation, so there is no SFINAE. return None; @@ -839,10 +802,9 @@ Optional Sema::isSFINAEContext() const { case CodeSynthesisContext::ExplicitTemplateArgumentSubstitution: case CodeSynthesisContext::DeducedTemplateArgumentSubstitution: case CodeSynthesisContext::ConstraintSubstitution: - case CodeSynthesisContext::RequirementInstantiation: - // We're either substituting explicitly-specified template arguments, - // deduced template arguments, a constraint expression or a requirement - // in a requires expression, so SFINAE applies. + // We're either substituting explicitly-specified template arguments + // or deduced template arguments or a constraint expression, so SFINAE + // applies. assert(Active->DeductionInfo && "Missing deduction info pointer"); return Active->DeductionInfo; @@ -1094,41 +1056,6 @@ namespace { return TreeTransform::TransformLambdaExpr(E); } - ExprResult TransformRequiresExpr(RequiresExpr *E) { - LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true); - return TreeTransform::TransformRequiresExpr(E); - } - - bool TransformRequiresExprRequirements( - ArrayRef Reqs, - SmallVectorImpl &Transformed) { - bool SatisfactionDetermined = false; - for (concepts::Requirement *Req : Reqs) { - concepts::Requirement *TransReq = nullptr; - if (!SatisfactionDetermined) { - if (auto *TypeReq = dyn_cast(Req)) - TransReq = TransformTypeRequirement(TypeReq); - else if (auto *ExprReq = dyn_cast(Req)) - TransReq = TransformExprRequirement(ExprReq); - else - TransReq = TransformNestedRequirement( - cast(Req)); - if (!TransReq) - return true; - if (!TransReq->isDependent() && !TransReq->isSatisfied()) - // [expr.prim.req]p6 - // [...] The substitution and semantic constraint checking - // proceeds in lexical order and stops when a condition that - // determines the result of the requires-expression is - // encountered. [..] - SatisfactionDetermined = true; - } else - TransReq = Req; - Transformed.push_back(TransReq); - } - return false; - } - TemplateParameterList *TransformTemplateParameterList( TemplateParameterList *OrigTPL) { if (!OrigTPL || !OrigTPL->size()) return OrigTPL; @@ -1138,14 +1065,6 @@ namespace { /* DeclContext *Owner */ Owner, TemplateArgs); return DeclInstantiator.SubstTemplateParams(OrigTPL); } - - concepts::TypeRequirement * - TransformTypeRequirement(concepts::TypeRequirement *Req); - concepts::ExprRequirement * - TransformExprRequirement(concepts::ExprRequirement *Req); - concepts::NestedRequirement * - TransformNestedRequirement(concepts::NestedRequirement *Req); - private: ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm, SourceLocation loc, @@ -1750,163 +1669,6 @@ TemplateInstantiator::TransformSubstTemplateTypeParmPackType( return Result; } -template -static concepts::Requirement::SubstitutionDiagnostic * -createSubstDiag(Sema &S, TemplateDeductionInfo &Info, EntityPrinter Printer) { - SmallString<128> Message; - SourceLocation ErrorLoc; - if (Info.hasSFINAEDiagnostic()) { - PartialDiagnosticAt PDA(SourceLocation(), - PartialDiagnostic::NullDiagnostic{}); - Info.takeSFINAEDiagnostic(PDA); - PDA.second.EmitToString(S.getDiagnostics(), Message); - ErrorLoc = PDA.first; - } else { - ErrorLoc = Info.getLocation(); - } - char *MessageBuf = new (S.Context) char[Message.size()]; - std::copy(Message.begin(), Message.end(), MessageBuf); - SmallString<128> Entity; - llvm::raw_svector_ostream OS(Entity); - Printer(OS); - char *EntityBuf = new (S.Context) char[Entity.size()]; - std::copy(Entity.begin(), Entity.end(), EntityBuf); - return new (S.Context) concepts::Requirement::SubstitutionDiagnostic{ - StringRef(EntityBuf, Entity.size()), ErrorLoc, - StringRef(MessageBuf, Message.size())}; -} - -concepts::TypeRequirement * -TemplateInstantiator::TransformTypeRequirement(concepts::TypeRequirement *Req) { - if (!Req->isDependent() && !AlwaysRebuild()) - return Req; - if (Req->isSubstitutionFailure()) { - if (AlwaysRebuild()) - return RebuildTypeRequirement( - Req->getSubstitutionDiagnostic()); - return Req; - } - - Sema::SFINAETrap Trap(SemaRef); - TemplateDeductionInfo Info(Req->getType()->getTypeLoc().getBeginLoc()); - Sema::InstantiatingTemplate TypeInst(SemaRef, - Req->getType()->getTypeLoc().getBeginLoc(), Req, Info, - Req->getType()->getTypeLoc().getSourceRange()); - if (TypeInst.isInvalid()) - return nullptr; - TypeSourceInfo *TransType = TransformType(Req->getType()); - if (!TransType || Trap.hasErrorOccurred()) - return RebuildTypeRequirement(createSubstDiag(SemaRef, Info, - [&] (llvm::raw_ostream& OS) { - Req->getType()->getType().print(OS, SemaRef.getPrintingPolicy()); - })); - return RebuildTypeRequirement(TransType); -} - -concepts::ExprRequirement * -TemplateInstantiator::TransformExprRequirement(concepts::ExprRequirement *Req) { - if (!Req->isDependent() && !AlwaysRebuild()) - return Req; - - Sema::SFINAETrap Trap(SemaRef); - TemplateDeductionInfo Info(Req->getExpr()->getBeginLoc()); - - llvm::PointerUnion - TransExpr; - if (Req->isExprSubstitutionFailure()) - TransExpr = Req->getExprSubstitutionDiagnostic(); - else { - Sema::InstantiatingTemplate ExprInst(SemaRef, Req->getExpr()->getBeginLoc(), - Req, Info, - Req->getExpr()->getSourceRange()); - if (ExprInst.isInvalid()) - return nullptr; - ExprResult TransExprRes = TransformExpr(Req->getExpr()); - if (TransExprRes.isInvalid() || Trap.hasErrorOccurred()) - TransExpr = createSubstDiag(SemaRef, Info, - [&] (llvm::raw_ostream& OS) { - Req->getExpr()->printPretty(OS, nullptr, - SemaRef.getPrintingPolicy()); - }); - else - TransExpr = TransExprRes.get(); - } - - llvm::Optional TransRetReq; - const auto &RetReq = Req->getReturnTypeRequirement(); - if (RetReq.isEmpty()) - TransRetReq.emplace(); - else if (RetReq.isSubstitutionFailure()) - TransRetReq.emplace(RetReq.getSubstitutionDiagnostic()); - else if (RetReq.isTypeConstraint()) { - TemplateParameterList *OrigTPL = - RetReq.getTypeConstraintTemplateParameterList(); - Sema::InstantiatingTemplate TPLInst(SemaRef, OrigTPL->getTemplateLoc(), - Req, Info, OrigTPL->getSourceRange()); - if (TPLInst.isInvalid()) - return nullptr; - TemplateParameterList *TPL = - TransformTemplateParameterList(OrigTPL); - if (!TPL) - TransRetReq.emplace(createSubstDiag(SemaRef, Info, - [&] (llvm::raw_ostream& OS) { - RetReq.getTypeConstraint()->getImmediatelyDeclaredConstraint() - ->printPretty(OS, nullptr, SemaRef.getPrintingPolicy()); - })); - else { - TPLInst.Clear(); - TransRetReq.emplace(TPL); - } - } - assert(TransRetReq.hasValue() && - "All code paths leading here must set TransRetReq"); - if (Expr *E = TransExpr.dyn_cast()) - return RebuildExprRequirement(E, Req->isSimple(), Req->getNoexceptLoc(), - std::move(*TransRetReq)); - return RebuildExprRequirement( - TransExpr.get(), - Req->isSimple(), Req->getNoexceptLoc(), std::move(*TransRetReq)); -} - -concepts::NestedRequirement * -TemplateInstantiator::TransformNestedRequirement( - concepts::NestedRequirement *Req) { - if (!Req->isDependent() && !AlwaysRebuild()) - return Req; - if (Req->isSubstitutionFailure()) { - if (AlwaysRebuild()) - return RebuildNestedRequirement( - Req->getSubstitutionDiagnostic()); - return Req; - } - Sema::InstantiatingTemplate ReqInst(SemaRef, - Req->getConstraintExpr()->getBeginLoc(), Req, - Sema::InstantiatingTemplate::ConstraintsCheck{}, - Req->getConstraintExpr()->getSourceRange()); - - ExprResult TransConstraint; - TemplateDeductionInfo Info(Req->getConstraintExpr()->getBeginLoc()); - { - EnterExpressionEvaluationContext ContextRAII( - SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); - Sema::SFINAETrap Trap(SemaRef); - Sema::InstantiatingTemplate ConstrInst(SemaRef, - Req->getConstraintExpr()->getBeginLoc(), Req, Info, - Req->getConstraintExpr()->getSourceRange()); - if (ConstrInst.isInvalid()) - return nullptr; - TransConstraint = TransformExpr(Req->getConstraintExpr()); - if (TransConstraint.isInvalid() || Trap.hasErrorOccurred()) - return RebuildNestedRequirement(createSubstDiag(SemaRef, Info, - [&] (llvm::raw_ostream& OS) { - Req->getConstraintExpr()->printPretty(OS, nullptr, - SemaRef.getPrintingPolicy()); - })); - } - return RebuildNestedRequirement(TransConstraint.get()); -} - - /// Perform substitution on the type T with a given set of template /// arguments. /// diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index a470cfc874407..64500d0a26d54 100755 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3600,12 +3600,6 @@ Decl *TemplateDeclInstantiator::VisitConceptDecl(ConceptDecl *D) { llvm_unreachable("Concept definitions cannot reside inside a template"); } -Decl * -TemplateDeclInstantiator::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) { - return RequiresExprBodyDecl::Create(SemaRef.Context, D->getDeclContext(), - D->getBeginLoc()); -} - Decl *TemplateDeclInstantiator::VisitDecl(Decl *D) { llvm_unreachable("Unexpected decl"); } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index efb4437b3e60e..a860640444e39 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2994,9 +2994,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case DeclaratorContext::PrototypeContext: Error = 0; break; - case DeclaratorContext::RequiresExprContext: - Error = 21; - break; case DeclaratorContext::LambdaExprParameterContext: // In C++14, generic lambdas allow 'auto' in their parameters. if (!SemaRef.getLangOpts().CPlusPlus14 || @@ -3224,7 +3221,6 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, case DeclaratorContext::ObjCParameterContext: case DeclaratorContext::ObjCResultContext: case DeclaratorContext::KNRTypeListContext: - case DeclaratorContext::RequiresExprContext: // C++ [dcl.fct]p6: // Types shall not be defined in return or parameter types. DiagID = diag::err_type_defined_in_param_type; @@ -4283,7 +4279,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case DeclaratorContext::TemplateTypeArgContext: case DeclaratorContext::TypeNameContext: case DeclaratorContext::FunctionalCastContext: - case DeclaratorContext::RequiresExprContext: // Don't infer in these contexts. break; } @@ -5232,7 +5227,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, switch (D.getContext()) { case DeclaratorContext::PrototypeContext: case DeclaratorContext::LambdaExprParameterContext: - case DeclaratorContext::RequiresExprContext: // C++0x [dcl.fct]p13: // [...] When it is part of a parameter-declaration-clause, the // parameter pack is a function parameter pack (14.5.3). The type T diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 1f72511738382..3b827fbc950b7 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -19,7 +19,6 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" -#include "clang/AST/ExprConcepts.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExprOpenMP.h" @@ -510,15 +509,6 @@ class TreeTransform { DeclarationNameInfo TransformDeclarationNameInfo(const DeclarationNameInfo &NameInfo); - bool TransformRequiresExprRequirements(ArrayRef Reqs, - llvm::SmallVectorImpl &Transformed); - concepts::TypeRequirement * - TransformTypeRequirement(concepts::TypeRequirement *Req); - concepts::ExprRequirement * - TransformExprRequirement(concepts::ExprRequirement *Req); - concepts::NestedRequirement * - TransformNestedRequirement(concepts::NestedRequirement *Req); - /// Transform the given template name. /// /// \param SS The nested-name-specifier that qualifies the template @@ -1066,8 +1056,23 @@ class TreeTransform { } if (Keyword == ETK_None || Keyword == ETK_Typename) { - return SemaRef.CheckTypenameType(Keyword, KeywordLoc, QualifierLoc, - *Id, IdLoc, DeducedTSTContext); + QualType T = SemaRef.CheckTypenameType(Keyword, KeywordLoc, QualifierLoc, + *Id, IdLoc); + // If a dependent name resolves to a deduced template specialization type, + // check that we're in one of the syntactic contexts permitting it. + if (!DeducedTSTContext) { + if (auto *Deduced = dyn_cast_or_null( + T.isNull() ? nullptr : T->getContainedDeducedType())) { + SemaRef.Diag(IdLoc, diag::err_dependent_deduced_tst) + << (int)SemaRef.getTemplateNameKindForDiagnostics( + Deduced->getTemplateName()) + << QualType(QualifierLoc.getNestedNameSpecifier()->getAsType(), 0); + if (auto *TD = Deduced->getTemplateName().getAsTemplateDecl()) + SemaRef.Diag(TD->getLocation(), diag::note_template_decl_here); + return QualType(); + } + } + return T; } TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForKeyword(Keyword); @@ -3073,56 +3078,7 @@ class TreeTransform { return Result; } - /// \brief Build a new requires expression. - /// - /// By default, performs semantic analysis to build the new expression. - /// Subclasses may override this routine to provide different behavior. - ExprResult RebuildRequiresExpr(SourceLocation RequiresKWLoc, - RequiresExprBodyDecl *Body, - ArrayRef LocalParameters, - ArrayRef Requirements, - SourceLocation ClosingBraceLoc) { - return RequiresExpr::Create(SemaRef.Context, RequiresKWLoc, Body, - LocalParameters, Requirements, ClosingBraceLoc); - } - - concepts::TypeRequirement * - RebuildTypeRequirement( - concepts::Requirement::SubstitutionDiagnostic *SubstDiag) { - return SemaRef.BuildTypeRequirement(SubstDiag); - } - - concepts::TypeRequirement *RebuildTypeRequirement(TypeSourceInfo *T) { - return SemaRef.BuildTypeRequirement(T); - } - - concepts::ExprRequirement * - RebuildExprRequirement( - concepts::Requirement::SubstitutionDiagnostic *SubstDiag, bool IsSimple, - SourceLocation NoexceptLoc, - concepts::ExprRequirement::ReturnTypeRequirement Ret) { - return SemaRef.BuildExprRequirement(SubstDiag, IsSimple, NoexceptLoc, - std::move(Ret)); - } - - concepts::ExprRequirement * - RebuildExprRequirement(Expr *E, bool IsSimple, SourceLocation NoexceptLoc, - concepts::ExprRequirement::ReturnTypeRequirement Ret) { - return SemaRef.BuildExprRequirement(E, IsSimple, NoexceptLoc, - std::move(Ret)); - } - - concepts::NestedRequirement * - RebuildNestedRequirement( - concepts::Requirement::SubstitutionDiagnostic *SubstDiag) { - return SemaRef.BuildNestedRequirement(SubstDiag); - } - - concepts::NestedRequirement *RebuildNestedRequirement(Expr *Constraint) { - return SemaRef.BuildNestedRequirement(Constraint); - } - - /// \brief Build a new Objective-C boxed expression. + /// \brief Build a new Objective-C boxed expression. /// /// By default, performs semantic analysis to build the new expression. /// Subclasses may override this routine to provide different behavior. @@ -11223,146 +11179,6 @@ TreeTransform::TransformConceptSpecializationExpr( &TransArgs); } -template -ExprResult -TreeTransform::TransformRequiresExpr(RequiresExpr *E) { - SmallVector TransParams; - SmallVector TransParamTypes; - Sema::ExtParameterInfoBuilder ExtParamInfos; - - // C++2a [expr.prim.req]p2 - // Expressions appearing within a requirement-body are unevaluated operands. - EnterExpressionEvaluationContext Ctx( - SemaRef, Sema::ExpressionEvaluationContext::Unevaluated); - - RequiresExprBodyDecl *Body = RequiresExprBodyDecl::Create( - getSema().Context, E->getBody()->getDeclContext(), - E->getBody()->getBeginLoc()); - - Sema::ContextRAII SavedContext(getSema(), Body, /*NewThisContext*/false); - - if (getDerived().TransformFunctionTypeParams(E->getRequiresKWLoc(), - E->getLocalParameters(), - /*ParamTypes=*/nullptr, - /*ParamInfos=*/nullptr, - TransParamTypes, &TransParams, - ExtParamInfos)) - return ExprError(); - - for (ParmVarDecl *Param : TransParams) - Param->setDeclContext(Body); - - SmallVector TransReqs; - if (getDerived().TransformRequiresExprRequirements(E->getRequirements(), - TransReqs)) - return ExprError(); - - for (concepts::Requirement *Req : TransReqs) { - if (auto *ER = dyn_cast(Req)) { - if (ER->getReturnTypeRequirement().isTypeConstraint()) { - ER->getReturnTypeRequirement() - .getTypeConstraintTemplateParameterList()->getParam(0) - ->setDeclContext(Body); - } - } - } - - return getDerived().RebuildRequiresExpr(E->getRequiresKWLoc(), Body, - TransParams, TransReqs, - E->getRBraceLoc()); -} - -template -bool TreeTransform::TransformRequiresExprRequirements( - ArrayRef Reqs, - SmallVectorImpl &Transformed) { - for (concepts::Requirement *Req : Reqs) { - concepts::Requirement *TransReq = nullptr; - if (auto *TypeReq = dyn_cast(Req)) - TransReq = getDerived().TransformTypeRequirement(TypeReq); - else if (auto *ExprReq = dyn_cast(Req)) - TransReq = getDerived().TransformExprRequirement(ExprReq); - else - TransReq = getDerived().TransformNestedRequirement( - cast(Req)); - if (!TransReq) - return true; - Transformed.push_back(TransReq); - } - return false; -} - -template -concepts::TypeRequirement * -TreeTransform::TransformTypeRequirement( - concepts::TypeRequirement *Req) { - if (Req->isSubstitutionFailure()) { - if (getDerived().AlwaysRebuild()) - return getDerived().RebuildTypeRequirement( - Req->getSubstitutionDiagnostic()); - return Req; - } - TypeSourceInfo *TransType = getDerived().TransformType(Req->getType()); - if (!TransType) - return nullptr; - return getDerived().RebuildTypeRequirement(TransType); -} - -template -concepts::ExprRequirement * -TreeTransform::TransformExprRequirement(concepts::ExprRequirement *Req) { - llvm::PointerUnion TransExpr; - if (Req->isExprSubstitutionFailure()) - TransExpr = Req->getExprSubstitutionDiagnostic(); - else { - ExprResult TransExprRes = getDerived().TransformExpr(Req->getExpr()); - if (TransExprRes.isInvalid()) - return nullptr; - TransExpr = TransExprRes.get(); - } - - llvm::Optional TransRetReq; - const auto &RetReq = Req->getReturnTypeRequirement(); - if (RetReq.isEmpty()) - TransRetReq.emplace(); - else if (RetReq.isSubstitutionFailure()) - TransRetReq.emplace(RetReq.getSubstitutionDiagnostic()); - else if (RetReq.isTypeConstraint()) { - TemplateParameterList *OrigTPL = - RetReq.getTypeConstraintTemplateParameterList(); - TemplateParameterList *TPL = - getDerived().TransformTemplateParameterList(OrigTPL); - if (!TPL) - return nullptr; - TransRetReq.emplace(TPL); - } - assert(TransRetReq.hasValue() && - "All code paths leading here must set TransRetReq"); - if (Expr *E = TransExpr.dyn_cast()) - return getDerived().RebuildExprRequirement(E, Req->isSimple(), - Req->getNoexceptLoc(), - std::move(*TransRetReq)); - return getDerived().RebuildExprRequirement( - TransExpr.get(), - Req->isSimple(), Req->getNoexceptLoc(), std::move(*TransRetReq)); -} - -template -concepts::NestedRequirement * -TreeTransform::TransformNestedRequirement( - concepts::NestedRequirement *Req) { - if (Req->isSubstitutionFailure()) { - if (getDerived().AlwaysRebuild()) - return getDerived().RebuildNestedRequirement( - Req->getSubstitutionDiagnostic()); - return Req; - } - ExprResult TransConstraint = - getDerived().TransformExpr(Req->getConstraintExpr()); - if (TransConstraint.isInvalid()) - return nullptr; - return getDerived().RebuildNestedRequirement(TransConstraint.get()); -} template ExprResult diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp index f93f1f77405d3..cdb5b17022c2f 100644 --- a/clang/lib/Serialization/ASTCommon.cpp +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -402,7 +402,6 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) { case Decl::Binding: case Decl::Concept: case Decl::LifetimeExtendedTemporary: - case Decl::RequiresExprBody: return false; // These indirectly derive from Redeclarable but are not actually diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 4fd079e9d8e15..96a7d5ae0a31c 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -375,7 +375,6 @@ namespace clang { void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); DeclID VisitTemplateDecl(TemplateDecl *D); void VisitConceptDecl(ConceptDecl *D); - void VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D); RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); void VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D); @@ -2038,9 +2037,6 @@ void ASTDeclReader::VisitConceptDecl(ConceptDecl *D) { mergeMergeable(D); } -void ASTDeclReader::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) { -} - ASTDeclReader::RedeclarableResult ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { RedeclarableResult Redecl = VisitRedeclarable(D); @@ -3843,9 +3839,6 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_CONCEPT: D = ConceptDecl::CreateDeserialized(Context, ID); break; - case DECL_REQUIRES_EXPR_BODY: - D = RequiresExprBodyDecl::CreateDeserialized(Context, ID); - break; case DECL_STATIC_ASSERT: D = StaticAssertDecl::CreateDeserialized(Context, ID); break; diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 5dd0ef9d43c3e..f558c26b5f1e8 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -724,15 +724,27 @@ void ASTStmtReader::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { E->setRParenLoc(readSourceLocation()); } -static ConstraintSatisfaction -readConstraintSatisfaction(ASTRecordReader &Record) { +void ASTStmtReader::VisitConceptSpecializationExpr( + ConceptSpecializationExpr *E) { + VisitExpr(E); + unsigned NumTemplateArgs = Record.readInt(); + E->NestedNameSpec = Record.readNestedNameSpecifierLoc(); + E->TemplateKWLoc = Record.readSourceLocation(); + E->ConceptName = Record.readDeclarationNameInfo(); + E->NamedConcept = readDeclAs(); + E->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); + llvm::SmallVector Args; + for (unsigned I = 0; I < NumTemplateArgs; ++I) + Args.push_back(Record.readTemplateArgument()); + E->setTemplateArguments(Args); ConstraintSatisfaction Satisfaction; Satisfaction.IsSatisfied = Record.readInt(); if (!Satisfaction.IsSatisfied) { unsigned NumDetailRecords = Record.readInt(); for (unsigned i = 0; i != NumDetailRecords; ++i) { Expr *ConstraintExpr = Record.readExpr(); - if (bool IsDiagnostic = Record.readInt()) { + bool IsDiagnostic = Record.readInt(); + if (IsDiagnostic) { SourceLocation DiagLocation = Record.readSourceLocation(); std::string DiagMessage = Record.readString(); Satisfaction.Details.emplace_back( @@ -743,137 +755,8 @@ readConstraintSatisfaction(ASTRecordReader &Record) { Satisfaction.Details.emplace_back(ConstraintExpr, Record.readExpr()); } } - return Satisfaction; -} - -void ASTStmtReader::VisitConceptSpecializationExpr( - ConceptSpecializationExpr *E) { - VisitExpr(E); - unsigned NumTemplateArgs = Record.readInt(); - E->NestedNameSpec = Record.readNestedNameSpecifierLoc(); - E->TemplateKWLoc = Record.readSourceLocation(); - E->ConceptName = Record.readDeclarationNameInfo(); - E->NamedConcept = readDeclAs(); - E->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); - llvm::SmallVector Args; - for (unsigned I = 0; I < NumTemplateArgs; ++I) - Args.push_back(Record.readTemplateArgument()); - E->setTemplateArguments(Args); - E->Satisfaction = E->isValueDependent() ? nullptr : - ASTConstraintSatisfaction::Create(Record.getContext(), - readConstraintSatisfaction(Record)); -} - -static concepts::Requirement::SubstitutionDiagnostic * -readSubstitutionDiagnostic(ASTRecordReader &Record) { - std::string SubstitutedEntity = Record.readString(); - SourceLocation DiagLoc = Record.readSourceLocation(); - std::string DiagMessage = Record.readString(); - return new (Record.getContext()) - concepts::Requirement::SubstitutionDiagnostic{SubstitutedEntity, DiagLoc, - DiagMessage}; -} - -void ASTStmtReader::VisitRequiresExpr(RequiresExpr *E) { - VisitExpr(E); - unsigned NumLocalParameters = Record.readInt(); - unsigned NumRequirements = Record.readInt(); - E->RequiresExprBits.RequiresKWLoc = Record.readSourceLocation(); - E->RequiresExprBits.IsSatisfied = Record.readInt(); - E->Body = Record.readDeclAs(); - llvm::SmallVector LocalParameters; - for (unsigned i = 0; i < NumLocalParameters; ++i) - LocalParameters.push_back(cast(Record.readDecl())); - std::copy(LocalParameters.begin(), LocalParameters.end(), - E->getTrailingObjects()); - llvm::SmallVector Requirements; - for (unsigned i = 0; i < NumRequirements; ++i) { - auto RK = - static_cast(Record.readInt()); - concepts::Requirement *R = nullptr; - switch (RK) { - case concepts::Requirement::RK_Type: { - auto Status = - static_cast( - Record.readInt()); - if (Status == concepts::TypeRequirement::SS_SubstitutionFailure) - R = new (Record.getContext()) - concepts::TypeRequirement(readSubstitutionDiagnostic(Record)); - else - R = new (Record.getContext()) - concepts::TypeRequirement(Record.readTypeSourceInfo()); - } break; - case concepts::Requirement::RK_Simple: - case concepts::Requirement::RK_Compound: { - auto Status = - static_cast( - Record.readInt()); - llvm::PointerUnion E; - if (Status == concepts::ExprRequirement::SS_ExprSubstitutionFailure) { - E = readSubstitutionDiagnostic(Record); - } else - E = Record.readExpr(); - - llvm::Optional Req; - ConceptSpecializationExpr *SubstitutedConstraintExpr = nullptr; - SourceLocation NoexceptLoc; - if (RK == concepts::Requirement::RK_Simple) { - Req.emplace(); - } else { - NoexceptLoc = Record.readSourceLocation(); - switch (auto returnTypeRequirementKind = Record.readInt()) { - case 0: - // No return type requirement. - Req.emplace(); - break; - case 1: { - // type-constraint - TemplateParameterList *TPL = Record.readTemplateParameterList(); - if (Status >= - concepts::ExprRequirement::SS_ConstraintsNotSatisfied) - SubstitutedConstraintExpr = - cast(Record.readExpr()); - Req.emplace(TPL); - } break; - case 2: - // Substitution failure - Req.emplace(readSubstitutionDiagnostic(Record)); - break; - } - } - if (Expr *Ex = E.dyn_cast()) - R = new (Record.getContext()) concepts::ExprRequirement( - Ex, RK == concepts::Requirement::RK_Simple, NoexceptLoc, - std::move(*Req), Status, SubstitutedConstraintExpr); - else - R = new (Record.getContext()) concepts::ExprRequirement( - E.get(), - RK == concepts::Requirement::RK_Simple, NoexceptLoc, - std::move(*Req)); - } break; - case concepts::Requirement::RK_Nested: { - if (bool IsSubstitutionDiagnostic = Record.readInt()) { - R = new (Record.getContext()) concepts::NestedRequirement( - readSubstitutionDiagnostic(Record)); - break; - } - Expr *E = Record.readExpr(); - if (E->isInstantiationDependent()) - R = new (Record.getContext()) concepts::NestedRequirement(E); - else - R = new (Record.getContext()) - concepts::NestedRequirement(Record.getContext(), E, - readConstraintSatisfaction(Record)); - } break; - } - if (!R) - continue; - Requirements.push_back(R); - } - std::copy(Requirements.begin(), Requirements.end(), - E->getTrailingObjects()); - E->RBraceLoc = Record.readSourceLocation(); + E->Satisfaction = ASTConstraintSatisfaction::Create(Record.getContext(), + Satisfaction); } void ASTStmtReader::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { @@ -3683,18 +3566,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { S = new (Context) DependentCoawaitExpr(Empty); break; - case EXPR_CONCEPT_SPECIALIZATION: { + case EXPR_CONCEPT_SPECIALIZATION: unsigned numTemplateArgs = Record[ASTStmtReader::NumExprFields]; S = ConceptSpecializationExpr::Create(Context, Empty, numTemplateArgs); break; - } - - case EXPR_REQUIRES: - unsigned numLocalParameters = Record[ASTStmtReader::NumExprFields]; - unsigned numRequirement = Record[ASTStmtReader::NumExprFields + 1]; - S = RequiresExpr::Create(Context, Empty, numLocalParameters, - numRequirement); - break; + } // We hit a STMT_STOP, so we're done with this expression. diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index c216b14661d41..8247f5a84ecaa 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -885,7 +885,6 @@ void ASTWriter::WriteBlockInfoBlock() { RECORD(DECL_NON_TYPE_TEMPLATE_PARM); RECORD(DECL_TEMPLATE_TEMPLATE_PARM); RECORD(DECL_CONCEPT); - RECORD(DECL_REQUIRES_EXPR_BODY); RECORD(DECL_TYPE_ALIAS_TEMPLATE); RECORD(DECL_STATIC_ASSERT); RECORD(DECL_CXX_BASE_SPECIFIERS); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 459e61713ed16..b2a8c118d4011 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -104,7 +104,6 @@ namespace clang { void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); void VisitTemplateDecl(TemplateDecl *D); void VisitConceptDecl(ConceptDecl *D); - void VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D); void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); void VisitVarTemplateDecl(VarTemplateDecl *D); @@ -1482,10 +1481,6 @@ void ASTDeclWriter::VisitConceptDecl(ConceptDecl *D) { Code = serialization::DECL_CONCEPT; } -void ASTDeclWriter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) { - Code = serialization::DECL_REQUIRES_EXPR_BODY; -} - void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { VisitRedeclarable(D); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 1b118c257a4cc..9231f3b2b9ba2 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "clang/Serialization/ASTRecordWriter.h" -#include "clang/Sema/DeclSpec.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" @@ -389,9 +388,19 @@ void ASTStmtWriter::VisitDependentCoawaitExpr(DependentCoawaitExpr *E) { Code = serialization::EXPR_DEPENDENT_COAWAIT; } -static void -addConstraintSatisfaction(ASTRecordWriter &Record, - const ASTConstraintSatisfaction &Satisfaction) { +void ASTStmtWriter::VisitConceptSpecializationExpr( + ConceptSpecializationExpr *E) { + VisitExpr(E); + ArrayRef TemplateArgs = E->getTemplateArguments(); + Record.push_back(TemplateArgs.size()); + Record.AddNestedNameSpecifierLoc(E->getNestedNameSpecifierLoc()); + Record.AddSourceLocation(E->getTemplateKWLoc()); + Record.AddDeclarationNameInfo(E->getConceptNameInfo()); + Record.AddDeclRef(E->getNamedConcept()); + Record.AddASTTemplateArgumentListInfo(E->getTemplateArgsAsWritten()); + for (const TemplateArgument &Arg : TemplateArgs) + Record.AddTemplateArgument(Arg); + const ASTConstraintSatisfaction &Satisfaction = E->getSatisfaction(); Record.push_back(Satisfaction.IsSatisfied); if (!Satisfaction.IsSatisfied) { Record.push_back(Satisfaction.NumRecords); @@ -409,98 +418,10 @@ addConstraintSatisfaction(ASTRecordWriter &Record, } } } -} - -static void -addSubstitutionDiagnostic( - ASTRecordWriter &Record, - const concepts::Requirement::SubstitutionDiagnostic *D) { - Record.AddString(D->SubstitutedEntity); - Record.AddSourceLocation(D->DiagLoc); - Record.AddString(D->DiagMessage); -} - -void ASTStmtWriter::VisitConceptSpecializationExpr( - ConceptSpecializationExpr *E) { - VisitExpr(E); - ArrayRef TemplateArgs = E->getTemplateArguments(); - Record.push_back(TemplateArgs.size()); - Record.AddNestedNameSpecifierLoc(E->getNestedNameSpecifierLoc()); - Record.AddSourceLocation(E->getTemplateKWLoc()); - Record.AddDeclarationNameInfo(E->getConceptNameInfo()); - Record.AddDeclRef(E->getNamedConcept()); - Record.AddASTTemplateArgumentListInfo(E->getTemplateArgsAsWritten()); - for (const TemplateArgument &Arg : TemplateArgs) - Record.AddTemplateArgument(Arg); - if (!E->isValueDependent()) - addConstraintSatisfaction(Record, E->getSatisfaction()); Code = serialization::EXPR_CONCEPT_SPECIALIZATION; } -void ASTStmtWriter::VisitRequiresExpr(RequiresExpr *E) { - VisitExpr(E); - Record.push_back(E->getLocalParameters().size()); - Record.push_back(E->getRequirements().size()); - Record.AddSourceLocation(E->RequiresExprBits.RequiresKWLoc); - Record.push_back(E->RequiresExprBits.IsSatisfied); - Record.AddDeclRef(E->getBody()); - for (ParmVarDecl *P : E->getLocalParameters()) - Record.AddDeclRef(P); - for (concepts::Requirement *R : E->getRequirements()) { - if (auto *TypeReq = dyn_cast(R)) { - Record.push_back(concepts::Requirement::RK_Type); - Record.push_back(TypeReq->Status); - if (TypeReq->Status == concepts::TypeRequirement::SS_SubstitutionFailure) - addSubstitutionDiagnostic(Record, TypeReq->getSubstitutionDiagnostic()); - else - Record.AddTypeSourceInfo(TypeReq->getType()); - } else if (auto *ExprReq = dyn_cast(R)) { - Record.push_back(ExprReq->getKind()); - Record.push_back(ExprReq->Status); - if (ExprReq->isExprSubstitutionFailure()) { - addSubstitutionDiagnostic(Record, - ExprReq->Value.get()); - } else - Record.AddStmt(ExprReq->Value.get()); - if (ExprReq->getKind() == concepts::Requirement::RK_Compound) { - Record.AddSourceLocation(ExprReq->NoexceptLoc); - const auto &RetReq = ExprReq->getReturnTypeRequirement(); - if (RetReq.isSubstitutionFailure()) { - Record.push_back(2); - addSubstitutionDiagnostic(Record, RetReq.getSubstitutionDiagnostic()); - } else if (RetReq.isTypeConstraint()) { - Record.push_back(1); - Record.AddTemplateParameterList( - RetReq.getTypeConstraintTemplateParameterList()); - if (ExprReq->Status >= - concepts::ExprRequirement::SS_ConstraintsNotSatisfied) - Record.AddStmt( - ExprReq->getReturnTypeRequirementSubstitutedConstraintExpr()); - } else { - assert(RetReq.isEmpty()); - Record.push_back(0); - } - } - } else { - auto *NestedReq = cast(R); - Record.push_back(concepts::Requirement::RK_Nested); - Record.push_back(NestedReq->isSubstitutionFailure()); - if (NestedReq->isSubstitutionFailure()){ - addSubstitutionDiagnostic(Record, - NestedReq->getSubstitutionDiagnostic()); - } else { - Record.AddStmt(NestedReq->Value.get()); - if (!NestedReq->isDependent()) - addConstraintSatisfaction(Record, *NestedReq->Satisfaction); - } - } - } - Record.AddSourceLocation(E->getEndLoc()); - - Code = serialization::EXPR_REQUIRES; -} - void ASTStmtWriter::VisitCapturedStmt(CapturedStmt *S) { VisitStmt(S); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index b542cf2c03038..f917a4c8637b6 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1386,7 +1386,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::AsTypeExprClass: case Stmt::ConceptSpecializationExprClass: case Stmt::CXXRewrittenBinaryOperatorClass: - case Stmt::RequiresExprClass: // Fall through. // Cases we intentionally don't evaluate, since they don't need diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp deleted file mode 100644 index 578efb5b24eae..0000000000000 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp +++ /dev/null @@ -1,175 +0,0 @@ -// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify - -static_assert(requires { { 0 }; }); -static_assert(requires { { "aaaa" }; }); -static_assert(requires { { (0).da }; }); // expected-error{{member reference base type 'int' is not a structure or union}} - -void foo() {} -static_assert(requires { { foo() }; }); - -// Substitution failure in expression - -struct A {}; -struct B { - B operator+(const B &other) const { return other; } -}; -struct C { - C operator+(C &other) const { return other; } -}; - -template requires requires (T a, const T& b) { { a + b }; } // expected-note{{because 'a + b' would be invalid: invalid operands to binary expression ('A' and 'const A')}} expected-note{{because 'a + b' would be invalid: invalid operands to binary expression ('C' and 'const C')}} -struct r1 {}; - -using r1i1 = r1; -using r1i2 = r1; // expected-error{{constraints not satisfied for class template 'r1' [with T = A]}} -using r1i3 = r1; -using r1i4 = r1; // expected-error{{constraints not satisfied for class template 'r1' [with T = C]}} - -struct D { void foo() {} }; - -template requires requires (T a) { { a.foo() }; } // expected-note{{because 'a.foo()' would be invalid: no member named 'foo' in 'A'}} expected-note{{because 'a.foo()' would be invalid: member reference base type 'int' is not a structure or union}} expected-note{{because 'a.foo()' would be invalid: 'this' argument to member function 'foo' has type 'const D', but function is not marked const}} -struct r2 {}; - -using r2i1 = r2; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}} -using r2i2 = r2; // expected-error{{constraints not satisfied for class template 'r2' [with T = A]}} -using r2i3 = r2; -using r2i4 = r2; // expected-error{{constraints not satisfied for class template 'r2' [with T = const D]}} - -template requires requires { { sizeof(T) }; } // expected-note{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}} expected-note{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'nonexistent'}} -struct r3 {}; - -using r3i1 = r3; -using r3i2 = r3; -using r3i3 = r3; -using r3i4 = r3; // expected-error{{constraints not satisfied for class template 'r3' [with T = void]}} -using r3i4 = r3; // expected-error{{constraints not satisfied for class template 'r3' [with T = nonexistent]}} - -// Non-dependent expressions - -template requires requires (T t) { { 0 }; { "a" }; { (void)'a' }; } -struct r4 {}; - -using r4i1 = r4; -using r4i2 = r4; -using r4i3 = r4; - -// Noexcept requirement -void maythrow() { } -static_assert(!requires { { maythrow() } noexcept; }); -static_assert(requires { { 1 } noexcept; }); - -struct E { void operator++(int) noexcept; }; -struct F { void operator++(int); }; - -template requires requires (T t) { { t++ } noexcept; } // expected-note{{because 't ++' may throw an exception}} -struct r5 {}; - -using r5i1 = r5; -using r5i2 = r5; -using r5i2 = r5; // expected-error{{constraints not satisfied for class template 'r5' [with T = F]}} - -template requires requires (T t) { { t.foo() } noexcept; } // expected-note{{because 't.foo()' would be invalid: no member named 'foo' in 'E'}} -struct r6 {}; - -using r6i = r6; // expected-error{{constraints not satisfied for class template 'r6' [with T = E]}} - -template -constexpr bool is_same_v = false; - -template -constexpr bool is_same_v = true; - -template -concept Same = is_same_v; - -template -concept Large = sizeof(T) >= 4; // expected-note{{because 'sizeof(short) >= 4' (2 >= 4) evaluated to false}} - -template requires requires (T t) { { t } -> Large; } // expected-note{{because 'decltype(t)' (aka 'short') does not satisfy 'Large':}} -struct r7 {}; - -using r7i1 = r7; -using r7i2 = r7; // expected-error{{constraints not satisfied for class template 'r7' [with T = short]}} - -template requires requires (T t) { { t } -> Same; } -struct r8 {}; - -using r8i1 = r8; -using r8i2 = r8; - -// Substitution failure in type constraint - -template requires requires (T t) { { t } -> Same; } // expected-note{{because 'Same' would be invalid: type 'int' cannot be used prior to '::' because it has no members}} -struct r9 {}; - -struct M { using type = M; }; - -using r9i1 = r9; -using r9i2 = r9; // expected-error{{constraints not satisfied for class template 'r9' [with T = int]}} - -// Substitution failure in both expression and return type requirement - -template requires requires (T t) { { t.foo() } -> Same; } // expected-note{{because 't.foo()' would be invalid: member reference base type 'int' is not a structure or union}} -struct r10 {}; - -using r10i = r10; // expected-error{{constraints not satisfied for class template 'r10' [with T = int]}} - -// Non-type concept in type constraint - -template -concept IsEven = (T % 2) == 0; - -template requires requires (T t) { { t } -> IsEven; } // expected-error{{concept named in type constraint is not a type concept}} -struct r11 {}; - -// C++ [expr.prim.req.compound] Example -namespace std_example { - template concept C1 = - requires(T x) { - {x++}; - }; - - template constexpr bool is_same_v = false; - template constexpr bool is_same_v = true; - - template concept same_as = is_same_v; - // expected-note@-1 {{because 'is_same_v' evaluated to false}} - - static_assert(C1); - static_assert(C1); - template struct C1_check {}; - using c1c1 = C1_check; - using c1c2 = C1_check; - - template concept C2 = - requires(T x) { - {*x} -> same_as; - // expected-note@-1{{because type constraint 'same_as' was not satisfied:}} - // expected-note@-2{{because '*x' would be invalid: indirection requires pointer operand ('int' invalid)}} - }; - - struct T1 { - using inner = int; - inner operator *() { return 0; } - }; - struct T2 { - using inner = int *; - int operator *() { return 0; } - }; - static_assert(C2); - template struct C2_check {}; // expected-note{{because 'int' does not satisfy 'C2'}} expected-note{{because 'std_example::T2' does not satisfy 'C2'}} - using c2c1 = C2_check; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = int]}} - using c2c2 = C2_check; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = std_example::T2]}} - - template - void g(T t) noexcept(sizeof(T) == 1) {} - - template concept C5 = - requires(T x) { - {g(x)} noexcept; // expected-note{{because 'g(x)' may throw an exception}} - }; - - static_assert(C5); - template struct C5_check {}; // expected-note{{because 'short' does not satisfy 'C5'}} - using c5 = C5_check; // expected-error{{constraints not satisfied for class template 'C5_check' [with T = short]}} -} \ No newline at end of file diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/equivalence.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/equivalence.cpp deleted file mode 100644 index ea34532019029..0000000000000 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/equivalence.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify - -template constexpr bool is_same_v = false; -template constexpr bool is_same_v = true; - -template struct identity { using type = T; }; -template using identity_t = T; - -// Type requirements -template requires requires { typename identity_t; } -struct r1; -template requires requires { typename identity_t; } // expected-note{{previous template declaration is here}} -struct r1; -template requires requires { typename identity_t; } // expected-error{{requires clause differs in template redeclaration}} -struct r1; -template requires requires { typename ::identity_t; } -struct r1; - -template requires requires { typename identity::type; } -struct r2; -template requires requires { typename identity::type; } -struct r2; -template requires requires { typename ::identity::type; } // expected-note 2{{previous template declaration is here}} -struct r2; -template requires requires { typename identity::typr; } // expected-error{{requires clause differs in template redeclaration}} -struct r2; -namespace ns { - template struct identity { using type = T; }; -} -template requires requires { typename ns::identity::type; } // expected-error{{requires clause differs in template redeclaration}} -struct r2; - -template requires requires { typename T::template identity::type; } -struct r3; -template requires requires { typename U::template identity::type; } // expected-note{{previous template declaration is here}} -struct r3; -template requires requires { typename T::template identitr::type; } // expected-error{{requires clause differs in template redeclaration}} -struct r3; - -template requires requires { typename T::template temp<>; } -struct r4; -template requires requires { typename U::template temp<>; } -struct r4; - -// Expr requirements -template requires requires { 0; } // expected-note{{previous template declaration is here}} -struct r5; -template requires requires { 1; } // expected-error{{requires clause differs in template redeclaration}} -struct r5; - -template -concept C1 = true; - -template requires requires { sizeof(T); } -struct r6; -template requires requires { sizeof(U); } // expected-note{{previous template declaration is here}} -struct r6; -template requires requires { sizeof(U) - 1; } // expected-error{{requires clause differs in template redeclaration}} -struct r6; -template requires requires { { sizeof(T) }; } // expected-note 2{{previous template declaration is here}} -struct r6; -template requires requires { { sizeof(T) } noexcept; } // expected-error{{requires clause differs in template redeclaration}} -struct r6; -template requires requires { { sizeof(T) } -> C1; } // expected-error{{requires clause differs in template redeclaration}} -struct r6; - -template requires requires { { sizeof(T) } -> C1; } -struct r7; -template requires requires { { sizeof(U) } -> C1; } -struct r7; -template requires requires { { sizeof(T) } -> C1<>; } // expected-note {{previous template declaration is here}} -struct r7; -template requires requires { { sizeof(U) }; } // expected-error{{requires clause differs in template redeclaration}} -struct r7; - -template -concept C2 = true; - -template requires requires { { sizeof(T) } -> C2; } -struct r8; -template requires requires { { sizeof(U) } -> C2; } // expected-note{{previous template declaration is here}} -struct r8; -template requires requires { { sizeof(T) } -> C2; } // expected-error{{requires clause differs in template redeclaration}} -struct r8; - -// Nested requirements -template requires requires { requires sizeof(T) == 0; } -struct r9; -template requires requires { requires sizeof(U) == 0; } // expected-note{{previous template declaration is here}} -struct r9; -template requires requires { requires sizeof(T) == 1; } // expected-error{{requires clause differs in template redeclaration}} -struct r9; - -// Parameter list -template requires requires { requires true; } -struct r10; -template requires requires() { requires true; } // expected-note{{previous template declaration is here}} -struct r10; -template requires requires(T i) { requires true; } // expected-error{{requires clause differs in template redeclaration}} -struct r10; - -template requires requires(T i, T *j) { requires true; } // expected-note 2{{previous template declaration is here}} -struct r11; -template requires requires(T i) { requires true; } // expected-error{{requires clause differs in template redeclaration}} -struct r11; -template requires requires(T i, T *j, T &k) { requires true; } // expected-error{{requires clause differs in template redeclaration}} -struct r11; - -// Parameter names -template requires requires(int i) { requires sizeof(i) == 1; } -struct r12; -template requires requires(int j) { requires sizeof(j) == 1; } // expected-note 2{{previous template declaration is here}} -struct r12; -template requires requires(int k) { requires sizeof(k) == 2; } // expected-error{{requires clause differs in template redeclaration}} -struct r12; -template requires requires(const int k) { requires sizeof(k) == 1; } // expected-error{{requires clause differs in template redeclaration}} -struct r12; - -// Order of requirements -template requires requires { requires true; 0; } -struct r13; -template requires requires { requires true; 0; } // expected-note{{previous template declaration is here}} -struct r13; -template requires requires { 0; requires true; } // expected-error{{requires clause differs in template redeclaration}} -struct r13; diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp deleted file mode 100644 index f8776832d33f7..0000000000000 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify - -static_assert(requires { requires true; }); - -template requires requires { requires false; } // expected-note{{because 'false' evaluated to false}} -struct r1 {}; - -using r1i = r1; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}} - -template requires requires { requires sizeof(T) == 0; } // expected-note{{because 'sizeof(int) == 0' (4 == 0) evaluated to false}} -struct r2 {}; - -using r2i = r2; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}} - -template requires requires (T t) { requires sizeof(t) == 0; } // expected-note{{because 'sizeof (t) == 0' (4 == 0) evaluated to false}} -struct r3 {}; - -using r3i = r3; // expected-error{{constraints not satisfied for class template 'r3' [with T = int]}} - -template -struct X { - template requires requires (U u) { requires sizeof(u) == sizeof(T); } // expected-note{{because 'sizeof (u) == sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}} - struct r4 {}; -}; - -using r4i = X::r4; // expected-error{{constraints not satisfied for class template 'r4' [with U = int]}} - -// C++ [expr.prim.req.nested] Examples -namespace std_example { - template concept C1 = sizeof(U) == 1; // expected-note{{because 'sizeof(int) == 1' (4 == 1) evaluated to false}} - template concept D = - requires (T t) { - requires C1; // expected-note{{because 'decltype(+t)' (aka 'int') does not satisfy 'C1'}} - }; - - struct T1 { char operator+() { return 'a'; } }; - static_assert(D); - template struct D_check {}; // expected-note{{because 'short' does not satisfy 'D'}} - using dc1 = D_check; // expected-error{{constraints not satisfied for class template 'D_check' [with T = short]}} - - template - concept C2 = requires (T a) { // expected-note{{'a' declared here}} - requires sizeof(a) == 4; // OK - requires a == 0; // expected-error{{constraint variable 'a' cannot be used in an evaluated context}} - }; -} \ No newline at end of file diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/p3.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/p3.cpp deleted file mode 100644 index a1a745253dd45..0000000000000 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/p3.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify - -// Examples from standard - -template -concept convertible_to = requires(T t) { U(t); }; - -template -concept R = requires (T i) { - typename T::type; - {*i} -> convertible_to; -}; - -template requires R struct S {}; - -struct T { - using type = int; - type i; - const type &operator*() { return i; } -}; - -using si = S; - -template -requires requires (T x) { x + x; } // expected-note{{because 'x + x' would be invalid: invalid operands to binary expression ('T' and 'T')}} -T add(T a, T b) { return a + b; } // expected-note{{candidate template ignored: constraints not satisfied [with T = T]}} - -int x = add(1, 2); -int y = add(T{}, T{}); // expected-error{{no matching function for call to 'add'}} - -template -concept C = requires (T x) { x + x; }; // expected-note{{because 'x + x' would be invalid: invalid operands to binary expression ('T' and 'T')}} -template requires C // expected-note{{because 'T' does not satisfy 'C'}} -T add2(T a, T b) { return a + b; } // expected-note{{candidate template ignored: constraints not satisfied [with T = T]}} - -int z = add2(1, 2); -int w = add2(T{}, T{}); // expected-error{{no matching function for call to 'add2'}} \ No newline at end of file diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/requires-expr.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/requires-expr.cpp deleted file mode 100644 index f9d8c3eed1115..0000000000000 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/requires-expr.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify - -using A = int; - -template -constexpr bool is_same_v = false; - -template -constexpr bool is_same_v = true; - -template -concept same_as = is_same_v; - -static_assert(requires { requires true; 0; typename A; - { 0 } -> same_as; }); -static_assert(is_same_v); - -// Check that requires expr is an unevaluated context. -struct Y { - int i; - static constexpr bool r = requires { i; }; -}; - -template requires requires (T t) { - requires false; // expected-note{{because 'false' evaluated to false}} - requires false; - requires requires { - requires false; - }; -} -struct r1 { }; - -using r1i = r1; -// expected-error@-1 {{constraints not satisfied for class template 'r1' [with T = int]}} - -template requires requires (T t) { - requires requires { - requires false; // expected-note{{because 'false' evaluated to false}} - }; -} -struct r2 { }; - -using r2i = r2; -// expected-error@-1 {{constraints not satisfied for class template 'r2' [with T = int]}} - -template requires requires (T t) { - requires requires { - requires true; - }; - requires true; - requires requires { - requires false; // expected-note{{because 'false' evaluated to false}} - }; -} -struct r3 { }; - -using r3i = r3; -// expected-error@-1 {{constraints not satisfied for class template 'r3' [with T = int]}} - -template -struct S { static const int s = T::value; }; - -template requires requires { T::value; S::s; } -// expected-note@-1 {{because 'T::value' would be invalid: type 'int' cannot be used prior to '::' because it has no members}} -struct r4 { }; - -using r4i = r4; -// expected-error@-1 {{constraints not satisfied for class template 'r4' [with T = int]}} \ No newline at end of file diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp deleted file mode 100644 index a5e6c3057fe60..0000000000000 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// RUN: %clang_cc1 %s -I%S -std=c++2a -fconcepts-ts -verify - -namespace std { struct type_info; } - -static_assert(requires { 0; }); -static_assert(requires { "aaaa"; }); -static_assert(requires { (0).da; }); // expected-error{{member reference base type 'int' is not a structure or union}} - -struct A {}; -struct B { - B operator+(const B &other) const { return other; } -}; -struct C { - C operator+(C &other) const { return other; } -}; - -template requires requires (T a, const T& b) { a + b; } -// expected-note@-1{{because 'a + b' would be invalid: invalid operands to binary expression ('A' and 'const A')}} -// expected-note@-2{{because 'a + b' would be invalid: invalid operands to binary expression ('C' and 'const C')}} -struct r1 {}; - -using r1i1 = r1; -using r1i2 = r1; // expected-error{{constraints not satisfied for class template 'r1' [with T = A]}} -using r1i3 = r1; -using r1i4 = r1; // expected-error{{constraints not satisfied for class template 'r1' [with T = C]}} - -struct D { void foo() {} }; - -template requires requires (T a) { a.foo(); } -// expected-note@-1{{because 'a.foo()' would be invalid: no member named 'foo' in 'A'}} -// expected-note@-2{{because 'a.foo()' would be invalid: member reference base type 'int' is not a structure or union}} -// expected-note@-3{{because 'a.foo()' would be invalid: 'this' argument to member function 'foo' has type 'const D', but function is not marked const}} -struct r2 {}; - -using r2i1 = r2; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}} -using r2i2 = r2; // expected-error{{constraints not satisfied for class template 'r2' [with T = A]}} -using r2i3 = r2; -using r2i4 = r2; // expected-error{{constraints not satisfied for class template 'r2' [with T = const D]}} - -template requires requires { sizeof(T); } -// expected-note@-1{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'void'}} -// expected-note@-2{{because 'sizeof(T)' would be invalid: invalid application of 'sizeof' to an incomplete type 'nonexistent'}} -struct r3 {}; - -using r3i1 = r3; -using r3i2 = r3; -using r3i3 = r3; -using r3i4 = r3; // expected-error{{constraints not satisfied for class template 'r3' [with T = void]}} -using r3i4 = r3; // expected-error{{constraints not satisfied for class template 'r3' [with T = nonexistent]}} - -template requires requires (T t) { 0; "a"; (void)'a'; } -struct r4 {}; - -using r4i1 = r4; -using r4i2 = r4; -using r4i3 = r4; - -template void f(T) = delete; -template requires (sizeof(T) == 1) void f(T) { } - -template requires requires(T t) { f(t); } -// expected-note@-1{{because 'f(t)' would be invalid: call to deleted function 'f'}} -struct r5 {}; - -using r5i1 = r5; -// expected-error@-1 {{constraints not satisfied for class template 'r5' [with T = int]}} -using r5i2 = r5; - -template -struct E { - struct non_default_constructible { non_default_constructible(T t) { } }; -}; - -template requires requires(T t) { typename E::non_default_constructible{}; } -// expected-note@-1 {{because 'typename E::non_default_constructible({})' would be invalid: no matching constructor for initialization of 'typename E::non_default_constructible'}} -struct r6 {}; - -using r6i1 = r6; -// expected-error@-1 {{constraints not satisfied for class template 'r6' [with T = int]}} - -template requires requires(T t) { typename E::non_default_constructible(); } -// expected-note@-1 {{because 'typename E::non_default_constructible()' would be invalid: no matching constructor for initialization of 'typename E::non_default_constructible'}} -struct r7 {}; - -using r7i1 = r7; -// expected-error@-1 {{constraints not satisfied for class template 'r7' [with T = int]}} - -// C++ [expr.prim.req.simple] Example -namespace std_example { - template concept C = - requires (T a, T b) { // expected-note{{because substituted constraint expression is ill-formed: argument may not have 'void' type}} - a + b; // expected-note{{because 'a + b' would be invalid: invalid operands to binary expression ('int *' and 'int *')}} - }; - - static_assert(C); - template struct C_check {}; // expected-note{{because 'void' does not satisfy 'C'}} expected-note{{because 'int *' does not satisfy 'C'}} - using c1c1 = C_check; // expected-error{{constraints not satisfied for class template 'C_check' [with T = void]}} - using c1c2 = C_check; // expected-error{{constraints not satisfied for class template 'C_check' [with T = int *]}} -} - -// typeid() of an expression becomes potentially evaluated if the expression is -// of a polymorphic type. -class X { virtual ~X(); }; -constexpr bool b = requires (X &x) { static_cast(nullptr); }; -// expected-error@-1{{constraint variable 'x' cannot be used in an evaluated context}} -// expected-note@-2{{'x' declared here}} diff --git a/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp deleted file mode 100644 index 8e402a88c4033..0000000000000 --- a/clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp +++ /dev/null @@ -1,194 +0,0 @@ -// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify - -using A = int; - -template using identity_t = T; // expected-note 4{{template is declared here}}} - -template struct identity { using type = T; }; -// expected-note@-1 2{{template is declared here}} - -struct C {}; - -struct D { static int type; }; // expected-note{{referenced member 'type' is declared here}} - -// Basic unqualified and global-qualified lookups - -static_assert(requires { typename A; typename ::A; }); -static_assert(requires { typename identity_t; typename ::identity_t; }); -static_assert(!requires { typename identity_t; }); // expected-error{{too many template arguments for alias template 'identity_t'}} -static_assert(!requires { typename ::identity_t; }); // expected-error{{too many template arguments for alias template 'identity_t'}} -static_assert(requires { typename identity; }); -static_assert(!requires { typename identity; }); -// expected-error@-1 {{typename specifier refers to class template; argument deduction not allowed here}} -static_assert(!requires { typename ::identity; }); -// expected-error@-1 {{typename specifier refers to class template; argument deduction not allowed here}} -static_assert(!requires { typename identity_t; }); -// expected-error@-1 {{typename specifier refers to alias template; argument deduction not allowed here}} -static_assert(!requires { typename ::identity_t; }); -// expected-error@-1 {{typename specifier refers to alias template; argument deduction not allowed here}} - -namespace ns { - using B = int; - int C = 0; - // expected-note@-1 {{referenced 'C' is declared here}} - static_assert(requires { typename A; typename B; typename ::A; }); - static_assert(!requires { typename ns::A; }); // expected-error{{no type named 'A' in namespace 'ns'}} - static_assert(!requires { typename ::B; }); // expected-error{{no type named 'B' in the global namespace}} - static_assert(requires { typename C; }); - // expected-error@-1 {{typename specifier refers to non-type 'C'}} -} - -// member type lookups - -static_assert(requires { typename identity::type; typename ::identity::type; }); -static_assert(!requires { typename identity::typr; }); // expected-error{{no type named 'typr' in 'identity'}} -static_assert(!requires { typename ::identity::typr; }); // expected-error{{no type named 'typr' in 'identity'}} - -template requires requires { typename T::type; } -// expected-note@-1 {{because 'typename T::type' would be invalid: type 'int' cannot be used prior to '::' because it has no members}} -// expected-note@-2 {{because 'typename T::type' would be invalid: no type named 'type' in 'C'}} -// expected-note@-3 {{because 'typename T::type' would be invalid: typename specifier refers to non-type member 'type' in 'D'}} -// expected-note@-4 {{in instantiation of template class 'invalid' requested here}} -// expected-note@-5 {{in instantiation of requirement here}} -// expected-note@-6 {{while substituting template arguments into constraint expression here}} -// expected-note@-7 {{because 'typename T::type' would be invalid}} -struct r1 {}; - -using r1i1 = r1>; -using r1i2 = r1; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}} -using r1i3 = r1; // expected-error{{constraints not satisfied for class template 'r1' [with T = C]}} -using r1i4 = r1; // expected-error{{constraints not satisfied for class template 'r1' [with T = D]}} - -template struct invalid { typename T::type x; }; -// expected-error@-1 {{typename specifier refers to non-type member 'type' in 'D'}} -using r1i5 = r1>; -// expected-error@-1 {{constraints not satisfied for class template 'r1' [with T = invalid]}} -// expected-note@-2 {{while checking constraint satisfaction for template 'r1 >' required here}} - -// mismatching template arguments - -template requires requires { typename identity; } // expected-note{{because 'typename identity' would be invalid: too many template arguments for class template 'identity'}} -struct r2 {}; - -using r2i1 = r2; -using r2i2 = r2; -using r2i3 = r2; // expected-error{{constraints not satisfied for class template 'r2' [with Ts = ]}} - -namespace ns2 { - template struct identity {}; - - template requires requires { typename identity; } // expected-note 2{{because 'typename identity' would be invalid: too few template arguments for class template 'identity'}} - struct r4 {}; - - using r4i1 = r4; // expected-error{{constraints not satisfied for class template 'r4' [with Ts = ]}} -} - -using r4i2 = ns2::r4; // expected-error{{constraints not satisfied for class template 'r4' [with Ts = ]}} - -using E = int; -template requires requires { typename E; } // expected-error{{expected ';' at end of requirement}} -struct r5v1 {}; -template requires requires { typename ::E; } // expected-error{{expected ';' at end of requirement}} -struct r5v2 {}; - -template requires (sizeof(T) == 1) -struct chars_only {}; - -template requires requires { typename chars_only; } // expected-note{{because 'typename chars_only' would be invalid: constraints not satisfied for class template 'chars_only' [with T = int]}} -struct r6 {}; - -using r6i = r6; // expected-error{{constraints not satisfied for class template 'r6' [with T = int]}} - -template int F = 0; // expected-note 2{{variable template 'F' declared here}} - -static_assert(!requires { typename F; }); -// expected-error@-1{{template name refers to non-type template 'F'}} -static_assert(!requires { typename ::F; }); -// expected-error@-1{{template name refers to non-type template '::F'}} - -struct G { template static T temp; }; - -template requires requires { typename T::template temp; } -// expected-note@-1{{because 'typename T::temp' would be invalid: type 'int' cannot be used prior to '::' because it has no members}} -// expected-note@-2{{because 'typename T::temp' would be invalid: no member named 'temp' in 'D'}} -// expected-note@-3{{because 'typename T::temp' would be invalid: template name refers to non-type template 'G::template temp'}} -struct r7 {}; - -using r7i1 = r7; // expected-error{{constraints not satisfied for class template 'r7' [with T = int]}} -using r7i2 = r7; // expected-error{{constraints not satisfied for class template 'r7' [with T = D]}} -using r7i3 = r7; // expected-error{{constraints not satisfied for class template 'r7' [with T = G]}} - -template struct H; - -template requires requires { typename H; } -struct r8 {}; - -using r8i = r8; - -template struct I { struct incomplete; }; // expected-note{{member is declared here}} - -static_assert(!requires { I::incomplete::inner; }); // expected-error{{implicit instantiation of undefined member 'I::incomplete'}} - -template requires requires { typename I::incomplete::inner; } // expected-note{{because 'typename I::incomplete::inner' would be invalid: implicit instantiation of undefined member 'I::incomplete'}} -struct r9 {}; - -using r9i = r9; // expected-error{{constraints not satisfied for class template 'r9' [with T = int]}} - -namespace ns3 { - struct X { }; // expected-note 2{{candidate found by name lookup is 'ns3::X'}} -} - -struct X { using inner = int; }; // expected-note 2{{candidate found by name lookup is 'X'}} - -using namespace ns3; -static_assert(requires { typename X; }); // expected-error{{reference to 'X' is ambiguous}} -static_assert(requires { typename X::inner; }); // expected-error{{reference to 'X' is ambiguous}} -// expected-error@-1{{unknown type name 'inner'}} - -// naming a type template specialization in a type requirement does not require -// it to be complete and should not care about partial specializations. - -template -struct Z; - -template requires (sizeof(T) >= 1) -struct Z {}; // expected-note{{partial specialization matches [with T = int]}} - -template requires (sizeof(T) <= 4) -struct Z {}; // expected-note{{partial specialization matches [with T = int]}} - -Z x; // expected-error{{ambiguous partial specializations of 'Z'}} - -static_assert(requires { typename Z; }); - -// C++ [expr.prim.req.type] Example -namespace std_example { - template struct S; - // expected-note@-1 {{because 'typename S' would be invalid: no type named 'type' in 'std_example::has_inner}} - template using Ref = T&; // expected-note{{because 'typename Ref' would be invalid: cannot form a reference to 'void'}} - template concept C1 = - requires { - typename T::inner; - // expected-note@-1 {{because 'typename T::inner' would be invalid: type 'int' cannot be used prior to '::' because it has no members}} - // expected-note@-2 {{because 'typename T::inner' would be invalid: no type named 'inner' in 'std_example::has_type'}} - }; - template concept C2 = requires { typename S; }; - template concept C3 = requires { typename Ref; }; - - struct has_inner { using inner = int;}; - struct has_type { using type = int; }; - struct has_inner_and_type { using inner = int; using type = int; }; - - static_assert(C1 && C2 && C3); - template struct C1_check {}; - // expected-note@-1 {{because 'int' does not satisfy 'C1'}} - // expected-note@-2 {{because 'std_example::has_type' does not satisfy 'C1'}} - template struct C2_check {}; - // expected-note@-1 {{because 'std_example::has_inner' does not satisfy 'C2'}} - template struct C3_check {}; - // expected-note@-1 {{because 'void' does not satisfy 'C3'}} - using c1 = C1_check; // expected-error{{constraints not satisfied for class template 'C1_check' [with T = int]}} - using c2 = C1_check; // expected-error{{constraints not satisfied for class template 'C1_check' [with T = std_example::has_type]}} - using c3 = C2_check; // expected-error{{constraints not satisfied for class template 'C2_check' [with T = std_example::has_inner]}} - using c4 = C3_check; // expected-error{{constraints not satisfied for class template 'C3_check' [with T = void]}} -} \ No newline at end of file diff --git a/clang/test/PCH/cxx2a-requires-expr.cpp b/clang/test/PCH/cxx2a-requires-expr.cpp deleted file mode 100644 index d52d451c2d687..0000000000000 --- a/clang/test/PCH/cxx2a-requires-expr.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// RUN: %clang_cc1 -emit-pch -std=c++2a -fconcepts-ts -o %t %s -// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x ast -ast-print %t | FileCheck %s - -template -concept C = true; - -template -concept C2 = true; - -template -bool f() { - // CHECK: requires (T t) { t++; { t++ } noexcept -> C; { t++ } -> C2; typename T::a; requires T::val; }; - return requires (T t) { - t++; - { t++ } noexcept -> C; - { t++ } -> C2; - typename T::a; - requires T::val; - }; -} diff --git a/clang/test/Parser/cxx2a-concepts-requires-expr.cpp b/clang/test/Parser/cxx2a-concepts-requires-expr.cpp deleted file mode 100644 index a53189caa5f7c..0000000000000 --- a/clang/test/Parser/cxx2a-concepts-requires-expr.cpp +++ /dev/null @@ -1,141 +0,0 @@ -// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify - -bool r1 = requires () {}; -// expected-error@-1 {{a requires expression must contain at least one requirement}} - -bool r2 = requires { requires true; }; - -bool r3 = requires (int a, ...) { requires true; }; -// expected-error@-1 {{varargs not allowed in requires expression}} - -template -bool r4 = requires (T... ts) { requires true; }; - -bool r5 = requires (bool c, int d) { c; d; }; - -bool r6 = requires (bool c, int d) { c; d; } && decltype(d){}; -// expected-error@-1 {{use of undeclared identifier 'd'}} - -bool r7 = requires (bool c) { c; (requires (int d) { c; d; }); d; } && decltype(c){} && decltype(d){}; -// expected-error@-1 2{{use of undeclared identifier 'd'}} -// expected-error@-2 {{use of undeclared identifier 'c'}} - -bool r8 = requires (bool, int) { requires true; }; - -bool r9 = requires (bool a, int a) { requires true; }; -// expected-error@-1 {{redefinition of parameter 'a'}} -// expected-note@-2 {{previous declaration is here}} - -bool r10 = requires (struct new_struct { int x; } s) { requires true; }; -// expected-error@-1 {{'new_struct' cannot be defined in a parameter type}} - -bool r11 = requires (int x(1)) { requires true; }; -// expected-error@-1 {{expected parameter declarator}} -// expected-error@-2 {{expected ')'}} -// expected-note@-3 {{to match this '('}} - -bool r12 = requires (int x = 10) { requires true; }; -// expected-error@-1 {{default arguments not allowed for parameters of a requires expression}} - -bool r13 = requires (int f(int)) { requires true; }; - -bool r14 = requires (int (*f)(int)) { requires true; }; - -bool r15 = requires (10) { requires true; }; -// expected-error@-1 {{expected parameter declarator}} - -bool r16 = requires (auto x) { requires true; }; -// expected-error@-1 {{'auto' not allowed in requires expression parameter}} - -bool r17 = requires (auto [x, y]) { requires true; }; -// expected-error@-1 {{'auto' not allowed in requires expression parameter}} -// expected-error@-2 {{use of undeclared identifier 'x'}} - -using a = int; - -bool r18 = requires { typename a; }; - -bool r19 = requires { typename ::a; }; - -template struct identity { using type = T; }; - -template using identity_t = T; - -bool r20 = requires { - typename identity::type; - typename identity; - typename ::identity_t; -}; - -struct s { bool operator==(const s&); ~s(); }; - -bool r21 = requires { typename s::operator==; }; -// expected-error@-1 {{expected an identifier or template-id after '::'}} - -bool r22 = requires { typename s::~s; }; -// expected-error@-1 {{expected an identifier or template-id after '::'}} - -template -bool r23 = requires { typename identity::temp; }; -// expected-error@-1 {{use 'template' keyword to treat 'temp' as a dependent template name}} - -template -bool r24 = requires { - typename identity::template temp; - typename identity::template temp; // expected-error{{expected an identifier or template-id after '::'}} -}; - -bool r25 = requires { ; }; -// expected-error@-1 {{expected expression}} - -bool r26 = requires { {}; }; -// expected-error@-1 {{expected expression}} - -bool r27 = requires { { 0 } noexcept; }; - -bool r28 = requires { { 0 } noexcept noexcept; }; -// expected-error@-1 {{expected '->' before expression type requirement}} -// expected-error@-2 {{expected concept name with optional arguments}} - -template -concept C1 = true; - -template -concept C2 = true; - -bool r29 = requires { { 0 } noexcept C1; }; -// expected-error@-1 {{expected '->' before expression type requirement}} - -bool r30 = requires { { 0 } noexcept -> C2; }; - -template -T i1 = 0; - -bool r31 = requires { requires false, 1; }; -// expected-error@-1 {{expected ';' at end of requirement}} - -bool r32 = requires { 0 noexcept; }; -// expected-error@-1 {{'noexcept' can only be used in a compound requirement (with '{' '}' around the expression)}} - -bool r33 = requires { 0 int; }; -// expected-error@-1 {{expected ';' at end of requirement}} - -bool r34 = requires { requires true }; -// expected-error@-1 {{expected ';' at end of requirement}} - -bool r35 = requires (bool b) { requires sizeof(b) == 1; }; - -void r36(bool b) requires requires { 1 } {} -// expected-error@-1 {{expected ';' at end of requirement}} - -bool r37 = requires { requires { 1; }; }; -// expected-warning@-1 {{this requires expression will only be checked for syntactic validity; did you intend to place it in a nested requirement? (add another 'requires' before the expression)}} - -bool r38 = requires { requires () { 1; }; }; -// expected-warning@-1 {{this requires expression will only be checked for syntactic validity; did you intend to place it in a nested requirement? (add another 'requires' before the expression)}} - -bool r39 = requires { requires (int i) { i; }; }; -// expected-warning@-1 {{this requires expression will only be checked for syntactic validity; did you intend to place it in a nested requirement? (add another 'requires' before the expression)}} - -bool r40 = requires { requires (); }; -// expected-error@-1 {{expected expression}} diff --git a/clang/test/SemaTemplate/instantiate-requires-expr.cpp b/clang/test/SemaTemplate/instantiate-requires-expr.cpp deleted file mode 100644 index 3304fd25cdc9d..0000000000000 --- a/clang/test/SemaTemplate/instantiate-requires-expr.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ %s -verify -Wno-unused-value - -template -constexpr bool is_same_v = false; - -template -constexpr bool is_same_v = true; - -// We use a hack in this file to make the compiler print out the requires -// expression after it has been instantiated - we put false_v as -// the requires clause of a class template, then instantiate the template. -// The requirement will not be satisfied, and the explaining diagnostic will -// print out false_v in its raw form (the false_v serves to -// prevent the diagnostic from elaborating on why the requires expr wasn't -// satisfied). - -template -constexpr bool false_v = false; - -template -using void_t = void; - -// Check that requires parameters are instantiated correctly. - -template requires -false_v; }> -// expected-note@-1 {{because 'false_v; }>' evaluated to false}} -// expected-note@-2 {{because 'false_v; }>' evaluated to false}} -struct r1 {}; - -using r1i1 = r1; // expected-error {{constraints not satisfied for class template 'r1' [with T = int]}} -using r1i2 = r1; // expected-error {{constraints not satisfied for class template 'r1' [with T = char]}} - -// Check that parameter packs work. - -template requires -false_v -// expected-note@-1 {{because 'false_v'}} -// expected-note@-2 {{because 'false_v' evaluated to false}} -struct r2 {}; - -using r2i1 = r2; // expected-error {{constraints not satisfied for class template 'r2' [with Ts = ]}} -using r2i2 = r2; // expected-error {{constraints not satisfied for class template 'r2' [with Ts = ]}} - -template requires -false_v<(requires (Ts ts) {requires sizeof(ts) != 0;} && ...)> -// expected-note@-1 {{because 'false_v' evaluated to false}} -// expected-note@-2 {{because 'false_v' evaluated to false}} -struct r3 {}; - -using r3i1 = r3; // expected-error {{constraints not satisfied for class template 'r3' [with Ts = ]}} -using r3i2 = r3; // expected-error {{constraints not satisfied for class template 'r3' [with Ts = ]}} - -template -struct identity { using type = T; }; - -namespace type_requirement { - struct A {}; - - // check that nested name specifier is instantiated correctly. - template requires false_v // expected-note{{because 'false_v::type; }>' evaluated to false}} - struct r1 {}; - - using r1i = r1>; // expected-error{{constraints not satisfied for class template 'r1' [with T = identity]}} - - // check that template argument list is instantiated correctly. - template - struct contains_template { - template requires is_same_v, U> - using temp = int; - }; - - template requires - false_v; }> - // expected-note@-1 {{because 'false_v::temp >; }>' evaluated to false}} - // expected-note@-2 {{because 'false_v::temp >; }>' evaluated to false}} - struct r2 {}; - - using r2i1 = r2>; // expected-error{{constraints not satisfied for class template 'r2' [with T = type_requirement::contains_template]}} - using r2i2 = r2>; // expected-error{{constraints not satisfied for class template 'r2' [with T = type_requirement::contains_template]}} - - // substitution error occurs, then requires expr is instantiated again - - template - struct a { - template requires (requires { typename T::a::a; }, false) - // expected-note@-1{{because 'requires { <>; } , false' evaluated to false}} - struct r {}; - }; - - using ari = a::r; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}} - - // Parameter pack inside expr - template requires - false_v<(requires { typename Ts::type; } && ...)> - // expected-note@-1 {{because 'false_v::type; } && requires { typename identity::type; } && requires { <>; }>' evaluated to false}} - struct r5 {}; - - using r5i = r5, identity, short>; // expected-error{{constraints not satisfied for class template 'r5' [with Ts = , identity, short>]}} - template requires - false_v<(requires { typename void_t; } && ...)> // expected-note{{because 'false_v; } && requires { typename void_t; }>' evaluated to false}} - struct r6 {}; - - using r6i = r6; // expected-error{{constraints not satisfied for class template 'r6' [with Ts = ]}} - - template requires - false_v<(requires { typename Ts::template aaa; } && ...)> - // expected-note@-1 {{because 'false_v>; } && requires { <>; }>' evaluated to false}} - struct r7 {}; - - using r7i = r7; // expected-error{{constraints not satisfied for class template 'r7' [with Ts = ]}} -} - -namespace expr_requirement { - // check that compound/simple requirements are instantiated correctly. - - template requires false_v - // expected-note@-1 {{because 'false_v' evaluated to false}} - // expected-note@-2 {{because 'false_v>; { sizeof(T) }; }>' evaluated to false}} - struct r1 {}; - - using r1i1 = r1; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}} - using r1i2 = r1; // expected-error{{constraints not satisfied for class template 'r1' [with T = void]}} - - // substitution error occurs in expr, then expr is instantiated again. - - template - struct a { - template requires (requires { sizeof(T::a); }, false) // expected-note{{because 'requires { <>; } , false' evaluated to false}} - struct r {}; - }; - - using ari = a::r; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}} - - // check that the return-type-requirement is instantiated correctly. - - template - concept C1 = is_same_v; - - template requires false_v C1; }> - // expected-note@-1 {{because 'false_v C1; }>' evaluated to false}} - // expected-note@-2 {{because 'false_v C1; }>' evaluated to false}} - struct r2 {}; - - using r2i1 = r2; // expected-error{{constraints not satisfied for class template 'r2' [with T = int]}} - using r2i2 = r2; // expected-error{{constraints not satisfied for class template 'r2' [with T = double]}} - - - // substitution error occurs in return type requirement, then requires expr is - // instantiated again. - - template - struct b { - template requires (requires { { 0 } -> C1; }, false) // expected-note{{because 'requires { { 0 } -> <>; } , false' evaluated to false}} - struct r {}; - }; - - using bri = b::r; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}} - - - template requires - false_v<(requires { { 0 } noexcept -> C1; } && ...)> - // expected-note@-1 {{because 'false_v C1; } && requires { { 0 } noexcept -> C1; }>' evaluated to false}} - struct r3 {}; - - using r3i = r3; // expected-error{{constraints not satisfied for class template 'r3' [with Ts = ]}} -} - -namespace nested_requirement { - // check that constraint expression is instantiated correctly - template requires false_v // expected-note{{because 'false_v' evaluated to false}} - struct r1 {}; - - using r1i = r1; // expected-error{{constraints not satisfied for class template 'r1' [with T = int]}} - - // substitution error occurs in expr, then expr is instantiated again. - template - struct a { - template requires - (requires { requires sizeof(T::a) == 0; }, false) // expected-note{{because 'requires { requires <>; } , false' evaluated to false}} - struct r {}; - }; - - using ari = a::r; // expected-error{{constraints not satisfied for class template 'r' [with U = short]}} - - // Parameter pack inside expr - template requires - false_v<(requires { requires sizeof(Ts) == 0; } && ...)> - // expected-note@-1 {{because 'false_v' evaluated to false}} - struct r2 {}; - - using r2i = r2; // expected-error{{constraints not satisfied for class template 'r2' [with Ts = ]}} -} - -// Parameter pack inside multiple requirements -template requires -false_v<(requires { requires sizeof(Ts) == 0; sizeof(Ts); } && ...)> -// expected-note@-1 {{because 'false_v' evaluated to false}} -struct r4 {}; - -using r4i = r4; // expected-error{{constraints not satisfied for class template 'r4' [with Ts = ]}} - -template requires -false_v<(requires(Ts t) { requires sizeof(t) == 0; t++; } && ...)> -// expected-note@-1 {{because 'false_v' evaluated to false}} -struct r5 {}; - -using r5i = r5; // expected-error{{constraints not satisfied for class template 'r5' [with Ts = ]}} - -template requires -false_v<(requires(T t) { T{t}; })> // T{t} creates an "UnevaluatedList" context. -// expected-note@-1 {{because 'false_v<(requires (int t) { int{t}; })>' evaluated to false}} -struct r6 {}; - -using r6i = r6; -// expected-error@-1 {{constraints not satisfied for class template 'r6' [with T = int]}} diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 9a09fca5e269e..6f3490471de56 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -6340,7 +6340,6 @@ CXCursor clang_getCursorDefinition(CXCursor C) { case Decl::UsingPack: case Decl::Concept: case Decl::LifetimeExtendedTemporary: - case Decl::RequiresExprBody: return C; // Declaration kinds that don't make any sense here, but are diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index 04b713c68b807..3632e0f85d10e 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -257,7 +257,6 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::TypeTraitExprClass: case Stmt::CoawaitExprClass: case Stmt::ConceptSpecializationExprClass: - case Stmt::RequiresExprClass: case Stmt::DependentCoawaitExprClass: case Stmt::CoyieldExprClass: case Stmt::CXXBindTemporaryExprClass: