[OpenCL] Add diagnostics for references to functions

Restrict use of references to functions as they can
result in non-conforming behavior.

Tags: #clang

Differential Revision: https://reviews.llvm.org/D95442
This commit is contained in:
Anastasia Stulova 2021-02-02 13:00:09 +00:00
parent 9a5dc01e4b
commit 5bbf39704c
5 changed files with 68 additions and 25 deletions

View File

@ -8547,7 +8547,7 @@ def err_invalid_conversion_between_vector_and_integer : Error<
"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">;

View File

@ -6756,10 +6756,13 @@ static bool diagnoseOpenCLTypes(Scope *S, Sema &Se, Declarator &D,
// 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;
}

View File

@ -2091,7 +2091,7 @@ QualType Sema::BuildPointerType(QualType T,
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 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
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 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
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 =

View File

@ -13,31 +13,13 @@ struct C {
};
typedef void (C::*p_t)(int);
template <class T> struct remove_reference { typedef T type; };
template <class T> struct remove_reference<T &> { typedef T type; };
template <typename T>
void templ_test() {
typename remove_reference<T>::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<int (&)()>();
#ifndef FUNCPTREXT
//expected-note@-2{{in instantiation of function template specialization}}
#endif
}

View File

@ -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}}
}