<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - Call to consteval function isn't folded to a constant"
   href="https://bugs.llvm.org/show_bug.cgi?id=45912">45912</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Call to consteval function isn't folded to a constant
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>LLVM Codegen
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>ldionne@apple.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org, neeilans@live.com, richard-llvm@metafoo.co.uk
          </td>
        </tr></table>
      <p>
        <div>
        <pre>The following program calling a consteval function causes code to be emitted to
compute the result of maxFoo() at runtime, when one would expect it to be
computed at compile-time:

    $ cat <<EOF | clang++ -xc++ - -std=c++2a -Os -S -o a.s && cat a.s
    #include <array>
    #include <algorithm>

    struct Foo { int i; };
    static constexpr std::array<Foo, 3> foos = {{{1}, {2}, {3}}};

    static int consteval maxFoo() {
        auto it = std::max_element(foos.begin(), foos.end(), [](auto lhs, auto
rhs) {
            return lhs.i < rhs.i;
        });

        return it->i;
    }

    int main() { return maxFoo(); }
    EOF

Here's a few interesting observations:
1. This only happens when -Os or -O1 are used.
2. Even slight modifications of the above code will cause it to be inlined, for
example implementing `maxFoo()` equivalently but in a single expression.
3. The same issue happens whether `consteval` is used or not (which leads me to
think this is a codegen issue, not a front-end issue).

Godbolt link: <a href="https://godbolt.org/z/MA9U8b">https://godbolt.org/z/MA9U8b</a>

After playing around and debugging Clang for a bit, I am fairly confident that
this is not a bug per-se, but only an important QOI issue. In particular, I
think Clang behaves correctly with respect to the Standard, which only says
about immediate functions (<a href="http://eel.is/c++draft/expr.const#13">http://eel.is/c++draft/expr.const#13</a>):

    > [...] An expression or conversion is an immediate invocation if 
    > it is a potentially-evaluated explicit or implicit invocation of 
    > an immediate function and is not in an immediate function context. 
    > An immediate invocation shall be a constant expression.

This doesn't talk about codegen, since the Standard doesn't have such a notion.
Also, Clang does treat `maxFoo()` as a constant expression, and in fact the
front-end even calculates the result properly in an APValue -- so Clang is
*correct* as far as the Standard is concerned.

However, the code generation appears to never be passed that knowledge, and as
a result it can sometimes fail to fold the immediate call, depending on
optimization levels. Since the intent of consteval was *specifically* to make
sure that no code is generated for such calls, I would argue this is an
important QOI issue (if we're being pedantic), and straight up a bug (as far as
99% of users are concerned).</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>