From 82bebd88990fdf6c635b85522c366f1a3c535e24 Mon Sep 17 00:00:00 2001 From: Anastasia Stulova Date: Thu, 7 Sep 2017 17:00:33 +0000 Subject: [PATCH] [OpenCL] Handle taking an address of block captures. 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 --- include/clang/Basic/DiagnosticSemaKinds.td | 4 ++-- lib/Sema/SemaExpr.cpp | 23 +++++++++++----------- test/SemaOpenCL/invalid-block.cl | 11 +++++++++++ 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 30f1528fec43..5b8277f5fee2 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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">; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 510c5214d48c..1a644c88296b 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -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(E->IgnoreParenCasts())) if (auto *FD = dyn_cast(DRE->getDecl())) if (!checkAddressOfFunctionIsAvailable(FD, Diagnose, E->getExprLoc())) @@ -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(op); + if (VarRef && VarRef->refersToEnclosingVariableOrCapture()) { + Diag(op->getExprLoc(), diag::err_opencl_taking_address_capture); + return QualType(); + } } if (getLangOpts().C99) { diff --git a/test/SemaOpenCL/invalid-block.cl b/test/SemaOpenCL/invalid-block.cl index 89bf03264e13..5d6dc380a37a 100644 --- a/test/SemaOpenCL/invalid-block.cl +++ b/test/SemaOpenCL/invalid-block.cl @@ -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}} + }; +}