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
