Index: clang/lib/Sema/SemaOverload.cpp =================================================================== --- clang/lib/Sema/SemaOverload.cpp +++ clang/lib/Sema/SemaOverload.cpp @@ -10749,6 +10749,8 @@ Expr *FromExpr = Conv.Bad.FromExpr; QualType FromTy = Conv.Bad.getFromType(); QualType ToTy = Conv.Bad.getToType(); + SourceRange ToParamRange = + !isObjectArgument ? Fn->getParamDecl(I)->getSourceRange() : SourceRange(); if (FromTy == S.Context.OverloadTy) { assert(FromExpr && "overload set argument came from implicit argument?"); @@ -10759,8 +10761,7 @@ S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_overload) << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << ToTy - << Name << I + 1; + << ToParamRange << ToTy << Name << I + 1; MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } @@ -10789,14 +10790,12 @@ if (isObjectArgument) S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace_this) << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second - << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << FromQs.getAddressSpace() << ToQs.getAddressSpace(); + << FnDesc << FromQs.getAddressSpace() << ToQs.getAddressSpace(); else S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_addrspace) << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second - << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << FromQs.getAddressSpace() << ToQs.getAddressSpace() - << ToTy->isReferenceType() << I + 1; + << FnDesc << ToParamRange << FromQs.getAddressSpace() + << ToQs.getAddressSpace() << ToTy->isReferenceType() << I + 1; MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } @@ -10804,9 +10803,8 @@ if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_ownership) << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy - << FromQs.getObjCLifetime() << ToQs.getObjCLifetime() - << (unsigned)isObjectArgument << I + 1; + << ToParamRange << FromTy << FromQs.getObjCLifetime() + << ToQs.getObjCLifetime() << (unsigned)isObjectArgument << I + 1; MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } @@ -10814,13 +10812,13 @@ if (FromQs.getObjCGCAttr() != ToQs.getObjCGCAttr()) { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_gc) << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy - << FromQs.getObjCGCAttr() << ToQs.getObjCGCAttr() - << (unsigned)isObjectArgument << I + 1; + << ToParamRange << FromTy << FromQs.getObjCGCAttr() + << ToQs.getObjCGCAttr() << (unsigned)isObjectArgument << I + 1; MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } + // FIXME: No test case for this. Can we remove this block? if (FromQs.hasUnaligned() != ToQs.hasUnaligned()) { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_unaligned) << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc @@ -10836,13 +10834,11 @@ if (isObjectArgument) { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr_this) << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy - << (CVR - 1); + << FromTy << (CVR - 1); } else { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_cvr) << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy - << (CVR - 1) << I + 1; + << ToParamRange << FromTy << (CVR - 1) << I + 1; } MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; @@ -10854,7 +10850,7 @@ << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc << (unsigned)isObjectArgument << I + 1 << (Conv.Bad.Kind == BadConversionSequence::rvalue_ref_to_lvalue) - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()); + << ToParamRange; MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } @@ -10864,8 +10860,7 @@ if (FromExpr && isa(FromExpr)) { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_list_argument) << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc - << FromExpr->getSourceRange() << FromTy << ToTy - << (unsigned)isObjectArgument << I + 1 + << ToParamRange << FromTy << ToTy << (unsigned)isObjectArgument << I + 1 << (Conv.Bad.Kind == BadConversionSequence::too_few_initializers ? 1 : Conv.Bad.Kind == BadConversionSequence::too_many_initializers ? 2 @@ -10884,8 +10879,7 @@ // Emit the generic diagnostic and, optionally, add the hints to it. S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_conv_incomplete) << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy - << ToTy << (unsigned)isObjectArgument << I + 1 + << ToParamRange << FromTy << ToTy << (unsigned)isObjectArgument << I + 1 << (unsigned)(Cand->Fix.Kind); MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); @@ -10926,24 +10920,24 @@ if (BaseToDerivedConversion) { S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_base_to_derived_conv) << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << (BaseToDerivedConversion - 1) << FromTy << ToTy << I + 1; + << ToParamRange << (BaseToDerivedConversion - 1) << FromTy << ToTy + << I + 1; MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); return; } if (isa(CFromTy) && isa(CToTy)) { - Qualifiers FromQs = CFromTy.getQualifiers(); - Qualifiers ToQs = CToTy.getQualifiers(); - if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) { - S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_arc_conv) - << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second - << FnDesc << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) - << FromTy << ToTy << (unsigned)isObjectArgument << I + 1; - MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); - return; - } + Qualifiers FromQs = CFromTy.getQualifiers(); + Qualifiers ToQs = CToTy.getQualifiers(); + if (FromQs.getObjCLifetime() != ToQs.getObjCLifetime()) { + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_arc_conv) + << (unsigned)FnKindPair.first << (unsigned)FnKindPair.second << FnDesc + << ToParamRange << FromTy << ToTy << (unsigned)isObjectArgument + << I + 1; + MaybeEmitInheritedConstructorNote(S, Cand->FoundDecl); + return; + } } if (TakingCandidateAddress && @@ -10953,8 +10947,7 @@ // 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 - << (FromExpr ? FromExpr->getSourceRange() : SourceRange()) << FromTy - << ToTy << (unsigned)isObjectArgument << I + 1 + << ToParamRange << FromTy << ToTy << (unsigned)isObjectArgument << I + 1 << (unsigned)(Cand->Fix.Kind); // Check that location of Fn is not in system header. Index: clang/test/Misc/diag-overload-cand-ranges.cpp =================================================================== --- /dev/null +++ clang/test/Misc/diag-overload-cand-ranges.cpp @@ -0,0 +1,72 @@ +// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-print-source-range-info %s 2>&1 | FileCheck %s --strict-whitespace +// CHECK: error: no matching function +template struct mcdata { + typedef int result_type; +}; +template typename mcdata::result_type wrap_mean(mcdata const &); +// CHECK: :{[[@LINE+1]]:19-[[@LINE+1]]:53}: note: {{.*}}: no overload of 'wrap_mean' +void add_property(double (*)(mcdata const &)); +void f() { add_property(&wrap_mean); } + +// CHECK: error: no matching function +// CHECK: :{[[@LINE+1]]:10-[[@LINE+1]]:51}: note: {{.*}}: cannot pass pointer to generic address space +void baz(__attribute__((opencl_private)) int *Data) {} +void fizz() { + int *Nop; + baz(Nop); + // CHECK: error: no matching function + // CHECK: :[[@LINE+1]]:53: note: {{.*}}: 'this' object is in address space '__private' + __attribute__((opencl_private)) static auto err = [&]() {}; + err(); +} + +// CHECK: error: no matching function +struct Bar { +// CHECK: :{[[@LINE+1]]:26-[[@LINE+1]]:32}: note: {{.*}} would lose const qualifier +static void foo(int num, int *X) {} +// CHECK: :{[[@LINE+1]]:17-[[@LINE+1]]:25}: note: {{.*}} no known conversion +static void foo(int *err, int *x) {} +}; +void bar(const int *Y) { + Bar::foo(5, Y); +} + +struct InComp; + +struct A {}; +struct B : public A{}; +// CHECK: error: no matching function +// CHECK: :{[[@LINE+5]]:36-[[@LINE+5]]:50}: note: {{.*}}: cannot convert initializer +// CHECK: error: no matching function +// CHECK: :{[[@LINE+3]]:36-[[@LINE+3]]:50}: note: {{.*}}: cannot convert argument +// CHECK: error: no matching function +// CHECK: :{[[@LINE+1]]:11-[[@LINE+1]]:18}: note: {{.*}}: no known conversion +void hoge(char aa, const char *bb, const A& third); + +// CHECK: error: no matching function +// CHECK: :{[[@LINE+1]]:14-[[@LINE+1]]:16}: note: {{.*}}: cannot convert from base class +void derived(B*); + +void func(const A &arg) { + hoge(1, "pass", {{{arg}}}); + InComp *a; + hoge(1, "pass", a); + hoge("first", 5, 6); + A *b; + derived(b); +} + +struct Q { + // CHECK: error: invalid operands + // CHECK: :[[@LINE+1]]:6: note: {{.*}}: 'this' argument has type 'const Q' + Q &operator+(void*); +}; + +void fuga(const Q q) { q + 3; } + +template class Type1 {}; +// CHECK: error: no matching function +// CHECK: :{[[@LINE+1]]:43-[[@LINE+1]]:54}: note: {{.*}}: expects an lvalue +template void Function1(int zz, Type1 &x, int ww) {} + +void Function() { Function1(33, Type1<-42>(), 66); } Index: clang/test/Misc/diag-overload-cand-ranges.mm =================================================================== --- /dev/null +++ clang/test/Misc/diag-overload-cand-ranges.mm @@ -0,0 +1,26 @@ +// RUN: not %clang_cc1 -fobjc-runtime-has-weak -fobjc-arc -fsyntax-only -fdiagnostics-print-source-range-info %s 2>&1 | FileCheck %s --strict-whitespace -check-prefixes=CHECK,ARC +// RUN: not %clang_cc1 -fobjc-runtime-has-weak -fobjc-gc -fsyntax-only -fdiagnostics-print-source-range-info %s 2>&1 | FileCheck %s --strict-whitespace -check-prefixes=CHECK,GC + +// CHECK: error: no matching function +// CHECK: :{[[@LINE+1]]:15-[[@LINE+1]]:28}: note: {{.*}}: 1st argument +void powerful(__strong id &); +void lifetime_gcattr_mismatch() { + static __weak id weak_id; + powerful(weak_id); +} + +// CHECK: error: no matching function +// ARC: :{[[@LINE+2]]:11-[[@LINE+2]]:21}: note: {{.*}}: cannot implicitly convert +// GC: :{[[@LINE+1]]:11-[[@LINE+1]]:21}: note: {{.*}}: no known conversion +void func(char *uiui); + +__attribute__((objc_root_class)) +@interface Interface +- (void)something; +@end + +@implementation Interface +- (void)something{ + func(self); +} +@end