[cfe-commits] r39587 - in /cfe/cfe/trunk: AST/Expr.cpp Sema/Sema.h Sema/SemaDecl.cpp include/clang/Basic/DiagnosticKinds.def

clattner at cs.uiuc.edu clattner at cs.uiuc.edu
Wed Jul 11 09:45:58 PDT 2007


Author: clattner
Date: Wed Jul 11 11:45:58 2007
New Revision: 39587

URL: http://llvm.org/viewvc/llvm-project?rev=39587&view=rev
Log:
Rename Sema::isConstantArrayType -> VerifyConstantArrayType.  Make sure to
check canonical types in a few places.  Tighten up VerifyConstantArrayType
to diagnose more errors, now that we can evaluate i-c-e's.  Add some fixmes
about poor diagnostics.

We now correctly typecheck this example:

void s(void) {
  typedef int a[(int) +1.0];
  static a b;    // invalid, static VLA

  static int c[(int) +1.0];  // invalid, static VLA
}

void t(void) {
  typedef int a[(int)1.0];
  static a b;    // valid, constant size
}

void u() {
  static int X[-1];
  static int Y[0];
}

producing:

static-vla.c:3:12: error: variable length array declared outside of any function
  static a b;    // invalid, static VLA
           ^
static-vla.c:5:14: error: variable length array declared outside of any function
  static int c[(int) +1.0];  // invalid, static VLA
             ^ ~~~~~~~~~~
static-vla.c:15:14: error: array size is negative
  static int X[-1];
             ^ ~~
static-vla.c:16:14: warning: zero size arrays are an extension
  static int Y[0];
             ^ ~

Modified:
    cfe/cfe/trunk/AST/Expr.cpp
    cfe/cfe/trunk/Sema/Sema.h
    cfe/cfe/trunk/Sema/SemaDecl.cpp
    cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def

Modified: cfe/cfe/trunk/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/AST/Expr.cpp?rev=39587&r1=39586&r2=39587&view=diff

==============================================================================
--- cfe/cfe/trunk/AST/Expr.cpp (original)
+++ cfe/cfe/trunk/AST/Expr.cpp Wed Jul 11 11:45:58 2007
@@ -410,7 +410,7 @@
       Result = (int)FL->getValue();
       break;
     }
-    if (Loc) *Loc = getLocStart();
+    if (Loc) *Loc = Operand->getLocStart();
     return false;
   }
   case ConditionalOperatorClass: {

Modified: cfe/cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/Sema.h?rev=39587&r1=39586&r2=39587&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/Sema.h (original)
+++ cfe/cfe/trunk/Sema/Sema.h Wed Jul 11 11:45:58 2007
@@ -331,9 +331,11 @@
   QualType CheckSizeOfAlignOfOperand(QualType type, SourceLocation loc, 
                                      bool isSizeof);
     
-  // C99: 6.7.5p3: Used by ParseDeclarator/ParseField to make sure we have
-  // a constant expression of type int with a value greater than zero.
-  bool isConstantArrayType(ArrayType *ary, SourceLocation loc); 
+  /// C99: 6.7.5p3: Used by ParseDeclarator/ParseField to make sure we have
+  /// a constant expression of type int with a value greater than zero.  If the
+  /// array has an incomplete type or a valid constant size, return false,
+  /// otherwise emit a diagnostic and return true.
+  bool VerifyConstantArrayType(const ArrayType *ary, SourceLocation loc); 
 };
 
 

Modified: cfe/cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/Sema/SemaDecl.cpp?rev=39587&r1=39586&r2=39587&view=diff

==============================================================================
--- cfe/cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/cfe/trunk/Sema/SemaDecl.cpp Wed Jul 11 11:45:58 2007
@@ -30,23 +30,47 @@
 
 // C99: 6.7.5p3: Used by ParseDeclarator/ParseField to make sure we have
 // a constant expression of type int with a value greater than zero.
-bool Sema::isConstantArrayType(ArrayType *ary, SourceLocation loc) { 
-  if (Expr *size = ary->getSize()) {
-    SourceLocation expLoc;
-    if (!size->isIntegerConstantExpr(&expLoc)) {
-      Diag(expLoc, diag::err_typecheck_illegal_vla);
-      return false;
-    }
-    if (!size->getType()->isIntegerType()) {
-      Diag(size->getLocStart(), diag::err_array_size_non_int, 
-           size->getType().getAsString());
-      return false;
-    }
-    // We have a constant expression with an integer type, now make sure 
-    // value greater than zero (C99 6.7.5.2p1).
-    // FIXME: evaluate constant expression.
+bool Sema::VerifyConstantArrayType(const ArrayType *Array,
+                                   SourceLocation DeclLoc) { 
+  const Expr *Size = Array->getSize();
+  if (Size == 0) return false;  // incomplete type.
+  
+  if (!Size->getType()->isIntegerType()) {
+    Diag(Size->getLocStart(), diag::err_array_size_non_int, 
+         Size->getType().getAsString(), Size->getSourceRange());
+    return true;
+  }
+
+  // Verify that the size of the array is an integer constant expr.
+  SourceLocation Loc;
+  APSInt SizeVal(32);
+  if (!Size->isIntegerConstantExpr(SizeVal, &Loc)) {
+    // FIXME: This emits the diagnostic to enforce 6.7.2.1p8, but the message
+    // is wrong.  It is also wrong for static variables.
+    Diag(DeclLoc, diag::err_typecheck_illegal_vla, Size->getSourceRange());
+    return true;
+  }
+  
+  // We have a constant expression with an integer type, now make sure 
+  // value greater than zero (C99 6.7.5.2p1).
+  
+  // FIXME: This check isn't specific to static VLAs, this should be moved
+  // elsewhere or replicated.  'int X[-1];' inside a function should emit an
+  // error.
+  if (SizeVal.isSigned()) {
+    APSInt Zero(SizeVal.getBitWidth());
+    Zero.setIsUnsigned(false);
+    if (SizeVal < Zero) {
+      Diag(DeclLoc, diag::err_typecheck_negative_array_size,
+           Size->getSourceRange());
+      return true;
+    } else if (SizeVal == 0) {
+      // GCC accepts zero sized static arrays.
+      Diag(DeclLoc, diag::err_typecheck_zero_array_size, 
+           Size->getSourceRange());
+    }
   }
-  return true;
+  return false;
 }
 
 Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const {
@@ -272,7 +296,7 @@
       // C99 6.7.7p2: If a typedef name specifies a variably modified type
       // then it shall have block scope.
       if (ArrayType *ary = dyn_cast<ArrayType>(NewTD->getUnderlyingType())) {
-        if (!isConstantArrayType(ary, D.getIdentifierLoc()))
+        if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
           return 0;
       }
     }
@@ -340,8 +364,8 @@
       }
       // C99 6.7.5.2p2: If an identifier is declared to be an object with 
       // static storage duration, it shall not have a variable length array.
-      if (ArrayType *ary = dyn_cast<ArrayType>(R)) {
-        if (!isConstantArrayType(ary, D.getIdentifierLoc()))
+      if (ArrayType *ary = dyn_cast<ArrayType>(R.getCanonicalType())) {
+        if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
           return 0;
       }
       NewVD = new FileVarDecl(D.getIdentifierLoc(), II, R, SC);
@@ -358,8 +382,8 @@
       if (SC == VarDecl::Static) {
         // C99 6.7.5.2p2: If an identifier is declared to be an object with 
         // static storage duration, it shall not have a variable length array.
-        if (ArrayType *ary = dyn_cast<ArrayType>(R)) {
-          if (!isConstantArrayType(ary, D.getIdentifierLoc()))
+        if (ArrayType *ary = dyn_cast<ArrayType>(R.getCanonicalType())) {
+          if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
             return 0;
         }
       }
@@ -669,8 +693,8 @@
   
   // C99 6.7.2.1p8: A member of a structure or union may have any type other
   // than a variably modified type.
-  if (ArrayType *ary = dyn_cast<ArrayType>(T)) {
-    if (!isConstantArrayType(ary, Loc))
+  if (ArrayType *ary = dyn_cast<ArrayType>(T.getCanonicalType())) {
+    if (VerifyConstantArrayType(ary, Loc))
       return 0;
   }
   return new FieldDecl(Loc, II, T);
@@ -807,6 +831,7 @@
   }
   SourceLocation expLoc;
   // C99 6.7.2.2p2: Make sure we have an integer constant expression.
+  // FIXME: Capture this value in the enumconstantdecl.
   if (Val && !((Expr *)Val)->isIntegerConstantExpr(&expLoc)) {
     Diag(expLoc, diag::err_enum_value_not_integer_constant_expr, Id->getName());
     return 0;

Modified: cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=39587&r1=39586&r2=39587&view=diff

==============================================================================
--- cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/cfe/trunk/include/clang/Basic/DiagnosticKinds.def Wed Jul 11 11:45:58 2007
@@ -469,6 +469,10 @@
      "case label does not reduce to an integer constant")
 DIAG(err_typecheck_illegal_vla, ERROR,
      "variable length array declared outside of any function")
+DIAG(err_typecheck_negative_array_size, ERROR,
+     "array size is negative")
+DIAG(err_typecheck_zero_array_size, EXTENSION,
+     "zero size arrays are an extension")
 DIAG(err_array_size_non_int, ERROR,
      "size of array has non-integer type '%0'")
 





More information about the cfe-commits mailing list