]> granicus.if.org Git - clang/commitdiff
Always diagnose and complain about problems in
authorDouglas Gregor <dgregor@apple.com>
Wed, 14 Apr 2010 23:11:21 +0000 (23:11 +0000)
committerDouglas Gregor <dgregor@apple.com>
Wed, 14 Apr 2010 23:11:21 +0000 (23:11 +0000)
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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaCXXCast.cpp
lib/Sema/SemaOverload.cpp
lib/Sema/SemaTemplate.cpp
test/SemaCXX/addr-of-overloaded-function.cpp
test/SemaTemplate/temp_arg_nontype.cpp

index 4b4780e09b49fb80ba19606f02b725c6d2edf7af..231031829fc0cb4d1434681a718d1a1ba0c2a941 100644 (file)
@@ -1122,9 +1122,13 @@ def err_member_call_without_object : Error<
   "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_no_ref_bind : Error<
 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<
index 11c8e6ddab5ca6e2fe34f599bffbc574fb00e40e..37df2a60005ff69a984058c1f2889591d5c0c37d 100644 (file)
@@ -809,15 +809,17 @@ TryStaticMemberPointerUpcast(Sema &Self, Expr *&SrcExpr, QualType SrcType,
 
   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;
index e039669257ba34bbfa97b30403bd1800d2f91525..53e05eed60a1b711bc583381e948e56f19413e53 100644 (file)
@@ -613,31 +613,36 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
     // 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;
-
-    // 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 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);
+      }
+    } else {
+      return false;
+    }
   } else {
     // We don't require any conversions for the first step.
     SCS.First = ICK_Identity;
@@ -5295,15 +5300,6 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
     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 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
     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 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
   }
 
   // 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);
index 28d6f0a40aa88d8dd35242f59dad7775fdca2933..65e0e5e95e894b3c3cc0a57d3a2ad0660f4ebbc0 100644 (file)
@@ -2368,14 +2368,8 @@ CheckTemplateArgumentAddressOfObjectOrFunction(Sema &S,
     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 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
        ParamType->getAs<MemberPointerType>()->getPointeeType()
          ->isFunctionType())) {
 
-    if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType, 
-                                                              true,
-                                                              FoundResult)) {
-      if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
-        return true;
+    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();
+        Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
+        ArgType = Arg->getType();
+      } else
+        return true;
     }
-
+        
     if (!ParamType->isMemberPointerType())
       return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param,
                                                             ParamType, 
@@ -2902,17 +2899,20 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
     assert(ParamRefType->getPointeeType()->isObjectType() &&
            "Only object references allowed here");
 
-    if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, 
-                                               ParamRefType->getPointeeType(), 
-                                                              true,
-                                                              FoundResult)) {
-      if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))
-        return true;
+    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();
+        Arg = FixOverloadedFunctionReference(Arg, FoundResult, Fn);
+        ArgType = Arg->getType();
+      } else
+        return true;
     }
-
+    
     return CheckTemplateArgumentAddressOfObjectOrFunction(*this, Param, 
                                                           ParamType,
                                                           Arg, Converted);
index 3b06119393d00bfa0b2c8ac35349c0c84e9d2781..391fc3095986781003712c8043f505ad18d86655 100644 (file)
@@ -54,3 +54,19 @@ struct B
   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 ()'}}
+  }
+};
index 6e4f751d47d1bfd80c2cf87e4d39faf80b4c2a8e..1d23c3df084735a2817e8085cf68c345dd2aa17c 100644 (file)
@@ -36,19 +36,19 @@ A<X(17, 42)> *a11; // expected-error{{non-type template argument of type 'X' mus
 
 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<*X_volatile_ptr> *a15_2; // expected-error{{non-type template argument does n
 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);