aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-08-04 07:31:14 +0000
committerChris Lattner <sabre@nondot.org>2008-08-04 07:31:14 +0000
commitc63a1f276f7b324fd9a4be82098b1c8f7bf30733 (patch)
treed20bfdf2549bd5906f9e6347e7576871205f6453
parent0998c65aeab7ad319bec8a93931196c170ed74d8 (diff)
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
-rw-r--r--include/clang/AST/ASTContext.h17
-rw-r--r--include/clang/AST/Type.h76
-rw-r--r--lib/AST/ASTContext.cpp171
-rw-r--r--lib/AST/Expr.cpp11
-rw-r--r--lib/AST/Type.cpp140
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp12
-rw-r--r--lib/CodeGen/CGExpr.cpp3
-rw-r--r--lib/CodeGen/CGExprAgg.cpp7
-rw-r--r--lib/CodeGen/CGExprConstant.cpp9
-rw-r--r--lib/CodeGen/CodeGenModule.cpp3
-rw-r--r--lib/Sema/SemaDecl.cpp22
-rw-r--r--lib/Sema/SemaExpr.cpp4
-rw-r--r--lib/Sema/SemaInit.cpp9
-rw-r--r--test/Sema/typedef-retain.c16
14 files changed, 264 insertions, 236 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 0def988140..2c1e1e4ec6 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -253,7 +253,7 @@ public:
// Return the ObjC type encoding for a given type.
void getObjCEncodingForType(QualType t, std::string &S,
- llvm::SmallVector<const RecordType *, 8> &RT) const;
+ llvm::SmallVector<const RecordType*,8> &RT) const;
// Put the string version of type qualifiers into S.
void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT,
@@ -339,6 +339,21 @@ public:
/// for exact equality with a simple pointer comparison.
QualType getCanonicalType(QualType T);
+ /// Type Query functions. If the type is an instance of the specified class,
+ /// return the Type pointer for the underlying maximally pretty type. This
+ /// is a member of ASTContext because this may need to do some amount of
+ /// canonicalization, e.g. to move type qualifiers into the element type.
+ const ArrayType *getAsArrayType(QualType T);
+ const ConstantArrayType *getAsConstantArrayType(QualType T) {
+ return dyn_cast_or_null<ConstantArrayType>(getAsArrayType(T));
+ }
+ const VariableArrayType *getAsVariableArrayType(QualType T) {
+ return dyn_cast_or_null<VariableArrayType>(getAsArrayType(T));
+ }
+ const IncompleteArrayType *getAsIncompleteArrayType(QualType T) {
+ return dyn_cast_or_null<IncompleteArrayType>(getAsArrayType(T));
+ }
+
/// getArrayDecayedType - Return the properly qualified result of decaying the
/// specified array type to a pointer. This operation is non-trivial when
/// handling typedefs etc. The canonical type of "T" must be an array type,
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 5d764894c2..4b349f4d10 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -143,6 +143,9 @@ public:
QualType getQualifiedType(unsigned TQs) const {
return QualType(getTypePtr(), TQs);
}
+ QualType getWithAdditionalQualifiers(unsigned TQs) const {
+ return QualType(getTypePtr(), TQs|getCVRQualifiers());
+ }
inline QualType getUnqualifiedType() const;
@@ -285,10 +288,6 @@ public:
/// types that have a non-constant expression. This does not include "[]".
bool isVariablyModifiedType() const;
- /// isIncompleteArrayType (C99 6.2.5p22) - Return true for variable array
- /// types that don't have any expression ("[]").
- bool isIncompleteArrayType() const;
-
/// Helper methods to distinguish type categories. All type predicates
/// operate on the canonical type, ignoring typedefs and qualifiers.
@@ -322,6 +321,9 @@ public:
bool isReferenceType() const;
bool isFunctionPointerType() const;
bool isArrayType() const;
+ bool isConstantArrayType() const;
+ bool isIncompleteArrayType() const;
+ bool isVariableArrayType() const;
bool isRecordType() const;
bool isClassType() const;
bool isStructureType() const;
@@ -342,12 +344,9 @@ public:
const PointerLikeType *getAsPointerLikeType() const; // Pointer or Reference.
const PointerType *getAsPointerType() const;
const ReferenceType *getAsReferenceType() const;
- const ArrayType *getAsArrayType() const;
- const ConstantArrayType *getAsConstantArrayType() const;
- const VariableArrayType *getAsVariableArrayType() const;
- const IncompleteArrayType *getAsIncompleteArrayType() const;
const RecordType *getAsRecordType() const;
const RecordType *getAsStructureType() const;
+ /// NOTE: getAsArrayType* are methods on ASTContext.
const TypedefType *getAsTypedefType() const;
const RecordType *getAsUnionType() const;
const EnumType *getAsEnumType() const;
@@ -358,11 +357,17 @@ public:
const ObjCInterfaceType *getAsObjCInterfaceType() const;
const ObjCQualifiedInterfaceType *getAsObjCQualifiedInterfaceType() const;
const ObjCQualifiedIdType *getAsObjCQualifiedIdType() const;
-
+
/// getAsPointerToObjCInterfaceType - If this is a pointer to an ObjC
/// interface, return the interface type, otherwise return null.
const ObjCInterfaceType *getAsPointerToObjCInterfaceType() const;
+ /// getArrayElementTypeNoTypeQual - If this is an array type, return the
+ /// element type of the array, potentially with type qualifiers missing.
+ /// This method should never be used when type qualifiers are meaningful.
+ const Type *getArrayElementTypeNoTypeQual() const;
+
+
/// getDesugaredType - Return the specified type with any "sugar" removed from
/// the type. This takes off typedefs, typeof's etc. If the outer level of
@@ -370,7 +375,7 @@ public:
/// to getting the canonical type, but it doesn't remove *all* typedefs. For
/// example, it returns "T*" as "T*", (not as "int*"), because the pointer is
/// concrete.
- const Type *getDesugaredType() const;
+ QualType getDesugaredType() const;
/// More type predicates useful for type checking/promotion
bool isPromotableIntegerType() const; // C99 6.3.1.1p2
@@ -391,11 +396,8 @@ public:
/// according to the rules of C99 6.7.5p3. It is not legal to call this on
/// incomplete types.
bool isConstantSizeType() const;
-private:
+
QualType getCanonicalTypeInternal() const { return CanonicalType; }
- friend class QualType;
- friend class TypedefType;
-public:
void dump() const;
virtual void getAsStringInternal(std::string &InnerString) const = 0;
static bool classof(const Type *) { return true; }
@@ -619,14 +621,6 @@ public:
}
unsigned getIndexTypeQualifier() const { return IndexTypeQuals; }
- QualType getBaseType() const {
- const ArrayType *AT;
- QualType ElmtType = getElementType();
- // If we have a multi-dimensional array, navigate to the base type.
- while ((AT = ElmtType->getAsArrayType()))
- ElmtType = AT->getElementType();
- return ElmtType;
- }
static bool classof(const Type *T) {
return T->getTypeClass() == ConstantArray ||
T->getTypeClass() == VariableArray ||
@@ -646,19 +640,7 @@ class ConstantArrayType : public ArrayType {
: ArrayType(ConstantArray, et, can, sm, tq), Size(sz) {}
friend class ASTContext; // ASTContext creates these.
public:
- llvm::APInt getSize() const { return Size; }
- int getMaximumElements() const {
- QualType ElmtType = getElementType();
- int maxElements = static_cast<int>(getSize().getZExtValue());
-
- const ConstantArrayType *CAT;
- // If we have a multi-dimensional array, include it's elements.
- while ((CAT = ElmtType->getAsConstantArrayType())) {
- ElmtType = CAT->getElementType();
- maxElements *= static_cast<int>(CAT->getSize().getZExtValue());
- }
- return maxElements;
- }
+ const llvm::APInt &getSize() const { return Size; }
virtual void getAsStringInternal(std::string &InnerString) const;
void Profile(llvm::FoldingSetNodeID &ID) {
@@ -740,7 +722,7 @@ class VariableArrayType : public ArrayType {
virtual void Destroy(ASTContext& C);
public:
- const Expr *getSizeExpr() const {
+ Expr *getSizeExpr() const {
// We use C-style casts instead of cast<> here because we do not wish
// to have a dependency of Type.h on Stmt.h/Expr.h.
return (Expr*) SizeExpr;
@@ -1274,7 +1256,7 @@ inline QualType QualType::getUnqualifiedType() const {
inline unsigned QualType::getAddressSpace() const {
QualType CT = getTypePtr()->getCanonicalTypeInternal();
if (const ArrayType *AT = dyn_cast<ArrayType>(CT))
- return AT->getBaseType().getAddressSpace();
+ return AT->getElementType().getAddressSpace();
if (const RecordType *RT = dyn_cast<RecordType>(CT))
return RT->getAddressSpace();
if (const ASQualType *ASQT = dyn_cast<ASQualType>(CT))
@@ -1291,7 +1273,8 @@ inline const ObjCInterfaceType *Type::getAsPointerToObjCInterfaceType() const {
return 0;
}
-
+// NOTE: All of these methods use "getUnqualifiedType" to strip off address
+// space qualifiers if present.
inline bool Type::isFunctionType() const {
return isa<FunctionType>(CanonicalType.getUnqualifiedType());
}
@@ -1313,11 +1296,20 @@ inline bool Type::isFunctionPointerType() const {
inline bool Type::isArrayType() const {
return isa<ArrayType>(CanonicalType.getUnqualifiedType());
}
+inline bool Type::isConstantArrayType() const {
+ return isa<ConstantArrayType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isIncompleteArrayType() const {
+ return isa<IncompleteArrayType>(CanonicalType.getUnqualifiedType());
+}
+inline bool Type::isVariableArrayType() const {
+ return isa<VariableArrayType>(CanonicalType.getUnqualifiedType());
+}
inline bool Type::isRecordType() const {
return isa<RecordType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isAnyComplexType() const {
- return isa<ComplexType>(CanonicalType);
+ return isa<ComplexType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isVectorType() const {
return isa<VectorType>(CanonicalType.getUnqualifiedType());
@@ -1326,13 +1318,13 @@ inline bool Type::isExtVectorType() const {
return isa<ExtVectorType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isObjCInterfaceType() const {
- return isa<ObjCInterfaceType>(CanonicalType);
+ return isa<ObjCInterfaceType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isObjCQualifiedInterfaceType() const {
- return isa<ObjCQualifiedInterfaceType>(CanonicalType);
+ return isa<ObjCQualifiedInterfaceType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isObjCQualifiedIdType() const {
- return isa<ObjCQualifiedIdType>(CanonicalType);
+ return isa<ObjCQualifiedIdType>(CanonicalType.getUnqualifiedType());
}
} // end namespace clang
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 47a3e3ac67..002a51f877 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -375,7 +375,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo,
// 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 @@ QualType ASTContext::getPointerDiffType() const {
/// 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 @@ QualType ASTContext::getCanonicalType(QualType T) {
///
/// 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::getObjCEncodingForMethodDecl(ObjCMethodDecl *Decl,
}
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 @@ void ASTContext::getObjCEncodingForType(QualType T, std::string& S,
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))
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 60b762f66d..21f2b07d13 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -466,14 +466,17 @@ Expr::isModifiableLvalueResult Expr::isModifiableLvalue(ASTContext &Ctx) const {
case LV_DuplicateVectorComponents: return MLV_DuplicateVectorComponents;
case LV_InvalidExpression: return MLV_InvalidExpression;
}
- if (TR.isConstQualified())
+
+ QualType CT = Ctx.getCanonicalType(getType());
+
+ if (CT.isConstQualified())
return MLV_ConstQualified;
- if (TR->isArrayType())
+ if (CT->isArrayType())
return MLV_ArrayType;
- if (TR->isIncompleteType())
+ if (CT->isIncompleteType())
return MLV_IncompleteType;
- if (const RecordType *r = TR->getAsRecordType()) {
+ if (const RecordType *r = CT->getAsRecordType()) {
if (r->hasConstFields())
return MLV_ConstQualified;
}
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index d32f963acb..f9f6ecac07 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -35,6 +35,45 @@ void VariableArrayType::Destroy(ASTContext& C) {
delete this;
}
+
+/// getArrayElementTypeNoTypeQual - If this is an array type, return the
+/// element type of the array, potentially with type qualifiers missing.
+/// This method should never be used when type qualifiers are meaningful.
+const Type *Type::getArrayElementTypeNoTypeQual() const {
+ // If this is directly an array type, return it.
+ if (const ArrayType *ATy = dyn_cast<ArrayType>(this))
+ return ATy->getElementType().getTypePtr();
+
+ // If the canonical form of this type isn't the right kind, reject it.
+ if (!isa<ArrayType>(CanonicalType)) {
+ // Look through type qualifiers
+ if (ArrayType *AT = dyn_cast<ArrayType>(CanonicalType.getUnqualifiedType()))
+ return AT->getElementType().getTypePtr();
+ return 0;
+ }
+
+ // If this is a typedef for an array type, strip the typedef off without
+ // losing all typedef information.
+ return getDesugaredType()->getArrayElementTypeNoTypeQual();
+}
+
+/// getDesugaredType - Return the specified type with any "sugar" removed from
+/// type type. This takes off typedefs, typeof's etc. If the outer level of
+/// the type is already concrete, it returns it unmodified. This is similar
+/// to getting the canonical type, but it doesn't remove *all* typedefs. For
+/// example, it return "T*" as "T*", (not as "int*"), because the pointer is
+/// concrete.
+QualType Type::getDesugaredType() const {
+ if (const TypedefType *TDT = dyn_cast<TypedefType>(this))
+ return TDT->LookThroughTypedefs();
+ if (const TypeOfExpr *TOE = dyn_cast<TypeOfExpr>(this))
+ return TOE->getUnderlyingExpr()->getType();
+ if (const TypeOfType *TOT = dyn_cast<TypeOfType>(this))
+ return TOT->getUnderlyingType();
+ // FIXME: remove this cast.
+ return QualType(const_cast<Type*>(this), 0);
+}
+
/// isVoidType - Helper method to determine if this is the 'void' type.
bool Type::isVoidType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
@@ -118,23 +157,6 @@ const ComplexType *Type::getAsComplexIntegerType() const {
return getDesugaredType()->getAsComplexIntegerType();
}
-/// getDesugaredType - Return the specified type with any "sugar" removed from
-/// type type. This takes off typedefs, typeof's etc. If the outer level of
-/// the type is already concrete, it returns it unmodified. This is similar
-/// to getting the canonical type, but it doesn't remove *all* typedefs. For
-/// example, it return "T*" as "T*", (not as "int*"), because the pointer is
-/// concrete.
-const Type *Type::getDesugaredType() const {
- if (const TypedefType *TDT = dyn_cast<TypedefType>(this))
- return TDT->LookThroughTypedefs().getTypePtr();
- if (const TypeOfExpr *TOE = dyn_cast<TypeOfExpr>(this))
- return TOE->getUnderlyingExpr()->getType().getTypePtr();
- if (const TypeOfType *TOT = dyn_cast<TypeOfType>(this))
- return TOT->getUnderlyingType().getTypePtr();
- return this;
-}
-
-
const BuiltinType *Type::getAsBuiltinType() const {
// If this is directly a builtin type, return it.
if (const BuiltinType *BTy = dyn_cast<BuiltinType>(this))
@@ -230,71 +252,17 @@ const ReferenceType *Type::getAsReferenceType() const {
return getDesugaredType()->getAsReferenceType();
}
-const ArrayType *Type::getAsArrayType() const {
- // If this is directly an array type, return it.
- if (const ArrayType *ATy = dyn_cast<ArrayType>(this))
- return ATy;
-
- // If the canonical form of this type isn't the right kind, reject it.
- if (!isa<ArrayType>(CanonicalType)) {
- // Look through type qualifiers
- if (isa<ArrayType>(CanonicalType.getUnqualifiedType()))
- return CanonicalType.getUnqualifiedType()->getAsArrayType();
- return 0;
- }
-
- // If this is a typedef for an array type, strip the typedef off without
- // losing all typedef information.
- return getDesugaredType()->getAsArrayType();
-}
-
-const ConstantArrayType *Type::getAsConstantArrayType() const {
- // If this is directly a constant array type, return it.
- if (const ConstantArrayType *ATy = dyn_cast<ConstantArrayType>(this))
- return ATy;
-
- // If the canonical form of this type isn't the right kind, reject it.
- if (!isa<ConstantArrayType>(CanonicalType)) {
- // Look through type qualifiers
- if (isa<ConstantArrayType>(CanonicalType.getUnqualifiedType()))
- return CanonicalType.getUnqualifiedType()->getAsConstantArrayType();
- return 0;
- }
-
- // If this is a typedef for a constant array type, strip the typedef off
- // without losing all typedef information.
- return getDesugaredType()->getAsConstantArrayType();
-}
-
-const VariableArrayType *Type::getAsVariableArrayType() const {
- // If this is directly a variable array type, return it.
- if (const VariableArrayType *ATy = dyn_cast<VariableArrayType>(this))
- return ATy;
-
- // If the canonical form of this type isn't the right kind, reject it.
- if (!isa<VariableArrayType>(CanonicalType)) {
- // Look through type qualifiers
- if (isa<VariableArrayType>(CanonicalType.getUnqualifiedType()))
- return CanonicalType.getUnqualifiedType()->getAsVariableArrayType();
- return 0;
- }
-
- // If this is a typedef for a variable array type, strip the typedef off
- // without losing all typedef information.
- return getDesugaredType()->getAsVariableArrayType();
-}
-
/// isVariablyModifiedType (C99 6.7.5p3) - Return true for variable length
/// array types and types that contain variable array types in their
/// declarator
bool Type::isVariablyModifiedType() const {
- // A VLA is a veriably modified type
- if (getAsVariableArrayType())
+ // A VLA is a variably modified type.
+ if (isVariableArrayType())
return true;
// An array can contain a variably modified type
- if (const ArrayType* AT = getAsArrayType())
- return AT->getElementType()->isVariablyModifiedType();
+ if (const Type *T = getArrayElementTypeNoTypeQual())
+ return T->isVariablyModifiedType();
// A pointer can point to a variably modified type
if (const PointerType* PT = getAsPointerType())
@@ -310,28 +278,6 @@ bool Type::isVariablyModifiedType() const {
return false;
}
-bool Type::isIncompleteArrayType() const {
- return isa<IncompleteArrayType>(CanonicalType);
-}
-
-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;
- }
-
- // 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 {
// If this is directly a reference type, return it.
if (const RecordType *RTy = dyn_cast<RecordType>(this))
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index d232fd9560..0b63463d1f 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -108,10 +108,8 @@ CGDebugInfo::~CGDebugInfo()
delete GlobalVariableAnchor;
}
-void CGDebugInfo::setLocation(SourceLocation loc)
-{
- SourceManager &SM = M->getContext().getSourceManager();
- CurLoc = SM.getLogicalLoc(loc);
+void CGDebugInfo::setLocation(SourceLocation loc) {
+ CurLoc = M->getContext().getSourceManager().getLogicalLoc(loc);
}
/// getCastValueFor - Return a llvm representation for a given debug information
@@ -481,20 +479,20 @@ CGDebugInfo::getOrCreateArrayType(QualType type, llvm::CompileUnitDesc *Unit)
// Add the dimensions of the array.
std::vector<llvm::DebugInfoDesc *> &Elements = ArrayTy->getElements();
do {
+ const ArrayType *AT = M->getContext().getAsArrayType(type);
llvm::SubrangeDesc *Subrange = new llvm::SubrangeDesc();
// push it back on the subrange desc list so that we can free it later.
SubrangeDescList.push_back(Subrange);
uint64_t Upper = 0;
- if (type->getTypeClass() == Type::ConstantArray) {
- const ConstantArrayType *ConstArrTy = type->getAsConstantArrayType();
+ if (const ConstantArrayType *ConstArrTy = dyn_cast<ConstantArrayType>(AT)) {
Upper = ConstArrTy->getSize().getZExtValue() - 1;
}
Subrange->setLo(0);
Subrange->setHi(Upper);
Elements.push_back(Subrange);
- type = type->getAsArrayType()->getElementType();
+ type = AT->getElementType();
} while (type->isArrayType());
ArrayTy->setFromType(getOrCreateType(type, Unit));
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 1fd616c648..ca52b070dd 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -429,7 +429,8 @@ LValue CodeGenFunction::EmitStringLiteralLValue(const StringLiteral *E) {
std::string StringLiteral(StrData, StrData+Len);
// Resize the string to the right size
- const ConstantArrayType *CAT = E->getType()->getAsConstantArrayType();
+ const ConstantArrayType *CAT =
+ getContext().getAsConstantArrayType(E->getType());
uint64_t RealLen = CAT->getSize().getZExtValue();
StringLiteral.resize(RealLen, '\0');
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 815e296e79..df90ee09f5 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -393,11 +393,10 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
}
uint64_t NumArrayElements = AType->getNumElements();
- QualType ElementType = E->getType()->getAsArrayType()->getElementType();
+ QualType ElementType = CGF.getContext().getCanonicalType(E->getType());
+ ElementType =CGF.getContext().getAsArrayType(ElementType)->getElementType();
- unsigned CVRqualifier =
- CGF.getContext().getCanonicalType(E->getType())->getAsArrayType()
- ->getElementType().getCVRQualifiers();
+ unsigned CVRqualifier = ElementType.getCVRQualifiers();
for (uint64_t i = 0; i != NumArrayElements; ++i) {
llvm::Value *NextVal = Builder.CreateStructGEP(DestPtr, i, ".array");
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index 681993a5d4..d58d004607 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -85,7 +85,7 @@ public:
unsigned NumInitElements = ILE->getNumInits();
// FIXME: Check for wide strings
if (NumInitElements > 0 && isa<StringLiteral>(ILE->getInit(0)) &&
- ILE->getType()->getAsArrayType()->getElementType()->isCharType())
+ ILE->getType()->getArrayElementTypeNoTypeQual()->isCharType())
return Visit(ILE->getInit(0));
const llvm::Type *ElemTy = AType->getElementType();
unsigned NumElements = AType->getNumElements();
@@ -332,9 +332,7 @@ public:
llvm::Constant *Idx0 = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);
llvm::Constant *Ops[] = {Idx0, Idx0};
C = llvm::ConstantExpr::getGetElementPtr(C, Ops, 2);
-
- QualType ElemType = SType->getAsArrayType()->getElementType();
- T = CGM.getContext().getPointerType(ElemType);
+ T = CGM.getContext().getArrayDecayedType(SType);
} else if (SType->isFunctionType()) {
// Function types decay to a pointer to the function
C = EmitLValue(SExpr);
@@ -357,7 +355,8 @@ public:
// Otherwise this must be a string initializing an array in a static
// initializer. Don't emit it as the address of the string, emit the string
// data itself as an inline array.
- const ConstantArrayType *CAT = E->getType()->getAsConstantArrayType();
+ const ConstantArrayType *CAT =
+ CGM.getContext().getAsConstantArrayType(E->getType());
assert(CAT && "String isn't pointer or array!");
std::string Str(StrData, StrData + Len);
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index b531616b13..5d85b7a70f 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -632,7 +632,8 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
// FIXME: This is silly; getTypeAlign should just work for incomplete arrays
unsigned Align;
- if (const IncompleteArrayType* IAT = D->getType()->getAsIncompleteArrayType())
+ if (const IncompleteArrayType* IAT =
+ Context.getAsIncompleteArrayType(D->getType()))
Align = Context.getTypeAlign(IAT->getElementType());
else
Align = Context.getTypeAlign(D->getType());
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp