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.




git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47165 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/AST/Type.cpp b/AST/Type.cpp
index 1ce5059..13ffb0e 100644
--- a/AST/Type.cpp
+++ b/AST/Type.cpp
@@ -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 += '[';