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:
parent
2067816b3a
commit
819e873791
|
@ -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); }
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue