Always try to fold array sizes, and warn if we could fold something that isn't an ICE. This makes us compatible with GCC.

llvm-svn: 65140
This commit is contained in:
Anders Carlsson 2009-02-20 18:53:20 +00:00
parent 6ef6a04dd6
commit c4c6031859
3 changed files with 17 additions and 48 deletions

View File

@ -3398,36 +3398,6 @@ void Sema::ActOnTagFinishDefinition(Scope *S, DeclTy *TagD) {
Consumer.HandleTagDeclDefinition(Tag);
}
/// TryToFixInvalidVariablyModifiedType - Helper method to turn variable array
/// types into constant array types in certain situations which would otherwise
/// be errors (for GCC compatibility).
static QualType TryToFixInvalidVariablyModifiedType(QualType T,
ASTContext &Context,
bool &SizeIsNegative) {
// This method tries to turn a variable array into a constant
// array even when the size isn't an ICE. This is necessary
// for compatibility with code that depends on gcc's buggy
// constant expression folding, like struct {char x[(int)(char*)2];}
SizeIsNegative = false;
const VariableArrayType* VLATy = dyn_cast<VariableArrayType>(T);
if (!VLATy) return QualType();
Expr::EvalResult EvalResult;
if (!VLATy->getSizeExpr() ||
!VLATy->getSizeExpr()->Evaluate(EvalResult, Context))
return QualType();
assert(EvalResult.Val.isInt() && "Size expressions must be integers!");
llvm::APSInt &Res = EvalResult.Val.getInt();
if (Res >= llvm::APSInt(Res.getBitWidth(), Res.isUnsigned()))
return Context.getConstantArrayType(VLATy->getElementType(),
Res, ArrayType::Normal, 0);
SizeIsNegative = true;
return QualType();
}
bool Sema::VerifyBitField(SourceLocation FieldLoc, IdentifierInfo *FieldName,
QualType FieldTy, const Expr *BitWidth) {
// FIXME: 6.7.2.1p4 - verify the field type.
@ -3473,20 +3443,9 @@ Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagD,
// C99 6.7.2.1p8: A member of a structure or union may have any type other
// than a variably modified type.
if (T->isVariablyModifiedType()) {
bool SizeIsNegative;
QualType FixedTy = TryToFixInvalidVariablyModifiedType(T, Context,
SizeIsNegative);
if (!FixedTy.isNull()) {
Diag(Loc, diag::warn_illegal_constant_array_size);
T = FixedTy;
} else {
if (SizeIsNegative)
Diag(Loc, diag::err_typecheck_negative_array_size);
else
Diag(Loc, diag::err_typecheck_field_variable_size);
T = Context.IntTy;
InvalidDecl = true;
}
Diag(Loc, diag::err_typecheck_field_variable_size);
T = Context.IntTy;
InvalidDecl = true;
}
if (BitWidth) {

View File

@ -423,17 +423,26 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
ArraySize->Destroy(Context);
ATI.NumElts = ArraySize = 0;
}
llvm::APSInt ConstVal(32);
Expr::EvalResult Result;
if (!ArraySize) {
T = Context.getIncompleteArrayType(T, ASM, ATI.TypeQuals);
} else if (ArraySize->isValueDependent()) {
T = Context.getDependentSizedArrayType(T, ArraySize, ASM, ATI.TypeQuals);
} else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context) ||
} else if (!ArraySize->Evaluate(Result, Context) ||
!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
T = Context.getVariableArrayType(T, ArraySize, ASM, ATI.TypeQuals);
} else {
const llvm::APSInt& ConstVal = Result.Val.getInt();
// FIXME: We should really use Result.Diag here - which is supposed
// to be nonzero if we have a foldable expression that is not an ICE
// but for now we'll just warn if the array size is not an ICE.
if (!ArraySize->isIntegerConstantExpr(Context))
Diag(ArraySize->getLocStart(),
diag::warn_illegal_constant_array_size);
// C99 6.7.5.2p1: If the expression is a constant expression, it shall
// have a value greater than zero.
if (ConstVal.isSigned()) {
@ -444,7 +453,8 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
D.setInvalidType(true);
} else if (ConstVal == 0) {
// GCC accepts zero sized static arrays.
Diag(ArraySize->getLocStart(), diag::ext_typecheck_zero_array_size)
Diag(ArraySize->getLocStart(),
diag::ext_typecheck_zero_array_size)
<< ArraySize->getSourceRange();
}
}

View File

@ -1,3 +1,3 @@
// RUN: clang %s -verify -fsyntax-only -pedantic
typedef int (*a)[!.0]; // expected-error{{variably modified type declaration not allowed at file scope}}
typedef int (*a)[!.0]; // expected-warning{{size of static array must be an integer constant expression}}