Skip to content

Commit 58e6fe5

Browse files
committedMay 16, 2018
clang-format: Allow optimizer to break template declaration.
Summary: Introduce `PenaltyBreakTemplateDeclaration` to control the penalty, and change `AlwaysBreakTemplateDeclarations` to an enum with 3 modes: * `No` for regular, penalty based, wrapping of template declaration * `MultiLine` for always wrapping before multi-line declarations (e.g. same as legacy behavior when `AlwaysBreakTemplateDeclarations=false`) * `Yes` for always wrapping (e.g. same as legacy behavior when `AlwaysBreakTemplateDeclarations=true`) Reviewers: krasimir, djasper, klimek Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D42684 llvm-svn: 332436
1 parent 5df1ef7 commit 58e6fe5

File tree

6 files changed

+158
-22
lines changed

6 files changed

+158
-22
lines changed
 

Diff for: ‎clang/docs/ClangFormatStyleOptions.rst

+45-7
Original file line numberDiff line numberDiff line change
@@ -490,15 +490,50 @@ the configuration (without a prefix: ``Auto``).
490490
"bbbb" "cccc";
491491
"cccc";
492492

493-
**AlwaysBreakTemplateDeclarations** (``bool``)
494-
If ``true``, always break after the ``template<...>`` of a template
495-
declaration.
493+
**AlwaysBreakTemplateDeclarations** (``BreakTemplateDeclarationsStyle``)
494+
The template declaration breaking style to use.
495+
496+
Possible values:
497+
498+
* ``BTDS_No`` (in configuration: ``No``)
499+
Do not force break before declaration.
500+
``PenaltyBreakTemplateDeclaration`` is taken into account.
501+
502+
.. code-block:: c++
503+
504+
template <typename T> T foo() {
505+
}
506+
template <typename T> T foo(int aaaaaaaaaaaaaaaaaaaaa,
507+
int bbbbbbbbbbbbbbbbbbbbb) {
508+
}
509+
510+
* ``BTDS_MultiLine`` (in configuration: ``MultiLine``)
511+
Force break after template declaration only when the following
512+
declaration spans multiple lines.
513+
514+
.. code-block:: c++
515+
516+
template <typename T> T foo() {
517+
}
518+
template <typename T>
519+
T foo(int aaaaaaaaaaaaaaaaaaaaa,
520+
int bbbbbbbbbbbbbbbbbbbbb) {
521+
}
522+
523+
* ``BTDS_Yes`` (in configuration: ``Yes``)
524+
Always break after template declaration.
525+
526+
.. code-block:: c++
527+
528+
template <typename T>
529+
T foo() {
530+
}
531+
template <typename T>
532+
T foo(int aaaaaaaaaaaaaaaaaaaaa,
533+
int bbbbbbbbbbbbbbbbbbbbb) {
534+
}
496535

497-
.. code-block:: c++
498536

499-
true: false:
500-
template <typename T> vs. template <typename T> class C {};
501-
class C {};
502537

503538
**BinPackArguments** (``bool``)
504539
If ``false``, a function call's arguments will either be all on the
@@ -1590,6 +1625,9 @@ the configuration (without a prefix: ``Auto``).
15901625
**PenaltyBreakString** (``unsigned``)
15911626
The penalty for each line break introduced inside a string literal.
15921627

1628+
**PenaltyBreakTemplateDeclaration** (``unsigned``)
1629+
The penalty for breaking after template declaration.
1630+
15931631
**PenaltyExcessCharacter** (``unsigned``)
15941632
The penalty for each character outside of the column limit.
15951633

Diff for: ‎clang/include/clang/Format/Format.h

+43-8
Original file line numberDiff line numberDiff line change
@@ -351,14 +351,44 @@ struct FormatStyle {
351351
/// \endcode
352352
bool AlwaysBreakBeforeMultilineStrings;
353353

354-
/// If ``true``, always break after the ``template<...>`` of a template
355-
/// declaration.
356-
/// \code
357-
/// true: false:
358-
/// template <typename T> vs. template <typename T> class C {};
359-
/// class C {};
360-
/// \endcode
361-
bool AlwaysBreakTemplateDeclarations;
354+
/// Different ways to break after the template declaration.
355+
enum BreakTemplateDeclarationsStyle {
356+
/// Do not force break before declaration.
357+
/// ``PenaltyBreakTemplateDeclaration`` is taken into account.
358+
/// \code
359+
/// template <typename T> T foo() {
360+
/// }
361+
/// template <typename T> T foo(int aaaaaaaaaaaaaaaaaaaaa,
362+
/// int bbbbbbbbbbbbbbbbbbbbb) {
363+
/// }
364+
/// \endcode
365+
BTDS_No,
366+
/// Force break after template declaration only when the following
367+
/// declaration spans multiple lines.
368+
/// \code
369+
/// template <typename T> T foo() {
370+
/// }
371+
/// template <typename T>
372+
/// T foo(int aaaaaaaaaaaaaaaaaaaaa,
373+
/// int bbbbbbbbbbbbbbbbbbbbb) {
374+
/// }
375+
/// \endcode
376+
BTDS_MultiLine,
377+
/// Always break after template declaration.
378+
/// \code
379+
/// template <typename T>
380+
/// T foo() {
381+
/// }
382+
/// template <typename T>
383+
/// T foo(int aaaaaaaaaaaaaaaaaaaaa,
384+
/// int bbbbbbbbbbbbbbbbbbbbb) {
385+
/// }
386+
/// \endcode
387+
BTDS_Yes
388+
};
389+
390+
/// The template declaration breaking style to use.
391+
BreakTemplateDeclarationsStyle AlwaysBreakTemplateDeclarations;
362392

363393
/// If ``false``, a function call's arguments will either be all on the
364394
/// same line or will have one line each.
@@ -1295,6 +1325,9 @@ struct FormatStyle {
12951325
/// The penalty for each line break introduced inside a string literal.
12961326
unsigned PenaltyBreakString;
12971327

1328+
/// The penalty for breaking after template declaration.
1329+
unsigned PenaltyBreakTemplateDeclaration;
1330+
12981331
/// The penalty for each character outside of the column limit.
12991332
unsigned PenaltyExcessCharacter;
13001333

@@ -1679,6 +1712,8 @@ struct FormatStyle {
16791712
PenaltyBreakString == R.PenaltyBreakString &&
16801713
PenaltyExcessCharacter == R.PenaltyExcessCharacter &&
16811714
PenaltyReturnTypeOnItsOwnLine == R.PenaltyReturnTypeOnItsOwnLine &&
1715+
PenaltyBreakTemplateDeclaration ==
1716+
R.PenaltyBreakTemplateDeclaration &&
16821717
PointerAlignment == R.PointerAlignment &&
16831718
RawStringFormats == R.RawStringFormats &&
16841719
SpaceAfterCStyleCast == R.SpaceAfterCStyleCast &&

Diff for: ‎clang/lib/Format/ContinuationIndenter.cpp

+7-1
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,12 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
402402
Style.Language == FormatStyle::LK_JavaScript))
403403
return true;
404404

405+
// If the template declaration spans multiple lines, force wrap before the
406+
// function/class declaration
407+
if (Previous.ClosesTemplateDeclaration &&
408+
State.Stack.back().BreakBeforeParameter)
409+
return true;
410+
405411
if (State.Column <= NewLineColumn)
406412
return false;
407413

@@ -453,7 +459,7 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
453459
// for cases where the entire line does not fit on a single line as a
454460
// different LineFormatter would be used otherwise.
455461
if (Previous.ClosesTemplateDeclaration)
456-
return true;
462+
return Style.AlwaysBreakTemplateDeclarations != FormatStyle::BTDS_No;
457463
if (Previous.is(TT_FunctionAnnotationRParen))
458464
return true;
459465
if (Previous.is(TT_LeadingJavaAnnotation) && Current.isNot(tok::l_paren) &&

Diff for: ‎clang/lib/Format/Format.cpp

+19-3
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,19 @@ struct ScalarEnumerationTraits<FormatStyle::ReturnTypeBreakingStyle> {
168168
}
169169
};
170170

171+
template <>
172+
struct ScalarEnumerationTraits<FormatStyle::BreakTemplateDeclarationsStyle> {
173+
static void enumeration(IO &IO, FormatStyle::BreakTemplateDeclarationsStyle &Value) {
174+
IO.enumCase(Value, "No", FormatStyle::BTDS_No);
175+
IO.enumCase(Value, "MultiLine", FormatStyle::BTDS_MultiLine);
176+
IO.enumCase(Value, "Yes", FormatStyle::BTDS_Yes);
177+
178+
// For backward compatibility.
179+
IO.enumCase(Value, "false", FormatStyle::BTDS_MultiLine);
180+
IO.enumCase(Value, "true", FormatStyle::BTDS_Yes);
181+
}
182+
};
183+
171184
template <>
172185
struct ScalarEnumerationTraits<FormatStyle::DefinitionReturnTypeBreakingStyle> {
173186
static void
@@ -400,6 +413,8 @@ template <> struct MappingTraits<FormatStyle> {
400413
IO.mapOptional("PenaltyBreakFirstLessLess",
401414
Style.PenaltyBreakFirstLessLess);
402415
IO.mapOptional("PenaltyBreakString", Style.PenaltyBreakString);
416+
IO.mapOptional("PenaltyBreakTemplateDeclaration",
417+
Style.PenaltyBreakTemplateDeclaration);
403418
IO.mapOptional("PenaltyExcessCharacter", Style.PenaltyExcessCharacter);
404419
IO.mapOptional("PenaltyReturnTypeOnItsOwnLine",
405420
Style.PenaltyReturnTypeOnItsOwnLine);
@@ -598,7 +613,7 @@ FormatStyle getLLVMStyle() {
598613
LLVMStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_None;
599614
LLVMStyle.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_None;
600615
LLVMStyle.AlwaysBreakBeforeMultilineStrings = false;
601-
LLVMStyle.AlwaysBreakTemplateDeclarations = false;
616+
LLVMStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_MultiLine;
602617
LLVMStyle.BinPackArguments = true;
603618
LLVMStyle.BinPackParameters = true;
604619
LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
@@ -670,6 +685,7 @@ FormatStyle getLLVMStyle() {
670685
LLVMStyle.PenaltyExcessCharacter = 1000000;
671686
LLVMStyle.PenaltyReturnTypeOnItsOwnLine = 60;
672687
LLVMStyle.PenaltyBreakBeforeFirstCallParameter = 19;
688+
LLVMStyle.PenaltyBreakTemplateDeclaration = prec::Relational;
673689

674690
LLVMStyle.DisableFormat = false;
675691
LLVMStyle.SortIncludes = true;
@@ -694,7 +710,7 @@ FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language) {
694710
GoogleStyle.AllowShortIfStatementsOnASingleLine = true;
695711
GoogleStyle.AllowShortLoopsOnASingleLine = true;
696712
GoogleStyle.AlwaysBreakBeforeMultilineStrings = true;
697-
GoogleStyle.AlwaysBreakTemplateDeclarations = true;
713+
GoogleStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
698714
GoogleStyle.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
699715
GoogleStyle.DerivePointerAlignment = true;
700716
GoogleStyle.IncludeStyle.IncludeCategories = {
@@ -819,7 +835,7 @@ FormatStyle getMozillaStyle() {
819835
MozillaStyle.AlwaysBreakAfterReturnType = FormatStyle::RTBS_TopLevel;
820836
MozillaStyle.AlwaysBreakAfterDefinitionReturnType =
821837
FormatStyle::DRTBS_TopLevel;
822-
MozillaStyle.AlwaysBreakTemplateDeclarations = true;
838+
MozillaStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
823839
MozillaStyle.BinPackParameters = false;
824840
MozillaStyle.BinPackArguments = false;
825841
MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;

Diff for: ‎clang/lib/Format/TokenAnnotator.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -2338,6 +2338,8 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line,
23382338
return 2;
23392339
return 1;
23402340
}
2341+
if (Left.ClosesTemplateDeclaration)
2342+
return Style.PenaltyBreakTemplateDeclaration;
23412343
if (Left.is(TT_ConditionalExpr))
23422344
return prec::Conditional;
23432345
prec::Level Level = Left.getPrecedence();
@@ -2869,7 +2871,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
28692871
if (Right.Previous->ClosesTemplateDeclaration &&
28702872
Right.Previous->MatchingParen &&
28712873
Right.Previous->MatchingParen->NestingLevel == 0 &&
2872-
Style.AlwaysBreakTemplateDeclarations)
2874+
Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Yes)
28732875
return true;
28742876
if (Right.is(TT_CtorInitializerComma) &&
28752877
Style.BreakConstructorInitializers == FormatStyle::BCIS_BeforeComma &&

Diff for: ‎clang/unittests/Format/FormatTest.cpp

+41-2
Original file line numberDiff line numberDiff line change
@@ -5475,7 +5475,7 @@ TEST_F(FormatTest, WrapsTemplateDeclarations) {
54755475
" const typename aaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaa);");
54765476

54775477
FormatStyle AlwaysBreak = getLLVMStyle();
5478-
AlwaysBreak.AlwaysBreakTemplateDeclarations = true;
5478+
AlwaysBreak.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
54795479
verifyFormat("template <typename T>\nclass C {};", AlwaysBreak);
54805480
verifyFormat("template <typename T>\nvoid f();", AlwaysBreak);
54815481
verifyFormat("template <typename T>\nvoid f() {}", AlwaysBreak);
@@ -5493,6 +5493,32 @@ TEST_F(FormatTest, WrapsTemplateDeclarations) {
54935493
"public:\n"
54945494
" E *f();\n"
54955495
"};");
5496+
5497+
FormatStyle NeverBreak = getLLVMStyle();
5498+
NeverBreak.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_No;
5499+
verifyFormat("template <typename T> class C {};", NeverBreak);
5500+
verifyFormat("template <typename T> void f();", NeverBreak);
5501+
verifyFormat("template <typename T> void f() {}", NeverBreak);
5502+
verifyFormat("template <typename T>\nvoid foo(aaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbb) {}",
5503+
NeverBreak);
5504+
verifyFormat("void aaaaaaaaaaaaaaaaaaa<aaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
5505+
" bbbbbbbbbbbbbbbbbbbbbbbbbbbb>(\n"
5506+
" ccccccccccccccccccccccccccccccccccccccccccccccc);",
5507+
NeverBreak);
5508+
verifyFormat("template <template <typename> class Fooooooo,\n"
5509+
" template <typename> class Baaaaaaar>\n"
5510+
"struct C {};",
5511+
NeverBreak);
5512+
verifyFormat("template <typename T> // T can be A, B or C.\n"
5513+
"struct C {};",
5514+
NeverBreak);
5515+
verifyFormat("template <enum E> class A {\n"
5516+
"public:\n"
5517+
" E *f();\n"
5518+
"};", NeverBreak);
5519+
NeverBreak.PenaltyBreakTemplateDeclaration = 100;
5520+
verifyFormat("template <typename T> void\nfoo(aaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbb) {}",
5521+
NeverBreak);
54965522
}
54975523

54985524
TEST_F(FormatTest, WrapsTemplateParameters) {
@@ -10440,7 +10466,6 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
1044010466
CHECK_PARSE_BOOL(AllowShortCaseLabelsOnASingleLine);
1044110467
CHECK_PARSE_BOOL(AllowShortIfStatementsOnASingleLine);
1044210468
CHECK_PARSE_BOOL(AllowShortLoopsOnASingleLine);
10443-
CHECK_PARSE_BOOL(AlwaysBreakTemplateDeclarations);
1044410469
CHECK_PARSE_BOOL(BinPackArguments);
1044510470
CHECK_PARSE_BOOL(BinPackParameters);
1044610471
CHECK_PARSE_BOOL(BreakAfterJavaFieldAnnotations);
@@ -10506,6 +10531,8 @@ TEST_F(FormatTest, ParsesConfiguration) {
1050610531
PenaltyBreakAssignment, 1234u);
1050710532
CHECK_PARSE("PenaltyBreakBeforeFirstCallParameter: 1234",
1050810533
PenaltyBreakBeforeFirstCallParameter, 1234u);
10534+
CHECK_PARSE("PenaltyBreakTemplateDeclaration: 1234",
10535+
PenaltyBreakTemplateDeclaration, 1234u);
1050910536
CHECK_PARSE("PenaltyExcessCharacter: 1234", PenaltyExcessCharacter, 1234u);
1051010537
CHECK_PARSE("PenaltyReturnTypeOnItsOwnLine: 1234",
1051110538
PenaltyReturnTypeOnItsOwnLine, 1234u);
@@ -10660,6 +10687,18 @@ TEST_F(FormatTest, ParsesConfiguration) {
1066010687
AlwaysBreakAfterReturnType,
1066110688
FormatStyle::RTBS_TopLevelDefinitions);
1066210689

10690+
Style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
10691+
CHECK_PARSE("AlwaysBreakTemplateDeclarations: No", AlwaysBreakTemplateDeclarations,
10692+
FormatStyle::BTDS_No);
10693+
CHECK_PARSE("AlwaysBreakTemplateDeclarations: MultiLine", AlwaysBreakTemplateDeclarations,
10694+
FormatStyle::BTDS_MultiLine);
10695+
CHECK_PARSE("AlwaysBreakTemplateDeclarations: Yes", AlwaysBreakTemplateDeclarations,
10696+
FormatStyle::BTDS_Yes);
10697+
CHECK_PARSE("AlwaysBreakTemplateDeclarations: false", AlwaysBreakTemplateDeclarations,
10698+
FormatStyle::BTDS_MultiLine);
10699+
CHECK_PARSE("AlwaysBreakTemplateDeclarations: true", AlwaysBreakTemplateDeclarations,
10700+
FormatStyle::BTDS_Yes);
10701+
1066310702
Style.AlwaysBreakAfterDefinitionReturnType = FormatStyle::DRTBS_All;
1066410703
CHECK_PARSE("AlwaysBreakAfterDefinitionReturnType: None",
1066510704
AlwaysBreakAfterDefinitionReturnType, FormatStyle::DRTBS_None);

0 commit comments

Comments
 (0)
Please sign in to comment.