diff options
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r-- | lib/AST/ASTContext.cpp | 507 |
1 files changed, 378 insertions, 129 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index e028186..7f5fa35 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -40,7 +40,8 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, bool FreeMem, unsigned size_reserve) : GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0), ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0), - sigjmp_bufDecl(0), SourceMgr(SM), LangOpts(LOpts), + sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0), + SourceMgr(SM), LangOpts(LOpts), LoadedExternalComments(false), FreeMemory(FreeMem), Target(t), Idents(idents), Selectors(sels), BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) { @@ -554,10 +555,6 @@ ASTContext::getTypeInfo(const Type *T) { assert(false && "Should not see dependent types"); break; - case Type::ObjCProtocolList: - assert(false && "Should not see protocol list types"); - break; - case Type::FunctionNoProto: case Type::FunctionProto: // GCC extension: alignof(function) = 32 bits @@ -571,8 +568,6 @@ ASTContext::getTypeInfo(const Type *T) { Align = getTypeAlign(cast<ArrayType>(T)->getElementType()); break; - case Type::ConstantArrayWithExpr: - case Type::ConstantArrayWithoutExpr: case Type::ConstantArray: { const ConstantArrayType *CAT = cast<ConstantArrayType>(T); @@ -583,14 +578,16 @@ ASTContext::getTypeInfo(const Type *T) { } case Type::ExtVector: case Type::Vector: { - std::pair<uint64_t, unsigned> EltInfo = - getTypeInfo(cast<VectorType>(T)->getElementType()); - Width = EltInfo.first*cast<VectorType>(T)->getNumElements(); + const VectorType *VT = cast<VectorType>(T); + std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(VT->getElementType()); + Width = EltInfo.first*VT->getNumElements(); Align = Width; // If the alignment is not a power of 2, round up to the next power of 2. // This happens for non-power-of-2 length vectors. - // FIXME: this should probably be a target property. - Align = 1 << llvm::Log2_32_Ceil(Align); + if (VT->getNumElements() & (VT->getNumElements()-1)) { + Align = llvm::NextPowerOf2(Align); + Width = llvm::RoundUpToAlignment(Width, Align); + } break; } @@ -749,9 +746,13 @@ ASTContext::getTypeInfo(const Type *T) { break; } - case Type::Elaborated: { - return getTypeInfo(cast<ElaboratedType>(T)->getUnderlyingType().getTypePtr()); - } + case Type::SubstTemplateTypeParm: + return getTypeInfo(cast<SubstTemplateTypeParmType>(T)-> + getReplacementType().getTypePtr()); + + case Type::Elaborated: + return getTypeInfo(cast<ElaboratedType>(T)->getUnderlyingType() + .getTypePtr()); case Type::Typedef: { const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl(); @@ -940,8 +941,14 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD, /// \param T the type that will be the basis for type source info. This type /// should refer to how the declarator was written in source code, not to /// what type semantic analysis resolved the declarator to. -DeclaratorInfo *ASTContext::CreateDeclaratorInfo(QualType T) { - unsigned DataSize = TypeLoc::getFullDataSizeForType(T); +DeclaratorInfo *ASTContext::CreateDeclaratorInfo(QualType T, + unsigned DataSize) { + if (!DataSize) + DataSize = TypeLoc::getFullDataSizeForType(T); + else + assert(DataSize == TypeLoc::getFullDataSizeForType(T) && + "incorrect data size provided to CreateDeclaratorInfo!"); + DeclaratorInfo *DInfo = (DeclaratorInfo*)BumpAlloc.Allocate(sizeof(DeclaratorInfo) + DataSize, 8); new (DInfo) DeclaratorInfo(T); @@ -1140,7 +1147,7 @@ QualType ASTContext::getComplexType(QualType T) { // If the pointee type isn't canonical, this won't be a canonical type either, // so fill in the canonical type field. QualType Canonical; - if (!T->isCanonical()) { + if (!T.isCanonical()) { Canonical = getComplexType(getCanonicalType(T)); // Get the new insert position for the node we care about. @@ -1177,7 +1184,7 @@ QualType ASTContext::getPointerType(QualType T) { // If the pointee type isn't canonical, this won't be a canonical type either, // so fill in the canonical type field. QualType Canonical; - if (!T->isCanonical()) { + if (!T.isCanonical()) { Canonical = getPointerType(getCanonicalType(T)); // Get the new insert position for the node we care about. @@ -1207,7 +1214,7 @@ QualType ASTContext::getBlockPointerType(QualType T) { // If the block pointee type isn't canonical, this won't be a canonical // type either so fill in the canonical type field. QualType Canonical; - if (!T->isCanonical()) { + if (!T.isCanonical()) { Canonical = getBlockPointerType(getCanonicalType(T)); // Get the new insert position for the node we care about. @@ -1224,22 +1231,25 @@ QualType ASTContext::getBlockPointerType(QualType T) { /// getLValueReferenceType - Return the uniqued reference to the type for an /// lvalue reference to the specified type. -QualType ASTContext::getLValueReferenceType(QualType T) { +QualType ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) { // Unique pointers, to guarantee there is only one pointer of a particular // structure. llvm::FoldingSetNodeID ID; - ReferenceType::Profile(ID, T); + ReferenceType::Profile(ID, T, SpelledAsLValue); void *InsertPos = 0; if (LValueReferenceType *RT = LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(RT, 0); + const ReferenceType *InnerRef = T->getAs<ReferenceType>(); + // If the referencee type isn't canonical, this won't be a canonical type // either, so fill in the canonical type field. QualType Canonical; - if (!T->isCanonical()) { - Canonical = getLValueReferenceType(getCanonicalType(T)); + if (!SpelledAsLValue || InnerRef || !T.isCanonical()) { + QualType PointeeType = (InnerRef ? InnerRef->getPointeeType() : T); + Canonical = getLValueReferenceType(getCanonicalType(PointeeType)); // Get the new insert position for the node we care about. LValueReferenceType *NewIP = @@ -1248,9 +1258,11 @@ QualType ASTContext::getLValueReferenceType(QualType T) { } LValueReferenceType *New - = new (*this, TypeAlignment) LValueReferenceType(T, Canonical); + = new (*this, TypeAlignment) LValueReferenceType(T, Canonical, + SpelledAsLValue); Types.push_back(New); LValueReferenceTypes.InsertNode(New, InsertPos); + return QualType(New, 0); } @@ -1260,18 +1272,21 @@ QualType ASTContext::getRValueReferenceType(QualType T) { // Unique pointers, to guarantee there is only one pointer of a particular // structure. llvm::FoldingSetNodeID ID; - ReferenceType::Profile(ID, T); + ReferenceType::Profile(ID, T, false); void *InsertPos = 0; if (RValueReferenceType *RT = RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(RT, 0); + const ReferenceType *InnerRef = T->getAs<ReferenceType>(); + // If the referencee type isn't canonical, this won't be a canonical type // either, so fill in the canonical type field. QualType Canonical; - if (!T->isCanonical()) { - Canonical = getRValueReferenceType(getCanonicalType(T)); + if (InnerRef || !T.isCanonical()) { + QualType PointeeType = (InnerRef ? InnerRef->getPointeeType() : T); + Canonical = getRValueReferenceType(getCanonicalType(PointeeType)); // Get the new insert position for the node we care about. RValueReferenceType *NewIP = @@ -1302,7 +1317,7 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) { // If the pointee or class type isn't canonical, this won't be a canonical // type either, so fill in the canonical type field. QualType Canonical; - if (!T->isCanonical()) { + if (!T.isCanonical()) { Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(Cls)); // Get the new insert position for the node we care about. @@ -1342,7 +1357,7 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, // 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()) { + if (!EltTy.isCanonical()) { Canonical = getConstantArrayType(getCanonicalType(EltTy), ArySize, ASM, EltTypeQuals); // Get the new insert position for the node we care about. @@ -1358,53 +1373,6 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, return QualType(New, 0); } -/// getConstantArrayWithExprType - Return a reference to the type for -/// an array of the specified element type. -QualType -ASTContext::getConstantArrayWithExprType(QualType EltTy, - const llvm::APInt &ArySizeIn, - Expr *ArySizeExpr, - ArrayType::ArraySizeModifier ASM, - unsigned EltTypeQuals, - SourceRange Brackets) { - // Convert the array size into a canonical width matching the pointer - // size for the target. - llvm::APInt ArySize(ArySizeIn); - ArySize.zextOrTrunc(Target.getPointerWidth(EltTy.getAddressSpace())); - - // Compute the canonical ConstantArrayType. - QualType Canonical = getConstantArrayType(getCanonicalType(EltTy), - ArySize, ASM, EltTypeQuals); - // Since we don't unique expressions, it isn't possible to unique VLA's - // that have an expression provided for their size. - ConstantArrayWithExprType *New = new(*this, TypeAlignment) - ConstantArrayWithExprType(EltTy, Canonical, ArySize, ArySizeExpr, - ASM, EltTypeQuals, Brackets); - Types.push_back(New); - return QualType(New, 0); -} - -/// getConstantArrayWithoutExprType - Return a reference to the type for -/// an array of the specified element type. -QualType -ASTContext::getConstantArrayWithoutExprType(QualType EltTy, - const llvm::APInt &ArySizeIn, - ArrayType::ArraySizeModifier ASM, - unsigned EltTypeQuals) { - // Convert the array size into a canonical width matching the pointer - // size for the target. - llvm::APInt ArySize(ArySizeIn); - ArySize.zextOrTrunc(Target.getPointerWidth(EltTy.getAddressSpace())); - - // Compute the canonical ConstantArrayType. - QualType Canonical = getConstantArrayType(getCanonicalType(EltTy), - ArySize, ASM, EltTypeQuals); - ConstantArrayWithoutExprType *New = new(*this, TypeAlignment) - ConstantArrayWithoutExprType(EltTy, Canonical, ArySize, ASM, EltTypeQuals); - Types.push_back(New); - return QualType(New, 0); -} - /// getVariableArrayType - Returns a non-unique reference to the type for a /// variable array of the specified element type. QualType ASTContext::getVariableArrayType(QualType EltTy, @@ -1484,7 +1452,7 @@ QualType ASTContext::getIncompleteArrayType(QualType EltTy, // either, so fill in the canonical type field. QualType Canonical; - if (!EltTy->isCanonical()) { + if (!EltTy.isCanonical()) { Canonical = getIncompleteArrayType(getCanonicalType(EltTy), ASM, EltTypeQuals); @@ -1520,7 +1488,7 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts) { // 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 (!vecType->isCanonical()) { + if (!vecType.isCanonical()) { Canonical = getVectorType(getCanonicalType(vecType), NumElts); // Get the new insert position for the node we care about. @@ -1552,7 +1520,7 @@ QualType ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) { // 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 (!vecType->isCanonical()) { + if (!vecType.isCanonical()) { Canonical = getExtVectorType(getCanonicalType(vecType), NumElts); // Get the new insert position for the node we care about. @@ -1616,7 +1584,7 @@ QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn) { return QualType(FT, 0); QualType Canonical; - if (!ResultTy->isCanonical()) { + if (!ResultTy.isCanonical()) { Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), NoReturn); // Get the new insert position for the node we care about. @@ -1639,12 +1607,6 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray, unsigned TypeQuals, bool hasExceptionSpec, bool hasAnyExceptionSpec, unsigned NumExs, const QualType *ExArray, bool NoReturn) { - if (LangOpts.CPlusPlus) { - for (unsigned i = 0; i != NumArgs; ++i) - assert(!ArgArray[i].hasQualifiers() && - "C++ arguments can't have toplevel qualifiers!"); - } - // Unique functions, to guarantee there is only one function of a particular // structure. llvm::FoldingSetNodeID ID; @@ -1658,11 +1620,9 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray, return QualType(FTP, 0); // Determine whether the type being created is already canonical or not. - bool isCanonical = ResultTy->isCanonical(); - if (hasExceptionSpec) - isCanonical = false; + bool isCanonical = !hasExceptionSpec && ResultTy.isCanonical(); for (unsigned i = 0; i != NumArgs && isCanonical; ++i) - if (!ArgArray[i]->isCanonical()) + if (!ArgArray[i].isCanonicalAsParam()) isCanonical = false; // If this type isn't canonical, get the canonical version of it. @@ -1672,7 +1632,7 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray, llvm::SmallVector<QualType, 16> CanonicalArgs; CanonicalArgs.reserve(NumArgs); for (unsigned i = 0; i != NumArgs; ++i) - CanonicalArgs.push_back(getCanonicalType(ArgArray[i])); + CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i])); Canonical = getFunctionType(getCanonicalType(ResultTy), CanonicalArgs.data(), NumArgs, @@ -1743,6 +1703,29 @@ QualType ASTContext::getTypedefType(TypedefDecl *Decl) { return QualType(Decl->TypeForDecl, 0); } +/// \brief Retrieve a substitution-result type. +QualType +ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm, + QualType Replacement) { + assert(Replacement.isCanonical() + && "replacement types must always be canonical"); + + llvm::FoldingSetNodeID ID; + SubstTemplateTypeParmType::Profile(ID, Parm, Replacement); + void *InsertPos = 0; + SubstTemplateTypeParmType *SubstParm + = SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); + + if (!SubstParm) { + SubstParm = new (*this, TypeAlignment) + SubstTemplateTypeParmType(Parm, Replacement); + Types.push_back(SubstParm); + SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos); + } + + return QualType(SubstParm, 0); +} + /// \brief Retrieve the template type parameter type for a template /// parameter or parameter pack with the given depth, index, and (optionally) /// name. @@ -1933,7 +1916,17 @@ static bool CmpProtocolNames(const ObjCProtocolDecl *LHS, return LHS->getDeclName() < RHS->getDeclName(); } -static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols, +static bool areSortedAndUniqued(ObjCProtocolDecl **Protocols, + unsigned NumProtocols) { + if (NumProtocols == 0) return true; + + for (unsigned i = 1; i != NumProtocols; ++i) + if (!CmpProtocolNames(Protocols[i-1], Protocols[i])) + return false; + return true; +} + +static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols, unsigned &NumProtocols) { ObjCProtocolDecl **ProtocolsEnd = Protocols+NumProtocols; @@ -1950,10 +1943,6 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols, QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT, ObjCProtocolDecl **Protocols, unsigned NumProtocols) { - // Sort the protocol list alphabetically to canonicalize it. - if (NumProtocols) - SortAndUniqueProtocols(Protocols, NumProtocols); - llvm::FoldingSetNodeID ID; ObjCObjectPointerType::Profile(ID, InterfaceT, Protocols, NumProtocols); @@ -1962,9 +1951,31 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT, ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(QT, 0); + // Sort the protocol list alphabetically to canonicalize it. + QualType Canonical; + if (!InterfaceT.isCanonical() || + !areSortedAndUniqued(Protocols, NumProtocols)) { + if (!areSortedAndUniqued(Protocols, NumProtocols)) { + llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(NumProtocols); + unsigned UniqueCount = NumProtocols; + + std::copy(Protocols, Protocols + NumProtocols, Sorted.begin()); + SortAndUniqueProtocols(&Sorted[0], UniqueCount); + + Canonical = getObjCObjectPointerType(getCanonicalType(InterfaceT), + &Sorted[0], UniqueCount); + } else { + Canonical = getObjCObjectPointerType(getCanonicalType(InterfaceT), + Protocols, NumProtocols); + } + + // Regenerate InsertPos. + ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos); + } + // No Match; ObjCObjectPointerType *QType = new (*this, TypeAlignment) - ObjCObjectPointerType(InterfaceT, Protocols, NumProtocols); + ObjCObjectPointerType(Canonical, InterfaceT, Protocols, NumProtocols); Types.push_back(QType); ObjCObjectPointerTypes.InsertNode(QType, InsertPos); @@ -1975,10 +1986,6 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT, /// specified ObjC interface decl. The list of protocols is optional. QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCProtocolDecl **Protocols, unsigned NumProtocols) { - if (NumProtocols) - // Sort the protocol list alphabetically to canonicalize it. - SortAndUniqueProtocols(Protocols, NumProtocols); - llvm::FoldingSetNodeID ID; ObjCInterfaceType::Profile(ID, Decl, Protocols, NumProtocols); @@ -1987,31 +1994,26 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(QT, 0); - // No Match; - ObjCInterfaceType *QType = new (*this, TypeAlignment) - ObjCInterfaceType(const_cast<ObjCInterfaceDecl*>(Decl), - Protocols, NumProtocols); - Types.push_back(QType); - ObjCInterfaceTypes.InsertNode(QType, InsertPos); - return QualType(QType, 0); -} + // Sort the protocol list alphabetically to canonicalize it. + QualType Canonical; + if (NumProtocols && !areSortedAndUniqued(Protocols, NumProtocols)) { + llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(NumProtocols); + std::copy(Protocols, Protocols + NumProtocols, Sorted.begin()); -QualType ASTContext::getObjCProtocolListType(QualType T, - ObjCProtocolDecl **Protocols, - unsigned NumProtocols) { - llvm::FoldingSetNodeID ID; - ObjCProtocolListType::Profile(ID, T, Protocols, NumProtocols); + unsigned UniqueCount = NumProtocols; + SortAndUniqueProtocols(&Sorted[0], UniqueCount); - void *InsertPos = 0; - if (ObjCProtocolListType *QT = - ObjCProtocolListTypes.FindNodeOrInsertPos(ID, InsertPos)) - return QualType(QT, 0); + Canonical = getObjCInterfaceType(Decl, &Sorted[0], UniqueCount); + + ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos); + } + + ObjCInterfaceType *QType = new (*this, TypeAlignment) + ObjCInterfaceType(Canonical, const_cast<ObjCInterfaceDecl*>(Decl), + Protocols, NumProtocols); - // No Match; - ObjCProtocolListType *QType = new (*this, TypeAlignment) - ObjCProtocolListType(T, Protocols, NumProtocols); Types.push_back(QType); - ObjCProtocolListTypes.InsertNode(QType, InsertPos); + ObjCInterfaceTypes.InsertNode(QType, InsertPos); return QualType(QType, 0); } @@ -2168,6 +2170,24 @@ QualType ASTContext::getPointerDiffType() const { // Type Operators //===----------------------------------------------------------------------===// +CanQualType ASTContext::getCanonicalParamType(QualType T) { + // Push qualifiers into arrays, and then discard any remaining + // qualifiers. + T = getCanonicalType(T); + const Type *Ty = T.getTypePtr(); + + QualType Result; + if (isa<ArrayType>(Ty)) { + Result = getArrayDecayedType(QualType(Ty,0)); + } else if (isa<FunctionType>(Ty)) { + Result = getPointerType(QualType(Ty, 0)); + } else { + Result = QualType(Ty, 0); + } + + return CanQualType::CreateUnsafe(Result); +} + /// getCanonicalType - Return the canonical (structural) type corresponding to /// the specified potentially non-canonical type. The non-canonical version /// of a type may have many "decorated" versions of types. Decorators can @@ -2512,7 +2532,7 @@ int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) { /// routine will assert if passed a built-in type that isn't an integer or enum, /// or if it is not canonicalized. unsigned ASTContext::getIntegerRank(Type *T) { - assert(T->isCanonical() && "T should be canonicalized"); + assert(T->isCanonicalUnqualified() && "T should be canonicalized"); if (EnumType* ET = dyn_cast<EnumType>(T)) T = ET->getDecl()->getIntegerType().getTypePtr(); @@ -2713,6 +2733,226 @@ QualType ASTContext::getObjCFastEnumerationStateType() { return getTagDeclType(ObjCFastEnumerationStateTypeDecl); } +QualType ASTContext::getBlockDescriptorType() { + if (BlockDescriptorType) + return getTagDeclType(BlockDescriptorType); + + RecordDecl *T; + // FIXME: Needs the FlagAppleBlock bit. + T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + &Idents.get("__block_descriptor")); + + QualType FieldTypes[] = { + UnsignedLongTy, + UnsignedLongTy, + }; + + const char *FieldNames[] = { + "reserved", + "Size" + }; + + for (size_t i = 0; i < 2; ++i) { + FieldDecl *Field = FieldDecl::Create(*this, + T, + SourceLocation(), + &Idents.get(FieldNames[i]), + FieldTypes[i], /*DInfo=*/0, + /*BitWidth=*/0, + /*Mutable=*/false); + T->addDecl(Field); + } + + T->completeDefinition(*this); + + BlockDescriptorType = T; + + return getTagDeclType(BlockDescriptorType); +} + +void ASTContext::setBlockDescriptorType(QualType T) { + const RecordType *Rec = T->getAs<RecordType>(); + assert(Rec && "Invalid BlockDescriptorType"); + BlockDescriptorType = Rec->getDecl(); +} + +QualType ASTContext::getBlockDescriptorExtendedType() { + if (BlockDescriptorExtendedType) + return getTagDeclType(BlockDescriptorExtendedType); + + RecordDecl *T; + // FIXME: Needs the FlagAppleBlock bit. + T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + &Idents.get("__block_descriptor_withcopydispose")); + + QualType FieldTypes[] = { + UnsignedLongTy, + UnsignedLongTy, + getPointerType(VoidPtrTy), + getPointerType(VoidPtrTy) + }; + + const char *FieldNames[] = { + "reserved", + "Size", + "CopyFuncPtr", + "DestroyFuncPtr" + }; + + for (size_t i = 0; i < 4; ++i) { + FieldDecl *Field = FieldDecl::Create(*this, + T, + SourceLocation(), + &Idents.get(FieldNames[i]), + FieldTypes[i], /*DInfo=*/0, + /*BitWidth=*/0, + /*Mutable=*/false); + T->addDecl(Field); + } + + T->completeDefinition(*this); + + BlockDescriptorExtendedType = T; + + return getTagDeclType(BlockDescriptorExtendedType); +} + +void ASTContext::setBlockDescriptorExtendedType(QualType T) { + const RecordType *Rec = T->getAs<RecordType>(); + assert(Rec && "Invalid BlockDescriptorType"); + BlockDescriptorExtendedType = Rec->getDecl(); +} + +bool ASTContext::BlockRequiresCopying(QualType Ty) { + if (Ty->isBlockPointerType()) + return true; + if (isObjCNSObjectType(Ty)) + return true; + if (Ty->isObjCObjectPointerType()) + return true; + return false; +} + +QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) { + // type = struct __Block_byref_1_X { + // void *__isa; + // struct __Block_byref_1_X *__forwarding; + // unsigned int __flags; + // unsigned int __size; + // void *__copy_helper; // as needed + // void *__destroy_help // as needed + // int X; + // } * + + bool HasCopyAndDispose = BlockRequiresCopying(Ty); + + // FIXME: Move up + static int UniqueBlockByRefTypeID = 0; + char Name[36]; + sprintf(Name, "__Block_byref_%d_%s", ++UniqueBlockByRefTypeID, DeclName); + RecordDecl *T; + T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + &Idents.get(Name)); + T->startDefinition(); + QualType Int32Ty = IntTy; + assert(getIntWidth(IntTy) == 32 && "non-32bit int not supported"); + QualType FieldTypes[] = { + getPointerType(VoidPtrTy), + getPointerType(getTagDeclType(T)), + Int32Ty, + Int32Ty, + getPointerType(VoidPtrTy), + getPointerType(VoidPtrTy), + Ty + }; + + const char *FieldNames[] = { + "__isa", + "__forwarding", + "__flags", + "__size", + "__copy_helper", + "__destroy_helper", + DeclName, + }; + + for (size_t i = 0; i < 7; ++i) { + if (!HasCopyAndDispose && i >=4 && i <= 5) + continue; + FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), + &Idents.get(FieldNames[i]), + FieldTypes[i], /*DInfo=*/0, + /*BitWidth=*/0, /*Mutable=*/false); + T->addDecl(Field); + } + + T->completeDefinition(*this); + + return getPointerType(getTagDeclType(T)); +} + + +QualType ASTContext::getBlockParmType( + bool BlockHasCopyDispose, + llvm::SmallVector<const Expr *, 8> &BlockDeclRefDecls) { + // FIXME: Move up + static int UniqueBlockParmTypeID = 0; + char Name[36]; + sprintf(Name, "__block_literal_%u", ++UniqueBlockParmTypeID); + RecordDecl *T; + T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), + &Idents.get(Name)); + QualType FieldTypes[] = { + getPointerType(VoidPtrTy), + IntTy, + IntTy, + getPointerType(VoidPtrTy), + (BlockHasCopyDispose ? + getPointerType(getBlockDescriptorExtendedType()) : + getPointerType(getBlockDescriptorType())) + }; + + const char *FieldNames[] = { + "__isa", + "__flags", + "__reserved", + "__FuncPtr", + "__descriptor" + }; + + for (size_t i = 0; i < 5; ++i) { + FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), + &Idents.get(FieldNames[i]), + FieldTypes[i], /*DInfo=*/0, + /*BitWidth=*/0, /*Mutable=*/false); + T->addDecl(Field); + } + + for (size_t i = 0; i < BlockDeclRefDecls.size(); ++i) { + const Expr *E = BlockDeclRefDecls[i]; + const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E); + clang::IdentifierInfo *Name = 0; + if (BDRE) { + const ValueDecl *D = BDRE->getDecl(); + Name = &Idents.get(D->getName()); + } + QualType FieldType = E->getType(); + + if (BDRE && BDRE->isByRef()) + FieldType = BuildByRefType(BDRE->getDecl()->getNameAsCString(), + FieldType); + + FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), + Name, FieldType, /*DInfo=*/0, + /*BitWidth=*/0, /*Mutable=*/false); + T->addDecl(Field); + } + + T->completeDefinition(*this); + + return getPointerType(getTagDeclType(T)); +} + void ASTContext::setObjCFastEnumerationStateType(QualType T) { const RecordType *Rec = T->getAs<RecordType>(); assert(Rec && "Invalid ObjCFAstEnumerationStateType"); @@ -2945,6 +3185,7 @@ static void EncodeBitField(const ASTContext *Context, std::string& S, S += llvm::utostr(N); } +// FIXME: Use SmallString for accumulating string. void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, bool ExpandPointedToStructures, bool ExpandStructures, @@ -3420,7 +3661,7 @@ Qualifiers::GC ASTContext::getObjCGCAttrKind(const QualType &Ty) const { /// compatible. static bool areCompatVectorTypes(const VectorType *LHS, const VectorType *RHS) { - assert(LHS->isCanonical() && RHS->isCanonical()); + assert(LHS->isCanonicalUnqualified() && RHS->isCanonicalUnqualified()); return LHS->getElementType() == RHS->getElementType() && LHS->getNumElements() == RHS->getNumElements(); } @@ -3979,7 +4220,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { unsigned ASTContext::getIntWidth(QualType T) { if (T == BoolTy) return 1; - if (FixedWidthIntType* FWIT = dyn_cast<FixedWidthIntType>(T)) { + if (FixedWidthIntType *FWIT = dyn_cast<FixedWidthIntType>(T)) { return FWIT->getWidth(); } // For builtin types, just use the standard type sizing method @@ -3988,10 +4229,18 @@ unsigned ASTContext::getIntWidth(QualType T) { QualType ASTContext::getCorrespondingUnsignedType(QualType T) { assert(T->isSignedIntegerType() && "Unexpected type"); - if (const EnumType* ETy = T->getAs<EnumType>()) + + // Turn <4 x signed int> -> <4 x unsigned int> + if (const VectorType *VTy = T->getAs<VectorType>()) + return getVectorType(getCorrespondingUnsignedType(VTy->getElementType()), + VTy->getNumElements()); + + // For enums, we return the unsigned version of the base type. + if (const EnumType *ETy = T->getAs<EnumType>()) T = ETy->getDecl()->getIntegerType(); - const BuiltinType* BTy = T->getAs<BuiltinType>(); - assert (BTy && "Unexpected signed integer type"); + + const BuiltinType *BTy = T->getAs<BuiltinType>(); + assert(BTy && "Unexpected signed integer type"); switch (BTy->getKind()) { case BuiltinType::Char_S: case BuiltinType::SChar: |