rymiel created this revision. rymiel added reviewers: HazardyKnusperkeks, owenpan, MyDeveloperDay. rymiel added a project: clang-format. Herald added a project: All. rymiel requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
D119599 <https://reviews.llvm.org/D119599> added the ability to align compound assignments, right aligning them in order to line up at the equals sign. However, that patch didn't account for AlignTokens being called recursively across scopes, which reset the right justification to be false in any scope besides the top scope. This meant the compound assignments were aligned, just not at the right place. (No tests also ever introduced any scopes) This patch makes sure to inherit the right justification value, just as every other parameter is passed on. Fixes https://github.com/llvm/llvm-project/issues/58029 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D141287 Files: clang/lib/Format/ContinuationIndenter.cpp clang/lib/Format/FormatToken.h clang/lib/Format/TokenAnnotator.cpp clang/unittests/Format/FormatTest.cpp clang/unittests/Format/TokenAnnotatorTest.cpp
Index: clang/unittests/Format/TokenAnnotatorTest.cpp =================================================================== --- clang/unittests/Format/TokenAnnotatorTest.cpp +++ clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1136,6 +1136,14 @@ EXPECT_TOKEN(Tokens[1], tok::identifier, TT_FunctionDeclarationName); } +TEST_F(TokenAnnotatorTest, UnderstandsC11GenericSelection) { + auto Tokens = annotate("_Generic(x, int: 1, default: 0)"); + ASSERT_EQ(Tokens.size(), 13u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::kw__Generic, TT_Unknown); + EXPECT_TOKEN(Tokens[5], tok::colon, TT_GenericSelectionColon); + EXPECT_TOKEN(Tokens[9], tok::colon, TT_GenericSelectionColon); +} + TEST_F(TokenAnnotatorTest, UnderstandsVerilogOperators) { auto Annotate = [this](llvm::StringRef Code) { return annotate(Code, getLLVMStyle(FormatStyle::LK_Verilog)); Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -22996,6 +22996,41 @@ verifyFormat("x = (_Atomic( uint64_t ))&a;", Style); } +TEST_F(FormatTest, C11Generic) { + verifyFormat("_Generic(x, int: 1, default: 0)"); + verifyFormat("#define cbrt(X) _Generic((X), float: cbrtf, default: cbrt)(X)"); + verifyFormat("_Generic(x, const char *: 1, char *const: 16, int: 8);"); + verifyFormat("_Generic(x, int: f1, const int: f2)();"); + verifyFormat("_Generic(x, struct A: 1, void (*)(void): 2);"); + + verifyFormat("_Generic(x,\n" + " float: f,\n" + " default: d,\n" + " long double: ld,\n" + " float _Complex: fc,\n" + " double _Complex: dc,\n" + " long double _Complex: ldc)"); + + FormatStyle Style = getLLVMStyle(); + Style.ColumnLimit = 40; + verifyFormat("#define LIMIT_MAX(T) \\\n" + " _Generic(((T)0), \\\n" + " unsigned int: UINT_MAX, \\\n" + " unsigned long: ULONG_MAX, \\\n" + " unsigned long long: ULLONG_MAX)", + Style); + verifyFormat("_Generic(x,\n" + " struct A: 1,\n" + " void (*)(void): 2);", + Style); + + Style.ContinuationIndentWidth = 2; + verifyFormat("_Generic(x,\n" + " struct A: 1,\n" + " void (*)(void): 2);", + Style); +} + TEST_F(FormatTest, AmbersandInLamda) { // Test case reported in https://bugs.llvm.org/show_bug.cgi?id=41899 FormatStyle AlignStyle = getLLVMStyle(); Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -323,6 +323,10 @@ Contexts.back().IsExpression = false; } else if (OpeningParen.is(TT_RequiresExpressionLParen)) { Contexts.back().IsExpression = false; + } else if (OpeningParen.Previous && + OpeningParen.Previous->is(tok::kw__Generic)) { + Contexts.back().ContextType = Context::C11GenericSelection; + Contexts.back().IsExpression = true; } else if (Line.InPPDirective && (!OpeningParen.Previous || !OpeningParen.Previous->is(tok::identifier))) { @@ -1028,6 +1032,8 @@ } } else if (Contexts.back().ColonIsForRangeExpr) { Tok->setType(TT_RangeBasedForLoopColon); + } else if (Contexts.back().ContextType == Context::C11GenericSelection) { + Tok->setType(TT_GenericSelectionColon); } else if (CurrentToken && CurrentToken->is(tok::numeric_constant)) { Tok->setType(TT_BitFieldColon); } else if (Contexts.size() == 1 && @@ -1623,6 +1629,8 @@ StructArrayInitializer, // Like in `static_cast<int>`. TemplateArgument, + // C11 _Generic selection. + C11GenericSelection, } ContextType = Unknown; }; @@ -3251,7 +3259,8 @@ return 100; } if (Left.is(tok::l_paren) && Left.Previous && - (Left.Previous->is(tok::kw_for) || Left.Previous->isIf())) { + (Left.Previous->isOneOf(tok::kw_for, tok::kw__Generic) || + Left.Previous->isIf())) { return 1000; } if (Left.is(tok::equal) && InFunctionDecl) @@ -4159,6 +4168,8 @@ return false; if (Right.is(TT_CSharpNamedArgumentColon)) return false; + if (Right.is(TT_GenericSelectionColon)) + return false; if (Right.is(TT_BitFieldColon)) { return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both || Style.BitFieldColonSpacing == FormatStyle::BFCS_Before; Index: clang/lib/Format/FormatToken.h =================================================================== --- clang/lib/Format/FormatToken.h +++ clang/lib/Format/FormatToken.h @@ -70,6 +70,8 @@ TYPE(FunctionLBrace) \ TYPE(FunctionLikeOrFreestandingMacro) \ TYPE(FunctionTypeLParen) \ + /* The colons as part of a C11 _Generic selection */ \ + TYPE(GenericSelectionColon) \ /* The colon at the end of a goto label or a case label. Currently only used \ * for Verilog. */ \ TYPE(GotoLabelColon) \ Index: clang/lib/Format/ContinuationIndenter.cpp =================================================================== --- clang/lib/Format/ContinuationIndenter.cpp +++ clang/lib/Format/ContinuationIndenter.cpp @@ -1538,6 +1538,12 @@ std::max(State.Column, NewParenState.Indent), CurrentState.LastSpace); } + // Special case for generic selection expressions, its comma-separated + // expressions are not aligned to the opening paren like regular calls, but + // rather continuation-indented relative to the _Generic keyword. + if (Previous && Previous->endsSequence(tok::l_paren, tok::kw__Generic)) + NewParenState.Indent = CurrentState.LastSpace; + if (Previous && (Previous->getPrecedence() == prec::Assignment || Previous->isOneOf(tok::kw_return, TT_RequiresClause) || @@ -1684,8 +1690,12 @@ (State.Line->Type != LT_ObjCDecl && Style.BinPackParameters) || (State.Line->Type == LT_ObjCDecl && ObjCBinPackProtocolList); + bool GenericSelection = + Current.getPreviousNonComment() && + Current.getPreviousNonComment()->is(tok::kw__Generic); + AvoidBinPacking = - (CurrentState.IsCSharpGenericTypeConstraint) || + (CurrentState.IsCSharpGenericTypeConstraint) || GenericSelection || (Style.isJavaScript() && EndsInComma) || (State.Line->MustBeDeclaration && !BinPackDeclaration) || (!State.Line->MustBeDeclaration && !Style.BinPackArguments) ||
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits