GCC bug or UB? Should this code compile?
Asked Answered
S

1

16

The code below compiles fine with clang, but does not compile with GCC (tried 4.1.2, 4.5.4 and 4.7.2):

template <typename T>
struct A
{
    struct B { };
};

template <typename T>
bool operator==(typename A<T>::B const& b, T const&  t);

enum { BAR };

template <typename T>
bool test()
{
    return 0 == BAR;
}

The error message from GCC 4.7.2 is:

a.cpp: In instantiation of ‘struct A<<anonymous enum> >’:
a.cpp:12:6:   required by substitution of ‘template<class T> bool operator==(const typename A<T>::B&, const T&) [with T = <anonymous enum>]’
a.cpp:19:17:   required from here
a.cpp:6:12: error: ‘<anonymous enum>’ is/uses anonymous type
a.cpp:6:12: error:   trying to instantiate ‘template<class T> struct A<T>::B’
a.cpp:6:12: error: ‘<anonymous enum>’ is/uses anonymous type
a.cpp:6:12: error:   trying to instantiate ‘template<class T> struct A<T>::B’

Is GCC correct in rejecting the code, or am I hitting its bug?

P.S. I've seen this error while trying to build one of opensource projects. I tried to make smallest possible example that reproduces it.

Stair answered 2/12, 2012 at 6:44 Comment(17)
Visual Studio 2008 and 2010 both compile it.Uteutensil
What function are you calling? Could you please post the entire a.cpp?Abbatial
@AndersJohansson This is entire a.cpp. I'm not calling any function.Stair
Looks like a g++ bug to me. Comeau online compiles the code as well.Mastat
SFINAE should kick in and use the normal enum-to-int comparison.Ingleside
@iv_, maybe I'm missing something but there's no main and template functions are only instantiated when called, so if you're not calling any function, this a.cpp should definitely not compile, nor do anything.Abbatial
Can you submit the function call that causes the errors because it compiles fine in Ideone.com.Vietnamese
@SChepurin: when I tried it, ideone.com throws the errors described.Existence
@AndersJohansson: the code might not compile to a complete program, but it can still be compilable (use the -c option to just compile without linking). An empty file will compile successfully.Existence
@GManNickG: I don't see any of these templates being instantiated - why would SFINAE kick in?Existence
@Michael Burr "when I tried it, ideone.com throws the errors described."- And would you kindly submit the link to ideone.com with your test?Vietnamese
ideone.com/ZHK1W2Existence
@Michael Burr - What do you test? Does the order matter? Where is main()?Vietnamese
g++ a.cpp -c -std=c++0x compiles fine. The bug seems to be fixed in the c++11 specific parts of g++.Ipswich
i am not sure that this is a bug. in c++11, they simply changed the rules to be less strict. There are several rules that relate linkage-less entities with types that have linkage and restrict their relation in certain ways. Will read the relevant parts of the spec later..Exonerate
@MichaelBurr: 0 == BAR should be compiled during phase one, no instantiation needed.Ingleside
It's certainly not a bug, it's a change in C++11 and implemented as of gcc 4.4 if you specify the correct language version (but, only then, which is, again, correct).Herrin
C
1

It is not valid C++ according to the original standard:

14.3.1 of the standard says:

2 A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall not be used as a template argument for a template type-parameter. [Example: ...

However I believe this was restriction was removed by the latest C++11 standard. That may explain why some compilers accept it while others reject it.

Convenance answered 4/12, 2012 at 12:40 Comment(2)
As GManNickG pointed out in the comments, SFINAE. The failing overload should be silently eliminated.Biosynthesis
I confirm that g++ is not compiling it until you ask for C++11 specs: g++ -std=c++11 -o foo.o -c foo.cCooper

© 2022 - 2024 — McMap. All rights reserved.