]> granicus.if.org Git - clang/commitdiff
Bound member function diagnostic - suggest no-args calls and note overload candidates
authorDavid Blaikie <dblaikie@gmail.com>
Tue, 4 Jun 2013 00:28:46 +0000 (00:28 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Tue, 4 Jun 2013 00:28:46 +0000 (00:28 +0000)
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

lib/Sema/Sema.cpp
test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp
test/CXX/over/over.over/p2-resolve-single-template-id.cpp
test/SemaCXX/addr-of-overloaded-function.cpp
test/SemaCXX/expression-traits.cpp
test/SemaCXX/overloaded-operator.cpp
test/SemaTemplate/resolve-single-template-id.cpp

index c5f689fe493083b6dd87d67e1c7aafa7ccc06056..4f79c938b80e920a1f7a4dc5fa88ba78115e57d2 100644 (file)
@@ -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<Expr*>(&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<UnresolvedMemberExpr>(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<FunctionDecl>((*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<DeclRefExpr>(E.IgnoreParens())) {
index d327efcc20df5d6deceb0997d88658243f994714..1f811164145347c56623a81a08d320922cc2d2fd 100644 (file)
@@ -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<typename T> T g(T);
index e0217112d91b519d1234eb07798be270c541656d..b1c819a93b4218c9aa61c3c6235487f003810648 100644 (file)
@@ -125,7 +125,7 @@ int main()
 
 namespace member_pointers {
   struct S {
-    template <typename T> bool f(T) { return false; }
+    template <typename T> bool f(T) { return false; } // expected-note 4 {{possible target for call}}
     template <typename T> static bool g(T) { return false; }
 
     template <typename T> bool h(T) { return false; }  // expected-note 3 {{possible target for call}}
index 096f74823a4298cf86366fa2cfd877d675ba47da..95223f0f5e3be2f831878efb2740743c9f2d1323 100644 (file)
@@ -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}}
index 2767d4a159c7fce7eb3b99fcc5af8ffd3a6241b0..3a00687f1125530c4e495c86eca57a35f9165e2c 100644 (file)
@@ -189,12 +189,12 @@ struct Class : BaseClass
     static int& NestedFuncTemplate() { return variable; }  // expected-note{{possible target for call}}
 
     template <class T>
-    int& NestedMemfunTemplate() { return variable; }
+    int& NestedMemfunTemplate() { return variable; } // expected-note{{possible target for call}}
 
     int operator*() const;
 
     template <class T>
-    int operator+(T) const;
+    int operator+(T) const; // expected-note{{possible target for call}}
 
     int NonstaticMemberFunction();
     static int StaticMemberFunction();
index d794850a3920d0cefb0dea6115d6f149d22aacb4..bdb75a5e5f6e23df6bd590c86ebb8402f4df9e0d 100644 (file)
@@ -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?}}
   }
 }
 
index 0c9bacca3eddb915fb4f0faa1cce515a67aa286c..c436225b24cf16cb22964571dcc40acf637218f1 100644 (file)
@@ -74,7 +74,7 @@ int main()
 }
 
 struct rdar9108698 {
-  template<typename> void f();
+  template<typename> void f(); // expected-note{{possible target for call}}
 };
 
 void test_rdar9108698(rdar9108698 x) {