Bug 17459 - Spurious message when forgetting parentheses on call of member
Summary: Spurious message when forgetting parentheses on call of member
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.0.0
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2004-09-13 14:19 UTC by Wolfgang Bangerth
Modified: 2024-01-26 17:58 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-07-15 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Wolfgang Bangerth 2004-09-13 14:19:57 UTC
(This is a spin-off from PR 17456) 
 
Take this code: 
----------------- 
struct S { 
  void foo(); 
  void bar() { foo; } 
}; 
----------------- 
Sure, the code looks odd: someone probably wanted to write foo() but 
forgot the parentheses. But I would think it is valid: we take a reference 
to the function S::foo and discard the result of this statement. But 
we get an error from gcc instead: 
 
g/x> /home/bangerth/bin/gcc-3.5-pre/bin/c++ -c x.cc 
x.cc: In member function `void S::bar()': 
x.cc:3: error: statement cannot resolve address of overloaded function 
 
That strikes me as completely odd and wrong: first, I think there shouldn't 
be an error in the first place; second, we certainly have no overloads 
here, so the message's intent is completely puzzling to me. Note that  
gcc2.95 printed this instead: 
 
g/x> /home/bangerth/bin/gcc-2.*/bin/c++ -c x.cc 
x.cc: In method `void S::bar()': 
x.cc:3: invalid use of member (did you forget the `&' ?) 
 
icc accepts the code without any warning or error. 
 
 
No, for comparison, think of the case where the two functions are 
non-members: 
------------------ 
void foo(); 
void bar() { foo; } 
------------------ 
Now we get 
 
g/x> /home/bangerth/bin/gcc-3.5-pre/bin/c++ -c x.cc 
x.cc: In function `void bar()': 
x.cc:2: warning: statement is a reference, not call, to function `foo' 
 
That makes more sense, and should have been what we get for the 
member case as well. 
 
W.
Comment 1 Giovanni Bajo 2004-09-13 17:33:12 UTC
Notice that you need "&S::foo" to take the address of a member function. The 
syntax "foo(blah)" is the function call syntax, and it is available only for 
function calls.

I am not sure why EDG accepts it. Anyway, our diagnostic is suboptimal.
Comment 2 Wolfgang Bangerth 2004-09-13 18:32:41 UTC
Uhm, yes... I tend to take icc's acceptance as standards conformance  
sometimes :-( 
 
W. 
Comment 3 Manuel López-Ibáñez 2010-02-21 19:07:51 UTC
More weirdeness.

// PR c++/17459: Spurious message when forgetting parentheses on call of member
// { dg-do compile }
struct S {
  void foo();
  void bar() { foo; } // { dg-error "statement cannot resolve address of overloaded function" }
  // { dg-message "note: taking the address of a member function requires the syntax '&S::foo'" "" { target *-*-* } 5 }
  void bar3() { &foo; } // { dg-error "ISO C.. forbids taking the address" }
  void * bar2() { return foo; }
};


This testcase produces:

pr17459.C: In member function 'void S::bar()':
pr17459.C:5:19: error: statement cannot resolve address of overloaded function
pr17459.C:5:19: note: taking the address of a member function requires the syntax '&S::foo'
pr17459.C: In member function 'void S::bar3()':
pr17459.C:7:18: error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function.  Say '&S::f\
oo'
pr17459.C: In member function 'void* S::bar2()':
pr17459.C:8:26: error: argument of type 'void (S::)()' does not match 'void*'


The last one really kills me. It should be the same error as the first one, isn't it? 

Oh, I give up on this one!
Comment 4 Paolo Carlini 2013-05-16 17:09:35 UTC
Manuel can you help me reassessing this? I think we are doing much better.
Comment 5 Manuel López-Ibáñez 2013-05-16 17:26:42 UTC
(In reply to Paolo Carlini from comment #4)
> Manuel can you help me reassessing this? I think we are doing much better.

I get this:

test.cc:3:19: error: invalid use of non-static member function
   void bar() { foo; } 
                   ^
 void S::bar3()
test.cc:5:18: error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function.  Say ‘&S::foo’ [-fpermissive]
   void bar3() { &foo; } 
                  ^
 void* S::bar2()
test.cc:6:26: error: cannot convert ‘S::foo’ from type ‘void (S::)()’ to type ‘void*’
   void * bar2() { return foo; }
                          ^

The first error could be a bit nicer if it said why it is invalid. Clang does:

test.cc:3:16: error: reference to non-static member function must be called; did you mean to call it with no arguments?

but the thing is that this is not even a valid reference, so the error could clarify a bit more the problem, no?

ISO C++ forbids taking the address of an unqualified non-static member function, say ‘&S::foo’ instead; or did you mean to call 'foo()'?

The last error is bogus, it should be the same as the first one. Clang gives two errors, but at least the first is the correct one:

test.cc:6:26: error: reference to non-static member function must be called; did you mean to call it with no arguments?
  void * bar2() { return foo; }
                         ^~~
                            ()
test.cc:6:26: error: cannot initialize return object of type 'void *' with an rvalue of type 'void'
  void * bar2() { return foo; }
                         ^~~~
Comment 6 Jonathan Wakely 2021-07-15 20:38:15 UTC
(In reply to Manuel López-Ibáñez from comment #5)
> The first error could be a bit nicer if it said why it is invalid. Clang
> does:
> 
> test.cc:3:16: error: reference to non-static member function must be called;
> did you mean to call it with no arguments?

I think we should just add a fix-it hint suggesting to add the ()


> but the thing is that this is not even a valid reference, so the error could
> clarify a bit more the problem, no?

I don't think mentioning "reference" here is a good idea at all, because that means something specific in C++ (and completely unrelated to this).

I prefer GCC's "invalid use" wording. With a fix-it to add the () the error would be fine.

If the function can't be called with no arguments, the fix-it would be wrong. I'm not sure what we want to do in that case. Suggest the fix-it anyway, and let the user figure out the next step?

Clang just says:

17459-c3.C:3:16: error: reference to non-static member function must be called

i.e. it omits the "did you mean to call it with no arguments?" part. So we could do the same and just not provide a fix-it in that case.


> ISO C++ forbids taking the address of an unqualified non-static member
> function, say ‘&S::foo’ instead; or did you mean to call 'foo()'?

Maybe we should remove the -fpermissive extension that allows &foo as a non-standard way to form a pointer-to-member. That simplifies the handling of &foo, because we can just reject it instead of using a permerror. It's more than 20 years since that was acceptable syntax.

And that could use a fix-it hint too, to suggest turning &foo into &S::foo.


> The last error is bogus, it should be the same as the first one.

Agreed.