[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