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 @@ -281,7 +281,8 @@ llvm::StringRef Name; const MacroInfo *Info; }; -/// Gets the macro at a specified \p Loc. +/// Gets the macro at a specified \p Loc. It must be a spelling location and +/// point to the beginning of identifier. llvm::Optional locateMacroAt(SourceLocation Loc, Preprocessor &PP); 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 @@ -893,10 +893,11 @@ llvm::Optional locateMacroAt(SourceLocation Loc, Preprocessor &PP) { + assert(Loc.isFileID()); const auto &SM = PP.getSourceManager(); const auto &LangOpts = PP.getLangOpts(); Token Result; - if (Lexer::getRawToken(SM.getSpellingLoc(Loc), Result, SM, LangOpts, false)) + if (Lexer::getRawToken(Loc, Result, SM, LangOpts, false)) return None; if (Result.is(tok::raw_identifier)) PP.LookUpIdentifierInfo(Result); @@ -904,14 +905,12 @@ if (!IdentifierInfo || !IdentifierInfo->hadMacroDefinition()) return None; - std::pair DecLoc = SM.getDecomposedExpansionLoc(Loc); // Get the definition just before the searched location so that a macro - // referenced in a '#undef MACRO' can still be found. - SourceLocation BeforeSearchedLocation = - SM.getMacroArgExpandedLocation(SM.getLocForStartOfFile(DecLoc.first) - .getLocWithOffset(DecLoc.second - 1)); - MacroDefinition MacroDef = - PP.getMacroDefinitionAtLoc(IdentifierInfo, BeforeSearchedLocation); + // 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}; return None; diff --git a/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp b/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp --- a/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp +++ b/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp @@ -436,6 +436,20 @@ EXPECT_THAT(*Result, MacroName("MACRO")); } +TEST(SourceCodeTests, WorksAtBeginOfFile) { + Annotations Code("^MACRO"); + TestTU TU = TestTU::withCode(Code.code()); + TU.HeaderCode = "#define MACRO int x;"; + auto AST = TU.build(); + auto CurLoc = sourceLocationInMainFile(AST.getSourceManager(), Code.point()); + ASSERT_TRUE(bool(CurLoc)); + const auto *Id = syntax::spelledIdentifierTouching(*CurLoc, AST.getTokens()); + ASSERT_TRUE(Id); + auto Result = locateMacroAt(Id->location(), AST.getPreprocessor()); + ASSERT_TRUE(Result); + EXPECT_THAT(*Result, MacroName("MACRO")); +} + TEST(SourceCodeTests, IsInsideMainFile){ TestTU TU; TU.HeaderCode = R"cpp(