[clang] [clang-format] Avoid crashing on malformed template closers in mustBreak (PR #173453)

via cfe-commits cfe-commits at lists.llvm.org
Tue Dec 23 21:50:08 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-format

Author: Dillon Amburgey (dillona)

<details>
<summary>Changes</summary>

If a template closer has no MatchingParen, return false instead of asserting so malformed enable_if declarations don’t force a break.

Fixes: https://github.com/llvm/llvm-project/issues/173382

---
Full diff: https://github.com/llvm/llvm-project/pull/173453.diff


3 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+3) 
- (modified) clang/lib/Format/ContinuationIndenter.cpp (+2-1) 
- (modified) clang/unittests/Format/FormatTest.cpp (+16) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2319ff13f7864..3dc1698616ff3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -793,6 +793,9 @@ clang-format
 - Rename ``(Binary|Decimal|Hex)MinDigits`` to ``...MinDigitsInsert`` and  add
   ``(Binary|Decimal|Hex)MaxDigitsSeparator`` suboptions to
   ``IntegerLiteralSeparator``.
+- Avoid crashing when formatting malformed template code that lacks a matching
+  template closer (e.g., broken ``enable_if`` declarations) by bailing out
+  instead of asserting. (#GH173382)
 
 libclang
 --------
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index 1272bb72d423f..30f7278946fa9 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -675,7 +675,8 @@ bool ContinuationIndenter::mustBreak(const LineState &State) {
         return false;
       if (Tok->is(TT_TemplateCloser)) {
         Tok = Tok->MatchingParen;
-        assert(Tok);
+        if (!Tok)
+          return false; // Bail out on malformed template structure.
       }
       if (Tok->FirstAfterPPLine)
         return false;
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 5cdac66d1dcbd..ecc184cb3b79f 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -15421,6 +15421,22 @@ TEST_F(FormatTest, UnderstandContextOfRecordTypeKeywords) {
   verifyFormat("class A:");
 }
 
+TEST_F(FormatTest, DoesNotCrashOnMalformedEnableIf) {
+  const char *Code =
+      "template <typename T, typename TIString>\n"
+      "typename etl::enable_if<etl::is_integral<T>::value &&\n"
+      "                        !etl::is_same<T, bool>::value>::value,\n"
+      "  const TIString& > ::type\n"
+      "to_string(const T value, TIString& str,\n"
+      "          const etl::basic_format_spec<TIString>& format,\n"
+      "          const bool append = false) {\n"
+      "}\n";
+  // Ensure formatting malformed template syntax doesn't assert, regardless of
+  // whether clang-format considers the input complete.
+  EXPECT_NO_FATAL_FAILURE(format(Code, std::nullopt, SC_DoNotCheck));
+  EXPECT_NO_FATAL_FAILURE(format(messUp(Code), std::nullopt, SC_DoNotCheck));
+}
+
 TEST_F(FormatTest, DoNotInterfereWithErrorAndWarning) {
   verifyNoChange("#error Leave     all         white!!!!! space* alone!");
   verifyNoChange("#warning Leave     all         white!!!!! space* alone!");

``````````

</details>


https://github.com/llvm/llvm-project/pull/173453


More information about the cfe-commits mailing list