Skip to content

Commit 89307aa

Browse files
committed
[OpenCL] Add Sema checks for OpenCL 2.0 block
Summary: Add Sema checks for opencl 2.0 new features: Block. This patch is partitioned from http://reviews.llvm.org/D16047 Reviewers: Anastasia Subscribers: pekka.jaaskelainen, cfe-commits Differential Revision: http://reviews.llvm.org/D17436 llvm-svn: 261719
1 parent 74a1fc6 commit 89307aa

File tree

5 files changed

+85
-0
lines changed

5 files changed

+85
-0
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7712,6 +7712,14 @@ def err_atomic_init_constant : Error<
77127712
" in the declaration statement in the program scope">;
77137713
def err_opencl_implicit_vector_conversion : Error<
77147714
"implicit conversions between vector types (%0 and %1) are not permitted">;
7715+
def err_opencl_dereferencing : Error<
7716+
"dereferencing pointer of type %0 is not allowed in OpenCL">;
7717+
def err_opencl_block_proto_variadic : Error<
7718+
"invalid block prototype, variadic arguments are not allowed in OpenCL">;
7719+
def err_opencl_invalid_type_array : Error<
7720+
"array of %0 type is invalid in OpenCL">;
7721+
def err_opencl_ternary_with_block : Error<
7722+
"block type cannot be used as expression in ternary expression in OpenCL">;
77157723

77167724
// OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions
77177725
def err_opencl_builtin_pipe_first_arg : Error<

clang/lib/Sema/SemaDecl.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6708,6 +6708,19 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
67086708
NewVD->setInvalidDecl();
67096709
return;
67106710
}
6711+
6712+
// OpenCL v2.0 s6.12.5 - Blocks with variadic arguments are not supported.
6713+
if (LangOpts.OpenCL && T->isBlockPointerType()) {
6714+
const BlockPointerType *BlkTy = T->getAs<BlockPointerType>();
6715+
const FunctionProtoType *FTy =
6716+
BlkTy->getPointeeType()->getAs<FunctionProtoType>();
6717+
if (FTy->isVariadic()) {
6718+
Diag(NewVD->getLocation(), diag::err_opencl_block_proto_variadic)
6719+
<< T << NewVD->getSourceRange();
6720+
NewVD->setInvalidDecl();
6721+
return;
6722+
}
6723+
}
67116724
}
67126725

67136726
/// \brief Perform semantic checking on a newly-created variable

clang/lib/Sema/SemaExpr.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6458,6 +6458,18 @@ OpenCLCheckVectorConditional(Sema &S, ExprResult &Cond,
64586458
return OpenCLConvertScalarsToVectors(S, LHS, RHS, CondTy, QuestionLoc);
64596459
}
64606460

6461+
/// \brief Return true if the Expr is block type
6462+
static bool checkBlockType(Sema &S, const Expr *E) {
6463+
if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
6464+
QualType Ty = CE->getCallee()->getType();
6465+
if (Ty->isBlockPointerType()) {
6466+
S.Diag(E->getExprLoc(), diag::err_opencl_ternary_with_block);
6467+
return true;
6468+
}
6469+
}
6470+
return false;
6471+
}
6472+
64616473
/// Note that LHS is not null here, even if this is the gnu "x ?: y" extension.
64626474
/// In that case, LHS = cond.
64636475
/// C99 6.5.15
@@ -6507,6 +6519,13 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
65076519
QualType LHSTy = LHS.get()->getType();
65086520
QualType RHSTy = RHS.get()->getType();
65096521

6522+
// OpenCL v2.0 s6.12.5 - Blocks cannot be used as expressions of the ternary
6523+
// selection operator (?:).
6524+
if (getLangOpts().OpenCL &&
6525+
(checkBlockType(*this, LHS.get()) | checkBlockType(*this, RHS.get()))) {
6526+
return QualType();
6527+
}
6528+
65106529
// If both operands have arithmetic type, do the usual arithmetic conversions
65116530
// to find a common type: C99 6.5.15p3,5.
65126531
if (LHSTy->isArithmeticType() && RHSTy->isArithmeticType()) {
@@ -10334,6 +10353,14 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
1033410353
// If the operand has type "type", the result has type "pointer to type".
1033510354
if (op->getType()->isObjCObjectType())
1033610355
return Context.getObjCObjectPointerType(op->getType());
10356+
10357+
// OpenCL v2.0 s6.12.5 - The unary operators & cannot be used with a block.
10358+
if (getLangOpts().OpenCL && OrigOp.get()->getType()->isBlockPointerType()) {
10359+
Diag(OpLoc, diag::err_typecheck_unary_expr) << OrigOp.get()->getType()
10360+
<< op->getSourceRange();
10361+
return QualType();
10362+
}
10363+
1033710364
return Context.getPointerType(op->getType());
1033810365
}
1033910366

@@ -10375,7 +10402,15 @@ static QualType CheckIndirectionOperand(Sema &S, Expr *Op, ExprValueKind &VK,
1037510402
}
1037610403

1037710404
if (const PointerType *PT = OpTy->getAs<PointerType>())
10405+
{
1037810406
Result = PT->getPointeeType();
10407+
// OpenCL v2.0 s6.12.5 - The unary operators * cannot be used with a block.
10408+
if (S.getLangOpts().OpenCLVersion >= 200 && Result->isBlockPointerType()) {
10409+
S.Diag(OpLoc, diag::err_opencl_dereferencing) << OpTy
10410+
<< Op->getSourceRange();
10411+
return QualType();
10412+
}
10413+
}
1037910414
else if (const ObjCObjectPointerType *OPT =
1038010415
OpTy->getAs<ObjCObjectPointerType>())
1038110416
Result = OPT->getPointeeType();

clang/lib/Sema/SemaType.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2175,6 +2175,15 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
21752175
Diag(Loc, diag::warn_vla_used);
21762176
}
21772177

2178+
// OpenCL v2.0 s6.12.5 - Arrays of blocks are not supported.
2179+
if (getLangOpts().OpenCL) {
2180+
const QualType ArrType = Context.getBaseElementType(T);
2181+
if (ArrType->isBlockPointerType()) {
2182+
Diag(Loc, diag::err_opencl_invalid_type_array) << ArrType;
2183+
return QualType();
2184+
}
2185+
}
2186+
21782187
return T;
21792188
}
21802189

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %clang_cc1 -verify -fblocks -cl-std=CL2.0 %s
2+
3+
int (^BlkVariadic)(int, ...) = ^int(int I, ...) { // expected-error {{invalid block prototype, variadic arguments are not allowed in OpenCL}}
4+
return 0;
5+
};
6+
7+
typedef int (^BlkInt)(int);
8+
void f1(int i) {
9+
BlkInt B1 = ^int(int I) {return 1;};
10+
BlkInt B2 = ^int(int I) {return 2;};
11+
BlkInt Arr[] = {B1, B2}; // expected-error {{array of 'BlkInt' (aka 'int (^)(int)') type is invalid in OpenCL}}
12+
int tmp = i ? B1(i) // expected-error {{block type cannot be used as expression in ternary expression in OpenCL}}
13+
: B2(i); // expected-error {{block type cannot be used as expression in ternary expression in OpenCL}}
14+
}
15+
16+
void f2(BlkInt *BlockPtr) {
17+
BlkInt B = ^int(int I) {return 1;};
18+
BlkInt *P = &B; // expected-error {{invalid argument type 'BlkInt' (aka 'int (^)(int)') to unary expression}}
19+
B = *BlockPtr; // expected-error {{dereferencing pointer of type '__generic BlkInt *' (aka 'int (^__generic *)(int)') is not allowed in OpenCL}}
20+
}

0 commit comments

Comments
 (0)