diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8547,7 +8547,7 @@ "of different size">; def err_opencl_function_pointer : Error< - "pointers to functions are not allowed">; + "%select{pointers|references}0 to functions are not allowed">; def err_opencl_taking_address_capture : Error< "taking address of a capture is not allowed">; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -6756,10 +6756,13 @@ // OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed. if (!Se.getOpenCLOptions().isEnabled("__cl_clang_function_pointers")) { - QualType NR = R; - while (NR->isPointerType() || NR->isMemberFunctionPointerType()) { - if (NR->isFunctionPointerType() || NR->isMemberFunctionPointerType()) { - Se.Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer); + QualType NR = R.getCanonicalType(); + while (NR->isPointerType() || NR->isMemberFunctionPointerType() || + NR->isReferenceType()) { + if (NR->isFunctionPointerType() || NR->isMemberFunctionPointerType() || + NR->isFunctionReferenceType()) { + Se.Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer) + << NR->isReferenceType(); D.setInvalidType(); return false; } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2091,7 +2091,7 @@ if (T->isFunctionType() && getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("__cl_clang_function_pointers")) { - Diag(Loc, diag::err_opencl_function_pointer); + Diag(Loc, diag::err_opencl_function_pointer) << /*pointer*/ 0; return QualType(); } @@ -2163,6 +2163,12 @@ if (checkQualifiedFunction(*this, T, Loc, QFK_Reference)) return QualType(); + if (T->isFunctionType() && getLangOpts().OpenCL && + !getOpenCLOptions().isEnabled("__cl_clang_function_pointers")) { + Diag(Loc, diag::err_opencl_function_pointer) << /*reference*/ 1; + return QualType(); + } + // In ARC, it is forbidden to build references to unqualified pointers. if (getLangOpts().ObjCAutoRefCount) T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ true); @@ -2889,6 +2895,12 @@ return QualType(); } + if (T->isFunctionType() && getLangOpts().OpenCL && + !getOpenCLOptions().isEnabled("__cl_clang_function_pointers")) { + Diag(Loc, diag::err_opencl_function_pointer) << /*pointer*/ 0; + return QualType(); + } + // Adjust the default free function calling convention to the default method // calling convention. bool IsCtorOrDtor = diff --git a/clang/test/SemaOpenCLCXX/members.cl b/clang/test/SemaOpenCLCXX/members.cl --- a/clang/test/SemaOpenCLCXX/members.cl +++ b/clang/test/SemaOpenCLCXX/members.cl @@ -13,31 +13,13 @@ }; typedef void (C::*p_t)(int); - -template struct remove_reference { typedef T type; }; -template struct remove_reference { typedef T type; }; - -template -void templ_test() { - typename remove_reference::type *ptr; #ifndef FUNCPTREXT - //expected-error@-2{{pointers to functions are not allowed}} +//expected-error@-2{{pointers to functions are not allowed}} #endif -} void test() { void (C::*p)(int); #ifndef FUNCPTREXT //expected-error@-2{{pointers to functions are not allowed}} -#endif - - p_t p1; -#ifndef FUNCPTREXT -//expected-error@-2{{pointers to functions are not allowed}} -#endif - - templ_test(); -#ifndef FUNCPTREXT -//expected-note@-2{{in instantiation of function template specialization}} #endif } diff --git a/clang/test/SemaOpenCLCXX/references.cl b/clang/test/SemaOpenCLCXX/references.cl new file mode 100644 --- /dev/null +++ b/clang/test/SemaOpenCLCXX/references.cl @@ -0,0 +1,46 @@ +//RUN: %clang_cc1 %s -cl-std=clc++ -verify -fsyntax-only +//RUN: %clang_cc1 %s -cl-std=clc++ -verify -fsyntax-only -DFPTREXT + +#ifdef FPTREXT +#pragma OPENCL EXTENSION __cl_clang_function_pointers : enable +#endif // FPTREXT + +// References to functions are not allowed. +struct myclass { +//FIXME: Here we provide incorrect diagnostic. + void (&mem)(); //expected-error{{reference to function type cannot have '__generic' qualifier}} +}; + +void (&glob)(); +#ifndef FPTREXT +//expected-error@-2{{references to functions are not allowed}} +#else +//expected-error@-4{{declaration of reference variable 'glob' requires an initializer}} +#endif // FPTREXT + +using ref2fct_t = void (&)(); +#ifndef FPTREXT +//expected-error@-2{{references to functions are not allowed}} +#endif // FPTREXT +typedef void (&ref2fct_t)(); +#ifndef FPTREXT +//expected-error@-2{{references to functions are not allowed}} +#endif // FPTREXT + +void test(void (&par)()) { +#ifndef FPTREXT +//expected-error@-2{{references to functions are not allowed}} +#endif // FPTREXT + void (&loc)(); +#ifndef FPTREXT +//expected-error@-2{{references to functions are not allowed}} +#else +//expected-error@-4{{declaration of reference variable 'loc' requires an initializer}} +#endif // FPTREXT + + void (*&ref2fptr)(); +#ifndef FPTREXT +//expected-error@-2{{pointers to functions are not allowed}} +#endif // FPTREXT +//expected-error@-4{{declaration of reference variable 'ref2fptr' requires an initializer}} +}