From de64427ac69aaabd4161c9d9200c2c3a8b27c3a1 Mon Sep 17 00:00:00 2001 From: Alexander Kornienko Date: Mon, 8 Apr 2013 22:16:06 +0000 Subject: [PATCH] Recognize function-like macro usages without semicolon in declaration context. Summary: Preserve line breaks after function-like macro usages without semicolon, e.g.: QQQ(xxx) class X { }; Reviewers: djasper, klimek Reviewed By: djasper CC: cfe-commits Differential Revision: http://llvm-reviews.chandlerc.com/D638 llvm-svn: 179064 --- clang/lib/Format/UnwrappedLineParser.cpp | 25 +++++++++++++++--------- clang/unittests/Format/FormatTest.cpp | 16 +++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 89a391bd1928..12b7f7866fb3 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -71,7 +71,7 @@ public: } private: - bool eof() { return Token.NewlinesBefore > 0 && Token.HasUnescapedNewline; } + bool eof() { return Token.HasUnescapedNewline; } FormatToken createEOF() { FormatToken FormatTok; @@ -262,7 +262,6 @@ void UnwrappedLineParser::parsePPUnknown() { void UnwrappedLineParser::parseStructuralElement() { assert(!FormatTok.Tok.is(tok::l_brace)); - int TokenNumber = 0; switch (FormatTok.Tok.getKind()) { case tok::at: nextToken(); @@ -297,7 +296,6 @@ void UnwrappedLineParser::parseStructuralElement() { return; case tok::kw_inline: nextToken(); - TokenNumber++; if (FormatTok.Tok.is(tok::kw_namespace)) { parseNamespace(); return; @@ -347,7 +345,6 @@ void UnwrappedLineParser::parseStructuralElement() { break; } do { - ++TokenNumber; switch (FormatTok.Tok.getKind()) { case tok::at: nextToken(); @@ -384,9 +381,20 @@ void UnwrappedLineParser::parseStructuralElement() { return; case tok::identifier: nextToken(); - if (TokenNumber == 1 && FormatTok.Tok.is(tok::colon)) { - parseLabel(); - return; + if (Line->Tokens.size() == 1) { + if (FormatTok.Tok.is(tok::colon)) { + parseLabel(); + return; + } + // Recognize function-like macro usages without trailing semicolon in + // declaration context. + if (FormatTok.Tok.is(tok::l_paren)) { + parseParens(); + if (Line->MustBeDeclaration && FormatTok.HasUnescapedNewline) { + addUnwrappedLine(); + return; + } + } } break; case tok::equal: @@ -820,8 +828,7 @@ void UnwrappedLineParser::readToken() { do { FormatTok = Tokens->getNextToken(); while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) && - ((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) || - FormatTok.IsFirst)) { + (FormatTok.HasUnescapedNewline || FormatTok.IsFirst)) { // If there is an unfinished unwrapped line, we flush the preprocessor // directives only after that unwrapped line was finished later. bool SwitchToPreprocessorLines = diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index d5995b2fd91b..3d350208f2e7 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -1339,6 +1339,22 @@ TEST_F(FormatTest, MacroDefinitionsWithIncompleteCode) { "f(STR(this_is_a_string_literal{));"); } +TEST_F(FormatTest, MacroCallsWithoutTrailingSemicolon) { + EXPECT_EQ("INITIALIZE_PASS_BEGIN(ScopDetection, \"polly-detect\")\n" + "INITIALIZE_AG_DEPENDENCY(AliasAnalysis)\n" + "INITIALIZE_PASS_DEPENDENCY(DominatorTree)\n" + "class X {\n" + "};\n" + "INITIALIZE_PASS_END(ScopDetection, \"polly-detect\")\n" + "int *createScopDetectionPass() { return 0; }", + format(" INITIALIZE_PASS_BEGIN(ScopDetection, \"polly-detect\")\n" + " INITIALIZE_AG_DEPENDENCY(AliasAnalysis)\n" + " INITIALIZE_PASS_DEPENDENCY(DominatorTree)\n" + " class X {};\n" + " INITIALIZE_PASS_END(ScopDetection, \"polly-detect\")\n" + " int *createScopDetectionPass() { return 0; }")); +} + TEST_F(FormatTest, IndentPreprocessorDirectivesAtZero) { EXPECT_EQ("{\n {\n#define A\n }\n}", format("{{\n#define A\n}}")); } -- GitLab