diff --git a/src/interpret.c b/src/interpret.c index b06b001b3c..0becfb1fd2 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -9500,6 +9500,13 @@ loop body push a work item for it and continue in a later phase. { a_dynamic_init_ptr dip = stmt->variant.dynamic_init; a_variable_ptr vp = dip->variable; a_byte *var_storage; + if (var_has_static_or_thread_storage_duration(vp)) { + /* A local static variable (e.g., a default-initialized one of + class type) that is usable in constant expressions (see + stmk_decl below): its value is obtained when it is + referenced. */ + break; + } /* if */ /* Allocate and bind storage for the variable. */ var_storage = do_constexpr_alloc_variable(ips, vp, &result); if (!result) break; diff --git a/src/pending_changes/gh-399-default-initialized-local-static-constexpr.txt b/src/pending_changes/gh-399-default-initialized-local-static-constexpr.txt new file mode 100644 index 0000000000..d8dd6f93cd --- /dev/null +++ b/src/pending_changes/gh-399-default-initialized-local-static-constexpr.txt @@ -0,0 +1,12 @@ +[GH #399] +Default-initialized local static constexpr variables in constant evaluation + +In C++23 mode, a default-initialized local "static constexpr" variable of +class type caused the constant evaluation of the enclosing function to fail. +For example, with --c++23: + + struct Q { int q = 1; }; + constexpr int f() { static constexpr Q q; return q.q; } + static_assert(f() == 1); // Previously failed. + +This is now fixed. diff --git a/tests/tests/changes/.gh-399.rto/default.1.1.txt b/tests/tests/changes/.gh-399.rto/default.1.1.txt new file mode 100644 index 0000000000..4163d8bb9a --- /dev/null +++ b/tests/tests/changes/.gh-399.rto/default.1.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=1 --c++23 Test_name.c diff --git a/tests/tests/changes/gh-399.sft.cpp b/tests/tests/changes/gh-399.sft.cpp new file mode 100644 index 0000000000..309425355e --- /dev/null +++ b/tests/tests/changes/gh-399.sft.cpp @@ -0,0 +1,23 @@ +//type:fp +//options:--c++23 +//remark:Default-initialized local static constexpr in constant evaluation + +struct Q { int q = 1; }; +constexpr int default_init() { static constexpr Q q; return q.q; } +static_assert(default_init() == 1); // Previously failed. +constexpr int value_init() { static constexpr Q q{}; return q.q + 1; } +static_assert(value_init() == 2); + +struct R { int r = 3; constexpr R() {} }; +constexpr int user_ctor() { + static constexpr R r; + constexpr const R* p = &r; + return p->r; +} +static_assert(user_ctor() == 3); // Previously failed. + +template constexpr int templ() { + static constexpr T t; + return t.q * 10; +} +static_assert(templ() == 10); // Previously failed.