forked from OSchip/llvm-project
[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
This commit is contained in:
parent
52ffbfdffc
commit
ddda05add5
|
@ -193,9 +193,9 @@ public:
|
|||
}
|
||||
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();
|
||||
|
|
|
@ -69,6 +69,7 @@ class FriendDecl;
|
|||
class FunctionTemplateDecl;
|
||||
class IdentifierInfo;
|
||||
class MemberSpecializationInfo;
|
||||
class BaseUsingDecl;
|
||||
class TemplateDecl;
|
||||
class TemplateParameterList;
|
||||
class UsingDecl;
|
||||
|
@ -3163,21 +3164,27 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// 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 @@ public:
|
|||
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 @@ public:
|
|||
~(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 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// 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 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_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 @@ public:
|
|||
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 @@ public:
|
|||
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 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_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.
|
||||
///
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -5702,10 +5702,10 @@ public:
|
|||
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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -502,6 +502,9 @@ public:
|
|||
/// 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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -7000,7 +7000,7 @@ public:
|
|||
: 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 @@ public:
|
|||
// 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();
|
||||
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());
|
||||
// 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 (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...?
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue