Skip to content

[clang] rejects-valid constexpr expression #106509

@naav

Description

@naav

While investigating a potential GCC bug, I went through https://eel.is/c++draft/expr.const#9 which contains the following (reduced) example:

struct Swim {
  constexpr int phelps() { return 28; }
};

void splash(Swim& swam) {
  static_assert(swam.phelps() == 28);           // OK
}

clang trunk rejects this with:

<source>:6:17: error: static assertion expression is not an integral constant expression
    6 |   static_assert(swam.phelps() == 28);           // OK
      |                 ^~~~~~~~~~~~~~~~~~~
<source>:6:17: note: function parameter 'swam' with unknown value cannot be used in a constant expression
<source>:5:19: note: declared here
    5 | void splash(Swim& swam) {
      |                   ^

Whereas GCC accepts it. https://godbolt.org/z/s1vTK7G3h

--

Moreover, if one feeds the whole example to clang (replacing size_t with int and removing the lines that are specified to be invalid):

template <typename T, int N>
constexpr int array_size(T (&)[N]) {
  return N;
}

void use_array(int const (&gold_medal_mel)[2]) {
  constexpr auto gold = array_size(gold_medal_mel);     // OK
}

constexpr auto olympic_mile() {
  const int ledecky = 1500;
  return []{ return ledecky; };
}
static_assert(olympic_mile()() == 1500);                // OK

struct Swim {
  constexpr int phelps() { return 28; }
  virtual constexpr int lochte() { return 12; }
  int coughlin = 12;
};

constexpr int how_many(Swim& swam) {
  Swim* p = &swam;
  return (p + 1 - 1)->phelps();
}

void splash(Swim& swam) {
  static_assert(swam.phelps() == 28);           // OK
  static_assert((&swam)->phelps() == 28);       // OK

  Swim* pswam = &swam;
  
  static_assert(how_many(swam) == 28);          // OK
  static_assert(Swim().lochte() == 12);         // OK
}

clang trunk rejects with:

<source>:7:18: error: constexpr variable 'gold' must be initialized by a constant expression
    7 |   constexpr auto gold = array_size(gold_medal_mel);     // OK
      |                  ^      ~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:7:36: note: function parameter 'gold_medal_mel' with unknown value cannot be used in a constant expression
    7 |   constexpr auto gold = array_size(gold_medal_mel);     // OK
      |                                    ^
<source>:6:28: note: declared here
    6 | void use_array(int const (&gold_medal_mel)[2]) {
      |                            ^
<source>:28:17: error: static assertion expression is not an integral constant expression
   28 |   static_assert(swam.phelps() == 28);           // OK
      |                 ^~~~~~~~~~~~~~~~~~~
<source>:28:17: note: function parameter 'swam' with unknown value cannot be used in a constant expression
<source>:27:19: note: declared here
   27 | void splash(Swim& swam) {
      |                   ^
<source>:29:17: error: static assertion expression is not an integral constant expression
   29 |   static_assert((&swam)->phelps() == 28);       // OK
      |                 ^~~~~~~~~~~~~~~~~~~~~~~
<source>:29:19: note: function parameter 'swam' with unknown value cannot be used in a constant expression
   29 |   static_assert((&swam)->phelps() == 28);       // OK
      |                   ^
<source>:27:19: note: declared here
   27 | void splash(Swim& swam) {
      |                   ^
<source>:33:17: error: static assertion expression is not an integral constant expression
   33 |   static_assert(how_many(swam) == 28);          // OK
      |                 ^~~~~~~~~~~~~~~~~~~~
<source>:33:26: note: function parameter 'swam' with unknown value cannot be used in a constant expression
   33 |   static_assert(how_many(swam) == 28);          // OK
      |                          ^
<source>:27:19: note: declared here
   27 | void splash(Swim& swam) {
      |                   ^
4 errors generated.
Compiler returned: 1

Whereas GCC accepts. https://godbolt.org/z/3r9nKc9bz

This seems to be related to #63139

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:frontendLanguage frontend issues, e.g. anything involving "Sema"duplicateResolved as duplicaterejects-valid

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions