[PATCH] D133979: [clangd] XRef functions treat visible class definitions as primary.
Sam McCall via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 15 14:27:49 PDT 2022
sammccall created this revision.
sammccall added a reviewer: kadircet.
Herald added a subscriber: arphaman.
Herald added a project: All.
sammccall requested review of this revision.
Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov.
Herald added a project: clang-tools-extra.
This means go-to-type will take us to a class definition in most cases.
As an exception, if the class is declared in a header and defined in a CC file,
then these are treated as a decl/def pair.
This is (fairly) consistent with how the index behaves, though the index
benefits from aggregation across translation units so does a simpler "main file"
check rather than explicitly "is this a header".
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D133979
Files:
clang-tools-extra/clangd/XRefs.cpp
clang-tools-extra/clangd/unittests/XRefsTests.cpp
Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -568,8 +568,8 @@
)cpp",
R"cpp(// Forward class declaration
- class $decl[[Foo]];
- class $def[[Foo]] {};
+ class Foo;
+ class [[Foo]] {};
F^oo* foo();
)cpp",
@@ -1030,6 +1030,33 @@
}
}
}
+
+TEST(LocateSymbol, TypeForwardDeclaredInHeader) {
+ Annotations Code(R"cpp(
+ class [[X]] {};
+ ^X *x;
+ )cpp");
+
+ TestTU TU;
+ TU.HeaderCode = "class X;";
+ TU.Code = Code.code();
+
+ auto AST = TU.build();
+ auto Index = TU.index();
+ LocatedSymbol S = locateSymbolAt(AST, Code.point(), Index.get()).front();
+ EXPECT_EQ(S.Name, "X");
+ auto Filename = [&](const Location &L) {
+ return llvm::sys::path::filename(L.uri.file());
+ };
+ EXPECT_EQ(Filename(S.PreferredDeclaration), TU.HeaderFilename);
+ EXPECT_EQ(Filename(*S.Definition), TU.Filename);
+
+ S = findType(AST, Code.point()).front();
+ EXPECT_EQ(S.Name, "X");
+ EXPECT_EQ(Filename(S.PreferredDeclaration), TU.HeaderFilename);
+ EXPECT_EQ(Filename(*S.Definition), TU.Filename);
+}
+
TEST(LocateSymbol, ValidSymbolID) {
auto T = Annotations(R"cpp(
#define MACRO(x, y) ((x) + (y))
Index: clang-tools-extra/clangd/XRefs.cpp
===================================================================
--- clang-tools-extra/clangd/XRefs.cpp
+++ clang-tools-extra/clangd/XRefs.cpp
@@ -283,6 +283,30 @@
// instead of failing.
D = llvm::cast<NamedDecl>(D->getCanonicalDecl());
+ // Prefer C++ class definitions over a forward declaration.
+ if (const auto *TD = llvm::dyn_cast<TagDecl>(D)) {
+ if (const auto *Def = TD->getDefinition()) {
+ // Exception: forward decl is exposed in a header, definition is not.
+ // (This exception matches the spirit of our indexing heuristics).
+ if (/*PreferDef=*/[&] {
+ if (Def == TD)
+ return true;
+ const auto &SM = D->getASTContext().getSourceManager();
+ FileID DefFile = SM.getDecomposedExpansionLoc(Def->getLocation()).first;
+ if (DefFile != SM.getMainFileID())
+ return true; // definition is in a header.
+ FileID DeclFile = SM.getDecomposedExpansionLoc(D->getLocation()).first;
+ if (DefFile == DeclFile)
+ return true; // def/decl are equally visible.
+ // We've established that the definition is in the main file, and the
+ // decl is some other header.
+ return isHeaderFile(SM.getFileEntryRefForID(DefFile)->getName(),
+ D->getASTContext().getLangOpts());
+ }())
+ D = Def;
+ }
+ }
+
// Prefer Objective-C class/protocol definitions over the forward declaration.
if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(D))
if (const auto *DefinitionID = ID->getDefinition())
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D133979.460511.patch
Type: text/x-patch
Size: 2974 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20220915/ce4f4749/attachment.bin>
More information about the cfe-commits
mailing list