crayroud created this revision.
crayroud added reviewers: aaron.ballman, rsmith.
crayroud added projects: clang, clang-format.
crayroud requested review of this revision.
For some projects the coding style defined requires to have a space before
opening parentheses for function definitions.
This revision adds the
ControlStatementsAndFunctionDefinitionsExceptControlMacros option to
SpaceBeforeParens which act as SBPO_ControlStatementsExceptControlMacros but
also put a space before opening parentheses for function definitions.
The goal of this commit is too add the support of clang-format to these
projects.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D110833
Files:
clang/docs/ClangFormatStyleOptions.rst
clang/include/clang/Format/Format.h
clang/lib/Format/Format.cpp
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTest.cpp
Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -2117,6 +2117,13 @@
"}",
Style);
+ Style.SpaceBeforeParens = FormatStyle::
+ SBPO_ControlStatementsAndFunctionDefinitionsExceptControlMacros;
+ verifyFormat("void f () {\n"
+ " Q_FOREACH(Item *item, itemlist) {}\n"
+ "}",
+ Style);
+
// As function-like macros.
verifyFormat("#define foreach(x, y)\n"
"#define Q_FOREACH(x, y)\n"
@@ -14133,6 +14140,62 @@
verifyFormat("X A::operator++ (T);", SomeSpace);
verifyFormat("int x = int (y);", SomeSpace);
verifyFormat("auto lambda = []() { return 0; };", SomeSpace);
+
+ FormatStyle SomeSpace2 = getLLVMStyle();
+ SomeSpace2.SpaceBeforeParens = FormatStyle::
+ SBPO_ControlStatementsAndFunctionDefinitionsExceptControlMacros;
+
+ verifyFormat("int f();", SomeSpace2);
+ verifyFormat("void f (int a, T b) {\n"
+ " while (true)\n"
+ " continue;\n"
+ "}",
+ SomeSpace2);
+ verifyFormat("if (true)\n"
+ " f();\n"
+ "else if (true)\n"
+ " f();",
+ SomeSpace2);
+ verifyFormat("do {\n"
+ " do_something();\n"
+ "} while (something());",
+ SomeSpace2);
+ verifyFormat("switch (x) {\n"
+ "default:\n"
+ " break;\n"
+ "}",
+ SomeSpace2);
+ verifyFormat("A::A () : a(1) {}", SomeSpace2);
+ verifyFormat("void f() __attribute__((asdf));", SomeSpace2);
+ verifyFormat("*(&a + 1);\n"
+ "&((&a)[1]);\n"
+ "a[(b + c) * d];\n"
+ "(((a + 1) * 2) + 3) * 4;",
+ SomeSpace2);
+ verifyFormat("#define A(x) x", SomeSpace2);
+ verifyFormat("#define A (x) x", SomeSpace2);
+ verifyFormat("#if defined(x)\n"
+ "#endif",
+ SomeSpace2);
+ verifyFormat("auto i = std::make_unique<int>(5);", SomeSpace2);
+ verifyFormat("size_t x = sizeof(x);", SomeSpace2);
+ verifyFormat("auto f(int x) -> decltype(x);", SomeSpace2);
+ verifyFormat("auto f(int x) -> typeof(x);", SomeSpace2);
+ verifyFormat("auto f(int x) -> _Atomic(x);", SomeSpace2);
+ verifyFormat("auto f(int x) -> __underlying_type(x);", SomeSpace2);
+ verifyFormat("int f(T x) noexcept(x.create());", SomeSpace2);
+ verifyFormat("alignas(128) char a[128];", SomeSpace2);
+ verifyFormat("size_t x = alignof(MyType);", SomeSpace2);
+ verifyFormat("static_assert(sizeof(char) == 1, \"Impossible!\");",
+ SomeSpace2);
+ verifyFormat("int f() throw(Deprecated);", SomeSpace2);
+ verifyFormat("typedef void (*cb)(int);", SomeSpace2);
+ verifyFormat("T A::operator()();", SomeSpace2);
+ verifyFormat("X A::operator++(T);", SomeSpace2);
+ verifyFormat("auto lambda = []() { return 0; };", SomeSpace2);
+ verifyFormat("int x = int(y);", SomeSpace2);
+ verifyFormat("M (std::size_t R, std::size_t C) : C(C), data(R) {}",
+ SomeSpace2);
}
TEST_F(FormatTest, SpaceAfterLogicalNot) {
Index: clang/lib/Format/TokenAnnotator.cpp
===================================================================
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -3138,12 +3138,18 @@
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_ControlStatementsExceptControlMacros &&
+ if ((Style.SpaceBeforeParens ==
+ FormatStyle::SBPO_ControlStatementsExceptControlMacros ||
+ Style.SpaceBeforeParens ==
+ FormatStyle::
+ SBPO_ControlStatementsAndFunctionDefinitionsExceptControlMacros) &&
Left.is(TT_ForEachMacro))
return false;
- if (Style.SpaceBeforeParens ==
- FormatStyle::SBPO_ControlStatementsExceptControlMacros &&
+ if ((Style.SpaceBeforeParens ==
+ FormatStyle::SBPO_ControlStatementsExceptControlMacros ||
+ Style.SpaceBeforeParens ==
+ FormatStyle::
+ SBPO_ControlStatementsAndFunctionDefinitionsExceptControlMacros) &&
Left.is(TT_IfMacro))
return false;
return Line.Type == LT_ObjCDecl || Left.is(tok::semi) ||
@@ -3440,6 +3446,26 @@
if (Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow) ||
Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow))
return true;
+ if (Right.is(tok::l_paren) && Line.MightBeFunctionDecl) {
+ if (Style.SpaceBeforeParens ==
+ FormatStyle::
+ SBPO_ControlStatementsAndFunctionDefinitionsExceptControlMacros) {
+ // Find in the line if there was another set of parenthesis,
+ // indeed we want to add a space only before the first one
+ bool IsFirstLParen = true;
+ const FormatToken *Tok = Right.Previous;
+ while (Tok) {
+ if (Tok->is(tok::r_paren)) {
+ IsFirstLParen = false;
+ break;
+ }
+ Tok = Tok->Previous;
+ }
+ if (IsFirstLParen && Line.mightBeFunctionDefinition()) {
+ return true;
+ }
+ }
+ }
if (Right.is(TT_OverloadedOperatorLParen))
return spaceRequiredBeforeParens(Right);
if (Left.is(tok::comma))
Index: clang/lib/Format/Format.cpp
===================================================================
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -459,6 +459,10 @@
FormatStyle::SBPO_ControlStatements);
IO.enumCase(Value, "ControlStatementsExceptControlMacros",
FormatStyle::SBPO_ControlStatementsExceptControlMacros);
+ IO.enumCase(
+ Value, "ControlStatementsAndFunctionDefinitionsExceptControlMacros",
+ FormatStyle::
+ SBPO_ControlStatementsAndFunctionDefinitionsExceptControlMacros);
IO.enumCase(Value, "NonEmptyParentheses",
FormatStyle::SBPO_NonEmptyParentheses);
IO.enumCase(Value, "Always", FormatStyle::SBPO_Always);
Index: clang/include/clang/Format/Format.h
===================================================================
--- clang/include/clang/Format/Format.h
+++ clang/include/clang/Format/Format.h
@@ -3286,6 +3286,19 @@
/// }
/// \endcode
SBPO_ControlStatementsExceptControlMacros,
+ /// Same as ``SBPO_ControlStatementsExceptControlMacros`` but also put a
+ /// space before opening parentheses for function definitions.
+ /// \code
+ /// void f();
+ /// void f () {
+ /// if (true) {
+ /// Q_FOREACH(...) {
+ /// f();
+ /// }
+ /// }
+ /// }
+ /// \endcode
+ SBPO_ControlStatementsAndFunctionDefinitionsExceptControlMacros,
/// Put a space before opening parentheses only if the parentheses are not
/// empty i.e. '()'
/// \code
Index: clang/docs/ClangFormatStyleOptions.rst
===================================================================
--- clang/docs/ClangFormatStyleOptions.rst
+++ clang/docs/ClangFormatStyleOptions.rst
@@ -3656,6 +3656,21 @@
}
}
+ * ``SBPO_ControlStatementsAndFunctionDefinitionsExceptControlMacros`` (in configuration: ``ControlStatementsAndFunctionDefinitionsExceptControlMacros``)
+ Same as ``SBPO_ControlStatementsExceptControlMacros`` but also put a
+ space before opening parentheses for function definitions.
+
+ .. code-block:: c++
+
+ void f();
+ void f () {
+ if (true) {
+ Q_FOREACH(...) {
+ f();
+ }
+ }
+ }
+
* ``SBPO_NonEmptyParentheses`` (in configuration: ``NonEmptyParentheses``)
Put a space before opening parentheses only if the parentheses are not
empty i.e. '()'
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits