[clang] e596422 - [clang-format] Fix template arguments in macros
via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 16 06:35:46 PDT 2022
Author: sstwcw
Date: 2022-09-16T13:30:46Z
New Revision: e5964223d99a119e4077e3ed1f1322fa2b8cc703
URL: https://github.com/llvm/llvm-project/commit/e5964223d99a119e4077e3ed1f1322fa2b8cc703
DIFF: https://github.com/llvm/llvm-project/commit/e5964223d99a119e4077e3ed1f1322fa2b8cc703.diff
LOG: [clang-format] Fix template arguments in macros
Fixes https://github.com/llvm/llvm-project/issues/57738
old
```
#define FOO(typeName, realClass) \
{ \
#typeName, foo < FooType>(new foo <realClass>(#typeName)) \
}
```
new
```
#define FOO(typeName, realClass) \
{ #typeName, foo<FooType>(new foo<realClass>(#typeName)) }
```
Previously, when an UnwrappedLine began with a hash in a macro
definition, the program incorrectly assumed the line was a preprocessor
directive. It should be stringification.
The rule in spaceRequiredBefore was added in 8b5297117b. Its purpose is
to add a space in an include directive. It also added a space to a
template opener when the line began with a stringification hash. So we
changed it.
Reviewed By: HazardyKnusperkeks, owenpan
Differential Revision: https://reviews.llvm.org/D133954
Added:
Modified:
clang/lib/Format/TokenAnnotator.cpp
clang/lib/Format/TokenAnnotator.h
clang/lib/Format/UnwrappedLineParser.cpp
clang/lib/Format/UnwrappedLineParser.h
clang/unittests/Format/FormatTest.cpp
clang/unittests/Format/TokenAnnotatorTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index d7c2e66ca488..d18adc308efb 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1427,7 +1427,7 @@ class AnnotatingParser {
if (!CurrentToken)
return LT_Invalid;
NonTemplateLess.clear();
- if (CurrentToken->is(tok::hash)) {
+ if (!Line.InMacroBody && CurrentToken->is(tok::hash)) {
// We were not yet allowed to use C++17 optional when this was being
// written. So we used LT_Invalid to mark that the line is not a
// preprocessor directive.
@@ -4241,7 +4241,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return false;
}
if (Right.is(tok::less) && Left.isNot(tok::l_paren) &&
- Line.startsWith(tok::hash)) {
+ Line.Type == LT_ImportStatement) {
return true;
}
if (Right.is(TT_TrailingUnaryOperator))
diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h
index 028ff6d2ccb2..b6f086d76728 100644
--- a/clang/lib/Format/TokenAnnotator.h
+++ b/clang/lib/Format/TokenAnnotator.h
@@ -40,7 +40,7 @@ class AnnotatedLine {
: First(Line.Tokens.front().Tok), Level(Line.Level),
MatchingOpeningBlockLineIndex(Line.MatchingOpeningBlockLineIndex),
MatchingClosingBlockLineIndex(Line.MatchingClosingBlockLineIndex),
- InPPDirective(Line.InPPDirective),
+ InPPDirective(Line.InPPDirective), InMacroBody(Line.InMacroBody),
MustBeDeclaration(Line.MustBeDeclaration), MightBeFunctionDecl(false),
IsMultiVariableDeclStmt(false), Affected(false),
LeadingEmptyLinesAffected(false), ChildrenAffected(false),
@@ -130,6 +130,7 @@ class AnnotatedLine {
size_t MatchingOpeningBlockLineIndex;
size_t MatchingClosingBlockLineIndex;
bool InPPDirective;
+ bool InMacroBody;
bool MustBeDeclaration;
bool MightBeFunctionDecl;
bool IsMultiVariableDeclStmt;
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index fce50d65fc36..4fd4fd4f7c27 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -116,12 +116,14 @@ class ScopedMacroState : public FormatTokenSource {
TokenSource = this;
Line.Level = 0;
Line.InPPDirective = true;
+ // InMacroBody gets set after the `#define x` part.
}
~ScopedMacroState() override {
TokenSource = PreviousTokenSource;
ResetToken = Token;
Line.InPPDirective = false;
+ Line.InMacroBody = false;
Line.Level = PreviousLineLevel;
}
@@ -196,6 +198,7 @@ class ScopedLineState {
Parser.Line = std::make_unique<UnwrappedLine>();
Parser.Line->Level = PreBlockLine->Level;
Parser.Line->InPPDirective = PreBlockLine->InPPDirective;
+ Parser.Line->InMacroBody = PreBlockLine->InMacroBody;
}
~ScopedLineState() {
@@ -1253,6 +1256,7 @@ void UnwrappedLineParser::parsePPDefine() {
Line->Level += PPBranchLevel + 1;
addUnwrappedLine();
++Line->Level;
+ Line->InMacroBody = true;
// Errors during a preprocessor directive can only affect the layout of the
// preprocessor directive, and thus we ignore them. An alternative approach
diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index 7d6c84ecfb0d..ce51d17d5f9c 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -46,6 +46,8 @@ struct UnwrappedLine {
/// Whether this \c UnwrappedLine is part of a preprocessor directive.
bool InPPDirective;
+ /// Whether it is part of a macro body.
+ bool InMacroBody;
bool MustBeDeclaration;
@@ -353,8 +355,8 @@ struct UnwrappedLineNode {
};
inline UnwrappedLine::UnwrappedLine()
- : Level(0), InPPDirective(false), MustBeDeclaration(false),
- MatchingOpeningBlockLineIndex(kInvalidIndex) {}
+ : Level(0), InPPDirective(false), InMacroBody(false),
+ MustBeDeclaration(false), MatchingOpeningBlockLineIndex(kInvalidIndex) {}
} // end namespace format
} // end namespace clang
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 8d9ccfd0cfe1..828948e8f577 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -9864,6 +9864,10 @@ TEST_F(FormatTest, UnderstandsTemplateParameters) {
verifyFormat("Constructor(A... a) : a_(X<A>{std::forward<A>(a)}...) {}");
verifyFormat("< < < < < < < < < < < < < < < < < < < < < < < < < < < < < <");
verifyFormat("some_templated_type<decltype([](int i) { return i; })>");
+
+ verifyFormat("#define FOO(typeName, realClass) \\\n"
+ " { #typeName, foo<FooType>(new foo<realClass>(#typeName)) }",
+ getLLVMStyleWithColumns(60));
}
TEST_F(FormatTest, UnderstandsShiftOperators) {
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp
index a92d44be34f0..1fe8bece722c 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -284,6 +284,17 @@ TEST_F(TokenAnnotatorTest, UnderstandsVariableTemplates) {
EXPECT_TOKEN(Tokens[13], tok::ampamp, TT_BinaryOperator);
}
+TEST_F(TokenAnnotatorTest, UnderstandsTemplatesInMacros) {
+ auto Tokens =
+ annotate("#define FOO(typeName) \\\n"
+ " { #typeName, foo<FooType>(new foo<realClass>(#typeName)) }");
+ ASSERT_EQ(Tokens.size(), 27u) << Tokens;
+ EXPECT_TOKEN(Tokens[11], tok::less, TT_TemplateOpener);
+ EXPECT_TOKEN(Tokens[13], tok::greater, TT_TemplateCloser);
+ EXPECT_TOKEN(Tokens[17], tok::less, TT_TemplateOpener);
+ EXPECT_TOKEN(Tokens[19], tok::greater, TT_TemplateCloser);
+}
+
TEST_F(TokenAnnotatorTest, UnderstandsWhitespaceSensitiveMacros) {
FormatStyle Style = getLLVMStyle();
Style.WhitespaceSensitiveMacros.push_back("FOO");
More information about the cfe-commits
mailing list