From: Anna Zaks Date: Thu, 8 Mar 2012 23:16:35 +0000 (+0000) Subject: [analyzer] Rework inlining related command line options. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=66253352131e3e7a22b3bfd0e180607aa2bfb988;p=clang [analyzer] Rework inlining related command line options. - Remove -analyzer-inline-call. - Add -analyzer-ipa=[none|inlining] - Add -analyzer-inlining-mode to allow experimentation for different performance tuning methods. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152351 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 04168f043c..d32ea0b9e0 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -80,12 +80,25 @@ def analyzer_viz_egraph_graphviz : Flag<"-analyzer-viz-egraph-graphviz">, HelpText<"Display exploded graph using GraphViz">; def analyzer_viz_egraph_ubigraph : Flag<"-analyzer-viz-egraph-ubigraph">, HelpText<"Display exploded graph using Ubigraph">; -def analyzer_inline_call : Flag<"-analyzer-inline-call">, - HelpText<"Experimental: Inline callees when their definitions are available">; + def analyzer_inline_max_stack_depth : Separate<"-analyzer-inline-max-stack-depth">, HelpText<"Bound on stack depth while inlining (4 by default)">; +def analyzer_inline_max_stack_depth_EQ : Joined<"-analyzer-inline-max-stack-depth=">, + Alias; + def analyzer_inline_max_function_size : Separate<"-analyzer-inline-max-function-size">, HelpText<"Bound on the number of basic blocks in an inlined function (200 by default)">; +def analyzer_inline_max_function_size_EQ : Joined<"-analyzer-inline-max-function-size=">, + Alias; + +def analyzer_ipa : Separate<"-analyzer-ipa">, + HelpText<"Specify the inter-procedural analysis mode">; +def analyzer_ipa_EQ : Joined<"-analyzer-ipa=">, Alias; + +def analyzer_inlining_mode : Separate<"-analyzer-inlining-mode">, + HelpText<"Specify the function selection heuristic used during inlining">; +def analyzer_inlining_mode_EQ : Joined<"-analyzer-inlining-mode=">, Alias; + def analyzer_max_nodes : Separate<"-analyzer-max-nodes">, HelpText<"The maximum number of nodes the analyzer can generate (150000 default, 0 = no limit)">; def analyzer_max_loop : Separate<"-analyzer-max-loop">, diff --git a/include/clang/Frontend/Analyses.def b/include/clang/Frontend/Analyses.def index 010f889c09..de33c52172 100644 --- a/include/clang/Frontend/Analyses.def +++ b/include/clang/Frontend/Analyses.def @@ -41,8 +41,24 @@ ANALYSIS_PURGE(PurgeStmt, "statement", "Purge symbols, bindings, and constraint ANALYSIS_PURGE(PurgeBlock, "block", "Purge symbols, bindings, and constraints before every basic block") ANALYSIS_PURGE(PurgeNone, "none", "Do not purge symbols, bindings, or constraints") +#ifndef ANALYSIS_IPA +#define ANALYSIS_IPA(NAME, CMDFLAG, DESC) +#endif + +ANALYSIS_IPA(None, "none", "Perform only intra-procedural analysis") +ANALYSIS_IPA(Inlining, "inlining", "Experimental: Inline callees when their definitions are available") + +#ifndef ANALYSIS_INLINING_MODE +#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) +#endif + +ANALYSIS_INLINING_MODE(All, "all", "Analyze all functions in the order defined in the TU") +ANALYSIS_INLINING_MODE(NoRedundancy, "noredundancy", "Do not analyze a function which has been previously inlined, use call graph to order") + #undef ANALYSIS_STORE #undef ANALYSIS_CONSTRAINTS #undef ANALYSIS_DIAGNOSTICS #undef ANALYSIS_PURGE +#undef ANALYSIS_INLINING_MODE +#undef ANALYSIS_IPA diff --git a/include/clang/Frontend/AnalyzerOptions.h b/include/clang/Frontend/AnalyzerOptions.h index 3b41f4b1fb..90ef93621c 100644 --- a/include/clang/Frontend/AnalyzerOptions.h +++ b/include/clang/Frontend/AnalyzerOptions.h @@ -60,6 +60,20 @@ enum AnalysisPurgeMode { NumPurgeModes }; +/// AnalysisIPAMode - Set of inter-procedural modes. +enum AnalysisIPAMode { +#define ANALYSIS_IPA(NAME, CMDFLAG, DESC) NAME, +#include "clang/Frontend/Analyses.def" +NumIPAModes +}; + +/// AnalysisInlineFunctionSelection - Set of inlining function selection heuristics. +enum AnalysisInliningMode { +#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) NAME, +#include "clang/Frontend/Analyses.def" +NumInliningModes +}; + class AnalyzerOptions { public: /// \brief Pair of checker name and enable/disable. @@ -68,6 +82,7 @@ public: AnalysisConstraints AnalysisConstraintsOpt; AnalysisDiagClients AnalysisDiagOpt; AnalysisPurgeMode AnalysisPurgeOpt; + AnalysisIPAMode IPAMode; std::string AnalyzeSpecificFunction; unsigned MaxNodes; unsigned MaxLoop; @@ -79,7 +94,6 @@ public: unsigned TrimGraph : 1; unsigned VisualizeEGDot : 1; unsigned VisualizeEGUbi : 1; - unsigned InlineCall : 1; unsigned UnoptimizedCFG : 1; unsigned CFGAddImplicitDtors : 1; unsigned CFGAddInitializers : 1; @@ -87,6 +101,7 @@ public: unsigned PrintStats : 1; unsigned InlineMaxStackDepth; unsigned InlineMaxFunctionSize; + AnalysisInliningMode InliningMode; public: AnalyzerOptions() { @@ -94,6 +109,7 @@ public: AnalysisConstraintsOpt = RangeConstraintsModel; AnalysisDiagOpt = PD_HTML; AnalysisPurgeOpt = PurgeStmt; + IPAMode = Inlining; ShowCheckerHelp = 0; AnalyzeAll = 0; AnalyzerDisplayProgress = 0; @@ -102,7 +118,6 @@ public: TrimGraph = 0; VisualizeEGDot = 0; VisualizeEGUbi = 0; - InlineCall = 1; UnoptimizedCFG = 0; CFGAddImplicitDtors = 0; CFGAddInitializers = 0; @@ -111,6 +126,7 @@ public: // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls). InlineMaxStackDepth = 5; InlineMaxFunctionSize = 200; + InliningMode = All; } }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index 39020c1cbb..5fba5b039b 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -75,16 +75,19 @@ class AnalysisManager : public BugReporterData { /// bifurcates paths. bool EagerlyAssume; bool TrimGraph; - bool InlineCall; bool EagerlyTrimEGraph; public: - // Settings for inlining tuning. + // \brief inter-procedural analysis mode. + AnalysisIPAMode IPAMode; + // Settings for inlining tuning. /// \brief The inlining stack depth limit. unsigned InlineMaxStackDepth; /// \brief The max number of basic blocks in a function being inlined. unsigned InlineMaxFunctionSize; + /// \brief The mode of function selection used during inlining. + AnalysisInliningMode InliningMode; public: AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags, @@ -96,11 +99,13 @@ public: unsigned maxnodes, unsigned maxvisit, bool vizdot, bool vizubi, AnalysisPurgeMode purge, bool eager, bool trim, - bool inlinecall, bool useUnoptimizedCFG, + bool useUnoptimizedCFG, bool addImplicitDtors, bool addInitializers, bool eagerlyTrimEGraph, + AnalysisIPAMode ipa, unsigned inlineMaxStack, - unsigned inlineMaxFunctionSize); + unsigned inlineMaxFunctionSize, + AnalysisInliningMode inliningMode); /// Construct a clone of the given AnalysisManager with the given ASTContext /// and DiagnosticsEngine. @@ -174,7 +179,7 @@ public: bool shouldEagerlyAssume() const { return EagerlyAssume; } - bool shouldInlineCall() const { return InlineCall; } + bool shouldInlineCall() const { return (IPAMode == Inlining); } bool hasIndexer() const { return Idxer != 0; } diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index c9db799976..69b084b7ef 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1345,7 +1345,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-analyzer-eagerly-assume"); - CmdArgs.push_back("-analyzer-inline-call"); + CmdArgs.push_back("-analyzer-ipa=inlining"); // Add default argument set. if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) { diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 9ccd9b2373..8d72991890 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -78,13 +78,34 @@ static const char *getAnalysisDiagClientName(AnalysisDiagClients Kind) { static const char *getAnalysisPurgeModeName(AnalysisPurgeMode Kind) { switch (Kind) { default: - llvm_unreachable("Unknown analysis client!"); + llvm_unreachable("Unknown analysis purge mode!"); #define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) \ case NAME: return CMDFLAG; #include "clang/Frontend/Analyses.def" } } +static const char *getAnalysisIPAModeName(AnalysisIPAMode Kind) { + switch (Kind) { + default: + llvm_unreachable("Unknown analysis ipa mode!"); +#define ANALYSIS_IPA(NAME, CMDFLAG, DESC) \ + case NAME: return CMDFLAG; +#include "clang/Frontend/Analyses.def" + } +} + +static const char * + getAnalysisInliningModeName(AnalysisInliningMode Kind) { + switch (Kind) { + default: + llvm_unreachable("Unknown analysis inlining mode!"); +#define ANALYSIS_INLINE_SELECTION(NAME, CMDFLAG, DESC) \ + case NAME: return CMDFLAG; +#include "clang/Frontend/Analyses.def" + } +} + //===----------------------------------------------------------------------===// // Serialization (to args) //===----------------------------------------------------------------------===// @@ -113,6 +134,15 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts, Res.push_back("-analyze-function"); Res.push_back(Opts.AnalyzeSpecificFunction); } + if (Opts.IPAMode != Inlining) { + Res.push_back("-analyzer-ipa"); + Res.push_back(getAnalysisIPAModeName(Opts.IPAMode)); + } + if (Opts.InliningMode != All) { + Res.push_back("-analyzer-inlining-mode"); + Res.push_back(getAnalysisInliningModeName(Opts.InliningMode)); + } + if (Opts.AnalyzeAll) Res.push_back("-analyzer-opt-analyze-headers"); if (Opts.AnalyzerDisplayProgress) @@ -1036,6 +1066,38 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, } } + if (Arg *A = Args.getLastArg(OPT_analyzer_ipa)) { + StringRef Name = A->getValue(Args); + AnalysisIPAMode Value = llvm::StringSwitch(Name) +#define ANALYSIS_IPA(NAME, CMDFLAG, DESC) \ + .Case(CMDFLAG, NAME) +#include "clang/Frontend/Analyses.def" + .Default(NumIPAModes); + if (Value == NumIPAModes) { + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << Name; + Success = false; + } else { + Opts.IPAMode = Value; + } + } + + if (Arg *A = Args.getLastArg(OPT_analyzer_inlining_mode)) { + StringRef Name = A->getValue(Args); + AnalysisInliningMode Value = llvm::StringSwitch(Name) +#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) \ + .Case(CMDFLAG, NAME) +#include "clang/Frontend/Analyses.def" + .Default(NumInliningModes); + if (Value == NumInliningModes) { + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << Name; + Success = false; + } else { + Opts.InliningMode = Value; + } + } + Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help); Opts.VisualizeEGDot = Args.hasArg(OPT_analyzer_viz_egraph_graphviz); Opts.VisualizeEGUbi = Args.hasArg(OPT_analyzer_viz_egraph_ubigraph); @@ -1052,8 +1114,6 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, Opts.MaxNodes = Args.getLastArgIntValue(OPT_analyzer_max_nodes, 150000,Diags); Opts.MaxLoop = Args.getLastArgIntValue(OPT_analyzer_max_loop, 4, Diags); Opts.EagerlyTrimEGraph = !Args.hasArg(OPT_analyzer_no_eagerly_trim_egraph); - if (Args.hasArg(OPT_analyzer_inline_call)) - Opts.InlineCall = 1; Opts.PrintStats = Args.hasArg(OPT_analyzer_stats); Opts.InlineMaxStackDepth = Args.getLastArgIntValue(OPT_analyzer_inline_max_stack_depth, diff --git a/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/lib/StaticAnalyzer/Core/AnalysisManager.cpp index 00701c9a05..821b1fbbe4 100644 --- a/lib/StaticAnalyzer/Core/AnalysisManager.cpp +++ b/lib/StaticAnalyzer/Core/AnalysisManager.cpp @@ -27,21 +27,25 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags, bool vizdot, bool vizubi, AnalysisPurgeMode purge, bool eager, bool trim, - bool inlinecall, bool useUnoptimizedCFG, + bool useUnoptimizedCFG, bool addImplicitDtors, bool addInitializers, bool eagerlyTrimEGraph, + AnalysisIPAMode ipa, unsigned inlineMaxStack, - unsigned inlineMaxFunctionSize) + unsigned inlineMaxFunctionSize, + AnalysisInliningMode IMode) : AnaCtxMgr(useUnoptimizedCFG, addImplicitDtors, addInitializers), Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd), CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr), CheckerMgr(checkerMgr), Idxer(idxer), AScope(ScopeDecl), MaxNodes(maxnodes), MaxVisit(maxvisit), VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge), - EagerlyAssume(eager), TrimGraph(trim), InlineCall(inlinecall), + EagerlyAssume(eager), TrimGraph(trim), EagerlyTrimEGraph(eagerlyTrimEGraph), + IPAMode(ipa), InlineMaxStackDepth(inlineMaxStack), - InlineMaxFunctionSize(inlineMaxFunctionSize) + InlineMaxFunctionSize(inlineMaxFunctionSize), + InliningMode(IMode) { AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd(); } @@ -65,10 +69,11 @@ AnalysisManager::AnalysisManager(ASTContext &ctx, DiagnosticsEngine &diags, PurgeDead(ParentAM.PurgeDead), EagerlyAssume(ParentAM.EagerlyAssume), TrimGraph(ParentAM.TrimGraph), - InlineCall(ParentAM.InlineCall), EagerlyTrimEGraph(ParentAM.EagerlyTrimEGraph), + IPAMode(ParentAM.IPAMode), InlineMaxStackDepth(ParentAM.InlineMaxStackDepth), - InlineMaxFunctionSize(ParentAM.InlineMaxFunctionSize) + InlineMaxFunctionSize(ParentAM.InlineMaxFunctionSize), + InliningMode(ParentAM.InliningMode) { AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd(); } diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index e683ec9cd9..bcf65e4716 100644 --- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -167,12 +167,14 @@ public: Opts.MaxNodes, Opts.MaxLoop, Opts.VisualizeEGDot, Opts.VisualizeEGUbi, Opts.AnalysisPurgeOpt, Opts.EagerlyAssume, - Opts.TrimGraph, Opts.InlineCall, + Opts.TrimGraph, Opts.UnoptimizedCFG, Opts.CFGAddImplicitDtors, Opts.CFGAddInitializers, Opts.EagerlyTrimEGraph, + Opts.IPAMode, Opts.InlineMaxStackDepth, - Opts.InlineMaxFunctionSize)); + Opts.InlineMaxFunctionSize, + Opts.InliningMode)); } virtual void HandleTranslationUnit(ASTContext &C); diff --git a/test/Analysis/dtor.cpp b/test/Analysis/dtor.cpp index dfd438ed40..8d63cc47be 100644 --- a/test/Analysis/dtor.cpp +++ b/test/Analysis/dtor.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store region -analyzer-inline-call -cfg-add-implicit-dtors -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-store region -analyzer-ipa=inlining -cfg-add-implicit-dtors -verify %s class A { public: diff --git a/test/Analysis/inline-not-supported.c b/test/Analysis/inline-not-supported.c index 0bde6f7e21..bff0e4d0b2 100644 --- a/test/Analysis/inline-not-supported.c +++ b/test/Analysis/inline-not-supported.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fblocks -analyze -analyzer-checker=core -analyzer-inline-call -analyzer-store region -verify %s +// RUN: %clang_cc1 -fblocks -analyze -analyzer-checker=core -analyzer-ipa=inlining -analyzer-store region -verify %s // For now, don't inline varargs. void foo(int *x, ...) { diff --git a/test/Analysis/inline-plist.c b/test/Analysis/inline-plist.c index c3420425ad..f2ef606601 100644 --- a/test/Analysis/inline-plist.c +++ b/test/Analysis/inline-plist.c @@ -1,4 +1,4 @@ -// RUN: %clang --analyze %s -Xclang -analyzer-inline-call -o %t +// RUN: %clang --analyze %s -Xclang -analyzer-ipa=inlining -o %t // RUN: FileCheck -input-file %t %s // diff --git a/test/Analysis/inline-unique-reports.c b/test/Analysis/inline-unique-reports.c index c99a303335..1cc3130c47 100644 --- a/test/Analysis/inline-unique-reports.c +++ b/test/Analysis/inline-unique-reports.c @@ -1,4 +1,4 @@ -// RUN: %clang --analyze %s -Xclang -analyzer-inline-call -o %t > /dev/null 2>&1 +// RUN: %clang --analyze %s -Xclang -analyzer-ipa=inlining -o %t > /dev/null 2>&1 // RUN: FileCheck -input-file %t %s static inline bug(int *p) { diff --git a/test/Analysis/inline.c b/test/Analysis/inline.c index 6acbeb959a..0827d93461 100644 --- a/test/Analysis/inline.c +++ b/test/Analysis/inline.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-inline-call -analyzer-store region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-ipa=inlining -analyzer-store region -verify %s int test1_f1() { int y = 1; diff --git a/test/Analysis/inline2.c b/test/Analysis/inline2.c index 97e479d4b2..473146c0be 100644 --- a/test/Analysis/inline2.c +++ b/test/Analysis/inline2.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-inline-call -analyzer-store region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-ipa=inlining -analyzer-store region -verify %s // Test parameter 'a' is registered to LiveVariables analysis data although it // is not referenced in the function body. diff --git a/test/Analysis/inline3.c b/test/Analysis/inline3.c index 1fa8b905dc..968d82acd6 100644 --- a/test/Analysis/inline3.c +++ b/test/Analysis/inline3.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-inline-call -analyzer-store region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-ipa=inlining -analyzer-store region -verify %s // Test when entering f1(), we set the right AnalysisDeclContext to Environment. // Otherwise, block-level expr '1 && a' would not be block-level. diff --git a/test/Analysis/inline4.c b/test/Analysis/inline4.c index c428aad5ec..e7715e01dd 100644 --- a/test/Analysis/inline4.c +++ b/test/Analysis/inline4.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-inline-call -analyzer-store region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-ipa=inlining -analyzer-store region -verify %s int g(int a) { return a; diff --git a/test/Analysis/keychainAPI.m b/test/Analysis/keychainAPI.m index 50aa4efbb9..cb4f72c9c4 100644 --- a/test/Analysis/keychainAPI.m +++ b/test/Analysis/keychainAPI.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=osx.SecKeychainAPI %s -analyzer-inline-call -verify +// RUN: %clang_cc1 -analyze -analyzer-checker=osx.SecKeychainAPI %s -analyzer-ipa=inlining -verify // Fake typedefs. typedef unsigned int OSStatus; diff --git a/test/Analysis/malloc-interprocedural.c b/test/Analysis/malloc-interprocedural.c index 8a42f393ba..eae8342795 100644 --- a/test/Analysis/malloc-interprocedural.c +++ b/test/Analysis/malloc-interprocedural.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=unix.Malloc -analyzer-inline-call -analyzer-inline-max-stack-depth 5 -analyzer-inline-max-function-size 6 -analyzer-store=region -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=unix.Malloc -analyzer-ipa=inlining -analyzer-inline-max-stack-depth=5 -analyzer-inline-max-function-size=6 -analyzer-store=region -verify %s #include "system-header-simulator.h" diff --git a/test/Analysis/retain-release-inline.m b/test/Analysis/retain-release-inline.m index 0323374a14..cbef9995bc 100644 --- a/test/Analysis/retain-release-inline.m +++ b/test/Analysis/retain-release-inline.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fblocks -analyzer-inline-call -verify %s +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -analyze -analyzer-checker=core,osx.coreFoundation.CFRetainRelease,osx.cocoa.ClassRelease,osx.cocoa.RetainCount -analyzer-store=region -fblocks -analyzer-ipa=inlining -verify %s //===----------------------------------------------------------------------===// // The following code is reduced using delta-debugging from Mac OS X headers: