[clang-tools-extra] ddda05a - [clang][NFC] Break out BaseUsingDecl from UsingDecl

Nathan Sidwell via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 7 06:29:50 PDT 2021


Author: Nathan Sidwell
Date: 2021-06-07T06:29:28-07:00
New Revision: ddda05add527f7f92a71f387b927f237334f46d9

URL: https://github.com/llvm/llvm-project/commit/ddda05add527f7f92a71f387b927f237334f46d9
DIFF: https://github.com/llvm/llvm-project/commit/ddda05add527f7f92a71f387b927f237334f46d9.diff

LOG: [clang][NFC] Break out BaseUsingDecl from UsingDecl

This is a pre-patch for adding using-enum support.  It breaks out
the shadow decl handling of UsingDecl to a new intermediate base
class, BaseUsingDecl, altering the decl hierarchy to

def BaseUsing : DeclNode<Named, "", 1>;
  def Using : DeclNode<BaseUsing>;
def UsingPack : DeclNode<Named>;
def UsingShadow : DeclNode<Named>;
  def ConstructorUsingShadow : DeclNode<UsingShadow>;

Differential Revision: https://reviews.llvm.org/D101777

Added: 
    

Modified: 
    clang-tools-extra/clangd/FindTarget.cpp
    clang/include/clang/AST/DeclCXX.h
    clang/include/clang/Basic/DeclNodes.td
    clang/include/clang/Sema/Sema.h
    clang/lib/AST/ASTImporter.cpp
    clang/lib/AST/DeclCXX.cpp
    clang/lib/CodeGen/CGDebugInfo.cpp
    clang/lib/CodeGen/CGDebugInfo.h
    clang/lib/Sema/SemaAccess.cpp
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaDeclCXX.cpp
    clang/lib/Sema/SemaLookup.cpp
    clang/lib/Sema/SemaTemplate.cpp
    clang/tools/libclang/CIndex.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp
index c8eca4e7ca8c7..9068fffcbd402 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<UsingShadowDecl>(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 5c7cdd67e3d32..c8095bb2ca2b3 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<UsingShadowDecl> {
-  friend class UsingDecl;
+  friend class BaseUsingDecl;
 
   /// The referenced declaration.
   NamedDecl *Underlying = nullptr;
@@ -3204,7 +3211,8 @@ class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> {
 
 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<UsingShadowDecl> {
   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<UsingShadowDecl> {
         ~(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<UsingShadowDecl> {
   }
 };
 
+/// 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<UsingShadowDecl *, 1, bool> 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 
diff erence_type = std::ptr
diff _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_iterator>;
+
+  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<UsingDecl> {
+  /// 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<UsingDecl>(getFirstDecl());
+  }
+  const UsingDecl *getCanonicalDecl() const {
+    return cast<UsingDecl>(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<ConstructorUsingShadowDecl>(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<UsingDecl>(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<UsingDecl> {
-  /// 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<UsingShadowDecl *, 1, bool> 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 
diff erence_type = std::ptr
diff _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_iterator>;
-
-  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 5e60226db7b57..ceaea521f1182 100644
--- a/clang/include/clang/Basic/DeclNodes.td
+++ b/clang/include/clang/Basic/DeclNodes.td
@@ -71,7 +71,8 @@ def Named : DeclNode<Decl, "named declarations", 1>;
     def TemplateTemplateParm : DeclNode<Template>;
     def BuiltinTemplate : DeclNode<Template>;
     def Concept : DeclNode<Template>;
-  def Using : DeclNode<Named>;
+  def BaseUsing : DeclNode<Named, "", 1>;
+    def Using : DeclNode<BaseUsing>;
   def UsingPack : DeclNode<Named>;
   def UsingShadow : DeclNode<Named>;
     def ConstructorUsingShadow : DeclNode<UsingShadow>;

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 2978f7249ea48..57be1cb6d21c3 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5702,10 +5702,10 @@ class Sema final {
                                IdentifierInfo *Ident);
 
   void HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow);
-  bool CheckUsingShadowDecl(UsingDecl *UD, NamedDecl *Target,
+  bool CheckUsingShadowDecl(BaseUsingDecl *BUD, NamedDecl *Target,
                             const LookupResult &PreviousDecls,
                             UsingShadowDecl *&PrevShadow);
-  UsingShadowDecl *BuildUsingShadowDecl(Scope *S, UsingDecl *UD,
+  UsingShadowDecl *BuildUsingShadowDecl(Scope *S, BaseUsingDecl *BUD,
                                         NamedDecl *Target,
                                         UsingShadowDecl *PrevDecl);
 

diff  --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 66f384ada1485..c27a50eba1d8e 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -4624,9 +4624,9 @@ ExpectedDecl ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) {
   if (ToD)
     return ToD;
 
-  Expected<UsingDecl *> ToUsingOrErr = import(D->getUsingDecl());
-  if (!ToUsingOrErr)
-    return ToUsingOrErr.takeError();
+  Expected<BaseUsingDecl *> ToIntroducerOrErr = import(D->getIntroducer());
+  if (!ToIntroducerOrErr)
+    return ToIntroducerOrErr.takeError();
 
   Expected<NamedDecl *> ToTargetOrErr = import(D->getTargetDecl());
   if (!ToTargetOrErr)
@@ -4634,7 +4634,7 @@ ExpectedDecl ASTNodeImporter::VisitUsingShadowDecl(UsingShadowDecl *D) {
 
   UsingShadowDecl *ToShadow;
   if (GetImportedOrCreateDecl(ToShadow, D, Importer.getToContext(), DC, Loc,
-                              *ToUsingOrErr, *ToTargetOrErr))
+                              Name, *ToIntroducerOrErr, *ToTargetOrErr))
     return ToShadow;
 
   ToShadow->setLexicalDeclContext(LexicalDC);

diff  --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 5b459686d8795..10d59bce3f5ce 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -2983,10 +2983,10 @@ APValue *LifetimeExtendedTemporaryDecl::getOrCreateValue(bool MayCreate) const {
 void UsingShadowDecl::anchor() {}
 
 UsingShadowDecl::UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC,
-                                 SourceLocation Loc, UsingDecl *Using,
-                                 NamedDecl *Target)
-    : NamedDecl(K, DC, Loc, Using ? Using->getDeclName() : DeclarationName()),
-      redeclarable_base(C), UsingOrNextShadow(cast<NamedDecl>(Using)) {
+                                 SourceLocation Loc, DeclarationName Name,
+                                 BaseUsingDecl *Introducer, NamedDecl *Target)
+    : NamedDecl(K, DC, Loc, Name), redeclarable_base(C),
+      UsingOrNextShadow(Introducer) {
   if (Target)
     setTargetDecl(Target);
   setImplicit();
@@ -3001,12 +3001,12 @@ UsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
   return new (C, ID) UsingShadowDecl(UsingShadow, C, EmptyShell());
 }
 
-UsingDecl *UsingShadowDecl::getUsingDecl() const {
+BaseUsingDecl *UsingShadowDecl::getIntroducer() const {
   const UsingShadowDecl *Shadow = this;
   while (const auto *NextShadow =
              dyn_cast<UsingShadowDecl>(Shadow->UsingOrNextShadow))
     Shadow = NextShadow;
-  return cast<UsingDecl>(Shadow->UsingOrNextShadow);
+  return cast<BaseUsingDecl>(Shadow->UsingOrNextShadow);
 }
 
 void ConstructorUsingShadowDecl::anchor() {}
@@ -3025,25 +3025,25 @@ ConstructorUsingShadowDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
 }
 
 CXXRecordDecl *ConstructorUsingShadowDecl::getNominatedBaseClass() const {
-  return getUsingDecl()->getQualifier()->getAsRecordDecl();
+  return getIntroducer()->getQualifier()->getAsRecordDecl();
 }
 
-void UsingDecl::anchor() {}
+void BaseUsingDecl::anchor() {}
 
-void UsingDecl::addShadowDecl(UsingShadowDecl *S) {
+void BaseUsingDecl::addShadowDecl(UsingShadowDecl *S) {
   assert(std::find(shadow_begin(), shadow_end(), S) == shadow_end() &&
          "declaration already in set");
-  assert(S->getUsingDecl() == this);
+  assert(S->getIntroducer() == this);
 
   if (FirstUsingShadow.getPointer())
     S->UsingOrNextShadow = FirstUsingShadow.getPointer();
   FirstUsingShadow.setPointer(S);
 }
 
-void UsingDecl::removeShadowDecl(UsingShadowDecl *S) {
+void BaseUsingDecl::removeShadowDecl(UsingShadowDecl *S) {
   assert(std::find(shadow_begin(), shadow_end(), S) != shadow_end() &&
          "declaration not in set");
-  assert(S->getUsingDecl() == this);
+  assert(S->getIntroducer() == this);
 
   // Remove S from the shadow decl chain. This is O(n) but hopefully rare.
 
@@ -3061,6 +3061,8 @@ void UsingDecl::removeShadowDecl(UsingShadowDecl *S) {
   S->UsingOrNextShadow = this;
 }
 
+void UsingDecl::anchor() {}
+
 UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL,
                              NestedNameSpecifierLoc QualifierLoc,
                              const DeclarationNameInfo &NameInfo,

diff  --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index e8c310e0c060c..b1db8a889b3fc 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -4967,24 +4967,7 @@ void CGDebugInfo::EmitUsingDirective(const UsingDirectiveDecl &UD) {
   }
 }
 
-void CGDebugInfo::EmitUsingDecl(const UsingDecl &UD) {
-  if (!CGM.getCodeGenOpts().hasReducedDebugInfo())
-    return;
-  assert(UD.shadow_size() &&
-         "We shouldn't be codegening an invalid UsingDecl containing no decls");
-  // Emitting one decl is sufficient - debuggers can detect that this is an
-  // overloaded name & provide lookup for all the overloads.
-  const UsingShadowDecl &USD = **UD.shadow_begin();
-
-  // FIXME: Skip functions with undeduced auto return type for now since we
-  // don't currently have the plumbing for separate declarations & definitions
-  // of free functions and mismatched types (auto in the declaration, concrete
-  // return type in the definition)
-  if (const auto *FD = dyn_cast<FunctionDecl>(USD.getUnderlyingDecl()))
-    if (const auto *AT =
-            FD->getType()->castAs<FunctionProtoType>()->getContainedAutoType())
-      if (AT->getDeducedType().isNull())
-        return;
+void CGDebugInfo::EmitUsingShadowDecl(const UsingShadowDecl &USD) {
   if (llvm::DINode *Target =
           getDeclarationOrDefinition(USD.getUnderlyingDecl())) {
     auto Loc = USD.getLocation();
@@ -4994,6 +4977,31 @@ void CGDebugInfo::EmitUsingDecl(const UsingDecl &UD) {
   }
 }
 
+void CGDebugInfo::EmitUsingDecl(const UsingDecl &UD) {
+  if (!CGM.getCodeGenOpts().hasReducedDebugInfo())
+    return;
+  assert(UD.shadow_size() &&
+         "We shouldn't be codegening an invalid UsingDecl containing no decls");
+
+  for (const auto *USD : UD.shadows()) {
+    // FIXME: Skip functions with undeduced auto return type for now since we
+    // don't currently have the plumbing for separate declarations & definitions
+    // of free functions and mismatched types (auto in the declaration, concrete
+    // return type in the definition)
+    if (const auto *FD = dyn_cast<FunctionDecl>(USD->getUnderlyingDecl()))
+      if (const auto *AT = FD->getType()
+                               ->castAs<FunctionProtoType>()
+                               ->getContainedAutoType())
+        if (AT->getDeducedType().isNull())
+          continue;
+
+    EmitUsingShadowDecl(*USD);
+    // Emitting one decl is sufficient - debuggers can detect that this is an
+    // overloaded name & provide lookup for all the overloads.
+    break;
+  }
+}
+
 void CGDebugInfo::EmitImportDecl(const ImportDecl &ID) {
   if (CGM.getCodeGenOpts().getDebuggerTuning() != llvm::DebuggerKind::LLDB)
     return;

diff  --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index 228ac691a0b7c..e9ead90aafb52 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -502,6 +502,9 @@ class CGDebugInfo {
   /// Emit the type even if it might not be used.
   void EmitAndRetainType(QualType Ty);
 
+  /// Emit a shadow decl brought in by a using or using-enum
+  void EmitUsingShadowDecl(const UsingShadowDecl &USD);
+
   /// Emit C++ using declaration.
   void EmitUsingDecl(const UsingDecl &UD);
 

diff  --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp
index 3af05988073ed..580305c1110bc 100644
--- a/clang/lib/Sema/SemaAccess.cpp
+++ b/clang/lib/Sema/SemaAccess.cpp
@@ -1308,17 +1308,18 @@ static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S,
                                                  SourceLocation AccessLoc,
                                                  AccessTarget &Entity) {
   if (UsingShadowDecl *Shadow =
-                         dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) {
-    const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl();
-    if (Entity.getTargetDecl()->getAccess() == AS_private &&
-        (OrigDecl->getAccess() == AS_public ||
-         OrigDecl->getAccess() == AS_protected)) {
-      S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)
-        << Shadow->getUsingDecl()->getQualifiedNameAsString()
-        << OrigDecl->getQualifiedNameAsString();
-      return true;
+          dyn_cast<UsingShadowDecl>(Entity.getTargetDecl()))
+    if (UsingDecl *UD = dyn_cast<UsingDecl>(Shadow->getIntroducer())) {
+      const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl();
+      if (Entity.getTargetDecl()->getAccess() == AS_private &&
+          (OrigDecl->getAccess() == AS_public ||
+           OrigDecl->getAccess() == AS_protected)) {
+        S.Diag(AccessLoc, diag::ext_ms_using_declaration_inaccessible)
+            << UD->getQualifiedNameAsString()
+            << OrigDecl->getQualifiedNameAsString();
+        return true;
+      }
     }
-  }
   return false;
 }
 

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 4f62113dd8e60..21a35002159ed 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -3200,7 +3200,7 @@ static bool checkUsingShadowRedecl(Sema &S, UsingShadowDecl *OldS,
   if (!Old) {
     S.Diag(New->getLocation(), diag::err_using_decl_conflict_reverse);
     S.Diag(OldS->getTargetDecl()->getLocation(), diag::note_using_decl_target);
-    S.Diag(OldS->getUsingDecl()->getLocation(), diag::note_using_decl) << 0;
+    S.Diag(OldS->getIntroducer()->getLocation(), diag::note_using_decl) << 0;
     return true;
   }
   return false;
@@ -3285,8 +3285,8 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, NamedDecl *&OldD,
         Diag(New->getLocation(), diag::err_using_decl_friend);
         Diag(Shadow->getTargetDecl()->getLocation(),
              diag::note_using_decl_target);
-        Diag(Shadow->getUsingDecl()->getLocation(),
-             diag::note_using_decl) << 0;
+        Diag(Shadow->getIntroducer()->getLocation(), diag::note_using_decl)
+            << 0;
         return true;
       }
 
@@ -15988,7 +15988,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
         Diag(KWLoc, diag::err_using_decl_conflict_reverse);
         Diag(Shadow->getTargetDecl()->getLocation(),
              diag::note_using_decl_target);
-        Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl)
+        Diag(Shadow->getIntroducer()->getLocation(), diag::note_using_decl)
             << 0;
         // Recover by ignoring the old declaration.
         Previous.clear();

diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 3fffcd33ac50f..6b2fc0358a791 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7000,7 +7000,7 @@ class Sema::InheritedConstructorInfo {
       : S(S), UseLoc(UseLoc) {
     bool DiagnosedMultipleConstructedBases = false;
     CXXRecordDecl *ConstructedBase = nullptr;
-    UsingDecl *ConstructedBaseUsing = nullptr;
+    BaseUsingDecl *ConstructedBaseIntroducer = nullptr;
 
     // Find the set of such base class subobjects and check that there's a
     // unique constructed subobject.
@@ -7024,18 +7024,18 @@ class Sema::InheritedConstructorInfo {
       //   of type B, the program is ill-formed.
       if (!ConstructedBase) {
         ConstructedBase = DConstructedBase;
-        ConstructedBaseUsing = D->getUsingDecl();
+        ConstructedBaseIntroducer = D->getIntroducer();
       } else if (ConstructedBase != DConstructedBase &&
                  !Shadow->isInvalidDecl()) {
         if (!DiagnosedMultipleConstructedBases) {
           S.Diag(UseLoc, diag::err_ambiguous_inherited_constructor)
               << Shadow->getTargetDecl();
-          S.Diag(ConstructedBaseUsing->getLocation(),
-               diag::note_ambiguous_inherited_constructor_using)
+          S.Diag(ConstructedBaseIntroducer->getLocation(),
+                 diag::note_ambiguous_inherited_constructor_using)
               << ConstructedBase;
           DiagnosedMultipleConstructedBases = true;
         }
-        S.Diag(D->getUsingDecl()->getLocation(),
+        S.Diag(D->getIntroducer()->getLocation(),
                diag::note_ambiguous_inherited_constructor_using)
             << DConstructedBase;
       }
@@ -11640,7 +11640,7 @@ IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2) {
 
 /// Determines whether to create a using shadow decl for a particular
 /// decl, given the set of decls existing prior to this using lookup.
-bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
+bool Sema::CheckUsingShadowDecl(BaseUsingDecl *BUD, NamedDecl *Orig,
                                 const LookupResult &Previous,
                                 UsingShadowDecl *&PrevShadow) {
   // Diagnose finding a decl which is not from a base class of the
@@ -11662,35 +11662,36 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
   // specialization.  The UsingShadowDecl in D<T> then points directly
   // to A::foo, which will look well-formed when we instantiate.
   // The right solution is to not collapse the shadow-decl chain.
-  if (!getLangOpts().CPlusPlus11 && CurContext->isRecord()) {
-    DeclContext *OrigDC = Orig->getDeclContext();
-
-    // Handle enums and anonymous structs.
-    if (isa<EnumDecl>(OrigDC)) OrigDC = OrigDC->getParent();
-    CXXRecordDecl *OrigRec = cast<CXXRecordDecl>(OrigDC);
-    while (OrigRec->isAnonymousStructOrUnion())
-      OrigRec = cast<CXXRecordDecl>(OrigRec->getDeclContext());
-
-    if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(OrigRec)) {
-      if (OrigDC == CurContext) {
-        Diag(Using->getLocation(),
-             diag::err_using_decl_nested_name_specifier_is_current_class)
-          << Using->getQualifierLoc().getSourceRange();
+  if (!getLangOpts().CPlusPlus11 && CurContext->isRecord())
+    if (auto *Using = dyn_cast<UsingDecl>(BUD)) {
+      DeclContext *OrigDC = Orig->getDeclContext();
+
+      // Handle enums and anonymous structs.
+      if (isa<EnumDecl>(OrigDC))
+        OrigDC = OrigDC->getParent();
+      CXXRecordDecl *OrigRec = cast<CXXRecordDecl>(OrigDC);
+      while (OrigRec->isAnonymousStructOrUnion())
+        OrigRec = cast<CXXRecordDecl>(OrigRec->getDeclContext());
+
+      if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(OrigRec)) {
+        if (OrigDC == CurContext) {
+          Diag(Using->getLocation(),
+               diag::err_using_decl_nested_name_specifier_is_current_class)
+              << Using->getQualifierLoc().getSourceRange();
+          Diag(Orig->getLocation(), diag::note_using_decl_target);
+          Using->setInvalidDecl();
+          return true;
+        }
+
+        Diag(Using->getQualifierLoc().getBeginLoc(),
+             diag::err_using_decl_nested_name_specifier_is_not_base_class)
+            << Using->getQualifier() << cast<CXXRecordDecl>(CurContext)
+            << Using->getQualifierLoc().getSourceRange();
         Diag(Orig->getLocation(), diag::note_using_decl_target);
         Using->setInvalidDecl();
         return true;
       }
-
-      Diag(Using->getQualifierLoc().getBeginLoc(),
-           diag::err_using_decl_nested_name_specifier_is_not_base_class)
-        << Using->getQualifier()
-        << cast<CXXRecordDecl>(CurContext)
-        << Using->getQualifierLoc().getSourceRange();
-      Diag(Orig->getLocation(), diag::note_using_decl_target);
-      Using->setInvalidDecl();
-      return true;
     }
-  }
 
   if (Previous.empty()) return false;
 
@@ -11723,7 +11724,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
           !isa<UnresolvedUsingValueDecl>(Target) &&
           DiagnoseClassNameShadow(
               CurContext,
-              DeclarationNameInfo(Using->getDeclName(), Using->getLocation())))
+              DeclarationNameInfo(BUD->getDeclName(), BUD->getLocation())))
         return true;
     }
 
@@ -11766,7 +11767,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
       return false;
 
     case Ovl_NonFunction:
-      Diag(Using->getLocation(), diag::err_using_decl_conflict);
+      Diag(BUD->getLocation(), diag::err_using_decl_conflict);
       break;
 
     // We found a decl with the exact signature.
@@ -11778,13 +11779,13 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
         return true;
 
       // If we're not in a record, this is an error.
-      Diag(Using->getLocation(), diag::err_using_decl_conflict);
+      Diag(BUD->getLocation(), diag::err_using_decl_conflict);
       break;
     }
 
     Diag(Target->getLocation(), diag::note_using_decl_target);
     Diag(OldDecl->getLocation(), diag::note_using_decl_conflict);
-    Using->setInvalidDecl();
+    BUD->setInvalidDecl();
     return true;
   }
 
@@ -11794,20 +11795,20 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
     // No conflict between a tag and a non-tag.
     if (!Tag) return false;
 
-    Diag(Using->getLocation(), diag::err_using_decl_conflict);
+    Diag(BUD->getLocation(), diag::err_using_decl_conflict);
     Diag(Target->getLocation(), diag::note_using_decl_target);
     Diag(Tag->getLocation(), diag::note_using_decl_conflict);
-    Using->setInvalidDecl();
+    BUD->setInvalidDecl();
     return true;
   }
 
   // No conflict between a tag and a non-tag.
   if (!NonTag) return false;
 
-  Diag(Using->getLocation(), diag::err_using_decl_conflict);
+  Diag(BUD->getLocation(), diag::err_using_decl_conflict);
   Diag(Target->getLocation(), diag::note_using_decl_target);
   Diag(NonTag->getLocation(), diag::note_using_decl_conflict);
-  Using->setInvalidDecl();
+  BUD->setInvalidDecl();
   return true;
 }
 
@@ -11822,8 +11823,7 @@ static bool isVirtualDirectBase(CXXRecordDecl *Derived, CXXRecordDecl *Base) {
 }
 
 /// Builds a shadow declaration corresponding to a 'using' declaration.
-UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
-                                            UsingDecl *UD,
+UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S, BaseUsingDecl *BUD,
                                             NamedDecl *Orig,
                                             UsingShadowDecl *PrevDecl) {
   // If we resolved to another shadow declaration, just coalesce them.
@@ -11839,19 +11839,20 @@ UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
 
   UsingShadowDecl *Shadow;
   if (NonTemplateTarget && isa<CXXConstructorDecl>(NonTemplateTarget)) {
+    UsingDecl *Using = cast<UsingDecl>(BUD);
     bool IsVirtualBase =
         isVirtualDirectBase(cast<CXXRecordDecl>(CurContext),
-                            UD->getQualifier()->getAsRecordDecl());
+                            Using->getQualifier()->getAsRecordDecl());
     Shadow = ConstructorUsingShadowDecl::Create(
-        Context, CurContext, UD->getLocation(), UD, Orig, IsVirtualBase);
+        Context, CurContext, Using->getLocation(), Using, Orig, IsVirtualBase);
   } else {
-    Shadow = UsingShadowDecl::Create(Context, CurContext, UD->getLocation(), UD,
-                                     Target);
+    Shadow = UsingShadowDecl::Create(Context, CurContext, BUD->getLocation(),
+                                     Target->getDeclName(), BUD, Target);
   }
-  UD->addShadowDecl(Shadow);
+  BUD->addShadowDecl(Shadow);
 
-  Shadow->setAccess(UD->getAccess());
-  if (Orig->isInvalidDecl() || UD->isInvalidDecl())
+  Shadow->setAccess(BUD->getAccess());
+  if (Orig->isInvalidDecl() || BUD->isInvalidDecl())
     Shadow->setInvalidDecl();
 
   Shadow->setPreviousDecl(PrevDecl);
@@ -11907,7 +11908,7 @@ void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) {
   }
 
   // ...and the using decl.
-  Shadow->getUsingDecl()->removeShadowDecl(Shadow);
+  Shadow->getIntroducer()->removeShadowDecl(Shadow);
 
   // TODO: complain somehow if Shadow was used.  It shouldn't
   // be possible for this to happen, because...?

diff  --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 4b3d7de04bf72..d953805696e5a 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -3732,7 +3732,7 @@ NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) {
       // A shadow declaration that's created by a resolved using declaration
       // is not hidden by the same using declaration.
       if (isa<UsingShadowDecl>(ND) && isa<UsingDecl>(D) &&
-          cast<UsingShadowDecl>(ND)->getUsingDecl() == D)
+          cast<UsingShadowDecl>(ND)->getIntroducer() == D)
         continue;
 
       // We've found a declaration that hides this one.

diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index fd376148c1c45..77866a27e47ef 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -1870,7 +1870,7 @@ DeclResult Sema::CheckClassTemplate(
       Diag(KWLoc, diag::err_using_decl_conflict_reverse);
       Diag(Shadow->getTargetDecl()->getLocation(),
            diag::note_using_decl_target);
-      Diag(Shadow->getUsingDecl()->getLocation(), diag::note_using_decl) << 0;
+      Diag(Shadow->getIntroducer()->getLocation(), diag::note_using_decl) << 0;
       // Recover by ignoring the old declaration.
       PrevDecl = PrevClassTemplate = nullptr;
     }

diff  --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 76f6ef3f66a74..3ec41c9b025c1 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -6541,7 +6541,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
   }
 
   case Decl::Using:
-    return MakeCursorOverloadedDeclRef(cast<UsingDecl>(D), D->getLocation(),
+    return MakeCursorOverloadedDeclRef(cast<BaseUsingDecl>(D), D->getLocation(),
                                        TU);
 
   case Decl::UsingShadow:


        


More information about the cfe-commits mailing list