Anastasia created this revision.
Anastasia added reviewers: bader, yaxunl.
Anastasia added a subscriber: cfe-commits.

This change:
1. Changes diagnostics for Blocks to be implicitly const qualified OpenCL v2.0 
s6.12.5.
2. Adds and unifies diagnostics of some OpenCL special types: blocks, images, 
samplers, pipes. These types are intended for use with the OpenCL builtin 
function only and, therefore, most regular uses are not allowed including 
assignments, arithmetic operations, pointer dereferencing, etc...

http://reviews.llvm.org/D21989

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaType.cpp
  test/SemaOpenCL/invalid-block.cl
  test/SemaOpenCL/invalid-image.cl
  test/SemaOpenCL/invalid-pipes-cl2.0.cl
  test/SemaOpenCL/sampler_t.cl

Index: test/SemaOpenCL/sampler_t.cl
===================================================================
--- test/SemaOpenCL/sampler_t.cl
+++ test/SemaOpenCL/sampler_t.cl
@@ -18,3 +18,12 @@
 }
 
 void bad(sampler_t*); // expected-error {{pointer to type 'sampler_t' is invalid in OpenCL}}
+
+void bar(){
+  sampler_t smp1 = 7;
+  sampler_t smp2 = 2;
+  smp1=smp2; //expected-error{{invalid operands to binary expression ('sampler_t' and 'sampler_t')}}
+  smp1+1; //expected-error{{invalid operands to binary expression ('sampler_t' and 'int')}}
+  &smp1; //expected-error{{invalid argument type 'sampler_t' to unary expression}}
+  *smp2; //expected-error{{invalid argument type 'sampler_t' to unary expression}}
+}
Index: test/SemaOpenCL/invalid-pipes-cl2.0.cl
===================================================================
--- test/SemaOpenCL/invalid-pipes-cl2.0.cl
+++ test/SemaOpenCL/invalid-pipes-cl2.0.cl
@@ -7,5 +7,13 @@
 void test3(int pipe p){// expected-error {{cannot combine with previous 'int' declaration specifier}}
 }
 void test4() {
-  pipe int p; // expected-error {{type 'pipe int' can only be used as a function parameter}}
+  pipe int p; // expected-error {{type 'pipe int' can only be used as a function parameter}}gedit test.cl
+  //TODO: fix parsing of this pipe int (*p);
+}
+
+void test5(pipe int p){
+  p+p; // expected-error{{invalid operands to binary expression ('pipe int' and 'pipe int')}}
+  p=p; // expected-error{{invalid operands to binary expression ('pipe int' and 'pipe int')}}
+  &p; // expected-error{{invalid argument type 'pipe int' to unary expression}}
+  *p; // expected-error{{invalid argument type 'pipe int' to unary expression}}
 }
Index: test/SemaOpenCL/invalid-image.cl
===================================================================
--- test/SemaOpenCL/invalid-image.cl
+++ test/SemaOpenCL/invalid-image.cl
@@ -5,4 +5,8 @@
 void test2(image1d_t i) {
   image1d_t ti;            // expected-error {{type '__read_only image1d_t' can only be used as a function parameter}}
   image1d_t ai[] = {i, i}; // expected-error {{array of '__read_only image1d_t' type is invalid in OpenCL}}
+  i=i; //expected-error{{invalid operands to binary expression ('__read_only image1d_t' and '__read_only image1d_t')}}
+  i+1; //expected-error{{invalid operands to binary expression ('__read_only image1d_t' and 'int')}}
+  &i; //expected-error{{invalid argument type '__read_only image1d_t' to unary expression}}
+  *i; //expected-error{{invalid argument type '__read_only image1d_t' to unary expression}}
 }
Index: test/SemaOpenCL/invalid-block.cl
===================================================================
--- test/SemaOpenCL/invalid-block.cl
+++ test/SemaOpenCL/invalid-block.cl
@@ -1,49 +1,53 @@
 // RUN: %clang_cc1 -verify -fblocks -cl-std=CL2.0 %s
 
 // OpenCL v2.0 s6.12.5
-
+void f0(int (^const bl)());
 // All blocks declarations must be const qualified and initialized.
 void f1() {
-  int (^bl1)() = ^() {return 1;}; // expected-error{{invalid block variable declaration - must be const qualified}}
-  int (^const bl2)(); // expected-error{{invalid block variable declaration - must be initialized}}
-  int (^const bl3)() = ^(){return 1;};
+  int (^bl1)() = ^() {return 1;};
+  int (^const bl2)() = ^(){return 1;};
+  f0(bl1);
+  f0(bl2);
+  bl1 = bl2; // expected-error{{invalid operands to binary expression ('int (^const)()' and 'int (^const)()')}}
+  int (^const bl3)(); // expected-error{{invalid block variable declaration - must be initialized}}
 }
 
 // A block with extern storage class is not allowed.
-extern int (^const bl)() = ^(){return 1;}; // expected-error{{invalid block variable declaration - using 'extern' storage class is disallowed}}
+extern int (^bl)() = ^(){return 1;}; // expected-error{{invalid block variable declaration - using 'extern' storage class is disallowed}}
 void f2() {
-  extern int (^const bl)() = ^(){return 1;}; // expected-error{{invalid block variable declaration - using 'extern' storage class is disallowed}}
+  extern int (^bl)() = ^(){return 1;}; // expected-error{{invalid block variable declaration - using 'extern' storage class is disallowed}}
 }
 
 // A block cannot be the return value of a function.
-typedef int (^const bl_t)(void);
+typedef int (^bl_t)(void);
 bl_t f3(bl_t bl); // expected-error{{declaring function return value of type 'bl_t' (aka 'int (^const)(void)') is not allowed}}
 
 struct bl_s {
-  int (^const bl)(void); // expected-error {{the 'int (^const)(void)' type cannot be used to declare a structure or union field}}
+  int (^bl)(void); // expected-error {{the 'int (^const)(void)' type cannot be used to declare a structure or union field}}
 };
 
 void f4() {
   __block int a = 10; // expected-error {{the __block storage type is not permitted}}
 }
 
 // A block with variadic argument is not allowed.
-int (^const bl)(int, ...) = ^int(int I, ...) { // expected-error {{invalid block prototype, variadic arguments are not allowed in OpenCL}}
+int (^bl)(int, ...) = ^int(int I, ...) { // expected-error {{invalid block prototype, variadic arguments are not allowed in OpenCL}}
   return 0;
 };
 
 // A block can't be used to declare an array
-typedef int (^const bl1_t)(int);
+typedef int (^bl1_t)(int);
 void f5(int i) {
   bl1_t bl1 = ^(int i) {return 1;};
   bl1_t bl2 = ^(int i) {return 2;};
   bl1_t arr[] = {bl1, bl2}; // expected-error {{array of 'bl1_t' (aka 'int (^const)(int)') type is invalid in OpenCL}}
   int tmp = i ? bl1(i)      // expected-error {{block type cannot be used as expression in ternary expression in OpenCL}}
               : bl2(i);     // expected-error {{block type cannot be used as expression in ternary expression in OpenCL}}
 }
-
-void f6(bl1_t * bl_ptr) {
+// A block pointer type and all pointer operations are disallowed
+void f6(bl1_t * bl_ptr) { // expected-error{{pointer to type '__generic bl1_t' (aka 'int (^const __generic)(int)') is invalid in OpenCL}}
   bl1_t bl = ^(int i) {return 1;};
-  bl1_t *p = &bl; // expected-error {{invalid argument type 'bl1_t' (aka 'int (^const)(int)') to unary expression}}
-  bl = *bl_ptr;  // expected-error {{dereferencing pointer of type '__generic bl1_t *' (aka 'int (^const __generic *)(int)') is not allowed in OpenCL}}
+  bl1_t *p; // expected-error {{pointer to type '__generic bl1_t' (aka 'int (^const __generic)(int)') is invalid in OpenCL}}
+  *bl;  // expected-error {{invalid argument type 'bl1_t' (aka 'int (^const)(int)') to unary expression}}
+  &bl; // expected-error {{invalid argument type 'bl1_t' (aka 'int (^const)(int)') to unary expression}}
 }
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -3825,8 +3825,13 @@
                               DeclType.Loc, DeclType.getAttrListRef());
 
       T = S.BuildBlockPointerType(T, D.getIdentifierLoc(), Name);
-      if (DeclType.Cls.TypeQuals)
+      if (DeclType.Cls.TypeQuals || LangOpts.OpenCL) {
+        // OpenCL v2.0, s6.12.5 - Block variable declarations are implicitly
+        // qualified with const. 
+        if (LangOpts.OpenCL)
+          DeclType.Cls.TypeQuals|=DeclSpec::TQ_const;
         T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Cls.TypeQuals);
+      }
       break;
     case DeclaratorChunk::Pointer:
       // Verify that we're not building a pointer to pointer to function with
@@ -3847,6 +3852,18 @@
           T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
         break;
       }
+
+      // OpenCL v2.0 s6.9b - Pointer to image/sampler cannot be used.
+      // OpenCL v2.0 s6.13.16.1 - Pointer to pipe cannot be used.
+      // OpenCL v2.0 s6.12.5 - Pointers to Blocks are not allowed.
+      if (LangOpts.OpenCL) {
+        if (T->isImageType() || T->isSamplerT() || T->isPipeType() ||
+            T->isBlockPointerType()) {
+          S.Diag(D.getIdentifierLoc(), diag::err_opencl_pointer_to_type) << T;
+          D.setInvalidType(true);
+        }
+      }
+
       T = S.BuildPointerType(T, DeclType.Loc, Name);
       if (DeclType.Ptr.TypeQuals)
         T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -10518,13 +10518,6 @@
   if (op->getType()->isObjCObjectType())
     return Context.getObjCObjectPointerType(op->getType());
 
-  // OpenCL v2.0 s6.12.5 - The unary operators & cannot be used with a block.
-  if (getLangOpts().OpenCL && OrigOp.get()->getType()->isBlockPointerType()) {
-    Diag(OpLoc, diag::err_typecheck_unary_expr) << OrigOp.get()->getType()
-                                                << op->getSourceRange();
-    return QualType();
-  }
-
   return Context.getPointerType(op->getType());
 }
 
@@ -10568,12 +10561,6 @@
   if (const PointerType *PT = OpTy->getAs<PointerType>())
   {
     Result = PT->getPointeeType();
-    // OpenCL v2.0 s6.12.5 - The unary operators * cannot be used with a block.
-    if (S.getLangOpts().OpenCLVersion >= 200 && Result->isBlockPointerType()) {
-      S.Diag(OpLoc, diag::err_opencl_dereferencing) << OpTy
-                                                    << Op->getSourceRange();
-      return QualType();
-    }
   }
   else if (const ObjCObjectPointerType *OPT =
              OpTy->getAs<ObjCObjectPointerType>())
@@ -10812,6 +10799,8 @@
   }
 
   if (getLangOpts().OpenCL) {
+    QualType LHSTy = LHSExpr->getType();
+    QualType RHSTy = RHSExpr->getType();
     // OpenCLC v2.0 s6.13.11.1 allows atomic variables to be initialized by
     // the ATOMIC_VAR_INIT macro.
     if (LHSExpr->getType()->isAtomicType() ||
@@ -10823,6 +10812,16 @@
         ResultTy = InvalidOperands(OpLoc, LHS, RHS);
       return ExprError();
     }
+
+    // OpenCL special types - image, sampler, pipe, and blocks are to be used
+    // only with a builtin functions and therefore should be disallowed here.
+    if (LHSTy->isImageType() || RHSTy->isImageType() ||
+        LHSTy->isSamplerT() || RHSTy->isSamplerT() ||
+        LHSTy->isPipeType() || RHSTy->isPipeType() ||
+        LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType()) {
+      ResultTy = InvalidOperands(OpLoc, LHS, RHS);
+      return ExprError();
+    }
   }
 
   switch (Opc) {
@@ -11293,8 +11292,13 @@
   ExprObjectKind OK = OK_Ordinary;
   QualType resultType;
   if (getLangOpts().OpenCL) {
+    QualType Ty = InputExpr->getType();
     // The only legal unary operation for atomics is '&'.
-    if (Opc != UO_AddrOf && InputExpr->getType()->isAtomicType()) {
+    if ((Opc != UO_AddrOf && Ty->isAtomicType()) ||
+    // OpenCL special types - image, sampler, pipe, and blocks are to be used
+    // only with a builtin functions and therefore should be disallowed here.
+        (Ty->isImageType() || Ty->isSamplerT() || Ty->isPipeType()
+        || Ty->isBlockPointerType())) {
       return ExprError(Diag(OpLoc, diag::err_typecheck_unary_expr)
                        << InputExpr->getType()
                        << Input.get()->getSourceRange());
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -11032,16 +11032,6 @@
     }
   }
 
-  // OpenCL v2.0 s6.9b - Pointer to image/sampler cannot be used.
-  // OpenCL v2.0 s6.13.16.1 - Pointer to pipe cannot be used.
-  if (getLangOpts().OpenCL && T->isPointerType()) {
-    const QualType PTy = T->getPointeeType();
-    if (PTy->isImageType() || PTy->isSamplerT() || PTy->isPipeType()) {
-      Diag(NameLoc, diag::err_opencl_pointer_to_type) << PTy;
-      New->setInvalidDecl();
-    }
-  }
-
   return New;
 }
 
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -7893,8 +7893,6 @@
   " in the declaration statement in the program scope">;
 def err_opencl_implicit_vector_conversion : Error<
   "implicit conversions between vector types (%0 and %1) are not permitted">;
-def err_opencl_dereferencing : Error<
-  "dereferencing pointer of type %0 is not allowed in OpenCL">;
 def err_opencl_block_proto_variadic : Error<
   "invalid block prototype, variadic arguments are not allowed in OpenCL">;
 def err_opencl_invalid_type_array : Error<
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to