Index: clang/lib/Format/DefinitionBlockSeparator.cpp =================================================================== --- clang/lib/Format/DefinitionBlockSeparator.cpp +++ clang/lib/Format/DefinitionBlockSeparator.cpp @@ -35,19 +35,31 @@ const bool IsNeverStyle = Style.SeparateDefinitionBlocks == FormatStyle::SDS_Never; const AdditionalKeywords &ExtraKeywords = Tokens.getKeywords(); - auto LikelyDefinition = [this, ExtraKeywords](const AnnotatedLine *Line, - bool ExcludeEnum = false) { + auto GetBracketLevelChange = [](const FormatToken *Tok) { + if (Tok->isOneOf(tok::l_brace, tok::l_paren, tok::l_square)) + return 1; + if (Tok->isOneOf(tok::r_brace, tok::r_paren, tok::r_square)) + return -1; + return 0; + }; + auto LikelyDefinition = [&](const AnnotatedLine *Line, + bool ExcludeEnum = false) { if ((Line->MightBeFunctionDecl && Line->mightBeFunctionDefinition()) || Line->startsWithNamespace()) return true; - FormatToken *CurrentToken = Line->First; - while (CurrentToken) { - if (CurrentToken->isOneOf(tok::kw_class, tok::kw_struct) || - (Style.isJavaScript() && CurrentToken->is(ExtraKeywords.kw_function))) - return true; - if (!ExcludeEnum && CurrentToken->is(tok::kw_enum)) - return true; - CurrentToken = CurrentToken->Next; + int BracketLevel = 0; + for (const FormatToken *CurrentToken = Line->First; CurrentToken; + CurrentToken = CurrentToken->Next) { + if (BracketLevel == 0) { + if ((CurrentToken->isOneOf(tok::kw_class, tok::kw_struct, + tok::kw_union) || + (Style.isJavaScript() && + CurrentToken->is(ExtraKeywords.kw_function)))) + return true; + if (!ExcludeEnum && CurrentToken->is(tok::kw_enum)) + return true; + } + BracketLevel += GetBracketLevelChange(CurrentToken); } return false; }; @@ -102,14 +114,17 @@ IsPPConditional(OpeningLineIndex - 1); }; const auto HasEnumOnLine = [&]() { - FormatToken *CurrentToken = CurrentLine->First; bool FoundEnumKeyword = false; - while (CurrentToken) { - if (CurrentToken->is(tok::kw_enum)) - FoundEnumKeyword = true; - else if (FoundEnumKeyword && CurrentToken->is(tok::l_brace)) - return true; - CurrentToken = CurrentToken->Next; + int BracketLevel = 0; + for (const FormatToken *CurrentToken = CurrentLine->First; CurrentToken; + CurrentToken = CurrentToken->Next) { + if (BracketLevel == 0) { + if (CurrentToken->is(tok::kw_enum)) + FoundEnumKeyword = true; + else if (FoundEnumKeyword && CurrentToken->is(tok::l_brace)) + return true; + } + BracketLevel += GetBracketLevelChange(CurrentToken); } return FoundEnumKeyword && I + 1 < Lines.size() && Lines[I + 1]->First->is(tok::l_brace); Index: clang/unittests/Format/DefinitionBlockSeparatorTest.cpp =================================================================== --- clang/unittests/Format/DefinitionBlockSeparatorTest.cpp +++ clang/unittests/Format/DefinitionBlockSeparatorTest.cpp @@ -109,6 +109,15 @@ "};", Style); + verifyFormat("union foo {\n" + " int i, j;\n" + "};\n" + "\n" + "union bar {\n" + " int j, k;\n" + "};", + Style); + verifyFormat("class foo {\n" " int i, j;\n" "};\n" @@ -311,6 +320,9 @@ "int bar3(int j, int k, const enum Bar b) {\n" " // A comment\n" " int r = j % k;\n" + " if (struct S = getS()) {\n" + " // if condition\n" + " }\n" " return r;\n" "}\n"; std::string Postfix = "\n" @@ -364,6 +376,9 @@ "int bar3(int j, int k, const enum Bar b) {\n" " // A comment\n" " int r = j % k;\n" + " if (struct S = getS()) {\n" + " // if condition\n" + " }\n" " return r;\n" "}\n" "} // namespace"; @@ -425,6 +440,10 @@ "{\n" " // A comment\n" " int r = j % k;\n" + " if (struct S = getS())\n" + " {\n" + " // if condition\n" + " }\n" " return r;\n" "}\n" "} // namespace NS", @@ -473,6 +492,9 @@ "int bar3(int j, int k, const enum Bar b) {\n" " // A comment\n" " int r = j % k;\n" + " if (struct S = getS()) {\n" + " // if condition\n" + " }\n" " return r;\n" "}\n" "} // namespace";