summaryrefslogtreecommitdiffstats
path: root/test/Analysis/inlining/DynDispatchBifurcate.m
diff options
context:
space:
mode:
Diffstat (limited to 'test/Analysis/inlining/DynDispatchBifurcate.m')
-rw-r--r--test/Analysis/inlining/DynDispatchBifurcate.m181
1 files changed, 181 insertions, 0 deletions
diff --git a/test/Analysis/inlining/DynDispatchBifurcate.m b/test/Analysis/inlining/DynDispatchBifurcate.m
new file mode 100644
index 0000000..e78b90b
--- /dev/null
+++ b/test/Analysis/inlining/DynDispatchBifurcate.m
@@ -0,0 +1,181 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-ipa=dynamic-bifurcate -verify %s
+
+#include "InlineObjCInstanceMethod.h"
+
+@interface MyParent : NSObject
+- (int)getZero;
+@end
+@implementation MyParent
+- (int)getZero {
+ return 0;
+}
+@end
+
+@interface PublicClass () {
+ int value2;
+}
+@property (readwrite) int value1;
+- (void)setValue2:(int)newValue2;
+@end
+
+@implementation PublicClass
+
+- (int)getZeroPublic {
+ return 0;
+}
+
+@synthesize value1;
+
+- (int)value2 {
+ return value2;
+}
+- (void)setValue2:(int)newValue {
+ value2 = newValue;
+}
+
+- (int)value3 {
+ return value3;
+}
+- (void)setValue3:(int)newValue {
+ value3 = newValue;
+}
+
+@end
+
+@interface MyClassWithPublicParent : PublicClass
+- (int)getZeroPublic;
+@end
+@implementation MyClassWithPublicParent
+- (int)getZeroPublic {
+ return 0;
+}
+@end
+
+// Category overrides a public method.
+@interface PublicSubClass (PrvateCat)
+ - (int) getZeroPublic;
+@end
+@implementation PublicSubClass (PrvateCat)
+- (int)getZeroPublic {
+ return 0;
+}
+@end
+
+
+@interface MyClass : MyParent {
+ int value;
+}
+- (int)getZero;
+@property int value;
+@end
+
+// Since class is private, we assume that it cannot be subclassed.
+// False negative: this class is "privately subclassed". this is very rare
+// in practice.
+@implementation MyClass
++ (int) testTypeFromParam:(MyParent*) p {
+ int m = 0;
+ int z = [p getZero];
+ if (z)
+ return 5/m; // false negative
+ return 5/[p getZero];// expected-warning {{Division by zero}}
+}
+
+// Here only one definition is possible, since the declaration is not visible
+// from outside.
++ (int) testTypeFromParamPrivateChild:(MyClass*) c {
+ int m = 0;
+ int z = [c getZero]; // MyClass overrides getZero to return '1'.
+ if (z)
+ return 5/m; // expected-warning {{Division by zero}}
+ return 5/[c getZero];//no warning
+}
+
+- (int)getZero {
+ return 1;
+}
+
+- (int)value {
+ return value;
+}
+
+- (void)setValue:(int)newValue {
+ value = newValue;
+}
+
+// Test ivar access.
+- (int) testIvarInSelf {
+ value = 0;
+ return 5/value; // expected-warning {{Division by zero}}
+}
+
++ (int) testIvar: (MyClass*) p {
+ p.value = 0;
+ return 5/p.value; // expected-warning {{Division by zero}}
+}
+
+// Test simple property access.
++ (int) testProperty: (MyClass*) p {
+ int x= 0;
+ [p setValue:0];
+ return 5/[p value]; // expected-warning {{Division by zero}}
+}
+
+@end
+
+// The class is prvate and is not subclassed.
+int testCallToPublicAPIInParent(MyClassWithPublicParent *p) {
+ int m = 0;
+ int z = [p getZeroPublic];
+ if (z)
+ return 5/m; // no warning
+ return 5/[p getZeroPublic];// expected-warning {{Division by zero}}
+}
+
+// When the called method is public (due to it being defined outside of main file),
+// split the path and analyze both branches.
+// In this case, p can be either the object of type MyParent* or MyClass*:
+// - If it's MyParent*, getZero returns 0.
+// - If it's MyClass*, getZero returns 1 and 'return 5/m' is reachable.
+// Declaration is provate, but p can be a subclass (MyClass*).
+int testCallToPublicAPI(PublicClass *p) {
+ int m = 0;
+ int z = [p getZeroPublic];
+ if (z)
+ return 5/m; // expected-warning {{Division by zero}}
+ return 5/[p getZeroPublic];// expected-warning {{Division by zero}}
+}
+
+// Even though the method is privately declared in the category, the parent
+// declares the method as public. Assume the instance can be subclassed.
+int testCallToPublicAPICat(PublicSubClass *p) {
+ int m = 0;
+ int z = [p getZeroPublic];
+ if (z)
+ return 5/m; // expected-warning {{Division by zero}}
+ return 5/[p getZeroPublic];// expected-warning {{Division by zero}}
+}
+
+// Test public property - properties should always be inlined, regardless
+// weither they are "public" or private.
+int testPublicProperty(PublicClass *p) {
+ int x = 0;
+ [p setValue3:0];
+ if ([p value3] != 0)
+ return 5/x; // expected-warning {{Division by zero}} // TODO: no warning, we should always inline the property.
+ return 5/[p value3];// expected-warning {{Division by zero}}
+}
+
+int testExtension(PublicClass *p) {
+ int x = 0;
+ [p setValue2:0];
+ if ([p value2] != 0)
+ return 5/x; // expected-warning {{Division by zero}} // TODO: no warning, we should always inline the property.
+ return 5/[p value2]; // expected-warning {{Division by zero}}
+}
+
+// TODO: we do not handle synthesized properties yet.
+int testPropertySynthesized(PublicClass *p) {
+ [p setValue1:0];
+ return 5/[p value1];
+}
OpenPOWER on IntegriCloud