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

Jordan Rose jordan_rose at apple.com
Sat Jun 30 13:09:24 PDT 2012

On Jun 30, 2012, at 11:55 AM, Johannes Schaub wrote:

> 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.

Ah, right. In my mind that was not ill-formed, because A::f hasn't been instantiated yet. But of course the reference to "B" is already bound, as well as the implicit reference to B's constructor. So yes, this would be something we could diagnose in theory.


More information about the cfe-dev mailing list