Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -221,6 +221,23 @@ ------------ +- Option ``IndentExternBlock`` has been added to optionally apply indenting inside extern "C" blocks. + + The ``BraceWrapping.AfterExternBlock`` option has been modified so it no longer indents when set to true, now it just wraps the braces around extern blocks. + + .. code-block:: c++ + + true: false: + #ifdef __cplusplus #ifdef __cplusplus + extern "C" { extern "C" { + #endif #endif + + void f(void); void f(void); + + #ifdef __cplusplus #ifdef __cplusplus + } } + #endif #endif + - Option ``IndentCaseBlocks`` has been added to support treating the block following a switch case label as a scope block which gets indented itself. It helps avoid having the closing bracket align with the switch statement's Index: clang/include/clang/Format/Format.h =================================================================== --- clang/include/clang/Format/Format.h +++ clang/include/clang/Format/Format.h @@ -953,7 +953,7 @@ /// true: /// extern "C" /// { - /// int foo(); + /// int foo(); /// } /// /// false: @@ -1462,6 +1462,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 @@ -2206,6 +2232,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 @@ -1114,11 +1114,9 @@ if (FormatTok->Tok.is(tok::l_brace)) { if (Style.BraceWrapping.AfterExternBlock) { addUnwrappedLine(); - parseBlock(/*MustBeDeclaration=*/true); - } else { - parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/false); } - addUnwrappedLine(); + parseBlock(/*MustBeDeclaration=*/true, + /*AddLevel=*/Style.IndentExternBlock); return; } } Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -2491,11 +2491,35 @@ Style); verifyFormat("extern \"C\"\n" "{\n" - " int foo();\n" + "int foo();\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 foo();\n}", Style); + + Style.BraceWrapping.AfterExternBlock = false; + Style.IndentExternBlock = true; + verifyFormat("extern \"C\" {}", Style); + verifyFormat("extern \"C\" {\n int foo();\n}", Style); + + Style.BraceWrapping.AfterExternBlock = true; + Style.IndentExternBlock = false; + verifyFormat("extern \"C\" {}", Style); + verifyFormat("extern \"C\" {\nint foo();\n}", Style); + + Style.BraceWrapping.AfterExternBlock = false; + Style.IndentExternBlock = false; + verifyFormat("extern \"C\" {}", Style); + verifyFormat("extern \"C\" {\nint foo();\n}", Style); +} + TEST_F(FormatTest, FormatsInlineASM) { verifyFormat("asm(\"xyz\" : \"=a\"(a), \"=d\"(b) : \"a\"(data));"); verifyFormat("asm(\"nop\" ::: \"memory\");"); @@ -12660,6 +12684,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);