[cfe-commits] r47165 - in /cfe/trunk: AST/ASTContext.cpp AST/Type.cpp AST/TypeSerialization.cpp CodeGen/CodeGenTypes.cpp Sema/SemaDecl.cpp Sema/SemaType.cpp include/clang/AST/ASTContext.h include/clang/AST/Type.h

Eli Friedman eli.friedman at gmail.com
Fri Feb 15 10:16:39 PST 2008


Author: efriedma
Date: Fri Feb 15 12:16:39 2008
New Revision: 47165

URL: http://llvm.org/viewvc/llvm-project?rev=47165&view=rev
Log:
Split out incomplete arrays from VariableArrayType into 
IncompleteArrayType.  This should make code dealing with both incomplete 
and variable length arrays much more readable, plus it allows properly 
making the distinction between isVariableArrayType() and 
isVariablyModifiedType().  The patch is a little big, but it's 
strightforward. so I don't think there should be any issues.



Modified:
    cfe/trunk/AST/ASTContext.cpp
    cfe/trunk/AST/Type.cpp
    cfe/trunk/AST/TypeSerialization.cpp
    cfe/trunk/CodeGen/CodeGenTypes.cpp
    cfe/trunk/Sema/SemaDecl.cpp
    cfe/trunk/Sema/SemaType.cpp
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Type.h

Modified: cfe/trunk/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/ASTContext.cpp?rev=47165&r1=47164&r2=47165&view=diff

==============================================================================
--- cfe/trunk/AST/ASTContext.cpp (original)
+++ cfe/trunk/AST/ASTContext.cpp Fri Feb 15 12:16:39 2008
@@ -532,49 +532,49 @@
 QualType ASTContext::getVariableArrayType(QualType EltTy, Expr *NumElts,
                                           ArrayType::ArraySizeModifier ASM,
                                           unsigned EltTypeQuals) {
-  if (NumElts) {
-    // Since we don't unique expressions, it isn't possible to unique VLA's
-    // that have an expression provided for their size.
-    
-    VariableArrayType *New = new VariableArrayType(EltTy, QualType(), NumElts, 
-                                                   ASM, EltTypeQuals);
-    
-    CompleteVariableArrayTypes.push_back(New);
-    Types.push_back(New);
-    return QualType(New, 0);
-  }
-  else {
-    // No size is provided for the VLA.  These we can unique.
-    llvm::FoldingSetNodeID ID;
-    VariableArrayType::Profile(ID, EltTy);
-    
-    void *InsertPos = 0;
-    if (VariableArrayType *ATP = 
-         IncompleteVariableArrayTypes.FindNodeOrInsertPos(ID, InsertPos))
-      return QualType(ATP, 0);
-    
-    // If the element type isn't canonical, this won't be a canonical type
-    // either, so fill in the canonical type field.
-    QualType Canonical;
-    
-    if (!EltTy->isCanonical()) {
-      Canonical = getVariableArrayType(EltTy.getCanonicalType(), NumElts,
+  // Since we don't unique expressions, it isn't possible to unique VLA's
+  // that have an expression provided for their size.
+
+  VariableArrayType *New = new VariableArrayType(EltTy, QualType(), NumElts, 
+                                                 ASM, EltTypeQuals);
+
+  VariableArrayTypes.push_back(New);
+  Types.push_back(New);
+  return QualType(New, 0);
+}
+
+QualType ASTContext::getIncompleteArrayType(QualType EltTy,
+                                            ArrayType::ArraySizeModifier ASM,
+                                            unsigned EltTypeQuals) {
+  llvm::FoldingSetNodeID ID;
+  IncompleteArrayType::Profile(ID, EltTy);
+
+  void *InsertPos = 0;
+  if (IncompleteArrayType *ATP = 
+       IncompleteArrayTypes.FindNodeOrInsertPos(ID, InsertPos))
+    return QualType(ATP, 0);
+
+  // If the element type isn't canonical, this won't be a canonical type
+  // either, so fill in the canonical type field.
+  QualType Canonical;
+
+  if (!EltTy->isCanonical()) {
+    Canonical = getIncompleteArrayType(EltTy.getCanonicalType(),
                                        ASM, EltTypeQuals);
-      
-      // Get the new insert position for the node we care about.
-      VariableArrayType *NewIP =
-        IncompleteVariableArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
-      
-      assert(NewIP == 0 && "Shouldn't be in the map!");
-    }
-    
-    VariableArrayType *New = new VariableArrayType(EltTy, QualType(), NumElts, 
-                                                   ASM, EltTypeQuals);
-    
-    IncompleteVariableArrayTypes.InsertNode(New, InsertPos);
-    Types.push_back(New);
-    return QualType(New, 0);            
+
+    // Get the new insert position for the node we care about.
+    IncompleteArrayType *NewIP =
+      IncompleteArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
+
+    assert(NewIP == 0 && "Shouldn't be in the map!");
   }
+
+  IncompleteArrayType *New = new IncompleteArrayType(EltTy, Canonical,
+                                                     ASM, EltTypeQuals);
+
+  IncompleteArrayTypes.InsertNode(New, InsertPos);
+  Types.push_back(New);
+  return QualType(New, 0);
 }
 
 /// getVectorType - Return the unique reference to a vector type of
@@ -1690,6 +1690,8 @@
   // Same as above for arrays
   if (LHSClass == Type::VariableArray) LHSClass = Type::ConstantArray;
   if (RHSClass == Type::VariableArray) RHSClass = Type::ConstantArray;
+  if (LHSClass == Type::IncompleteArray) LHSClass = Type::ConstantArray;
+  if (RHSClass == Type::IncompleteArray) RHSClass = Type::ConstantArray;
   
   // If the canonical type classes don't match...
   if (LHSClass != RHSClass) {
@@ -1719,6 +1721,7 @@
     return pointerTypesAreCompatible(lcanon, rcanon);
   case Type::ConstantArray:
   case Type::VariableArray:
+  case Type::IncompleteArray:
     return arrayTypesAreCompatible(lcanon, rcanon);
   case Type::FunctionNoProto:
     return functionTypesAreCompatible(lcanon, rcanon);

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

==============================================================================
--- cfe/trunk/AST/Type.cpp (original)
+++ cfe/trunk/AST/Type.cpp Fri Feb 15 12:16:39 2008
@@ -46,6 +46,7 @@
   case Pointer:
   case VariableArray:
   case ConstantArray:
+  case IncompleteArray:
   case FunctionProto:
   case FunctionNoProto:
   case Reference:
@@ -255,28 +256,26 @@
   return false;
 }
 
-const VariableArrayType *Type::getAsVariablyModifiedType() const {
-  if (const VariableArrayType *VAT = getAsVariableArrayType()) {
-    if (VAT->getSizeExpr())
-      return VAT;
-  }
-  return 0;
-}
-
 bool Type::isIncompleteArrayType() const {
-  if (const VariableArrayType *VAT = getAsVariableArrayType()) {
-    if (!VAT->getSizeExpr())
-      return true;
-  }
-  return false;
+  return isa<IncompleteArrayType>(CanonicalType);
 }
 
-const VariableArrayType *Type::getAsIncompleteArrayType() const {
-  if (const VariableArrayType *VAT = getAsVariableArrayType()) {
-    if (!VAT->getSizeExpr())
-      return VAT;
+const IncompleteArrayType *Type::getAsIncompleteArrayType() const {
+  // If this is directly a variable array type, return it.
+  if (const IncompleteArrayType *ATy = dyn_cast<IncompleteArrayType>(this))
+    return ATy;
+  
+  // If the canonical form of this type isn't the right kind, reject it.
+  if (!isa<IncompleteArrayType>(CanonicalType)) {
+    // Look through type qualifiers
+    if (isa<IncompleteArrayType>(CanonicalType.getUnqualifiedType()))
+      return CanonicalType.getUnqualifiedType()->getAsIncompleteArrayType();
+    return 0;
   }
-  return 0;
+
+  // If this is a typedef for a variable array type, strip the typedef off
+  // without losing all typedef information.
+  return getDesugaredType()->getAsIncompleteArrayType();
 }
 
 const RecordType *Type::getAsRecordType() const {
@@ -563,8 +562,7 @@
   }
   if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
     return ASQT->getBaseType()->isAggregateType();
-  return CanonicalType->getTypeClass() == ConstantArray ||
-         CanonicalType->getTypeClass() == VariableArray;
+  return isa<ArrayType>(CanonicalType);
 }
 
 /// isConstantSizeType - Return true if this is not a variable sized type,
@@ -594,9 +592,9 @@
     // A tagged type (struct/union/enum/class) is incomplete if the decl is a
     // forward declaration, but not a full definition (C99 6.2.5p22).
     return !cast<TagType>(CanonicalType)->getDecl()->isDefinition();
-  case VariableArray:
+  case IncompleteArray:
     // An array of unknown size is an incomplete type (C99 6.2.5p22).
-    return cast<VariableArrayType>(CanonicalType)->getSizeExpr() == 0;
+    return true;
   }
 }
 
@@ -804,6 +802,12 @@
   getElementType().getAsStringInternal(S);
 }
 
+void IncompleteArrayType::getAsStringInternal(std::string &S) const {
+  S += "[]";
+
+  getElementType().getAsStringInternal(S);
+}
+
 void VariableArrayType::getAsStringInternal(std::string &S) const {
   S += '[';
   

Modified: cfe/trunk/AST/TypeSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/TypeSerialization.cpp?rev=47165&r1=47164&r2=47165&view=diff

==============================================================================
--- cfe/trunk/AST/TypeSerialization.cpp (original)
+++ cfe/trunk/AST/TypeSerialization.cpp Fri Feb 15 12:16:39 2008
@@ -91,6 +91,10 @@
       D.RegisterPtr(PtrID,FunctionTypeProto::CreateImpl(Context,D));
       break;
       
+    case Type::IncompleteArray:
+      D.RegisterPtr(PtrID,IncompleteArrayType::CreateImpl(Context,D));
+      break;
+      
     case Type::Pointer:
       D.RegisterPtr(PtrID,PointerType::CreateImpl(Context,D));
       break;
@@ -269,3 +273,21 @@
   
   return Context.getVariableArrayType(ElTy,SizeExpr,am,ITQ).getTypePtr();
 }
+
+//===----------------------------------------------------------------------===//
+// IncompleteArrayType
+//===----------------------------------------------------------------------===//
+
+void IncompleteArrayType::EmitImpl(Serializer& S) const {
+  S.Emit(getElementType());
+  S.EmitInt(getSizeModifier());
+  S.EmitInt(getIndexTypeQualifier());
+}
+
+Type* IncompleteArrayType::CreateImpl(ASTContext& Context, Deserializer& D) {
+  QualType ElTy = QualType::ReadVal(D);
+  ArraySizeModifier am = static_cast<ArraySizeModifier>(D.ReadInt());
+  unsigned ITQ = D.ReadInt();
+
+  return Context.getIncompleteArrayType(ElTy,am,ITQ).getTypePtr();
+}

Modified: cfe/trunk/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenTypes.cpp?rev=47165&r1=47164&r2=47165&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/CodeGen/CodeGenTypes.cpp Fri Feb 15 12:16:39 2008
@@ -207,15 +207,18 @@
     
   case Type::VariableArray: {
     const VariableArrayType &A = cast<VariableArrayType>(Ty);
-    assert(A.getSizeModifier() == ArrayType::Normal &&
-           A.getIndexTypeQualifier() == 0 &&
+    assert(A.getIndexTypeQualifier() == 0 &&
            "FIXME: We only handle trivial array types so far!");
-    if (A.getSizeExpr() == 0) {
-      // int X[] -> [0 x int]
-      return llvm::ArrayType::get(ConvertType(A.getElementType()), 0);
-    } else {
-      assert(0 && "FIXME: VLAs not implemented yet!");
-    }
+    // VLAs resolve to the innermost element type; this matches
+    // the return of alloca, and there isn't any obviously better choice.
+    return ConvertType(A.getElementType());
+  }
+  case Type::IncompleteArray: {
+    const IncompleteArrayType &A = cast<IncompleteArrayType>(Ty);
+    assert(A.getIndexTypeQualifier() == 0 &&
+           "FIXME: We only handle trivial array types so far!");
+    // int X[] -> [0 x int]
+    return llvm::ArrayType::get(ConvertType(A.getElementType()), 0);
   }
   case Type::ConstantArray: {
     const ConstantArrayType &A = cast<ConstantArrayType>(Ty);

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

==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Fri Feb 15 12:16:39 2008
@@ -412,13 +412,13 @@
 }
 
 bool Sema::CheckStringLiteralInit(StringLiteral *strLiteral, QualType &DeclT) {
-  if (const VariableArrayType *VAT = DeclT->getAsIncompleteArrayType()) {
+  if (const IncompleteArrayType *IAT = DeclT->getAsIncompleteArrayType()) {
     // C99 6.7.8p14. We have an array of character type with unknown size 
     // being initialized to a string literal.
     llvm::APSInt ConstVal(32);
     ConstVal = strLiteral->getByteLength() + 1;
     // Return a new array type (C99 6.7.8p22).
-    DeclT = Context.getConstantArrayType(VAT->getElementType(), ConstVal, 
+    DeclT = Context.getConstantArrayType(IAT->getElementType(), ConstVal, 
                                          ArrayType::Normal, 0);
   } else if (const ConstantArrayType *CAT = DeclT->getAsConstantArrayType()) {
     // C99 6.7.8p14. We have an array of character type with known size.
@@ -564,17 +564,18 @@
         }
       }
       int maxElements;
-      if (const VariableArrayType *VAT = DeclType->getAsVariableArrayType()) {
+      if (DeclType->isIncompleteArrayType()) {
         // FIXME: use a proper constant
         maxElements = 0x7FFFFFFF;
+      } else if (const VariableArrayType *VAT = DeclType->getAsVariableArrayType()) {
         // Check for VLAs; in standard C it would be possible to check this
         // earlier, but I don't know where clang accepts VLAs (gcc accepts
         // them in all sorts of strange places).
-        if (const Expr *expr = VAT->getSizeExpr()) {
-          Diag(expr->getLocStart(), diag::err_variable_object_no_init,
-               expr->getSourceRange());
-          hadError = true;
-        }
+        Diag(VAT->getSizeExpr()->getLocStart(),
+             diag::err_variable_object_no_init,
+             VAT->getSizeExpr()->getSourceRange());
+        hadError = true;
+        maxElements = 0x7FFFFFFF;
       } else {
         const ConstantArrayType *CAT = DeclType->getAsConstantArrayType();
         maxElements = static_cast<int>(CAT->getSize().getZExtValue());
@@ -638,7 +639,7 @@
 bool Sema::CheckInitializerTypes(Expr *&Init, QualType &DeclType) {  
   // C99 6.7.8p3: The type of the entity to be initialized shall be an array
   // of unknown size ("[]") or an object type that is not a variable array type.
-  if (const VariableArrayType *VAT = DeclType->getAsVariablyModifiedType())
+  if (const VariableArrayType *VAT = DeclType->getAsVariableArrayType())
     return Diag(VAT->getSizeExpr()->getLocStart(), 
                 diag::err_variable_object_no_init, 
                 VAT->getSizeExpr()->getSourceRange());
@@ -897,10 +898,8 @@
     // static storage duration, it shall not have a variable length array.
     if ((FVD || BVD) && IDecl->getStorageClass() == VarDecl::Static) {
       if (const VariableArrayType *VLA = T->getAsVariableArrayType()) {
-        if (VLA->getSizeExpr()) {  
-          Diag(IDecl->getLocation(), diag::err_typecheck_illegal_vla);
-          IDecl->setInvalidDecl();
-        }
+        Diag(IDecl->getLocation(), diag::err_typecheck_illegal_vla);
+        IDecl->setInvalidDecl();
       }
     }
     // Block scope. C99 6.7p7: If an identifier for an object is declared with

Modified: cfe/trunk/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaType.cpp?rev=47165&r1=47164&r2=47165&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaType.cpp (original)
+++ cfe/trunk/Sema/SemaType.cpp Fri Feb 15 12:16:39 2008
@@ -231,9 +231,11 @@
       }
       llvm::APSInt ConstVal(32);
       // If no expression was provided, we consider it a VLA.
-      if (!ArraySize || !ArraySize->isIntegerConstantExpr(ConstVal, Context))
+      if (!ArraySize) {
+        T = Context.getIncompleteArrayType(T, ASM, ATI.TypeQuals);
+      } else if (!ArraySize->isIntegerConstantExpr(ConstVal, Context)) {
         T = Context.getVariableArrayType(T, ArraySize, ASM, ATI.TypeQuals);
-      else {
+      } else {
         // C99 6.7.5.2p1: If the expression is a constant expression, it shall
         // have a value greater than zero.
         if (ConstVal.isSigned()) {

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

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Feb 15 12:16:39 2008
@@ -37,8 +37,8 @@
   llvm::FoldingSet<PointerType> PointerTypes;
   llvm::FoldingSet<ReferenceType> ReferenceTypes;
   llvm::FoldingSet<ConstantArrayType> ConstantArrayTypes;
-  llvm::FoldingSet<VariableArrayType> IncompleteVariableArrayTypes;
-  std::vector<VariableArrayType*> CompleteVariableArrayTypes;
+  llvm::FoldingSet<IncompleteArrayType> IncompleteArrayTypes;
+  std::vector<VariableArrayType*> VariableArrayTypes;
   llvm::FoldingSet<VectorType> VectorTypes;
   llvm::FoldingSet<FunctionTypeNoProto> FunctionTypeNoProtos;
   llvm::FoldingSet<FunctionTypeProto> FunctionTypeProtos;
@@ -143,6 +143,12 @@
                                 ArrayType::ArraySizeModifier ASM,
                                 unsigned EltTypeQuals);
 
+  /// getIncompleteArrayType - Returns a unique reference to the type for a
+  /// incomplete array of the specified element type.
+  QualType getIncompleteArrayType(QualType EltTy,
+                                  ArrayType::ArraySizeModifier ASM,
+                                  unsigned EltTypeQuals);
+
   /// getConstantArrayType - Return the unique reference to the type for a
   /// constant array of the specified element type.
   QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize,

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

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Fri Feb 15 12:16:39 2008
@@ -44,6 +44,7 @@
   class ArrayType;
   class ConstantArrayType;
   class VariableArrayType;
+  class IncompleteArrayType;
   class RecordType;
   class ComplexType;
   class TagType;
@@ -217,7 +218,7 @@
 public:
   enum TypeClass {
     Builtin, Complex, Pointer, Reference, 
-    ConstantArray, VariableArray, 
+    ConstantArray, VariableArray, IncompleteArray,
     Vector, OCUVector,
     FunctionNoProto, FunctionProto,
     TypeName, Tagged, ASQual,
@@ -319,8 +320,7 @@
   const ArrayType *getAsArrayType() const;
   const ConstantArrayType *getAsConstantArrayType() const;
   const VariableArrayType *getAsVariableArrayType() const;
-  const VariableArrayType *getAsIncompleteArrayType() const;
-  const VariableArrayType *getAsVariablyModifiedType() const;
+  const IncompleteArrayType *getAsIncompleteArrayType() const;
   const RecordType *getAsRecordType() const;
   const RecordType *getAsStructureType() const;   
   const RecordType *getAsUnionType() const;
@@ -576,7 +576,8 @@
   }
   static bool classof(const Type *T) {
     return T->getTypeClass() == ConstantArray ||
-           T->getTypeClass() == VariableArray;
+           T->getTypeClass() == VariableArray ||
+           T->getTypeClass() == IncompleteArray;
   }
   static bool classof(const ArrayType *) { return true; }
 };
@@ -623,6 +624,36 @@
   friend class Type;
 };
 
+class IncompleteArrayType : public ArrayType {
+  IncompleteArrayType(QualType et, QualType can,
+                    ArraySizeModifier sm, unsigned tq)
+    : ArrayType(IncompleteArray, et, can, sm, tq) {}
+  friend class ASTContext;  // ASTContext creates these.
+public:
+
+  virtual void getAsStringInternal(std::string &InnerString) const;
+
+  static bool classof(const Type *T) { 
+    return T->getTypeClass() == IncompleteArray; 
+  }
+  static bool classof(const IncompleteArrayType *) { return true; }
+  
+  friend class StmtIteratorBase;
+  
+  void Profile(llvm::FoldingSetNodeID &ID) {
+    Profile(ID, getElementType());
+  }
+  
+  static void Profile(llvm::FoldingSetNodeID &ID, QualType ET) {
+    ID.AddPointer(ET.getAsOpaquePtr());
+  }
+  
+protected:  
+  virtual void EmitImpl(llvm::Serializer& S) const;
+  static Type* CreateImpl(ASTContext& Context,llvm::Deserializer& D);
+  friend class Type;
+};
+
 // FIXME: VariableArrayType's aren't uniqued (since expressions aren't).
 class VariableArrayType : public ArrayType {
   /// SizeExpr - An assignment expression. VLA's are only permitted within 
@@ -647,14 +678,7 @@
   friend class StmtIteratorBase;
   
   void Profile(llvm::FoldingSetNodeID &ID) {
-    assert (SizeExpr == NULL 
-            && "Can only unique VariableArrayTypes with no specified size.");
-    
-    Profile(ID, getElementType());
-  }
-  
-  static void Profile(llvm::FoldingSetNodeID &ID, QualType ET) {
-    ID.AddPointer(ET.getAsOpaquePtr());
+    assert (0 && "Cannnot unique VariableArrayTypes.");
   }
   
 protected:  





More information about the cfe-commits mailing list