diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 37409d090035..6fa36f03e251 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -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">; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 2814004b0b07..f55a6babd8cf 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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()) { diff --git a/clang/test/SemaCXX/unknown-anytype.cpp b/clang/test/SemaCXX/unknown-anytype.cpp index b0a2981f470d..ba52122bc490 100644 --- a/clang/test/SemaCXX/unknown-anytype.cpp +++ b/clang/test/SemaCXX/unknown-anytype.cpp @@ -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}} + } +}