urnathan updated this revision to Diff 345416. urnathan added a comment. Herald added subscribers: cfe-commits, usaxena95, kadircet. Herald added a project: clang-tools-extra.
Address the build failure --thanks for explaining, it wasn;t clear what else I should try and build. Grepping showed no other getUsingDecl calls. Let's see ... CHANGES SINCE LAST ACTION https://reviews.llvm.org/D101777/new/ https://reviews.llvm.org/D101777 Files: 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
Index: clang/tools/libclang/CIndex.cpp =================================================================== --- clang/tools/libclang/CIndex.cpp +++ clang/tools/libclang/CIndex.cpp @@ -6540,7 +6540,7 @@ } case Decl::Using: - return MakeCursorOverloadedDeclRef(cast<UsingDecl>(D), D->getLocation(), + return MakeCursorOverloadedDeclRef(cast<BaseUsingDecl>(D), D->getLocation(), TU); case Decl::UsingShadow: Index: clang/lib/Sema/SemaTemplate.cpp =================================================================== --- clang/lib/Sema/SemaTemplate.cpp +++ clang/lib/Sema/SemaTemplate.cpp @@ -1870,7 +1870,7 @@ 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; } Index: clang/lib/Sema/SemaLookup.cpp =================================================================== --- clang/lib/Sema/SemaLookup.cpp +++ clang/lib/Sema/SemaLookup.cpp @@ -3732,7 +3732,7 @@ // 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. Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -6992,7 +6992,7 @@ : 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. @@ -7016,18 +7016,18 @@ // 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; } @@ -11625,7 +11625,7 @@ /// 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 @@ -11647,35 +11647,36 @@ // 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; @@ -11708,7 +11709,7 @@ !isa<UnresolvedUsingValueDecl>(Target) && DiagnoseClassNameShadow( CurContext, - DeclarationNameInfo(Using->getDeclName(), Using->getLocation()))) + DeclarationNameInfo(BUD->getDeclName(), BUD->getLocation()))) return true; } @@ -11737,7 +11738,7 @@ 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. @@ -11749,13 +11750,13 @@ 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; } @@ -11765,20 +11766,20 @@ // 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; } @@ -11793,8 +11794,7 @@ } /// 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. @@ -11810,19 +11810,20 @@ 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); @@ -11878,7 +11879,7 @@ } // ...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...? Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -3145,7 +3145,7 @@ 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; @@ -3230,8 +3230,8 @@ 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; } @@ -15904,7 +15904,7 @@ 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(); Index: clang/lib/Sema/SemaAccess.cpp =================================================================== --- clang/lib/Sema/SemaAccess.cpp +++ clang/lib/Sema/SemaAccess.cpp @@ -1294,17 +1294,18 @@ 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; } Index: clang/lib/CodeGen/CGDebugInfo.h =================================================================== --- clang/lib/CodeGen/CGDebugInfo.h +++ clang/lib/CodeGen/CGDebugInfo.h @@ -502,6 +502,9 @@ /// 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); Index: clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- clang/lib/CodeGen/CGDebugInfo.cpp +++ clang/lib/CodeGen/CGDebugInfo.cpp @@ -4960,24 +4960,7 @@ } } -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(); @@ -4987,6 +4970,31 @@ } } +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; Index: clang/lib/AST/DeclCXX.cpp =================================================================== --- clang/lib/AST/DeclCXX.cpp +++ clang/lib/AST/DeclCXX.cpp @@ -2981,10 +2981,10 @@ 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(); @@ -2999,12 +2999,12 @@ 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() {} @@ -3023,25 +3023,25 @@ } CXXRecordDecl *ConstructorUsingShadowDecl::getNominatedBaseClass() const { - return getUsingDecl()->getQualifier()->getAsRecordDecl(); + return cast<UsingDecl>(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. @@ -3059,6 +3059,8 @@ S->UsingOrNextShadow = this; } +void UsingDecl::anchor() {} + UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, Index: clang/lib/AST/ASTImporter.cpp =================================================================== --- clang/lib/AST/ASTImporter.cpp +++ clang/lib/AST/ASTImporter.cpp @@ -4620,9 +4620,9 @@ 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) @@ -4630,7 +4630,7 @@ UsingShadowDecl *ToShadow; if (GetImportedOrCreateDecl(ToShadow, D, Importer.getToContext(), DC, Loc, - *ToUsingOrErr, *ToTargetOrErr)) + Name, *ToIntroducerOrErr, *ToTargetOrErr)) return ToShadow; ToShadow->setLexicalDeclContext(LexicalDC); Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -5672,10 +5672,10 @@ 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); Index: clang/include/clang/Basic/DeclNodes.td =================================================================== --- clang/include/clang/Basic/DeclNodes.td +++ clang/include/clang/Basic/DeclNodes.td @@ -71,7 +71,8 @@ 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>; Index: clang/include/clang/AST/DeclCXX.h =================================================================== --- clang/include/clang/AST/DeclCXX.h +++ clang/include/clang/AST/DeclCXX.h @@ -69,6 +69,7 @@ class FunctionTemplateDecl; class IdentifierInfo; class MemberSpecializationInfo; +class BaseUsingDecl; class TemplateDecl; class TemplateParameterList; class UsingDecl; @@ -3153,21 +3154,27 @@ } }; -/// 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; @@ -3194,7 +3201,8 @@ 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: @@ -3202,9 +3210,10 @@ 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); @@ -3242,8 +3251,9 @@ ~(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. @@ -3257,6 +3267,98 @@ } }; +/// 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 shadow constructor declaration introduced into a /// class by a C++11 using-declaration that names a constructor. /// @@ -3285,9 +3387,10 @@ unsigned IsVirtual : 1; ConstructorUsingShadowDecl(ASTContext &C, DeclContext *DC, SourceLocation Loc, - UsingDecl *Using, NamedDecl *Target, + BaseUsingDecl *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)), @@ -3373,7 +3476,7 @@ /// \code /// using someNameSpace::someIdentifier; /// \endcode -class UsingDecl : public NamedDecl, public Mergeable<UsingDecl> { +class UsingDecl : public BaseUsingDecl, public Mergeable<UsingDecl> { /// The source location of the 'using' keyword itself. SourceLocation UsingLocation; @@ -3384,19 +3487,13 @@ /// 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) { + : BaseUsingDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()), + UsingLocation(UL), QualifierLoc(QualifierLoc), + DNLoc(NameInfo.getInfo()) { + setShadowFlag(HasTypenameKeyword); } void anchor() override; @@ -3428,69 +3525,10 @@ bool isAccessDeclaration() const { return UsingLocation.isInvalid(); } /// Return true if the using declaration has 'typename'. - bool hasTypename() const { return FirstUsingShadow.getInt(); } + bool hasTypename() const { return getShadowFlag(); } /// 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); + void setTypename(bool TN) { setShadowFlag(TN); } static UsingDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation UsingL, @@ -3503,8 +3541,12 @@ SourceRange getSourceRange() const override LLVM_READONLY; /// Retrieves the canonical declaration of this declaration. - UsingDecl *getCanonicalDecl() override { return getFirstDecl(); } - const UsingDecl *getCanonicalDecl() const { return getFirstDecl(); } + 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; } Index: clang-tools-extra/clangd/FindTarget.cpp =================================================================== --- clang-tools-extra/clangd/FindTarget.cpp +++ clang-tools-extra/clangd/FindTarget.cpp @@ -181,6 +181,9 @@ for (const UsingShadowDecl *S : UD->shadows()) add(S->getUnderlyingDecl(), Flags); Flags |= Rel::Alias; // continue with the alias. + } else if (const UsingEnumDecl *UED = dyn_cast<UsingEnumDecl>(D)) { + add(UED->getEnumDecl(), Flags); + Flags |= Rel::Alias; // continue with the alias. } else if (const auto *NAD = dyn_cast<NamespaceAliasDecl>(D)) { add(NAD->getUnderlyingDecl(), Flags | Rel::Underlying); Flags |= Rel::Alias; // continue with the alias @@ -193,9 +196,9 @@ } 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();
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits