Index: clang-tools-extra/clangd/FindTarget.cpp =================================================================== --- clang-tools-extra/clangd/FindTarget.cpp +++ clang-tools-extra/clangd/FindTarget.cpp @@ -193,9 +193,9 @@ } Flags |= Rel::Alias; // continue with the alias } else if (const UsingShadowDecl *USD = dyn_cast(D)) { - // Include the using decl, but don't traverse it. This may end up + // Include the Introducing decl, but don't traverse it. This may end up // including *all* shadows, which we don't want. - report(USD->getUsingDecl(), Flags | Rel::Alias); + report(USD->getIntroducer(), Flags | Rel::Alias); // Shadow decls are synthetic and not themselves interesting. // Record the underlying decl instead, if allowed. D = USD->getTargetDecl(); Index: clang/include/clang/AST/DeclCXX.h =================================================================== --- clang/include/clang/AST/DeclCXX.h +++ clang/include/clang/AST/DeclCXX.h @@ -69,6 +69,7 @@ class FunctionTemplateDecl; class IdentifierInfo; class MemberSpecializationInfo; +class BaseUsingDecl; class TemplateDecl; class TemplateParameterList; class UsingDecl; @@ -3153,21 +3154,27 @@ } }; -/// Represents a shadow declaration introduced into a scope by a -/// (resolved) using declaration. +/// Represents a shadow declaration implicitly introduced into a scope by a +/// (resolved) using-declaration or using-enum-declaration to achieve +/// the desired lookup semantics. /// -/// For example, +/// For example: /// \code /// namespace A { /// void foo(); +/// void foo(int); +/// struct foo {}; +/// enum bar { bar1, bar2 }; /// } /// namespace B { -/// using A::foo; // <- a UsingDecl -/// // Also creates a UsingShadowDecl for A::foo() in B +/// // add a UsingDecl and three UsingShadowDecls (named foo) to B. +/// using A::foo; +/// // adds UsingEnumDecl and two UsingShadowDecls (named bar1 and bar2) to B. +/// using enum A::bar; /// } /// \endcode class UsingShadowDecl : public NamedDecl, public Redeclarable { - friend class UsingDecl; + friend class BaseUsingDecl; /// The referenced declaration. NamedDecl *Underlying = nullptr; @@ -3194,7 +3201,8 @@ protected: UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC, SourceLocation Loc, - UsingDecl *Using, NamedDecl *Target); + DeclarationName Name, BaseUsingDecl *Introducer, + NamedDecl *Target); UsingShadowDecl(Kind K, ASTContext &C, EmptyShell); public: @@ -3202,9 +3210,10 @@ friend class ASTDeclWriter; static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation Loc, UsingDecl *Using, - NamedDecl *Target) { - return new (C, DC) UsingShadowDecl(UsingShadow, C, DC, Loc, Using, Target); + SourceLocation Loc, DeclarationName Name, + BaseUsingDecl *Introducer, NamedDecl *Target) { + return new (C, DC) + UsingShadowDecl(UsingShadow, C, DC, Loc, Name, Introducer, Target); } static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -3242,8 +3251,9 @@ ~(IDNS_OrdinaryFriend | IDNS_TagFriend | IDNS_LocalExtern); } - /// Gets the using declaration to which this declaration is tied. - UsingDecl *getUsingDecl() const; + /// Gets the (written or instantiated) using declaration that introduced this + /// declaration. + BaseUsingDecl *getIntroducer() const; /// The next using shadow declaration contained in the shadow decl /// chain of the using declaration which introduced this decl. @@ -3257,6 +3267,98 @@ } }; +/// Represents a C++ declaration that introduces decls from somewhere else. It +/// provides a set of the shadow decls so introduced. + +class BaseUsingDecl : public NamedDecl { + /// The first shadow declaration of the shadow decl chain associated + /// with this using declaration. + /// + /// The bool member of the pair is a bool flag a derived type may use + /// (UsingDecl makes use of it). + llvm::PointerIntPair FirstUsingShadow; + +protected: + BaseUsingDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N) + : NamedDecl(DK, DC, L, N), FirstUsingShadow(nullptr, 0) {} + +private: + void anchor() override; + +protected: + /// A bool flag for use by a derived type + bool getShadowFlag() const { return FirstUsingShadow.getInt(); } + + /// A bool flag a derived type may set + void setShadowFlag(bool V) { FirstUsingShadow.setInt(V); } + +public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + + /// Iterates through the using shadow declarations associated with + /// this using declaration. + class shadow_iterator { + /// The current using shadow declaration. + UsingShadowDecl *Current = nullptr; + + public: + using value_type = UsingShadowDecl *; + using reference = UsingShadowDecl *; + using pointer = UsingShadowDecl *; + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + + shadow_iterator() = default; + explicit shadow_iterator(UsingShadowDecl *C) : Current(C) {} + + reference operator*() const { return Current; } + pointer operator->() const { return Current; } + + shadow_iterator &operator++() { + Current = Current->getNextUsingShadowDecl(); + return *this; + } + + shadow_iterator operator++(int) { + shadow_iterator tmp(*this); + ++(*this); + return tmp; + } + + friend bool operator==(shadow_iterator x, shadow_iterator y) { + return x.Current == y.Current; + } + friend bool operator!=(shadow_iterator x, shadow_iterator y) { + return x.Current != y.Current; + } + }; + + using shadow_range = llvm::iterator_range; + + shadow_range shadows() const { + return shadow_range(shadow_begin(), shadow_end()); + } + + shadow_iterator shadow_begin() const { + return shadow_iterator(FirstUsingShadow.getPointer()); + } + + shadow_iterator shadow_end() const { return shadow_iterator(); } + + /// Return the number of shadowed declarations associated with this + /// using declaration. + unsigned shadow_size() const { + return std::distance(shadow_begin(), shadow_end()); + } + + void addShadowDecl(UsingShadowDecl *S); + void removeShadowDecl(UsingShadowDecl *S); + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == Using; } +}; + /// Represents a shadow constructor declaration introduced into a /// class by a C++11 using-declaration that names a constructor. /// @@ -3285,9 +3387,10 @@ unsigned IsVirtual : 1; ConstructorUsingShadowDecl(ASTContext &C, DeclContext *DC, SourceLocation Loc, - UsingDecl *Using, NamedDecl *Target, + BaseUsingDecl *Using, NamedDecl *Target, bool TargetInVirtualBase) - : UsingShadowDecl(ConstructorUsingShadow, C, DC, Loc, Using, + : UsingShadowDecl(ConstructorUsingShadow, C, DC, Loc, + Using->getDeclName(), Using, Target->getUnderlyingDecl()), NominatedBaseClassShadowDecl( dyn_cast(Target)), @@ -3373,7 +3476,7 @@ /// \code /// using someNameSpace::someIdentifier; /// \endcode -class UsingDecl : public NamedDecl, public Mergeable { +class UsingDecl : public BaseUsingDecl, public Mergeable { /// The source location of the 'using' keyword itself. SourceLocation UsingLocation; @@ -3384,19 +3487,13 @@ /// embedded in the ValueDecl base class. DeclarationNameLoc DNLoc; - /// The first shadow declaration of the shadow decl chain associated - /// with this using declaration. - /// - /// The bool member of the pair store whether this decl has the \c typename - /// keyword. - llvm::PointerIntPair FirstUsingShadow; - UsingDecl(DeclContext *DC, SourceLocation UL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool HasTypenameKeyword) - : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()), - UsingLocation(UL), QualifierLoc(QualifierLoc), - DNLoc(NameInfo.getInfo()), FirstUsingShadow(nullptr, HasTypenameKeyword) { + : BaseUsingDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()), + UsingLocation(UL), QualifierLoc(QualifierLoc), + DNLoc(NameInfo.getInfo()) { + setShadowFlag(HasTypenameKeyword); } void anchor() override; @@ -3428,69 +3525,10 @@ bool isAccessDeclaration() const { return UsingLocation.isInvalid(); } /// Return true if the using declaration has 'typename'. - bool hasTypename() const { return FirstUsingShadow.getInt(); } + bool hasTypename() const { return getShadowFlag(); } /// Sets whether the using declaration has 'typename'. - void setTypename(bool TN) { FirstUsingShadow.setInt(TN); } - - /// Iterates through the using shadow declarations associated with - /// this using declaration. - class shadow_iterator { - /// The current using shadow declaration. - UsingShadowDecl *Current = nullptr; - - public: - using value_type = UsingShadowDecl *; - using reference = UsingShadowDecl *; - using pointer = UsingShadowDecl *; - using iterator_category = std::forward_iterator_tag; - using difference_type = std::ptrdiff_t; - - shadow_iterator() = default; - explicit shadow_iterator(UsingShadowDecl *C) : Current(C) {} - - reference operator*() const { return Current; } - pointer operator->() const { return Current; } - - shadow_iterator& operator++() { - Current = Current->getNextUsingShadowDecl(); - return *this; - } - - shadow_iterator operator++(int) { - shadow_iterator tmp(*this); - ++(*this); - return tmp; - } - - friend bool operator==(shadow_iterator x, shadow_iterator y) { - return x.Current == y.Current; - } - friend bool operator!=(shadow_iterator x, shadow_iterator y) { - return x.Current != y.Current; - } - }; - - using shadow_range = llvm::iterator_range; - - shadow_range shadows() const { - return shadow_range(shadow_begin(), shadow_end()); - } - - shadow_iterator shadow_begin() const { - return shadow_iterator(FirstUsingShadow.getPointer()); - } - - shadow_iterator shadow_end() const { return shadow_iterator(); } - - /// Return the number of shadowed declarations associated with this - /// using declaration. - unsigned shadow_size() const { - return std::distance(shadow_begin(), shadow_end()); - } - - void addShadowDecl(UsingShadowDecl *S); - void removeShadowDecl(UsingShadowDecl *S); + void setTypename(bool TN) { setShadowFlag(TN); } static UsingDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation UsingL, @@ -3503,8 +3541,12 @@ SourceRange getSourceRange() const override LLVM_READONLY; /// Retrieves the canonical declaration of this declaration. - UsingDecl *getCanonicalDecl() override { return getFirstDecl(); } - const UsingDecl *getCanonicalDecl() const { return getFirstDecl(); } + UsingDecl *getCanonicalDecl() override { + return cast(getFirstDecl()); + } + const UsingDecl *getCanonicalDecl() const { + return cast(getFirstDecl()); + } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Using; } Index: clang/include/clang/Basic/DeclNodes.td =================================================================== --- clang/include/clang/Basic/DeclNodes.td +++ clang/include/clang/Basic/DeclNodes.td @@ -71,7 +71,8 @@ def TemplateTemplateParm : DeclNode