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.

llvm-svn: 64889
This commit is contained in:
Fariborz Jahanian 2009-02-18 05:09:49 +00:00
parent 38a9631d5f
commit e27e934d45
5 changed files with 100 additions and 16 deletions

View File

@ -190,6 +190,11 @@ public:
/// replaced. /// replaced.
QualType getAddrSpaceQualType(QualType T, unsigned AddressSpace); 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 /// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type. /// number with the specified element type.
QualType getComplexType(QualType T); QualType getComplexType(QualType T);

View File

@ -93,6 +93,12 @@ public:
CVRFlags = Const|Restrict|Volatile CVRFlags = Const|Restrict|Volatile
}; };
enum GCAttrTypes {
GCNone = 0,
Weak,
Strong
};
QualType() {} QualType() {}
QualType(const Type *Ptr, unsigned Quals) QualType(const Type *Ptr, unsigned Quals)
@ -188,6 +194,9 @@ public:
/// getAddressSpace - Return the address space of this type. /// getAddressSpace - Return the address space of this type.
inline unsigned getAddressSpace() const; inline unsigned getAddressSpace() const;
/// GCAttrTypesAttr - Returns gc attribute of this type.
inline QualType::GCAttrTypes getObjCGCAttr() const;
/// Emit - Serialize a QualType to Bitcode. /// Emit - Serialize a QualType to Bitcode.
void Emit(llvm::Serializer& S) const; void Emit(llvm::Serializer& S) const;
@ -255,6 +264,7 @@ public:
BlockPointer, // C extension BlockPointer, // C extension
FixedWidthInt FixedWidthInt
}; };
private: private:
QualType CanonicalType; QualType CanonicalType;
@ -461,14 +471,6 @@ protected:
/// __strong attributes. /// __strong attributes.
/// ///
class ExtQualType : public Type, public llvm::FoldingSetNode { 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 /// BaseType - This is the underlying type that this qualifies. All CVR
/// qualifiers are stored on the QualType that references this type, so we /// qualifiers are stored on the QualType that references this type, so we
/// can't have any here. /// can't have any here.
@ -477,16 +479,16 @@ private:
/// Address Space ID - The address space ID this type is qualified with. /// Address Space ID - The address space ID this type is qualified with.
unsigned AddressSpace; unsigned AddressSpace;
/// GC __weak/__strong attributes /// GC __weak/__strong attributes
GCAttrTypes GCAttrType; QualType::GCAttrTypes GCAttrType;
ExtQualType(Type *Base, QualType CanonicalPtr, unsigned AddrSpace, ExtQualType(Type *Base, QualType CanonicalPtr, unsigned AddrSpace,
GCAttrTypes gcAttr) : QualType::GCAttrTypes gcAttr) :
Type(ExtQual, CanonicalPtr, Base->isDependentType()), BaseType(Base), Type(ExtQual, CanonicalPtr, Base->isDependentType()), BaseType(Base),
AddressSpace(AddrSpace), GCAttrType(gcAttr) { } AddressSpace(AddrSpace), GCAttrType(gcAttr) { }
friend class ASTContext; // ASTContext creates these. friend class ASTContext; // ASTContext creates these.
public: public:
Type *getBaseType() const { return BaseType; } Type *getBaseType() const { return BaseType; }
GCAttrTypes getType() const { return GCAttrType; } QualType::GCAttrTypes getObjCGCAttr() const { return GCAttrType; }
unsigned getAddressSpace() const { return AddressSpace; } unsigned getAddressSpace() const { return AddressSpace; }
virtual void getAsStringInternal(std::string &InnerString) const; virtual void getAsStringInternal(std::string &InnerString) const;
@ -495,7 +497,7 @@ public:
Profile(ID, getBaseType(), AddressSpace, GCAttrType); Profile(ID, getBaseType(), AddressSpace, GCAttrType);
} }
static void Profile(llvm::FoldingSetNodeID &ID, Type *Base, static void Profile(llvm::FoldingSetNodeID &ID, Type *Base,
unsigned AddrSpace, GCAttrTypes gcAttr) { unsigned AddrSpace, QualType::GCAttrTypes gcAttr) {
ID.AddPointer(Base); ID.AddPointer(Base);
ID.AddInteger(AddrSpace); ID.AddInteger(AddrSpace);
ID.AddInteger(gcAttr); ID.AddInteger(gcAttr);
@ -1741,6 +1743,16 @@ inline unsigned QualType::getAddressSpace() const {
return 0; 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 /// isMoreQualifiedThan - Determine whether this type is more
/// qualified than the Other type. For example, "const volatile int" /// qualified than the Other type. For example, "const volatile int"
/// is more qualified than "const int", "volatile int", and /// is more qualified than "const int", "volatile int", and

View File

@ -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 // Check if we've already instantiated an address space qual'd type of this
// type. // type.
llvm::FoldingSetNodeID ID; llvm::FoldingSetNodeID ID;
ExtQualType::Profile(ID, T.getTypePtr(), AddressSpace, ExtQualType::GCNone); ExtQualType::Profile(ID, T.getTypePtr(), AddressSpace, T.getObjCGCAttr());
void *InsertPos = 0; void *InsertPos = 0;
if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos)) if (ExtQualType *EXTQy = ExtQualTypes.FindNodeOrInsertPos(ID, InsertPos))
return QualType(EXTQy, 0); 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; assert(NewIP == 0 && "Shouldn't be in the map!"); NewIP = NewIP;
} }
ExtQualType *New = new (*this, 8) ExtQualType(T.getTypePtr(), Canonical, ExtQualType *New = new (*this, 8) ExtQualType(T.getTypePtr(), Canonical,
AddressSpace, ExtQualType::GCNone); AddressSpace,
QualType::GCNone);
ExtQualTypes.InsertNode(New, InsertPos); ExtQualTypes.InsertNode(New, InsertPos);
Types.push_back(New); Types.push_back(New);
return QualType(New, T.getCVRQualifiers()); 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 /// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type. /// number with the specified element type.

View File

@ -1058,11 +1058,11 @@ void ExtQualType::getAsStringInternal(std::string &S) const {
S = "__attribute__((address_space("+llvm::utostr_32(AddressSpace)+")))" + S; S = "__attribute__((address_space("+llvm::utostr_32(AddressSpace)+")))" + S;
space = true; space = true;
} }
if (GCAttrType != GCNone) { if (GCAttrType != QualType::GCNone) {
if (space) if (space)
S += ' '; S += ' ';
S += "__attribute__((objc_gc("; S += "__attribute__((objc_gc(";
if (GCAttrType == Weak) if (GCAttrType == QualType::Weak)
S += "weak"; S += "weak";
else else
S += "strong"; S += "strong";

View File

@ -758,6 +758,35 @@ static void HandleAddressSpaceTypeAttribute(QualType &Type,
Type = S.Context.getAddrSpaceQualType(Type, ASIdx); 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) { void Sema::ProcessTypeAttributeList(QualType &Result, const AttributeList *AL) {
// Scan through and apply attributes to this type where it makes sense. Some // Scan through and apply attributes to this type where it makes sense. Some
// attributes (such as __address_space__, __vector_size__, etc) apply to the // 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: case AttributeList::AT_address_space:
HandleAddressSpaceTypeAttribute(Result, *AL, *this); HandleAddressSpaceTypeAttribute(Result, *AL, *this);
break; break;
case AttributeList::AT_objc_gc:
HandleObjCGCTypeAttribute(Result, *AL, *this);
break;
} }
} }
} }