pxli168 updated this revision to Diff 47074.
pxli168 updated the summary for this revision.
pxli168 added a comment.
Rebase for partition
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
@@ -2175,6 +2175,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
@@ -6426,6 +6426,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
@@ -6475,6 +6487,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()) {
@@ -7588,7 +7609,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;
@@ -7696,13 +7718,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;
}
@@ -10212,6 +10234,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());
}
@@ -10253,7 +10286,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
@@ -3902,6 +3902,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();
@@ -5716,6 +5722,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());
@@ -6704,6 +6731,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
@@ -7231,8 +7276,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
@@ -7250,6 +7300,9 @@
if (PT->isHalfType())
return InvalidKernelParam;
+ if (PT->isReserveIDT())
+ return InvalidKernelParam;
+
if (PT->isRecordType())
return RecordKernelParam;
@@ -10712,6 +10765,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;
}
@@ -11427,6 +11489,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
@@ -596,6 +596,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">;
@@ -7692,6 +7693,22 @@
" 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 v2.0 s6.13.6 -- Builtin Pipe Functions
def err_opencl_builtin_pipe_first_arg : Error<
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits