Fix the following redefinition errors submitted by Keith Bauer...

[dylan:~/llvm/tools/clang] admin% cat tentative_decls.c 
// incorrectly generates redefinition error
extern int array[3];
int array[3];

// incorrectly generates a redefinition error
extern void nup(int a[3]);
void nup(int a[3]) {}

It turns out that this exposed a fairly major flaw in the type system,
array types were never getting uniqued! This is because all array types
contained an expression, which aren't unique.

To solve this, we now have 2 array types, ConstantArrayType and
VariableArrayType. ConstantArrayType's are unique, VAT's aren't.

This is a fairly extensive set of fundamental changes. Fortunately,
all the tests pass. Nevertheless, there may be some collateral damage:-)
If so, let me know!


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41592 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/AST/ASTContext.cpp b/AST/ASTContext.cpp
index a68ebb5..57c1c44 100644
--- a/AST/ASTContext.cpp
+++ b/AST/ASTContext.cpp
@@ -162,16 +162,14 @@
   case Type::FunctionProto:
   default:
     assert(0 && "Incomplete types have no size!");
-  case Type::Array: {
+  case Type::VariableArray:
+    assert(0 && "VLAs not implemented yet!");
+  case Type::ConstantArray: {
+    ConstantArrayType *CAT = cast<ConstantArrayType>(T);
+    
     std::pair<uint64_t, unsigned> EltInfo = 
-      getTypeInfo(cast<ArrayType>(T)->getElementType(), L);
-    
-    // Get the size of the array.
-    llvm::APSInt Sz(32);
-    if (!cast<ArrayType>(T)->getSizeExpr()->isIntegerConstantExpr(Sz, *this))
-      assert(0 && "VLAs not implemented yet!");
-    
-    Size = EltInfo.first*Sz.getZExtValue();
+      getTypeInfo(CAT->getElementType(), L);
+    Size = EltInfo.first*CAT->getSize().getZExtValue();
     Align = EltInfo.second;
     break;
   }    
@@ -403,37 +401,55 @@
   return QualType(New, 0);
 }
 
-/// getArrayType - Return the unique reference to the type for an array of the
-/// specified element type.
-QualType ASTContext::getArrayType(QualType EltTy,ArrayType::ArraySizeModifier ASM,
-                                  unsigned EltTypeQuals, Expr *NumElts) {
-  // Unique array types, to guarantee there is only one array of a particular
-  // structure.
+/// getConstantArrayType - Return the unique reference to the type for an 
+/// array of the specified element type.
+QualType ASTContext::getConstantArrayType(QualType EltTy, 
+                                          const llvm::APInt &ArySize) {
   llvm::FoldingSetNodeID ID;
-  ArrayType::Profile(ID, ASM, EltTypeQuals, EltTy, NumElts);
+  ConstantArrayType::Profile(ID, EltTy, ArySize);
       
   void *InsertPos = 0;
-  if (ArrayType *ATP = ArrayTypes.FindNodeOrInsertPos(ID, InsertPos))
+  if (ConstantArrayType *ATP = ArrayTypes.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 = getArrayType(EltTy.getCanonicalType(), ASM, EltTypeQuals,
-                             NumElts);
+    Canonical = getConstantArrayType(EltTy.getCanonicalType(), ArySize);
     
     // Get the new insert position for the node we care about.
-    ArrayType *NewIP = ArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
+    ConstantArrayType *NewIP = ArrayTypes.FindNodeOrInsertPos(ID, InsertPos);
     assert(NewIP == 0 && "Shouldn't be in the map!");
   }
   
-  ArrayType *New = new ArrayType(EltTy, ASM, EltTypeQuals, Canonical, NumElts);
+  ConstantArrayType *New = new ConstantArrayType(EltTy, Canonical, ArySize);
   ArrayTypes.InsertNode(New, InsertPos);
   Types.push_back(New);
   return QualType(New, 0);
 }
 
+/// getArrayType - If NumElts is a constant expression, we return a unique
+/// reference to an AST node of type ConstantArrayType. If NumElts is not
+/// a constant expression, we return an instance of VaribleLengthArrayType.
+QualType ASTContext::getArrayType(QualType EltTy,
+                                  ArrayType::ArraySizeModifier ASM,
+                                  unsigned EltTypeQuals, Expr *NumElts) {
+  llvm::APSInt ArySize(32);
+  // If no expression was provided, we consider it a VLA.
+  if (!NumElts || !NumElts->isIntegerConstantExpr(ArySize, *this)) {
+    // Since we don't unique expressions, it isn't possible to unique VLA's.
+    ArrayType *New = new VariableArrayType(EltTy, ASM, EltTypeQuals, 
+                                           QualType(), NumElts);
+    Types.push_back(New);
+    return QualType(New, 0);
+  }
+  // Unique constant array types, to guarantee there is only one array of a
+  // particular structure.
+  // FIXME: should we warn if ASM != ArrayType::Normal or EltTypeQuals != 0?
+  return getConstantArrayType(EltTy, ArySize);
+}
+
 /// getVectorType - Return the unique reference to a vector type of
 /// the specified element type and size. VectorType must be a built-in type.
 QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts) {