From: Daniel Jasper Date: Fri, 13 Sep 2013 09:20:45 +0000 (+0000) Subject: clang-format: Fix incorrect enum parsing / layouting. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5798120bc015360951d13a06e17501b909ecd21d;p=clang clang-format: Fix incorrect enum parsing / layouting. Before: enum { Bar = Foo < int, int > ::value }; After: enum { Bar = Foo::value }; git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@190674 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Format/ContinuationIndenter.cpp b/lib/Format/ContinuationIndenter.cpp index f1924c3776..7066e15d5d 100644 --- a/lib/Format/ContinuationIndenter.cpp +++ b/lib/Format/ContinuationIndenter.cpp @@ -106,8 +106,10 @@ bool ContinuationIndenter::mustBreak(const LineState &State) { const FormatToken &Previous = *Current.Previous; if (Current.MustBreakBefore || Current.Type == TT_InlineASMColon) return true; - if (!Style.Cpp11BracedListStyle && Current.is(tok::r_brace) && - State.Stack.back().BreakBeforeClosingBrace) + if ((!Style.Cpp11BracedListStyle || + (Current.MatchingParen && + Current.MatchingParen->BlockKind == BK_Block)) && + Current.is(tok::r_brace) && State.Stack.back().BreakBeforeClosingBrace) return true; if (Previous.is(tok::semi) && State.LineContainsContinuedForLoopSection) return true; @@ -224,7 +226,9 @@ unsigned ContinuationIndenter::addTokenToState(LineState &State, bool Newline, State.Column <= Style.ColumnLimit / 2) Penalty += Style.PenaltyBreakFirstLessLess; - if (Current.is(tok::r_brace)) { + if (Current.is(tok::l_brace) && Current.BlockKind == BK_Block) { + State.Column = State.FirstIndent; + } else if (Current.is(tok::r_brace)) { if (Current.MatchingParen && (Current.MatchingParen->BlockKind == BK_BracedInit || !Current.MatchingParen->Children.empty())) @@ -524,14 +528,15 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, // }); for (unsigned i = 0; i != Current.MatchingParen->FakeRParens; ++i) State.Stack.pop_back(); - NewIndent = State.Stack.back().LastSpace; + NewIndent = State.Stack.back().LastSpace + Style.IndentWidth; } else { NewIndent = State.Stack.back().LastSpace + (Style.Cpp11BracedListStyle ? 4 : Style.IndentWidth); } const FormatToken *NextNoComment = Current.getNextNonComment(); - AvoidBinPacking = NextNoComment && - NextNoComment->Type == TT_DesignatedInitializerPeriod; + AvoidBinPacking = Current.BlockKind == BK_Block || + (NextNoComment && + NextNoComment->Type == TT_DesignatedInitializerPeriod); } else { NewIndent = 4 + std::max(State.Stack.back().LastSpace, State.Stack.back().StartOfFunctionCall); @@ -545,6 +550,7 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State, State.Stack.push_back(ParenState(NewIndent, State.Stack.back().LastSpace, AvoidBinPacking, State.Stack.back().NoLineBreak)); + State.Stack.back().BreakBeforeParameter = Current.BlockKind == BK_Block; ++State.ParenLevel; } diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp index 52f8b07475..034f6e6ee8 100644 --- a/lib/Format/Format.cpp +++ b/lib/Format/Format.cpp @@ -529,7 +529,7 @@ private: E = LBrace.Children.end(); I != E; ++I) { unsigned Indent = - ParentIndent + ((*I)->Level - Line.Level) * Style.IndentWidth; + ParentIndent + ((*I)->Level - Line.Level - 1) * Style.IndentWidth; if (!DryRun) { unsigned Newlines = std::min((*I)->First->NewlinesBefore, Style.MaxEmptyLinesToKeep + 1); diff --git a/lib/Format/FormatToken.cpp b/lib/Format/FormatToken.cpp index 49e0ce8337..7469216a14 100644 --- a/lib/Format/FormatToken.cpp +++ b/lib/Format/FormatToken.cpp @@ -36,6 +36,7 @@ unsigned CommaSeparatedList::format(LineState &State, // Ensure that we start on the opening brace. const FormatToken *LBrace = State.NextToken->Previous->Previous; if (LBrace->isNot(tok::l_brace) || + LBrace->BlockKind == BK_Block || LBrace->Next->Type == TT_DesignatedInitializerPeriod) return 0; diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index dec631fcfb..db17135a0c 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -1057,6 +1057,12 @@ void TokenAnnotator::calculateFormattingInformation(AnnotatedLine &Line) { } else if (Current->Type == TT_CtorInitializerComma && Style.BreakConstructorInitializersBeforeComma) { Current->MustBreakBefore = true; + } else if (Current->Previous->BlockKind == BK_Block && + Current->isNot(tok::r_brace)) { + Current->MustBreakBefore = true; + } else if (Current->is(tok::l_brace) && (Current->BlockKind == BK_Block)) { + Current->MustBreakBefore = + Style.BreakBeforeBraces == FormatStyle::BS_Allman; } Current->CanBreakBefore = Current->MustBreakBefore || canBreakBefore(Line, *Current); diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp index f70de5f6d8..3fb46f2f56 100644 --- a/lib/Format/UnwrappedLineParser.cpp +++ b/lib/Format/UnwrappedLineParser.cpp @@ -759,7 +759,8 @@ bool UnwrappedLineParser::tryToParseBracedList() { return true; } -void UnwrappedLineParser::parseBracedList() { +bool UnwrappedLineParser::parseBracedList(bool ContinueOnSemicolons) { + bool HasError = false; nextToken(); // FIXME: Once we have an expression parser in the UnwrappedLineParser, @@ -786,10 +787,13 @@ void UnwrappedLineParser::parseBracedList() { break; case tok::r_brace: nextToken(); - return; + return !HasError; case tok::semi: - // Probably a missing closing brace. Bail out. - return; + HasError = true; + if (!ContinueOnSemicolons) + return !HasError; + nextToken(); + break; case tok::comma: nextToken(); break; @@ -798,6 +802,7 @@ void UnwrappedLineParser::parseBracedList() { break; } } while (!eof()); + return false; } void UnwrappedLineParser::parseReturn() { @@ -1046,42 +1051,14 @@ void UnwrappedLineParser::parseEnum() { if (FormatTok->Tok.is(tok::identifier)) nextToken(); } - bool HasError = false; if (FormatTok->Tok.is(tok::l_brace)) { - if (Style.BreakBeforeBraces == FormatStyle::BS_Allman) - addUnwrappedLine(); - nextToken(); - addUnwrappedLine(); - ++Line->Level; - do { - switch (FormatTok->Tok.getKind()) { - case tok::l_paren: - parseParens(); - break; - case tok::r_brace: - addUnwrappedLine(); - nextToken(); - --Line->Level; - if (HasError) { - if (FormatTok->is(tok::semi)) - nextToken(); - addUnwrappedLine(); - } - return; - case tok::semi: - HasError = true; - nextToken(); - addUnwrappedLine(); - break; - case tok::comma: - nextToken(); - addUnwrappedLine(); - break; - default: + FormatTok->BlockKind = BK_Block; + bool HasError = !parseBracedList(/*ContinueOnSemicolons=*/true); + if (HasError) { + if (FormatTok->is(tok::semi)) nextToken(); - break; - } - } while (!eof()); + addUnwrappedLine(); + } } // We fall through to parsing a structural element afterwards, so that in // enum A {} n, m; diff --git a/lib/Format/UnwrappedLineParser.h b/lib/Format/UnwrappedLineParser.h index c79c35e1b9..3acdbd60a5 100644 --- a/lib/Format/UnwrappedLineParser.h +++ b/lib/Format/UnwrappedLineParser.h @@ -79,7 +79,7 @@ private: void parsePPUnknown(); void parseStructuralElement(); bool tryToParseBracedList(); - void parseBracedList(); + bool parseBracedList(bool ContinueOnSemicolons = false); void parseReturn(); void parseParens(); void parseIfThenElse(); diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 2500c8e4a7..5202073e16 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -1530,12 +1530,23 @@ TEST_F(FormatTest, FormatsEnum) { " Four = (Zero && (One ^ Two)) | (One << Two),\n" " Five = (One, Two, Three, Four, 5)\n" "};"); + verifyGoogleFormat("enum {\n" + " Zero,\n" + " One = 1,\n" + " Two = One + 1,\n" + " Three = (One + Two),\n" + " Four = (Zero && (One ^ Two)) | (One << Two),\n" + " Five = (One, Two, Three, Four, 5)\n" + "};"); verifyFormat("enum Enum {};"); verifyFormat("enum {};"); - verifyFormat("enum X E {\n} d;"); - verifyFormat("enum __attribute__((...)) E {\n} d;"); - verifyFormat("enum __declspec__((...)) E {\n} d;"); + verifyFormat("enum X E {} d;"); + verifyFormat("enum __attribute__((...)) E {} d;"); + verifyFormat("enum __declspec__((...)) E {} d;"); verifyFormat("enum X f() {\n a();\n return 42;\n}"); + verifyFormat("enum {\n" + " Bar = Foo::value\n" + "};"); } TEST_F(FormatTest, FormatsEnumsWithErrors) { @@ -1563,9 +1574,9 @@ TEST_F(FormatTest, FormatsEnumStruct) { "};"); verifyFormat("enum struct Enum {};"); verifyFormat("enum struct {};"); - verifyFormat("enum struct X E {\n} d;"); - verifyFormat("enum struct __attribute__((...)) E {\n} d;"); - verifyFormat("enum struct __declspec__((...)) E {\n} d;"); + verifyFormat("enum struct X E {} d;"); + verifyFormat("enum struct __attribute__((...)) E {} d;"); + verifyFormat("enum struct __declspec__((...)) E {} d;"); verifyFormat("enum struct X f() {\n a();\n return 42;\n}"); } @@ -1580,9 +1591,9 @@ TEST_F(FormatTest, FormatsEnumClass) { "};"); verifyFormat("enum class Enum {};"); verifyFormat("enum class {};"); - verifyFormat("enum class X E {\n} d;"); - verifyFormat("enum class __attribute__((...)) E {\n} d;"); - verifyFormat("enum class __declspec__((...)) E {\n} d;"); + verifyFormat("enum class X E {} d;"); + verifyFormat("enum class __attribute__((...)) E {} d;"); + verifyFormat("enum class __declspec__((...)) E {} d;"); verifyFormat("enum class X f() {\n a();\n return 42;\n}"); }