summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/docs/ClangFormatStyleOptions.rst4
-rw-r--r--clang/include/clang/Format/Format.h5
-rw-r--r--clang/lib/Format/ContinuationIndenter.cpp19
-rw-r--r--clang/lib/Format/Format.cpp4
-rw-r--r--clang/lib/Format/FormatToken.h1
-rw-r--r--clang/lib/Format/TokenAnnotator.cpp14
-rw-r--r--clang/unittests/Format/FormatTest.cpp12
7 files changed, 55 insertions, 4 deletions
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index efc3612b3ea..3f9d1676d7d 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -528,6 +528,10 @@ the configuration (without a prefix: ``Auto``).
+**BreakBeforeInheritanceComma** (``bool``)
+ If ``true``, in the class inheritance expression clang-format will
+ break before ``:`` and ``,`` if there is multiple inheritance.
+
**BreakBeforeTernaryOperators** (``bool``)
If ``true``, ternary operators will be placed after line breaks.
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index d017247b7b1..4b66dd667de 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -422,6 +422,10 @@ struct FormatStyle {
/// which should not be split into lines or otherwise changed.
std::string CommentPragmas;
+ /// \brief If ``true``, in the class inheritance expression clang-format will
+ /// break before ``:`` and ``,`` if there is multiple inheritance.
+ bool BreakBeforeInheritanceComma;
+
/// \brief If the constructor initializers don't fit on a line, put each
/// initializer on its own line.
bool ConstructorInitializerAllOnOneLineOrOnePerLine;
@@ -844,6 +848,7 @@ struct FormatStyle {
BreakAfterJavaFieldAnnotations == R.BreakAfterJavaFieldAnnotations &&
BreakStringLiterals == R.BreakStringLiterals &&
ColumnLimit == R.ColumnLimit && CommentPragmas == R.CommentPragmas &&
+ BreakBeforeInheritanceComma == R.BreakBeforeInheritanceComma &&
ConstructorInitializerAllOnOneLineOrOnePerLine ==
R.ConstructorInitializerAllOnOneLineOrOnePerLine &&
ConstructorInitializerIndentWidth ==
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 0561cdbdaf9..c518db8b1af 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -57,8 +57,10 @@ static bool startsNextParameter(const FormatToken &Current,
Style.BreakConstructorInitializersBeforeComma)
return true;
return Previous.is(tok::comma) && !Current.isTrailingComment() &&
- (Previous.isNot(TT_CtorInitializerComma) ||
- !Style.BreakConstructorInitializersBeforeComma);
+ ((Previous.isNot(TT_CtorInitializerComma) ||
+ !Style.BreakConstructorInitializersBeforeComma) &&
+ (Previous.isNot(TT_InheritanceComma) ||
+ !Style.BreakBeforeInheritanceComma));
}
ContinuationIndenter::ContinuationIndenter(const FormatStyle &Style,
@@ -350,6 +352,11 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun,
Whitespaces.replaceWhitespace(Current, /*Newlines=*/0, Spaces,
State.Column + Spaces);
+ // If "BreakBeforeInheritanceComma" mode, don't break within the inheritance
+ // declaration unless there is multiple inheritance.
+ if (Style.BreakBeforeInheritanceComma && Current.is(TT_InheritanceColon))
+ State.Stack.back().NoLineBreak = true;
+
if (Current.is(TT_SelectorName) &&
!State.Stack.back().ObjCSelectorNameFound) {
unsigned MinIndent =
@@ -737,10 +744,11 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
if (PreviousNonComment && PreviousNonComment->is(tok::colon) &&
PreviousNonComment->isOneOf(TT_ObjCMethodExpr, TT_DictLiteral))
return ContinuationIndent;
- if (NextNonComment->is(TT_CtorInitializerColon))
- return State.FirstIndent + Style.ConstructorInitializerIndentWidth;
if (NextNonComment->is(TT_CtorInitializerComma))
return State.Stack.back().Indent;
+ if (NextNonComment->isOneOf(TT_CtorInitializerColon, TT_InheritanceColon,
+ TT_InheritanceComma))
+ return State.FirstIndent + Style.ConstructorInitializerIndentWidth;
if (Previous.is(tok::r_paren) && !Current.isBinaryOperator() &&
!Current.isOneOf(tok::colon, tok::comment))
return ContinuationIndent;
@@ -810,6 +818,9 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
State.Stack.back().AvoidBinPacking = true;
State.Stack.back().BreakBeforeParameter = false;
}
+ if (Current.is(TT_InheritanceColon))
+ State.Stack.back().Indent =
+ State.FirstIndent + Style.ContinuationIndentWidth;
if (Current.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) && Newline)
State.Stack.back().NestedBlockIndent =
State.Column + Current.ColumnWidth + 1;
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 7431feb8f59..07624620d01 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -298,6 +298,8 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("BreakStringLiterals", Style.BreakStringLiterals);
IO.mapOptional("ColumnLimit", Style.ColumnLimit);
IO.mapOptional("CommentPragmas", Style.CommentPragmas);
+ IO.mapOptional("BreakBeforeInheritanceComma",
+ Style.BreakBeforeInheritanceComma);
IO.mapOptional("ConstructorInitializerAllOnOneLineOrOnePerLine",
Style.ConstructorInitializerAllOnOneLineOrOnePerLine);
IO.mapOptional("ConstructorInitializerIndentWidth",
@@ -521,6 +523,7 @@ FormatStyle getLLVMStyle() {
false, false, false, false, false};
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
LLVMStyle.BreakConstructorInitializersBeforeComma = false;
+ LLVMStyle.BreakBeforeInheritanceComma = false;
LLVMStyle.BreakStringLiterals = true;
LLVMStyle.ColumnLimit = 80;
LLVMStyle.CommentPragmas = "^ IWYU pragma:";
@@ -674,6 +677,7 @@ FormatStyle getMozillaStyle() {
MozillaStyle.BinPackArguments = false;
MozillaStyle.BreakBeforeBraces = FormatStyle::BS_Mozilla;
MozillaStyle.BreakConstructorInitializersBeforeComma = true;
+ MozillaStyle.BreakBeforeInheritanceComma = true;
MozillaStyle.ConstructorInitializerIndentWidth = 2;
MozillaStyle.ContinuationIndentWidth = 2;
MozillaStyle.Cpp11BracedListStyle = false;
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 3cf95ae1251..8492829abf0 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -48,6 +48,7 @@ namespace format {
TYPE(FunctionTypeLParen) \
TYPE(ImplicitStringLiteral) \
TYPE(InheritanceColon) \
+ TYPE(InheritanceComma) \
TYPE(InlineASMBrace) \
TYPE(InlineASMColon) \
TYPE(JavaAnnotation) \
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 97a22d8e97e..c529f1e4a62 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -676,6 +676,8 @@ private:
case tok::comma:
if (Contexts.back().InCtorInitializer)
Tok->Type = TT_CtorInitializerComma;
+ else if (Contexts.back().InInheritanceList)
+ Tok->Type = TT_InheritanceComma;
else if (Contexts.back().FirstStartOfName &&
(Contexts.size() == 1 || Line.startsWith(tok::kw_for))) {
Contexts.back().FirstStartOfName->PartOfMultiVariableDeclStmt = true;
@@ -945,6 +947,7 @@ private:
bool CanBeExpression = true;
bool InTemplateArgument = false;
bool InCtorInitializer = false;
+ bool InInheritanceList = false;
bool CaretFound = false;
bool IsForEachMacro = false;
};
@@ -1004,6 +1007,9 @@ private:
Current.Previous->is(TT_CtorInitializerColon)) {
Contexts.back().IsExpression = true;
Contexts.back().InCtorInitializer = true;
+ } else if (Current.Previous &&
+ Current.Previous->is(TT_InheritanceColon)) {
+ Contexts.back().InInheritanceList = true;
} else if (Current.isOneOf(tok::r_paren, tok::greater, tok::comma)) {
for (FormatToken *Previous = Current.Previous;
Previous && Previous->isOneOf(tok::star, tok::amp);
@@ -2474,6 +2480,10 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
Style.BreakConstructorInitializersBeforeComma &&
!Style.ConstructorInitializerAllOnOneLineOrOnePerLine)
return true;
+ // Break only if we have multiple inheritance.
+ if (Style.BreakBeforeInheritanceComma &&
+ Right.is(TT_InheritanceComma))
+ return true;
if (Right.is(tok::string_literal) && Right.TokenText.startswith("R\""))
// Raw string literals are special wrt. line breaks. The author has made a
// deliberate choice and might have aligned the contents of the string
@@ -2653,6 +2663,10 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
if (Right.is(TT_CtorInitializerComma) &&
Style.BreakConstructorInitializersBeforeComma)
return true;
+ if (Left.is(TT_InheritanceComma) && Style.BreakBeforeInheritanceComma)
+ return false;
+ if (Right.is(TT_InheritanceComma) && Style.BreakBeforeInheritanceComma)
+ return true;
if ((Left.is(tok::greater) && Right.is(tok::greater)) ||
(Left.is(tok::less) && Right.is(tok::less)))
return false;
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 0c91b63a528..bcbdbbf3e5d 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -1029,6 +1029,17 @@ TEST_F(FormatTest, FormatsClasses) {
verifyFormat("class ::A::B {};");
}
+TEST_F(FormatTest, BreakBeforeInheritanceComma) {
+ FormatStyle StyleWithInheritanceBreak = getLLVMStyle();
+ StyleWithInheritanceBreak.BreakBeforeInheritanceComma = true;
+
+ verifyFormat("class MyClass : public X {};", StyleWithInheritanceBreak);
+ verifyFormat("class MyClass\n"
+ " : public X\n"
+ " , public Y {};",
+ StyleWithInheritanceBreak);
+}
+
TEST_F(FormatTest, FormatsVariableDeclarationsAfterStructOrClass) {
verifyFormat("class A {\n} a, b;");
verifyFormat("struct A {\n} a, b;");
@@ -8582,6 +8593,7 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
CHECK_PARSE_BOOL(BreakBeforeTernaryOperators);
CHECK_PARSE_BOOL(BreakConstructorInitializersBeforeComma);
CHECK_PARSE_BOOL(BreakStringLiterals);
+ CHECK_PARSE_BOOL(BreakBeforeInheritanceComma)
CHECK_PARSE_BOOL(ConstructorInitializerAllOnOneLineOrOnePerLine);
CHECK_PARSE_BOOL(DerivePointerAlignment);
CHECK_PARSE_BOOL_FIELD(DerivePointerAlignment, "DerivePointerBinding");
OpenPOWER on IntegriCloud