[analyzer] Very simple ObjC instance method inlining

- Retrieves the type of the object/receiver from the state.
- Binds self during stack setup.
- Only explores the path on which the method is inlined (no
bifurcation to explore the path on which the method is not inlined).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160991 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/Analysis/inlining/InlineObjCInstanceMethod.m b/test/Analysis/inlining/InlineObjCInstanceMethod.m
new file mode 100644
index 0000000..682d02a
--- /dev/null
+++ b/test/Analysis/inlining/InlineObjCInstanceMethod.m
@@ -0,0 +1,80 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-ipa=dynamic -verify %s
+
+#include "InlineObjCInstanceMethod.h"
+
+// Method is defined in the parent; called through self.
+@interface MyParent : NSObject
+- (int)getInt;
+@end
+@implementation MyParent
+- (int)getInt {
+    return 0;
+}
+@end
+
+@interface MyClass : MyParent
+@end
+@implementation MyClass
+- (int)testDynDispatchSelf {
+  int y = [self getInt];
+  return 5/y; // expected-warning {{Division by zero}}
+}
+
+// Method is called on inited object.
++ (int)testAllocInit {
+  MyClass *a = [[self alloc] init];
+  return 5/[a getInt]; // todo
+}
+
+// Method is called on inited object.
++ (int)testAllocInit2 {
+  MyClass *a = [[MyClass alloc] init];
+  return 5/[a getInt]; // todo
+}
+
+// Method is called on a parameter.
++ (int)testParam: (MyClass*) a {
+  return 5/[a getInt]; // expected-warning {{Division by zero}}
+}
+
+// Method is called on a parameter of unnown type.
++ (int)testParamUnknownType: (id) a {
+  return 5/[a getInt]; // no warning
+}
+
+@end
+
+// TODO: When method is inlined, the attribute reset should be visible.
+@interface TestSettingAnAttributeInCallee : NSObject {
+  int _attribute;
+}
+  - (void) method2;
+@end
+
+@implementation TestSettingAnAttributeInCallee
+- (int) method1 {
+  [self method2];
+  return 5/_attribute; // expected-warning {{Division by zero}}
+}
+
+- (void) method2 {
+  _attribute = 0;
+}
+@end
+
+@interface TestSettingAnAttributeInCaller : NSObject {
+  int _attribute;
+}
+  - (int) method2;
+@end
+
+@implementation TestSettingAnAttributeInCaller
+- (void) method1 {
+  _attribute = 0;
+  [self method2];
+}
+
+- (int) method2 {
+  return 5/_attribute; // expected-warning {{Division by zero}}
+}
+@end
\ No newline at end of file