summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrasimir Georgiev <krasimir@google.com>2017-09-15 11:23:50 +0000
committerKrasimir Georgiev <krasimir@google.com>2017-09-15 11:23:50 +0000
commit57065b2de4d945670107a164ea557cdfd94643b7 (patch)
tree61c7027c8cd6687150ab6f3d9fb996c4ff5e0add
parent6d42a101dd0232c99d2358145f7d77e4de68596b (diff)
[clang-format] New flag - BraceWrapping.AfterExternBlock
Summary: Bug: https://bugs.llvm.org/show_bug.cgi?id=34016 - **"extern C part"** **Problem:** Due to the lack of "brace wrapping extern" flag, clang format does parse the block after **extern** keyword moving the opening bracket to the header line always! **Patch description:** A new style added, new configuration flag - **BraceWrapping.AfterExternBlock** that allows us to decide whether we want a break before brace or not. Reviewers: djasper, krasimir Reviewed By: krasimir Subscribers: klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D37845 Contributed by @PriMee! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@313354 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--docs/ClangFormatStyleOptions.rst15
-rw-r--r--include/clang/Format/Format.h14
-rw-r--r--lib/Format/Format.cpp21
-rw-r--r--lib/Format/UnwrappedLineFormatter.cpp5
-rw-r--r--lib/Format/UnwrappedLineParser.cpp7
-rw-r--r--unittests/Format/FormatTest.cpp38
6 files changed, 87 insertions, 13 deletions
diff --git a/docs/ClangFormatStyleOptions.rst b/docs/ClangFormatStyleOptions.rst
index 7b5ce52f51..48accc753a 100644
--- a/docs/ClangFormatStyleOptions.rst
+++ b/docs/ClangFormatStyleOptions.rst
@@ -661,6 +661,21 @@ the configuration (without a prefix: ``Auto``).
int x;
}
+ * ``bool AfterExternBlock`` Wrap extern blocks.
+
+ .. code-block:: c++
+
+ true:
+ extern "C"
+ {
+ int foo();
+ }
+
+ false:
+ extern "C" {
+ int foo();
+ }
+
* ``bool BeforeCatch`` Wrap before ``catch``.
.. code-block:: c++
diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h
index 44f027ce81..302ced3f78 100644
--- a/include/clang/Format/Format.h
+++ b/include/clang/Format/Format.h
@@ -681,6 +681,20 @@ struct FormatStyle {
/// }
/// \endcode
bool AfterUnion;
+ /// \brief Wrap extern blocks.
+ /// \code
+ /// true:
+ /// extern "C"
+ /// {
+ /// int foo();
+ /// }
+ ///
+ /// false:
+ /// extern "C" {
+ /// int foo();
+ /// }
+ /// \endcode
+ bool AfterExternBlock;
/// \brief Wrap before ``catch``.
/// \code
/// true:
diff --git a/lib/Format/Format.cpp b/lib/Format/Format.cpp
index bacf92a86e..8663faf9e1 100644
--- a/lib/Format/Format.cpp
+++ b/lib/Format/Format.cpp
@@ -420,6 +420,7 @@ template <> struct MappingTraits<FormatStyle::BraceWrappingFlags> {
IO.mapOptional("AfterObjCDeclaration", Wrapping.AfterObjCDeclaration);
IO.mapOptional("AfterStruct", Wrapping.AfterStruct);
IO.mapOptional("AfterUnion", Wrapping.AfterUnion);
+ IO.mapOptional("AfterExternBlock", Wrapping.AfterExternBlock);
IO.mapOptional("BeforeCatch", Wrapping.BeforeCatch);
IO.mapOptional("BeforeElse", Wrapping.BeforeElse);
IO.mapOptional("IndentBraces", Wrapping.IndentBraces);
@@ -500,9 +501,9 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
if (Style.BreakBeforeBraces == FormatStyle::BS_Custom)
return Style;
FormatStyle Expanded = Style;
- Expanded.BraceWrapping = {false, false, false, false, false, false,
- false, false, false, false, false, true,
- true, true};
+ Expanded.BraceWrapping = {false, false, false, false, false, false,
+ false, false, false, false, false, false,
+ true, true, true};
switch (Style.BreakBeforeBraces) {
case FormatStyle::BS_Linux:
Expanded.BraceWrapping.AfterClass = true;
@@ -515,6 +516,7 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
Expanded.BraceWrapping.AfterFunction = true;
Expanded.BraceWrapping.AfterStruct = true;
Expanded.BraceWrapping.AfterUnion = true;
+ Expanded.BraceWrapping.AfterExternBlock = true;
Expanded.BraceWrapping.SplitEmptyFunction = true;
Expanded.BraceWrapping.SplitEmptyRecord = false;
break;
@@ -531,13 +533,14 @@ static FormatStyle expandPresets(const FormatStyle &Style) {
Expanded.BraceWrapping.AfterNamespace = true;
Expanded.BraceWrapping.AfterObjCDeclaration = true;
Expanded.BraceWrapping.AfterStruct = true;
+ Expanded.BraceWrapping.AfterExternBlock = true;
Expanded.BraceWrapping.BeforeCatch = true;
Expanded.BraceWrapping.BeforeElse = true;
break;
case FormatStyle::BS_GNU:
- Expanded.BraceWrapping = {true, true, true, true, true, true,
- true, true, true, true, true, true,
- true, true};
+ Expanded.BraceWrapping = {true, true, true, true, true, true,
+ true, true, true, true, true, true,
+ true, true, true};
break;
case FormatStyle::BS_WebKit:
Expanded.BraceWrapping.AfterFunction = true;
@@ -573,9 +576,9 @@ FormatStyle getLLVMStyle() {
LLVMStyle.BreakBeforeBinaryOperators = FormatStyle::BOS_None;
LLVMStyle.BreakBeforeTernaryOperators = true;
LLVMStyle.BreakBeforeBraces = FormatStyle::BS_Attach;
- LLVMStyle.BraceWrapping = {false, false, false, false, false, false,
- false, false, false, false, false, true,
- true, true};
+ LLVMStyle.BraceWrapping = {false, false, false, false, false, false,
+ false, false, false, false, false, false,
+ true, true, true};
LLVMStyle.BreakAfterJavaFieldAnnotations = false;
LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
LLVMStyle.BreakBeforeInheritanceComma = false;
diff --git a/lib/Format/UnwrappedLineFormatter.cpp b/lib/Format/UnwrappedLineFormatter.cpp
index 8dbfdda497..ff98008e85 100644
--- a/lib/Format/UnwrappedLineFormatter.cpp
+++ b/lib/Format/UnwrappedLineFormatter.cpp
@@ -233,9 +233,10 @@ private:
if (Tok && Tok->is(tok::kw_typedef))
Tok = Tok->getNextNonComment();
if (Tok && Tok->isOneOf(tok::kw_class, tok::kw_struct, tok::kw_union,
- Keywords.kw_interface))
+ tok::kw_extern, Keywords.kw_interface))
return !Style.BraceWrapping.SplitEmptyRecord && EmptyBlock
- ? tryMergeSimpleBlock(I, E, Limit) : 0;
+ ? tryMergeSimpleBlock(I, E, Limit)
+ : 0;
}
// FIXME: TheLine->Level != 0 might or might not be the right check to do.
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index b15e52aeb2..40d133ff0d 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -1039,7 +1039,12 @@ void UnwrappedLineParser::parseStructuralElement() {
if (FormatTok->Tok.is(tok::string_literal)) {
nextToken();
if (FormatTok->Tok.is(tok::l_brace)) {
- parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/false);
+ if (Style.BraceWrapping.AfterExternBlock) {
+ addUnwrappedLine();
+ parseBlock(/*MustBeDeclaration=*/true);
+ } else {
+ parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/false);
+ }
addUnwrappedLine();
return;
}
diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp
index c7685c6cfc..e974550f22 100644
--- a/unittests/Format/FormatTest.cpp
+++ b/unittests/Format/FormatTest.cpp
@@ -1704,7 +1704,42 @@ TEST_F(FormatTest, FormatsCompactNamespaces) {
Style));
}
-TEST_F(FormatTest, FormatsExternC) { verifyFormat("extern \"C\" {\nint a;"); }
+TEST_F(FormatTest, FormatsExternC) {
+ verifyFormat("extern \"C\" {\nint a;");
+ verifyFormat("extern \"C\" {}");
+ verifyFormat("extern \"C\" {\n"
+ "int foo();\n"
+ "}");
+ verifyFormat("extern \"C\" int foo() {}");
+ verifyFormat("extern \"C\" int foo();");
+ verifyFormat("extern \"C\" int foo() {\n"
+ " int i = 42;\n"
+ " return i;\n"
+ "}");
+
+ FormatStyle Style = getLLVMStyle();
+ Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+ Style.BraceWrapping.AfterFunction = true;
+ verifyFormat("extern \"C\" int foo() {}", Style);
+ verifyFormat("extern \"C\" int foo();", Style);
+ verifyFormat("extern \"C\" int foo()\n"
+ "{\n"
+ " int i = 42;\n"
+ " return i;\n"
+ "}",
+ Style);
+
+ Style.BraceWrapping.AfterExternBlock = true;
+ Style.BraceWrapping.SplitEmptyRecord = false;
+ verifyFormat("extern \"C\"\n"
+ "{}",
+ Style);
+ verifyFormat("extern \"C\"\n"
+ "{\n"
+ " int foo();\n"
+ "}",
+ Style);
+}
TEST_F(FormatTest, FormatsInlineASM) {
verifyFormat("asm(\"xyz\" : \"=a\"(a), \"=d\"(b) : \"a\"(data));");
@@ -9979,6 +10014,7 @@ TEST_F(FormatTest, ParsesConfigurationBools) {
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterObjCDeclaration);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterStruct);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterUnion);
+ CHECK_PARSE_NESTED_BOOL(BraceWrapping, AfterExternBlock);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeCatch);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, BeforeElse);
CHECK_PARSE_NESTED_BOOL(BraceWrapping, IndentBraces);