forked from OSchip/llvm-project
[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
This commit is contained in:
parent
2183fe2160
commit
e5964223d9
|
@ -1427,7 +1427,7 @@ public:
|
|||
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))
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
: 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 @@ public:
|
|||
size_t MatchingOpeningBlockLineIndex;
|
||||
size_t MatchingClosingBlockLineIndex;
|
||||
bool InPPDirective;
|
||||
bool InMacroBody;
|
||||
bool MustBeDeclaration;
|
||||
bool MightBeFunctionDecl;
|
||||
bool IsMultiVariableDeclStmt;
|
||||
|
|
|
@ -116,12 +116,14 @@ public:
|
|||
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 @@ public:
|
|||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Reference in New Issue