Allocate the 'Protocols' array in ObjCInterfaceType and

ObjCObjectPointerType using the allocator associated with ASTContext.
Not only does this fix a memory leak, but it also makes these arrays
BumpPtrAllocated (in the typical case).

llvm-svn: 94090
This commit is contained in:
Ted Kremenek 2010-01-21 19:22:34 +00:00
parent 2067816b3a
commit 819e873791
3 changed files with 76 additions and 26 deletions

View File

@ -2514,26 +2514,31 @@ class ObjCInterfaceType : public Type, public llvm::FoldingSetNode {
// List of protocols for this protocol conforming object type // List of protocols for this protocol conforming object type
// List is sorted on protocol name. No protocol is enterred more than once. // List is sorted on protocol name. No protocol is enterred more than once.
llvm::SmallVector<ObjCProtocolDecl*, 4> Protocols; ObjCProtocolDecl **Protocols;
unsigned NumProtocols;
ObjCInterfaceType(QualType Canonical, ObjCInterfaceDecl *D, ObjCInterfaceType(ASTContext &Ctx, QualType Canonical, ObjCInterfaceDecl *D,
ObjCProtocolDecl **Protos, unsigned NumP) : ObjCProtocolDecl **Protos, unsigned NumP);
Type(ObjCInterface, Canonical, /*Dependent=*/false),
Decl(D), Protocols(Protos, Protos+NumP) { }
friend class ASTContext; // ASTContext creates these. friend class ASTContext; // ASTContext creates these.
public: public:
void Destroy(ASTContext& C);
ObjCInterfaceDecl *getDecl() const { return Decl; } ObjCInterfaceDecl *getDecl() const { return Decl; }
/// getNumProtocols - Return the number of qualifying protocols in this /// getNumProtocols - Return the number of qualifying protocols in this
/// interface type, or 0 if there are none. /// interface type, or 0 if there are none.
unsigned getNumProtocols() const { return Protocols.size(); } unsigned getNumProtocols() const { return NumProtocols; }
/// qual_iterator and friends: this provides access to the (potentially empty) /// qual_iterator and friends: this provides access to the (potentially empty)
/// list of protocols qualifying this interface. /// list of protocols qualifying this interface.
typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator; typedef ObjCProtocolDecl* const * qual_iterator;
qual_iterator qual_begin() const { return Protocols.begin(); } qual_iterator qual_begin() const {
qual_iterator qual_end() const { return Protocols.end(); } return Protocols;
bool qual_empty() const { return Protocols.size() == 0; } }
qual_iterator qual_end() const {
return Protocols ? Protocols + NumProtocols : 0;
}
bool qual_empty() const { return NumProtocols == 0; }
bool isSugared() const { return false; } bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); } QualType desugar() const { return QualType(this, 0); }
@ -2559,15 +2564,16 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
// List of protocols for this protocol conforming object type // List of protocols for this protocol conforming object type
// List is sorted on protocol name. No protocol is entered more than once. // List is sorted on protocol name. No protocol is entered more than once.
llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols; ObjCProtocolDecl **Protocols;
unsigned NumProtocols;
ObjCObjectPointerType(QualType Canonical, QualType T, ObjCObjectPointerType(ASTContext &Ctx, QualType Canonical, QualType T,
ObjCProtocolDecl **Protos, unsigned NumP) : ObjCProtocolDecl **Protos, unsigned NumP);
Type(ObjCObjectPointer, Canonical, /*Dependent=*/false),
PointeeType(T), Protocols(Protos, Protos+NumP) { }
friend class ASTContext; // ASTContext creates these. friend class ASTContext; // ASTContext creates these.
public: public:
void Destroy(ASTContext& C);
// Get the pointee type. Pointee will either be: // Get the pointee type. Pointee will either be:
// - a built-in type (for 'id' and 'Class'). // - a built-in type (for 'id' and 'Class').
// - an interface type (for user-defined types). // - an interface type (for user-defined types).
@ -2585,35 +2591,39 @@ public:
/// isObjCIdType - true for "id". /// isObjCIdType - true for "id".
bool isObjCIdType() const { bool isObjCIdType() const {
return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) && return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) &&
!Protocols.size(); !NumProtocols;
} }
/// isObjCClassType - true for "Class". /// isObjCClassType - true for "Class".
bool isObjCClassType() const { bool isObjCClassType() const {
return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) && return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) &&
!Protocols.size(); !NumProtocols;
} }
/// isObjCQualifiedIdType - true for "id <p>". /// isObjCQualifiedIdType - true for "id <p>".
bool isObjCQualifiedIdType() const { bool isObjCQualifiedIdType() const {
return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) && return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) &&
Protocols.size(); NumProtocols;
} }
/// isObjCQualifiedClassType - true for "Class <p>". /// isObjCQualifiedClassType - true for "Class <p>".
bool isObjCQualifiedClassType() const { bool isObjCQualifiedClassType() const {
return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) && return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) &&
Protocols.size(); NumProtocols;
} }
/// qual_iterator and friends: this provides access to the (potentially empty) /// qual_iterator and friends: this provides access to the (potentially empty)
/// list of protocols qualifying this interface. /// list of protocols qualifying this interface.
typedef llvm::SmallVector<ObjCProtocolDecl*, 8>::const_iterator qual_iterator; typedef ObjCProtocolDecl* const * qual_iterator;
qual_iterator qual_begin() const { return Protocols.begin(); } qual_iterator qual_begin() const {
qual_iterator qual_end() const { return Protocols.end(); } return Protocols;
bool qual_empty() const { return Protocols.size() == 0; } }
qual_iterator qual_end() const {
return Protocols ? Protocols + NumProtocols : NULL;
}
bool qual_empty() const { return NumProtocols == 0; }
/// getNumProtocols - Return the number of qualifying protocols in this /// getNumProtocols - Return the number of qualifying protocols in this
/// interface type, or 0 if there are none. /// interface type, or 0 if there are none.
unsigned getNumProtocols() const { return Protocols.size(); } unsigned getNumProtocols() const { return NumProtocols; }
bool isSugared() const { return false; } bool isSugared() const { return false; }
QualType desugar() const { return QualType(this, 0); } QualType desugar() const { return QualType(this, 0); }

View File

@ -2127,7 +2127,8 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,
// No Match; // No Match;
ObjCObjectPointerType *QType = new (*this, TypeAlignment) ObjCObjectPointerType *QType = new (*this, TypeAlignment)
ObjCObjectPointerType(Canonical, InterfaceT, Protocols, NumProtocols); ObjCObjectPointerType(*this, Canonical, InterfaceT, Protocols,
NumProtocols);
Types.push_back(QType); Types.push_back(QType);
ObjCObjectPointerTypes.InsertNode(QType, InsertPos); ObjCObjectPointerTypes.InsertNode(QType, InsertPos);
@ -2161,7 +2162,7 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,
} }
ObjCInterfaceType *QType = new (*this, TypeAlignment) ObjCInterfaceType *QType = new (*this, TypeAlignment)
ObjCInterfaceType(Canonical, const_cast<ObjCInterfaceDecl*>(Decl), ObjCInterfaceType(*this, Canonical, const_cast<ObjCInterfaceDecl*>(Decl),
Protocols, NumProtocols); Protocols, NumProtocols);
Types.push_back(QType); Types.push_back(QType);

View File

@ -339,6 +339,25 @@ const RecordType *Type::getAsUnionType() const {
return 0; return 0;
} }
ObjCInterfaceType::ObjCInterfaceType(ASTContext &Ctx, QualType Canonical,
ObjCInterfaceDecl *D,
ObjCProtocolDecl **Protos, unsigned NumP) :
Type(ObjCInterface, Canonical, /*Dependent=*/false),
Decl(D), Protocols(0), NumProtocols(NumP)
{
if (NumProtocols) {
Protocols = new (Ctx) ObjCProtocolDecl*[NumProtocols];
memcpy(Protocols, Protos, NumProtocols * sizeof(*Protocols));
}
}
void ObjCInterfaceType::Destroy(ASTContext& C) {
if (Protocols)
C.Deallocate(Protocols);
this->~ObjCInterfaceType();
C.Deallocate(this);
}
const ObjCInterfaceType *Type::getAsObjCQualifiedInterfaceType() const { const ObjCInterfaceType *Type::getAsObjCQualifiedInterfaceType() const {
// There is no sugar for ObjCInterfaceType's, just return the canonical // There is no sugar for ObjCInterfaceType's, just return the canonical
// type pointer if it is the right class. There is no typedef information to // type pointer if it is the right class. There is no typedef information to
@ -353,6 +372,26 @@ bool Type::isObjCQualifiedInterfaceType() const {
return getAsObjCQualifiedInterfaceType() != 0; return getAsObjCQualifiedInterfaceType() != 0;
} }
ObjCObjectPointerType::ObjCObjectPointerType(ASTContext &Ctx,
QualType Canonical, QualType T,
ObjCProtocolDecl **Protos,
unsigned NumP) :
Type(ObjCObjectPointer, Canonical, /*Dependent=*/false),
PointeeType(T), Protocols(NULL), NumProtocols(NumP)
{
if (NumProtocols) {
Protocols = new (Ctx) ObjCProtocolDecl*[NumProtocols];
memcpy(Protocols, Protos, NumProtocols * sizeof(*Protocols));
}
}
void ObjCObjectPointerType::Destroy(ASTContext& C) {
if (Protocols)
C.Deallocate(Protocols);
this->~ObjCObjectPointerType();
C.Deallocate(this);
}
const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const { const ObjCObjectPointerType *Type::getAsObjCQualifiedIdType() const {
// There is no sugar for ObjCQualifiedIdType's, just return the canonical // There is no sugar for ObjCQualifiedIdType's, just return the canonical
// type pointer if it is the right class. // type pointer if it is the right class.