[clang] [CUDA] Disallow use of address_space(N) on CUDA device variables. (PR #142857)
Artem Belevich via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 4 14:25:49 PDT 2025
https://github.com/Artem-B created https://github.com/llvm/llvm-project/pull/142857
The variables have implicit host-side shadow instances and explicit address space attribute breaks them on the host.
>From e2e8da0271ae11711dbd54f6e8d9ff498f3226d4 Mon Sep 17 00:00:00 2001
From: Artem Belevich <tra at google.com>
Date: Tue, 27 May 2025 17:09:01 -0700
Subject: [PATCH] [CUDA] Disallow use of address_space(N) on CUDA device
variables.
The variables have implicit host-side shadow instances and explicit address space attribute breaks them on the host.
---
.../include/clang/Basic/DiagnosticSemaKinds.td | 2 ++
clang/lib/Sema/SemaCUDA.cpp | 17 +++++++++++------
clang/test/SemaCUDA/bad-attributes.cu | 8 ++++++++
3 files changed, 21 insertions(+), 6 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 78b36ceb88125..3862454ed2ee9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9388,6 +9388,8 @@ def err_cuda_host_shared : Error<
"%select{__device__|__global__|__host__|__host__ __device__}0 functions">;
def err_cuda_nonstatic_constdev: Error<"__constant__, __device__, and "
"__managed__ are not allowed on non-static local variables">;
+def err_cuda_address_space_gpuvar: Error<"__constant__, __device__, and "
+ "__shared__ variables must use default address space">;
def err_cuda_grid_constant_not_allowed : Error<
"__grid_constant__ is only allowed on const-qualified kernel parameters">;
def err_cuda_ovl_target : Error<
diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp
index 176d9322d3d2a..67e7a2ed61db9 100644
--- a/clang/lib/Sema/SemaCUDA.cpp
+++ b/clang/lib/Sema/SemaCUDA.cpp
@@ -322,7 +322,7 @@ void SemaCUDA::EraseUnwantedMatches(
if (Matches.size() <= 1)
return;
- using Pair = std::pair<DeclAccessPair, FunctionDecl*>;
+ using Pair = std::pair<DeclAccessPair, FunctionDecl *>;
// Gets the CUDA function preference for a call from Caller to Match.
auto GetCFP = [&](const Pair &Match) {
@@ -505,7 +505,6 @@ bool SemaCUDA::inferTargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl,
}
}
-
// If no target was inferred, mark this member as __host__ __device__;
// it's the least restrictive option that can be invoked from any target.
bool NeedsH = true, NeedsD = true;
@@ -680,16 +679,22 @@ void SemaCUDA::checkAllowedInitializer(VarDecl *VD) {
FD && FD->isDependentContext())
return;
+ bool IsSharedVar = VD->hasAttr<CUDASharedAttr>();
+ bool IsDeviceOrConstantVar =
+ !IsSharedVar &&
+ (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>());
+ if ((IsSharedVar || IsDeviceOrConstantVar) &&
+ VD->getType().getQualifiers().getAddressSpace() != LangAS::Default) {
+ Diag(VD->getLocation(), diag::err_cuda_address_space_gpuvar);
+ VD->setInvalidDecl();
+ return;
+ }
// Do not check dependent variables since the ctor/dtor/initializer are not
// determined. Do it after instantiation.
if (VD->isInvalidDecl() || !VD->hasInit() || !VD->hasGlobalStorage() ||
IsDependentVar(VD))
return;
const Expr *Init = VD->getInit();
- bool IsSharedVar = VD->hasAttr<CUDASharedAttr>();
- bool IsDeviceOrConstantVar =
- !IsSharedVar &&
- (VD->hasAttr<CUDADeviceAttr>() || VD->hasAttr<CUDAConstantAttr>());
if (IsDeviceOrConstantVar || IsSharedVar) {
if (HasAllowedCUDADeviceStaticInitializer(
*this, VD, IsSharedVar ? CICK_Shared : CICK_DeviceOrConstant))
diff --git a/clang/test/SemaCUDA/bad-attributes.cu b/clang/test/SemaCUDA/bad-attributes.cu
index 8ac6fa1ab5c2d..acb2f38a75282 100644
--- a/clang/test/SemaCUDA/bad-attributes.cu
+++ b/clang/test/SemaCUDA/bad-attributes.cu
@@ -50,6 +50,14 @@ __global__ __device__ void z11(); // expected-error {{attributes are not compat
__global__ __host__ void z12(); // expected-error {{attributes are not compatible}}
// expected-note at -1 {{conflicting attribute is here}}
+// Make sure GPU-side variables do not allow __attribute((address_space(N)))
+// expected-error at +1 {{__constant__, __device__, and __shared__ variables must use default address space}}
+__shared__ __attribute__((address_space(999))) int as_s;
+// expected-error at +1 {{__constant__, __device__, and __shared__ variables must use default address space}}
+__device__ __attribute__((address_space(999))) int as_d;
+// expected-error at +1 {{__constant__, __device__, and __shared__ variables must use default address space}}
+__constant__ __attribute__((address_space(999))) int as_c;
+
struct S {
__global__ void foo() {}; // expected-error {{must be a free function or static member function}}
__global__ static void bar(); // expected-warning {{kernel function 'bar' is a member function}}
More information about the cfe-commits
mailing list