https://github.com/owenca created 
https://github.com/llvm/llvm-project/pull/150166

Replace true/false with SAN_Exclaim/SAN_Never and add SAN_Always.

Closes #149971

>From b5442f59d649b38086ccd91d40c7c291dd924cc8 Mon Sep 17 00:00:00 2001
From: Owen Pan <owenpi...@gmail.com>
Date: Tue, 22 Jul 2025 22:07:05 -0700
Subject: [PATCH] [clang-format] Change SpaceAfterLogicalNot to enumeration
 type

Replace true/false with SAN_Exclaim/SAN_Never and add SAN_Always.

Closes #149971
---
 clang/docs/ClangFormatStyleOptions.rst     | 34 ++++++++++++++++++----
 clang/include/clang/Format/Format.h        | 31 ++++++++++++++++----
 clang/lib/Format/Format.cpp                | 14 ++++++++-
 clang/lib/Format/TokenAnnotator.cpp        |  5 ++--
 clang/unittests/Format/ConfigParseTest.cpp | 13 ++++++++-
 clang/unittests/Format/FormatTest.cpp      |  9 ++++--
 6 files changed, 89 insertions(+), 17 deletions(-)

diff --git a/clang/docs/ClangFormatStyleOptions.rst 
b/clang/docs/ClangFormatStyleOptions.rst
index d39ee49b432e5..ff91c4f63fc46 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -6118,13 +6118,37 @@ the configuration (without a prefix: ``Auto``).
 
 .. _SpaceAfterLogicalNot:
 
-**SpaceAfterLogicalNot** (``Boolean``) :versionbadge:`clang-format 9` :ref:`¶ 
<SpaceAfterLogicalNot>`
-  If ``true``, a space is inserted after the logical not operator (``!``).
+**SpaceAfterLogicalNot** (``SpaceAfterNotOptions``) 
:versionbadge:`clang-format 9` :ref:`¶ <SpaceAfterLogicalNot>`
+  Controls if a space is inserted after the logical not operator (``!`` or
+  ``not``).
+
+  Possible values:
+
+  * ``SAN_Never`` (in configuration: ``Never``)
+    Never insert a space after ``!``.
+
+    .. code-block:: c++
+
+       return !someExpression();
+       return not(a || b);
+
+  * ``SAN_Exclaim`` (in configuration: ``Exclaim``)
+    Always insert a space after ``!``.
+
+    .. code-block:: c++
+
+       return ! someExpression();
+       return not(a || b);
+
+  * ``SAN_Always`` (in configuration: ``Always``)
+    Always insert a space after both ``!`` and ``not``.
+
+    .. code-block:: c++
+
+       return ! someExpression();
+       return not (a || b);
 
-  .. code-block:: c++
 
-     true:                                  false:
-     ! someExpression();            vs.     !someExpression();
 
 .. _SpaceAfterOperatorKeyword:
 
diff --git a/clang/include/clang/Format/Format.h 
b/clang/include/clang/Format/Format.h
index 7677604484f52..6398662fe7847 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4483,13 +4483,32 @@ struct FormatStyle {
   /// \version 3.5
   bool SpaceAfterCStyleCast;
 
-  /// If ``true``, a space is inserted after the logical not operator (``!``).
-  /// \code
-  ///    true:                                  false:
-  ///    ! someExpression();            vs.     !someExpression();
-  /// \endcode
+  /// Space after logical not operator options.
+  enum SpaceAfterNotOptions : int8_t {
+    /// Never insert a space after ``!``.
+    /// \code
+    ///    return !someExpression();
+    ///    return not(a || b);
+    /// \endcode
+    SAN_Never,
+    /// Always insert a space after ``!``.
+    /// \code
+    ///    return ! someExpression();
+    ///    return not(a || b);
+    /// \endcode
+    SAN_Exclaim,
+    /// Always insert a space after both ``!`` and ``not``.
+    /// \code
+    ///    return ! someExpression();
+    ///    return not (a || b);
+    /// \endcode
+    SAN_Always,
+  };
+
+  /// Controls if a space is inserted after the logical not operator (``!`` or
+  /// ``not``).
   /// \version 9
-  bool SpaceAfterLogicalNot;
+  SpaceAfterNotOptions SpaceAfterLogicalNot;
 
   /// If ``true``, a space will be inserted after the ``operator`` keyword.
   /// \code
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 62feb3db0ed5e..3ce931a0ffdb6 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -711,6 +711,18 @@ struct 
ScalarEnumerationTraits<FormatStyle::SortUsingDeclarationsOptions> {
   }
 };
 
+template <> struct ScalarEnumerationTraits<FormatStyle::SpaceAfterNotOptions> {
+  static void enumeration(IO &IO, FormatStyle::SpaceAfterNotOptions &Value) {
+    IO.enumCase(Value, "Never", FormatStyle::SAN_Never);
+    IO.enumCase(Value, "Exclaim", FormatStyle::SAN_Exclaim);
+    IO.enumCase(Value, "Always", FormatStyle::SAN_Always);
+
+    // For backward compatibility.
+    IO.enumCase(Value, "false", FormatStyle::SAN_Never);
+    IO.enumCase(Value, "true", FormatStyle::SAN_Exclaim);
+  }
+};
+
 template <>
 struct ScalarEnumerationTraits<FormatStyle::SpaceAroundPointerQualifiersStyle> 
{
   static void
@@ -1659,7 +1671,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind 
Language) {
   LLVMStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before;
   LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric;
   LLVMStyle.SpaceAfterCStyleCast = false;
-  LLVMStyle.SpaceAfterLogicalNot = false;
+  LLVMStyle.SpaceAfterLogicalNot = FormatStyle::SAN_Never;
   LLVMStyle.SpaceAfterOperatorKeyword = false;
   LLVMStyle.SpaceAfterTemplateKeyword = true;
   LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default;
diff --git a/clang/lib/Format/TokenAnnotator.cpp 
b/clang/lib/Format/TokenAnnotator.cpp
index 581bfbab0972d..e5b96a9e2f635 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5476,9 +5476,10 @@ bool TokenAnnotator::spaceRequiredBefore(const 
AnnotatedLine &Line,
     if (Left.isNot(tok::exclaim))
       return false;
     if (Left.TokenText == "!")
-      return Style.SpaceAfterLogicalNot;
+      return Style.SpaceAfterLogicalNot != FormatStyle::SAN_Never;
     assert(Left.TokenText == "not");
-    return Right.isOneOf(tok::coloncolon, TT_UnaryOperator);
+    return Right.isOneOf(tok::coloncolon, TT_UnaryOperator) ||
+           Style.SpaceAfterLogicalNot == FormatStyle::SAN_Always;
   }
 
   // If the next token is a binary operator or a selector name, we have
diff --git a/clang/unittests/Format/ConfigParseTest.cpp 
b/clang/unittests/Format/ConfigParseTest.cpp
index 65d8b36c677bd..b71bcb20d00ca 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -205,7 +205,6 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
   CHECK_PARSE_BOOL(SpaceAfterCStyleCast);
   CHECK_PARSE_BOOL(SpaceAfterTemplateKeyword);
   CHECK_PARSE_BOOL(SpaceAfterOperatorKeyword);
-  CHECK_PARSE_BOOL(SpaceAfterLogicalNot);
   CHECK_PARSE_BOOL(SpaceBeforeAssignmentOperators);
   CHECK_PARSE_BOOL(SpaceBeforeCaseColon);
   CHECK_PARSE_BOOL(SpaceBeforeCpp11BracedList);
@@ -654,6 +653,18 @@ TEST(ConfigParseTest, ParsesConfiguration) {
   CHECK_PARSE("AllowShortLambdasOnASingleLine: true",
               AllowShortLambdasOnASingleLine, FormatStyle::SLS_All);
 
+  CHECK_PARSE("SpaceAfterLogicalNot: Exclaim", SpaceAfterLogicalNot,
+              FormatStyle::SAN_Exclaim);
+  CHECK_PARSE("SpaceAfterLogicalNot: Never", SpaceAfterLogicalNot,
+              FormatStyle::SAN_Never);
+  CHECK_PARSE("SpaceAfterLogicalNot: Always", SpaceAfterLogicalNot,
+              FormatStyle::SAN_Always);
+  // For backward compatibility:
+  CHECK_PARSE("SpaceAfterLogicalNot: false", SpaceAfterLogicalNot,
+              FormatStyle::SAN_Never);
+  CHECK_PARSE("SpaceAfterLogicalNot: true", SpaceAfterLogicalNot,
+              FormatStyle::SAN_Exclaim);
+
   Style.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Both;
   CHECK_PARSE("SpaceAroundPointerQualifiers: Default",
               SpaceAroundPointerQualifiers, FormatStyle::SAPQ_Default);
diff --git a/clang/unittests/Format/FormatTest.cpp 
b/clang/unittests/Format/FormatTest.cpp
index dbf6950446ef0..bd732d2b0aa81 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -17762,14 +17762,19 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
 }
 
 TEST_F(FormatTest, SpaceAfterLogicalNot) {
-  FormatStyle Spaces = getLLVMStyle();
-  Spaces.SpaceAfterLogicalNot = true;
+  auto Spaces = getLLVMStyle();
+  EXPECT_EQ(Spaces.SpaceAfterLogicalNot, FormatStyle::SAN_Never);
 
+  Spaces.SpaceAfterLogicalNot = FormatStyle::SAN_Exclaim;
   verifyFormat("bool x = ! y", Spaces);
   verifyFormat("if (! isFailure())", Spaces);
   verifyFormat("if (! (a && b))", Spaces);
   verifyFormat("\"Error!\"", Spaces);
   verifyFormat("! ! x", Spaces);
+
+  Spaces.SpaceAfterLogicalNot = FormatStyle::SAN_Always;
+  verifyFormat("return ! (a || b);", Spaces);
+  verifyFormat("return not (a || b);", Spaces);
 }
 
 TEST_F(FormatTest, ConfigurableSpacesInParens) {

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to