]> granicus.if.org Git - clang/commitdiff
Fix diagnostics for C-style cast to function type.
authorLogan Chien <tzuhsiang.chien@gmail.com>
Sun, 13 Apr 2014 16:08:24 +0000 (16:08 +0000)
committerLogan Chien <tzuhsiang.chien@gmail.com>
Sun, 13 Apr 2014 16:08:24 +0000 (16:08 +0000)
If the C-style type cast is applied to the overloaded
function and the destination type is function type,
then Clang will crash with assertion failure.  For example,

    void foo(int);
    void foo(int, int);
    void bar() {
        typedef void (ft)(int);
        ft p = (ft)foo;
    }

In this case, the overloaded function foo will be cast to
a function type, which should be considered as an error.
But, unfortunately, since the function resolution is using
canonical type, the matched function will be returned, and
result in SEGV.

This patch fixes this issue by removing the assertion and
add some error diagnostics as the one in static_cast.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@206133 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaCast.cpp
test/SemaCXX/addr-of-overloaded-function-casting.cpp

index 5d49225ac4c96ef73c78c0c4e61f8176e9235be7..41570962a2481337b2c4c43e3278380222e6b2cb 100644 (file)
@@ -2097,10 +2097,16 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
                                 DestType,
                                 /*Complain*/ true,
                                 Found);
-      
-      assert(!Fn && "cast failed but able to resolve overload expression!!");
-      (void)Fn;
-
+      if (Fn) {
+        // If DestType is a function type (not to be confused with the function
+        // pointer type), it will be possible to resolve the function address,
+        // but the type cast should be considered as failure.
+        OverloadExpr *OE = OverloadExpr::find(SrcExpr.get()).Expression;
+        Self.Diag(OpRange.getBegin(), diag::err_bad_cstyle_cast_overload)
+          << OE->getName() << DestType << OpRange
+          << OE->getQualifierLoc().getSourceRange();
+        Self.NoteAllOverloadCandidates(SrcExpr.get());
+      }
     } else {
       diagnoseBadCast(Self, msg, (FunctionalStyle ? CT_Functional : CT_CStyle),
                       OpRange, SrcExpr.get(), DestType, ListInitialization);
index 784c8a0007445da1d125b02d5ec2fc144d756987..edf4c138a840283f4d760111ff66c44d29dd4952 100644 (file)
@@ -1,8 +1,8 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 void g();
 
-void f(); // expected-note 9{{candidate function}}
-void f(int); // expected-note 9{{candidate function}}
+void f(); // expected-note 11{{candidate function}}
+void f(int); // expected-note 11{{candidate function}}
 
 template <class T>
 void t(T); // expected-note 3{{candidate function}} \
@@ -58,4 +58,13 @@ int main()
   { bool b = static_cast<int (&)(char)>(t); } // expected-error{{does not match required}}
   
   { bool b = static_cast<void (&)(char)>(f); } // expected-error{{does not match}}
+
+  {
+    // The error should be reported when casting overloaded function to the
+    // compatible function type (not to be confused with function pointer or
+    // function reference type.)
+    typedef void (FnType)(int);
+    FnType a = static_cast<FnType>(f); // expected-error{{address of overloaded function}}
+    FnType b = (FnType)(f); // expected-error{{address of overloaded function}}
+  }
 }