<html>
    <head>
      <base href="http://llvm.org/bugs/" />
    </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 --- - invalid merging of two template variables"
   href="http://llvm.org/bugs/show_bug.cgi?id=19025">19025</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>invalid merging of two template variables
          </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>Windows NT
          </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++1y
          </td>
        </tr>

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

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

        <tr>
          <th>CC</th>
          <td>llvmbugs@cs.uiuc.edu
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Created <span class=""><a href="attachment.cgi?id=12175" name="attach_12175" title="the two source file and a batch to build with clang-cl">attachment 12175</a> <a href="attachment.cgi?id=12175&action=edit" title="the two source file and a batch to build with clang-cl">[details]</a></span>
the two source file and a batch to build with clang-cl

The attached code try to convert constexpr arrays of enum classes values to
arrays of their underlying type.

The arrays are then accessed with template variables.

When arrays are indexed, if it is in a template function on the enum type, the
compiler mess with the arrays and use for each template instantiation the first
encountered one. If the functions are not template, every thing is ok.

I have the following functions ( E1 and E2 are enum class, and baz is the
template variable ) :

template <typename T> int read(int i) { return baz<T> [i]; }
int array1(int i) { return read<E1>(i); }
int array2(int i) { return read<E2>(i); }

constexpr auto const tab1 = baz<E1>;
constexpr auto const tab2 = baz<E2>;
int array1b(int i) { return tab1[i]; }
int array2b(int i) { return tab2[i]; }

They are called in the main function to dump the arrays 
for (int i{}; i != 3; ++i)
        std::cout << array1(i) << " ";
for (int i{}; i != 3; ++i)
        std::cout << array2(i) << " ";
std::cout << std::endl;
for (int i{}; i != 3; ++i)
    std::cout << array1b(i) << " ";
for (int i{}; i != 3; ++i)
    std::cout << array2b(i) << " ";

The output should be :
0 1 2 3 4 5
0 1 2 3 4 5
But it is :
3 4 5 3 4 5
0 1 2 3 4 5

If array1 and array2 definition is swapped, the first line will be "0 1 2 0 1
2" instead.

The remaining code to generate the arrays ( do not use std::array as it lacks
constexpr operator[] ):

template <typename T_, size_t N_> struct Array {
    constexpr size_t size() const { return N_; }
    constexpr bool empty() const { return N_ == 0; }

    constexpr T_ &operator[](size_t i) { return values_[i]; }
    constexpr T_ const &operator[](size_t i) const { return values_[i]; }

    constexpr T_ *begin() { return values_; }
    constexpr T_ *end() { return values_ + N_; }
    constexpr T_ const *begin() const { return values_; }
    constexpr T_ const *end() const { return values_ + N_; }

    T_ values_[N_];
};

enum class E1 { a = 0, b, c };
enum class E2 { a = 3, b, c };

template <typename E_> constexpr auto foo();

template <> constexpr auto foo<E1>() {
    return Array<E1, 4>{{E1::a, E1::b, E1::c}};
}
template <> constexpr auto foo<E2>() {
    return Array<E2, 4>{{E2::a, E2::b, E2::c}};
}

template <typename E_, size_t N_> constexpr auto ToIntArray(Array<E_, N_> const
&tab) {
    Array<std::underlying_type_t<E_>, N_> result{};
    for (size_t i{}; i != N_; ++i)
        result[i] = std::underlying_type_t<E_>(tab[i]);
    return result;
}

template <typename T_> constexpr decltype(foo<T_>()) bar = foo<T_>();
template <typename T_> constexpr decltype(ToIntArray(bar<T_>)) baz =
ToIntArray(bar<T_>);

Clang is built with the trunk of 20140302 with VS2013 :
clang version 3.5 (202633)
Target: x86_64-pc-win32
Thread model: posix</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>