Closed llvmbot closed 11 years ago
It's not clear what C++98 is supposed to do here. I'm content with having it fixed in C++11 by the C++11 rules.
Fixed for C++11 in r154886.
We still diagnose the instantiations in C++98 mode. I'm not sure whether that's correct.
So we want to suppress instantiation of the specification while only doing overload resolution.
Hmm ... this is going to be fun.
It's more fun than that :)
Essentially, instantiating the function declaration does not instantiate the exception specification. Rather, we instantiate the exception specification on demand when we need it, e.g.,
Basically, we'll end up instantiating the exception specification lazily.
So we want to suppress instantiation of the specification while only doing overload resolution.
Hmm ... this is going to be fun.
The direction the committee intends to go with this is to only instantiate the exception specification when it's needed, e.g., if there's a call to that function, or its address is taken, or 'noexcept' is asking whether it throws.
Extended Description
Consider:
template
void f1(T) throw(typename T::exception);
template
void f1(T, int = 0) throw(typename T::noitpecxe);
template
void f2(T) noexcept(T::throws);
template
void f2(T, int = 0) noexcept(T::sworht);
void test() { f1(0); f2(0); }
The above test case can distinguish between the treatment of exception specifications during overload resolution and template instantiations. There are three possible outcomes: 1) The program fails with an ambiguity error. This is what the standard says should happen, because exception specifications are not part of the function type and thus are not instantiated during overload resolution, only when actually instantiating the function. So both templates are equally valid. This is what Comeau Online does. (For the throw() spec. Comeau doesn't yet support noexcept.) 2) The program fails with no available overloads. This is what would happen if the exception specification were a SFINAE context. This also happens to be what GCC 4.5 does. (Again, for throw(). I don't have handy access to GCC 4.6.) 3) The program generates errors when resolving the overloads, because int cannot be used on the left side of ::. This is what happens when the compiler instantiates the spec together with the type, but doesn't treat it as a SFINAE context.
Clang first produces the error from 3, but then also produces the error from 1.