From 5446f4dfb1bc2b0cb4cf2f0f5427eb71522760e6 Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Mon, 10 Sep 2012 22:56:41 +0000 Subject: [PATCH] [analyzer] Add an option to enable/disable objc inlining. llvm-svn: 163562 --- .../StaticAnalyzer/Core/AnalyzerOptions.h | 6 ++++ .../StaticAnalyzer/Core/AnalyzerOptions.cpp | 13 ++++++-- .../Core/ExprEngineCallAndReturn.cpp | 2 ++ .../inlining/test_objc_inlining_option.m | 33 +++++++++++++++++++ 4 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 clang/test/Analysis/inlining/test_objc_inlining_option.m diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index 72e614d3e769..718f54c75aaf 100644 --- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -178,6 +178,9 @@ private: /// \sa mayInlineTemplateFunctions llvm::Optional InlineTemplateFunctions; + /// \sa mayInlineObjCMethod + llvm::Optional ObjCInliningMode; + // Cache of the "ipa-always-inline-size" setting. // \sa getAlwaysInlineSize llvm::Optional AlwaysInlineSize; @@ -200,6 +203,9 @@ public: /// \sa CXXMemberInliningMode bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K) const; + /// Returns true if ObjectiveC inlining is enabled, false otherwise. + bool mayInlineObjCMethod() const; + /// Returns whether or not the destructors for C++ temporary objects should /// be included in the CFG. /// diff --git a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp index 5cbbb8d46285..9e029c7e298a 100644 --- a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -82,6 +82,14 @@ bool AnalyzerOptions::mayInlineTemplateFunctions() const { return *InlineTemplateFunctions; } +bool AnalyzerOptions::mayInlineObjCMethod() const { + if (!ObjCInliningMode.hasValue()) + const_cast &>(ObjCInliningMode) = + getBooleanOption("objc-inlining", /*Default=*/true); + + return *ObjCInliningMode; +} + int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal) const { std::string OptStr = Config.lookup(Name); if (OptStr.empty()) @@ -97,9 +105,8 @@ int AnalyzerOptions::getOptionAsInteger(StringRef Name, int DefaultVal) const { unsigned AnalyzerOptions::getAlwaysInlineSize() const { if (!AlwaysInlineSize.hasValue()) { unsigned DefaultSize = 3; - Optional &MutableOption = - const_cast &>(AlwaysInlineSize); - MutableOption = getOptionAsInteger("ipa-always-inline-size", DefaultSize); + const_cast &>(AlwaysInlineSize) = + getOptionAsInteger("ipa-always-inline-size", DefaultSize); } return AlwaysInlineSize.getValue(); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index a4e1eb2f4ccb..54c66d37ba7f 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -448,6 +448,8 @@ bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D, break; } case CE_ObjCMessage: + if (!Opts.mayInlineObjCMethod()) + return false; if (!(getAnalysisManager().options.IPAMode == DynamicDispatch || getAnalysisManager().options.IPAMode == DynamicDispatchBifurcate)) return false; diff --git a/clang/test/Analysis/inlining/test_objc_inlining_option.m b/clang/test/Analysis/inlining/test_objc_inlining_option.m new file mode 100644 index 000000000000..963b572b1e3f --- /dev/null +++ b/clang/test/Analysis/inlining/test_objc_inlining_option.m @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-ipa=dynamic-bifurcate -analyzer-config objc-inlining=false -verify %s + +typedef signed char BOOL; +typedef struct objc_class *Class; +typedef struct objc_object { + Class isa; +} *id; +@protocol NSObject - (BOOL)isEqual:(id)object; @end +@interface NSObject {} ++(id)alloc; +-(id)init; +-(id)autorelease; +-(id)copy; +- (Class)class; +-(id)retain; +@end + +// Vanila: ObjC class method is called by name. +@interface MyParent : NSObject ++ (int)getInt; +@end +@interface MyClass : MyParent ++ (int)getInt; +@end +@implementation MyClass ++ (int)testClassMethodByName { + int y = [MyClass getInt]; + return 5/y; // no-warning +} ++ (int)getInt { + return 0; +} +@end \ No newline at end of file -- GitLab