diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-09-10 21:27:35 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-09-10 21:27:35 +0000 |
commit | 81fb50e8b120fc95dc0245b4112972d4d7cca3b5 (patch) | |
tree | 894ad7f7b82fe1b0cc4a003a5d0c9650beb38a98 /lib/StaticAnalyzer/Core | |
parent | 1ad23d62007162df82b58bca31b4aa277a5f6586 (diff) |
[analyzer] For now, don't inline C++ standard library functions.
This is a (heavy-handed) solution to PR13724 -- until we know we can do
a good job inlining the STL, it's best to be consistent and not generate
more false positives than we did before. We can selectively whitelist
certain parts of the 'std' namespace that are known to be safe.
This is controlled by analyzer config option 'c++-stdlib-inlining', which
can be set to "true" or "false".
This commit also adds control for whether or not to inline any templated
functions (member or non-member), under the config option
'c++-template-inlining'. This option is currently on by default.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@163548 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core')
-rw-r--r-- | lib/StaticAnalyzer/Core/AnalyzerOptions.cpp | 32 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp | 30 |
2 files changed, 61 insertions, 1 deletions
diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp index 9e45a11528..b410890f8e 100644 --- a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -47,6 +47,36 @@ AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const { return CXXMemberInliningMode >= K; } +bool AnalyzerOptions::getBooleanOption(StringRef Name, bool DefaultVal) const { + // FIXME: We should emit a warning here if the value is something other than + // "true", "false", or the empty string (meaning the default value), + // but the AnalyzerOptions doesn't have access to a diagnostic engine. + return llvm::StringSwitch<bool>(Config.lookup(Name)) + .Case("true", true) + .Case("false", false) + .Default(DefaultVal); +} + bool AnalyzerOptions::includeTemporaryDtorsInCFG() const { - return !Config.lookup("cfg-temporary-dtors").empty(); + if (!IncludeTemporaryDtorsInCFG.hasValue()) + const_cast<llvm::Optional<bool> &>(IncludeTemporaryDtorsInCFG) = + getBooleanOption("cfg-temporary-dtors"); + + return *IncludeTemporaryDtorsInCFG; +} + +bool AnalyzerOptions::mayInlineCXXStandardLibrary() const { + if (!InlineCXXStandardLibrary.hasValue()) + const_cast<llvm::Optional<bool> &>(InlineCXXStandardLibrary) = + getBooleanOption("c++-stdlib-inlining"); + + return *InlineCXXStandardLibrary; +} + +bool AnalyzerOptions::mayInlineTemplateFunctions() const { + if (!InlineTemplateFunctions.hasValue()) + const_cast<llvm::Optional<bool> &>(InlineTemplateFunctions) = + getBooleanOption("c++-template-inlining", /*Default=*/true); + + return *InlineTemplateFunctions; } diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index fd94c1926b..9bf63c5b96 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -257,6 +257,21 @@ static unsigned getNumberStackFrames(const LocationContext *LCtx) { return count; } +static bool IsInStdNamespace(const FunctionDecl *FD) { + const DeclContext *DC = FD->getEnclosingNamespaceContext(); + const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC); + if (!ND) + return false; + + while (const DeclContext *Parent = ND->getParent()) { + if (!isa<NamespaceDecl>(Parent)) + break; + ND = cast<NamespaceDecl>(Parent); + } + + return ND->getName() == "std"; +} + // Determine if we should inline the call. bool ExprEngine::shouldInlineDecl(const Decl *D, ExplodedNode *Pred) { AnalysisDeclContext *CalleeADC = AMgr.getAnalysisDeclContext(D); @@ -287,6 +302,21 @@ bool ExprEngine::shouldInlineDecl(const Decl *D, ExplodedNode *Pred) { return false; } + if (getContext().getLangOpts().CPlusPlus) { + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + // Conditionally allow the inlining of template functions. + if (!getAnalysisManager().options.mayInlineTemplateFunctions()) + if (FD->getTemplatedKind() != FunctionDecl::TK_NonTemplate) + return false; + + // Conditionally allow the inlining of C++ standard library functions. + if (!getAnalysisManager().options.mayInlineCXXStandardLibrary()) + if (getContext().getSourceManager().isInSystemHeader(FD->getLocation())) + if (IsInStdNamespace(FD)) + return false; + } + } + // It is possible that the live variables analysis cannot be // run. If so, bail out. if (!CalleeADC->getAnalysis<RelaxedLiveVariables>()) |