Bug 14500 - most specialized function template vs. non-template function
Summary: most specialized function template vs. non-template function
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.4.0
: P2 normal
Target Milestone: 4.0.0
Assignee: Jason Merrill
URL:
Keywords:
Depends on: 13294
Blocks:
  Show dependency treegraph
 
Reported: 2004-03-09 04:51 UTC by Benjamin Kosnik
Modified: 2006-02-28 08:52 UTC (History)
4 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2005-09-10 17:04:15


Attachments
Patch for 14500 (787 bytes, patch)
2004-04-05 23:01 UTC, Jason Merrill
Details | Diff
Revised patch (756 bytes, patch)
2004-04-07 17:09 UTC, Benjamin Kosnik
Details | Diff
This is a testcase that compiles (315 bytes, text/plain)
2004-04-08 19:59 UTC, Benjamin Kosnik
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Benjamin Kosnik 2004-03-09 04:51:53 UTC
While working on c++/13658, I ran into divergent behavior between icc 7.1 and g++.

I think g++ is wrong, and that in the code below, the explicitly specialized
function template is the most specialized function, and should be called.

By removing the template specialization syntax (ie "template<>"), and trying
again, I get something that is considered the most specialized. But, why this
and not the other?

-benjamin

#include <vector>
#include <cassert>
#define VERIFY assert
 
struct T { int i; };

int swap_calls;

namespace std
{
  // Should be most specialized.
#if 1
  template<> 
#endif
    inline void 
    swap(vector<T, allocator<T> >&, vector<T, allocator<T> >&) 
    { ++swap_calls; }
}

void test01()
{
  bool test __attribute__((unused)) = true;
  std::vector<T> A;
  std::vector<T> B;
  swap_calls = 0;
  std::swap(A, B);
  VERIFY(1 == swap_calls); // XXX fails
}

void test02()
{
  bool test __attribute__((unused)) = true;
  using namespace std;
  vector<T> A;
  vector<T> B;
  swap_calls = 0;
  swap(A, B);
  VERIFY(1 == swap_calls);
}

int main()
{
  test01();
  test02();
  return 0;
}
Comment 1 Wolfgang Bangerth 2004-03-09 05:18:29 UTC
Hm, I have a hard time understanding what's going on. Would you 
mind posting a self-contained example that doesn't make use 
of odd include files that contain using namespace stuff? 
 
W. 
Comment 2 Gabriel Dos Reis 2004-03-09 07:13:20 UTC
Subject: Re:  New: most specialized function template vs. non-template function

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

| While working on c++/13658, I ran into divergent behavior between
| icc 7.1 and g++. 
| 
| I think g++ is wrong, and that in the code below, the explicitly specialized
| function template is the most specialized function, and should be called.

It looks to me that this is an interaction between "strong using" and
specializations:  The most specialized swap() (for vector<>) leaves in 
__gnu_norm:: whereas the most general leaves in std::. Therefore, when
you explicitly specialize, the compiler just considers the template in
std:: and forgets about the other one in __gnu_norm::; therefore it 
thinks that you're specializing the one in std::.  Which is wrong.
It should have collected all swap() reachable through strongly used
namespaces. (Recall that strong using says for all purposes except
mangling, everything is the same). 

| By removing the template specialization syntax (ie "template<>"), and trying
| again, I get something that is considered the most specialized. But, why this
| and not the other?

When you remove the explicit specialization marker, you're overloading
with an *ordinary* function and overload resolution prefers
non-templates over templates when given equal chances.

-- Gaby
Comment 3 Gabriel Dos Reis 2004-03-09 07:21:29 UTC
Subject: Re:  most specialized function template vs. non-template function

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

| ------- Additional Comments From bangerth at dealii dot org  2004-03-09 05:18 -------
| Hm, I have a hard time understanding what's going on. Would you 
| mind posting a self-contained example that doesn't make use 
| of odd include files that contain using namespace stuff? 

Try with this:

   namespace A {
     template<class T> X { };

     template<class T>
       void f(X<T>&);            // #1
   }

  namespace B {
    using namespace A __attribute__((trustme));
    
    template<class T>
      void f(T&);               // #2
  }

  struct foo { };

  namespace B {
    template<>
      void(X<foo>&);            // #3
  }

  B::X<int> x;
  B::f(x);                      // calls #2 instead of #3

-- Gaby
Comment 4 Paolo Carlini 2004-03-09 14:34:45 UTC
Is c++/13294 "strongly related" ;) ?
Comment 5 Benjamin Kosnik 2004-03-09 16:34:08 UTC
Subject: Re:  most specialized function template vs.
 non-template function


>It looks to me that this is an interaction between "strong using" and
>specializations:  The most specialized swap() (for vector<>) leaves in 
>__gnu_norm:: whereas the most general leaves in std::. Therefore, when
>you explicitly specialize, the compiler just considers the template in
>std:: and forgets about the other one in __gnu_norm::; therefore it 
>thinks that you're specializing the one in std::.  Which is wrong.
>It should have collected all swap() reachable through strongly used
>namespaces. (Recall that strong using says for all purposes except
>mangling, everything is the same). 

Ok, that's what I thought too. Thanks for the clarification, and the
smaller testcase. 

-benjamin
Comment 6 Giovanni Bajo 2004-03-10 12:23:38 UTC
Surely related to PR 13294, which is targeted at 3.4.0.
Comment 7 Giovanni Bajo 2004-03-10 12:28:04 UTC
Gaby, I tried your testcase with mainline, but the code does call your function 
#3. If I change the attribute to be "strong", then function #1 is called. Is 
this the bug? I don't know the semantics of strong using.
Comment 8 Gabriel Dos Reis 2004-03-10 15:21:19 UTC
Subject: Re:  most specialized function template vs. non-template function

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

| Gaby, I tried your testcase with mainline, but the code does call
| your function #3. If I change the attribute to be "strong", then
| function #1 is called. Is this the bug? I don't know the semantics
| of strong using. 

If that happens then we have a double bug :-)

Yes, the testcasse for the bug is what happens when you use "strong"
in the attribute.
(Sorry, I should not have been testing a fine point made by Jason a
while ago).  

Thanks for experimenting and correcting the testcase..

-- Gaby

Comment 9 Jason Merrill 2004-04-05 23:01:40 UTC
Created attachment 6038 [details]
Patch for 14500
Comment 10 Jason Merrill 2004-04-05 23:08:10 UTC
I've attached a patch for this bug, which I haven't been able to fully test
because I'm on vacation.  It would be nice to get this into 3.4.0, since it's a
significant lack of functionality in strong using, but it could wait for 3.4.1.
Comment 11 Benjamin Kosnik 2004-04-05 23:16:40 UTC
Subject: Re:  most specialized function template vs.
 non-template function


>I've attached a patch for this bug, which I haven't been able to fully test
>because I'm on vacation.  It would be nice to get this into 3.4.0, since it's a
>significant lack of functionality in strong using, but it could wait for 3.4.1.

I've tested this, and it looks like there are a couple of new failures.

FAIL: g++.dg/template/lookup5.C (test for excess errors)
FAIL: g++.old-deja/g++.ns/template12.C (test for excess errors)
FAIL: g++.old-deja/g++.ns/template13.C (test for excess errors)
FAIL: g++.old-deja/g++.pt/lookup10.C (test for excess errors)

Where the errors are:

FAIL: g++.dg/template/lookup5.C (test for excess errors)
Excess errors:
/mnt/hd/src/gcc/gcc/testsuite/g++.dg/template/lookup5.C:8: error: specializing `void N::f(T) [with T = int]' in different namespace
/mnt/hd/src/gcc/gcc/testsuite/g++.dg/template/lookup5.C:4: error:   from definition of `template<class T> void N::f(T)'

-benjamin
Comment 12 Benjamin Kosnik 2004-04-07 17:09:09 UTC
Created attachment 6051 [details]
Revised patch


This revised patch only adds two new FAILs, which may or may not be real fails.
I'll investigate this today.
Comment 13 Benjamin Kosnik 2004-04-08 19:59:46 UTC
Created attachment 6060 [details]
This is a testcase that compiles


Jason, here's a testcase that we should (IMHO) check in with this patch.

The other implementation of namespace association, EDG, had a similar error to
g++ pre patch. Should we ask Daveed for his opinion on this?

-benjamin
Comment 14 Jason Merrill 2004-04-08 20:42:18 UTC
Subject: Re:  most specialized function template vs.
 non-template function

On 8 Apr 2004 19:59:47 -0000, "bkoz at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org> wrote:

> The other implementation of namespace association, EDG, had a similar
> error to g++ pre patch. Should we ask Daveed for his opinion on this?

I'm sure EDG was just trying to be compatible with us.

Jason
Comment 15 Giovanni Bajo 2004-04-15 09:45:45 UTC
Jason, given the resolution of PR 13294, what is your position on this bug?
Comment 16 Jason Merrill 2004-04-15 20:55:44 UTC
Subject: Re:  most specialized function template vs.
 non-template function

On 15 Apr 2004 09:45:46 -0000, "giovannibajo at libero dot it" <gcc-bugzilla@gcc.gnu.org> wrote:

> Jason, given the resolution of PR 13294, what is your position on this bug?

It's still a bug, but it's not worth blocking 3.4.0 for.

Jason
Comment 17 Mark Mitchell 2004-06-12 21:51:09 UTC
Postponed until GCC 3.4.2.
Comment 18 Mark Mitchell 2004-08-29 18:51:54 UTC
Postponed until GCC 3.4.3.
Comment 19 Mark Mitchell 2004-11-01 00:45:59 UTC
Postponed until GCC 3.4.4.
Comment 20 Andrew Pinski 2005-02-21 21:08:31 UTC
Any news on this?
Comment 21 Wolfgang Bangerth 2005-07-23 22:32:56 UTC
Benjamin, what's the status on this now? 
 
W. 
Comment 22 Gabriel Dos Reis 2006-02-28 08:52:32 UTC
Fixed in 4.0.
Won't fix in 3.4.6