Index: clang/docs/ClangFormatStyleOptions.rst =================================================================== --- clang/docs/ClangFormatStyleOptions.rst +++ clang/docs/ClangFormatStyleOptions.rst @@ -1712,6 +1712,46 @@ plop(); plop(); } } +**IndentExternBlock** (``IndentExternBlockStyle``) + IndentExternBlockStyle is the type of indenting of extern blocks. + + Possible values: + + * ``IEBS_AfterExternBlock`` (in configuration: ``AfterExternBlock``) + Backwards compatible with AfterExternBlock's indenting. + + .. code-block:: c++ + + AfterExternBlock: true + extern "C" + { + void foo(); + } + AfterExternBlock: false + extern "C" { + void foo(); + } + + * ``IEBS_NoIndent`` (in configuration: ``NoIndent``) + Does not indent extern blocks. + + .. code-block:: c++ + + extern "C" { + void foo(); + } + + * ``IEBS_Indent`` (in configuration: ``Indent``) + Indents extern blocks. + + .. code-block:: c++ + + extern "C" { + void foo(); + } + + + **IndentGotoLabels** (``bool``) Indent goto labels. Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -251,6 +251,23 @@ clang-format ------------ +- Option ``IndentExternBlock`` has been added to optionally apply indenting inside ``extern "C"`` and ``extern "C++"`` blocks. + +- ``IndentExternBlock`` option accepts ``AfterExternBlock`` to use the old behavior, as well as Indent and NoIndent options, which map to true and false, respectively. + + .. code-block:: c++ + + Indent: NoIndent: + #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 @@ -1017,7 +1017,7 @@ /// int foo(); /// } /// \endcode - bool AfterExternBlock; + bool AfterExternBlock; // Partially superseded by IndentExternBlock /// Wrap before ``catch``. /// \code /// true: @@ -1492,6 +1492,40 @@ /// The preprocessor directive indenting style to use. PPDirectiveIndentStyle IndentPPDirectives; + /// Indents extern blocks + enum IndentExternBlockStyle { + /// Backwards compatible with AfterExternBlock's indenting. + /// \code + /// AfterExternBlock: true + /// extern "C" + /// { + /// void foo(); + /// } + /// AfterExternBlock: false + /// extern "C" { + /// void foo(); + /// } + /// \endcode + IEBS_AfterExternBlock, + /// Does not indent extern blocks. + /// \code + /// extern "C" { + /// void foo(); + /// } + /// \endcode + IEBS_NoIndent, + /// Indents extern blocks. + /// \code + /// extern "C" { + /// void foo(); + /// } + /// \endcode + IEBS_Indent, + }; + + /// IndentExternBlockStyle is the type of indenting of extern blocks. + IndentExternBlockStyle IndentExternBlock; + /// The number of columns to use for indentation. /// \code /// IndentWidth: 3 @@ -2011,8 +2045,8 @@ /// \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. + /// ForEach macros. This is useful in projects where ForEach macros are + /// treated as function calls instead of control statements. /// \code /// void f() { /// Q_FOREACH(...) { @@ -2276,6 +2310,7 @@ IndentCaseBlocks == R.IndentCaseBlocks && IndentGotoLabels == R.IndentGotoLabels && IndentPPDirectives == R.IndentPPDirectives && + IndentExternBlock == R.IndentExternBlock && IndentWidth == R.IndentWidth && Language == R.Language && IndentWrappedFunctionNames == R.IndentWrappedFunctionNames && JavaImportGroups == R.JavaImportGroups && Index: clang/lib/Format/Format.cpp =================================================================== --- clang/lib/Format/Format.cpp +++ clang/lib/Format/Format.cpp @@ -234,6 +234,17 @@ } }; +template <> +struct ScalarEnumerationTraits { + static void enumeration(IO &IO, FormatStyle::IndentExternBlockStyle &Value) { + IO.enumCase(Value, "AfterExternBlock", FormatStyle::IEBS_AfterExternBlock); + IO.enumCase(Value, "Indent", FormatStyle::IEBS_Indent); + IO.enumCase(Value, "NoIndent", FormatStyle::IEBS_NoIndent); + IO.enumCase(Value, "true", FormatStyle::IEBS_Indent); + IO.enumCase(Value, "false", FormatStyle::IEBS_NoIndent); + } +}; + template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, FormatStyle::ReturnTypeBreakingStyle &Value) { @@ -510,6 +521,7 @@ IO.mapOptional("IndentCaseBlocks", Style.IndentCaseBlocks); IO.mapOptional("IndentGotoLabels", Style.IndentGotoLabels); IO.mapOptional("IndentPPDirectives", Style.IndentPPDirectives); + IO.mapOptional("IndentExternBlock", Style.IndentExternBlock); IO.mapOptional("IndentWidth", Style.IndentWidth); IO.mapOptional("IndentWrappedFunctionNames", Style.IndentWrappedFunctionNames); @@ -704,6 +716,7 @@ Expanded.BraceWrapping.AfterStruct = true; Expanded.BraceWrapping.AfterUnion = true; Expanded.BraceWrapping.AfterExternBlock = true; + Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; Expanded.BraceWrapping.SplitEmptyFunction = true; Expanded.BraceWrapping.SplitEmptyRecord = false; break; @@ -723,6 +736,7 @@ Expanded.BraceWrapping.AfterStruct = true; Expanded.BraceWrapping.AfterUnion = true; Expanded.BraceWrapping.AfterExternBlock = true; + Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; Expanded.BraceWrapping.BeforeCatch = true; Expanded.BraceWrapping.BeforeElse = true; break; @@ -736,6 +750,7 @@ Expanded.BraceWrapping.AfterObjCDeclaration = true; Expanded.BraceWrapping.AfterStruct = true; Expanded.BraceWrapping.AfterExternBlock = true; + Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; Expanded.BraceWrapping.BeforeCatch = true; Expanded.BraceWrapping.BeforeElse = true; Expanded.BraceWrapping.BeforeLambdaBody = true; @@ -747,6 +762,7 @@ true, true, true, false, true, true, true, true}; + Expanded.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; break; case FormatStyle::BS_WebKit: Expanded.BraceWrapping.AfterFunction = true; @@ -793,6 +809,7 @@ false, false, false, false, false, true, true, true}; + LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; LLVMStyle.BreakAfterJavaFieldAnnotations = false; LLVMStyle.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon; LLVMStyle.BreakInheritanceList = FormatStyle::BILS_BeforeColon; @@ -1154,6 +1171,7 @@ Style.BraceWrapping.AfterObjCDeclaration = true; Style.BraceWrapping.AfterStruct = true; Style.BraceWrapping.AfterExternBlock = true; + Style.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; Style.BraceWrapping.BeforeCatch = true; Style.BraceWrapping.BeforeElse = true; Style.PenaltyReturnTypeOnItsOwnLine = 1000; Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -1113,11 +1113,16 @@ if (FormatTok->Tok.is(tok::string_literal)) { nextToken(); if (FormatTok->Tok.is(tok::l_brace)) { - if (Style.BraceWrapping.AfterExternBlock) { - addUnwrappedLine(); - parseBlock(/*MustBeDeclaration=*/true); + if (!Style.IndentExternBlock) { + if (Style.BraceWrapping.AfterExternBlock) { + addUnwrappedLine(); + } + parseBlock(/*MustBeDeclaration=*/true, + /*AddLevel=*/Style.BraceWrapping.AfterExternBlock); } else { - parseBlock(/*MustBeDeclaration=*/true, /*AddLevel=*/false); + parseBlock(/*MustBeDeclaration=*/true, + /*AddLevel=*/Style.IndentExternBlock == + FormatStyle::IEBS_Indent); } addUnwrappedLine(); return; Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -2539,6 +2539,43 @@ Style); } +TEST_F(FormatTest, IndentExternBlockStyle) { + FormatStyle Style = getLLVMStyle(); + Style.IndentWidth = 2; + + Style.IndentExternBlock = FormatStyle::IEBS_Indent; + verifyFormat("extern \"C\" { /*9*/\n}", Style); + verifyFormat("extern \"C\" {\n" + " int foo10();\n" + "}", + Style); + + Style.IndentExternBlock = FormatStyle::IEBS_NoIndent; + verifyFormat("extern \"C\" { /*11*/\n}", Style); + verifyFormat("extern \"C\" {\n" + "int foo12();\n" + "}", + Style); + + Style.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterExternBlock = true; + verifyFormat("extern \"C\"\n{ /*13*/\n}", Style); + verifyFormat("extern \"C\"\n{\n" + " int foo14();\n" + "}", + Style); + + Style.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock; + Style.BreakBeforeBraces = FormatStyle::BS_Custom; + Style.BraceWrapping.AfterExternBlock = false; + verifyFormat("extern \"C\" { /*15*/\n}", Style); + verifyFormat("extern \"C\" {\n" + "int foo16();\n" + "}", + Style); +} + TEST_F(FormatTest, FormatsInlineASM) { verifyFormat("asm(\"xyz\" : \"=a\"(a), \"=d\"(b) : \"a\"(data));"); verifyFormat("asm(\"nop\" ::: \"memory\");"); @@ -13716,6 +13753,18 @@ AllowShortIfStatementsOnASingleLine, FormatStyle::SIS_WithoutElse); + Style.IndentExternBlock = FormatStyle::IEBS_NoIndent; + CHECK_PARSE("IndentExternBlock: AfterExternBlock", IndentExternBlock, + FormatStyle::IEBS_AfterExternBlock); + CHECK_PARSE("IndentExternBlock: Indent", IndentExternBlock, + FormatStyle::IEBS_Indent); + CHECK_PARSE("IndentExternBlock: NoIndent", IndentExternBlock, + FormatStyle::IEBS_NoIndent); + CHECK_PARSE("IndentExternBlock: true", IndentExternBlock, + FormatStyle::IEBS_Indent); + CHECK_PARSE("IndentExternBlock: false", IndentExternBlock, + FormatStyle::IEBS_NoIndent); + // FIXME: This is required because parsing a configuration simply overwrites // the first N elements of the list instead of resetting it. Style.ForEachMacros.clear();