This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG0904e0bac831: [clang-format] Properly handle the C11
_Generic keyword. (authored by rymiel).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D139211/new/
https://reviews.llvm.org/D139211
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
@@ -1152,6 +1152,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
@@ -23012,6 +23012,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
@@ -322,6 +322,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))) {
@@ -1027,6 +1031,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 &&
@@ -1626,6 +1632,8 @@
StructArrayInitializer,
// Like in `static_cast<int>`.
TemplateArgument,
+ // C11 _Generic selection.
+ C11GenericSelection,
} ContextType = Unknown;
};
@@ -3254,7 +3262,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)
@@ -4163,6 +4172,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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits