forked from OSchip/llvm-project
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:
parent
6ef6a04dd6
commit
c4c6031859
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}}
|
||||
|
|
Loading…
Reference in New Issue