[clang] 5bbf397 - [OpenCL] Add diagnostics for references to functions

Anastasia Stulova via cfe-commits cfe-commits at lists.llvm.org
Tue Feb 2 07:07:56 PST 2021


Author: Anastasia Stulova
Date: 2021-02-02T15:07:40Z
New Revision: 5bbf39704c2b70581d78a463f3c9d20b0eb7dcd5

URL: https://github.com/llvm/llvm-project/commit/5bbf39704c2b70581d78a463f3c9d20b0eb7dcd5
DIFF: https://github.com/llvm/llvm-project/commit/5bbf39704c2b70581d78a463f3c9d20b0eb7dcd5.diff

LOG: [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

Added: 
    clang/test/SemaOpenCLCXX/references.cl

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaType.cpp
    clang/test/SemaOpenCLCXX/members.cl

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 67c59f3ca09a..d31cc76b04d1 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8547,7 +8547,7 @@ def err_invalid_conversion_between_vector_and_integer : Error<
   "of 
diff erent 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
index ef4947baf665..7da00cb598f4 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -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;
       }

diff  --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 4178024d1264..e24eb266dd5f 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -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 =

diff  --git a/clang/test/SemaOpenCLCXX/members.cl b/clang/test/SemaOpenCLCXX/members.cl
index d561445eb8a2..855948f0615e 100644
--- a/clang/test/SemaOpenCLCXX/members.cl
+++ b/clang/test/SemaOpenCLCXX/members.cl
@@ -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 at -2{{pointers to functions are not allowed}}
+//expected-error at -2{{pointers to functions are not allowed}}
 #endif
-}
 
 void test() {
   void (C::*p)(int);
 #ifndef FUNCPTREXT
 //expected-error at -2{{pointers to functions are not allowed}}
-#endif
-
-  p_t p1;
-#ifndef FUNCPTREXT
-//expected-error at -2{{pointers to functions are not allowed}}
-#endif
-
-  templ_test<int (&)()>();
-#ifndef FUNCPTREXT
-//expected-note at -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
index 000000000000..c02d73a4bd69
--- /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 at -2{{references to functions are not allowed}}
+#else
+//expected-error at -4{{declaration of reference variable 'glob' requires an initializer}}
+#endif // FPTREXT
+
+using ref2fct_t = void (&)();
+#ifndef FPTREXT
+//expected-error at -2{{references to functions are not allowed}}
+#endif // FPTREXT
+typedef void (&ref2fct_t)();
+#ifndef FPTREXT
+//expected-error at -2{{references to functions are not allowed}}
+#endif // FPTREXT
+
+void test(void (&par)()) {
+#ifndef FPTREXT
+//expected-error at -2{{references to functions are not allowed}}
+#endif // FPTREXT
+  void (&loc)();
+#ifndef FPTREXT
+//expected-error at -2{{references to functions are not allowed}}
+#else
+//expected-error at -4{{declaration of reference variable 'loc' requires an initializer}}
+#endif // FPTREXT
+
+  void (*&ref2fptr)();
+#ifndef FPTREXT
+//expected-error at -2{{pointers to functions are not allowed}}
+#endif // FPTREXT
+//expected-error at -4{{declaration of reference variable 'ref2fptr' requires an initializer}}
+}


        


More information about the cfe-commits mailing list