Bug 14007 - [3.3/3.4 Regression] Incorrect use of const partial specialization for reference template argument
Summary: [3.3/3.4 Regression] Incorrect use of const partial specialization for refere...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.0.0
: P1 normal
Target Milestone: 3.4.1
Assignee: Nathan Sidwell
URL:
Keywords: rejects-valid, wrong-code
Depends on:
Blocks:
 
Reported: 2004-02-03 19:57 UTC by Matt Austern
Modified: 2004-10-30 21:11 UTC (History)
4 users (show)

See Also:
Host: powerpc-apple-darwin7.2.0
Target: powerpc-apple-darwin7.2.0
Build: powerpc-apple-darwin7.2.0
Known to work: 3.0.4 2.95.3
Known to fail: 3.3.1 3.2.3 3.2.2 3.4.0 4.0.0
Last reconfirmed: 2004-02-03 20:16:58


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Matt Austern 2004-02-03 19:57:13 UTC
Consider the following test program:
    #include <stdio.h>
    
    template <class T> struct X          { enum { val = 0 }; };
    template <class T> struct X<const T> { enum { val = 1 }; };
    
    int main() {
      printf("%d\n", X<int&>::val);
    }

The value printed is "1".  That is, the 3.x compiler (tested with 3.1, 3.3, and mainline) thinks that 
X<int&> refers to the X<const T> partial specialization rather than to the primary template.

I believe that this is wrong.  The partial specialization should only be used for a type that has a 
top-level const qualifier, and references are not cv-qualified.  (8.3.2, paragraph 1).

This is a regression from 2.95.
Comment 1 Andrew Pinski 2004-02-03 20:16:56 UTC
Here is something which is easy for regression testers to reject:
template <class T> struct X          { enum { val = 0 }; };
template <class T> struct X<const T> { enum { val = 1 }; };
int i[X<int&>::val == 0?1:-1];

Confirmed.

From Phil's regression hunter: Search converges between 2002-02-17-trunk (#59) and 2002-02-24-
trunk (#60).
Comment 2 Wolfgang Bangerth 2004-02-03 20:22:09 UTC
Or, still simpler: 
------------------ 
template <typename T> struct X {}; 
template <typename T> struct X<const T>; 
template struct X<int&>; 
------------------ 
 
W. 
Comment 3 Andrew Pinski 2004-02-03 20:26:06 UTC
Maybe related to bug 2645 and most likely broke by the patch which fixed that one.
Comment 4 Gabriel Dos Reis 2004-02-15 12:45:30 UTC
Adjust milestone
Comment 5 Mark Mitchell 2004-03-17 03:13:42 UTC
Nathan Sidwell believes that the standard, as presently written, requires the
current behavior.  He is going to try to write up an explanation of why he
believes this behavior is presently required and attach it to the PR.
Comment 6 Matt Austern 2004-03-17 18:23:11 UTC
Depending on what that explanation looks like, it might be a good idea to get in touch with the 
committee and request clarification.
Comment 7 Nathan Sidwell 2004-03-17 19:02:01 UTC
Subject: Re:  [3.3/3.4/3.5 Regression] Incorrect use of const
 partial specialization for reference template argument

austern at apple dot com wrote:
> ------- Additional Comments From austern at apple dot com  2004-03-17 18:23 -------
> Depending on what that explanation looks like, it might be a good idea to get in touch with the 
> committee and request clarification.
yes, I know. I had a conversation a while back with John Spicer, but
I was unable to properly describe the situation.  I need to iterate.

nathan

Comment 8 Nathan Sidwell 2004-03-19 14:27:09 UTC
given
	template <typename T> struct X {};  // #1
	template <typename T> struct X<const T>; //#2
	template struct X<int&>; //#3
Does #3 instantiate #1 or #2?  It seems obvious that #1 is what
is desired, but that is not what the standard says.  The relevent
bits of the standard are the partial specialization rules [14.5.4.1]
and the ignoring of cv qualifiers on a reference type introduced
by a typedef or template parameter [8.3.2]/1

To determine which partial specializations match, we see if its
arguments can be deduced from the actual template argument list. In
this case, can we deduce a 'T const' from 'int &' ? [14.8.2] describes
template argument deduction, but primarily focusses on deduction of a
templated function. Presumable [14.8.2.4] is what applies here. In
this case P is 'T const' and A is 'int &'. Para1 tells us to find a
type such that when subtituted into P, will make that compatible with
A.  Here 'int &' is such a type for T, because when substituted into
'T const', we ignore the const as the reference is introduced via a
template type.  Hence partial specialization #2 deduces with T='int
&'.

However, if the rule in [8.3.2]/1 about ignoring cv qualifiers on
references does not apply during deduction, then presumably the
same applies to DR295, where CV qualifiers of function types
introduced via a typedef or template parameter are similarly not
ignored in deduction.   If that is the case, does it apply during
deduction only in deduced contexts, or in both deduced and non-deduced
contexts? In either case, I can find nothing in the standard to
indicate this.

template <typename T> void Foo (T); // #1
template <typename T> void Foo (T const); // #2
static_cast <void (int &)> (Foo); // #1 or #2?

template <typename T> void Foo (T *); // #1
template <typename T> void Foo (T const *); // #2
void Baz ();
Foo (Baz); // which?

template <typename T> T const *Foo (T *); // #1
void Baz ();
Foo (Baz); // well formed?

template <typename T> void Foo (T *, T const * = 0);
void Baz ();
Foo (Baz); // well formed?
Comment 9 Mark Mitchell 2004-03-19 17:34:11 UTC
Without commenting on the function-type issues, I'll note that Nathan's argument
now makes sense to me.  Here is another way to approach it.

Given

	template <typename T> struct X {};  // #1
	template <typename T> struct X<const T>; //#2
	template struct X<int&>; //#3

the only issue is whether #2 matches #3.  If so, then it is clearly the most
specialized and is the one selected.

Presumably, 14.8.2/2 -- which is written for function templates, but makes sense
for explicitly specified class template arguments as well -- applies.  It lists
the cases in which deduction fails because an invalid type is created -- and
creating a cv-qualified reference type is not among them.   As Nathan notes,
8.3.2 explicitly allows cv-qualified reference types in this situation.

(Clearly, this example:

  template <typename T> void f(const T) {}
  template void f<int&>(int &);

is valid.)

I'm therefore closing this as INVALID.

Nathan, Matt -- if y'all thing this is the wrong behavior, would you please
submit a DR?
Comment 10 Gabriel Dos Reis 2004-03-19 17:39:32 UTC
Subject: Re:  [3.3/3.4/3.5 Regression] Incorrect use of const partial specialization for reference template argument

"mmitchel at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org> writes:

| I'm therefore closing this as INVALID.
| 
| Nathan, Matt -- if y'all thing this is the wrong behavior, would you please
| submit a DR?

Wihle I can see the logic in Nathan's reasoning, I think the proper
action is indeed to bring this before the committee.

-- Gaby

Comment 11 Matt Austern 2004-03-19 18:12:14 UTC
Subject: Re:  [3.3/3.4/3.5 Regression] Incorrect use of const partial specialization for reference template argument

Gaby and I have raised this with the committee.  c++std-core-10466.
  
  

Comment 12 Andrew Pinski 2004-03-19 18:19:21 UTC
Reopening to ...
Comment 13 Andrew Pinski 2004-03-19 18:20:24 UTC
Suspend it as this might not be the correct behaviour.
Comment 14 GCC Commits 2004-04-02 11:49:02 UTC
Subject: Bug 14007

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	nathan@gcc.gnu.org	2004-04-02 11:48:56

Modified files:
	gcc/cp         : ChangeLog tree.c pt.c 
	gcc/testsuite  : ChangeLog 
	gcc/testsuite/g++.dg/template: qualttp20.C 
	gcc/testsuite/g++.old-deja/g++.jason: report.C 
	gcc/testsuite/g++.old-deja/g++.other: qual1.C 
Added files:
	gcc/testsuite/g++.dg/template: unify5.C unify6.C 

Log message:
	cp:
	PR c++/14007
	* pt.c (check_cv_quals_for_unify): Correct logic for disallowed
	cv-qualifier unification.
	* tree.c (cp_build_qualified_type_real): Renable DR295 logic.
	testsuite:
	PR c++/14007
	* g++.dg/template/unify5.C: New.
	* g++.dg/template/unify6.C: New.
	* g++.dg/template/qualttp20.C: Adjust.
	* g++.old-deja/g++.jason/report.C: Adjust.
	* g++.old-deja/g++.other/qual1.C: Adjust.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.4026&r2=1.4027
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/tree.c.diff?cvsroot=gcc&r1=1.370&r2=1.371
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/pt.c.diff?cvsroot=gcc&r1=1.845&r2=1.846
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.3650&r2=1.3651
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/unify5.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/unify6.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/qualttp20.C.diff?cvsroot=gcc&r1=1.5&r2=1.6
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.old-deja/g++.jason/report.C.diff?cvsroot=gcc&r1=1.10&r2=1.11
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.old-deja/g++.other/qual1.C.diff?cvsroot=gcc&r1=1.6&r2=1.7

Comment 15 Nathan Sidwell 2004-04-02 12:06:54 UTC
apply to 3.4.1 when appropriate
Comment 16 Giovanni Bajo 2004-04-02 12:10:39 UTC
Mark, this is a wrong-code regression, and Nathan's patch silently changes the 
semantic of well-formed programs. Now that it's been made clear by the 
commettee that GCC behaviour is wrong, I think this bug is very critical. What 
about having the patch for 3.4.0? I'm not sure we want such a change to occur 
between point releases...
Comment 17 Gabriel Dos Reis 2004-04-02 15:12:59 UTC
Subject: Re:  [3.3/3.4/3.5 Regression] Incorrect use of const partial specialization for reference template argument

"giovannibajo at libero dot it" <gcc-bugzilla@gcc.gnu.org> writes:

| Mark, this is a wrong-code regression, and Nathan's patch silently changes the 
| semantic of well-formed programs. Now that it's been made clear by the 
| commettee that GCC behaviour is wrong, I think this bug is very critical. What 
| about having the patch for 3.4.0? I'm not sure we want such a change to occur 
| between point releases...

I second Giovanni's assessement.

I'm studying the applicability of this patch to 3.3.4.

-- Gaby
Comment 18 Nathan Sidwell 2004-04-02 15:29:15 UTC
This patch should not be applied to 3.4 or 3.3 without further discussion.
It appears the rules are still inconsistent, refer to 3518 for details.
Comment 19 Mark Mitchell 2004-04-02 16:59:49 UTC
I don't think we should be making any drastic changes right now.

The behavior in 3.4.0 is consistent with all releases from 3.0.x onwards. 
Changing the semantics from these releases should not be done until we are
absolutely sure what the right behavior is.

In my opinion, that logic should apply to 3.3.4 as well.  Making changes in
3.3.4 that will make it behave differently from 3.3.3 and from 3.4.0 would be a
mistake.
Comment 20 Wolfgang Bangerth 2004-04-02 17:39:01 UTC
I agree with Mark. This patch should only be allowed to go into 
3.3.4 if it also goes into 3.4, and maybe even then it shouldn't to 
not generate different code than 3.3.3. On the other hand, it would 
be better if it were applied to 3.4.0 rather than 3.4.1, to keep 
things consistent within dot releases. 
 
W. 
Comment 21 Gabriel Dos Reis 2004-04-03 12:38:11 UTC
Subject: Re:  [3.3/3.4 Regression] Incorrect use of const partial specialization for reference template argument

"mmitchel at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org> writes:

| I don't think we should be making any drastic changes right now.
| 
| The behavior in 3.4.0 is consistent with all releases from 3.0.x onwards. 
| Changing the semantics from these releases should not be done until we are
| absolutely sure what the right behavior is.

Agreed.

| In my opinion, that logic should apply to 3.3.4 as well.  Making changes in
| 3.3.4 that will make it behave differently from 3.3.3 and from 3.4.0 would be a
| mistake.

I'm considering the applicability of the patch for 3.3.4 only if it
goes to 3.4.[01].

-- Gaby
Comment 22 Mark Mitchell 2004-06-12 21:53:09 UTC
Nathan, does it make sense to apply your patch to 3.4.1?  Or does your Comment
#18 about remaining issues still apply?
Comment 23 Nathan Sidwell 2004-06-13 10:02:25 UTC
There is still someting wrong with this patch, which I tried to fix at the summit
on mainline.  Unfortunately the expected set of unexpected failures has changed, 
probably transiently due to the ssa merge, and I've not followed up on that.
Volker Reichelt sent me this test case 
template <typename T> int ref (T&)                { return 0; }
template <typename T> int ref (const volatile T&) { return 1; }

template <typename T> int ptr (T*)                { return 0; }
template <typename T> int ptr (const volatile T*) { return 2; }

void foo (void) {}

int main()
{
    return ref(foo) + ptr(&foo);
}

it should return zero, but does not.
Comment 24 Mark Mitchell 2004-06-18 23:54:11 UTC
Postponed until GCC 3.4.2.
Comment 25 Nathan Sidwell 2004-06-19 09:00:35 UTC
I have looked at the example in comment 23 and concluded that g++ DTRT. That
example should indeed return 1.  EDG 3.4 in strict mode does this too.

I conclude that the fix on mainline for this bug is ok for the 3.4 branch too.
Comment 26 Mark Mitchell 2004-06-19 17:39:44 UTC
Subject: Re:  [3.3/3.4 Regression] Incorrect use of const partial
 specialization for reference template argument

nathan at gcc dot gnu dot org wrote:

> ------- Additional Comments From nathan at gcc dot gnu dot org  2004-06-19 09:00 -------
> I have looked at the example in comment 23 and concluded that g++ DTRT. That
> example should indeed return 1.  EDG 3.4 in strict mode does this too.
> 
> I conclude that the fix on mainline for this bug is ok for the 3.4 branch too.

OK, please apply then.

Thanks,

Comment 27 Nathan Sidwell 2004-06-21 12:46:05 UTC
Applied to 3.4 branch
2004-06-21  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/3518
	* pt.c (check_cv_quals_for_unify): Ignore bogus CV quals at outer
	level.
	
	PR c++/14007
	* pt.c (check_cv_quals_for_unify): Correct logic for disallowed
	cv-qualifier unification.
	* tree.c (cp_build_qualified_type_real): Renable DR295 logic.
Comment 28 GCC Commits 2004-06-21 12:46:41 UTC
Subject: Bug 14007

CVSROOT:	/cvs/gcc
Module name:	gcc
Branch: 	gcc-3_4-branch
Changes by:	nathan@gcc.gnu.org	2004-06-21 12:46:29

Modified files:
	gcc/cp         : ChangeLog pt.c tree.c 
	gcc/testsuite  : ChangeLog 
	gcc/testsuite/g++.dg/template: qualttp20.C 
	gcc/testsuite/g++.old-deja/g++.jason: report.C 
	gcc/testsuite/g++.old-deja/g++.other: qual1.C 
Added files:
	gcc/testsuite/g++.dg/template: unify5.C unify6.C unify7.C 

Log message:
	cp:
	PR c++/3518
	* pt.c (check_cv_quals_for_unify): Ignore bogus CV quals at outer
	level.
	
	PR c++/14007
	* pt.c (check_cv_quals_for_unify): Correct logic for disallowed
	cv-qualifier unification.
	* tree.c (cp_build_qualified_type_real): Renable DR295 logic.
	testsuite:
	PR c++/3518
	* g++.dg/template/unify7.C: New.
	
	PR c++/14007
	* g++.dg/template/unify5.C: New.
	* g++.dg/template/unify6.C: New.
	* g++.dg/template/qualttp20.C: Adjust.
	* g++.old-deja/g++.jason/report.C: Adjust.
	* g++.old-deja/g++.other/qual1.C: Adjust.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.3892.2.125&r2=1.3892.2.126
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/pt.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.816.2.31&r2=1.816.2.32
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/tree.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.360.4.6&r2=1.360.4.7
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.3389.2.212&r2=1.3389.2.213
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/unify5.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.18.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/unify6.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.18.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/unify7.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.18.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/qualttp20.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.4&r2=1.4.32.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.old-deja/g++.jason/report.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.10&r2=1.10.16.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.old-deja/g++.other/qual1.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.5&r2=1.5.16.1

Comment 29 andreasmeier80 2004-07-01 20:58:49 UTC
Please adjust the target milestone to 3.4.1