diff --git a/clang/lib/Format/MacroCallReconstructor.cpp b/clang/lib/Format/MacroCallReconstructor.cpp --- a/clang/lib/Format/MacroCallReconstructor.cpp +++ b/clang/lib/Format/MacroCallReconstructor.cpp @@ -41,10 +41,10 @@ } MacroCallReconstructor::MacroCallReconstructor( - unsigned Level, + unsigned Level, int PPLevel, const llvm::DenseMap> &ActiveExpansions) - : Level(Level), IdToReconstructed(ActiveExpansions) { + : Level(Level), PPLevel(PPLevel), IdToReconstructed(ActiveExpansions) { Result.Tokens.push_back(std::make_unique()); ActiveReconstructedLines.push_back(&Result); } @@ -63,7 +63,7 @@ assert(Result.Tokens.size() == 1 && Result.Tokens.front()->Children.size() == 1); UnwrappedLine Final = - createUnwrappedLine(*Result.Tokens.front()->Children.front(), Level); + createUnwrappedLine(*Result.Tokens.front()->Children.front(), Level, PPLevel); assert(!Final.Tokens.empty()); return Final; } @@ -502,16 +502,17 @@ UnwrappedLine MacroCallReconstructor::createUnwrappedLine(const ReconstructedLine &Line, - int Level) { + int Level, int PPLevel) { UnwrappedLine Result; Result.Level = Level; + Result.PPLevel = PPLevel; for (const auto &N : Line.Tokens) { Result.Tokens.push_back(N->Tok); UnwrappedLineNode &Current = Result.Tokens.back(); for (const auto &Child : N->Children) { if (Child->Tokens.empty()) continue; - Current.Children.push_back(createUnwrappedLine(*Child, Level + 1)); + Current.Children.push_back(createUnwrappedLine(*Child, Level + 1, PPLevel)); } if (Current.Children.size() == 1 && Current.Tok->isOneOf(tok::l_paren, tok::comma)) { diff --git a/clang/lib/Format/Macros.h b/clang/lib/Format/Macros.h --- a/clang/lib/Format/Macros.h +++ b/clang/lib/Format/Macros.h @@ -176,6 +176,7 @@ /// tokens of the spelled macro call. MacroCallReconstructor( unsigned Level, + int PPLevel, const llvm::DenseMap> &ActiveExpansions); @@ -237,7 +238,8 @@ struct ReconstructedLine; void appendToken(FormatToken *Token, ReconstructedLine *L = nullptr); - UnwrappedLine createUnwrappedLine(const ReconstructedLine &Line, int Level); + UnwrappedLine createUnwrappedLine(const ReconstructedLine &Line, int Level, + int PPLevel); void debug(const ReconstructedLine &Line, int Level); ReconstructedLine &parentLine(); ReconstructedLine *currentLine(); @@ -369,6 +371,9 @@ // Level the generated UnwrappedLine will be at. const unsigned Level; + // PPLevel the generated UnwrappedLine will be at. + const int PPLevel; + // Maps from identifier of the macro call to an unwrapped line containing // all tokens of the macro call. const llvm::DenseMap> diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -38,6 +38,7 @@ public: AnnotatedLine(const UnwrappedLine &Line) : First(Line.Tokens.front().Tok), Level(Line.Level), + PPLevel(Line.PPLevel), MatchingOpeningBlockLineIndex(Line.MatchingOpeningBlockLineIndex), MatchingClosingBlockLineIndex(Line.MatchingClosingBlockLineIndex), InPPDirective(Line.InPPDirective), @@ -129,6 +130,7 @@ LineType Type; unsigned Level; + int PPLevel; size_t MatchingOpeningBlockLineIndex; size_t MatchingClosingBlockLineIndex; bool InPPDirective; diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -973,7 +973,9 @@ // Colons from ?: are annotated in parseConditional(). Tok->setType(TT_GotoLabelColon); if (Line.Level > 1 || (!Line.InPPDirective && Line.Level > 0)) - --Line.Level; + if (Line.InPPDirective) + --Line.PPLevel; + --Line.Level; } break; } @@ -1253,6 +1255,8 @@ // Unindent case labels. if (Style.isVerilog() && Keywords.isVerilogEndOfLabel(*Tok) && (Line.Level > 1 || (!Line.InPPDirective && Line.Level > 0))) { + if (Line.InPPDirective) + --Line.PPLevel; --Line.Level; } break; diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -63,9 +63,18 @@ if (Line.InPPDirective || (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash && Line.Type == LT_CommentAbovePPDirective)) { - unsigned IndentWidth = + unsigned PPIndentWidth = (Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth; - Indent = Line.Level * IndentWidth + AdditionalIndent; + + if (Line.InMacroBody && Line.PPLevel > 0 && + static_cast(Line.PPLevel) <= Line.Level) { + + Indent = Line.PPLevel * PPIndentWidth; + Indent += (Line.Level - Line.PPLevel) * Style.IndentWidth; + } else { + Indent = Line.Level * PPIndentWidth; + } + Indent += AdditionalIndent; } else { Indent = getIndent(Line.Level); } @@ -78,9 +87,9 @@ /// Update the indent state given that \p Line indent should be /// skipped. void skipLine(const AnnotatedLine &Line, bool UnknownIndent = false) { - if (Line.Level >= IndentForLevel.size()) - IndentForLevel.resize(Line.Level + 1, UnknownIndent ? -1 : Indent); - } + if (Line.Level >= IndentForLevel.size()) + IndentForLevel.resize(Line.Level + 1, UnknownIndent ? -1 : Indent); +} /// Update the level indent to adapt to the given \p Line. /// diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -44,6 +44,9 @@ /// The indent level of the \c UnwrappedLine. unsigned Level; + /// The preprocessor indent level of the \c UnwrappedLine. + int PPLevel; + /// Whether this \c UnwrappedLine is part of a preprocessor directive. bool InPPDirective; /// Whether this \c UnwrappedLine is part of a pramga directive. diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -109,12 +109,14 @@ ScopedMacroState(UnwrappedLine &Line, FormatTokenSource *&TokenSource, FormatToken *&ResetToken) : Line(Line), TokenSource(TokenSource), ResetToken(ResetToken), - PreviousLineLevel(Line.Level), PreviousTokenSource(TokenSource), - Token(nullptr), PreviousToken(nullptr) { + PreviousLineLevel(Line.Level), PreviousLinePPLevel(Line.PPLevel), + PreviousTokenSource(TokenSource), Token(nullptr), + PreviousToken(nullptr) { FakeEOF.Tok.startToken(); FakeEOF.Tok.setKind(tok::eof); TokenSource = this; Line.Level = 0; + Line.PPLevel = 0; Line.InPPDirective = true; // InMacroBody gets set after the `#define x` part. } @@ -125,6 +127,7 @@ Line.InPPDirective = false; Line.InMacroBody = false; Line.Level = PreviousLineLevel; + Line.PPLevel = PreviousLinePPLevel; } FormatToken *getNextToken() override { @@ -177,6 +180,7 @@ FormatTokenSource *&TokenSource; FormatToken *&ResetToken; unsigned PreviousLineLevel; + unsigned PreviousLinePPLevel; FormatTokenSource *PreviousTokenSource; FormatToken *Token; @@ -197,6 +201,7 @@ PreBlockLine = std::move(Parser.Line); Parser.Line = std::make_unique(); Parser.Line->Level = PreBlockLine->Level; + Parser.Line->PPLevel = PreBlockLine->PPLevel; Parser.Line->InPPDirective = PreBlockLine->InPPDirective; Parser.Line->InMacroBody = PreBlockLine->InMacroBody; } @@ -364,8 +369,10 @@ // the guard) are over-indented by one. if (IncludeGuard == IG_Found) { for (auto &Line : Lines) - if (Line.InPPDirective && Line.Level > 0) + if (Line.InPPDirective && Line.Level > 0) { + --Line.PPLevel; --Line.Level; + } } // Create line with eof token. @@ -590,6 +597,8 @@ if (!SwitchLabelEncountered && (Style.IndentCaseLabels || (Line->InPPDirective && Line->Level == 1))) { + if (Line->InPPDirective) + ++Line->PPLevel; ++Line->Level; } SwitchLabelEncountered = true; @@ -873,6 +882,7 @@ size_t PPStartHash = computePPHash(); const unsigned InitialLevel = Line->Level; + const int InitialPPLevel = Line->PPLevel; if (VerilogHierarchy) { AddLevels += parseVerilogHierarchyHeader(); } else { @@ -916,6 +926,7 @@ if (MacroBlock ? !FormatTok->is(TT_MacroBlockEnd) : !FormatTok->is(tok::r_brace)) { Line->Level = InitialLevel; + Line->PPLevel = InitialPPLevel; FormatTok->setBlockKind(BK_Block); return IfLBrace; } @@ -979,6 +990,7 @@ parseParens(); Line->Level = InitialLevel; + Line->PPLevel = InitialPPLevel; if (FormatTok->is(tok::kw_noexcept)) { // A noexcept in a requires expression. @@ -1269,10 +1281,13 @@ !FormatTok->hasWhitespaceBefore()) { parseParens(); } - if (Style.IndentPPDirectives != FormatStyle::PPDIS_None) + if (Style.IndentPPDirectives != FormatStyle::PPDIS_None) { Line->Level += PPBranchLevel + 1; + Line->PPLevel += PPBranchLevel + 1; + } addUnwrappedLine(); ++Line->Level; + ++Line->PPLevel; Line->InMacroBody = true; // Errors during a preprocessor directive can only affect the layout of the @@ -1292,8 +1307,10 @@ do { nextToken(); } while (!eof()); - if (Style.IndentPPDirectives != FormatStyle::PPDIS_None) + if (Style.IndentPPDirectives != FormatStyle::PPDIS_None) { Line->Level += PPBranchLevel + 1; + Line->PPLevel += PPBranchLevel + 1; + } addUnwrappedLine(); } @@ -3110,8 +3127,12 @@ void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) { nextToken(); unsigned OldLineLevel = Line->Level; - if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0)) + unsigned OldLinePPLevel = Line->PPLevel; + if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0)) { + if (Line->InPPDirective) + --Line->PPLevel; --Line->Level; + } if (LeftAlignLabel) Line->Level = 0; @@ -3140,6 +3161,7 @@ addUnwrappedLine(); } Line->Level = OldLineLevel; + Line->PPLevel = OldLinePPLevel; if (FormatTok->isNot(tok::l_brace)) { parseStructuralElement(); addUnwrappedLine(); @@ -4297,10 +4319,13 @@ // don't know whether this colon is a label or a ternary expression at this // point. auto OrigLevel = Line->Level; + auto OrigPPLevel = Line->PPLevel; auto FirstLine = CurrentLines->size(); - if (Line->Level == 0 || (Line->InPPDirective && Line->Level <= 1)) + if (Line->Level == 0 || (Line->InPPDirective && Line->Level <= 1)) { + if (Line->InPPDirective) + ++Line->PPLevel; ++Line->Level; - else if (!Style.IndentCaseBlocks && Keywords.isVerilogBegin(*FormatTok)) + } else if (!Style.IndentCaseBlocks && Keywords.isVerilogBegin(*FormatTok)) --Line->Level; parseStructuralElement(); // Restore the indentation in both the new line and the line that has the @@ -4308,6 +4333,7 @@ if (CurrentLines->size() > FirstLine) (*CurrentLines)[FirstLine].Level = OrigLevel; Line->Level = OrigLevel; + Line->PPLevel = OrigPPLevel; } LLVM_ATTRIBUTE_UNUSED static void printDebugInfo(const UnwrappedLine &Line, @@ -4632,6 +4658,7 @@ if (Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash && PPBranchLevel > 0) { Line->Level += PPBranchLevel; + Line->PPLevel += PPBranchLevel; } flushComments(isOnNewLine(*FormatTok)); parsePPDirective(); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -5040,6 +5040,157 @@ " int y = 0;\n" "}", style); + + style.IndentPPDirectives = FormatStyle::PPDIS_None; + verifyFormat("#ifdef foo\n" + "#define bar() \\\n" + " if (A) { \\\n" + " B(); \\\n" + " } \\\n" + " C();\n" + "#endif", + style); + verifyFormat("if (emacs) {\n" + "#ifdef is\n" + "#define lit \\\n" + " if (af) { \\\n" + " return duh(); \\\n" + " }\n" + "#endif\n" + "}", + style); + verifyFormat("#if abc\n" + "#ifdef foo\n" + "#define bar() \\\n" + " if (A) { \\\n" + " if (B) { \\\n" + " C(); \\\n" + " } \\\n" + " } \\\n" + " D();\n" + "#endif\n" + "#endif", + style); + verifyFormat("#ifndef foo\n" + "#define foo\n" + "if (emacs) {\n" + "#ifdef is\n" + "#define lit \\\n" + " if (af) { \\\n" + " return duh(); \\\n" + " }\n" + "#endif\n" + "}\n" + "#endif", + style); + #if 1 + style.IndentPPDirectives = FormatStyle::PPDIS_AfterHash; + verifyFormat("#ifdef foo\n" + "# define bar() \\\n" + " if (A) { \\\n" + " B(); \\\n" + " } \\\n" + " C();\n" + "#endif", + style); + verifyFormat("if (emacs) {\n" + "#ifdef is\n" + "# define lit \\\n" + " if (af) { \\\n" + " return duh(); \\\n" + " }\n" + "#endif\n" + "}", + style); + verifyFormat("#if abc\n" + "# ifdef foo\n" + "# define bar() \\\n" + " if (A) { \\\n" + " if (B) { \\\n" + " C(); \\\n" + " } \\\n" + " } \\\n" + " D();\n" + "# endif\n" + "#endif", + style); + verifyFormat("#if abc\n" + "# ifdef foo\n" + "# define bar() \\\n" + " if (A) { \\\n" + " B(); \\\n" + " } \\\n" + " C();\n" + "# endif\n" + "#endif", + style); + verifyFormat("#ifndef foo\n" + "#define foo\n" + "if (emacs) {\n" + "#ifdef is\n" + "# define lit \\\n" + " if (af) { \\\n" + " return duh(); \\\n" + " }\n" + "#endif\n" + "}\n" + "#endif", + style); + + style.IndentPPDirectives = FormatStyle::PPDIS_BeforeHash; + verifyFormat("#ifdef foo\n" + " #define bar() \\\n" + " if (A) { \\\n" + " B(); \\\n" + " } \\\n" + " C();\n" + "#endif", + style); + verifyFormat("if (emacs) {\n" + "#ifdef is\n" + " #define lit \\\n" + " if (af) { \\\n" + " return duh(); \\\n" + " }\n" + "#endif\n" + "}", + style); + verifyFormat("#if abc\n" + " #ifdef foo\n" + " #define bar() \\\n" + " if (A) { \\\n" + " if (B) { \\\n" + " C(); \\\n" + " } \\\n" + " } \\\n" + " D();\n" + " #endif\n" + "#endif", + style); + verifyFormat("#if abc\n" + " #ifdef foo\n" + " #define bar() \\\n" + " if (A) { \\\n" + " B(); \\\n" + " } \\\n" + " C();\n" + " #endif\n" + "#endif", + style); + verifyFormat("#ifndef foo\n" + "#define foo\n" + "if (emacs) {\n" + "#ifdef is\n" + " #define lit \\\n" + " if (af) { \\\n" + " return duh(); \\\n" + " }\n" + "#endif\n" + "}\n" + "#endif", + style); + #endif + } TEST_F(FormatTest, IndentsPPDirectiveInReducedSpace) { diff --git a/clang/unittests/Format/MacroCallReconstructorTest.cpp b/clang/unittests/Format/MacroCallReconstructorTest.cpp --- a/clang/unittests/Format/MacroCallReconstructorTest.cpp +++ b/clang/unittests/Format/MacroCallReconstructorTest.cpp @@ -194,7 +194,7 @@ Expansion Exp(Lex, *Macros); TokenList Call = Exp.expand("X"); - MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); + MacroCallReconstructor Unexp(0, 0, Exp.getUnexpanded()); Unexp.addLine(line(Exp.getTokens())); EXPECT_TRUE(Unexp.finished()); Matcher U(Call, Lex); @@ -206,7 +206,7 @@ Expansion Exp(Lex, *Macros); TokenList Call = Exp.expand("C", {"void f()"}); - MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); + MacroCallReconstructor Unexp(0, 0, Exp.getUnexpanded()); Matcher E(Exp.getTokens(), Lex); Unexp.addLine(line(E.consume("class X {"))); EXPECT_FALSE(Unexp.finished()); @@ -228,7 +228,7 @@ UnexpandedMap Unexpanded = mergeUnexpanded(Exp1.getUnexpanded(), Exp2.getUnexpanded()); - MacroCallReconstructor Unexp(0, Unexpanded); + MacroCallReconstructor Unexp(0, 0, Unexpanded); Matcher E(Exp2.getTokens(), Lex); Unexp.addLine(line(E.consume("a"))); EXPECT_FALSE(Unexp.finished()); @@ -257,7 +257,7 @@ TokenList Call2 = Exp.expand("SEMI"); TokenList Call3 = Exp.expand("SEMI"); - MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); + MacroCallReconstructor Unexp(0, 0, Exp.getUnexpanded()); Matcher E(Exp.getTokens(), Lex); Unexp.addLine(line(E.consume(";"))); EXPECT_TRUE(Unexp.finished()); @@ -296,7 +296,7 @@ // } UnexpandedMap Unexpanded = mergeUnexpanded(Exp1.getUnexpanded(), Exp2.getUnexpanded()); - MacroCallReconstructor Unexp(0, Unexpanded); + MacroCallReconstructor Unexp(0, 0, Unexpanded); Matcher E(Exp2.getTokens(), Lex); Unexp.addLine(line(E.consume("{"))); EXPECT_FALSE(Unexp.finished()); @@ -357,7 +357,7 @@ UnexpandedMap Unexpanded = mergeUnexpanded( Exp1.getUnexpanded(), mergeUnexpanded(Exp2.getUnexpanded(), Exp3.getUnexpanded())); - MacroCallReconstructor Unexp(0, Unexpanded); + MacroCallReconstructor Unexp(0, 0, Unexpanded); Matcher E(Exp3.getTokens(), Lex); Unexp.addLine(line(E.consume("{"))); Unexp.addLine( @@ -409,7 +409,7 @@ Expansion Exp(Lex, *Macros); TokenList Call = Exp.expand("CALL", {std::string("int a"), "int b"}); - MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); + MacroCallReconstructor Unexp(0, 0, Exp.getUnexpanded()); Matcher E(Exp.getTokens(), Lex); Unexp.addLine(line({ E.consume("f([] {"), @@ -430,7 +430,7 @@ Expansion Exp(Lex, *Macros); TokenList Call = Exp.expand("CALL", {std::string("x"), "y"}); - MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); + MacroCallReconstructor Unexp(0, 0, Exp.getUnexpanded()); Matcher E(Exp.getTokens(), Lex); Unexp.addLine(line(E.consume("y + x"))); EXPECT_TRUE(Unexp.finished()); @@ -444,7 +444,7 @@ Expansion Exp(Lex, *Macros); TokenList Call = Exp.expand("ID", {std::string("x; x"), "y"}); - MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); + MacroCallReconstructor Unexp(0, 0, Exp.getUnexpanded()); Matcher E(Exp.getTokens(), Lex); Unexp.addLine(line(E.consume("x;"))); Unexp.addLine(line(E.consume("x y"))); @@ -482,7 +482,7 @@ // 2: } UnexpandedMap Unexpanded = mergeUnexpanded(Exp1.getUnexpanded(), Exp2.getUnexpanded()); - MacroCallReconstructor Unexp(0, Unexpanded); + MacroCallReconstructor Unexp(0, 0, Unexpanded); Matcher E(Exp2.getTokens(), Lex); Unexp.addLine(line(E.consume("{"))); Unexp.addLine(line(E.consume("a * b;"))); @@ -524,7 +524,7 @@ auto Prefix = tokens("int a = []() {"); auto Postfix = tokens("}();"); - MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); + MacroCallReconstructor Unexp(0, 0, Exp.getUnexpanded()); Matcher E(Exp.getTokens(), Lex); Unexp.addLine(line({ Prefix, @@ -560,7 +560,7 @@ Expansion Exp(Lex, *Macros); TokenList Call = Exp.expand("X", {"a", "b", "c"}); - MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); + MacroCallReconstructor Unexp(0, 0, Exp.getUnexpanded()); Unexp.addLine(line(Exp.getTokens())); EXPECT_TRUE(Unexp.finished()); Matcher U(Call, Lex); @@ -573,7 +573,7 @@ Expansion Exp(Lex, *Macros); TokenList Call = Exp.expand("X", {std::string("")}); - MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); + MacroCallReconstructor Unexp(0, 0, Exp.getUnexpanded()); Matcher E(Exp.getTokens(), Lex); auto Semi = tokens(";"); Unexp.addLine(line({E.consume("x"), Semi})); @@ -588,7 +588,7 @@ Expansion Exp(Lex, *Macros); TokenList Call = Exp.expand("CALL", {std::string("{ a;"), "b; }"}); - MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); + MacroCallReconstructor Unexp(0, 0, Exp.getUnexpanded()); Matcher E(Exp.getTokens(), Lex); Unexp.addLine(line({ E.consume("f([]() {"), @@ -613,7 +613,7 @@ Expansion Exp(Lex, *Macros); TokenList Call = Exp.expand("CALL", {std::string("{ a"), "b"}); - MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); + MacroCallReconstructor Unexp(0, 0, Exp.getUnexpanded()); Matcher E(Exp.getTokens(), Lex); auto Semi = tokens(";"); auto SecondLine = tokens("c d;"); @@ -651,7 +651,7 @@ Expansion Exp(Lex, *Macros); TokenList Call = Exp.expand("M", {std::string("{"), "x", ""}); - MacroCallReconstructor Unexp(0, Exp.getUnexpanded()); + MacroCallReconstructor Unexp(0, 0, Exp.getUnexpanded()); Matcher E(Exp.getTokens(), Lex); auto Prefix = tokens("({"); Unexp.addLine(line({