pxli168 updated this revision to Diff 44619.
pxli168 added a comment.

FIxed bugs and relocate the test cases.
Upload the full diff.


http://reviews.llvm.org/D16047

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaInit.cpp
  lib/Sema/SemaType.cpp
  test/CodeGenOpenCL/opencl_types.cl
  test/Parser/opencl-atomics-cl20.cl
  test/SemaOpenCL/invalid-block.cl
  test/SemaOpenCL/invalid-decl.cl
  test/SemaOpenCL/invalid-image.cl
  test/SemaOpenCL/invalid-pipes-cl2.0.cl

Index: test/SemaOpenCL/invalid-pipes-cl2.0.cl
===================================================================
--- test/SemaOpenCL/invalid-pipes-cl2.0.cl
+++ test/SemaOpenCL/invalid-pipes-cl2.0.cl
@@ -6,3 +6,6 @@
 }
 void test3(int pipe p){// expected-error {{cannot combine with previous 'int' declaration specifier}}
 }
+void test4() {
+  pipe int p; // expected-error {{pipe can only be used as a function parameter}}
+}
Index: test/SemaOpenCL/invalid-image.cl
===================================================================
--- /dev/null
+++ test/SemaOpenCL/invalid-image.cl
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -verify %s
+
+void test1(image1d_t *i){} // expected-error {{pointer to image is invalid in OpenCL}}
+
+void test2() {
+  image1d_t i; // expected-error {{image can only be used as a function parameter}}
+}
Index: test/SemaOpenCL/invalid-decl.cl
===================================================================
--- /dev/null
+++ test/SemaOpenCL/invalid-decl.cl
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -verify -cl-std=CL2.0 %s 
+int; // expected-error {{declaration does not declare anything}}
+
+void test1(){
+  myfun(); // expected-error {{implicit declaration of function 'myfun' is invalid in OpenCL}}
+}
Index: test/SemaOpenCL/invalid-block.cl
===================================================================
--- /dev/null
+++ test/SemaOpenCL/invalid-block.cl
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -verify -fblocks -cl-std=CL2.0 %s
+
+int (^BlkVariadic)(int, ...) = ^int(int I, ...) { // expected-error {{invalid block prototype, variadic arguments are not allowed}}
+  return 0;
+};
+
+typedef int (^BlkInt)(int);
+void f1(int i) {
+  BlkInt B1 = ^int(int I) {return 1;};
+  BlkInt B2 = ^int(int I) {return 2;};
+  BlkInt Arr[] = {B1, B2}; // expected-error {{array of block is invalid in OpenCL}}
+  int tmp = i ? B1(i)      // expected-error {{blocks cannot be used as expressions in ternary expressions}}
+              : B2(i);     // expected-error {{blocks cannot be used as expressions in ternary expressions}}
+}
+
+void f2(BlkInt *BlockPtr) {
+  BlkInt B = ^int(int I) {return 1;};
+  BlkInt *P = &B; // expected-error {{invalid argument type 'BlkInt' (aka 'int (^)(int)') to unary expression}}
+  B = *BlockPtr;  // expected-error {{dereferencing pointer of type '__generic BlkInt *' (aka 'int (^__generic *)(int)') is not allowed}}
+}
+
Index: test/Parser/opencl-atomics-cl20.cl
===================================================================
--- test/Parser/opencl-atomics-cl20.cl
+++ test/Parser/opencl-atomics-cl20.cl
@@ -56,6 +56,7 @@
 #endif
 
 #ifdef CL20
+#define ATOMIC_VAR_INIT
 void foo(atomic_int * ptr) {}
 void atomic_ops_test() {
   atomic_int i;
@@ -66,4 +67,7 @@
   i += 1; // expected-error {{invalid operands to binary expression ('atomic_int' (aka '_Atomic(int)') and 'int')}}
   i = i + i; // expected-error {{invalid operands to binary expression ('atomic_int' (aka '_Atomic(int)') and 'atomic_int')}}
 }
+void atomic_init_test() {
+    atomic_int guide = ATOMIC_VAR_INIT(42); // expected-error {{initialization of atomic variables is restricted to variables in global address space in opencl}}
+}
 #endif
Index: test/CodeGenOpenCL/opencl_types.cl
===================================================================
--- test/CodeGenOpenCL/opencl_types.cl
+++ test/CodeGenOpenCL/opencl_types.cl
@@ -35,6 +35,3 @@
   fnc4smp(glb_smp);
 // CHECK: call {{.*}}void @fnc4smp(i32
 }
-
-void __attribute__((overloadable)) bad1(image1d_t *b, image2d_t *c, image2d_t *d) {}
-// CHECK-LABEL: @{{_Z4bad1P11ocl_image1dP11ocl_image2dS2_|"\\01\?bad1@@\$\$J0YAXPE?APAUocl_image1d@@PE?APAUocl_image2d@@1@Z"}}
Index: lib/Sema/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -2176,6 +2176,14 @@
     Diag(Loc, diag::warn_vla_used);
   }
 
+  // OpenCL v2.0 s6.12.5 - The following Blocks features are currently not
+  // supported in OpenCL C: Arrays of Blocks.
+  if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion >= 200 &&
+      Context.getBaseElementType(T)->isBlockPointerType()) {
+    Diag(Loc, diag::err_opencl_invalid_block_array);
+    return QualType();
+  }
+
   return T;
 }
 
Index: lib/Sema/SemaInit.cpp
===================================================================
--- lib/Sema/SemaInit.cpp
+++ lib/Sema/SemaInit.cpp
@@ -6135,6 +6135,32 @@
       << Init->getSourceRange();
   }
 
+  // OpenCL v2.0 s6.13.11.1 - The ATOMIC_VAR_INIT macro expands to a token
+  // sequence suitable for initializing an atomic object of a type that is
+  // initialization-compatible with value. An atomic object with automatic
+  // storage duration that is not explicitly initialized using ATOMIC_VAR_INIT
+  // is initially in an indeterminate state; however, the default (zero)
+  // initialization for objects with static storage duration is guaranteed to
+  // produce a valid state.
+  // #define ATOMIC_VAR_INIT(C value)
+  // This macro can only be used to initialize atomic objects that are declared
+  // in program scope in the global address space.
+  // Examples:
+  // global atomic_int guide = ATOMIC_VAR_INIT(42);
+  if (S.getLangOpts().OpenCL && S.getLangOpts().OpenCLVersion >= 200 &&
+      Entity.getType()->isAtomicType()) {
+    Qualifiers TyQualifiers = Entity.getType().getQualifiers();
+    bool HasGlobalAS = TyQualifiers.hasAddressSpace() &&
+                       TyQualifiers.getAddressSpace() == LangAS::opencl_global;
+    if (!HasGlobalAS && Entity.getKind() == InitializedEntity::EK_Variable &&
+        Args.size() > 0) {
+      Expr *Init = Args[0];
+      S.Diag(Init->getLocStart(), diag::err_opencl_atomic_init_addressspace)
+          << SourceRange(Entity.getDecl()->getLocStart(), Init->getLocEnd());
+      return ExprError();
+    }
+  }
+
   // Diagnose cases where we initialize a pointer to an array temporary, and the
   // pointer obviously outlives the temporary.
   if (Args.size() == 1 && Args[0]->getType()->isArrayType() &&
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -6248,6 +6248,18 @@
   return OpenCLConvertScalarsToVectors(S, LHS, RHS, CondTy, QuestionLoc);
 }
 
+/// \brief Return true if the Expr is block type
+static bool checkBlockType(Sema &S, const Expr *E) {
+  if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
+    QualType Ty = CE->getCallee()->getType();
+    if (Ty->isBlockPointerType()) {
+      S.Diag(E->getExprLoc(), diag::err_opencl_ternary_with_block);
+      return true;
+    }
+  }
+  return false;
+}
+
 /// Note that LHS is not null here, even if this is the gnu "x ?: y" extension.
 /// In that case, LHS = cond.
 /// C99 6.5.15
@@ -6297,6 +6309,15 @@
   QualType LHSTy = LHS.get()->getType();
   QualType RHSTy = RHS.get()->getType();
 
+  // OpenCL v2.0 s6.12.5 - To support these behaviors, additional
+  // restrictions in addition to the above feature restrictions are: Blocks
+  // cannot be used as expressions of the ternary selection operator (?:).
+  if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion >= 200) {
+    // should output error for both LHS and RHS, use | instead ||
+    if (checkBlockType(*this, LHS.get()) | checkBlockType(*this, RHS.get()))
+      return QualType();
+  }
+
   // If both operands have arithmetic type, do the usual arithmetic conversions
   // to find a common type: C99 6.5.15p3,5.
   if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) {
@@ -7411,7 +7432,8 @@
 static bool tryVectorConvertAndSplat(Sema &S, ExprResult *scalar,
                                      QualType scalarTy,
                                      QualType vectorEltTy,
-                                     QualType vectorTy) {
+                                     QualType vectorTy,
+                                     SourceLocation Loc) {
   // The conversion to apply to the scalar before splatting it,
   // if necessary.
   CastKind scalarCast = CK_Invalid;
@@ -7519,13 +7541,13 @@
   // the vector element type and splat.
   if (!RHSVecType && isa<ExtVectorType>(LHSVecType)) {
     if (!tryVectorConvertAndSplat(*this, &RHS, RHSType,
-                                  LHSVecType->getElementType(), LHSType))
+                                  LHSVecType->getElementType(), LHSType, Loc))
       return LHSType;
   }
   if (!LHSVecType && isa<ExtVectorType>(RHSVecType)) {
     if (!tryVectorConvertAndSplat(*this, (IsCompAssign ? nullptr : &LHS),
                                   LHSType, RHSVecType->getElementType(),
-                                  RHSType))
+                                  RHSType, Loc))
       return RHSType;
   }
 
@@ -10034,6 +10056,17 @@
   // If the operand has type "type", the result has type "pointer to type".
   if (op->getType()->isObjCObjectType())
     return Context.getObjCObjectPointerType(op->getType());
+
+  // OpenCL v2.0 s6.12.5 - The unary operators (* and &) cannot be used with a
+  // Block
+  if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion >= 200) {
+    if (OrigOp.get()->getType()->isBlockPointerType()) {
+      Diag(OpLoc, diag::err_typecheck_unary_expr) << OrigOp.get()->getType()
+                                                  << op->getSourceRange();
+      return QualType();
+    }
+  }
+
   return Context.getPointerType(op->getType());
 }
 
@@ -10075,7 +10108,17 @@
   }
 
   if (const PointerType *PT = OpTy->getAs<PointerType>())
+  {
     Result = PT->getPointeeType();
+    // OpenCL v2.0 s6.12.5 - The unary operators (* and &) cannot be used with a
+    // Block.
+    if (S.getLangOpts().OpenCL && 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>())
     Result = OPT->getPointeeType();
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -3884,6 +3884,12 @@
   //   names into the program, or shall redeclare a name introduced by a
   //   previous declaration.
   if (!DeclaresAnything) {
+    // OpenCL C doesn't support bit-field, so declaration with no declarator
+    // has no use.
+    if (getLangOpts().OpenCL) {
+      Diag(DS.getLocStart(), diag::err_no_declarators) << DS.getSourceRange();
+      return 0;
+    }
     // In C, we allow this as a (popular) extension / bug. Don't bother
     // producing further diagnostics for redundant qualifiers after this.
     Diag(DS.getLocStart(), diag::ext_no_declarators) << DS.getSourceRange();
@@ -5701,6 +5707,27 @@
   QualType R = TInfo->getType();
   DeclarationName Name = GetNameForDeclarator(D).getName();
 
+  // OpenCL v2.0 s6.9.b
+  // An image type can only be used as a type of a function argument.
+  if (getLangOpts().OpenCL && R->isImageType()) {
+    Diag(D.getIdentifierLoc(),
+         diag::err_opencl_type_can_only_be_used_as_function_parameter)
+        << "image";
+    D.setInvalidType();
+    return nullptr;
+  }
+
+  // OpenCL v2.0 s6.13.16.1
+  // Pipes can only be passed as arguments to a function.
+  if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion >= 200 &&
+      R->isPipeType()) {
+    Diag(D.getIdentifierLoc(),
+         diag::err_opencl_type_can_only_be_used_as_function_parameter)
+        << "pipe";
+    D.setInvalidType();
+    return nullptr;
+  }
+
   DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec();
   StorageClass SC = StorageClassSpecToVarDeclStorageClass(D.getDeclSpec());
 
@@ -6680,6 +6707,24 @@
     NewVD->setInvalidDecl();
     return;
   }
+
+  // OpenCL v2.0 s6.12.5 - The following Blocks features are currently not
+  // supported in OpenCL C: Blocks with variadic arguments.
+  if (getLangOpts().OpenCL && LangOpts.OpenCLVersion >= 200 &&
+      T->isBlockPointerType()) {
+    const BlockPointerType *BlkTy = T->getAs<BlockPointerType>();
+    assert(BlkTy && "Not a block pointer.");
+
+    const FunctionProtoType *FTy =
+        BlkTy->getPointeeType()->getAs<FunctionProtoType>();
+
+    if (FTy->isVariadic()) {
+      Diag(NewVD->getLocation(), diag::err_opencl_block_proto_variadic)
+          << T << NewVD->getSourceRange();
+      NewVD->setInvalidDecl();
+      return;
+    }
+  }
 }
 
 /// \brief Perform semantic checking on a newly-created variable
@@ -7207,8 +7252,13 @@
     QualType PointeeType = PT->getPointeeType();
     if (PointeeType->isPointerType())
       return PtrPtrKernelParam;
-    return PointeeType.getAddressSpace() == 0 ? PrivatePtrKernelParam
-                                              : PtrKernelParam;
+    // Now generice address space is added, we need to handle like this
+    unsigned addrSpace = PointeeType.getAddressSpace();
+    return (addrSpace != LangAS::opencl_global &&
+            addrSpace != LangAS::opencl_constant &&
+            addrSpace != LangAS::opencl_local)
+               ? PrivatePtrKernelParam
+               : PtrKernelParam;
   }
 
   // TODO: Forbid the other integer types (size_t, ptrdiff_t...) when they can
@@ -7226,6 +7276,9 @@
   if (PT->isHalfType())
     return InvalidKernelParam;
 
+  if (PT->isReserveIDT())
+    return InvalidKernelParam;
+
   if (PT->isRecordType())
     return RecordKernelParam;
 
@@ -10634,6 +10687,15 @@
     }
   }   
 
+  // OpenCL v2.0 s6.9b2 - An image type cannot be used to declare a variable, a
+  // structure or union field, an array of images, a pointer to an image, or the
+  // return type of a function.
+  if (getLangOpts().OpenCL && T->isPointerType() &&
+      T->getPointeeType()->isImageType()) {
+    Diag(NameLoc, diag::err_opencl_pointer_to_image);
+    New->setInvalidDecl();
+  }
+
   return New;
 }
 
@@ -11345,6 +11407,10 @@
   unsigned diag_id;
   if (II.getName().startswith("__builtin_"))
     diag_id = diag::warn_builtin_unknown;
+  else if (getLangOpts().OpenCL)
+    // OpenCL function need to be called with prototype, so we don't allow
+    // implicit function declarations in OpenCL
+    diag_id = diag::err_opencl_implicit_function_decl;
   else if (getLangOpts().C99)
     diag_id = diag::ext_implicit_function_decl;
   else
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -589,6 +589,7 @@
 /// parser diagnostics
 def ext_no_declarators : ExtWarn<"declaration does not declare anything">,
   InGroup<MissingDeclarations>;
+def err_no_declarators : Error<"declaration does not declare anything">;
 def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">,
   InGroup<MissingDeclarations>;
 def err_typedef_not_identifier : Error<"typedef name must be an identifier">;
@@ -7658,6 +7659,23 @@
   " 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_implicit_function_decl : Error<
+  "implicit declaration of function %0 is invalid in OpenCL">;
+def err_opencl_dereferencing : Error<
+  "dereferencing pointer of type %0 is not allowed in OpenCL">;
+def err_opencl_pointer_to_image : Error<
+  "pointer to image is invalid in OpenCL">;
+def err_opencl_type_can_only_be_used_as_function_parameter : Error <
+  "%0 can only be used as a function parameter">;
+def err_opencl_atomic_init_addressspace : Error<
+  "initialization of atomic variables is restricted to variables in global address space in opencl">;
+def err_opencl_block_proto_variadic : Error<
+  "invalid block prototype, variadic arguments are not allowed in opencl">;
+def err_opencl_invalid_block_array : Error<
+  "array of block is invalid in OpenCL">;
+def err_opencl_ternary_with_block : Error<
+  "blocks cannot be used as expressions in ternary expressions in opencl">;
+
 
 // OpenCL Section 6.8.g
 def err_opencl_unknown_type_specifier : Error<
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to