https://github.com/divyansh-1009 updated https://github.com/llvm/llvm-project/pull/205452
>From 8ddb4b1a09af7c11b744bc18d3ea8a2ba4a6fb84 Mon Sep 17 00:00:00 2001 From: Divyansh <[email protected]> Date: Wed, 24 Jun 2026 04:28:01 +0530 Subject: [PATCH 1/5] [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 563d6b3bb0cf9..26dc1e84babc3 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -20007,6 +20007,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 20ae46b3a50a5d556dd41cf8344683dbc99c4a28 Mon Sep 17 00:00:00 2001 From: Divyansh <[email protected]> Date: Wed, 24 Jun 2026 21:53:06 +0530 Subject: [PATCH 2/5] update release notes, add comprehensive test coverages, restrict support to ordinary string literals, add run directives for C and C++ --- clang/docs/ReleaseNotes.md | 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.md b/clang/docs/ReleaseNotes.md index 31e7979612a76..d566c5f5b135a 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -734,6 +734,7 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the 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) - Clang now SFINAE friendly when the ``__reference_meows_from_temporary`` builtins should SFINAE friendly when the 1st type is not a reference type. (#GH206524) diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 26dc1e84babc3..afc2f2d2dd8de 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -20007,7 +20007,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 f8d13ab6808ef94b77d5453a6fd2c0cf4983f274 Mon Sep 17 00:00:00 2001 From: Divyansh <[email protected]> Date: Thu, 25 Jun 2026 00:02:05 +0530 Subject: [PATCH 3/5] 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 7e4a9338d5b1f..bd69f08350cc0 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -172,6 +172,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 01b1f4c26f017..b0dadc83d3e93 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3037,6 +3037,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 7906d2452adfced45574cf9ab264daeded86f557 Mon Sep 17 00:00:00 2001 From: Divyansh <[email protected]> Date: Fri, 26 Jun 2026 00:16:14 +0530 Subject: [PATCH 4/5] 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 bd69f08350cc0..7e4a9338d5b1f 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -172,8 +172,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 73952e032f1eb..48275680466b4 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 afc2f2d2dd8de..26dc1e84babc3 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -20007,7 +20007,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 b0dadc83d3e93..01b1f4c26f017 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3037,29 +3037,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""); >From a48f4d6305c3749b34aaf65b51429d3c0c90b0c1 Mon Sep 17 00:00:00 2001 From: Divyansh <[email protected]> Date: Tue, 30 Jun 2026 23:21:15 +0530 Subject: [PATCH 5/5] [Clang] Add explicit target triple to builtin-nan-wide-string.c to fix Windows CI --- clang/test/Sema/builtin-nan-wide-string.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clang/test/Sema/builtin-nan-wide-string.c b/clang/test/Sema/builtin-nan-wide-string.c index d97af1c7ad898..c3ec698462872 100644 --- a/clang/test/Sema/builtin-nan-wide-string.c +++ b/clang/test/Sema/builtin-nan-wide-string.c @@ -1,7 +1,7 @@ -// 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 +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify=c -x c %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify=cxx -x c++ %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify=c -x c -fexperimental-new-constant-interpreter %s +// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify=cxx -x c++ -fexperimental-new-constant-interpreter %s #ifdef __cplusplus #define CONSTEXPR constexpr _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
