This is an archive of the discontinued LLVM Phabricator instance.

[clang][Diagnostics] Emit fix-it hint separately on overload resolution failure
AbandonedPublic

Authored by hazohelet on Aug 21 2023, 5:39 PM.

Details

Summary

D153359 addressed the distant source ranges in overload resolution failure, but still clang generates distant source locations when emitting fix-it hint about the addition/deletion of * and & operators.
This patch separates the fix-it emission to another note to resolve this issue.
Code Example:

void f(int n);


void g(int *p) { f(p); }

Before:

source:4:18: error: no matching function for call to 'f'
    4 | void g(int *p) { f(p); }
      |                  ^
source:1:6: note: candidate function not viable: no known conversion from 'int *' to 'int' for 1st argument; dereference the argument with *
    1 | void f(int n);
      |      ^ ~~~~~
    2 |
    3 |
    4 | void g(int *p) { f(p); }
      |
      |                    *

After:

source:4:18: error: no matching function for call to 'f'
    4 | void g(int *p) { f(p); }
      |                  ^
source:1:6: note: candidate function not viable: no known conversion from 'int *' to 'int' for 1st argument
    1 | void f(int n);
      |      ^ ~~~~~
source:4:20: note: dereference the argument with *
    4 | void g(int *p) { f(p); }
      |                    ^
      |                    *

Diff Detail

Event Timeline

hazohelet created this revision.Aug 21 2023, 5:39 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 21 2023, 5:39 PM
Herald added a subscriber: arphaman. · View Herald Transcript
hazohelet requested review of this revision.Aug 21 2023, 5:39 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 21 2023, 5:39 PM

This breaks the one-note-for-one-overload-candidate rule of overload resolution failure diagnostics (https://github.com/llvm/llvm-project/blob/ff08c8e57e39d7970b65637595cdc221901f4ed1/clang/lib/Sema/SemaOverload.cpp#L11517-L11526), but in most cases this change would produce less lines of diagnostics.
If we don't like this additional note, we could instead suppress the fix-it diagnostics when the fix-it location and the diagnosed candidate location are not close (for example, more than 2 lines away).

Fixed clangd test

Herald added a project: Restricted Project. · View Herald TranscriptAug 22 2023, 10:05 AM
Herald added a subscriber: kadircet. · View Herald Transcript

This breaks the one-note-for-one-overload-candidate rule of overload resolution failure diagnostics (https://github.com/llvm/llvm-project/blob/ff08c8e57e39d7970b65637595cdc221901f4ed1/clang/lib/Sema/SemaOverload.cpp#L11517-L11526), but in most cases this change would produce less lines of diagnostics.
If we don't like this additional note, we could instead suppress the fix-it diagnostics when the fix-it location and the diagnosed candidate location are not close (for example, more than 2 lines away).

IIRC @aaron.ballman usually has an opinion on rules like that.

This breaks the one-note-for-one-overload-candidate rule of overload resolution failure diagnostics (https://github.com/llvm/llvm-project/blob/ff08c8e57e39d7970b65637595cdc221901f4ed1/clang/lib/Sema/SemaOverload.cpp#L11517-L11526), but in most cases this change would produce less lines of diagnostics.
If we don't like this additional note, we could instead suppress the fix-it diagnostics when the fix-it location and the diagnosed candidate location are not close (for example, more than 2 lines away).

I'm uncomfortable with starting down the slippery slope of multiple notes per overload resolution failure; that leads to an explosion of extra diagnostics which makes it harder to spot the issue in the first place. My inclination is to try to resolve this by fixing the way we emit fix-it diagnostics so that we remove the extra whitespace from there because this seems like it's a general problem with fix-its. Or am I wrong about this being a general issue? CC @cjdb for opinions as well

clang/test/Sema/overloadable.c
31

Something odd is going on -- why is the note emitted twice?

hazohelet abandoned this revision.Sep 18 2023, 1:34 AM

This breaks the one-note-for-one-overload-candidate rule of overload resolution failure diagnostics (https://github.com/llvm/llvm-project/blob/ff08c8e57e39d7970b65637595cdc221901f4ed1/clang/lib/Sema/SemaOverload.cpp#L11517-L11526), but in most cases this change would produce less lines of diagnostics.
If we don't like this additional note, we could instead suppress the fix-it diagnostics when the fix-it location and the diagnosed candidate location are not close (for example, more than 2 lines away).

I'm uncomfortable with starting down the slippery slope of multiple notes per overload resolution failure; that leads to an explosion of extra diagnostics which makes it harder to spot the issue in the first place. My inclination is to try to resolve this by fixing the way we emit fix-it diagnostics so that we remove the extra whitespace from there because this seems like it's a general problem with fix-its. Or am I wrong about this being a general issue? CC @cjdb for opinions as well

I agree that the ideal fix would be a systematic change in how we display fix-it hints, or for that matter, distant source ranges in general.
We probably want output that looks like this:

<source>:1:6: note: candidate function not viable: no known conversion from 'int' to 'int *' for 1st argument; take the address of the argument with &
    1 | void ptr(int *p);
      |      ^   ~~~~~~
    ---
    5 |   ptr(n);
      |       
      |       &

In any case, suppressing fix-it hints would be disastrous for LSP things like clangd that use clang diagnostic output. So, this is a problem of how clang diagnostic engine display fix-it hints.

clang/test/Sema/overloadable.c
31

There are two candidates, both of which would become viable if we take the address of them. (https://godbolt.org/z/6onn9x89a)