-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathA.java
More file actions
135 lines (120 loc) · 2.59 KB
/
A.java
File metadata and controls
135 lines (120 loc) · 2.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
public class A {
public void f1() {
C c = new C();
B b = B.make(c);
sink(b.c); // flow
}
public void f2() {
B b = new B();
b.set(new C1());
sink(b.get()); // flow
sink((new B(new C())).get()); // flow
}
public void f3() {
B b1 = new B();
B b2;
b2 = setOnB(b1, new C2());
sink(b1.c); // no flow
sink(b2.c); // flow
}
public void f4() {
B b1 = new B();
B b2;
b2 = setOnBWrap(b1, new C2());
sink(b1.c); // no flow
sink(b2.c); // flow
}
public B setOnBWrap(B b1, C c) {
B b2;
b2 = setOnB(b1, c);
return r() ? b1 : b2;
}
public B setOnB(B b1, C c) {
if (r()) {
B b2 = new B();
b2.set(c);
return b2;
}
return b1;
}
public void f5() {
A a = new A();
C1 c1 = new C1();
c1.a = a;
f6(c1);
}
public void f6(C c) {
if (c instanceof C1) {
sink(((C1)c).a); // flow
}
C cc;
if (c instanceof C2) {
cc = (C2)c;
} else {
cc = new C1();
}
if (cc instanceof C1) {
sink(((C1)cc).a); // no flow, stopped by cast to C2
}
}
public void f7(B b) {
b.set(new C());
}
public void f8() {
B b = new B();
f7(b);
sink(b.c); // flow
}
public static class D {
public B b;
public D(B b, boolean x) {
b.c = new C();
this.b = x ? b : new B();
}
}
public void f9() {
B b = new B();
D d = new D(b, r());
sink(d.b); // flow x2
sink(d.b.c); // flow
sink(b.c); // flow
}
public void f10() {
B b = new B();
MyList l1 = new MyList(b, new MyList(null, null));
MyList l2 = new MyList(null, l1);
MyList l3 = new MyList(null, l2);
sink(l3.head); // no flow, b is nested beneath at least one .next
sink(l3.next.head); // flow, the precise nesting depth isn't tracked
sink(l3.next.next.head); // flow
sink(l3.next.next.next.head); // flow
for (MyList l = l3; l != null; l = l.next) {
sink(l.head); // flow
}
}
public static void sink(Object o) { }
public boolean r() { return this.hashCode() % 10 > 5; }
public static class C { }
public static class C1 extends C { public A a; }
public static class C2 extends C { }
public static class B {
public C c;
public B() { }
public B(C c) {
this.c = c;
}
public void set(C c) { this.c = c; }
public C get() { return this.c; }
public static B make(C c) {
return new B(c);
}
}
public static class MyList {
public B head;
public MyList next;
public MyList(B head, MyList next) {
this.head = head;
this.next = next;
}
}
}