Visual Studio C++ compiler weird behaviour
Asked Answered
Q

2

38

I'm just curious to know why this small piece of code compiles correctly (and without warnings) in Visual Studio. Maybe the result is the same with GCC and Clang, but unfortunately I can't test them now.

struct T {
    int t;
    T() : t(0) {}
};

int main() {
    T(i_do_not_exist);
    return 0;
}
Quatrain answered 22/12, 2015 at 13:32 Comment(6)
extremly interesting! the most WTF compiler bug I have ever seen!Bilicki
also int(i_do_not_exist) works fine, but with undefined variable warningQuatrain
It also compiles with g++: coliru.stacked-crooked.com/a/d8dd5a50af7c888dBeige
See a similar question: Is Type(::x); valid?Dirt
@DavidHaim this is not a bugMagdalenemagdalenian
duplicate of #24622972Magdalenemagdalenian
G
44

T(i_do_not_exist); is an object declaration with the same meaning as T i_do_not_exist;.

N4567 § 6.8[stmt.ambig]p1

There is an ambiguity in the grammar involving expression-statements and declarations: An expression-statement with a function-style explicit type conversion (5.2.3) as its leftmost subexpression can be indistinguishable from a declaration where the first declarator starts with a (. In those cases the statement is a declaration.

§ 8.3[dcl.meaning]p6

In a declaration T D where D has the form

( D1 )

the type of the contained declarator-id is the same as that of the contained declarator-id in the declaration

T D1

Parentheses do not alter the type of the embedded declarator-id, but they can alter the binding of complex declarators.

Galina answered 22/12, 2015 at 13:46 Comment(4)
I sometimes hate C++... like just now.Trinitytrinket
That's why one should use list initialization T{i_do_not_exist} which gives a compiler error.Laquitalar
Can someone clarify: is this an instance of a "most vexing parse" problem or something unrelated?Monophysite
@Monophysite how about we call it "slightly vexing parse"? It could be "vexing" because it's ambiguous, but it is less vexing than the traditional "most vexing" T func( U(x), U(y) ); , and perhaps also less vexing than the "somewhat vexing parse" T func();Magdalenemagdalenian
P
17

Because it defines a variable of type T:

http://coliru.stacked-crooked.com/a/d420870b1a6490d7

#include <iostream>

struct T {
    int t;
    T() : t(0) {}
};

int main() {
    T(i_do_not_exist);
    i_do_not_exist.t = 120;
    std::cout << i_do_not_exist.t;
    return 0;
}

The above example looks silly, but this syntax is allowed for a reason.

A better example is:

int func1();
namespace A
{
   void func1(int);
   struct X {
       friend int (::func1)();
   };
}

Probably other examples could be found.

Pisa answered 22/12, 2015 at 13:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.