<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 - static construction order within translation unit, static data member of template class"
   href="https://bugs.llvm.org/show_bug.cgi?id=39250">39250</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>static construction order within translation unit, static data member of template class
          </td>
        </tr>

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

        <tr>
          <th>Version</th>
          <td>7.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++
          </td>
        </tr>

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

        <tr>
          <th>Reporter</th>
          <td>cbcode@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>dgregor@apple.com, llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Created <span class=""><a href="attachment.cgi?id=20988" name="attach_20988" title="test case">attachment 20988</a> <a href="attachment.cgi?id=20988&action=edit" title="test case">[details]</a></span>
test case

Within a single translation unit, static construction order is well defined, so
that the construction of classes appearing late in the source file should be
able to depend on the completed construction of static instances of classes
appearing early in the source file. It appears that in certain situations
static data members of template classes are statically constructed too early.

See a test case below and in the attachment.

Expected output is something like: 

a_int : 0x6b4bc8 0x6b4bc8
a_bool: 0x6b4bc0 0x6b4bc0
A_int(): 0x6b4bc8
A_bool(): 0x6b4bc0
C(): 0x6b4bc8
C(): 0x6b4bc0

Bad output:
C(): (nil)
C(): (nil)
a_int : 0x601050 0x601050
a_bool: 0x601058 0x601058
A_int(): 0x601050
A_bool(): 0x601058

For x86_64-unknown-linux-gnu I get bad output with:
7.0.0 (tags/RELEASE_700/final)
6.0.1 (tags/RELEASE_601/final)
5.0.2 (tags/RELEASE_502/final)
and earlier

Under windows with clang-cl, the problem appears for version 4.0 and earlier
but does not show up for 5.0 and later.

gcc or msvc generate correct output for all versions and platforms tested.

Test code:

#include <cstdio>

#pragma clang diagnostic ignored "-Wformat-pedantic"

struct A {
    virtual ~A() {}
    virtual void do_some_useful() {}
};
extern A const &a_int, &a_bool;
//goal: define struct B<T> such that &B<int>::a == &a_int and &B<bool>::a ==
&a_bool

template<typename> struct B {
    static A const& a;
};
template<> A const& B<int >::a = a_int;
template<> A const& B<bool>::a = a_bool;

static struct check { check() {
    std::printf("a_int : %p %p\n", &a_int,  &B<int >::a);
    std::printf("a_bool: %p %p\n", &a_bool, &B<bool>::a);
}} check;

struct A_int : A {
    A_int() { std::printf("A_int(): %p\n", this); }
} const a_int_inst;

struct A_bool : A {
    A_bool() { std::printf("A_bool(): %p\n", this); }
} const a_bool_inst;

A const &a_int = a_int_inst, &a_bool = a_bool_inst;

//Note: Everything happens within a single translation unit.
//Note: There is no reason anything below should be statically constructed
before anything above.

template<typename T> struct C {
    C() { std::printf("C(): %p\n", &B<T>::a); }
    static C const c;
};
template<typename T> C<T> const C<T>::c;

C<int > const& c_int  = C<int >::c;
C<bool> const& c_bool = C<bool>::c;

int main() {
    return 0;
}</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>