forked from OSchip/llvm-project
[OpenCL] Improved diagnostics of OpenCL types.
- Changes diagnostics for Blocks to be implicitly const qualified OpenCL v2.0 s6.12.5. - Added and unified diagnostics of some OpenCL special types: blocks, images, samplers, pipes. These types are intended for use with the OpenCL builtin functions only and, therefore, most regular uses are not allowed including assignments, arithmetic operations, pointer dereferencing, etc. Review: http://reviews.llvm.org/D21989 llvm-svn: 275061
This commit is contained in:
parent
c73301bbe3
commit
4d85003964
|
@ -7893,8 +7893,6 @@ def err_atomic_init_constant : Error<
|
|||
" 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<
|
||||
|
|
|
@ -11032,16 +11032,6 @@ ParmVarDecl *Sema::CheckParameter(DeclContext *DC, SourceLocation StartLoc,
|
|||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -10534,13 +10534,6 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
|
|||
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());
|
||||
}
|
||||
|
||||
|
@ -10584,12 +10577,6 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
|
|||
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>())
|
||||
|
@ -10828,10 +10815,11 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -10839,6 +10827,16 @@ ExprResult Sema::CreateBuiltinBinOp(SourceLocation OpLoc,
|
|||
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) {
|
||||
|
@ -11309,8 +11307,13 @@ ExprResult Sema::CreateBuiltinUnaryOp(SourceLocation OpLoc,
|
|||
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());
|
||||
|
|
|
@ -3825,8 +3825,13 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|||
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 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|||
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 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|||
|
||||
// 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);
|
||||
|
|
|
@ -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 @@ void f4() {
|
|||
}
|
||||
|
||||
// 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 @@ void f5(int i) {
|
|||
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}}
|
||||
}
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -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}}
|
||||
|
|
|
@ -5,16 +5,27 @@ constant sampler_t glb_smp = 5;
|
|||
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}}
|
||||
|
|
Loading…
Reference in New Issue