https://github.com/divyansh-1009 updated https://github.com/llvm/llvm-project/pull/205452
>From 30ef9df38f27f6511fea3aa378f42e5eccf8f489 Mon Sep 17 00:00:00 2001 From: Divyansh <[email protected]> Date: Wed, 24 Jun 2026 04:28:01 +0530 Subject: [PATCH 1/4] [Clang] Fix assertion failure when passing wide string literal to __builtin_nanf Fixes #205306. --- clang/lib/AST/ExprConstant.cpp | 2 ++ clang/test/Sema/builtin-nan-wide-string.c | 3 +++ 2 files changed, 5 insertions(+) create mode 100644 clang/test/Sema/builtin-nan-wide-string.c diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 8efceff7e8c31..02afad4096655 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -19999,6 +19999,8 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context, const StringLiteral *S = dyn_cast<StringLiteral>(Arg->IgnoreParenCasts()); if (!S) return false; + if (!S->isOrdinary() && !S->isUTF8()) return false; + const llvm::fltSemantics &Sem = Context.getFloatTypeSemantics(ResultTy); llvm::APInt fill; diff --git a/clang/test/Sema/builtin-nan-wide-string.c b/clang/test/Sema/builtin-nan-wide-string.c new file mode 100644 index 0000000000000..52e1b4a17db94 --- /dev/null +++ b/clang/test/Sema/builtin-nan-wide-string.c @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +char hello = __builtin_nanf(L""); // expected-error {{incompatible pointer types passing 'int[1]' to parameter of type 'const char *'}} >From 2c461a63e4fcefb14ebebb416b89212dd5603906 Mon Sep 17 00:00:00 2001 From: Divyansh <[email protected]> Date: Wed, 24 Jun 2026 21:53:06 +0530 Subject: [PATCH 2/4] update release notes, add comprehensive test coverages, restrict support to ordinary string literals, add run directives for C and C++ --- clang/docs/ReleaseNotes.rst | 1 + clang/lib/AST/ExprConstant.cpp | 2 +- clang/test/Sema/builtin-nan-wide-string.c | 47 ++++++++++++++++++++++- clang/test/Sema/constant-builtins-2.c | 4 ++ test_nan_u8.c | 1 + test_nan_u8.cpp | 1 + test_nan_wide.c | 1 + test_nan_wide2.c | 1 + 8 files changed, 55 insertions(+), 3 deletions(-) create mode 100644 test_nan_u8.c create mode 100644 test_nan_u8.cpp create mode 100644 test_nan_wide.c create mode 100644 test_nan_wide2.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 0ff8e8f5afd3c..829f919f892af 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -744,6 +744,7 @@ Bug Fixes to Compiler Builtins crash when using it with ``-fms-extensions`` on other platforms. (#GH184318) - Fixed a compiler crash due to an unresolved overloaded function type when calling ``__builtin_bit_cast``. (#GH200112) +- Fixed an assertion failure when passing a wide string literal to ``__builtin_nan`` and related builtins. (#GH205306) Bug Fixes to Attribute Support ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 02afad4096655..fa34c4ff3a9a2 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -19999,7 +19999,7 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context, const StringLiteral *S = dyn_cast<StringLiteral>(Arg->IgnoreParenCasts()); if (!S) return false; - if (!S->isOrdinary() && !S->isUTF8()) return false; + if (!S->isOrdinary()) return false; const llvm::fltSemantics &Sem = Context.getFloatTypeSemantics(ResultTy); diff --git a/clang/test/Sema/builtin-nan-wide-string.c b/clang/test/Sema/builtin-nan-wide-string.c index 52e1b4a17db94..d97af1c7ad898 100644 --- a/clang/test/Sema/builtin-nan-wide-string.c +++ b/clang/test/Sema/builtin-nan-wide-string.c @@ -1,3 +1,46 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify=c -x c %s +// RUN: %clang_cc1 -fsyntax-only -verify=cxx -x c++ %s +// RUN: %clang_cc1 -fsyntax-only -verify=c -x c -fexperimental-new-constant-interpreter %s +// RUN: %clang_cc1 -fsyntax-only -verify=cxx -x c++ -fexperimental-new-constant-interpreter %s -char hello = __builtin_nanf(L""); // expected-error {{incompatible pointer types passing 'int[1]' to parameter of type 'const char *'}} +#ifdef __cplusplus +#define CONSTEXPR constexpr +#else +#define CONSTEXPR +#endif + +CONSTEXPR float f1 = __builtin_nanf(L""); +// c-warning@-1 {{incompatible pointer types passing 'int[1]' to parameter of type 'const char *'}} +// cxx-error@-2 {{cannot initialize a parameter of type 'const char *' with an lvalue of type 'const wchar_t[1]'}} + +CONSTEXPR double d1 = __builtin_nan(L""); +// c-warning@-1 {{incompatible pointer types passing 'int[1]' to parameter of type 'const char *'}} +// cxx-error@-2 {{cannot initialize a parameter of type 'const char *' with an lvalue of type 'const wchar_t[1]'}} + +CONSTEXPR long double ld1 = __builtin_nanl(L""); +// c-warning@-1 {{incompatible pointer types passing 'int[1]' to parameter of type 'const char *'}} +// cxx-error@-2 {{cannot initialize a parameter of type 'const char *' with an lvalue of type 'const wchar_t[1]'}} + +CONSTEXPR float f2 = __builtin_nanf(u""); +// c-warning@-1 {{incompatible pointer types passing 'unsigned short[1]' to parameter of type 'const char *'}} +// cxx-error@-2 {{cannot initialize a parameter of type 'const char *' with an lvalue of type 'const char16_t[1]'}} + +CONSTEXPR double d2 = __builtin_nan(u""); +// c-warning@-1 {{incompatible pointer types passing 'unsigned short[1]' to parameter of type 'const char *'}} +// cxx-error@-2 {{cannot initialize a parameter of type 'const char *' with an lvalue of type 'const char16_t[1]'}} + +CONSTEXPR long double ld2 = __builtin_nanl(u""); +// c-warning@-1 {{incompatible pointer types passing 'unsigned short[1]' to parameter of type 'const char *'}} +// cxx-error@-2 {{cannot initialize a parameter of type 'const char *' with an lvalue of type 'const char16_t[1]'}} + +CONSTEXPR float f3 = __builtin_nanf(U""); +// c-warning@-1 {{incompatible pointer types passing 'unsigned int[1]' to parameter of type 'const char *'}} +// cxx-error@-2 {{cannot initialize a parameter of type 'const char *' with an lvalue of type 'const char32_t[1]'}} + +CONSTEXPR double d3 = __builtin_nan(U""); +// c-warning@-1 {{incompatible pointer types passing 'unsigned int[1]' to parameter of type 'const char *'}} +// cxx-error@-2 {{cannot initialize a parameter of type 'const char *' with an lvalue of type 'const char32_t[1]'}} + +CONSTEXPR long double ld3 = __builtin_nanl(U""); +// c-warning@-1 {{incompatible pointer types passing 'unsigned int[1]' to parameter of type 'const char *'}} +// cxx-error@-2 {{cannot initialize a parameter of type 'const char *' with an lvalue of type 'const char32_t[1]'}} diff --git a/clang/test/Sema/constant-builtins-2.c b/clang/test/Sema/constant-builtins-2.c index fd3643bbdb7c8..4890ff0ecc1cc 100644 --- a/clang/test/Sema/constant-builtins-2.c +++ b/clang/test/Sema/constant-builtins-2.c @@ -19,6 +19,10 @@ __float128 g5_2 = __builtin_inff128(); double g6 = __builtin_nan(""); float g7 = __builtin_nanf(""); long double g8 = __builtin_nanl(""); + +double g6_u8 = __builtin_nan(u8""); +float g7_u8 = __builtin_nanf(u8""); +long double g8_u8 = __builtin_nanl(u8""); #if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__) __float128 g8_2 = __builtin_nanf128(""); #endif diff --git a/test_nan_u8.c b/test_nan_u8.c new file mode 100644 index 0000000000000..6859499504725 --- /dev/null +++ b/test_nan_u8.c @@ -0,0 +1 @@ +float g8 = __builtin_nanf(u8""); diff --git a/test_nan_u8.cpp b/test_nan_u8.cpp new file mode 100644 index 0000000000000..1016b5b948ef3 --- /dev/null +++ b/test_nan_u8.cpp @@ -0,0 +1 @@ +constexpr float g8 = __builtin_nanf(u8""); diff --git a/test_nan_wide.c b/test_nan_wide.c new file mode 100644 index 0000000000000..6c8abecf78d31 --- /dev/null +++ b/test_nan_wide.c @@ -0,0 +1 @@ +float g8 = __builtin_nanf(L""); diff --git a/test_nan_wide2.c b/test_nan_wide2.c new file mode 100644 index 0000000000000..657ef0ac7ad19 --- /dev/null +++ b/test_nan_wide2.c @@ -0,0 +1 @@ +char hello = __builtin_nanf(L""); >From 8b0428b3c34ed8f95b57f50ab8216164d72b4e1b Mon Sep 17 00:00:00 2001 From: Divyansh <[email protected]> Date: Thu, 25 Jun 2026 00:02:05 +0530 Subject: [PATCH 3/4] fix: validate that arguments to __builtin_nan functions are ordinary string literals --- .../clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaChecking.cpp | 23 +++++++++++++++++++ test_cxx17_u8.cpp | 1 + test_nan_all.c | 5 ++++ test_nan_u8_c.c | 1 + 5 files changed, 32 insertions(+) create mode 100644 test_cxx17_u8.cpp create mode 100644 test_nan_all.c create mode 100644 test_nan_u8_c.c diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index cde99dfb16ec5..062d0c5384dfd 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -171,6 +171,8 @@ def err_ice_too_large : Error< "integer constant expression evaluates to value %0 that cannot be " "represented in a %1-bit %select{signed|unsigned}2 integer type">; def err_expr_not_string_literal : Error<"expression is not a string literal">; +def err_expected_ordinary_string_literal : Error< + "argument to %0 must be an ordinary string literal">; def note_constexpr_assert_failed : Note< "assertion failed during evaluation of constant expression">; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index fa0ec55a63bb7..4343af146b147 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3001,6 +3001,29 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, FPOptions FPO; switch (BuiltinID) { + case Builtin::BI__builtin_nan: + case Builtin::BI__builtin_nanf: + case Builtin::BI__builtin_nanl: + case Builtin::BI__builtin_nanf16: + case Builtin::BI__builtin_nanf128: + case Builtin::BI__builtin_nans: + case Builtin::BI__builtin_nansf: + case Builtin::BI__builtin_nansl: + case Builtin::BI__builtin_nansf16: + case Builtin::BI__builtin_nansf128: { + if (TheCall->getNumArgs() > 0) { + Expr *Arg = TheCall->getArg(0)->IgnoreParenCasts(); + if (StringLiteral *S = dyn_cast<StringLiteral>(Arg)) { + if (!S->isOrdinary()) { + Diag(Arg->getBeginLoc(), diag::err_expected_ordinary_string_literal) + << Context.BuiltinInfo.getQuotedName(BuiltinID) + << Arg->getSourceRange(); + return ExprError(); + } + } + } + break; + } case Builtin::BI__builtin___get_unsafe_stack_start: case Builtin::BI__builtin___get_unsafe_stack_bottom: Diag(TheCall->getBeginLoc(), diag::warn_deprecated_builtin) diff --git a/test_cxx17_u8.cpp b/test_cxx17_u8.cpp new file mode 100644 index 0000000000000..1016b5b948ef3 --- /dev/null +++ b/test_cxx17_u8.cpp @@ -0,0 +1 @@ +constexpr float g8 = __builtin_nanf(u8""); diff --git a/test_nan_all.c b/test_nan_all.c new file mode 100644 index 0000000000000..3c9dddda8597a --- /dev/null +++ b/test_nan_all.c @@ -0,0 +1,5 @@ +float f1 = __builtin_nanf(u8""); +float f2 = __builtin_nanf(L""); +float f3 = __builtin_nanf(u""); +float f4 = __builtin_nanf(U""); +float f5 = __builtin_nanf(""); diff --git a/test_nan_u8_c.c b/test_nan_u8_c.c new file mode 100644 index 0000000000000..6859499504725 --- /dev/null +++ b/test_nan_u8_c.c @@ -0,0 +1 @@ +float g8 = __builtin_nanf(u8""); >From 40fe99030be11023f800ef1750bd934951eea4b2 Mon Sep 17 00:00:00 2001 From: Divyansh <[email protected]> Date: Fri, 26 Jun 2026 00:16:14 +0530 Subject: [PATCH 4/4] Revert changes related to disallowing u8 string literals This focuses the PR exclusively on fixing the failed assertion for wide strings, keeping the changes for u8 literals for a separate PR. Also updates the new constant evaluator to properly handle unsigned 8-bit character arrays. --- .../clang/Basic/DiagnosticSemaKinds.td | 2 -- clang/lib/AST/ByteCode/InterpBuiltin.cpp | 12 ++++++++-- clang/lib/AST/ExprConstant.cpp | 2 +- clang/lib/Sema/SemaChecking.cpp | 23 ------------------- test_cxx17_u8.cpp | 1 - test_nan_all.c | 5 ---- test_nan_u8_c.c | 1 - 7 files changed, 11 insertions(+), 35 deletions(-) delete mode 100644 test_cxx17_u8.cpp delete mode 100644 test_nan_all.c delete mode 100644 test_nan_u8_c.c diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 062d0c5384dfd..cde99dfb16ec5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -171,8 +171,6 @@ def err_ice_too_large : Error< "integer constant expression evaluates to value %0 that cannot be " "represented in a %1-bit %select{signed|unsigned}2 integer type">; def err_expr_not_string_literal : Error<"expression is not a string literal">; -def err_expected_ordinary_string_literal : Error< - "argument to %0 must be an ordinary string literal">; def note_constexpr_assert_failed : Note< "assertion failed during evaluation of constant expression">; diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index e59d14db896a2..bf0be2a817701 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -441,11 +441,19 @@ static bool interp__builtin_nan(InterpState &S, CodePtr OpPC, if (!Arg.isElementInitialized(I)) return false; - if (Arg.elem<int8_t>(I) == 0) { + char C; + if (Arg.getFieldDesc()->getPrimType() == PT_Sint8) + C = Arg.elem<int8_t>(I); + else if (Arg.getFieldDesc()->getPrimType() == PT_Uint8) + C = Arg.elem<uint8_t>(I); + else + return false; + + if (C == 0) { FoundZero = true; break; } - Str += Arg.elem<char>(I); + Str += C; } // If we didn't find a NUL byte, diagnose as a one-past-the-end read. diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index d6de806722661..5368de32f4316 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -19999,7 +19999,7 @@ static bool TryEvaluateBuiltinNaN(const ASTContext &Context, const StringLiteral *S = dyn_cast<StringLiteral>(Arg->IgnoreParenCasts()); if (!S) return false; - if (!S->isOrdinary()) return false; + if (!S->isOrdinary() && !S->isUTF8()) return false; const llvm::fltSemantics &Sem = Context.getFloatTypeSemantics(ResultTy); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 4343af146b147..fa0ec55a63bb7 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3001,29 +3001,6 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID, FPOptions FPO; switch (BuiltinID) { - case Builtin::BI__builtin_nan: - case Builtin::BI__builtin_nanf: - case Builtin::BI__builtin_nanl: - case Builtin::BI__builtin_nanf16: - case Builtin::BI__builtin_nanf128: - case Builtin::BI__builtin_nans: - case Builtin::BI__builtin_nansf: - case Builtin::BI__builtin_nansl: - case Builtin::BI__builtin_nansf16: - case Builtin::BI__builtin_nansf128: { - if (TheCall->getNumArgs() > 0) { - Expr *Arg = TheCall->getArg(0)->IgnoreParenCasts(); - if (StringLiteral *S = dyn_cast<StringLiteral>(Arg)) { - if (!S->isOrdinary()) { - Diag(Arg->getBeginLoc(), diag::err_expected_ordinary_string_literal) - << Context.BuiltinInfo.getQuotedName(BuiltinID) - << Arg->getSourceRange(); - return ExprError(); - } - } - } - break; - } case Builtin::BI__builtin___get_unsafe_stack_start: case Builtin::BI__builtin___get_unsafe_stack_bottom: Diag(TheCall->getBeginLoc(), diag::warn_deprecated_builtin) diff --git a/test_cxx17_u8.cpp b/test_cxx17_u8.cpp deleted file mode 100644 index 1016b5b948ef3..0000000000000 --- a/test_cxx17_u8.cpp +++ /dev/null @@ -1 +0,0 @@ -constexpr float g8 = __builtin_nanf(u8""); diff --git a/test_nan_all.c b/test_nan_all.c deleted file mode 100644 index 3c9dddda8597a..0000000000000 --- a/test_nan_all.c +++ /dev/null @@ -1,5 +0,0 @@ -float f1 = __builtin_nanf(u8""); -float f2 = __builtin_nanf(L""); -float f3 = __builtin_nanf(u""); -float f4 = __builtin_nanf(U""); -float f5 = __builtin_nanf(""); diff --git a/test_nan_u8_c.c b/test_nan_u8_c.c deleted file mode 100644 index 6859499504725..0000000000000 --- a/test_nan_u8_c.c +++ /dev/null @@ -1 +0,0 @@ -float g8 = __builtin_nanf(u8""); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
