Newer
Older
// CFRefCount.cpp - Transfer functions for tracking simple values -*- C++ -*--//
Ted Kremenek
committed
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the methods for CFRefCount, which implements
Ted Kremenek
committed
// a reference count checker for Core Foundation (Mac OS X).
//
//===----------------------------------------------------------------------===//
#include "GRSimpleVals.h"
#include "clang/Basic/LangOptions.h"
Ted Kremenek
committed
#include "clang/Basic/SourceManager.h"
Ted Kremenek
committed
#include "clang/Analysis/PathSensitive/ValueState.h"
Ted Kremenek
committed
#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek
committed
#include "clang/Analysis/LocalCheckers.h"
Ted Kremenek
committed
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Analysis/PathSensitive/BugReporter.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
Ted Kremenek
committed
#include "llvm/ADT/StringExtras.h"
Ted Kremenek
committed
#include "llvm/Support/Compiler.h"
#include "llvm/ADT/STLExtras.h"
Ted Kremenek
committed
#include <ostream>
Ted Kremenek
committed
using namespace clang;
Ted Kremenek
committed
using llvm::CStrInCStrNoCase;
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
IdentifierInfo* II = &Ctx.Idents.get(name);
return Ctx.Selectors.getSelector(0, &II);
}
static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {
IdentifierInfo* II = &Ctx.Idents.get(name);
return Ctx.Selectors.getSelector(1, &II);
}
//===----------------------------------------------------------------------===//
// Type querying functions.
//===----------------------------------------------------------------------===//
static bool isCFRefType(QualType T) {
if (!T->isPointerType())
return false;
// Check the typedef for the name "CF" and the substring "Ref".
TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
if (!TD)
return false;
const char* TDName = TD->getDecl()->getIdentifier()->getName();
assert (TDName);
if (TDName[0] != 'C' || TDName[1] != 'F')
return false;
if (strstr(TDName, "Ref") == 0)
return false;
return true;
}
static bool isCGRefType(QualType T) {
if (!T->isPointerType())
return false;
// Check the typedef for the name "CG" and the substring "Ref".
TypedefType* TD = dyn_cast<TypedefType>(T.getTypePtr());
if (!TD)
return false;
const char* TDName = TD->getDecl()->getIdentifier()->getName();
assert (TDName);
if (TDName[0] != 'C' || TDName[1] != 'G')
return false;
if (strstr(TDName, "Ref") == 0)
return false;
return true;
}
static bool isNSType(QualType T) {
if (!T->isPointerType())
return false;
ObjCInterfaceType* OT = dyn_cast<ObjCInterfaceType>(T.getTypePtr());
if (!OT)
return false;
const char* ClsName = OT->getDecl()->getIdentifier()->getName();
assert (ClsName);
if (ClsName[0] != 'N' || ClsName[1] != 'S')
return false;
return true;
}
//===----------------------------------------------------------------------===//
// Primitives used for constructing summaries for function/method calls.
//===----------------------------------------------------------------------===//
namespace {
/// ArgEffect is used to summarize a function/method call's effect on a
/// particular argument.
enum ArgEffect { IncRef, DecRef, DoNothing, DoNothingByRef,
StopTracking, MayEscape, SelfOwn, Autorelease };
/// ArgEffects summarizes the effects of a function/method call on all of
/// its arguments.
typedef std::vector<std::pair<unsigned,ArgEffect> > ArgEffects;
Ted Kremenek
committed
namespace llvm {
template <> struct FoldingSetTrait<ArgEffects> {
static void Profile(const ArgEffects& X, FoldingSetNodeID& ID) {
for (ArgEffects::const_iterator I = X.begin(), E = X.end(); I!= E; ++I) {
ID.AddInteger(I->first);
ID.AddInteger((unsigned) I->second);
}
}
};
} // end llvm namespace
namespace {
/// RetEffect is used to summarize a function/method call's behavior with
/// respect to its return value.
class VISIBILITY_HIDDEN RetEffect {
enum Kind { NoRet, Alias, OwnedSymbol, OwnedAllocatedSymbol,
NotOwnedSymbol, ReceiverAlias };
private:
unsigned Data;
RetEffect(Kind k, unsigned D = 0) { Data = (D << 3) | (unsigned) k; }
Kind getKind() const { return (Kind) (Data & 0x7); }
assert(getKind() == Alias);
return Data >> 3;
static RetEffect MakeAlias(unsigned Idx) {
return RetEffect(Alias, Idx);
}
static RetEffect MakeReceiverAlias() {
return RetEffect(ReceiverAlias);
}
static RetEffect MakeOwned(bool isAllocated = false) {
return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol);
}
static RetEffect MakeNotOwned() {
return RetEffect(NotOwnedSymbol);
}
static RetEffect MakeNoRet() {
return RetEffect(NoRet);
}
void Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger(Data);
}
class VISIBILITY_HIDDEN RetainSummary : public llvm::FoldingSetNode {
Ted Kremenek
committed
/// 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;
Ted Kremenek
committed
/// DefaultArgEffect - The default ArgEffect to apply to arguments that
/// do not have an entry in Args.
Loading
Loading full blame...