diff options
-rw-r--r-- | include/clang/AST/ASTContext.h | 17 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 76 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 171 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 11 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 140 | ||||
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 12 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 7 | ||||
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 9 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 22 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 9 | ||||
-rw-r--r-- | test/Sema/typedef-retain.c | 16 |
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 index f8835ffa8c..e9343e3989 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -386,8 +386,8 @@ Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, bool &Redeclaration) { /// definition that would be otherwise equivalent. static bool areEquivalentArrayTypes(QualType NewQType, QualType OldQType, ASTContext &Context) { - const ArrayType *NewAT = NewQType->getAsArrayType(); - const ArrayType *OldAT = OldQType->getAsArrayType(); + const ArrayType *NewAT = Context.getAsArrayType(NewQType); + const ArrayType *OldAT = Context.getAsArrayType(OldQType); if (!NewAT || !OldAT) return false; @@ -549,7 +549,9 @@ bool Sema::CheckSingleInitializer(Expr *&Init, QualType DeclType) { } bool Sema::CheckStringLiteralInit(StringLiteral *strLiteral, QualType &DeclT) { - if (const IncompleteArrayType *IAT = DeclT->getAsIncompleteArrayType()) { + const ArrayType *AT = Context.getAsArrayType(DeclT); + + if (const |