From: Anders Carlsson Date: Fri, 20 Feb 2009 18:53:20 +0000 (+0000) Subject: Always try to fold array sizes, and warn if we could fold something that isn't an... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=540b146d013b3b6d5ab7c485b9e692a866173e15;p=clang Always try to fold array sizes, and warn if we could fold something that isn't an ICE. This makes us compatible with GCC. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65140 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 08b5a8c2ab..b69453d447 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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(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) { diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 252cd2d533..8727fbcd8c 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -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(); } } diff --git a/test/Sema/typedef-variable-type.c b/test/Sema/typedef-variable-type.c index e982637feb..703792fcdc 100644 --- a/test/Sema/typedef-variable-type.c +++ b/test/Sema/typedef-variable-type.c @@ -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}}