]> granicus.if.org Git - clang/commitdiff
Change an assert into a check. I'm pretty sure there was a point
authorJohn McCall <rjmccall@apple.com>
Wed, 10 Aug 2011 04:12:23 +0000 (04:12 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 10 Aug 2011 04:12:23 +0000 (04:12 +0000)
in time when this assert was valid, but it's not valid now.
Also teach this code to correctly introduce function-to-pointer
decay.

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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaExpr.cpp
test/SemaCXX/unknown-anytype.cpp

index 37409d090035ded8197db6dc08e5a6e38147c3c9..6fa36f03e2515513eed4035962a933df20d42135 100644 (file)
@@ -4500,6 +4500,8 @@ def err_unknown_any_addrof : Error<
   "can only be cast to a pointer type">;
 def err_unknown_any_var_function_type : Error<
   "variable %0 with unknown type cannot be given a function type">;
+def err_unknown_any_function : Error<
+  "function %0 with unknown type must be given a function type">;
 
 def err_filter_expression_integral : Error<
   "filter expression type should be an integral value not %0">;
index 2814004b0b071a5245dc46c7860306f59df69673..f55a6babd8cfa063506987c255b6ee81e59f7e9f 100644 (file)
@@ -9819,9 +9819,19 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *expr, ValueDecl *decl) {
 
   //  - functions
   if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
-    // This is true because FunctionDecls must always have function
-    // type, so we can't be resolving the entire thing at once.
-    assert(type->isFunctionType());
+    if (const PointerType *ptr = type->getAs<PointerType>()) {
+      DestType = ptr->getPointeeType();
+      ExprResult result = resolveDecl(expr, decl);
+      if (result.isInvalid()) return ExprError();
+      return S.ImpCastExprToType(result.take(), type,
+                                 CK_FunctionToPointerDecay, VK_RValue);
+    }
+
+    if (!type->isFunctionType()) {
+      S.Diag(expr->getExprLoc(), diag::err_unknown_any_function)
+        << decl << expr->getSourceRange();
+      return ExprError();
+    }
 
     if (CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(fn))
       if (method->isInstance()) {
index b0a2981f470d5a700f939cdf68276d23b54856ad..ba52122bc4908d2221b66f50c8eaf686b2ad22f6 100644 (file)
@@ -34,3 +34,14 @@ namespace test3 {
     ((void(void)) foo)(); // expected-error {{variable 'foo' with unknown type cannot be given a function type}}
   }
 }
+
+// rdar://problem/9899447
+namespace test4 {
+  extern __unknown_anytype test0(...);
+  extern __unknown_anytype test1(...);
+
+  void test() {
+    void (*fn)(int) = (void(*)(int)) test0;
+    int x = (int) test1; // expected-error {{function 'test1' with unknown type must be given a function type}}
+  }
+}