[clang-format] Don't use PPIndentWidth inside multi-line macros

Differential Revision: https://reviews.llvm.org/D137181
This commit is contained in:
Noah Goldstein
2022-11-19 01:06:37 -08:00
committed by Owen Pan
parent c903136f19
commit 92bccf5d3d
6 changed files with 234 additions and 8 deletions

View File

@@ -5095,8 +5095,9 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
}
void TokenAnnotator::printDebugInfo(const AnnotatedLine &Line) const {
llvm::errs() << "AnnotatedTokens(L=" << Line.Level << ", T=" << Line.Type
<< ", C=" << Line.IsContinuation << "):\n";
llvm::errs() << "AnnotatedTokens(L=" << Line.Level << ", P=" << Line.PPLevel
<< ", T=" << Line.Type << ", C=" << Line.IsContinuation
<< "):\n";
const FormatToken *Tok = Line.First;
while (Tok) {
llvm::errs() << " M=" << Tok->MustBreakBefore

View File

@@ -38,6 +38,7 @@ class AnnotatedLine {
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 @@ public:
LineType Type;
unsigned Level;
unsigned PPLevel;
size_t MatchingOpeningBlockLineIndex;
size_t MatchingClosingBlockLineIndex;
bool InPPDirective;

View File

@@ -60,12 +60,17 @@ public:
// Update the indent level cache size so that we can rely on it
// having the right size in adjustToUnmodifiedline.
skipLine(Line, /*UnknownIndent=*/true);
if (Line.InPPDirective ||
(Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
Line.Type == LT_CommentAbovePPDirective)) {
unsigned IndentWidth =
if (Style.IndentPPDirectives != FormatStyle::PPDIS_None &&
(Line.InPPDirective ||
(Style.IndentPPDirectives == FormatStyle::PPDIS_BeforeHash &&
Line.Type == LT_CommentAbovePPDirective))) {
unsigned PPIndentWidth =
(Style.PPIndentWidth >= 0) ? Style.PPIndentWidth : Style.IndentWidth;
Indent = Line.Level * IndentWidth + AdditionalIndent;
Indent = Line.InMacroBody
? Line.PPLevel * PPIndentWidth +
(Line.Level - Line.PPLevel) * Style.IndentWidth
: Line.Level * PPIndentWidth;
Indent += AdditionalIndent;
} else {
Indent = getIndent(Line.Level);
}

View File

@@ -197,6 +197,7 @@ public:
PreBlockLine = std::move(Parser.Line);
Parser.Line = std::make_unique<UnwrappedLine>();
Parser.Line->Level = PreBlockLine->Level;
Parser.Line->PPLevel = PreBlockLine->PPLevel;
Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
Parser.Line->InMacroBody = PreBlockLine->InMacroBody;
}
@@ -833,6 +834,9 @@ bool UnwrappedLineParser::mightFitOnOneLine(
delete SavedToken.Tok;
}
// If these change PPLevel needs to be used for get correct indentation.
assert(!Line.InMacroBody);
assert(!Line.InPPDirective);
return Line.Level * Style.IndentWidth + Length <= ColumnLimit;
}
@@ -1270,6 +1274,9 @@ void UnwrappedLineParser::parsePPDefine() {
Line->Level += PPBranchLevel + 1;
addUnwrappedLine();
++Line->Level;
Line->PPLevel = PPBranchLevel + (IncludeGuard == IG_Defined ? 0 : 1);
assert((int)Line->PPLevel >= 0);
Line->InMacroBody = true;
// Errors during a preprocessor directive can only affect the layout of the

View File

@@ -44,6 +44,10 @@ struct UnwrappedLine {
/// The indent level of the \c UnwrappedLine.
unsigned Level;
/// The \c PPBranchLevel (adjusted for header guards) if this line is a
/// \c InMacroBody line, and 0 otherwise.
unsigned PPLevel;
/// Whether this \c UnwrappedLine is part of a preprocessor directive.
bool InPPDirective;
/// Whether this \c UnwrappedLine is part of a pramga directive.
@@ -357,7 +361,7 @@ struct UnwrappedLineNode {
};
inline UnwrappedLine::UnwrappedLine()
: Level(0), InPPDirective(false), InPragmaDirective(false),
: Level(0), PPLevel(0), InPPDirective(false), InPragmaDirective(false),
InMacroBody(false), MustBeDeclaration(false),
MatchingOpeningBlockLineIndex(kInvalidIndex) {}

View File

@@ -5059,6 +5059,213 @@ TEST_F(FormatTest, IndentsPPDirectiveWithPPIndentWidth) {
" 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);
verifyFormat("#if 1\n"
"#define X \\\n"
" { \\\n"
" x; \\\n"
" x; \\\n"
" }\n"
"#endif",
style);
verifyFormat("#define X \\\n"
" { \\\n"
" x; \\\n"
" x; \\\n"
" }",
style);
style.PPIndentWidth = 2;
verifyFormat("#ifdef foo\n"
"#define bar() \\\n"
" if (A) { \\\n"
" B(); \\\n"
" } \\\n"
" C();\n"
"#endif",
style);
style.IndentWidth = 8;
verifyFormat("#ifdef foo\n"
"#define bar() \\\n"
" if (A) { \\\n"
" B(); \\\n"
" } \\\n"
" C();\n"
"#endif",
style);
style.IndentWidth = 1;
style.PPIndentWidth = 4;
verifyFormat("#if 1\n"
"#define X \\\n"
" { \\\n"
" x; \\\n"
" x; \\\n"
" }\n"
"#endif",
style);
verifyFormat("#define X \\\n"
" { \\\n"
" x; \\\n"
" x; \\\n"
" }",
style);
style.IndentWidth = 4;
style.PPIndentWidth = 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 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);
verifyFormat("#define X \\\n"
" { \\\n"
" x; \\\n"
" x; \\\n"
" }",
style);
style.PPIndentWidth = 2;
style.IndentWidth = 8;
verifyFormat("#ifdef foo\n"
"# define bar() \\\n"
" if (A) { \\\n"
" B(); \\\n"
" } \\\n"
" C();\n"
"#endif",
style);
style.PPIndentWidth = 4;
style.IndentWidth = 1;
verifyFormat("#define X \\\n"
" { \\\n"
" x; \\\n"
" x; \\\n"
" }",
style);
style.IndentWidth = 4;
style.PPIndentWidth = 1;
style.IndentPPDirectives = FormatStyle::PPDIS_BeforeHash;
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"
" B(); \\\n"
" } \\\n"
" C();\n"
" #endif\n"
"#endif",
style);
verifyFormat("#if 1\n"
" #define X \\\n"
" { \\\n"
" x; \\\n"
" x; \\\n"
" }\n"
"#endif",
style);
style.PPIndentWidth = 2;
verifyFormat("#ifdef foo\n"
" #define bar() \\\n"
" if (A) { \\\n"
" B(); \\\n"
" } \\\n"
" C();\n"
"#endif",
style);
style.PPIndentWidth = 4;
style.IndentWidth = 1;
verifyFormat("#if 1\n"
" #define X \\\n"
" { \\\n"
" x; \\\n"
" x; \\\n"
" }\n"
"#endif",
style);
}
TEST_F(FormatTest, IndentsPPDirectiveInReducedSpace) {