diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h index 00500e214f4ce..ace4de0d62772 100644 --- a/clang/include/clang/AST/ASTConcept.h +++ b/clang/include/clang/AST/ASTConcept.h @@ -26,6 +26,7 @@ namespace clang { class ConceptDecl; +class TemplateDecl; class Expr; class NamedDecl; struct PrintingPolicy; @@ -122,6 +123,7 @@ struct ASTConstraintSatisfaction final : /// template T> void dump(); /// ~~~~~~~~~~~~~~~~~~~~~~~ (in TemplateTypeParmDecl) class ConceptReference { +protected: // \brief The optional nested name specifier used when naming the concept. NestedNameSpecifierLoc NestedNameSpec; @@ -139,7 +141,7 @@ class ConceptReference { NamedDecl *FoundDecl; /// \brief The concept named. - ConceptDecl *NamedConcept; + TemplateDecl *NamedConcept; /// \brief The template argument list source info used to specialize the /// concept. @@ -147,7 +149,7 @@ class ConceptReference { ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, - ConceptDecl *NamedConcept, + TemplateDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten) : NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc), ConceptName(ConceptNameInfo), FoundDecl(FoundDecl), @@ -157,7 +159,7 @@ class ConceptReference { static ConceptReference * Create(const ASTContext &C, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, - NamedDecl *FoundDecl, ConceptDecl *NamedConcept, + NamedDecl *FoundDecl, TemplateDecl *NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten); const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { @@ -196,9 +198,7 @@ class ConceptReference { return FoundDecl; } - ConceptDecl *getNamedConcept() const { - return NamedConcept; - } + TemplateDecl *getNamedConcept() const { return NamedConcept; } const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { return ArgsAsWritten; @@ -247,7 +247,7 @@ class TypeConstraint { // FIXME: Instead of using these concept related functions the callers should // directly work with the corresponding ConceptReference. - ConceptDecl *getNamedConcept() const { return ConceptRef->getNamedConcept(); } + TemplateDecl *getNamedConcept() const { return ConceptRef->getNamedConcept(); } SourceLocation getConceptNameLoc() const { return ConceptRef->getConceptNameLoc(); @@ -278,6 +278,56 @@ class TypeConstraint { void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const { ConceptRef->print(OS, Policy); } + +}; + +class PartiallyAppliedConcept : public ConceptReference, + public llvm::FoldingSetNode { + + SourceLocation ConceptKWLoc; + PartiallyAppliedConcept(NestedNameSpecifierLoc NNS, + DeclarationNameInfo ConceptNameInfo, + SourceLocation ConceptKWLoc, NamedDecl *FoundDecl, + TemplateDecl *NamedConcept, + const ASTTemplateArgumentListInfo *ArgsAsWritten) + : ConceptReference(NNS, /*TemplateKWLoc=*/SourceLocation(), + ConceptNameInfo, FoundDecl, NamedConcept, + ArgsAsWritten), + ConceptKWLoc(ConceptKWLoc) {} + +public: + static PartiallyAppliedConcept * + Create(const ASTContext &C, NestedNameSpecifierLoc NNS, + DeclarationNameInfo ConceptNameInfo, SourceLocation ConceptKWLoc, + NamedDecl *FoundDecl, TemplateDecl *NamedConcept, + const TemplateArgumentListInfo &TemplateArgs); + + TemplateArgumentDependence getDependence() const; + + bool isDependent() const { + return getDependence() & TemplateArgumentDependence::Dependent; + } + + bool isInstantiationDependent() const { + return getDependence() & TemplateArgumentDependence::Instantiation; + } + + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) const { + Profile(ID, C, getNamedConcept(), getTemplateArgsAsWritten()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C, + const TemplateDecl *NamedConcept, + const ASTTemplateArgumentListInfo *ArgsAsWritten); + + SourceLocation getConceptKWLoc() const { return ConceptKWLoc; } + + SourceRange getSourceRange() const { + return {ConceptKWLoc, ArgsAsWritten->getRAngleLoc()}; + } + + friend const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, + PartiallyAppliedConcept &C); }; } // clang diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 1984310df0442..272a712fe170c 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -24,6 +24,7 @@ #include "clang/AST/PrettyPrinter.h" #include "clang/AST/RawCommentList.h" #include "clang/AST/TemplateName.h" +#include "clang/AST/UniversalTemplateParameterName.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceLocation.h" @@ -96,6 +97,7 @@ class ObjCTypeParamDecl; class OMPTraitInfo; class ParentMapContext; struct ParsedTargetAttr; +class PartiallyAppliedConcept; class Preprocessor; class ProfileList; class StoredDeclsMap; @@ -1660,7 +1662,7 @@ class ASTContext : public RefCountedBase { QualType getAutoTypeInternal(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent, bool IsPack = false, - ConceptDecl *TypeConstraintConcept = nullptr, + TemplateDecl *TypeConstraintConcept = nullptr, ArrayRef TypeConstraintArgs = {}, bool IsCanon = false) const; @@ -1825,10 +1827,11 @@ class ASTContext : public RefCountedBase { UnaryTransformType::UTTKind UKind) const; /// C++11 deduced auto type. - QualType getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, - bool IsDependent, bool IsPack = false, - ConceptDecl *TypeConstraintConcept = nullptr, - ArrayRef TypeConstraintArgs ={}) const; + QualType + getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent, + bool IsPack = false, + TemplateDecl *TypeConstraintConcept = nullptr, + ArrayRef TypeConstraintArgs = {}) const; /// C++11 deduction pattern for 'auto' type. QualType getAutoDeductType() const; @@ -2334,6 +2337,10 @@ class ASTContext : public RefCountedBase { unsigned Index, bool Final) const; + UniversalTemplateParameterName * + getUniversalTemplateParameterName(SourceLocation Loc, + DeclarationNameInfo Name, + UniversalTemplateParmDecl *Decl) const; /// Represents a TemplateName which had some of its default arguments /// deduced. This both represents this default argument deduction as sugar, /// and provides the support for it's equivalences through canonicalization. diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index a443a88bab1f2..b0f1109ad1977 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -722,6 +722,8 @@ class ASTNodeTraverser D->defaultArgumentWasInherited() ? "inherited from" : "previous"); } + void VisitUniversalTemplateParmDecl(const UniversalTemplateParmDecl *D) {} + void VisitConceptDecl(const ConceptDecl *D) { dumpTemplateParameters(D->getTemplateParameters()); Visit(D->getConstraintExpr()); diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 687715a22e9fd..bdc37eb6224b5 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -26,6 +26,7 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" +#include "clang/Basic/TemplateKinds.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerIntPair.h" @@ -53,6 +54,7 @@ class IdentifierInfo; class NonTypeTemplateParmDecl; class TemplateDecl; class TemplateTemplateParmDecl; +class UniversalTemplateParmDecl; class TemplateTypeParmDecl; class ConceptDecl; class UnresolvedSetImpl; @@ -62,7 +64,7 @@ class VarTemplatePartialSpecializationDecl; /// Stores a template parameter of any kind. using TemplateParameter = llvm::PointerUnion; + TemplateTemplateParmDecl *, UniversalTemplateParmDecl *>; NamedDecl *getAsNamedDecl(TemplateParameter P); @@ -1600,15 +1602,22 @@ class TemplateTemplateParmDecl final /// The number of parameters in an expanded parameter pack. unsigned NumExpandedParams = 0; + TemplateNameKind ParameterKind = TemplateNameKind::TNK_Type_template; + TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, bool ParameterPack, IdentifierInfo *Id, - bool Typename, TemplateParameterList *Params) + TemplateNameKind ParameterKind, + bool Typename, + TemplateParameterList *Params) : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), TemplateParmPosition(D, P), Typename(Typename), - ParameterPack(ParameterPack), ExpandedParameterPack(false) {} + ParameterPack(ParameterPack), + ExpandedParameterPack(false), ParameterKind(ParameterKind) {} TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, bool Typename, + unsigned P, IdentifierInfo *Id, + TemplateNameKind ParameterKind, + bool Typename, TemplateParameterList *Params, ArrayRef Expansions); @@ -1619,14 +1628,17 @@ class TemplateTemplateParmDecl final friend class ASTDeclWriter; friend TrailingObjects; - static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC, - SourceLocation L, unsigned D, - unsigned P, bool ParameterPack, - IdentifierInfo *Id, bool Typename, - TemplateParameterList *Params); static TemplateTemplateParmDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, bool Typename, + unsigned P, bool ParameterPack, IdentifierInfo *Id, + TemplateNameKind ParameterKind, bool Typename, + TemplateParameterList *Params); + + static TemplateTemplateParmDecl * + Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, + unsigned P, IdentifierInfo *Id, + TemplateNameKind ParameterKind, + bool Typename, TemplateParameterList *Params, ArrayRef Expansions); @@ -1741,11 +1753,90 @@ class TemplateTemplateParmDecl final return SourceRange(getTemplateParameters()->getTemplateLoc(), End); } + TemplateNameKind kind() const { + return ParameterKind; + } + + bool isTypeConceptTemplateParam() const { + return kind() == TemplateNameKind::TNK_Concept_template && + getTemplateParameters()->size() > 0 && + isa(getTemplateParameters()->getParam(0)); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == TemplateTemplateParm; } }; +class UniversalTemplateParmDecl final : public NamedDecl, + protected TemplateParmPosition { + + /// Whether this universal template parameter is a parameter pack. + bool ParameterPack; + + UniversalTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, + unsigned P, bool ParameterPack, IdentifierInfo *Id) + : NamedDecl(UniversalTemplateParm, DC, L, Id), TemplateParmPosition(D, P), + ParameterPack(ParameterPack) {} + + // UniversalTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, + // unsigned P, IdentifierInfo *Id, + // TemplateNameKind ParameterKind, + // TemplateParameterList *Params, + // ArrayRef Expansions); + + void anchor() override {} + +public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + + static UniversalTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC, + SourceLocation L, unsigned D, + unsigned P, bool ParameterPack, + IdentifierInfo *Id); + + // static TemplateTemplateParmDecl * + // Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, + /// unsigned P, IdentifierInfo *Id, TemplateNameKind ParameterKind, + // TemplateParameterList *Params, + // ArrayRef Expansions); + + static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C, + unsigned ID); + // static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C, + // unsigned ID, + // unsigned + // NumExpansions); + + using TemplateParmPosition::getDepth; + using TemplateParmPosition::getIndex; + using TemplateParmPosition::getPosition; + using TemplateParmPosition::setDepth; + using TemplateParmPosition::setPosition; + + /// Whether this template template parameter is a template + /// parameter pack. + /// + /// \code + /// template