]> granicus.if.org Git - clang/commitdiff
VariableArrayTypes (VLAs) without a size expression are now uniqued
authorTed Kremenek <kremenek@apple.com>
Mon, 29 Oct 2007 23:37:31 +0000 (23:37 +0000)
committerTed Kremenek <kremenek@apple.com>
Mon, 29 Oct 2007 23:37:31 +0000 (23:37 +0000)
and inserted into a FoldingSet owned by ASTContext.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43482 91177308-0d34-0410-b5e6-96231b3b80d8

AST/ASTContext.cpp
include/clang/AST/ASTContext.h
include/clang/AST/Type.h

index 93d4232bf2a59f8d43e3e98ab45eff8da2b4a610..72511bd7b01fcf79b2635e198b1d3d74b6f92d5c 100644 (file)
@@ -451,11 +451,49 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,
 QualType ASTContext::getVariableArrayType(QualType EltTy, Expr *NumElts,
                                           ArrayType::ArraySizeModifier ASM,
                                           unsigned EltTypeQuals) {
-  // Since we don't unique expressions, it isn't possible to unique VLA's.
-  ArrayType *New = new VariableArrayType(EltTy, QualType(), NumElts, 
-                                         ASM, EltTypeQuals);
-  Types.push_back(New);
-  return QualType(New, 0);
+  if (NumElts) {
+    // Since we don't unique expressions, it isn't possible to unique VLA's
+    // that have an expression provided for their size.
+    
+    ArrayType *New = new VariableArrayType(EltTy, QualType(), NumElts, 
+                                           ASM, EltTypeQuals);
+    
+    // FIXME: Also add non-uniqued VLAs into a list of their own.
+    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,
+                                       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);            
+  }
 }
 
 /// getVectorType - Return the unique reference to a vector type of
index 3169726a76ef8792e31e26953c37ef2b0dfabb05..48e7e13c909667b1157795464e8a0319d96cc8e2 100644 (file)
@@ -29,12 +29,13 @@ namespace clang {
   
 /// ASTContext - This class holds long-lived AST nodes (such as types and
 /// decls) that can be referred to throughout the semantic analysis of a file.
-class ASTContext {
+class ASTContext {  
   std::vector<Type*> Types;
   llvm::FoldingSet<ComplexType> ComplexTypes;
   llvm::FoldingSet<PointerType> PointerTypes;
   llvm::FoldingSet<ReferenceType> ReferenceTypes;
   llvm::FoldingSet<ConstantArrayType> ArrayTypes;
+  llvm::FoldingSet<VariableArrayType> IncompleteVariableArrayTypes;
   llvm::FoldingSet<VectorType> VectorTypes;
   llvm::FoldingSet<FunctionTypeNoProto> FunctionTypeNoProtos;
   llvm::FoldingSet<FunctionTypeProto> FunctionTypeProtos;
index 59178b8d9bdb014fdb02cc4e8077b58167e0c16c..052f5801c4c4710539f7301a1e4999734e98b21a 100644 (file)
@@ -573,7 +573,7 @@ public:
 };
 
 // FIXME: VariableArrayType's aren't uniqued (since expressions aren't).
-class VariableArrayType : public ArrayType {
+class VariableArrayType : public ArrayType, public llvm::FoldingSetNode {
   /// SizeExpr - An assignment expression. VLA's are only permitted within 
   /// a function block. 
   Expr *SizeExpr;
@@ -593,6 +593,18 @@ public:
   static bool classof(const VariableArrayType *) { return true; }
   
   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());
+  }
+  
   // FIXME: Who owns VariableArrayType's?  What are the semantics
   //  for serialization.
 };