Index: clang/include/clang/Format/Format.h =================================================================== --- clang/include/clang/Format/Format.h +++ clang/include/clang/Format/Format.h @@ -1485,6 +1485,32 @@ /// \endcode bool IndentWrappedFunctionNames; + /// Indent extern blocks; indent size = IndentWidth + /// \code + /// true: + /// #ifdef __cplusplus + /// extern "C" { + /// #endif + /// + /// void f(void); + /// + /// #ifdef __cplusplus + /// } + /// #endif + /// + /// false: + /// #ifdef __cplusplus + /// extern "C" { + /// #endif + /// + /// void f(void); + /// + /// #ifdef __cplusplus + /// } + /// #endif + /// \endcode + bool IndentExternBlock; + /// A vector of prefixes ordered by the desired groups for Java imports. /// /// Each group is separated by a newline. Static imports will also follow the @@ -2229,6 +2255,7 @@ IndentPPDirectives == R.IndentPPDirectives && IndentWidth == R.IndentWidth && Language == R.Language && IndentWrappedFunctionNames == R.IndentWrappedFunctionNames && + IndentExternBlock == R.IndentExternBlock && JavaImportGroups == R.JavaImportGroups && JavaScriptQuotes == R.JavaScriptQuotes && JavaScriptWrapImports == R.JavaScriptWrapImports && Index: clang/lib/Format/Format.cpp =================================================================== --- clang/lib/Format/Format.cpp +++ clang/lib/Format/Format.cpp @@ -493,6 +493,7 @@ IO.mapOptional("IndentWidth", Style.IndentWidth); IO.mapOptional("IndentWrappedFunctionNames", Style.IndentWrappedFunctionNames); + IO.mapOptional("IndentExternBlock", Style.IndentExternBlock); IO.mapOptional("InsertTrailingCommas", Style.InsertTrailingCommas); IO.mapOptional("JavaImportGroups", Style.JavaImportGroups); IO.mapOptional("JavaScriptQuotes", Style.JavaScriptQuotes); @@ -801,6 +802,7 @@ LLVMStyle.IndentGotoLabels = true; LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None; LLVMStyle.IndentWrappedFunctionNames = false; + LLVMStyle.IndentExternBlock = false; LLVMStyle.IndentWidth = 2; LLVMStyle.InsertTrailingCommas = FormatStyle::TCS_None; LLVMStyle.JavaScriptQuotes = FormatStyle::JSQS_Leave; @@ -888,6 +890,7 @@ GoogleStyle.IncludeStyle.IncludeIsMainRegex = "([-_](test|unittest))?$"; GoogleStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; GoogleStyle.IndentCaseLabels = true; + GoogleStyle.IndentExternBlock = false; GoogleStyle.KeepEmptyLinesAtTheStartOfBlocks = false; GoogleStyle.ObjCBinPackProtocolList = FormatStyle::BPS_Never; GoogleStyle.ObjCSpaceAfterProperty = false; @@ -1023,6 +1026,7 @@ ChromiumStyle.BreakAfterJavaFieldAnnotations = true; ChromiumStyle.ContinuationIndentWidth = 8; ChromiumStyle.IndentWidth = 4; + ChromiumStyle.IndentExternBlock = false; // See styleguide for import groups: // https://chromium.googlesource.com/chromium/src/+/master/styleguide/java/java.md#Import-Order ChromiumStyle.JavaImportGroups = { @@ -1072,6 +1076,7 @@ MozillaStyle.Cpp11BracedListStyle = false; MozillaStyle.FixNamespaceComments = false; MozillaStyle.IndentCaseLabels = true; + MozillaStyle.IndentExternBlock = false; MozillaStyle.ObjCSpaceAfterProperty = true; MozillaStyle.ObjCSpaceBeforeProtocolList = false; MozillaStyle.PenaltyReturnTypeOnItsOwnLine = 200; @@ -1094,6 +1099,7 @@ Style.ColumnLimit = 0; Style.FixNamespaceComments = false; Style.IndentWidth = 4; + Style.IndentExternBlock = true; Style.NamespaceIndentation = FormatStyle::NI_Inner; Style.ObjCBlockIndentWidth = 4; Style.ObjCSpaceAfterProperty = true; @@ -1113,6 +1119,7 @@ Style.Cpp11BracedListStyle = false; Style.ColumnLimit = 79; Style.FixNamespaceComments = false; + Style.IndentExternBlock = false; Style.SpaceBeforeParens = FormatStyle::SBPO_Always; Style.Standard = FormatStyle::LS_Cpp03; return Style; @@ -1123,6 +1130,7 @@ Style.ColumnLimit = 120; Style.TabWidth = 4; Style.IndentWidth = 4; + Style.IndentExternBlock = false; Style.UseTab = FormatStyle::UT_Never; Style.BreakBeforeBraces = FormatStyle::BS_Custom; Style.BraceWrapping.AfterClass = true; Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -1085,10 +1085,21 @@ if (FormatTok->Tok.is(tok::string_literal)) { nextToken(); if (FormatTok->Tok.is(tok::l_brace)) { - if (Style.BraceWrapping.AfterExternBlock) { - parseBlock(/*MustBeDeclaration=*/true); - } else { + if (Style.BraceWrapping.AfterExternBlock == true && + Style.IndentExternBlock == true) { + addUnwrappedLine(); + parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/true); + } else if (Style.BraceWrapping.AfterExternBlock == false && + Style.IndentExternBlock == false) { parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/false); + } else if (Style.BraceWrapping.AfterExternBlock == false && + Style.IndentExternBlock == true) { + parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/true); + } else if (Style.BraceWrapping.AfterExternBlock == true && + Style.IndentExternBlock == false) { + addUnwrappedLine(); + parseBlock(/*MustBeDeclaration=*/true, + /*AddLevel=*/false); } addUnwrappedLine(); return; Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -2436,14 +2436,14 @@ } TEST_F(FormatTest, FormatsExternC) { - verifyFormat("extern \"C\" {\nint a;"); + verifyFormat("extern \"C\" {\nint a; /*2.1*/"); verifyFormat("extern \"C\" {}"); verifyFormat("extern \"C\" {\n" - "int foo();\n" + "int FormatsExternC_1();\n" "}"); - verifyFormat("extern \"C\" int foo() {}"); - verifyFormat("extern \"C\" int foo();"); - verifyFormat("extern \"C\" int foo() {\n" + verifyFormat("extern \"C\" int FormatsExternC_2() {}"); + verifyFormat("extern \"C\" int FormatsExternC_3();"); + verifyFormat("extern \"C\" int FormatsExternC_4() {\n" " int i = 42;\n" " return i;\n" "}"); @@ -2451,9 +2451,9 @@ 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" + verifyFormat("extern \"C\" int FormatsExternC_5() {}", Style); + verifyFormat("extern \"C\" int FormatsExternC_6();", Style); + verifyFormat("extern \"C\" int FormatsExternC_7()\n" "{\n" " int i = 42;\n" " return i;\n" @@ -2462,20 +2462,41 @@ Style.BraceWrapping.AfterExternBlock = true; Style.BraceWrapping.SplitEmptyRecord = false; - verifyFormat("extern \"C\" {}", Style); - verifyFormat("extern \"C\" {\n" - " int foo();\n" - "}", - Style); + verifyFormat("extern \"C\"\n{}", Style); + verifyFormat("extern \"C\"\n{\nint FormatsExternC_8();\n}", Style); Style.BraceWrapping.AfterExternBlock = false; verifyFormat("extern \"C\" {}", Style); verifyFormat("extern \"C\" {\n" - "int foo();\n" + "int FormatsExternC_9();\n" "}", Style); } +TEST_F(FormatTest, FormatsExternBlock) { + FormatStyle Style = getLLVMStyle(); + Style.IndentWidth = 2; + Style.BraceWrapping.AfterExternBlock = true; + Style.IndentExternBlock = true; + verifyFormat("extern \"C\" {}", Style); + verifyFormat("extern \"C\" {\n int FormatsExternBlock_1();\n}", Style); + + Style.BraceWrapping.AfterExternBlock = false; + Style.IndentExternBlock = true; + verifyFormat("extern \"C\" {}", Style); + verifyFormat("extern \"C\" {\n int FormatsExternBlock_2();\n}", Style); + + Style.BraceWrapping.AfterExternBlock = true; + Style.IndentExternBlock = false; + verifyFormat("extern \"C\" {}", Style); + verifyFormat("extern \"C\" {\nint FormatsExternBlock_3();\n}", Style); + + Style.BraceWrapping.AfterExternBlock = false; + Style.IndentExternBlock = false; + verifyFormat("extern \"C\" {}", Style); + verifyFormat("extern \"C\" {\nint FormatsExternBlock_4();\n}", Style); +} + TEST_F(FormatTest, FormatsInlineASM) { verifyFormat("asm(\"xyz\" : \"=a\"(a), \"=d\"(b) : \"a\"(data));"); verifyFormat("asm(\"nop\" ::: \"memory\");"); @@ -12640,6 +12661,7 @@ CHECK_PARSE_BOOL(IndentCaseBlocks); CHECK_PARSE_BOOL(IndentGotoLabels); CHECK_PARSE_BOOL(IndentWrappedFunctionNames); + CHECK_PARSE_BOOL(IndentExternBlock); CHECK_PARSE_BOOL(KeepEmptyLinesAtTheStartOfBlocks); CHECK_PARSE_BOOL(ObjCSpaceAfterProperty); CHECK_PARSE_BOOL(ObjCSpaceBeforeProtocolList);