11

Suppose you have the following (ill-formed) program:

struct A
{
    A(int, int)
    {
    }
};

template <typename T>
class B
{
    B()
    {
        if (sizeof (T) == 1)
        {
            throw A(0); // wrong, A() needs two arguments
        }
    }
};

int main()
{
    return 0;
}

GCC compiles this program without any errors, clang++ refuses it with an error.

  1. Is it justified to say thats it is not a bug in GCC because the template isnt instantiated?
  2. What magic does clang do to find this error?
  3. What does the C++ standard say about those situations?
cschwan
  • 3,283
  • 3
  • 22
  • 32
  • See also http://stackoverflow.com/questions/7182359/template-instantiation-details-of-gcc-and-ms-compilers/ . The two keywords are "point of instantiation", "two phase lookup" and "(non)dependent names". Wait, those were three keywords. – Sebastian Mach Jan 07 '13 at 11:01
  • Oh crap, I want to revoke my close-vote but can't. That was stupid from my side. – Sebastian Mach Jan 07 '13 at 11:03

2 Answers2

11

The template is instantiated when used. However, it should be compiled when it's defined. Your code A(0) uses the name A, which doesn't depend on the template parameter T, so it should be resolved when the template is defined. This is called two-phase lookup. The way clang finds the error is simply by trying to resolve the call A(0) as soon as it sees it.

My version of GCC also compiles this code silently, even with -pedantic-errors. Both C++03 and C++11 say that no diagnostic is required, even though the program is ill-formed, so GCC conforms. This is 14.6/7 in C++03 and 14.6/8 in C++11:

If no valid specialization can be generated for a template definition, and that template is not instantiated, the template definition is ill-formed, no diagnostic required.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • Ah, I see. When I change A to a template class and adjust the call to `A(0)` clang compiles it. Thanks also for the hint to two-phase lookup. Do you have some interesting pointers? – cschwan Jan 07 '13 at 10:29
  • 2
    It's ill-formed but with an explicit mention that no diagnostics are required. – AProgrammer Jan 07 '13 at 10:35
  • @AProgrammer: yes, updated. I didn't realise C++11 had added that mention. – Steve Jessop Jan 07 '13 at 10:36
  • @Steve, It was already the case in C++03 (14.6/7), and if I'm not misinterpreting the change marks, in C++98. (There is additional language in C++03 making it "ill-formed, no diagnostic required" to have an incomplete type complete at instantiation point.). – AProgrammer Jan 07 '13 at 10:43
  • @AProgrammer: oops, I was looking at the wrong paragraph in C++03, they were renumbered. – Steve Jessop Jan 07 '13 at 10:50
5
  1. Yes. When no valid specialization exist but the template isn't instantiated -- like here -- the program is ill-formed, but no diagnostic is required (14.6/8). So both clang and g++ are right.

  2. clang does more checks than g++ on the template declaration.

  3. See above.

AProgrammer
  • 51,233
  • 8
  • 91
  • 143
  • How does the behaviour differ when we use an undeclared/undefined name instead of `A`? GCC complains (unless we specify `-fpermissive`) when the name is undeclared (but not when it’s undefined) but is this covered by the standard or is this still a case that doesn’t *require* diagnostic? – Konrad Rudolph Jan 07 '13 at 10:36
  • @Konrad: the text is "If no valid specialization can be generated for a template definition, and that template is not instantiated, the template definition is ill-formed, no diagnostic required.". In this case, modified so that the code contains a used of an entirely undefined name, no specialization of `B` can be generated. – Steve Jessop Jan 07 '13 at 10:39