From: David Blaikie Date: Tue, 4 Jun 2013 00:28:46 +0000 (+0000) Subject: Bound member function diagnostic - suggest no-args calls and note overload candidates X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c2fe81898b1b3b948791ca4ababd3d495601f22a;p=clang Bound member function diagnostic - suggest no-args calls and note overload candidates Still missing cases for templates, but this is a step in the right direction. Also omits suggestions that would be ambiguous (eg: void func(int = 0); + void func(float = 0); func;) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183173 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index c5f689fe49..4f79c938b8 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -1148,10 +1148,20 @@ bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy, ZeroArgCallReturnTy = QualType(); OverloadSet.clear(); + const OverloadExpr *Overloads = NULL; if (E.getType() == Context.OverloadTy) { OverloadExpr::FindResult FR = OverloadExpr::find(const_cast(&E)); - const OverloadExpr *Overloads = FR.Expression; + // Ignore overloads that are pointer-to-member constants. + if (FR.HasFormOfMemberPointer) + return false; + + Overloads = FR.Expression; + } else if (E.getType() == Context.BoundMemberTy) { + Overloads = dyn_cast(E.IgnoreParens()); + } + if (Overloads) { + bool Ambiguous = false; for (OverloadExpr::decls_iterator it = Overloads->decls_begin(), DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) { OverloadSet.addDecl(*it); @@ -1160,16 +1170,17 @@ bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy, // arguments. if (const FunctionDecl *OverloadDecl = dyn_cast((*it)->getUnderlyingDecl())) { - if (OverloadDecl->getMinRequiredArguments() == 0) - ZeroArgCallReturnTy = OverloadDecl->getResultType(); + if (OverloadDecl->getMinRequiredArguments() == 0) { + if (!ZeroArgCallReturnTy.isNull() && !Ambiguous) { + ZeroArgCallReturnTy = QualType(); + Ambiguous = true; + } else + ZeroArgCallReturnTy = OverloadDecl->getResultType(); + } } } - // Ignore overloads that are pointer-to-member constants. - if (FR.HasFormOfMemberPointer) - return false; - - return true; + return !Ambiguous; } if (const DeclRefExpr *DeclRef = dyn_cast(E.IgnoreParens())) { diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp index d327efcc20..1f81116414 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp @@ -85,8 +85,8 @@ struct S { namespace PR10939 { struct X { - int method(int); - int method(float); + int method(int); // expected-note{{possible target for call}} + int method(float); // expected-note{{possible target for call}} }; template T g(T); diff --git a/test/CXX/over/over.over/p2-resolve-single-template-id.cpp b/test/CXX/over/over.over/p2-resolve-single-template-id.cpp index e0217112d9..b1c819a93b 100644 --- a/test/CXX/over/over.over/p2-resolve-single-template-id.cpp +++ b/test/CXX/over/over.over/p2-resolve-single-template-id.cpp @@ -125,7 +125,7 @@ int main() namespace member_pointers { struct S { - template bool f(T) { return false; } + template bool f(T) { return false; } // expected-note 4 {{possible target for call}} template static bool g(T) { return false; } template bool h(T) { return false; } // expected-note 3 {{possible target for call}} diff --git a/test/SemaCXX/addr-of-overloaded-function.cpp b/test/SemaCXX/addr-of-overloaded-function.cpp index 096f74823a..95223f0f5e 100644 --- a/test/SemaCXX/addr-of-overloaded-function.cpp +++ b/test/SemaCXX/addr-of-overloaded-function.cpp @@ -57,11 +57,12 @@ struct B struct C { C &getC() { - return makeAC; // expected-error{{reference to non-static member function must be called}} + return makeAC; // expected-error-re{{reference to non-static member function must be called$}} } - C &makeAC(); - const C &makeAC() const; + // FIXME: filter by const so we can unambiguously suggest '()' & point to just the one candidate, probably + C &makeAC(); // expected-note{{possible target for call}} + const C &makeAC() const; // expected-note{{possible target for call}} static void f(); // expected-note{{candidate function}} static void f(int); // expected-note{{candidate function}} diff --git a/test/SemaCXX/expression-traits.cpp b/test/SemaCXX/expression-traits.cpp index 2767d4a159..3a00687f11 100644 --- a/test/SemaCXX/expression-traits.cpp +++ b/test/SemaCXX/expression-traits.cpp @@ -189,12 +189,12 @@ struct Class : BaseClass static int& NestedFuncTemplate() { return variable; } // expected-note{{possible target for call}} template - int& NestedMemfunTemplate() { return variable; } + int& NestedMemfunTemplate() { return variable; } // expected-note{{possible target for call}} int operator*() const; template - int operator+(T) const; + int operator+(T) const; // expected-note{{possible target for call}} int NonstaticMemberFunction(); static int StaticMemberFunction(); diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp index d794850a39..bdb75a5e5f 100644 --- a/test/SemaCXX/overloaded-operator.cpp +++ b/test/SemaCXX/overloaded-operator.cpp @@ -387,8 +387,8 @@ void test_lookup_through_using() { namespace rdar9136502 { struct X { - int i(); - int i(int); + int i(); // expected-note{{possible target for call}} + int i(int); // expected-note{{possible target for call}} }; struct Y { @@ -397,7 +397,7 @@ namespace rdar9136502 { void f(X x, Y y) { y << x - .i; // expected-error{{reference to non-static member function must be called}} + .i; // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} } } diff --git a/test/SemaTemplate/resolve-single-template-id.cpp b/test/SemaTemplate/resolve-single-template-id.cpp index 0c9bacca3e..c436225b24 100644 --- a/test/SemaTemplate/resolve-single-template-id.cpp +++ b/test/SemaTemplate/resolve-single-template-id.cpp @@ -74,7 +74,7 @@ int main() } struct rdar9108698 { - template void f(); + template void f(); // expected-note{{possible target for call}} }; void test_rdar9108698(rdar9108698 x) {