[clang] 8b5331f - [clang-format] Update goto label indentation styles (#180109)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Mar 8 08:45:51 PDT 2026
Author: Ezlanding1
Date: 2026-03-08T16:45:47+01:00
New Revision: 8b5331f06f5e58dcb99fd8ebd75d209975f714b7
URL: https://github.com/llvm/llvm-project/commit/8b5331f06f5e58dcb99fd8ebd75d209975f714b7
DIFF: https://github.com/llvm/llvm-project/commit/8b5331f06f5e58dcb99fd8ebd75d209975f714b7.diff
LOG: [clang-format] Update goto label indentation styles (#180109)
Updates the goto label indentation styles based on the feature request.
Resolves #24492.
Added:
Modified:
clang/docs/ClangFormatStyleOptions.rst
clang/include/clang/Format/Format.h
clang/lib/Format/Format.cpp
clang/lib/Format/UnwrappedLineFormatter.cpp
clang/lib/Format/UnwrappedLineParser.cpp
clang/lib/Format/UnwrappedLineParser.h
clang/unittests/Format/ConfigParseTest.cpp
clang/unittests/Format/FormatTest.cpp
Removed:
################################################################################
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index b72481c7fd27b..e869afbcaef6f 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -4613,22 +4613,70 @@ the configuration (without a prefix: ``Auto``).
.. _IndentGotoLabels:
-**IndentGotoLabels** (``Boolean``) :versionbadge:`clang-format 10` :ref:`¶ <IndentGotoLabels>`
- Indent goto labels.
+**IndentGotoLabels** (``IndentGotoLabelStyle``) :versionbadge:`clang-format 10` :ref:`¶ <IndentGotoLabels>`
+ The goto label indenting style to use.
- When ``false``, goto labels are flushed left.
+ Possible values:
+
+ * ``IGLS_NoIndent`` (in configuration: ``NoIndent``)
+ Do not indent goto labels.
+
+ .. code-block:: c++
+
+ int f() {
+ if (foo()) {
+ label1:
+ bar();
+ }
+ label2:
+ return 1;
+ }
+
+ * ``IGLS_OuterIndent`` (in configuration: ``OuterIndent``)
+ Indent goto labels to the enclosing block (previous indenting level).
+
+ .. code-block:: c++
+
+ int f() {
+ if (foo()) {
+ label1:
+ bar();
+ }
+ label2:
+ return 1;
+ }
+
+ * ``IGLS_InnerIndent`` (in configuration: ``InnerIndent``)
+ Indent goto labels to the surrounding statements (current indenting
+ level).
+
+ .. code-block:: c++
+
+ int f() {
+ if (foo()) {
+ label1:
+ bar();
+ }
+ label2:
+ return 1;
+ }
+
+ * ``IGLS_HalfIndent`` (in configuration: ``HalfIndent``)
+ Indent goto labels to half the indentation of the surrounding code.
+ If the indentation width is an odd number, it will round up.
+
+ .. code-block:: c++
+
+ int f() {
+ if (foo()) {
+ label1:
+ bar();
+ }
+ label2:
+ return 1;
+ }
- .. code-block:: c++
- true: false:
- int f() { vs. int f() {
- if (foo()) { if (foo()) {
- label1: label1:
- bar(); bar();
- } }
- label2: label2:
- return 1; return 1;
- } }
.. _IndentPPDirectives:
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index a18987113938a..aea18a836328f 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -3160,22 +3160,63 @@ struct FormatStyle {
/// \version 11
IndentExternBlockStyle IndentExternBlock;
- /// Indent goto labels.
- ///
- /// When ``false``, goto labels are flushed left.
- /// \code
- /// true: false:
- /// int f() { vs. int f() {
- /// if (foo()) { if (foo()) {
- /// label1: label1:
- /// bar(); bar();
- /// } }
- /// label2: label2:
- /// return 1; return 1;
- /// } }
- /// \endcode
+ /// Options for indenting goto labels.
+ enum IndentGotoLabelStyle : int8_t {
+ /// Do not indent goto labels.
+ /// \code
+ /// int f() {
+ /// if (foo()) {
+ /// label1:
+ /// bar();
+ /// }
+ /// label2:
+ /// return 1;
+ /// }
+ /// \endcode
+ IGLS_NoIndent,
+ /// Indent goto labels to the enclosing block (previous indenting level).
+ /// \code
+ /// int f() {
+ /// if (foo()) {
+ /// label1:
+ /// bar();
+ /// }
+ /// label2:
+ /// return 1;
+ /// }
+ /// \endcode
+ IGLS_OuterIndent,
+ /// Indent goto labels to the surrounding statements (current indenting
+ /// level).
+ /// \code
+ /// int f() {
+ /// if (foo()) {
+ /// label1:
+ /// bar();
+ /// }
+ /// label2:
+ /// return 1;
+ /// }
+ /// \endcode
+ IGLS_InnerIndent,
+ /// Indent goto labels to half the indentation of the surrounding code.
+ /// If the indentation width is an odd number, it will round up.
+ /// \code
+ /// int f() {
+ /// if (foo()) {
+ /// label1:
+ /// bar();
+ /// }
+ /// label2:
+ /// return 1;
+ /// }
+ /// \endcode
+ IGLS_HalfIndent,
+ };
+
+ /// The goto label indenting style to use.
/// \version 10
- bool IndentGotoLabels;
+ IndentGotoLabelStyle IndentGotoLabels;
/// Options for indenting preprocessor directives.
enum PPDirectiveIndentStyle : int8_t {
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index c7eaca2091913..47be33299eadb 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1525,6 +1525,20 @@ template <> struct DocumentListTraits<std::vector<FormatStyle>> {
return Seq[Index];
}
};
+
+template <> struct ScalarEnumerationTraits<FormatStyle::IndentGotoLabelStyle> {
+ static void enumeration(IO &IO, FormatStyle::IndentGotoLabelStyle &Value) {
+ IO.enumCase(Value, "NoIndent", FormatStyle::IGLS_NoIndent);
+ IO.enumCase(Value, "OuterIndent", FormatStyle::IGLS_OuterIndent);
+ IO.enumCase(Value, "InnerIndent", FormatStyle::IGLS_InnerIndent);
+ IO.enumCase(Value, "HalfIndent", FormatStyle::IGLS_HalfIndent);
+
+ // For backward compatibility.
+ IO.enumCase(Value, "false", FormatStyle::IGLS_NoIndent);
+ IO.enumCase(Value, "true", FormatStyle::IGLS_OuterIndent);
+ }
+};
+
} // namespace yaml
} // namespace llvm
@@ -1819,7 +1833,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.IndentCaseLabels = false;
LLVMStyle.IndentExportBlock = true;
LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
- LLVMStyle.IndentGotoLabels = true;
+ LLVMStyle.IndentGotoLabels = FormatStyle::IGLS_OuterIndent;
LLVMStyle.IndentPPDirectives = FormatStyle::PPDIS_None;
LLVMStyle.IndentRequiresClause = true;
LLVMStyle.IndentWidth = 2;
diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp
index 8589aa83f6c55..74c0f4bf75721 100644
--- a/clang/lib/Format/UnwrappedLineFormatter.cpp
+++ b/clang/lib/Format/UnwrappedLineFormatter.cpp
@@ -120,7 +120,14 @@ class LevelIndentTracker {
int getIndentOffset(const AnnotatedLine &Line) {
if (Style.isJava() || Style.isJavaScript() || Style.isCSharp())
return 0;
+
const auto &RootToken = *Line.First;
+
+ if (Style.IndentGotoLabels == FormatStyle::IGLS_HalfIndent &&
+ RootToken.Next && RootToken.Next->is(TT_GotoLabelColon)) {
+ return -static_cast<int>(Style.IndentWidth / 2);
+ }
+
if (Line.Type == LT_AccessModifier ||
RootToken.isAccessSpecifier(/*ColonRequired=*/false) ||
RootToken.isObjCAccessSpecifier() ||
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index d76a74349fe04..ddf584c6ed818 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -1714,7 +1714,7 @@ void UnwrappedLineParser::parseStructuralElement(
if (!Line->InMacroBody || CurrentLines->size() > 1)
Line->Tokens.begin()->Tok->MustBreakBefore = true;
FormatTok->setFinalizedType(TT_GotoLabelColon);
- parseLabel(!Style.IndentGotoLabels);
+ parseLabel(Style.IndentGotoLabels);
if (HasLabel)
*HasLabel = true;
return;
@@ -3358,14 +3358,23 @@ void UnwrappedLineParser::parseDoWhile() {
parseStructuralElement();
}
-void UnwrappedLineParser::parseLabel(bool LeftAlignLabel) {
+void UnwrappedLineParser::parseLabel(
+ FormatStyle::IndentGotoLabelStyle IndentGotoLabels) {
nextToken();
unsigned OldLineLevel = Line->Level;
- if (LeftAlignLabel)
+ switch (IndentGotoLabels) {
+ case FormatStyle::IGLS_NoIndent:
Line->Level = 0;
- else if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))
- --Line->Level;
+ break;
+ case FormatStyle::IGLS_OuterIndent:
+ if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))
+ --Line->Level;
+ break;
+ case FormatStyle::IGLS_HalfIndent:
+ case FormatStyle::IGLS_InnerIndent:
+ break;
+ }
if (!Style.IndentCaseBlocks && CommentsBeforeNextToken.empty() &&
FormatTok->is(tok::l_brace)) {
diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h
index 86022d9b316c6..f3c1b70147db8 100644
--- a/clang/lib/Format/UnwrappedLineParser.h
+++ b/clang/lib/Format/UnwrappedLineParser.h
@@ -159,7 +159,8 @@ class UnwrappedLineParser {
void parseLoopBody(bool KeepBraces, bool WrapRightBrace);
void parseForOrWhileLoop(bool HasParens = true);
void parseDoWhile();
- void parseLabel(bool LeftAlignLabel = false);
+ void parseLabel(FormatStyle::IndentGotoLabelStyle IndentGotoLabels =
+ FormatStyle::IGLS_OuterIndent);
void parseCaseLabel();
void parseSwitch(bool IsExpr);
void parseNamespace();
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index 31326c27b3c59..511db573cdcf3 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -193,7 +193,6 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
CHECK_PARSE_BOOL(IndentCaseBlocks);
CHECK_PARSE_BOOL(IndentCaseLabels);
CHECK_PARSE_BOOL(IndentExportBlock);
- CHECK_PARSE_BOOL(IndentGotoLabels);
CHECK_PARSE_BOOL(IndentRequiresClause);
CHECK_PARSE_BOOL_FIELD(IndentRequiresClause, "IndentRequires");
CHECK_PARSE_BOOL(IndentWrappedFunctionNames);
@@ -939,6 +938,20 @@ TEST(ConfigParseTest, ParsesConfiguration) {
CHECK_PARSE("IndentExternBlock: false", IndentExternBlock,
FormatStyle::IEBS_NoIndent);
+ Style.IndentGotoLabels = FormatStyle::IGLS_OuterIndent;
+ CHECK_PARSE("IndentGotoLabels: NoIndent", IndentGotoLabels,
+ FormatStyle::IGLS_NoIndent);
+ CHECK_PARSE("IndentGotoLabels: OuterIndent", IndentGotoLabels,
+ FormatStyle::IGLS_OuterIndent);
+ CHECK_PARSE("IndentGotoLabels: InnerIndent", IndentGotoLabels,
+ FormatStyle::IGLS_InnerIndent);
+ CHECK_PARSE("IndentGotoLabels: HalfIndent", IndentGotoLabels,
+ FormatStyle::IGLS_HalfIndent);
+ CHECK_PARSE("IndentGotoLabels: false", IndentGotoLabels,
+ FormatStyle::IGLS_NoIndent);
+ CHECK_PARSE("IndentGotoLabels: true", IndentGotoLabels,
+ FormatStyle::IGLS_OuterIndent);
+
Style.BitFieldColonSpacing = FormatStyle::BFCS_None;
CHECK_PARSE("BitFieldColonSpacing: Both", BitFieldColonSpacing,
FormatStyle::BFCS_Both);
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 33af71de398be..63edc17b6da25 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -3158,7 +3158,7 @@ TEST_F(FormatTest, FormatsLabels) {
"}");
FormatStyle Style = getLLVMStyle();
- Style.IndentGotoLabels = false;
+ Style.IndentGotoLabels = FormatStyle::IGLS_NoIndent;
verifyFormat("void f() {\n"
" some_code();\n"
"test_label:\n"
@@ -3196,6 +3196,115 @@ TEST_F(FormatTest, FormatsLabels) {
" }\n"
"}",
Style);
+ verifyFormat("void f() {\n"
+ "L1:\n"
+ " a();\n"
+ " {\n"
+ "L2:\n"
+ " b();\n"
+ " {\n"
+ "L3:\n"
+ " c();\n"
+ " {\n"
+ "L4:\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}",
+ Style);
+ Style.IndentGotoLabels = FormatStyle::IGLS_OuterIndent;
+ verifyFormat("void f() {\n"
+ " some_code();\n"
+ "test_label:\n"
+ " some_other_code();\n"
+ " {\n"
+ " some_more_code();\n"
+ " another_label:\n"
+ " some_more_code();\n"
+ " }\n"
+ "}",
+ Style);
+ verifyFormat("void f() {\n"
+ "L1:\n"
+ " a();\n"
+ " {\n"
+ " L2:\n"
+ " b();\n"
+ " {\n"
+ " L3:\n"
+ " c();\n"
+ " {\n"
+ " L4:\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}",
+ Style);
+ Style.IndentGotoLabels = FormatStyle::IGLS_InnerIndent;
+ verifyFormat("void f() {\n"
+ " some_code();\n"
+ " test_label:\n"
+ " some_other_code();\n"
+ " {\n"
+ " some_more_code();\n"
+ " another_label:\n"
+ " some_more_code();\n"
+ " }\n"
+ "}",
+ Style);
+ verifyFormat("void f() {\n"
+ " L1:\n"
+ " a();\n"
+ " {\n"
+ " L2:\n"
+ " b();\n"
+ " {\n"
+ " L3:\n"
+ " c();\n"
+ " {\n"
+ " L4:\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}",
+ Style);
+ Style.IndentGotoLabels = FormatStyle::IGLS_HalfIndent;
+ verifyFormat("void f() {\n"
+ " some_code();\n"
+ " test_label:\n"
+ " some_other_code();\n"
+ " {\n"
+ " some_more_code();\n"
+ " another_label:\n"
+ " some_more_code();\n"
+ " }\n"
+ "}",
+ Style);
+ verifyFormat("void f() {\n"
+ " L1:\n"
+ " a();\n"
+ " {\n"
+ " L2:\n"
+ " b();\n"
+ " {\n"
+ " L3:\n"
+ " c();\n"
+ " {\n"
+ " L4:\n"
+ " }\n"
+ " }\n"
+ " }\n"
+ "}",
+ Style);
+ Style.IndentWidth = 3;
+ verifyFormat("void f() {\n"
+ " some_code();\n"
+ " test_label:\n"
+ " some_other_code();\n"
+ "}",
+ Style);
+ Style.IndentWidth = 2;
+ Style.IndentGotoLabels = FormatStyle::IGLS_NoIndent;
Style.ColumnLimit = 15;
verifyFormat("#define FOO \\\n"
More information about the cfe-commits
mailing list