forked from OSchip/llvm-project
when compiling in a GNU mode (e.g. gnu99) treat VLAs with a size that can be folded to a constant
as constant size arrays. This has slightly different semantics in some insane cases, but allows us to accept some constructs that GCC does. Continue to be pedantic in -std=c99 and other modes. This addressed rdar://8733881 - error "variable-sized object may not be initialized"; g++ accepts same code llvm-svn: 132983
This commit is contained in:
parent
b5f19d9f6f
commit
f35de48c90
|
@ -48,6 +48,8 @@ def err_vla_decl_has_static_storage : Error<
|
|||
"variable length array declaration can not have 'static' storage duration">;
|
||||
def err_vla_decl_has_extern_linkage : Error<
|
||||
"variable length array declaration can not have 'extern' linkage">;
|
||||
def ext_vla_folded_to_constant : Extension<
|
||||
"variable length array folded to constant array as an extension">;
|
||||
|
||||
// C99 variably modified types
|
||||
def err_variably_modified_template_arg : Error<
|
||||
|
|
|
@ -1100,6 +1100,28 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
|
|||
return Context.getRValueReferenceType(T);
|
||||
}
|
||||
|
||||
/// Check whether the specified array size makes the array type a VLA. If so,
|
||||
/// return true, if not, return the size of the array in SizeVal.
|
||||
static bool isArraySizeVLA(Expr *ArraySize, llvm::APSInt &SizeVal, Sema &S) {
|
||||
// If the size is an ICE, it certainly isn't a VLA.
|
||||
if (ArraySize->isIntegerConstantExpr(SizeVal, S.Context))
|
||||
return false;
|
||||
|
||||
// If we're in a GNU mode (like gnu99, but not c99) accept any evaluatable
|
||||
// value as an extension.
|
||||
Expr::EvalResult Result;
|
||||
if (S.LangOpts.GNUMode && ArraySize->Evaluate(Result, S.Context)) {
|
||||
if (!Result.hasSideEffects() && Result.Val.isInt()) {
|
||||
SizeVal = Result.Val.getInt();
|
||||
S.Diag(ArraySize->getLocStart(), diag::ext_vla_folded_to_constant);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// \brief Build an array type.
|
||||
///
|
||||
/// \param T The type of each element in the array.
|
||||
|
@ -1200,11 +1222,13 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
|
|||
T = Context.getIncompleteArrayType(T, ASM, Quals);
|
||||
} else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) {
|
||||
T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets);
|
||||
} else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) ||
|
||||
(!T->isDependentType() && !T->isIncompleteType() &&
|
||||
!T->isConstantSizeType())) {
|
||||
// Per C99, a variable array is an array with either a non-constant
|
||||
// size or an element type that has a non-constant-size
|
||||
} else if (!T->isDependentType() && !T->isIncompleteType() &&
|
||||
!T->isConstantSizeType()) {
|
||||
// C99: an array with an element type that has a non-constant-size is a VLA.
|
||||
T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
|
||||
} else if (isArraySizeVLA(ArraySize, ConstVal, *this)) {
|
||||
// C99: an array with a non-ICE size is a VLA. We accept any expression
|
||||
// that we can fold to a non-zero positive value as an extension.
|
||||
T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
|
||||
} else {
|
||||
// C99 6.7.5.2p1: If the expression is a constant expression, it shall
|
||||
|
|
|
@ -36,7 +36,7 @@ int g17[(3?:1) - 2];
|
|||
EVAL_EXPR(18, ((int)((void*)10 + 10)) == 20 ? 1 : -1);
|
||||
|
||||
struct s {
|
||||
int a[(int)-1.0f]; // expected-error {{array size is negative}}
|
||||
int a[(int)-1.0f]; // expected-error {{'a' declared as an array with a negative size}}
|
||||
};
|
||||
|
||||
EVAL_EXPR(19, ((int)&*(char*)10 == 10 ? 1 : -1));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang %s -ffreestanding -fsyntax-only -Xclang -verify -pedantic -fpascal-strings
|
||||
// RUN: %clang %s -ffreestanding -fsyntax-only -Xclang -verify -pedantic -fpascal-strings -std=c99
|
||||
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
|
|
@ -6,7 +6,7 @@ struct bar {
|
|||
|
||||
struct foo {
|
||||
char name[(int)&((struct bar *)0)->n];
|
||||
char name2[(int)&((struct bar *)0)->n - 1]; //expected-error{{array size is negative}}
|
||||
char name2[(int)&((struct bar *)0)->n - 1]; //expected-error{{'name2' declared as an array with a negative size}}
|
||||
};
|
||||
|
||||
// PR3430
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// RUN: %clang_cc1 %s -verify -fsyntax-only -pedantic -Wno-typedef-redefinition
|
||||
// RUN: %clang_cc1 %s -verify -fsyntax-only -pedantic -Wno-typedef-redefinition -std=c99
|
||||
|
||||
// Make sure we accept a single typedef
|
||||
typedef int (*a)[!.0]; // expected-warning{{size of static array must be an integer constant expression}}
|
||||
|
|
|
@ -42,7 +42,7 @@ void f3()
|
|||
}
|
||||
|
||||
// PR3663
|
||||
static const unsigned array[((2 * (int)((((4) / 2) + 1.0/3.0) * (4) - 1e-8)) + 1)]; // expected-warning {{size of static array must be an integer constant expression}}
|
||||
static const unsigned array[((2 * (int)((((4) / 2) + 1.0/3.0) * (4) - 1e-8)) + 1)]; // expected-warning {{variable length array folded to constant array as an extension}}
|
||||
|
||||
int a[*]; // expected-error {{star modifier used outside of function prototype}}
|
||||
int f4(int a[*][*]);
|
||||
|
@ -53,7 +53,7 @@ int pr2044b;
|
|||
int (*pr2044c(void))[pr2044b]; // expected-error {{variably modified type}}
|
||||
|
||||
const int f5_ci = 1;
|
||||
void f5() { char a[][f5_ci] = {""}; } // expected-error {{variable-sized object may not be initialized}}
|
||||
void f5() { char a[][f5_ci] = {""}; } // expected-warning {{variable length array folded to constant array as an extension}}
|
||||
|
||||
// PR5185
|
||||
void pr5185(int a[*]);
|
||||
|
|
|
@ -121,3 +121,12 @@ namespace PR8209 {
|
|||
(void)new vla_type; // expected-error{{variably}}
|
||||
}
|
||||
}
|
||||
|
||||
namespace rdar8733881 { // rdar://8733881
|
||||
|
||||
static const int k_cVal3 = (int)(1000*0.2f);
|
||||
int f() {
|
||||
// Ok, fold to a constant size array as an extension.
|
||||
char rgch[k_cVal3] = {0};
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue