This is GCC Bugzilla
This is GCC Bugzilla Version 2.20+
View Bug Activity | Format For Printing | Clone This Bug
This puzzle surfaced while analyzing Boost's testsuite failure of call_traits_test.cpp. That code assumes that two typedefs (for a const int&) are equivalent to an explicit const int & in order to specify a template type, but this is not the case for Gcc2.95.2 and Gcc3.0. The following code, which does compile (and should not!), illustrates the case: template <typename T> struct call_traits { public: typedef T type_less_spec; }; template <typename T> struct call_traits<T&> { typedef T type_more_spec; }; int main() { int num; // Two typedefs lead to the instant. of the less spec. ("wrong") template typedef int& r_type; typedef const r_type cr_type; call_traits<cr_type>::type_less_spec var1 = num; // ^^^^^^^^^^^^^^ // The explicit type leads to the instantiation of the "correct" one call_traits<const int&>::type_more_spec var2 = num; // ^^^^^^^^^^^^^^ // As happen with a single typedef! typedef const int& std_cr_type; call_traits<std_cr_type>::type_more_spec var3 = num; // As happen, indeed, without the cv-qualifier call_traits<r_type>::type_more_spec var4; } Release: 3.0 20010423 (prerelease) & Codesourcery Environment: i686, Linux2.2.19, glibc2.2.2, binutils2.11 How-To-Repeat: Before submitting the bug report, I cross checked with two other (commonly believed) very ISO-compliant compilers, which, indeed, rejected the testcase.
Fix: [nathan] [8.3.2] says that cv qualifers are ignored on a reference introduced via typdef/typename or tempate type arg. We should do the same for restrict on non-pointer types for consistency. After discussion on the gcc list (http://gcc.gnu.org/ml/gcc/2001-04/msg01235.html) the consensus is to do this with a warning for all cases other than constifying a reference.
From: Paolo Carlini <pcarlini@unitus.it> To: gcc-gnats@gcc.gnu.org, pcarlini@unitus.it, nobody@gcc.gnu.org Cc: landauer@apple.com Subject: Re: c++/2645 Date: Thu, 26 Apr 2001 00:12:02 +0200 --------------FCEFF1AD2F56FB11569E6057 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Sorry for the confusion in the testcase (I badly mistaken a ref to a const int with a const ref to an int :( (thanks to Doug Landauer for pointing this out!) Therefore I cleaned up my testcase (which shows the Gcc problem) as follows: ---------------------- template <typename T> struct call_traits { public: typedef T type_less_spec; }; template <typename T> struct call_traits<T&> { typedef T type_more_spec; }; int main() { int num; // Using two typedefs to specify a const & leads to the instant. of the less // specialized ("wrong") template typedef int& r_type; typedef const r_type cr_type; call_traits<cr_type>::type_less_spec var1 = num; // ^^^^^^^^^^^^^^ // Without the cv-qualifier the more spec. ("right") template is instantiated call_traits<r_type>::type_more_spec var4; // ^^^^^^^^^^^^^^ } ------------------ http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view&pr=2645&database=gcc --------------FCEFF1AD2F56FB11569E6057 Content-Type: text/html; charset=us-ascii Content-Transfer-Encoding: 7bit <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> <html> <pre>Sorry for the confusion in the testcase (I badly mistaken a ref to a const int with a const ref</pre> <pre>to an int :(</pre> <pre>(thanks to Doug Landauer for pointing this out!)</pre> <pre></pre> <pre>Therefore I cleaned up my testcase (which shows the Gcc problem) as follows:</pre> <pre>----------------------</pre> <pre>template <typename T></pre> <pre>struct call_traits</pre> <pre>{</pre> <pre>public:</pre> <pre> typedef T type_less_spec;</pre> <pre>};</pre> <pre></pre> <pre>template <typename T></pre> <pre>struct call_traits<T&></pre> <pre>{</pre> <pre> typedef T type_more_spec;</pre> <pre>};</pre> <pre></pre> <pre>int main()</pre> <pre>{</pre> <pre> int num;</pre> <pre></pre> <pre> // Using two typedefs to specify a const & leads to the instant. of the less</pre> <pre> // specialized ("wrong") template</pre> <pre> typedef int& r_type;</pre> <pre> typedef const r_type cr_type;</pre> <pre> call_traits<cr_type>::type_less_spec var1 = num;</pre> <pre> // ^^^^^^^^^^^^^^</pre> <pre> </pre> <pre> // Without the cv-qualifier the more spec. ("right") template is instantiated</pre> <pre> call_traits<r_type>::type_more_spec var4;</pre> <pre> // ^^^^^^^^^^^^^^</pre> <pre>}</pre> <pre>------------------</pre> <pre></pre> <pre></pre> <pre></pre> <pre></pre> <pre><A HREF="http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view&pr=2645&database=gcc">http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view&pr=2645&database=gcc</A></pre> <pre></pre> </html> --------------FCEFF1AD2F56FB11569E6057--
State-Changed-From-To: open->analyzed State-Changed-Why: confirmed. [8.3.2] says we should ignore the const when constifying a reference type via a typedef. i.e int & const thing; // ill-formed typedef int &ref_t; const ref_t thing; // ok, thing is int & ditto for volatile
From: nathan@gcc.gnu.org To: gcc-gnats@gcc.gnu.org, nobody@gcc.gnu.org, pcarlini@unitus.it Cc: Subject: Re: c++/2645 Date: 26 Apr 2001 08:23:29 -0000 Synopsis: Boost-related const & typdef in template puzzle State-Changed-From-To: open->analyzed State-Changed-By: nathan State-Changed-When: Thu Apr 26 01:23:29 2001 State-Changed-Why: confirmed. [8.3.2] says we should ignore the const when constifying a reference type via a typedef. i.e int & const thing; // ill-formed typedef int &ref_t; const ref_t thing; // ok, thing is int & ditto for volatile http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view&pr=2645&database=gcc
Responsible-Changed-From-To: unassigned->nathan Responsible-Changed-Why: patch in progress
From: nathan@gcc.gnu.org To: gcc-bugs@gcc.gnu.org, gcc-gnats@gcc.gnu.org, gcc-prs@gcc.gnu.org, nathan@gcc.gnu.org, nobody@gcc.gnu.org, pcarlini@unitus.it Cc: Subject: Re: c++/2645: cvr qualifiers and typedef/typename/template reference types Date: 11 Dec 2001 20:18:31 -0000 Synopsis: cvr qualifiers and typedef/typename/template reference types Responsible-Changed-From-To: unassigned->nathan Responsible-Changed-By: nathan Responsible-Changed-When: Tue Dec 11 12:18:31 2001 Responsible-Changed-Why: patch in progress http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&pr=2645&database=gcc
State-Changed-From-To: analyzed->closed State-Changed-Why: 2002-02-19 Nathan Sidwell <nathan@codesourcery.com> PR c++/2645, DR 295 * cp-tree.h (tsubst_flags_t): Add tf_ignore_bad_quals, tf_keep_type_decl. (make_typename_type): Use tsubst_flags_t. * decl.c (make_typename_type): Adjust. Return non-artificial TYPE_DECLs, if required. (grokdeclarator): Simplify CVR qualification handling. Allow bad qualifiers on typedef types. * decl2.c (handle_class_head): Adjust make_typename_type call. * parse.y (nested_name_specifier): Likewise. (typename_sub0): Likewise. (typename_sub1): Likewise. * pt.c (convert_template_argument): Adjust make_typename_type return value. (tsubst): Adjust cp_build_qualified_type_real calls. (check_cv_quals_for_unify): Cope with alowing bad qualifications on template type parms. (instantiate_decl): Recheck substitutions to give warnings on bad qualifications. * tree.c (cp_build_qualified_type_real): Use tf_allow_bad_quals.
State-Changed-From-To: closed->analyzed State-Changed-Why: I will look at this again
State-Changed-From-To: analyzed->closed State-Changed-Why: afaict 3.3 & 3.4 do the right thing