From: Daniel Jasper Date: Wed, 6 May 2015 14:03:02 +0000 (+0000) Subject: clang-format: Accept slightly more record declarations. X-Git-Tag: llvmorg-3.7.0-rc1~5286 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=04785d04883b30b07899cb280829976fb5754497;p=platform%2Fupstream%2Fllvm.git clang-format: Accept slightly more record declarations. This fixes llvm.org/PR23397. llvm-svn: 236599 --- diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 41c7fd1..9461911 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -1531,38 +1531,40 @@ void UnwrappedLineParser::parseJavaEnumBody() { void UnwrappedLineParser::parseRecord() { const FormatToken &InitialToken = *FormatTok; nextToken(); - if (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::kw___attribute, - tok::kw___declspec, tok::kw_alignas)) { + + + // The actual identifier can be a nested name specifier, and in macros + // it is often token-pasted. + while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::hashhash, + tok::kw___attribute, tok::kw___declspec, + tok::kw_alignas) || + ((Style.Language == FormatStyle::LK_Java || + Style.Language == FormatStyle::LK_JavaScript) && + FormatTok->isOneOf(tok::period, tok::comma))) { + bool IsNonMacroIdentifier = + FormatTok->is(tok::identifier) && + FormatTok->TokenText != FormatTok->TokenText.upper(); nextToken(); // We can have macros or attributes in between 'class' and the class name. - if (FormatTok->Tok.is(tok::l_paren)) { + if (!IsNonMacroIdentifier && FormatTok->Tok.is(tok::l_paren)) parseParens(); - } - // The actual identifier can be a nested name specifier, and in macros - // it is often token-pasted. - while (FormatTok->is(tok::identifier) || FormatTok->is(tok::coloncolon) || - FormatTok->is(tok::hashhash) || - ((Style.Language == FormatStyle::LK_Java || - Style.Language == FormatStyle::LK_JavaScript) && - FormatTok->isOneOf(tok::period, tok::comma))) - nextToken(); + } - // Note that parsing away template declarations here leads to incorrectly - // accepting function declarations as record declarations. - // In general, we cannot solve this problem. Consider: - // class A B() {} - // which can be a function definition or a class definition when B() is a - // macro. If we find enough real-world cases where this is a problem, we - // can parse for the 'template' keyword in the beginning of the statement, - // and thus rule out the record production in case there is no template - // (this would still leave us with an ambiguity between template function - // and class declarations). - if (FormatTok->Tok.is(tok::colon) || FormatTok->Tok.is(tok::less)) { - while (!eof() && FormatTok->Tok.isNot(tok::l_brace)) { - if (FormatTok->Tok.is(tok::semi)) - return; - nextToken(); - } + // Note that parsing away template declarations here leads to incorrectly + // accepting function declarations as record declarations. + // In general, we cannot solve this problem. Consider: + // class A B() {} + // which can be a function definition or a class definition when B() is a + // macro. If we find enough real-world cases where this is a problem, we + // can parse for the 'template' keyword in the beginning of the statement, + // and thus rule out the record production in case there is no template + // (this would still leave us with an ambiguity between template function + // and class declarations). + if (FormatTok->Tok.is(tok::colon) || FormatTok->Tok.is(tok::less)) { + while (!eof() && FormatTok->Tok.isNot(tok::l_brace)) { + if (FormatTok->Tok.is(tok::semi)) + return; + nextToken(); } } if (FormatTok->Tok.is(tok::l_brace)) { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 7e75de4..9173061 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -6396,6 +6396,8 @@ TEST_F(FormatTest, UnderstandContextOfRecordTypeKeywords) { verifyFormat("class __declspec(X) Z {\n} n;"); verifyFormat("class A##B##C {\n} n;"); verifyFormat("class alignas(16) Z {\n} n;"); + verifyFormat("class MACRO(X) alignas(16) Z {\n} n;"); + verifyFormat("class MACROA MACRO(X) Z {\n} n;"); // Redefinition from nested context: verifyFormat("class A::B::C {\n} n;");