Anastasia created this revision. Anastasia added a reviewer: mantognini. Herald added subscribers: ebevhan, yaxunl. Anastasia requested review of this revision.
References to functions are less permissive than pointers to functions and therefore some use cases could be allowed for example: - For local variables - For non-extern static and global variables - For template parameters that are not used as function parameters or class members - In constexpr However, more language work is needed to analyze the invalid/valid cases. This can be done in the future language versions if there is enough interest in the feature from the application developers. Even if we had a request for allowing some function pointer functionality (PR44788), OpenCL has never adopted the feature as a part of the standard and therefore many applications have been written successfully without it. On the other hand C++ provides other related features - lambdas and function objects that are allowed in OpenCL and can be used to express some sort of the indirect function call logic. For now it seems reasonable to just disallow the references to functions just like we disallow function pointers. This prevents erroneous programs from being compiled silently. Note that for the advanced users there is the following extension available `__cl_clang_function_pointers` that can be used if there is knowledge about the application sources or compilation options to make sure the non-conformant functionality is safe (more details are in https://clang.llvm.org/docs/LanguageExtensions.html#opencl-features). https://reviews.llvm.org/D95442 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaType.cpp clang/test/SemaOpenCLCXX/references.cl Index: clang/test/SemaOpenCLCXX/references.cl =================================================================== --- /dev/null +++ clang/test/SemaOpenCLCXX/references.cl @@ -0,0 +1,43 @@ +//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 { + void (&mem)(); +//FIXME: Here we provide incorrect diagnostic. +#ifndef FPTREXT +//expected-error@-3{{reference to function type cannot have '__generic' qualifier}} +#endif // FPTREXT +}; + +void (&glob)(); +#ifndef FPTREXT +//expected-error@-2{{references to functions are not allowed}} +//expected-error@-3{{declaration of reference variable 'glob' requires an initializer}} +#endif // FPTREXT +template <typename T> +void templ() { + // FIXME: We miss to diagnose the reference to function. + T loc; //expected-error{{declaration of reference variable 'loc' requires an initializer}} +} + +void foo(); +void test(void (&par)()) { + void (&loc)(); +#ifndef FPTREXT +//expected-error@-2{{references to functions are not allowed}} +//expected-error@-3{{declaration of reference variable 'loc' requires an initializer}} +#endif // FPTREXT + + void (*&ref2fptr)(); +#ifndef FPTREXT +//expected-error@-2{{pointers to functions are not allowed}} +//expected-error@-3{{declaration of reference variable 'ref2fptr' requires an initializer}} +#endif // FPTREXT + + templ<void (&)()>(); //expected-note{{in instantiation of function template specialization}} +} Index: clang/lib/Sema/SemaType.cpp =================================================================== --- clang/lib/Sema/SemaType.cpp +++ 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(); } Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -6752,9 +6752,12 @@ // 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); + 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; } Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8541,7 +8541,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">;
Index: clang/test/SemaOpenCLCXX/references.cl =================================================================== --- /dev/null +++ clang/test/SemaOpenCLCXX/references.cl @@ -0,0 +1,43 @@ +//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 { + void (&mem)(); +//FIXME: Here we provide incorrect diagnostic. +#ifndef FPTREXT +//expected-error@-3{{reference to function type cannot have '__generic' qualifier}} +#endif // FPTREXT +}; + +void (&glob)(); +#ifndef FPTREXT +//expected-error@-2{{references to functions are not allowed}} +//expected-error@-3{{declaration of reference variable 'glob' requires an initializer}} +#endif // FPTREXT +template <typename T> +void templ() { + // FIXME: We miss to diagnose the reference to function. + T loc; //expected-error{{declaration of reference variable 'loc' requires an initializer}} +} + +void foo(); +void test(void (&par)()) { + void (&loc)(); +#ifndef FPTREXT +//expected-error@-2{{references to functions are not allowed}} +//expected-error@-3{{declaration of reference variable 'loc' requires an initializer}} +#endif // FPTREXT + + void (*&ref2fptr)(); +#ifndef FPTREXT +//expected-error@-2{{pointers to functions are not allowed}} +//expected-error@-3{{declaration of reference variable 'ref2fptr' requires an initializer}} +#endif // FPTREXT + + templ<void (&)()>(); //expected-note{{in instantiation of function template specialization}} +} Index: clang/lib/Sema/SemaType.cpp =================================================================== --- clang/lib/Sema/SemaType.cpp +++ 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(); } Index: clang/lib/Sema/SemaDecl.cpp =================================================================== --- clang/lib/Sema/SemaDecl.cpp +++ clang/lib/Sema/SemaDecl.cpp @@ -6752,9 +6752,12 @@ // 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); + 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; } Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8541,7 +8541,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">;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits