summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorArtem Belevich <tra@google.com>2016-02-02 22:29:48 +0000
committerArtem Belevich <tra@google.com>2016-02-02 22:29:48 +0000
commit97c01c35f8da48b47c397fd915a82bd1d881d4ab (patch)
tree06d8b1e2ae200287569e9ad71bdaa548e5ef75d6 /clang/lib/Sema/SemaDecl.cpp
parent8abc2e51b81efe2f540f6a61a3028f8fe72fe478 (diff)
downloadbcm5719-llvm-97c01c35f8da48b47c397fd915a82bd1d881d4ab.tar.gz
bcm5719-llvm-97c01c35f8da48b47c397fd915a82bd1d881d4ab.zip
[CUDA] Do not allow dynamic initialization of global device side variables.
In general CUDA does not allow dynamic initialization of global device-side variables. One exception is that CUDA allows records with empty constructors as described in section E2.2.1 of CUDA 7.5 Programming guide. This patch applies initializer checks for all device-side variables. Empty constructors are accepted, but no code is generated for them. Differential Revision: http://reviews.llvm.org/D15305 llvm-svn: 259592
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp32
1 files changed, 32 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 5db2c374aed..ffd71e38c6c 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -10223,6 +10223,38 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
}
}
+ // Perform check for initializers of device-side global variables.
+ // CUDA allows empty constructors as initializers (see E.2.3.1, CUDA
+ // 7.5). CUDA also allows constant initializers for __constant__ and
+ // __device__ variables.
+ if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) {
+ const Expr *Init = VD->getInit();
+ const bool IsGlobal = VD->hasGlobalStorage() && !VD->isStaticLocal();
+ if (Init && IsGlobal &&
+ (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>() ||
+ VD->hasAttr<CUDASharedAttr>())) {
+ bool AllowedInit = false;
+ if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(Init))
+ AllowedInit =
+ isEmptyCudaConstructor(VD->getLocation(), CE->getConstructor());
+ // We'll allow constant initializers even if it's a non-empty
+ // constructor according to CUDA rules. This deviates from NVCC,
+ // but allows us to handle things like constexpr constructors.
+ if (!AllowedInit &&
+ (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>()))
+ AllowedInit = VD->getInit()->isConstantInitializer(
+ Context, VD->getType()->isReferenceType());
+
+ if (!AllowedInit) {
+ Diag(VD->getLocation(), VD->hasAttr<CUDASharedAttr>()
+ ? diag::err_shared_var_init
+ : diag::err_dynamic_var_init)
+ << Init->getSourceRange();
+ VD->setInvalidDecl();
+ }
+ }
+ }
+
// Grab the dllimport or dllexport attribute off of the VarDecl.
const InheritableAttr *DLLAttr = getDLLAttr(VD);
OpenPOWER on IntegriCloud