summaryrefslogtreecommitdiff
path: root/clang/include
diff options
context:
space:
mode:
Diffstat (limited to 'clang/include')
-rw-r--r--clang/include/clang/AST/ASTConcept.h31
-rw-r--r--clang/include/clang/AST/ASTContext.h7
-rw-r--r--clang/include/clang/AST/ASTNodeTraverser.h4
-rw-r--r--clang/include/clang/AST/DeclCXX.h31
-rw-r--r--clang/include/clang/AST/DeclTemplate.h43
-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/PropertiesBase.td2
-rw-r--r--clang/include/clang/AST/RecursiveASTVisitor.h39
-rw-r--r--clang/include/clang/AST/Stmt.h12
-rw-r--r--clang/include/clang/AST/StmtVisitor.h1
-rw-r--r--clang/include/clang/AST/TemplateBase.h7
-rw-r--r--clang/include/clang/AST/Type.h74
-rw-r--r--clang/include/clang/AST/TypeLoc.h138
-rw-r--r--clang/include/clang/AST/TypeProperties.td11
-rw-r--r--clang/include/clang/Basic/AttrDocs.td2
-rw-r--r--clang/include/clang/Basic/Builtins.def3
-rw-r--r--clang/include/clang/Basic/CodeGenOptions.def1
-rw-r--r--clang/include/clang/Basic/DeclNodes.td1
-rw-r--r--clang/include/clang/Basic/DiagnosticDriverKinds.td2
-rw-r--r--clang/include/clang/Basic/DiagnosticFrontendKinds.td3
-rw-r--r--clang/include/clang/Basic/DiagnosticParseKinds.td42
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td68
-rw-r--r--clang/include/clang/Basic/LangOptions.def2
-rw-r--r--clang/include/clang/Basic/StmtNodes.td1
-rw-r--r--clang/include/clang/Basic/TokenKinds.def2
-rw-r--r--clang/include/clang/Driver/CC1Options.td8
-rw-r--r--clang/include/clang/Driver/Driver.h2
-rw-r--r--clang/include/clang/Driver/Options.td2
-rw-r--r--clang/include/clang/Parse/Parser.h25
-rw-r--r--clang/include/clang/Sema/DeclSpec.h81
-rw-r--r--clang/include/clang/Sema/ParsedTemplate.h24
-rw-r--r--clang/include/clang/Sema/Scope.h6
-rw-r--r--clang/include/clang/Sema/ScopeInfo.h20
-rw-r--r--clang/include/clang/Sema/Sema.h164
-rw-r--r--clang/include/clang/Sema/SemaConcept.h7
-rw-r--r--clang/include/clang/Sema/TemplateDeduction.h1
-rw-r--r--clang/include/clang/Serialization/ASTBitCodes.h4
38 files changed, 1280 insertions, 225 deletions
diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h
index 896d857d8c96c..30c4706d2a156 100644
--- a/clang/include/clang/AST/ASTConcept.h
+++ b/clang/include/clang/AST/ASTConcept.h
@@ -22,10 +22,25 @@
#include <utility>
namespace clang {
class ConceptDecl;
+class ConceptSpecializationExpr;
+
+/// The result of a constraint satisfaction check, containing the necessary
+/// information to diagnose an unsatisfied constraint.
+class ConstraintSatisfaction : public llvm::FoldingSetNode {
+ // The template-like entity that 'owns' the constraint checked here (can be a
+ // constrained entity or a concept).
+ NamedDecl *ConstraintOwner = nullptr;
+ llvm::SmallVector<TemplateArgument, 4> TemplateArgs;
+
+public:
+
+ ConstraintSatisfaction() = default;
+
+ ConstraintSatisfaction(NamedDecl *ConstraintOwner,
+ ArrayRef<TemplateArgument> TemplateArgs) :
+ ConstraintOwner(ConstraintOwner), TemplateArgs(TemplateArgs.begin(),
+ TemplateArgs.end()) { }
-/// \brief The result of a constraint satisfaction check, containing the
-/// necessary information to diagnose an unsatisfied constraint.
-struct ConstraintSatisfaction {
using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>;
using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>;
@@ -37,9 +52,13 @@ struct ConstraintSatisfaction {
/// invalid expression.
llvm::SmallVector<std::pair<const Expr *, Detail>, 4> Details;
- // This can leak if used in an AST node, use ASTConstraintSatisfaction
- // instead.
- void *operator new(size_t bytes, ASTContext &C) = delete;
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) {
+ Profile(ID, C, ConstraintOwner, TemplateArgs);
+ }
+
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C,
+ NamedDecl *ConstraintOwner,
+ ArrayRef<TemplateArgument> TemplateArgs);
};
/// Pairs of unsatisfied atomic constraint expressions along with the
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index fb269cef1ce8a..f8403cf13c4a0 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -88,6 +88,7 @@ class AtomicExpr;
class BlockExpr;
class BuiltinTemplateDecl;
class CharUnits;
+class ConceptDecl;
class CXXABI;
class CXXConstructorDecl;
class CXXMethodDecl;
@@ -211,7 +212,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
mutable llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;
mutable llvm::FoldingSet<DependentUnaryTransformType>
DependentUnaryTransformTypes;
- mutable llvm::FoldingSet<AutoType> AutoTypes;
+ mutable llvm::ContextualFoldingSet<AutoType, ASTContext&> AutoTypes;
mutable llvm::FoldingSet<DeducedTemplateSpecializationType>
DeducedTemplateSpecializationTypes;
mutable llvm::FoldingSet<AtomicType> AtomicTypes;
@@ -1542,7 +1543,9 @@ public:
/// C++11 deduced auto type.
QualType getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
- bool IsDependent, bool IsPack = false) const;
+ bool IsDependent, bool IsPack = false,
+ ConceptDecl *TypeConstraintConcept = nullptr,
+ ArrayRef<TemplateArgument> TypeConstraintArgs ={}) const;
/// C++11 deduction pattern for 'auto' type.
QualType getAutoDeductType() const;
diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index e0ebb020e697c..9ebf64a12af5c 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -548,8 +548,8 @@ public:
}
void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) {
- if (const auto *TC = D->getPlaceholderTypeConstraint())
- Visit(TC->getImmediatelyDeclaredConstraint());
+ if (const auto *E = D->getPlaceholderTypeConstraint())
+ Visit(E);
if (D->hasDefaultArgument())
Visit(D->getDefaultArgument(), SourceRange(),
D->getDefaultArgStorage().getInheritedFrom(),
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h
index b716ea453a5a0..2e8e31dbf4c7b 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/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 7a55d04a0f352..7a9f623d8152b 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -1102,6 +1102,17 @@ public:
/// template.
ArrayRef<TemplateArgument> getInjectedTemplateArgs();
+ /// Return whether this function template is an abbreviated function template,
+ /// e.g. `void foo(auto x)` or `template<typename T> void foo(auto x)`
+ bool isAbbreviated() const {
+ // Since the invented template parameters generated from 'auto' parameters
+ // are either appended to the end of the explicit template parameter list or
+ // form a new template paramter list, we can simply observe the last
+ // parameter to determine if such a thing happened.
+ const TemplateParameterList *TPL = getTemplateParameters();
+ return TPL->getParam(TPL->size() - 1)->isImplicit();
+ }
+
/// Merge \p Prev with our RedeclarableTemplateDecl::Common.
void mergePrevDecl(FunctionTemplateDecl *Prev);
@@ -1215,7 +1226,6 @@ public:
bool ParameterPack,
bool HasTypeConstraint = false,
Optional<unsigned> NumExpanded = None);
-
static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
unsigned ID);
static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C,
@@ -1374,7 +1384,8 @@ class NonTypeTemplateParmDecl final
: public DeclaratorDecl,
protected TemplateParmPosition,
private llvm::TrailingObjects<NonTypeTemplateParmDecl,
- std::pair<QualType, TypeSourceInfo *>> {
+ std::pair<QualType, TypeSourceInfo *>,
+ Expr *> {
friend class ASTDeclReader;
friend TrailingObjects;
@@ -1429,10 +1440,12 @@ public:
ArrayRef<TypeSourceInfo *> ExpandedTInfos);
static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C,
- unsigned ID);
+ unsigned ID,
+ bool HasTypeConstraint);
static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C,
unsigned ID,
- unsigned NumExpandedTypes);
+ unsigned NumExpandedTypes,
+ bool HasTypeConstraint);
using TemplateParmPosition::getDepth;
using TemplateParmPosition::setDepth;
@@ -1543,20 +1556,22 @@ public:
return TypesAndInfos[I].second;
}
- /// Return the type-constraint in the placeholder type of this non-type
+ /// Return the constraint introduced by the placeholder type of this non-type
/// template parameter (if any).
- TypeConstraint *getPlaceholderTypeConstraint() const {
- // TODO: Concepts: Implement once we have actual placeholders with type
- // constraints.
- return nullptr;
+ Expr *getPlaceholderTypeConstraint() const {
+ return hasPlaceholderTypeConstraint() ? *getTrailingObjects<Expr *>() :
+ nullptr;
+ }
+
+ void setPlaceholderTypeConstraint(Expr *E) {
+ *getTrailingObjects<Expr *>() = E;
}
/// Determine whether this non-type template parameter's type has a
/// placeholder with a type-constraint.
bool hasPlaceholderTypeConstraint() const {
- // TODO: Concepts: Implement once we have actual placeholders with type
- // constraints.
- return false;
+ auto *AT = getType()->getContainedAutoType();
+ return AT && AT->isConstrained();
}
/// \brief Get the associated-constraints of this template parameter.
@@ -1566,8 +1581,8 @@ public:
/// Use this instead of getPlaceholderImmediatelyDeclaredConstraint for
/// concepts APIs that accept an ArrayRef of constraint expressions.
void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
- if (TypeConstraint *TC = getPlaceholderTypeConstraint())
- AC.push_back(TC->getImmediatelyDeclaredConstraint());
+ if (Expr *E = getPlaceholderTypeConstraint())
+ AC.push_back(E);
}
// Implement isa/cast/dyncast/etc.
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index 2c29409e0ca57..cea360d12e91e 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 0000000000000..2a64326e8604b
--- /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/PropertiesBase.td b/clang/include/clang/AST/PropertiesBase.td
index 9aacdb9fee362..ba0f237a3bc3c 100644
--- a/clang/include/clang/AST/PropertiesBase.td
+++ b/clang/include/clang/AST/PropertiesBase.td
@@ -99,6 +99,8 @@ def DeclRef : RefPropertyType<"Decl"> { let ConstWhenWriting = 1; }
SubclassPropertyType<"TagDecl", DeclRef>;
def TemplateDeclRef :
SubclassPropertyType<"TemplateDecl", DeclRef>;
+ def ConceptDeclRef :
+ SubclassPropertyType<"ConceptDecl", DeclRef>;
def TemplateTypeParmDeclRef :
SubclassPropertyType<"TemplateTypeParmDecl", DeclRef>;
def TemplateTemplateParmDeclRef :
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index f8ab8e451d8c3..86521d82c6ff1 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"
@@ -1039,7 +1040,13 @@ DEF_TRAVERSE_TYPE(UnaryTransformType, {
TRY_TO(TraverseType(T->getUnderlyingType()));
})
-DEF_TRAVERSE_TYPE(AutoType, { TRY_TO(TraverseType(T->getDeducedType())); })
+DEF_TRAVERSE_TYPE(AutoType, {
+ TRY_TO(TraverseType(T->getDeducedType()));
+ if (T->isConstrained()) {
+ TRY_TO(TraverseDecl(T->getTypeConstraintConcept()));
+ TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
+ }
+})
DEF_TRAVERSE_TYPE(DeducedTemplateSpecializationType, {
TRY_TO(TraverseTemplateName(T->getTemplateName()));
TRY_TO(TraverseType(T->getDeducedType()));
@@ -1286,6 +1293,12 @@ DEF_TRAVERSE_TYPELOC(UnaryTransformType, {
DEF_TRAVERSE_TYPELOC(AutoType, {
TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
+ if (TL.isConstrained()) {
+ TRY_TO(TraverseNestedNameSpecifierLoc(TL.getNestedNameSpecifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(TL.getConceptNameInfo()));
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I)
+ TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I)));
+ }
})
DEF_TRAVERSE_TYPELOC(DeducedTemplateSpecializationType, {
@@ -2138,6 +2151,8 @@ DEF_TRAVERSE_DECL(ParmVarDecl, {
TRY_TO(TraverseStmt(D->getDefaultArg()));
})
+DEF_TRAVERSE_DECL(RequiresExprBodyDecl, {})
+
#undef DEF_TRAVERSE_DECL
// ----------------- Stmt traversal -----------------
@@ -2709,6 +2724,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 eaacb1a5b252e..253b76941991c 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 d3be93d228ccb..3e5155199eace 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/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h
index 058a5bc0a0674..93f7b62b8aea2 100644
--- a/clang/include/clang/AST/TemplateBase.h
+++ b/clang/include/clang/AST/TemplateBase.h
@@ -637,7 +637,7 @@ public:
}
static const ASTTemplateArgumentListInfo *
- Create(ASTContext &C, const TemplateArgumentListInfo &List);
+ Create(const ASTContext &C, const TemplateArgumentListInfo &List);
};
/// Represents an explicit template argument list in C++, e.g.,
@@ -702,6 +702,11 @@ inline const TemplateArgument &
return getArgs()[Idx];
}
+inline const TemplateArgument &AutoType::getArg(unsigned Idx) const {
+ assert(Idx < getNumArgs() && "Template argument out of range");
+ return getArgs()[Idx];
+}
+
} // namespace clang
#endif // LLVM_CLANG_AST_TEMPLATEBASE_H
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index f5955c45fafc5..abc8136653fa2 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -58,6 +58,7 @@ namespace clang {
class ExtQuals;
class QualType;
+class ConceptDecl;
class TagDecl;
class Type;
@@ -1683,6 +1684,15 @@ protected:
/// Was this placeholder type spelled as 'auto', 'decltype(auto)',
/// or '__auto_type'? AutoTypeKeyword value.
unsigned Keyword : 2;
+
+ /// The number of template arguments in the type-constraints, which is
+ /// expected to be able to hold at least 1024 according to [implimits].
+ /// However as this limit is somewhat easy to hit with template
+ /// metaprogramming we'd prefer to keep it as large as possible.
+ /// At the moment it has been left as a non-bitfield since this type
+ /// safely fits in 64 bits as an unsigned, so there is no reason to
+ /// introduce the performance impact of a bitfield.
+ unsigned NumArgs;
};
class SubstTemplateTypeParmPackTypeBitfields {
@@ -4814,8 +4824,7 @@ public:
/// Common base class for placeholders for types that get replaced by
/// placeholder type deduction: C++11 auto, C++14 decltype(auto), C++17 deduced
-/// class template types, and (eventually) constrained type names from the C++
-/// Concepts TS.
+/// class template types, and constrained type names.
///
/// These types are usually a placeholder for a deduced type. However, before
/// the initializer is attached, or (usually) if the initializer is
@@ -4860,18 +4869,50 @@ public:
}
};
-/// Represents a C++11 auto or C++14 decltype(auto) type.
-class AutoType : public DeducedType, public llvm::FoldingSetNode {
+/// Represents a C++11 auto or C++14 decltype(auto) type, possibly constrained
+/// by a type-constraint.
+class alignas(8) AutoType : public DeducedType, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these
+ ConceptDecl *TypeConstraintConcept;
+
AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
- bool IsDeducedAsDependent, bool IsDeducedAsPack)
- : DeducedType(Auto, DeducedAsType, IsDeducedAsDependent,
- IsDeducedAsDependent, IsDeducedAsPack) {
- AutoTypeBits.Keyword = (unsigned)Keyword;
+ bool IsDeducedAsDependent, bool IsDeducedAsPack, ConceptDecl *CD,
+ ArrayRef<TemplateArgument> TypeConstraintArgs);
+
+ const TemplateArgument *getArgBuffer() const {
+ return reinterpret_cast<const TemplateArgument*>(this+1);
+ }
+
+ TemplateArgument *getArgBuffer() {
+ return reinterpret_cast<TemplateArgument*>(this+1);
}
public:
+ /// Retrieve the template arguments.
+ const TemplateArgument *getArgs() const {
+ return getArgBuffer();
+ }
+
+ /// Retrieve the number of template arguments.
+ unsigned getNumArgs() const {
+ return AutoTypeBits.NumArgs;
+ }
+
+ const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h
+
+ ArrayRef<TemplateArgument> getTypeConstraintArguments() const {
+ return {getArgs(), getNumArgs()};
+ }
+
+ ConceptDecl *getTypeConstraintConcept() const {
+ return TypeConstraintConcept;
+ }
+
+ bool isConstrained() const {
+ return TypeConstraintConcept != nullptr;
+ }
+
bool isDecltypeAuto() const {
return getKeyword() == AutoTypeKeyword::DecltypeAuto;
}
@@ -4880,18 +4921,15 @@ public:
return (AutoTypeKeyword)AutoTypeBits.Keyword;
}
- void Profile(llvm::FoldingSetNodeID &ID) {
- Profile(ID, getDeducedType(), getKeyword(), isDependentType(),
- containsUnexpandedParameterPack());
+ void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) {
+ Profile(ID, Context, getDeducedType(), getKeyword(), isDependentType(),
+ getTypeConstraintConcept(), getTypeConstraintArguments());
}
- static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced,
- AutoTypeKeyword Keyword, bool IsDependent, bool IsPack) {
- ID.AddPointer(Deduced.getAsOpaquePtr());
- ID.AddInteger((unsigned)Keyword);
- ID.AddBoolean(IsDependent);
- ID.AddBoolean(IsPack);
- }
+ static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
+ QualType Deduced, AutoTypeKeyword Keyword,
+ bool IsDependent, ConceptDecl *CD,
+ ArrayRef<TemplateArgument> Arguments);
static bool classof(const Type *T) {
return T->getTypeClass() == Auto;
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index c3baaa3e4174e..3fc53d823c376 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_AST_TYPELOC_H
#define LLVM_CLANG_AST_TYPELOC_H
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
@@ -34,6 +35,7 @@ namespace clang {
class Attr;
class ASTContext;
class CXXRecordDecl;
+class ConceptDecl;
class Expr;
class ObjCInterfaceDecl;
class ObjCProtocolDecl;
@@ -181,6 +183,11 @@ public:
/// AttributedTypeLoc, for those type attributes that behave as qualifiers
TypeLoc findExplicitQualifierLoc() const;
+ /// Get the typeloc of an AutoType whose type will be deduced for a variable
+ /// with an initializer of this type. This looks through declarators like
+ /// pointer types, but not through decltype or typedefs.
+ AutoTypeLoc getContainedAutoTypeLoc() const;
+
/// Initializes this to state that every location in this
/// type is the given location.
///
@@ -1923,8 +1930,137 @@ class DeducedTypeLoc
: public InheritingConcreteTypeLoc<TypeSpecTypeLoc, DeducedTypeLoc,
DeducedType> {};
+struct AutoTypeLocInfo : TypeSpecLocInfo {
+ NestedNameSpecifierLoc NestedNameSpec;
+ SourceLocation TemplateKWLoc;
+ SourceLocation ConceptNameLoc;
+ NamedDecl *FoundDecl;
+ SourceLocation LAngleLoc;
+ SourceLocation RAngleLoc;
+};
+
class AutoTypeLoc
- : public InheritingConcreteTypeLoc<DeducedTypeLoc, AutoTypeLoc, AutoType> {
+ : public ConcreteTypeLoc<DeducedTypeLoc,
+ AutoTypeLoc,
+ AutoType,
+ AutoTypeLocInfo> {
+public:
+ AutoTypeKeyword getAutoKeyword() const {
+ return getTypePtr()->getKeyword();
+ }
+
+ bool isConstrained() const {
+ return getTypePtr()->isConstrained();
+ }
+
+ const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
+ return getLocalData()->NestedNameSpec;
+ }
+
+ void setNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
+ getLocalData()->NestedNameSpec = NNS;
+ }
+
+ SourceLocation getTemplateKWLoc() const {
+ return getLocalData()->TemplateKWLoc;
+ }
+
+ void setTemplateKWLoc(SourceLocation Loc) {
+ getLocalData()->TemplateKWLoc = Loc;
+ }
+
+ SourceLocation getConceptNameLoc() const {
+ return getLocalData()->ConceptNameLoc;
+ }
+
+ void setConceptNameLoc(SourceLocation Loc) {
+ getLocalData()->ConceptNameLoc = Loc;
+ }
+
+ NamedDecl *getFoundDecl() const {
+ return getLocalData()->FoundDecl;
+ }
+
+ void setFoundDecl(NamedDecl *D) {
+ getLocalData()->FoundDecl = D;
+ }
+
+ ConceptDecl *getNamedConcept() const {
+ return getTypePtr()->getTypeConstraintConcept();
+ }
+
+ DeclarationNameInfo getConceptNameInfo() const;
+
+ bool hasExplicitTemplateArgs() const {
+ return getLocalData()->LAngleLoc.isValid();
+ }
+
+ SourceLocation getLAngleLoc() const {
+ return this->getLocalData()->LAngleLoc;
+ }
+
+ void setLAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->LAngleLoc = Loc;
+ }
+
+ SourceLocation getRAngleLoc() const {
+ return this->getLocalData()->RAngleLoc;
+ }
+
+ void setRAngleLoc(SourceLocation Loc) {
+ this->getLocalData()->RAngleLoc = Loc;
+ }
+
+ unsigned getNumArgs() const {
+ return getTypePtr()->getNumArgs();
+ }
+
+ void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) {
+ getArgInfos()[i] = AI;
+ }
+
+ TemplateArgumentLocInfo getArgLocInfo(unsigned i) const {
+ return getArgInfos()[i];
+ }
+
+ TemplateArgumentLoc getArgLoc(unsigned i) const {
+ return TemplateArgumentLoc(getTypePtr()->getTypeConstraintArguments()[i],
+ getArgLocInfo(i));
+ }
+
+ SourceRange getLocalSourceRange() const {
+ return{
+ isConstrained()
+ ? (getNestedNameSpecifierLoc()
+ ? getNestedNameSpecifierLoc().getBeginLoc()
+ : (getTemplateKWLoc().isValid()
+ ? getTemplateKWLoc()
+ : getConceptNameLoc()))
+ : getNameLoc(),
+ getNameLoc()
+ };
+ }
+
+ void copy(AutoTypeLoc Loc) {
+ unsigned size = getFullDataSize();
+ assert(size == Loc.getFullDataSize());
+ memcpy(Data, Loc.Data, size);
+ }
+
+ void initializeLocal(ASTContext &Context, SourceLocation Loc);
+
+ unsigned getExtraLocalDataSize() const {
+ return getNumArgs() * sizeof(TemplateArgumentLocInfo);
+ }
+
+ unsigned getExtraLocalDataAlignment() const {
+ return alignof(TemplateArgumentLocInfo);
+ }
+
+private:
+ TemplateArgumentLocInfo *getArgInfos() const {
+ return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
+ }
};
class DeducedTemplateSpecializationTypeLoc
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 4df2e2f77e2b3..3cf56e5a5629a 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -395,6 +395,13 @@ let Class = AutoType in {
def : Property<"keyword", AutoTypeKeyword> {
let Read = [{ node->getKeyword() }];
}
+ def : Property<"typeConstraintConcept", Optional<ConceptDeclRef>> {
+ let Read = [{ makeOptionalFromPointer(
+ const_cast<const ConceptDecl*>(node->getTypeConstraintConcept())) }];
+ }
+ def : Property<"typeConstraintArguments", Array<TemplateArgument>> {
+ let Read = [{ node->getTypeConstraintArguments() }];
+ }
// FIXME: better enumerated value
// Only really required when the deduced type is null
def : Property<"dependence", UInt32> {
@@ -406,7 +413,9 @@ let Class = AutoType in {
def : Creator<[{
return ctx.getAutoType(makeNullableFromOptional(deducedType), keyword,
/*isDependentWithoutDeducedType*/ dependence > 0,
- /*isPackWithoutDeducedType*/ dependence > 1);
+ /*isPackWithoutDeducedType*/ dependence > 1,
+ makePointerFromOptional(typeConstraintConcept),
+ typeConstraintArguments);
}]>;
}
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 03d36ae7ab324..7976d08a5258d 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -3995,8 +3995,6 @@ def PatchableFunctionEntryDocs : Documentation {
before the function entry and N-M NOPs after the function entry. This attribute
takes precedence over the command line option ``-fpatchable-function-entry=N,M``.
``M`` defaults to 0 if omitted.
-
-Currently, only M=0 is supported.
}];
}
diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
index d388afe7fae6e..1a6c85ce2dd36 100644
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -788,6 +788,9 @@ BUILTIN(__builtin_abort, "v", "Fnr")
BUILTIN(__builtin_index, "c*cC*i", "Fn")
BUILTIN(__builtin_rindex, "c*cC*i", "Fn")
+// ignored glibc builtin, see https://sourceware.org/bugzilla/show_bug.cgi?id=25399
+BUILTIN(__warn_memset_zero_len, "v", "nU")
+
// Microsoft builtins. These are only active with -fms-extensions.
LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES)
LANGBUILTIN(__annotation, "wC*.","n", ALL_MS_LANGUAGES)
diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def
index 50fc1836282f5..1ecae98b13b15 100644
--- a/clang/include/clang/Basic/CodeGenOptions.def
+++ b/clang/include/clang/Basic/CodeGenOptions.def
@@ -111,6 +111,7 @@ CODEGENOPT(XRayAlwaysEmitTypedEvents , 1, 0)
VALUE_CODEGENOPT(XRayInstructionThreshold , 32, 200)
VALUE_CODEGENOPT(PatchableFunctionEntryCount , 32, 0) ///< Number of NOPs at function entry
+VALUE_CODEGENOPT(PatchableFunctionEntryOffset , 32, 0)
CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled.
CODEGENOPT(CallFEntry , 1, 0) ///< Set when -mfentry is enabled.
diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td
index c2c23237285b2..d5bbc604819f8 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/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 0fe14e4e05bee..2da41bef2669e 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -408,7 +408,7 @@ def err_drv_unsupported_indirect_jump_opt : Error<
def err_drv_unknown_indirect_jump_opt : Error<
"unknown '-mindirect-jump=' option '%0'">;
def err_drv_unsupported_fpatchable_function_entry_argument : Error<
- "the second argument of '-fpatchable-function-entry' must be 0 or omitted">;
+ "the second argument of '-fpatchable-function-entry' must be smaller than the first argument">;
def warn_drv_unable_to_find_directory_expected : Warning<
"unable to find %0 directory, expected to be in '%1'">,
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index a798b498d4e9a..ed2092fb4c845 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -105,6 +105,9 @@ def err_fe_invalid_wchar_type
: Error<"invalid wchar_t type '%0'; must be one of 'char', 'short', 'int'">;
def err_fe_invalid_exception_model
: Error<"invalid exception model '%0' for target '%1'">;
+def warn_fe_concepts_ts_flag : Warning<
+ "-fconcepts-ts is deprecated - use '-std=c++2a' for Concepts support">,
+ InGroup<Deprecated>;
def warn_fe_serialized_diag_merge_failure : Warning<
"unable to merge a subprocess's serialized diagnostics">,
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index cc6a74ac3e6dd..04b103e3087ae 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -33,10 +33,6 @@ def err_asm_goto_cannot_have_output : Error<
let CategoryName = "Parse Issue" in {
-def warn_cxx2a_compat_explicit_bool : Warning<
- "this expression will be parsed as explicit(bool) in C++2a">,
- InGroup<CXX2aCompat>, DefaultIgnore;
-
def ext_empty_translation_unit : Extension<
"ISO C requires a translation unit to contain at least one declaration">,
InGroup<DiagGroup<"empty-translation-unit">>;
@@ -684,6 +680,15 @@ def err_ms_property_expected_comma_or_rparen : Error<
def err_ms_property_initializer : Error<
"property declaration cannot have an in-class initializer">;
+def warn_cxx2a_compat_explicit_bool : Warning<
+ "this expression will be parsed as explicit(bool) in C++2a">,
+ InGroup<CXX2aCompat>, DefaultIgnore;
+def warn_cxx17_compat_explicit_bool : Warning<
+ "explicit(bool) is incompatible with C++ standards before C++2a">,
+ InGroup<CXXPre2aCompat>, DefaultIgnore;
+def ext_explicit_bool : ExtWarn<"explicit(bool) is a C++2a extension">,
+ InGroup<CXX2a>;
+
/// C++ Templates
def err_expected_template : Error<"expected template">;
def err_unknown_template_name : Error<
@@ -739,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">;
@@ -1339,6 +1371,8 @@ def err_concept_definition_not_identifier : Error<
def ext_concept_legacy_bool_keyword : ExtWarn<
"ISO C++2a does not permit the 'bool' keyword after 'concept'">,
InGroup<DiagGroup<"concepts-ts-compat">>;
+def err_placeholder_expected_auto_or_decltype_auto : Error<
+ "expected 'auto' or 'decltype(auto)' after concept name">;
}
} // end of Parser diagnostics
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 7d8231d140e44..7636d04a34c37 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2102,12 +2102,18 @@ 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 function prototype that is "
+ "not a function declaration|in requires expression parameter}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<
@@ -2590,25 +2596,65 @@ 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 "
"same concept">;
def note_ambiguous_atomic_constraints_similar_expression : Note<
"similar constraint expression here">;
+def err_unsupported_placeholder_constraint : Error<
+ "constrained placeholder types other than simple 'auto' on non-type template "
+ "parameters not supported yet">;
def err_template_different_requires_clause : Error<
"requires clause differs in template redeclaration">;
@@ -2623,6 +2669,8 @@ def err_type_constraint_non_type_concept : Error<
def err_type_constraint_missing_arguments : Error<
"%0 requires more than 1 template argument; provide the remaining arguments "
"explicitly to use it here">;
+def err_placeholder_constraints_not_satisfied : Error<
+ "deduced type %0 does not satisfy %1">;
// C++11 char16_t/char32_t
def warn_cxx98_compat_unicode_type : Warning<
@@ -4588,6 +4636,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 +4673,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 +4808,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/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 068f206f44847..3319a31239768 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -237,7 +237,7 @@ LANGOPT(SizedDeallocation , 1, 0, "sized deallocation")
LANGOPT(AlignedAllocation , 1, 0, "aligned allocation")
LANGOPT(AlignedAllocationUnavailable, 1, 0, "aligned allocation functions are unavailable")
LANGOPT(NewAlignOverride , 32, 0, "maximum alignment guaranteed by '::operator new(size_t)'")
-LANGOPT(ConceptsTS , 1, 0, "enable C++ Extensions for Concepts")
+LANGOPT(ConceptSatisfactionCaching , 1, 1, "enable satisfaction caching for C++2a Concepts")
BENIGN_LANGOPT(ModulesCodegen , 1, 0, "Modules code generation")
BENIGN_LANGOPT(ModulesDebugInfo , 1, 0, "Modules debug info")
BENIGN_LANGOPT(ElideConstructors , 1, 1, "C++ copy constructor elision")
diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index 294993298a18a..41923cddc4930 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/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index d58b0d987d71d..fec029ae995ed 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -373,7 +373,7 @@ CXX11_KEYWORD(nullptr , 0)
CXX11_KEYWORD(static_assert , KEYMSCOMPAT)
CXX11_KEYWORD(thread_local , 0)
-// C++2a / concepts TS keywords
+// C++2a keywords
CONCEPTS_KEYWORD(concept)
CONCEPTS_KEYWORD(requires)
diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td
index 1d550eb15ea8f..9387285518de1 100644
--- a/clang/include/clang/Driver/CC1Options.td
+++ b/clang/include/clang/Driver/CC1Options.td
@@ -372,6 +372,9 @@ def fsanitize_coverage_no_prune
def fsanitize_coverage_stack_depth
: Flag<["-"], "fsanitize-coverage-stack-depth">,
HelpText<"Enable max stack depth tracing">;
+def fpatchable_function_entry_offset_EQ
+ : Joined<["-"], "fpatchable-function-entry-offset=">, MetaVarName<"<M>">,
+ HelpText<"Generate M NOPs before function entry">;
def fprofile_instrument_EQ : Joined<["-"], "fprofile-instrument=">,
HelpText<"Enable PGO instrumentation. The accepted value is clang, llvm, "
"or none">, Values<"none,clang,llvm">;
@@ -553,7 +556,10 @@ def ftest_module_file_extension_EQ :
HelpText<"introduce a module file extension for testing purposes. "
"The argument is parsed as blockname:major:minor:hashed:user info">;
def fconcepts_ts : Flag<["-"], "fconcepts-ts">,
- HelpText<"Enable C++ Extensions for Concepts.">;
+ HelpText<"Enable C++ Extensions for Concepts. (deprecated - use -std=c++2a)">;
+def fno_concept_satisfaction_caching : Flag<["-"],
+ "fno-concept-satisfaction-caching">,
+ HelpText<"Disable satisfaction caching for C++2a Concepts.">;
let Group = Action_Group in {
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index fd25663bd3587..6c3feaba05682 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -208,7 +208,7 @@ public:
/// When the clangDriver lib is used through clang.exe, this provides a
/// shortcut for executing the -cc1 command-line directly, in the same
/// process.
- typedef int (*CC1ToolFunc)(ArrayRef<const char *> argv);
+ typedef int (*CC1ToolFunc)(SmallVectorImpl<const char *> &ArgV);
CC1ToolFunc CC1Main = nullptr;
private:
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index abfa767afea8f..0a60873443fc0 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1707,7 +1707,7 @@ def fno_max_type_align : Flag<["-"], "fno-max-type-align">, Group<f_Group>;
def fpascal_strings : Flag<["-"], "fpascal-strings">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Recognize and construct Pascal-style string literals">;
def fpatchable_function_entry_EQ : Joined<["-"], "fpatchable-function-entry=">, Group<f_Group>, Flags<[CC1Option]>,
- HelpText<"Generate N NOPs at function entry">;
+ MetaVarName<"<N,M>">, HelpText<"Generate M NOPs before function entry and N-M NOPs after function entry">;
def fpcc_struct_return : Flag<["-"], "fpcc-struct-return">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Override the default ABI to return all structs on the stack">;
def fpch_preprocess : Flag<["-"], "fpch-preprocess">, Group<f_Group>;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index e320c96478188..41f46861d0895 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -806,6 +806,16 @@ public:
bool IsNewScope);
bool TryAnnotateCXXScopeToken(bool EnteringContext = false);
+ bool MightBeCXXScopeToken() {
+ return Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
+ (Tok.is(tok::annot_template_id) &&
+ NextToken().is(tok::coloncolon)) ||
+ Tok.is(tok::kw_decltype) || Tok.is(tok::kw___super);
+ }
+ bool TryAnnotateOptionalCXXScopeToken(bool EnteringContext = false) {
+ return MightBeCXXScopeToken() && TryAnnotateCXXScopeToken(EnteringContext);
+ }
+
private:
enum AnnotatedNameKind {
/// Annotation has failed and emitted an error.
@@ -1923,6 +1933,7 @@ private:
//===--------------------------------------------------------------------===//
// C++ Concepts
+ ExprResult ParseRequiresExpression();
void ParseTrailingRequiresClause(Declarator &D);
//===--------------------------------------------------------------------===//
@@ -2395,6 +2406,11 @@ private:
/// rather than a less-than expression.
TPResult isTemplateArgumentList(unsigned TokensToSkip);
+ /// Determine whether an '(' after an 'explicit' keyword is part of a C++20
+ /// 'explicit(bool)' declaration, in earlier language modes where that is an
+ /// extension.
+ TPResult isExplicitBool();
+
/// Determine whether an identifier has been tentatively declared as a
/// non-type. Such tentative declarations should not be found to name a type
/// during a tentative parse, but also should not be annotated as a non-type.
@@ -2756,7 +2772,7 @@ private:
Declarator &D,
SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo);
void ParseParameterDeclarationClause(
- Declarator &D,
+ DeclaratorContext DeclaratorContext,
ParsedAttributes &attrs,
SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
SourceLocation &EllipsisLoc);
@@ -3064,13 +3080,13 @@ private:
SourceLocation &RAngleLoc);
bool ParseTemplateParameterList(unsigned Depth,
SmallVectorImpl<NamedDecl*> &TemplateParams);
- bool isStartOfTemplateTypeParameter(bool &ScopeError);
+ TPResult isStartOfTemplateTypeParameter();
NamedDecl *ParseTemplateParameter(unsigned Depth, unsigned Position);
NamedDecl *ParseTypeParameter(unsigned Depth, unsigned Position);
NamedDecl *ParseTemplateTemplateParameter(unsigned Depth, unsigned Position);
NamedDecl *ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position);
bool isTypeConstraintAnnotation();
- bool TryAnnotateTypeConstraint(CXXScopeSpec &SS);
+ bool TryAnnotateTypeConstraint();
NamedDecl *
ParseConstrainedTemplateTypeParameter(unsigned Depth, unsigned Position);
void DiagnoseMisplacedEllipsis(SourceLocation EllipsisLoc,
@@ -3096,7 +3112,8 @@ private:
UnqualifiedId &TemplateName,
bool AllowTypeAnnotation = true,
bool TypeConstraint = false);
- void AnnotateTemplateIdTokenAsType(bool IsClassName = false);
+ void AnnotateTemplateIdTokenAsType(CXXScopeSpec &SS,
+ bool IsClassName = false);
bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
ParsedTemplateArgument ParseTemplateTemplateArgument();
ParsedTemplateArgument ParseTemplateArgument();
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index aceec9cbe1c9e..1559b51ea77fc 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -349,6 +349,7 @@ private:
unsigned TypeSpecOwned : 1;
unsigned TypeSpecPipe : 1;
unsigned TypeSpecSat : 1;
+ unsigned ConstrainedAuto : 1;
// type-qualifiers
unsigned TypeQualifiers : 5; // Bitwise OR of TQ.
@@ -369,6 +370,7 @@ private:
UnionParsedType TypeRep;
Decl *DeclRep;
Expr *ExprRep;
+ TemplateIdAnnotation *TemplateIdRep;
};
/// ExplicitSpecifier - Store information about explicit spicifer.
@@ -413,6 +415,9 @@ private:
static bool isExprRep(TST T) {
return (T == TST_typeofExpr || T == TST_decltype);
}
+ static bool isTemplateIdRep(TST T) {
+ return (T == TST_auto || T == TST_decltype_auto);
+ }
DeclSpec(const DeclSpec &) = delete;
void operator=(const DeclSpec &) = delete;
@@ -430,7 +435,8 @@ public:
TypeSpecComplex(TSC_unspecified), TypeSpecSign(TSS_unspecified),
TypeSpecType(TST_unspecified), TypeAltiVecVector(false),
TypeAltiVecPixel(false), TypeAltiVecBool(false), TypeSpecOwned(false),
- TypeSpecPipe(false), TypeSpecSat(false), TypeQualifiers(TQ_unspecified),
+ TypeSpecPipe(false), TypeSpecSat(false), ConstrainedAuto(false),
+ TypeQualifiers(TQ_unspecified),
FS_inline_specified(false), FS_forceinline_specified(false),
FS_virtual_specified(false), FS_noreturn_specified(false),
Friend_specified(false), ConstexprSpecifier(CSK_unspecified),
@@ -478,6 +484,7 @@ public:
bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); }
bool isTypeSpecPipe() const { return TypeSpecPipe; }
bool isTypeSpecSat() const { return TypeSpecSat; }
+ bool isConstrainedAuto() const { return ConstrainedAuto; }
ParsedType getRepAsType() const {
assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");
@@ -491,6 +498,11 @@ public:
assert(isExprRep((TST) TypeSpecType) && "DeclSpec does not store an expr");
return ExprRep;
}
+ TemplateIdAnnotation *getRepAsTemplateId() const {
+ assert(isTemplateIdRep((TST) TypeSpecType) &&
+ "DeclSpec does not store a template id");
+ return TemplateIdRep;
+ }
CXXScopeSpec &getTypeSpecScope() { return TypeScope; }
const CXXScopeSpec &getTypeSpecScope() const { return TypeScope; }
@@ -666,6 +678,9 @@ public:
SourceLocation TagNameLoc, const char *&PrevSpec,
unsigned &DiagID, Decl *Rep, bool Owned,
const PrintingPolicy &Policy);
+ bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
+ unsigned &DiagID, TemplateIdAnnotation *Rep,
+ const PrintingPolicy &Policy);
bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec,
unsigned &DiagID, Expr *Rep,
@@ -1757,7 +1772,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.
};
@@ -1830,6 +1846,14 @@ private:
/// requires-clause, or null if no such clause was specified.
Expr *TrailingRequiresClause;
+ /// If this declarator declares a template, its template parameter lists.
+ ArrayRef<TemplateParameterList *> TemplateParameterLists;
+
+ /// If the declarator declares an abbreviated function template, the innermost
+ /// template parameter list containing the invented and explicit template
+ /// parameters (if any).
+ TemplateParameterList *InventedTemplateParameterList;
+
#ifndef _MSC_VER
union {
#endif
@@ -1860,7 +1884,8 @@ public:
Redeclaration(false), Extension(false), ObjCIvar(false),
ObjCWeakProperty(false), InlineStorageUsed(false),
Attrs(ds.getAttributePool().getFactory()), AsmLabel(nullptr),
- TrailingRequiresClause(nullptr) {}
+ TrailingRequiresClause(nullptr),
+ InventedTemplateParameterList(nullptr) {}
~Declarator() {
clear();
@@ -1981,6 +2006,7 @@ public:
case DeclaratorContext::TemplateTypeArgContext:
case DeclaratorContext::TrailingReturnContext:
case DeclaratorContext::TrailingReturnVarContext:
+ case DeclaratorContext::RequiresExprContext:
return true;
}
llvm_unreachable("unknown context kind!");
@@ -2003,6 +2029,7 @@ public:
case DeclaratorContext::TemplateParamContext:
case DeclaratorContext::CXXCatchContext:
case DeclaratorContext::ObjCCatchContext:
+ case DeclaratorContext::RequiresExprContext:
return true;
case DeclaratorContext::TypeNameContext:
@@ -2039,6 +2066,7 @@ public:
case DeclaratorContext::MemberContext:
case DeclaratorContext::PrototypeContext:
case DeclaratorContext::TemplateParamContext:
+ case DeclaratorContext::RequiresExprContext:
// Maybe one day...
return false;
@@ -2116,6 +2144,7 @@ public:
case DeclaratorContext::TemplateArgContext:
case DeclaratorContext::TemplateTypeArgContext:
case DeclaratorContext::TrailingReturnContext:
+ case DeclaratorContext::RequiresExprContext:
return false;
}
llvm_unreachable("unknown context kind!");
@@ -2337,6 +2366,7 @@ public:
case DeclaratorContext::TemplateTypeArgContext:
case DeclaratorContext::TrailingReturnContext:
case DeclaratorContext::TrailingReturnVarContext:
+ case DeclaratorContext::RequiresExprContext:
return false;
}
llvm_unreachable("unknown context kind!");
@@ -2370,6 +2400,7 @@ public:
case DeclaratorContext::TrailingReturnContext:
case DeclaratorContext::TrailingReturnVarContext:
case DeclaratorContext::TemplateTypeArgContext:
+ case DeclaratorContext::RequiresExprContext:
return false;
case DeclaratorContext::BlockContext:
@@ -2422,6 +2453,30 @@ public:
return TrailingRequiresClause != nullptr;
}
+ /// Sets the template parameter lists that preceded the declarator.
+ void setTemplateParameterLists(ArrayRef<TemplateParameterList *> TPLs) {
+ TemplateParameterLists = TPLs;
+ }
+
+ /// The template parameter lists that preceded the declarator.
+ ArrayRef<TemplateParameterList *> getTemplateParameterLists() const {
+ return TemplateParameterLists;
+ }
+
+ /// Sets the template parameter list generated from the explicit template
+ /// parameters along with any invented template parameters from
+ /// placeholder-typed parameters.
+ void setInventedTemplateParameterList(TemplateParameterList *Invented) {
+ InventedTemplateParameterList = Invented;
+ }
+
+ /// The template parameter list generated from the explicit template
+ /// parameters along with any invented template parameters from
+ /// placeholder-typed parameters, if there were any such parameters.
+ TemplateParameterList * getInventedTemplateParameterList() const {
+ return InventedTemplateParameterList;
+ }
+
/// takeAttributes - Takes attributes from the given parsed-attributes
/// set and add them to this declarator.
///
@@ -2622,6 +2677,26 @@ struct LambdaIntroducer {
}
};
+struct InventedTemplateParameterInfo {
+ /// The number of parameters in the template parameter list that were
+ /// explicitly specified by the user, as opposed to being invented by use
+ /// of an auto parameter.
+ unsigned NumExplicitTemplateParams = 0;
+
+ /// If this is a generic lambda or abbreviated function template, use this
+ /// as the depth of each 'auto' parameter, during initial AST construction.
+ unsigned AutoTemplateParameterDepth = 0;
+
+ /// Store the list of the template parameters for a generic lambda or an
+ /// abbreviated function template.
+ /// If this is a generic lambda or abbreviated function template, this holds
+ /// the explicit template parameters followed by the auto parameters
+ /// converted into TemplateTypeParmDecls.
+ /// It can be used to construct the generic lambda or abbreviated template's
+ /// template parameter list during initial AST construction.
+ SmallVector<NamedDecl*, 4> TemplateParams;
+};
+
} // end namespace clang
#endif // LLVM_CLANG_SEMA_DECLSPEC_H
diff --git a/clang/include/clang/Sema/ParsedTemplate.h b/clang/include/clang/Sema/ParsedTemplate.h
index 0874905b38a5b..82d00494b0d6b 100644
--- a/clang/include/clang/Sema/ParsedTemplate.h
+++ b/clang/include/clang/Sema/ParsedTemplate.h
@@ -139,9 +139,8 @@ namespace clang {
/// Information about a template-id annotation
/// token.
///
- /// A template-id annotation token contains the template declaration,
- /// template arguments, whether those template arguments were types,
- /// expressions, or template names, and the source locations for important
+ /// A template-id annotation token contains the template name,
+ /// template arguments, and the source locations for important
/// tokens. All of the information about template arguments is allocated
/// directly after this structure.
/// A template-id annotation token can also be generated by a type-constraint
@@ -152,9 +151,6 @@ namespace clang {
: private llvm::TrailingObjects<TemplateIdAnnotation,
ParsedTemplateArgument> {
friend TrailingObjects;
- /// The nested-name-specifier that precedes the template name.
- CXXScopeSpec SS;
-
/// TemplateKWLoc - The location of the template keyword.
/// For e.g. typename T::template Y<U>
SourceLocation TemplateKWLoc;
@@ -195,16 +191,15 @@ namespace clang {
/// Creates a new TemplateIdAnnotation with NumArgs arguments and
/// appends it to List.
static TemplateIdAnnotation *
- Create(CXXScopeSpec SS, SourceLocation TemplateKWLoc,
- SourceLocation TemplateNameLoc, IdentifierInfo *Name,
- OverloadedOperatorKind OperatorKind,
+ Create(SourceLocation TemplateKWLoc, SourceLocation TemplateNameLoc,
+ IdentifierInfo *Name, OverloadedOperatorKind OperatorKind,
ParsedTemplateTy OpaqueTemplateName, TemplateNameKind TemplateKind,
SourceLocation LAngleLoc, SourceLocation RAngleLoc,
ArrayRef<ParsedTemplateArgument> TemplateArgs,
SmallVectorImpl<TemplateIdAnnotation *> &CleanupList) {
TemplateIdAnnotation *TemplateId = new (llvm::safe_malloc(
totalSizeToAlloc<ParsedTemplateArgument>(TemplateArgs.size())))
- TemplateIdAnnotation(SS, TemplateKWLoc, TemplateNameLoc, Name,
+ TemplateIdAnnotation(TemplateKWLoc, TemplateNameLoc, Name,
OperatorKind, OpaqueTemplateName, TemplateKind,
LAngleLoc, RAngleLoc, TemplateArgs);
CleanupList.push_back(TemplateId);
@@ -221,17 +216,16 @@ namespace clang {
private:
TemplateIdAnnotation(const TemplateIdAnnotation &) = delete;
- TemplateIdAnnotation(CXXScopeSpec SS, SourceLocation TemplateKWLoc,
+ TemplateIdAnnotation(SourceLocation TemplateKWLoc,
SourceLocation TemplateNameLoc, IdentifierInfo *Name,
OverloadedOperatorKind OperatorKind,
ParsedTemplateTy OpaqueTemplateName,
TemplateNameKind TemplateKind,
SourceLocation LAngleLoc, SourceLocation RAngleLoc,
ArrayRef<ParsedTemplateArgument> TemplateArgs) noexcept
- : SS(SS), TemplateKWLoc(TemplateKWLoc),
- TemplateNameLoc(TemplateNameLoc), Name(Name), Operator(OperatorKind),
- Template(OpaqueTemplateName), Kind(TemplateKind),
- LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
+ : TemplateKWLoc(TemplateKWLoc), TemplateNameLoc(TemplateNameLoc),
+ Name(Name), Operator(OperatorKind), Template(OpaqueTemplateName),
+ Kind(TemplateKind), LAngleLoc(LAngleLoc), RAngleLoc(RAngleLoc),
NumArgs(TemplateArgs.size()) {
std::uninitialized_copy(TemplateArgs.begin(), TemplateArgs.end(),
diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h
index 7848df8f70d9c..6133425a42a62 100644
--- a/clang/include/clang/Sema/Scope.h
+++ b/clang/include/clang/Sema/Scope.h
@@ -385,6 +385,12 @@ public:
return getFlags() & Scope::FunctionPrototypeScope;
}
+ /// isFunctionDeclarationScope - Return true if this scope is a
+ /// function prototype scope.
+ bool isFunctionDeclarationScope() const {
+ return getFlags() & Scope::FunctionDeclarationScope;
+ }
+
/// isAtCatchScope - Return true if this scope is \@catch.
bool isAtCatchScope() const {
return getFlags() & Scope::AtCatchScope;
diff --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h
index 4f7534f9ef1af..3c4847a2932cd 100644
--- a/clang/include/clang/Sema/ScopeInfo.h
+++ b/clang/include/clang/Sema/ScopeInfo.h
@@ -22,6 +22,7 @@
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Sema/CleanupInfo.h"
+#include "clang/Sema/DeclSpec.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/MapVector.h"
@@ -789,7 +790,8 @@ public:
}
};
-class LambdaScopeInfo final : public CapturingScopeInfo {
+class LambdaScopeInfo final :
+ public CapturingScopeInfo, public InventedTemplateParameterInfo {
public:
/// The class that describes the lambda.
CXXRecordDecl *Lambda = nullptr;
@@ -823,25 +825,9 @@ public:
/// Packs introduced by this lambda, if any.
SmallVector<NamedDecl*, 4> LocalPacks;
- /// If this is a generic lambda, use this as the depth of
- /// each 'auto' parameter, during initial AST construction.
- unsigned AutoTemplateParameterDepth = 0;
-
- /// The number of parameters in the template parameter list that were
- /// explicitly specified by the user, as opposed to being invented by use
- /// of an auto parameter.
- unsigned NumExplicitTemplateParams = 0;
-
/// Source range covering the explicit template parameter list (if it exists).
SourceRange ExplicitTemplateParamsRange;
- /// Store the list of the template parameters for a generic lambda.
- /// If this is a generic lambda, this holds the explicit template parameters
- /// followed by the auto parameters converted into TemplateTypeParmDecls.
- /// It can be used to construct the generic lambda's template parameter list
- /// during initial AST construction.
- SmallVector<NamedDecl*, 4> TemplateParams;
-
/// If this is a generic lambda, and the template parameter
/// list has been created (from the TemplateParams) then store
/// a reference to it (cache it to avoid reconstructing it).
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 47a055f696b13..a88dd28144871 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"
@@ -619,6 +620,13 @@ public:
/// function, block, and method scopes that are currently active.
SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes;
+ /// Stack containing information needed when in C++2a an 'auto' is encountered
+ /// in a function declaration parameter type specifier in order to invent a
+ /// corresponding template parameter in the enclosing abbreviated function
+ /// template. This information is also present in LambdaScopeInfo, stored in
+ /// the FunctionScopes stack.
+ SmallVector<InventedTemplateParameterInfo, 4> InventedParameterInfos;
+
typedef LazyVector<TypedefNameDecl *, ExternalSemaSource,
&ExternalSemaSource::ReadExtVectorDecls, 2, 2>
ExtVectorDeclsType;
@@ -1424,6 +1432,11 @@ public:
/// Retrieve the module loader associated with the preprocessor.
ModuleLoader &getModuleLoader() const;
+ /// Invent a new identifier for parameters of abbreviated templates.
+ IdentifierInfo *
+ InventAbbreviatedTemplateParameterTypeName(IdentifierInfo *ParamName,
+ unsigned Index);
+
void emitAndClearUnusedLocalTypedefWarnings();
enum TUFragmentKind {
@@ -1518,6 +1531,15 @@ public:
/// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls
SmallVectorImpl<Decl *> &WeakTopLevelDecls() { return WeakTopLevelDecl; }
+ /// Called before parsing a function declarator belonging to a function
+ /// declaration.
+ void ActOnStartFunctionDeclarationDeclarator(Declarator &D,
+ unsigned TemplateParameterDepth);
+
+ /// Called after parsing a function declarator belonging to a function
+ /// declaration.
+ void ActOnFinishFunctionDeclarationDeclarator(Declarator &D);
+
void ActOnComment(SourceRange Comment);
//===--------------------------------------------------------------------===//
@@ -1921,6 +1943,8 @@ public:
NC_FunctionTemplate,
/// The name was classified as an ADL-only function template name.
NC_UndeclaredTemplate,
+ /// The name was classified as a concept name.
+ NC_Concept,
};
class NameClassification {
@@ -1985,6 +2009,12 @@ public:
return Result;
}
+ static NameClassification Concept(TemplateName Name) {
+ NameClassification Result(NC_Concept);
+ Result.Template = Name;
+ return Result;
+ }
+
static NameClassification UndeclaredTemplate(TemplateName Name) {
NameClassification Result(NC_UndeclaredTemplate);
Result.Template = Name;
@@ -2010,7 +2040,8 @@ public:
TemplateName getTemplateName() const {
assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate ||
- Kind == NC_VarTemplate || Kind == NC_UndeclaredTemplate);
+ Kind == NC_VarTemplate || Kind == NC_Concept ||
+ Kind == NC_UndeclaredTemplate);
return Template;
}
@@ -2022,6 +2053,8 @@ public:
return TNK_Function_template;
case NC_VarTemplate:
return TNK_Var_template;
+ case NC_Concept:
+ return TNK_Concept_template;
case NC_UndeclaredTemplate:
return TNK_Undeclared_template;
default:
@@ -6199,6 +6232,9 @@ private:
llvm::DenseMap<NamedDecl *, NormalizedConstraint *>
NormalizationCache;
+ llvm::ContextualFoldingSet<ConstraintSatisfaction, const ASTContext &>
+ SatisfactionCache;
+
public:
const NormalizedConstraint *
getNormalizedAssociatedConstraints(
@@ -6225,6 +6261,8 @@ public:
/// \brief Check whether the given list of constraint expressions are
/// satisfied (as if in a 'conjunction') given template arguments.
+ /// \param Template the template-like entity that triggered the constraints
+ /// check (either a concept or a constrained entity).
/// \param ConstraintExprs a list of constraint expressions, treated as if
/// they were 'AND'ed together.
/// \param TemplateArgs the list of template arguments to substitute into the
@@ -6236,23 +6274,10 @@ public:
/// expression.
/// \returns true if an error occurred and satisfaction could not be checked,
/// false otherwise.
- bool CheckConstraintSatisfaction(TemplateDecl *Template,
- ArrayRef<const Expr *> ConstraintExprs,
- ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange TemplateIDRange,
- ConstraintSatisfaction &Satisfaction);
-
- bool CheckConstraintSatisfaction(ClassTemplatePartialSpecializationDecl *TD,
- ArrayRef<const Expr *> ConstraintExprs,
- ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange TemplateIDRange,
- ConstraintSatisfaction &Satisfaction);
-
- bool CheckConstraintSatisfaction(VarTemplatePartialSpecializationDecl *TD,
- ArrayRef<const Expr *> ConstraintExprs,
- ArrayRef<TemplateArgument> TemplateArgs,
- SourceRange TemplateIDRange,
- ConstraintSatisfaction &Satisfaction);
+ bool CheckConstraintSatisfaction(
+ NamedDecl *Template, ArrayRef<const Expr *> ConstraintExprs,
+ ArrayRef<TemplateArgument> TemplateArgs,
+ SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction);
/// \brief Check whether the given non-dependent constraint expression is
/// satisfied. Returns false and updates Satisfaction with the satisfaction
@@ -6282,13 +6307,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.
@@ -6873,7 +6902,8 @@ public:
SourceLocation EqualLoc,
ParsedType DefaultArg, bool HasTypeConstraint);
- bool ActOnTypeConstraint(TemplateIdAnnotation *TypeConstraint,
+ bool ActOnTypeConstraint(const CXXScopeSpec &SS,
+ TemplateIdAnnotation *TypeConstraint,
TemplateTypeParmDecl *ConstrainedParameter,
SourceLocation EllipsisLoc);
@@ -6884,6 +6914,10 @@ public:
TemplateTypeParmDecl *ConstrainedParameter,
SourceLocation EllipsisLoc);
+ bool AttachTypeConstraint(AutoTypeLoc TL,
+ NonTypeTemplateParmDecl *ConstrainedParameter,
+ SourceLocation EllipsisLoc);
+
QualType CheckNonTypeTemplateParameterType(TypeSourceInfo *&TSI,
SourceLocation Loc);
QualType CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc);
@@ -6933,7 +6967,8 @@ public:
SourceLocation DeclStartLoc, SourceLocation DeclLoc,
const CXXScopeSpec &SS, TemplateIdAnnotation *TemplateId,
ArrayRef<TemplateParameterList *> ParamLists,
- bool IsFriend, bool &IsMemberSpecialization, bool &Invalid);
+ bool IsFriend, bool &IsMemberSpecialization, bool &Invalid,
+ bool SuppressDiagnostic = false);
DeclResult CheckClassTemplate(
Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
@@ -7028,8 +7063,8 @@ public:
DeclResult ActOnClassTemplateSpecialization(
Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc,
- SourceLocation ModulePrivateLoc, TemplateIdAnnotation &TemplateId,
- const ParsedAttributesView &Attr,
+ SourceLocation ModulePrivateLoc, CXXScopeSpec &SS,
+ TemplateIdAnnotation &TemplateId, const ParsedAttributesView &Attr,
MultiTemplateParamsArg TemplateParameterLists,
SkipBodyInfo *SkipBody = nullptr);
@@ -7261,7 +7296,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,
@@ -7281,11 +7326,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])
//===--------------------------------------------------------------------===//
@@ -7794,10 +7880,12 @@ public:
DeduceAutoResult
DeduceAutoType(TypeSourceInfo *AutoType, Expr *&Initializer, QualType &Result,
- Optional<unsigned> DependentDeductionDepth = None);
+ Optional<unsigned> DependentDeductionDepth = None,
+ bool IgnoreConstraints = false);
DeduceAutoResult
DeduceAutoType(TypeLoc AutoTypeLoc, Expr *&Initializer, QualType &Result,
- Optional<unsigned> DependentDeductionDepth = None);
+ Optional<unsigned> DependentDeductionDepth = None,
+ bool IgnoreConstraints = false);
void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init);
bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
bool Diagnose = true);
@@ -7932,6 +8020,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,
@@ -8253,6 +8348,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 acd1e604211a1..7fc42a4816ec0 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/Sema/TemplateDeduction.h b/clang/include/clang/Sema/TemplateDeduction.h
index b60939c97872d..f787c2689d850 100644
--- a/clang/include/clang/Sema/TemplateDeduction.h
+++ b/clang/include/clang/Sema/TemplateDeduction.h
@@ -15,6 +15,7 @@
#define LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
#include "clang/Sema/Ownership.h"
+#include "clang/Sema/SemaConcept.h"
#include "clang/AST/ASTConcept.h"
#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/DeclTemplate.h"
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 1bfcbda8c9f1e..44a12c875da7d 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