From 2c092257ce69ee7207ae1733f11b2a2275c42e3f Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 19 Dec 2016 04:08:53 +0000 Subject: [PATCH] [c++1z] P0195R2: Support pack-expansion of using-declarations. This change introduces UsingPackDecl as a marker for the set of UsingDecls produced by pack expansion of a single (unresolved) using declaration. This is not strictly necessary (we just need to be able to map from the original using declaration to its expansions somehow), but it's useful to maintain the invariant that each declaration reference instantiates to refer to one declaration. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@290080 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclCXX.h | 119 ++++++++- include/clang/AST/RecursiveASTVisitor.h | 2 + include/clang/Basic/DeclNodes.td | 1 + include/clang/Basic/DiagnosticParseKinds.td | 7 + include/clang/Basic/DiagnosticSemaKinds.td | 5 + include/clang/Parse/Parser.h | 6 +- include/clang/Sema/Sema.h | 16 +- include/clang/Sema/Template.h | 5 + include/clang/Serialization/ASTBitCodes.h | 2 + lib/AST/DeclBase.cpp | 5 +- lib/AST/DeclCXX.cpp | 36 ++- lib/CodeGen/CGDecl.cpp | 4 + lib/Parse/ParseDeclCXX.cpp | 79 ++---- lib/Sema/SemaDeclCXX.cpp | 74 ++++-- lib/Sema/SemaExprCXX.cpp | 14 +- lib/Sema/SemaOverload.cpp | 8 +- lib/Sema/SemaTemplateInstantiateDecl.cpp | 193 ++++++++++----- lib/Sema/SemaTemplateVariadic.cpp | 19 +- lib/Sema/TreeTransform.h | 142 ++++++----- lib/Serialization/ASTCommon.cpp | 1 + lib/Serialization/ASTReaderDecl.cpp | 15 ++ lib/Serialization/ASTWriterDecl.cpp | 12 + test/PCH/cxx1z-using-declaration.cpp | 35 +++ test/Parser/cxx1z-using-declaration.cpp | 9 +- test/SemaTemplate/cxx1z-using-declaration.cpp | 230 ++++++++++++++++++ tools/libclang/CIndex.cpp | 1 + 26 files changed, 793 insertions(+), 247 deletions(-) create mode 100644 test/PCH/cxx1z-using-declaration.cpp create mode 100644 test/SemaTemplate/cxx1z-using-declaration.cpp 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