Bug 42018

Summary: Template specialization in wrong namespace accepted if it matches template arguments of an earlier specialization
Product: gcc Reporter: Simon Richter <Simon.Richter>
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED DUPLICATE    
Severity: minor CC: egallager, fang, gcc-bugs, redi, webrown.cpp
Priority: P3 Keywords: accepts-invalid, patch
Version: 4.3.4   
Target Milestone: ---   
Host: x86_64-unknown-linux-gnu Target: x86_64-unknown-linux-gnu
Build: x86_64-unknown-linux-gnu Known to work: 7.1.0
Known to fail: 4.1.2, 4.3.4, 4.4.3, 4.5.1, 4.6.0, 6.4.0 Last reconfirmed: 2010-10-01 11:52:43

Description Simon Richter 2009-11-12 12:36:51 UTC
The following code should fail to compile due to ambiguity (the non-template case properly fails):

template<typename>
void foo(void);

template<>
void foo<int>(void);

namespace {
  template<>
  void foo<int>(void) { return; }
}

int main(int, char **) { foo<int>(); }
Comment 1 Jonathan Wakely 2009-11-12 13:24:30 UTC
It should fail to compile because you are specializing a template which was never declared, not because it is ambiguous.

namespace {
  template<>
  void foo<int>(void) { return; }
}

That is a specialization, but there is no matching primary template.

This fails due to ambiguous overloads:

template<typename>
void foo(void);

template<>
void foo<int>(void);

namespace {
  template<class>
  void foo(void) { return; }
}

Comment 2 Jonathan Wakely 2009-11-12 13:28:19 UTC
This fails:

template<typename>
void foo(void);

template<>
void foo<int>(void);

namespace {
  template<>
  void foo<int>(void) { return; }
}

int main(int, char **) { foo<int>(); }

ttt.cc:6: error: specialization of 'template<class> void foo()' in different namespace
ttt.cc:2: error:   from definition of 'template<class> void foo()'


But if a valid specialization already exists, the one in the anon namespace is not rejected. That's a bug.
Comment 3 Jonathan Wakely 2010-10-01 11:52:43 UTC
Oops, I've just realised I pasted the wrong code in comment 2, I meant to say that this fails:

template<typename>
void foo(void);

namespace {
  template<>
  void foo<int>(void) { return; }
}

template<>
void foo<int>(void);

int main(int, char **) { foo<int>(); }

i.e. if the invalid specialization comes before the valid specialization, it's rejected.

But in the original example, where the invalid specialization comes later, it's incorrectly accepted. The same error should be given in both cases: the specialization in the anon namespace does not match any primary template declaration.
Comment 4 Jonathan Wakely 2010-10-01 12:00:51 UTC
It doesn't even depend on unnamed namespaces!

This is also accepted:

template<typename>
void foo(void);

template<>
void foo<int>(void);

namespace xxx {
  template<>
  void foo<int>(void) { return; }
}


I've adjusted the summary accordingly.
Comment 5 Jonathan Wakely 2010-10-01 21:21:03 UTC
incomplete patch posted to
http://gcc.gnu.org/ml/gcc-patches/2010-10/msg00054.html
Comment 6 Eric Gallager 2018-03-10 03:17:36 UTC
(In reply to Jonathan Wakely from comment #5)
> incomplete patch posted to
> http://gcc.gnu.org/ml/gcc-patches/2010-10/msg00054.html

adding the "patch" keyword
Comment 7 Andrew Pinski 2021-08-23 08:31:42 UTC
Fixed by r7-4488
Comment 8 Andrew Pinski 2021-08-23 08:33:28 UTC
Dup of bug 56480.

*** This bug has been marked as a duplicate of bug 56480 ***