ADL causing implicit template class instantiation failure

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

ADL causing implicit template class instantiation failure

Marco
I'm taking a look at a possible clang issue with the following code:
___________________________
struct incomplete;

template<class T> 
struct A { T d; };

template <class T> 
struct B { };

template<typename T> void func(T &t);

int main() {
    B<A<incomplete>> a, b;
    a = b;
}
___________________________


this code causes clang to emit an error "incomplete type T d;". I searched in the cpp standard and found nothing related to ADL causing an implicit instantiation in this case. So I started researching clang's source and I believe this is what is happening:

- ADL process starts
- A<incomplete> is tried to be instantiated to have a better ADL set (and also for other reasons as explained here: http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20140310/101487.html ) with a "complain = false" flag (so it won't complain if the template can't be instantiated)
- The flag is lost during instantiation of the template members, I'm posting the entire MSVC stack trace here: http://nopaste.info/829f7404e6.html

I spoke with David Blaikie about this issue and told me to give it a wider audience here.

What is strange to me is that also gcc behaves in the same way as clang, so it might as well mean that I'm getting something wrong and clang/gcc are both correct in this.
Reply | Threaded
Open this post in threaded view
|

Re: ADL causing implicit template class instantiation failure

Richard Smith
On Tue, Sep 23, 2014 at 8:57 AM, Marco <[hidden email]> wrote:
I'm taking a look at a possible clang issue with the following code:
___________________________
struct incomplete;

template<class T>
struct A { T d; };

template <class T>
struct B { };

template<typename T> void func(T &t);

int main() {
    B<A&lt;incomplete>> a, b;
    a = b;
}
___________________________


this code causes clang to emit an error "incomplete type T d;". I searched
in the cpp standard and found nothing related to ADL causing an implicit
instantiation in this case.

Here it is:

[basic.lookup.argdep]/2:

"[...] if T is a class template specialization, its associated [...] classes also include: the [...] classes associated with the types of the template arguments provided for template type parameters [...]"

[basic.lookup.argdep]/4:

"When considering an associated namespace, the lookup is the same as the lookup performed when the associated namespace is used as a qualifier (3.4.3.2) except that:
[...] Any namespace-scope friend functions or friend function templates declared in associated classes are visible within their respective namespaces even if they are not visible during an ordinary lookup (11.3)"

[temp.inst]/1:

"Unless a class template specialization has been explicitly instantiated (14.7.2) or explicitly specialized (14.7.3), the class template specialization is implicitly instantiated [...] when the completeness of the class type affects the semantics of the program."

The completeness of the class type can affect whether friends are declared in an associated class, which therefore affects the semantics of the program. Therefore ADL triggers the implicit instantiation of all associated classes, and A<incomplete> is an associated class of B<A<incomplete>>.

So I started researching clang's source and I
believe this is what is happening:

- ADL process starts

This seems like the interesting part. Why are we performing ADL? There can be no non-member operator= functions (other than the builtin ones, which are not found by ADL). [over.match.oper]/3.2 says:

"The set of non-member candidates is the result of the unqualified lookup of operator@ in the context of the expression according to the usual rules for name lookup in unqualified function calls (3.4.2) except that all member functions are ignored."

The implication is that we don't perform this lookup (and thus do not perform ADL) if there is no non-member form in Table 11, but that's not explicitly stated. In any case, we're /permitted/ to skip this due to [temp.inst]p7: "If the overload resolution process can determine the correct function to call without instantiating a class template definition, it is unspecified whether that instantiation actually takes place."

Anyway, fixed in r218330 by skipping ADL in this case. I'm also taking this to the C++ committee to see if we can get the rules clarified here.

(GCC gets this wrong for operator[] and operator-> too; Clang already did the right thing there.)

- A<incomplete> is tried to be instantiated to have a better ADL set (and
also for other reasons as explained here:
http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20140310/101487.html
) with a "complain = false" flag (so it won't complain if the template can't
be instantiated)
- The flag is lost during instantiation of the template members, I'm posting
the entire MSVC stack trace here: http://nopaste.info/829f7404e6.html

I spoke with David Blaikie about this issue and told me to give it a wider
audience here.

What is strange to me is that also gcc behaves in the same way as clang, so
it might as well mean that I'm getting something wrong and clang/gcc are
both correct in this.



--
View this message in context: http://clang-developers.42468.n3.nabble.com/ADL-causing-implicit-template-class-instantiation-failure-tp4041705.html
Sent from the Clang Developers mailing list archive at Nabble.com.
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: ADL causing implicit template class instantiation failure

Marco
Thanks Richard! Now it makes sense. I completely agree that the standard might be rendered clearer on this point.

2014-09-23 22:55 GMT+02:00 Richard Smith [via Clang Developers] <[hidden email]>:
On Tue, Sep 23, 2014 at 8:57 AM, Marco <[hidden email]> wrote:
I'm taking a look at a possible clang issue with the following code:
___________________________
struct incomplete;

template<class T>
struct A { T d; };

template <class T>
struct B { };

template<typename T> void func(T &t);

int main() {
    B<A&lt;incomplete>> a, b;
    a = b;
}
___________________________


this code causes clang to emit an error "incomplete type T d;". I searched
in the cpp standard and found nothing related to ADL causing an implicit
instantiation in this case.

Here it is:

[basic.lookup.argdep]/2:

"[...] if T is a class template specialization, its associated [...] classes also include: the [...] classes associated with the types of the template arguments provided for template type parameters [...]"

[basic.lookup.argdep]/4:

"When considering an associated namespace, the lookup is the same as the lookup performed when the associated namespace is used as a qualifier (3.4.3.2) except that:
[...] Any namespace-scope friend functions or friend function templates declared in associated classes are visible within their respective namespaces even if they are not visible during an ordinary lookup (11.3)"

[temp.inst]/1:

"Unless a class template specialization has been explicitly instantiated (14.7.2) or explicitly specialized (14.7.3), the class template specialization is implicitly instantiated [...] when the completeness of the class type affects the semantics of the program."

The completeness of the class type can affect whether friends are declared in an associated class, which therefore affects the semantics of the program. Therefore ADL triggers the implicit instantiation of all associated classes, and A<incomplete> is an associated class of B<A<incomplete>>.

So I started researching clang's source and I
believe this is what is happening:

- ADL process starts

This seems like the interesting part. Why are we performing ADL? There can be no non-member operator= functions (other than the builtin ones, which are not found by ADL). [over.match.oper]/3.2 says:

"The set of non-member candidates is the result of the unqualified lookup of operator@ in the context of the expression according to the usual rules for name lookup in unqualified function calls (3.4.2) except that all member functions are ignored."

The implication is that we don't perform this lookup (and thus do not perform ADL) if there is no non-member form in Table 11, but that's not explicitly stated. In any case, we're /permitted/ to skip this due to [temp.inst]p7: "If the overload resolution process can determine the correct function to call without instantiating a class template definition, it is unspecified whether that instantiation actually takes place."

Anyway, fixed in r218330 by skipping ADL in this case. I'm also taking this to the C++ committee to see if we can get the rules clarified here.

(GCC gets this wrong for operator[] and operator-> too; Clang already did the right thing there.)

- A<incomplete> is tried to be instantiated to have a better ADL set (and
also for other reasons as explained here:
http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20140310/101487.html
) with a "complain = false" flag (so it won't complain if the template can't
be instantiated)
- The flag is lost during instantiation of the template members, I'm posting
the entire MSVC stack trace here: http://nopaste.info/829f7404e6.html

I spoke with David Blaikie about this issue and told me to give it a wider
audience here.

What is strange to me is that also gcc behaves in the same way as clang, so
it might as well mean that I'm getting something wrong and clang/gcc are
both correct in this.



--
View this message in context: http://clang-developers.42468.n3.nabble.com/ADL-causing-implicit-template-class-instantiation-failure-tp4041705.html
Sent from the Clang Developers mailing list archive at Nabble.com.
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev


_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev



To unsubscribe from ADL causing implicit template class instantiation failure, click here.
NAML



--

__________________________

Marco Alesiani
Software Engineer @ NVIDIA Corporation (www.nvidia.com)
Via Giacomo Matteotti 20
Colli del Tronto (AP)
(+39) 0736890858
(+39) 3331169898