summaryrefslogtreecommitdiffstats
path: root/clang/include
diff options
context:
space:
mode:
authorSaar Raz <saar@raz.email>2020-01-18 09:11:43 +0200
committerSaar Raz <saar@raz.email>2020-01-24 02:28:22 +0200
commitc96ef5118857ff938aa6d304ccf7c0f9b81bc5ba (patch)
treedd3f90c54e9cfd869b0e74b1f6b7bd85e8888094 /clang/include
parentab514b91196345ba4c61026e4997871e85ddd97d (diff)
downloadbcm5719-llvm-c96ef5118857ff938aa6d304ccf7c0f9b81bc5ba.tar.gz
bcm5719-llvm-c96ef5118857ff938aa6d304ccf7c0f9b81bc5ba.zip
[Concepts] Requires Expressions
Implement support for C++2a requires-expressions. Re-commit after compilation failure on some platforms due to alignment issues with PointerIntPair. Differential Revision: https://reviews.llvm.org/D50360 (cherry picked from commit a0f50d731639350c7a79f140f026c27a18215531)
Diffstat (limited to 'clang/include')
-rw-r--r--clang/include/clang/AST/ASTConcept.h1
-rw-r--r--clang/include/clang/AST/DeclCXX.h31
-rw-r--r--clang/include/clang/AST/ExprCXX.h94
-rw-r--r--clang/include/clang/AST/ExprConcepts.h540
-rw-r--r--clang/include/clang/AST/RecursiveASTVisitor.h25
-rw-r--r--clang/include/clang/AST/Stmt.h12
-rw-r--r--clang/include/clang/AST/StmtVisitor.h1
-rw-r--r--clang/include/clang/Basic/DeclNodes.td1
-rw-r--r--clang/include/clang/Basic/DiagnosticParseKinds.td27
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td66
-rw-r--r--clang/include/clang/Basic/StmtNodes.td1
-rw-r--r--clang/include/clang/Parse/Parser.h3
-rw-r--r--clang/include/clang/Sema/DeclSpec.h9
-rw-r--r--clang/include/clang/Sema/Sema.h84
-rw-r--r--clang/include/clang/Sema/SemaConcept.h7
-rw-r--r--clang/include/clang/Serialization/ASTBitCodes.h4
16 files changed, 800 insertions, 106 deletions
diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h
index 896d857d8c9..84a611c14e0 100644
--- a/clang/include/clang/AST/ASTConcept.h
+++ b/clang/include/clang/AST/ASTConcept.h
@@ -22,6 +22,7 @@
#include <utility>
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 b716ea453a5..2e8e31dbf4c 100644
--- a/clang/include/clang/AST/DeclCXX.h
+++ b/clang/include/clang/AST/DeclCXX.h
@@ -1893,6 +1893,37 @@ public:
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<typename T> 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 2c29409e0ca..cea360d12e9 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -14,7 +14,6 @@
#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"
@@ -4836,99 +4835,6 @@ public:
}
};
-/// \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<ConceptSpecializationExpr,
- TemplateArgument> {
- friend class ASTStmtReader;
- friend TrailingObjects;
-public:
- using SubstitutionDiagnostic = std::pair<SourceLocation, std::string>;
-
-protected:
- /// \brief The number of template arguments in the tail-allocated list of
- /// converted template arguments.
- unsigned NumTemplateArgs;
-
- /// \brief Information about the satisfaction of the named concept with the
- /// given arguments. If this expression is value dependent, this is to be
- /// ignored.
- ASTConstraintSatisfaction *Satisfaction;
-
- ConceptSpecializationExpr(const ASTContext &C, NestedNameSpecifierLoc NNS,
- SourceLocation TemplateKWLoc,
- DeclarationNameInfo ConceptNameInfo,
- NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
- const ASTTemplateArgumentListInfo *ArgsAsWritten,
- ArrayRef<TemplateArgument> ConvertedArgs,
- 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<TemplateArgument> ConvertedArgs,
- const ConstraintSatisfaction *Satisfaction);
-
- static ConceptSpecializationExpr *
- Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs);
-
- ArrayRef<TemplateArgument> getTemplateArguments() const {
- return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(),
- NumTemplateArgs);
- }
-
- /// \brief Set new template arguments for this concept specialization.
- void setTemplateArguments(ArrayRef<TemplateArgument> 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
new file mode 100644
index 00000000000..2a64326e860
--- /dev/null
+++ b/clang/include/clang/AST/ExprConcepts.h
@@ -0,0 +1,540 @@
+//===- 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 <utility>
+#include <string>
+
+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<ConceptSpecializationExpr,
+ TemplateArgument> {
+ friend class ASTStmtReader;
+ friend TrailingObjects;
+public:
+ using SubstitutionDiagnostic = std::pair<SourceLocation, std::string>;
+
+protected:
+ /// \brief The number of template arguments in the tail-allocated list of
+ /// converted template arguments.
+ unsigned NumTemplateArgs;
+
+ /// \brief Information about the satisfaction of the named concept with the
+ /// given arguments. If this expression is value dependent, this is to be
+ /// ignored.
+ ASTConstraintSatisfaction *Satisfaction;
+
+ ConceptSpecializationExpr(const ASTContext &C, NestedNameSpecifierLoc NNS,
+ SourceLocation TemplateKWLoc,
+ DeclarationNameInfo ConceptNameInfo,
+ NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ ArrayRef<TemplateArgument> ConvertedArgs,
+ 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<TemplateArgument> ConvertedArgs,
+ const ConstraintSatisfaction *Satisfaction);
+
+ static ConceptSpecializationExpr *
+ Create(ASTContext &C, EmptyShell Empty, unsigned NumTemplateArgs);
+
+ ArrayRef<TemplateArgument> getTemplateArguments() const {
+ return ArrayRef<TemplateArgument>(getTrailingObjects<TemplateArgument>(),
+ NumTemplateArgs);
+ }
+
+ /// \brief Set new template arguments for this concept specialization.
+ void setTemplateArguments(ArrayRef<TemplateArgument> 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<SubstitutionDiagnostic *, TypeSourceInfo *> 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<SubstitutionDiagnostic *>();
+ }
+
+ TypeSourceInfo *getType() const {
+ assert(!isSubstitutionFailure() &&
+ "Attempted to get type when there has been a substitution failure.");
+ return Value.get<TypeSourceInfo *>();
+ }
+
+ 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<TemplateParameterList *, SubstitutionDiagnostic *>,
+ 1, bool>
+ 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();
+ }
+
+ bool containsUnexpandedParameterPack() const {
+ if (!isTypeConstraint())
+ return false;
+ return getTypeConstraintTemplateParameterList()
+ ->containsUnexpandedParameterPack();
+ }
+
+ bool isEmpty() const {
+ return TypeConstraintInfo.getPointer().isNull();
+ }
+
+ bool isSubstitutionFailure() const {
+ return !isEmpty() &&
+ TypeConstraintInfo.getPointer().is<SubstitutionDiagnostic *>();
+ }
+
+ bool isTypeConstraint() const {
+ return !isEmpty() &&
+ TypeConstraintInfo.getPointer().is<TemplateParameterList *>();
+ }
+
+ SubstitutionDiagnostic *getSubstitutionDiagnostic() const {
+ assert(isSubstitutionFailure());
+ return TypeConstraintInfo.getPointer().get<SubstitutionDiagnostic *>();
+ }
+
+ const TypeConstraint *getTypeConstraint() const;
+
+ TemplateParameterList *getTypeConstraintTemplateParameterList() const {
+ assert(isTypeConstraint());
+ return TypeConstraintInfo.getPointer().get<TemplateParameterList *>();
+ }
+ };
+private:
+ llvm::PointerUnion<Expr *, SubstitutionDiagnostic *> 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<SubstitutionDiagnostic *>();
+ }
+
+ Expr *getExpr() const {
+ assert(!isExprSubstitutionFailure() &&
+ "ExprRequirement has no expression because there has been a "
+ "substitution failure.");
+ return Value.get<Expr *>();
+ }
+
+ 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<Expr *, SubstitutionDiagnostic *> 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 *>();
+ }
+
+ SubstitutionDiagnostic *getSubstitutionDiagnostic() const {
+ assert(isSubstitutionFailure() &&
+ "getSubstitutionDiagnostic() may not be called when there was no "
+ "substitution failure.");
+ return Value.get<SubstitutionDiagnostic *>();
+ }
+
+ Expr *getConstraintExpr() const {
+ assert(!isSubstitutionFailure() && "getConstraintExpr() may not be called "
+ "on nested requirements with "
+ "substitution failures.");
+ return Value.get<Expr *>();
+ }
+
+ 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<RequiresExpr, ParmVarDecl *,
+ concepts::Requirement *> {
+ friend TrailingObjects;
+ friend class ASTStmtReader;
+
+ unsigned NumLocalParameters;
+ unsigned NumRequirements;
+ RequiresExprBodyDecl *Body;
+ SourceLocation RBraceLoc;
+
+ unsigned numTrailingObjects(OverloadToken<ParmVarDecl *>) const {
+ return NumLocalParameters;
+ }
+
+ unsigned numTrailingObjects(OverloadToken<concepts::Requirement *>) const {
+ return NumRequirements;
+ }
+
+ RequiresExpr(ASTContext &C, SourceLocation RequiresKWLoc,
+ RequiresExprBodyDecl *Body,
+ ArrayRef<ParmVarDecl *> LocalParameters,
+ ArrayRef<concepts::Requirement *> Requirements,
+ SourceLocation RBraceLoc);
+ RequiresExpr(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters,
+ unsigned NumRequirements);
+
+public:
+ static RequiresExpr *
+ Create(ASTContext &C, SourceLocation RequiresKWLoc,
+ RequiresExprBodyDecl *Body, ArrayRef<ParmVarDecl *> LocalParameters,
+ ArrayRef<concepts::Requirement *> Requirements,
+ SourceLocation RBraceLoc);
+ static RequiresExpr *
+ Create(ASTContext &C, EmptyShell Empty, unsigned NumLocalParameters,
+ unsigned NumRequirements);
+
+ ArrayRef<ParmVarDecl *> getLocalParameters() const {
+ return {getTrailingObjects<ParmVarDecl *>(), NumLocalParameters};
+ }
+
+ RequiresExprBodyDecl *getBody() const { return Body; }
+
+ ArrayRef<concepts::Requirement *> getRequirements() const {
+ return {getTrailingObjects<concepts::Requirement *>(), 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 f8ab8e451d8..4633122aba4 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -23,6 +23,7 @@
#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"
@@ -2138,6 +2139,8 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
TRY_TO(TraverseStmt(D->getDefaultArg()));
})
+DEF_TRAVERSE_DECL(RequiresExprBodyDecl, {})
+
#undef DEF_TRAVERSE_DECL
// ----------------- Stmt traversal -----------------
@@ -2709,6 +2712,28 @@ 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<concepts::TypeRequirement>(Req)) {
+ if (!TypeReq->isSubstitutionFailure())
+ TRY_TO(TraverseTypeLoc(TypeReq->getType()->getTypeLoc()));
+ } else if (auto *ExprReq = dyn_cast<concepts::ExprRequirement>(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<concepts::NestedRequirement>(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 eaacb1a5b25..253b7694199 100644
--- a/clang/include/clang/AST/Stmt.h
+++ b/clang/include/clang/AST/Stmt.h
@@ -910,6 +910,17 @@ protected:
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 {
@@ -1008,6 +1019,7 @@ protected:
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 d3be93d228c..3e5155199ea 100644
--- a/clang/include/clang/AST/StmtVisitor.h
+++ b/clang/include/clang/AST/StmtVisitor.h
@@ -13,6 +13,7 @@
#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 c2c23237285..d5bbc604819 100644
--- a/clang/include/clang/Basic/DeclNodes.td
+++ b/clang/include/clang/Basic/DeclNodes.td
@@ -100,5 +100,6 @@ def OMPThreadPrivate : DeclNode<Decl>;
def OMPAllocate : DeclNode<Decl>;
def OMPRequires : DeclNode<Decl>;
def Empty : DeclNode<Decl>;
+def RequiresExprBody : DeclNode<Decl>, DeclContext;
def LifetimeExtendedTemporary : DeclNode<Decl>;
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 41f788e7d9b..105ed7bf6c8 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -744,6 +744,33 @@ 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<DiagGroup<"requires-expression">>;
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 7d8231d140e..82649ddf8ab 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2102,12 +2102,21 @@ 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}1">;
+ "|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">;
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<
@@ -2590,19 +2599,56 @@ 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 "
@@ -4588,6 +4634,8 @@ 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<UndefinedVarTemplate>;
@@ -4623,6 +4671,8 @@ 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<
@@ -4756,8 +4806,12 @@ 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 note_typename_refers_here : Note<
+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">;
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 294993298a1..41923cddc49 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -164,6 +164,7 @@ def CoyieldExpr : StmtNode<CoroutineSuspendExpr>;
// C++2a Concepts expressions
def ConceptSpecializationExpr : StmtNode<Expr>;
+def RequiresExpr : StmtNode<Expr>;
// Obj-C Expressions.
def ObjCStringLiteral : StmtNode<Expr>;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 182024ea510..41f46861d08 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -1933,6 +1933,7 @@ private:
//===--------------------------------------------------------------------===//
// C++ Concepts
+ ExprResult ParseRequiresExpression();
void ParseTrailingRequiresClause(Declarator &D);
//===--------------------------------------------------------------------===//
@@ -2771,7 +2772,7 @@ private:
Declarator &D,
SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo);
void ParseParameterDeclarationClause(
- Declarator &D,
+ DeclaratorContext DeclaratorContext,
ParsedAttributes &attrs,
SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
SourceLocation &EllipsisLoc);
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index aceec9cbe1c..1222549161e 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -1757,7 +1757,8 @@ 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.
+ AliasTemplateContext, // C++11 alias-declaration template.
+ RequiresExprContext // C++2a requires-expression.
};
@@ -1981,6 +1982,7 @@ public:
case DeclaratorContext::TemplateTypeArgContext:
case DeclaratorContext::TrailingReturnContext:
case DeclaratorContext::TrailingReturnVarContext:
+ case DeclaratorContext::RequiresExprContext:
return true;
}
llvm_unreachable("unknown context kind!");
@@ -2003,6 +2005,7 @@ public:
case DeclaratorContext::TemplateParamContext:
case DeclaratorContext::CXXCatchContext:
case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::RequiresExprContext:
return true;
case DeclaratorContext::TypeNameContext:
@@ -2039,6 +2042,7 @@ public:
case DeclaratorContext::MemberContext:
case DeclaratorContext::PrototypeContext:
case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::RequiresExprContext:
// Maybe one day...
return false;
@@ -2116,6 +2120,7 @@ public:
case DeclaratorContext::TemplateArgContext:
case DeclaratorContext::TemplateTypeArgContext:
case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::RequiresExprContext:
return false;
}
llvm_unreachable("unknown context kind!");
@@ -2337,6 +2342,7 @@ public:
case DeclaratorContext::TemplateTypeArgContext:
case DeclaratorContext::TrailingReturnContext:
case DeclaratorContext::TrailingReturnVarContext:
+ case DeclaratorContext::RequiresExprContext:
return false;
}
llvm_unreachable("unknown context kind!");
@@ -2370,6 +2376,7 @@ public:
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 4789fad8956..0f02c0f9d2b 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -21,6 +21,7 @@
#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"
@@ -6282,13 +6283,17 @@ public:
/// \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);
+ DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction,
+ bool First = true);
/// \brief Emit diagnostics explaining why a constraint expression was deemed
/// unsatisfied.
void
- DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction& Satisfaction);
+ DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction,
+ bool First = true);
/// \brief Emit diagnostics explaining why a constraint expression was deemed
/// unsatisfied because it was ill-formed.
@@ -7262,7 +7267,17 @@ public:
SourceLocation KeywordLoc,
NestedNameSpecifierLoc QualifierLoc,
const IdentifierInfo &II,
- SourceLocation IILoc);
+ SourceLocation IILoc,
+ TypeSourceInfo **TSI,
+ bool DeducedTSTContext);
+
+ QualType CheckTypenameType(ElaboratedTypeKeyword Keyword,
+ SourceLocation KeywordLoc,
+ NestedNameSpecifierLoc QualifierLoc,
+ const IdentifierInfo &II,
+ SourceLocation IILoc,
+ bool DeducedTSTContext = true);
+
TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T,
SourceLocation Loc,
@@ -7282,11 +7297,52 @@ public:
const TemplateArgument *Args,
unsigned NumArgs);
- // Concepts
+ //===--------------------------------------------------------------------===//
+ // C++ Concepts
+ //===--------------------------------------------------------------------===//
Decl *ActOnConceptDefinition(
Scope *S, MultiTemplateParamsArg TemplateParameterLists,
IdentifierInfo *Name, SourceLocation NameLoc, Expr *ConstraintExpr);
+ RequiresExprBodyDecl *
+ ActOnStartRequiresExpr(SourceLocation RequiresKWLoc,
+ ArrayRef<ParmVarDecl *> 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<ParmVarDecl *> LocalParameters,
+ ArrayRef<concepts::Requirement *> Requirements,
+ SourceLocation ClosingBraceLoc);
+
//===--------------------------------------------------------------------===//
// C++ Variadic Templates (C++0x [temp.variadic])
//===--------------------------------------------------------------------===//
@@ -7933,6 +7989,13 @@ public:
/// 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,
@@ -8254,6 +8317,19 @@ public:
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 acd1e604211..7fc42a4816e 100644
--- a/clang/include/clang/Sema/SemaConcept.h
+++ b/clang/include/clang/Sema/SemaConcept.h
@@ -13,10 +13,17 @@
#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 <string>
+#include <utility>
+
namespace clang {
class Sema;
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 1bfcbda8c9f..44a12c875da 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1403,6 +1403,9 @@ namespace serialization {
/// An LifetimeExtendedTemporaryDecl record.
DECL_LIFETIME_EXTENDED_TEMPORARY,
+ /// A RequiresExprBodyDecl record.
+ DECL_REQUIRES_EXPR_BODY,
+
/// An ObjCTypeParamDecl record.
DECL_OBJC_TYPE_PARAM,
@@ -1785,6 +1788,7 @@ namespace serialization {
EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr
EXPR_CXX_FOLD, // CXXFoldExpr
EXPR_CONCEPT_SPECIALIZATION,// ConceptSpecializationExpr
+ EXPR_REQUIRES, // RequiresExpr
// CUDA
EXPR_CUDA_KERNEL_CALL, // CUDAKernelCallExpr
OpenPOWER on IntegriCloud