Bug 124445 - Variables with non-literal types accepted in constexpr templates for C++20
Summary: Variables with non-literal types accepted in constexpr templates for C++20
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 16.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: accepts-invalid
Depends on:
Blocks: constexpr
  Show dependency treegraph
 
Reported: 2026-03-11 08:13 UTC by Jakub Jelinek
Modified: 2026-03-13 15:27 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2026-03-11 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jakub Jelinek 2026-03-11 08:13:38 UTC
struct S { S () : s (42) {} ~S () {} int s; };
#ifdef TMPL
template <int N>
#endif
constexpr bool
foo ()
{
  if (__builtin_is_constant_evaluated ()) { return true; }
  S s;
  return true;
}
#ifdef TMPL
auto a = foo <42> ();
#else
auto a = foo ();
#endif
Both g++ and clang++ reject this with -std=c++20 if TMPL is not defined
g++ -S -std=c++20 -o /tmp/0.s /tmp/0.C
/tmp/0.C: In function ‘constexpr bool foo()’:
/tmp/0.C:9:5: error: variable ‘s’ of non-literal type ‘S’ in ‘constexpr’ function only available with ‘-std=c++23’ or ‘-std=gnu++23’
    9 |   S s;
      |     ^
/tmp/0.C:1:8: note: ‘S’ is not literal because:
    1 | struct S { S () : s (42) {} ~S () {} int s; };
      |        ^
/tmp/0.C:1:8: note:   ‘S’ does not have ‘constexpr’ destructor
clang++ -S -std=c++20 -o /tmp/0.s /tmp/0.C
/tmp/0.C:9:5: error: variable of non-literal type 'S' cannot be defined in a constexpr function before C++23
    9 |   S s;
      |     ^
/tmp/0.C:1:8: note: 'S' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors
    1 | struct S { S () : s (42) {} ~S () {} int s; };
      |        ^
1 error generated.
but 
g++ -S -DTMPL -std=c++20 -o /tmp/0.s /tmp/0.C
is quiet and
clang++ -S -DTMPL -std=c++20 -o /tmp/0.s /tmp/0.C
/tmp/0.C:9:5: error: variable of non-literal type 'S' cannot be defined in a constexpr function before C++23
    9 |   S s;
      |     ^
/tmp/0.C:1:8: note: 'S' is not literal because it is not an aggregate and has no constexpr constructors other than copy or move constructors
    1 | struct S { S () : s (42) {} ~S () {} int s; };
      |        ^
/tmp/0.C:13:10: error: no matching function for call to 'foo'
   13 | auto a = foo <42> ();
      |          ^~~~~~~~
/tmp/0.C:6:1: note: candidate template ignored: substitution failure [with N = 42]
    6 | foo ()
      | ^
2 errors generated.
Comment 1 Marek Polacek 2026-03-11 17:27:22 UTC
Confirmed.  ensure_literal_type_for_constexpr_object emits errors only when !processing_template_decl.