Skip to content

Commit

Permalink
[CUDA] Disallow variable-length arrays in CUDA device code.
Browse files Browse the repository at this point in the history
Reviewers: tra

Subscribers: cfe-commits, jhen

Differential Revision: https://reviews.llvm.org/D25050

llvm-svn: 282647
  • Loading branch information
Justin Lebar committed Sep 28, 2016
1 parent 2a8db34 commit b17840d
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 0 deletions.
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Expand Up @@ -6713,6 +6713,10 @@ def err_shared_var_init : Error<
def err_device_static_local_var : Error<
"Within a __device__/__global__ function, "
"only __shared__ variables may be marked \"static\"">;
def err_cuda_vla : Error<
"cannot use variable-length arrays in "
"%select{__device__|__global__|__host__|__host__ __device__}0 functions">;

def warn_non_pod_vararg_with_format_string : Warning<
"cannot pass %select{non-POD|non-trivial}0 object of type %1 to variadic "
"%select{function|block|method|constructor}2; expected type from format "
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/Sema/Sema.h
Expand Up @@ -9255,6 +9255,8 @@ class Sema {
/// ExprTy should be the string "try" or "throw", as appropriate.
bool CheckCUDAExceptionExpr(SourceLocation Loc, StringRef ExprTy);

bool CheckCUDAVLA(SourceLocation Loc);

/// Finds a function in \p Matches with highest calling priority
/// from \p Caller context and erases all functions with lower
/// calling priority.
Expand Down
20 changes: 20 additions & 0 deletions clang/lib/Sema/SemaCUDA.cpp
Expand Up @@ -539,3 +539,23 @@ bool Sema::CheckCUDAExceptionExpr(SourceLocation Loc, StringRef ExprTy) {
}
return true;
}

bool Sema::CheckCUDAVLA(SourceLocation Loc) {
assert(getLangOpts().CUDA && "Should only be called during CUDA compilation");
FunctionDecl *CurFn = dyn_cast<FunctionDecl>(CurContext);
if (!CurFn)
return true;
CUDAFunctionTarget Target = IdentifyCUDATarget(CurFn);
if (Target == CFT_Global || Target == CFT_Device) {
Diag(Loc, diag::err_cuda_vla) << Target;
return false;
}
if (Target == CFT_HostDevice && getLangOpts().CUDAIsDevice) {
PartialDiagnostic ErrPD{PartialDiagnostic::NullDiagnostic()};
ErrPD.Reset(diag::err_cuda_vla);
ErrPD << Target;
CurFn->addDeferredDiag({Loc, std::move(ErrPD)});
return false;
}
return true;
}
4 changes: 4 additions & 0 deletions clang/lib/Sema/SemaType.cpp
Expand Up @@ -2241,6 +2241,10 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
Diag(Loc, diag::err_opencl_vla);
return QualType();
}
// CUDA device code doesn't support VLAs.
if (getLangOpts().CUDA && T->isVariableArrayType() && !CheckCUDAVLA(Loc))
return QualType();

// If this is not C99, extwarn about VLA's and C99 array size modifiers.
if (!getLangOpts().C99) {
if (T->isVariableArrayType()) {
Expand Down
21 changes: 21 additions & 0 deletions clang/test/SemaCUDA/vla-host-device.cu
@@ -0,0 +1,21 @@
// RUN: %clang_cc1 -fcuda-is-device -verify -S %s -o /dev/null
// RUN: %clang_cc1 -verify -DHOST %s -S -o /dev/null

#include "Inputs/cuda.h"

#ifdef HOST
// expected-no-diagnostics
#endif

__host__ __device__ void hd(int n) {
int x[n];
#ifndef HOST
// expected-error@-2 {{cannot use variable-length arrays in __host__ __device__ functions}}
#endif
}

// No error because never codegen'ed for device.
__host__ __device__ inline void hd_inline(int n) {
int x[n];
}
void call_hd_inline() { hd_inline(42); }
12 changes: 12 additions & 0 deletions clang/test/SemaCUDA/vla.cu
@@ -0,0 +1,12 @@
// RUN: %clang_cc1 -fcuda-is-device -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -verify -DHOST %s

#include "Inputs/cuda.h"

void host(int n) {
int x[n];
}

__device__ void device(int n) {
int x[n]; // expected-error {{cannot use variable-length arrays in __device__ functions}}
}

0 comments on commit b17840d

Please sign in to comment.