Skip to content

Commit

Permalink
[OpenCL] Add Sema checks for OpenCL 2.0 block
Browse files Browse the repository at this point in the history
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
  • Loading branch information
xiulipan committed Feb 24, 2016
1 parent 74a1fc6 commit 89307aa
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 0 deletions.
8 changes: 8 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Expand Up @@ -7712,6 +7712,14 @@ 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<
"array of %0 type is invalid in OpenCL">;
def err_opencl_ternary_with_block : Error<
"block type cannot be used as expression in ternary expression in OpenCL">;

// OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions
def err_opencl_builtin_pipe_first_arg : Error<
Expand Down
13 changes: 13 additions & 0 deletions clang/lib/Sema/SemaDecl.cpp
Expand Up @@ -6708,6 +6708,19 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
NewVD->setInvalidDecl();
return;
}

// OpenCL v2.0 s6.12.5 - Blocks with variadic arguments are not supported.
if (LangOpts.OpenCL && T->isBlockPointerType()) {
const BlockPointerType *BlkTy = T->getAs<BlockPointerType>();
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
Expand Down
35 changes: 35 additions & 0 deletions clang/lib/Sema/SemaExpr.cpp
Expand Up @@ -6458,6 +6458,18 @@ OpenCLCheckVectorConditional(Sema &S, ExprResult &Cond,
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
Expand Down Expand Up @@ -6507,6 +6519,13 @@ QualType Sema::CheckConditionalOperands(ExprResult &Cond, ExprResult &LHS,
QualType LHSTy = LHS.get()->getType();
QualType RHSTy = RHS.get()->getType();

// OpenCL v2.0 s6.12.5 - Blocks cannot be used as expressions of the ternary
// selection operator (?:).
if (getLangOpts().OpenCL &&
(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()) {
Expand Down Expand Up @@ -10334,6 +10353,14 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
// 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 & 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());
}

Expand Down Expand Up @@ -10375,7 +10402,15 @@ 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>())
Result = OPT->getPointeeType();
Expand Down
9 changes: 9 additions & 0 deletions clang/lib/Sema/SemaType.cpp
Expand Up @@ -2175,6 +2175,15 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
Diag(Loc, diag::warn_vla_used);
}

// OpenCL v2.0 s6.12.5 - Arrays of blocks are not supported.
if (getLangOpts().OpenCL) {
const QualType ArrType = Context.getBaseElementType(T);
if (ArrType->isBlockPointerType()) {
Diag(Loc, diag::err_opencl_invalid_type_array) << ArrType;
return QualType();
}
}

return T;
}

Expand Down
20 changes: 20 additions & 0 deletions clang/test/SemaOpenCL/invalid-block.cl
@@ -0,0 +1,20 @@
// 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 in OpenCL}}
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 'BlkInt' (aka 'int (^)(int)') type is invalid in OpenCL}}
int tmp = i ? B1(i) // expected-error {{block type cannot be used as expression in ternary expression in OpenCL}}
: B2(i); // expected-error {{block type cannot be used as expression in ternary expression in OpenCL}}
}

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 in OpenCL}}
}

0 comments on commit 89307aa

Please sign in to comment.