diff --git a/clang/lib/Format/MacroExpander.cpp b/clang/lib/Format/MacroExpander.cpp index fd2a16894d643..ba2992889e674 100644 --- a/clang/lib/Format/MacroExpander.cpp +++ b/clang/lib/Format/MacroExpander.cpp @@ -233,6 +233,10 @@ MacroExpander::expand(FormatToken *ID, if (Result.size() > 1) { ++Result[0]->MacroCtx->StartOfExpansion; ++Result[Result.size() - 2]->MacroCtx->EndOfExpansion; + } else { + // If the macro expansion is empty, mark the start and end. + Result[0]->MacroCtx->StartOfExpansion = 1; + Result[0]->MacroCtx->EndOfExpansion = 1; } return Result; } diff --git a/clang/unittests/Format/MacroCallReconstructorTest.cpp b/clang/unittests/Format/MacroCallReconstructorTest.cpp index b4ee8d0e37efa..b58241fd8c4e8 100644 --- a/clang/unittests/Format/MacroCallReconstructorTest.cpp +++ b/clang/unittests/Format/MacroCallReconstructorTest.cpp @@ -65,7 +65,9 @@ class Expansion { } Unexpanded[ID] = std::move(UnexpandedLine); - auto Expanded = uneof(Macros.expand(ID, Args)); + auto Expanded = Macros.expand(ID, Args); + if (Expanded.size() > 1) + Expanded = uneof(Expanded); Tokens.append(Expanded.begin(), Expanded.end()); TokenList UnexpandedTokens; @@ -217,6 +219,31 @@ TEST_F(MacroCallReconstructorTest, Identifier) { EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(line(U.consume("X")))); } +TEST_F(MacroCallReconstructorTest, EmptyDefinition) { + auto Macros = createExpander({"X"}); + Expansion Exp(Lex, *Macros); + TokenList Call = Exp.expand("X"); + + MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); + Unexp.addLine(line(Exp.getTokens())); + EXPECT_TRUE(Unexp.finished()); + Matcher U(Call, Lex); + EXPECT_THAT(std::move(Unexp).takeResult(), matchesLine(line(U.consume("X")))); +} + +TEST_F(MacroCallReconstructorTest, EmptyExpansion) { + auto Macros = createExpander({"A(x)=x"}); + Expansion Exp(Lex, *Macros); + TokenList Call = Exp.expand("A", {""}); + + MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); + Unexp.addLine(line(Exp.getTokens())); + EXPECT_TRUE(Unexp.finished()); + Matcher U(Call, Lex); + EXPECT_THAT(std::move(Unexp).takeResult(), + matchesLine(line(U.consume("A()")))); +} + TEST_F(MacroCallReconstructorTest, NestedLineWithinCall) { auto Macros = createExpander({"C(a)=class X { a; };"}); Expansion Exp(Lex, *Macros);