]> granicus.if.org Git - clang/commitdiff
Emit the correct diagnostics when we constant fold an array size to a negative value.
authorAnders Carlsson <andersca@mac.com>
Thu, 19 Feb 2009 06:30:50 +0000 (06:30 +0000)
committerAnders Carlsson <andersca@mac.com>
Thu, 19 Feb 2009 06:30:50 +0000 (06:30 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65023 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDecl.cpp
test/Sema/const-eval.c

index 294be70488263a73b5fe6bc6668e5e201673fef0..f3eb201fa2224c02b2697d4fb31043247c61337b 100644 (file)
@@ -3397,11 +3397,14 @@ void Sema::ActOnTagFinishDefinition(Scope *S, DeclTy *TagD) {
 /// types into constant array types in certain situations which would otherwise
 /// be errors (for GCC compatibility).
 static QualType TryToFixInvalidVariablyModifiedType(QualType T,
-                                                    ASTContext &Context) {
+                                                    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();
   
@@ -3415,6 +3418,8 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,
   if (Res >= llvm::APSInt(Res.getBitWidth(), Res.isUnsigned()))
     return Context.getConstantArrayType(VLATy->getElementType(),
                                         Res, ArrayType::Normal, 0);
+
+  SizeIsNegative = true;
   return QualType();
 }
 
@@ -3463,12 +3468,17 @@ 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()) {
-    QualType FixedTy = TryToFixInvalidVariablyModifiedType(T, Context);
+    bool SizeIsNegative;
+    QualType FixedTy = TryToFixInvalidVariablyModifiedType(T, Context,
+                                                           SizeIsNegative);
     if (!FixedTy.isNull()) {
       Diag(Loc, diag::warn_illegal_constant_array_size);
       T = FixedTy;
     } else {
-      Diag(Loc, diag::err_typecheck_field_variable_size);
+      if (SizeIsNegative)
+        Diag(Loc, diag::err_typecheck_negative_array_size);
+      else
+        Diag(Loc, diag::err_typecheck_field_variable_size);
       T = Context.IntTy;
       InvalidDecl = true;
     }
index 4fd2a558519d470801ddff53c2035197c508f5c7..af785e4bddb990336eaf55a0d0618d8a2938b310 100644 (file)
@@ -34,3 +34,7 @@ _Complex float g16 = (1.0f + 1.0fi);
 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}}
+};