Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Operator cast, GCC and clang: which compiler is right?

Consider the following code:

struct S {
    using T = int;
    operator T() { return 42; }
};

int main() {
    S s;
    S::T t = s;
    // Is the following line correct?
    t = s.operator T();
}

It compiles with GCC (4.9/5.1/6.1), but it fails to compile with clang (3.8/3.7).
The error returned is:

error: unknown type name 'T'; did you mean 'S::T'?

Which compiler is right in this case and why?

Note

Solving it is a matter of qualifying T:

t = s.operator S::T();

The question is not about how to make it work.

like image 540
skypjack Avatar asked May 18 '16 22:05

skypjack


People also ask

Which is better Clang or GCC?

Clang is much faster and uses far less memory than GCC. Clang aims to provide extremely clear and concise diagnostics (error and warning messages), and includes support for expressive diagnostics. GCC's warnings are sometimes acceptable, but are often confusing and it does not support expressive diagnostics.

Is GCC compatible with clang?

Yes, for C code Clang and GCC are compatible (they both use the GNU Toolchain for linking, in fact.) You just have to make sure that you tell clang to create compiled objects and not intermediate bitcode objects.

Is clang a good compiler?

But the framework underlying Clang called LLVM is extensible enough to support newer languages like Julia and Swift. From the perspective of C++, both are excellent compilers supporting the C++17 standard. From Incredibuild perspective, both are great tools. That's why we support both Clang and GCC.

Is Linux compiled with GCC or clang?

GCC supports more language extensions and more assembly language features than Clang and LLVM. GCC is still the only option for compiling the Linux kernel.


1 Answers

I believe this is clang bug (submitted as #27807)

From [basic.lookup.classref]:

If the id-expression is a conversion-function-id, its conversion-type-id is first looked up in the class of the object expression and the name, if found, is used. Otherwise it is looked up in the context of the entire postfix-expression. In each of these lookups, only names that denote types or templates whose specializations are types are considered. [ Example:

struct A { };
namespace N {
    struct A {
        void g() { }
        template <class T> operator T();
    };
}

int main() {
    N::A a;
    a.operator A(); // calls N::A::operator N::A
}

—end example ]

In t = s.operator T();, T is first looked up in the class of S, which should find your typedef and hence end up calling operator int().

like image 189
Barry Avatar answered Oct 11 '22 11:10

Barry