diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2009-02-18 05:09:49 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2009-02-18 05:09:49 +0000 |
commit | d33d9c0cc0cfdcd0b10f35a6acdfb25da4a64f19 (patch) | |
tree | 62ddec380281fd5d7584b9ad958acdf4df241f5d | |
parent | 00dbfde0d7d0ef003a5a6bf7de0116636d0c1278 (diff) |
Representation of objc gc's attribute using ExtQualType.
Note that one test attr-objc-gc.m fails. I will fix this
after removing these attributes from the Decl nodes.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64889 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/ASTContext.h | 5 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 36 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 39 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 32 |
5 files changed, 100 insertions, 16 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 349b6e3f83..76bb01ebe5 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -190,6 +190,11 @@ public: /// replaced. QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace); + /// getObjCGCQualType - Returns the uniqued reference to the type for an + /// objc gc qualified type. The retulting type has a union of the qualifiers + /// from T and the gc attribute. + QualType getObjCGCQualType(QualType T, QualType::GCAttrTypes gcAttr); + /// getComplexType - Return the uniqued reference to the type for a complex /// number with the specified element type. QualType getComplexType(QualType T); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index ebbc5504a5..909f395791 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -93,6 +93,12 @@ public: CVRFlags = Const|Restrict|Volatile }; + enum GCAttrTypes { + GCNone = 0, + Weak, + Strong + }; + QualType() {} QualType(const Type *Ptr, unsigned Quals) @@ -188,6 +194,9 @@ public: /// getAddressSpace - Return the address space of this type. inline unsigned getAddressSpace() const; + /// GCAttrTypesAttr - Returns gc attribute of this type. + inline QualType::GCAttrTypes getObjCGCAttr() const; + /// Emit - Serialize a QualType to Bitcode. void Emit(llvm::Serializer& S) const; @@ -255,6 +264,7 @@ public: BlockPointer, // C extension FixedWidthInt }; + private: QualType CanonicalType; @@ -461,14 +471,6 @@ protected: /// __strong attributes. /// class ExtQualType : public Type, public llvm::FoldingSetNode { -public: - enum GCAttrTypes { - GCNone = 0, - Weak, - Strong - }; - -private: /// BaseType - This is the underlying type that this qualifies. All CVR /// qualifiers are stored on the QualType that references this type, so we /// can't have any here. @@ -477,16 +479,16 @@ private: /// Address Space ID - The address space ID this type is qualified with. unsigned AddressSpace; /// GC __weak/__strong attributes - GCAttrTypes GCAttrType; + QualType::GCAttrTypes GCAttrType; ExtQualType(Type *Base, QualType CanonicalPtr, unsigned AddrSpace, - GCAttrTypes gcAttr) : + QualType::GCAttrTypes gcAttr) : Type(ExtQual, CanonicalPtr, Base->isDependentType()), BaseType(Base), AddressSpace(AddrSpace), GCAttrType(gcAttr) { } friend class ASTContext; // ASTContext creates these. public: Type *getBaseType() const { return BaseType; } - GCAttrTypes getType() const { return GCAttrType; } + QualType::GCAttrTypes getObjCGCAttr() const { return GCAttrType; } unsigned getAddressSpace() const { return AddressSpace; } virtual void getAsStringInternal(std::string &InnerString) const; @@ -495,7 +497,7 @@ public: Profile(ID, getBaseType(), AddressSpace, GCAttrType); } static void Profile(llvm::FoldingSetNodeID &ID, Type *Base, - unsigned AddrSpace, GCAttrTypes gcAttr) { + unsigned AddrSpace, QualType::GCAttrTypes gcAttr) { ID.AddPointer(Base); ID.AddInteger(AddrSpace); ID.AddInteger(gcAttr); @@ -1741,6 +1743,16 @@ inline unsigned QualType::getAddressSpace() const { return 0; } +/// getObjCGCAttr - Return the gc attribute of this type. +inline QualType::GCAttrTypes QualType::getObjCGCAttr() const { + QualType CT = getTypePtr()->getCanonicalTypeInternal(); + if (const ArrayType *AT = dyn_cast<ArrayType>(CT)) + return AT->getElementType().getObjCGCAttr(); + if (const ExtQualType *EXTQT = dyn_cast<ExtQualType>(CT)) + return EXTQT->getObjCGCAttr(); + return GCNone; +} + /// isMoreQualifiedThan - Determine whether this type is more /// qualified than the Other type. For example, "const volatile int" /// is more qualified than "const int", "volatile int", and diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 4a3f00f356..6b49b85c24 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -725,7 +725,7 @@ QualType ASTContext::getAddrSpaceQualType(QualType T, unsigned AddressSpace) { // Check if we've already instantiated an address space qual'd type of this // type. llvm::FoldingSetNodeID ID; - ExtQualType::Profile(ID, T.getTypePtr(), AddressSpace, ExtQualType::GCNone); + ExtQualType::Profile(ID, T.getTypePtr(), AddressSpace, T.getObjCGCAttr()); void *InsertPos = 0; if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(EXTQy, 0); @@ -741,12 +741,47 @@ QualType ASTContext::getAddrSpaceQualType(QualType T, unsigned AddressSpace) { assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; } ExtQualType *New = new (*this, 8) ExtQualType(T.getTypePtr(), Canonical, - AddressSpace, ExtQualType::GCNone); + AddressSpace, + QualType::GCNone); ExtQualTypes.InsertNode(New, InsertPos); Types.push_back(New); return QualType(New, T.getCVRQualifiers()); } +QualType ASTContext::getObjCGCQualType(QualType T, + QualType::GCAttrTypes attr) { + QualType CanT = getCanonicalType(T); + if (CanT.getObjCGCAttr() == attr) + return T; + + // Type's cannot have multiple ExtQuals, therefore we know we only have to deal + // with CVR qualifiers from here on out. + assert(CanT.getObjCGCAttr() == QualType::GCNone && + "Type is already gc qualified"); + + // Check if we've already instantiated an gc qual'd type of this type. + llvm::FoldingSetNodeID ID; + ExtQualType::Profile(ID, T.getTypePtr(), T.getAddressSpace(), attr); + void *InsertPos = 0; + if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos)) + return QualType(EXTQy, 0); + + // If the base 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 = getObjCGCQualType(CanT, attr); + + // Get the new insert position for the node we care about. + ExtQualType *NewIP = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP; + } + ExtQualType *New = new (*this, 8) ExtQualType(T.getTypePtr(), Canonical, + 0, attr); + ExtQualTypes.InsertNode(New, InsertPos); + Types.push_back(New); + return QualType(New, T.getCVRQualifiers()); +} /// getComplexType - Return the uniqued reference to the type for a complex /// number with the specified element type. diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index bc597072ed..6c72a76a60 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1058,11 +1058,11 @@ void ExtQualType::getAsStringInternal(std::string &S) const { S = "__attribute__((address_space("+llvm::utostr_32(AddressSpace)+")))" + S; space = true; } - if (GCAttrType != GCNone) { + if (GCAttrType != QualType::GCNone) { if (space) S += ' '; S += "__attribute__((objc_gc("; - if (GCAttrType == Weak) + if (GCAttrType == QualType::Weak) S += "weak"; else S += "strong"; diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index db885e97fd..e6aafdab08 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -758,6 +758,35 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type, Type = S.Context.getAddrSpaceQualType(Type, ASIdx); } +/// HandleObjCGCTypeAttribute - Process an objc's gc attribute on the +/// specified type. The attribute contains 1 argument, weak or strong. +static void HandleObjCGCTypeAttribute(QualType &Type, + const AttributeList &Attr, Sema &S){ + // FIXME. Needs more work for this to make sense. + if (Type.getObjCGCAttr() != QualType::GCNone) { + S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers); + return; + } + + // Check the attribute arguments. + QualType::GCAttrTypes attr; + if (!Attr.getParameterName() || Attr.getNumArgs() != 0) { + S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; + return; + } + if (Attr.getParameterName()->isStr("weak")) + attr = QualType::Weak; + else if (Attr.getParameterName()->isStr("strong")) + attr = QualType::Strong; + else { + S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported) + << "objc_gc" << Attr.getParameterName(); + return; + } + + Type = S.Context.getObjCGCQualType(Type, attr); +} + void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) { // Scan through and apply attributes to this type where it makes sense. Some // attributes (such as __address_space__, __vector_size__, etc) apply to the @@ -771,6 +800,9 @@ void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) { case AttributeList::AT_address_space: HandleAddressSpaceTypeAttribute(Result, *AL, *this); break; + case AttributeList::AT_objc_gc: + HandleObjCGCTypeAttribute(Result, *AL, *this); + break; } } } |