[cfe-commits] r101312 - in /cfe/trunk: 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

Douglas Gregor dgregor at apple.com
Wed Apr 14 16:11:21 PDT 2010


Author: dgregor
Date: Wed Apr 14 18:11:21 2010
New Revision: 101312

URL: http://llvm.org/viewvc/llvm-project?rev=101312&view=rev
Log:
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>.

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

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=101312&r1=101311&r2=101312&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Apr 14 18:11:21 2010
@@ -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<

Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=101312&r1=101311&r2=101312&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Wed Apr 14 18:11:21 2010
@@ -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;

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=101312&r1=101311&r2=101312&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Apr 14 18:11:21 2010
@@ -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;
-
-    // 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 @@
     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);

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=101312&r1=101311&r2=101312&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Apr 14 18:11:21 2010
@@ -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()))
-        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 @@
     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);

Modified: cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp?rev=101312&r1=101311&r2=101312&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp (original)
+++ cfe/trunk/test/SemaCXX/addr-of-overloaded-function.cpp Wed Apr 14 18:11:21 2010
@@ -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 ()'}}
+  }
+};

Modified: cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp?rev=101312&r1=101311&r2=101312&view=diff
==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp Wed Apr 14 18:11:21 2010
@@ -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);





More information about the cfe-commits mailing list