Mercurial > hg > CbC > CbC_llvm
diff clang-tools-extra/clangd/FindTarget.cpp @ 236:c4bab56944e8 llvm-original
LLVM 16
author | kono |
---|---|
date | Wed, 09 Nov 2022 17:45:10 +0900 |
parents | 5f17cb93ff66 |
children | 1f2b6ac9f198 |
line wrap: on
line diff
--- a/clang-tools-extra/clangd/FindTarget.cpp Wed Jul 21 10:27:27 2021 +0900 +++ b/clang-tools-extra/clangd/FindTarget.cpp Wed Nov 09 17:45:10 2022 +0900 @@ -31,15 +31,17 @@ #include "clang/AST/TypeLocVisitor.h" #include "clang/AST/TypeVisitor.h" #include "clang/Basic/LangOptions.h" -#include "clang/Basic/OperatorKinds.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include <iterator> +#include <string> #include <utility> #include <vector> @@ -94,6 +96,16 @@ return nullptr; } +// Returns true if the `TypedefNameDecl` should not be reported. +bool shouldSkipTypedef(const TypedefNameDecl *TD) { + // These should be treated as keywords rather than decls - the typedef is an + // odd implementation detail. + if (TD == TD->getASTContext().getObjCInstanceTypeDecl() || + TD == TD->getASTContext().getObjCIdDecl()) + return true; + return false; +} + // TargetFinder locates the entities that an AST node refers to. // // Typically this is (possibly) one declaration and (possibly) one type, but @@ -115,11 +127,6 @@ // template<class X> using pvec = vector<x*>; pvec<int> x; // There's no Decl `pvec<int>`, we must choose `pvec<X>` or `vector<int*>` // and both are lossy. We must know upfront what the caller ultimately wants. -// -// FIXME: improve common dependent scope using name lookup in primary templates. -// We currently handle several dependent constructs, but some others remain to -// be handled: -// - UnresolvedUsingTypenameDecl struct TargetFinder { using RelSet = DeclRelationSet; using Rel = DeclRelation; @@ -182,8 +189,8 @@ 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. + // UsingEnumDecl is not an alias at all, just a reference. + D = UED->getEnumDecl(); } else if (const auto *NAD = dyn_cast<NamespaceAliasDecl>(D)) { add(NAD->getUnderlyingDecl(), Flags | Rel::Underlying); Flags |= Rel::Alias; // continue with the alias @@ -195,10 +202,17 @@ } } Flags |= Rel::Alias; // continue with the alias + } else if (isa<UnresolvedUsingTypenameDecl>(D)) { + // FIXME: improve common dependent scope using name lookup in primary + // templates. + Flags |= Rel::Alias; } else if (const UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) { - // Include the Introducing decl, but don't traverse it. This may end up - // including *all* shadows, which we don't want. - report(USD->getIntroducer(), Flags | Rel::Alias); + // Include the introducing UsingDecl, but don't traverse it. This may end + // up including *all* shadows, which we don't want. + // Don't apply this logic to UsingEnumDecl, which can't easily be + // conflated with the aliases it introduces. + if (llvm::isa<UsingDecl>(USD->getIntroducer())) + report(USD->getIntroducer(), Flags | Rel::Alias); // Shadow decls are synthetic and not themselves interesting. // Record the underlying decl instead, if allowed. D = USD->getTargetDecl(); @@ -354,6 +368,10 @@ Outer.add(ET->desugar(), Flags); } + void VisitUsingType(const UsingType *ET) { + Outer.add(ET->getFoundDecl(), Flags); + } + void VisitInjectedClassNameType(const InjectedClassNameType *ICNT) { Outer.add(ICNT->getDecl(), Flags); } @@ -364,15 +382,21 @@ void VisitDeducedType(const DeducedType *DT) { // FIXME: In practice this doesn't work: the AutoType you find inside // TypeLoc never has a deduced type. https://llvm.org/PR42914 - Outer.add(DT->getDeducedType(), Flags | Rel::Underlying); + Outer.add(DT->getDeducedType(), Flags); + } + void VisitUnresolvedUsingType(const UnresolvedUsingType *UUT) { + Outer.add(UUT->getDecl(), Flags); } void VisitDeducedTemplateSpecializationType( const DeducedTemplateSpecializationType *DTST) { + if (const auto *USD = DTST->getTemplateName().getAsUsingShadowDecl()) + Outer.add(USD, Flags); + // FIXME: This is a workaround for https://llvm.org/PR42914, // which is causing DTST->getDeducedType() to be empty. We // fall back to the template pattern and miss the instantiation // even when it's known in principle. Once that bug is fixed, - // this method can be removed (the existing handling in + // the following code can be removed (the existing handling in // VisitDeducedType() is sufficient). if (auto *TD = DTST->getTemplateName().getAsTemplateDecl()) Outer.add(TD->getTemplatedDecl(), Flags | Rel::TemplatePattern); @@ -395,12 +419,17 @@ } } void VisitTypedefType(const TypedefType *TT) { + if (shouldSkipTypedef(TT->getDecl())) + return; Outer.add(TT->getDecl(), Flags); } void VisitTemplateSpecializationType(const TemplateSpecializationType *TST) { // Have to handle these case-by-case. + if (const auto *UTN = TST->getTemplateName().getAsUsingShadowDecl()) + Outer.add(UTN, Flags); + // templated type aliases: there's no specialized/instantiated using // decl to point to. So try to find a decl for the underlying type // (after substitution), and failing that point to the (templated) using @@ -428,21 +457,16 @@ Outer.add(TD->getTemplatedDecl(), Flags | Rel::TemplatePattern); } } + void + VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *STTPT) { + Outer.add(STTPT->getReplacementType(), Flags); + } void VisitTemplateTypeParmType(const TemplateTypeParmType *TTPT) { Outer.add(TTPT->getDecl(), Flags); } void VisitObjCInterfaceType(const ObjCInterfaceType *OIT) { Outer.add(OIT->getDecl(), Flags); } - void VisitObjCObjectType(const ObjCObjectType *OOT) { - // Make all of the protocols targets since there's no child nodes for - // protocols. This isn't needed for the base type, which *does* have a - // child `ObjCInterfaceTypeLoc`. This structure is a hack, but it works - // well for go-to-definition. - unsigned NumProtocols = OOT->getNumProtocols(); - for (unsigned I = 0; I < NumProtocols; I++) - Outer.add(OOT->getProtocol(I), Flags); - } }; Visitor(*this, Flags).Visit(T.getTypePtr()); } @@ -495,9 +519,13 @@ // DeclRefExpr). if (Arg.getKind() == TemplateArgument::Template || Arg.getKind() == TemplateArgument::TemplateExpansion) { - if (TemplateDecl *TD = Arg.getAsTemplate().getAsTemplateDecl()) { + if (TemplateDecl *TD = + Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) { report(TD, Flags); } + if (const auto *USD = + Arg.getAsTemplateOrTemplatePattern().getAsUsingShadowDecl()) + add(USD, Flags); } } }; @@ -527,6 +555,8 @@ Finder.add(TAL->getArgument(), Flags); else if (const CXXBaseSpecifier *CBS = N.get<CXXBaseSpecifier>()) Finder.add(CBS->getTypeSourceInfo()->getType(), Flags); + else if (const ObjCProtocolLoc *PL = N.get<ObjCProtocolLoc>()) + Finder.add(PL->getProtocol(), Flags); return Finder.takeDecls(); } @@ -599,6 +629,12 @@ DeclRelation::Underlying, Resolver)}); } + void VisitUsingEnumDecl(const UsingEnumDecl *D) { + // "using enum ns::E" is a non-declaration reference. + // The reference is covered by the embedded typeloc. + // Don't use the default VisitNamedDecl, which would report a declaration. + } + void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { // For namespace alias, "namespace Foo = Target;", we add two references. // Add a declaration reference for Foo. @@ -649,25 +685,7 @@ {OMD}}); } - void visitProtocolList( - llvm::iterator_range<ObjCProtocolList::iterator> Protocols, - llvm::iterator_range<const SourceLocation *> Locations) { - for (const auto &P : llvm::zip(Protocols, Locations)) { - Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), - std::get<1>(P), - /*IsDecl=*/false, - {std::get<0>(P)}}); - } - } - - void VisitObjCInterfaceDecl(const ObjCInterfaceDecl *OID) { - if (OID->isThisDeclarationADefinition()) - visitProtocolList(OID->protocols(), OID->protocol_locs()); - Base::VisitObjCInterfaceDecl(OID); // Visit the interface's name. - } - void VisitObjCCategoryDecl(const ObjCCategoryDecl *OCD) { - visitProtocolList(OCD->protocols(), OCD->protocol_locs()); // getLocation is the extended class's location, not the category's. Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), OCD->getLocation(), @@ -689,12 +707,6 @@ /*IsDecl=*/true, {OCID->getCategoryDecl()}}); } - - void VisitObjCProtocolDecl(const ObjCProtocolDecl *OPD) { - if (OPD->isThisDeclarationADefinition()) - visitProtocolList(OPD->protocols(), OPD->protocol_locs()); - Base::VisitObjCProtocolDecl(OPD); // Visit the protocol's name. - } }; Visitor V{Resolver}; @@ -842,6 +854,13 @@ } } + void VisitUsingTypeLoc(UsingTypeLoc L) { + Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), + L.getLocalSourceRange().getBegin(), + /*IsDecl=*/false, + {L.getFoundDecl()}}); + } + void VisitTagTypeLoc(TagTypeLoc L) { Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), L.getNameLoc(), @@ -903,6 +922,8 @@ } void VisitTypedefTypeLoc(TypedefTypeLoc L) { + if (shouldSkipTypedef(L.getTypedefNameDecl())) + return; Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), L.getNameLoc(), /*IsDecl=*/false, @@ -915,16 +936,6 @@ /*IsDecl=*/false, {L.getIFaceDecl()}}); } - - void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc L) { - unsigned NumProtocols = L.getNumProtocols(); - for (unsigned I = 0; I < NumProtocols; I++) { - Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(), - L.getProtocolLoc(I), - /*IsDecl=*/false, - {L.getProtocol(I)}}); - } - } }; Visitor V{Resolver}; @@ -952,7 +963,10 @@ // ElaboratedTypeLoc will reports information for its inner type loc. // Otherwise we loose information about inner types loc's qualifier. TypeLoc Inner = L.getNamedTypeLoc().getUnqualifiedLoc(); - TypeLocsToSkip.insert(Inner.getBeginLoc()); + if (L.getBeginLoc() == Inner.getBeginLoc()) + return RecursiveASTVisitor::TraverseTypeLoc(Inner); + else + TypeLocsToSkip.insert(Inner.getBeginLoc()); return RecursiveASTVisitor::TraverseElaboratedTypeLoc(L); } @@ -1020,6 +1034,11 @@ return RecursiveASTVisitor::TraverseNestedNameSpecifierLoc(L); } + bool TraverseObjCProtocolLoc(ObjCProtocolLoc ProtocolLoc) { + visitNode(DynTypedNode::create(ProtocolLoc)); + return true; + } + bool TraverseConstructorInitializer(CXXCtorInitializer *Init) { visitNode(DynTypedNode::create(*Init)); return RecursiveASTVisitor::TraverseConstructorInitializer(Init); @@ -1065,6 +1084,12 @@ {CCI->getAnyMember()}}}; } } + if (const ObjCProtocolLoc *PL = N.get<ObjCProtocolLoc>()) + return {ReferenceLoc{NestedNameSpecifierLoc(), + PL->getLocation(), + /*IsDecl=*/false, + {PL->getProtocol()}}}; + // We do not have location information for other nodes (QualType, etc) return {}; } @@ -1143,14 +1168,13 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, ReferenceLoc R) { // note we cannot print R.NameLoc without a source manager. OS << "targets = {"; - bool First = true; + llvm::SmallVector<std::string> Targets; for (const NamedDecl *T : R.Targets) { - if (!First) - OS << ", "; - else - First = false; - OS << printQualifiedName(*T) << printTemplateSpecializationArgs(*T); + llvm::raw_string_ostream Target(Targets.emplace_back()); + Target << printQualifiedName(*T) << printTemplateSpecializationArgs(*T); } + llvm::sort(Targets); + OS << llvm::join(Targets, ", "); OS << "}"; if (R.Qualifier) { OS << ", qualifier = '";