diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -2279,7 +2279,7 @@ /// ExprError(). static ExprResult checkArraySize(Sema &S, Expr *&ArraySize, llvm::APSInt &SizeVal, unsigned VLADiag, - bool VLAIsError) { + bool VLAIsError, Sema::AllowFoldKind CanFold) { if (S.getLangOpts().CPlusPlus14 && (VLAIsError || !ArraySize->getType()->isIntegralOrUnscopedEnumerationType())) { @@ -2323,8 +2323,8 @@ } } Diagnoser(VLADiag, VLAIsError); - ExprResult R = - S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser); + ExprResult R = S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, + Diagnoser, CanFold); if (Diagnoser.IsVLA) return ExprResult(); return R; @@ -2442,10 +2442,20 @@ // VLAs always produce at least a -Wvla diagnostic, sometimes an error. unsigned VLADiag; bool VLAIsError; + AllowFoldKind CanFold = Sema::NoFold; if (getLangOpts().OpenCL) { // OpenCL v1.2 s6.9.d: variable length arrays are not supported. VLADiag = diag::err_opencl_vla; VLAIsError = true; + } else if (Context.getTargetInfo().getTriple().isBPF()) { + // BPF target does not support variable length array, but + // we don't force an error here. We will try to do constant + // folding for array size as much as possible. LLVM backend + // will do some checking and warn users if variable length + // array still remains. + VLADiag = diag::warn_vla_used; + VLAIsError = false; + CanFold = Sema::AllowFold; } else if (getLangOpts().C99) { VLADiag = diag::warn_vla_used; VLAIsError = false; @@ -2471,8 +2481,8 @@ } else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) { T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets); } else { - ExprResult R = - checkArraySize(*this, ArraySize, ConstVal, VLADiag, VLAIsError); + ExprResult R = checkArraySize(*this, ArraySize, ConstVal, VLADiag, + VLAIsError, CanFold); if (R.isInvalid()) return QualType(); diff --git a/clang/test/CodeGen/bpf-vla.c b/clang/test/CodeGen/bpf-vla.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/bpf-vla.c @@ -0,0 +1,29 @@ +// REQUIRES: bpf-registered-target +// RUN: %clang -target bpf -emit-llvm -S -g %s -o - | FileCheck %s + +#define AA 40 +struct t { + char a[20]; +}; +void foo(void *); +int test() { + const int a = 8; + char tmp[AA + sizeof(struct t) + a]; + +// CHECK: define dso_local i32 @test( +// CHECK: %tmp = alloca [68 x i8], align 1 +// CHECK-NOT: llvm.stacksave + + foo(tmp); + return 0; +} + +int test2(int b) { + const int a = 8; + char tmp[a + b]; + +// CHECK: define dso_local i32 @test2( +// CHECK: llvm.stacksave + foo(tmp); + return 0; +} diff --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h --- a/llvm/include/llvm/ADT/Triple.h +++ b/llvm/include/llvm/ADT/Triple.h @@ -738,6 +738,11 @@ : PointerWidth == 64; } + /// Tests whether the target is BPF (little and big endian). + bool isBPF() const { + return getArch() == Triple::bpfel || getArch() == Triple::bpfeb; + } + /// Tests whether the target is MIPS 32-bit (little and big endian). bool isMIPS32() const { return getArch() == Triple::mips || getArch() == Triple::mipsel;