Skip to content

Commit

Permalink
[OpenCL] Handle taking an address of block captures.
Browse files Browse the repository at this point in the history
Block captures can have different physical locations
in memory segments depending on the use case (as a function
call or as a kernel enqueue) and in different vendor
implementations.

Therefore it's unclear how to add address space to capture
addresses uniformly. Currently it has been decided to disallow
taking addresses of captured variables until further
clarifications in the spec.

Differential Revision: https://reviews.llvm.org/D36410



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@312728 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Anastasia Stulova committed Sep 7, 2017
1 parent 824f38d commit 82bebd8
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 14 deletions.
4 changes: 2 additions & 2 deletions include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -7349,8 +7349,8 @@ def err_invalid_conversion_between_vector_and_integer : Error<
def err_opencl_function_pointer : Error<
"pointers to functions are not allowed">;

def err_opencl_taking_function_address : Error<
"taking address of function is not allowed">;
def err_opencl_taking_address_capture : Error<
"taking address of a capture is not allowed">;

def err_invalid_conversion_between_vector_and_scalar : Error<
"invalid conversion between vector type %0 and scalar type %1">;
Expand Down
23 changes: 11 additions & 12 deletions lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,14 +425,6 @@ ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) {
assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type");

if (Ty->isFunctionType()) {
// If we are here, we are not calling a function but taking
// its address (which is not allowed in OpenCL v1.0 s6.8.a.3).
if (getLangOpts().OpenCL) {
if (Diagnose)
Diag(E->getExprLoc(), diag::err_opencl_taking_function_address);
return ExprError();
}

if (auto *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()))
if (auto *FD = dyn_cast<FunctionDecl>(DRE->getDecl()))
if (!checkAddressOfFunctionIsAvailable(FD, Diagnose, E->getExprLoc()))
Expand Down Expand Up @@ -10869,10 +10861,17 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) {
// Make sure to ignore parentheses in subsequent checks
Expr *op = OrigOp.get()->IgnoreParens();

// OpenCL v1.0 s6.8.a.3: Pointers to functions are not allowed.
if (LangOpts.OpenCL && op->getType()->isFunctionType()) {
Diag(op->getExprLoc(), diag::err_opencl_taking_function_address);
return QualType();
// In OpenCL captures for blocks called as lambda functions
// are located in the private address space. Blocks used in
// enqueue_kernel can be located in a different address space
// depending on a vendor implementation. Thus preventing
// taking an address of the capture to avoid invalid AS casts.
if (LangOpts.OpenCL) {
auto* VarRef = dyn_cast<DeclRefExpr>(op);
if (VarRef && VarRef->refersToEnclosingVariableOrCapture()) {
Diag(op->getExprLoc(), diag::err_opencl_taking_address_capture);
return QualType();
}
}

if (getLangOpts().C99) {
Expand Down
11 changes: 11 additions & 0 deletions test/SemaOpenCL/invalid-block.cl
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,14 @@ kernel void f7() {
};
return;
}

// Taking address of a capture is not allowed
int g;
kernel void f8(int a1) {
int a2;
void (^bl)(void) = ^(void) {
&g; //expected-warning{{expression result unused}}
&a1; //expected-error{{taking address of a capture is not allowed}}
&a2; //expected-error{{taking address of a capture is not allowed}}
};
}

0 comments on commit 82bebd8

Please sign in to comment.