[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:
Nathan Sidwell 2021-05-03 11:05:56 -07:00
parent 52ffbfdffc
commit ddda05add5
14 changed files with 322 additions and 258 deletions

View File

@ -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();

View File

@ -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.
///

View File

@ -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>;

View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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();

View File

@ -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...?

View File

@ -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.

View File

@ -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;
}

View File

@ -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: