diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -2336,6 +2336,19 @@ } } + * ``SBPO_ControlStatementsExceptForEachMacros`` (in configuration: ``ControlStatementsExceptForEachMacros``) + Same as ``SBPO_ControlStatements`` except this option doesn't apply to + ForEach macros. This is useful in projects where ForEach macros are + treated as function calls instead of control statements. + + .. code-block:: c++ + + void f() { + Q_FOREACH(...) { + f(); + } + } + * ``SBPO_NonEmptyParentheses`` (in configuration: ``NonEmptyParentheses``) Put a space before opening parentheses only if the parentheses are not empty i.e. '()' 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 @@ -1983,6 +1983,17 @@ /// } /// \endcode SBPO_ControlStatements, + /// Same as ``SBPO_ControlStatements`` except this option doesn't apply to + /// ForEach macros. This is useful in projects where ForEach macros are + /// treated as function calls instead of control statements. + /// \code + /// void f() { + /// Q_FOREACH(...) { + /// f(); + /// } + /// } + /// \endcode + SBPO_ControlStatementsExceptForEachMacros, /// Put a space before opening parentheses only if the parentheses are not /// empty i.e. '()' /// \code 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 @@ -329,6 +329,8 @@ IO.enumCase(Value, "Never", FormatStyle::SBPO_Never); IO.enumCase(Value, "ControlStatements", FormatStyle::SBPO_ControlStatements); + IO.enumCase(Value, "ControlStatementsExceptForEachMacros", + FormatStyle::SBPO_ControlStatementsExceptForEachMacros); IO.enumCase(Value, "NonEmptyParentheses", FormatStyle::SBPO_NonEmptyParentheses); IO.enumCase(Value, "Always", FormatStyle::SBPO_Always); 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 @@ -2900,6 +2900,10 @@ if ((Left.is(tok::r_paren) && Left.is(TT_AttributeParen)) || (Left.is(tok::r_square) && Left.is(TT_AttributeSquare))) return true; + if (Style.SpaceBeforeParens == + FormatStyle::SBPO_ControlStatementsExceptForEachMacros && + Left.is(TT_ForEachMacro)) + return false; return Line.Type == LT_ObjCDecl || Left.is(tok::semi) || (Style.SpaceBeforeParens != FormatStyle::SBPO_Never && (Left.isOneOf(tok::pp_elif, tok::kw_for, tok::kw_while, 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 @@ -972,6 +972,17 @@ " UNKNOWN_FORACH(Item * item, itemlist) {}\n" "}"); + FormatStyle Style = getLLVMStyle(); + Style.SpaceBeforeParens = + FormatStyle::SBPO_ControlStatementsExceptForEachMacros; + verifyFormat("void f() {\n" + " foreach(Item *item, itemlist) {}\n" + " Q_FOREACH(Item *item, itemlist) {}\n" + " BOOST_FOREACH(Item *item, itemlist) {}\n" + " UNKNOWN_FORACH(Item * item, itemlist) {}\n" + "}", + Style); + // As function-like macros. verifyFormat("#define foreach(x, y)\n" "#define Q_FOREACH(x, y)\n"