[cfe-dev] Is clang name lookup too restrictive for dependent base classes?

Douglas Gregor dgregor at apple.com
Fri Feb 12 09:09:48 PST 2010


On Feb 12, 2010, at 2:09 AM, Enea Zaffanella wrote:

> John McCall wrote:
>> On Feb 11, 2010, at 3:03 AM, Enea Zaffanella wrote:
> 
> [...]
> 
>>> I checked clang source for a reference to the standard and I found the
>>> following (Sema/SemaTemplate.cpp):
>>> 
>>>    // C++0x [temp.expl.spec]p17:
>>>    //   A member or a member template may be nested within many
>>>    //   enclosing class templates. In an explicit specialization for
>>>    //   such a member, the member declaration shall be preceded by a
>>>    //   template<> for each enclosing class template that is
>>>    //   explicitly specialized.
>>>    // We interpret this as forbidding typedefs of template
>>>    // specializations in the scope specifiers of out-of-line decls.
>>> 
>>> Both g++ and Comeau will refuse the example above if the "template <>"
>>> was omitted ... but I don't see a strong relation between this behavior
>>> and the presence of a typedef name.
>> 
>> Without the template<>, the compiler doesn't realize you're declaring
>> an explicit specialization.  But the design of template parameters in the
>> language (and Doug can speak more to this) is that parameter clauses
>> are matched up with argument clauses in the declared name — that is,
>> you match angle brackets to angle brackets.  Using a typedef screws
>> up this matching because it means that parts of the name without
>> angle-brackets are supposed to matched against.
>> 
>> That's why the language requires it.  From a user-design point of view,
>> gcc's permissiveness on this goes a long way towards explaining why
>> nobody but language geeks understands how this matching is
>> supposed to work.
>> 
>> John.
> 
> Unfortunately, I made an error when extracting the testcase from GMP.
> 
> The complete testcase showing the problem (that could be found in 
> gmpxx.h, both versions 4.3.2 and 5.0.1) is as follows:
> ======================================================
> // Declaration of class template (__gmp_expr).
> template <typename T>
> struct S;
> 
> // Definition of explicit specialization (__gmp_expr<mpz_t, mpz_t>).
> template <>
> struct S<int> {
>   S foo(S);
> };
> 
> // Typedef declaration for explicit specialization (mpz_class).
> typedef S<int> SInt;
> 
> // Out-of-line definition of member of explicit specialization
> // (e.g., mpz_class::operator+=).
> SInt SInt::foo(SInt x)
> {
>   return x;
> }
> ======================================================
> 
> The big difference wrt previous testcase is that the class template 
> specialization is *defined* before introducing its typedef alias.

Someone amusingly, core issue 529 [*] is likely to change this behavior

	http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#529

by treating explicitly-specialized class template specializations the same way as implicitly-instantiated ones. That could require 'template<>' in this case.... at least, it would certainly require 'template<>' in

	template<> S<int> S<int>::foo(S<int> x) { return x; }

[*] This issue was discussed among the committee's core working group members during Monday's teleconference and has been marked as "tentative ready" for the upcoming committee meeting, so it's very likely to make it into C++0x.

> Here, clang complains the same way as above:
> ======================================================
> # clang++ -fsyntax-only test.cc
> test.cc:15:1: error: cannot use typedef 'SInt' (aka 'S<int>') in scope 
> specifier
>       for out-of-line declaration
> SInt SInt::foo(SInt x)
> ^
> 1 diagnostic generated.
> ======================================================
> 
> This code is accepted by g++ and Comeau and, as far as I can tell, it is 
> standard compliant. In fact, since we now have the explicit 
> specialization, C++98 14.7.3 p5 becomes relevant.
> Quoting the end of that paragraph:
> 
>   "Definitions of members of an explicitly specialized class
>    are defined in the same manner as members of normal classes,
>    and not using the explicit specialization syntax."
> 
> Since these definitions do not use the "template <>" prefixes, there is 
> no way (or need) to perform the matching you were mentioning above, 
> hence there is no need to forbid the use of typedef names.

John and I had discussed the use of typedef names within qualified declarator names a while back, and we thought we had support from the standard for diagnosing this as an error. However, I'm finding mostly weak support, so at some point we will fix

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



	- Doug



More information about the cfe-dev mailing list