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/Support/Compiler.h"
Ted Kremenek
committed
#include <ostream>
Ted Kremenek
committed
using namespace clang;
//===----------------------------------------------------------------------===//
// Utility functions.
//===----------------------------------------------------------------------===//
static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
IdentifierInfo* II = &Ctx.Idents.get(name);
return Ctx.Selectors.getSelector(0, &II);
}
//===----------------------------------------------------------------------===//
// Symbolic Evaluation of Reference Counting Logic
//===----------------------------------------------------------------------===//
namespace {
enum ArgEffect { IncRef, DecRef, DoNothing };
Ted Kremenek
committed
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) {
Ted Kremenek
committed
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 {
class RetEffect {
public:
Ted Kremenek
committed
enum Kind { NoRet = 0x0, Alias = 0x1, OwnedSymbol = 0x2,
NotOwnedSymbol = 0x3, ReceiverAlias=0x4 };
private:
unsigned Data;
RetEffect(Kind k, unsigned D) { Data = (D << 3) | (unsigned) k; }
Kind getKind() const { return (Kind) (Data & 0x7); }
unsigned getValue() const {
assert(getKind() == Alias);
return Data >> 3;
Ted Kremenek
committed
static RetEffect MakeAlias(unsigned Idx) { return RetEffect(Alias, Idx); }
static RetEffect MakeReceiverAlias() { return RetEffect(ReceiverAlias, 0); }
static RetEffect MakeOwned() { return RetEffect(OwnedSymbol, 0); }
static RetEffect MakeNotOwned() { return RetEffect(NotOwnedSymbol, 0); }
Ted Kremenek
committed
static RetEffect MakeNoRet() { return RetEffect(NoRet, 0); }
operator Kind() const { return getKind(); }
void Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger(Data); }
};
class RetainSummary : public llvm::FoldingSetNode {
ArgEffects* Args;
RetEffect Ret;
public:
RetainSummary(ArgEffects* A, RetEffect R) : Args(A), Ret(R) {}
unsigned getNumArgs() const { return Args->size(); }
ArgEffect getArg(unsigned idx) const {
Ted Kremenek
committed
if (!Args)
return DoNothing;
// If Args is present, it is likely to contain only 1 element.
// Just do a linear search. Do it from the back because functions with
// large numbers of arguments will be tail heavy with respect to which
// argument they actually modify with respect to the reference count.
for (ArgEffects::reverse_iterator I=Args->rbegin(), E=Args->rend();
I!=E; ++I) {
if (idx > I->first)
return DoNothing;
if (idx == I->first)
return I->second;
}
return DoNothing;
RetEffect getRet() const {
return Ret;
}
typedef ArgEffects::const_iterator arg_iterator;
arg_iterator begin_args() const { return Args->begin(); }
arg_iterator end_args() const { return Args->end(); }
Ted Kremenek
committed
static void Profile(llvm::FoldingSetNodeID& ID, ArgEffects* A, RetEffect R) {
ID.AddPointer(A);
ID.Add(R);
}
void Profile(llvm::FoldingSetNodeID& ID) const {
Profile(ID, Args, Ret);
}
};
Ted Kremenek
committed
class RetainSummaryManager {
//==-----------------------------------------------------------------==//
// Typedefs.
//==-----------------------------------------------------------------==//
typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<ArgEffects> >
ArgEffectsSetTy;
typedef llvm::FoldingSet<RetainSummary>
SummarySetTy;
typedef llvm::DenseMap<FunctionDecl*, RetainSummary*>
FuncSummariesTy;
typedef llvm::DenseMap<Selector, RetainSummary*>
ObjCMethodSummariesTy;
//==-----------------------------------------------------------------==//
// Data.
//==-----------------------------------------------------------------==//
// Ctx - The ASTContext object for the analyzed ASTs.
ASTContext& Ctx;
// GCEnabled - Records whether or not the analyzed code runs in GC mode.
const bool GCEnabled;
// SummarySet - A FoldingSet of uniqued summaries.
SummarySetTy SummarySet;
// FuncSummaries - A map from FunctionDecls to summaries.
FuncSummariesTy FuncSummaries;
// ObjCInstanceMethodSummaries - A map from selectors (for instance methods)
// to summaries.
ObjCMethodSummariesTy ObjCInstanceMethodSummaries;
// ObjCMethodSummaries - A map from selectors to summaries.
ObjCMethodSummariesTy ObjCMethodSummaries;
// ArgEffectsSet - A FoldingSet of uniqued ArgEffects.
ArgEffectsSetTy ArgEffectsSet;
// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
// and all other data used by the checker.
llvm::BumpPtrAllocator BPAlloc;
// ScratchArgs - A holding buffer for construct ArgEffects.
ArgEffects ScratchArgs;
//==-----------------------------------------------------------------==//
// Methods.
Loading
Loading full blame...