diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-08-31 17:06:49 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-08-31 17:06:49 +0000 |
commit | de5277fc555551857602bd7a7e5e616274e2d4a6 (patch) | |
tree | 1baafdce006a65a6af51b15b7c41c41a7fef9fbf /lib/StaticAnalyzer | |
parent | 376c43223ee29334685250c59fdb11e4b3c594fb (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.cpp | 48 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp | 44 |
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; |