diff options
author | Artem Belevich <tra@google.com> | 2016-02-02 22:29:48 +0000 |
---|---|---|
committer | Artem Belevich <tra@google.com> | 2016-02-02 22:29:48 +0000 |
commit | 97c01c35f8da48b47c397fd915a82bd1d881d4ab (patch) | |
tree | 06d8b1e2ae200287569e9ad71bdaa548e5ef75d6 /clang/lib/Sema/SemaDecl.cpp | |
parent | 8abc2e51b81efe2f540f6a61a3028f8fe72fe478 (diff) | |
download | bcm5719-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.cpp | 32 |
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); |