]> granicus.if.org Git - clang/commitdiff
[OpenCL] Fix access qualifiers handling for typedefs
authorAlexey Bader <aleksey.bader@mail.ru>
Fri, 8 Jul 2016 15:34:59 +0000 (15:34 +0000)
committerAlexey Bader <aleksey.bader@mail.ru>
Fri, 8 Jul 2016 15:34:59 +0000 (15:34 +0000)
OpenCL s6.6: "Access qualifier must be used with image object arguments
of kernels and of user-defined functions [...] If no qualifier is
provided, read_only is assumed".

This does not define the behavior for image types used in typedef
declaration, but following the spec logic, we should allow access
qualifiers specification in typedefs, e.g.:

  typedef write_only image1d_t img1d_wo;

Unlike cv-qualifiers, user cannot add access qualifier to a typedef
type, i.e. this is not allowed:

  typedef image1d_t img1d; // note: previously declared 'read_only' here
  void foo(write_only img1d im) {} // error: multiple access qualifier

Patch by Andrew Savonichev.
Reviewers: Anastasia Stulova.

Differential revision: http://reviews.llvm.org/D20948

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@274858 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/Attr.td
include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/AttributeList.h
lib/Sema/SemaType.cpp
test/CodeGenOpenCL/kernel-arg-info.cl
test/SemaOpenCL/access-qualifier.cl [new file with mode: 0644]
test/SemaOpenCL/invalid-access-qualifier.cl [deleted file]

index f5b31d0d737817b2ad4c4d1e95ecdb062f674b60..51903cbf921dff121c158819cee577e815032d05 100644 (file)
@@ -688,7 +688,8 @@ def OpenCLAccess : Attr {
   let Spellings = [Keyword<"__read_only">, Keyword<"read_only">,
                    Keyword<"__write_only">, Keyword<"write_only">,
                    Keyword<"__read_write">, Keyword<"read_write">];
-  let Subjects = SubjectList<[ParmVar], ErrorDiag>;
+  let Subjects = SubjectList<[ParmVar, TypedefName], ErrorDiag,
+                             "ExpectedParameterOrTypedef">;
   let Accessors = [Accessor<"isReadOnly", [Keyword<"__read_only">,
                                            Keyword<"read_only">]>,
                    Accessor<"isReadWrite", [Keyword<"__read_write">,
index 5ca7c397a60aac0a578de1252dff06586d6c095a..91388cebaf5882b610fa82271c7020124a0ae8ed 100644 (file)
@@ -2506,8 +2506,8 @@ def warn_attribute_wrong_decl_type : Warning<
   "variables and functions|functions and methods|parameters|"
   "functions, methods and blocks|functions, methods, and classes|"
   "functions, methods, and parameters|classes|enums|variables|methods|"
-  "fields and global variables|structs|variables and typedefs|thread-local variables|"
-  "variables and fields|variables, data members and tag types|"
+  "fields and global variables|structs|parameters and typedefs|variables and typedefs|"
+  "thread-local variables|variables and fields|variables, data members and tag types|"
   "types and namespaces|Objective-C interfaces|methods and properties|"
   "struct or union|struct, union or class|types|"
   "Objective-C instance methods|init methods of interface or class extension declarations|"
@@ -7923,9 +7923,11 @@ def err_opencl_builtin_pipe_invalid_access_modifier : Error<
 def err_opencl_invalid_access_qualifier : Error<
   "access qualifier can only be used for pipe and image type">;
 def err_opencl_invalid_read_write : Error<
-  "access qualifier %0 can not be used for %1 %select{|earlier than OpenCL version 2.0}2">;
+  "access qualifier %0 can not be used for %1 %select{|prior to OpenCL version 2.0}2">;
 def err_opencl_multiple_access_qualifiers : Error<
   "multiple access qualifiers">;
+def note_opencl_typedef_access_qualifier : Note<
+  "previously declared '%0' here">;
 
 // OpenCL Section 6.8.g
 def err_opencl_unknown_type_specifier : Error<
index 38e5e94390ac0b8dbaa5b629cda042b76674ec8c..5b838d35071dad7cd7a84dffe55c6ac42e035bd8 100644 (file)
@@ -880,6 +880,7 @@ enum AttributeDeclKind {
   ExpectedMethod,
   ExpectedFieldOrGlobalVar,
   ExpectedStruct,
+  ExpectedParameterOrTypedef,
   ExpectedVariableOrTypedef,
   ExpectedTLSVar,
   ExpectedVariableOrField,
index c0d03a15f31606dc475b1710b6bb130c96d5b8f1..3aade70c9fc77b24e4967c4a76055dfd978b689b 100644 (file)
@@ -6481,12 +6481,31 @@ static void HandleNeonVectorTypeAttr(QualType& CurType,
 /// Handle OpenCL Access Qualifier Attribute.
 static void HandleOpenCLAccessAttr(QualType &CurType, const AttributeList &Attr,
                                    Sema &S) {
-  // OpenCL v2.0 s6.6 - Access qualifier can used only for image and pipe type.
+  // OpenCL v2.0 s6.6 - Access qualifier can be used only for image and pipe type.
   if (!(CurType->isImageType() || CurType->isPipeType())) {
     S.Diag(Attr.getLoc(), diag::err_opencl_invalid_access_qualifier);
     Attr.setInvalid();
     return;
   }
+
+  if (const TypedefType* TypedefTy = CurType->getAs<TypedefType>()) {
+    QualType PointeeTy = TypedefTy->desugar();
+    S.Diag(Attr.getLoc(), diag::err_opencl_multiple_access_qualifiers);
+
+    std::string PrevAccessQual;
+    switch (cast<BuiltinType>(PointeeTy.getTypePtr())->getKind()) {
+      #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
+    case BuiltinType::Id:                                          \
+      PrevAccessQual = #Access;                                    \
+      break;
+      #include "clang/Basic/OpenCLImageTypes.def"
+    default:
+      assert(0 && "Unable to find corresponding image type.");
+    }
+
+    S.Diag(TypedefTy->getDecl()->getLocStart(),
+       diag::note_opencl_typedef_access_qualifier) << PrevAccessQual;
+  }
 }
 
 static void processTypeAttrs(TypeProcessingState &state, QualType &type,
index 9f61f1c418b9d7980b77fee8cefce725593474cd..5a5c8f9d6c5f63c3ff92a202ff1b84e5940c6c69 100644 (file)
@@ -49,7 +49,7 @@ kernel void foo4(__global unsigned int * X, __global myunsignedint * Y) {
 // ARGINFO: !kernel_arg_name ![[MD46:[0-9]+]]
 
 typedef image1d_t myImage;
-kernel void foo5(read_only myImage img1, write_only image1d_t img2) {
+kernel void foo5(myImage img1, write_only image1d_t img2) {
 }
 // CHECK: define spir_kernel void @foo5{{[^!]+}}
 // CHECK: !kernel_arg_addr_space ![[MD41:[0-9]+]]
diff --git a/test/SemaOpenCL/access-qualifier.cl b/test/SemaOpenCL/access-qualifier.cl
new file mode 100644 (file)
index 0000000..7e5c70f
--- /dev/null
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -verify -pedantic -fsyntax-only -cl-std=CL1.2 %s
+// RUN: %clang_cc1 -verify -pedantic -fsyntax-only -cl-std=CL2.0 %s
+
+typedef image1d_t img1d_ro_default; // expected-note {{previously declared 'read_only' here}}
+
+typedef write_only image1d_t img1d_wo; // expected-note {{previously declared 'write_only' here}}
+typedef read_only image1d_t img1d_ro;
+
+#if __OPENCL_C_VERSION__ >= 200
+typedef read_write image1d_t img1d_rw;
+#endif
+
+typedef int Int;
+typedef read_only int IntRO; // expected-error {{access qualifier can only be used for pipe and image type}}
+
+
+void myWrite(write_only image1d_t); // expected-note {{passing argument to parameter here}} expected-note {{passing argument to parameter here}}
+void myRead(read_only image1d_t); // expected-note {{passing argument to parameter here}}
+
+#if __OPENCL_C_VERSION__ >= 200
+void myReadWrite(read_write image1d_t);
+#else
+void myReadWrite(read_write image1d_t); // expected-error {{access qualifier 'read_write' can not be used for '__read_write image1d_t' prior to OpenCL version 2.0}}
+#endif
+
+
+kernel void k1(img1d_wo img) {
+  myRead(img); // expected-error {{passing 'img1d_wo' (aka '__write_only image1d_t') to parameter of incompatible type '__read_only image1d_t'}}
+}
+
+kernel void k2(img1d_ro img) {
+  myWrite(img); // expected-error {{passing 'img1d_ro' (aka '__read_only image1d_t') to parameter of incompatible type '__write_only image1d_t'}}
+}
+
+kernel void k3(img1d_wo img) {
+  myWrite(img);
+}
+
+#if __OPENCL_C_VERSION__ >= 200
+kernel void k4(img1d_rw img) {
+  myReadWrite(img);
+}
+#endif
+
+kernel void k5(img1d_ro_default img) {
+  myWrite(img); // expected-error {{passing 'img1d_ro_default' (aka '__read_only image1d_t') to parameter of incompatible type '__write_only image1d_t'}}
+}
+
+kernel void k6(img1d_ro img) {
+  myRead(img);
+}
+
+kernel void k7(read_only img1d_wo img){} // expected-error {{multiple access qualifiers}}
+
+kernel void k8(write_only img1d_ro_default img){} // expected-error {{multiple access qualifiers}}
+
+kernel void k9(read_only int i){} // expected-error{{access qualifier can only be used for pipe and image type}}
+
+kernel void k10(read_only Int img){} // expected-error {{access qualifier can only be used for pipe and image type}}
+
+kernel void k11(read_only write_only image1d_t i){} // expected-error{{multiple access qualifiers}}
+
+kernel void k12(read_only read_only image1d_t i){} // expected-error{{multiple access qualifiers}}
+
+#if __OPENCL_C_VERSION__ >= 200
+kernel void k13(read_write pipe int i){} // expected-error{{access qualifier 'read_write' can not be used for 'pipe int'}}
+#else
+kernel void k13(__read_write image1d_t i){} // expected-error{{access qualifier '__read_write' can not be used for '__read_write image1d_t' prior to OpenCL version 2.0}}
+#endif
diff --git a/test/SemaOpenCL/invalid-access-qualifier.cl b/test/SemaOpenCL/invalid-access-qualifier.cl
deleted file mode 100644 (file)
index 1aeb996..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-// RUN: %clang_cc1 -verify %s
-// RUN: %clang_cc1 -verify -cl-std=CL2.0 -DCL20 %s
-
-void test1(read_only int i){} // expected-error{{access qualifier can only be used for pipe and image type}}
-
-void test2(read_only write_only image1d_t i){} // expected-error{{multiple access qualifiers}}
-
-void test3(read_only read_only image1d_t i){} // expected-error{{multiple access qualifiers}}
-
-#ifdef CL20
-void test4(read_write pipe int i){} // expected-error{{access qualifier 'read_write' can not be used for 'pipe int'}}
-#else
-void test4(__read_write image1d_t i) {} // expected-error{{access qualifier '__read_write' can not be used for '__read_write image1d_t' earlier than OpenCL version 2.0}}
-#endif