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

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

>From 39a84016f63e2c61e90c34ca503f4bb28651518e Mon Sep 17 00:00:00 2001
From: Dillon Amburgey <[email protected]>
Date: Wed, 24 Dec 2025 04:52:22 +0000
Subject: [PATCH] [clang-format] Avoid crashing on malformed template closers
 in mustBreak
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

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
---
 clang/docs/ReleaseNotes.rst               |  3 +++
 clang/lib/Format/ContinuationIndenter.cpp |  3 ++-
 clang/unittests/Format/FormatTest.cpp     | 16 ++++++++++++++++
 3 files changed, 21 insertions(+), 1 deletion(-)

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!");

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to