llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.01k stars 11.56k forks source link

[QOI] [diags] Improve diagnostic with missing parens #5850

Open llvmbot opened 14 years ago

llvmbot commented 14 years ago
Bugzilla Link 5478
Version unspecified
OS All
Blocks llvm/llvm-project#3476
Reporter LLVM Bugzilla Contributor
CC @DougGregor

Extended Description

Somehow I manage to do this all the time, and the resulting C++ warnings are frequently totally awesome.

ddunbar@giles:tmp$ cat t.cpp

struct A;
A *f0(int x, float y);
void f1(A *);
void f2() { f1(f0); }

ddunbar@giles:tmp$ gcc t.cpp

t.cpp: In function 'void f2()':
t.cpp:4: error: cannot convert 'A* (*)(int, float)' to 'A*' for argument '1' to 'void f1(A*)'

ddunbar@giles:tmp$ clang -fsyntax-only t.cpp

t.cpp:4:13: error: no matching function for call to 'f1'
void f2() { f1(f0); }
            ^~
t.cpp:3:6: note: candidate function
void f1(A *);
     ^
2 diagnostics generated.

ddunbar@giles:tmp$

DougGregor commented 2 years ago

mentioned in issue llvm/llvm-bugzilla-archive#8056

llvmbot commented 12 years ago

As of r158660, clang produces much better results for both of the examples mentioned in this bug.

For the example in the original description: $ cat tmp.cc struct A; A f0(int x, float y); void f1(A ); void f2() { f1(f0); }

$ ./bin/clang -fsyntax-only tmp.cc tmp.cc:4:13: error: no matching function for call to 'f1' void f2() { f1(f0); } ^~ tmp.cc:3:6: note: candidate function not viable: no known conversion from 'A (int, float)' to 'A ' for 1st argument; void f1(A *); ^ 1 error generated.

And for Jeffry Yasskin's example:

$ cat tmp.cc struct string { bool operator==(const char*); }; struct A { string foo(); }; bool bar() { A a; return a.foo == "Hello World"; }

$ ./bin/clang -fsyntax-only tmp.cc tmp.cc:9:12: error: reference to non-static member function must be called; did you mean to call it with no arguments? return a.foo == "Hello World"; ^ () 1 error generated.

It looks like all that is left to do is provide a suggestion to add the missing parens in the overload resolution, as is done with the second (non-overloaded) example when adding parens would actually help. In the original example it wouldn't because f0 takes two arguments... though changing it to take zero arguments results in the same "no known conversion..." message without a suggestion for adding parens.

DougGregor commented 14 years ago

Bug llvm/llvm-bugzilla-archive#8056 has been marked as a duplicate of this bug.

llvmbot commented 14 years ago

Here's a similar case of forgotten parens that doesn't involve overload resolution:

$ cat test.cc struct string { bool operator==(const char*); };

struct A { string foo(); };

bool bar() { A a; return a.foo == "Hello World"; }

$ Debug/bin/clang -fsyntax-only test.cc test.cc:11:16: warning: result of comparison against a string literal is unspecified (use strncmp instead) return a.foo == "Hello World"; ^ ~~~~~ test.cc:11:16: error: comparison of distinct pointer types ('string ()()' and 'char const ') return a.foo == "Hello World";


1 warning and 1 error generated.
DougGregor commented 14 years ago

We do slightly better in C:

t.c:4:16: warning: incompatible pointer types passing 'struct A (int, float)', expected 'struct A ' void f2() { f1(f0); }

The idea here is to add a fix-it suggesting the addition of ()'s after the use of f0, since calling the function would have made the program well-formed. We could tackle the C case here, then improve the C++ case when we address llvm/llvm-project#3476 .

philnik777 commented 1 year ago

We are doing a lot better, but it would be nice if clang could suggest adding parens in this case:

struct A;
A *f0();
void f1(A *);

void f2() { f1(f0); }

(Godbolt)