<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 - AST not generated for static constexpr member variable value for c++17 (is for c++14)"
   href="https://bugs.llvm.org/show_bug.cgi?id=51290">51290</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>AST not generated for static constexpr member variable value for c++17 (is for c++14)
          </td>
        </tr>

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

        <tr>
          <th>Version</th>
          <td>12.0
          </td>
        </tr>

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

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

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

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

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

        <tr>
          <th>Component</th>
          <td>C++17
          </td>
        </tr>

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

        <tr>
          <th>Reporter</th>
          <td>bensan.morris@googlemail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>blitzrakete@gmail.com, erik.pilkington@gmail.com, llvm-bugs@lists.llvm.org, richard-llvm@metafoo.co.uk
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Hi,

For the following code snippet:

// snippet.h
template<int X>
class T {
          static constexpr int Y = X;
};
T<42> foo;

I run it under clang-check dumping AST for c++14 vs 17:

// clang-check (c++14)
/usr/bin/clang-check-12 --extra-arg-before=-xc++ --extra-arg-before=-std=c++14
snippet.h --ast-dump &> 14.txt

// clang-check (c++17)
/usr/bin/clang-check-12 --extra-arg-before=-xc++ --extra-arg-before=-std=c++17
snippet.h --ast-dump &> 17.txt

And then diff:

// diff 14.txt 17.txt
...
44,57c44,53
< |   |-CXXRecordDecl 0x13ee6b8 prev 0x13ee418 <col:1, col:7> col:7 implicit
class T
< |   |-VarDecl 0x13ee748 <line:3:4, col:29> col:25 Y 'const int' static
constexpr cinit
< |   | |-value: Int 42 <-- WORKS UNDER 14 
< |   | `-SubstNonTypeTemplateParmExpr 0x13ee7e0 <col:29> 'int'
< |   |   |-NonTypeTemplateParmDecl 0x13edf28 <line:1:10, col:14> col:14
referenced 'int' depth 0 index 0 X
< |   |   `-IntegerLiteral 0x13ee7c0 <line:3:29> 'int' 42
< |   |-CXXConstructorDecl 0x13ee888 <line:2:7> col:7 implicit used constexpr T
'void () noexcept' inline default trivial
< |   | `-CompoundStmt 0x13eed18 <col:7>
< |   |-CXXConstructorDecl 0x13ee9b8 <col:7> col:7 implicit constexpr T 'void
(const T<42> &)' inline default trivial noexcept-unevaluated 0x13ee9b8
< |   | `-ParmVarDecl 0x13eeac8 <col:7> col:7 'const T<42> &'
< |   `-CXXConstructorDecl 0x13eeb68 <col:7> col:7 implicit constexpr T 'void
(T<42> &&)' inline default trivial noexcept-unevaluated 0x13eeb68
< |     `-ParmVarDecl 0x13eec78 <col:7> col:7 'T<42> &&'
< `-VarDecl 0x13ee5a0 <line:5:1, col:7> col:7 foo 'T<42>':'T<42>' callinit
<   `-CXXConstructExpr 0x13eed28 <col:7> 'T<42>':'T<42>' 'void () noexcept'
---
<span class="quote">> |   |-CXXRecordDecl 0x1d3cc78 prev 0x1d3c9d8 <col:1, col:7> col:7 implicit class T
> |   |-VarDecl 0x1d3cd08 <line:3:4, col:25> col:25 Y 'const int' static constexpr</span >
                <-- MISSING VALUE UNDER 17
<span class="quote">> |   |-CXXConstructorDecl 0x1d3cdb0 <line:2:7> col:7 implicit used constexpr T 'void () noexcept' inline default trivial
> |   | `-CompoundStmt 0x1d3d248 <col:7>
> |   |-CXXConstructorDecl 0x1d3cee8 <col:7> col:7 implicit constexpr T 'void (const T<42> &)' inline default trivial noexcept-unevaluated 0x1d3cee8
> |   | `-ParmVarDecl 0x1d3cff8 <col:7> col:7 'const T<42> &'
> |   `-CXXConstructorDecl 0x1d3d098 <col:7> col:7 implicit constexpr T 'void (T<42> &&)' inline default trivial noexcept-unevaluated 0x1d3d098
> |     `-ParmVarDecl 0x1d3d1a8 <col:7> col:7 'T<42> &&'
> `-VarDecl 0x1d3cb60 <line:5:1, col:7> col:7 foo 'T<42>':'T<42>' callinit
>   `-CXXConstructExpr 0x1d3d258 <col:7> 'T<42>':'T<42>' 'void () noexcept'</span >

Under 14 AST for static constexpr Y member is generated with value (42) however
17 generates decl only (no value). 

If I then modify snippet as follows:

(modified snippet.h)
template<int X>
class T {
          static constexpr int Y = X;
          T()
          {
                auto tmp = Y;
          }
};
T<42> foo;

Y's value is generated in AST for c++17. Is this a bug in clang or something we
are not doing correctly wrt C++ standard?

This issue was originally mentioned in a stack overflow post (so kudos to the
original author for identifying the workaround for clang AST generation under
17 for this scenario):
<a href="https://stackoverflow.com/questions/60308864/accessing-the-initializer-of-a-static-constexpr-in-llvm-c17">https://stackoverflow.com/questions/60308864/accessing-the-initializer-of-a-static-constexpr-in-llvm-c17</a>

Many thanks in advance,
Ben.</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>