diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -3257,6 +3257,14 @@ true: false: Foo::Foo() : a(a) {} Foo::Foo(): a(a) {} +**SpaceBeforeForLoopSemiColon** (``bool``) + If ``false``, spaces will be removed before for loop semi-colon. + + .. code-block:: c++ + + true: false: + for (i = 0 ; i < 10 ; ++i) {} vs. for (i = 0; i < 10; ++i) {} + **SpaceBeforeInheritanceColon** (``bool``) If ``false``, spaces will be removed before inheritance colon. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -165,6 +165,9 @@ clang-format ------------ +- Option ``SpaceBeforeForLoopSemiColon`` has been added to control whether + spaces will be added before the semi-colons in for loops. + - Option ``SpacesInLineCommentPrefix`` has been added to control the number of spaces in a line comments prefix. diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -2835,6 +2835,13 @@ /// \endcode bool SpaceBeforeCtorInitializerColon; + /// If ``false``, spaces will be removed before semi-colons in for loops. + /// \code + /// true: false: + /// for (i = 0 ; i < 1 ; ++i) {} vs. for (i = 0; i < 1; ++i) {} + /// \endcode + bool SpaceBeforeForLoopSemiColon; + /// If ``false``, spaces will be removed before inheritance colon. /// \code /// true: false: @@ -3259,6 +3266,7 @@ SpaceBeforeCpp11BracedList == R.SpaceBeforeCpp11BracedList && SpaceBeforeCtorInitializerColon == R.SpaceBeforeCtorInitializerColon && + SpaceBeforeForLoopSemiColon == R.SpaceBeforeForLoopSemiColon && SpaceBeforeInheritanceColon == R.SpaceBeforeInheritanceColon && SpaceBeforeParens == R.SpaceBeforeParens && SpaceAroundPointerQualifiers == R.SpaceAroundPointerQualifiers && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -657,6 +657,8 @@ Style.SpaceBeforeCpp11BracedList); IO.mapOptional("SpaceBeforeCtorInitializerColon", Style.SpaceBeforeCtorInitializerColon); + IO.mapOptional("SpaceBeforeForLoopSemiColon", + Style.SpaceBeforeForLoopSemiColon); IO.mapOptional("SpaceBeforeInheritanceColon", Style.SpaceBeforeInheritanceColon); IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens); @@ -1026,6 +1028,7 @@ LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default; LLVMStyle.SpaceBeforeCaseColon = false; LLVMStyle.SpaceBeforeCtorInitializerColon = true; + LLVMStyle.SpaceBeforeForLoopSemiColon = false; LLVMStyle.SpaceBeforeInheritanceColon = true; LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements; LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true; diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -46,6 +46,7 @@ TYPE(DesignatedInitializerLSquare) \ TYPE(DesignatedInitializerPeriod) \ TYPE(DictLiteral) \ + TYPE(ForLoopSemiColon) \ TYPE(ForEachMacro) \ TYPE(FunctionAnnotationRParen) \ TYPE(FunctionDeclarationName) \ diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1111,6 +1111,10 @@ parseCSharpGenericTypeConstraint(); } break; + case tok::semi: + if (Contexts.back().ColonIsForRangeExpr) + Tok->setType(TT_ForLoopSemiColon); + break; default: break; } @@ -3345,6 +3349,8 @@ if (Right.is(TT_RangeBasedForLoopColon) && !Style.SpaceBeforeRangeBasedForLoopColon) return false; + if (Right.is(TT_ForLoopSemiColon) && Style.SpaceBeforeForLoopSemiColon) + return true; if (Left.is(TT_BitFieldColon)) return Style.BitFieldColonSpacing == FormatStyle::BFCS_Both || Style.BitFieldColonSpacing == FormatStyle::BFCS_After; @@ -3995,6 +4001,8 @@ return true; if (Right.is(TT_RangeBasedForLoopColon)) return false; + if (Right.is(TT_ForLoopSemiColon)) + return false; if (Left.is(TT_TemplateCloser) && Right.is(TT_TemplateOpener)) return true; if (Left.isOneOf(TT_TemplateCloser, TT_UnaryOperator) || diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -12701,6 +12701,17 @@ InvertedSpaceStyle); } +TEST_F(FormatTest, ConfigurableSpaceBeforeForLoopSemiColon) { + FormatStyle NoSpaceStyle = getLLVMStyle(); + verifyFormat("for (i = 0; i < 10; ++i) {\n}", NoSpaceStyle); + verifyFormat("for (int i = 0; auto a : b) {\n}", NoSpaceStyle); + + FormatStyle Space = getLLVMStyle(); + Space.SpaceBeforeForLoopSemiColon = true; + verifyFormat("for (i = 0 ; i < 10 ; ++i) {\n}", Space); + verifyFormat("for (int i = 0 ; auto a : b) {\n}", Space); +} + TEST_F(FormatTest, ConfigurableSpaceAroundPointerQualifiers) { FormatStyle Style = getLLVMStyle(); @@ -15610,6 +15621,7 @@ CHECK_PARSE_BOOL(SpaceBeforeCaseColon); CHECK_PARSE_BOOL(SpaceBeforeCpp11BracedList); CHECK_PARSE_BOOL(SpaceBeforeCtorInitializerColon); + CHECK_PARSE_BOOL(SpaceBeforeForLoopSemiColon); CHECK_PARSE_BOOL(SpaceBeforeInheritanceColon); CHECK_PARSE_BOOL(SpaceBeforeRangeBasedForLoopColon); CHECK_PARSE_BOOL(SpaceBeforeSquareBrackets);