Nick Nick - 2 months ago 20
C++ Question

Is this clang bug?

The code below compiles correctly on

clang 3.8.1-1
on ArchLinux.

Is this
clang
bug?

gcc
issue correct warning/error on this.

template <class T>
struct BugReproducer{
using size_type = typename T::size_type;

int bug1(size_type count);
int bug2(size_type count) const;
static int bug3(size_type count);
};

template <class T>
int BugReproducer<T>::bug1(size_type const count){
// this is a bug. must be not allowed
count = 5;

// return is to use the result...
return count;
}

template <class T>
int BugReproducer<T>::bug2(size_type const count) const{
// same for const method
count = 5;
return count;
}

template <class T>
int BugReproducer<T>::bug3(size_type const count){
// same for static method
count = 5;
return count;
}



struct DummyVector{
using size_type = int;
};



int main(){
using BugRepr = BugReproducer<DummyVector>;

BugRepr reproducer;

auto a = reproducer.bug1(1);
auto b = reproducer.bug2(1);
auto c = BugRepr::bug3(1);

// return is to use the result...
return a + b + c;
}


Here how I compile:

[nmmm@zenbook HM3]$ clang x.cc -std=c++11 -lstdc++ -Wall -Wpedantic -Wconversion


clang
and
c++14
- same result.

[nmmm@zenbook HM3]$ clang x.cc -std=c++14 -lstdc++ -Wall -Wpedantic -Wconversion


Here is gcc output:

[nmmm@zenbook HM3]$ gcc x.cc -std=c++11 -lstdc++ -Wall -Wpedantic -Wconversion
x.cc: In instantiation of ‘int BugReproducer<T>::bug1(BugReproducer<T>::size_type) [with T = DummyVector; BugReproducer<T>::size_type = int]’:
x.cc:46:28: required from here
x.cc:13:8: error: assignment of read-only parameter ‘count’
count = 5;
~~~~~~^~~
x.cc: In instantiation of ‘int BugReproducer<T>::bug2(BugReproducer<T>::size_type) const [with T = DummyVector; BugReproducer<T>::size_type = int]’:
x.cc:47:28: required from here
x.cc:22:8: error: assignment of read-only parameter ‘count’
count = 5;
~~~~~~^~~
x.cc: In instantiation of ‘static int BugReproducer<T>::bug3(BugReproducer<T>::size_type) [with T = DummyVector; BugReproducer<T>::size_type = int]’:
x.cc:48:20: required from here
x.cc:29:8: error: assignment of read-only parameter ‘count’
count = 5;
~~~~~~^~~

Answer

Yes, this is a bug in clang; filed at https://llvm.org/bugs/show_bug.cgi?id=30365.

The nature of the bug is that in a class template member function definition appearing outside ([class.mfct]/1) the class template, with the type of a parameter dependent on the class template parameters, clang uses the parameter type of the declaration rather than the parameter type of the definition where they differ in topmost cv-qualification. Simplified example:

template<class T> struct A { void f(typename T::U); };
template<class T> void A<T>::f(typename T::U const i) { i = 1; }
struct X { using U = int; };
int main() { A<X>{}.f(0); }

Per [dcl.fct]/5 the type of i within the definition of A<X>::f is int const (Use of 'const' for function parameters):

5 - [...] After producing the list of parameter types, any top-level cv-qualifiers modifying a parameter type are deleted when forming the function type. [...] [ Note: This transformation does not affect the types of the parameters. [...] — end note ]