5

The following code crashes the Microsoft compiler:

class Var
{
public:
    template <typename T>
    operator T () const
    { }
};

int main()
{
    Var v;
    switch (v)
    { }
}

My question: Is the code correct or should the compiler give an appropriate error? Is an unambiguous conversion to an integral type possible?

typ1232
  • 5,535
  • 6
  • 35
  • 51
  • Can you be more specific when you say "crashes the compiler?" What do you mean by "is the code correct?" – Robert Harvey Jul 30 '14 at 20:35
  • @RobertHarvey `fatal error C1001: An internal error has occurred in the compiler.` ... blahblah ... please report to microsoft (I did report the bug). On the line of the conversion operator. – typ1232 Jul 30 '14 at 20:36
  • Even if the code is incorrect, it shouldn't crash the compiler...Your `operator T` doesn't actually return anything, though, so that's UB right there even if it compiled. – T.C. Jul 30 '14 at 20:37
  • 2
    First of `operator T()` must return something. Second, `switch` waits for an `int`. – 101010 Jul 30 '14 at 20:38
  • You can only use `class Var` in `switch` statement if it can be converted into an integral value. – Thomas Matthews Jul 30 '14 at 20:41
  • @40two why switch expects int? – Slava Jul 30 '14 at 20:42
  • 3
    @40two: worse - `switch` wants "integral type, enumeration type, or of a class type for which a single non-explicit conversion function to integral or enumeration type exists" (**6.4.2/2**). If it wanted `int` specifically, it could have gotten one with `v.operator int()`. But `v` is convertible to anything, so the statement is ambiguous. – Igor Tandetnik Jul 30 '14 at 20:42
  • @40two It does not matter what is inside the function body of the operator, the compiler crashes regardless. I just stripped it to keep the code minimal. – typ1232 Jul 30 '14 at 20:42
  • @typ1232 you made it too minimal, it should be correct. – Slava Jul 30 '14 at 20:44
  • @IgorTandetnik Your comment has answer quality! Thank you for looking up the quote. – typ1232 Jul 30 '14 at 20:44
  • Compiler crashing (ICE) is, of course, **always a bug**. If the code is incorrect (as here), then this is merely a minor nuisance. But if the code is correct, an ICE is really annoying and requires an (often tedious) work around. – Walter Jul 30 '14 at 20:46
  • @Slava I meant requires expression of integer type but felt `int` was shorter :). Sorry for unintended misleading. – 101010 Jul 30 '14 at 20:46
  • I tried it in Studio 2013 and also got the crash. The interesting thing is that the editor flags the `switch(v)` with a red squiggle and the pop-up "Error: expression must have integral or enum type". – Rob K Jul 30 '14 at 20:59
  • @RobK Curiously, IntelliSense in VS is backed by a [compiler other than MSVC](http://blogs.msdn.com/b/vcblog/archive/2009/05/27/rebuilding-intellisense.aspx). It's common for the two to flag different sets of errors. – Igor Tandetnik Jul 30 '14 at 21:05

1 Answers1

8

The compiler crashing is always a bug, this code does not compile on either gcc or clang but both provide an error without crashing. For clang the error is:

error: statement requires expression of integer type ('Var' invalid)
switch (v)
^       ~

gcc provides the following error:

error: ambiguous default type conversion from 'Var'
 switch (v)
          ^

Also, note that flowing off the end of a value returning function is undefined behavior in C++.

Update

Adding:

operator int () const
{ return 0; }

to the class brings about different results from clang and gcc.

See Classes with both template and non-template conversion operators in the condition of switch statement for a discussion on whether gcc or clang is correct. My interpretation of N3323 implies clang is correct on this one.

Filed bug report

I filed a bug report for this ICE, so far no response. Even though this seems like an odd corner case it does cause an internal compiler error which should be fixed.

Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740