[clang] [clang-format] Update goto label indentation styles (PR #180109)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 10 22:51:41 PST 2026
https://github.com/Ezlanding1 updated https://github.com/llvm/llvm-project/pull/180109
>From c9f48b69a2be9f59e4526f7807a5521d0ff8a7b2 Mon Sep 17 00:00:00 2001
From: Ezlanding1 <113404035+Ezlanding1 at users.noreply.github.com>
Date: Thu, 5 Feb 2026 21:10:54 -0500
Subject: [PATCH 1/2] Update goto label indentation styles
---
clang/docs/ClangFormatStyleOptions.rst | 73 +++++++++++++++++----
clang/include/clang/Format/Format.h | 72 +++++++++++++++-----
clang/lib/Format/Format.cpp | 14 +++-
clang/lib/Format/UnwrappedLineFormatter.cpp | 7 ++
clang/lib/Format/UnwrappedLineParser.cpp | 20 ++++--
clang/lib/Format/UnwrappedLineParser.h | 3 +-
6 files changed, 153 insertions(+), 36 deletions(-)
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 5ba117c231ad5..4ef93f08562ac 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -4535,22 +4535,69 @@ the configuration (without a prefix: ``Auto``).
.. _IndentGotoLabels:
-**IndentGotoLabels** (``Boolean``) :versionbadge:`clang-format 10` :ref:`¶ <IndentGotoLabels>`
- Indent goto labels.
+**IndentGotoLabels** (``IndentGotoLabelStyle``) :versionbadge:`clang-format 23` :ref:`¶ <IndentGotoLabels>`
+ The goto label indenting style to use.
- When ``false``, goto labels are flushed left.
+ Possible values:
+
+ * ``IGLS_LeftAlign`` (in configuration: ``LeftAlign``)
+ Left align goto labels.
+
+ .. code-block:: c++
+
+ int f() {
+ if (foo()) {
+ label1:
+ bar();
+ }
+ label2:
+ return 1;
+ }
+
+ * ``IGLS_NoIndent`` (in configuration: ``NoIndent``)
+ Do not indent goto labels.
+
+ .. code-block:: c++
+
+ int f() {
+ if (foo()) {
+ label1:
+ bar();
+ }
+ label2:
+ return 1;
+ }
+
+ * ``IGLS_Indent`` (in configuration: ``Indent``)
+ Indent goto labels.
+
+ .. 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 not an even 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 43bea4b80cb8a..a1314d56f6949 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -3078,22 +3078,62 @@ 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
- /// \version 10
- bool IndentGotoLabels;
+ /// Options for indenting goto labels.
+ enum IndentGotoLabelStyle : int8_t {
+ /// Left align goto labels.
+ /// \code
+ /// int f() {
+ /// if (foo()) {
+ /// label1:
+ /// bar();
+ /// }
+ /// label2:
+ /// return 1;
+ /// }
+ /// \endcode
+ IGLS_LeftAlign,
+ /// Do not indent goto labels.
+ /// \code
+ /// int f() {
+ /// if (foo()) {
+ /// label1:
+ /// bar();
+ /// }
+ /// label2:
+ /// return 1;
+ /// }
+ /// \endcode
+ IGLS_NoIndent,
+ /// Indent goto labels.
+ /// \code
+ /// int f() {
+ /// if (foo()) {
+ /// label1:
+ /// bar();
+ /// }
+ /// label2:
+ /// return 1;
+ /// }
+ /// \endcode
+ IGLS_Indent,
+ /// Indent goto labels to half the indentation of the surrounding code.
+ /// If the indentation width is not an even 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 23
+ 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 1e68de531791f..0abfd534631cb 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1465,6 +1465,18 @@ 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, "LeftAlign", FormatStyle::IGLS_LeftAlign);
+ IO.enumCase(Value, "NoIndent", FormatStyle::IGLS_NoIndent);
+ IO.enumCase(Value, "Indent", FormatStyle::IGLS_Indent);
+ IO.enumCase(Value, "HalfIndent", FormatStyle::IGLS_HalfIndent);
+ IO.enumCase(Value, "false", FormatStyle::IGLS_LeftAlign);
+ IO.enumCase(Value, "true", FormatStyle::IGLS_NoIndent);
+ }
+};
+
} // namespace yaml
} // namespace llvm
@@ -1759,7 +1771,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.IndentCaseLabels = false;
LLVMStyle.IndentExportBlock = true;
LLVMStyle.IndentExternBlock = FormatStyle::IEBS_AfterExternBlock;
- LLVMStyle.IndentGotoLabels = true;
+ LLVMStyle.IndentGotoLabels = FormatStyle::IGLS_NoIndent;
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..552038d1e0753 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 != NULL && 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 f57ef1328eac7..14e72ffdd8aa7 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -1710,7 +1710,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;
@@ -3354,14 +3354,24 @@ 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_LeftAlign:
Line->Level = 0;
- else if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))
- --Line->Level;
+ break;
+ case FormatStyle::IGLS_NoIndent:
+ if (Line->Level > 1 || (!Line->InPPDirective && Line->Level > 0))
+ --Line->Level;
+ break;
+ case FormatStyle::IGLS_HalfIndent:
+ case FormatStyle::IGLS_Indent:
+ default:
+ 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..48119e8802b57 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_NoIndent);
void parseCaseLabel();
void parseSwitch(bool IsExpr);
void parseNamespace();
>From 1dd860a8dd319b82382cf2eb841e2493d20a840e Mon Sep 17 00:00:00 2001
From: Ezlanding1 <113404035+Ezlanding1 at users.noreply.github.com>
Date: Wed, 11 Feb 2026 01:51:23 -0500
Subject: [PATCH 2/2] Add unit tests
---
clang/unittests/Format/ConfigParseTest.cpp | 15 ++++++-
clang/unittests/Format/FormatTest.cpp | 47 +++++++++++++++++++++-
2 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index 0a116b770f52a..d958b0d128456 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);
@@ -892,6 +891,20 @@ TEST(ConfigParseTest, ParsesConfiguration) {
CHECK_PARSE("IndentExternBlock: false", IndentExternBlock,
FormatStyle::IEBS_NoIndent);
+ Style.IndentGotoLabels = FormatStyle::IGLS_NoIndent;
+ CHECK_PARSE("IndentGotoLabels: LeftAlign", IndentGotoLabels,
+ FormatStyle::IGLS_LeftAlign);
+ CHECK_PARSE("IndentGotoLabels: NoIndent", IndentGotoLabels,
+ FormatStyle::IGLS_NoIndent);
+ CHECK_PARSE("IndentGotoLabels: Indent", IndentGotoLabels,
+ FormatStyle::IGLS_Indent);
+ CHECK_PARSE("IndentGotoLabels: HalfIndent", IndentGotoLabels,
+ FormatStyle::IGLS_HalfIndent);
+ CHECK_PARSE("IndentGotoLabels: false", IndentGotoLabels,
+ FormatStyle::IGLS_LeftAlign);
+ CHECK_PARSE("IndentGotoLabels: true", IndentGotoLabels,
+ FormatStyle::IGLS_NoIndent);
+
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 33836e28289b4..23e68fd41c588 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_LeftAlign;
verifyFormat("void f() {\n"
" some_code();\n"
"test_label:\n"
@@ -3196,6 +3196,51 @@ TEST_F(FormatTest, FormatsLabels) {
" }\n"
"}",
Style);
+ Style.IndentGotoLabels = FormatStyle::IGLS_NoIndent;
+ 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);
+ Style.IndentGotoLabels = FormatStyle::IGLS_Indent;
+ 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);
+ 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);
+ 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_LeftAlign;
Style.ColumnLimit = 15;
verifyFormat("#define FOO \\\n"
More information about the cfe-commits
mailing list