summaryrefslogtreecommitdiffstats
path: root/lib/AST/ASTContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r--lib/AST/ASTContext.cpp507
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:
OpenPOWER on IntegriCloud