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/ASTContext.cpp b/AST/ASTContext.cpp
index d4a689c..608858b 100644
--- a/AST/ASTContext.cpp
+++ b/AST/ASTContext.cpp
@@ -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);
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 += '[';
diff --git a/AST/TypeSerialization.cpp b/AST/TypeSerialization.cpp
index 7583a07..e2ccd3c 100644
--- a/AST/TypeSerialization.cpp
+++ b/AST/TypeSerialization.cpp
@@ -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();
+}