Always diagnose and complain about problems in
ResolveAddressOfOverloadedFunction when asked to complain. Previously,
we had some weird handshake where ResolveAddressOfOverloadedFunction
expected its caller to handle some of the diagnostics but not others,
and yet there was no way for the caller to know which case we were
in. Eliminate this madness, fixing <rdar://problem/7765884>.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101312 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 4b4780e..2310318 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1122,9 +1122,13 @@
   "call to non-static member function without an object argument">;
 
 // C++ Address of Overloaded Function
+def err_addr_ovl_no_viable : Error<
+  "address of overloaded function %0 does not match required type %1">;
 def err_addr_ovl_ambiguous : Error<
   "address of overloaded function %0 is ambiguous">;
-
+def err_addr_ovl_not_func_ptrref : Error<
+  "address of overloaded function %0 cannot be converted to type %1">;
+  
 // C++ Template Declarations
 def err_template_param_shadow : Error<
   "declaration of %0 shadows template parameter">;
@@ -1239,9 +1243,6 @@
 def err_template_arg_ref_bind_ignores_quals : Error<
   "reference binding of non-type template parameter of type %0 to template "
   "argument of type %1 ignores qualifiers">;
-def err_template_arg_unresolved_overloaded_function : Error<
-  "overloaded function cannot be resolved to a non-type template parameter of "
-  "type %0">;
 def err_template_arg_not_decl_ref : Error<
   "non-type template argument does not refer to any declaration">;
 def err_template_arg_not_object_or_func_form : Error<
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index 11c8e6d..37df2a6 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -809,15 +809,17 @@
 
   bool WasOverloadedFunction = false;
   DeclAccessPair FoundOverload;
-  if (FunctionDecl *Fn
-        = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false,
-                                                  FoundOverload)) {
-    CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
-    SrcType = Self.Context.getMemberPointerType(Fn->getType(),
-                    Self.Context.getTypeDeclType(M->getParent()).getTypePtr());
-    WasOverloadedFunction = true;
+  if (SrcExpr->getType() == Self.Context.OverloadTy) {
+    if (FunctionDecl *Fn
+          = Self.ResolveAddressOfOverloadedFunction(SrcExpr, DestType, false,
+                                                    FoundOverload)) {
+      CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
+      SrcType = Self.Context.getMemberPointerType(Fn->getType(),
+                      Self.Context.getTypeDeclType(M->getParent()).getTypePtr());
+      WasOverloadedFunction = true;
+    }
   }
-
+  
   const MemberPointerType *SrcMemPtr = SrcType->getAs<MemberPointerType>();
   if (!SrcMemPtr) {
     msg = diag::err_bad_static_cast_member_pointer_nonmp;
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index e039669..53e05ee 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -613,31 +613,36 @@
     // type "pointer to T." The result is a pointer to the
     // function. (C++ 4.3p1).
     FromType = Context.getPointerType(FromType);
-  } else if (FunctionDecl *Fn
-               = ResolveAddressOfOverloadedFunction(From, ToType, false,
-                                                    AccessPair)) {
-    // Address of overloaded function (C++ [over.over]).
-    SCS.First = ICK_Function_To_Pointer;
+  } else if (From->getType() == Context.OverloadTy) {
+    if (FunctionDecl *Fn
+          = ResolveAddressOfOverloadedFunction(From, ToType, false, 
+                                               AccessPair)) {
+      // Address of overloaded function (C++ [over.over]).
+      SCS.First = ICK_Function_To_Pointer;
 
-    // We were able to resolve the address of the overloaded function,
-    // so we can convert to the type of that function.
-    FromType = Fn->getType();
-    if (ToType->isLValueReferenceType())
-      FromType = Context.getLValueReferenceType(FromType);
-    else if (ToType->isRValueReferenceType())
-      FromType = Context.getRValueReferenceType(FromType);
-    else if (ToType->isMemberPointerType()) {
-      // Resolve address only succeeds if both sides are member pointers,
-      // but it doesn't have to be the same class. See DR 247.
-      // Note that this means that the type of &Derived::fn can be
-      // Ret (Base::*)(Args) if the fn overload actually found is from the
-      // base class, even if it was brought into the derived class via a
-      // using declaration. The standard isn't clear on this issue at all.
-      CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
-      FromType = Context.getMemberPointerType(FromType,
-                    Context.getTypeDeclType(M->getParent()).getTypePtr());
-    } else
-      FromType = Context.getPointerType(FromType);
+      // We were able to resolve the address of the overloaded function,
+      // so we can convert to the type of that function.
+      FromType = Fn->getType();
+      if (ToType->isLValueReferenceType())
+        FromType = Context.getLValueReferenceType(FromType);
+      else if (ToType->isRValueReferenceType())
+        FromType = Context.getRValueReferenceType(FromType);
+      else if (ToType->isMemberPointerType()) {
+        // Resolve address only succeeds if both sides are member pointers,
+        // but it doesn't have to be the same class. See DR 247.
+        // Note that this means that the type of &Derived::fn can be
+        // Ret (Base::*)(Args) if the fn overload actually found is from the
+        // base class, even if it was brought into the derived class via a
+        // using declaration. The standard isn't clear on this issue at all.
+        CXXMethodDecl *M = cast<CXXMethodDecl>(Fn);
+        FromType = Context.getMemberPointerType(FromType,
+                      Context.getTypeDeclType(M->getParent()).getTypePtr());
+      } else {
+        FromType = Context.getPointerType(FromType);
+      }
+    } else {
+      return false;
+    }
   } else {
     // We don't require any conversions for the first step.
     SCS.First = ICK_Identity;
@@ -5295,15 +5300,6 @@
     IsMember = true;
   }
 
-  // We only look at pointers or references to functions.
-  FunctionType = Context.getCanonicalType(FunctionType).getUnqualifiedType();
-  if (!FunctionType->isFunctionType())
-    return 0;
-
-  // Find the actual overloaded function declaration.
-  if (From->getType() != Context.OverloadTy)
-    return 0;
-
   // C++ [over.over]p1:
   //   [...] [Note: any redundant set of parentheses surrounding the
   //   overloaded function name is ignored (5.1). ]
@@ -5316,6 +5312,18 @@
     OvlExpr->getExplicitTemplateArgs().copyInto(ETABuffer);
     ExplicitTemplateArgs = &ETABuffer;
   }
+  
+  // We expect a pointer or reference to function, or a function pointer.
+  FunctionType = Context.getCanonicalType(FunctionType).getUnqualifiedType();
+  if (!FunctionType->isFunctionType()) {
+    if (Complain)
+      Diag(From->getLocStart(), diag::err_addr_ovl_not_func_ptrref)
+        << OvlExpr->getName() << ToType;
+    
+    return 0;
+  }
+
+  assert(From->getType() == Context.OverloadTy);
 
   // Look through all of the overloaded functions, searching for one
   // whose type matches exactly.
@@ -5397,9 +5405,19 @@
   }
 
   // If there were 0 or 1 matches, we're done.
-  if (Matches.empty())
+  if (Matches.empty()) {
+    if (Complain) {
+      Diag(From->getLocStart(), diag::err_addr_ovl_no_viable)
+        << OvlExpr->getName() << FunctionType;
+      for (UnresolvedSetIterator I = OvlExpr->decls_begin(),
+                                 E = OvlExpr->decls_end(); 
+           I != E; ++I)
+        if (FunctionDecl *F = dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()))
+          NoteOverloadCandidate(F);
+    }
+    
     return 0;
-  else if (Matches.size() == 1) {
+  } else if (Matches.size() == 1) {
     FunctionDecl *Result = Matches[0].second;
     FoundResult = Matches[0].first;
     MarkDeclarationReferenced(From->getLocStart(), Result);
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 28d6f0a..65e0e5e 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2368,14 +2368,8 @@
     DRE = dyn_cast<DeclRefExpr>(Arg);
 
   if (!DRE) {
-    if (S.Context.hasSameUnqualifiedType(ArgType, S.Context.OverloadTy)) {
-      S.Diag(Arg->getLocStart(), 
-             diag::err_template_arg_unresolved_overloaded_function)
-        << ParamType << Arg->getSourceRange();
-    } else {
-      S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
-        << Arg->getSourceRange();
-    }
+    S.Diag(Arg->getLocStart(), diag::err_template_arg_not_decl_ref)
+      << Arg->getSourceRange();
     S.Diag(Param->getLocation(), diag::note_template_param_here);
     return true;
   }
@@ -2848,16 +2842,19 @@
        ParamType->getAs<MemberPointerType>()->getPointeeType()
          ->isFunctionType())) {
 
-    if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType, 
-                                                              true,
-                                                              FoundResult)) {
-      if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
+    if (Arg->getType() == Context.OverloadTy) {
+      if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType, 
+                                                                true,
+                                                                FoundResult)) {
+        if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
+          return true;
+
+        Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
+        ArgType = Arg->getType();
+      } else
         return true;
-
-      Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
-      ArgType = Arg->getType();
     }
-
+        
     if (!ParamType->isMemberPointerType())
       return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
                                                             ParamType, 
@@ -2902,17 +2899,20 @@
     assert(ParamRefType->getPointeeType()->isObjectType() &&
            "Only object references allowed here");
 
-    if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, 
-                                               ParamRefType->getPointeeType(), 
-                                                              true,
-                                                              FoundResult)) {
-      if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
+    if (Arg->getType() == Context.OverloadTy) {
+      if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, 
+                                                 ParamRefType->getPointeeType(), 
+                                                                true,
+                                                                FoundResult)) {
+        if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
+          return true;
+
+        Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
+        ArgType = Arg->getType();
+      } else
         return true;
-
-      Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
-      ArgType = Arg->getType();
     }
-
+    
     return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, 
                                                           ParamType,
                                                           Arg, Converted);
diff --git a/test/SemaCXX/addr-of-overloaded-function.cpp b/test/SemaCXX/addr-of-overloaded-function.cpp
index 3b06119..391fc30 100644
--- a/test/SemaCXX/addr-of-overloaded-function.cpp
+++ b/test/SemaCXX/addr-of-overloaded-function.cpp
@@ -54,3 +54,19 @@
   void d(void *);
   static void d(A *);
 };
+
+struct C {
+  C &getC() {
+    return makeAC; // expected-error{{address of overloaded function 'makeAC' cannot be converted to type 'C'}}
+  }
+
+  C &makeAC();
+  const C &makeAC() const;
+
+  static void f(); // expected-note{{candidate function}}
+  static void f(int); // expected-note{{candidate function}}
+
+  void g() {
+    int (&fp)() = f; // expected-error{{address of overloaded function 'f' does not match required type 'int ()'}}
+  }
+};
diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp
index 6e4f751..1d23c3d 100644
--- a/test/SemaTemplate/temp_arg_nontype.cpp
+++ b/test/SemaTemplate/temp_arg_nontype.cpp
@@ -36,19 +36,19 @@
 
 float f(float);
 
-float g(float);
-double g(double);
+float g(float); // expected-note 2{{candidate function}}
+double g(double); // expected-note 2{{candidate function}}
 
 int h(int);
 float h2(float);
 
-template<int fp(int)> struct A3; // expected-note 2{{template parameter is declared here}}
+template<int fp(int)> struct A3; // expected-note 1{{template parameter is declared here}}
 A3<h> *a14_1;
 A3<&h> *a14_2;
 A3<f> *a14_3;
 A3<&f> *a14_4;
 A3<h2> *a14_6;  // expected-error{{non-type template argument of type 'float (float)' cannot be converted to a value of type 'int (*)(int)'}}
-A3<g> *a14_7; // expected-error{{overloaded function cannot be resolved to a non-type template parameter of type 'int (*)(int)'}}
+A3<g> *a14_7; // expected-error{{address of overloaded function 'g' does not match required type 'int (int)'}}
 
 
 struct Y { } y;
@@ -61,11 +61,11 @@
 A4<y> *15_3; //  expected-error{{non-type template parameter of reference type 'X const &' cannot bind to template argument of type 'struct Y'}} \
             // FIXME: expected-error{{expected unqualified-id}}
 
-template<int (&fr)(int)> struct A5; // expected-note 2{{template parameter is declared here}}
+template<int (&fr)(int)> struct A5; // expected-note{{template parameter is declared here}}
 A5<h> *a16_1;
 A5<f> *a16_3;
 A5<h2> *a16_6;  // expected-error{{non-type template parameter of reference type 'int (&)(int)' cannot bind to template argument of type 'float (float)'}}
-A5<g> *a14_7; // expected-error{{overloaded function cannot be resolved to a non-type template parameter of type 'int (&)(int)'}}
+A5<g> *a14_7; // expected-error{{address of overloaded function 'g' does not match required type 'int (int)'}}
 
 struct Z {
   int foo(int);