[cfe-dev] Flag for better diagnosing errors in member templates

Johannes Schaub schaub.johannes at googlemail.com
Sat Jun 30 11:55:02 PDT 2012


Am 30.06.2012 20:36, schrieb Jordan Rose:
>
> On Jun 30, 2012, at 8:39 AM, Johannes Schaub wrote:
>
>> I would appreciate a clang flag that leads to better diagnosis in member
>> templates. Consider
>>
>>      template<typename T>
>>      struct A {
>>        template<typename U>
>>        void f(U u) {
>>          T t;
>>          // ...
>>        }
>>      };
>>
>>      struct B;
>>      template struct A<B>;
>>
>> A<B>::f's definition is ill-formed without a diagnostic being required
>> and Clang does not diagnose it. But Clang aims for catching as many bugs
>> as possible in user programs, and finding this bug appears to be
>> possible with the current clang abilities.
>>
>> What do you think?
>
> I'm pretty sure this is NOT an issue until A<B>::f is instantiated. It's
> possible a specialization of A<B>::f could be introduced that did not declare a
> B, or that B's definition could be completed before A<B>::f is actually used. That
> said, I understand your point about "catching as many bugs as possible", so maybe
> we could add this as an optional warning?
>

I think we may be talking about two different "instantiations" here. 
There are two entities that can be instantiated with regard to that "f" 
function template: The still-templated member definition of the class 
A<B> when T is provided, and the non-template function when U is provided.

What the user defined is A<T>::f<U>. When he explicitly instantiates A 
for T = B, then "An explicit instantiation that names a class template 
specialization is also an explicit instantiation of the same kind 
(declaration or definition) of each of its members (not including 
members inherited from base classes) that has not been previously 
explicitly specialized in the translation unit containing the explicit 
instantiation, except as described below.".

Hence when A<B> is instantiated, that will also instantiate A<B>::f, 
which leaves us with

     struct A<B> {
       template<typename U>
       void f(U u) {
         B t;
       }
     };


This template definition is ill-formed, because B was still incomplete 
at that point.




More information about the cfe-dev mailing list