Fix long-lurking bug in ObjCSummaryCache revealed by Torok's recent memory

poisoning changes to DenseMap. We were using an iterator after it had been
invalidated by an insertion into the DenseMap.

llvm-svn: 76677
This commit is contained in:
Ted Kremenek 2009-07-21 23:27:57 +00:00
parent 3666c34db8
commit 8be513822c
1 changed files with 38 additions and 41 deletions

View File

@ -496,24 +496,22 @@ class VISIBILITY_HIDDEN ObjCSummaryCache {
MapTy M; MapTy M;
public: public:
ObjCSummaryCache() {} ObjCSummaryCache() {}
typedef MapTy::iterator iterator; RetainSummary* find(const ObjCInterfaceDecl* D, IdentifierInfo *ClsName,
iterator find(const ObjCInterfaceDecl* D, IdentifierInfo *ClsName,
Selector S) { Selector S) {
// Lookup the method using the decl for the class @interface. If we // Lookup the method using the decl for the class @interface. If we
// have no decl, lookup using the class name. // have no decl, lookup using the class name.
return D ? find(D, S) : find(ClsName, S); return D ? find(D, S) : find(ClsName, S);
} }
iterator find(const ObjCInterfaceDecl* D, Selector S) { RetainSummary* find(const ObjCInterfaceDecl* D, Selector S) {
// Do a lookup with the (D,S) pair. If we find a match return // Do a lookup with the (D,S) pair. If we find a match return
// the iterator. // the iterator.
ObjCSummaryKey K(D, S); ObjCSummaryKey K(D, S);
MapTy::iterator I = M.find(K); MapTy::iterator I = M.find(K);
if (I != M.end() || !D) if (I != M.end() || !D)
return I; return I->second;
// Walk the super chain. If we find a hit with a parent, we'll end // Walk the super chain. If we find a hit with a parent, we'll end
// up returning that summary. We actually allow that key (null,S), as // up returning that summary. We actually allow that key (null,S), as
@ -526,25 +524,30 @@ public:
break; break;
if (!C) if (!C)
return I; return NULL;
} }
// Cache the summary with original key to make the next lookup faster // Cache the summary with original key to make the next lookup faster
// and return the iterator. // and return the iterator.
M[K] = I->second; RetainSummary *Summ = I->second;
return I; M[K] = Summ;
return Summ;
} }
iterator find(Expr* Receiver, Selector S) { RetainSummary* find(Expr* Receiver, Selector S) {
return find(getReceiverDecl(Receiver), S); return find(getReceiverDecl(Receiver), S);
} }
iterator find(IdentifierInfo* II, Selector S) { RetainSummary* find(IdentifierInfo* II, Selector S) {
// FIXME: Class method lookup. Right now we dont' have a good way // FIXME: Class method lookup. Right now we dont' have a good way
// of going between IdentifierInfo* and the class hierarchy. // of going between IdentifierInfo* and the class hierarchy.
iterator I = M.find(ObjCSummaryKey(II, S)); MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
return I == M.end() ? M.find(ObjCSummaryKey(S)) : I;
if (I == M.end())
I = M.find(ObjCSummaryKey(S));
return I == M.end() ? NULL : I->second;
} }
const ObjCInterfaceDecl* getReceiverDecl(Expr* E) { const ObjCInterfaceDecl* getReceiverDecl(Expr* E) {
@ -555,8 +558,6 @@ public:
return NULL; return NULL;
} }
iterator end() { return M.end(); }
RetainSummary*& operator[](ObjCMessageExpr* ME) { RetainSummary*& operator[](ObjCMessageExpr* ME) {
Selector S = ME->getSelector(); Selector S = ME->getSelector();
@ -1347,25 +1348,24 @@ RetainSummaryManager::getInstanceMethodSummary(Selector S,
QualType RetTy) { QualType RetTy) {
// Look up a summary in our summary cache. // Look up a summary in our summary cache.
ObjCMethodSummariesTy::iterator I = ObjCMethodSummaries.find(ID, ClsName, S); RetainSummary *Summ = ObjCMethodSummaries.find(ID, ClsName, S);
if (I != ObjCMethodSummaries.end()) if (!Summ) {
return I->second; assert(ScratchArgs.isEmpty());
assert(ScratchArgs.isEmpty());
RetainSummary *Summ = 0;
// "initXXX": pass-through for receiver. // "initXXX": pass-through for receiver.
if (deriveNamingConvention(S) == InitRule) if (deriveNamingConvention(S) == InitRule)
Summ = getInitMethodSummary(RetTy); Summ = getInitMethodSummary(RetTy);
else else
Summ = getCommonMethodSummary(MD, S, RetTy); Summ = getCommonMethodSummary(MD, S, RetTy);
// Annotations override defaults. // Annotations override defaults.
updateSummaryFromAnnotations(*Summ, MD); updateSummaryFromAnnotations(*Summ, MD);
// Memoize the summary.
ObjCMethodSummaries[ObjCSummaryKey(ID, ClsName, S)] = Summ;
}
// Memoize the summary.
ObjCMethodSummaries[ObjCSummaryKey(ID, ClsName, S)] = Summ;
return Summ; return Summ;
} }
@ -1376,19 +1376,16 @@ RetainSummaryManager::getClassMethodSummary(Selector S, IdentifierInfo *ClsName,
QualType RetTy) { QualType RetTy) {
assert(ClsName && "Class name must be specified."); assert(ClsName && "Class name must be specified.");
ObjCMethodSummariesTy::iterator I = RetainSummary *Summ = ObjCClassMethodSummaries.find(ID, ClsName, S);
ObjCClassMethodSummaries.find(ID, ClsName, S);
if (I != ObjCClassMethodSummaries.end()) if (!Summ) {
return I->second; Summ = getCommonMethodSummary(MD, S, RetTy);
// Annotations override defaults.
RetainSummary *Summ = getCommonMethodSummary(MD, S, RetTy); updateSummaryFromAnnotations(*Summ, MD);
// Memoize the summary.
ObjCClassMethodSummaries[ObjCSummaryKey(ID, ClsName, S)] = Summ;
}
// Annotations override defaults.
updateSummaryFromAnnotations(*Summ, MD);
// Memoize the summary.
ObjCClassMethodSummaries[ObjCSummaryKey(ID, ClsName, S)] = Summ;
return Summ; return Summ;
} }