aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/CFRefCount.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/CFRefCount.cpp')
-rw-r--r--lib/Analysis/CFRefCount.cpp1275
1 files changed, 637 insertions, 638 deletions
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 9cd59c2c14..e511f76195 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -22,7 +22,7 @@
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "clang/Analysis/PathSensitive/SymbolManager.h"
#include "clang/Analysis/PathSensitive/GRTransferFuncs.h"
-#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclObjC.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
@@ -44,7 +44,7 @@ using namespace clang;
// MemoryMgmt/Tasks/MemoryManagementRules.html
//
// "You take ownership of an object if you create it using a method whose name
-// begins with "alloc" or "new" or contains "copy" (for example, alloc,
+// begins with "alloc" or "new" or contains "copy" (for example, alloc,
// newObject, or mutableCopy), or if you send it a retain message. You are
// responsible for relinquishing ownership of objects you own using release
// or autorelease. Any other time you receive an object, you must
@@ -62,8 +62,8 @@ static inline bool isWordEnd(char ch, char prev, char next) {
|| (isupper(prev) && isupper(ch) && islower(next)) // XXCreate
|| !isalpha(ch);
}
-
-static inline const char* parseWord(const char* s) {
+
+static inline const char* parseWord(const char* s) {
char ch = *s, prev = '\0';
assert(ch != '\0');
char next = *(s+1);
@@ -77,18 +77,18 @@ static inline const char* parseWord(const char* s) {
static NamingConvention deriveNamingConvention(Selector S) {
IdentifierInfo *II = S.getIdentifierInfoForSlot(0);
-
+
if (!II)
return NoConvention;
-
+
const char *s = II->getName();
-
+
// A method/function name may contain a prefix. We don't know it is there,
// however, until we encounter the first '_'.
bool InPossiblePrefix = true;
bool AtBeginning = true;
NamingConvention C = NoConvention;
-
+
while (*s != '\0') {
// Skip '_'.
if (*s == '_') {
@@ -103,24 +103,24 @@ static NamingConvention deriveNamingConvention(Selector S) {
++s;
continue;
}
-
+
// Skip numbers, ':', etc.
if (!isalpha(*s)) {
++s;
continue;
}
-
+
const char *wordEnd = parseWord(s);
assert(wordEnd > s);
unsigned len = wordEnd - s;
-
+
switch (len) {
default:
break;
case 3:
// Methods starting with 'new' follow the create rule.
if (AtBeginning && StringsEqualNoCase("new", s, len))
- C = CreateRule;
+ C = CreateRule;
break;
case 4:
// Methods starting with 'alloc' or contain 'copy' follow the
@@ -136,7 +136,7 @@ static NamingConvention deriveNamingConvention(Selector S) {
C = CreateRule;
break;
}
-
+
// If we aren't in the prefix and have a derived convention then just
// return it now.
if (!InPossiblePrefix && C != NoConvention)
@@ -156,10 +156,10 @@ static bool followsFundamentalRule(Selector S) {
}
static const ObjCMethodDecl*
-ResolveToInterfaceMethodDecl(const ObjCMethodDecl *MD) {
+ResolveToInterfaceMethodDecl(const ObjCMethodDecl *MD) {
ObjCInterfaceDecl *ID =
const_cast<ObjCInterfaceDecl*>(MD->getClassInterface());
-
+
return MD->isInstanceMethod()
? ID->lookupInstanceMethod(MD->getSelector())
: ID->lookupClassMethod(MD->getSelector());
@@ -178,12 +178,12 @@ public:
GenericNodeBuilder(GREndPathNodeBuilder &enb)
: SNB(0), S(0), tag(0), ENB(&enb) {}
-
+
ExplodedNode *MakeNode(const GRState *state, ExplodedNode *Pred) {
if (SNB)
- return SNB->generateNode(PostStmt(S, Pred->getLocationContext(), tag),
+ return SNB->generateNode(PostStmt(S, Pred->getLocationContext(), tag),
state, Pred);
-
+
assert(ENB);
return ENB->generateNode(state, Pred);
}
@@ -211,16 +211,16 @@ static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
static bool hasPrefix(const char* s, const char* prefix) {
if (!prefix)
return true;
-
+
char c = *s;
char cP = *prefix;
-
+
while (c != '\0' && cP != '\0') {
if (c != cP) break;
c = *(++s);
cP = *(++prefix);
}
-
+
return cP == '\0';
}
@@ -231,14 +231,14 @@ static bool hasSuffix(const char* s, const char* suffix) {
static bool isRefType(QualType RetTy, const char* prefix,
ASTContext* Ctx = 0, const char* name = 0) {
-
+
// Recursively walk the typedef stack, allowing typedefs of reference types.
while (1) {
if (TypedefType* TD = dyn_cast<TypedefType>(RetTy.getTypePtr())) {
const char* TDName = TD->getDecl()->getIdentifier()->getName();
if (hasPrefix(TDName, prefix) && hasSuffix(TDName, "Ref"))
return true;
-
+
RetTy = TD->getDecl()->getUnderlyingType();
continue;
}
@@ -282,14 +282,14 @@ typedef llvm::ImmutableMap<unsigned,ArgEffect> ArgEffects;
namespace {
/// RetEffect is used to summarize a function/method call's behavior with
-/// respect to its return value.
+/// respect to its return value.
class VISIBILITY_HIDDEN RetEffect {
public:
enum Kind { NoRet, Alias, OwnedSymbol, OwnedAllocatedSymbol,
NotOwnedSymbol, GCNotOwnedSymbol, ReceiverAlias,
OwnedWhenTrackedReceiver };
-
- enum ObjKind { CF, ObjC, AnyObj };
+
+ enum ObjKind { CF, ObjC, AnyObj };
private:
Kind K;
@@ -298,124 +298,124 @@ private:
RetEffect(Kind k, unsigned idx = 0) : K(k), O(AnyObj), index(idx) {}
RetEffect(Kind k, ObjKind o) : K(k), O(o), index(0) {}
-
+
public:
Kind getKind() const { return K; }
ObjKind getObjKind() const { return O; }
-
- unsigned getIndex() const {
+
+ unsigned getIndex() const {
assert(getKind() == Alias);
return index;
}
-
+
bool isOwned() const {
return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
K == OwnedWhenTrackedReceiver;
}
-
+
static RetEffect MakeOwnedWhenTrackedReceiver() {
return RetEffect(OwnedWhenTrackedReceiver, ObjC);
}
-
+
static RetEffect MakeAlias(unsigned Idx) {
return RetEffect(Alias, Idx);
}
static RetEffect MakeReceiverAlias() {
return RetEffect(ReceiverAlias);
- }
+ }
static RetEffect MakeOwned(ObjKind o, bool isAllocated = false) {
return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol, o);
- }
+ }
static RetEffect MakeNotOwned(ObjKind o) {
return RetEffect(NotOwnedSymbol, o);
}
static RetEffect MakeGCNotOwned() {
return RetEffect(GCNotOwnedSymbol, ObjC);
}
-
+
static RetEffect MakeNoRet() {
return RetEffect(NoRet);
}
-
+
void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger((unsigned)K);
ID.AddInteger((unsigned)O);
ID.AddInteger(index);
}
};
-
-
+
+
class VISIBILITY_HIDDEN RetainSummary {
/// Args - an ordered vector of (index, ArgEffect) pairs, where index
/// specifies the argument (starting from 0). This can be sparsely
/// populated; arguments with no entry in Args use 'DefaultArgEffect'.
ArgEffects Args;
-
+
/// DefaultArgEffect - The default ArgEffect to apply to arguments that
/// do not have an entry in Args.
ArgEffect DefaultArgEffect;
-
+
/// Receiver - If this summary applies to an Objective-C message expression,
/// this is the effect applied to the state of the receiver.
ArgEffect Receiver;
-
+
/// Ret - The effect on the return value. Used to indicate if the
/// function/method call returns a new tracked symbol, returns an
/// alias of one of the arguments in the call, and so on.
RetEffect Ret;
-
+
/// EndPath - Indicates that execution of this method/function should
/// terminate the simulation of a path.
bool EndPath;
-
+
public:
RetainSummary(ArgEffects A, RetEffect R, ArgEffect defaultEff,
ArgEffect ReceiverEff, bool endpath = false)
: Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R),
- EndPath(endpath) {}
-
+ EndPath(endpath) {}
+
/// getArg - Return the argument effect on the argument specified by
/// idx (starting from 0).
ArgEffect getArg(unsigned idx) const {
if (const ArgEffect *AE = Args.lookup(idx))
return *AE;
-
+
return DefaultArgEffect;
}
-
+
/// setDefaultArgEffect - Set the default argument effect.
void setDefaultArgEffect(ArgEffect E) {
DefaultArgEffect = E;
}
-
+
/// setArg - Set the argument effect on the argument specified by idx.
void setArgEffect(ArgEffects::Factory& AF, unsigned idx, ArgEffect E) {
Args = AF.Add(Args, idx, E);
}
-
+
/// getRetEffect - Returns the effect on the return value of the call.
RetEffect getRetEffect() const { return Ret; }
-
+
/// setRetEffect - Set the effect of the return value of the call.
void setRetEffect(RetEffect E) { Ret = E; }
-
+
/// isEndPath - Returns true if executing the given method/function should
/// terminate the path.
bool isEndPath() const { return EndPath; }
-
+
/// getReceiverEffect - Returns the effect on the receiver of the call.
/// This is only meaningful if the summary applies to an ObjCMessageExpr*.
ArgEffect getReceiverEffect() const { return Receiver; }
-
+
/// setReceiverEffect - Set the effect on the receiver of the call.
void setReceiverEffect(ArgEffect E) { Receiver = E; }
-
+
typedef ArgEffects::iterator ExprIterator;
-
+
ExprIterator begin_args() const { return Args.begin(); }
ExprIterator end_args() const { return Args.end(); }
-
+
static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects A,
RetEffect RetEff, ArgEffect DefaultEff,
ArgEffect ReceiverEff, bool EndPath) {
@@ -425,7 +425,7 @@ public:
ID.AddInteger((unsigned) ReceiverEff);
ID.AddInteger((unsigned) EndPath);
}
-
+
void Profile(llvm::FoldingSetNodeID& ID) const {
Profile(ID, Args, Ret, DefaultArgEffect, Receiver, EndPath);
}
@@ -440,7 +440,7 @@ namespace {
class VISIBILITY_HIDDEN ObjCSummaryKey {
IdentifierInfo* II;
Selector S;
-public:
+public:
ObjCSummaryKey(IdentifierInfo* ii, Selector s)
: II(ii), S(s) {}
@@ -449,10 +449,10 @@ public:
ObjCSummaryKey(const ObjCInterfaceDecl* d, IdentifierInfo *ii, Selector s)
: II(d ? d->getIdentifier() : ii), S(s) {}
-
+
ObjCSummaryKey(Selector s)
: II(0), S(s) {}
-
+
IdentifierInfo* getIdentifier() const { return II; }
Selector getSelector() const { return S; }
};
@@ -464,56 +464,56 @@ template <> struct DenseMapInfo<ObjCSummaryKey> {
return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
DenseMapInfo<Selector>::getEmptyKey());
}
-
+
static inline ObjCSummaryKey getTombstoneKey() {
return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
- DenseMapInfo<Selector>::getTombstoneKey());
+ DenseMapInfo<Selector>::getTombstoneKey());
}
-
+
static unsigned getHashValue(const ObjCSummaryKey &V) {
return (DenseMapInfo<IdentifierInfo*>::getHashValue(V.getIdentifier())
- & 0x88888888)
+ & 0x88888888)
| (DenseMapInfo<Selector>::getHashValue(V.getSelector())
& 0x55555555);
}
-
+
static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
return DenseMapInfo<IdentifierInfo*>::isEqual(LHS.getIdentifier(),
RHS.getIdentifier()) &&
DenseMapInfo<Selector>::isEqual(LHS.getSelector(),
RHS.getSelector());
}
-
+
static bool isPod() {
return DenseMapInfo<ObjCInterfaceDecl*>::isPod() &&
DenseMapInfo<Selector>::isPod();
}
};
} // end llvm namespace
-
+
namespace {
class VISIBILITY_HIDDEN ObjCSummaryCache {
typedef llvm::DenseMap<ObjCSummaryKey, RetainSummary*> MapTy;
MapTy M;
public:
ObjCSummaryCache() {}
-
+
RetainSummary* find(const ObjCInterfaceDecl* D, IdentifierInfo *ClsName,
Selector S) {
// Lookup the method using the decl for the class @interface. If we
// have no decl, lookup using the class name.
return D ? find(D, S) : find(ClsName, S);
}
-
- RetainSummary* 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
// the iterator.
ObjCSummaryKey K(D, S);
MapTy::iterator I = M.find(K);
-
+
if (I != M.end() || !D)
return I->second;
-
+
// 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
// we cache summaries for the null ObjCInterfaceDecl* to allow us to
@@ -523,62 +523,62 @@ public:
for (ObjCInterfaceDecl* C=D->getSuperClass() ;; C=C->getSuperClass()) {
if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
break;
-
+
if (!C)
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.
RetainSummary *Summ = I->second;
M[K] = Summ;
return Summ;
}
-
+
RetainSummary* find(Expr* Receiver, Selector S) {
return find(getReceiverDecl(Receiver), S);
}
-
+
RetainSummary* find(IdentifierInfo* II, Selector S) {
// FIXME: Class method lookup. Right now we dont' have a good way
// of going between IdentifierInfo* and the class hierarchy.
MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
-
+
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) {
if (const ObjCObjectPointerType* PT =
E->getType()->getAsObjCObjectPointerType())
return PT->getInterfaceDecl();
return NULL;
}
-
+
RetainSummary*& operator[](ObjCMessageExpr* ME) {
-
+
Selector S = ME->getSelector();
-
+
if (Expr* Receiver = ME->getReceiver()) {
const ObjCInterfaceDecl* OD = getReceiverDecl(Receiver);
return OD ? M[ObjCSummaryKey(OD->getIdentifier(), S)] : M[S];
}
-
+
return M[ObjCSummaryKey(ME->getClassName(), S)];
}
-
+
RetainSummary*& operator[](ObjCSummaryKey K) {
return M[K];
}
-
+
RetainSummary*& operator[](Selector S) {
return M[ ObjCSummaryKey(S) ];
}
-};
+};
} // end anonymous namespace
//===----------------------------------------------------------------------===//
@@ -591,29 +591,29 @@ class VISIBILITY_HIDDEN RetainSummaryManager {
//==-----------------------------------------------------------------==//
// Typedefs.
//==-----------------------------------------------------------------==//
-
+
typedef llvm::DenseMap<FunctionDecl*, RetainSummary*>
FuncSummariesTy;
-
+
typedef ObjCSummaryCache ObjCMethodSummariesTy;
-
+
//==-----------------------------------------------------------------==//
// Data.
//==-----------------------------------------------------------------==//
-
+
/// Ctx - The ASTContext object for the analyzed ASTs.
ASTContext& Ctx;
/// CFDictionaryCreateII - An IdentifierInfo* representing the indentifier
/// "CFDictionaryCreate".
IdentifierInfo* CFDictionaryCreateII;
-
+
/// GCEnabled - Records whether or not the analyzed code runs in GC mode.
const bool GCEnabled;
-
+
/// FuncSummaries - A map from FunctionDecls to summaries.
- FuncSummariesTy FuncSummaries;
-
+ FuncSummariesTy FuncSummaries;
+
/// ObjCClassMethodSummaries - A map from selectors (for instance methods)
/// to summaries.
ObjCMethodSummariesTy ObjCClassMethodSummaries;
@@ -624,34 +624,34 @@ class VISIBILITY_HIDDEN RetainSummaryManager {
/// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
/// and all other data used by the checker.
llvm::BumpPtrAllocator BPAlloc;
-
+
/// AF - A factory for ArgEffects objects.
- ArgEffects::Factory AF;
-
+ ArgEffects::Factory AF;
+
/// ScratchArgs - A holding buffer for construct ArgEffects.
ArgEffects ScratchArgs;
-
+
/// ObjCAllocRetE - Default return effect for methods returning Objective-C
/// objects.
RetEffect ObjCAllocRetE;
- /// ObjCInitRetE - Default return effect for init methods returning
+ /// ObjCInitRetE - Default return effect for init methods returning
/// Objective-C objects.
RetEffect ObjCInitRetE;
-
+
RetainSummary DefaultSummary;
RetainSummary* StopSummary;
-
+
//==-----------------------------------------------------------------==//
// Methods.
//==-----------------------------------------------------------------==//
-
+
/// getArgEffects - Returns a persistent ArgEffects object based on the
/// data in ScratchArgs.
ArgEffects getArgEffects();
- enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
-
+ enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };
+
public:
RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
@@ -659,13 +659,13 @@ public:
RetainSummary *Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
return new (Summ) RetainSummary(DefaultSummary);
}
-
+
RetainSummary* getUnarySummary(const FunctionType* FT, UnaryFuncKind func);
-
+
RetainSummary* getCFSummaryCreateRule(FunctionDecl* FD);
- RetainSummary* getCFSummaryGetRule(FunctionDecl* FD);
+ RetainSummary* getCFSummaryGetRule(FunctionDecl* FD);
RetainSummary* getCFCreateGetRuleSummary(FunctionDecl* FD, const char* FName);
-
+
RetainSummary* getPersistentSummary(ArgEffects AE, RetEffect RetEff,
ArgEffect ReceiverEff = DoNothing,
ArgEffect DefaultEff = MayEscape,
@@ -676,36 +676,36 @@ public:
ArgEffect DefaultEff = MayEscape) {
return getPersistentSummary(getArgEffects(), RE, ReceiverEff, DefaultEff);
}
-
+
RetainSummary *getPersistentStopSummary() {
if (StopSummary)
return StopSummary;
-
+
StopSummary = getPersistentSummary(RetEffect::MakeNoRet(),
StopTracking, StopTracking);
return StopSummary;
- }
+ }
RetainSummary *getInitMethodSummary(QualType RetTy);
void InitializeClassMethodSummaries();
void InitializeMethodSummaries();
-
+
bool isTrackedObjCObjectType(QualType T);
bool isTrackedCFObjectType(QualType T);
-
+
private:
-
+
void addClsMethSummary(IdentifierInfo* ClsII, Selector S,
RetainSummary* Summ) {
ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
}
-
+
void addNSObjectClsMethSummary(Selector S, RetainSummary *Summ) {
ObjCClassMethodSummaries[S] = Summ;
}
-
+
void addNSObjectMethSummary(Selector S, RetainSummary *Summ) {
ObjCMethodSummaries[S] = Summ;
}
@@ -716,43 +716,43 @@ private:
Selector S = GetNullarySelector(nullaryName, Ctx);
ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
}
-
+
void addInstMethSummary(const char* Cls, const char* nullaryName,
RetainSummary *Summ) {
IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
Selector S = GetNullarySelector(nullaryName, Ctx);
ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
}
-
+
Selector generateSelector(va_list argp) {
llvm::SmallVector<IdentifierInfo*, 10> II;
while (const char* s = va_arg(argp, const char*))
II.push_back(&Ctx.Idents.get(s));
- return Ctx.Selectors.getSelector(II.size(), &II[0]);
+ return Ctx.Selectors.getSelector(II.size(), &II[0]);
}
-
+
void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy& Summaries,
RetainSummary* Summ, va_list argp) {
Selector S = generateSelector(argp);
Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
}
-
+
void addInstMethSummary(const char* Cls, RetainSummary* Summ, ...) {
va_list argp;
va_start(argp, Summ);
addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
- va_end(argp);
+ va_end(argp);
}
-
+
void addClsMethSummary(const char* Cls, RetainSummary* Summ, ...) {
va_list argp;
va_start(argp, Summ);
addMethodSummary(&Ctx.Idents.get(Cls),ObjCClassMethodSummaries, Summ, argp);
va_end(argp);
}
-
+
void addClsMethSummary(IdentifierInfo *II, RetainSummary* Summ, ...) {
va_list argp;
va_start(argp, Summ);
@@ -769,9 +769,9 @@ private:
addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
va_end(argp);
}
-
+
public:
-
+
RetainSummaryManager(ASTContext& ctx, bool gcenabled)
: Ctx(ctx),
CFDictionaryCreateII(&ctx.Idents.get("CFDictionaryCreate")),
@@ -789,17 +789,17 @@ public:
InitializeClassMethodSummaries();
InitializeMethodSummaries();
}
-
+
~RetainSummaryManager();
-
- RetainSummary* getSummary(FunctionDecl* FD);
-
+
+ RetainSummary* getSummary(FunctionDecl* FD);
+
RetainSummary* getInstanceMethodSummary(ObjCMessageExpr* ME,
const ObjCInterfaceDecl* ID) {
return getInstanceMethodSummary(ME->getSelector(), ME->getClassName(),
- ID, ME->getMethodDecl(), ME->getType());
+ ID, ME->getMethodDecl(), ME->getType());
}
-
+
RetainSummary* getInstanceMethodSummary(Selector S, IdentifierInfo *ClsName,
const ObjCInterfaceDecl* ID,
const ObjCMethodDecl *MD,
@@ -809,7 +809,7 @@ public:
const ObjCInterfaceDecl *ID,
const ObjCMethodDecl *MD,
QualType RetTy);
-
+
RetainSummary *getClassMethodSummary(ObjCMessageExpr *ME) {
return getClassMethodSummary(ME->getSelector(), ME->getClassName(),
ME->getClassInfo().first,
@@ -824,17 +824,17 @@ public:
Selector S = MD->getSelector();
IdentifierInfo *ClsName = ID->getIdentifier();
QualType ResultTy = MD->getResultType();
-
- // Resolve the method decl last.
+
+ // Resolve the method decl last.
if (const ObjCMethodDecl *InterfaceMD = ResolveToInterfaceMethodDecl(MD))
MD = InterfaceMD;
-
+
if (MD->isInstanceMethod())
return getInstanceMethodSummary(S, ClsName, ID, MD, ResultTy);
else
return getClassMethodSummary(S, ClsName, ID, MD, ResultTy);
}
-
+
RetainSummary* getCommonMethodSummary(const ObjCMethodDecl* MD,
Selector S, QualType RetTy);
@@ -845,14 +845,14 @@ public:
const FunctionDecl *FD);
bool isGCEnabled() const { return GCEnabled; }
-
+
RetainSummary *copySummary(RetainSummary *OldSumm) {
RetainSummary *Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
new (Summ) RetainSummary(*OldSumm);
return Summ;
- }
+ }
};
-
+
} // end anonymous namespace
//===----------------------------------------------------------------------===//
@@ -871,7 +871,7 @@ RetainSummary*
RetainSummaryManager::getPersistentSummary(ArgEffects AE, RetEffect RetEff,
ArgEffect ReceiverEff,
ArgEffect DefaultEff,
- bool isEndPath) {
+ bool isEndPath) {
// Create the summary and return it.
RetainSummary *Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
new (Summ) RetainSummary(AE, RetEff, DefaultEff, ReceiverEff, isEndPath);
@@ -887,31 +887,31 @@ bool RetainSummaryManager::isTrackedObjCObjectType(QualType Ty) {
return false;
const ObjCObjectPointerType *PT = Ty->getAsObjCObjectPointerType();
-
+
// Can be true for objects with the 'NSObject' attribute.
if (!PT)
return true;
-
+
// We assume that id<..>, id, and "Class" all represent tracked objects.
if (PT->isObjCIdType() || PT->isObjCQualifiedIdType() ||
PT->isObjCClassType())
return true;
- // Does the interface subclass NSObject?
- // FIXME: We can memoize here if this gets too expensive.
- const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
+ // Does the interface subclass NSObject?
+ // FIXME: We can memoize here if this gets too expensive.
+ const ObjCInterfaceDecl *ID = PT->getInterfaceDecl();
// Assume that anything declared with a forward declaration and no
// @interface subclasses NSObject.
if (ID->isForwardDecl())
return true;
-
+
IdentifierInfo* NSObjectII = &Ctx.Idents.get("NSObject");
for ( ; ID ; ID = ID->getSuperClass())
if (ID->getIdentifier() == NSObjectII)
return true;
-
+
return false;
}
@@ -945,33 +945,33 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
// No summary? Generate one.
RetainSummary *S = 0;
-
+
do {
// We generate "stop" summaries for implicitly defined functions.
if (FD->isImplicit()) {
S = getPersistentStopSummary();
break;
}
-
+
// [PR 3337] Use 'getAsFunctionType' to strip away any typedefs on the
// function's type.
const FunctionType* FT = FD->getType()->getAsFunctionType();
const char* FName = FD->getIdentifier()->getName();
-
+
// Strip away preceding '_'. Doing this here will effect all the checks
// down below.
while (*FName == '_') ++FName;
-
+
// Inspect the result type.
QualType RetTy = FT->getResultType();
-
+
// FIXME: This should all be refactored into a chain of "summary lookup"
// filters.
assert (ScratchArgs.isEmpty());
-
+
switch (strlen(FName)) {
default: break;
-
+
case 17:
// Handle: id NSMakeCollectable(CFTypeRef)
@@ -1003,10 +1003,10 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
// Part of <rdar://problem/6961230>. (IOKit)
// This should be addressed using a API table.
ScratchArgs = AF.Add(ScratchArgs, 2, DecRef);
- S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+ S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
}
break;
-
+
case 25:
if (!memcmp(FName, "IORegistryEntryIDMatching", 25)) {
// Part of <rdar://problem/6961230>. (IOKit)
@@ -1015,13 +1015,13 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
DoNothing, DoNothing);
}
break;
-
+
case 26:
if (!memcmp(FName, "IOOpenFirmwarePathMatching", 26)) {
// Part of <rdar://problem/6961230>. (IOKit)
// This should be addressed using a API table.
S = getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true),
- DoNothing, DoNothing);
+ DoNothing, DoNothing);
}
break;
@@ -1030,7 +1030,7 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
// Part of <rdar://problem/6961230>.
// This should be addressed using a API table.
ScratchArgs = AF.Add(ScratchArgs, 1, DecRef);
- S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+ S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
}
break;
@@ -1043,17 +1043,17 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
}
break;
-
+
case 32:
if (!memcmp(FName, "IOServiceAddMatchingNotification", 32)) {
// Part of <rdar://problem/6961230>.
// This should be addressed using a API table.
ScratchArgs = AF.Add(ScratchArgs, 2, DecRef);
- S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+ S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
}
break;
}
-
+
// Did we get a summary?
if (S)
break;
@@ -1063,7 +1063,7 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
#if 0
// Handle: NSDeallocateObject(id anObject);
// This method does allow 'nil' (although we don't check it now).
- if (strcmp(FName, "NSDeallocateObject") == 0) {
+ if (strcmp(FName, "NSDeallocateObject") == 0) {
return RetTy == Ctx.VoidTy
? getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, Dealloc)
: getPersistentStopSummary();
@@ -1077,7 +1077,7 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
S = getUnarySummary(FT, cfretain);
else if (strstr(FName, "MakeCollectable"))
S = getUnarySummary(FT, cfmakecollectable);
- else
+ else
S = getCFCreateGetRuleSummary(FD, FName);
break;
@@ -1100,7 +1100,7 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
S = getCFCreateGetRuleSummary(FD, FName);
break;
}
-
+
break;
}
@@ -1112,7 +1112,7 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
FName += 4;
else
FName += 2;
-
+
if (isRelease(FD, FName))
S = getUnarySummary(FT, cfrelease);
else {
@@ -1122,9 +1122,9 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
// and that ownership cannot be transferred. While this is technically
// correct, many methods allow a tracked object to escape. For example:
//
- // CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);
+ // CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);
// CFDictionaryAddValue(y, key, x);
- // CFRelease(x);
+ // CFRelease(x);
// ... it is okay to use 'x' since 'y' has a reference to it
//
// We handle this and similar cases with the follow heuristic. If the
@@ -1138,34 +1138,34 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
CStrInCStrNoCase(FName, "AppendValue") ||
CStrInCStrNoCase(FName, "SetAttribute"))
? MayEscape : DoNothing;
-
+
S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, E);
}
}
}
while (0);
-
+
if (!S)
S = getDefaultSummary();
// Annotations override defaults.
assert(S);
updateSummaryFromAnnotations(*S, FD);
-
+
FuncSummaries[FD] = S;
- return S;
+ return S;
}
RetainSummary*
RetainSummaryManager::getCFCreateGetRuleSummary(FunctionDecl* FD,
const char* FName) {
-
+
if (strstr(FName, "Create") || strstr(FName, "Copy"))
return getCFSummaryCreateRule(FD);
-
+
if (strstr(FName, "Get"))
return getCFSummaryGetRule(FD);
-
+
return getDefaultSummary();
}
@@ -1178,27 +1178,27 @@ RetainSummaryManager::getUnarySummary(const FunctionType* FT,
const FunctionProtoType* FTP = dyn_cast<FunctionProtoType>(FT);
if (!FTP || FTP->getNumArgs() != 1)
return getPersistentStopSummary();
-
+
assert (ScratchArgs.isEmpty());
-
+
switch (func) {
case cfretain: {
ScratchArgs = AF.Add(ScratchArgs, 0, IncRef);
return getPersistentSummary(RetEffect::MakeAlias(0),
DoNothing, DoNothing);
}
-
+
case cfrelease: {
ScratchArgs = AF.Add(ScratchArgs, 0, DecRef);
return getPersistentSummary(RetEffect::MakeNoRet(),
DoNothing, DoNothing);
}
-
+
case cfmakecollectable: {
ScratchArgs = AF.Add(ScratchArgs, 0, MakeCollectable);
- return getPersistentSummary(RetEffect::MakeAlias(0),DoNothing, DoNothing);
+ return getPersistentSummary(RetEffect::MakeAlias(0),DoNothing, DoNothing);
}
-
+
default:
assert (false && "Not a supported unary function.");
return getDefaultSummary();
@@ -1207,17 +1207,17 @@ RetainSummaryManager::getUnarySummary(const FunctionType* FT,
RetainSummary* RetainSummaryManager::getCFSummaryCreateRule(FunctionDecl* FD) {
assert (ScratchArgs.isEmpty());
-
+
if (FD->getIdentifier() == CFDictionaryCreateII) {
ScratchArgs = AF.Add(ScratchArgs, 1, DoNothingByRef);
ScratchArgs = AF.Add(ScratchArgs, 2, DoNothingByRef);
}
-
+
return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF, true));
}
RetainSummary* RetainSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
- assert (ScratchArgs.isEmpty());
+ assert (ScratchArgs.isEmpty());
return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF),
DoNothing, DoNothing);
}
@@ -1228,12 +1228,12 @@ RetainSummary* RetainSummaryManager::getCFSummaryGetRule(FunctionDecl* FD) {
RetainSummary*
RetainSummaryManager::getInitMethodSummary(QualType RetTy) {
- assert(ScratchArgs.isEmpty());
+ assert(ScratchArgs.isEmpty());
// 'init' methods conceptually return a newly allocated object and claim
- // the receiver.
+ // the receiver.
if (isTrackedObjCObjectType(RetTy) || isTrackedCFObjectType(RetTy))
return getPersistentSummary(ObjCInitRetE, DecRefMsg);
-
+
return getDefaultSummary();
}
@@ -1244,7 +1244,7 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
return;
QualType RetTy = FD->getResultType();
-
+
// Determine if there is a special return effect for this method.
if (isTrackedObjCObjectType(RetTy)) {
if (FD->getAttr<NSReturnsRetainedAttr>()) {
@@ -1268,20 +1268,20 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ,
return;
bool isTrackedLoc = false;
-
+
// Dete