aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-08-31 17:06:49 +0000
committerJordan Rose <jordan_rose@apple.com>2012-08-31 17:06:49 +0000
commitde5277fc555551857602bd7a7e5e616274e2d4a6 (patch)
tree1baafdce006a65a6af51b15b7c41c41a7fef9fbf /lib/StaticAnalyzer
parent376c43223ee29334685250c59fdb11e4b3c594fb (diff)
[analyzer] Though C++ inlining is enabled, don't inline ctors and dtors.
More generally, this adds a new configuration option 'c++-inlining', which controls which C++ member functions can be considered for inlining. This uses the new -analyzer-config table, so the cc1 arguments will look like this: ... -analyzer-config c++-inlining=[none|methods|constructors|destructors] Note that each mode implies that all the previous member function kinds will be inlined as well; it doesn't make sense to inline destructors without inlining constructors, for example. The default mode is 'methods'. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@163004 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer')
-rw-r--r--lib/StaticAnalyzer/Core/AnalyzerOptions.cpp48
-rw-r--r--lib/StaticAnalyzer/Core/CMakeLists.txt1
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp44
3 files changed, 63 insertions, 30 deletions
diff --git a/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
new file mode 100644
index 0000000000..5574a2f226
--- /dev/null
+++ b/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -0,0 +1,48 @@
+//===-- AnalyzerOptions.cpp - Analysis Engine Options -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains special accessors for analyzer configuration options
+// with string representations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace clang;
+
+bool
+AnalyzerOptions::mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const {
+ if (IPAMode < Inlining)
+ return false;
+
+ if (!CXXMemberInliningMode) {
+ static const char *ModeKey = "c++-inlining";
+ std::string ModeStr = Config.lookup(ModeKey);
+
+ CXXInlineableMemberKind &MutableMode =
+ const_cast<CXXInlineableMemberKind &>(CXXMemberInliningMode);
+
+ MutableMode = llvm::StringSwitch<CXXInlineableMemberKind>(ModeStr)
+ .Case("", CIMK_MemberFunctions)
+ .Case("constructors", CIMK_Constructors)
+ .Case("destructors", CIMK_Destructors)
+ .Case("none", CIMK_None)
+ .Case("methods", CIMK_MemberFunctions)
+ .Default(CXXInlineableMemberKind());
+
+ if (!MutableMode) {
+ // FIXME: We should emit a warning here about an unknown inlining kind,
+ // but the AnalyzerOptions doesn't have access to a diagnostic engine.
+ MutableMode = CIMK_None;
+ }
+ }
+
+ return CXXMemberInliningMode >= K;
+}
diff --git a/lib/StaticAnalyzer/Core/CMakeLists.txt b/lib/StaticAnalyzer/Core/CMakeLists.txt
index 359a34ff7d..43d42b3e0d 100644
--- a/lib/StaticAnalyzer/Core/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Core/CMakeLists.txt
@@ -3,6 +3,7 @@ set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangStaticAnalyzerCore
APSIntType.cpp
AnalysisManager.cpp
+ AnalyzerOptions.cpp
BasicValueFactory.cpp
BlockCounter.cpp
BugReporter.cpp
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
index 4313e727c5..ad30596b92 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -316,21 +316,6 @@ template<> struct ProgramStateTrait<DynamicDispatchBifurcationMap>
}}
-static bool shouldInlineCXX(AnalysisManager &AMgr) {
- switch (AMgr.options.IPAMode) {
- case None:
- case BasicInlining:
- return false;
- case Inlining:
- case DynamicDispatch:
- case DynamicDispatchBifurcate:
- return true;
- case NumIPAModes:
- llvm_unreachable("not actually a valid option");
- }
- llvm_unreachable("bogus IPAMode");
-}
-
bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D,
NodeBuilder &Bldr, ExplodedNode *Pred,
ProgramStateRef State) {
@@ -340,17 +325,19 @@ bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D,
const StackFrameContext *CallerSFC = CurLC->getCurrentStackFrame();
const LocationContext *ParentOfCallee = 0;
+ const AnalyzerOptions &Opts = getAnalysisManager().options;
+
// FIXME: Refactor this check into a hypothetical CallEvent::canInline.
switch (Call.getKind()) {
case CE_Function:
break;
case CE_CXXMember:
case CE_CXXMemberOperator:
- if (!shouldInlineCXX(getAnalysisManager()))
+ if (!Opts.mayInlineCXXMemberFunction(CIMK_MemberFunctions))
return false;
break;
case CE_CXXConstructor: {
- if (!shouldInlineCXX(getAnalysisManager()))
+ if (!Opts.mayInlineCXXMemberFunction(CIMK_Constructors))
return false;
const CXXConstructorCall &Ctor = cast<CXXConstructorCall>(Call);
@@ -369,15 +356,17 @@ bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D,
if (isa<CXXNewExpr>(Parent))
return false;
+ // Inlining constructors requires including initializers in the CFG.
+ const AnalysisDeclContext *ADC = CallerSFC->getAnalysisDeclContext();
+ assert(ADC->getCFGBuildOptions().AddInitializers && "No CFG initializers");
+
// If the destructor is trivial, it's always safe to inline the constructor.
if (Ctor.getDecl()->getParent()->hasTrivialDestructor())
break;
- // For other types, only inline constructors if we built the CFGs for the
- // destructor properly.
- const AnalysisDeclContext *ADC = CallerSFC->getAnalysisDeclContext();
- assert(ADC->getCFGBuildOptions().AddInitializers && "No CFG initializers");
- if (!ADC->getCFGBuildOptions().AddImplicitDtors)
+ // For other types, only inline constructors if destructor inlining is
+ // also enabled.
+ if (!Opts.mayInlineCXXMemberFunction(CIMK_Destructors))
return false;
// FIXME: This is a hack. We don't handle temporary destructors
@@ -389,14 +378,12 @@ bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D,
break;
}
case CE_CXXDestructor: {
- if (!shouldInlineCXX(getAnalysisManager()))
+ if (!Opts.mayInlineCXXMemberFunction(CIMK_Destructors))
return false;
- // Only inline constructors and destructors if we built the CFGs for them
- // properly.
+ // Inlining destructors requires building the CFG correctly.
const AnalysisDeclContext *ADC = CallerSFC->getAnalysisDeclContext();
- if (!ADC->getCFGBuildOptions().AddImplicitDtors)
- return false;
+ assert(ADC->getCFGBuildOptions().AddImplicitDtors && "No CFG destructors");
const CXXDestructorCall &Dtor = cast<CXXDestructorCall>(Call);
@@ -408,9 +395,6 @@ bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D,
break;
}
case CE_CXXAllocator:
- if (!shouldInlineCXX(getAnalysisManager()))
- return false;
-
// Do not inline allocators until we model deallocators.
// This is unfortunate, but basically necessary for smart pointers and such.
return false;