class C { public: void f() {} } c; int main() { return c.f.a; } -Wall g++ (GCC) 5.0.0 20150224 (experimental) ------------------------------------------------------------------------------- 10.C: In function ‘int main()’: 10.C:2:21: error: ‘c.C::f’ does not have class type int main() { return c.f.a; } ^ ------------------------------------------------------------------------------- clang-3.5.0-6.fc21.x86_64 ------------------------------------------------------------------------------- 10.C:2:23: error: reference to non-static member function must be called; did you mean to call it with no arguments? int main() { return c.f.a; } ~~^ () 10.C:2:24: error: member reference base type 'void' is not a structure or union int main() { return c.f.a; } ~~~^~ 2 errors generated. ------------------------------------------------------------------------------- I had no idea what GCC errors on until I asked clang. It may be obvious here but with complicated classes the better error message is really helpful.
How does Clang message help in this case? The suggested fix 'c.f().a' will just give 'invalid use of void type' Of course, g++ could be better, as this testcase shows: class C { public: void g() {}; C& f() {}; int a; } c; void g2(); C&f2(); int foo(char **p, char **q) { return (p-q).a; } int bar() { return c.f.a; } int baz() { return c.g.a; } int bar2() { return f2.a; } int baz2() { return g2.a; } g++: test.cc:10:44: error: request for member ‘a’ in ‘((((long int)p) - ((long int)q)) (ceiling /) 8l)’, which is of non-class type ‘long int’ int foo(char **p, char **q) { return (p-q).a; } ^ test.cc: In function ‘int bar()’: test.cc:11:20: error: ‘c.C::f’ does not have class type int bar() { return c.f.a; } ^ test.cc: In function ‘int baz()’: test.cc:12:20: error: ‘c.C::g’ does not have class type int baz() { return c.g.a; } ^ test.cc: In function ‘int bar2()’: test.cc:13:24: error: request for member ‘a’ in ‘f2’, which is of non-class type ‘C&()’ int bar2() { return f2.a; } ^ test.cc: In function ‘int baz2()’: test.cc:14:24: error: request for member ‘a’ in ‘g2’, which is of non-class type ‘void()’ int baz2() { return g2.a; } ^ Possible improvements: 1) Consistency: all these errors should print the same message. 2) Location: the location should point to the expression that is not of class type. 3) No pretty-printing of arbitrary expressions: If the expression is a name or a declaration, print it; otherwise, print "request for member 'a' in expression of non-class type 'long int'" 4) For types that have declarations, we could point to the declaration with a note: 'c.C::f' declared here For your testcase, it could be: 10.C:2:23: error: request for member in ‘c.C::f’, which is of non-class type 'void (C::)()' int main() { return c.f.a; } ^ 10.C:1:19: note: declared here class C { public: void f() {} } c; ^
(In reply to Manuel López-Ibáñez from comment #1) > How does Clang message help in this case? The suggested fix 'c.f().a' will > just give 'invalid use of void type' I have minimized the testcase maybe more than appropriate, it was in fact: class D { public: int a; } d; class C { public: D &f() { return d; } } c; int main() { return c.f.a; } g++ (GCC) 5.0.0 20150224 (experimental) ------------------------------------------------------------------------------- 10.C: In function ‘int main()’: 10.C:3:21: error: ‘c.C::f’ does not have class type int main() { return c.f.a; } ^ ------------------------------------------------------------------------------- clang-3.5.0-6.fc21.x86_64 ------------------------------------------------------------------------------- 10.C:3:23: error: reference to non-static member function must be called; did you mean to call it with no arguments? int main() { return c.f.a; } ~~^ () 1 error generated. ------------------------------------------------------------------------------- > 4) For types that have declarations, we could point to the declaration with > a note: 'c.C::f' declared here Yes, that would be very useful.
gcc-7.1.1-3.fc26.x86_64 1.C:2:23: error: invalid use of member function ‘void C::f()’ (did you forget the ‘()’ ?) It looks as fixed now.