diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 46434c4c7b..06ecd3c373 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -3140,6 +3140,77 @@ public: friend class ASTDeclWriter; }; +/// Represents a pack of using declarations that a single +/// using-declarator pack-expanded into. +/// +/// \code +/// template struct X : T... { +/// using T::operator()...; +/// using T::operator T...; +/// }; +/// \endcode +/// +/// In the second case above, the UsingPackDecl will have the name +/// 'operator T' (which contains an unexpanded pack), but the individual +/// UsingDecls and UsingShadowDecls will have more reasonable names. +class UsingPackDecl final + : public NamedDecl, public Mergeable, + private llvm::TrailingObjects { + void anchor() override; + + /// The UnresolvedUsingValueDecl or UnresolvedUsingTypenameDecl from + /// which this waas instantiated. + NamedDecl *InstantiatedFrom; + + /// The number of using-declarations created by this pack expansion. + unsigned NumExpansions; + + UsingPackDecl(DeclContext *DC, NamedDecl *InstantiatedFrom, + ArrayRef UsingDecls) + : NamedDecl(UsingPack, DC, + InstantiatedFrom ? InstantiatedFrom->getLocation() + : SourceLocation(), + InstantiatedFrom ? InstantiatedFrom->getDeclName() + : DeclarationName()), + InstantiatedFrom(InstantiatedFrom), NumExpansions(UsingDecls.size()) { + std::uninitialized_copy(UsingDecls.begin(), UsingDecls.end(), + getTrailingObjects()); + } + +public: + /// Get the using declaration from which this was instantiated. This will + /// always be an UnresolvedUsingValueDecl or an UnresolvedUsingTypenameDecl + /// that is a pack expansion. + NamedDecl *getInstantiatedFromUsingDecl() { return InstantiatedFrom; } + + /// Get the set of using declarations that this pack expanded into. Note that + /// some of these may still be unresolved. + ArrayRef expansions() const { + return llvm::makeArrayRef(getTrailingObjects(), NumExpansions); + } + + static UsingPackDecl *Create(ASTContext &C, DeclContext *DC, + NamedDecl *InstantiatedFrom, + ArrayRef UsingDecls); + + static UsingPackDecl *CreateDeserialized(ASTContext &C, unsigned ID, + unsigned NumExpansions); + + SourceRange getSourceRange() const override LLVM_READONLY { + return InstantiatedFrom->getSourceRange(); + } + + UsingPackDecl *getCanonicalDecl() override { return getFirstDecl(); } + const UsingPackDecl *getCanonicalDecl() const { return getFirstDecl(); } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == UsingPack; } + + friend class ASTDeclReader; + friend class ASTDeclWriter; + friend TrailingObjects; +}; + /// \brief Represents a dependent using declaration which was not marked with /// \c typename. /// @@ -3158,6 +3229,9 @@ class UnresolvedUsingValueDecl : public ValueDecl, /// \brief The source location of the 'using' keyword SourceLocation UsingLocation; + /// \brief If this is a pack expansion, the location of the '...'. + SourceLocation EllipsisLoc; + /// \brief The nested-name-specifier that precedes the name. NestedNameSpecifierLoc QualifierLoc; @@ -3168,11 +3242,12 @@ class UnresolvedUsingValueDecl : public ValueDecl, UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty, SourceLocation UsingLoc, NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo) + const DeclarationNameInfo &NameInfo, + SourceLocation EllipsisLoc) : ValueDecl(UnresolvedUsingValue, DC, NameInfo.getLoc(), NameInfo.getName(), Ty), - UsingLocation(UsingLoc), QualifierLoc(QualifierLoc), - DNLoc(NameInfo.getInfo()) + UsingLocation(UsingLoc), EllipsisLoc(EllipsisLoc), + QualifierLoc(QualifierLoc), DNLoc(NameInfo.getInfo()) { } public: @@ -3198,10 +3273,20 @@ public: return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } + /// \brief Determine whether this is a pack expansion. + bool isPackExpansion() const { + return EllipsisLoc.isValid(); + } + + /// \brief Get the location of the ellipsis if this is a pack expansion. + SourceLocation getEllipsisLoc() const { + return EllipsisLoc; + } + static UnresolvedUsingValueDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo); + const DeclarationNameInfo &NameInfo, SourceLocation EllipsisLoc); static UnresolvedUsingValueDecl * CreateDeserialized(ASTContext &C, unsigned ID); @@ -3242,6 +3327,9 @@ class UnresolvedUsingTypenameDecl /// \brief The source location of the 'typename' keyword SourceLocation TypenameLocation; + /// \brief If this is a pack expansion, the location of the '...'. + SourceLocation EllipsisLoc; + /// \brief The nested-name-specifier that precedes the name. NestedNameSpecifierLoc QualifierLoc; @@ -3249,10 +3337,12 @@ class UnresolvedUsingTypenameDecl SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TargetNameLoc, - IdentifierInfo *TargetName) + IdentifierInfo *TargetName, + SourceLocation EllipsisLoc) : TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName, UsingLoc), - TypenameLocation(TypenameLoc), QualifierLoc(QualifierLoc) { } + TypenameLocation(TypenameLoc), EllipsisLoc(EllipsisLoc), + QualifierLoc(QualifierLoc) { } friend class ASTDeclReader; @@ -3272,10 +3362,25 @@ public: return QualifierLoc.getNestedNameSpecifier(); } + DeclarationNameInfo getNameInfo() const { + return DeclarationNameInfo(getDeclName(), getLocation()); + } + + /// \brief Determine whether this is a pack expansion. + bool isPackExpansion() const { + return EllipsisLoc.isValid(); + } + + /// \brief Get the location of the ellipsis if this is a pack expansion. + SourceLocation getEllipsisLoc() const { + return EllipsisLoc; + } + static UnresolvedUsingTypenameDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc, - SourceLocation TargetNameLoc, DeclarationName TargetName); + SourceLocation TargetNameLoc, DeclarationName TargetName, + SourceLocation EllipsisLoc); static UnresolvedUsingTypenameDecl * CreateDeserialized(ASTContext &C, unsigned ID); diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 058ab1fcbe..afacfd5723 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -1505,6 +1505,8 @@ DEF_TRAVERSE_DECL(UsingDecl, { TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo())); }) +DEF_TRAVERSE_DECL(UsingPackDecl, {}) + DEF_TRAVERSE_DECL(UsingDirectiveDecl, { TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); }) diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td index 6da2c2c3d6..7b581d3eec 100644 --- a/include/clang/Basic/DeclNodes.td +++ b/include/clang/Basic/DeclNodes.td @@ -67,6 +67,7 @@ def Named : Decl<1>; def TemplateTemplateParm : DDecl