Bug 91483 - Poor diagnostic on trying to take constexpr reference to non-static object
Summary: Poor diagnostic on trying to take constexpr reference to non-static object
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 9.1.1
: P3 normal
Target Milestone: ---
Assignee: Marek Polacek
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2019-08-18 15:09 UTC by Barry Revzin
Modified: 2023-09-05 18:32 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-08-18 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Barry Revzin 2019-08-18 15:09:55 UTC
Consider:

struct X {
    int const& var;
};

void foo() {
    constexpr int i = 42;
    constexpr X x{i};
}

This is ill-formed because i doesn't have static storage duration. But the error gcc provides is:

<source>: In function 'void foo()':
<source>:7:20: error: 'const X{i}' is not a constant expression
    7 |     constexpr X x{i};
      |                    ^

It would be a lot nicer if the diagnostic here explained the reason that this isn't a constant expression.
Comment 1 Marek Polacek 2019-08-18 15:12:53 UTC
Yup, that's true.  I'll add it onto my list.
Comment 2 Marek Polacek 2020-09-08 15:41:40 UTC
Related test:

void
foo ()
{
  constexpr int a = 0;
  constexpr const int *p = &a;
}

We just say
error: ‘& a’ is not a constant expression
but that's inadequate.  clang++ now says

note: address of non-static constexpr variable 'a' may differ on each invocation of the enclosing function; add 'static' to give it a constant address
Comment 3 Marek Polacek 2023-08-25 20:26:36 UTC
The error comes from verify_constant, which doesn't explain anything.  verify_constant uses reduced_constant_expression_p which just says yes/no but doesn't explain anything.  reduced_constant_expression_p uses the middle-end initializer_constant_valid_p but that's not going to say anything, either.

Either we need a version of reduced_constant_expression_p that actually says what's wrong, or add a function that, when given an expression that isn't reduced_constant_expression_p, will look for known problematical cases, like the one above.
Comment 4 GCC Commits 2023-09-05 18:30:10 UTC
The trunk branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>:

https://gcc.gnu.org/g:b78cedc6b5bc062717a3e0efb10da8e19af1c422

commit r14-3718-gb78cedc6b5bc062717a3e0efb10da8e19af1c422
Author: Marek Polacek <polacek@redhat.com>
Date:   Fri Sep 1 17:26:01 2023 -0400

    c++: improve verify_constant diagnostic [PR91483]
    
    When verify_constant complains, it's pretty terse.  Consider
    
      void test ()
      {
        constexpr int i = 42;
        constexpr const int *p = &i;
      }
    
    where it says "'& i' is not a constant expression".  OK, but why?
    
    With this patch, we say:
    
    b.C:5:28: error: '& i' is not a constant expression
        5 |   constexpr const int *p = &i;
          |                            ^~
    b.C:5:28: note: pointer to 'i' is not a constant expression
    b.C:4:17: note: address of non-static constexpr variable 'i' may differ on each invocation of the enclosing function; add 'static' to give it a constant address
        4 |   constexpr int i = 42;
          |                 ^
          |                 static
    
    which brings g++ on par with clang++.
    
            PR c++/91483
    
    gcc/cp/ChangeLog:
    
            * constexpr.cc (verify_constant_explain_r): New.
            (verify_constant): Call it.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/diagnostic/constexpr3.C: New test.
Comment 5 Marek Polacek 2023-09-05 18:32:09 UTC
Should be fixed now.