diff --git a/clang-tools-extra/clangd/SourceCode.h b/clang-tools-extra/clangd/SourceCode.h --- a/clang-tools-extra/clangd/SourceCode.h +++ b/clang-tools-extra/clangd/SourceCode.h @@ -297,7 +297,8 @@ /// aligned to the beginning of an identifier. llvm::Optional locateMacroAt(const syntax::Token &SpelledTok, Preprocessor &PP, - const syntax::TokenBuffer &TB); + const syntax::TokenBuffer &TB, + bool UseLineDirectives = true); /// Infers whether this is a header from the FileName and LangOpts (if /// presents). diff --git a/clang-tools-extra/clangd/SourceCode.cpp b/clang-tools-extra/clangd/SourceCode.cpp --- a/clang-tools-extra/clangd/SourceCode.cpp +++ b/clang-tools-extra/clangd/SourceCode.cpp @@ -952,7 +952,8 @@ llvm::Optional locateMacroAt(const syntax::Token &SpelledTok, Preprocessor &PP, - const syntax::TokenBuffer &TB) { + const syntax::TokenBuffer &TB, + bool UseLineDirectives) { SourceLocation Loc = SpelledTok.location(); assert(Loc.isFileID()); const auto &SM = PP.getSourceManager(); @@ -971,6 +972,9 @@ return None; SourceRange DefRange(MI->getDefinitionLoc(), MI->getDefinitionEndLoc()); + if (!UseLineDirectives) + return DefinedMacro{IdentifierInfo->getName(), + CharSourceRange::getTokenRange(DefRange)}; // Macro definitions could be injected through preamble patch. These contain // line directives to hint their original location in main file. 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 @@ -751,7 +751,7 @@ if (const auto *IdentifierAtCursor = syntax::spelledIdentifierTouching(*CurLoc, AST.getTokens())) { Macro = locateMacroAt(*IdentifierAtCursor, AST.getPreprocessor(), - AST.getTokens()); + AST.getTokens(), false); } RefsRequest Req; 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 @@ -10,13 +10,16 @@ #include "Compiler.h" #include "Headers.h" #include "Preamble.h" +#include "SourceCode.h" #include "TestFS.h" #include "TestTU.h" +#include "XRefs.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" @@ -28,6 +31,7 @@ using testing::Contains; using testing::Field; +using testing::Matcher; namespace clang { namespace clangd { @@ -338,6 +342,48 @@ EXPECT_THAT(FoundMacro->Name, "FOO"); } +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", + }, + }; + + 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