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.
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);

View File

@ -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

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
// 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.

View File

@ -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";

View File

@ -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;
}
}
}