]> granicus.if.org Git - clang/commitdiff
[analyzer] Add an option to enable/disable objc inlining.
authorAnna Zaks <ganna@apple.com>
Mon, 10 Sep 2012 22:56:41 +0000 (22:56 +0000)
committerAnna Zaks <ganna@apple.com>
Mon, 10 Sep 2012 22:56:41 +0000 (22:56 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@163562 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
test/Analysis/inlining/test_objc_inlining_option.m [new file with mode: 0644]

index 72e614d3e769e9118fc7937f614ff148f99da2a9..718f54c75aaf0944094e9848e89ecbc3ff98b548 100644 (file)
@@ -178,6 +178,9 @@ private:
   /// \sa mayInlineTemplateFunctions
   llvm::Optional<bool> InlineTemplateFunctions;
 
+  /// \sa mayInlineObjCMethod
+  llvm::Optional<bool> ObjCInliningMode;
+
   // Cache of the "ipa-always-inline-size" setting.
   // \sa getAlwaysInlineSize
   llvm::Optional<unsigned> 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.
   ///
index 5cbbb8d46285fed9d54142b5cf6954d63ff1902a..9e029c7e298a0554deba502ce4bb3ffb38a6b1e2 100644 (file)
@@ -82,6 +82,14 @@ bool AnalyzerOptions::mayInlineTemplateFunctions() const {
   return *InlineTemplateFunctions;
 }
 
+bool AnalyzerOptions::mayInlineObjCMethod() const {
+  if (!ObjCInliningMode.hasValue())
+    const_cast<llvm::Optional<bool> &>(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<unsigned> &MutableOption =
-      const_cast<Optional<unsigned> &>(AlwaysInlineSize);
-    MutableOption = getOptionAsInteger("ipa-always-inline-size", DefaultSize);
+    const_cast<Optional<unsigned> &>(AlwaysInlineSize) =
+      getOptionAsInteger("ipa-always-inline-size", DefaultSize);
   }
 
   return AlwaysInlineSize.getValue();
index a4e1eb2f4ccb86b14bced5a76bbbcb1d047900f4..54c66d37ba7f229af3edaada8beab66a7548dbb2 100644 (file)
@@ -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/test/Analysis/inlining/test_objc_inlining_option.m b/test/Analysis/inlining/test_objc_inlining_option.m
new file mode 100644 (file)
index 0000000..963b572
--- /dev/null
@@ -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 <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