forked from OSchip/llvm-project
[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:
parent
9a5dc01e4b
commit
5bbf39704c
|
@ -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">;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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}}
|
||||
}
|
Loading…
Reference in New Issue