diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -1807,7 +1807,8 @@ // These can be followed by postfix-expr pieces. PreferredType = SavedType; Res = ParsePostfixExpressionSuffix(Res); - if (getLangOpts().OpenCL) + if (getLangOpts().OpenCL && !getActions().getOpenCLOptions().isEnabled( + "__cl_clang_function_pointers")) if (Expr *PostfixExpr = Res.get()) { QualType Ty = PostfixExpr->getType(); if (!Ty.isNull() && Ty->isFunctionType()) { diff --git a/clang/test/SemaOpenCL/func.cl b/clang/test/SemaOpenCL/func.cl --- a/clang/test/SemaOpenCL/func.cl +++ b/clang/test/SemaOpenCL/func.cl @@ -38,6 +38,9 @@ //Function pointer void foo(void*); +#ifdef FUNCPTREXT +//expected-note@-2{{passing argument to parameter here}} +#endif // Expect no diagnostics for an empty parameter list. void bar(); @@ -51,11 +54,30 @@ #endif // taking the address of a function is an error - foo((void*)foo); // expected-error{{taking address of function is not allowed}} - foo(&foo); // expected-error{{taking address of function is not allowed}} + foo((void*)foo); +#ifndef FUNCPTREXT + // expected-error@-2{{taking address of function is not allowed}} +#else + // FIXME: Functions should probably be in the address space defined by the + // implementation. It might make sense to put them into the Default address + // space that is bind to a physical segment by the target rather than fixing + // it to any of the concrete OpenCL address spaces during parsing. + // expected-error@-8{{casting 'void (*)(__private void *__private)' to type '__private void *' changes address space}} +#endif + foo(&foo); +#ifndef FUNCPTREXT + // expected-error@-2{{taking address of function is not allowed}} +#else + // expected-error@-4{{passing 'void (*)(__private void *__private)' to parameter of type '__private void *' changes address space of pointer}} +#endif + + // FIXME: If we stop rejecting the line below a bug (PR49315) gets + // hit due to incorrectly handled pointer conversion. +#ifndef FUNCPTREXT // initializing an array with the address of functions is an error void* vptrarr[2] = {foo, &foo}; // expected-error{{taking address of function is not allowed}} expected-error{{taking address of function is not allowed}} +#endif // just calling a function is correct foo(0);