Index: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp +++ clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp @@ -1991,9 +1991,7 @@ UnorderedElementsAre(AllOf( Diag(Source.range("diag"), "no matching function for call to 'foo'"), withFix(Fix(Source.range("fix"), "&", - "candidate function not viable: no known conversion from " - "'int' to 'int *' for 1st argument; take the address of " - "the argument with &"))))); + "take the address of the argument with &"))))); } TEST(DiagnosticsTest, UnusedInHeader) { Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -144,6 +144,8 @@ tautologies like ``x && !x`` and ``!x || x`` in expressions. This also makes ``-Winfinite-recursion`` diagnose more cases. (`#56035: `_). +- Clang now emits a separate note for fix-it hint about the use of ``*`` and ``&`` + unary operators in overload resolution failure. Bug Fixes in This Version ------------------------- Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4698,11 +4698,12 @@ "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "no known conversion " "%diff{from $ to $|from argument type to parameter type}3,4 for " - "%select{%ordinal6 argument|object argument}5" - "%select{|; dereference the argument with *|" - "; take the address of the argument with &|" - "; remove *|" - "; remove &}7">; + "%select{%ordinal6 argument|object argument}5">; +def note_ovl_candidate_fixit : Note< + "%select{|dereference the argument with *|" + "take the address of the argument with &|" + "remove *|" + "remove &}0">; def note_ovl_candidate_bad_arc_conv : Note< "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "cannot implicitly convert argument " Index: clang/lib/Sema/SemaOverload.cpp =================================================================== --- clang/lib/Sema/SemaOverload.cpp +++ clang/lib/Sema/SemaOverload.cpp @@ -11010,20 +11010,26 @@ return; // Emit the generic diagnostic and, optionally, add the hints to it. - PartialDiagnostic FDiag = S.PDiag(diag::note_ovl_candidate_bad_conv); - FDiag << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc - << ToParamRange << FromTy << ToTy << (unsigned)isObjectArgument << I + 1 - << (unsigned)(Cand->Fix.Kind); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv) + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc + << ToParamRange << FromTy << ToTy << (unsigned)isObjectArgument << I + 1; // Check that location of Fn is not in system header. - if (!S.SourceMgr.isInSystemHeader(Fn->getLocation())) { + if (!S.SourceMgr.isInSystemHeader(Fn->getLocation()) && + Cand->Fix.Hints.size() > 0) { // If we can fix the conversion, suggest the FixIts. + PartialDiagnostic HintDiag = S.PDiag(diag::note_ovl_candidate_fixit) + << (unsigned)(Cand->Fix.Kind); for (const FixItHint &HI : Cand->Fix.Hints) - FDiag << HI; + HintDiag << HI; + const FixItHint &FirstHint = Cand->Fix.Hints[0]; + SourceLocation FirstHintLoc = FirstHint.RemoveRange.getBegin(); + FirstHintLoc = FirstHintLoc.isInvalid() + ? FirstHint.InsertFromRange.getBegin() + : FirstHintLoc; + S.Diag(FirstHintLoc, HintDiag); } - S.Diag(Fn->getLocation(), FDiag); - MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); } Index: clang/test/FixIt/fixit-function-call.cpp =================================================================== --- clang/test/FixIt/fixit-function-call.cpp +++ clang/test/FixIt/fixit-function-call.cpp @@ -16,7 +16,7 @@ void f2(intTy2 *a) { // CHECK: error: no matching function for call to 'f1 // CHECK: dereference the argument with * -// CHECK: void f1(intTy &a); +// CHECK-NEXT: f1(a + 1); // CHECK: fix-it{{.*}}*( // CHECK-NEXT: fix-it{{.*}}) // CHECK: void f1(double *a); @@ -109,7 +109,8 @@ bp(c); // CHECK: no matching function for call to 'u' -// CHECK: candidate function not viable: no known conversion from 'C' to 'const C *' for 1st argument; take the address of the argument with & +// CHECK: candidate function not viable: no known conversion from 'C' to 'const C *' for 1st argument +// CHECK: take the address of the argument with & // CHECK: candidate function not viable // CHECK: candidate function not viable u(c); Index: clang/test/Index/fixit-sysheader-test.cpp =================================================================== --- clang/test/Index/fixit-sysheader-test.cpp +++ clang/test/Index/fixit-sysheader-test.cpp @@ -9,12 +9,14 @@ func_in_sys_header(str, str + 10); // CHECK: Number FIX-ITs = 0 - // CHECK-NEXT: candidate function not viable: no known conversion from 'char *' to 'unsigned long' for 2nd argument; dereference the argument with * + // CHECK-NEXT: candidate function not viable: no known conversion from 'char *' to 'unsigned long' for 2nd argument // CHECK-NEXT: Number FIX-ITs = 0 func_in_user_header(str, str + 10); // CHECK: Number FIX-ITs = 0 - // CHECK-NEXT: candidate function not viable: no known conversion from 'char *' to 'unsigned long' for 2nd argument; dereference the argument with * + // CHECK-NEXT: candidate function not viable: no known conversion from 'char *' to 'unsigned long' for 2nd argument + // CHECK-NEXT: Number FIX-ITs = 0 + // CHECK-NEXT: dereference the argument with * // CHECK-NEXT: Number FIX-ITs = 2 return 0; Index: clang/test/Sema/overloadable.c =================================================================== --- clang/test/Sema/overloadable.c +++ clang/test/Sema/overloadable.c @@ -27,7 +27,8 @@ void test_funcptr(int (*f1)(int, double), int (*f2)(int, float)) { float *fp = accept_funcptr(f1); - accept_funcptr(f2); // expected-error{{no matching function for call to 'accept_funcptr'}} + accept_funcptr(f2); // expected-error{{no matching function for call to 'accept_funcptr'}} \ + // expected-note 2{{take the address of the argument with &}} } struct X { int x; float y; }; Index: clang/test/SemaCXX/MicrosoftExtensions.cpp =================================================================== --- clang/test/SemaCXX/MicrosoftExtensions.cpp +++ clang/test/SemaCXX/MicrosoftExtensions.cpp @@ -83,7 +83,8 @@ foo_unaligned(p1); const __unaligned int *const_p1 = 0; - foo_unaligned(const_p1); // expected-error {{no matching function for call to 'foo_unaligned'}} + foo_unaligned(const_p1); // expected-error {{no matching function for call to 'foo_unaligned'}} \ + // expected-note {{dereference the argument with *}} __unaligned int *p2 = 0; foo_unaligned(p2); Index: clang/test/SemaCXX/builtin-operator-new-delete.cpp =================================================================== --- clang/test/SemaCXX/builtin-operator-new-delete.cpp +++ clang/test/SemaCXX/builtin-operator-new-delete.cpp @@ -138,8 +138,10 @@ void test_no_matching_fn() { Tag<1> tag; - __builtin_operator_new(42, tag); // expected-error {{no matching function for call to 'operator new'}} - __builtin_operator_delete(NP, tag); // expected-error {{no matching function for call to 'operator delete'}} + __builtin_operator_new(42, tag); // expected-error {{no matching function for call to 'operator new'}} \ + // expected-note {{take the address of the argument with &}} + __builtin_operator_delete(NP, tag); // expected-error {{no matching function for call to 'operator delete'}} \ + // expected-note {{take the address of the argument with &}} } template Index: clang/test/SemaCXX/crashes.cpp =================================================================== --- clang/test/SemaCXX/crashes.cpp +++ clang/test/SemaCXX/crashes.cpp @@ -44,7 +44,8 @@ struct { Y obj; } objs[] = { - new Y // expected-error{{no viable conversion}} + new Y // expected-error{{no viable conversion}} \ + // expected-note{{dereference the argument with *}} }; } Index: clang/test/SemaCXX/for-range-dereference.cpp =================================================================== --- clang/test/SemaCXX/for-range-dereference.cpp +++ clang/test/SemaCXX/for-range-dereference.cpp @@ -56,7 +56,8 @@ ADLNoEnd ANE; for (auto i : ANE) { } // expected-error{{invalid range expression of type 'ADLNoEnd'; no viable 'end' function available}} ADLNoEnd *pANE; - for (auto i : pANE) { } // expected-error{{invalid range expression of type 'ADLNoEnd *'; no viable 'begin' function available}} + for (auto i : pANE) { } // expected-error{{invalid range expression of type 'ADLNoEnd *'; no viable 'begin' function available}} \ + // expected-note {{dereference the argument with *}} DeletedEnd DE; for (auto i : DE) { } // expected-error{{attempt to use a deleted function}} \ Index: clang/test/SemaCXX/overload-member-call.cpp =================================================================== --- clang/test/SemaCXX/overload-member-call.cpp +++ clang/test/SemaCXX/overload-member-call.cpp @@ -124,6 +124,7 @@ void member_call_op_template(int *p) { // Ensure that we don't get confused about relative parameter / argument // indexing here. - [](int, int, auto...){}(p, p); // expected-error {{no matching function}} expected-note {{no known conversion}} + [](int, int, auto...){}(p, p); // expected-error {{no matching function}} expected-note {{no known conversion}} \ + // expected-note {{dereference the argument with *}} } Index: clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl =================================================================== --- clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl +++ clang/test/SemaOpenCL/fdeclare-opencl-builtins.cl @@ -175,10 +175,12 @@ // expected-error@-1{{no matching function for call to 'atomic_init'}} #if defined(NO_FP64) // Expecting 5 candidates: int, uint, long, ulong, float - // expected-note@-4 5 {{candidate function not viable: no known conversion}} + // expected-note@-4 5 {{candidate function not viable: no known conversion}} \ + // expected-note@-4 5{{dereference the argument with *}} #else // Expecting 6 candidates: int, uint, long, ulong, float, double - // expected-note@-7 6 {{candidate function not viable: no known conversion}} + // expected-note@-8 6 {{candidate function not viable: no known conversion}} \ + // expected-note@-8 6{{dereference the argument with *}} #endif } Index: clang/test/SemaTemplate/instantiate-expr-4.cpp =================================================================== --- clang/test/SemaTemplate/instantiate-expr-4.cpp +++ clang/test/SemaTemplate/instantiate-expr-4.cpp @@ -94,7 +94,8 @@ template struct New2 { T* f(bool x, Arg1 a1, Arg2 a2) { - return new T(a1, a2); // expected-error{{no matching}} + return new T(a1, a2); // expected-error{{no matching}} \ + // expected-note{{dereference the argument with *}} } };