Bug 29236

Summary: [4.2 Regression] Bogus ambiguity with templates + friend
Product: gcc Reporter: Ivan Shynkarenka <4ekucT>
Component: c++Assignee: Jason Merrill <jason>
Status: RESOLVED FIXED    
Severity: normal CC: 4ekucT, bangerth, fang, gcc-bugs, jwakely.gcc, mmitchel, paolo.carlini, rguenth, syntheticpp, s__nakayama, tsuna
Priority: P1 Keywords: rejects-valid
Version: 3.4.4   
Target Milestone: 4.2.5   
Host: Target:
Build: Known to work: 2.95 4.3.0
Known to fail: 3.2.3 3.3.5 3.4.6 4.0.3 4.0.4 4.1.1 4.1.2 4.2.0 3.0.4 Last reconfirmed: 2007-10-28 15:49:56
Bug Depends on:    
Bug Blocks: 29438, 29486    
Attachments: Friend operators with template in template argument

Description Ivan Shynkarenka 2006-09-26 14:04:49 UTC
The following code does not compile because class TestBad has both template in template argument T2 and friend operators.

template <class T>
class Temp {};

template <class T1, template <class> class T2>
class TestBad
{
public:
  template <class OtherT1, template <class> class OtherT2>
  friend bool operator == (const TestBad<OtherT1, OtherT2>& a, const TestBad<OtherT1, OtherT2>& b);
  template <class OtherT1, template <class> class OtherT2>
  friend bool operator != (const TestBad<OtherT1, OtherT2>& a, const TestBad<OtherT1, OtherT2>& b);

private:
  T2<T1> vector;
};

template <class OtherT1, template <class> class OtherT2>
bool operator == (const TestBad<OtherT1, OtherT2>& a, const TestBad<OtherT1, OtherT2>& b)
{
  (void)a;
  (void)b;
  return true;
}

template <class OtherT1, template <class> class OtherT2>
bool operator != (const TestBad<OtherT1, OtherT2>& a, const TestBad<OtherT1, OtherT2>& b)
{
  (void)a;
  (void)b;
  return false;
}

int main(int argc, char* argv[])
{
  bool result;
  TestBad<int, Temp> a;
  TestBad<int, Temp> b;

  result = (a == b);

  (void)a;
  (void)b;
  (void)result;
  (void)argc;
  (void)argv;
  return 0;
}

I've tried with gcc 3.4.4 in Mingw32 and it shows me the following error message:

test.cpp: In function `int main(int, char**)':
test.cpp:43: error: ambiguous overload for 'operator==' i
n 'a == b'
test.cpp:23: note: candidates are: bool operator==(const
TestBad<OtherT1, OtherT2>&, const TestBad<OtherT1, OtherT2>&) [with OtherT1 = in
t, OtherT2 = Temp]
test.cpp:13: note:                 bool operator==(const
TestBad<OtherT1, OtherT2>&, const TestBad<OtherT1, OtherT2>&) [with OtherT1 = in
t, OtherT2 = Temp, T1 = int, T2 = Temp]

PS: With out template in template argument everything is fine!
Comment 1 Ivan Shynkarenka 2006-09-26 14:07:51 UTC
Created attachment 12330 [details]
Friend operators with template in template argument

Test example which shows compiler error message.
Comment 2 Ivan Shynkarenka 2006-09-26 14:14:24 UTC
I've just tested this code under VC8 and it accepted it without errors.
Comment 3 Wolfgang Bangerth 2006-10-10 04:11:45 UTC
Confirmed:
--------------
template <typename T> struct A {};

template <template <typename> class P>
struct B {
    template <template <typename> class Q>
    friend bool foo (const B<Q>& a);
};

template <template <typename> class Q>
bool foo (const B<Q>& a);

void bar () {
  B<A> a;
  foo (a);
}
--------------------------

g/x> /home/bangerth/bin/gcc-4.2-pre/bin/c++ -c x.cc
x.cc: In function &#8216;void bar()&#8217;:
x.cc:14: error: call of overloaded &#8216;foo(B<A>&)&#8217; is ambiguous
x.cc:10: note: candidates are: bool foo(const B<Q>&) [with Q = A]
x.cc:6: note:                 bool foo(const B<Q>&) [with Q = A, P = A]


icc accepts the code. I believe we simply forget to unify the tentative
declaration from the friend declaration with the real template once we
encounter it, and end up with two declarations instead of one. We then
get confused when we have to pick one of the two.

This is a regression introduced in 3.2 over 2.95.

W.
Comment 4 Wolfgang Bangerth 2006-10-10 04:13:12 UTC
btw, this only happens if Q is really a template template argument. As noted
by the original reporter, the problem goes away if Q is simply a template
argument.

W.
Comment 5 Andrew Pinski 2006-10-10 04:31:36 UTC
foo should not have been injected by the friend.
Note the Priority should be only changed by the release manager.
Comment 6 Wolfgang Bangerth 2006-10-10 14:25:44 UTC
(In reply to comment #5)
> foo should not have been injected by the friend.

True, but that's irrelevant here. We get a tentative declaration that we
simply have to unify with the later real declaration.


> Note the Priority should be only changed by the release manager.

We've been over that before, Andrew. It has always been the case that
bugmasters do the initial triage, including setting an initial priority.
We've done that at least back to 2002, when we were still using GNATS instead
of bugzilla. It is also true that the RM has the prerogative to downgrade
priorities if he doesn't deem things that important. 

I maintain that it is important to raise the priority of PRs that are
rejects-valid so that they get some visibility, and in particular of
regressions. If someone higher up in the food chain thinks otherwise
wants to downgrade things, that's fine by me. But it's not productive
if bugmasters quarrel among themselves if something should be a P2 or a
P3 ...

W.
Comment 7 Mark Mitchell 2006-10-10 16:23:11 UTC
Subject: Re:  [4.0/4.1/4.2 Regression] Bogus ambiguity with
 templates + friend

bangerth at dealii dot org wrote:

> We've been over that before, Andrew. It has always been the case that
> bugmasters do the initial triage, including setting an initial priority.
> We've done that at least back to 2002, when we were still using GNATS instead
> of bugzilla. It is also true that the RM has the prerogative to downgrade
> priorities if he doesn't deem things that important. 

I have asked that all bugs be left at P3, and that I set their initial 
priority.  I also welcome input about what the priority should be, 
ideally in the audit trail for the PR itself.  But, looking at P3 bugs 
is how I see what the new bugs are.

Thanks,

Comment 8 Mark Mitchell 2006-10-16 18:36:50 UTC
The problem here is that tsubst, for a TEMPLATE_TEMPLATE_PARM, reduces the parameter level for the new TEMPLATE_TEMPLATE_PARM (via a call to reduce_template_parm_level), but does not reset TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL to a substituted version of the template.  Therefore, when we consider merging the friend declaration and the global declaration, we think that there types are different.
Comment 9 bangerth@math.tamu.edu 2006-10-17 01:49:20 UTC
Subject: Re:  [4.0/4.1/4.2 Regression] Bogus ambiguity with
 templates + friend


> TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL

If I didn't know better, this would sure sound like something written
under the influence :-)

-------------------------------------------------------------------------
Wolfgang Bangerth                email:            bangerth@math.tamu.edu
                                 www: http://www.math.tamu.edu/~bangerth/

Comment 10 Andrew Pinski 2006-10-20 07:33:42 UTC
*** Bug 29486 has been marked as a duplicate of this bug. ***
Comment 11 Andrew Pinski 2006-10-20 07:34:52 UTC
*** Bug 29438 has been marked as a duplicate of this bug. ***
Comment 12 Paolo Carlini 2007-01-06 15:54:51 UTC
Mark, I'm looking a bit into this issue myself, starting from your notes: at the moment I'm puzzled because, AFAICS, in the 2.95.3 tsubst nothing special happens after the reduce_template_parm_level, still the testcase passes. Any additional hint? Thanks in advance.

PS: Having looked at Kriang' 2000-09-04 change, I'm working under the assumption that BOUND_TEMPLATE_TEMPLATE_PARM is equivalent to the old TEMPLATE_TEMPLATE_PARM && TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO.
Comment 13 Mark Mitchell 2007-01-09 02:49:19 UTC
Subject: Re:  [4.0/4.1/4.2/4.3 Regression] Bogus ambiguity
 with templates + friend

pcarlini at suse dot de wrote:
> ------- Comment #12 from pcarlini at suse dot de  2007-01-06 15:54 -------
> Mark, I'm looking a bit into this issue myself, starting from your notes: at
> the moment I'm puzzled because, AFAICS, in the 2.95.3 tsubst nothing special
> happens after the reduce_template_parm_level, still the testcase passes. Any
> additional hint? Thanks in advance.

I no longer remember any more detail.  I wrote that note because I had
done some research, and then had to go work on something else, but it's
possible that the note wasn't as helpful as I had hoped. :-(

Comment 14 Gabriel Dos Reis 2007-02-03 20:26:44 UTC
won't fix in GCC-4.0.x.  Adjusting milestone.
Comment 15 Jason Merrill 2007-11-02 05:50:23 UTC
Subject: Bug 29236

Author: jason
Date: Fri Nov  2 05:50:06 2007
New Revision: 129844

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=129844
Log:
        PR c++/30897
        * pt.c (push_template_decl_real): Set DECL_CONTEXT on template
        template parms.
        (lookup_template_class): Use it to get the outer template args
        for instantiating one.

        PR c++/29236
        * pt.c (reduce_template_parm_level): tsubst the parameters
        of a template template parm.

Added:
    trunk/gcc/testsuite/g++.dg/template/ttp23.C
    trunk/gcc/testsuite/g++.dg/template/ttp24.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/pt.c

Comment 16 Jason Merrill 2007-11-02 05:59:20 UTC
Fixed for 4.3.0.
Comment 17 Joseph S. Myers 2008-07-04 21:32:39 UTC
Closing 4.1 branch.
Comment 18 Jason Merrill 2008-12-02 17:11:17 UTC
Fixed in 4.3.