forked from OSchip/llvm-project
Augment retain/release checker to not warn about tracked objects passed as arguments to C++ constructors. This is a stop-gap measure for Objective-C++ code that uses smart pointers to manage reference counts.
llvm-svn: 130711
This commit is contained in:
parent
24874a449c
commit
aa181174e7
|
@ -240,9 +240,11 @@ public:
|
|||
class RegionChanges {
|
||||
template <typename CHECKER>
|
||||
static const GRState *_checkRegionChanges(void *checker, const GRState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End) {
|
||||
return ((const CHECKER *)checker)->checkRegionChanges(state, Begin, End);
|
||||
return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
|
||||
Begin, End);
|
||||
}
|
||||
template <typename CHECKER>
|
||||
static bool _wantsRegionChangeUpdate(void *checker, const GRState *state) {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
|
@ -49,6 +50,18 @@ public:
|
|||
|
||||
template <typename T> class CheckerFn;
|
||||
|
||||
template <typename RET, typename P1, typename P2, typename P3, typename P4>
|
||||
class CheckerFn<RET(P1, P2, P3, P4)> {
|
||||
typedef RET (*Func)(void *, P1, P2, P3, P4);
|
||||
Func Fn;
|
||||
public:
|
||||
void *Checker;
|
||||
CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
|
||||
RET operator()(P1 p1, P2 p2, P3 p3, P4 p4) const {
|
||||
return Fn(Checker, p1, p2, p3, p4);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename RET, typename P1, typename P2, typename P3>
|
||||
class CheckerFn<RET(P1, P2, P3)> {
|
||||
typedef RET (*Func)(void *, P1, P2, P3);
|
||||
|
@ -224,9 +237,11 @@ public:
|
|||
bool wantsRegionChangeUpdate(const GRState *state);
|
||||
|
||||
/// \brief Run checkers for region changes.
|
||||
const GRState *runCheckersForRegionChanges(const GRState *state,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End);
|
||||
const GRState *
|
||||
runCheckersForRegionChanges(const GRState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End);
|
||||
|
||||
/// \brief Run checkers for handling assumptions on symbolic values.
|
||||
const GRState *runCheckersForEvalAssume(const GRState *state,
|
||||
|
@ -283,6 +298,7 @@ public:
|
|||
typedef CheckerFn<void (const GRState *,SymbolReaper &)> CheckLiveSymbolsFunc;
|
||||
|
||||
typedef CheckerFn<const GRState * (const GRState *,
|
||||
const StoreManager::InvalidatedSymbols *symbols,
|
||||
const MemRegion * const *begin,
|
||||
const MemRegion * const *end)>
|
||||
CheckRegionChangesFunc;
|
||||
|
|
|
@ -188,9 +188,11 @@ public:
|
|||
|
||||
/// processRegionChanges - Called by GRStateManager whenever a change is made
|
||||
/// to the store. Used to update checkers that track region values.
|
||||
const GRState* processRegionChanges(const GRState *state,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End);
|
||||
const GRState *
|
||||
processRegionChanges(const GRState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End);
|
||||
|
||||
virtual GRStateManager& getStateManager() { return StateMgr; }
|
||||
|
||||
|
|
|
@ -368,6 +368,12 @@ private:
|
|||
assert(refCount > 0);
|
||||
--refCount;
|
||||
}
|
||||
|
||||
const GRState *invalidateRegionsImpl(const MemRegion * const *Begin,
|
||||
const MemRegion * const *End,
|
||||
const Expr *E, unsigned BlockCount,
|
||||
StoreManager::InvalidatedSymbols &IS,
|
||||
bool invalidateGlobals) const;
|
||||
};
|
||||
|
||||
class GRStateSet {
|
||||
|
|
|
@ -188,7 +188,7 @@ public:
|
|||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End,
|
||||
const Expr *E, unsigned Count,
|
||||
InvalidatedSymbols *IS,
|
||||
InvalidatedSymbols &IS,
|
||||
bool invalidateGlobals,
|
||||
InvalidatedRegions *Regions) = 0;
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "clang/Analysis/ProgramPoint.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
|
@ -95,13 +96,17 @@ public:
|
|||
|
||||
/// processRegionChanges - Called by GRStateManager whenever a change is made
|
||||
/// to the store. Used to update checkers that track region values.
|
||||
virtual const GRState* processRegionChanges(const GRState* state,
|
||||
const MemRegion* const *Begin,
|
||||
const MemRegion* const *End) = 0;
|
||||
virtual const GRState *
|
||||
processRegionChanges(const GRState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion* const *Begin,
|
||||
const MemRegion* const *End) = 0;
|
||||
|
||||
inline const GRState* processRegionChange(const GRState* state,
|
||||
const MemRegion* MR) {
|
||||
return processRegionChanges(state, &MR, &MR+1);
|
||||
|
||||
inline const GRState *
|
||||
processRegionChange(const GRState* state,
|
||||
const MemRegion* MR) {
|
||||
return processRegionChanges(state, 0, &MR, &MR+1);
|
||||
}
|
||||
|
||||
/// Called by CoreEngine when the analysis worklist is either empty or the
|
||||
|
|
|
@ -42,6 +42,7 @@ public:
|
|||
bool wantsRegionChangeUpdate(const GRState *state) const;
|
||||
|
||||
const GRState *checkRegionChanges(const GRState *state,
|
||||
const StoreManager::InvalidatedSymbols *,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End) const;
|
||||
|
||||
|
@ -1305,6 +1306,7 @@ bool CStringChecker::wantsRegionChangeUpdate(const GRState *state) const {
|
|||
|
||||
const GRState *
|
||||
CStringChecker::checkRegionChanges(const GRState *state,
|
||||
const StoreManager::InvalidatedSymbols *,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End) const {
|
||||
CStringLength::EntryMap Entries = state->get<CStringLength>();
|
||||
|
|
|
@ -49,11 +49,11 @@ public:
|
|||
SVal Retrieve(Store store, Loc loc, QualType T = QualType());
|
||||
|
||||
StoreRef invalidateRegion(Store store, const MemRegion *R, const Expr *E,
|
||||
unsigned Count, InvalidatedSymbols *IS);
|
||||
unsigned Count, InvalidatedSymbols &IS);
|
||||
|
||||
StoreRef invalidateRegions(Store store, const MemRegion * const *Begin,
|
||||
const MemRegion * const *End, const Expr *E,
|
||||
unsigned Count, InvalidatedSymbols *IS,
|
||||
unsigned Count, InvalidatedSymbols &IS,
|
||||
bool invalidateGlobals,
|
||||
InvalidatedRegions *Regions);
|
||||
|
||||
|
@ -538,7 +538,7 @@ StoreRef BasicStoreManager::invalidateRegions(Store store,
|
|||
const MemRegion * const *I,
|
||||
const MemRegion * const *End,
|
||||
const Expr *E, unsigned Count,
|
||||
InvalidatedSymbols *IS,
|
||||
InvalidatedSymbols &IS,
|
||||
bool invalidateGlobals,
|
||||
InvalidatedRegions *Regions) {
|
||||
StoreRef newStore(store, *this);
|
||||
|
@ -587,18 +587,16 @@ StoreRef BasicStoreManager::invalidateRegion(Store store,
|
|||
const MemRegion *R,
|
||||
const Expr *E,
|
||||
unsigned Count,
|
||||
InvalidatedSymbols *IS) {
|
||||
InvalidatedSymbols &IS) {
|
||||
R = R->StripCasts();
|
||||
|
||||
if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
|
||||
return StoreRef(store, *this);
|
||||
|
||||
if (IS) {
|
||||
BindingsTy B = GetBindings(store);
|
||||
if (BindingsTy::data_type *Val = B.lookup(R)) {
|
||||
if (SymbolRef Sym = Val->getAsSymbol())
|
||||
IS->insert(Sym);
|
||||
}
|
||||
BindingsTy B = GetBindings(store);
|
||||
if (BindingsTy::data_type *Val = B.lookup(R)) {
|
||||
if (SymbolRef Sym = Val->getAsSymbol())
|
||||
IS.insert(Sym);
|
||||
}
|
||||
|
||||
QualType T = cast<TypedRegion>(R)->getValueType();
|
||||
|
|
|
@ -2494,6 +2494,23 @@ static QualType GetReturnType(const Expr* RetE, ASTContext& Ctx) {
|
|||
return RetTy;
|
||||
}
|
||||
|
||||
|
||||
// HACK: Symbols that have ref-count state that are referenced directly
|
||||
// (not as structure or array elements, or via bindings) by an argument
|
||||
// should not have their ref-count state stripped after we have
|
||||
// done an invalidation pass.
|
||||
//
|
||||
// FIXME: This is a global to currently share between CFRefCount and
|
||||
// RetainReleaseChecker. Eventually all functionality in CFRefCount should
|
||||
// be migrated to RetainReleaseChecker, and we can make this a non-global.
|
||||
llvm::DenseSet<SymbolRef> WhitelistedSymbols;
|
||||
namespace {
|
||||
struct ResetWhiteList {
|
||||
ResetWhiteList() {}
|
||||
~ResetWhiteList() { WhitelistedSymbols.clear(); }
|
||||
};
|
||||
}
|
||||
|
||||
void CFRefCount::evalSummary(ExplodedNodeSet& Dst,
|
||||
ExprEngine& Eng,
|
||||
StmtNodeBuilder& Builder,
|
||||
|
@ -2510,12 +2527,9 @@ void CFRefCount::evalSummary(ExplodedNodeSet& Dst,
|
|||
SymbolRef ErrorSym = 0;
|
||||
|
||||
llvm::SmallVector<const MemRegion*, 10> RegionsToInvalidate;
|
||||
|
||||
// HACK: Symbols that have ref-count state that are referenced directly
|
||||
// (not as structure or array elements, or via bindings) by an argument
|
||||
// should not have their ref-count state stripped after we have
|
||||
// done an invalidation pass.
|
||||
llvm::DenseSet<SymbolRef> WhitelistedSymbols;
|
||||
|
||||
// Use RAII to make sure the whitelist is properly cleared.
|
||||
ResetWhiteList resetWhiteList;
|
||||
|
||||
// Invalidate all instance variables of the receiver of a message.
|
||||
// FIXME: We should be able to do better with inter-procedural analysis.
|
||||
|
@ -2624,21 +2638,13 @@ void CFRefCount::evalSummary(ExplodedNodeSet& Dst,
|
|||
|
||||
// NOTE: Even if RegionsToInvalidate is empty, we must still invalidate
|
||||
// global variables.
|
||||
// NOTE: RetainReleaseChecker handles the actual invalidation of symbols.
|
||||
state = state->invalidateRegions(RegionsToInvalidate.data(),
|
||||
RegionsToInvalidate.data() +
|
||||
RegionsToInvalidate.size(),
|
||||
Ex, Count, &IS,
|
||||
/* invalidateGlobals = */ true);
|
||||
|
||||
for (StoreManager::InvalidatedSymbols::iterator I = IS.begin(),
|
||||
E = IS.end(); I!=E; ++I) {
|
||||
SymbolRef sym = *I;
|
||||
if (WhitelistedSymbols.count(sym))
|
||||
continue;
|
||||
// Remove any existing reference-count binding.
|
||||
state = state->remove<RefBindings>(*I);
|
||||
}
|
||||
|
||||
// Evaluate the effect on the message receiver.
|
||||
if (!ErrorRange.isValid() && Receiver) {
|
||||
SymbolRef Sym = Receiver.getSValAsScalarOrLoc(state).getAsLocSymbol();
|
||||
|
@ -3418,12 +3424,43 @@ void CFRefCount::ProcessNonLeakError(ExplodedNodeSet& Dst,
|
|||
|
||||
namespace {
|
||||
class RetainReleaseChecker
|
||||
: public Checker< check::PostStmt<BlockExpr> > {
|
||||
: public Checker< check::PostStmt<BlockExpr>, check::RegionChanges > {
|
||||
public:
|
||||
bool wantsRegionUpdate;
|
||||
|
||||
RetainReleaseChecker() : wantsRegionUpdate(true) {}
|
||||
|
||||
|
||||
void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
|
||||
const GRState *checkRegionChanges(const GRState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *begin,
|
||||
const MemRegion * const *end) const;
|
||||
|
||||
bool wantsRegionChangeUpdate(const GRState *state) const {
|
||||
return wantsRegionUpdate;
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
const GRState *
|
||||
RetainReleaseChecker::checkRegionChanges(const GRState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *begin,
|
||||
const MemRegion * const *end) const {
|
||||
if (!invalidated)
|
||||
return state;
|
||||
|
||||
for (StoreManager::InvalidatedSymbols::const_iterator I=invalidated->begin(),
|
||||
E = invalidated->end(); I!=E; ++I) {
|
||||
SymbolRef sym = *I;
|
||||
if (WhitelistedSymbols.count(sym))
|
||||
continue;
|
||||
// Remove any existing reference-count binding.
|
||||
state = state->remove<RefBindings>(sym);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
void RetainReleaseChecker::checkPostStmt(const BlockExpr *BE,
|
||||
CheckerContext &C) const {
|
||||
|
|
|
@ -345,6 +345,7 @@ bool CheckerManager::wantsRegionChangeUpdate(const GRState *state) {
|
|||
/// \brief Run checkers for region changes.
|
||||
const GRState *
|
||||
CheckerManager::runCheckersForRegionChanges(const GRState *state,
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End) {
|
||||
for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
|
||||
|
@ -352,7 +353,7 @@ CheckerManager::runCheckersForRegionChanges(const GRState *state,
|
|||
// bail out.
|
||||
if (!state)
|
||||
return NULL;
|
||||
state = RegionChangesCheckers[i].CheckFn(state, Begin, End);
|
||||
state = RegionChangesCheckers[i].CheckFn(state, invalidated, Begin, End);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -179,9 +179,11 @@ bool ExprEngine::wantsRegionChangeUpdate(const GRState* state) {
|
|||
|
||||
const GRState *
|
||||
ExprEngine::processRegionChanges(const GRState *state,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End) {
|
||||
return getCheckerManager().runCheckersForRegionChanges(state, Begin, End);
|
||||
const StoreManager::InvalidatedSymbols *invalidated,
|
||||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End) {
|
||||
return getCheckerManager().runCheckersForRegionChanges(state, invalidated,
|
||||
Begin, End);
|
||||
}
|
||||
|
||||
void ExprEngine::processEndWorklist(bool hasWorkRemaining) {
|
||||
|
|
|
@ -59,7 +59,7 @@ public:
|
|||
|
||||
StoreRef invalidateRegions(Store store, const MemRegion * const *I,
|
||||
const MemRegion * const *E, const Expr *Ex,
|
||||
unsigned Count, InvalidatedSymbols *IS,
|
||||
unsigned Count, InvalidatedSymbols &IS,
|
||||
bool invalidateGlobals,
|
||||
InvalidatedRegions *Regions);
|
||||
|
||||
|
@ -175,7 +175,7 @@ StoreRef FlatStoreManager::invalidateRegions(Store store,
|
|||
const MemRegion * const *I,
|
||||
const MemRegion * const *E,
|
||||
const Expr *Ex, unsigned Count,
|
||||
InvalidatedSymbols *IS,
|
||||
InvalidatedSymbols &IS,
|
||||
bool invalidateGlobals,
|
||||
InvalidatedRegions *Regions) {
|
||||
assert(false && "Not implemented");
|
||||
|
|
|
@ -141,6 +141,20 @@ const GRState *GRState::invalidateRegions(const MemRegion * const *Begin,
|
|||
const Expr *E, unsigned Count,
|
||||
StoreManager::InvalidatedSymbols *IS,
|
||||
bool invalidateGlobals) const {
|
||||
if (!IS) {
|
||||
StoreManager::InvalidatedSymbols invalidated;
|
||||
return invalidateRegionsImpl(Begin, End, E, Count,
|
||||
invalidated, invalidateGlobals);
|
||||
}
|
||||
return invalidateRegionsImpl(Begin, End, E, Count, *IS, invalidateGlobals);
|
||||
}
|
||||
|
||||
const GRState *
|
||||
GRState::invalidateRegionsImpl(const MemRegion * const *Begin,
|
||||
const MemRegion * const *End,
|
||||
const Expr *E, unsigned Count,
|
||||
StoreManager::InvalidatedSymbols &IS,
|
||||
bool invalidateGlobals) const {
|
||||
GRStateManager &Mgr = getStateManager();
|
||||
SubEngine* Eng = Mgr.getOwningEngine();
|
||||
|
||||
|
@ -150,7 +164,7 @@ const GRState *GRState::invalidateRegions(const MemRegion * const *Begin,
|
|||
= Mgr.StoreMgr->invalidateRegions(getStore(), Begin, End, E, Count, IS,
|
||||
invalidateGlobals, &Regions);
|
||||
const GRState *newState = makeWithStore(newStore);
|
||||
return Eng->processRegionChanges(newState,
|
||||
return Eng->processRegionChanges(newState, &IS,
|
||||
&Regions.front(),
|
||||
&Regions.back()+1);
|
||||
}
|
||||
|
|
|
@ -240,7 +240,7 @@ public:
|
|||
const MemRegion * const *Begin,
|
||||
const MemRegion * const *End,
|
||||
const Expr *E, unsigned Count,
|
||||
InvalidatedSymbols *IS,
|
||||
InvalidatedSymbols &IS,
|
||||
bool invalidateGlobals,
|
||||
InvalidatedRegions *Regions);
|
||||
|
||||
|
@ -586,14 +586,14 @@ class invalidateRegionsWorker : public ClusterAnalysis<invalidateRegionsWorker>
|
|||
{
|
||||
const Expr *Ex;
|
||||
unsigned Count;
|
||||
StoreManager::InvalidatedSymbols *IS;
|
||||
StoreManager::InvalidatedSymbols &IS;
|
||||
StoreManager::InvalidatedRegions *Regions;
|
||||
public:
|
||||
invalidateRegionsWorker(RegionStoreManager &rm,
|
||||
GRStateManager &stateMgr,
|
||||
RegionBindings b,
|
||||
const Expr *ex, unsigned count,
|
||||
StoreManager::InvalidatedSymbols *is,
|
||||
StoreManager::InvalidatedSymbols &is,
|
||||
StoreManager::InvalidatedRegions *r,
|
||||
bool includeGlobals)
|
||||
: ClusterAnalysis<invalidateRegionsWorker>(rm, stateMgr, b, includeGlobals),
|
||||
|
@ -609,9 +609,8 @@ private:
|
|||
|
||||
void invalidateRegionsWorker::VisitBinding(SVal V) {
|
||||
// A symbol? Mark it touched by the invalidation.
|
||||
if (IS)
|
||||
if (SymbolRef Sym = V.getAsSymbol())
|
||||
IS->insert(Sym);
|
||||
if (SymbolRef Sym = V.getAsSymbol())
|
||||
IS.insert(Sym);
|
||||
|
||||
if (const MemRegion *R = V.getAsRegion()) {
|
||||
AddToWorkList(R);
|
||||
|
@ -648,11 +647,9 @@ void invalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
|
|||
}
|
||||
|
||||
void invalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) {
|
||||
if (IS) {
|
||||
// Symbolic region? Mark that symbol touched by the invalidation.
|
||||
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
|
||||
IS->insert(SR->getSymbol());
|
||||
}
|
||||
// Symbolic region? Mark that symbol touched by the invalidation.
|
||||
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
|
||||
IS.insert(SR->getSymbol());
|
||||
|
||||
// BlockDataRegion? If so, invalidate captured variables that are passed
|
||||
// by reference.
|
||||
|
@ -724,7 +721,7 @@ StoreRef RegionStoreManager::invalidateRegions(Store store,
|
|||
const MemRegion * const *I,
|
||||
const MemRegion * const *E,
|
||||
const Expr *Ex, unsigned Count,
|
||||
InvalidatedSymbols *IS,
|
||||
InvalidatedSymbols &IS,
|
||||
bool invalidateGlobals,
|
||||
InvalidatedRegions *Regions) {
|
||||
invalidateRegionsWorker W(*this, StateMgr,
|
||||
|
|
|
@ -280,7 +280,7 @@ CFAbsoluteTime f1() {
|
|||
CFRelease(date);
|
||||
CFDateGetAbsoluteTime(date); // no-warning
|
||||
CFRelease(date);
|
||||
t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released.}}
|
||||
t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released}}
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -291,7 +291,7 @@ CFAbsoluteTime f2() {
|
|||
CFRelease(date);
|
||||
CFDateGetAbsoluteTime(date); // no-warning
|
||||
[((NSDate*) date) release];
|
||||
t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released.}}
|
||||
t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released}}
|
||||
return t;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,284 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease -analyzer-store=region -fblocks -verify %s
|
||||
|
||||
#if __has_feature(attribute_ns_returns_retained)
|
||||
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
|
||||
#endif
|
||||
#if __has_feature(attribute_cf_returns_retained)
|
||||
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
|
||||
#endif
|
||||
#if __has_feature(attribute_ns_returns_not_retained)
|
||||
#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
|
||||
#endif
|
||||
#if __has_feature(attribute_cf_returns_not_retained)
|
||||
#define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
|
||||
#endif
|
||||
#if __has_feature(attribute_ns_consumes_self)
|
||||
#define NS_CONSUMES_SELF __attribute__((ns_consumes_self))
|
||||
#endif
|
||||
#if __has_feature(attribute_ns_consumed)
|
||||
#define NS_CONSUMED __attribute__((ns_consumed))
|
||||
#endif
|
||||
#if __has_feature(attribute_cf_consumed)
|
||||
#define CF_CONSUMED __attribute__((cf_consumed))
|
||||
#endif
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// The following code is reduced using delta-debugging from Mac OS X headers:
|
||||
//
|
||||
// #include <Cocoa/Cocoa.h>
|
||||
// #include <CoreFoundation/CoreFoundation.h>
|
||||
// #include <DiskArbitration/DiskArbitration.h>
|
||||
// #include <QuartzCore/QuartzCore.h>
|
||||
// #include <Quartz/Quartz.h>
|
||||
// #include <IOKit/IOKitLib.h>
|
||||
//
|
||||
// It includes the basic definitions for the test cases below.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
typedef unsigned int __darwin_natural_t;
|
||||
typedef unsigned long uintptr_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef unsigned int UInt32;
|
||||
typedef signed long CFIndex;
|
||||
typedef struct {
|
||||
CFIndex location;
|
||||
CFIndex length;
|
||||
} CFRange;
|
||||
static __inline__ __attribute__((always_inline)) CFRange CFRangeMake(CFIndex loc, CFIndex len) {
|
||||
CFRange range;
|
||||
range.location = loc;
|
||||
range.length = len;
|
||||
return range;
|
||||
}
|
||||
typedef const void * CFTypeRef;
|
||||
typedef const struct __CFString * CFStringRef;
|
||||
typedef const struct __CFAllocator * CFAllocatorRef;
|
||||
extern const CFAllocatorRef kCFAllocatorDefault;
|
||||
extern CFTypeRef CFRetain(CFTypeRef cf);
|
||||
extern void CFRelease(CFTypeRef cf);
|
||||
typedef struct {
|
||||
}
|
||||
CFArrayCallBacks;
|
||||
extern const CFArrayCallBacks kCFTypeArrayCallBacks;
|
||||
typedef const struct __CFArray * CFArrayRef;
|
||||
typedef struct __CFArray * CFMutableArrayRef;
|
||||
extern CFMutableArrayRef CFArrayCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFArrayCallBacks *callBacks);
|
||||
extern const void *CFArrayGetValueAtIndex(CFArrayRef theArray, CFIndex idx);
|
||||
extern void CFArrayAppendValue(CFMutableArrayRef theArray, const void *value);
|
||||
typedef struct {
|
||||
}
|
||||
CFDictionaryKeyCallBacks;
|
||||
extern const CFDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks;
|
||||
typedef struct {
|
||||
}
|
||||
CFDictionaryValueCallBacks;
|
||||
extern const CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks;
|
||||
typedef const struct __CFDictionary * CFDictionaryRef;
|
||||
typedef struct __CFDictionary * CFMutableDictionaryRef;
|
||||
extern CFMutableDictionaryRef CFDictionaryCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks);
|
||||
typedef UInt32 CFStringEncoding;
|
||||
enum {
|
||||
kCFStringEncodingMacRoman = 0, kCFStringEncodingWindowsLatin1 = 0x0500, kCFStringEncodingISOLatin1 = 0x0201, kCFStringEncodingNextStepLatin = 0x0B01, kCFStringEncodingASCII = 0x0600, kCFStringEncodingUnicode = 0x0100, kCFStringEncodingUTF8 = 0x08000100, kCFStringEncodingNonLossyASCII = 0x0BFF , kCFStringEncodingUTF16 = 0x0100, kCFStringEncodingUTF16BE = 0x10000100, kCFStringEncodingUTF16LE = 0x14000100, kCFStringEncodingUTF32 = 0x0c000100, kCFStringEncodingUTF32BE = 0x18000100, kCFStringEncodingUTF32LE = 0x1c000100 };
|
||||
extern CFStringRef CFStringCreateWithCString(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding);
|
||||
typedef double CFTimeInterval;
|
||||
typedef CFTimeInterval CFAbsoluteTime;
|
||||
extern CFAbsoluteTime CFAbsoluteTimeGetCurrent(void);
|
||||
typedef const struct __CFDate * CFDateRef;
|
||||
extern CFDateRef CFDateCreate(CFAllocatorRef allocator, CFAbsoluteTime at);
|
||||
extern CFAbsoluteTime CFDateGetAbsoluteTime(CFDateRef theDate);
|
||||
typedef __darwin_natural_t natural_t;
|
||||
typedef natural_t mach_port_name_t;
|
||||
typedef mach_port_name_t mach_port_t;
|
||||
typedef int kern_return_t;
|
||||
typedef kern_return_t mach_error_t;
|
||||
enum {
|
||||
kCFNumberSInt8Type = 1, kCFNumberSInt16Type = 2, kCFNumberSInt32Type = 3, kCFNumberSInt64Type = 4, kCFNumberFloat32Type = 5, kCFNumberFloat64Type = 6, kCFNumberCharType = 7, kCFNumberShortType = 8, kCFNumberIntType = 9, kCFNumberLongType = 10, kCFNumberLongLongType = 11, kCFNumberFloatType = 12, kCFNumberDoubleType = 13, kCFNumberCFIndexType = 14, kCFNumberNSIntegerType = 15, kCFNumberCGFloatType = 16, kCFNumberMaxType = 16 };
|
||||
typedef CFIndex CFNumberType;
|
||||
typedef const struct __CFNumber * CFNumberRef;
|
||||
extern CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr);
|
||||
typedef const struct __CFAttributedString *CFAttributedStringRef;
|
||||
typedef struct __CFAttributedString *CFMutableAttributedStringRef;
|
||||
extern CFAttributedStringRef CFAttributedStringCreate(CFAllocatorRef alloc, CFStringRef str, CFDictionaryRef attributes) ;
|
||||
extern CFMutableAttributedStringRef CFAttributedStringCreateMutableCopy(CFAllocatorRef alloc, CFIndex maxLength, CFAttributedStringRef aStr) ;
|
||||
extern void CFAttributedStringSetAttribute(CFMutableAttributedStringRef aStr, CFRange range, CFStringRef attrName, CFTypeRef value) ;
|
||||
typedef signed char BOOL;
|
||||
typedef unsigned long NSUInteger;
|
||||
@class NSString, Protocol;
|
||||
extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
|
||||
typedef struct _NSZone NSZone;
|
||||
@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
|
||||
@protocol NSObject
|
||||
- (BOOL)isEqual:(id)object;
|
||||
- (id)retain;
|
||||
- (oneway void)release;
|
||||
- (id)autorelease;
|
||||
@end @protocol NSCopying - (id)copyWithZone:(NSZone *)zone;
|
||||
@end @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone;
|
||||
@end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder;
|
||||
@end
|
||||
@interface NSObject <NSObject> {}
|
||||
+ (id)allocWithZone:(NSZone *)zone;
|
||||
+ (id)alloc;
|
||||
- (void)dealloc;
|
||||
@end
|
||||
@interface NSObject (NSCoderMethods)
|
||||
- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder;
|
||||
@end
|
||||
extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
|
||||
typedef struct {
|
||||
}
|
||||
NSFastEnumerationState;
|
||||
@protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len;
|
||||
@end @class NSString, NSDictionary;
|
||||
@interface NSValue : NSObject <NSCopying, NSCoding> - (void)getValue:(void *)value;
|
||||
@end @interface NSNumber : NSValue - (char)charValue;
|
||||
- (id)initWithInt:(int)value;
|
||||
@end @class NSString;
|
||||
@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count;
|
||||
@end @interface NSArray (NSArrayCreation) + (id)array;
|
||||
@end @interface NSAutoreleasePool : NSObject {
|
||||
}
|
||||
- (void)drain;
|
||||
@end extern NSString * const NSBundleDidLoadNotification;
|
||||
typedef double NSTimeInterval;
|
||||
@interface NSDate : NSObject <NSCopying, NSCoding> - (NSTimeInterval)timeIntervalSinceReferenceDate;
|
||||
@end typedef unsigned short unichar;
|
||||
@interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length;
|
||||
- ( const char *)UTF8String;
|
||||
- (id)initWithUTF8String:(const char *)nullTerminatedCString;
|
||||
+ (id)stringWithUTF8String:(const char *)nullTerminatedCString;
|
||||
@end @class NSString, NSURL, NSError;
|
||||
@interface NSData : NSObject <NSCopying, NSMutableCopying, NSCoding> - (NSUInteger)length;
|
||||
+ (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length;
|
||||
+ (id)dataWithBytesNoCopy:(void *)bytes length:(NSUInteger)length freeWhenDone:(BOOL)b;
|
||||
@end @class NSLocale, NSDate, NSCalendar, NSTimeZone, NSError, NSArray, NSMutableDictionary;
|
||||
@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count;
|
||||
@end @interface NSMutableDictionary : NSDictionary - (void)removeObjectForKey:(id)aKey;
|
||||
- (void)setObject:(id)anObject forKey:(id)aKey;
|
||||
@end @interface NSMutableDictionary (NSMutableDictionaryCreation) + (id)dictionaryWithCapacity:(NSUInteger)numItems;
|
||||
@end typedef double CGFloat;
|
||||
struct CGSize {
|
||||
};
|
||||
typedef struct CGSize CGSize;
|
||||
struct CGRect {
|
||||
};
|
||||
typedef struct CGRect CGRect;
|
||||
typedef mach_port_t io_object_t;
|
||||
typedef char io_name_t[128];
|
||||
typedef io_object_t io_iterator_t;
|
||||
typedef io_object_t io_service_t;
|
||||
typedef struct IONotificationPort * IONotificationPortRef;
|
||||
typedef void (*IOServiceMatchingCallback)( void * refcon, io_iterator_t iterator );
|
||||
io_service_t IOServiceGetMatchingService( mach_port_t masterPort, CFDictionaryRef matching );
|
||||
kern_return_t IOServiceGetMatchingServices( mach_port_t masterPort, CFDictionaryRef matching, io_iterator_t * existing );
|
||||
kern_return_t IOServiceAddNotification( mach_port_t masterPort, const io_name_t notificationType, CFDictionaryRef matching, mach_port_t wakePort, uintptr_t reference, io_iterator_t * notification ) __attribute__((deprecated));
|
||||
kern_return_t IOServiceAddMatchingNotification( IONotificationPortRef notifyPort, const io_name_t notificationType, CFDictionaryRef matching, IOServiceMatchingCallback callback, void * refCon, io_iterator_t * notification );
|
||||
CFMutableDictionaryRef IOServiceMatching( const char * name );
|
||||
CFMutableDictionaryRef IOServiceNameMatching( const char * name );
|
||||
CFMutableDictionaryRef IOBSDNameMatching( mach_port_t masterPort, uint32_t options, const char * bsdName );
|
||||
CFMutableDictionaryRef IOOpenFirmwarePathMatching( mach_port_t masterPort, uint32_t options, const char * path );
|
||||
CFMutableDictionaryRef IORegistryEntryIDMatching( uint64_t entryID );
|
||||
typedef struct __DASession * DASessionRef;
|
||||
extern DASessionRef DASessionCreate( CFAllocatorRef allocator );
|
||||
typedef struct __DADisk * DADiskRef;
|
||||
extern DADiskRef DADiskCreateFromBSDName( CFAllocatorRef allocator, DASessionRef session, const char * name );
|
||||
extern DADiskRef DADiskCreateFromIOMedia( CFAllocatorRef allocator, DASessionRef session, io_service_t media );
|
||||
extern CFDictionaryRef DADiskCopyDescription( DADiskRef disk );
|
||||
extern DADiskRef DADiskCopyWholeDisk( DADiskRef disk );
|
||||
@interface NSTask : NSObject - (id)init;
|
||||
@end typedef struct CGColorSpace *CGColorSpaceRef;
|
||||
typedef struct CGImage *CGImageRef;
|
||||
typedef struct CGLayer *CGLayerRef;
|
||||
@interface NSResponder : NSObject <NSCoding> {
|
||||
}
|
||||
@end @protocol NSAnimatablePropertyContainer - (id)animator;
|
||||
@end extern NSString *NSAnimationTriggerOrderIn ;
|
||||
@interface NSView : NSResponder <NSAnimatablePropertyContainer> {
|
||||
}
|
||||
@end @protocol NSValidatedUserInterfaceItem - (SEL)action;
|
||||
@end @protocol NSUserInterfaceValidations - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)anItem;
|
||||
@end @class NSDate, NSDictionary, NSError, NSException, NSNotification;
|
||||
@interface NSApplication : NSResponder <NSUserInterfaceValidations> {
|
||||
}
|
||||
@end enum {
|
||||
NSTerminateCancel = 0, NSTerminateNow = 1, NSTerminateLater = 2 };
|
||||
typedef NSUInteger NSApplicationTerminateReply;
|
||||
@protocol NSApplicationDelegate <NSObject> @optional - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
|
||||
@end @class NSAttributedString, NSEvent, NSFont, NSFormatter, NSImage, NSMenu, NSText, NSView, NSTextView;
|
||||
@interface NSCell : NSObject <NSCopying, NSCoding> {
|
||||
}
|
||||
@end @class NSTextField, NSPanel, NSArray, NSWindow, NSImage, NSButton, NSError;
|
||||
typedef struct {
|
||||
}
|
||||
CVTimeStamp;
|
||||
@interface CIImage : NSObject <NSCoding, NSCopying> {
|
||||
}
|
||||
typedef int CIFormat;
|
||||
@end enum {
|
||||
kDAReturnSuccess = 0, kDAReturnError = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x01, kDAReturnBusy = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x02, kDAReturnBadArgument = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x03, kDAReturnExclusiveAccess = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x04, kDAReturnNoResources = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x05, kDAReturnNotFound = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x06, kDAReturnNotMounted = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x07, kDAReturnNotPermitted = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x08, kDAReturnNotPrivileged = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x09, kDAReturnNotReady = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0A, kDAReturnNotWritable = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0B, kDAReturnUnsupported = (((0x3eU)&0x3f)<<26) | (((0x368)&0xfff)<<14) | 0x0C };
|
||||
typedef mach_error_t DAReturn;
|
||||
typedef const struct __DADissenter * DADissenterRef;
|
||||
extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn status, CFStringRef string );
|
||||
@interface CIContext: NSObject {
|
||||
}
|
||||
- (CGImageRef)createCGImage:(CIImage *)im fromRect:(CGRect)r;
|
||||
- (CGImageRef)createCGImage:(CIImage *)im fromRect:(CGRect)r format:(CIFormat)f colorSpace:(CGColorSpaceRef)cs;
|
||||
- (CGLayerRef)createCGLayerWithSize:(CGSize)size info:(CFDictionaryRef)d;
|
||||
@end extern NSString* const QCRendererEventKey;
|
||||
@protocol QCCompositionRenderer - (NSDictionary*) attributes;
|
||||
@end @interface QCRenderer : NSObject <QCCompositionRenderer> {
|
||||
}
|
||||
- (id) createSnapshotImageOfType:(NSString*)type;
|
||||
@end extern NSString* const QCViewDidStartRenderingNotification;
|
||||
@interface QCView : NSView <QCCompositionRenderer> {
|
||||
}
|
||||
- (id) createSnapshotImageOfType:(NSString*)type;
|
||||
@end enum {
|
||||
ICEXIFOrientation1 = 1, ICEXIFOrientation2 = 2, ICEXIFOrientation3 = 3, ICEXIFOrientation4 = 4, ICEXIFOrientation5 = 5, ICEXIFOrientation6 = 6, ICEXIFOrientation7 = 7, ICEXIFOrientation8 = 8, };
|
||||
@class ICDevice;
|
||||
@protocol ICDeviceDelegate <NSObject> @required - (void)didRemoveDevice:(ICDevice*)device;
|
||||
@end extern NSString *const ICScannerStatusWarmingUp;
|
||||
@class ICScannerDevice;
|
||||
@protocol ICScannerDeviceDelegate <ICDeviceDelegate> @optional - (void)scannerDeviceDidBecomeAvailable:(ICScannerDevice*)scanner;
|
||||
@end
|
||||
|
||||
typedef long unsigned int __darwin_size_t;
|
||||
typedef __darwin_size_t size_t;
|
||||
typedef unsigned long CFTypeID;
|
||||
struct CGPoint {
|
||||
CGFloat x;
|
||||
CGFloat y;
|
||||
};
|
||||
typedef struct CGPoint CGPoint;
|
||||
typedef struct CGGradient *CGGradientRef;
|
||||
typedef uint32_t CGGradientDrawingOptions;
|
||||
extern CFTypeID CGGradientGetTypeID(void);
|
||||
extern CGGradientRef CGGradientCreateWithColorComponents(CGColorSpaceRef
|
||||
space, const CGFloat components[], const CGFloat locations[], size_t count);
|
||||
extern CGGradientRef CGGradientCreateWithColors(CGColorSpaceRef space,
|
||||
CFArrayRef colors, const CGFloat locations[]);
|
||||
extern CGGradientRef CGGradientRetain(CGGradientRef gradient);
|
||||
extern void CGGradientRelease(CGGradientRef gradient);
|
||||
typedef struct CGContext *CGContextRef;
|
||||
extern void CGContextDrawLinearGradient(CGContextRef context,
|
||||
CGGradientRef gradient, CGPoint startPoint, CGPoint endPoint,
|
||||
CGGradientDrawingOptions options);
|
||||
extern CGColorSpaceRef CGColorSpaceCreateDeviceRGB(void);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Test cases.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
class SmartPointer {
|
||||
id x;
|
||||
public:
|
||||
SmartPointer(id x) : x(x) {}
|
||||
~SmartPointer() { [x release]; }
|
||||
};
|
||||
|
||||
void test_smartpointer_1() {
|
||||
id x = [[NSObject alloc] init]; // no-warning
|
||||
SmartPointer foo(x);
|
||||
}
|
||||
|
Loading…
Reference in New Issue