Index: clangd/ClangdUnit.cpp =================================================================== --- clangd/ClangdUnit.cpp +++ clangd/ClangdUnit.cpp @@ -390,7 +390,6 @@ log("getBeginningOfIdentifier: {0}", Offset.takeError()); return SourceLocation(); } - SourceLocation InputLoc = SourceMgr.getComposedLoc(FID, *Offset); // GetBeginningOfToken(pos) is almost what we want, but does the wrong thing // if the cursor is at the end of the identifier. @@ -401,15 +400,16 @@ // 3) anywhere outside an identifier, we'll get some non-identifier thing. // We can't actually distinguish cases 1 and 3, but returning the original // location is correct for both! + SourceLocation InputLoc = SourceMgr.getComposedLoc(FID, *Offset); if (*Offset == 0) // Case 1 or 3. return SourceMgr.getMacroArgExpandedLocation(InputLoc); - SourceLocation Before = - SourceMgr.getMacroArgExpandedLocation(InputLoc.getLocWithOffset(-1)); + SourceLocation Before = SourceMgr.getComposedLoc(FID, *Offset - 1); + Before = Lexer::GetBeginningOfToken(Before, SourceMgr, AST.getLangOpts()); Token Tok; if (Before.isValid() && !Lexer::getRawToken(Before, Tok, SourceMgr, AST.getLangOpts(), false) && Tok.is(tok::raw_identifier)) - return Before; // Case 2. + return SourceMgr.getMacroArgExpandedLocation(Before); // Case 2. return SourceMgr.getMacroArgExpandedLocation(InputLoc); // Case 1 or 3. } Index: unittests/clangd/ClangdUnitTests.cpp =================================================================== --- unittests/clangd/ClangdUnitTests.cpp +++ unittests/clangd/ClangdUnitTests.cpp @@ -205,8 +205,13 @@ } TEST(ClangdUnitTest, GetBeginningOfIdentifier) { + std::string Preamble = R"cpp( +struct Bar { int func(); }; +#define MACRO(X) void f() { X; } +Bar* bar; + )cpp"; // First ^ is the expected beginning, last is the search position. - for (const char *Text : { + for (std::string Text : std::vector{ "int ^f^oo();", // inside identifier "int ^foo();", // beginning of identifier "int ^foo^();", // end of identifier @@ -214,14 +219,26 @@ "^int foo();", // beginning of file (can't back up) "int ^f0^0();", // after a digit (lexing at N-1 is wrong) "int ^λλ^λ();", // UTF-8 handled properly when backing up + + // identifier in macro arg + "MACRO(bar->^func())", // beginning of identifier + "MACRO(bar->^fun^c())", // inside identifier + "MACRO(bar->^func^())", // end of identifier + "MACRO(^bar->func())", // begin identifier + "MACRO(^bar^->func())", // end identifier + "^MACRO(bar->func())", // beginning of macro name + "^MAC^RO(bar->func())", // inside macro name + "^MACRO^(bar->func())", // end of macro name }) { - Annotations TestCase(Text); + std::string WithPreamble = Preamble + Text; + Annotations TestCase(WithPreamble); auto AST = TestTU::withCode(TestCase.code()).build(); const auto &SourceMgr = AST.getASTContext().getSourceManager(); SourceLocation Actual = getBeginningOfIdentifier( AST, TestCase.points().back(), SourceMgr.getMainFileID()); - Position ActualPos = - offsetToPosition(TestCase.code(), SourceMgr.getFileOffset(Actual)); + Position ActualPos = offsetToPosition( + TestCase.code(), + SourceMgr.getFileOffset(SourceMgr.getSpellingLoc(Actual))); EXPECT_EQ(TestCase.points().front(), ActualPos) << Text; } }