diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp index c8eca4e7ca8c77..9068fffcbd4026 100644 --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -193,9 +193,9 @@ struct TargetFinder { } 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(); diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 5c7cdd67e3d329..c8095bb2ca2b3e 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -69,6 +69,7 @@ class FriendDecl; class FunctionTemplateDecl; class IdentifierInfo; class MemberSpecializationInfo; +class BaseUsingDecl; class TemplateDecl; class TemplateParameterList; class UsingDecl; @@ -3163,21 +3164,27 @@ class LifetimeExtendedTemporaryDecl final } }; -/// 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; @@ -3204,7 +3211,8 @@ class UsingShadowDecl : public NamedDecl, public Redeclarable { 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: @@ -3212,9 +3220,10 @@ class UsingShadowDecl : public NamedDecl, public Redeclarable { 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); @@ -3252,8 +3261,9 @@ class UsingShadowDecl : public NamedDecl, public Redeclarable { ~(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. @@ -3267,6 +3277,180 @@ class UsingShadowDecl : public NamedDecl, public Redeclarable { } }; +/// 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 C++ using-declaration. +/// +/// For example: +/// \code +/// using someNameSpace::someIdentifier; +/// \endcode +class UsingDecl : public BaseUsingDecl, public Mergeable { + /// The source location of the 'using' keyword itself. + SourceLocation UsingLocation; + + /// The nested-name-specifier that precedes the name. + NestedNameSpecifierLoc QualifierLoc; + + /// Provides source/type location info for the declaration name + /// embedded in the ValueDecl base class. + DeclarationNameLoc DNLoc; + + UsingDecl(DeclContext *DC, SourceLocation UL, + NestedNameSpecifierLoc QualifierLoc, + const DeclarationNameInfo &NameInfo, bool HasTypenameKeyword) + : BaseUsingDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()), + UsingLocation(UL), QualifierLoc(QualifierLoc), + DNLoc(NameInfo.getInfo()) { + setShadowFlag(HasTypenameKeyword); + } + + void anchor() override; + +public: + friend class ASTDeclReader; + friend class ASTDeclWriter; + + /// Return the source location of the 'using' keyword. + SourceLocation getUsingLoc() const { return UsingLocation; } + + /// Set the source location of the 'using' keyword. + void setUsingLoc(SourceLocation L) { UsingLocation = L; } + + /// Retrieve the nested-name-specifier that qualifies the name, + /// with source-location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// Retrieve the nested-name-specifier that qualifies the name. + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } + + DeclarationNameInfo getNameInfo() const { + return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); + } + + /// Return true if it is a C++03 access declaration (no 'using'). + bool isAccessDeclaration() const { return UsingLocation.isInvalid(); } + + /// Return true if the using declaration has 'typename'. + bool hasTypename() const { return getShadowFlag(); } + + /// Sets whether the using declaration has 'typename'. + void setTypename(bool TN) { setShadowFlag(TN); } + + static UsingDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation UsingL, + NestedNameSpecifierLoc QualifierLoc, + const DeclarationNameInfo &NameInfo, + bool HasTypenameKeyword); + + static UsingDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + SourceRange getSourceRange() const override LLVM_READONLY; + + /// Retrieves the canonical declaration of this declaration. + 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; } +}; + /// Represents a shadow constructor declaration introduced into a /// class by a C++11 using-declaration that names a constructor. /// @@ -3297,7 +3481,8 @@ class ConstructorUsingShadowDecl final : public UsingShadowDecl { ConstructorUsingShadowDecl(ASTContext &C, DeclContext *DC, SourceLocation Loc, UsingDecl *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)), @@ -3330,6 +3515,12 @@ class ConstructorUsingShadowDecl final : public UsingShadowDecl { static ConstructorUsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID); + /// Override the UsingShadowDecl's getIntroducer, returning the UsingDecl that + /// introduced this. + UsingDecl *getIntroducer() const { + return cast(UsingShadowDecl::getIntroducer()); + } + /// Returns the parent of this using shadow declaration, which /// is the class in which this is declared. //@{ @@ -3377,149 +3568,6 @@ class ConstructorUsingShadowDecl final : public UsingShadowDecl { static bool classofKind(Kind K) { return K == ConstructorUsingShadow; } }; -/// Represents a C++ using-declaration. -/// -/// For example: -/// \code -/// using someNameSpace::someIdentifier; -/// \endcode -class UsingDecl : public NamedDecl, public Mergeable { - /// The source location of the 'using' keyword itself. - SourceLocation UsingLocation; - - /// The nested-name-specifier that precedes the name. - NestedNameSpecifierLoc QualifierLoc; - - /// Provides source/type location info for the declaration name - /// 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) { - } - - void anchor() override; - -public: - friend class ASTDeclReader; - friend class ASTDeclWriter; - - /// Return the source location of the 'using' keyword. - SourceLocation getUsingLoc() const { return UsingLocation; } - - /// Set the source location of the 'using' keyword. - void setUsingLoc(SourceLocation L) { UsingLocation = L; } - - /// Retrieve the nested-name-specifier that qualifies the name, - /// with source-location information. - NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - - /// Retrieve the nested-name-specifier that qualifies the name. - NestedNameSpecifier *getQualifier() const { - return QualifierLoc.getNestedNameSpecifier(); - } - - DeclarationNameInfo getNameInfo() const { - return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); - } - - /// Return true if it is a C++03 access declaration (no 'using'). - bool isAccessDeclaration() const { return UsingLocation.isInvalid(); } - - /// Return true if the using declaration has 'typename'. - bool hasTypename() const { return FirstUsingShadow.getInt(); } - - /// 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); - - static UsingDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation UsingL, - NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo, - bool HasTypenameKeyword); - - static UsingDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - SourceRange getSourceRange() const override LLVM_READONLY; - - /// Retrieves the canonical declaration of this declaration. - UsingDecl *getCanonicalDecl() override { return getFirstDecl(); } - const UsingDecl *getCanonicalDecl() const { return getFirstDecl(); } - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == Using; } -}; - /// Represents a pack of using declarations that a single /// using-declarator pack-expanded into. /// diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td index 5e60226db7b572..ceaea521f11821 100644 --- a/clang/include/clang/Basic/DeclNodes.td +++ b/clang/include/clang/Basic/DeclNodes.td @@ -71,7 +71,8 @@ def Named : DeclNode; def TemplateTemplateParm : DeclNode