diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -756,8 +756,10 @@ RefsRequest Req; if (Macro) { - // Handle references to macro. - if (auto MacroSID = getSymbolID(Macro->Name, Macro->IdentLoc, SM)) { + // Handle references to macro, we are using DefRange instead of IdentLoc as + // references are collected without #line directive mappings. + if (auto MacroSID = + getSymbolID(Macro->Name, Macro->DefRange.getBegin(), SM)) { // Collect macro references from main file. const auto &IDToRefs = AST.getMacros().MacroRefs; auto Refs = IDToRefs.find(*MacroSID); diff --git a/clang-tools-extra/clangd/unittests/PreambleTests.cpp b/clang-tools-extra/clangd/unittests/PreambleTests.cpp --- a/clang-tools-extra/clangd/unittests/PreambleTests.cpp +++ b/clang-tools-extra/clangd/unittests/PreambleTests.cpp @@ -14,12 +14,14 @@ #include "SourceCode.h" #include "TestFS.h" #include "TestTU.h" +#include "XRefs.h" #include "clang/Format/Format.h" #include "clang/Frontend/PrecompiledPreamble.h" #include "clang/Lex/PreprocessorOptions.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/VirtualFileSystem.h" #include "gmock/gmock.h" @@ -31,6 +33,7 @@ using testing::Contains; using testing::Field; +using testing::Matcher; namespace clang { namespace clangd { @@ -362,6 +365,55 @@ } } +TEST(PreamblePatchTest, RefsToMacros) { + struct { + llvm::StringLiteral Baseline; + llvm::StringLiteral Modified; + } Cases[] = { + // Newly added + { + "", + R"cpp( + #define ^FOO + ^[[FOO]])cpp", + }, + // Moved around + { + "#define FOO", + R"cpp( + #define BAR + #define ^FOO + ^[[FOO]])cpp", + }, + // Ref in preamble section + { + "", + R"cpp( + #define ^FOO + #undef ^FOO)cpp", + }, + }; + + for (const auto &Case : Cases) { + Annotations Modified(Case.Modified); + auto AST = createPatchedAST("", Modified.code()); + ASSERT_TRUE(AST); + + const auto &SM = AST->getSourceManager(); + std::vector> ExpectedLocations; + for (const auto &R : Modified.ranges()) + ExpectedLocations.push_back(Field(&Location::range, R)); + + for (const auto &P : Modified.points()) { + auto *MacroTok = AST->getTokens().spelledTokenAt(SM.getComposedLoc( + SM.getMainFileID(), + llvm::cantFail(positionToOffset(Modified.code(), P)))); + ASSERT_TRUE(MacroTok); + EXPECT_THAT(findReferences(*AST, P, 0).References, + testing::ElementsAreArray(ExpectedLocations)); + } + } +} } // namespace } // namespace clangd } // namespace clang