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< 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: 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()) { 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()) @@ -10812,10 +10799,11 @@ } 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() || - RHSExpr->getType()->isAtomicType()) { + if (LHSTy->isAtomicType() || RHSTy->isAtomicType()) { SourceRange SR(LHSExpr->getLocStart(), RHSExpr->getLocEnd()); if (BO_Assign == Opc) Diag(OpLoc, diag::err_atomic_init_constant) << SR; @@ -10823,6 +10811,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 +11291,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/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); @@ -4029,7 +4046,8 @@ // OpenCL v2.0 s6.12.5 - A block cannot be the return value of a // function. - if (LangOpts.OpenCL && T->isBlockPointerType()) { + if (LangOpts.OpenCL && (T->isBlockPointerType() || T->isImageType() || + T->isSamplerT() || T->isPipeType())) { S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return) << T << 1 /*hint off*/; D.setInvalidType(true); Index: test/SemaOpenCL/invalid-block.cl =================================================================== --- test/SemaOpenCL/invalid-block.cl +++ test/SemaOpenCL/invalid-block.cl @@ -1,26 +1,29 @@ // 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() { @@ -28,12 +31,12 @@ } // 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;}; @@ -41,9 +44,10 @@ 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: test/SemaOpenCL/invalid-image.cl =================================================================== --- test/SemaOpenCL/invalid-image.cl +++ test/SemaOpenCL/invalid-image.cl @@ -1,8 +1,14 @@ // RUN: %clang_cc1 -verify %s -void test1(image1d_t *i) {} // expected-error {{pointer to type '__read_only image1d_t' is invalid in OpenCL}} +void test1(image1d_t *i) {} // expected-error{{pointer to type '__read_only image1d_t' is invalid in OpenCL}} 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}} + 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}} } + +image1d_t test3() {} // expected-error{{declaring function return value of type '__read_only image1d_t' is not allowed}} Index: test/SemaOpenCL/invalid-pipes-cl2.0.cl =================================================================== --- test/SemaOpenCL/invalid-pipes-cl2.0.cl +++ test/SemaOpenCL/invalid-pipes-cl2.0.cl @@ -1,11 +1,22 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0 -void test1(pipe int *p){// expected-error {{pipes packet types cannot be of reference type}} +void test1(pipe int *p) {// expected-error {{pipes packet types cannot be of reference type}} } -void test2(pipe p){// expected-error {{missing actual type specifier for pipe}} +void test2(pipe p) {// expected-error {{missing actual type specifier for pipe}} } -void test3(int pipe p){// expected-error {{cannot combine with previous 'int' declaration specifier}} +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}} + //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}} +} + +typedef pipe int pipe_int_t; +pipe_int_t test6() {} // expected-error{{declaring function return value of type 'pipe_int_t' (aka 'pipe int') is not allowed}} Index: test/SemaOpenCL/sampler_t.cl =================================================================== --- test/SemaOpenCL/sampler_t.cl +++ test/SemaOpenCL/sampler_t.cl @@ -5,16 +5,27 @@ void foo(sampler_t); constant struct sampler_s { - sampler_t smp; // expected-error {{the 'sampler_t' type cannot be used to declare a structure or union field}} + sampler_t smp; // expected-error{{the 'sampler_t' type cannot be used to declare a structure or union field}} } sampler_str = {0}; void kernel ker(sampler_t argsmp) { - local sampler_t smp; // expected-error {{sampler type cannot be used with the __local and __global address space qualifiers}} + local sampler_t smp; // expected-error{{sampler type cannot be used with the __local and __global address space qualifiers}} const sampler_t const_smp = 7; foo(glb_smp); foo(const_smp); - foo(5); // expected-error {{sampler_t variable required - got 'int'}} + foo(5); // expected-error{{sampler_t variable required - got 'int'}} sampler_t sa[] = {argsmp, const_smp}; // expected-error {{array of 'sampler_t' type is invalid in OpenCL}} } -void bad(sampler_t*); // expected-error {{pointer to type 'sampler_t' is invalid in OpenCL}} +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}} +} + +sampler_t bad(); //expected-error{{declaring function return value of type 'sampler_t' is not allowed}}