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:
Ted Kremenek 2011-05-02 19:42:42 +00:00
parent 24874a449c
commit aa181174e7
16 changed files with 427 additions and 61 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -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; }

View File

@ -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 {

View File

@ -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;

View File

@ -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

View File

@ -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>();

View File

@ -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();

View File

@ -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 {

View File

@ -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;
}

View File

@ -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) {

View File

@ -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");

View File

@ -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);
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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);
}