Author: Nathan Ridge Date: 2020-12-13T18:33:33-05:00 New Revision: fef242c32e833b84e8b46bd56a28c01c5f9aa65d
URL: https://github.com/llvm/llvm-project/commit/fef242c32e833b84e8b46bd56a28c01c5f9aa65d DIFF: https://github.com/llvm/llvm-project/commit/fef242c32e833b84e8b46bd56a28c01c5f9aa65d.diff LOG: [clangd] Fix locateMacroAt() for macro definition outside preamble Fixes https://github.com/clangd/clangd/issues/577 Differential Revision: https://reviews.llvm.org/D91025 Added: Modified: clang-tools-extra/clangd/SourceCode.cpp clang-tools-extra/clangd/unittests/XRefsTests.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clangd/SourceCode.cpp b/clang-tools-extra/clangd/SourceCode.cpp index 54248386d7b4..c0ccf2152750 100644 --- a/clang-tools-extra/clangd/SourceCode.cpp +++ b/clang-tools-extra/clangd/SourceCode.cpp @@ -975,17 +975,30 @@ llvm::Optional<DefinedMacro> locateMacroAt(const syntax::Token &SpelledTok, if (!IdentifierInfo || !IdentifierInfo->hadMacroDefinition()) return None; - // Get the definition just before the searched location so that a macro - // referenced in a '#undef MACRO' can still be found. Note that we only do - // that if Loc is not pointing at start of file. - if (SM.getLocForStartOfFile(SM.getFileID(Loc)) != Loc) - Loc = Loc.getLocWithOffset(-1); - MacroDefinition MacroDef = PP.getMacroDefinitionAtLoc(IdentifierInfo, Loc); - if (auto *MI = MacroDef.getMacroInfo()) - return DefinedMacro{ - IdentifierInfo->getName(), MI, - translatePreamblePatchLocation(MI->getDefinitionLoc(), SM)}; - return None; + // We need to take special case to handle #define and #undef. + // Preprocessor::getMacroDefinitionAtLoc() only considers a macro + // definition to be in scope *after* the location of the macro name in a + // #define that introduces it, and *before* the location of the macro name + // in an #undef that undefines it. To handle these cases, we check for + // the macro being in scope either just after or just before the location + // of the token. In getting the location before, we also take care to check + // for start-of-file. + FileID FID = SM.getFileID(Loc); + assert(Loc != SM.getLocForEndOfFile(FID)); + SourceLocation JustAfterToken = Loc.getLocWithOffset(1); + auto *MacroInfo = + PP.getMacroDefinitionAtLoc(IdentifierInfo, JustAfterToken).getMacroInfo(); + if (!MacroInfo && SM.getLocForStartOfFile(FID) != Loc) { + SourceLocation JustBeforeToken = Loc.getLocWithOffset(-1); + MacroInfo = PP.getMacroDefinitionAtLoc(IdentifierInfo, JustBeforeToken) + .getMacroInfo(); + } + if (!MacroInfo) { + return None; + } + return DefinedMacro{ + IdentifierInfo->getName(), MacroInfo, + translatePreamblePatchLocation(MacroInfo->getDefinitionLoc(), SM)}; } llvm::Expected<std::string> Edit::apply() const { diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp index c3c87bd628bd..5b0ceb1cc200 100644 --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -1624,6 +1624,14 @@ TEST(FindReferences, WithinAST) { } )cpp", + R"cpp(// Macro outside preamble + int breakPreamble; + #define [[MA^CRO]](X) (X+1) + void test() { + int x = [[MACRO]]([[MACRO]](1)); + } + )cpp", + R"cpp( int [[v^ar]] = 0; void foo(int s = [[var]]); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits