Index: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h =================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -253,6 +253,9 @@ /// \sa getMaxTimesInlineLarge Optional MaxTimesInlineLarge; + /// \sa getMinCFGSizeTreatFunctionsAsLarge + Optional MinCFGSizeTreatFunctionsAsLarge; + /// \sa getMaxNodesPerTopLevelFunction Optional MaxNodesPerTopLevelFunction; @@ -505,6 +508,13 @@ /// This is controlled by the 'max-times-inline-large' config option. unsigned getMaxTimesInlineLarge(); + /// Returns the number of basic blocks a function needs to have to be + /// considered large for the 'max-times-inline-large' config option. + /// + /// This is controlled by the 'min-cfg-size-treat-functions-as-large' config + /// option. + unsigned getMinCFGSizeTreatFunctionsAsLarge(); + /// Returns the maximum number of nodes the analyzer can generate while /// exploring a top level function (for each exploded graph). /// 150000 is default; 0 means no limit. Index: cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -295,6 +295,13 @@ return MaxTimesInlineLarge.getValue(); } +unsigned AnalyzerOptions::getMinCFGSizeTreatFunctionsAsLarge() { + if (!MinCFGSizeTreatFunctionsAsLarge.hasValue()) + MinCFGSizeTreatFunctionsAsLarge = getOptionAsInteger( + "min-cfg-size-treat-functions-as-large", 14); + return MinCFGSizeTreatFunctionsAsLarge.getValue(); +} + unsigned AnalyzerOptions::getMaxNodesPerTopLevelFunction() { if (!MaxNodesPerTopLevelFunction.hasValue()) { int DefaultValue = 0; Index: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -870,7 +870,8 @@ // Do not inline large functions too many times. if ((Engine.FunctionSummaries->getNumTimesInlined(D) > Opts.getMaxTimesInlineLarge()) && - CalleeCFG->getNumBlockIDs() > 13) { + CalleeCFG->getNumBlockIDs() >= + Opts.getMinCFGSizeTreatFunctionsAsLarge()) { NumReachedInlineCountMax++; return false; } Index: cfe/trunk/test/Analysis/analyzer-config.c =================================================================== --- cfe/trunk/test/Analysis/analyzer-config.c +++ cfe/trunk/test/Analysis/analyzer-config.c @@ -1,22 +1,30 @@ -// RUN: %clang -target x86_64-apple-darwin10 --analyze %s -o /dev/null -Xclang -analyzer-checker=debug.ConfigDumper > %t 2>&1 +// RUN: %clang -target x86_64-apple-darwin10 --analyze %s -o /dev/null -Xclang -analyzer-checker=debug.ConfigDumper -Xclang -analyzer-max-loop -Xclang 34 > %t 2>&1 // RUN: FileCheck --input-file=%t %s void bar() {} -void foo() { bar(); } +void foo() { + // Call bar 33 times so max-times-inline-large is met and + // min-blocks-for-inline-large is checked + for (int i = 0; i < 34; ++i) { + bar(); + } +} // CHECK: [config] // CHECK-NEXT: cfg-conditional-static-initializers = true // CHECK-NEXT: cfg-temporary-dtors = false // CHECK-NEXT: faux-bodies = true // CHECK-NEXT: graph-trim-interval = 1000 +// CHECK-NEXT: inline-lambdas = true // CHECK-NEXT: ipa = dynamic-bifurcate // CHECK-NEXT: ipa-always-inline-size = 3 // CHECK-NEXT: leak-diagnostics-reference-allocation = false // CHECK-NEXT: max-inlinable-size = 50 // CHECK-NEXT: max-nodes = 150000 // CHECK-NEXT: max-times-inline-large = 32 +// CHECK-NEXT: min-cfg-size-treat-functions-as-large = 14 // CHECK-NEXT: mode = deep // CHECK-NEXT: region-store-small-struct-limit = 2 // CHECK-NEXT: [stats] -// CHECK-NEXT: num-entries = 12 +// CHECK-NEXT: num-entries = 14 Index: cfe/trunk/test/Analysis/analyzer-config.cpp =================================================================== --- cfe/trunk/test/Analysis/analyzer-config.cpp +++ cfe/trunk/test/Analysis/analyzer-config.cpp @@ -1,8 +1,14 @@ -// RUN: %clang -target x86_64-apple-darwin10 --analyze %s -o /dev/null -Xclang -analyzer-checker=debug.ConfigDumper > %t 2>&1 +// RUN: %clang -target x86_64-apple-darwin10 --analyze %s -o /dev/null -Xclang -analyzer-checker=debug.ConfigDumper -Xclang -analyzer-max-loop -Xclang 34 > %t 2>&1 // RUN: FileCheck --input-file=%t %s void bar() {} -void foo() { bar(); } +void foo() { + // Call bar 33 times so max-times-inline-large is met and + // min-blocks-for-inline-large is checked + for (int i = 0; i < 34; ++i) { + bar(); + } +} class Foo { public: @@ -20,13 +26,15 @@ // CHECK-NEXT: cfg-temporary-dtors = false // CHECK-NEXT: faux-bodies = true // CHECK-NEXT: graph-trim-interval = 1000 +// CHECK-NEXT: inline-lambdas = true // CHECK-NEXT: ipa = dynamic-bifurcate // CHECK-NEXT: ipa-always-inline-size = 3 // CHECK-NEXT: leak-diagnostics-reference-allocation = false // CHECK-NEXT: max-inlinable-size = 50 // CHECK-NEXT: max-nodes = 150000 // CHECK-NEXT: max-times-inline-large = 32 +// CHECK-NEXT: min-cfg-size-treat-functions-as-large = 14 // CHECK-NEXT: mode = deep // CHECK-NEXT: region-store-small-struct-limit = 2 // CHECK-NEXT: [stats] -// CHECK-NEXT: num-entries = 17 +// CHECK-NEXT: num-entries = 19