diff options
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); |