[cfe-commits] r41647 - in /cfe/trunk: AST/Type.cpp Sema/Sema.h Sema/SemaDecl.cpp include/clang/AST/Type.h test/Sema/array-constraint.c

Steve Naroff snaroff at apple.com
Fri Aug 31 10:20:08 PDT 2007


Author: snaroff
Date: Fri Aug 31 12:20:07 2007
New Revision: 41647

URL: http://llvm.org/viewvc/llvm-project?rev=41647&view=rev
Log:

Removed Sema::VerifyConstantArrayType(). With the new Array/ConstantArray/VariableArray nodes, this
routine was causing more trouble than it was worth. Anders/Chris noticed that it could return an error code
without emiting a diagnostic (which results in an silent invalid decl, which should *never* happen). In addition,
this routine didn't work well for typedefs and field decls. Lastly, it didn't consider that initializers aren't
in place yet.

Added Type::getAsConstantArrayType(), Type::getAsVariableArrayType(), Type::getAsVariablyModifiedType(),
and Type::isVariablyModifiedType();

Modified Sema::ParseDeclarator() and Sema::ParseField() to use the new predicates. Also added a FIXME for
the initializer omission. Also added a missing test for "static" @ file scope.

Modified:
    cfe/trunk/AST/Type.cpp
    cfe/trunk/Sema/Sema.h
    cfe/trunk/Sema/SemaDecl.cpp
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/test/Sema/array-constraint.c

Modified: cfe/trunk/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Type.cpp?rev=41647&r1=41646&r2=41647&view=diff

==============================================================================
--- cfe/trunk/AST/Type.cpp (original)
+++ cfe/trunk/AST/Type.cpp Fri Aug 31 12:20:07 2007
@@ -125,7 +125,7 @@
 }
 
 const ArrayType *Type::getAsArrayType() const {
-  // If this is directly a reference type, return it.
+  // If this is directly an array type, return it.
   if (const ArrayType *ATy = dyn_cast<ArrayType>(this))
     return ATy;
   
@@ -136,6 +136,48 @@
   return 0;
 }
 
+const ConstantArrayType *Type::getAsConstantArrayType() const {
+  // If this is directly a constant array type, return it.
+  if (const ConstantArrayType *ATy = dyn_cast<ConstantArrayType>(this))
+    return ATy;
+  
+  // If this is a typedef for an array type, strip the typedef off without
+  // losing all typedef information.
+  if (isa<ConstantArrayType>(CanonicalType))
+    return cast<ConstantArrayType>(cast<TypedefType>(this)->LookThroughTypedefs());
+  return 0;
+}
+
+const VariableArrayType *Type::getAsVariableArrayType() const {
+  // If this is directly a variable array type, return it.
+  if (const VariableArrayType *ATy = dyn_cast<VariableArrayType>(this))
+    return ATy;
+  
+  // If this is a typedef for an array type, strip the typedef off without
+  // losing all typedef information.
+  if (isa<VariableArrayType>(CanonicalType))
+    return cast<VariableArrayType>(cast<TypedefType>(this)->LookThroughTypedefs());
+  return 0;
+}
+
+/// isVariablyModifiedType (C99 6.7.5.2p2) - Return true for variable array
+/// types that have a non-constant expression. This does not include "[]".
+bool Type::isVariablyModifiedType() const {
+  if (const VariableArrayType *VAT = getAsVariableArrayType()) {
+    if (VAT->getSizeExpr())
+      return true;
+  }
+  return false;
+}
+
+const VariableArrayType *Type::getAsVariablyModifiedType() const {
+  if (const VariableArrayType *VAT = getAsVariableArrayType()) {
+    if (VAT->getSizeExpr())
+      return VAT;
+  }
+  return 0;
+}
+
 const RecordType *Type::getAsRecordType() const {
   // If this is directly a reference type, return it.
   if (const RecordType *RTy = dyn_cast<RecordType>(this))

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

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Fri Aug 31 12:20:07 2007
@@ -439,12 +439,6 @@
   QualType CheckOCUVectorComponent(QualType baseType, SourceLocation OpLoc,
                                    IdentifierInfo &Comp, SourceLocation CmpLoc);
   
-  /// 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);
-  
   /// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have
   /// the specified width and sign.  If an overflow occurs, detect it and emit
   /// the specified diagnostic.

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

==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Fri Aug 31 12:20:07 2007
@@ -25,25 +25,6 @@
 #include "llvm/ADT/SmallSet.h"
 using namespace clang;
 
-// C99 6.7.2.1p8: Used by ParseDeclarator/ParseField to make sure we have
-// a constant expression. We return true if we don't have a ConstantArrayType. 
-bool Sema::VerifyConstantArrayType(const ArrayType *Array,
-                                   SourceLocation DeclLoc) { 
-  if (const VariableArrayType *VLA = dyn_cast<VariableArrayType>(Array)) {
-    Expr *Size = VLA->getSizeExpr();
-    if (Size) {  
-      // FIXME: This emits the diagnostic to enforce 6.7.2.1p8, but the message
-      // is wrong.  It is also wrong for static variables.
-      // FIXME: This is also wrong for:
-      // int sub1(int i, char *pi) { typedef int foo[i];
-      // struct bar {foo f1; int f2:3; int f3:4} *p; }
-      Diag(DeclLoc, diag::err_typecheck_illegal_vla, Size->getSourceRange());
-    }
-    return true;
-  }
-  return false;
-}
-
 Sema::DeclTy *Sema::isTypeName(const IdentifierInfo &II, Scope *S) const {
   return dyn_cast_or_null<TypedefDecl>(II.getFETokenInfo<Decl>());
 }
@@ -305,9 +286,11 @@
     if (S->getParent() == 0) {
       // 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 (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
-          InvalidDecl = true;
+      if (const VariableArrayType *VAT = 
+            NewTD->getUnderlyingType()->getAsVariablyModifiedType()) {
+        Diag(D.getIdentifierLoc(), diag::err_typecheck_illegal_vla, 
+             VAT->getSizeExpr()->getSourceRange());
+        InvalidDecl = true;
       }
     }
   } else if (D.isFunctionDeclarator()) {
@@ -377,11 +360,19 @@
              R.getAsString());
         InvalidDecl = true;
       }
-      // 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 (const ArrayType *ary = R->getAsArrayType()) {
-        if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
-          InvalidDecl = true;
+      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 (const VariableArrayType *VLA = R->getAsVariableArrayType()) {
+          Expr *Size = VLA->getSizeExpr();
+          if (Size || (!Size && !Init)) {  
+            // FIXME: Since we don't support initializers yet, we only emit this
+            // error when we don't have an initializer. Once initializers are 
+            // implemented, the VLA will change to a CLA.
+            Diag(D.getIdentifierLoc(), diag::err_typecheck_illegal_vla);
+            InvalidDecl = true;
+          }
+        }
       }
       NewVD = new FileVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator);
     } else { 
@@ -397,9 +388,15 @@
       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 (const ArrayType *ary = R->getAsArrayType()) {
-          if (VerifyConstantArrayType(ary, D.getIdentifierLoc()))
+        if (const VariableArrayType *VLA = R->getAsVariableArrayType()) {
+          Expr *Size = VLA->getSizeExpr();
+          if (Size || (!Size && !Init)) {  
+            // FIXME: Since we don't support initializers yet, we only emit this
+            // error when we don't have an initializer. Once initializers are 
+            // implemented, the VLA will change to a CLA.
+            Diag(D.getIdentifierLoc(), diag::err_typecheck_illegal_vla);
             InvalidDecl = true;
+          }
         }
       }
       NewVD = new BlockVarDecl(D.getIdentifierLoc(), II, R, SC, LastDeclarator);
@@ -779,14 +776,14 @@
   QualType T = GetTypeForDeclarator(D, S);
   assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
   bool InvalidDecl = false;
-  
+
   // C99 6.7.2.1p8: A member of a structure or union may have any type other
   // than a variably modified type.
-  if (const ArrayType *ary = T->getAsArrayType()) {
-    if (VerifyConstantArrayType(ary, Loc))
-      InvalidDecl = true;
+  if (const VariableArrayType *VAT = T->getAsVariablyModifiedType()) {
+    Diag(Loc, diag::err_typecheck_illegal_vla, 
+           VAT->getSizeExpr()->getSourceRange());
+    InvalidDecl = true;
   }
-  
   // FIXME: Chain fielddecls together.
   FieldDecl *NewFD = new FieldDecl(Loc, II, T, 0);
   if (D.getInvalidType() || InvalidDecl)

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=41647&r1=41646&r2=41647&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Fri Aug 31 12:20:07 2007
@@ -37,6 +37,8 @@
   class ReferenceType;
   class VectorType;
   class ArrayType;
+  class ConstantArrayType;
+  class VariableArrayType;
   class RecordType;
   class ComplexType;
   class TagType;
@@ -233,6 +235,10 @@
   /// routine will need to determine if the size is actually required.  
   bool isIncompleteType() const;
   
+  /// isVariablyModifiedType (C99 6.7.5.2p2) - Return true for variable array
+  /// types that have a non-constant expression. This does not include "[]".
+  bool isVariablyModifiedType() const;
+  
   /// Helper methods to distinguish type categories. All type predicates
   /// operate on the canonical type, ignoring typedefs.
   bool isIntegerType() const;     // C99 6.2.5p17 (int, char, bool, enum)
@@ -271,6 +277,9 @@
   const PointerType *getAsPointerType() const;
   const ReferenceType *getAsReferenceType() const;
   const ArrayType *getAsArrayType() const;
+  const ConstantArrayType *getAsConstantArrayType() const;
+  const VariableArrayType *getAsVariableArrayType() const;
+  const VariableArrayType *getAsVariablyModifiedType() const;
   const RecordType *getAsRecordType() const;
   const RecordType *getAsStructureType() const;   
   const RecordType *getAsUnionType() const;

Modified: cfe/trunk/test/Sema/array-constraint.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/array-constraint.c?rev=41647&r1=41646&r2=41647&view=diff

==============================================================================
--- cfe/trunk/test/Sema/array-constraint.c (original)
+++ cfe/trunk/test/Sema/array-constraint.c Fri Aug 31 12:20:07 2007
@@ -39,3 +39,13 @@
   int zero_size[0]; // expected-warning{{zero size arrays are an extension}}
 }
 
+static int I;
+typedef int TA[I]; // expected-error {{variable length array declared outside of any function}}
+
+void strFunc(char *);
+const char staticAry[] = "test";
+int checkStaticAry() { 
+  strFunc(staticAry); // expected-warning{{passing 'char const []' to 'char *' discards qualifiers}}
+}
+
+





More information about the cfe-commits mailing list