[LLVMbugs] [Bug 22738] New: After r224456, clang++ fails to substitute some non-type template arguments

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Sat Feb 28 06:28:13 PST 2015


http://llvm.org/bugs/show_bug.cgi?id=22738

            Bug ID: 22738
           Summary: After r224456, clang++ fails to substitute some
                    non-type template arguments
           Product: new-bugs
           Version: trunk
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: new bugs
          Assignee: unassignedbugs at nondot.org
          Reporter: dimitry at andric.com
                CC: llvmbugs at cs.uiuc.edu
    Classification: Unclassified

After r224456 [1], clang++ fails to substitute some non-type template
arguments, in particular a construction used by google sparsehash [2].

This resulted in a port build failure during a test run for importing clang
3.6.0 into FreeBSD [3].

The resulting error is of the form:

./src/hash_test_interface.h:772:15: note: candidate template ignored:
substitution failure [with K2 = int, T2 = int]: deduced non-type template
argument does not have the same type as the its corresponding template
parameter ('int' vs 'const int &')
  friend void swap(HashtableInterface_DenseHashMap<K2,T2,Empty2,H2,E2,A2>& a,
              ^

A reduced example is as follows:

========================================================================
template <class K, const K& E>
class NonTypeTest {
public:
  template <class K2, const K2& E2>
  friend void swap(NonTypeTest<K2,E2>& a, NonTypeTest<K2,E2>& b);
};

template <class K2, const K2& E2>
void swap(NonTypeTest<K2,E2>& a, NonTypeTest<K2,E2>& b)
{
}

extern const int N = 42;

typedef NonTypeTest<int, N> TestType;

void test(TestType x, TestType y)
{
  swap(x, y);
}
========================================================================

When clang tries to deduce the non-type template argument for the free swap
function, it fails:

non-type2.cpp:19:3: error: no matching function for call to 'swap'
  swap(x, y);
  ^~~~
non-type2.cpp:9:6: note: candidate template ignored: substitution failure [with
K2 = int]: deduced non-type template argument does not have the same type as
the its corresponding template parameter ('int' vs 'const int &')
void swap(NonTypeTest<K2,E2>& a, NonTypeTest<K2,E2>& b)
     ^
1 error generated.

And strangely, it complains that the non-type template argument has the wrong
type, where it clearly is "const K2&", K2 being "int" in this case.

Note that gcc has no problems compiling this: I tried 4.7 through 5.0.

Even replacing the 'derived' non-type template argument with an explicit int
does not help:

========================================================================
template <class K, const int& E>
class NonTypeTest {
public:
  template <class K2, const int& E2>
  friend void swap(NonTypeTest<K2,E2>& a, NonTypeTest<K2,E2>& b);
};

template <class K2, const int& E2>
void swap(NonTypeTest<K2,E2>& a, NonTypeTest<K2,E2>& b)
{
}

extern const int N = 42;

typedef NonTypeTest<int, N> TestType;

void test(TestType x, TestType y)
{
  swap(x, y);
}
========================================================================

Resulting in:

non-type6.cpp:19:3: error: no matching function for call to 'swap'
  swap(x, y);
  ^~~~
non-type6.cpp:9:6: note: candidate template ignored: substitution failure [with
K2 = int]: deduced non-type template argument does not have the same type as
the its corresponding template parameter ('int' vs 'const int &')
void swap(NonTypeTest<K2,E2>& a, NonTypeTest<K2,E2>& b)
     ^
1 error generated.

Again, the versions of gcc that I tried had no problems compiling it.

Interestingly, when you remove the first template argument, it also begins to
trip up gcc 4.9 and later:

========================================================================
template <const int& E>
class NonTypeTest {
public:
  template <const int& E2>
  friend void swap(NonTypeTest<E2>& a, NonTypeTest<E2>& b);
};

template <const int& E2>
void swap(NonTypeTest<E2>& a, NonTypeTest<E2>& b)
{
}

extern const int N = 42;

typedef NonTypeTest<N> TestType;

void test(TestType x, TestType y)
{
  swap(x, y);
}
========================================================================

Clang produces the by now familiar error:

non-type7.cpp:19:3: error: no matching function for call to 'swap'
  swap(x, y);
  ^~~~
non-type7.cpp:9:6: note: candidate template ignored: substitution failure :
deduced non-type template argument does not have the same type as the its
corresponding template parameter ('int' vs 'const int &')
void swap(NonTypeTest<E2>& a, NonTypeTest<E2>& b)
     ^
1 error generated.

But while gcc 4.7 and 4.8 compile this without error, both gcc 4.9 and 5.0
start complaining:

non-type7.cpp: In function 'void test(TestType, TestType)':
non-type7.cpp:19:12: error: no matching function for call to 'swap(TestType&,
TestType&)'
   swap(x, y);
            ^
non-type7.cpp:9:6: note: candidate: template<const int& E2> void
swap(NonTypeTest<E2>&, NonTypeTest<E2>&)
 void swap(NonTypeTest<E2>& a, NonTypeTest<E2>& b)
      ^
non-type7.cpp:9:6: note:   template argument deduction/substitution failed:
non-type7.cpp:19:12: note:   couldn't deduce template parameter 'E2'
   swap(x, y);
            ^

It is not entirely clear from the error message *why* it could not deduce the
parameter, though.

Summarizing the above: is this a construction that was never really legal in
C++ (or C++11), but is it only recently being flagged as invalid?  Or is this a
bug in non-type template argument deduction, both in clang, and some versions
of gcc?

And if the construction is not legal, what is the correct way of achieving the
goal that google sparsehash tries to achieve? :-)

[1] http://llvm.org/viewvc/llvm-project?view=revision&revision=224456
[2] https://code.google.com/p/sparsehash/
[3]
http://package18.nyi.freebsd.org/data/headamd64PR197395-default/2015-02-27_12h37m16s/logs/errors/google-sparsehash-2.0.2_2.log

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20150228/bc8654fb/attachment.html>


More information about the llvm-bugs mailing list