Finally fix PR2189. This makes a fairly invasive but important change to
move getAsArrayType into ASTContext instead of being a method on type.
This is required because getAsArrayType(const AT), where AT is a typedef
for "int[10]" needs to return ArrayType(const int, 10).
Fixing this greatly simplifies getArrayDecayedType, which is a good sign.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54317 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 47a3e3a..002a51f 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -375,7 +375,7 @@
// Flexible array members don't have any size, but they
// have to be aligned appropriately for their element type.
FieldSize = 0;
- const ArrayType* ATy = FD->getType()->getAsArrayType();
+ const ArrayType* ATy = Context.getAsArrayType(FD->getType());
FieldAlign = Context.getTypeAlign(ATy->getElementType());
} else {
std::pair<uint64_t, unsigned> FieldInfo =
@@ -1018,8 +1018,107 @@
/// for exact equality with a simple pointer comparison.
QualType ASTContext::getCanonicalType(QualType T) {
QualType CanType = T.getTypePtr()->getCanonicalTypeInternal();
- return QualType(CanType.getTypePtr(),
- T.getCVRQualifiers() | CanType.getCVRQualifiers());
+
+ // If the result has type qualifiers, make sure to canonicalize them as well.
+ unsigned TypeQuals = T.getCVRQualifiers() | CanType.getCVRQualifiers();
+ if (TypeQuals == 0) return CanType;
+
+ // If the type qualifiers are on an array type, get the canonical type of the
+ // array with the qualifiers applied to the element type.
+ ArrayType *AT = dyn_cast<ArrayType>(CanType);
+ if (!AT)
+ return CanType.getQualifiedType(TypeQuals);
+
+ // Get the canonical version of the element with the extra qualifiers on it.
+ // This can recursively sink qualifiers through multiple levels of arrays.
+ QualType NewEltTy=AT->getElementType().getWithAdditionalQualifiers(TypeQuals);
+ NewEltTy = getCanonicalType(NewEltTy);
+
+ if (ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
+ return getConstantArrayType(NewEltTy, CAT->getSize(),CAT->getSizeModifier(),
+ CAT->getIndexTypeQualifier());
+ if (IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT))
+ return getIncompleteArrayType(NewEltTy, IAT->getSizeModifier(),
+ IAT->getIndexTypeQualifier());
+
+ // FIXME: What is the ownership of size expressions in VLAs?
+ VariableArrayType *VAT = cast<VariableArrayType>(AT);
+ return getVariableArrayType(NewEltTy, VAT->getSizeExpr(),
+ VAT->getSizeModifier(),
+ VAT->getIndexTypeQualifier());
+}
+
+
+const ArrayType *ASTContext::getAsArrayType(QualType T) {
+ // Handle the non-qualified case efficiently.
+ if (T.getCVRQualifiers() == 0) {
+ // Handle the common positive case fast.
+ if (const ArrayType *AT = dyn_cast<ArrayType>(T))
+ return AT;
+ }
+
+ // Handle the common negative case fast, ignoring CVR qualifiers.
+ QualType CType = T->getCanonicalTypeInternal();
+
+ // Make sure to look through type qualifiers (like ASQuals) for the negative
+ // test.
+ if (!isa<ArrayType>(CType) &&
+ !isa<ArrayType>(CType.getUnqualifiedType()))
+ return 0;
+
+ // Apply any CVR qualifiers from the array type to the element type. This
+ // implements C99 6.7.3p8: "If the specification of an array type includes
+ // any type qualifiers, the element type is so qualified, not the array type."
+
+ // If we get here, we either have type qualifiers on the type, or we have
+ // sugar such as a typedef in the way. If we have type qualifiers on the type
+ // we must propagate them down into the elemeng type.
+ unsigned CVRQuals = T.getCVRQualifiers();
+ unsigned AddrSpace = 0;
+ Type *Ty = T.getTypePtr();
+
+ // Rip through ASQualType's and typedefs to get to a concrete type.
+ while (1) {
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(Ty)) {
+ AddrSpace = ASQT->getAddressSpace();
+ Ty = ASQT->getBaseType();
+ } else {
+ T = Ty->getDesugaredType();
+ if (T.getTypePtr() == Ty && T.getCVRQualifiers() == 0)
+ break;
+ CVRQuals |= T.getCVRQualifiers();
+ Ty = T.getTypePtr();
+ }
+ }
+
+ // If we have a simple case, just return now.
+ const ArrayType *ATy = dyn_cast<ArrayType>(Ty);
+ if (ATy == 0 || (AddrSpace == 0 && CVRQuals == 0))
+ return ATy;
+
+ // Otherwise, we have an array and we have qualifiers on it. Push the
+ // qualifiers into the array element type and return a new array type.
+ // Get the canonical version of the element with the extra qualifiers on it.
+ // This can recursively sink qualifiers through multiple levels of arrays.
+ QualType NewEltTy = ATy->getElementType();
+ if (AddrSpace)
+ NewEltTy = getASQualType(NewEltTy, AddrSpace);
+ NewEltTy = NewEltTy.getWithAdditionalQualifiers(CVRQuals);
+
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(ATy))
+ return cast<ArrayType>(getConstantArrayType(NewEltTy, CAT->getSize(),
+ CAT->getSizeModifier(),
+ CAT->getIndexTypeQualifier()));
+ if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(ATy))
+ return cast<ArrayType>(getIncompleteArrayType(NewEltTy,
+ IAT->getSizeModifier(),
+ IAT->getIndexTypeQualifier()));
+
+ // FIXME: What is the ownership of size expressions in VLAs?
+ const VariableArrayType *VAT = cast<VariableArrayType>(ATy);
+ return cast<ArrayType>(getVariableArrayType(NewEltTy, VAT->getSizeExpr(),
+ VAT->getSizeModifier(),
+ VAT->getIndexTypeQualifier()));
}
@@ -1030,60 +1129,17 @@
///
/// See C99 6.7.5.3p7 and C99 6.3.2.1p3.
QualType ASTContext::getArrayDecayedType(QualType Ty) {
- // Handle the common case where typedefs are not involved directly.
- QualType EltTy;
- unsigned ArrayQuals = 0;
- unsigned PointerQuals = 0;
- if (ArrayType *AT = dyn_cast<ArrayType>(Ty)) {
- // Since T "isa" an array type, it could not have had an address space
- // qualifier, just CVR qualifiers. The properly qualified element pointer
- // gets the union of the CVR qualifiers from the element and the array, and
- // keeps any address space qualifier on the element type if present.
- EltTy = AT->getElementType();
- ArrayQuals = Ty.getCVRQualifiers();
- PointerQuals = AT->getIndexTypeQualifier();
- } else {
- // Otherwise, we have an ASQualType or a typedef, etc. Make sure we don't
- // lose qualifiers when dealing with typedefs. Example:
- // typedef int arr[10];
- // void test2() {
- // const arr b;
- // b[4] = 1;
- // }
- //
- // The decayed type of b is "const int*" even though the element type of the
- // array is "int".
- QualType CanTy = getCanonicalType(Ty);
- const ArrayType *PrettyArrayType = Ty->getAsArrayType();
- assert(PrettyArrayType && "Not an array type!");
-
- // Get the element type with 'getAsArrayType' so that we don't lose any
- // typedefs in the element type of the array.
- EltTy = PrettyArrayType->getElementType();
-
- // If the array was address-space qualifier, make sure to ASQual the element
- // type. We can just grab the address space from the canonical type.
- if (unsigned AS = CanTy.getAddressSpace())
- EltTy = getASQualType(EltTy, AS);
-
- // To properly handle [multiple levels of] typedefs, typeof's etc, we take
- // the CVR qualifiers directly from the canonical type, which is guaranteed
- // to have the full set unioned together.
- ArrayQuals = CanTy.getCVRQualifiers();
- PointerQuals = PrettyArrayType->getIndexTypeQualifier();
- }
+ // Get the element type with 'getAsArrayType' so that we don't lose any
+ // typedefs in the element type of the array. This also handles propagation
+ // of type qualifiers from the array type into the element type if present
+ // (C99 6.7.3p8).
+ const ArrayType *PrettyArrayType = getAsArrayType(Ty);
+ assert(PrettyArrayType && "Not an array type!");
- // Apply any CVR qualifiers from the array type to the element type. This
- // implements C99 6.7.3p8: "If the specification of an array type includes
- // any type qualifiers, the element type is so qualified, not the array type."
- EltTy = EltTy.getQualifiedType(ArrayQuals | EltTy.getCVRQualifiers());
-
- QualType PtrTy = getPointerType(EltTy);
+ QualType PtrTy = getPointerType(PrettyArrayType->getElementType());
// int x[restrict 4] -> int *restrict
- PtrTy = PtrTy.getQualifiedType(PointerQuals);
-
- return PtrTy;
+ return PtrTy.getQualifiedType(PrettyArrayType->getIndexTypeQualifier());
}
/// getFloatingRank - Return a relative rank for floating point types.
@@ -1308,8 +1364,7 @@
}
void ASTContext::getObjCEncodingForType(QualType T, std::string& S,
- llvm::SmallVector<const RecordType *, 8> &ERType) const
-{
+ llvm::SmallVector<const RecordType *, 8> &ERType) const {
// FIXME: This currently doesn't encode:
// @ An object (whether statically typed or typed id)
// # A class object (Class)
@@ -1372,7 +1427,9 @@
S += '^';
getObjCEncodingForType(PT->getPointeeType(), S, ERType);
- } else if (const ArrayType *AT = T->getAsArrayType()) {
+ } else if (const ArrayType *AT =
+ // Ignore type qualifiers etc.
+ dyn_cast<ArrayType>(T->getCanonicalTypeInternal())) {
S += '[';
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))