On 4/22/26 1:36 PM, Marek Polacek wrote:
On Tue, Apr 21, 2026 at 05:20:02PM -0400, Jason Merrill wrote:
On 4/21/26 4:21 PM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
wrapup_namespace_globals gives errors for code like

    extern inline int i;
    int &r = i; // odr-used inline variable is not defined

but because we mark consteval-only vars DECL_EXTERNAL, we also wrongly
emit the error for:

    inline constexpr info value{};
    static_assert(value == info{});

where value clearly is defined.  ISTM that we should check !consteval_only_p
before giving this error because the test where this could trigger:

    extern constexpr inline info x;

is already ill-formed ("declaration of 'constexpr' variable 'x' is not
a definition").

        PR c++/124770

gcc/cp/ChangeLog:

        * decl.cc (wrapup_namespace_globals): Don't give the odr-used
        inline variable error for consteval-only variables.

gcc/testsuite/ChangeLog:

        * g++.dg/reflect/init18.C: New test.
---
   gcc/cp/decl.cc                        |  6 +++++-
   gcc/testsuite/g++.dg/reflect/init18.C | 14 ++++++++++++++
   2 files changed, 19 insertions(+), 1 deletion(-)
   create mode 100644 gcc/testsuite/g++.dg/reflect/init18.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 679a8007ca6..7837e322d17 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -1024,7 +1024,11 @@ wrapup_namespace_globals ()
          if (VAR_P (decl)
              && DECL_EXTERNAL (decl)
              && DECL_INLINE_VAR_P (decl)
-             && DECL_ODR_USED (decl))
+             && DECL_ODR_USED (decl)
+             /* We mark consteval-only vars extern, but they also have to be
+                declared constexpr and "extern constexpr inline info x;" is
+                ill-formed.  */
+             && !consteval_only_p (decl))

Would it work to check DECL_THIS_EXTERN instead, so we're complaining about
an extern declaration rather than just based on the compiler deciding not to
emit?

Sadly, no, we'd give the error for

   extern constexpr inline info v2{};
   static_assert(v2 == info{});

where the extern is I think redundant due to [basic.link]/3.2.3.
EDG and clang++ accept that code too.

Ah, true, but DECL_THIS_EXTERN && !DECL_INITIAL ought to work?

(decl_defined_p could also use refinement)

Jason

Reply via email to