View | Details | Raw Unified | Return to bug 127570
Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java (-728 / +635 lines)
Lines 42-68 Link Here
42
	// never release with the coverageTestFlag set to true
42
	// never release with the coverageTestFlag set to true
43
	public static int coverageTestId;
43
	public static int coverageTestId;
44
44
45
	// assignment bits - first segment
45
	public long definiteInits;
46
	public long definiteInits;
46
	public long potentialInits;
47
	public long potentialInits;
47
	
48
	
48
	public long nullAssignmentStatusBit1;
49
	// null bits - first segment
49
	public long nullAssignmentStatusBit2;
50
	public long 
50
	// 0 0 is potential (bit 1 is leftmost here)
51
		nullBit1,
51
	// 1 0 is assigned
52
		nullBit2,
52
	// 0 1 is protected null (aka if (o == null) { // here o protected null...)
53
		nullBit3,
53
	// 1 1 is protected non null
54
		nullBit4;
54
	public long nullAssignmentValueBit1;
55
/*
55
	public long nullAssignmentValueBit2;
56
		nullBit1
56
	// information only relevant for potential and assigned
57
		 nullBit2...
57
	// 0 0 is start -- nothing known at all
58
		0000	start
58
	// 0 1 is assigned non null or potential anything but null
59
		0001	pot. unknown
59
	// 1 0 is assigned null or potential null
60
		0010	pot. non null
60
	// 1 1 is potential null and potential anything but null or definite unknown
61
		0011	pot. nn & pot. un
61
	// consider reintroducing the difference between potential non null and potential
62
		0100	pot. null
62
	// unknown; if this is done, rename to nullAssignmentBit[1-4] since the semantics
63
		0101	pot. n & pot. un
63
	// would be ever less clear
64
		0110	pot. n & pot. nn
64
	// went public in order to grant access to tests; do not like it...
65
		1001	def. unknown
65
66
		1010	def. non null
67
		1011	pot. nn & prot. nn
68
		1100	def. null
69
		1101	pot. n & prot. n
70
		1110	prot. null
71
		1111	prot. non null
72
 */	
73
		
74
	// extra segments
66
	public static final int extraLength = 6;
75
	public static final int extraLength = 6;
67
	public long extra[][];
76
	public long extra[][];
68
		// extra bit fields for larger numbers of fields/variables
77
		// extra bit fields for larger numbers of fields/variables
Lines 71-77 Link Here
71
		// arrays which have the same size
80
		// arrays which have the same size
72
81
73
	public int maxFieldCount; // limit between fields and locals
82
	public int maxFieldCount; // limit between fields and locals
74
	
83
75
	// Constants
84
	// Constants
76
	public static final int BitCacheSize = 64; // 64 bits in a long.
85
	public static final int BitCacheSize = 64; // 64 bits in a long.
77
86
Lines 87-136 Link Here
87
	// union of potentially set ones
96
	// union of potentially set ones
88
	this.potentialInits |= otherInits.potentialInits;
97
	this.potentialInits |= otherInits.potentialInits;
89
	// combine null information
98
	// combine null information
90
	// note: we may have both forms of protection (null and non null) 
99
	boolean thisHadNulls = (this.tagBits & NULL_FLAG_MASK) != 0,
91
	// coming with otherInits, because of loops
100
		otherHasNulls = (otherInits.tagBits & NULL_FLAG_MASK) != 0;
92
	boolean considerNulls = (otherInits.tagBits & NULL_FLAG_MASK) != 0;
101
	long 
93
	long a1, na1, a2, na2, a3, a4, na4, b1, b2, nb2, b3, nb3, b4, nb4;
102
		a1, a2, a3, a4, 
94
	if (considerNulls) {
103
		na1, na2, na3, na4, 
95
		if ((this.tagBits & NULL_FLAG_MASK) == 0) {
104
		b1, b2, b3, b4,
96
			this.nullAssignmentStatusBit1 = otherInits.nullAssignmentStatusBit1;
105
		nb1, nb2, nb3, nb4;
97
			this.nullAssignmentStatusBit2 = otherInits.nullAssignmentStatusBit2;
106
	if (otherHasNulls) {
98
			this.nullAssignmentValueBit1 = otherInits.nullAssignmentValueBit1;
107
		if (!thisHadNulls) {
99
			this.nullAssignmentValueBit2 = otherInits.nullAssignmentValueBit2;
108
			this.nullBit1 = otherInits.nullBit1;
109
			this.nullBit2 = otherInits.nullBit2;
110
			this.nullBit3 = otherInits.nullBit3;
111
			this.nullBit4 = otherInits.nullBit4;
100
			if (coverageTestFlag && coverageTestId == 1) {
112
			if (coverageTestFlag && coverageTestId == 1) {
101
				this.nullAssignmentValueBit2 = ~0;
113
			  this.nullBit4 = ~0;
102
			}
114
			}
103
		}
115
		}
104
		else {
116
		else {
105
			this.nullAssignmentStatusBit1 =
117
			this.nullBit1 = (b1 = otherInits.nullBit1)
106
				(b1 = otherInits.nullAssignmentStatusBit1) 
118
                				| (a1 = this.nullBit1) & ((a3 = this.nullBit3) 
107
					| ((a1 = this.nullAssignmentStatusBit1) 
119
                					& (a4 = this.nullBit4) & (nb2 = ~(b2 = otherInits.nullBit2)) 
108
						& (((nb2 = ~(b2 = otherInits.nullAssignmentStatusBit2)) 
120
                					& (nb4 = ~(b4 = otherInits.nullBit4))
109
								& (nb3 = ~(b3 = otherInits.nullAssignmentValueBit1)) 
121
                        		| ((na4 = ~a4) | (na3 = ~a3)) 
110
								& ((nb4 = ~(b4 = otherInits.nullAssignmentValueBit2)) 
122
                        			& ((na2 = ~(a2 = this.nullBit2)) & nb2 
111
									| ((a2 = this.nullAssignmentStatusBit2) 
123
                        				| a2 & (nb3 = ~(b3 = otherInits.nullBit3)) & nb4));
112
										^ (a4 = this.nullAssignmentValueBit2)))) 
124
			this.nullBit2  = b2 & (nb4 | nb3)
113
							| nb4 &	(na2 = ~a2)	& (na4 = ~a4)));
125
                    			| na3 & na4 & b2
114
			this.nullAssignmentStatusBit2 =
126
                    			| a2 & (nb3 & nb4
115
				(b1 & b2) 
127
                                			| (nb1 = ~b1) & (na3 | (na1 = ~a1))
116
					| (~b1 
128
                                			| a1 & b2);
117
						& ((((na1 = ~a1) | a4) & b2) 
129
			this.nullBit3 = b3 & (nb1 & (b2 | a2 | na1)
118
							| (a2 
130
                        			| b1 & (b4 | nb2 | a1 & a3)
119
								& (b2 
131
                         			| na1 & na2 & na4)
120
									| (a1 & (na4 = ~a4) & nb2 & nb3) 
132
                    			| a3 & nb2 & nb4
121
									| ((~(a3 = this.nullAssignmentValueBit1) & nb3) 
133
                    			| nb1 & ((na2 & a4 | na1) & a3
122
											| (na1 & na4)) 
134
                                			| a1 & na2 & na4 & b2);
123
										& nb4))));
135
			this.nullBit4 = nb1 & (a4 & (na3 & nb3	| (a3 | na2) & nb2)
124
			this.nullAssignmentValueBit1 = 
136
                      			| a1 & (a3 & nb2 & b4
125
				nb2 & b3 |
137
                              			| a2 & b2 & (b4	| a3 & na4 & nb3)))
126
				~b1 & ((a1 & na2 & na4 | na1 & a3) & (nb2 | nb4) |
138
                      			| b1 & (a3 & a4 & b4
127
						a1 & na2 & a3 & nb2 |
139
                          			| na2 & na4 & nb3 & b4
128
						(a1 | a2 | na4) & b3);
140
                          			| a2 & ((b3 | a4) & b4
129
			this.nullAssignmentValueBit2 =
141
                                  				| na3 & a4 & b2 & b3)
130
				b4 |
142
                          			| na1 & (b4	| (a4 | a2) & b2 & b3))
131
				a4 & (nb2 & nb3 | ~(b1 ^ b2));
143
                      			| (na1 & (na3 & nb3 | na2 & nb2)
144
                      				| a1 & (nb2 & nb3 | a2 & a3)) & b4;	
132
			if (coverageTestFlag && coverageTestId == 2) {
145
			if (coverageTestFlag && coverageTestId == 2) {
133
				this.nullAssignmentValueBit2 = ~0;
146
			  this.nullBit4 = ~0;
134
			}
147
			}
135
		}
148
		}
136
		this.tagBits |= NULL_FLAG_MASK; // in all cases - avoid forgetting extras
149
		this.tagBits |= NULL_FLAG_MASK; // in all cases - avoid forgetting extras
Lines 144-152 Link Here
144
				int length, otherLength;
157
				int length, otherLength;
145
				if ((length = this.extra[0].length) < 
158
				if ((length = this.extra[0].length) < 
146
						(otherLength = otherInits.extra[0].length)) {
159
						(otherLength = otherInits.extra[0].length)) {
147
					if (coverageTestFlag && coverageTestId == 3) {
148
						throw new AssertionFailedException("COVERAGE 3"); //$NON-NLS-1$
149
					}
150
					// current storage is shorter -> grow current
160
					// current storage is shorter -> grow current
151
					for (int j = 0; j < extraLength; j++) {
161
					for (int j = 0; j < extraLength; j++) {
152
						System.arraycopy(this.extra[j], 0, 
162
						System.arraycopy(this.extra[j], 0, 
Lines 154-169 Link Here
154
					}
164
					}
155
					mergeLimit = length;
165
					mergeLimit = length;
156
					copyLimit = otherLength;
166
					copyLimit = otherLength;
167
					if (coverageTestFlag && coverageTestId == 3) {
168
						throw new AssertionFailedException("COVERAGE 3"); //$NON-NLS-1$
169
					}
157
				} else {
170
				} else {
171
					// current storage is longer
172
					mergeLimit = otherLength;
158
					if (coverageTestFlag && coverageTestId == 4) {
173
					if (coverageTestFlag && coverageTestId == 4) {
159
						throw new AssertionFailedException("COVERAGE 4"); //$NON-NLS-1$
174
						throw new AssertionFailedException("COVERAGE 4"); //$NON-NLS-1$
160
					}
175
					}
161
					// current storage is longer
162
					mergeLimit = otherLength;
163
				}
176
				}
164
			} 
177
			} 
165
		} 
178
		} else if (otherInits.extra != null) {
166
		else if (otherInits.extra != null) {
167
			// no storage here, but other has extra storage.
179
			// no storage here, but other has extra storage.
168
			// shortcut regular copy because array copy is better
180
			// shortcut regular copy because array copy is better
169
			int otherLength;
181
			int otherLength;
Lines 173-179 Link Here
173
					otherInits.extra[0].length]), 0, otherLength);			
185
					otherInits.extra[0].length]), 0, otherLength);			
174
			System.arraycopy(otherInits.extra[1], 0, 
186
			System.arraycopy(otherInits.extra[1], 0, 
175
				(this.extra[1] = new long[otherLength]), 0, otherLength);
187
				(this.extra[1] = new long[otherLength]), 0, otherLength);
176
			if (considerNulls) {
188
			if (otherHasNulls) {
177
				for (int j = 2; j < extraLength; j++) {
189
				for (int j = 2; j < extraLength; j++) {
178
					System.arraycopy(otherInits.extra[j], 0, 
190
					System.arraycopy(otherInits.extra[j], 0, 
179
						(this.extra[j] = new long[otherLength]), 0, otherLength);
191
						(this.extra[j] = new long[otherLength]), 0, otherLength);
Lines 187-252 Link Here
187
					this.extra[j] = new long[otherLength];			
199
					this.extra[j] = new long[otherLength];			
188
				}
200
				}
189
				if (coverageTestFlag && coverageTestId == 6) {
201
				if (coverageTestFlag && coverageTestId == 6) {
190
					this.extra[5][otherLength - 1] = ~0;
202
					throw new AssertionFailedException("COVERAGE 6"); //$NON-NLS-1$
191
				}
203
				}
192
			}
204
			}
193
		}
205
		}
194
		int i = 0;
206
		int i;
195
		for (; i < mergeLimit; i++) {
207
		// manage definite assignment info
208
		for (i = 0; i < mergeLimit; i++) {
196
			this.extra[0][i] |= otherInits.extra[0][i];
209
			this.extra[0][i] |= otherInits.extra[0][i];
197
			this.extra[1][i] |= otherInits.extra[1][i];
210
			this.extra[1][i] |= otherInits.extra[1][i];
198
			if (considerNulls) { // could consider pushing the test outside the loop
199
				if (this.extra[2][i] == 0 &&
200
						this.extra[3][i] == 0 &&
201
						this.extra[4][i] == 0 &&
202
						this.extra[5][i] == 0) {
203
					for (int j = 2; j < extraLength; j++) {
204
						this.extra[j][i] = otherInits.extra[j][i];
205
					}
206
					if (coverageTestFlag && coverageTestId == 7) {
207
						this.extra[5][i] = ~0;
208
					}
209
				}
210
				else {
211
					this.extra[2][i] =
212
						(b1 = otherInits.extra[2][i]) |
213
						(a1	 = this.extra[2][i]) & 
214
							((nb2 = ~(b2 = otherInits.extra[3][i])) &
215
								(nb3 = ~(b3 = otherInits.extra[4][i])) &
216
								((nb4 = ~(b4 = otherInits.extra[5][i])) |
217
									((a2 = this.extra[3][i]) ^ 
218
										(a4 = this.extra[5][i]))) | 
219
							nb4 & (na2 = ~a2) & (na4 = ~a4));
220
					this.extra[3][i] =
221
						b1 & b2 |
222
						~b1 & (((na1 = ~a1) | a4) & b2 |
223
								a2 & (b2 |
224
									a1 & (na4 = ~a4) & nb2 & nb3 |
225
									(~(a3 = this.extra[4][i]) & nb3 | na1 & na4) & nb4));
226
					this.extra[4][i] = 
227
						nb2 & b3 |
228
						~b1 & ((a1 & na2 & na4 | na1 & a3) & (nb2 | nb4) |
229
								a1 & na2 & a3 & nb2 |
230
								(a1 | a2 | na4) & b3);
231
					this.extra[5][i] =
232
						b4 |
233
						a4 & (nb2 & nb3 | ~(b1 ^ b2));
234
						if (coverageTestFlag && coverageTestId == 8) {
235
							this.extra[5][i] = ~0;
236
						}
237
				}
238
			}
239
		}
211
		}
240
		for (; i < copyLimit; i++) {
212
		for (; i < copyLimit; i++) {
241
			this.extra[0][i] = otherInits.extra[0][i];
213
			this.extra[0][i] = otherInits.extra[0][i];
242
			this.extra[1][i] = otherInits.extra[1][i];
214
			this.extra[1][i] = otherInits.extra[1][i];
243
			if (considerNulls) {
215
		}
244
				for (int j = 2; j < extraLength; j++) {
216
		// tweak limits for nulls
245
					this.extra[j][i] = otherInits.extra[j][i];
217
		if (!thisHadNulls) {
246
				}
218
		    if (copyLimit < mergeLimit) {
247
				if (coverageTestFlag && coverageTestId == 9) {
219
		      	copyLimit = mergeLimit;
248
					this.extra[5][i] = ~0;
220
		    }
249
				}
221
		  	mergeLimit = 0;
222
		}
223
		if (!otherHasNulls) {
224
		  	copyLimit = 0;
225
		  	mergeLimit = 0;
226
		}
227
		for (i = 0; i < mergeLimit; i++) {
228
			this.extra[1 + 1][i] = (b1 = otherInits.extra[1 + 1][i])
229
                				| (a1 = this.extra[1 + 1][i]) & ((a3 = this.extra[3 + 1][i]) 
230
                					& (a4 = this.extra[4 + 1][i]) & (nb2 = ~(b2 = otherInits.extra[2 + 1][i])) 
231
                					& (nb4 = ~(b4 = otherInits.extra[4 + 1][i]))
232
                        		| ((na4 = ~a4) | (na3 = ~a3)) 
233
                        			& ((na2 = ~(a2 = this.extra[2 + 1][i])) & nb2 
234
                        				| a2 & (nb3 = ~(b3 = otherInits.extra[3 + 1][i])) & nb4));
235
			this.extra[2 + 1][i]  = b2 & (nb4 | nb3)
236
                    			| na3 & na4 & b2
237
                    			| a2 & (nb3 & nb4
238
                                			| (nb1 = ~b1) & (na3 | (na1 = ~a1))
239
                                			| a1 & b2);
240
			this.extra[3 + 1][i] = b3 & (nb1 & (b2 | a2 | na1)
241
                        			| b1 & (b4 | nb2 | a1 & a3)
242
                         			| na1 & na2 & na4)
243
                    			| a3 & nb2 & nb4
244
                    			| nb1 & ((na2 & a4 | na1) & a3
245
                                			| a1 & na2 & na4 & b2);
246
			this.extra[4 + 1][i] = nb1 & (a4 & (na3 & nb3	| (a3 | na2) & nb2)
247
                      			| a1 & (a3 & nb2 & b4
248
                              			| a2 & b2 & (b4	| a3 & na4 & nb3)))
249
                      			| b1 & (a3 & a4 & b4
250
                          			| na2 & na4 & nb3 & b4
251
                          			| a2 & ((b3 | a4) & b4
252
                                  				| na3 & a4 & b2 & b3)
253
                          			| na1 & (b4	| (a4 | a2) & b2 & b3))
254
                      			| (na1 & (na3 & nb3 | na2 & nb2)
255
                      				| a1 & (nb2 & nb3 | a2 & a3)) & b4;	
256
			if (coverageTestFlag && coverageTestId == 7) {
257
			  this.extra[5][i] = ~0;
258
			}
259
		}
260
		for (; i < copyLimit; i++) {
261
			for (int j = 2; j < extraLength; j++) {
262
				this.extra[j][i] = otherInits.extra[j][i];
263
			}
264
			if (coverageTestFlag && coverageTestId == 8) {
265
			  this.extra[5][i] = ~0;
250
			}
266
			}
251
		}
267
		}
252
	}
268
	}
Lines 322-527 Link Here
322
		return this;
338
		return this;
323
	}
339
	}
324
	// if we get here, otherInits has some null info
340
	// if we get here, otherInits has some null info
325
	boolean thisHasNulls = (this.tagBits & NULL_FLAG_MASK) != 0;
341
	boolean thisHadNulls = (this.tagBits & NULL_FLAG_MASK) != 0,
326
	if (thisHasNulls) {
342
		thisHasNulls = false;
327
		long a1, a2, na2, a3, na3, a4, na4, b1, nb1, b2, nb2, b3, nb3, b4, nb4;
343
	long a1, a2, a3, a4,  
328
		this.nullAssignmentStatusBit1 =
344
		na1, na2, na3, na4, 
329
			((a1 = this.nullAssignmentStatusBit1) &
345
		b1, b2, b3, b4,
330
					(na4 = ~(a4 = this.nullAssignmentValueBit2)) &	
346
		nb1, nb2, nb3, nb4;
331
					((na3 = ~(a3 = this.nullAssignmentValueBit1)) | 
347
	if (thisHadNulls) {
332
							(a2 = this.nullAssignmentStatusBit2)) | 
348
		this.nullBit1  = (a1 = this.nullBit1) 
333
							a2 & na3 &	a4) & 
349
								& ((a3 = this.nullBit3) & (a4 = this.nullBit4) 
334
					(nb3 = ~(b3 = otherInits.nullAssignmentValueBit1)) &
350
									& ((nb2 = ~(b2 = otherInits.nullBit2)) 
335
					((b2 = otherInits.nullAssignmentStatusBit2) | 
351
										& (nb4 = ~(b4 = otherInits.nullBit4)) 
336
					(nb4 = ~(b4 = otherInits.nullAssignmentValueBit2))) |
352
											| (b1 = otherInits.nullBit1) & (b3 = otherInits.nullBit3))
337
			a1 & (na2 = ~a2) & 
353
                			| (na2 = ~(a2 = this.nullBit2)) 
338
				(a4 & ((nb1 = ~(b1 = otherInits.nullAssignmentStatusBit1)) & 
354
                				& (b1 & b3 | ((na4 = ~a4) | (na3 = ~a3)) & nb2)
339
						nb3 | b1 &
355
                			| a2 & ((na4 | na3) & ((nb3 = ~b3) & nb4 | b1 & b2)));
340
						(b4 | b2)) |
356
		this.nullBit2 = b2 & (nb3 | (nb1 = ~b1))
341
				na4 & (nb1 & (((nb2 = ~b2) & nb4 | b2) & nb3 | b3 & nb4) | 
357
    			| a2 & (nb3 & nb4 | b2 | na3 | (na1 = ~a1));
342
						b1 & nb4 & (nb2 | nb3)));
358
		this.nullBit3 = b3 & (nb1 & b2
343
		this.nullAssignmentStatusBit2 =
359
            		| a2 & (nb2	| a3)
344
			a2 & (~a1 & na4 & nb4 |
360
            		| na1 & nb2
345
					a1 & na3 & nb3 & (nb1 & (nb2 & nb4 | b2) |
361
            		| a1 & na2 & na4 & b1)
346
										b1 & (nb4 |b2 & b4)));
362
    			| a3 & (nb2 & nb4 | na2 & a4 | na1)
347
		this.nullAssignmentValueBit1 =
363
    			| a1 & na2 & na4 & b2;
348
			a3 |
364
		this.nullBit4 = na3 & (nb1 & nb3 & b4
349
			b1 & nb2 & nb4 |
365
    				| a4 & (nb3 | b1 & b2))
350
			nb1 & b3 |
366
    			| nb2 & (na3 & b1 & nb3	| na2 & (nb1 & b4 | b1 & nb3 | a4))
351
			a1 & na2 & (b1 & b3 | nb1 & b4);
367
    			| a3 & (a4 & (nb2 | b1 & b3)
352
//			b1 & (~b2 & ~b4 | a1 & ~a2 & b3) |
368
            			| a1 & a2 & (nb1 & b4 | na4 & (b2 | b1) & nb3));
353
//			~b1 & (b3 | a1 & ~a2 & b4); -- same op nb
369
		if (coverageTestFlag && coverageTestId == 9) {
354
		this.nullAssignmentValueBit2 =
370
		  this.nullBit4 = ~0;
355
			a4 & (na2 | a2 & na3) |
371
		}
356
			b4 & (nb2 | b2 & nb3);
372
		if ((this.nullBit2 | this.nullBit3 | this.nullBit4) != 0) { //  bit1 is redundant
357
		if (coverageTestFlag && coverageTestId == 15) {
373
		  	thisHasNulls = true;
358
			this.nullAssignmentValueBit2 = ~0;
374
		}
359
		}
375
	} else {
360
		// extra storage management
376
  		this.nullBit1 = 0;
361
		if (otherInits.extra != null) {
377
  		this.nullBit2 = (b2 = otherInits.nullBit2) 
362
			int mergeLimit = 0, copyLimit = 0;
378
  							& ((nb3 = ~(b3 = otherInits.nullBit3)) | 
363
			int otherLength = otherInits.extra[0].length;
379
  								(nb1 = ~(b1 = otherInits.nullBit1)));
364
			if (this.extra == null) {
380
  		this.nullBit3 = b3 & (nb1 | (nb2 = ~b2));
365
				this.extra = new long[extraLength][];
381
  		this.nullBit4 = ~b1 & ~b3 & (b4 = otherInits.nullBit4) | ~b2 & (b1 & ~b3 | ~b1 & b4);
366
				for (int j = 0; j < extraLength; j++) {
382
		if (coverageTestFlag && coverageTestId == 10) {
367
					this.extra[j] = new long[otherLength];
383
		  this.nullBit4 = ~0;
368
				}
384
		}
369
				copyLimit = otherLength;
385
		if ((this.nullBit2 | this.nullBit3 | this.nullBit4) != 0) { //  bit1 is redundant
370
				if (coverageTestFlag && coverageTestId == 16) {
386
		  	thisHasNulls = true;
371
					this.extra[2][0] = ~0; thisHasNulls = true;
387
		}
372
				}
388
	}
373
			}
389
	// extra storage management
374
			else {
390
	if (otherInits.extra != null) {
375
				mergeLimit = otherLength;
391
		int mergeLimit = 0, copyLimit = otherInits.extra[0].length;
376
				if (mergeLimit > this.extra[0].length) {
392
		if (this.extra == null) {
377
					copyLimit = mergeLimit;
393
			this.extra = new long[extraLength][];
378
					mergeLimit = this.extra[0].length;
394
			for (int j = 0; j < extraLength; j++) {
379
					for (int j = 0; j < extraLength; j++) {
395
				this.extra[j] = new long[copyLimit];
380
						System.arraycopy(this.extra[j], 0,
381
								this.extra[j] = new long[otherLength], 0,
382
								mergeLimit);
383
					}
384
				}
385
				int i;
386
				for (i = 0; i < mergeLimit; i++) {
387
					this.extra[2][i] =
388
						((a1 = this.extra[2][i]) &
389
								(na4 = ~(a4 = this.extra[5][i])) &	
390
								((na3 = ~(a3 = this.extra[4][i])) | 
391
										(a2 = this.extra[3][i])) | 
392
										a2 & na3 &	a4) & 
393
								(nb3 = ~(b3 = otherInits.extra[4][i])) &
394
								((b2 = otherInits.extra[3][i]) | 
395
								(nb4 = ~(b4 = otherInits.extra[5][i]))) |
396
						a1 & (na2 = ~a2) & 
397
							(a4 & ((nb1 = ~(b1 = otherInits.extra[2][i])) & 
398
									nb3 | b1 &
399
									(b4 | b2)) |
400
							na4 & (nb1 & (((nb2 = ~b2) & nb4 | b2) & nb3 | b3 & nb4) | 
401
									b1 & nb4 & (nb2 | nb3)));
402
					this.extra[3][i] =
403
						a2 & (~a1 & na4 & nb4 |
404
								a1 & na3 & nb3 & (nb1 & (nb2 & nb4 | b2) |
405
													b1 & (nb4 |b2 & b4)));
406
					this.extra[4][i] =
407
						a3 |
408
						b1 & nb2 & nb4 |
409
						nb1 & b3 |
410
						a1 & na2 & (b1 & b3 | nb1 & b4);
411
					this.extra[5][i] =
412
						a4 & (na2 | a2 & na3) |
413
						b4 & (nb2 | b2 & nb3);
414
					if (coverageTestFlag && coverageTestId == 17) {
415
						this.nullAssignmentValueBit2 = ~0;
416
					}
417
				}
418
				for (; i < copyLimit; i++) {
419
					if (otherInits.extra[4][i] != 0 ||
420
						otherInits.extra[5][i] != 0) {
421
						this.tagBits |= NULL_FLAG_MASK; 
422
						this.extra[4][i] = 
423
							otherInits.extra[4][i] &
424
							~(otherInits.extra[2][i] &
425
							  ~otherInits.extra[3][i] &
426
							  otherInits.extra[5][i]);
427
						this.extra[5][i] = 
428
							otherInits.extra[5][i];
429
						if (coverageTestFlag && coverageTestId == 18) {
430
							this.extra[5][i] = ~0;
431
						}
432
					}
433
				}
434
			}
396
			}
435
		}
397
			if (coverageTestFlag && coverageTestId == 11) {
436
	}
398
				throw new AssertionFailedException("COVERAGE 11"); //$NON-NLS-1$
437
	else {
438
		if (otherInits.nullAssignmentValueBit1 != 0 ||
439
			otherInits.nullAssignmentValueBit2 != 0) {
440
			// add potential values
441
			this.nullAssignmentValueBit1 = 
442
				otherInits.nullAssignmentValueBit1 & 
443
					~(otherInits.nullAssignmentStatusBit1 &
444
					  ~otherInits.nullAssignmentStatusBit2 &
445
					  otherInits.nullAssignmentValueBit2); // exclude assigned unknown
446
			this.nullAssignmentValueBit2 = 
447
				otherInits.nullAssignmentValueBit2;
448
			thisHasNulls = 
449
				this.nullAssignmentValueBit1 != 0 ||
450
				this.nullAssignmentValueBit2 != 0;
451
			if (coverageTestFlag && coverageTestId == 10) {
452
				this.nullAssignmentValueBit2 = ~0;
453
			}
399
			}
454
		}
400
		} else {
455
		// extra storage management
401
			mergeLimit = copyLimit;
456
		if (otherInits.extra != null) {
402
			if (mergeLimit > this.extra[0].length) {
457
			int mergeLimit = 0, copyLimit = 0;
403
				mergeLimit = this.extra[0].length;
458
			int otherLength = otherInits.extra[0].length;
459
			if (this.extra == null) {
460
				copyLimit = otherLength; 
461
					// cannot happen when called from addPotentialInitializationsFrom
462
				this.extra = new long[extraLength][];
463
				for (int j = 0; j < extraLength; j++) {
404
				for (int j = 0; j < extraLength; j++) {
464
					this.extra[j] = new long[otherLength];
405
					System.arraycopy(this.extra[j], 0,
465
				}
406
							this.extra[j] = new long[copyLimit], 0,
466
				if (coverageTestFlag && coverageTestId == 11) {
467
					this.extra[5][0] = ~0; this.tagBits |= NULL_FLAG_MASK;
468
				}
469
			}
470
			else {
471
				mergeLimit = otherLength;
472
				if (mergeLimit > this.extra[0].length) {
473
					copyLimit = mergeLimit;
474
					mergeLimit = this.extra[0].length;
475
					System.arraycopy(this.extra[0], 0,
476
							this.extra[0] = new long[otherLength], 0,
477
							mergeLimit);
407
							mergeLimit);
478
					System.arraycopy(this.extra[1], 0,
408
				}
479
							this.extra[1] = new long[otherLength], 0,
409
				if (! thisHadNulls) {
480
							mergeLimit);
410
    				mergeLimit = 0; 
481
					for (int j = 2; j < extraLength; j++) {
411
    				// will do with a copy -- caveat: only valid because definite assignment bits copied above
482
						this.extra[j] = new long[otherLength];
412
        			if (coverageTestFlag && coverageTestId == 12) {
483
					}
484
					if (coverageTestFlag && coverageTestId == 12) {
485
						throw new AssertionFailedException("COVERAGE 12"); //$NON-NLS-1$
413
						throw new AssertionFailedException("COVERAGE 12"); //$NON-NLS-1$
486
					}
414
        			}
487
				}
415
				}
488
			}
416
			}
489
			int i;
417
		}
490
			for (i = 0; i < mergeLimit; i++) {
418
		// PREMATURE skip operations for fields
491
				if (otherInits.extra[4][i] != 0 ||
419
		int i;
492
					otherInits.extra[5][i] != 0) {
420
		for (i = 0 ; i < mergeLimit ; i++) {
493
					this.extra[4][i] |= 
421
    		this.extra[1 + 1][i]  = (a1 = this.extra[1 + 1][i]) 
494
						otherInits.extra[4][i] &
422
    								& ((a3 = this.extra[3 + 1][i]) & (a4 = this.extra[4 + 1][i]) 
495
						~(otherInits.extra[2][i] &
423
    									& ((nb2 = ~(b2 = otherInits.extra[2 + 1][i])) 
496
						  ~otherInits.extra[3][i] &
424
    										& (nb4 = ~(b4 = otherInits.extra[4 + 1][i])) 
497
						  otherInits.extra[5][i]);
425
    											| (b1 = otherInits.extra[1 + 1][i]) & (b3 = otherInits.extra[3 + 1][i]))
498
					this.extra[5][i] |= 
426
                    			| (na2 = ~(a2 = this.extra[2 + 1][i])) 
499
						otherInits.extra[5][i];
427
                    				& (b1 & b3 | ((na4 = ~a4) | (na3 = ~a3)) & nb2)
500
					thisHasNulls = thisHasNulls ||
428
                    			| a2 & ((na4 | na3) & ((nb3 = ~b3) & nb4 | b1 & b2)));
501
						this.extra[4][i] != 0 ||
429
    		this.extra[2 + 1][i] = b2 & (nb3 | (nb1 = ~b1))
502
						this.extra[5][i] != 0;
430
        			| a2 & (nb3 & nb4 | b2 | na3 | (na1 = ~a1));
503
					if (coverageTestFlag && coverageTestId == 13) {
431
    		this.extra[3 + 1][i] = b3 & (nb1 & b2
504
						this.extra[5][i] = ~0;
432
                		| a2 & (nb2	| a3)
505
					}
433
                		| na1 & nb2
506
				}
434
                		| a1 & na2 & na4 & b1)
435
        			| a3 & (nb2 & nb4 | na2 & a4 | na1)
436
        			| a1 & na2 & na4 & b2;
437
    		this.extra[4 + 1][i] = na3 & (nb1 & nb3 & b4
438
        				| a4 & (nb3 | b1 & b2))
439
        			| nb2 & (na3 & b1 & nb3	| na2 & (nb1 & b4 | b1 & nb3 | a4))
440
        			| a3 & (a4 & (nb2 | b1 & b3)
441
                			| a1 & a2 & (nb1 & b4 | na4 & (b2 | b1) & nb3));
442
    		if ((this.extra[2 + 1][i] | this.extra[3 + 1][i] | this.extra[4 + 1][i]) != 0) { //  bit1 is redundant
443
    		  	thisHasNulls = true;
444
    		}
445
			if (coverageTestFlag && coverageTestId == 13) {
446
			  this.nullBit4 = ~0;
507
			}
447
			}
508
			for (; i < copyLimit; i++) {
448
		}
509
				if (otherInits.extra[4][i] != 0 ||
449
		for (; i < copyLimit; i++) {
510
					otherInits.extra[5][i] != 0) {
450
    		this.extra[1 + 1][i] = 0;
511
					this.extra[4][i] = 
451
    		this.extra[2 + 1][i] = (b2 = otherInits.extra[2 + 1][i]) 
512
						otherInits.extra[4][i] &
452
    							& ((nb3 = ~(b3 = otherInits.extra[3 + 1][i])) | 
513
						~(otherInits.extra[2][i] &
453
    								(nb1 = ~(b1 = otherInits.extra[1 + 1][i])));
514
						  ~otherInits.extra[3][i] &
454
    		this.extra[3 + 1][i] = b3 & (nb1 | (nb2 = ~b2));
515
						  otherInits.extra[5][i]);
455
    		this.extra[4 + 1][i] = ~b1 & ~b3 & (b4 = otherInits.extra[4 + 1][i]) | ~b2 & (b1 & ~b3 | ~b1 & b4);
516
					this.extra[5][i] = 
456
    		if ((this.extra[2 + 1][i] | this.extra[3 + 1][i] | this.extra[4 + 1][i]) != 0) { //  bit1 is redundant
517
						otherInits.extra[5][i];
457
    		  	thisHasNulls = true;
518
					thisHasNulls = thisHasNulls ||
458
    		}
519
						this.extra[4][i] != 0 ||
459
			if (coverageTestFlag && coverageTestId == 14) {
520
						this.extra[5][i] != 0;
460
			  this.extra[5][i] = ~0;
521
					if (coverageTestFlag && coverageTestId == 14) {
522
						this.extra[5][i] = ~0;
523
					}
524
				}
525
			}
461
			}
526
		}
462
		}
527
	}
463
	}
Lines 545-554 Link Here
545
	copy.potentialInits = this.potentialInits;
481
	copy.potentialInits = this.potentialInits;
546
	boolean hasNullInfo = (this.tagBits & NULL_FLAG_MASK) != 0;
482
	boolean hasNullInfo = (this.tagBits & NULL_FLAG_MASK) != 0;
547
	if (hasNullInfo) { 
483
	if (hasNullInfo) { 
548
		copy.nullAssignmentStatusBit1 = this.nullAssignmentStatusBit1;
484
		copy.nullBit1 = this.nullBit1;
549
		copy.nullAssignmentStatusBit2 = this.nullAssignmentStatusBit2;
485
		copy.nullBit2 = this.nullBit2;
550
		copy.nullAssignmentValueBit1 = this.nullAssignmentValueBit1;
486
		copy.nullBit3 = this.nullBit3;
551
		copy.nullAssignmentValueBit2 = this.nullAssignmentValueBit2;
487
		copy.nullBit4 = this.nullBit4;
552
	}
488
	}
553
	copy.tagBits = this.tagBits;
489
	copy.tagBits = this.tagBits;
554
	copy.maxFieldCount = this.maxFieldCount;
490
	copy.maxFieldCount = this.maxFieldCount;
Lines 604-613 Link Here
604
		long mask = (1L << limit)-1;
540
		long mask = (1L << limit)-1;
605
		this.definiteInits &= mask;
541
		this.definiteInits &= mask;
606
		this.potentialInits &= mask;
542
		this.potentialInits &= mask;
607
		this.nullAssignmentStatusBit1 &= mask;
543
		this.nullBit1 &= mask;
608
		this.nullAssignmentStatusBit2 &= mask;
544
		this.nullBit2 &= mask;
609
		this.nullAssignmentValueBit1 &= mask;
545
		this.nullBit3 &= mask;
610
		this.nullAssignmentValueBit2 &= mask;
546
		this.nullBit4 &= mask;
611
	} 
547
	} 
612
	// use extra vector
548
	// use extra vector
613
	if (this.extra == null) {
549
	if (this.extra == null) {
Lines 694-708 Link Here
694
		return true;
630
		return true;
695
	}
631
	}
696
	int position = local.id + this.maxFieldCount;
632
	int position = local.id + this.maxFieldCount;
697
	long mask;
698
	if (position < BitCacheSize) { // use bits
633
	if (position < BitCacheSize) { // use bits
699
		return 
634
		return ((this.nullBit1 & this.nullBit3 & (~this.nullBit2 | this.nullBit4))
700
			(this.nullAssignmentStatusBit2 & 
635
			    & (1L << position)) != 0;
701
				(mask = 1L << position)) != 0 ?
702
			(this.nullAssignmentStatusBit1 & mask) != 0 :
703
			(this.nullAssignmentStatusBit1 & 
704
				this.nullAssignmentValueBit2 & mask) != 0 &&
705
			(this.nullAssignmentValueBit1 & mask) == 0; 
706
	}
636
	}
707
	// use extra vector
637
	// use extra vector
708
	if (this.extra == null) {
638
	if (this.extra == null) {
Lines 713-725 Link Here
713
			>= this.extra[0].length) {
643
			>= this.extra[0].length) {
714
		return false; // if not enough room in vector, then not initialized
644
		return false; // if not enough room in vector, then not initialized
715
	}
645
	}
716
	return 
646
	return ((this.extra[2][vectorIndex] & this.extra[4][vectorIndex]
717
		(this.extra[3][vectorIndex] & 
647
		        & (~this.extra[3][vectorIndex] | this.extra[5][vectorIndex]))
718
			(mask = 1L << (position % BitCacheSize))) != 0 ?
648
		    & (1L << (position % BitCacheSize))) != 0;
719
		(this.extra[2][vectorIndex] & mask) != 0 :
720
		(this.extra[2][vectorIndex] & 
721
			this.extra[5][vectorIndex] & mask) != 0 &&
722
		(this.extra[4][vectorIndex] & mask) == 0;
723
}
649
}
724
650
725
final public boolean isDefinitelyNull(LocalVariableBinding local) {
651
final public boolean isDefinitelyNull(LocalVariableBinding local) {
Lines 730-743 Link Here
730
		return false;
656
		return false;
731
	}
657
	}
732
	int position = local.id + this.maxFieldCount;
658
	int position = local.id + this.maxFieldCount;
733
	long mask;
734
	if (position < BitCacheSize) { // use bits
659
	if (position < BitCacheSize) { // use bits
735
		return 
660
		return ((this.nullBit1 & this.nullBit2
736
			(this.nullAssignmentStatusBit2 & (mask = 1L << position)) != 0 ?
661
			        & (~this.nullBit3 | ~this.nullBit4))
737
			(this.nullAssignmentStatusBit1 & mask) == 0 :
662
			    & (1L << position)) != 0;
738
			(this.nullAssignmentStatusBit1 & 
739
				this.nullAssignmentValueBit1 & mask) != 0 &&
740
			(this.nullAssignmentValueBit2 & mask) == 0; 
741
	}
663
	}
742
	// use extra vector
664
	// use extra vector
743
	if (this.extra == null) {
665
	if (this.extra == null) {
Lines 748-760 Link Here
748
			this.extra[0].length) {
670
			this.extra[0].length) {
749
		return false; // if not enough room in vector, then not initialized
671
		return false; // if not enough room in vector, then not initialized
750
	}
672
	}
751
	return
673
	return ((this.extra[2][vectorIndex] & this.extra[3][vectorIndex]
752
		(this.extra[3][vectorIndex] & 
674
		        & (~this.extra[4][vectorIndex] | ~this.extra[5][vectorIndex]))
753
			(mask = 1L << (position % BitCacheSize))) != 0 ?
675
		    & (1L << (position % BitCacheSize))) != 0;
754
		(this.extra[2][vectorIndex] & mask) == 0 :
755
		(this.extra[2][vectorIndex] & 
756
			this.extra[4][vectorIndex] & mask) != 0 &&
757
		(this.extra[5][vectorIndex] & mask) == 0;
758
}
676
}
759
677
760
final public boolean isDefinitelyUnknown(LocalVariableBinding local) {
678
final public boolean isDefinitelyUnknown(LocalVariableBinding local) {
Lines 764-777 Link Here
764
		return false;
682
		return false;
765
	}
683
	}
766
	int position = local.id + this.maxFieldCount;
684
	int position = local.id + this.maxFieldCount;
767
	long mask;
768
	if (position < BitCacheSize) { // use bits
685
	if (position < BitCacheSize) { // use bits
769
		return 
686
		return ((this.nullBit1 & this.nullBit4
770
			(this.nullAssignmentStatusBit2 & (mask = 1L << position)) != 0 ?
687
				& ~this.nullBit2 & ~this.nullBit3) & (1L << position)) != 0;
771
			false :
772
			(this.nullAssignmentStatusBit1 & 
773
				this.nullAssignmentValueBit1 & 
774
				this.nullAssignmentValueBit2 & mask) != 0; 
775
	}
688
	}
776
	// use extra vector
689
	// use extra vector
777
	if (this.extra == null) {
690
	if (this.extra == null) {
Lines 782-795 Link Here
782
			this.extra[0].length) {
695
			this.extra[0].length) {
783
		return false; // if not enough room in vector, then not initialized
696
		return false; // if not enough room in vector, then not initialized
784
	}
697
	}
785
	return
698
	return ((this.extra[2][vectorIndex] & this.extra[5][vectorIndex]
786
		(this.extra[3][vectorIndex] & 
699
	    & ~this.extra[3][vectorIndex] & ~this.extra[4][vectorIndex])
787
			(mask = 1L << (position % BitCacheSize))) != 0 ?
700
		    & (1L << (position % BitCacheSize))) != 0;
788
		false :
789
		(this.extra[2][vectorIndex] & 
790
			this.extra[4][vectorIndex] &
791
			this.extra[5][vectorIndex] &
792
			mask) != 0;
793
}
701
}
794
702
795
/**
703
/**
Lines 826-847 Link Here
826
	return isPotentiallyAssigned(local.id + this.maxFieldCount);
734
	return isPotentiallyAssigned(local.id + this.maxFieldCount);
827
}
735
}
828
736
737
final public boolean isPotentiallyNonNull(LocalVariableBinding local) {
738
	if ((this.tagBits & NULL_FLAG_MASK) == 0 || 
739
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
740
		return false;
741
	}
742
	int position;
743
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
744
		// use bits
745
		return ((this.nullBit3 & (~this.nullBit1 | ~this.nullBit2))
746
			    & (1L << position)) != 0;
747
	}
748
	// use extra vector
749
	if (this.extra == null) {
750
		return false; // if vector not yet allocated, then not initialized
751
	}
752
	int vectorIndex;
753
	if ((vectorIndex = (position / BitCacheSize) - 1) >= 
754
			this.extra[0].length) {
755
		return false; // if not enough room in vector, then not initialized
756
	}
757
	return ((this.extra[4][vectorIndex]
758
		        & (~this.extra[2][vectorIndex] | ~this.extra[3][vectorIndex]))
759
		    & (1L << (position % BitCacheSize))) != 0;
760
}
761
829
final public boolean isPotentiallyNull(LocalVariableBinding local) {
762
final public boolean isPotentiallyNull(LocalVariableBinding local) {
830
	if ((this.tagBits & NULL_FLAG_MASK) == 0 || 
763
	if ((this.tagBits & NULL_FLAG_MASK) == 0 || 
831
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
764
			(local.type.tagBits & TagBits.IsBaseType) != 0) {
832
		return false;
765
		return false;
833
	}
766
	}
834
	int position;
767
	int position;
835
	long mask;
836
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
768
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
837
		// use bits
769
		// use bits
838
		return
770
		return ((this.nullBit2 & (~this.nullBit1 | ~this.nullBit3))
839
			(this.nullAssignmentStatusBit2 & (mask = 1L << position)) != 0 ?
771
			    & (1L << position)) != 0;
840
			(this.nullAssignmentStatusBit1 & mask) == 0 : // protected null
841
			(this.nullAssignmentValueBit1 & mask) != 0 && // null bit set and
842
				((this.nullAssignmentStatusBit1 & mask) == 0 || // (potential or
843
				 (this.nullAssignmentValueBit2 & mask) == 0); 
844
											// assigned, but not unknown)
845
	}
772
	}
846
	// use extra vector
773
	// use extra vector
847
	if (this.extra == null) {
774
	if (this.extra == null) {
Lines 852-864 Link Here
852
			this.extra[0].length) {
779
			this.extra[0].length) {
853
		return false; // if not enough room in vector, then not initialized
780
		return false; // if not enough room in vector, then not initialized
854
	}
781
	}
855
	return 
782
	return ((this.extra[3][vectorIndex]
856
		(this.extra[3][vectorIndex] & 
783
		        & (~this.extra[2][vectorIndex] | ~this.extra[4][vectorIndex]))
857
			(mask = 1L << (position % BitCacheSize))) != 0 ?
784
		    & (1L << (position % BitCacheSize))) != 0;
858
		(this.extra[2][vectorIndex] & mask) == 0 :
859
		(this.extra[4][vectorIndex] & mask) != 0 && 
860
			((this.extra[2][vectorIndex] & mask) == 0 || 
861
			 (this.extra[5][vectorIndex] & mask) == 0); 
862
}
785
}
863
786
864
final public boolean isPotentiallyUnknown(LocalVariableBinding local) {
787
final public boolean isPotentiallyUnknown(LocalVariableBinding local) {
Lines 868-883 Link Here
868
		return false;
791
		return false;
869
	}
792
	}
870
	int position = local.id + this.maxFieldCount;
793
	int position = local.id + this.maxFieldCount;
871
	long mask;
872
	if (position < BitCacheSize) { // use bits
794
	if (position < BitCacheSize) { // use bits
873
		return 
795
		return (this.nullBit4 
874
			(this.nullAssignmentStatusBit2 & (mask = 1L << position)) != 0 ?
796
			& (~this.nullBit1 | ~this.nullBit2 & ~this.nullBit3)
875
			false :
797
			& (1L << position)) != 0;
876
			((this.nullAssignmentStatusBit1 & 
877
				this.nullAssignmentValueBit1 |
878
			 ~this.nullAssignmentStatusBit1 &
879
				~this.nullAssignmentValueBit1) & 
880
				this.nullAssignmentValueBit2 & mask) != 0; 
881
	}
798
	}
882
	// use extra vector
799
	// use extra vector
883
	if (this.extra == null) {
800
	if (this.extra == null) {
Lines 888-903 Link Here
888
			this.extra[0].length) {
805
			this.extra[0].length) {
889
		return false; // if not enough room in vector, then not initialized
806
		return false; // if not enough room in vector, then not initialized
890
	}
807
	}
891
	return
808
	return (this.extra[5][vectorIndex]
892
		(this.extra[3][vectorIndex] & 
809
	        & (~this.extra[2][vectorIndex] 
893
			(mask = 1L << (position % BitCacheSize))) != 0 ?
810
	            | ~this.extra[3][vectorIndex] & ~this.extra[4][vectorIndex]) 
894
		false :
811
		    & (1L << (position % BitCacheSize))) != 0;
895
		((this.extra[2][vectorIndex] & 
896
			this.extra[4][vectorIndex] |
897
		  ~this.extra[2][vectorIndex] &
898
			~this.extra[4][vectorIndex]) &
899
			this.extra[5][vectorIndex] &
900
			mask) != 0;
901
}
812
}
902
813
903
final public boolean isProtectedNonNull(LocalVariableBinding local) {
814
final public boolean isProtectedNonNull(LocalVariableBinding local) {
Lines 908-915 Link Here
908
	int position;
819
	int position;
909
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
820
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
910
		// use bits
821
		// use bits
911
		return (this.nullAssignmentStatusBit1 &
822
		return (this.nullBit1 & this.nullBit3 & this.nullBit4 & (1L << position)) != 0;
912
				this.nullAssignmentStatusBit2 & (1L << position)) != 0;
913
	}
823
	}
914
	// use extra vector
824
	// use extra vector
915
	if (this.extra == null) {
825
	if (this.extra == null) {
Lines 920-928 Link Here
920
		this.extra[0].length) {
830
		this.extra[0].length) {
921
		return false; // if not enough room in vector, then not initialized
831
		return false; // if not enough room in vector, then not initialized
922
	}
832
	}
923
	return (this.extra[2][vectorIndex] & 
833
	return (this.extra[2][vectorIndex] 
924
			this.extra[3][vectorIndex] & 
834
	            & this.extra[4][vectorIndex]
925
			(1L << (position % BitCacheSize))) != 0;
835
	            & this.extra[5][vectorIndex]
836
		    & (1L << (position % BitCacheSize))) != 0;
926
}
837
}
927
838
928
final public boolean isProtectedNull(LocalVariableBinding local) {
839
final public boolean isProtectedNull(LocalVariableBinding local) {
Lines 933-940 Link Here
933
	int position;
844
	int position;
934
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
845
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
935
		// use bits
846
		// use bits
936
		return (~this.nullAssignmentStatusBit1 &
847
		return (this.nullBit1 & this.nullBit2
937
				this.nullAssignmentStatusBit2 & (1L << position)) != 0;
848
			& (this.nullBit3 ^ this.nullBit4)
849
			& (1L << position)) != 0;
938
	}
850
	}
939
	// use extra vector
851
	// use extra vector
940
	if (this.extra == null) {
852
	if (this.extra == null) {
Lines 945-953 Link Here
945
			this.extra[0].length) {
857
			this.extra[0].length) {
946
		return false; // if not enough room in vector, then not initialized
858
		return false; // if not enough room in vector, then not initialized
947
	}
859
	}
948
	return (~this.extra[2][vectorIndex] & 
860
	return (this.extra[2][vectorIndex] & this.extra[3][vectorIndex]
949
			this.extra[3][vectorIndex] &
861
	        & (this.extra[4][vectorIndex] ^ this.extra[5][vectorIndex])
950
			(1L << (position % BitCacheSize))) != 0;
862
		    & (1L << (position % BitCacheSize))) != 0;
951
}
863
}
952
864
953
public void markAsComparedEqualToNonNull(LocalVariableBinding local) {
865
public void markAsComparedEqualToNonNull(LocalVariableBinding local) {
Lines 956-980 Link Here
956
		this.tagBits |= NULL_FLAG_MASK;
868
		this.tagBits |= NULL_FLAG_MASK;
957
		int position;
869
		int position;
958
		long mask;
870
		long mask;
871
		long a1, a2, a3, a4, na2;
959
		// position is zero-based
872
		// position is zero-based
960
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
873
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
961
			// use bits
874
			// use bits
962
			if (((mask = 1L << position) & // leave assigned non null unchanged 
875
			if (((mask = 1L << position) 
963
					this.nullAssignmentStatusBit1 &
876
				& (a1 = this.nullBit1)
964
					~this.nullAssignmentStatusBit2 &
877
				& (na2 = ~(a2 = this.nullBit2))
965
					~this.nullAssignmentValueBit1 &
878
				& ~(a3 = this.nullBit3)
966
					this.nullAssignmentValueBit2) == 0) {
879
				& (a4 = this.nullBit4))
967
				// set protected non null
880
					!= 0) {
968
				this.nullAssignmentStatusBit1 |= mask;
881
			  	this.nullBit4 &= ~mask;
969
				this.nullAssignmentStatusBit2 |= mask;
882
			} else if ((mask & a1 & na2 & a3) == 0) {
970
				 // clear potential null
883
			  	this.nullBit4 |= mask;
971
				this.nullAssignmentValueBit1 &= ~mask;
884
			  	if ((mask & a1) == 0) {
972
				if (coverageTestFlag && coverageTestId == 19) {
885
			  	  	if ((mask & a2 & (a3 ^ a4)) != 0) {
973
					this.nullAssignmentValueBit2 = ~0;
886
			  	  	  	this.nullBit2 &= ~mask;
974
				}
887
			  	  	}
975
			}
888
			  	  	else if ((mask & (a2 | a3 | a4)) == 0) {
976
			if (coverageTestFlag && coverageTestId == 20) {
889
			  	  	  	this.nullBit2 |= mask;
977
				this.nullAssignmentValueBit2 = ~0;
890
			  	  	}
891
			  	}
892
			}
893
			this.nullBit1 |= mask;
894
			this.nullBit3 |= mask; 
895
			if (coverageTestFlag && coverageTestId == 15) {
896
			  	this.nullBit4 = ~0;
978
			}
897
			}
979
		} 
898
		} 
980
		else {
899
		else {
Lines 986-993 Link Here
986
				for (int j = 0; j < extraLength; j++) {
905
				for (int j = 0; j < extraLength; j++) {
987
					this.extra[j] = new long[length];
906
					this.extra[j] = new long[length];
988
				}
907
				}
989
				if (coverageTestFlag && coverageTestId == 21) {
908
				if (coverageTestFlag && coverageTestId == 16) {
990
					throw new AssertionFailedException("COVERAGE 21"); //$NON-NLS-1$
909
					throw new AssertionFailedException("COVERAGE 16"); //$NON-NLS-1$
991
				}
910
				}
992
			}
911
			}
993
			else {
912
			else {
Lines 999-1020 Link Here
999
							(this.extra[j] = new long[newLength]), 0, 
918
							(this.extra[j] = new long[newLength]), 0, 
1000
							oldLength);
919
							oldLength);
1001
					}
920
					}
1002
					if (coverageTestFlag && coverageTestId == 22) {
921
					if (coverageTestFlag && coverageTestId == 17) {
1003
						throw new AssertionFailedException("COVERAGE 22"); //$NON-NLS-1$
922
						throw new AssertionFailedException("COVERAGE 17"); //$NON-NLS-1$
1004
					}
923
					}
1005
				}
924
				}
1006
			}
925
			}
1007
			if (((mask = 1L << (position % BitCacheSize)) & 
926
			// MACRO :'b,'es/nullBit\(.\)/extra[\1 + 1][vectorIndex]/gc
1008
					this.extra[2][vectorIndex] &
927
			if (((mask = 1L << (position % BitCacheSize)) 
1009
					~this.extra[3][vectorIndex] &
928
  				& (a1 = this.extra[1 + 1][vectorIndex])
1010
					~this.extra[4][vectorIndex] &
929
  				& (na2 = ~(a2 = this.extra[2 + 1][vectorIndex]))
1011
					this.extra[5][vectorIndex]) == 0) {
930
  				& ~(a3 = this.extra[3 + 1][vectorIndex])
1012
				this.extra[2][vectorIndex] |= mask;
931
  				& (a4 = this.extra[4 + 1][vectorIndex]))
1013
				this.extra[3][vectorIndex] |= mask;
932
  					!= 0) {
1014
				this.extra[4][vectorIndex] &= ~mask;
933
  			  	this.extra[4 + 1][vectorIndex] &= ~mask;
1015
				if (coverageTestFlag && coverageTestId == 23) {
934
  			} else if ((mask & a1 & na2 & a3) == 0) {
1016
					this.extra[5][vectorIndex] = ~0;
935
  			  	this.extra[4 + 1][vectorIndex] |= mask;
1017
				}
936
  			  	if ((mask & a1) == 0) {
937
  			  	  	if ((mask & a2 & (a3 ^ a4)) != 0) {
938
  			  	  	  	this.extra[2 + 1][vectorIndex] &= ~mask;
939
  			  	  	}
940
  			  	  	else if ((mask & (a2 | a3 | a4)) == 0) {
941
  			  	  	  	this.extra[2 + 1][vectorIndex] |= mask;
942
  			  	  	}
943
  			  	}
944
  			}
945
  			this.extra[1 + 1][vectorIndex] |= mask;
946
  			this.extra[3 + 1][vectorIndex] |= mask; 
947
			if (coverageTestFlag && coverageTestId == 18) {
948
			  	this.extra[5][vectorIndex] = ~0;
1018
			}
949
			}
1019
		}
950
		}
1020
	}
951
	}
Lines 1025-1057 Link Here
1025
	if (this != DEAD_END) {
956
	if (this != DEAD_END) {
1026
		this.tagBits |= NULL_FLAG_MASK;
957
		this.tagBits |= NULL_FLAG_MASK;
1027
		int position;
958
		int position;
1028
		long mask, unknownAssigned;
959
		long mask;
1029
		// position is zero-based
960
		// position is zero-based
1030
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
961
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1031
			// use bits
962
			// use bits
1032
			mask = 1L << position;
963
			if (((mask = 1L << position) & this.nullBit1) != 0) {
1033
			if ((mask & // leave assigned null unchanged
964
  			  	if ((mask  
1034
					this.nullAssignmentStatusBit1 &
965
  			  		& (~this.nullBit2 | this.nullBit3
1035
					~this.nullAssignmentStatusBit2 &
966
  			  			| ~this.nullBit4)) != 0) {
1036
					this.nullAssignmentValueBit1 &
967
  			  	  	this.nullBit4 &= ~mask;
1037
					~this.nullAssignmentValueBit2) == 0) {
968
  			  	}
1038
				unknownAssigned = this.nullAssignmentStatusBit1 &
969
			} else if ((mask & this.nullBit4) != 0) {
1039
					~this.nullAssignmentStatusBit2 &
970
			  	  this.nullBit3 &= ~mask;
1040
					this.nullAssignmentValueBit1 &
971
			} else {
1041
					this.nullAssignmentValueBit2;
972
    			if ((mask & this.nullBit2) != 0) {
1042
				// set protected
973
    			  	this.nullBit3 &= ~mask;
1043
				this.nullAssignmentStatusBit2 |= mask;
974
      			  	this.nullBit4 |= mask;
1044
				this.nullAssignmentStatusBit1 &= (mask = ~mask);
975
    			} else {
1045
				// protected is null
976
    			  	this.nullBit3 |= mask;
1046
				this.nullAssignmentValueBit1 &= mask | ~unknownAssigned;
977
    			}
1047
				this.nullAssignmentValueBit2 &= mask;
978
			}
1048
				// clear potential anything but null
979
			this.nullBit1 |= mask;
1049
				if (coverageTestFlag && coverageTestId == 24) {
980
			this.nullBit2 |= mask; 
1050
					this.nullAssignmentValueBit2 = ~0;
981
			if (coverageTestFlag && coverageTestId == 19) {
1051
				}
982
			  	this.nullBit4 = ~0;
1052
			}
1053
			if (coverageTestFlag && coverageTestId == 25) {
1054
				this.nullAssignmentValueBit2 = ~0;
1055
			}
983
			}
1056
		} 
984
		} 
1057
		else {
985
		else {
Lines 1064-1071 Link Here
1064
				for (int j = 0; j < extraLength; j++) {
992
				for (int j = 0; j < extraLength; j++) {
1065
					this.extra[j] = new long[length ];
993
					this.extra[j] = new long[length ];
1066
				}
994
				}
1067
				if (coverageTestFlag && coverageTestId == 26) {
995
				if (coverageTestFlag && coverageTestId == 20) {
1068
					throw new AssertionFailedException("COVERAGE 26"); //$NON-NLS-1$
996
					throw new AssertionFailedException("COVERAGE 20"); //$NON-NLS-1$
1069
				}
997
				}
1070
			}
998
			}
1071
			else {
999
			else {
Lines 1077-1104 Link Here
1077
							(this.extra[j] = new long[newLength]), 0,
1005
							(this.extra[j] = new long[newLength]), 0,
1078
							oldLength);
1006
							oldLength);
1079
					}
1007
					}
1080
					if (coverageTestFlag && coverageTestId == 27) {
1008
					if (coverageTestFlag && coverageTestId == 21) {
1081
						throw new AssertionFailedException("COVERAGE 27"); //$NON-NLS-1$
1009
						throw new AssertionFailedException("COVERAGE 21"); //$NON-NLS-1$
1082
					}
1010
					}
1083
				}
1011
				}
1084
			}
1012
			}
1085
			if ((mask &
1013
			if ((mask & this.extra[1 + 1][vectorIndex]) != 0) {
1086
					this.extra[2][vectorIndex] &
1014
  			  	if ((mask  
1087
					~this.extra[3][vectorIndex] &
1015
  			  		& (~this.extra[2 + 1][vectorIndex] | this.extra[3 + 1][vectorIndex]
1088
					this.extra[4][vectorIndex] &
1016
  			  			| ~this.extra[4 + 1][vectorIndex])) != 0) {
1089
					~this.extra[5][vectorIndex]) == 0) {
1017
  			  	  	this.extra[4 + 1][vectorIndex] &= ~mask;
1090
				unknownAssigned = this.extra[2][vectorIndex] &
1018
  			  	}
1091
					~this.extra[3][vectorIndex] &
1019
			} else if ((mask & this.extra[4 + 1][vectorIndex]) != 0) {
1092
					this.extra[4][vectorIndex] &
1020
			  	  this.extra[3 + 1][vectorIndex] &= ~mask;
1093
					this.extra[5][vectorIndex];
1021
			} else {
1094
				this.extra[3][vectorIndex]	 |= mask;
1022
    			if ((mask & this.extra[2 + 1][vectorIndex]) != 0) {
1095
				this.extra[2][vectorIndex] &= (mask = ~mask);
1023
    			  	this.extra[3 + 1][vectorIndex] &= ~mask;
1096
				this.extra[4][vectorIndex] &= mask | ~unknownAssigned;
1024
      			  	this.extra[4 + 1][vectorIndex] |= mask;
1097
				this.extra[5][vectorIndex]	&= mask;
1025
    			} else {
1098
				if (coverageTestFlag && coverageTestId == 28) {
1026
    			  	this.extra[3 + 1][vectorIndex] |= mask;
1099
					this.extra[5][vectorIndex] = ~0;
1027
    			}
1100
				}
1101
			}
1028
			}
1029
			this.extra[1 + 1][vectorIndex] |= mask;
1030
			this.extra[2 + 1][vectorIndex] |= mask; 
1102
		}
1031
		}
1103
	}
1032
	}
1104
}
1033
}
Lines 1157-1218 Link Here
1157
public void markAsDefinitelyNonNull(LocalVariableBinding local) {
1086
public void markAsDefinitelyNonNull(LocalVariableBinding local) {
1158
	// protected from non-object locals in calling methods
1087
	// protected from non-object locals in calling methods
1159
	if (this != DEAD_END) {
1088
	if (this != DEAD_END) {
1160
		this.tagBits |= NULL_FLAG_MASK;
1089
    	this.tagBits |= NULL_FLAG_MASK;
1161
		int position;
1090
    	long mask;
1162
		long mask;
1091
    	int position;
1163
		// position is zero-based
1092
    	// position is zero-based
1164
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {		// use bits
1093
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
1165
			this.nullAssignmentStatusBit1 |= (mask = 1L << position);
1094
    		// set assigned non null
1166
			this.nullAssignmentValueBit2 |= mask; // set non null
1095
    		this.nullBit1 |= (mask = 1L << position);
1167
			this.nullAssignmentStatusBit2 &= ~mask; // clear protection
1096
    		this.nullBit3 |= mask;
1168
			this.nullAssignmentValueBit1 &= ~mask; // clear null
1097
    		// clear others
1169
			if (coverageTestFlag && coverageTestId == 29) {
1098
    		this.nullBit2 &= (mask = ~mask);
1170
				this.nullAssignmentStatusBit1 = 0;
1099
    		this.nullBit4 &= mask;
1171
			}
1100
    		if (coverageTestFlag && coverageTestId == 22) {
1172
		} 
1101
    		  	this.nullBit1 = 0;
1173
		else {
1102
    		}
1174
			// use extra vector
1103
    	} 
1175
			int vectorIndex = (position / BitCacheSize) - 1;
1104
    	else {
1176
			this.extra[2][vectorIndex] |= 
1105
    		// use extra vector
1177
				(mask = 1L << (position % BitCacheSize));
1106
    		int vectorIndex ;
1178
			this.extra[5][vectorIndex] |= mask;
1107
    		this.extra[2][vectorIndex = (position / BitCacheSize) - 1] 
1179
			this.extra[3][vectorIndex] &= ~mask;
1108
    		    |= (mask = 1L << (position % BitCacheSize));
1180
			this.extra[4][vectorIndex] &= ~mask;
1109
    		this.extra[4][vectorIndex] |= mask;
1181
			if (coverageTestFlag && coverageTestId == 30) {
1110
    		this.extra[3][vectorIndex] &= (mask = ~mask);
1182
				this.extra[5][vectorIndex] = ~0;
1111
    		this.extra[5][vectorIndex] &= mask;
1183
			}
1112
    		if (coverageTestFlag && coverageTestId == 23) {
1184
		}
1113
    			this.extra[2][vectorIndex] = 0;
1114
    		}
1115
    	}
1185
	}
1116
	}
1186
}
1117
}
1187
1118
1188
public void markAsDefinitelyNull(LocalVariableBinding local) {
1119
public void markAsDefinitelyNull(LocalVariableBinding local) {
1189
	// protected from non-object locals in calling methods
1120
	// protected from non-object locals in calling methods
1190
	if (this != DEAD_END) {
1121
	if (this != DEAD_END) {
1191
		this.tagBits |= NULL_FLAG_MASK;
1122
    	this.tagBits |= NULL_FLAG_MASK;
1192
		int position;
1123
    	long mask;
1193
		long mask;
1124
    	int position;
1194
		// position is zero-based
1125
    	// position is zero-based
1195
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {		// use bits
1126
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
1196
			this.nullAssignmentStatusBit1 |= (mask = 1L << position); // set assignment
1127
    		// mark assigned null
1197
			this.nullAssignmentStatusBit2 &= ~mask; // clear protection
1128
    		this.nullBit1 |= (mask = 1L << position);
1198
			this.nullAssignmentValueBit1 |= mask; // set null
1129
    		this.nullBit2 |= mask;
1199
			this.nullAssignmentValueBit2 &= ~mask; // clear non null
1130
    		// clear others
1200
			if (coverageTestFlag && coverageTestId == 31) {
1131
    		this.nullBit3 &= (mask = ~mask);
1201
				this.nullAssignmentValueBit2 = ~0;
1132
    		this.nullBit4 &= mask;
1202
			}
1133
    		if (coverageTestFlag && coverageTestId == 24) {
1203
		} 
1134
    		  	this.nullBit4 = ~0;
1204
		else {
1135
    		}
1205
			// use extra vector
1136
    	} 
1206
			int vectorIndex = (position / BitCacheSize) - 1;
1137
    	else {
1207
			this.extra[2][vectorIndex] |= 
1138
    		// use extra vector
1208
				(mask = 1L << (position % BitCacheSize));
1139
    		int vectorIndex ;
1209
			this.extra[3][vectorIndex] &= ~mask;
1140
    		this.extra[2][vectorIndex = (position / BitCacheSize) - 1] 
1210
			this.extra[4][vectorIndex] |= mask;
1141
    		    |= (mask = 1L << (position % BitCacheSize));
1211
			this.extra[5][vectorIndex] &= ~mask;
1142
    		this.extra[3][vectorIndex] |= mask;
1212
			if (coverageTestFlag && coverageTestId == 32) {
1143
    		this.extra[4][vectorIndex] &= (mask = ~mask);
1213
				this.extra[5][vectorIndex] = ~0;
1144
    		this.extra[5][vectorIndex] &= mask;
1214
			}
1145
    		if (coverageTestFlag && coverageTestId == 25) {
1215
		}
1146
    			this.extra[5][vectorIndex] = ~0;
1147
    		}
1148
    	}
1216
	}
1149
	}
1217
}
1150
}
1218
1151
Lines 1231-1257 Link Here
1231
		// position is zero-based
1164
		// position is zero-based
1232
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1165
		if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
1233
			// use bits
1166
			// use bits
1234
			this.nullAssignmentValueBit1 |= (mask = 1L << position);
1167
			// mark assigned null
1235
			this.nullAssignmentValueBit2 |= mask;
1168
			this.nullBit1 |= (mask = 1L << position);
1236
			// set unknown
1169
			this.nullBit4 |= mask;
1237
			this.nullAssignmentStatusBit1 |= mask;
1170
			// clear others
1238
			// set assignment
1171
			this.nullBit2 &= (mask = ~mask);
1239
			this.nullAssignmentStatusBit2 &= ~mask;
1172
			this.nullBit3 &= mask;
1240
			// clear protection
1173
			if (coverageTestFlag && coverageTestId == 26) {
1241
			if (coverageTestFlag && coverageTestId == 33) {
1174
			  	this.nullBit4 = 0;
1242
				this.nullAssignmentValueBit2 = ~0;
1243
			}
1175
			}
1244
		} 
1176
		} 
1245
		else {
1177
		else {
1246
			// use extra vector
1178
			// use extra vector
1247
			int vectorIndex = (position / BitCacheSize) - 1;
1179
			int vectorIndex ;
1248
			this.extra[4][vectorIndex] |=
1180
			this.extra[2][vectorIndex = (position / BitCacheSize) - 1] 
1249
				(mask = 1L << (position % BitCacheSize));
1181
			    |= (mask = 1L << (position % BitCacheSize));
1250
			this.extra[5][vectorIndex] |= mask;
1182
			this.extra[5][vectorIndex] |= mask;
1251
			this.extra[2][vectorIndex] |= mask;
1183
			this.extra[3][vectorIndex] &= (mask = ~mask);
1252
			this.extra[3][vectorIndex] &= ~mask;
1184
			this.extra[4][vectorIndex] &= mask;
1253
			if (coverageTestFlag && coverageTestId == 34) {
1185
			if (coverageTestFlag && coverageTestId == 27) {
1254
				this.extra[5][vectorIndex] = ~0;
1186
				this.extra[5][vectorIndex] = 0;
1255
			}
1187
			}
1256
		}
1188
		}
1257
	}
1189
	}
Lines 1259-1273 Link Here
1259
1191
1260
public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits) {
1192
public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits) {
1261
	if ((otherInits.tagBits & UNREACHABLE) != 0 && this != DEAD_END) {
1193
	if ((otherInits.tagBits & UNREACHABLE) != 0 && this != DEAD_END) {
1262
		if (coverageTestFlag && coverageTestId == 35) {
1194
		if (coverageTestFlag && coverageTestId == 28) {
1263
			throw new AssertionFailedException("COVERAGE 35"); //$NON-NLS-1$
1195
			throw new AssertionFailedException("COVERAGE 28"); //$NON-NLS-1$
1264
		}
1196
		}
1265
		// DEAD_END + unreachable other -> other
1266
		return this;
1197
		return this;
1267
	}
1198
	}
1268
	if ((this.tagBits & UNREACHABLE) != 0) {
1199
	if ((this.tagBits & UNREACHABLE) != 0) {
1269
		if (coverageTestFlag && coverageTestId == 36) {
1200
		if (coverageTestFlag && coverageTestId == 29) {
1270
			throw new AssertionFailedException("COVERAGE 36"); //$NON-NLS-1$
1201
			throw new AssertionFailedException("COVERAGE 29"); //$NON-NLS-1$
1271
		}
1202
		}
1272
		return (UnconditionalFlowInfo) otherInits.copy(); // make sure otherInits won't be affected
1203
		return (UnconditionalFlowInfo) otherInits.copy(); // make sure otherInits won't be affected
1273
	} 
1204
	} 
Lines 1278-1346 Link Here
1278
	this.potentialInits |= otherInits.potentialInits;
1209
	this.potentialInits |= otherInits.potentialInits;
1279
1210
1280
	// null combinations
1211
	// null combinations
1281
	boolean otherHasNulls = (otherInits.tagBits & NULL_FLAG_MASK) != 0,
1212
	boolean
1282
		thisHasNulls = false;
1213
		thisHasNulls = (this.tagBits & NULL_FLAG_MASK) != 0,
1283
	long a1, a2, na2, a3, na3, a4, na4, b1, nb1, b2, nb2, b3, nb3, b4, nb4;
1214
		otherHasNulls = (otherInits.tagBits & NULL_FLAG_MASK) != 0,
1284
	if (otherHasNulls) {
1215
		thisHadNulls = thisHasNulls;
1285
		this.nullAssignmentStatusBit1 =
1216
	long 
1286
			(a1 = this.nullAssignmentStatusBit1) & 
1217
		a1, a2, a3, a4,  
1287
			(b1 = otherInits.nullAssignmentStatusBit1) & (
1218
		na1, na2, na3, na4, 
1288
				(nb4 = ~(b4 = otherInits.nullAssignmentValueBit2)) & 
1219
		nb1, nb2, nb3, nb4,
1289
				((b2 = otherInits.nullAssignmentStatusBit2) & 
1220
		b1, b2, b3, b4;
1290
						(nb3 = ~(b3 = otherInits.nullAssignmentValueBit1)) & 
1221
	if (thisHadNulls) {
1291
						(na3 = ~(a3 = this.nullAssignmentValueBit1)) & 
1222
    	if (otherHasNulls) {
1292
						((a2 = this.nullAssignmentStatusBit2) & 
1223
    		this.nullBit1 = (a2 = this.nullBit2) & (a3 = this.nullBit3) 
1293
							(na4 = ~(a4 = this.nullAssignmentValueBit2)) | a4) |
1224
    							& (a4 = this.nullBit4) & (b1 = otherInits.nullBit1) 
1294
						(na2 = ~a2) & a3 & na4 & (nb2 = ~b2) & b3 ) |
1225
    							& (nb2 = ~(b2 = otherInits.nullBit2))
1295
				b4 & (na3 & nb3 & (na4 & a2 | a4) |
1226
                  			| (a1 = this.nullBit1) & (b1 & (a3 & a4 & (b3 = otherInits.nullBit3) 
1296
						na2 & a4 & nb2));
1227
                  													& (b4 = otherInits.nullBit4)
1297
		this.nullAssignmentStatusBit2 =
1228
                  												| (na2 = ~a2) & nb2 
1298
			a2 & b2 & ~(a1 ^ b1) & (na3 & nb3 | na4 & nb4) |
1229
                  													& ((nb4 = ~b4) | (na4 = ~a4) 
1299
			a1 & b1 & (a2 ^ b2) & na3 & nb3 |
1230
                  															| (na3 = ~a3) & (nb3 = ~b3))
1300
			(a1 & na2 & (nb1 = ~b1) & b2 | ~a1 & a2 & b1 & nb2) & na4 & nb4;
1231
                  												| a2 & b2 & ((na4 | na3) & (nb4	| nb3)))
1301
		this.nullAssignmentValueBit1 =
1232
                  											| na2 & b2 & b3 & b4);
1302
			b1 & nb2 & nb4 |
1233
    		this.nullBit2 = b2 & (nb3 | (nb1 = ~b1) | a3 & (a4 | (na1 = ~a1)) & nb4)
1303
			~a1 & (a3 |
1234
        			| a2 & (b2 | na4 & b3 & (b4 | nb1) | na3 | na1);
1304
					a2 & na3 & (b1 | nb2)) |
1235
    		this.nullBit3 = b3 & (nb2 & b4 | nb1 | a3 & (na4 & nb4 | a4 & b4))
1305
			(a1 | na2) & nb1 & b2 & nb3 |
1236
        			| a3 & (na2 & a4 | na1)
1306
			nb1 & b3 |
1237
        			| (a2 | na1) & b1 & nb2 & nb4
1307
			a1 & na2 & (na4 |
1238
        			| a1 & na2 & na4 & (b2 | nb1);
1308
						b1 & nb2 & (a3 | b3));
1239
    		this.nullBit4 = na3 & (nb1 & nb3 & b4
1309
		this.nullAssignmentValueBit2 =
1240
              			| b1 & (nb2 & nb3 | a4 & b2 & nb4)
1310
			a4 | b4;
1241
              			| na1 & a4 & (nb3 | b1 & b2))
1311
		
1242
        			| a3 & a4 & (b3 & b4 | b1 & nb2)
1312
		// WORK recode if tests succeed
1243
        			| na2 & (nb1 & b4 | b1 & nb3 | na1 & a4) & nb2
1313
		this.nullAssignmentValueBit1 &= 
1244
        			| a1 & (na3 & (nb3 & b4
1314
			~(a1 & na2 & na3 & a4 & nb1 & b2 & nb3 & nb4
1245
                        			| b1 & b2 & b3 & nb4
1315
					| ~a1 & a2 & na3 & na4 & b1 & nb2 & nb3 & b4);
1246
                        			| na2 & (nb3 | nb2))
1316
		
1247
                			| na2 & b3 & b4
1317
		if (coverageTestFlag && coverageTestId == 37) {
1248
                			| a2 & (nb1 & b4 | a3 & na4 & b1) & nb3);
1318
			this.nullAssignmentValueBit2 = ~0;
1249
    		if (coverageTestFlag && coverageTestId == 30) {
1319
		}
1250
    		  	this.nullBit4 = ~0;
1251
    		}
1252
    	} else { // other has no null info 
1253
    		a1 = this.nullBit1;
1254
      		this.nullBit1 = 0;
1255
      		this.nullBit2 = (a2 = this.nullBit2) & (na3 = ~(a3 = this.nullBit3) | (na1 = ~a1));
1256
      		this.nullBit3 = a3 & ((na2 = ~a2) & (a4 = this.nullBit4) | na1) | a1 & na2 & ~a4;
1257
      		this.nullBit4 = (na3 | na2) & na1 & a4	| a1 & na3 & na2;
1258
    		if (coverageTestFlag && coverageTestId == 31) {
1259
    		  	this.nullBit4 = ~0;
1260
    		}
1261
    	}
1262
	} else if (otherHasNulls) { // only other had nulls
1263
  		this.nullBit1 = 0;
1264
  		this.nullBit2 = (b2 = otherInits.nullBit2) & (nb3 = ~(b3 = otherInits.nullBit3) | (nb1 = ~(b1 = otherInits.nullBit1)));
1265
  		this.nullBit3 = b3 & ((nb2 = ~b2) & (b4 = otherInits.nullBit4) | nb1) | b1 & nb2 & ~b4;
1266
  		this.nullBit4 = (nb3 | nb2) & nb1 & b4	| b1 & nb3 & nb2;
1267
  		if (coverageTestFlag && coverageTestId == 32) {
1268
  		  	this.nullBit4 = ~0;
1269
  		}
1270
    	thisHasNulls =
1271
    		// redundant with the three following ones
1272
    		this.nullBit2 != 0 ||
1273
    		this.nullBit3 != 0 ||
1274
    		this.nullBit4 != 0;
1320
	}
1275
	}
1321
	else {
1322
		// tune potentials
1323
		this.nullAssignmentValueBit1 =
1324
			~(~this.nullAssignmentStatusBit1 &
1325
					~this.nullAssignmentStatusBit2 &
1326
					~this.nullAssignmentValueBit1) &
1327
			~(this.nullAssignmentStatusBit1 & 
1328
					(this.nullAssignmentStatusBit2 | this.nullAssignmentValueBit2));
1329
		// reset assignment and protected
1330
		this.nullAssignmentStatusBit1 = 
1331
		this.nullAssignmentStatusBit2 = 0;
1332
		if (coverageTestFlag && coverageTestId == 38) {
1333
			this.nullAssignmentValueBit2 = ~0;
1334
		}
1335
	}
1336
	thisHasNulls = this.nullAssignmentStatusBit1 != 0 || 
1337
		this.nullAssignmentStatusBit2 != 0 ||
1338
		this.nullAssignmentValueBit1 != 0 ||
1339
		this.nullAssignmentValueBit2 != 0;
1340
1276
1341
	// treating extra storage
1277
	// treating extra storage
1342
	if (this.extra != null || otherInits.extra != null) {
1278
	if (this.extra != null || otherInits.extra != null) {
1343
		int mergeLimit = 0, copyLimit = 0, resetLimit = 0;
1279
		int mergeLimit = 0, copyLimit = 0, resetLimit = 0;
1280
		int i;
1344
		if (this.extra != null) {
1281
		if (this.extra != null) {
1345
			if (otherInits.extra != null) {
1282
			if (otherInits.extra != null) {
1346
				// both sides have extra storage
1283
				// both sides have extra storage
Lines 1354-1376 Link Here
1354
					}
1291
					}
1355
					mergeLimit = length;
1292
					mergeLimit = length;
1356
					copyLimit = otherLength;
1293
					copyLimit = otherLength;
1357
					if (coverageTestFlag && coverageTestId == 39) {
1294
					if (coverageTestFlag && coverageTestId == 33) {
1358
						throw new AssertionFailedException("COVERAGE 39"); //$NON-NLS-1$
1295
						throw new AssertionFailedException("COVERAGE 33"); //$NON-NLS-1$
1359
					}
1296
					}
1360
				} 
1297
				} 
1361
				else {
1298
				else {
1362
					// current storage is longer
1299
					// current storage is longer
1363
					mergeLimit = otherLength;
1300
					mergeLimit = otherLength;
1364
					resetLimit = length;
1301
					resetLimit = length;
1365
					if (coverageTestFlag && coverageTestId == 40) {
1302
					if (coverageTestFlag && coverageTestId == 34) {
1366
						throw new AssertionFailedException("COVERAGE 40"); //$NON-NLS-1$
1303
						throw new AssertionFailedException("COVERAGE 34"); //$NON-NLS-1$
1367
					}
1304
					}
1368
				}
1305
				}
1369
			} 
1306
			} 
1370
			else {
1307
			else {
1371
				resetLimit = this.extra[0].length;
1308
				resetLimit = this.extra[0].length;
1372
				if (coverageTestFlag && coverageTestId == 41) {
1309
				if (coverageTestFlag && coverageTestId == 35) {
1373
					throw new AssertionFailedException("COVERAGE 41"); //$NON-NLS-1$
1310
					throw new AssertionFailedException("COVERAGE 35"); //$NON-NLS-1$
1374
				}
1311
				}
1375
			}
1312
			}
1376
		} 
1313
		} 
Lines 1384-1497 Link Here
1384
			System.arraycopy(otherInits.extra[1], 0, 
1321
			System.arraycopy(otherInits.extra[1], 0, 
1385
				this.extra[1], 0, otherLength);
1322
				this.extra[1], 0, otherLength);
1386
			copyLimit = otherLength;
1323
			copyLimit = otherLength;
1387
			if (coverageTestFlag && coverageTestId == 42) {
1324
			if (coverageTestFlag && coverageTestId == 36) {
1388
				throw new AssertionFailedException("COVERAGE 42"); //$NON-NLS-1$
1325
				throw new AssertionFailedException("COVERAGE 36"); //$NON-NLS-1$
1389
			}
1326
			}
1390
		}
1327
		}
1391
		int i;
1328
        // MACRO :'b,'es/nullBit\(.\)/extra[\1 + 1][i]/g
1392
		if (otherHasNulls) {
1329
		// manage definite assignment
1393
			for (i = 0; i < mergeLimit; i++) {
1330
		for (i = 0; i < mergeLimit; i++) {
1394
				this.extra[0][i] &= 
1331
	  		this.extra[0][i] &= otherInits.extra[0][i];
1395
					otherInits.extra[0][i];
1332
	  		this.extra[1][i] |= otherInits.extra[1][i];
1396
				this.extra[1][i] |= 
1397
					otherInits.extra[1][i];
1398
				this.extra[2][i] =
1399
					(a1 = this.extra[2][i]) & 
1400
					(b1 = otherInits.extra[2][i]) & (
1401
						(nb4 = ~(b4 = otherInits.extra[5][i])) & 
1402
						((b2 = otherInits.extra[3][i]) & 
1403
								(nb3 = ~(b3 = otherInits.extra[4][i])) & 
1404
								(na3 = ~(a3 = this.extra[4][i])) & 
1405
								((a2 = this.extra[3][i]) & 
1406
									(na4 = ~(a4 = this.extra[5][i])) | a4) |
1407
								(na2 = ~a2) & a3 & na4 & (nb2 = ~b2) & b3 ) |
1408
						b4 & (na3 & nb3 & (na4 & a2 | a4) |
1409
								na2 & a4 & nb2));
1410
				this.extra[3][i] =
1411
					a2 & b2 & ~(a1 ^ b1) & (na3 & nb3 | na4 & nb4) |
1412
					a1 & b1 & (a2 ^ b2) & na3 & nb3 |
1413
					(a1 & na2 & (nb1 = ~b1) & b2 | ~a1 & a2 & b1 & nb2) & na4 & nb4;
1414
				this.extra[4][i] =
1415
					b1 & nb2 & nb4 |
1416
					~a1 & (a3 |
1417
							a2 & na3 & (b1 | nb2)) |
1418
					(a1 | na2) & nb1 & b2 & nb3 |
1419
					nb1 & b3 |
1420
					a1 & na2 & (na4 |
1421
								b1 & nb2 & (a3 | b3));
1422
				this.extra[5][i] =
1423
					a4 | b4;
1424
1425
				// WORK recode if tests succeed
1426
				this.extra[4][i] &= 
1427
					~(a1 & na2 & na3 & a4 & nb1 & b2 & nb3 & nb4
1428
							| ~a1 & a2 & na3 & na4 & b1 & nb2 & nb3 & b4);
1429
		
1430
				thisHasNulls = thisHasNulls ||
1431
					this.extra[5][i] != 0 ||
1432
					this.extra[2][i] != 0 ||
1433
					this.extra[3][i] != 0 ||
1434
					this.extra[4][i] != 0;
1435
				if (coverageTestFlag && coverageTestId == 43) {
1436
					this.extra[5][i] = ~0;
1437
				}
1438
			}
1439
		}
1333
		}
1440
		else {
1334
		for (; i < copyLimit; i++) {
1441
			for (i = 0; i < mergeLimit; i++) {
1335
		  	this.extra[1][i] = otherInits.extra[1][i];
1442
				this.extra[0][i] &= 
1336
		}
1443
					otherInits.extra[0][i];
1337
		for (; i < resetLimit; i++) {
1444
				this.extra[1][i] |= 
1338
		  	this.extra[0][i] = 0;
1445
					otherInits.extra[1][i];
1339
		}
1446
				this.extra[4][i] =
1340
		// refine null bits requirements
1447
					~(~this.extra[2][i] &
1341
		if (!otherHasNulls) {
1448
							~this.extra[3][i] &
1342
		  if (resetLimit < mergeLimit) {
1449
							~this.extra[4][i]) &
1343
			resetLimit = mergeLimit;
1450
					~(this.extra[2][i] & 
1344
		  }
1451
							(this.extra[3][i] | 
1345
		  copyLimit = 0; // no need to carry inexisting nulls
1452
							this.extra[5][i]));
1346
		  mergeLimit = 0;
1453
				this.extra[2][i] = 
1347
		}
1454
				this.extra[3][i] = 0;
1348
		if (!thisHadNulls) {
1455
				thisHasNulls = thisHasNulls ||
1349
		  resetLimit = 0; // no need to reset anything
1456
					this.extra[4][i] != 0 ||
1350
		}
1457
					this.extra[5][i] != 0;
1351
		// compose nulls
1458
				if (coverageTestFlag && coverageTestId == 44) {
1352
		for (i = 0; i < mergeLimit; i++) {
1459
					this.extra[5][i] = ~0;
1353
    		this.extra[1 + 1][i] = (a2 = this.extra[2 + 1][i]) & (a3 = this.extra[3 + 1][i]) 
1460
				}
1354
    							& (a4 = this.extra[4 + 1][i]) & (b1 = otherInits.extra[1 + 1][i]) 
1355
    							& (nb2 = ~(b2 = otherInits.extra[2 + 1][i]))
1356
                  			| (a1 = this.extra[1 + 1][i]) & (b1 & (a3 & a4 & (b3 = otherInits.extra[3 + 1][i]) 
1357
                  													& (b4 = otherInits.extra[4 + 1][i])
1358
                  												| (na2 = ~a2) & nb2 
1359
                  													& ((nb4 = ~b4) | (na4 = ~a4) 
1360
                  															| (na3 = ~a3) & (nb3 = ~b3))
1361
                  												| a2 & b2 & ((na4 | na3) & (nb4	| nb3)))
1362
                  											| na2 & b2 & b3 & b4);
1363
    		this.extra[2 + 1][i] = b2 & (nb3 | (nb1 = ~b1) | a3 & (a4 | (na1 = ~a1)) & nb4)
1364
        			| a2 & (b2 | na4 & b3 & (b4 | nb1) | na3 | na1);
1365
    		this.extra[3 + 1][i] = b3 & (nb2 & b4 | nb1 | a3 & (na4 & nb4 | a4 & b4))
1366
        			| a3 & (na2 & a4 | na1)
1367
        			| (a2 | na1) & b1 & nb2 & nb4
1368
        			| a1 & na2 & na4 & (b2 | nb1);
1369
    		this.extra[4 + 1][i] = na3 & (nb1 & nb3 & b4
1370
              			| b1 & (nb2 & nb3 | a4 & b2 & nb4)
1371
              			| na1 & a4 & (nb3 | b1 & b2))
1372
        			| a3 & a4 & (b3 & b4 | b1 & nb2)
1373
        			| na2 & (nb1 & b4 | b1 & nb3 | na1 & a4) & nb2
1374
        			| a1 & (na3 & (nb3 & b4
1375
                        			| b1 & b2 & b3 & nb4
1376
                        			| na2 & (nb3 | nb2))
1377
                			| na2 & b3 & b4
1378
                			| a2 & (nb1 & b4 | a3 & na4 & b1) & nb3);
1379
			thisHasNulls = thisHasNulls ||
1380
				this.extra[3][i] != 0 ||
1381
				this.extra[4][i] != 0 ||
1382
				this.extra[5][i] != 0 ;
1383
			if (coverageTestFlag && coverageTestId == 37) {
1384
				this.extra[5][i] = ~0;
1461
			}
1385
			}
1462
		}
1386
		}
1463
		for (; i < copyLimit; i++) {
1387
		for (; i < copyLimit; i++) {
1464
			this.extra[1][i] = otherInits.extra[1][i];
1388
    		this.extra[1 + 1][i] = 0;
1465
			this.extra[4][i] =
1389
    		this.extra[2 + 1][i] = (b2 = otherInits.extra[2 + 1][i]) & (nb3 = ~(b3 = otherInits.extra[3 + 1][i]) | (nb1 = ~(b1 = otherInits.extra[1 + 1][i])));
1466
				~(~otherInits.extra[2][i] &
1390
    		this.extra[3 + 1][i] = b3 & ((nb2 = ~b2) & (b4 = otherInits.extra[4 + 1][i]) | nb1) | b1 & nb2 & ~b4;
1467
					~otherInits.extra[3][i] &
1391
    		this.extra[4 + 1][i] = (nb3 | nb2) & nb1 & b4	| b1 & nb3 & nb2;
1468
					~otherInits.extra[4][i]) &
1469
				~(otherInits.extra[2][i] & 
1470
					(otherInits.extra[3][i] |
1471
					otherInits.extra[5][i]));
1472
			this.extra[5][i] = otherInits.extra[5][i];
1473
			thisHasNulls = thisHasNulls ||
1392
			thisHasNulls = thisHasNulls ||
1393
				this.extra[3][i] != 0 ||
1474
				this.extra[4][i] != 0 ||
1394
				this.extra[4][i] != 0 ||
1475
				this.extra[5][i] != 0;
1395
				this.extra[5][i] != 0;
1476
			if (coverageTestFlag && coverageTestId == 45) {
1396
			if (coverageTestFlag && coverageTestId == 38) {
1477
				this.extra[5][i] = ~0;
1397
				this.extra[5][i] = ~0;
1478
			}
1398
			}
1479
		}
1399
		}
1480
		for (; i < resetLimit; i++) {
1400
		for (; i < resetLimit; i++) {
1481
			this.extra[4][i] =
1401
    		a1 = this.extra[1 + 1][i];
1482
				~(~this.extra[2][i] &
1402
      		this.extra[1 + 1][i] = 0;
1483
						~this.extra[3][i] &
1403
      		this.extra[2 + 1][i] = (a2 = this.extra[2 + 1][i]) & (na3 = ~(a3 = this.extra[3 + 1][i]) | (na1 = ~a1));
1484
						~this.extra[4][i]) &
1404
      		this.extra[3 + 1][i] = a3 & ((na2 = ~a2) & (a4 = this.extra[4 + 1][i]) | na1) | a1 & na2 & ~a4;
1485
				~(this.extra[2][i] & 
1405
      		this.extra[4 + 1][i] = (na3 | na2) & na1 & a4	| a1 & na3 & na2;
1486
						(this.extra[3][i] | 
1487
						this.extra[5][i]));
1488
			this.extra[0][i] = 
1489
			this.extra[2][i] = 
1490
			this.extra[3][i] = 0;
1491
			thisHasNulls = thisHasNulls ||
1406
			thisHasNulls = thisHasNulls ||
1407
				this.extra[3][i] != 0 ||
1492
				this.extra[4][i] != 0 ||
1408
				this.extra[4][i] != 0 ||
1493
				this.extra[5][i] != 0;
1409
				this.extra[5][i] != 0;
1494
			if (coverageTestFlag && coverageTestId == 46) {
1410
			if (coverageTestFlag && coverageTestId == 39) {
1495
				this.extra[5][i] = ~0;
1411
				this.extra[5][i] = ~0;
1496
			}
1412
			}
1497
		}
1413
		}
Lines 1577-1595 Link Here
1577
			return "FlowInfo<def: " + this.definiteInits //$NON-NLS-1$
1493
			return "FlowInfo<def: " + this.definiteInits //$NON-NLS-1$
1578
				+", pot: " + this.potentialInits  //$NON-NLS-1$
1494
				+", pot: " + this.potentialInits  //$NON-NLS-1$
1579
				+ ", reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$
1495
				+ ", reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$
1580
				+", nullS1: " + this.nullAssignmentStatusBit1 //$NON-NLS-1$
1496
				+", null: " + this.nullBit1 //$NON-NLS-1$
1581
				+", nullS2: " + this.nullAssignmentStatusBit2 //$NON-NLS-1$
1497
					+ this.nullBit2 + this.nullBit3 + this.nullBit4
1582
				+", nullV1: " + this.nullAssignmentValueBit1 //$NON-NLS-1$
1583
				+", nullV2: " + this.nullAssignmentValueBit2 //$NON-NLS-1$
1584
				+">"; //$NON-NLS-1$
1498
				+">"; //$NON-NLS-1$
1585
		}
1499
		}
1586
		else {
1500
		else {
1587
			String def = "FlowInfo<def:[" + this.definiteInits, //$NON-NLS-1$
1501
			String def = "FlowInfo<def:[" + this.definiteInits, //$NON-NLS-1$
1588
				pot = "], pot:[" + this.potentialInits, //$NON-NLS-1$
1502
				pot = "], pot:[" + this.potentialInits, //$NON-NLS-1$
1589
				nullS1 = ", nullS1:[" + this.nullAssignmentStatusBit1, //$NON-NLS-1$
1503
				nullS = ", null:[" + this.nullBit1 //$NON-NLS-1$
1590
				nullS2 = "], nullS2:[" + this.nullAssignmentStatusBit2, //$NON-NLS-1$
1504
					+ this.nullBit2 + this.nullBit3 + this.nullBit4;
1591
				nullV1 = "], nullV1:[" + this.nullAssignmentValueBit1, //$NON-NLS-1$
1592
				nullV2 = "], nullV2:[" + this.nullAssignmentValueBit2; //$NON-NLS-1$
1593
			int i, ceil;
1505
			int i, ceil;
1594
			for (i = 0, ceil = this.extra[0].length > 3 ? 
1506
			for (i = 0, ceil = this.extra[0].length > 3 ? 
1595
								3 : 
1507
								3 : 
Lines 1597-1618 Link Here
1597
				i < ceil; i++) {
1509
				i < ceil; i++) {
1598
				def += "," + this.extra[0][i]; //$NON-NLS-1$
1510
				def += "," + this.extra[0][i]; //$NON-NLS-1$
1599
				pot += "," + this.extra[1][i]; //$NON-NLS-1$
1511
				pot += "," + this.extra[1][i]; //$NON-NLS-1$
1600
				nullS1 += "," + this.extra[2][i]; //$NON-NLS-1$
1512
				nullS += "," + this.extra[2][i] //$NON-NLS-1$
1601
				nullS2 += "," + this.extra[3][i]; //$NON-NLS-1$
1513
				    + this.extra[3][i] + this.extra[4][i] + this.extra[5][i];
1602
				nullV1 += "," + this.extra[4][i]; //$NON-NLS-1$
1603
				nullV2 += "," + this.extra[5][i]; //$NON-NLS-1$
1604
			}
1514
			}
1605
			if (ceil < this.extra[0].length) {
1515
			if (ceil < this.extra[0].length) {
1606
				def += ",..."; //$NON-NLS-1$
1516
				def += ",..."; //$NON-NLS-1$
1607
				pot += ",..."; //$NON-NLS-1$
1517
				pot += ",..."; //$NON-NLS-1$
1608
				nullS1 += ",..."; //$NON-NLS-1$
1518
				nullS += ",..."; //$NON-NLS-1$
1609
				nullS2 += ",..."; //$NON-NLS-1$
1610
				nullV1 += ",..."; //$NON-NLS-1$
1611
				nullV2 += ",..."; //$NON-NLS-1$
1612
			}
1519
			}
1613
			return def + pot 
1520
			return def + pot 
1614
				+ "], reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$
1521
				+ "], reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$
1615
				+ nullS1 + nullS2 + nullV1 + nullV2
1522
				+ nullS
1616
				+ "]>"; //$NON-NLS-1$
1523
				+ "]>"; //$NON-NLS-1$
1617
		}
1524
		}
1618
	}
1525
	}
Lines 1659-1668 Link Here
1659
		long mask;
1566
		long mask;
1660
		copy.definiteInits = this.definiteInits & (mask = ~((1L << limit)-1));
1567
		copy.definiteInits = this.definiteInits & (mask = ~((1L << limit)-1));
1661
		copy.potentialInits = this.potentialInits & mask;
1568
		copy.potentialInits = this.potentialInits & mask;
1662
		copy.nullAssignmentStatusBit1 = this.nullAssignmentStatusBit1 & mask;
1569
		copy.nullBit1 = this.nullBit1 & mask;
1663
		copy.nullAssignmentStatusBit2 = this.nullAssignmentStatusBit2 & mask;
1570
		copy.nullBit2 = this.nullBit2 & mask;
1664
		copy.nullAssignmentValueBit1 = this.nullAssignmentValueBit1 & mask;
1571
		copy.nullBit3 = this.nullBit3 & mask;
1665
		copy.nullAssignmentValueBit2 = this.nullAssignmentValueBit2 & mask;
1572
		copy.nullBit4 = this.nullBit4 & mask;
1666
	} 
1573
	} 
1667
	// use extra vector
1574
	// use extra vector
1668
	if (this.extra == null) {
1575
	if (this.extra == null) {
(-)compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java (-1 / +10 lines)
Lines 141-146 Link Here
141
141
142
/**
142
/**
143
 * Check status of potential null assignment for a local. Return true if there 
143
 * Check status of potential null assignment for a local. Return true if there 
144
 * is a reasonable expectation that the variable be non null at this point.
145
 * @param local LocalVariableBinding - the binding for the checked local
146
 * @return true if there is a reasonable expectation that local be non null at 
147
 * this point
148
 */
149
public abstract boolean isPotentiallyNonNull(LocalVariableBinding local);
150
	
151
/**
152
 * Check status of potential null assignment for a local. Return true if there 
144
 * is a reasonable expectation that the variable be null at this point. This 
153
 * is a reasonable expectation that the variable be null at this point. This 
145
 * includes the protected null case, so as to augment diagnostics, but does not
154
 * includes the protected null case, so as to augment diagnostics, but does not
146
 * really check that someone deliberately assigned to null on any specific
155
 * really check that someone deliberately assigned to null on any specific
Lines 184-190 Link Here
184
 * @param local the checked local variable
193
 * @param local the checked local variable
185
 */
194
 */
186
abstract public void markAsComparedEqualToNull(LocalVariableBinding local);
195
abstract public void markAsComparedEqualToNull(LocalVariableBinding local);
187
	
196
188
	/**
197
	/**
189
	 * Record a field got definitely assigned.
198
	 * Record a field got definitely assigned.
190
	 */
199
	 */
(-)compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java (+5 lines)
Lines 102-107 Link Here
102
			|| initsWhenFalse.isPotentiallyAssigned(local);
102
			|| initsWhenFalse.isPotentiallyAssigned(local);
103
}
103
}
104
	
104
	
105
public boolean isPotentiallyNonNull(LocalVariableBinding local) {
106
	return initsWhenTrue.isPotentiallyNonNull(local) 
107
		|| initsWhenFalse.isPotentiallyNonNull(local);
108
}	
109
	
105
public boolean isPotentiallyNull(LocalVariableBinding local) {
110
public boolean isPotentiallyNull(LocalVariableBinding local) {
106
	return initsWhenTrue.isPotentiallyNull(local) 
111
	return initsWhenTrue.isPotentiallyNull(local) 
107
		|| initsWhenFalse.isPotentiallyNull(local);
112
		|| initsWhenFalse.isPotentiallyNull(local);
(-)compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java (-4 / +29 lines)
Lines 121-132 Link Here
121
			Expression expression = this.nullReferences[i];
121
			Expression expression = this.nullReferences[i];
122
			// final local variable
122
			// final local variable
123
			switch (this.nullCheckTypes[i]) {
123
			switch (this.nullCheckTypes[i]) {
124
				case CAN_ONLY_NON_NULL :
125
					if (flowInfo.isDefinitelyNonNull(local)) {
126
						this.nullReferences[i] = null;
127
						scope.problemReporter().localVariableCannotBeNull(local, expression);
128
						continue;
129
					}
130
					break;
124
				case CAN_ONLY_NULL_NON_NULL :
131
				case CAN_ONLY_NULL_NON_NULL :
125
					if (flowInfo.isDefinitelyNonNull(local)) {
132
					if (flowInfo.isDefinitelyNonNull(local)) {
126
						this.nullReferences[i] = null;
133
						this.nullReferences[i] = null;
127
						scope.problemReporter().localVariableCannotBeNull(local, expression);
134
						scope.problemReporter().localVariableCannotBeNull(local, expression);
128
						continue;
135
						continue;
129
					}
136
					}
137
					if (flowInfo.isDefinitelyNull(local)) {
138
						this.nullReferences[i] = null;
139
						scope.problemReporter().localVariableCanOnlyBeNull(local, expression);
140
						continue;
141
					}
142
					break;
130
				case CAN_ONLY_NULL :
143
				case CAN_ONLY_NULL :
131
					if (flowInfo.isDefinitelyNull(local)) {
144
					if (flowInfo.isDefinitelyNull(local)) {
132
						this.nullReferences[i] = null;
145
						this.nullReferences[i] = null;
Lines 311-321 Link Here
311
	}
324
	}
312
	switch (checkType) {
325
	switch (checkType) {
313
		case CAN_ONLY_NULL_NON_NULL :
326
		case CAN_ONLY_NULL_NON_NULL :
314
		case CAN_ONLY_NULL:
315
			if (flowInfo.isDefinitelyNonNull(local)) {
327
			if (flowInfo.isDefinitelyNonNull(local)) {
316
				if (checkType == CAN_ONLY_NULL_NON_NULL) {
328
				scope.problemReporter().localVariableCannotBeNull(local, reference);
317
					scope.problemReporter().localVariableCannotBeNull(local, reference);
318
				}
319
				return;
329
				return;
320
			}
330
			}
321
			if (flowInfo.isDefinitelyNull(local)) {
331
			if (flowInfo.isDefinitelyNull(local)) {
Lines 325-330 Link Here
325
			if (flowInfo.isPotentiallyUnknown(local)) {
335
			if (flowInfo.isPotentiallyUnknown(local)) {
326
				return;
336
				return;
327
			}
337
			}
338
			if (flowInfo.isPotentiallyNonNull(local)) {
339
			  recordNullReference(local, reference,CAN_ONLY_NON_NULL);
340
			} else {
341
			  recordNullReference(local, reference, checkType);
342
			}
343
			return;
344
		case CAN_ONLY_NULL:
345
			if (flowInfo.isPotentiallyNonNull(local)
346
					|| flowInfo.isPotentiallyUnknown(local)) {
347
				return;
348
			}
349
			if (flowInfo.isDefinitelyNull(local)) {
350
				scope.problemReporter().localVariableCanOnlyBeNull(local, reference);
351
				return;
352
			}
328
			recordNullReference(local, reference, checkType);
353
			recordNullReference(local, reference, checkType);
329
			return;
354
			return;
330
		case MAY_NULL :
355
		case MAY_NULL :
(-)compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java (-7 / +11 lines)
Lines 36-48 Link Here
36
	
36
	
37
	// preempt marks looping contexts
37
	// preempt marks looping contexts
38
	public final static FlowContext NotContinuableContext = new FlowContext(null, null);
38
	public final static FlowContext NotContinuableContext = new FlowContext(null, null);
39
	public static final int 
40
	  CAN_ONLY_NULL_NON_NULL = 20, 
41
	  	// check against null and non null, with definite values -- comparisons
42
	  CAN_ONLY_NULL = 21,
43
	  	// check against null, with definite values -- assignment to null
44
	  MAY_NULL = 22;
45
			// check against null, with potential values -- NPE guard
46
	public ASTNode associatedNode; 
39
	public ASTNode associatedNode; 
47
		public FlowContext parent;
40
		public FlowContext parent;
48
	public NullInfoRegistry initsOnFinally; 
41
	public NullInfoRegistry initsOnFinally; 
Lines 468-473 Link Here
468
	}
461
	}
469
}
462
}
470
463
464
public static final int 
465
  CAN_ONLY_NULL_NON_NULL = 20, 
466
  	// check against null and non null, with definite values -- comparisons
467
  CAN_ONLY_NULL = 21,
468
  	// check against null, with definite values -- assignment to null
469
  MAY_NULL = 22,
470
	// check against null, with potential values -- NPE guard
471
  CAN_ONLY_NON_NULL = 23;
472
	// subcase of CAN_ONLY_NULL_NON_NULL, in which we know that the local
473
	// may be non null
474
471
/**
475
/**
472
 * Record a null reference for use by deferred checks. Only looping or 
476
 * Record a null reference for use by deferred checks. Only looping or 
473
 * finally contexts really record that information. The context may
477
 * finally contexts really record that information. The context may
(-)compiler/org/eclipse/jdt/internal/compiler/flow/NullInfoRegistry.java (-248 / +219 lines)
Lines 24-38 Link Here
24
 * flow info presented in input of finally blocks.
24
 * flow info presented in input of finally blocks.
25
 */
25
 */
26
public class NullInfoRegistry extends UnconditionalFlowInfo {
26
public class NullInfoRegistry extends UnconditionalFlowInfo {
27
	// encoding of null status at this level:
27
	// significant states at this level:
28
//	public long nullAssignmentStatusBit1;
28
  	// def. non null, def. null, def. unknown, prot. non null
29
	// assigned null
30
//	public long nullAssignmentStatusBit2;
31
	// assigned non null
32
//	public long nullAssignmentValueBit1;
33
	// assigned unknown
34
//	public long nullAssignmentValueBit2;
35
	// message send (no NPE)
36
29
37
// PREMATURE implement coverage and low level tests
30
// PREMATURE implement coverage and low level tests
38
31
Lines 46-83 Link Here
46
 */
39
 */
47
public NullInfoRegistry(UnconditionalFlowInfo upstream) {
40
public NullInfoRegistry(UnconditionalFlowInfo upstream) {
48
	if ((upstream.tagBits & NULL_FLAG_MASK) != 0) {
41
	if ((upstream.tagBits & NULL_FLAG_MASK) != 0) {
49
		long a1, a2, a3, b1nb2, b3, b4;
42
		long u1, u2, u3, u4, nu2, nu3, nu4;
50
		a1 = this.nullAssignmentStatusBit1 = 
43
		this.nullBit2 = (u1 = upstream.nullBit1)
51
			(b1nb2 = upstream.nullAssignmentStatusBit1 
44
			& (u2 = upstream.nullBit2)
52
					&  ~upstream.nullAssignmentStatusBit2)
45
			& (nu3 = ~(u3 = upstream.nullBit3))
53
				& (b3 = upstream.nullAssignmentValueBit1)
46
			& (nu4 = ~(u4 = upstream.nullBit4));
54
				& ~(b4 = upstream.nullAssignmentValueBit2);
47
		this.nullBit3 =	u1 & (nu2 = ~u2) & u3 & nu4;
55
		a2 = this.nullAssignmentStatusBit2 =
48
		this.nullBit4 =	u1 & nu2 &nu3 & u4;
56
			b1nb2 & ~b3 & b4;
49
		if ((this.nullBit2 | this.nullBit3 | this.nullBit4) != 0) {
57
		a3 = this.nullAssignmentValueBit1 =
58
			b1nb2 & b3 & b4;
59
		if ((a1 | a2 | a3) != 0) {
60
			this.tagBits |= NULL_FLAG_MASK;
50
			this.tagBits |= NULL_FLAG_MASK;
61
		}
51
		}
62
		if (upstream.extra != null) {
52
		if (upstream.extra != null) {
63
			this.extra = new long[extraLength][];
53
			this.extra = new long[extraLength][];
64
			int length= upstream.extra[2].length;
54
			int length = upstream.extra[2].length;
65
			for (int i = 2; i < extraLength; i++) {
55
			for (int i = 2; i < extraLength; i++) {
66
				this.extra[i] = new long[length];
56
				this.extra[i] = new long[length];
67
			}
57
			}
68
			for (int i = 0; i < length; i++) {
58
			for (int i = 0; i < length; i++) {
69
				a1 = this.extra[2][i] = 
59
        		this.extra[2 + 1][i] = (u1 = upstream.extra[1 + 1][i])
70
					(b1nb2 = upstream.extra[2][i] 
60
        			& (u2 = upstream.extra[2 + 1][i])
71
							& ~upstream.extra[3][i])
61
        			& (nu3 = ~(u3 = upstream.extra[3 + 1][i]))
72
						& (b3 = upstream.extra[4][i])
62
        			& (nu4 = ~(u4 = upstream.extra[4 + 1][i]));
73
						& ~(b4 = upstream.extra[5][i]);
63
        		this.extra[3 + 1][i] =	u1 & (nu2 = ~u2) & u3 & nu4;
74
				a2 = this.extra[3][i] =
64
        		this.extra[4 + 1][i] =	u1 & nu2 &nu3 & u4;
75
					b1nb2 & ~b3 & b4;
65
        		if ((this.extra[2 + 1][i] | this.extra[3 + 1][i] | this.extra[4 + 1][i]) != 0) {
76
				a3 = this.extra[4][i] =
66
        			this.tagBits |= NULL_FLAG_MASK;
77
					b1nb2 & b3 & b4;
67
        		}
78
				if ((a1 | a2 | a3) != 0) {
79
					this.tagBits |= NULL_FLAG_MASK;
80
				}
81
			}
68
			}
82
		}
69
		}
83
	}
70
	}
Lines 94-103 Link Here
94
		return this;
81
		return this;
95
	}
82
	}
96
	this.tagBits |= NULL_FLAG_MASK;
83
	this.tagBits |= NULL_FLAG_MASK;
97
	this.nullAssignmentStatusBit1 |= other.nullAssignmentStatusBit1;
84
	this.nullBit1 |= other.nullBit1;
98
	this.nullAssignmentStatusBit2 |= other.nullAssignmentStatusBit2;
85
	this.nullBit2 |= other.nullBit2;
99
	this.nullAssignmentValueBit1 |= other.nullAssignmentValueBit1;
86
	this.nullBit3 |= other.nullBit3;
100
	this.nullAssignmentValueBit2 |= other.nullAssignmentValueBit2;
87
	this.nullBit4 |= other.nullBit4;
101
	if (other.extra != null) {
88
	if (other.extra != null) {
102
		if (this.extra == null) {
89
		if (this.extra == null) {
103
			this.extra = new long[extraLength][];
90
			this.extra = new long[extraLength][];
Lines 128-269 Link Here
128
}
115
}
129
116
130
public void markAsComparedEqualToNonNull(LocalVariableBinding local) {
117
public void markAsComparedEqualToNonNull(LocalVariableBinding local) {
131
	this.tagBits |= NULL_FLAG_MASK;
118
	// protected from non-object locals in calling methods
132
	int position;
119
	if (this != DEAD_END) {
133
	// position is zero-based
120
    	this.tagBits |= NULL_FLAG_MASK;
134
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
121
    	int position;
135
		// use bits
122
    	// position is zero-based
136
		this.nullAssignmentValueBit2 |= (1L << position);
123
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
137
	} 
124
    		// set protected non null
138
	else {
125
    		this.nullBit1 |= (1L << position);
139
		// use extra vector
126
    		if (coverageTestFlag && coverageTestId == 290) {
140
		int vectorIndex = (position / BitCacheSize) - 1;
127
    		  	this.nullBit1 = 0;
141
		if (this.extra == null) {
128
    		}
142
			int length = vectorIndex + 1;
129
    	} 
143
			this.extra = new long[extraLength][];
130
    	else {
144
			for (int j = 2 /* do not care about non null info */;
131
    		// use extra vector
145
					j < extraLength; j++) {
132
			int vectorIndex = (position / BitCacheSize) - 1;
146
				this.extra[j] = new long[length];
133
			if (this.extra == null) {
147
			}
134
				int length = vectorIndex + 1;
148
		}
135
				this.extra = new long[extraLength][];
149
		else {
136
				for (int j = 2; j < extraLength; j++) {
150
			int oldLength;
137
					this.extra[j] = new long[length];
151
			if (vectorIndex >= (oldLength = this.extra[2].length)) {
138
				}
152
				int newLength = vectorIndex + 1;
139
			} 
153
				for (int j = 2 /* do not care about non null info */; 
140
			else {
154
						j < extraLength; j++) {
141
				int oldLength; // might need to grow the arrays
155
					System.arraycopy(this.extra[j], 0, 
142
				if (vectorIndex >= (oldLength = this.extra[2].length)) {
156
						(this.extra[j] = new long[newLength]), 0, 
143
					for (int j = 2; j < extraLength; j++) {
157
						oldLength);
144
						System.arraycopy(this.extra[j], 0, 
145
							(this.extra[j] = new long[vectorIndex + 1]), 0, 
146
							oldLength);
147
					}
158
				}
148
				}
159
			}
149
			}
160
		}
150
    		this.extra[2][vectorIndex] |= (1L << (position % BitCacheSize));
161
		this.extra[5][vectorIndex] |= (1L << (position % BitCacheSize));
151
    		if (coverageTestFlag && coverageTestId == 300) {
152
    		  	this.extra[5][vectorIndex] = ~0;
153
    		}
154
    	}
162
	}
155
	}
163
}
156
}
164
157
165
public void markAsDefinitelyNonNull(LocalVariableBinding local) {
158
public void markAsDefinitelyNonNull(LocalVariableBinding local) {
166
	this.tagBits |= NULL_FLAG_MASK;
159
	// protected from non-object locals in calling methods
167
	int position;
160
	if (this != DEAD_END) {
168
	// position is zero-based
161
    	this.tagBits |= NULL_FLAG_MASK;
169
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
162
    	int position;
170
		// use bits
163
    	// position is zero-based
171
		this.nullAssignmentStatusBit2 |= (1L << position);
164
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
172
	} 
165
    		// set assigned non null
173
	else {
166
    		this.nullBit3 |= (1L << position);
174
		// use extra vector
167
    		if (coverageTestFlag && coverageTestId == 290) {
175
		int vectorIndex = (position / BitCacheSize) - 1;
168
    		  	this.nullBit1 = 0;
176
		if (this.extra == null) {
169
    		}
177
			int length = vectorIndex + 1;
170
    	} 
178
			this.extra = new long[extraLength][];
171
    	else {
179
			for (int j = 2 /* do not care about non null info */; 
172
    		// use extra vector
180
					j < extraLength; j++) {
173
			int vectorIndex = (position / BitCacheSize) - 1;
181
				this.extra[j] = new long[length];
174
			if (this.extra == null) {
182
			}
175
				int length = vectorIndex + 1;
183
		}
176
				this.extra = new long[extraLength][];
184
		else {
177
				for (int j = 2; j < extraLength; j++) {
185
			int oldLength;
178
					this.extra[j] = new long[length];
186
			if (vectorIndex >= (oldLength = this.extra[2].length)) {
179
				}
187
				int newLength = vectorIndex + 1;
180
			} 
188
				for (int j = 2 /* do not care about non null info */; 
181
			else {
189
						j < extraLength; j++) {
182
				int oldLength; // might need to grow the arrays
190
					System.arraycopy(this.extra[j], 0, 
183
				if (vectorIndex >= (oldLength = this.extra[2].length)) {
191
						(this.extra[j] = new long[newLength]), 0, 
184
					for (int j = 2; j < extraLength; j++) {
192
						oldLength);
185
						System.arraycopy(this.extra[j], 0, 
186
							(this.extra[j] = new long[vectorIndex + 1]), 0, 
187
							oldLength);
188
					}
193
				}
189
				}
194
			}
190
			}
195
		}
191
    		this.extra[4][vectorIndex] |= (1L << (position % BitCacheSize));
196
		this.extra[3][vectorIndex] |= (1L << (position % BitCacheSize));
192
    		if (coverageTestFlag && coverageTestId == 300) {
193
    		  	this.extra[5][vectorIndex] = ~0;
194
    		}
195
    	}
197
	}
196
	}
198
}
197
}
199
198
// PREMATURE consider ignoring extra 0 to 2 included - means a1 should not be used either
199
// PREMATURE project protected non null onto something else
200
public void markAsDefinitelyNull(LocalVariableBinding local) {
200
public void markAsDefinitelyNull(LocalVariableBinding local) {
201
	this.tagBits |= NULL_FLAG_MASK;
201
	// protected from non-object locals in calling methods
202
	int position;
202
	if (this != DEAD_END) {
203
	// position is zero-based
203
    	this.tagBits |= NULL_FLAG_MASK;
204
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
204
    	int position;
205
		// use bits
205
    	// position is zero-based
206
		this.nullAssignmentStatusBit1 |= (1L << position);
206
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
207
	} 
207
    		// set assigned null
208
	else {
208
    		this.nullBit2 |= (1L << position);
209
		// use extra vector
209
    		if (coverageTestFlag && coverageTestId == 290) {
210
		int vectorIndex = (position / BitCacheSize) - 1;
210
    		  	this.nullBit1 = 0;
211
		if (this.extra == null) {
211
    		}
212
			int length = vectorIndex + 1;
212
    	} 
213
			this.extra = new long[extraLength][];
213
    	else {
214
			for (int j = 2 /* do not care about non null info */;
214
    		// use extra vector
215
					j < extraLength; j++) {
215
			int vectorIndex = (position / BitCacheSize) - 1;
216
				this.extra[j] = new long[length];
216
			if (this.extra == null) {
217
			}
217
				int length = vectorIndex + 1;
218
		}
218
				this.extra = new long[extraLength][];
219
		else {
219
				for (int j = 2; j < extraLength; j++) {
220
			int oldLength;
220
					this.extra[j] = new long[length];
221
			if (vectorIndex >= (oldLength = this.extra[2].length)) {
221
				}
222
				int newLength = vectorIndex + 1;
222
			} 
223
				for (int j = 2 /* do not care about non null info */; 
223
			else {
224
						j < extraLength; j++) {
224
				int oldLength; // might need to grow the arrays
225
					System.arraycopy(this.extra[j], 0, 
225
				if (vectorIndex >= (oldLength = this.extra[2].length)) {
226
						(this.extra[j] = new long[newLength]), 0, 
226
					for (int j = 2; j < extraLength; j++) {
227
						oldLength);
227
						System.arraycopy(this.extra[j], 0, 
228
							(this.extra[j] = new long[vectorIndex + 1]), 0, 
229
							oldLength);
230
					}
228
				}
231
				}
229
			}
232
			}
230
		}
233
    		this.extra[3][vectorIndex] |= (1L << (position % BitCacheSize));
231
		this.extra[2][vectorIndex] |= (1L << (position % BitCacheSize));
234
    		if (coverageTestFlag && coverageTestId == 300) {
235
    		  	this.extra[5][vectorIndex] = ~0;
236
    		}
237
    	}
232
	}
238
	}
233
}
239
}
234
240
235
public void markAsDefinitelyUnknown(LocalVariableBinding local) {
241
public void markAsDefinitelyUnknown(LocalVariableBinding local) {
236
	this.tagBits |= NULL_FLAG_MASK;
242
	// protected from non-object locals in calling methods
237
	int position;
243
	if (this != DEAD_END) {
238
	// position is zero-based
244
    	this.tagBits |= NULL_FLAG_MASK;
239
	if ((position = local.id + this.maxFieldCount) < BitCacheSize) {
245
    	int position;
240
		// use bits
246
    	// position is zero-based
241
		this.nullAssignmentValueBit1 |= (1L << position);
247
    	if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits
242
	} 
248
    		// set assigned unknown
243
	else {
249
    		this.nullBit4 |= (1L << position);
244
		// use extra vector
250
    		if (coverageTestFlag && coverageTestId == 290) {
245
		int vectorIndex = (position / BitCacheSize) - 1;
251
    		  	this.nullBit1 = 0;
246
		if (this.extra == null) {
252
    		}
247
			int length = vectorIndex + 1;
253
    	} 
248
			this.extra = new long[extraLength][];
254
    	else {
249
			for (int j = 2 /* do not care about non null info */;
255
    		// use extra vector
250
					j < extraLength; j++) {
256
			int vectorIndex = (position / BitCacheSize) - 1;
251
				this.extra[j] = new long[length];
257
			if (this.extra == null) {
252
			}
258
				int length = vectorIndex + 1;
253
		}
259
				this.extra = new long[extraLength][];
254
		else {
260
				for (int j = 2; j < extraLength; j++) {
255
			int oldLength;
261
					this.extra[j] = new long[length];
256
			if (vectorIndex >= (oldLength = this.extra[2].length)) {
262
				}
257
				int newLength = vectorIndex + 1;
263
			} 
258
				for (int j = 2 /* do not care about non null info */; 
264
			else {
259
						j < extraLength; j++) {
265
				int oldLength; // might need to grow the arrays
260
					System.arraycopy(this.extra[j], 0, 
266
				if (vectorIndex >= (oldLength = this.extra[2].length)) {
261
						(this.extra[j] = new long[newLength]), 0, 
267
					for (int j = 2; j < extraLength; j++) {
262
						oldLength);
268
						System.arraycopy(this.extra[j], 0, 
269
							(this.extra[j] = new long[vectorIndex + 1]), 0, 
270
							oldLength);
271
					}
263
				}
272
				}
264
			}
273
			}
265
		}
274
    		this.extra[5][vectorIndex] |= (1L << (position % BitCacheSize));
266
		this.extra[4][vectorIndex] |= (1L << (position % BitCacheSize));
275
    		if (coverageTestFlag && coverageTestId == 300) {
276
    		  	this.extra[5][vectorIndex] = ~0;
277
    		}
278
    	}
267
	}
279
	}
268
}
280
}
269
281
Lines 281-338 Link Here
281
	if ((this.tagBits & NULL_FLAG_MASK) == 0) {
293
	if ((this.tagBits & NULL_FLAG_MASK) == 0) {
282
		return flowInfo.unconditionalInits();
294
		return flowInfo.unconditionalInits();
283
	}
295
	}
284
//	// Reference implementation
296
	long m, m1, nm1, m2, nm2, m3, a2, a3, a4, s1, s2, ns2, s3, ns3, s4, ns4;
285
//	UnconditionalFlowInfo source = flowInfo.unconditionalCopy();
286
//	long mask;
287
//	// clear uncompatible protections
288
//	mask = source.nullAssignmentStatusBit1 & source.nullAssignmentStatusBit2
289
//			// prot. non null
290
//		& (this.nullAssignmentStatusBit1 | this.nullAssignmentValueBit1);
291
//			// null or unknown
292
//	source.nullAssignmentStatusBit1 &= ~mask;
293
//	source.nullAssignmentStatusBit2 &= ~mask;
294
//	mask = ~source.nullAssignmentStatusBit1 & source.nullAssignmentStatusBit2
295
//			// prot. null
296
//		& (this.nullAssignmentStatusBit2 | this.nullAssignmentValueBit1
297
//				| this.nullAssignmentValueBit2);
298
//			// non null or unknown
299
//	source.nullAssignmentStatusBit2 &= ~mask;
300
//	// clear uncompatible assignments
301
//	mask = source.nullAssignmentStatusBit1 & ~source.nullAssignmentStatusBit2
302
//		& (source.nullAssignmentValueBit1 & ~source.nullAssignmentValueBit2 
303
//				& (this.nullAssignmentStatusBit2 | this.nullAssignmentValueBit1
304
//						| this.nullAssignmentValueBit2)
305
//			| ~source.nullAssignmentValueBit1 & source.nullAssignmentValueBit2
306
//				& (this.nullAssignmentStatusBit1 | this.nullAssignmentValueBit1)
307
//			| source.nullAssignmentValueBit1 & source.nullAssignmentValueBit2
308
//				& (this.nullAssignmentStatusBit1));
309
//	source.nullAssignmentStatusBit1 &= ~mask;
310
	long m1, m2, m3, a1, a2, a3, a4, s1, s2, s3, s4;
311
	boolean newCopy = false;
297
	boolean newCopy = false;
312
	UnconditionalFlowInfo source = flowInfo.unconditionalInits();
298
	UnconditionalFlowInfo source = flowInfo.unconditionalInits();
313
	// clear uncompatible protections
299
	// clear incompatible protections
314
	m1 = (s1 = source.nullAssignmentStatusBit1) 
300
	m1 = (s1 = source.nullBit1) & (s3 = source.nullBit3) 
315
			& (s2 = source.nullAssignmentStatusBit2)
301
				& (s4 = source.nullBit4)
316
			// prot. non null
302
			// prot. non null
317
		& ((a1 = this.nullAssignmentStatusBit1)
303
		& ((a2 = this.nullBit2) | (a4 = this.nullBit4));
318
				| (a3 = this.nullAssignmentValueBit1));
319
			// null or unknown
304
			// null or unknown
320
	m2 = ~s1 & s2
305
	m2 = s1 & (s2 = this.nullBit2) & (s3 ^ s4)
321
			// prot. null
306
			// prot. null
322
		& ((a2 = this.nullAssignmentStatusBit2) | a3
307
		& ((a3 = this.nullBit3) | a4);
323
				| (a4 = this.nullAssignmentValueBit2));
324
			// non null or unknown
308
			// non null or unknown
325
	// clear uncompatible assignments
309
	// clear incompatible assignments
326
	m3 = s1 & ~s2
310
	// PREMATURE check effect of protected non null (no NPE on call)
327
		& ((s3 = source.nullAssignmentValueBit1) 
311
	// TODO (maxime) code extensive implementation tests
328
				& ~(s4 = source.nullAssignmentValueBit2) 
312
	m3 = s1	& (s2 & (ns3 = ~s3) & (ns4 = ~s4) & (a3 | a4)
329
				& (a2 | a3 | a4)
313
				| (ns2 = ~s2) & s3 & ns4 & (a2 | a4)
330
					| s4 & (~s3 & a3 | a1));
314
				| ns2 & ns3 & s4 & (a2 | a3)); 
331
	if ((m1 | m2 | m3) != 0) {
315
	if ((m = (m1 | m2 | m3)) != 0) {
332
		newCopy = true;
316
		newCopy = true;
333
		source = source.unconditionalCopy();
317
		source = source.unconditionalCopy();
334
		source.nullAssignmentStatusBit1 &= ~(m1 | m3);
318
		source.nullBit1 &= ~m;
335
		source.nullAssignmentStatusBit2 &= ~(m1 | m2);
319
		source.nullBit2 &= (nm1 = ~m1) & ((nm2 = ~m2) | a4);
320
		source.nullBit3 &= (nm1 | a2) & nm2;
321
		source.nullBit4 &= nm1 & nm2;
336
	}
322
	}
337
	if (this.extra != null && source.extra != null) {
323
	if (this.extra != null && source.extra != null) {
338
		int length = this.extra[2].length, sourceLength = source.extra[0].length;
324
		int length = this.extra[2].length, sourceLength = source.extra[0].length;
Lines 340-368 Link Here
340
			length = sourceLength;
326
			length = sourceLength;
341
		}
327
		}
342
		for (int i = 0; i < length; i++) {
328
		for (int i = 0; i < length; i++) {
343
			// clear uncompatible protections
329
        	m1 = (s1 = source.extra[1 + 1][i]) & (s3 = source.extra[3 + 1][i]) 
344
			m1 = (s1 = source.extra[2][i]) & (s2 = source.extra[3][i])
330
        				& (s4 = source.extra[4 + 1][i])
345
					// prot. non null
331
        		& ((a2 = this.extra[2 + 1][i]) | (a4 = this.extra[4 + 1][i]));
346
				& ((a1 = this.extra[2][i]) | (a3 = this.extra[4][i]));
332
        	m2 = s1 & (s2 = this.extra[2 + 1][i]) & (s3 ^ s4)
347
					// null or unknown
333
        		& ((a3 = this.extra[3 + 1][i]) | a4);
348
			m2 = ~s1 & s2
334
        	m3 = s1	& (s2 & (ns3 = ~s3) & (ns4 = ~s4) & (a3 | a4)
349
					// prot. null
335
        				| (ns2 = ~s2) & s3 & ns4 & (a2 | a4)
350
				& ((a2 = this.extra[3][i]) | a3
336
        				| ns2 & ns3 & s4 & (a2 | a3)); 
351
						| (a4 = this.extra[5][i]));
337
        	if ((m = (m1 | m2 | m3)) != 0) {
352
					// non null or unknown
338
        	  	if (! newCopy) {
353
			// clear uncompatible assignments
339
            		newCopy = true;
354
			m3 = s1 & ~s2
340
            		source = source.unconditionalCopy();
355
				& ((s3 = source.extra[4][i]) & ~(s4 = source.extra[5][i]) 
341
        	  	}
356
						& (a2 | a3 | a4)
342
        		source.extra[1 + 1][i] &= ~m;
357
					| s4 & (~s3 & a3 | a1));
343
        		source.extra[2 + 1][i] &= (nm1 = ~m1) & ((nm2 = ~m2) | a4);
358
			if ((m1 | m2 | m3) != 0) {
344
        		source.extra[3 + 1][i] &= (nm1 | a2) & nm2;
359
				if (!newCopy) {
345
        		source.extra[4 + 1][i] &= nm1 & nm2;
360
					newCopy = true;
346
        	}
361
					source = source.unconditionalCopy();
362
				}
363
				source.extra[2][i] &= ~(m1 | m3);
364
				source.extra[3][i] &= ~(m1 | m2);
365
			}
366
		}
347
		}
367
	}
348
	}
368
	return source;
349
	return source;
Lines 370-404 Link Here
370
351
371
public String toString(){
352
public String toString(){
372
	if (this.extra == null) {
353
	if (this.extra == null) {
373
		return "NullInfoRegistry<nullS1: " + this.nullAssignmentStatusBit1 //$NON-NLS-1$
354
		return "NullInfoRegistry<" + this.nullBit1 //$NON-NLS-1$
374
			+", nullS2: " + this.nullAssignmentStatusBit2 //$NON-NLS-1$
355
			+ this.nullBit2 + this.nullBit3 + this.nullBit4
375
			+", nullV1: " + this.nullAssignmentValueBit1 //$NON-NLS-1$
356
			+ ">"; //$NON-NLS-1$
376
			+", nullV2: " + this.nullAssignmentValueBit2 //$NON-NLS-1$
377
			+">"; //$NON-NLS-1$
378
	}
357
	}
379
	else {
358
	else {
380
		String nullS1 = "NullInfoRegistry<nullS1:[" + this.nullAssignmentStatusBit1, //$NON-NLS-1$
359
		String nullS = "NullInfoRegistry<[" + this.nullBit1 //$NON-NLS-1$
381
			nullS2 = "], nullS2:[" + this.nullAssignmentStatusBit2, //$NON-NLS-1$
360
			+ this.nullBit2 + this.nullBit3 + this.nullBit4;
382
			nullV1 = "], nullV1:[" + this.nullAssignmentValueBit1, //$NON-NLS-1$
361
			int i, ceil;
383
			nullV2 = "], nullV2:[" + this.nullAssignmentValueBit2; //$NON-NLS-1$
362
			for (i = 0, ceil = this.extra[0].length > 3 ? 
384
		int i, ceil;
363
								3 : 
385
		for (i = 0, ceil = this.extra[0].length > 3 ? 
364
								this.extra[0].length;
386
							3 : 
365
				i < ceil; i++) {
387
							this.extra[0].length;
366
				nullS += "," + this.extra[2][i] //$NON-NLS-1$
388
			i < ceil; i++) {
367
				    + this.extra[3][i] + this.extra[4][i] + this.extra[5][i];
389
			nullS1 += "," + this.extra[2][i]; //$NON-NLS-1$
368
			}
390
			nullS2 += "," + this.extra[3][i]; //$NON-NLS-1$
369
			if (ceil < this.extra[0].length) {
391
			nullV1 += "," + this.extra[4][i]; //$NON-NLS-1$
370
				nullS += ",..."; //$NON-NLS-1$
392
			nullV2 += "," + this.extra[5][i]; //$NON-NLS-1$
371
			}
393
		}
372
			return nullS + "]>"; //$NON-NLS-1$
394
		if (ceil < this.extra[0].length) {
395
			nullS1 += ",..."; //$NON-NLS-1$
396
			nullS2 += ",..."; //$NON-NLS-1$
397
			nullV1 += ",..."; //$NON-NLS-1$
398
			nullV2 += ",..."; //$NON-NLS-1$
399
		}
400
		return nullS1 + nullS2 + nullV1 + nullV2
401
			+ "]>"; //$NON-NLS-1$
402
	}
373
	}
403
}
374
}
404
}
375
}
(-)compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java (-1 / +2 lines)
Lines 113-119 Link Here
113
		}
113
		}
114
		if (result instanceof UnconditionalFlowInfo && 
114
		if (result instanceof UnconditionalFlowInfo && 
115
				(result.tagBits & FlowInfo.UNREACHABLE) == 0) { // the flow info is flat
115
				(result.tagBits & FlowInfo.UNREACHABLE) == 0) { // the flow info is flat
116
			result = FlowInfo.conditional(result, result.copy());
116
			result = FlowInfo.conditional(result.copy(), result.copy());
117
			// TODO (maxime) check, reintroduced copy
117
		}
118
		}
118
	  checkNullComparison(currentScope, flowContext, result, result.initsWhenTrue(), result.initsWhenFalse());
119
	  checkNullComparison(currentScope, flowContext, result, result.initsWhenTrue(), result.initsWhenFalse());
119
	  return result;
120
	  return result;
(-)compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java (-3 / +3 lines)
Lines 41-50 Link Here
41
			this.expression, FlowContext.CAN_ONLY_NULL, flowInfo);
41
			this.expression, FlowContext.CAN_ONLY_NULL, flowInfo);
42
		flowInfo = expression.analyseCode(currentScope, flowContext, flowInfo).
42
		flowInfo = expression.analyseCode(currentScope, flowContext, flowInfo).
43
			unconditionalInits();
43
			unconditionalInits();
44
		FlowInfo initsWhenFalse = flowInfo.copy();
44
		FlowInfo initsWhenTrue = flowInfo.copy();
45
		flowInfo.markAsComparedEqualToNonNull(local);
45
		initsWhenTrue.markAsComparedEqualToNonNull(local);
46
		// no impact upon enclosing try context
46
		// no impact upon enclosing try context
47
		return FlowInfo.conditional(flowInfo, initsWhenFalse);
47
		return FlowInfo.conditional(initsWhenTrue, flowInfo.copy());
48
	}
48
	}
49
	return expression.analyseCode(currentScope, flowContext, flowInfo).
49
	return expression.analyseCode(currentScope, flowContext, flowInfo).
50
			unconditionalInits();
50
			unconditionalInits();
(-).settings/org.eclipse.jdt.core.prefs (-1 / +1 lines)
Lines 1-4 Link Here
1
#Fri Feb 17 16:48:15 CET 2006
1
#Mon Mar 20 16:28:55 CET 2006
2
eclipse.preferences.version=1
2
eclipse.preferences.version=1
3
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
3
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
4
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
4
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
(-).settings/org.eclipse.jdt.core.prefs (-1 / +247 lines)
Lines 1-4 Link Here
1
#Fri Sep 30 16:39:41 CEST 2005
1
#Thu Feb 23 14:36:02 CET 2006
2
eclipse.preferences.version=1
2
eclipse.preferences.version=1
3
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
3
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
4
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
4
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
Lines 66-70 Link Here
66
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
66
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
67
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
67
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
68
org.eclipse.jdt.core.compiler.source=1.3
68
org.eclipse.jdt.core.compiler.source=1.3
69
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
70
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
71
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
72
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
73
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
74
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
75
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
76
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
77
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
78
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
79
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
80
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
81
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
82
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
83
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
84
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
85
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
86
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
87
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
88
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
89
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
90
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
91
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
92
org.eclipse.jdt.core.formatter.blank_lines_before_field=1
93
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
94
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
95
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
96
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
97
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
98
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
99
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
100
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
101
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
102
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
103
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
104
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
105
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
106
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
107
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
108
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
109
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
110
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
111
org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false
112
org.eclipse.jdt.core.formatter.comment.format_comments=true
113
org.eclipse.jdt.core.formatter.comment.format_header=false
114
org.eclipse.jdt.core.formatter.comment.format_html=true
115
org.eclipse.jdt.core.formatter.comment.format_source_code=true
116
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
117
org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
118
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
119
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
120
org.eclipse.jdt.core.formatter.comment.line_length=80
121
org.eclipse.jdt.core.formatter.compact_else_if=true
122
org.eclipse.jdt.core.formatter.continuation_indentation=2
123
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
124
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
125
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
126
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
127
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
128
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
129
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
130
org.eclipse.jdt.core.formatter.indent_empty_lines=false
131
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
132
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
133
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
134
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
135
org.eclipse.jdt.core.formatter.indentation.size=4
136
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
137
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
138
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
139
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
140
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
141
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
142
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
143
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
144
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
145
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
146
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
147
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
148
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
149
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
150
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
151
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
152
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
153
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
154
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
155
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
156
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
157
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
158
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
159
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
160
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
161
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
162
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
163
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
164
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
165
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
166
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
167
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
168
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
169
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
170
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
171
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
172
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
173
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
174
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
175
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
176
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
177
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
178
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
179
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
180
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
181
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
182
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
183
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
184
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
185
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
186
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
187
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
188
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
189
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
190
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
191
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
192
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
193
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
194
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
195
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
196
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
197
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
198
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
199
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
200
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
201
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
202
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
203
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
204
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
205
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
206
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
207
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
208
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
209
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
210
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
211
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
212
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
213
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
214
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
215
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
216
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
217
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
218
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
219
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
220
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
221
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
222
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
223
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
224
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
225
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
226
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
227
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
228
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
229
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
230
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
231
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
232
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
233
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
234
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
235
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
236
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
237
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
238
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
239
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
240
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
241
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
242
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
243
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
244
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
245
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
246
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
247
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
248
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
249
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
250
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
251
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
252
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
253
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
254
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
255
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
256
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
257
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
258
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
259
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
260
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
261
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
262
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
263
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
264
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
265
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
266
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
267
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
268
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
269
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
270
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
271
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
272
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
273
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
274
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
275
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
276
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
277
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
278
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
279
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
280
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
281
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
282
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
283
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
284
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
285
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
286
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
287
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
288
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
289
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
290
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
291
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
292
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
293
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
294
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
295
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
296
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
297
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
298
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
299
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
300
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
301
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
302
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
303
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
304
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
305
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
306
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
307
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
308
org.eclipse.jdt.core.formatter.lineSplit=80
309
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
310
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
311
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
312
org.eclipse.jdt.core.formatter.tabulation.char=tab
313
org.eclipse.jdt.core.formatter.tabulation.size=4
314
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
69
org.eclipse.jdt.core.incompatibleJDKLevel=ignore
315
org.eclipse.jdt.core.incompatibleJDKLevel=ignore
70
org.eclipse.jdt.core.incompleteClasspath=error
316
org.eclipse.jdt.core.incompleteClasspath=error
(-)src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java (-3 / +5 lines)
Lines 832-838 Link Here
832
					  // start with the current directory which contains the source files
832
					  // start with the current directory which contains the source files
833
					Process compileProcess = Runtime.getRuntime().exec(
833
					Process compileProcess = Runtime.getRuntime().exec(
834
						cmdLineHeader.toString() + " -version", null, null);
834
						cmdLineHeader.toString() + " -version", null, null);
835
	        Logger versionLogger = new Logger(compileProcess.getErrorStream(), ""); // WORK            
835
	        Logger versionLogger = new Logger(compileProcess.getErrorStream(), "");
836
	        // PREMATURE implement consistent error policy
836
	        versionLogger.start();
837
	        versionLogger.start();
837
	        compileProcess.waitFor();
838
	        compileProcess.waitFor();
838
					versionLogger.join(); // make sure we get the whole output
839
					versionLogger.join(); // make sure we get the whole output
Lines 1148-1155 Link Here
1148
						javaCmdLine.append(' ').append(testFiles[0].substring(0, testFiles[0].indexOf('.')));
1149
						javaCmdLine.append(' ').append(testFiles[0].substring(0, testFiles[0].indexOf('.')));
1149
							// assume executable class is name of first test file - PREMATURE check if this is also the case in other test fwk classes
1150
							// assume executable class is name of first test file - PREMATURE check if this is also the case in other test fwk classes
1150
						execProcess = Runtime.getRuntime().exec(javaCmdLine.toString(), null, this.outputTestDirectoryPath.toFile());
1151
						execProcess = Runtime.getRuntime().exec(javaCmdLine.toString(), null, this.outputTestDirectoryPath.toFile());
1151
						Logger logger = new Logger(execProcess.getInputStream(), ""); // WORK
1152
						Logger logger = new Logger(execProcess.getInputStream(), "");
1152
						logger.start();
1153
						// PREMATURE implement consistent error policy
1154
	     				logger.start();
1153
						exitValue = execProcess.waitFor();
1155
						exitValue = execProcess.waitFor();
1154
						logger.join(); // make sure we get the whole output
1156
						logger.join(); // make sure we get the whole output
1155
						String javaOutput = logger.buffer.toString().trim();
1157
						String javaOutput = logger.buffer.toString().trim();
(-)src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java (-2222 / +297 lines)
Lines 11-26 Link Here
11
package org.eclipse.jdt.core.tests.compiler.regression;
11
package org.eclipse.jdt.core.tests.compiler.regression;
12
12
13
import java.util.Map;
13
import java.util.Map;
14
15
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
16
import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo;
17
import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo.AssertionFailedException;
18
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
14
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
19
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
20
21
import junit.framework.AssertionFailedError;
22
import junit.framework.Test;
15
import junit.framework.Test;
23
16
17
/* See also NullReferenceImplTests for low level, implementation dependent 
18
 * tests. */
24
public class NullReferenceTest extends AbstractRegressionTest {
19
public class NullReferenceTest extends AbstractRegressionTest {
25
20
26
public NullReferenceTest(String name) { 
21
public NullReferenceTest(String name) { 
Lines 1730-1744 Link Here
1730
}
1725
}
1731
1726
1732
// null analysis - if/else
1727
// null analysis - if/else
1733
// PMT: exactly the case we talked about; what happens is that the first
1734
// if shade doubts upon o; what we could do is to avoid marking in case
1735
// of error? not sure this is appropriate though, because of inner code
1736
// into the if itself; I believe I somewhat did that on purpose: the latest
1737
// wins; completed with o.toString()...
1738
// basically, the choice is about what we should do in case of error:
1739
// neglect the effect of the error, or propagate this effect; the second
1740
//  tends to produce less repeated errors (I believe) than the first...
1741
// PREMATURE could refine adding a null-dependent reachable mark... not urgent
1742
public void test0312_if_else() {
1728
public void test0312_if_else() {
1743
	this.runNegativeTest(
1729
	this.runNegativeTest(
1744
		new String[] {
1730
		new String[] {
Lines 1748-1755 Link Here
1748
			"  void foo() {\n" + 
1734
			"  void foo() {\n" + 
1749
			"    Object o = new Object();\n" + 
1735
			"    Object o = new Object();\n" + 
1750
			"    if (o == null) { /* */ }\n" + // complain 
1736
			"    if (o == null) { /* */ }\n" + // complain 
1751
			"    if (o != null) { /* */ }\n" + // quiet
1737
			"    if (o != null) { /* */ }\n" +
1752
			"    o.toString();\n" + // complain
1738
			"    o.toString();\n" +
1753
			"  }\n" + 
1739
			"  }\n" + 
1754
			"}\n"},
1740
			"}\n"},
1755
		"----------\n" + 
1741
		"----------\n" + 
Lines 2376-2381 Link Here
2376
		"");
2362
		"");
2377
}
2363
}
2378
2364
2365
// null analysis - if/else nested with unknown protection: unknown cannot protect
2366
public void test0339_if_else_nested() {
2367
	this.runNegativeTest(
2368
		new String[] {
2369
			"X.java",
2370
			"public class X {\n" + 
2371
			"  void foo(Object o, boolean b) {\n" + 
2372
			"    if (o == null || b) {\n" + 
2373
			"      if (bar() == o) {\n" + 
2374
			"        o.toString();\n" + 
2375
			"      }\n" + 
2376
			"    }\n" + 
2377
			"  }\n" + 
2378
			"  Object bar() {\n" + 
2379
			"    return new Object();\n" + 
2380
			"  }\n" + 
2381
			"}"},
2382
		"----------\n" + 
2383
		"1. ERROR in X.java (at line 5)\n" + 
2384
		"	o.toString();\n" + 
2385
		"	^\n" + 
2386
		"The variable o may be null\n" + 
2387
		"----------\n");
2388
}
2389
2390
// null analysis - if/else nested
2391
public void test0340_if_else_nested() {
2392
	this.runNegativeTest(
2393
		new String[] {
2394
			"X.java",
2395
			"public class X {\n" + 
2396
			"  void foo(Object o) {\n" + 
2397
			"    if (o == null) {\n" + 
2398
			"      if (bar() == o) {\n" + 
2399
			"        o.toString();\n" + 
2400
			"      }\n" + 
2401
			"    }\n" + 
2402
			"  }\n" + 
2403
			"  Object bar() {\n" + 
2404
			"    return new Object();\n" + 
2405
			"  }\n" + 
2406
			"}"},
2407
		"----------\n" + 
2408
		"1. ERROR in X.java (at line 5)\n" + 
2409
		"	o.toString();\n" + 
2410
		"	^\n" + 
2411
		"The variable o can only be null; it was either set to null or checked for null when last used\n" + 
2412
		"----------\n");
2413
}
2414
2415
// null analysis - if/else nested
2416
public void test0341_if_else_nested() {
2417
	this.runNegativeTest(
2418
		new String[] {
2419
			"X.java",
2420
			"public class X {\n" + 
2421
			"  void foo(Object o1, Object o2, boolean b) {\n" + 
2422
			"    if (o1 == null || b) {\n" + 
2423
			"      if (o1 == o2) {\n" + 
2424
			"        o1.toString();\n" + 
2425
			"      }\n" + 
2426
			"    }\n" + 
2427
			"  }\n" + 
2428
			"}"},
2429
		"----------\n" + 
2430
		"1. ERROR in X.java (at line 5)\n" + 
2431
		"	o1.toString();\n" + 
2432
		"	^^\n" + 
2433
		"The variable o1 may be null\n" + 
2434
		"----------\n");
2435
}
2436
2437
// null analysis - if/else nested
2438
public void test0342_if_else_nested() {
2439
	this.runNegativeTest(
2440
		new String[] {
2441
			"X.java",
2442
			"public class X {\n" + 
2443
			"  void foo(Object o1, Object o2, boolean b) {\n" + 
2444
			"    if (o1 == null || b) {\n" + 
2445
			"      if (o2 == o1) {\n" + 
2446
			"        o1.toString();\n" + 
2447
			"      }\n" + 
2448
			"    }\n" + 
2449
			"  }\n" + 
2450
			"}"},
2451
		"----------\n" + 
2452
		"1. ERROR in X.java (at line 5)\n" + 
2453
		"	o1.toString();\n" + 
2454
		"	^^\n" + 
2455
		"The variable o1 may be null\n" + 
2456
		"----------\n");
2457
}
2458
2379
// null analysis -- while
2459
// null analysis -- while
2380
public void test0401_while() {
2460
public void test0401_while() {
2381
	this.runNegativeTest(
2461
	this.runNegativeTest(
Lines 3511-3517 Link Here
3511
3591
3512
// null analysis - while
3592
// null analysis - while
3513
// TODO (maxime) https://bugs.eclipse.org/bugs/show_bug.cgi?id=133131
3593
// TODO (maxime) https://bugs.eclipse.org/bugs/show_bug.cgi?id=133131
3514
public void _test0451_while_nested() {
3594
// fixed along 127570, do the reporting
3595
public void test0451_while_nested() {
3515
	this.runNegativeTest(
3596
	this.runNegativeTest(
3516
		new String[] {
3597
		new String[] {
3517
			"X.java",
3598
			"X.java",
Lines 3526-3532 Link Here
3526
			"    if (o != null) { /* */ }\n" + 
3607
			"    if (o != null) { /* */ }\n" + 
3527
			"  }\n" + 
3608
			"  }\n" + 
3528
			"}"},
3609
			"}"},
3529
		"ERR");
3610
		"----------\n" + 
3611
		"1. ERROR in X.java (at line 9)\n" + 
3612
		"	if (o != null) { /* */ }\n" + 
3613
		"	    ^\n" + 
3614
		"The variable o cannot be null; it was either set to a non-null value or assumed to be non-null when last used\n" + 
3615
		"----------\n");
3530
} 
3616
} 
3531
3617
3532
// TODO (maxime) https://bugs.eclipse.org/bugs/show_bug.cgi?id=123399
3618
// TODO (maxime) https://bugs.eclipse.org/bugs/show_bug.cgi?id=123399
Lines 5357-5365 Link Here
5357
}
5443
}
5358
5444
5359
// null analysis -- for
5445
// null analysis -- for
5360
// contrast this with #311
5446
// changed with https://bugs.eclipse.org/bugs/show_bug.cgi?id=127570
5447
// we are now able to see that x2 is reinitialized with x1, which is unknown
5361
public void test0726_for() {
5448
public void test0726_for() {
5362
	this.runNegativeTest(
5449
	this.runConformTest(
5363
		new String[] {
5450
		new String[] {
5364
			"X.java",
5451
			"X.java",
5365
			"public class X {\n" + 
5452
			"public class X {\n" + 
Lines 5373-5384 Link Here
5373
			"    }\n" + 
5460
			"    }\n" + 
5374
			"  }\n" +  
5461
			"  }\n" +  
5375
			"}\n"},
5462
			"}\n"},
5376
		"----------\n" + 
5463
		"");
5377
		"1. ERROR in X.java (at line 8)\n" + 
5378
		"	x2.toString();\n" + 
5379
		"	^^\n" + 
5380
		"The variable x2 may be null\n" + 
5381
		"----------\n");
5382
}
5464
}
5383
5465
5384
// null analysis -- for
5466
// null analysis -- for
Lines 5587-5592 Link Here
5587
	}
5669
	}
5588
}
5670
}
5589
5671
5672
// null analysis - for
5673
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127570
5674
public void test0736_for_embedded_lazy_init() {
5675
	this.runConformTest(
5676
		new String[] {
5677
			"X.java",
5678
			"class X {\n" + 
5679
			"  public boolean foo() {\n" + 
5680
			"    Boolean b = null;\n" + 
5681
			"    for (int i = 0; i < 1; i++) {\n" + 
5682
			"      if (b == null) {\n" + 
5683
			"        b = Boolean.TRUE;\n" + 
5684
			"      }\n" + 
5685
			"      if (b.booleanValue()) {\n" + // quiet
5686
			"        return b.booleanValue();\n" + 
5687
			"      }\n" + 
5688
			"    }\n" + 
5689
			"    return false;\n" + 
5690
			"  }\n" + 
5691
			"}"},
5692
		"");
5693
}
5694
5695
// null analysis - for with unknown protection: unknown cannot protect anything
5696
// suggested by https://bugs.eclipse.org/bugs/show_bug.cgi?id=127570
5697
public void test0737_for_unknown_protection() {
5698
	this.runNegativeTest(
5699
		new String[] {
5700
			"X.java",
5701
			"class X {\n" + 
5702
			"  public boolean foo(Boolean p) {\n" + 
5703
			"    Boolean b = null;\n" + 
5704
			"    for (int i = 0; i < 1; i++) {\n" + 
5705
			"      if (b == p) {\n" + // tells us that p is null as well
5706
			"        // empty\n" + 
5707
			"      }\n" +
5708
			"      else {\n" +
5709
			"        continue;\n" +
5710
			"      }\n" + 
5711
			"      if (b.booleanValue()) {\n" + // complain b can only be null
5712
			"        return b.booleanValue();\n" + 
5713
			"      }\n" + 
5714
			"    }\n" + 
5715
			"    return false;\n" + 
5716
			"  }\n" + 
5717
			"}"},
5718
		"----------\n" + 
5719
		"1. ERROR in X.java (at line 11)\n" + 
5720
		"	if (b.booleanValue()) {\n" + 
5721
		"	    ^\n" + 
5722
		"The variable b can only be null; it was either set to null or checked for null when last used\n" + 
5723
		"----------\n");
5724
}
5725
5726
// null analysis - for with unknown protection
5727
// suggested by https://bugs.eclipse.org/bugs/show_bug.cgi?id=127570
5728
// the issue is that we cannot do less than full aliasing analysis to
5729
// catch this one
5730
// TODO (maxime) reconsider when/if we bring full aliasing in
5731
public void _test0738_for_unknown_protection() {
5732
	this.runConformTest(
5733
		new String[] {
5734
			"X.java",
5735
			"class X {\n" + 
5736
			"  public boolean foo(Boolean p) {\n" + 
5737
			"    Boolean b = null;\n" + 
5738
			"    for (int i = 0; i < 1; i++) {\n" + 
5739
			"      if (b == p) {\n" + 
5740
			"        // empty\n" + 
5741
			"      }\n" +
5742
			"      else {\n" +
5743
			"        b = p;\n" +
5744
			"      }\n" + 
5745
			"      if (b.booleanValue()) {\n" + // quiet because b is an alias for p, unknown
5746
			"        return b.booleanValue();\n" + 
5747
			"      }\n" + 
5748
			"    }\n" + 
5749
			"    return false;\n" + 
5750
			"  }\n" + 
5751
			"}"},
5752
		"");
5753
}
5754
5590
// null analysis -- switch
5755
// null analysis -- switch
5591
public void test0800_switch() {
5756
public void test0800_switch() {
5592
	this.runConformTest(
5757
	this.runConformTest(
Lines 7035-7040 Link Here
7035
		"----------\n");
7200
		"----------\n");
7036
}
7201
}
7037
7202
7203
// encoding validation
7204
public void test1500() {
7205
	this.runConformTest(
7206
		new String[] {
7207
			"X.java",
7208
			"public class X {\n" + 
7209
			"  void foo(Object o, int i, boolean b, Object u) {\n" +
7210
			"    o.toString();\n" + 
7211
			"    switch (i) {\n" + 
7212
			"      case 0:\n" +
7213
			"        if (b) {\n" +
7214
			"          o = u;\n" +
7215
			"        } else {\n" +
7216
			"          o = new Object();\n" +
7217
			"        }\n" +
7218
			"        break;\n" + 
7219
			"    }\n" +
7220
			"    if (o == null) { /* empty */ }\n" + 
7221
			"  }\n" + 
7222
			"}\n"},
7223
		"");
7224
}
7225
7226
// encoding validation
7227
public void test1501() {
7228
	this.runConformTest(
7229
		new String[] {
7230
			"X.java",
7231
			"public class X {\n" + 
7232
			"  void foo(Object o, int i, boolean b, Object u) {\n" +
7233
			"    if (b) {\n" +
7234
			"      o = new Object();\n" +
7235
			"    }\n" + 
7236
			"    o.toString();\n" + 
7237
			"    switch (i) {\n" + 
7238
			"      case 0:\n" +
7239
			"        if (b) {\n" +
7240
			"          o = u;\n" +
7241
			"        } else {\n" +
7242
			"          o = new Object();\n" +
7243
			"        }\n" +
7244
			"        break;\n" + 
7245
			"    }\n" +
7246
			"    if (o == null) { /* empty */ }\n" + 
7247
			"  }\n" + 
7248
			"}\n"},
7249
		"");
7250
}
7251
7252
// encoding validation
7253
public void test1502() {
7254
	this.runConformTest(
7255
		new String[] {
7256
			"X.java",
7257
			"public class X {\n" + 
7258
			"  void foo(Object o, int i, boolean b, Object u) {\n" +
7259
			"    if (b) {\n" +
7260
			"      o = u;\n" +
7261
			"    }\n" + 
7262
			"    o.toString();\n" + 
7263
			"    switch (i) {\n" + 
7264
			"      case 0:\n" +
7265
			"        if (b) {\n" +
7266
			"          o = u;\n" +
7267
			"        } else {\n" +
7268
			"          o = new Object();\n" +
7269
			"        }\n" +
7270
			"        break;\n" + 
7271
			"    }\n" +
7272
			"    if (o == null) { /* empty */ }\n" + 
7273
			"  }\n" + 
7274
			"}\n"},
7275
		"");
7276
}
7277
7278
// encoding validation
7279
public void test1503() {
7280
	this.runConformTest(
7281
		new String[] {
7282
			"X.java",
7283
			"public class X {\n" + 
7284
			"  void foo(Object o, int i, boolean b, Object u) {\n" +
7285
			"    if (b) {\n" +
7286
			"      o = u;\n" +
7287
			"    } else {\n" +
7288
			"      o = new Object();\n" +
7289
			"    }\n" + 
7290
			"    o.toString();\n" + 
7291
			"    switch (i) {\n" + 
7292
			"      case 0:\n" +
7293
			"        if (b) {\n" +
7294
			"          o = u;\n" +
7295
			"        } else {\n" +
7296
			"          o = new Object();\n" +
7297
			"        }\n" +
7298
			"        break;\n" + 
7299
			"    }\n" +
7300
			"    if (o == null) { /* empty */ }\n" + 
7301
			"  }\n" + 
7302
			"}\n"},
7303
		"");
7304
}
7305
7038
// flow info low-level validation
7306
// flow info low-level validation
7039
public void test2000_flow_info() {
7307
public void test2000_flow_info() {
7040
	this.runNegativeTest(
7308
	this.runNegativeTest(
Lines 7058-7064 Link Here
7058
			"      o60 = o0, o61 = o0, o62 = o0, o63 = o0, o64 = o0,\n" + 
7326
			"      o60 = o0, o61 = o0, o62 = o0, o63 = o0, o64 = o0,\n" + 
7059
			"      o65 = o0, o66 = o0, o67 = o0, o68 = o0, o69 = o0;\n" + 
7327
			"      o65 = o0, o66 = o0, o67 = o0, o68 = o0, o69 = o0;\n" + 
7060
			"    if (o65 == null) { /* */ }\n" + // complain 
7328
			"    if (o65 == null) { /* */ }\n" + // complain 
7061
			"    if (o65 != null) { /* */ }\n" + // quiet (already reported)
7329
			"    if (o65 != null) { /* */ }\n" +
7062
			"  }\n" + 
7330
			"  }\n" + 
7063
			"}\n"},
7331
			"}\n"},
7064
		"----------\n" + 
7332
		"----------\n" + 
Lines 7782-9978 Link Here
7782
		"The variable o1 may be null\n" + 
8050
		"The variable o1 may be null\n" + 
7783
		"----------\n");
8051
		"----------\n");
7784
}
8052
}
7785
7786
// Technical tests -- only available with patched sources
7787
static final boolean 
7788
	printTablesAsNames = false, 
7789
	printTablesAsCodes = false, 
7790
	printTruthMaps = false;
7791
static final int
7792
	combinationTestsloopsNb = 1; // define to 10000s to measure performances
7793
7794
7795
public void test2050_markAsComparedEqualToNonNull() {
7796
	long [][][] testData = {
7797
		{{0,0,0,0},{1,1,0,0}},
7798
		{{0,0,0,1},{1,1,0,1}},
7799
		{{0,0,1,0},{1,1,0,0}},
7800
		{{0,0,1,1},{1,1,0,1}},
7801
		{{0,1,0,0},{1,1,0,0}},
7802
		{{0,1,0,1},{1,1,0,1}},
7803
		{{0,1,1,0},{1,1,0,0}},
7804
		{{0,1,1,1},{1,1,0,1}},
7805
		{{1,0,0,0},{1,1,0,0}},
7806
		{{1,0,0,1},{1,0,0,1}},
7807
		{{1,0,1,0},{1,1,0,0}},
7808
		{{1,0,1,1},{1,1,0,1}},
7809
		{{1,1,0,0},{1,1,0,0}},
7810
		{{1,1,0,1},{1,1,0,1}},
7811
		{{1,1,1,0},{1,1,0,0}},
7812
		{{1,1,1,1},{1,1,0,1}},
7813
	};
7814
	int failures = 0;
7815
	LocalVariableBinding local = new TestLocalVariableBinding(0);
7816
	for (int i = 0; i < testData.length; i++) {
7817
		UnconditionalFlowInfoTestHarness 
7818
			result = UnconditionalFlowInfoTestHarness.
7819
				testUnconditionalFlowInfo(testData[i][0]);
7820
		result.markAsComparedEqualToNonNull(local);
7821
		if (!(result.testEquals(UnconditionalFlowInfoTestHarness.
7822
				testUnconditionalFlowInfo(testData[i][1])))) {
7823
			if (failures == 0) {
7824
				System.out.println("markAsComparedEqualToNonNull failures: ");
7825
			}
7826
			failures++;
7827
			System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
7828
				',' + result.testString() + 
7829
				"}, // instead of: " + testStringValueOf(testData[i][1]));
7830
		}
7831
	}
7832
	local = new TestLocalVariableBinding(64);
7833
	for (int i = 0; i < testData.length; i++) {
7834
		UnconditionalFlowInfoTestHarness 
7835
			result = UnconditionalFlowInfoTestHarness.
7836
				testUnconditionalFlowInfo(testData[i][0], 64),
7837
			expected = UnconditionalFlowInfoTestHarness.
7838
				testUnconditionalFlowInfo(testData[i][1], 64);
7839
		result.markAsComparedEqualToNonNull(local);
7840
		if (!(result.testEquals(expected))) {
7841
			if (failures == 0) {
7842
				System.out.println("markAsComparedEqualToNonNull failures: ");
7843
			}
7844
			failures++;
7845
			System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
7846
				',' + result.testString() + 
7847
				"}, //  (64) instead of: " + testStringValueOf(testData[i][1]));
7848
		}
7849
		if (testData[i][0][0] == 0 &&
7850
				testData[i][0][1] == 0 &&
7851
				testData[i][0][2] == 0 &&				
7852
				testData[i][0][3] == 0) {
7853
			result = UnconditionalFlowInfoTestHarness.
7854
				testUnconditionalFlowInfo(testData[i][1]);
7855
			result.markAsComparedEqualToNonNull(local);
7856
			if (!result.testEquals(expected, 64)) {
7857
				if (failures == 0) {
7858
					System.out.println("markAsComparedEqualToNonNull failures: ");
7859
				}
7860
				failures++;
7861
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
7862
						',' + result.testString() + 
7863
						"}, //  (zero 64) instead of: " + testStringValueOf(testData[i][1]));
7864
			}
7865
		}
7866
	}
7867
	local = new TestLocalVariableBinding(128);
7868
	for (int i = 0; i < testData.length; i++) {
7869
		if (testData[i][0][0] == 0 &&
7870
				testData[i][0][1] == 0 &&
7871
				testData[i][0][2] == 0 &&				
7872
				testData[i][0][3] == 0) {
7873
			UnconditionalFlowInfoTestHarness 
7874
				result = UnconditionalFlowInfoTestHarness.
7875
					testUnconditionalFlowInfo(testData[i][1], 64),
7876
				expected = UnconditionalFlowInfoTestHarness.
7877
					testUnconditionalFlowInfo(testData[i][1], 128);
7878
			result.markAsComparedEqualToNonNull(local);
7879
			if (!result.testEquals(expected, 128)) {
7880
				if (failures == 0) {
7881
					System.out.println("markAsComparedEqualToNonNull failures: ");
7882
				}
7883
				failures++;
7884
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
7885
						',' + result.testString() + 
7886
						"}, //  (zero 128) instead of: " + testStringValueOf(testData[i][1]));
7887
			}
7888
		}
7889
	}
7890
	if (printTablesAsNames) {
7891
		System.out.println("RECAP TABLE FOR MARK COMPARED NON NULL");
7892
		for (int i = 0; i < testData.length; i++) {
7893
			System.out.println(testSymbolicValueOf(testData[i][0]) + " -> " +
7894
				testSymbolicValueOf(testData[i][1]));
7895
		}	
7896
	}
7897
	if (printTablesAsCodes) {
7898
		System.out.println("RECAP TABLE FOR MARK COMPARED NON NULL");
7899
		for (int i = 0; i < testData.length; i++) {
7900
			System.out.println(testCodedValueOf(testData[i][0]) + " " +
7901
				testCodedValueOf(testData[i][1]));
7902
		}
7903
	}
7904
	assertTrue("nb of failures: " + failures, failures == 0);
7905
}
7906
7907
public void test2051_markAsComparedEqualToNull() {
7908
	long [][][] testData = {
7909
		{{0,0,0,0},{0,1,0,0}},
7910
		{{0,0,0,1},{0,1,0,0}},
7911
		{{0,0,1,0},{0,1,1,0}},
7912
		{{0,0,1,1},{0,1,1,0}},
7913
		{{0,1,0,0},{0,1,0,0}},
7914
		{{0,1,0,1},{0,1,0,0}},
7915
		{{0,1,1,0},{0,1,1,0}},
7916
		{{0,1,1,1},{0,1,1,0}},
7917
		{{1,0,0,0},{0,1,0,0}},
7918
		{{1,0,0,1},{0,1,0,0}},
7919
		{{1,0,1,0},{1,0,1,0}},
7920
		{{1,0,1,1},{0,1,0,0}},
7921
		{{1,1,0,0},{0,1,0,0}},
7922
		{{1,1,0,1},{0,1,0,0}},
7923
		{{1,1,1,0},{0,1,1,0}},
7924
		{{1,1,1,1},{0,1,1,0}},
7925
	};
7926
	int failures = 0;
7927
	LocalVariableBinding local = new TestLocalVariableBinding(0);
7928
	for (int i = 0; i < testData.length; i++) {
7929
		UnconditionalFlowInfoTestHarness 
7930
			result = UnconditionalFlowInfoTestHarness.
7931
				testUnconditionalFlowInfo(testData[i][0]);
7932
		result.markAsComparedEqualToNull(local);
7933
		if (!(result.testEquals(UnconditionalFlowInfoTestHarness.
7934
				testUnconditionalFlowInfo(testData[i][1])))) {
7935
			if (failures == 0) {
7936
				System.out.println("markAsComparedEqualToNull failures: ");
7937
			}
7938
			failures++;
7939
			System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
7940
				',' + result.testString() + 
7941
				"}, // instead of: " + testStringValueOf(testData[i][1]));
7942
		}
7943
	}
7944
	local = new TestLocalVariableBinding(64);
7945
	for (int i = 0; i < testData.length; i++) {
7946
		UnconditionalFlowInfoTestHarness 
7947
			result = UnconditionalFlowInfoTestHarness.
7948
				testUnconditionalFlowInfo(testData[i][0], 64),
7949
			expected = UnconditionalFlowInfoTestHarness.
7950
				testUnconditionalFlowInfo(testData[i][1], 64);
7951
		result.markAsComparedEqualToNull(local);
7952
		if (!(result.testEquals(expected))) {
7953
			if (failures == 0) {
7954
				System.out.println("markAsComparedEqualToNull failures: ");
7955
			}
7956
			failures++;
7957
			System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
7958
				',' + result.testString() + 
7959
				"}, // (64) instead of: " + testStringValueOf(testData[i][1]));
7960
		}
7961
		if (testData[i][0][0] == 0 &&
7962
				testData[i][0][1] == 0 &&
7963
				testData[i][0][2] == 0 &&				
7964
				testData[i][0][3] == 0) {
7965
			result = UnconditionalFlowInfoTestHarness.
7966
				testUnconditionalFlowInfo(testData[i][1]);
7967
			result.markAsComparedEqualToNull(local);
7968
			if (!result.testEquals(expected, 64)) {
7969
				if (failures == 0) {
7970
					System.out.println("markAsComparedEqualToNull failures: ");
7971
				}
7972
				failures++;
7973
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
7974
						',' + result.testString() + 
7975
						"}, //  (zero 64) instead of: " + testStringValueOf(testData[i][1]));
7976
			}
7977
		}		
7978
	}
7979
	local = new TestLocalVariableBinding(128);
7980
	for (int i = 0; i < testData.length; i++) {
7981
		if (testData[i][0][0] == 0 &&
7982
				testData[i][0][1] == 0 &&
7983
				testData[i][0][2] == 0 &&				
7984
				testData[i][0][3] == 0) {
7985
			UnconditionalFlowInfoTestHarness 
7986
				result = UnconditionalFlowInfoTestHarness.
7987
					testUnconditionalFlowInfo(testData[i][1], 64),
7988
				expected = UnconditionalFlowInfoTestHarness.
7989
					testUnconditionalFlowInfo(testData[i][1], 128);
7990
			result.markAsComparedEqualToNull(local);
7991
			if (!result.testEquals(expected, 128)) {
7992
				if (failures == 0) {
7993
					System.out.println("markAsComparedEqualToNull failures: ");
7994
				}
7995
				failures++;
7996
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
7997
						',' + result.testString() + 
7998
						"}, //  (zero 128) instead of: " + testStringValueOf(testData[i][1]));
7999
			}
8000
		}
8001
	}	
8002
	if (printTablesAsNames) {
8003
		System.out.println("RECAP TABLE FOR MARK COMPARED NULL");
8004
		for (int i = 0; i < testData.length; i++) {
8005
			System.out.println(testSymbolicValueOf(testData[i][0]) + " -> " +
8006
				testSymbolicValueOf(testData[i][1]));
8007
		}	
8008
	}
8009
	if (printTablesAsCodes) {
8010
		System.out.println("RECAP TABLE FOR MARK COMPARED NULL");
8011
		for (int i = 0; i < testData.length; i++) {
8012
			System.out.println(testCodedValueOf(testData[i][0]) + " " +
8013
				testCodedValueOf(testData[i][1]));
8014
		}
8015
	}
8016
	assertTrue("nb of failures: " + failures, failures == 0);
8017
}
8018
8019
public void test2052_markAsDefinitelyNonNull() {
8020
	long [][][] testData = {
8021
		{{0,0,0,0},{1,0,0,1}},
8022
		{{0,0,0,1},{1,0,0,1}},
8023
		{{0,0,1,0},{1,0,0,1}},
8024
		{{0,0,1,1},{1,0,0,1}},
8025
		{{0,1,0,0},{1,0,0,1}},
8026
		{{0,1,0,1},{1,0,0,1}},
8027
		{{0,1,1,0},{1,0,0,1}},
8028
		{{0,1,1,1},{1,0,0,1}},
8029
		{{1,0,0,0},{1,0,0,1}},
8030
		{{1,0,0,1},{1,0,0,1}},
8031
		{{1,0,1,0},{1,0,0,1}},
8032
		{{1,0,1,1},{1,0,0,1}},
8033
		{{1,1,0,0},{1,0,0,1}},
8034
		{{1,1,0,1},{1,0,0,1}},
8035
		{{1,1,1,0},{1,0,0,1}},
8036
		{{1,1,1,1},{1,0,0,1}},
8037
	};
8038
	int failures = 0;
8039
	LocalVariableBinding local = new TestLocalVariableBinding(0);
8040
	for (int i = 0; i < testData.length; i++) {
8041
		UnconditionalFlowInfoTestHarness 
8042
			result = UnconditionalFlowInfoTestHarness.
8043
				testUnconditionalFlowInfo(testData[i][0]);
8044
		result.markAsDefinitelyNonNull(local);
8045
		if (!(result.testEquals(UnconditionalFlowInfoTestHarness.
8046
				testUnconditionalFlowInfo(testData[i][1])))) {
8047
			if (failures == 0) {
8048
				System.out.println("markAsDefinitelyNonNull failures: ");
8049
			}
8050
			failures++;
8051
			System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8052
				',' + result.testString() + 
8053
				"}, // instead of: " + testStringValueOf(testData[i][1]));
8054
		}
8055
	}
8056
	local = new TestLocalVariableBinding(64);
8057
	for (int i = 0; i < testData.length; i++) {
8058
		UnconditionalFlowInfoTestHarness 
8059
			result = UnconditionalFlowInfoTestHarness.
8060
				testUnconditionalFlowInfo(testData[i][0], 64);
8061
		result.markAsDefinitelyNonNull(local);
8062
		if (!(result.testEquals(UnconditionalFlowInfoTestHarness.
8063
				testUnconditionalFlowInfo(testData[i][1], 64)))) {
8064
			if (failures == 0) {
8065
				System.out.println("markAsDefinitelyNonNull failures: ");
8066
			}
8067
			failures++;
8068
			System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8069
				',' + result.testString() + 
8070
				"}, // (64) instead of: " + testStringValueOf(testData[i][1]));
8071
		}
8072
	}
8073
	if (printTablesAsNames) {
8074
		System.out.println("RECAP TABLE FOR MARK DEFINITELY NON NULL");
8075
		for (int i = 0; i < testData.length; i++) {
8076
			System.out.println(testSymbolicValueOf(testData[i][0]) + " -> " +
8077
				testSymbolicValueOf(testData[i][1]));
8078
		}	
8079
	}
8080
	if (printTablesAsCodes) {
8081
		System.out.println("RECAP TABLE FOR MARK DEFINITELY NON NULL");
8082
		for (int i = 0; i < testData.length; i++) {
8083
			System.out.println(testCodedValueOf(testData[i][0]) + " " +
8084
				testCodedValueOf(testData[i][1]));
8085
		}
8086
	}
8087
	assertTrue("nb of failures: " + failures, failures == 0);
8088
}
8089
8090
public void test2053_markAsDefinitelyNull() {
8091
	long [][][] testData = {
8092
		{{0,0,0,0},{1,0,1,0}},
8093
		{{0,0,0,1},{1,0,1,0}},
8094
		{{0,0,1,0},{1,0,1,0}},
8095
		{{0,0,1,1},{1,0,1,0}},
8096
		{{0,1,0,0},{1,0,1,0}},
8097
		{{0,1,0,1},{1,0,1,0}},
8098
		{{0,1,1,0},{1,0,1,0}},
8099
		{{0,1,1,1},{1,0,1,0}},
8100
		{{1,0,0,0},{1,0,1,0}},
8101
		{{1,0,0,1},{1,0,1,0}},
8102
		{{1,0,1,0},{1,0,1,0}},
8103
		{{1,0,1,1},{1,0,1,0}},
8104
		{{1,1,0,0},{1,0,1,0}},
8105
		{{1,1,0,1},{1,0,1,0}},
8106
		{{1,1,1,0},{1,0,1,0}},
8107
		{{1,1,1,1},{1,0,1,0}},
8108
	};
8109
	int failures = 0;
8110
	LocalVariableBinding local = new TestLocalVariableBinding(0);
8111
	for (int i = 0; i < testData.length; i++) {
8112
		UnconditionalFlowInfoTestHarness 
8113
			result = UnconditionalFlowInfoTestHarness.
8114
				testUnconditionalFlowInfo(testData[i][0]);
8115
		result.markAsDefinitelyNull(local);
8116
		if (!(result.testEquals(UnconditionalFlowInfoTestHarness.
8117
				testUnconditionalFlowInfo(testData[i][1])))) {
8118
			if (failures == 0) {
8119
				System.out.println("markAsDefinitelyNull failures: ");
8120
			}
8121
			failures++;
8122
			System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8123
				',' + result.testString() + 
8124
				"}, // instead of: " + testStringValueOf(testData[i][1]));
8125
		}
8126
	}
8127
	local = new TestLocalVariableBinding(64);
8128
	for (int i = 0; i < testData.length; i++) {
8129
		UnconditionalFlowInfoTestHarness 
8130
			result = UnconditionalFlowInfoTestHarness.
8131
				testUnconditionalFlowInfo(testData[i][0], 64);
8132
		result.markAsDefinitelyNull(local);
8133
		if (!(result.testEquals(UnconditionalFlowInfoTestHarness.
8134
				testUnconditionalFlowInfo(testData[i][1], 64)))) {
8135
			if (failures == 0) {
8136
				System.out.println("markAsDefinitelyNull failures: ");
8137
			}
8138
			failures++;
8139
			System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8140
				',' + result.testString() + 
8141
				"}, // (64) instead of: " + testStringValueOf(testData[i][1]));
8142
		}
8143
	}
8144
	if (printTablesAsNames) {
8145
		System.out.println("RECAP TABLE FOR MARK DEFINITELY NULL");
8146
		for (int i = 0; i < testData.length; i++) {
8147
			System.out.println(testSymbolicValueOf(testData[i][0]) + " -> " +
8148
				testSymbolicValueOf(testData[i][1]));
8149
		}	
8150
	}
8151
	if (printTablesAsCodes) {
8152
		System.out.println("RECAP TABLE FOR MARK DEFINITELY NULL");
8153
		for (int i = 0; i < testData.length; i++) {
8154
			System.out.println(testCodedValueOf(testData[i][0]) + " " +
8155
				testCodedValueOf(testData[i][1]));
8156
		}
8157
	}
8158
	assertTrue("nb of failures: " + failures, failures == 0);
8159
}
8160
8161
public void test2054_markAsDefinitelyUnknown() {
8162
	long [][][] testData = {
8163
		{{0,0,0,0},{1,0,1,1}},
8164
		{{0,0,0,1},{1,0,1,1}},
8165
		{{0,0,1,0},{1,0,1,1}},
8166
		{{0,0,1,1},{1,0,1,1}},
8167
		{{0,1,0,0},{1,0,1,1}},
8168
		{{0,1,0,1},{1,0,1,1}},
8169
		{{0,1,1,0},{1,0,1,1}},
8170
		{{0,1,1,1},{1,0,1,1}},
8171
		{{1,0,0,0},{1,0,1,1}},
8172
		{{1,0,0,1},{1,0,1,1}},
8173
		{{1,0,1,0},{1,0,1,1}},
8174
		{{1,0,1,1},{1,0,1,1}},
8175
		{{1,1,0,0},{1,0,1,1}},
8176
		{{1,1,0,1},{1,0,1,1}},
8177
		{{1,1,1,0},{1,0,1,1}},
8178
		{{1,1,1,1},{1,0,1,1}},
8179
	};
8180
	int failures = 0;
8181
	LocalVariableBinding local = new TestLocalVariableBinding(0);
8182
	for (int i = 0; i < testData.length; i++) {
8183
		UnconditionalFlowInfoTestHarness 
8184
			result = UnconditionalFlowInfoTestHarness.
8185
				testUnconditionalFlowInfo(testData[i][0]);
8186
		result.markAsDefinitelyUnknown(local);
8187
		if (!(result.testEquals(UnconditionalFlowInfoTestHarness.
8188
				testUnconditionalFlowInfo(testData[i][1])))) {
8189
			if (failures == 0) {
8190
				System.out.println("markAsDefinitelyUnknown failures: ");
8191
			}
8192
			failures++;
8193
			System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8194
				',' + result.testString() + 
8195
				"}, // instead of: " + testStringValueOf(testData[i][1]));
8196
		}
8197
	}
8198
	local = new TestLocalVariableBinding(64);
8199
	for (int i = 0; i < testData.length; i++) {
8200
		UnconditionalFlowInfoTestHarness 
8201
			result = UnconditionalFlowInfoTestHarness.
8202
				testUnconditionalFlowInfo(testData[i][0], 64);
8203
		result.markAsDefinitelyUnknown(local);
8204
		if (!(result.testEquals(UnconditionalFlowInfoTestHarness.
8205
				testUnconditionalFlowInfo(testData[i][1], 64)))) {
8206
			if (failures == 0) {
8207
				System.out.println("markAsDefinitelyUnknown failures: ");
8208
			}
8209
			failures++;
8210
			System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8211
				',' + result.testString() + 
8212
				"}, // (64) instead of: " + testStringValueOf(testData[i][1]));
8213
		}
8214
	}
8215
	if (printTablesAsNames) {
8216
		System.out.println("RECAP TABLE FOR MARK DEFINITELY UNKNOWN");
8217
		for (int i = 0; i < testData.length; i++) {
8218
			System.out.println(testSymbolicValueOf(testData[i][0]) + " -> " +
8219
				testSymbolicValueOf(testData[i][1]));
8220
		}	
8221
	}
8222
	if (printTablesAsCodes) {
8223
		System.out.println("RECAP TABLE FOR MARK DEFINITELY UNKNOWN");
8224
		for (int i = 0; i < testData.length; i++) {
8225
			System.out.println(testCodedValueOf(testData[i][0]) + " " +
8226
				testCodedValueOf(testData[i][1]));
8227
		}
8228
	}
8229
	assertTrue("nb of failures: " + failures, failures == 0);
8230
}
8231
8232
public void test2055_addInitializationsFrom() {
8233
	long [][][] testData = {
8234
		{{0,0,0,0},{0,0,0,0},{0,0,0,0}},
8235
		{{0,0,0,0},{0,0,0,1},{0,0,0,1}},
8236
		{{0,0,0,0},{0,0,1,0},{0,0,1,0}},
8237
		{{0,0,0,0},{0,0,1,1},{0,0,1,1}},
8238
		{{0,0,0,0},{0,1,0,0},{0,1,0,0}},
8239
		{{0,0,0,0},{0,1,1,0},{0,1,1,0}},
8240
		{{0,0,0,0},{1,0,0,1},{1,0,0,1}},
8241
		{{0,0,0,0},{1,0,1,0},{1,0,1,0}},
8242
		{{0,0,0,0},{1,0,1,1},{1,0,1,1}},
8243
		{{0,0,0,0},{1,1,0,0},{1,1,0,0}},
8244
		{{0,0,0,0},{1,1,0,1},{1,1,0,1}},
8245
		{{0,0,0,1},{0,0,0,0},{0,0,0,1}},
8246
		{{0,0,0,1},{0,0,0,1},{0,0,0,1}},
8247
		{{0,0,0,1},{0,0,1,0},{0,0,1,1}},
8248
		{{0,0,0,1},{0,0,1,1},{0,0,1,1}},
8249
		{{0,0,0,1},{0,1,0,0},{0,1,0,0}},
8250
		{{0,0,0,1},{0,1,1,0},{0,1,0,0}},
8251
		{{0,0,0,1},{1,0,0,1},{1,0,0,1}},
8252
		{{0,0,0,1},{1,0,1,0},{1,0,1,0}},
8253
		{{0,0,0,1},{1,0,1,1},{1,0,1,1}},
8254
		{{0,0,0,1},{1,1,0,0},{1,1,0,1}},
8255
		{{0,0,0,1},{1,1,0,1},{1,1,0,1}},
8256
		{{0,0,1,0},{0,0,0,0},{0,0,1,0}},
8257
		{{0,0,1,0},{0,0,0,1},{0,0,1,1}},
8258
		{{0,0,1,0},{0,0,1,0},{0,0,1,0}},
8259
		{{0,0,1,0},{0,0,1,1},{0,0,1,1}},
8260
		{{0,0,1,0},{0,1,0,0},{0,1,1,0}},
8261
		{{0,0,1,0},{0,1,1,0},{0,1,1,0}},
8262
		{{0,0,1,0},{1,0,0,1},{1,0,0,1}},
8263
		{{0,0,1,0},{1,0,1,0},{1,0,1,0}},
8264
		{{0,0,1,0},{1,0,1,1},{1,0,1,1}},
8265
		{{0,0,1,0},{1,1,0,0},{1,1,0,0}},
8266
		{{0,0,1,0},{1,1,0,1},{1,1,0,1}},
8267
		{{0,0,1,1},{0,0,0,0},{0,0,1,1}},
8268
		{{0,0,1,1},{0,0,0,1},{0,0,1,1}},
8269
		{{0,0,1,1},{0,0,1,0},{0,0,1,1}},
8270
		{{0,0,1,1},{0,0,1,1},{0,0,1,1}},
8271
		{{0,0,1,1},{0,1,0,0},{0,1,1,0}},
8272
		{{0,0,1,1},{0,1,1,0},{0,1,1,0}},
8273
		{{0,0,1,1},{1,0,0,1},{1,0,0,1}},
8274
		{{0,0,1,1},{1,0,1,0},{1,0,1,0}},
8275
		{{0,0,1,1},{1,0,1,1},{1,0,1,1}},
8276
		{{0,0,1,1},{1,1,0,0},{1,1,0,1}},
8277
		{{0,0,1,1},{1,1,0,1},{1,1,0,1}},
8278
		{{0,1,0,0},{0,0,0,0},{0,1,0,0}},
8279
		{{0,1,0,0},{0,0,0,1},{0,0,0,1}},
8280
		{{0,1,0,0},{0,0,1,0},{0,1,1,0}},
8281
		{{0,1,0,0},{0,0,1,1},{0,0,1,1}},
8282
		{{0,1,0,0},{0,1,0,0},{0,1,0,0}},
8283
		{{0,1,0,0},{0,1,1,0},{0,1,1,0}},
8284
		{{0,1,0,0},{1,0,0,1},{1,0,0,1}},
8285
		{{0,1,0,0},{1,0,1,0},{1,0,1,0}},
8286
		{{0,1,0,0},{1,0,1,1},{1,0,1,1}},
8287
		{{0,1,0,0},{1,1,0,0},{1,1,0,0}},
8288
		{{0,1,0,0},{1,1,0,1},{1,1,0,1}},
8289
		{{0,1,1,0},{0,0,0,0},{0,1,1,0}},
8290
		{{0,1,1,0},{0,0,0,1},{0,0,1,1}},
8291
		{{0,1,1,0},{0,0,1,0},{0,1,1,0}},
8292
		{{0,1,1,0},{0,0,1,1},{0,0,1,1}},
8293
		{{0,1,1,0},{0,1,0,0},{0,1,1,0}},
8294
		{{0,1,1,0},{0,1,1,0},{0,1,1,0}},
8295
		{{0,1,1,0},{1,0,0,1},{1,0,0,1}},
8296
		{{0,1,1,0},{1,0,1,0},{1,0,1,0}},
8297
		{{0,1,1,0},{1,0,1,1},{1,0,1,1}},
8298
		{{0,1,1,0},{1,1,0,0},{1,1,0,0}},
8299
		{{0,1,1,0},{1,1,0,1},{1,1,0,1}},
8300
		{{1,0,0,1},{0,0,0,0},{1,0,0,1}},
8301
		{{1,0,0,1},{0,0,0,1},{1,0,0,1}},
8302
		{{1,0,0,1},{0,0,1,0},{0,0,1,1}},
8303
		{{1,0,0,1},{0,0,1,1},{0,0,1,1}},
8304
		{{1,0,0,1},{0,1,0,0},{0,1,0,0}},
8305
		{{1,0,0,1},{0,1,1,0},{0,1,1,0}},
8306
		{{1,0,0,1},{1,0,0,1},{1,0,0,1}},
8307
		{{1,0,0,1},{1,0,1,0},{1,0,1,0}},
8308
		{{1,0,0,1},{1,0,1,1},{1,0,1,1}},
8309
		{{1,0,0,1},{1,1,0,0},{1,1,0,1}},
8310
		{{1,0,0,1},{1,1,0,1},{1,1,0,1}},
8311
		{{1,0,1,0},{0,0,0,0},{1,0,1,0}},
8312
		{{1,0,1,0},{0,0,0,1},{0,0,1,1}},
8313
		{{1,0,1,0},{0,0,1,0},{1,0,1,0}},
8314
		{{1,0,1,0},{0,0,1,1},{0,0,1,1}},
8315
		{{1,0,1,0},{0,1,0,0},{1,0,1,0}},
8316
		{{1,0,1,0},{0,1,1,0},{1,0,1,0}},
8317
		{{1,0,1,0},{1,0,0,1},{1,0,0,1}},
8318
		{{1,0,1,0},{1,0,1,0},{1,0,1,0}},
8319
		{{1,0,1,0},{1,0,1,1},{1,0,1,1}},
8320
		{{1,0,1,0},{1,1,0,0},{1,1,0,0}},
8321
		{{1,0,1,0},{1,1,0,1},{1,1,0,1}},
8322
		{{1,0,1,1},{0,0,0,0},{1,0,1,1}},
8323
		{{1,0,1,1},{0,0,0,1},{1,0,1,1}},
8324
		{{1,0,1,1},{0,0,1,0},{0,0,1,1}},
8325
		{{1,0,1,1},{0,0,1,1},{0,0,1,1}},
8326
		{{1,0,1,1},{0,1,0,0},{0,1,0,0}},
8327
		{{1,0,1,1},{0,1,1,0},{0,1,1,0}},
8328
		{{1,0,1,1},{1,0,0,1},{1,0,0,1}},
8329
		{{1,0,1,1},{1,0,1,0},{1,0,1,0}},
8330
		{{1,0,1,1},{1,0,1,1},{1,0,1,1}},
8331
		{{1,0,1,1},{1,1,0,0},{1,1,0,1}},
8332
		{{1,0,1,1},{1,1,0,1},{1,1,0,1}},
8333
		{{1,1,0,0},{0,0,0,0},{1,1,0,0}},
8334
		{{1,1,0,0},{0,0,0,1},{1,1,0,1}},
8335
		{{1,1,0,0},{0,0,1,0},{0,0,1,0}},
8336
		{{1,1,0,0},{0,0,1,1},{0,0,1,1}},
8337
		{{1,1,0,0},{0,1,0,0},{0,1,0,0}},
8338
		{{1,1,0,0},{0,1,1,0},{0,1,1,0}},
8339
		{{1,1,0,0},{1,0,0,1},{1,0,0,1}},
8340
		{{1,1,0,0},{1,0,1,0},{1,0,1,0}},
8341
		{{1,1,0,0},{1,0,1,1},{1,0,1,1}},
8342
		{{1,1,0,0},{1,1,0,0},{1,1,0,0}},
8343
		{{1,1,0,0},{1,1,0,1},{1,1,0,1}},
8344
		{{1,1,0,1},{0,0,0,0},{1,1,0,1}},
8345
		{{1,1,0,1},{0,0,0,1},{0,0,0,1}},
8346
		{{1,1,0,1},{0,0,1,0},{0,0,1,1}},
8347
		{{1,1,0,1},{0,0,1,1},{0,0,1,1}},
8348
		{{1,1,0,1},{0,1,0,0},{0,1,0,0}},
8349
		{{1,1,0,1},{0,1,1,0},{0,1,1,0}},
8350
		{{1,1,0,1},{1,0,0,1},{1,0,0,1}},
8351
		{{1,1,0,1},{1,0,1,0},{1,0,1,0}},
8352
		{{1,1,0,1},{1,0,1,1},{1,0,1,1}},
8353
		{{1,1,0,1},{1,1,0,0},{1,1,0,1}},
8354
		{{1,1,0,1},{1,1,0,1},{1,1,0,1}},
8355
	};
8356
	int failures = 0;
8357
	long start;
8358
	if (combinationTestsloopsNb > 1) {
8359
		start = System.currentTimeMillis();
8360
	}
8361
	String header = "addInitializationsFrom failures: "; //$NON-NLS-1$
8362
	for (int l = 0; l < combinationTestsloopsNb ; l++) {
8363
		for (int i = 0; i < testData.length; i++) {
8364
			UnconditionalFlowInfoTestHarness result;
8365
			if (!(result = (UnconditionalFlowInfoTestHarness)(
8366
					UnconditionalFlowInfoTestHarness.
8367
						testUnconditionalFlowInfo(testData[i][0])).
8368
						addInitializationsFrom(
8369
								UnconditionalFlowInfoTestHarness.
8370
								testUnconditionalFlowInfo(testData[i][1]))).
8371
					testEquals(UnconditionalFlowInfoTestHarness.
8372
								testUnconditionalFlowInfo(testData[i][2]))) {
8373
				if (failures == 0) {
8374
					System.out.println(header);
8375
				}
8376
				failures++;
8377
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8378
					',' + testStringValueOf(testData[i][1]) +
8379
					',' + result.testString() + 
8380
					"}, // instead of: " + testStringValueOf(testData[i][2]));
8381
			}
8382
		}
8383
	}
8384
	if (combinationTestsloopsNb > 1) {
8385
		System.out.println("addInitial...\t\t" + combinationTestsloopsNb + "\t" + 
8386
				(System.currentTimeMillis() - start));
8387
	}
8388
	// PREMATURE optimize test (extraneous allocations and copies)
8389
	// PREMATURE optimize test (extraneous iterations - undup)
8390
	UnconditionalFlowInfoTestHarness 
8391
		zero = UnconditionalFlowInfoTestHarness.
8392
				testUnconditionalFlowInfo(new long[] {0,0,0,0}),
8393
		left0, left1, right1, left2, right2, 
8394
		expected0, expected1, expected2, result;
8395
	for (int i = 0; i < testData.length; i++) {
8396
			left0 = UnconditionalFlowInfoTestHarness.
8397
					testUnconditionalFlowInfo(testData[i][0]);
8398
			left1 = UnconditionalFlowInfoTestHarness.
8399
					testUnconditionalFlowInfo(testData[i][0], 64);
8400
			left2 = UnconditionalFlowInfoTestHarness.
8401
				testUnconditionalFlowInfo(testData[i][0], 128);
8402
			right1 = UnconditionalFlowInfoTestHarness.
8403
					testUnconditionalFlowInfo(testData[i][1], 64);
8404
			right2 = UnconditionalFlowInfoTestHarness.
8405
					testUnconditionalFlowInfo(testData[i][1], 128);
8406
			expected0 = UnconditionalFlowInfoTestHarness.
8407
					testUnconditionalFlowInfo(testData[i][2]);
8408
			expected1 = UnconditionalFlowInfoTestHarness.
8409
					testUnconditionalFlowInfo(testData[i][2], 64);
8410
			expected2 = UnconditionalFlowInfoTestHarness.
8411
				testUnconditionalFlowInfo(testData[i][2], 128);
8412
		if (!(result = (UnconditionalFlowInfoTestHarness) 
8413
				left1.copy().addInitializationsFrom(right1)).
8414
					testEquals(expected1)) {
8415
			if (failures == 0) {
8416
				System.out.println(header);
8417
			}
8418
			failures++;
8419
			System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8420
				',' + testStringValueOf(testData[i][1]) +
8421
				',' + result.testString() + 
8422
				"}, // (64, 64) - instead of: " + testStringValueOf(testData[i][2]));
8423
		}
8424
		if ((testData[i][0][0] | testData[i][0][1] | 
8425
				testData[i][0][2] | testData[i][0][3]) == 0) {
8426
			if (!(result = (UnconditionalFlowInfoTestHarness) 
8427
					zero.copy().addInitializationsFrom(right1)).
8428
						testEquals(expected1)) {
8429
				if (failures == 0) {
8430
					System.out.println(header);
8431
				}
8432
				failures++;
8433
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8434
					',' + testStringValueOf(testData[i][1]) +
8435
					',' + result.testString() + 
8436
					"}, // (zero, 64) - instead of: " + testStringValueOf(testData[i][2]));
8437
			}
8438
			if (!(result = (UnconditionalFlowInfoTestHarness) right2.copy().
8439
					addInitializationsFrom(right1)).
8440
						testEquals(expected1, 64)) {
8441
				if (failures == 0) {
8442
					System.out.println(header);
8443
				}
8444
				failures++;
8445
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8446
					',' + testStringValueOf(testData[i][1]) +
8447
					',' + result.testString() + 
8448
					"}, // (zero 128, 64) - instead of: " + testStringValueOf(testData[i][2]));
8449
			}
8450
			if (!(result = (UnconditionalFlowInfoTestHarness) 
8451
					 zero.copy().addInitializationsFrom(right2)).
8452
						testEquals(expected2, 128)) {
8453
				if (failures == 0) {
8454
					System.out.println(header);
8455
				}
8456
				failures++;
8457
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8458
					',' + testStringValueOf(testData[i][1]) +
8459
					',' + result.testString(128) + 
8460
					"}, // (zero, 128) - instead of: " + testStringValueOf(testData[i][2]));
8461
			}
8462
			if (!(result = (UnconditionalFlowInfoTestHarness) 
8463
					 right1.copy().addInitializationsFrom(right2)).
8464
						testEquals(expected2, 128)) {
8465
				if (failures == 0) {
8466
					System.out.println(header);
8467
				}
8468
				failures++;
8469
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8470
					',' + testStringValueOf(testData[i][1]) +
8471
					',' + result.testString(128) + 
8472
					"}, // (zero 64, 128) - instead of: " + testStringValueOf(testData[i][2]));
8473
			}
8474
		}
8475
		if ((testData[i][1][0] | testData[i][1][1] | 
8476
				testData[i][1][2] | testData[i][1][3]) == 0) {
8477
			if (!(result = (UnconditionalFlowInfoTestHarness) 
8478
					left0.copy().addInitializationsFrom(left2)).
8479
						testEquals(expected0, 0)) {
8480
				if (failures == 0) {
8481
					System.out.println(header);
8482
				}
8483
				failures++;
8484
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8485
					',' + testStringValueOf(testData[i][1]) +
8486
					',' + result.testString() + 
8487
					"}, // (1, zero 128) - instead of: " + testStringValueOf(testData[i][2]));
8488
			}
8489
			if (!(result = (UnconditionalFlowInfoTestHarness) 
8490
					left1.copy().addInitializationsFrom(zero)).
8491
						testEquals(expected1)) {
8492
				if (failures == 0) {
8493
					System.out.println(header);
8494
				}
8495
				failures++;
8496
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8497
					',' + testStringValueOf(testData[i][1]) +
8498
					',' + result.testString() + 
8499
					"}, // (64, zero) - instead of: " + testStringValueOf(testData[i][2]));
8500
			}
8501
			if (!(result = (UnconditionalFlowInfoTestHarness) 
8502
					left1.copy().addInitializationsFrom(left2)).
8503
						testEquals(expected1, 64)) {
8504
				if (failures == 0) {
8505
					System.out.println(header);
8506
				}
8507
				failures++;
8508
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8509
					',' + testStringValueOf(testData[i][1]) +
8510
					',' + result.testString() + 
8511
					"}, // (64, zero 128) - instead of: " + testStringValueOf(testData[i][2]));
8512
			}
8513
			if (!(result = (UnconditionalFlowInfoTestHarness) 
8514
					left2.copy().addInitializationsFrom(zero)).
8515
						testEquals(expected2, 128)) {
8516
				if (failures == 0) {
8517
					System.out.println(header);
8518
				}
8519
				failures++;
8520
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8521
					',' + testStringValueOf(testData[i][1]) +
8522
					',' + result.testString() + 
8523
					"}, // (128, zero) - instead of: " + testStringValueOf(testData[i][2]));
8524
			}
8525
			if (!(result = (UnconditionalFlowInfoTestHarness) 
8526
					left2.addInitializationsFrom(left1)).
8527
						testEquals(expected2, 128)) {
8528
				if (failures == 0) {
8529
					System.out.println(header);
8530
				}
8531
				failures++;
8532
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8533
					',' + testStringValueOf(testData[i][1]) +
8534
					',' + result.testString() + 
8535
					"}, // (128, zero 64) - instead of: " + testStringValueOf(testData[i][2]));
8536
			}
8537
		}
8538
	}
8539
	if (printTablesAsNames) {
8540
		System.out.println("RECAP TABLE FOR ADD");
8541
		for (int i = 0; i < testData.length; i++) {
8542
			System.out.println(testSymbolicValueOf(testData[i][0]) + " + " +
8543
				testSymbolicValueOf(testData[i][1]) + " -> " +
8544
				testSymbolicValueOf(testData[i][2]));
8545
		}	
8546
	}
8547
	if (printTablesAsCodes) {
8548
		System.out.println("RECAP TABLE FOR ADD");
8549
		for (int i = 0; i < testData.length; i++) {
8550
			System.out.println(testCodedValueOf(testData[i][0]) + " " +
8551
				testCodedValueOf(testData[i][1]) + " " +
8552
				testCodedValueOf(testData[i][2]));
8553
		}
8554
	}
8555
	if (printTruthMaps) {
8556
		for (int i = 0; i < 4; i++) {
8557
			System.out.println("======================================================");
8558
			System.out.println("Truth map for addInitializationsFrom null bit " + (i + 1));
8559
			System.out.println();
8560
			printTruthMap(testData, i);
8561
		}
8562
	}	
8563
	assertTrue("nb of failures: " + failures, failures == 0);
8564
}
8565
8566
public void test2056_addPotentialInitializationsFrom() {
8567
	long [][][] testData = {
8568
		{{0,0,0,0},{0,0,0,0},{0,0,0,0}},
8569
		{{0,0,0,0},{0,0,0,1},{0,0,0,1}},
8570
		{{0,0,0,0},{0,0,1,0},{0,0,1,0}},
8571
		{{0,0,0,0},{0,0,1,1},{0,0,1,1}},
8572
		{{0,0,0,0},{0,1,0,0},{0,0,0,0}},
8573
		{{0,0,0,0},{0,1,1,0},{0,0,1,0}},
8574
		{{0,0,0,0},{1,0,0,1},{0,0,0,1}},
8575
		{{0,0,0,0},{1,0,1,0},{0,0,1,0}},
8576
		{{0,0,0,0},{1,0,1,1},{0,0,0,1}},
8577
		{{0,0,0,0},{1,1,0,0},{0,0,0,0}},
8578
		{{0,0,0,0},{1,1,0,1},{0,0,0,1}},
8579
		{{0,0,0,1},{0,0,0,0},{0,0,0,1}},
8580
		{{0,0,0,1},{0,0,0,1},{0,0,0,1}},
8581
		{{0,0,0,1},{0,0,1,0},{0,0,1,1}},
8582
		{{0,0,0,1},{0,0,1,1},{0,0,1,1}},
8583
		{{0,0,0,1},{0,1,0,0},{0,0,0,1}},
8584
		{{0,0,0,1},{0,1,1,0},{0,0,1,1}},
8585
		{{0,0,0,1},{1,0,0,1},{0,0,0,1}},
8586
		{{0,0,0,1},{1,0,1,0},{0,0,1,1}},
8587
		{{0,0,0,1},{1,0,1,1},{0,0,0,1}},
8588
		{{0,0,0,1},{1,1,0,0},{0,0,0,1}},
8589
		{{0,0,0,1},{1,1,0,1},{0,0,0,1}},
8590
		{{0,0,1,0},{0,0,0,0},{0,0,1,0}},
8591
		{{0,0,1,0},{0,0,0,1},{0,0,1,1}},
8592
		{{0,0,1,0},{0,0,1,0},{0,0,1,0}},
8593
		{{0,0,1,0},{0,0,1,1},{0,0,1,1}},
8594
		{{0,0,1,0},{0,1,0,0},{0,0,1,0}},
8595
		{{0,0,1,0},{0,1,1,0},{0,0,1,0}},
8596
		{{0,0,1,0},{1,0,0,1},{0,0,1,1}},
8597
		{{0,0,1,0},{1,0,1,0},{0,0,1,0}},
8598
		{{0,0,1,0},{1,0,1,1},{0,0,1,1}},
8599
		{{0,0,1,0},{1,1,0,0},{0,0,1,0}},
8600
		{{0,0,1,0},{1,1,0,1},{0,0,1,1}},
8601
		{{0,0,1,1},{0,0,0,0},{0,0,1,1}},
8602
		{{0,0,1,1},{0,0,0,1},{0,0,1,1}},
8603
		{{0,0,1,1},{0,0,1,0},{0,0,1,1}},
8604
		{{0,0,1,1},{0,0,1,1},{0,0,1,1}},
8605
		{{0,0,1,1},{0,1,0,0},{0,0,1,1}},
8606
		{{0,0,1,1},{0,1,1,0},{0,0,1,1}},
8607
		{{0,0,1,1},{1,0,0,1},{0,0,1,1}},
8608
		{{0,0,1,1},{1,0,1,0},{0,0,1,1}},
8609
		{{0,0,1,1},{1,0,1,1},{0,0,1,1}},
8610
		{{0,0,1,1},{1,1,0,0},{0,0,1,1}},
8611
		{{0,0,1,1},{1,1,0,1},{0,0,1,1}},
8612
		{{0,1,0,0},{0,0,0,0},{0,1,0,0}},
8613
		{{0,1,0,0},{0,0,0,1},{0,0,0,1}},
8614
		{{0,1,0,0},{0,0,1,0},{0,1,1,0}},
8615
		{{0,1,0,0},{0,0,1,1},{0,0,1,1}},
8616
		{{0,1,0,0},{0,1,0,0},{0,1,0,0}},
8617
		{{0,1,0,0},{0,1,1,0},{0,1,1,0}},
8618
		{{0,1,0,0},{1,0,0,1},{0,0,0,1}},
8619
		{{0,1,0,0},{1,0,1,0},{0,1,1,0}},
8620
		{{0,1,0,0},{1,0,1,1},{0,0,0,1}},
8621
		{{0,1,0,0},{1,1,0,0},{0,1,0,0}},
8622
		{{0,1,0,0},{1,1,0,1},{0,0,0,1}},
8623
		{{0,1,1,0},{0,0,0,0},{0,1,1,0}},
8624
		{{0,1,1,0},{0,0,0,1},{0,0,1,1}},
8625
		{{0,1,1,0},{0,0,1,0},{0,1,1,0}},
8626
		{{0,1,1,0},{0,0,1,1},{0,0,1,1}},
8627
		{{0,1,1,0},{0,1,0,0},{0,1,1,0}},
8628
		{{0,1,1,0},{0,1,1,0},{0,1,1,0}},
8629
		{{0,1,1,0},{1,0,0,1},{0,0,1,1}},
8630
		{{0,1,1,0},{1,0,1,0},{0,1,1,0}},
8631
		{{0,1,1,0},{1,0,1,1},{0,0,1,1}},
8632
		{{0,1,1,0},{1,1,0,0},{0,1,1,0}},
8633
		{{0,1,1,0},{1,1,0,1},{0,0,1,1}},
8634
		{{1,0,0,1},{0,0,0,0},{1,0,0,1}},
8635
		{{1,0,0,1},{0,0,0,1},{1,0,1,1}},
8636
		{{1,0,0,1},{0,0,1,0},{0,0,1,1}},
8637
		{{1,0,0,1},{0,0,1,1},{0,0,1,1}},
8638
		{{1,0,0,1},{0,1,0,0},{1,0,0,1}},
8639
		{{1,0,0,1},{0,1,1,0},{0,0,1,1}},
8640
		{{1,0,0,1},{1,0,0,1},{1,0,0,1}},
8641
		{{1,0,0,1},{1,0,1,0},{0,0,1,1}},
8642
		{{1,0,0,1},{1,0,1,1},{1,0,1,1}},
8643
		{{1,0,0,1},{1,1,0,0},{1,0,0,1}},
8644
		{{1,0,0,1},{1,1,0,1},{1,0,0,1}},
8645
		{{1,0,1,0},{0,0,0,0},{1,0,1,0}},
8646
		{{1,0,1,0},{0,0,0,1},{0,0,1,1}},
8647
		{{1,0,1,0},{0,0,1,0},{1,0,1,0}},
8648
		{{1,0,1,0},{0,0,1,1},{0,0,1,1}},
8649
		{{1,0,1,0},{0,1,0,0},{1,0,1,0}},
8650
		{{1,0,1,0},{0,1,1,0},{1,0,1,0}},
8651
		{{1,0,1,0},{1,0,0,1},{0,0,1,1}},
8652
		{{1,0,1,0},{1,0,1,0},{1,0,1,0}},
8653
		{{1,0,1,0},{1,0,1,1},{0,0,1,1}},
8654
		{{1,0,1,0},{1,1,0,0},{1,0,1,0}},
8655
		{{1,0,1,0},{1,1,0,1},{0,0,1,1}},
8656
		{{1,0,1,1},{0,0,0,0},{1,0,1,1}},
8657
		{{1,0,1,1},{0,0,0,1},{1,0,1,1}},
8658
		{{1,0,1,1},{0,0,1,0},{0,0,1,1}},
8659
		{{1,0,1,1},{0,0,1,1},{0,0,1,1}},
8660
		{{1,0,1,1},{0,1,0,0},{1,0,1,1}},
8661
		{{1,0,1,1},{0,1,1,0},{0,0,1,1}},
8662
		{{1,0,1,1},{1,0,0,1},{1,0,1,1}},
8663
		{{1,0,1,1},{1,0,1,0},{0,0,1,1}},
8664
		{{1,0,1,1},{1,0,1,1},{1,0,1,1}},
8665
		{{1,0,1,1},{1,1,0,0},{1,0,1,1}},
8666
		{{1,0,1,1},{1,1,0,1},{1,0,1,1}},
8667
		{{1,1,0,0},{0,0,0,0},{1,1,0,0}},
8668
		{{1,1,0,0},{0,0,0,1},{0,0,0,1}},
8669
		{{1,1,0,0},{0,0,1,0},{0,0,1,0}},
8670
		{{1,1,0,0},{0,0,1,1},{0,0,1,1}},
8671
		{{1,1,0,0},{0,1,0,0},{1,1,0,0}},
8672
		{{1,1,0,0},{0,1,1,0},{0,0,1,0}},
8673
		{{1,1,0,0},{1,0,0,1},{0,0,0,1}},
8674
		{{1,1,0,0},{1,0,1,0},{0,0,1,0}},
8675
		{{1,1,0,0},{1,0,1,1},{0,0,0,1}},
8676
		{{1,1,0,0},{1,1,0,0},{1,1,0,0}},
8677
		{{1,1,0,0},{1,1,0,1},{1,1,0,1}},
8678
		{{1,1,0,1},{0,0,0,0},{1,1,0,1}},
8679
		{{1,1,0,1},{0,0,0,1},{0,0,0,1}},
8680
		{{1,1,0,1},{0,0,1,0},{0,0,1,1}},
8681
		{{1,1,0,1},{0,0,1,1},{0,0,1,1}},
8682
		{{1,1,0,1},{0,1,0,0},{1,1,0,1}},
8683
		{{1,1,0,1},{0,1,1,0},{0,0,1,1}},
8684
		{{1,1,0,1},{1,0,0,1},{0,0,0,1}},
8685
		{{1,1,0,1},{1,0,1,0},{0,0,1,1}},
8686
		{{1,1,0,1},{1,0,1,1},{0,0,0,1}},
8687
		{{1,1,0,1},{1,1,0,0},{1,1,0,1}},
8688
		{{1,1,0,1},{1,1,0,1},{1,1,0,1}},
8689
	};
8690
	int failures = 0;
8691
	long start;
8692
	if (combinationTestsloopsNb > 1) {
8693
		start = System.currentTimeMillis();
8694
	}
8695
	String header = "addPotentialInitializationsFrom failures: "; //$NON-NLS-1$
8696
	for (int l = 0; l < combinationTestsloopsNb ; l++) {
8697
		for (int i = 0; i < testData.length; i++) {
8698
			UnconditionalFlowInfoTestHarness result;
8699
			if (!(result = (UnconditionalFlowInfoTestHarness)(
8700
					UnconditionalFlowInfoTestHarness.
8701
						testUnconditionalFlowInfo(testData[i][0])).
8702
							addPotentialInitializationsFrom(
8703
								UnconditionalFlowInfoTestHarness.
8704
									testUnconditionalFlowInfo(testData[i][1]))).
8705
					testEquals(UnconditionalFlowInfoTestHarness.
8706
						testUnconditionalFlowInfo(testData[i][2]))) {
8707
				if (failures == 0) {
8708
					System.out.println(header);
8709
				}
8710
				failures++;
8711
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8712
					',' + testStringValueOf(testData[i][1]) +
8713
					',' + result.testString() + 
8714
					"}, // instead of: " + testStringValueOf(testData[i][2]));
8715
			}
8716
			if (combinationTestsloopsNb < 2 && 
8717
					!(result = (UnconditionalFlowInfoTestHarness)(
8718
							UnconditionalFlowInfoTestHarness.
8719
							testUnconditionalFlowInfo(testData[i][0])).
8720
								addPotentialNullInfoFrom(
8721
										UnconditionalFlowInfoTestHarness.
8722
											testUnconditionalFlowInfo(testData[i][1], 128))).
8723
					testEquals(UnconditionalFlowInfoTestHarness.
8724
						testUnconditionalFlowInfo(testData[14][0], 65), 64)) {
8725
				if (failures == 0) {
8726
					System.out.println(header);
8727
				}
8728
				failures++;
8729
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8730
					',' + testStringValueOf(testData[i][1]) +
8731
					',' + result.testString(64) + 
8732
					"}, // bit 64 only, instead of: {0,0,0,0}");
8733
			}
8734
		}
8735
	}
8736
	if (combinationTestsloopsNb > 1) {
8737
		System.out.println("addPotential...\t" + combinationTestsloopsNb + "\t" + 
8738
				(System.currentTimeMillis() - start));
8739
	}
8740
	UnconditionalFlowInfoTestHarness 
8741
		zero = UnconditionalFlowInfoTestHarness.
8742
				testUnconditionalFlowInfo(new long[] {0,0,0,0}),
8743
		left0, left1, right1, left2, right2, 
8744
		expected0, expected1, expected2, result;
8745
	for (int i = 0; i < testData.length; i++) {
8746
			left0 = UnconditionalFlowInfoTestHarness.
8747
						testUnconditionalFlowInfo(testData[i][0]);
8748
			left1 = UnconditionalFlowInfoTestHarness.
8749
						testUnconditionalFlowInfo(testData[i][0], 64);
8750
			left2 = UnconditionalFlowInfoTestHarness.
8751
						testUnconditionalFlowInfo(testData[i][0], 128);
8752
			right1 = UnconditionalFlowInfoTestHarness.
8753
						testUnconditionalFlowInfo(testData[i][1], 64);
8754
			right2 = UnconditionalFlowInfoTestHarness.
8755
						testUnconditionalFlowInfo(testData[i][1], 128);
8756
			expected0 = UnconditionalFlowInfoTestHarness.
8757
							testUnconditionalFlowInfo(testData[i][2]);
8758
			expected1 = UnconditionalFlowInfoTestHarness.
8759
							testUnconditionalFlowInfo(testData[i][2], 64);
8760
			expected2 = UnconditionalFlowInfoTestHarness.
8761
							testUnconditionalFlowInfo(testData[i][2], 128);
8762
		if (!(result = (UnconditionalFlowInfoTestHarness) 
8763
				left1.copy().addPotentialInitializationsFrom(right1)).
8764
					testEquals(expected1)) {
8765
			if (failures == 0) {
8766
				System.out.println(header);
8767
			}
8768
			failures++;
8769
			System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8770
				',' + testStringValueOf(testData[i][1]) +
8771
				',' + result.testString() + 
8772
				"}, // (64, 64) - instead of: " + testStringValueOf(testData[i][2]));
8773
		}
8774
		if (testData[i][0][0] + testData[i][0][1] + 
8775
				testData[i][0][2] + testData[i][0][3] == 0) {
8776
			if (!(result = (UnconditionalFlowInfoTestHarness)
8777
					zero.copy().addPotentialInitializationsFrom(right1)).
8778
						testEquals(expected1)) {
8779
				if (failures == 0) {
8780
					System.out.println(header);
8781
				}
8782
				failures++;
8783
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8784
					',' + testStringValueOf(testData[i][1]) +
8785
					',' + result.testString() + 
8786
					"}, // (zero, 64) - instead of: " + testStringValueOf(testData[i][2]));
8787
			}
8788
			if (!(result = (UnconditionalFlowInfoTestHarness) 
8789
					right2.copy().addPotentialInitializationsFrom(right1)).
8790
						testEquals(expected1, 64)) {
8791
				if (failures == 0) {
8792
					System.out.println(header);
8793
				}
8794
				failures++;
8795
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8796
					',' + testStringValueOf(testData[i][1]) +
8797
					',' + result.testString() + 
8798
					"}, // (zero 128, 64) - instead of: " + testStringValueOf(testData[i][2]));
8799
			}
8800
			if (!(result = (UnconditionalFlowInfoTestHarness)
8801
					(UnconditionalFlowInfoTestHarness.
8802
							testUnconditionalFlowInfo(new long[] {0,0,0,0}, 64)).
8803
								// make just in time to get the needed structure
8804
								addPotentialNullInfoFrom(right2)).
8805
									testEquals(expected2, 128)) {
8806
				if (failures == 0) {
8807
					System.out.println(header);
8808
				}
8809
				failures++;
8810
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8811
					',' + testStringValueOf(testData[i][1]) +
8812
					',' + result.testString() + 
8813
					"}, // (zero extra, 128) null only - instead of: " + testStringValueOf(testData[i][2]));
8814
			}
8815
			if (!(result = (UnconditionalFlowInfoTestHarness) 
8816
					((UnconditionalFlowInfo)right2.copy()).
8817
						addPotentialNullInfoFrom(right1)).
8818
							testEquals(expected1, 64)) {
8819
				if (failures == 0) {
8820
					System.out.println(header);
8821
				}
8822
				failures++;
8823
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8824
					',' + testStringValueOf(testData[i][1]) +
8825
					',' + result.testString() + 
8826
					"}, // (zero 128, 64) null only - instead of: " + testStringValueOf(testData[i][2]));
8827
			}
8828
			if (!(result = (UnconditionalFlowInfoTestHarness) 
8829
					 ((UnconditionalFlowInfo)zero.copy()).
8830
					 	addPotentialNullInfoFrom(right2)).
8831
					 		testEquals(expected2, 128)) {
8832
				if (failures == 0) {
8833
					System.out.println(header);
8834
				}
8835
				failures++;
8836
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8837
					',' + testStringValueOf(testData[i][1]) +
8838
					',' + result.testString(128) + 
8839
					"}, // (zero, 128) null only - instead of: " + testStringValueOf(testData[i][2]));
8840
			}
8841
			if (!(result = (UnconditionalFlowInfoTestHarness) 
8842
					 ((UnconditionalFlowInfo)right1.copy()).
8843
					 	addPotentialNullInfoFrom(right2)).
8844
					 		testEquals(expected2, 128)) {
8845
				if (failures == 0) {
8846
					System.out.println(header);
8847
				}
8848
				failures++;
8849
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8850
					',' + testStringValueOf(testData[i][1]) +
8851
					',' + result.testString(128) + 
8852
					"}, // (zero 64, 128) null only - instead of: " + testStringValueOf(testData[i][2]));
8853
			}		}
8854
		if (testData[i][1][0] + testData[i][1][1] + 
8855
				testData[i][1][2] + testData[i][1][3] == 0) {
8856
			if (!(result = (UnconditionalFlowInfoTestHarness) 
8857
					((UnconditionalFlowInfoTestHarness)left0.copy()).
8858
						addPotentialNullInfoFrom(left2)).
8859
							testEquals(expected0, 1)) {
8860
				if (failures == 0) {
8861
					System.out.println(header);
8862
				}
8863
				failures++;
8864
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8865
					',' + testStringValueOf(testData[i][1]) +
8866
					',' + result.testString() + 
8867
					"}, // (1, zero 128) null only - instead of: " + testStringValueOf(testData[i][2]));
8868
			}
8869
			if (!(result = (UnconditionalFlowInfoTestHarness)
8870
					left1.copy().addPotentialInitializationsFrom(zero)).
8871
						testEquals(expected1)) {
8872
				if (failures == 0) {
8873
					System.out.println(header);
8874
				}
8875
				failures++;
8876
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8877
					',' + testStringValueOf(testData[i][1]) +
8878
					',' + result.testString() + 
8879
					"}, // (64, zero) - instead of: " + testStringValueOf(testData[i][2]));
8880
			}
8881
			if (!(result = (UnconditionalFlowInfoTestHarness)
8882
					left1.copy().addPotentialInitializationsFrom(left2)).
8883
						testEquals(expected1, 64)) {
8884
				if (failures == 0) {
8885
					System.out.println(header);
8886
				}
8887
				failures++;
8888
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8889
					',' + testStringValueOf(testData[i][1]) +
8890
					',' + result.testString() + 
8891
					"}, // (64, zero 128) - instead of: " + testStringValueOf(testData[i][2]));
8892
			}
8893
			if (!(result = (UnconditionalFlowInfoTestHarness) 
8894
					((UnconditionalFlowInfo)left1.copy()).
8895
						addPotentialNullInfoFrom(left2)).
8896
							testEquals(expected1, 64)) {
8897
				if (failures == 0) {
8898
					System.out.println(header);
8899
				}
8900
				failures++;
8901
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8902
					',' + testStringValueOf(testData[i][1]) +
8903
					',' + result.testString() + 
8904
					"}, // (64, zero 128) null only - instead of: " + testStringValueOf(testData[i][2]));
8905
			}
8906
			if (!(result = (UnconditionalFlowInfoTestHarness) 
8907
					((UnconditionalFlowInfo)left2.copy()).
8908
						addPotentialNullInfoFrom(zero)).
8909
							testEquals(expected2, 128)) {
8910
				if (failures == 0) {
8911
					System.out.println(header);
8912
				}
8913
				failures++;
8914
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8915
					',' + testStringValueOf(testData[i][1]) +
8916
					',' + result.testString() + 
8917
					"}, // (128, zero) null only - instead of: " + testStringValueOf(testData[i][2]));
8918
			}
8919
			if (!(result = (UnconditionalFlowInfoTestHarness) 
8920
					left2.addPotentialNullInfoFrom(left1)).
8921
						testEquals(expected2, 128)) {
8922
				if (failures == 0) {
8923
					System.out.println(header);
8924
				}
8925
				failures++;
8926
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
8927
					',' + testStringValueOf(testData[i][1]) +
8928
					',' + result.testString() + 
8929
					"}, // (128, zero 64) null only - instead of: " + testStringValueOf(testData[i][2]));
8930
			}
8931
		}
8932
	}
8933
	if (printTablesAsNames) {
8934
		System.out.println("RECAP TABLE FOR ADD POTENTIAL");
8935
		for (int i = 0; i < testData.length; i++) {
8936
			System.out.println(testSymbolicValueOf(testData[i][0]) + " + " +
8937
				testSymbolicValueOf(testData[i][1]) + " -> " +
8938
				testSymbolicValueOf(testData[i][2]));
8939
		}
8940
	}
8941
	if (printTablesAsCodes) {
8942
		System.out.println("RECAP TABLE FOR ADD POTENTIAL");
8943
		for (int i = 0; i < testData.length; i++) {
8944
			System.out.println(testCodedValueOf(testData[i][0]) + " " +
8945
				testCodedValueOf(testData[i][1]) + " " +
8946
				testCodedValueOf(testData[i][2]));
8947
		}
8948
	}
8949
	if (printTruthMaps) {
8950
		for (int i = 0; i < 4; i++) {
8951
			System.out.println("======================================================");
8952
			System.out.println("Truth map for addPotentialInitializationsFrom null bit " + (i + 1));
8953
			System.out.println();
8954
		}
8955
	}	
8956
	assertTrue("nb of failures: " + failures, failures == 0);
8957
}
8958
8959
public void test2057_mergedWith() {
8960
	long [][][] testData = {
8961
		{{0,0,0,0},{0,0,0,0},{0,0,0,0}},
8962
		{{0,0,0,0},{0,0,0,1},{0,0,0,1}},
8963
		{{0,0,0,0},{0,0,1,0},{0,0,1,0}},
8964
		{{0,0,0,0},{0,0,1,1},{0,0,1,1}},
8965
		{{0,0,0,0},{0,1,0,0},{0,0,1,0}},
8966
		{{0,0,0,0},{0,1,1,0},{0,0,1,0}},
8967
		{{0,0,0,0},{1,0,0,1},{0,0,0,1}},
8968
		{{0,0,0,0},{1,0,1,0},{0,0,1,0}},
8969
		{{0,0,0,0},{1,0,1,1},{0,0,0,1}},
8970
		{{0,0,0,0},{1,1,0,0},{0,0,0,0}},
8971
		{{0,0,0,0},{1,1,0,1},{0,0,0,1}},
8972
		{{0,0,0,1},{0,0,0,0},{0,0,0,1}},
8973
		{{0,0,0,1},{0,0,0,1},{0,0,0,1}},
8974
		{{0,0,0,1},{0,0,1,0},{0,0,1,1}},
8975
		{{0,0,0,1},{0,0,1,1},{0,0,1,1}},
8976
		{{0,0,0,1},{0,1,0,0},{0,0,1,1}},
8977
		{{0,0,0,1},{0,1,1,0},{0,0,1,1}},
8978
		{{0,0,0,1},{1,0,0,1},{0,0,0,1}},
8979
		{{0,0,0,1},{1,0,1,0},{0,0,1,1}},
8980
		{{0,0,0,1},{1,0,1,1},{0,0,0,1}},
8981
		{{0,0,0,1},{1,1,0,0},{0,0,0,1}},
8982
		{{0,0,0,1},{1,1,0,1},{0,0,0,1}},
8983
		{{0,0,1,0},{0,0,0,0},{0,0,1,0}},
8984
		{{0,0,1,0},{0,0,0,1},{0,0,1,1}},
8985
		{{0,0,1,0},{0,0,1,0},{0,0,1,0}},
8986
		{{0,0,1,0},{0,0,1,1},{0,0,1,1}},
8987
		{{0,0,1,0},{0,1,0,0},{0,0,1,0}},
8988
		{{0,0,1,0},{0,1,1,0},{0,0,1,0}},
8989
		{{0,0,1,0},{1,0,0,1},{0,0,1,1}},
8990
		{{0,0,1,0},{1,0,1,0},{0,0,1,0}},
8991
		{{0,0,1,0},{1,0,1,1},{0,0,1,1}},
8992
		{{0,0,1,0},{1,1,0,0},{0,0,1,0}},
8993
		{{0,0,1,0},{1,1,0,1},{0,0,1,1}},
8994
		{{0,0,1,1},{0,0,0,0},{0,0,1,1}},
8995
		{{0,0,1,1},{0,0,0,1},{0,0,1,1}},
8996
		{{0,0,1,1},{0,0,1,0},{0,0,1,1}},
8997
		{{0,0,1,1},{0,0,1,1},{0,0,1,1}},
8998
		{{0,0,1,1},{0,1,0,0},{0,0,1,1}},
8999
		{{0,0,1,1},{0,1,1,0},{0,0,1,1}},
9000
		{{0,0,1,1},{1,0,0,1},{0,0,1,1}},
9001
		{{0,0,1,1},{1,0,1,0},{0,0,1,1}},
9002
		{{0,0,1,1},{1,0,1,1},{0,0,1,1}},
9003
		{{0,0,1,1},{1,1,0,0},{0,0,1,1}},
9004
		{{0,0,1,1},{1,1,0,1},{0,0,1,1}},
9005
		{{0,1,0,0},{0,0,0,0},{0,0,1,0}},
9006
		{{0,1,0,0},{0,0,0,1},{0,0,1,1}},
9007
		{{0,1,0,0},{0,0,1,0},{0,0,1,0}},
9008
		{{0,1,0,0},{0,0,1,1},{0,0,1,1}},
9009
		{{0,1,0,0},{0,1,0,0},{0,1,0,0}},
9010
		{{0,1,0,0},{0,1,1,0},{0,1,1,0}},
9011
		{{0,1,0,0},{1,0,0,1},{0,0,0,1}},
9012
		{{0,1,0,0},{1,0,1,0},{0,1,1,0}},
9013
		{{0,1,0,0},{1,0,1,1},{0,0,1,1}},
9014
		{{0,1,0,0},{1,1,0,0},{0,0,1,0}},
9015
		{{0,1,0,0},{1,1,0,1},{0,0,1,1}},
9016
		{{0,1,1,0},{0,0,0,0},{0,0,1,0}},
9017
		{{0,1,1,0},{0,0,0,1},{0,0,1,1}},
9018
		{{0,1,1,0},{0,0,1,0},{0,0,1,0}},
9019
		{{0,1,1,0},{0,0,1,1},{0,0,1,1}},
9020
		{{0,1,1,0},{0,1,0,0},{0,1,1,0}},
9021
		{{0,1,1,0},{0,1,1,0},{0,1,1,0}},
9022
		{{0,1,1,0},{1,0,0,1},{0,0,1,1}},
9023
		{{0,1,1,0},{1,0,1,0},{0,1,1,0}},
9024
		{{0,1,1,0},{1,0,1,1},{0,0,1,1}},
9025
		{{0,1,1,0},{1,1,0,0},{0,0,1,0}},
9026
		{{0,1,1,0},{1,1,0,1},{0,0,1,1}},
9027
		{{1,0,0,1},{0,0,0,0},{0,0,0,1}},
9028
		{{1,0,0,1},{0,0,0,1},{0,0,0,1}},
9029
		{{1,0,0,1},{0,0,1,0},{0,0,1,1}},
9030
		{{1,0,0,1},{0,0,1,1},{0,0,1,1}},
9031
		{{1,0,0,1},{0,1,0,0},{0,0,0,1}},
9032
		{{1,0,0,1},{0,1,1,0},{0,0,1,1}},
9033
		{{1,0,0,1},{1,0,0,1},{1,0,0,1}},
9034
		{{1,0,0,1},{1,0,1,0},{0,0,1,1}},
9035
		{{1,0,0,1},{1,0,1,1},{1,0,1,1}},
9036
		{{1,0,0,1},{1,1,0,0},{1,1,0,1}},
9037
		{{1,0,0,1},{1,1,0,1},{1,1,0,1}},
9038
		{{1,0,1,0},{0,0,0,0},{0,0,1,0}},
9039
		{{1,0,1,0},{0,0,0,1},{0,0,1,1}},
9040
		{{1,0,1,0},{0,0,1,0},{0,0,1,0}},
9041
		{{1,0,1,0},{0,0,1,1},{0,0,1,1}},
9042
		{{1,0,1,0},{0,1,0,0},{0,1,1,0}},
9043
		{{1,0,1,0},{0,1,1,0},{0,1,1,0}},
9044
		{{1,0,1,0},{1,0,0,1},{0,0,1,1}},
9045
		{{1,0,1,0},{1,0,1,0},{1,0,1,0}},
9046
		{{1,0,1,0},{1,0,1,1},{0,0,1,1}},
9047
		{{1,0,1,0},{1,1,0,0},{0,0,1,0}},
9048
		{{1,0,1,0},{1,1,0,1},{0,0,1,1}},
9049
		{{1,0,1,1},{0,0,0,0},{0,0,0,1}},
9050
		{{1,0,1,1},{0,0,0,1},{0,0,0,1}},
9051
		{{1,0,1,1},{0,0,1,0},{0,0,1,1}},
9052
		{{1,0,1,1},{0,0,1,1},{0,0,1,1}},
9053
		{{1,0,1,1},{0,1,0,0},{0,0,1,1}},
9054
		{{1,0,1,1},{0,1,1,0},{0,0,1,1}},
9055
		{{1,0,1,1},{1,0,0,1},{1,0,1,1}},
9056
		{{1,0,1,1},{1,0,1,0},{0,0,1,1}},
9057
		{{1,0,1,1},{1,0,1,1},{1,0,1,1}},
9058
		{{1,0,1,1},{1,1,0,0},{0,0,0,1}},
9059
		{{1,0,1,1},{1,1,0,1},{0,0,0,1}},
9060
		{{1,1,0,0},{0,0,0,0},{0,0,0,0}},
9061
		{{1,1,0,0},{0,0,0,1},{0,0,0,1}},
9062
		{{1,1,0,0},{0,0,1,0},{0,0,1,0}},
9063
		{{1,1,0,0},{0,0,1,1},{0,0,1,1}},
9064
		{{1,1,0,0},{0,1,0,0},{0,0,1,0}},
9065
		{{1,1,0,0},{0,1,1,0},{0,0,1,0}},
9066
		{{1,1,0,0},{1,0,0,1},{1,1,0,1}},
9067
		{{1,1,0,0},{1,0,1,0},{0,0,1,0}},
9068
		{{1,1,0,0},{1,0,1,1},{0,0,0,1}},
9069
		{{1,1,0,0},{1,1,0,0},{1,1,0,0}},
9070
		{{1,1,0,0},{1,1,0,1},{1,1,0,1}},
9071
		{{1,1,0,1},{0,0,0,0},{0,0,0,1}},
9072
		{{1,1,0,1},{0,0,0,1},{0,0,0,1}},
9073
		{{1,1,0,1},{0,0,1,0},{0,0,1,1}},
9074
		{{1,1,0,1},{0,0,1,1},{0,0,1,1}},
9075
		{{1,1,0,1},{0,1,0,0},{0,0,1,1}},
9076
		{{1,1,0,1},{0,1,1,0},{0,0,1,1}},
9077
		{{1,1,0,1},{1,0,0,1},{1,1,0,1}},
9078
		{{1,1,0,1},{1,0,1,0},{0,0,1,1}},
9079
		{{1,1,0,1},{1,0,1,1},{0,0,0,1}},
9080
		{{1,1,0,1},{1,1,0,0},{1,1,0,1}},
9081
		{{1,1,0,1},{1,1,0,1},{1,1,0,1}}
9082
	};
9083
	int failures = 0;
9084
	long start;
9085
	if (combinationTestsloopsNb > 1) {
9086
		start = System.currentTimeMillis();
9087
	}
9088
	String header = "mergedWith failures: ";
9089
	for (int l = 0; l < combinationTestsloopsNb ; l++) {
9090
		for (int i = 0; i < testData.length; i++) {
9091
			UnconditionalFlowInfoTestHarness result;
9092
			if (!(result = (UnconditionalFlowInfoTestHarness)
9093
					UnconditionalFlowInfoTestHarness.
9094
						testUnconditionalFlowInfo(testData[i][0]).
9095
							mergedWith(
9096
								UnconditionalFlowInfoTestHarness.
9097
									testUnconditionalFlowInfo(testData[i][1]))).
9098
					testEquals(UnconditionalFlowInfoTestHarness.
9099
						testUnconditionalFlowInfo(testData[i][2]))) {
9100
				if (failures == 0) {
9101
					System.out.println(header);
9102
				}
9103
				failures++;
9104
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
9105
					',' + testStringValueOf(testData[i][1]) +
9106
					',' + result.testString() + 
9107
					"}, // instead of: " + testStringValueOf(testData[i][2]));
9108
			}
9109
		}
9110
	}
9111
	if (combinationTestsloopsNb > 1) {
9112
		System.out.println("mergedWith\t\t\t" + combinationTestsloopsNb + "\t" + 
9113
				(System.currentTimeMillis() - start));
9114
	}
9115
	UnconditionalFlowInfoTestHarness 
9116
		zero = UnconditionalFlowInfoTestHarness.
9117
				testUnconditionalFlowInfo(new long[] {0,0,0,0}),
9118
		left1, right1, left2, right2, 
9119
		expected1, expected2, result;
9120
	for (int i = 0; i < testData.length; i++) {
9121
		left1 = UnconditionalFlowInfoTestHarness.
9122
				testUnconditionalFlowInfo(testData[i][0], 64);
9123
		left2 = UnconditionalFlowInfoTestHarness.
9124
			testUnconditionalFlowInfo(testData[i][0], 128);
9125
		right1 = UnconditionalFlowInfoTestHarness.
9126
				testUnconditionalFlowInfo(testData[i][1], 64);
9127
		right2 = UnconditionalFlowInfoTestHarness.
9128
				testUnconditionalFlowInfo(testData[i][1], 128);
9129
		expected1 = UnconditionalFlowInfoTestHarness.
9130
				testUnconditionalFlowInfo(testData[i][2], 64);
9131
		expected2 = UnconditionalFlowInfoTestHarness.
9132
			testUnconditionalFlowInfo(testData[i][2], 128);
9133
		if (!(result = (UnconditionalFlowInfoTestHarness) 
9134
				left1.copy().mergedWith(right1)).testEquals(expected1)) {
9135
			if (failures == 0) {
9136
				System.out.println(header);
9137
			}
9138
			failures++;
9139
			System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
9140
				',' + testStringValueOf(testData[i][1]) +
9141
				',' + result.testString() + 
9142
				"}, // (64, 64) - instead of: " + testStringValueOf(testData[i][2]));
9143
		}
9144
		if (testData[i][0][0] + testData[i][0][1] + 
9145
				testData[i][0][2] + testData[i][0][3] == 0) {
9146
			if (!(result = (UnconditionalFlowInfoTestHarness) 
9147
					zero.copy().mergedWith(right1)).testEquals(expected1)) {
9148
				if (failures == 0) {
9149
					System.out.println(header);
9150
				}
9151
				failures++;
9152
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
9153
					',' + testStringValueOf(testData[i][1]) +
9154
					',' + result.testString() + 
9155
					"}, // (zero, 64) - instead of: " + testStringValueOf(testData[i][2]));
9156
			}
9157
			if (!(result = (UnconditionalFlowInfoTestHarness)
9158
					right2.copy().mergedWith(right1)).
9159
						testEquals(expected1, 64)) {
9160
				if (failures == 0) {
9161
					System.out.println(header);
9162
				}
9163
				failures++;
9164
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
9165
					',' + testStringValueOf(testData[i][1]) +
9166
					',' + result.testString() + 
9167
					"}, // (zero 128, 64) - instead of: " + testStringValueOf(testData[i][2]));
9168
			}
9169
			if (!(result = (UnconditionalFlowInfoTestHarness)
9170
					zero.copy().mergedWith(right2)).
9171
						testEquals(expected2, 128)) {
9172
				if (failures == 0) {
9173
					System.out.println(header);
9174
				}
9175
				failures++;
9176
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
9177
					',' + testStringValueOf(testData[i][1]) +
9178
					',' + result.testString() + 
9179
					"}, // (zero, 128) - instead of: " + testStringValueOf(testData[i][2]));
9180
			}
9181
			if (!(result = (UnconditionalFlowInfoTestHarness)
9182
					right1.copy().mergedWith(right2)).
9183
						testEquals(expected2, 128)) {
9184
				if (failures == 0) {
9185
					System.out.println(header);
9186
				}
9187
				failures++;
9188
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
9189
					',' + testStringValueOf(testData[i][1]) +
9190
					',' + result.testString() + 
9191
					"}, // (zero 64, 128) - instead of: " + testStringValueOf(testData[i][2]));
9192
			}
9193
		}
9194
		if (testData[i][1][0] + testData[i][1][1] + 
9195
				testData[i][1][2] + testData[i][1][3] == 0) {
9196
			if (!(result = (UnconditionalFlowInfoTestHarness) 
9197
					left1.copy().mergedWith(zero)).testEquals(expected1)) {
9198
				if (failures == 0) {
9199
					System.out.println(header);
9200
				}
9201
				failures++;
9202
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
9203
					',' + testStringValueOf(testData[i][1]) +
9204
					',' + result.testString() + 
9205
					"}, // (64, zero) - instead of: " + testStringValueOf(testData[i][2]));
9206
			}
9207
			if (!(result = (UnconditionalFlowInfoTestHarness)
9208
					left1.mergedWith(left2)).
9209
						testEquals(expected1, 64)) {
9210
				if (failures == 0) {
9211
					System.out.println(header);
9212
				}
9213
				failures++;
9214
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
9215
					',' + testStringValueOf(testData[i][1]) +
9216
					',' + result.testString() + 
9217
					"}, // (64, zero 128) - instead of: " + testStringValueOf(testData[i][2]));
9218
			}
9219
			if (!(result = (UnconditionalFlowInfoTestHarness) 
9220
					left2.copy().mergedWith(zero)).
9221
						testEquals(expected2, 128)) {
9222
				if (failures == 0) {
9223
					System.out.println(header);
9224
				}
9225
				failures++;
9226
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
9227
					',' + testStringValueOf(testData[i][1]) +
9228
					',' + result.testString() + 
9229
					"}, // (128, zero) - instead of: " + testStringValueOf(testData[i][2]));
9230
			}
9231
			if (!(result = (UnconditionalFlowInfoTestHarness) 
9232
					left2.mergedWith(left1)).
9233
						testEquals(expected2, 128)) {
9234
				if (failures == 0) {
9235
					System.out.println(header);
9236
				}
9237
				failures++;
9238
				System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + 
9239
					',' + testStringValueOf(testData[i][1]) +
9240
					',' + result.testString() + 
9241
					"}, // (128, zero 64) - instead of: " + testStringValueOf(testData[i][2]));
9242
			}
9243
		}
9244
	}
9245
	if (printTablesAsNames) {
9246
		System.out.println("RECAP TABLE FOR MERGE");
9247
		for (int i = 0; i < testData.length; i++) {
9248
			System.out.println(testSymbolicValueOf(testData[i][0]) + " + " +
9249
				testSymbolicValueOf(testData[i][1]) + " -> " +
9250
				testSymbolicValueOf(testData[i][2]));
9251
		}
9252
		
9253
	}
9254
	if (printTablesAsCodes) {
9255
		System.out.println("RECAP TABLE FOR MERGE");
9256
		for (int i = 0; i < testData.length; i++) {
9257
			System.out.println(testCodedValueOf(testData[i][0]) + " " +
9258
				testCodedValueOf(testData[i][1]) + " " +
9259
				testCodedValueOf(testData[i][2]));
9260
		}
9261
	}
9262
	if (printTruthMaps) {
9263
		for (int i = 0; i < 4; i++) {
9264
			System.out.println("======================================================");
9265
			System.out.println("Truth map for mergedWith null bit " + (i + 1));
9266
			System.out.println();
9267
		}
9268
	}
9269
	assertTrue("nb of failures: " + failures, failures == 0);
9270
}
9271
9272
// Use for coverage tests only. Needs specific instrumentation of code,
9273
// that is controled by UnconditionalFlowInfo#coverageTestFlag.
9274
// Note: coverage tests tend to fill the console with messages, and the
9275
//       instrumented code is slower, so never release code with active
9276
//       coverage tests.
9277
private static int coveragePointsNb = 46;
9278
9279
// Coverage by state transition tables methods.
9280
public void test2998_coverage() {
9281
	if (UnconditionalFlowInfo.coverageTestFlag) {
9282
		// sanity check: need to be sure that the tests execute properly when not
9283
		// trying to check coverage
9284
		UnconditionalFlowInfo.coverageTestId = 0;
9285
		test0053_array();
9286
		test0070_type_reference();
9287
		test2050_markAsComparedEqualToNonNull();
9288
		test2051_markAsComparedEqualToNull();
9289
		test2052_markAsDefinitelyNonNull();
9290
		test2053_markAsDefinitelyNull();
9291
		test2054_markAsDefinitelyUnknown();
9292
		test2055_addInitializationsFrom();
9293
		test2056_addPotentialInitializationsFrom();
9294
		test2057_mergedWith();
9295
		// coverage check
9296
		int failuresNb = 0;
9297
		for (int i = 1; i <= coveragePointsNb; i++) {
9298
			try {
9299
				UnconditionalFlowInfo.coverageTestId = i;
9300
				test0053_array();
9301
				test0070_type_reference();
9302
				test2050_markAsComparedEqualToNonNull();
9303
				test2051_markAsComparedEqualToNull();
9304
				test2052_markAsDefinitelyNonNull();
9305
				test2053_markAsDefinitelyNull();
9306
				test2054_markAsDefinitelyUnknown();
9307
				test2055_addInitializationsFrom();
9308
				test2056_addPotentialInitializationsFrom();
9309
				test2057_mergedWith();
9310
			}
9311
			catch (AssertionFailedError e) {
9312
				continue;
9313
			}
9314
			catch (AssertionFailedException e) {
9315
				continue;
9316
			}
9317
			failuresNb++;
9318
			System.out.println("Missing coverage point: " + i);
9319
		}
9320
		UnconditionalFlowInfo.coverageTestId = 0; // reset for other tests
9321
		assertEquals(failuresNb + " missing coverage point(s)", failuresNb, 0);
9322
	}
9323
}
9324
9325
// Coverage by code samples.
9326
public void test2999_coverage() {
9327
	if (UnconditionalFlowInfo.coverageTestFlag) {
9328
		// sanity check: need to be sure that the tests execute properly when not
9329
		// trying to check coverage
9330
		UnconditionalFlowInfo.coverageTestId = 0;
9331
		test0001_simple_local();
9332
		test0053_array();
9333
		test0070_type_reference();
9334
		test0327_if_else();
9335
		test0401_while();
9336
		test0420_while();
9337
		test0509_try_finally_embedded();
9338
		test2000_flow_info();
9339
		test2004_flow_info();
9340
		test2008_flow_info();
9341
		test2011_flow_info();
9342
		test2013_flow_info();
9343
		test2018_flow_info();
9344
		test2019_flow_info();
9345
		test2020_flow_info();
9346
		// coverage check
9347
		int failuresNb = 0;
9348
		for (int i = 1; i <= coveragePointsNb; i++) {
9349
			if (i > 4 && i < 15 ||
9350
				i > 15 && i < 19 ||
9351
				i == 22 ||
9352
				i == 23 ||
9353
				i == 27 ||
9354
				i == 28 ||
9355
				i == 30 ||
9356
				i == 33 ||
9357
				i == 34 ||
9358
				i == 38 ||
9359
				i >= 43
9360
				) { // TODO (maxime) complete coverage tests
9361
				continue;
9362
			}
9363
			try {
9364
				UnconditionalFlowInfo.coverageTestId = i;
9365
				test0001_simple_local();
9366
				test0053_array();
9367
				test0070_type_reference();
9368
				test0327_if_else();
9369
				test0401_while();
9370
				test0420_while();
9371
				test0509_try_finally_embedded();
9372
				test2000_flow_info();
9373
				test2004_flow_info();
9374
				test2008_flow_info();
9375
				test2011_flow_info();
9376
				test2013_flow_info();
9377
				test2018_flow_info();
9378
				test2019_flow_info();
9379
				test2020_flow_info();
9380
			}
9381
			catch (AssertionFailedError e) {
9382
				continue;
9383
			}
9384
			catch (AssertionFailedException e) {
9385
				continue;
9386
			}
9387
			failuresNb++;
9388
			System.out.println("Missing coverage point: " + i);
9389
		}
9390
		UnconditionalFlowInfo.coverageTestId = 0; // reset for other tests
9391
		assertEquals(failuresNb + " missing coverage point(s)", failuresNb, 0);
9392
	}
9393
}
9394
9395
// only works for info coded on bit 0 - least significant
9396
String testCodedValueOf(long[] data) {
9397
	StringBuffer result = new StringBuffer(4);
9398
	for (int i = 0; i < data.length; i++) {
9399
		result.append(data[i] == 0 ? '0' : '1');
9400
	}
9401
	return result.toString();
9402
}
9403
9404
String testStringValueOf(long[] data) {
9405
	StringBuffer result = new StringBuffer(9);
9406
	result.append('{');
9407
	for (int j = 0; j < 4; j++) {
9408
		if (j > 0) {
9409
			result.append(',');
9410
		}
9411
		result.append(data[j]);
9412
	}
9413
	result.append('}');
9414
	return result.toString();
9415
}
9416
9417
String testStringValueOf(long[][] data) {
9418
	StringBuffer result = new StringBuffer(25);
9419
	result.append('{');
9420
	for (int i = 0; i < 3; i++) {
9421
		if (i > 0) {
9422
			result.append(',');
9423
		}
9424
		result.append('{');
9425
		for (int j = 0; j < 4; j++) {
9426
			if (j > 0) {
9427
				result.append(',');
9428
			}
9429
			result.append(data[i][j]);
9430
		}
9431
		result.append('}');
9432
	}
9433
	result.append('}');
9434
	return result.toString();
9435
}
9436
9437
// only works for info coded on bit 0 - least significant
9438
String testSymbolicValueOf(long[] data) {
9439
	if (data[0] == 0) {
9440
		if (data[1] == 0) {
9441
			if (data[2] == 0) {
9442
				if (data[3] == 0) {
9443
					return "start                 "; //$NON-NLS1$
9444
				}
9445
				else {
9446
					return "pot. nn/unknown       "; //$NON-NLS1$
9447
				}
9448
			}
9449
			else {
9450
				if (data[3] == 0) {
9451
					return "pot. null             "; //$NON-NLS1$
9452
				}
9453
				else {
9454
					return "pot. n/nn/unkn.       "; //$NON-NLS1$
9455
				}
9456
			}
9457
		}
9458
		else {
9459
			if (data[2] == 0) {
9460
				if (data[3] == 0) {
9461
					return "prot. null            "; //$NON-NLS1$
9462
				}
9463
				else {
9464
					return "0101                  "; //$NON-NLS1$
9465
				}
9466
			}
9467
			else {
9468
				if (data[3] == 0) {
9469
					return "prot. null + pot. null"; //$NON-NLS1$
9470
				}
9471
				else {
9472
					return "0111                  "; //$NON-NLS1$
9473
				}
9474
			}
9475
		}
9476
	}
9477
	else {
9478
		if (data[1] == 0) {
9479
			if (data[2] == 0) {
9480
				if (data[3] == 0) {
9481
					return "1000                  "; //$NON-NLS1$
9482
				}
9483
				else {
9484
					return "assigned non null     "; //$NON-NLS1$
9485
				}
9486
			}
9487
			else {
9488
				if (data[3] == 0) {
9489
					return "assigned null         "; //$NON-NLS1$
9490
				}
9491
				else {
9492
					return "assigned unknown      "; //$NON-NLS1$
9493
				}
9494
			}
9495
		}
9496
		else {
9497
			if (data[2] == 0) {
9498
				if (data[3] == 0) {
9499
					return "protected non null    "; //$NON-NLS1$
9500
				}
9501
				else {
9502
					return "prot. nn + pot. nn/unknown"; //$NON-NLS1$
9503
				}
9504
			}
9505
			else {
9506
				if (data[3] == 0) {
9507
					return "1110                  "; //$NON-NLS1$
9508
				}
9509
				else {
9510
					return "1111                  "; //$NON-NLS1$
9511
				}
9512
			}
9513
		}
9514
	}
9515
}
9516
9517
private void printTruthMap(long data[][][], int bit) {
9518
	final int dimension = 16;
9519
	printTruthMapHeader();
9520
	char truthValues[][] = new char[dimension][dimension];
9521
	int row, column;
9522
	for (row = 0; row < dimension; row++) {
9523
		for (column = 0; column < dimension; column++) {
9524
			truthValues[row][column] = '.';
9525
		}
9526
	}
9527
	String rows[] = {
9528
		"0000",
9529
		"0001",
9530
		"0011",
9531
		"0111",
9532
		"1111",
9533
		"1110",
9534
		"1100",
9535
		"1000",
9536
		"1010",
9537
		"1011",
9538
		"1001",
9539
		"1101",
9540
		"0101",
9541
		"0100",
9542
		"0110",
9543
		"0010"
9544
	};
9545
	if (false) { // checking row names
9546
		for (row = 0; row < dimension; row++) {
9547
			long [] state = new long [4];
9548
			for (int i = 0; i < 4; i++) {
9549
				state[i] = rows[row].charAt(i) - '0';
9550
			}
9551
			System.out.println(row + " " + rows[row] + " " + rankForState(state));
9552
		}
9553
	}
9554
	for (int i = 0; i < data.length; i++) {
9555
		truthValues[rankForState(data[i][0])][rankForState(data[i][1])] =
9556
			(char) ('0' + data[i][2][bit]);
9557
	}
9558
	for (row = 0; row < dimension; row++) {
9559
		StringBuffer line = new StringBuffer(120);
9560
		line.append(rows[row]);
9561
		line.append(" | ");
9562
		for (column = 0; column < dimension; column++) {
9563
			line.append(truthValues[row][column]);
9564
			line.append(' ');
9565
		}
9566
		System.out.println(line);
9567
	}
9568
}
9569
9570
private void printTruthMapHeader() {
9571
	System.out.println("       0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0");
9572
	System.out.println("       0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0");
9573
	System.out.println("       0 0 1 1 1 1 0 0 1 1 0 0 0 0 1 1");
9574
	System.out.println("       0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0");
9575
	System.out.println("      --------------------------------");
9576
}
9577
9578
private int rankForState(long [] state) {
9579
	if (state[0] == 0) {
9580
		if (state[1] == 0) {
9581
			if (state[2] == 0) {
9582
				if (state[3] == 0) {
9583
					return 0; 	// 0000
9584
				}
9585
				else {
9586
					return 1; 	// 0001
9587
				}
9588
			}
9589
			else {
9590
				if (state[3] == 0) {
9591
					return 15;	// 0010
9592
				}
9593
				else {
9594
					return 2;	// 0011
9595
				}
9596
			}
9597
		}
9598
		else {
9599
			if (state[2] == 0) {
9600
				if (state[3] == 0) {
9601
					return 13;	// 0100
9602
				}
9603
				else {
9604
					return 12;	// 0101
9605
				}
9606
			}
9607
			else {
9608
				if (state[3] == 0) {
9609
					return 14;	// 0110
9610
				}
9611
				else {
9612
					return 3;	// 0111
9613
				}
9614
			}
9615
		}
9616
	}
9617
	else {
9618
		if (state[1] == 0) {
9619
			if (state[2] == 0) {
9620
				if (state[3] == 0) {
9621
					return 7;	// 1000
9622
				}
9623
				else {
9624
					return 10;	// 1001
9625
				}
9626
			}
9627
			else {
9628
				if (state[3] == 0) {
9629
					return 8;	// 1010
9630
				}
9631
				else {
9632
					return 9;	// 1011
9633
				}
9634
			}
9635
		}
9636
		else {
9637
			if (state[2] == 0) {
9638
				if (state[3] == 0) {
9639
					return 6;	// 1100
9640
				}
9641
				else {
9642
					return 11;	// 1101
9643
				}
9644
			}
9645
			else {
9646
				if (state[3] == 0) {
9647
					return 5;	// 1110
9648
				}
9649
				else {
9650
					return 4;	// 1111
9651
				}
9652
			}
9653
		}
9654
	}
9655
}
9656
}
9657
9658
class TestLocalVariableBinding extends LocalVariableBinding {
9659
	final static char [] testName = {'t', 'e', 's', 't'};
9660
	TestLocalVariableBinding(int id) {
9661
		super(testName, null, 0, false);
9662
		this.id = id;
9663
	}
9664
}
9665
9666
/**
9667
 * A class meant to augment 
9668
 * @link{org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo} with
9669
 * capabilities in the test domain. It especially provides factories to build
9670
 * fake flow info instances for use in state transition tables validation.
9671
 */
9672
class UnconditionalFlowInfoTestHarness extends UnconditionalFlowInfo {
9673
	private int testPosition;
9674
	
9675
/**
9676
 * Return a fake unconditional flow info which bit fields represent the given
9677
 * null bits for a local variable of id 0 within a class that would have no
9678
 * field.
9679
 * @param nullBits the bits that must be set, given in the same order as the
9680
 *        nullAssignment* fields in UnconditionalFlowInfo definition; use 0
9681
 *        for a bit that is not set, 1 else
9682
 * @return a fake unconditional flow info which bit fields represent the
9683
 *         null bits given in parameter
9684
 */
9685
public static UnconditionalFlowInfoTestHarness testUnconditionalFlowInfo(
9686
		long [] nullBits) {
9687
	return testUnconditionalFlowInfo(nullBits, 0);
9688
}
9689
9690
public FlowInfo copy() {
9691
	UnconditionalFlowInfoTestHarness copy = 
9692
		new UnconditionalFlowInfoTestHarness();
9693
	copy.testPosition = this.testPosition;
9694
	copy.definiteInits = this.definiteInits;
9695
	copy.potentialInits = this.potentialInits;
9696
	boolean hasNullInfo = (this.tagBits & NULL_FLAG_MASK) != 0;
9697
	if (hasNullInfo) { 
9698
		copy.nullAssignmentStatusBit1 = this.nullAssignmentStatusBit1;
9699
		copy.nullAssignmentStatusBit2 = this.nullAssignmentStatusBit2;
9700
		copy.nullAssignmentValueBit1 = this.nullAssignmentValueBit1;
9701
		copy.nullAssignmentValueBit2 = this.nullAssignmentValueBit2;
9702
	}
9703
	copy.tagBits = this.tagBits;
9704
	copy.maxFieldCount = this.maxFieldCount;
9705
	if (this.extra != null) {
9706
		int length;
9707
        copy.extra = new long[extraLength][];
9708
		System.arraycopy(this.extra[0], 0, 
9709
			(copy.extra[0] = new long[length = extra[0].length]), 0, length);
9710
		System.arraycopy(this.extra[1], 0, 
9711
			(copy.extra[1] = new long[length]), 0, length);
9712
		if (hasNullInfo) {
9713
            for (int j = 0; j < extraLength; j++) {
9714
			    System.arraycopy(this.extra[j], 0, 
9715
				    (copy.extra[j] = new long[length]), 0, length);
9716
            }
9717
		}
9718
		else {
9719
            for (int j = 0; j < extraLength; j++) {
9720
			    copy.extra[j] = new long[length];
9721
            }
9722
		}
9723
	}
9724
	return copy;
9725
}
9726
9727
/**
9728
 * Return a fake unconditional flow info which bit fields represent the given
9729
 * null bits for a local variable of id position within a class that would have 
9730
 * no field.
9731
 * @param nullBits the bits that must be set, given in the same order as the
9732
 *        nullAssignment* fields in UnconditionalFlowInfo definition; use 0
9733
 *        for a bit that is not set, 1 else
9734
 * @param position the position of the variable within the bit fields; use
9735
 *        various values to test different parts of the bit fields, within
9736
 *        or beyond BitCacheSize
9737
 * @return a fake unconditional flow info which bit fields represent the
9738
 *         null bits given in parameter
9739
 */
9740
public static UnconditionalFlowInfoTestHarness testUnconditionalFlowInfo(
9741
		long [] nullBits, int position) {
9742
 	UnconditionalFlowInfoTestHarness result = 
9743
 		new UnconditionalFlowInfoTestHarness();
9744
	result.testPosition = position;
9745
	if (position < BitCacheSize) {
9746
		result.nullAssignmentStatusBit1 = nullBits[0] << position;
9747
		result.nullAssignmentStatusBit2 = nullBits[1] << position;
9748
		result.nullAssignmentValueBit1 = nullBits[2] << position;
9749
		result.nullAssignmentValueBit2 = nullBits[3] << position;
9750
	} 
9751
 	else {
9752
		int vectorIndex = (position / BitCacheSize) - 1,
9753
			length = vectorIndex + 1;
9754
        position %= BitCacheSize;
9755
        result.extra = new long[extraLength][];
9756
		result.extra[0] = new long[length];
9757
		result.extra[1] = new long[length];
9758
        for (int j = 2; j < extraLength; j++) {
9759
		    result.extra[j] = new long[length];
9760
		    result.extra[j][vectorIndex] = nullBits[j - 2] << 
9761
		        position;
9762
        }
9763
	}
9764
	if ((nullBits[0] | nullBits[1] | nullBits[2] | nullBits[3]) != 0) {
9765
		result.tagBits |= NULL_FLAG_MASK;
9766
	}
9767
	result.maxFieldCount = 0;
9768
	return result;
9769
}
9770
9771
/**
9772
 * Return a fake unconditional flow info which bit fields represent the given
9773
 * null bits for a pair of local variables of id position and position +
9774
 * extra * BitCacheSize within a class that would have no field.
9775
 * @param nullBits the bits that must be set, given in the same order as the
9776
 *        nullAssignment* fields in UnconditionalFlowInfo definition; use 0
9777
 *        for a bit that is not set, 1 else
9778
 * @param position the position of the variable within the bit fields; use
9779
 *        various values to test different parts of the bit fields, within
9780
 *        or beyond BitCacheSize
9781
 * @param extra the length of the allocated extra bit fields, if position is 
9782
 *        beyond BitCacheSize; unused otherwise; make sure it is big enough to
9783
 *        match position (that is, extra > position - BitCacheSize)
9784
 * @return a fake unconditional flow info which bit fields represent the
9785
 *         null bits given in parameter
9786
 */
9787
public static UnconditionalFlowInfoTestHarness testUnconditionalFlowInfo(
9788
		long [] nullBits, int position, int extra) {
9789
 	UnconditionalFlowInfoTestHarness result = 
9790
 		new UnconditionalFlowInfoTestHarness();
9791
	result.testPosition = position;
9792
	if (position < BitCacheSize) {
9793
		result.nullAssignmentStatusBit1 = nullBits[0] << position;
9794
		result.nullAssignmentStatusBit2 = nullBits[1] << position;
9795
		result.nullAssignmentValueBit1 = nullBits[2] << position;
9796
		result.nullAssignmentValueBit2 = nullBits[3] << position;
9797
	} 
9798
 	else {
9799
		int vectorIndex = (position / BitCacheSize) - 1,
9800
			length = extra / BitCacheSize;
9801
		position %= BitCacheSize;
9802
        result.extra = new long[extraLength][];
9803
		result.extra[0] = new long[length];
9804
		result.extra[1] = new long[length];
9805
        for (int j = 2; j < extraLength; j++) {
9806
		    result.extra[j] = new long[length];
9807
		    result.extra[j] [vectorIndex]= nullBits[j - 2] << position;
9808
        }
9809
	}
9810
	if (nullBits[1] != 0 || nullBits[3] != 0 || nullBits[0] != 0 || nullBits[2] != 0 ) {
9811
		// cascade better than nullBits[0] | nullBits[1] | nullBits[2] | nullBits[3]
9812
		// by 10%+
9813
		// TODO (maxime) run stats to determine which is the better order
9814
		result.tagBits |= NULL_FLAG_MASK;
9815
	}
9816
	result.maxFieldCount = 0;
9817
	return result;
9818
}
9819
9820
/**
9821
 * Return true iff this flow info can be considered as equal to the one passed
9822
 * in parameter.
9823
 * @param other the flow info to compare to
9824
 * @return true iff this flow info compares equal to other
9825
 */
9826
public boolean testEquals(UnconditionalFlowInfo other) {
9827
	if (this.tagBits != other.tagBits) {
9828
		return false;
9829
	}
9830
	if (this.nullAssignmentStatusBit1 != other.nullAssignmentStatusBit1 ||
9831
		this.nullAssignmentStatusBit2 != other.nullAssignmentStatusBit2 ||
9832
		this.nullAssignmentValueBit1 != other.nullAssignmentValueBit1 ||
9833
		this.nullAssignmentValueBit2 != other.nullAssignmentValueBit2) {
9834
		return false;
9835
	}
9836
	int left = this.extra == null ? 0 : this.extra[0].length,
9837
			right = other.extra == null ? 0 : other.extra[0].length,
9838
			both = 0, i;
9839
	if (left > right) {
9840
		both = right;
9841
	}
9842
	else {
9843
		both = left;
9844
	}
9845
	for (i = 0; i < both ; i++) {
9846
		if (this.extra[2][i] != 
9847
				other.extra[2][i] ||
9848
			this.extra[3][i] != 
9849
				other.extra[3][i] ||
9850
			this.extra[4][i] != 
9851
				other.extra[4][i] ||
9852
			this.extra[5][i] != 
9853
				other.extra[5][i]) {
9854
			return false;
9855
		}
9856
	}
9857
	for (; i < left; i++) {
9858
		if (this.extra[2][i] != 0 ||
9859
				this.extra[3][i] != 0 ||
9860
				this.extra[4][i] != 0 ||
9861
				this.extra[5][i] != 0) {
9862
			return false;
9863
		}
9864
	}
9865
	for (; i < right; i++) {
9866
		if (other.extra[2][i] != 0 ||
9867
				other.extra[3][i] != 0 ||
9868
				other.extra[4][i] != 0 ||
9869
				other.extra[5][i] != 0) {
9870
			return false;
9871
		}
9872
	}
9873
	return true;
9874
}
9875
9876
/**
9877
 * Return true iff this flow info can be considered as equal to the one passed
9878
 * in parameter in respect with a single local variable which id would be
9879
 * position in a class with no field.
9880
 * @param other the flow info to compare to
9881
 * @param position the position of the local to consider
9882
 * @return true iff this flow info compares equal to other for a given local
9883
 */
9884
public boolean testEquals(UnconditionalFlowInfo other, int position) {
9885
	int vectorIndex = position / BitCacheSize - 1;
9886
	if ((this.tagBits & other.tagBits & NULL_FLAG_MASK) == 0) {
9887
		return true;
9888
	}
9889
	long mask;
9890
	if (vectorIndex < 0) {
9891
		return ((this.nullAssignmentStatusBit1 & (mask = (1L << position))) ^
9892
				(other.nullAssignmentStatusBit1 & mask)) == 0 &&
9893
				((this.nullAssignmentStatusBit2 & mask) ^
9894
				(other.nullAssignmentStatusBit2 & mask)) == 0 &&
9895
				((this.nullAssignmentValueBit1 & mask) ^
9896
				(other.nullAssignmentValueBit1 & mask)) == 0 &&
9897
				((this.nullAssignmentValueBit2 & mask) ^
9898
				(other.nullAssignmentValueBit2 & mask)) == 0;
9899
	}
9900
	else {
9901
		int left = this.extra == null ?
9902
				0 :
9903
				this.extra[0].length;
9904
		int right = other.extra == null ?
9905
				0 :
9906
				other.extra[0].length;
9907
		int both = left < right ? left : right;
9908
		if (vectorIndex < both) {
9909
			return ((this.extra[2][vectorIndex] & 
9910
					(mask = (1L << (position % BitCacheSize)))) ^
9911
				(other.extra[2][vectorIndex] & mask)) == 0 &&
9912
				((this.extra[3][vectorIndex] & mask) ^
9913
				(other.extra[3][vectorIndex] & mask)) == 0 &&
9914
				((this.extra[4][vectorIndex] & mask) ^
9915
				(other.extra[4][vectorIndex] & mask)) == 0 &&
9916
				((this.extra[5][vectorIndex] & mask) ^
9917
				(other.extra[5][vectorIndex] & mask)) == 0;
9918
		}
9919
		if (vectorIndex < left) {
9920
			return ((this.extra[2][vectorIndex] |
9921
					this.extra[3][vectorIndex] |
9922
					this.extra[4][vectorIndex] |
9923
					this.extra[5][vectorIndex]) &
9924
					(1L << (position % BitCacheSize))) == 0;
9925
		}
9926
		return ((other.extra[2][vectorIndex] |
9927
				other.extra[3][vectorIndex] |
9928
				other.extra[4][vectorIndex] |
9929
				other.extra[5][vectorIndex]) &
9930
				(1L << (position % BitCacheSize))) == 0;
9931
	}
9932
}
9933
9934
/**
9935
 * Return a string suitable for use as a representation of this flow info
9936
 * within test series.
9937
 * @return a string suitable for use as a representation of this flow info
9938
 */
9939
public String testString() {
9940
	if (this == DEAD_END) {
9941
		return "FlowInfo.DEAD_END"; //$NON-NLS-1$
9942
	}
9943
	return testString(this.testPosition);
9944
}
9945
9946
/**
9947
 * Return a string suitable for use as a representation of this flow info
9948
 * within test series.
9949
 * @param position a position to consider instead of this flow info default
9950
 *                 test position
9951
 * @return a string suitable for use as a representation of this flow info
9952
 */
9953
public String testString(int position) {
9954
	if (this == DEAD_END) {
9955
		return "FlowInfo.DEAD_END"; //$NON-NLS-1$
9956
	}
9957
	if (position < BitCacheSize) {
9958
		return "{" + (this.nullAssignmentStatusBit1 >> position) //$NON-NLS-1$
9959
					+ "," + (this.nullAssignmentStatusBit2 >> position) //$NON-NLS-1$
9960
					+ "," + (this.nullAssignmentValueBit1 >> position) //$NON-NLS-1$
9961
					+ "," + (this.nullAssignmentValueBit2 >> position) //$NON-NLS-1$
9962
					+ "}"; //$NON-NLS-1$
9963
	}
9964
	else {
9965
		int vectorIndex = position / BitCacheSize - 1,
9966
			shift = position % BitCacheSize;
9967
			return "{" + (this.extra[2][vectorIndex] //$NON-NLS-1$
9968
			               >> shift) 
9969
						+ "," + (this.extra[3][vectorIndex] //$NON-NLS-1$
9970
						   >> shift)
9971
						+ "," + (this.extra[4][vectorIndex] //$NON-NLS-1$
9972
						   >> shift)
9973
						+ "," + (this.extra[5][vectorIndex] //$NON-NLS-1$
9974
						   >> shift)
9975
						+ "}"; //$NON-NLS-1$
9976
	}
9977
}
9978
}
8053
}
(-).settings/org.eclipse.jdt.ui.prefs (+5 lines)
Added Link Here
1
#Thu Feb 23 14:36:02 CET 2006
2
eclipse.preferences.version=1
3
formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
4
formatter_settings_version=10
5
internal.default.compliance=user
(-)src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTransformations.java (+3177 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.core.tests.compiler.regression;
12
13
import java.io.BufferedReader;
14
import java.io.BufferedWriter;
15
import java.io.File;
16
import java.io.FileOutputStream;
17
import java.io.IOException;
18
import java.io.PrintWriter;
19
import java.util.HashMap;
20
import java.util.Iterator;
21
import java.util.Map;
22
import java.util.SortedMap;
23
import java.util.TreeMap;
24
25
import org.eclipse.jdt.core.tests.compiler.regression.NullReferenceImplTests.State;
26
import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo;
27
public class NullReferenceImplTransformations {
28
	public static final Transformation
29
		markAsComparedEqualToNonNull = 
30
		// markAsComparedEqualToNonNull DEFINITION START
31
		// start => prot. non null
32
		// prot. non null => prot. non null
33
		// prot. null => prot. non null
34
		// pot. unknown => pot. nn & prot. nn 
35
		// pot. non null => pot. nn & prot. nn
36
		// pot. nn & prot. nn => pot. nn & prot. nn
37
		// pot. nn & pot. un => pot. nn & prot. nn
38
		// pot. null => prot. non null
39
		// pot. n & prot. n => prot. non null
40
		// pot. n & pot. un => pot. nn & prot. nn 
41
		// pot. n & pot. nn => pot. nn & prot. nn
42
		// def. unknown => def. non null 
43
		// def. non null => def. non null
44
		// def. null => prot. non null
45
		// markAsComparedEqualToNonNull DEFINITION END
46
			new TwoDimensionalTransformation("markAsComparedEqualToNonNull",
47
					new byte[][] {
48
					// markAsComparedEqualToNonNull INITIALIZER START
49
					{0x00,0x3C},
50
					{0x04,0x2C},
51
					{0x08,0x2C},
52
					{0x0C,0x2C},
53
					{0x10,0x3C},
54
					{0x14,0x2C},
55
					{0x18,0x2C},
56
					{0x24,0x28},
57
					{0x28,0x28},
58
					{0x2C,0x2C},
59
					{0x30,0x3C},
60
					{0x34,0x3C},
61
					{0x38,0x3C},
62
					{0x3C,0x3C},
63
					// markAsComparedEqualToNonNull INITIALIZER END
64
					}) {
65
				UnconditionalFlowInfo output(UnconditionalFlowInfo input, 
66
						TestLocalVariableBinding local) {
67
					UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy();
68
					result.markAsComparedEqualToNonNull(local);
69
					return result;
70
				}
71
			},
72
		markAsComparedEqualToNull =
73
		// markAsComparedEqualToNull DEFINITION START
74
		// start => prot. null
75
		// prot. non null => prot. null
76
		// prot. null => prot. null
77
		// pot. unknown => pot. n & prot. n
78
		// pot. non null => prot. null
79
		// pot. nn & prot. nn => prot. null
80
		// pot. nn & pot. un => pot. n & prot. n
81
		// pot. null => pot. n & prot. n
82
		// pot. n & prot. n => pot. n & prot. n
83
		// pot. n & pot. un => pot. n & prot. n
84
		// pot. n & pot. nn => pot. n & prot. n
85
		// def. unknown => def. null
86
		// def. non null => prot. null
87
		// def. null => def. null
88
		// markAsComparedEqualToNull DEFINITION END
89
			new TwoDimensionalTransformation("markAsComparedEqualToNull",
90
				new byte[][] {
91
				// markAsComparedEqualToNull INITIALIZER START
92
				{0x00,0x38},
93
				{0x04,0x34},
94
				{0x08,0x38},
95
				{0x0C,0x34},
96
				{0x10,0x34},
97
				{0x14,0x34},
98
				{0x18,0x34},
99
				{0x24,0x30},
100
				{0x28,0x38},
101
				{0x2C,0x38},
102
				{0x30,0x30},
103
				{0x34,0x34},
104
				{0x38,0x38},
105
				{0x3C,0x38},
106
				// markAsComparedEqualToNull INITIALIZER END
107
				}) {
108
			UnconditionalFlowInfo output(UnconditionalFlowInfo input, 
109
					TestLocalVariableBinding local) {
110
				UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy();
111
				result.markAsComparedEqualToNull(local);
112
				return result;
113
			}
114
		},
115
		markAsDefinitelyNonNull = 
116
		// markAsDefinitelyNonNull DEFINITION START
117
		// start => def. non null
118
		// prot. non null => def. non null
119
		// prot. null => def. non null
120
		// pot. unknown => def. non null
121
		// pot. non null => def. non null
122
		// pot. nn & prot. nn => def. non null
123
		// pot. nn & pot. un => def. non null
124
		// pot. null => def. non null
125
		// pot. n & prot. n => def. non null
126
		// pot. n & pot. un => def. non null
127
		// pot. n & pot. nn => def. non null
128
		// def. unknown => def. non null
129
		// def. non null => def. non null
130
		// def. null => def. non null
131
		// markAsDefinitelyNonNull DEFINITION END
132
			new TwoDimensionalTransformation("markAsDefinitelyNonNull",
133
				new byte[][] {
134
				// markAsDefinitelyNonNull INITIALIZER START
135
				{0x00,0x28},
136
				{0x04,0x28},
137
				{0x08,0x28},
138
				{0x0C,0x28},
139
				{0x10,0x28},
140
				{0x14,0x28},
141
				{0x18,0x28},
142
				{0x24,0x28},
143
				{0x28,0x28},
144
				{0x2C,0x28},
145
				{0x30,0x28},
146
				{0x34,0x28},
147
				{0x38,0x28},
148
				{0x3C,0x28},
149
				// markAsDefinitelyNonNull INITIALIZER END
150
				}) {
151
			UnconditionalFlowInfo output(UnconditionalFlowInfo input, 
152
					TestLocalVariableBinding local) {
153
				UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy();
154
				result.markAsDefinitelyNonNull(local);
155
				return result;
156
			}
157
		},
158
		markAsDefinitelyNull =
159
		// markAsDefinitelyNull DEFINITION START
160
		// start => def. null
161
		// prot. non null => def. null
162
		// prot. null => def. null
163
		// pot. unknown => def. null
164
		// pot. non null => def. null
165
		// pot. nn & prot. nn => def. null
166
		// pot. nn & pot. un => def. null
167
		// pot. null => def. null
168
		// pot. n & prot. n => def. null
169
		// pot. n & pot. un => def. null
170
		// pot. n & pot. nn => def. null
171
		// def. unknown => def. null
172
		// def. non null => def. null
173
		// def. null => def. null
174
		// markAsDefinitelyNull DEFINITION END
175
			// PREMATURE add 'catch rules'
176
			new TwoDimensionalTransformation("markAsDefinitelyNull",
177
				new byte[][] {
178
				// markAsDefinitelyNull INITIALIZER START
179
				{0x00,0x30},
180
				{0x04,0x30},
181
				{0x08,0x30},
182
				{0x0C,0x30},
183
				{0x10,0x30},
184
				{0x14,0x30},
185
				{0x18,0x30},
186
				{0x24,0x30},
187
				{0x28,0x30},
188
				{0x2C,0x30},
189
				{0x30,0x30},
190
				{0x34,0x30},
191
				{0x38,0x30},
192
				{0x3C,0x30},
193
				// markAsDefinitelyNull INITIALIZER END
194
				}) {
195
			UnconditionalFlowInfo output(UnconditionalFlowInfo input, 
196
					TestLocalVariableBinding local) {
197
				UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy();
198
				result.markAsDefinitelyNull(local);
199
				return result;
200
			}
201
		},
202
		markAsDefinitelyUnknown =
203
		// markAsDefinitelyUnknown DEFINITION START
204
		// start => def. unknown
205
		// prot. non null => def. unknown
206
		// prot. null => def. unknown
207
		// pot. unknown => def. unknown
208
		// pot. non null => def. unknown
209
		// pot. nn & prot. nn => def. unknown
210
		// pot. nn & pot. un => def. unknown
211
		// pot. null => def. unknown
212
		// pot. n & prot. n => def. unknown
213
		// pot. n & pot. un => def. unknown
214
		// pot. n & pot. nn => def. unknown
215
		// def. unknown => def. unknown
216
		// def. non null => def. unknown
217
		// def. null => def. unknown
218
		// markAsDefinitelyUnknown DEFINITION END
219
			new TwoDimensionalTransformation("markAsDefinitelyUnknown",
220
				new byte[][] {
221
				// markAsDefinitelyUnknown INITIALIZER START
222
				{0x00,0x24},
223
				{0x04,0x24},
224
				{0x08,0x24},
225
				{0x0C,0x24},
226
				{0x10,0x24},
227
				{0x14,0x24},
228
				{0x18,0x24},
229
				{0x24,0x24},
230
				{0x28,0x24},
231
				{0x2C,0x24},
232
				{0x30,0x24},
233
				{0x34,0x24},
234
				{0x38,0x24},
235
				{0x3C,0x24},
236
				// markAsDefinitelyUnknown INITIALIZER END
237
				}) {
238
			UnconditionalFlowInfo output(UnconditionalFlowInfo input, 
239
					TestLocalVariableBinding local) {
240
				UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy();
241
				result.markAsDefinitelyUnknown(local);
242
				return result;
243
			}
244
		},
245
		addInitializationsFrom =
246
		// addInitializationsFrom DEFINITION START
247
		// def. non null + def. non null => def. non null		
248
		// def. non null + def. null => def. null		
249
		// def. non null + def. unknown => def. unknown		
250
		// def. non null + pot. n & pot. nn => pot. n & pot. nn		
251
		// def. non null + pot. n & pot. un => pot. n & pot. nn		
252
		// def. non null + pot. n & prot. n => pot. n & prot. n		
253
		// def. non null + pot. nn & pot. un => def. unknown		
254
		// def. non null + pot. nn & prot. nn => def. non null		
255
		// def. non null + pot. non null => def. non null		
256
		// def. non null + pot. null => pot. n & pot. nn		
257
		// def. non null + pot. unknown => def. unknown // priv.	
258
		// def. non null + prot. non null => def. non null		
259
		// def. non null + prot. null => prot. null		
260
		// def. non null + start => def. non null		
261
		// def. null + def. non null => def. non null		
262
		// def. null + def. null => def. null		
263
		// def. null + def. unknown => def. unknown		
264
		// def. null + pot. n & pot. nn => pot. n & pot. nn		
265
		// def. null + pot. n & pot. un => pot. n & pot. un		
266
		// def. null + pot. n & prot. n => def. null		
267
		// def. null + pot. nn & pot. un => pot. n & pot. nn		
268
		// def. null + pot. nn & prot. nn => pot. nn & prot. nn		
269
		// def. null + pot. non null => pot. n & pot. nn		
270
		// def. null + pot. null => def. null		
271
		// def. null + pot. unknown => pot. n & pot. un // pot. null privileged over def. unknown		
272
		// def. null + prot. non null => prot. non null		
273
		// def. null + prot. null => def. null		
274
		// def. null + start => def. null		
275
		// def. unknown + def. non null => def. non null		
276
		// def. unknown + def. null => def. null		
277
		// def. unknown + def. unknown => def. unknown		
278
		// def. unknown + pot. n & pot. nn => pot. n & pot. nn		
279
		// def. unknown + pot. n & pot. un => pot. n & pot. un	// we loose the def here, but we need the pot. null
280
		// def. unknown + pot. n & prot. n => def. null		
281
		// def. unknown + pot. nn & pot. un => def. unknown // priv.
282
		// def. unknown + pot. nn & prot. nn => def. non null		
283
		// def. unknown + pot. non null => def. unknown	// privileging over pot. nn & pot. un
284
		// def. unknown + pot. null => pot. n & pot. un
285
		// def. unknown + pot. unknown => def. unknown		
286
		// def. unknown + prot. non null => def. non null 		
287
		// def. unknown + prot. null => def. null		
288
		// def. unknown + start => def. unknown		
289
		// pot. n & pot. nn + def. non null => def. non null		
290
		// pot. n & pot. nn + def. null => def. null		
291
		// pot. n & pot. nn + def. unknown => def. unknown		
292
		// pot. n & pot. nn + pot. n & pot. nn => pot. n & pot. nn		
293
		// pot. n & pot. nn + pot. n & pot. un => pot. n & pot. nn		
294
		// pot. n & pot. nn + pot. n & prot. n => pot. n & prot. n		
295
		// pot. n & pot. nn + pot. nn & pot. un => pot. n & pot. nn		
296
		// pot. n & pot. nn + pot. nn & prot. nn => pot. nn & prot. nn		
297
		// pot. n & pot. nn + pot. non null => pot. n & pot. nn		
298
		// pot. n & pot. nn + pot. null => pot. n & pot. nn		
299
		// pot. n & pot. nn + pot. unknown => pot. n & pot. nn		
300
		// pot. n & pot. nn + prot. non null => pot. nn & prot. nn		
301
		// pot. n & pot. nn + prot. null => pot. n & prot. n		
302
		// pot. n & pot. nn + start => pot. n & pot. nn		
303
		// pot. n & pot. un + def. non null => def. non null		
304
		// pot. n & pot. un + def. null => def. null		
305
		// pot. n & pot. un + def. unknown => def. unknown		
306
		// pot. n & pot. un + pot. n & pot. nn => pot. n & pot. nn		
307
		// pot. n & pot. un + pot. n & pot. un => pot. n & pot. un		
308
		// pot. n & pot. un + pot. n & prot. n => pot. n & prot. n		
309
		// pot. n & pot. un + pot. nn & pot. un => pot. n & pot. nn		
310
		// pot. n & pot. un + pot. nn & prot. nn => pot. nn & prot. nn		
311
		// pot. n & pot. un + pot. non null => pot. n & pot. nn		
312
		// pot. n & pot. un + pot. null => pot. n & pot. un		
313
		// pot. n & pot. un + pot. unknown => pot. n & pot. un		
314
		// pot. n & pot. un + prot. non null => pot. nn & prot. nn 		
315
		// pot. n & pot. un + prot. null => pot. n & prot. n		
316
		// pot. n & pot. un + start => pot. n & pot. un		
317
		// pot. n & prot. n + def. non null => def. non null		
318
		// pot. n & prot. n + def. null => def. null		
319
		// pot. n & prot. n + def. unknown => def. unknown		
320
		// pot. n & prot. n + pot. n & pot. nn => pot. n & pot. nn		
321
		// pot. n & prot. n + pot. n & pot. un => pot. n & pot. un		
322
		// pot. n & prot. n + pot. n & prot. n => pot. n & prot. n		
323
		// pot. n & prot. n + pot. nn & pot. un => pot. n & pot. nn		
324
		// pot. n & prot. n + pot. nn & prot. nn => pot. nn & prot. nn		
325
		// pot. n & prot. n + pot. non null => pot. n & pot. nn		
326
		// pot. n & prot. n + pot. null => pot. n & prot. n		
327
		// pot. n & prot. n + pot. unknown => pot. n & pot. un		
328
		// pot. n & prot. n + prot. non null => prot. non null		
329
		// pot. n & prot. n + prot. null => pot. n & prot. n		
330
		// pot. n & prot. n + start => pot. n & prot. n		
331
		// pot. nn & pot. un + def. non null => def. non null		
332
		// pot. nn & pot. un + def. null => def. null		
333
		// pot. nn & pot. un + def. unknown => def. unknown		
334
		// pot. nn & pot. un + pot. n & pot. nn => pot. n & pot. nn		
335
		// pot. nn & pot. un + pot. n & pot. un => pot. n & pot. nn		
336
		// pot. nn & pot. un + pot. n & prot. n => pot. n & prot. n		
337
		// pot. nn & pot. un + pot. nn & pot. un => pot. nn & pot. un		
338
		// pot. nn & pot. un + pot. nn & prot. nn => pot. nn & prot. nn		
339
		// pot. nn & pot. un + pot. non null => pot. nn & pot. un		
340
		// pot. nn & pot. un + pot. null => pot. n & pot. nn		
341
		// pot. nn & pot. un + pot. unknown => pot. nn & pot. un		
342
		// pot. nn & pot. un + prot. non null => pot. nn & prot. nn
343
		// pot. nn & pot. un + prot. null => pot. n & prot. n		
344
		// pot. nn & pot. un + start => pot. nn & pot. un		
345
		// pot. nn & prot. nn + def. non null => def. non null		
346
		// pot. nn & prot. nn + def. null => def. null		
347
		// pot. nn & prot. nn + def. unknown => def. unknown		
348
		// pot. nn & prot. nn + pot. n & pot. nn => pot. n & pot. nn		
349
		// pot. nn & prot. nn + pot. n & pot. un => pot. n & pot. nn		
350
		// pot. nn & prot. nn + pot. n & prot. n => pot. n & prot. n		
351
		// pot. nn & prot. nn + pot. nn & pot. un => pot. nn & pot. un
352
		// pot. nn & prot. nn + pot. nn & prot. nn => pot. nn & prot. nn		
353
		// pot. nn & prot. nn + pot. non null => pot. nn & prot. nn		
354
		// pot. nn & prot. nn + pot. null => pot. n & pot. nn		
355
		// pot. nn & prot. nn + pot. unknown => pot. nn & pot. un
356
		// pot. nn & prot. nn + prot. non null => pot. nn & prot. nn		
357
		// pot. nn & prot. nn + prot. null => prot. null		
358
		// pot. nn & prot. nn + start => pot. nn & prot. nn		
359
		// pot. non null + def. non null => def. non null		
360
		// pot. non null + def. null => def. null		
361
		// pot. non null + def. unknown => def. unknown		
362
		// pot. non null + pot. n & pot. nn => pot. n & pot. nn		
363
		// pot. non null + pot. n & pot. un => pot. n & pot. nn		
364
		// pot. non null + pot. n & prot. n => pot. n & prot. n		
365
		// pot. non null + pot. nn & pot. un => pot. nn & pot. un		
366
		// pot. non null + pot. nn & prot. nn => pot. nn & prot. nn		
367
		// pot. non null + pot. non null => pot. non null		
368
		// pot. non null + pot. null => pot. n & pot. nn		
369
		// pot. non null + pot. unknown => pot. nn & pot. un		
370
		// pot. non null + prot. non null => pot. nn & prot. nn		
371
		// pot. non null + prot. null => prot. null		
372
		// pot. non null + start => pot. non null
373
		// pot. null + def. non null => def. non null		
374
		// pot. null + def. null => def. null		
375
		// pot. null + def. unknown => def. unknown		
376
		// pot. null + pot. n & pot. nn => pot. n & pot. nn		
377
		// pot. null + pot. n & pot. un => pot. n & pot. un		
378
		// pot. null + pot. n & prot. n => pot. n & prot. n		
379
		// pot. null + pot. nn & pot. un => pot. n & pot. nn		
380
		// pot. null + pot. nn & prot. nn => pot. nn & prot. nn		
381
		// pot. null + pot. non null => pot. n & pot. nn		
382
		// pot. null + pot. null => pot. null		
383
		// pot. null + pot. unknown => pot. n & pot. un		
384
		// pot. null + prot. non null => prot. non null		
385
		// pot. null + prot. null => pot. n & prot. n		
386
		// pot. null + start => pot. null		
387
		// pot. unknown + def. non null => def. non null
388
		// pot. unknown + def. null => def. null
389
		// pot. unknown + def. unknown => def. unknown
390
		// pot. unknown + pot. n & pot. nn => pot. n & pot. nn
391
		// pot. unknown + pot. n & pot. un => pot. n & pot. un
392
		// pot. unknown + pot. n & prot. n => pot. n & prot. n
393
		// pot. unknown + pot. nn & pot. un => pot. nn & pot. un
394
		// pot. unknown + pot. nn & prot. nn => pot. nn & prot. nn
395
		// pot. unknown + pot. non null => pot. nn & pot. un
396
		// pot. unknown + pot. null => pot. n & pot. un
397
		// pot. unknown + pot. unknown => pot. unknown
398
		// pot. unknown + prot. non null => pot. nn & prot. nn
399
		// pot. unknown + prot. null => pot. n & prot. n
400
		// pot. unknown + start => pot. unknown
401
		// prot. non null + def. non null => def. non null
402
		// prot. non null + def. null => def. null
403
		// prot. non null + def. unknown => def. unknown
404
		// prot. non null + pot. n & pot. nn => pot. n & pot. nn
405
		// prot. non null + pot. n & pot. un => pot. n & pot. un
406
		// prot. non null + pot. n & prot. n => pot. n & prot. n
407
		// prot. non null + pot. nn & pot. un => pot. nn & pot. un
408
		// prot. non null + pot. nn & prot. nn => pot. nn & prot. nn
409
		// prot. non null + pot. non null => pot. nn & prot. nn
410
		// prot. non null + pot. null => pot. null
411
		// prot. non null + pot. unknown => pot. unknown
412
		// prot. non null + prot. non null => prot. non null
413
		// prot. non null + prot. null => prot. null
414
		// prot. non null + start => prot. non null
415
		// prot. null + def. non null => def. non null
416
		// prot. null + def. null => def. null
417
		// prot. null + def. unknown => def. unknown
418
		// prot. null + pot. n & pot. nn => pot. n & pot. nn
419
		// prot. null + pot. n & pot. un => pot. n & pot. un
420
		// prot. null + pot. n & prot. n => pot. n & prot. n
421
		// prot. null + pot. nn & pot. un => pot. nn & pot. un
422
		// prot. null + pot. nn & prot. nn => pot. nn & prot. nn
423
		// prot. null + pot. non null => pot. non null
424
		// prot. null + pot. null => pot. n & prot. n
425
		// prot. null + pot. unknown => pot. unknown
426
		// prot. null + prot. non null => prot. non null
427
		// prot. null + prot. null => prot. null
428
		// prot. null + start => prot. null
429
		// start + def. non null => def. non null
430
		// start + def. null => def. null
431
		// start + def. unknown => def. unknown
432
		// start + pot. n & pot. nn => pot. n & pot. nn
433
		// start + pot. n & pot. un => pot. n & pot. un
434
		// start + pot. n & prot. n => pot. n & prot. n
435
		// start + pot. nn & pot. un => pot. nn & pot. un
436
		// start + pot. nn & prot. nn => pot. nn & prot. nn
437
		// start + pot. non null => pot. non null
438
		// start + pot. null => pot. null
439
		// start + pot. unknown => pot. unknown
440
		// start + prot. non null => prot. non null
441
		// start + prot. null => prot. null
442
		// start + start => start
443
		// addInitializationsFrom DEFINITION END
444
			new ThreeDimensionalTransformation("addInitializationsFrom",
445
				new byte[][] {
446
				// addInitializationsFrom INITIALIZER START
447
				{0x00,0x00,0x00},
448
				{0x00,0x04,0x04},
449
				{0x00,0x08,0x08},
450
				{0x00,0x0C,0x0C},
451
				{0x00,0x10,0x10},
452
				{0x00,0x14,0x14},
453
				{0x00,0x18,0x18},
454
				{0x00,0x24,0x24},
455
				{0x00,0x28,0x28},
456
				{0x00,0x2C,0x2C},
457
				{0x00,0x30,0x30},
458
				{0x00,0x34,0x34},
459
				{0x00,0x38,0x38},
460
				{0x00,0x3C,0x3C},
461
				{0x04,0x00,0x04},
462
				{0x04,0x04,0x04},
463
				{0x04,0x08,0x0C},
464
				{0x04,0x0C,0x0C},
465
				{0x04,0x10,0x14},
466
				{0x04,0x14,0x14},
467
				{0x04,0x18,0x18},
468
				{0x04,0x24,0x24},
469
				{0x04,0x28,0x28},
470
				{0x04,0x2C,0x2C},
471
				{0x04,0x30,0x30},
472
				{0x04,0x34,0x34},
473
				{0x04,0x38,0x34},
474
				{0x04,0x3C,0x2C},
475
				{0x08,0x00,0x08},
476
				{0x08,0x04,0x0C},
477
				{0x08,0x08,0x08},
478
				{0x08,0x0C,0x0C},
479
				{0x08,0x10,0x18},
480
				{0x08,0x14,0x18},
481
				{0x08,0x18,0x18},
482
				{0x08,0x24,0x24},
483
				{0x08,0x28,0x28},
484
				{0x08,0x2C,0x2C},
485
				{0x08,0x30,0x30},
486
				{0x08,0x34,0x34},
487
				{0x08,0x38,0x38},
488
				{0x08,0x3C,0x2C},
489
				{0x0C,0x00,0x0C},
490
				{0x0C,0x04,0x0C},
491
				{0x0C,0x08,0x0C},
492
				{0x0C,0x0C,0x0C},
493
				{0x0C,0x10,0x18},
494
				{0x0C,0x14,0x18},
495
				{0x0C,0x18,0x18},
496
				{0x0C,0x24,0x24},
497
				{0x0C,0x28,0x28},
498
				{0x0C,0x2C,0x2C},
499
				{0x0C,0x30,0x30},
500
				{0x0C,0x34,0x34},
501
				{0x0C,0x38,0x34},
502
				{0x0C,0x3C,0x2C},
503
				{0x10,0x00,0x10},
504
				{0x10,0x04,0x14},
505
				{0x10,0x08,0x18},
506
				{0x10,0x0C,0x18},
507
				{0x10,0x10,0x10},
508
				{0x10,0x14,0x14},
509
				{0x10,0x18,0x18},
510
				{0x10,0x24,0x24},
511
				{0x10,0x28,0x28},
512
				{0x10,0x2C,0x2C},
513
				{0x10,0x30,0x30},
514
				{0x10,0x34,0x34},
515
				{0x10,0x38,0x34},
516
				{0x10,0x3C,0x3C},
517
				{0x14,0x00,0x14},
518
				{0x14,0x04,0x14},
519
				{0x14,0x08,0x18},
520
				{0x14,0x0C,0x18},
521
				{0x14,0x10,0x14},
522
				{0x14,0x14,0x14},
523
				{0x14,0x18,0x18},
524
				{0x14,0x24,0x24},
525
				{0x14,0x28,0x28},
526
				{0x14,0x2C,0x2C},
527
				{0x14,0x30,0x30},
528
				{0x14,0x34,0x34},
529
				{0x14,0x38,0x34},
530
				{0x14,0x3C,0x2C},
531
				{0x18,0x00,0x18},
532
				{0x18,0x04,0x18},
533
				{0x18,0x08,0x18},
534
				{0x18,0x0C,0x18},
535
				{0x18,0x10,0x18},
536
				{0x18,0x14,0x18},
537
				{0x18,0x18,0x18},
538
				{0x18,0x24,0x24},
539
				{0x18,0x28,0x28},
540
				{0x18,0x2C,0x2C},
541
				{0x18,0x30,0x30},
542
				{0x18,0x34,0x34},
543
				{0x18,0x38,0x34},
544
				{0x18,0x3C,0x2C},
545
				{0x24,0x00,0x24},
546
				{0x24,0x04,0x24},
547
				{0x24,0x08,0x24},
548
				{0x24,0x0C,0x24},
549
				{0x24,0x10,0x14},
550
				{0x24,0x14,0x14},
551
				{0x24,0x18,0x18},
552
				{0x24,0x24,0x24},
553
				{0x24,0x28,0x28},
554
				{0x24,0x2C,0x28},
555
				{0x24,0x30,0x30},
556
				{0x24,0x34,0x30},
557
				{0x24,0x38,0x30},
558
				{0x24,0x3C,0x28},
559
				{0x28,0x00,0x28},
560
				{0x28,0x04,0x24},
561
				{0x28,0x08,0x28},
562
				{0x28,0x0C,0x24},
563
				{0x28,0x10,0x18},
564
				{0x28,0x14,0x18},
565
				{0x28,0x18,0x18},
566
				{0x28,0x24,0x24},
567
				{0x28,0x28,0x28},
568
				{0x28,0x2C,0x28},
569
				{0x28,0x30,0x30},
570
				{0x28,0x34,0x34},
571
				{0x28,0x38,0x38},
572
				{0x28,0x3C,0x28},
573
				{0x2C,0x00,0x2C},
574
				{0x2C,0x04,0x0C},
575
				{0x2C,0x08,0x2C},
576
				{0x2C,0x0C,0x0C},
577
				{0x2C,0x10,0x18},
578
				{0x2C,0x14,0x18},
579
				{0x2C,0x18,0x18},
580
				{0x2C,0x24,0x24},
581
				{0x2C,0x28,0x28},
582
				{0x2C,0x2C,0x2C},
583
				{0x2C,0x30,0x30},
584
				{0x2C,0x34,0x34},
585
				{0x2C,0x38,0x38},
586
				{0x2C,0x3C,0x2C},
587
				{0x30,0x00,0x30},
588
				{0x30,0x04,0x14},
589
				{0x30,0x08,0x18},
590
				{0x30,0x0C,0x18},
591
				{0x30,0x10,0x30},
592
				{0x30,0x14,0x14},
593
				{0x30,0x18,0x18},
594
				{0x30,0x24,0x24},
595
				{0x30,0x28,0x28},
596
				{0x30,0x2C,0x2C},
597
				{0x30,0x30,0x30},
598
				{0x30,0x34,0x30},
599
				{0x30,0x38,0x30},
600
				{0x30,0x3C,0x3C},
601
				{0x34,0x00,0x34},
602
				{0x34,0x04,0x14},
603
				{0x34,0x08,0x18},
604
				{0x34,0x0C,0x18},
605
				{0x34,0x10,0x34},
606
				{0x34,0x14,0x14},
607
				{0x34,0x18,0x18},
608
				{0x34,0x24,0x24},
609
				{0x34,0x28,0x28},
610
				{0x34,0x2C,0x2C},
611
				{0x34,0x30,0x30},
612
				{0x34,0x34,0x34},
613
				{0x34,0x38,0x34},
614
				{0x34,0x3C,0x3C},
615
				{0x38,0x00,0x38},
616
				{0x38,0x04,0x04},
617
				{0x38,0x08,0x08},
618
				{0x38,0x0C,0x0C},
619
				{0x38,0x10,0x34},
620
				{0x38,0x14,0x14},
621
				{0x38,0x18,0x18},
622
				{0x38,0x24,0x24},
623
				{0x38,0x28,0x28},
624
				{0x38,0x2C,0x2C},
625
				{0x38,0x30,0x30},
626
				{0x38,0x34,0x34},
627
				{0x38,0x38,0x38},
628
				{0x38,0x3C,0x3C},
629
				{0x3C,0x00,0x3C},
630
				{0x3C,0x04,0x04},
631
				{0x3C,0x08,0x2C},
632
				{0x3C,0x0C,0x0C},
633
				{0x3C,0x10,0x10},
634
				{0x3C,0x14,0x14},
635
				{0x3C,0x18,0x18},
636
				{0x3C,0x24,0x24},
637
				{0x3C,0x28,0x28},
638
				{0x3C,0x2C,0x2C},
639
				{0x3C,0x30,0x30},
640
				{0x3C,0x34,0x34},
641
				{0x3C,0x38,0x38},
642
				{0x3C,0x3C,0x3C},
643
				// addInitializationsFrom INITIALIZER END
644
				}) {
645
			UnconditionalFlowInfo output(UnconditionalFlowInfo input1, 
646
					UnconditionalFlowInfo input2) {
647
				return (UnconditionalFlowInfo) 
648
					input1.copy().addInitializationsFrom(input2);
649
			}
650
		},
651
		// addPotentialInitializationsFrom DEFINITION START
652
		// def. non null + def. non null => def. non null		
653
		// def. non null + def. null => pot. n & pot. nn		
654
		// def. non null + def. unknown => def. unknown		
655
		// def. non null + pot. n & pot. nn => pot. n & pot. nn		
656
		// def. non null + pot. n & pot. un => pot. n & pot. nn		
657
		// def. non null + pot. n & prot. n => pot. n & pot. nn		
658
		// def. non null + pot. nn & pot. un => def. unknown		
659
		// def. non null + pot. nn & prot. nn => def. non null		
660
		// def. non null + pot. non null => def. non null		
661
		// def. non null + pot. null => pot. n & pot. nn		
662
		// def. non null + pot. unknown => def. unknown		
663
		// def. non null + prot. non null => def. non null		
664
		// def. non null + prot. null => def. non null		
665
		// def. non null + start => def. non null		
666
		// def. null + def. non null => pot. n & pot. nn		
667
		// def. null + def. null => def. null		
668
		// def. null + def. unknown => pot. n & pot. un		
669
		// def. null + pot. n & pot. nn => pot. n & pot. nn		
670
		// def. null + pot. n & pot. un => pot. n & pot. un
671
		// def. null + pot. n & prot. n => def. null		
672
		// def. null + pot. nn & pot. un => pot. n & pot. nn		
673
		// def. null + pot. nn & prot. nn => pot. n & pot. nn		
674
		// def. null + pot. non null => pot. n & pot. nn		
675
		// def. null + pot. null => def. null		
676
		// def. null + pot. unknown => pot. n & pot. un		
677
		// def. null + prot. non null => def. null		
678
		// def. null + prot. null => def. null		
679
		// def. null + start => def. null
680
		// def. unknown + def. non null => def. unknown
681
		// def. unknown + def. null => pot. n & pot. un		
682
		// def. unknown + def. unknown => def. unknown		
683
		// def. unknown + pot. n & pot. nn => pot. n & pot. nn		
684
		// def. unknown + pot. n & pot. un => pot. n & pot. un		
685
		// def. unknown + pot. n & prot. n => pot. n & pot. un		
686
		// def. unknown + pot. nn & pot. un => def. unknown		
687
		// def. unknown + pot. nn & prot. nn => def. unknown
688
		// def. unknown + pot. non null => def. unknown
689
		// def. unknown + pot. null => pot. n & pot. un		
690
		// def. unknown + pot. unknown => def. unknown		
691
		// def. unknown + prot. non null => def. unknown		
692
		// def. unknown + prot. null => def. unknown		
693
		// def. unknown + start => def. unknown		
694
		// pot. n & pot. nn + def. non null => pot. n & pot. nn		
695
		// pot. n & pot. nn + def. null => pot. n & pot. nn		
696
		// pot. n & pot. nn + def. unknown => pot. n & pot. nn		
697
		// pot. n & pot. nn + pot. n & pot. nn => pot. n & pot. nn		
698
		// pot. n & pot. nn + pot. n & pot. un => pot. n & pot. nn		
699
		// pot. n & pot. nn + pot. n & prot. n => pot. n & pot. nn		
700
		// pot. n & pot. nn + pot. nn & pot. un => pot. n & pot. nn		
701
		// pot. n & pot. nn + pot. nn & prot. nn => pot. n & pot. nn		
702
		// pot. n & pot. nn + pot. non null => pot. n & pot. nn		
703
		// pot. n & pot. nn + pot. null => pot. n & pot. nn		
704
		// pot. n & pot. nn + pot. unknown => pot. n & pot. nn		
705
		// pot. n & pot. nn + prot. non null => pot. n & pot. nn		
706
		// pot. n & pot. nn + prot. null => pot. n & pot. nn		
707
		// pot. n & pot. nn + start => pot. n & pot. nn		
708
		// pot. n & pot. un + def. non null => pot. n & pot. nn		
709
		// pot. n & pot. un + def. null => pot. n & pot. un		
710
		// pot. n & pot. un + def. unknown => pot. n & pot. un		
711
		// pot. n & pot. un + pot. n & pot. nn => pot. n & pot. nn		
712
		// pot. n & pot. un + pot. n & pot. un => pot. n & pot. un		
713
		// pot. n & pot. un + pot. n & prot. n => pot. n & pot. un		
714
		// pot. n & pot. un + pot. nn & pot. un => pot. n & pot. nn		
715
		// pot. n & pot. un + pot. nn & prot. nn => pot. n & pot. nn		
716
		// pot. n & pot. un + pot. non null => pot. n & pot. nn		
717
		// pot. n & pot. un + pot. null => pot. n & pot. un		
718
		// pot. n & pot. un + pot. unknown => pot. n & pot. un		
719
		// pot. n & pot. un + prot. non null => pot. n & pot. un		
720
		// pot. n & pot. un + prot. null => pot. n & pot. un		
721
		// pot. n & pot. un + start => pot. n & pot. un		
722
		// pot. n & prot. n + def. non null => pot. n & pot. nn		
723
		// pot. n & prot. n + def. null => pot. n & prot. n		
724
		// pot. n & prot. n + def. unknown => pot. n & pot. un		
725
		// pot. n & prot. n + pot. n & pot. nn => pot. n & pot. nn		
726
		// pot. n & prot. n + pot. n & pot. un => pot. n & pot. un		
727
		// pot. n & prot. n + pot. n & prot. n => pot. n & prot. n		
728
		// pot. n & prot. n + pot. nn & pot. un => pot. n & pot. nn		
729
		// pot. n & prot. n + pot. nn & prot. nn => pot. n & pot. nn		
730
		// pot. n & prot. n + pot. non null => pot. n & pot. nn		
731
		// pot. n & prot. n + pot. null => pot. n & prot. n		
732
		// pot. n & prot. n + pot. unknown => pot. n & pot. un		
733
		// pot. n & prot. n + prot. non null => pot. n & prot. n		
734
		// pot. n & prot. n + prot. null => pot. n & prot. n		
735
		// pot. n & prot. n + start => pot. n & prot. n		
736
		// pot. nn & pot. un + def. non null => pot. nn & pot. un		
737
		// pot. nn & pot. un + def. null => pot. n & pot. nn		
738
		// pot. nn & pot. un + def. unknown => pot. nn & pot. un		
739
		// pot. nn & pot. un + pot. n & pot. nn => pot. n & pot. nn		
740
		// pot. nn & pot. un + pot. n & pot. un => pot. n & pot. nn		
741
		// pot. nn & pot. un + pot. n & prot. n => pot. n & pot. nn		
742
		// pot. nn & pot. un + pot. nn & pot. un => pot. nn & pot. un		
743
		// pot. nn & pot. un + pot. nn & prot. nn => pot. nn & pot. un		
744
		// pot. nn & pot. un + pot. non null => pot. nn & pot. un		
745
		// pot. nn & pot. un + pot. null => pot. n & pot. nn		
746
		// pot. nn & pot. un + pot. unknown => pot. nn & pot. un		
747
		// pot. nn & pot. un + prot. non null => pot. nn & pot. un		
748
		// pot. nn & pot. un + prot. null => pot. nn & pot. un		
749
		// pot. nn & pot. un + start => pot. nn & pot. un		
750
		// pot. nn & prot. nn + def. non null => pot. nn & prot. nn		
751
		// pot. nn & prot. nn + def. null => pot. n & pot. nn		
752
		// pot. nn & prot. nn + def. unknown => pot. nn & pot. un
753
		// pot. nn & prot. nn + pot. n & pot. nn => pot. n & pot. nn		
754
		// pot. nn & prot. nn + pot. n & pot. un => pot. n & pot. nn		
755
		// pot. nn & prot. nn + pot. n & prot. n => pot. n & pot. nn		
756
		// pot. nn & prot. nn + pot. nn & pot. un => pot. nn & pot. un	// see test1501
757
		// pot. nn & prot. nn + pot. nn & prot. nn => pot. nn & prot. nn		
758
		// pot. nn & prot. nn + pot. non null => pot. nn & prot. nn		
759
		// pot. nn & prot. nn + pot. null => pot. n & pot. nn		
760
		// pot. nn & prot. nn + pot. unknown => pot. nn & pot. un
761
		// pot. nn & prot. nn + prot. non null => pot. nn & prot. nn		
762
		// pot. nn & prot. nn + prot. null => pot. nn & prot. nn		
763
		// pot. nn & prot. nn + start => pot. nn & prot. nn		
764
		// pot. non null + def. non null => pot. non null		
765
		// pot. non null + def. null => pot. n & pot. nn		
766
		// pot. non null + def. unknown => pot. nn & pot. un		
767
		// pot. non null + pot. n & pot. nn => pot. n & pot. nn		
768
		// pot. non null + pot. n & pot. un => pot. n & pot. nn		
769
		// pot. non null + pot. n & prot. n => pot. n & pot. nn		
770
		// pot. non null + pot. nn & pot. un => pot. nn & pot. un		
771
		// pot. non null + pot. nn & prot. nn => pot. non null		
772
		// pot. non null + pot. non null => pot. non null		
773
		// pot. non null + pot. null => pot. n & pot. nn		
774
		// pot. non null + pot. unknown => pot. nn & pot. un		
775
		// pot. non null + prot. non null => pot. non null		
776
		// pot. non null + prot. null => pot. non null		
777
		// pot. non null + start => pot. non null		
778
		// pot. null + def. non null => pot. n & pot. nn		
779
		// pot. null + def. null => pot. null		
780
		// pot. null + def. unknown => pot. n & pot. un		
781
		// pot. null + pot. n & pot. nn => pot. n & pot. nn		
782
		// pot. null + pot. n & pot. un => pot. n & pot. un		
783
		// pot. null + pot. n & prot. n => pot. null		
784
		// pot. null + pot. nn & pot. un => pot. n & pot. nn		
785
		// pot. null + pot. nn & prot. nn => pot. n & pot. nn		
786
		// pot. null + pot. non null => pot. n & pot. nn		
787
		// pot. null + pot. null => pot. null		
788
		// pot. null + pot. unknown => pot. n & pot. un		
789
		// pot. null + prot. non null => pot. null		
790
		// pot. null + prot. null => pot. null		
791
		// pot. null + start => pot. null		
792
		// pot. unknown + def. non null => pot. nn & pot. un		
793
		// pot. unknown + def. null => pot. n & pot. un		
794
		// pot. unknown + def. unknown => pot. unknown		
795
		// pot. unknown + pot. n & pot. nn => pot. n & pot. nn		
796
		// pot. unknown + pot. n & pot. un => pot. n & pot. un		
797
		// pot. unknown + pot. n & prot. n => pot. n & pot. un		
798
		// pot. unknown + pot. nn & pot. un => pot. nn & pot. un		
799
		// pot. unknown + pot. nn & prot. nn => pot. nn & pot. un		
800
		// pot. unknown + pot. non null => pot. nn & pot. un		
801
		// pot. unknown + pot. null => pot. n & pot. un		
802
		// pot. unknown + pot. unknown => pot. unknown		
803
		// pot. unknown + prot. non null => pot. unknown		
804
		// pot. unknown + prot. null => pot. unknown		
805
		// pot. unknown + start => pot. unknown		
806
		// prot. non null + def. non null => pot. nn & prot. nn
807
		// prot. non null + def. null => pot. null		
808
		// prot. non null + def. unknown => pot. unknown
809
		// prot. non null + pot. n & pot. nn => pot. n & pot. nn		
810
		// prot. non null + pot. n & pot. un => pot. n & pot. un		
811
		// prot. non null + pot. n & prot. n => pot. null		
812
		// prot. non null + pot. nn & pot. un => pot. nn & pot. un	// see test1500
813
		// prot. non null + pot. nn & prot. nn => pot. nn & prot. nn		
814
		// prot. non null + pot. non null => pot. nn & prot. nn		
815
		// prot. non null + pot. null => pot. null		
816
		// prot. non null + pot. unknown => pot. unknown
817
		// prot. non null + prot. non null => prot. non null		
818
		// prot. non null + prot. null => prot. non null
819
		// prot. non null + start => prot. non null		
820
		// prot. null + def. non null => pot. non null		
821
		// prot. null + def. null => pot. n & prot. n		
822
		// prot. null + def. unknown => pot. unknown		
823
		// prot. null + pot. n & pot. nn => pot. n & pot. nn		
824
		// prot. null + pot. n & pot. un => pot. n & pot. un		
825
		// prot. null + pot. n & prot. n => pot. n & prot. n		
826
		// prot. null + pot. nn & pot. un => pot. nn & pot. un		
827
		// prot. null + pot. nn & prot. nn => pot. non null		
828
		// prot. null + pot. non null => pot. non null		
829
		// prot. null + pot. null => pot. n & prot. n		
830
		// prot. null + pot. unknown => pot. unknown		
831
		// prot. null + prot. non null => prot. null
832
		// prot. null + prot. null => prot. null		
833
		// prot. null + start => prot. null		
834
		// start + def. non null => pot. non null		
835
		// start + def. null => pot. null		
836
		// start + def. unknown => pot. unknown		
837
		// start + pot. n & pot. nn => pot. n & pot. nn		
838
		// start + pot. n & pot. un => pot. n & pot. un		
839
		// start + pot. n & prot. n => pot. null		
840
		// start + pot. nn & pot. un => pot. nn & pot. un		
841
		// start + pot. nn & prot. nn => pot. non null		
842
		// start + pot. non null => pot. non null		
843
		// start + pot. null => pot. null		
844
		// start + pot. unknown => pot. unknown		
845
		// start + prot. non null => start // PREMATURE may need to be tainted?
846
		// start + prot. null => start		// PREMATURE may need to be tainted?
847
		// start + start => start
848
		// addPotentialInitializationsFrom DEFINITION END
849
		addPotentialInitializationsFrom =
850
			new ThreeDimensionalTransformation("addPotentialInitializationsFrom",
851
				new byte[][] {
852
				// addPotentialInitializationsFrom INITIALIZER START
853
				{0x00,0x00,0x00},
854
				{0x00,0x04,0x04},
855
				{0x00,0x08,0x08},
856
				{0x00,0x0C,0x0C},
857
				{0x00,0x10,0x10},
858
				{0x00,0x14,0x14},
859
				{0x00,0x18,0x18},
860
				{0x00,0x24,0x04},
861
				{0x00,0x28,0x08},
862
				{0x00,0x2C,0x08},
863
				{0x00,0x30,0x10},
864
				{0x00,0x34,0x10},
865
				{0x00,0x38,0x00},
866
				{0x00,0x3C,0x00},
867
				{0x04,0x00,0x04},
868
				{0x04,0x04,0x04},
869
				{0x04,0x08,0x0C},
870
				{0x04,0x0C,0x0C},
871
				{0x04,0x10,0x14},
872
				{0x04,0x14,0x14},
873
				{0x04,0x18,0x18},
874
				{0x04,0x24,0x04},
875
				{0x04,0x28,0x0C},
876
				{0x04,0x2C,0x0C},
877
				{0x04,0x30,0x14},
878
				{0x04,0x34,0x14},
879
				{0x04,0x38,0x04},
880
				{0x04,0x3C,0x04},
881
				{0x08,0x00,0x08},
882
				{0x08,0x04,0x0C},
883
				{0x08,0x08,0x08},
884
				{0x08,0x0C,0x0C},
885
				{0x08,0x10,0x18},
886
				{0x08,0x14,0x18},
887
				{0x08,0x18,0x18},
888
				{0x08,0x24,0x0C},
889
				{0x08,0x28,0x08},
890
				{0x08,0x2C,0x08},
891
				{0x08,0x30,0x18},
892
				{0x08,0x34,0x18},
893
				{0x08,0x38,0x08},
894
				{0x08,0x3C,0x08},
895
				{0x0C,0x00,0x0C},
896
				{0x0C,0x04,0x0C},
897
				{0x0C,0x08,0x0C},
898
				{0x0C,0x0C,0x0C},
899
				{0x0C,0x10,0x18},
900
				{0x0C,0x14,0x18},
901
				{0x0C,0x18,0x18},
902
				{0x0C,0x24,0x0C},
903
				{0x0C,0x28,0x0C},
904
				{0x0C,0x2C,0x0C},
905
				{0x0C,0x30,0x18},
906
				{0x0C,0x34,0x18},
907
				{0x0C,0x38,0x0C},
908
				{0x0C,0x3C,0x0C},
909
				{0x10,0x00,0x10},
910
				{0x10,0x04,0x14},
911
				{0x10,0x08,0x18},
912
				{0x10,0x0C,0x18},
913
				{0x10,0x10,0x10},
914
				{0x10,0x14,0x14},
915
				{0x10,0x18,0x18},
916
				{0x10,0x24,0x14},
917
				{0x10,0x28,0x18},
918
				{0x10,0x2C,0x18},
919
				{0x10,0x30,0x10},
920
				{0x10,0x34,0x10},
921
				{0x10,0x38,0x10},
922
				{0x10,0x3C,0x10},
923
				{0x14,0x00,0x14},
924
				{0x14,0x04,0x14},
925
				{0x14,0x08,0x18},
926
				{0x14,0x0C,0x18},
927
				{0x14,0x10,0x14},
928
				{0x14,0x14,0x14},
929
				{0x14,0x18,0x18},
930
				{0x14,0x24,0x14},
931
				{0x14,0x28,0x18},
932
				{0x14,0x2C,0x18},
933
				{0x14,0x30,0x14},
934
				{0x14,0x34,0x14},
935
				{0x14,0x38,0x14},
936
				{0x14,0x3C,0x14},
937
				{0x18,0x00,0x18},
938
				{0x18,0x04,0x18},
939
				{0x18,0x08,0x18},
940
				{0x18,0x0C,0x18},
941
				{0x18,0x10,0x18},
942
				{0x18,0x14,0x18},
943
				{0x18,0x18,0x18},
944
				{0x18,0x24,0x18},
945
				{0x18,0x28,0x18},
946
				{0x18,0x2C,0x18},
947
				{0x18,0x30,0x18},
948
				{0x18,0x34,0x18},
949
				{0x18,0x38,0x18},
950
				{0x18,0x3C,0x18},
951
				{0x24,0x00,0x24},
952
				{0x24,0x04,0x24},
953
				{0x24,0x08,0x24},
954
				{0x24,0x0C,0x24},
955
				{0x24,0x10,0x14},
956
				{0x24,0x14,0x14},
957
				{0x24,0x18,0x18},
958
				{0x24,0x24,0x24},
959
				{0x24,0x28,0x24},
960
				{0x24,0x2C,0x24},
961
				{0x24,0x30,0x14},
962
				{0x24,0x34,0x14},
963
				{0x24,0x38,0x24},
964
				{0x24,0x3C,0x24},
965
				{0x28,0x00,0x28},
966
				{0x28,0x04,0x24},
967
				{0x28,0x08,0x28},
968
				{0x28,0x0C,0x24},
969
				{0x28,0x10,0x18},
970
				{0x28,0x14,0x18},
971
				{0x28,0x18,0x18},
972
				{0x28,0x24,0x24},
973
				{0x28,0x28,0x28},
974
				{0x28,0x2C,0x28},
975
				{0x28,0x30,0x18},
976
				{0x28,0x34,0x18},
977
				{0x28,0x38,0x28},
978
				{0x28,0x3C,0x28},
979
				{0x2C,0x00,0x2C},
980
				{0x2C,0x04,0x0C},
981
				{0x2C,0x08,0x2C},
982
				{0x2C,0x0C,0x0C},
983
				{0x2C,0x10,0x18},
984
				{0x2C,0x14,0x18},
985
				{0x2C,0x18,0x18},
986
				{0x2C,0x24,0x0C},
987
				{0x2C,0x28,0x2C},
988
				{0x2C,0x2C,0x2C},
989
				{0x2C,0x30,0x18},
990
				{0x2C,0x34,0x18},
991
				{0x2C,0x38,0x2C},
992
				{0x2C,0x3C,0x2C},
993
				{0x30,0x00,0x30},
994
				{0x30,0x04,0x14},
995
				{0x30,0x08,0x18},
996
				{0x30,0x0C,0x18},
997
				{0x30,0x10,0x30},
998
				{0x30,0x14,0x14},
999
				{0x30,0x18,0x18},
1000
				{0x30,0x24,0x14},
1001
				{0x30,0x28,0x18},
1002
				{0x30,0x2C,0x18},
1003
				{0x30,0x30,0x30},
1004
				{0x30,0x34,0x30},
1005
				{0x30,0x38,0x30},
1006
				{0x30,0x3C,0x30},
1007
				{0x34,0x00,0x34},
1008
				{0x34,0x04,0x14},
1009
				{0x34,0x08,0x18},
1010
				{0x34,0x0C,0x18},
1011
				{0x34,0x10,0x34},
1012
				{0x34,0x14,0x14},
1013
				{0x34,0x18,0x18},
1014
				{0x34,0x24,0x14},
1015
				{0x34,0x28,0x18},
1016
				{0x34,0x2C,0x18},
1017
				{0x34,0x30,0x34},
1018
				{0x34,0x34,0x34},
1019
				{0x34,0x38,0x34},
1020
				{0x34,0x3C,0x34},
1021
				{0x38,0x00,0x38},
1022
				{0x38,0x04,0x04},
1023
				{0x38,0x08,0x08},
1024
				{0x38,0x0C,0x0C},
1025
				{0x38,0x10,0x34},
1026
				{0x38,0x14,0x14},
1027
				{0x38,0x18,0x18},
1028
				{0x38,0x24,0x04},
1029
				{0x38,0x28,0x08},
1030
				{0x38,0x2C,0x08},
1031
				{0x38,0x30,0x34},
1032
				{0x38,0x34,0x34},
1033
				{0x38,0x38,0x38},
1034
				{0x38,0x3C,0x38},
1035
				{0x3C,0x00,0x3C},
1036
				{0x3C,0x04,0x04},
1037
				{0x3C,0x08,0x2C},
1038
				{0x3C,0x0C,0x0C},
1039
				{0x3C,0x10,0x10},
1040
				{0x3C,0x14,0x14},
1041
				{0x3C,0x18,0x18},
1042
				{0x3C,0x24,0x04},
1043
				{0x3C,0x28,0x2C},
1044
				{0x3C,0x2C,0x2C},
1045
				{0x3C,0x30,0x10},
1046
				{0x3C,0x34,0x10},
1047
				{0x3C,0x38,0x3C},
1048
				{0x3C,0x3C,0x3C},
1049
				// addPotentialInitializationsFrom INITIALIZER END
1050
				}) {
1051
			UnconditionalFlowInfo output(UnconditionalFlowInfo input1, 
1052
					UnconditionalFlowInfo input2) {
1053
				return (UnconditionalFlowInfo) 
1054
					input1.copy().addPotentialInitializationsFrom(input2);
1055
			}
1056
		},
1057
		mergedWith =
1058
		// mergedWith DEFINITION START
1059
		// def. non null + def. non null => def. non null		
1060
		// def. non null + def. null => pot. n & pot. nn
1061
		// def. null + def. null => def. null		
1062
		// def. unknown + def. non null => def. unknown
1063
		// def. unknown + def. null => pot. n & pot. un // pot. n priv. over def. unknown
1064
		// def. unknown + def. unknown => def. unknown		
1065
		// pot. n & pot. nn + def. non null => pot. n & pot. nn		
1066
		// pot. n & pot. nn + def. null => pot. n & pot. nn		
1067
		// pot. n & pot. nn + def. unknown => pot. n & pot. nn		
1068
		// pot. n & pot. nn + pot. n & pot. nn => pot. n & pot. nn		
1069
		// pot. n & pot. un + def. non null => pot. n & pot. nn		
1070
		// pot. n & pot. un + def. null => pot. n & pot. un		
1071
		// pot. n & pot. un + def. unknown => pot. n & pot. un		
1072
		// pot. n & pot. un + pot. n & pot. nn => pot. n & pot. nn		
1073
		// pot. n & pot. un + pot. n & pot. un => pot. n & pot. un		
1074
		// pot. n & prot. n + def. non null => pot. n & pot. nn		
1075
		// pot. n & prot. n + def. null => pot. n & prot. n
1076
		// pot. n & prot. n + def. unknown => pot. n & pot. un		
1077
		// pot. n & prot. n + pot. n & pot. nn => pot. n & pot. nn		
1078
		// pot. n & prot. n + pot. n & pot. un => pot. n & pot. un		
1079
		// pot. n & prot. n + pot. n & prot. n => pot. n & prot. n		
1080
		// pot. nn & pot. un + def. non null => pot. nn & pot. un		
1081
		// pot. nn & pot. un + def. null => pot. n & pot. nn		
1082
		// pot. nn & pot. un + def. unknown => pot. nn & pot. un		
1083
		// pot. nn & pot. un + pot. n & pot. nn => pot. n & pot. nn		
1084
		// pot. nn & pot. un + pot. n & pot. un => pot. n & pot. nn		
1085
		// pot. nn & pot. un + pot. n & prot. n => pot. n & pot. nn		
1086
		// pot. nn & pot. un + pot. nn & pot. un => pot. nn & pot. un		
1087
		// pot. nn & pot. un + pot. null => pot. n & pot. nn		
1088
		// pot. nn & prot. nn + def. non null => pot. nn & prot. nn
1089
		// pot. nn & prot. nn + def. null => pot. n & pot. nn		
1090
		// pot. nn & prot. nn + def. unknown => pot. nn & pot. un		
1091
		// pot. nn & prot. nn + pot. n & pot. nn => pot. n & pot. nn		
1092
		// pot. nn & prot. nn + pot. n & pot. un => pot. n & pot. nn		
1093
		// pot. nn & prot. nn + pot. n & prot. n => pot. n & pot. nn		
1094
		// pot. nn & prot. nn + pot. nn & pot. un => pot. nn & pot. un		
1095
		// pot. nn & prot. nn + pot. nn & prot. nn => pot. nn & prot. nn		
1096
		// pot. nn & prot. nn + pot. null => pot. n & pot. nn		
1097
		// pot. non null + def. non null => pot. non null		
1098
		// pot. non null + def. null => pot. n & pot. nn		
1099
		// pot. non null + def. unknown => pot. nn & pot. un		
1100
		// pot. non null + pot. n & pot. nn => pot. n & pot. nn		
1101
		// pot. non null + pot. n & pot. un => pot. n & pot. nn		
1102
		// pot. non null + pot. n & prot. n => pot. n & pot. nn		
1103
		// pot. non null + pot. nn & pot. un => pot. nn & pot. un		
1104
		// pot. non null + pot. nn & prot. nn => pot. non null		
1105
		// pot. non null + pot. non null => pot. non null		
1106
		// pot. non null + pot. null => pot. n & pot. nn		
1107
		// pot. null + def. non null => pot. n & pot. nn		
1108
		// pot. null + def. null => pot. null		
1109
		// pot. null + def. unknown => pot. n & pot. un		
1110
		// pot. null + pot. n & pot. nn => pot. n & pot. nn		
1111
		// pot. null + pot. n & pot. un => pot. n & pot. un		
1112
		// pot. null + pot. n & prot. n => pot. null		
1113
		// pot. null + pot. null => pot. null		
1114
		// pot. unknown + def. non null => pot. nn & pot. un		
1115
		// pot. unknown + def. null => pot. n & pot. un		
1116
		// pot. unknown + def. unknown => pot. unknown		
1117
		// pot. unknown + pot. n & pot. nn => pot. n & pot. nn		
1118
		// pot. unknown + pot. n & pot. un => pot. n & pot. un		
1119
		// pot. unknown + pot. n & prot. n => pot. n & pot. un		
1120
		// pot. unknown + pot. nn & pot. un => pot. nn & pot. un		
1121
		// pot. unknown + pot. nn & prot. nn => pot. nn & pot. un		
1122
		// pot. unknown + pot. non null => pot. nn & pot. un		
1123
		// pot. unknown + pot. null => pot. n & pot. un		
1124
		// pot. unknown + pot. unknown => pot. unknown		
1125
		// prot. non null + def. non null => pot. nn & prot. nn		
1126
		// prot. non null + def. null => pot. null		
1127
		// prot. non null + def. unknown => def. unknown // test726
1128
		// prot. non null + pot. n & pot. nn => pot. n & pot. nn		
1129
		// prot. non null + pot. n & pot. un => pot. n & pot. un		
1130
		// prot. non null + pot. n & prot. n => pot. null		
1131
		// prot. non null + pot. nn & pot. un => pot. nn & pot. un		
1132
		// prot. non null + pot. nn & prot. nn => pot. nn & prot. nn		
1133
		// prot. non null + pot. non null => pot. non null		
1134
		// prot. non null + pot. null => pot. null		
1135
		// prot. non null + pot. unknown => pot. unknown		
1136
		// prot. non null + prot. non null => prot. non null		
1137
		// prot. non null + prot. null => pot. null // PREMATURE use tainted instead
1138
		// prot. null + def. non null => pot. non null		 // PREMATURE should become tainted null & pot. nn... not really, depends on the three way merge... or even on the conditions that got there (pb with no contrib prot. null branch)
1139
		// prot. null + def. null => pot. n & prot. n		
1140
		// prot. null + def. unknown => pot. unknown	// PREMATURE possibly wrong, but no test case yet	
1141
		// prot. null + pot. n & pot. nn => pot. n & pot. nn		
1142
		// prot. null + pot. n & pot. un => pot. n & pot. un		
1143
		// prot. null + pot. n & prot. n => pot. n & prot. n		
1144
		// prot. null + pot. nn & pot. un => pot. n & pot. nn
1145
		// prot. null + pot. nn & prot. nn => pot. n & pot. nn
1146
		// prot. null + pot. non null => pot. n & pot. nn
1147
		// prot. null + pot. null => pot. null		
1148
		// prot. null + pot. unknown => pot. unknown // PREMATURE possibly wrong, but no test case yet		
1149
		// prot. null + prot. null => prot. null		
1150
		// start + def. non null => pot. non null		
1151
		// start + def. null => pot. null		
1152
		// start + def. unknown => pot. unknown		
1153
		// start + pot. n & pot. nn => pot. n & pot. nn		
1154
		// start + pot. n & pot. un => pot. n & pot. un		
1155
		// start + pot. n & prot. n => pot. null		
1156
		// start + pot. nn & pot. un => pot. nn & pot. un		
1157
		// start + pot. nn & prot. nn => pot. non null		
1158
		// start + pot. non null => pot. non null		
1159
		// start + pot. null => pot. null		
1160
		// start + pot. unknown => pot. unknown		
1161
		// start + prot. non null => start // PREMATURE should it taint?		
1162
		// start + prot. null => start		
1163
		// start + start => start		
1164
		// mergedWith DEFINITION END
1165
			new SymmetricalThreeDimensionalTransformation("mergedWith",
1166
				new byte[][] {
1167
				// mergedWith INITIALIZER START
1168
				{0x00,0x00,0x00},
1169
				{0x00,0x04,0x04},
1170
				{0x00,0x08,0x08},
1171
				{0x00,0x0C,0x0C},
1172
				{0x00,0x10,0x10},
1173
				{0x00,0x14,0x14},
1174
				{0x00,0x18,0x18},
1175
				{0x00,0x24,0x04},
1176
				{0x00,0x28,0x08},
1177
				{0x00,0x2C,0x08},
1178
				{0x00,0x30,0x10},
1179
				{0x00,0x34,0x10},
1180
				{0x00,0x38,0x00},
1181
				{0x00,0x3C,0x00},
1182
				{0x04,0x04,0x04},
1183
				{0x04,0x08,0x0C},
1184
				{0x04,0x0C,0x0C},
1185
				{0x04,0x10,0x14},
1186
				{0x04,0x14,0x14},
1187
				{0x04,0x18,0x18},
1188
				{0x04,0x24,0x04},
1189
				{0x04,0x28,0x0C},
1190
				{0x04,0x2C,0x0C},
1191
				{0x04,0x30,0x14},
1192
				{0x04,0x34,0x14},
1193
				{0x08,0x08,0x08},
1194
				{0x08,0x0C,0x0C},
1195
				{0x08,0x10,0x18},
1196
				{0x08,0x14,0x18},
1197
				{0x08,0x18,0x18},
1198
				{0x08,0x24,0x0C},
1199
				{0x08,0x28,0x08},
1200
				{0x08,0x2C,0x08},
1201
				{0x08,0x30,0x18},
1202
				{0x08,0x34,0x18},
1203
				{0x0C,0x0C,0x0C},
1204
				{0x0C,0x10,0x18},
1205
				{0x0C,0x14,0x18},
1206
				{0x0C,0x18,0x18},
1207
				{0x0C,0x24,0x0C},
1208
				{0x0C,0x28,0x0C},
1209
				{0x0C,0x30,0x18},
1210
				{0x0C,0x34,0x18},
1211
				{0x10,0x10,0x10},
1212
				{0x10,0x14,0x14},
1213
				{0x10,0x18,0x18},
1214
				{0x10,0x24,0x14},
1215
				{0x10,0x28,0x18},
1216
				{0x10,0x30,0x10},
1217
				{0x10,0x34,0x10},
1218
				{0x14,0x14,0x14},
1219
				{0x14,0x18,0x18},
1220
				{0x14,0x24,0x14},
1221
				{0x14,0x28,0x18},
1222
				{0x14,0x30,0x14},
1223
				{0x18,0x18,0x18},
1224
				{0x18,0x24,0x18},
1225
				{0x18,0x28,0x18},
1226
				{0x18,0x30,0x18},
1227
				{0x24,0x24,0x24},
1228
				{0x24,0x28,0x24},
1229
				{0x24,0x30,0x14},
1230
				{0x28,0x28,0x28},
1231
				{0x28,0x30,0x18},
1232
				{0x2C,0x0C,0x0C},
1233
				{0x2C,0x10,0x18},
1234
				{0x2C,0x14,0x18},
1235
				{0x2C,0x18,0x18},
1236
				{0x2C,0x24,0x0C},
1237
				{0x2C,0x28,0x2C},
1238
				{0x2C,0x2C,0x2C},
1239
				{0x2C,0x30,0x18},
1240
				{0x2C,0x34,0x18},
1241
				{0x30,0x30,0x30},
1242
				{0x34,0x14,0x14},
1243
				{0x34,0x18,0x18},
1244
				{0x34,0x24,0x14},
1245
				{0x34,0x28,0x18},
1246
				{0x34,0x30,0x34},
1247
				{0x34,0x34,0x34},
1248
				{0x38,0x04,0x04},
1249
				{0x38,0x08,0x18},
1250
				{0x38,0x0C,0x18},
1251
				{0x38,0x10,0x10},
1252
				{0x38,0x14,0x14},
1253
				{0x38,0x18,0x18},
1254
				{0x38,0x24,0x04},
1255
				{0x38,0x28,0x08},
1256
				{0x38,0x2C,0x18},
1257
				{0x38,0x30,0x34},
1258
				{0x38,0x34,0x34},
1259
				{0x38,0x38,0x38},
1260
				{0x3C,0x04,0x04},
1261
				{0x3C,0x08,0x08},
1262
				{0x3C,0x0C,0x0C},
1263
				{0x3C,0x10,0x10},
1264
				{0x3C,0x14,0x14},
1265
				{0x3C,0x18,0x18},
1266
				{0x3C,0x24,0x24},
1267
				{0x3C,0x28,0x2C},
1268
				{0x3C,0x2C,0x2C},
1269
				{0x3C,0x30,0x10},
1270
				{0x3C,0x34,0x10},
1271
				{0x3C,0x38,0x10},
1272
				{0x3C,0x3C,0x3C},
1273
				// mergedWith INITIALIZER END
1274
				}) {
1275
			UnconditionalFlowInfo output(UnconditionalFlowInfo input1, 
1276
					UnconditionalFlowInfo input2) {
1277
				return input1.copy().mergedWith(input2);
1278
			}
1279
		},
1280
		newNullInfoRegistry = 
1281
		// newNullInfoRegistry DEFINITION START
1282
		// start => start
1283
		// prot. non null => start
1284
		// prot. null => start
1285
		// pot. unknown => start
1286
		// pot. non null => start
1287
		// pot. nn & prot. nn => start
1288
		// pot. nn & pot. un => start
1289
		// pot. null => start
1290
		// pot. n & prot. n => start
1291
		// pot. n & pot. un => start
1292
		// pot. n & pot. nn => start
1293
		// def. unknown => pot. unknown
1294
		// def. non null => pot. non null
1295
		// def. null => pot. null
1296
		// newNullInfoRegistry DEFINITION END
1297
			new CreationalTransformation("newNullInfoRegistry",
1298
				new byte[][] {
1299
				// newNullInfoRegistry INITIALIZER START
1300
				{0x00,0x00},
1301
				{0x04,0x00},
1302
				{0x08,0x00},
1303
				{0x0C,0x00},
1304
				{0x10,0x00},
1305
				{0x14,0x00},
1306
				{0x18,0x00},
1307
				{0x24,0x04},
1308
				{0x28,0x08},
1309
				{0x2C,0x00},
1310
				{0x30,0x10},
1311
				{0x34,0x00},
1312
				{0x38,0x00},
1313
				{0x3C,0x00},
1314
				// newNullInfoRegistry INITIALIZER END
1315
				}) {
1316
			UnconditionalFlowInfo output(UnconditionalFlowInfo input) {
1317
				return NullInfoRegistryTestHarness.
1318
					testNullInfoRegistry((UnconditionalFlowInfoTestHarness) input);
1319
			}
1320
		};		
1321
	public static final Transformation[] transformations = {
1322
			markAsComparedEqualToNonNull,
1323
			markAsComparedEqualToNull,
1324
			markAsDefinitelyNonNull,
1325
			markAsDefinitelyNull,
1326
			markAsDefinitelyUnknown,
1327
			addInitializationsFrom,
1328
			addPotentialInitializationsFrom,
1329
			mergedWith,
1330
			newNullInfoRegistry
1331
		};
1332
public abstract static class Transformation {
1333
	public String name; 
1334
	String	definitionStartMarker, definitionEndMarker, 
1335
		initializerStartMarker,	initializerEndMarker;
1336
	int dimension;
1337
	public Map initializedTransitions, computedTransitions;
1338
		// PREMATURE limit public access
1339
	int failuresNb; // transient
1340
// PREMATURE complete the test coverage for NullInfoRegistry (need to consider several classes
1341
//  		 of transitions so as to avoid considering NullInfoRegistry states and 
1342
//			 UnconditionalFlowInfo states into the same pool; moreover, cross classes 
1343
//			 transformations exist.
1344
Transformation(String name) {
1345
	this.name = name;
1346
	this.definitionStartMarker = "// " + name + " " + CodeAnalysis.definitionStartMarker;
1347
	this.definitionEndMarker = "// " + name + " " + CodeAnalysis.definitionEndMarker;
1348
	this.initializerStartMarker = "// " + name + " " + CodeAnalysis.initializerStartMarker;
1349
	this.initializerEndMarker = "// " + name + " " + CodeAnalysis.initializerEndMarker;
1350
}
1351
abstract State[] computeOutputs(State[] inputs);
1352
abstract void hydrate();
1353
void fail() {
1354
	if (this.failuresNb == 0) {
1355
		System.out.println(this.name + " failures: ");
1356
	}
1357
	this.failuresNb++;
1358
}
1359
abstract void printTruthTables(File outputDirectory);
1360
1361
static boolean checkContiguity(String a, String b) {
1362
	int aLength;
1363
	if ((aLength = a.length()) != b.length()) {
1364
		System.out.println("inappropriate string length: " + a + " vs " + b);
1365
		return false;
1366
	}
1367
	int status = 0;
1368
	for (int i = 0; i < aLength; i++) {
1369
		if (a.charAt(i) != b.charAt(i)) {
1370
			status++;
1371
		} 
1372
	}
1373
	if (status != 1) {
1374
		System.out.println("non contiguous strings: " + a + " vs " + b);
1375
		return false;
1376
	}
1377
	return true;
1378
}
1379
1380
final static String truthTableRowNames[] = { // need a specific order to yield simplication opportunities
1381
		"000000",
1382
		"000100",
1383
		"001100",
1384
		"001000",
1385
		"011000",
1386
		"011100",
1387
		"010100",
1388
		"010000",
1389
		"110000",
1390
		"110100",
1391
		"111100",
1392
		"111000",
1393
		"101000",
1394
		"101100",
1395
		"100100",
1396
		"100000",		
1397
		// PREMATURE cheated to group first four bits... reconsider
1398
		"000001",
1399
		"000011",
1400
		"000010",
1401
		"000110",
1402
		"000111",
1403
		"000101",
1404
		"001101",
1405
		"001111",
1406
		"001110",
1407
		"001010",
1408
		"001011",
1409
		"001001",
1410
		"011001",
1411
		"011011",
1412
		"011010",
1413
		"011110",
1414
		"011111",
1415
		"011101",
1416
		"010101",
1417
		"010111",
1418
		"010110",
1419
		"010010",
1420
		"010011",
1421
		"010001",
1422
		"110001",
1423
		"110011",
1424
		"110010",
1425
		"110110",
1426
		"110111",
1427
		"110101",
1428
		"111101",
1429
		"111111",
1430
		"111110",
1431
		"111010",
1432
		"111011",
1433
		"111001",
1434
		"101001",
1435
		"101011",
1436
		"101010",
1437
		"101110",
1438
		"101111",
1439
		"101101",
1440
		"100101",
1441
		"100111",
1442
		"100110",
1443
		"100010",
1444
		"100011",
1445
		"100001",
1446
	};
1447
1448
private static Map ranksForStates;
1449
int rankForState(State state) {
1450
	int length;
1451
	if (ranksForStates == null) {
1452
		ranksForStates = new HashMap(length = truthTableRowNames.length);
1453
		for (int i = 0; i < length; i++) {
1454
			ranksForStates.put(truthTableRowNames[i], new Integer(i));
1455
		}
1456
	}
1457
	Integer rank;
1458
	if ((rank = (Integer) ranksForStates.get(state.printableBitsField)) != null) {
1459
		return rank.intValue();
1460
	}
1461
	return 0;
1462
}
1463
1464
abstract void reinitializeFromComments(BufferedReader input, BufferedWriter output);
1465
abstract void reinitializeFromComputedValues(BufferedReader input, BufferedWriter output,
1466
	State[] consideredStates);
1467
/**
1468
 * Run a test against UnconditionalFlowInfo by comparing the transitions as memorized
1469
 * into the initializer and as delivered by UnconditionalFlowInfo for various positions
1470
 * in the encoding and return the number of failures.
1471
 * @return the number of failures, that is 0 if the results match the expectations
1472
 */
1473
abstract int test();
1474
}
1475
abstract static class TwoDimensionalTransformation extends Transformation {
1476
TwoDimensionalTransformation(String name, byte[][] transitions) {
1477
	super(name);
1478
	this.dimension = 2;
1479
	int length;
1480
	this.initializedTransitions = new HashMap(length = transitions.length);
1481
	State input1;
1482
	for (int i = 0; i < length; i++) {
1483
		if (transitions[i].length != 2) {
1484
			throw new IllegalArgumentException("transitions should have two entries");
1485
		}
1486
		input1 = State.states[transitions[i][0]]; // array out of bounds exception if broken
1487
		if (this.initializedTransitions.get(input1) != null) {
1488
			throw new IllegalArgumentException("duplicate entry");
1489
		}
1490
		this.initializedTransitions.put(input1, State.states[transitions[i][1]]);
1491
	}
1492
}
1493
State[] computeOutputs(State[] inputs) {
1494
	Map resultAccumulator = new HashMap(State.stateMaxValue + 1);
1495
	hydrate(); // pre-compute all possible combinations, then cache them
1496
	for (int i = 0, inputsLength = inputs.length; i < inputsLength; i++) {
1497
		resultAccumulator.put(this.computedTransitions.get(inputs[i]), null);
1498
	}
1499
	int length;
1500
	State[] result = new State[length = resultAccumulator.size()];
1501
	Iterator resultIterator = resultAccumulator.keySet().iterator();
1502
	for (int j = 0; j < length; j++) {
1503
		result[j] = (State) resultIterator.next();
1504
	}
1505
	return result;	
1506
}
1507
void hydrate() {
1508
	if (this.computedTransitions == null) {
1509
		State input, output;
1510
		this.computedTransitions = new HashMap(State.stateMaxValue + 1);
1511
		for (int i = 0, length = State.states.length; i < length; i++) {
1512
			output = ((UnconditionalFlowInfoTestHarness)
1513
				output(UnconditionalFlowInfoTestHarness.
1514
					testUnconditionalFlowInfo(input = State.states[i]), 
1515
						TestLocalVariableBinding.local0)).asState();
1516
			if (input.symbolic && !output.symbolic) {
1517
				System.err.println(this.name + " generates non-symbolic state " +
1518
					output + " upon entry: " + input);
1519
			}
1520
			this.computedTransitions.put(input, output);
1521
		}
1522
	}
1523
}
1524
abstract UnconditionalFlowInfo output(UnconditionalFlowInfo input, TestLocalVariableBinding local);
1525
1526
void printTruthTables(File outputDirectory) {
1527
	try {
1528
		String outputFileName = outputDirectory.getPath() + File.separator + this.name + ".txt";
1529
		PrintWriter out = new PrintWriter(new FileOutputStream(
1530
				new File(outputFileName)));
1531
		System.out.println("Printing " + outputFileName);
1532
		out.println("======================================================");
1533
		out.println("Truth table for " + this.name );
1534
		char truthValues[][] = new char[State.statesNb][State.stateWidth];
1535
		int row, column;
1536
		for (row = 0; row < State.statesNb; row++) {
1537
			for (column = 0; column < State.stateWidth; column++) {
1538
				truthValues[row][column] = '.';
1539
			}
1540
		}
1541
		boolean keepRow[] = new boolean[State.statesNb];
1542
		Iterator i1 = this.initializedTransitions.entrySet().iterator();
1543
		while (i1.hasNext()) {
1544
			Map.Entry transitionsSet = (Map.Entry) i1.next();
1545
			State input = (State) transitionsSet.getKey();
1546
			keepRow[row = rankForState(input)] = true;
1547
			for (int bit = 0; bit < State.stateWidth; bit++) {
1548
				truthValues[row][bit] = 
1549
					((State) transitionsSet.getValue()).printableBitsField.charAt(bit);
1550
			}
1551
		}
1552
		StringBuffer line;
1553
		line = new StringBuffer(140);
1554
		line.append("         ");
1555
		for (int i = 1; i <= State.stateWidth; i++) {
1556
			line.append(i);
1557
			line.append(' ');
1558
		}
1559
		out.println(line);
1560
		line = new StringBuffer(140);
1561
		line.append("       ---------------------");
1562
		out.println(line);
1563
		for (row = 0; row < State.statesNb; row++) {
1564
			if (keepRow[row]) {
1565
				line = new StringBuffer(140);
1566
				line.append(truthTableRowNames[row]);
1567
				line.append(" | ");
1568
				for (int i = 0; i < State.stateWidth; i++) {
1569
					line.append(truthValues[row][i]);
1570
					line.append(' ');
1571
				}
1572
				out.println(line);
1573
			}
1574
		}
1575
		out.println("======================================================");
1576
		out.flush();
1577
		out.close();
1578
	}
1579
	catch (Throwable t) {
1580
		// PREMATURE improve error handling
1581
	}
1582
}
1583
1584
void reinitializeFromComments(BufferedReader input, BufferedWriter output) {
1585
	String line, tab = "";
1586
	int cursor;
1587
	char c;
1588
	this.initializedTransitions = new HashMap(State.stateMaxValue);
1589
	int lineNumber = 0;
1590
	try {
1591
		while ((line = input.readLine()) != null) {
1592
			lineNumber++;
1593
			output.write(line);
1594
			output.write('\n');
1595
			if ((cursor = line.indexOf(definitionStartMarker)) != -1) {
1596
				// check the line format
1597
				boolean reachedStart = true;
1598
				for (int i = 0; i < cursor; i++) {
1599
					if (!Character.isWhitespace(c = line.charAt(i))) {
1600
						reachedStart = false;
1601
						break;
1602
					}
1603
					else {
1604
						tab += c;
1605
					}
1606
				}
1607
				if (reachedStart) {
1608
					while ((line = input.readLine()) != null && 
1609
							line.indexOf(definitionEndMarker) == -1) {
1610
						lineNumber++;
1611
						final int 
1612
							start = 0,
1613
							commentStart = 1,
1614
							commentFound = 2,
1615
							firstState = 10,
1616
							firstStateWS = 11,
1617
							implies = 20,
1618
							impliesWS = 21,
1619
							secondState = 30,
1620
							secondStateWS = 31, // caveat, multi-state
1621
							error = 99;
1622
						int state = start, 
1623
							firstStateStart = 0, firstStateEnd = 0, firstStateWhiteSpace = 0,
1624
							secondStateStart = 0, secondStateEnd = 0, secondStateWhiteSpace = 0;
1625
						char current;
1626
						analysis: for (int i = 0, length = line.length(); i < length; i++) {
1627
							current = line.charAt(i);
1628
							switch (state) {
1629
								case start:
1630
									if (current == '/') {
1631
										state = commentStart;
1632
									} else if (! Character.isWhitespace(current)) {
1633
										state = error;
1634
										break analysis;
1635
									} 
1636
									break;
1637
								case commentStart:
1638
									if (current == '/') {
1639
										state = commentFound;
1640
									} else {
1641
										state = error;
1642
										break analysis;
1643
									}
1644
									break;
1645
								case commentFound:
1646
									if (! Character.isWhitespace(current)) {
1647
										firstStateStart = firstStateEnd = i;
1648
										state = firstState;
1649
									}
1650
									break;
1651
								case firstState:
1652
									if (Character.isWhitespace(current)) {
1653
										state = firstStateWS;
1654
										firstStateWhiteSpace = 1;
1655
									} else {
1656
										firstStateEnd++;
1657
									}
1658
									break;
1659
								case firstStateWS:
1660
									if (current == '=') {
1661
										state = implies;
1662
									} else if (Character.isWhitespace(current)) {
1663
										firstStateWhiteSpace++;
1664
									} else {
1665
										state = firstState;
1666
										firstStateEnd += firstStateWhiteSpace + 1;
1667
									}
1668
									break;
1669
								case implies:
1670
									if (current == '>') {
1671
										state = impliesWS;
1672
									} else {
1673
										state = error;
1674
										break analysis;
1675
									}
1676
									break;
1677
								case impliesWS:
1678
									if (! Character.isWhitespace(current)) {
1679
										secondStateStart = secondStateEnd = i;
1680
										state = secondState;
1681
									}
1682
									break;
1683
								case secondState:
1684
									if (current == '/') {
1685
										break analysis;
1686
									} else if (Character.isWhitespace(current)) {
1687
										state = secondStateWS;
1688
										secondStateWhiteSpace = 1;
1689
									} else {
1690
										secondStateEnd++;
1691
									}
1692
									break;
1693
								case secondStateWS:
1694
									if (current == '/') {
1695
										state = secondState;
1696
										break analysis;
1697
									} else if (current == 'C') {
1698
										state++;
1699
									} else if (Character.isWhitespace(current)) {
1700
										secondStateWhiteSpace++;
1701
									} else {
1702
										state = secondState;
1703
										secondStateEnd += secondStateWhiteSpace + 1;
1704
									}
1705
									break;
1706
								case secondStateWS + 1:
1707
									if (current == '/') {
1708
										state = secondState;
1709
										break analysis;
1710
									} else if (current == 'H') {
1711
										state++;
1712
									} else {
1713
										state = secondState;
1714
										secondStateEnd += secondStateWhiteSpace + 2;
1715
									}
1716
									break;
1717
								case secondStateWS + 2:
1718
									if (current == '/') {
1719
										state = secondState;
1720
										break analysis;
1721
									} else if (current == 'E') {
1722
										state++;
1723
									} else {
1724
										state = secondState;
1725
										secondStateEnd += secondStateWhiteSpace + 3;
1726
									}
1727
									break;
1728
								case secondStateWS + 3:
1729
									if (current == '/') {
1730
										state = secondState;
1731
										break analysis;
1732
									} else if (current == 'C') {
1733
										state++;
1734
									} else {
1735
										state = secondState;
1736
										secondStateEnd += secondStateWhiteSpace + 4;
1737
									}
1738
									break;
1739
								case secondStateWS + 4:
1740
									if (current == '/' || current == 'K') {
1741
										state = secondState;
1742
										break analysis;
1743
									} else {
1744
										state = secondState;
1745
										secondStateEnd += secondStateWhiteSpace + 5;
1746
									}
1747
									break;
1748
									
1749
							}
1750
						}
1751
						if (state == error || state < secondState) {
1752
							System.err.println("Could not interpret comment definition"); // PREMATURE improve diagnostic
1753
						} else {
1754
							if (state > secondStateWS) {
1755
								secondStateEnd += (state - secondState);
1756
							}
1757
							String stateName;
1758
							State first, second;
1759
							if ((first = State.fromSymbolicName(
1760
										stateName = line.substring(firstStateStart, firstStateEnd + 1)))
1761
									== null) {
1762
								System.err.println("Could not find state: " + stateName); // PREMATURE improve diagnostic
1763
							}
1764
							if ((second = State.fromSymbolicName(
1765
										stateName = line.substring(secondStateStart, secondStateEnd + 1)))
1766
									== null) {
1767
								System.err.println("Could not find state: " + stateName); // PREMATURE improve diagnostic
1768
							}
1769
							if (first != null && second != null) {
1770
								if (this.initializedTransitions.get(first) != null) {
1771
									System.err.println("Line " + lineNumber + ": Skipping duplicate entry for state: " + first); // PREMATURE improve diagnostic
1772
								} else {
1773
									this.initializedTransitions.put(first, second);
1774
								}
1775
							}
1776
						}
1777
						output.write(line);
1778
						output.write('\n');
1779
					}
1780
					Iterator firsts = State.symbolicStates();
1781
					State first;
1782
					while (firsts.hasNext()) {
1783
						first = (State) firsts.next();
1784
						if (this.initializedTransitions.get(first) == null) {
1785
								System.err.println("Adding missing transition for state: " + first);
1786
								output.write(tab);
1787
								output.write("// ");
1788
								output.write(first.toString());
1789
								output.write(" => start\t\t CHECK\n");
1790
						}
1791
					}
1792
				}
1793
				output.write(tab + definitionEndMarker + "\n");
1794
			}
1795
			if (line != null && (cursor = line.indexOf(initializerStartMarker)) != -1) {
1796
				// check the line format
1797
				boolean reachedStart = true;
1798
				tab = "";
1799
				for (int i = 0; i < cursor; i++) {
1800
					if (!Character.isWhitespace(c = line.charAt(i))) {
1801
						reachedStart = false;
1802
						break;
1803
					}
1804
					else {
1805
						tab += c;
1806
					}
1807
				}
1808
				if (reachedStart) {
1809
					while ((line = input.readLine()) != null && 
1810
							line.indexOf(initializerEndMarker) == -1) {
1811
						// loop
1812
					}
1813
					SortedMap sorted = new TreeMap(this.initializedTransitions);
1814
					Iterator transitions = sorted.entrySet().iterator();
1815
					Map.Entry transition;
1816
					while (transitions.hasNext()) {
1817
						transition = (Map.Entry) transitions.next();
1818
						output.write(tab);
1819
						output.write('{');
1820
						output.write(((State)transition.getKey()).hexString);
1821
						output.write(',');
1822
						output.write(((State)transition.getValue()).hexString);
1823
						output.write("},");
1824
						output.write('\n');
1825
					}
1826
					output.write(tab + initializerEndMarker + "\n");
1827
				}
1828
			}
1829
		}
1830
		output.flush();
1831
	} catch (IOException e) {
1832
		throw new RuntimeException(e);
1833
	}
1834
}
1835
1836
void reinitializeFromComputedValues(BufferedReader input, BufferedWriter output,
1837
		State[] consideredStates) {
1838
	String line, tab = "";
1839
	int cursor;
1840
	char c;
1841
	State result;
1842
	try {
1843
		while ((line = input.readLine()) != null) {
1844
			output.write(line);
1845
			output.write('\n');
1846
			if ((cursor = line.indexOf(definitionStartMarker)) != -1) {
1847
				// check the line format
1848
				boolean reachedStart = true;
1849
				for (int i = 0; i < cursor; i++) {
1850
					if (!Character.isWhitespace(c = line.charAt(i))) {
1851
						reachedStart = false;
1852
						break;
1853
					}
1854
					else {
1855
						tab += c;
1856
					}
1857
				}
1858
				if (reachedStart) {
1859
					while ((line = input.readLine()) != null && 
1860
							line.indexOf(definitionEndMarker) == -1) {
1861
						// loop
1862
					}
1863
					int i, length;
1864
					for (i = 0, length = consideredStates.length; i < length; i++) {
1865
						output.write(tab);
1866
						output.write("// ");
1867
						output.write(consideredStates[i].name);
1868
						output.write(" => ");
1869
						output.write(
1870
							(result = (State) this.computedTransitions.get(consideredStates[i])).name);
1871
						if (!result.symbolic ||
1872
								result != this.initializedTransitions.get(consideredStates[i])) {
1873
							output.write("\t\t CHECK");
1874
						}
1875
						output.write('\n');
1876
					}
1877
					output.write(tab + definitionEndMarker + "\n");
1878
				}
1879
			}
1880
			if (line != null && (cursor = line.indexOf(initializerStartMarker)) != -1) {
1881
				// check the line format
1882
				boolean reachedStart = true;
1883
				tab = "";
1884
				for (int i = 0; i < cursor; i++) {
1885
					if (!Character.isWhitespace(c = line.charAt(i))) {
1886
						reachedStart = false;
1887
						break;
1888
					}
1889
					else {
1890
						tab += c;
1891
					}
1892
				}
1893
				if (reachedStart) {
1894
					while ((line = input.readLine()) != null && 
1895
							line.indexOf(initializerEndMarker) == -1) {
1896
						// loop
1897
					}
1898
					int i, length;
1899
					for (i = 0, length = consideredStates.length; i < length; i++) {
1900
						output.write(tab);
1901
						output.write('{');
1902
						output.write(consideredStates[i].hexString);
1903
						output.write(',');
1904
						output.write(
1905
							((State) this.computedTransitions.get(consideredStates[i])).hexString);
1906
						output.write("},");
1907
						output.write('\n');
1908
					}
1909
					output.write(tab + initializerEndMarker + "\n");
1910
				}
1911
			}
1912
		}
1913
		output.flush();
1914
	} catch (IOException e) {
1915
		throw new RuntimeException(e);
1916
	}
1917
}
1918
int test() {
1919
	Iterator transitions = this.initializedTransitions.entrySet().iterator();
1920
	State input, expectedOutput, effectiveOutput;
1921
	Map.Entry transition;
1922
	this.failuresNb = 0; // reset
1923
	while (transitions.hasNext()) {
1924
		transition = (Map.Entry) transitions.next();
1925
		input = (State) transition.getKey();
1926
		expectedOutput = (State) transition.getValue();
1927
		effectiveOutput = ((UnconditionalFlowInfoTestHarness) 
1928
			output(UnconditionalFlowInfoTestHarness.
1929
				testUnconditionalFlowInfo(input), 
1930
					TestLocalVariableBinding.local0)).asState();
1931
		if (effectiveOutput != expectedOutput) {
1932
			fail();
1933
			System.out.println("\t\t" + input.printableBitsField + 
1934
				" => " + effectiveOutput.printableBitsField + 
1935
				" instead of: " + expectedOutput.printableBitsField);
1936
		}
1937
	}
1938
	transitions = this.initializedTransitions.entrySet().iterator();
1939
	while (transitions.hasNext()) {
1940
		transition = (Map.Entry) transitions.next();
1941
		input = (State) transition.getKey();
1942
		expectedOutput = (State) transition.getValue();
1943
		effectiveOutput = ((UnconditionalFlowInfoTestHarness)
1944
				output(UnconditionalFlowInfoTestHarness.
1945
					testUnconditionalFlowInfo(input, 64), 
1946
						TestLocalVariableBinding.local64)).asState(64);
1947
		if (effectiveOutput != expectedOutput) {
1948
			fail();
1949
			System.out.println("\t\t" + input.printableBitsField + 
1950
				" => " + effectiveOutput.printableBitsField + 
1951
				" (64) instead of: " + expectedOutput.printableBitsField);
1952
		}
1953
		if (input == State.start) {
1954
			effectiveOutput = ((UnconditionalFlowInfoTestHarness)
1955
				output(UnconditionalFlowInfoTestHarness.
1956
					testUnconditionalFlowInfo(expectedOutput),
1957
						TestLocalVariableBinding.local64)).asState(64);
1958
			if (effectiveOutput != expectedOutput) {
1959
				fail();
1960
				System.out.println("\t\t" + input.printableBitsField + 
1961
					" => " + effectiveOutput.printableBitsField + 
1962
					" (zero 64) instead of: " + expectedOutput.printableBitsField);
1963
			}
1964
		}
1965
	}
1966
	transitions = this.initializedTransitions.entrySet().iterator();
1967
	while (transitions.hasNext()) {
1968
		transition = (Map.Entry) transitions.next();
1969
		input = (State) transition.getKey();
1970
		if (input == State.start) {
1971
			expectedOutput = (State) transition.getValue();
1972
			effectiveOutput = ((UnconditionalFlowInfoTestHarness)
1973
				output(UnconditionalFlowInfoTestHarness.
1974
					testUnconditionalFlowInfo(expectedOutput, 64),
1975
						TestLocalVariableBinding.local128)).asState(128);
1976
			if (effectiveOutput != expectedOutput) {
1977
				fail();
1978
				System.out.println("\t\t" + input.printableBitsField + 
1979
					" => " + effectiveOutput.printableBitsField + 
1980
					" (zero 128) instead of: " + expectedOutput.printableBitsField);
1981
			}
1982
		}
1983
	}
1984
	return this.failuresNb;
1985
}
1986
}
1987
abstract static class CreationalTransformation extends TwoDimensionalTransformation {
1988
CreationalTransformation(String name, byte[][] transitions) {
1989
	super(name, transitions);
1990
}
1991
void hydrate() {
1992
	if (this.computedTransitions == null) {
1993
		State input, output;
1994
		this.computedTransitions = new HashMap(State.stateMaxValue + 1);
1995
		for (int i = 0, length = State.states.length; i < length; i++) {
1996
			output = ((NullInfoRegistryTestHarness)
1997
				output(UnconditionalFlowInfoTestHarness.
1998
					testUnconditionalFlowInfo(input = State.states[i]), 
1999
						TestLocalVariableBinding.local0)).asState();
2000
			if (input.symbolic && !output.symbolic) {
2001
				System.err.println(this.name + " generates non-symbolic state " +
2002
					output + " upon entry: " + input);
2003
			}
2004
			this.computedTransitions.put(input, output);
2005
		}
2006
	}
2007
}
2008
UnconditionalFlowInfo output(UnconditionalFlowInfo input, TestLocalVariableBinding local) {
2009
	return output(input);
2010
}
2011
abstract UnconditionalFlowInfo output(UnconditionalFlowInfo input);
2012
int test() {
2013
	Iterator transitions = this.initializedTransitions.entrySet().iterator();
2014
	State input, expectedOutput, effectiveOutput;
2015
	Map.Entry transition;
2016
	this.failuresNb = 0; // reset
2017
	while (transitions.hasNext()) {
2018
		transition = (Map.Entry) transitions.next();
2019
		input = (State) transition.getKey();
2020
		expectedOutput = (State) transition.getValue();
2021
		effectiveOutput = ((NullInfoRegistryTestHarness) 
2022
			output(UnconditionalFlowInfoTestHarness.
2023
				testUnconditionalFlowInfo(input), 
2024
					TestLocalVariableBinding.local0)).asState();
2025
		if (effectiveOutput != expectedOutput) {
2026
			fail();
2027
			System.out.println("\t\t" + input.printableBitsField + 
2028
				" => " + effectiveOutput.printableBitsField + 
2029
				" instead of: " + expectedOutput.printableBitsField);
2030
		}
2031
	}
2032
	transitions = this.initializedTransitions.entrySet().iterator();
2033
	while (transitions.hasNext()) {
2034
		transition = (Map.Entry) transitions.next();
2035
		input = (State) transition.getKey();
2036
		expectedOutput = (State) transition.getValue();
2037
		effectiveOutput = ((NullInfoRegistryTestHarness)
2038
				output(UnconditionalFlowInfoTestHarness.
2039
					testUnconditionalFlowInfo(input, 64))).asState(64);
2040
		if (effectiveOutput != expectedOutput) {
2041
			fail();
2042
			System.out.println("\t\t" + input.printableBitsField + 
2043
				" => " + effectiveOutput.printableBitsField + 
2044
				" (64) instead of: " + expectedOutput.printableBitsField);
2045
		}
2046
	}
2047
	return this.failuresNb;
2048
}
2049
}
2050
public abstract static class ThreeDimensionalTransformation extends Transformation {
2051
ThreeDimensionalTransformation(String name) {
2052
	super(name);
2053
	this.dimension = 3;
2054
}
2055
ThreeDimensionalTransformation(String name, byte[][] transitions) {
2056
	super(name);
2057
	this.dimension = 3;
2058
	int length;
2059
	this.initializedTransitions = new HashMap(length = transitions.length);
2060
	State input1, input2;
2061
	for (int i = 0; i < length; i++) {
2062
		if (transitions[i].length != 3) {
2063
			throw new IllegalArgumentException("transitions should have three entries");
2064
		}
2065
		input1 = State.states[transitions[i][0]]; // array out of bounds exception if broken
2066
		input2 = State.states[transitions[i][1]];
2067
		Map transitionsForInput1 = (Map) this.initializedTransitions.get(input1);
2068
		if (transitionsForInput1 == null) {
2069
			transitionsForInput1 = new HashMap(length);
2070
			this.initializedTransitions.put(input1, transitionsForInput1);
2071
		}
2072
		if (transitionsForInput1.get(input2) != null) {
2073
			throw new IllegalArgumentException("duplicate entry");
2074
		}
2075
		transitionsForInput1.put(input2, State.states[transitions[i][2]]);
2076
	}
2077
}
2078
State[] computeOutputs(State[] inputs) {
2079
	Map resultAccumulator = new HashMap(State.stateMaxValue + 1);
2080
	hydrate(); // pre-compute all possible combinations, then cache them
2081
	for (int i = 0, inputsLength = inputs.length; i < inputsLength; i++) {
2082
		for (int i2 = 0; i2 < inputsLength; i2++) {
2083
			resultAccumulator.put(
2084
				((Map) this.computedTransitions.get(inputs[i])).get(inputs[i2]), null);
2085
		}
2086
	}
2087
	int length;
2088
	State[] result = new State[length = resultAccumulator.size()];
2089
	Iterator resultIterator = resultAccumulator.keySet().iterator();
2090
	for (int j = 0; j < length; j++) {
2091
		result[j] = (State) resultIterator.next();
2092
	}
2093
	return result;	
2094
}
2095
void hydrate() {
2096
	if (this.computedTransitions == null) {
2097
		State input1, input2, output;
2098
		this.computedTransitions = new HashMap(State.stateMaxValue + 1);
2099
		Map entry;
2100
		for (int i = 0, length = State.states.length; i < length; i++) {
2101
			entry = new HashMap(State.stateMaxValue + 1);
2102
			this.computedTransitions.put(input1 = State.states[i], entry);
2103
			for (int j = 0; j < length; j++) {
2104
				output = ((UnconditionalFlowInfoTestHarness)
2105
					output(UnconditionalFlowInfoTestHarness.
2106
						testUnconditionalFlowInfo(input1),
2107
						UnconditionalFlowInfoTestHarness.
2108
						testUnconditionalFlowInfo(input2 = State.states[j]))).asState();
2109
				if (input1.symbolic && input2.symbolic && !output.symbolic) {
2110
					System.err.println(this.name + " generates non-symbolic state " +
2111
						output + " upon entry: " + input1 + " + " + input2);
2112
				}
2113
				entry.put(input2, output);
2114
			}
2115
		}
2116
	}	
2117
}
2118
abstract UnconditionalFlowInfo output(UnconditionalFlowInfo input1, UnconditionalFlowInfo input2);
2119
void printDefinitions(BufferedWriter output, State[] consideredStates, String tab)
2120
		throws IOException {
2121
	int i, j, length;
2122
	State result;
2123
	for (i = 0, length = consideredStates.length; i < length; i++) {
2124
		for (j = 0; j < length; j++) {
2125
			output.write(tab);
2126
			output.write("// ");
2127
			output.write(consideredStates[i].name);
2128
			output.write(" + ");
2129
			output.write(consideredStates[j].name);
2130
			output.write(" => ");
2131
			output.write(
2132
				(result = (State)
2133
					((Map) this.computedTransitions.get(consideredStates[i])).get(consideredStates[j])).name);
2134
			if (!result.symbolic ||
2135
				result != this.initializedTransitions.get(consideredStates[i])) {
2136
				output.write("\t\t CHECK");
2137
			}
2138
			output.write('\n');
2139
		}
2140
	}
2141
}
2142
void printInitializers(BufferedWriter output, State[] consideredStates, String tab)
2143
		throws IOException {
2144
	int i, j, length;
2145
	for (i = 0, length = consideredStates.length; i < length; i++) {
2146
		for (j = 0; j < length; j++) {
2147
			output.write(tab);
2148
			output.write('{');
2149
			output.write(consideredStates[i].hexString);
2150
			output.write(',');
2151
			output.write(consideredStates[j].hexString);
2152
			output.write(',');
2153
			output.write(
2154
				((State)
2155
					((Map) this.computedTransitions.get(consideredStates[i])).get(consideredStates[j])).hexString);
2156
			output.write("},");
2157
			output.write('\n');
2158
		}
2159
				}
2160
}
2161
void printMissingEntries(BufferedWriter output, String tab) throws IOException {
2162
	Iterator firsts = State.symbolicStates(), seconds;
2163
	State first, second;
2164
	Map transitions;
2165
	while (firsts.hasNext()) {
2166
		first = (State) firsts.next();
2167
		seconds = State.symbolicStates();
2168
		if ((transitions = (Map) this.initializedTransitions.get(first))
2169
				== null) {
2170
			while (seconds.hasNext()) {
2171
				second = (State) seconds.next();
2172
				System.err.println("Adding missing transition for states (" + first + ", " + second + ")");
2173
				output.write(tab);
2174
				output.write("// ");
2175
				output.write(first.toString());
2176
				output.write(" + ");
2177
				output.write(second.toString());
2178
				output.write(" => start\t\t CHECK\n");
2179
			}
2180
		} else {
2181
			while (seconds.hasNext()) {
2182
				second = (State) seconds.next();
2183
				if (transitions.get(second) == null) {
2184
					System.err.println("Adding missing transition for states (" + first + ", " + second + ")");
2185
					output.write(tab);
2186
					output.write("// ");
2187
					output.write(first.toString());
2188
					output.write(" + ");
2189
					output.write(second.toString());
2190
					output.write(" => start\t\t CHECK\n");
2191
				}
2192
			}
2193
		}
2194
	}
2195
}
2196
void printTruthTables(File outputDirectory) {
2197
	for (int bit = 1; bit <= State.stateWidth; bit++) {
2198
		try {
2199
			String outputFileName = outputDirectory.getPath() + File.separator + this.name + "_" + bit + ".txt";
2200
			PrintWriter out = new PrintWriter(new FileOutputStream(
2201
					new File(outputFileName)));
2202
			System.out.println("Printing " + outputFileName);
2203
			out.println("======================================================");
2204
			out.println("Truth table for " + this.name + " null bit " + bit);
2205
			char truthValues[][] = new char[State.statesNb][State.statesNb];
2206
			int row, column;
2207
			for (row = 0; row < State.statesNb; row++) {
2208
				for (column = 0; column < State.statesNb; column++) {
2209
					truthValues[row][column] = '.';
2210
				}
2211
			}
2212
			if (false) { // checking row names
2213
				boolean gotProblem = false;
2214
				if (truthTableRowNames.length > State.statesNb) {
2215
					System.out.println("row names table contains too many rows");
2216
					gotProblem = true;
2217
				}
2218
				else if (truthTableRowNames.length < State.statesNb) {
2219
					System.out.println("row names table contains too few rows");
2220
					gotProblem = true;
2221
				}
2222
				Map check = new HashMap(State.statesNb);
2223
				for (row = 0; row < truthTableRowNames.length; row++) {
2224
					if (check.containsKey(truthTableRowNames[row])) {
2225
						System.out.println("duplicate row: " + truthTableRowNames[row]);
2226
						gotProblem = true;
2227
					}
2228
					else {
2229
						check.put(truthTableRowNames[row], null);
2230
					}
2231
					if (row > 0 && !checkContiguity(truthTableRowNames[row - 1], truthTableRowNames[row])) {
2232
						gotProblem = true;
2233
					}
2234
				}
2235
		//		assertFalse("invalid rows table", gotProblem);
2236
			}
2237
			boolean keepRow[] = new boolean[State.statesNb], 
2238
				keepColumn[] = new boolean[State.statesNb];
2239
			Iterator i1 = this.initializedTransitions.entrySet().iterator();
2240
			while (i1.hasNext()) {
2241
				Map.Entry transitionsSet = (Map.Entry) i1.next();
2242
				State first = (State) transitionsSet.getKey();
2243
				Iterator i2 = ((Map) transitionsSet.getValue()).entrySet().iterator();
2244
				while (i2.hasNext()) {
2245
					Map.Entry transition = (Map.Entry) i2.next();
2246
					mark(truthValues, keepRow, keepColumn, rankForState(first),
2247
							rankForState((State) transition.getKey()),
2248
							((State) transition.getValue()).printableBitsField.charAt(bit - 1));
2249
				}
2250
			}
2251
			for (row = 0; row < State.statesNb; row += 2) {
2252
				if (keepRow[row]) {
2253
					keepRow[row + 1] = true;
2254
				}
2255
				else if (keepRow[row + 1]) {
2256
					keepRow[row] = true;
2257
				}
2258
				if (keepColumn[row]) {
2259
					keepColumn[row + 1] = true;
2260
				}
2261
				else if (keepColumn[row + 1]) {
2262
					keepColumn[row] = true;
2263
				}
2264
			}
2265
			StringBuffer line;
2266
			for (int i = 0; i < State.stateWidth; i++) {
2267
				line = new StringBuffer(140);
2268
				line.append("         ");
2269
				for (column = 0; column < State.statesNb; column++) {
2270
					if (keepColumn[column]) {
2271
						line.append(truthTableRowNames[column].charAt(i));
2272
						line.append(' ');
2273
					}
2274
				}
2275
				out.println(line);
2276
			}
2277
			line = new StringBuffer(140);
2278
			line.append("       --");
2279
			for (column = 0; column < State.statesNb; column++) {
2280
				if (keepColumn[column]) {
2281
					line.append('-');
2282
					line.append('-');
2283
				}
2284
			}
2285
			out.println(line);
2286
			for (row = 0; row < State.statesNb; row++) {
2287
				if (keepRow[row]) {
2288
					line = new StringBuffer(140);
2289
					line.append(truthTableRowNames[row]);
2290
					line.append(" | ");
2291
					for (column = 0; column < State.statesNb; column++) {
2292
						if (keepColumn[column]) {
2293
							line.append(truthValues[row][column]);
2294
							line.append(' ');
2295
						}
2296
					}
2297
					out.println(line);
2298
				}
2299
			}
2300
			out.println("======================================================");
2301
			out.flush();
2302
			out.close();
2303
		}
2304
		catch (Throwable t) {
2305
			// PREMATURE improve error handling
2306
		}
2307
	}
2308
}
2309
2310
void mark(char truthValues[][], boolean keepRow[], boolean keepColumn[],
2311
		int row, int column, char value) {
2312
	truthValues[row][column] = value;
2313
	keepRow[row] = true;
2314
	keepColumn[column] = true;
2315
}
2316
2317
void reinitializeFromComments(BufferedReader input, BufferedWriter output) {
2318
	String line, tab = "";
2319
	int cursor;
2320
	char c;
2321
	this.initializedTransitions = new HashMap(State.stateMaxValue);
2322
	int lineNumber = 0;
2323
	try {
2324
		while ((line = input.readLine()) != null) {
2325
			lineNumber++;
2326
			output.write(line);
2327
			output.write('\n');
2328
			if ((cursor = line.indexOf(definitionStartMarker)) != -1) {
2329
				// check the line format
2330
				boolean reachedStart = true;
2331
				for (int i = 0; i < cursor; i++) {
2332
					if (!Character.isWhitespace(c = line.charAt(i))) {
2333
						reachedStart = false;
2334
						break;
2335
					}
2336
					else {
2337
						tab += c;
2338
					}
2339
				}
2340
				if (reachedStart) {
2341
					while ((line = input.readLine()) != null && 
2342
							line.indexOf(definitionEndMarker) == -1) {
2343
						lineNumber++;
2344
						final int 
2345
							start = 0,
2346
							commentStart = 1,
2347
							commentFound = 2,
2348
							firstState = 10,
2349
							firstStateWS = 11,
2350
							plus = 20,
2351
							secondState = 30,
2352
							secondStateWS = 31,
2353
							implies = 40,
2354
							impliesWS = 41,
2355
							thirdState = 50,
2356
							thirdStateWS = 51, // caveat, multi-state
2357
							error = 99;
2358
						int state = start, 
2359
							firstStateStart = 0, firstStateEnd = 0, firstStateWhiteSpace = 0,
2360
							secondStateStart = 0, secondStateEnd = 0, secondStateWhiteSpace = 0,
2361
							thirdStateStart = 0, thirdStateEnd = 0, thirdStateWhiteSpace = 0;
2362
						char current;
2363
						analysis: for (int i = 0, length = line.length(); i < length; i++) {
2364
							current = line.charAt(i);
2365
							switch (state) {
2366
								case start:
2367
									if (current == '/') {
2368
										state = commentStart;
2369
									} else if (! Character.isWhitespace(current)) {
2370
										state = error;
2371
										break analysis;
2372
									} 
2373
									break;
2374
								case commentStart:
2375
									if (current == '/') {
2376
										state = commentFound;
2377
									} else {
2378
										state = error;
2379
										break analysis;
2380
									}
2381
									break;
2382
								case commentFound:
2383
									if (! Character.isWhitespace(current)) {
2384
										firstStateStart = firstStateEnd = i;
2385
										state = firstState;
2386
									}
2387
									break;
2388
								case firstState:
2389
									if (Character.isWhitespace(current)) {
2390
										state = firstStateWS;
2391
										firstStateWhiteSpace = 1;
2392
									} else {
2393
										firstStateEnd++;
2394
									}
2395
									break;
2396
								case firstStateWS:
2397
									if (current == '+') {
2398
										state = plus;
2399
									} else if (Character.isWhitespace(current)) {
2400
										firstStateWhiteSpace++;
2401
									} else {
2402
										state = firstState;
2403
										firstStateEnd += firstStateWhiteSpace + 1;
2404
									}
2405
									break;
2406
								case plus:
2407
									if (! Character.isWhitespace(current)) {
2408
										secondStateStart = secondStateEnd = i;
2409
										state = secondState;
2410
									}
2411
									break;
2412
								case secondState:
2413
									if (Character.isWhitespace(current)) {
2414
										state = secondStateWS;
2415
										secondStateWhiteSpace = 1;
2416
									} else {
2417
										secondStateEnd++;
2418
									}
2419
									break;
2420
								case secondStateWS:
2421
									if (current == '=') {
2422
										state = implies;
2423
									} else if (Character.isWhitespace(current)) {
2424
										secondStateWhiteSpace++;
2425
									} else {
2426
										state = secondState;
2427
										secondStateEnd += secondStateWhiteSpace + 1;
2428
									}
2429
									break;
2430
								case implies:
2431
									if (current == '>') {
2432
										state = impliesWS;
2433
									} else {
2434
										state = error;
2435
										break analysis;
2436
									}
2437
									break;
2438
								case impliesWS:
2439
									if (! Character.isWhitespace(current)) {
2440
										thirdStateStart = thirdStateEnd = i;
2441
										state = thirdState;
2442
									}
2443
									break;
2444
								case thirdState:
2445
									if (current == '/') {
2446
										break analysis;
2447
									} else if (Character.isWhitespace(current)) {
2448
										state = thirdStateWS;
2449
										thirdStateWhiteSpace = 1;
2450
									} else {
2451
										thirdStateEnd++;
2452
									}
2453
									break;
2454
								case thirdStateWS:
2455
									if (current == '/') {
2456
										state = thirdState;
2457
										break analysis;
2458
									} else if (current == 'C') {
2459
										state++;
2460
									} else if (Character.isWhitespace(current)) {
2461
										thirdStateWhiteSpace++;
2462
									} else {
2463
										state = thirdState;
2464
										thirdStateEnd += thirdStateWhiteSpace + 1;
2465
									}
2466
									break;
2467
								case thirdStateWS + 1:
2468
									if (current == '/') {
2469
										state = thirdState;
2470
										break analysis;
2471
									} else if (current == 'H') {
2472
										state++;
2473
									} else {
2474
										state = thirdState;
2475
										thirdStateEnd += thirdStateWhiteSpace + 2;
2476
									}
2477
									break;
2478
								case thirdStateWS + 2:
2479
									if (current == '/') {
2480
										state = thirdState;
2481
										break analysis;
2482
									} else if (current == 'E') {
2483
										state++;
2484
									} else {
2485
										state = thirdState;
2486
										thirdStateEnd += thirdStateWhiteSpace + 3;
2487
									}
2488
									break;
2489
								case thirdStateWS + 3:
2490
									if (current == '/') {
2491
										state = thirdState;
2492
										break analysis;
2493
									} else if (current == 'C') {
2494
										state++;
2495
									} else {
2496
										state = thirdState;
2497
										thirdStateEnd += thirdStateWhiteSpace + 4;
2498
									}
2499
									break;
2500
								case thirdStateWS + 4:
2501
									if (current == '/' || current == 'K') {
2502
										state = thirdState;
2503
										break analysis;
2504
									} else {
2505
										state = thirdState;
2506
										thirdStateEnd += thirdStateWhiteSpace + 5;
2507
									}
2508
									break;
2509
									
2510
							}
2511
						}
2512
						if (state == error || state < thirdState) {
2513
							System.err.println("Could not interpret comment definition"); // PREMATURE improve diagnostic
2514
						} else {
2515
							if (state > thirdStateWS) {
2516
								thirdStateEnd += (state - thirdState);
2517
							}
2518
							String stateName;
2519
							State first, second, third;
2520
							if ((first = State.fromSymbolicName(
2521
										stateName = line.substring(firstStateStart, firstStateEnd + 1)))
2522
									== null) {
2523
								System.err.println("Could not find state: " + stateName); // PREMATURE improve diagnostic
2524
							}
2525
							if ((second = State.fromSymbolicName(
2526
										stateName = line.substring(secondStateStart, secondStateEnd + 1)))
2527
									== null) {
2528
								System.err.println("Could not find state: " + stateName); // PREMATURE improve diagnostic
2529
							}
2530
							if ((third = State.fromSymbolicName(
2531
										stateName = line.substring(thirdStateStart, thirdStateEnd + 1)))
2532
									== null) {
2533
								System.err.println("Could not find state: " + stateName); // PREMATURE improve diagnostic
2534
							}
2535
							if (first != null && second != null && third != null) {
2536
								Map transitions;
2537
								if ((transitions = (Map) this.initializedTransitions.get(first)) == null) {
2538
									transitions = new HashMap(State.stateMaxValue + 1);
2539
									this.initializedTransitions.put(first, transitions);
2540
								}
2541
								if (transitions.get(second) != null) {
2542
									System.err.println("Line " + lineNumber + ": Skipping duplicate entry for states: (" + first
2543
											+ ", " + second + ")"); // PREMATURE improve diagnostic
2544
								} else {
2545
									transitions.put(second, third);
2546
								}
2547
							}
2548
						}
2549
						output.write(line);
2550
						output.write('\n');
2551
					}
2552
				}
2553
				printMissingEntries(output, tab);
2554
				output.write(tab + definitionEndMarker + "\n");
2555
			}
2556
			if (line != null && (cursor = line.indexOf(initializerStartMarker)) != -1) {
2557
				// check the line format
2558
				boolean reachedStart = true;
2559
				tab = "";
2560
				for (int i = 0; i < cursor; i++) {
2561
					if (!Character.isWhitespace(c = line.charAt(i))) {
2562
						reachedStart = false;
2563
						break;
2564
					}
2565
					else {
2566
						tab += c;
2567
					}
2568
				}
2569
				if (reachedStart) {
2570
					while ((line = input.readLine()) != null && 
2571
							line.indexOf(initializerEndMarker) == -1) {
2572
						// loop
2573
					}
2574
					SortedMap sortedTransitionsSet = new TreeMap(this.initializedTransitions);
2575
					Iterator transitionsSets = sortedTransitionsSet.entrySet().iterator();
2576
					Map.Entry transitionsSet;
2577
					while (transitionsSets.hasNext()) {
2578
						transitionsSet = (Map.Entry) transitionsSets.next();
2579
						SortedMap sortedTransitions = new TreeMap((Map) transitionsSet.getValue());
2580
						Iterator transitions = sortedTransitions.entrySet().iterator();
2581
						Map.Entry transition;
2582
						while (transitions.hasNext()) {
2583
							transition = (Map.Entry) transitions.next();
2584
							output.write(tab);
2585
							output.write('{');
2586
							output.write(((State)transitionsSet.getKey()).hexString);
2587
							output.write(',');
2588
							output.write(((State)transition.getKey()).hexString);
2589
							output.write(',');
2590
							output.write(((State)transition.getValue()).hexString);
2591
							output.write("},");
2592
							output.write('\n');
2593
						}
2594
					}
2595
					output.write(tab + initializerEndMarker + "\n");
2596
				}
2597
			}
2598
		}
2599
		output.flush();
2600
	} catch (IOException e) {
2601
		throw new RuntimeException(e);
2602
	}
2603
}
2604
void reinitializeFromComputedValues(BufferedReader input, BufferedWriter output,
2605
		State[] consideredStates) {
2606
	String line, tab = "";
2607
	int cursor;
2608
	char c;
2609
	try {
2610
		while ((line = input.readLine()) != null) {
2611
			output.write(line);
2612
			output.write('\n');
2613
			if ((cursor = line.indexOf(definitionStartMarker)) != -1) {
2614
				// check the line format
2615
				boolean reachedStart = true;
2616
				for (int i = 0; i < cursor; i++) {
2617
					if (!Character.isWhitespace(c = line.charAt(i))) {
2618
						reachedStart = false;
2619
						break;
2620
					}
2621
					else {
2622
						tab += c;
2623
					}
2624
				}
2625
				if (reachedStart) {
2626
					while ((line = input.readLine()) != null && 
2627
							line.indexOf(definitionEndMarker) == -1) {
2628
						// loop
2629
					}
2630
					printDefinitions(output, consideredStates, tab);
2631
					output.write(tab + definitionEndMarker + "\n");
2632
				}
2633
			}
2634
			if (line != null && (cursor = line.indexOf(initializerStartMarker)) != -1) {
2635
				// check the line format
2636
				boolean reachedStart = true;
2637
				tab = "";
2638
				for (int i = 0; i < cursor; i++) {
2639
					if (!Character.isWhitespace(c = line.charAt(i))) {
2640
						reachedStart = false;
2641
						break;
2642
					}
2643
					else {
2644
						tab += c;
2645
					}
2646
				}
2647
				if (reachedStart) {
2648
					while ((line = input.readLine()) != null && 
2649
							line.indexOf(initializerEndMarker) == -1) {
2650
						// loop
2651
					}
2652
					printInitializers(output, consideredStates, tab);
2653
					output.write(tab + initializerEndMarker + "\n");
2654
				}
2655
			}
2656
		}
2657
		output.flush();
2658
	} catch (IOException e) {
2659
		throw new RuntimeException(e);
2660
	}
2661
}
2662
int test() {
2663
	return test(1, false);
2664
}
2665
int test(int combinationTestsLoopsNb, boolean skipHighOrderBits) {
2666
	Iterator transitionsSetsIterator, transitionsIterator;
2667
	State input1, input2, expectedOutput, effectiveOutput;
2668
	Map.Entry transition, transitionsSet;
2669
	this.failuresNb = 0; // reset
2670
	this.failuresNb = 0; // reset
2671
	long start = 0;
2672
	if (combinationTestsLoopsNb > 1) {
2673
		start = System.currentTimeMillis();
2674
	}
2675
	for (int l = 0; l < combinationTestsLoopsNb ; l++) {
2676
		transitionsSetsIterator = this.initializedTransitions.entrySet().iterator();
2677
		while (transitionsSetsIterator.hasNext()) {
2678
			transitionsSet = (Map.Entry) transitionsSetsIterator.next();
2679
			input1 = (State) transitionsSet.getKey();
2680
			transitionsIterator = ((Map) transitionsSet.getValue()).
2681
				entrySet().iterator();
2682
			while (transitionsIterator.hasNext()) {
2683
				transition = (Map.Entry) transitionsIterator.next();
2684
				input2 = (State) transition.getKey();
2685
				expectedOutput = (State) transition.getValue();
2686
				effectiveOutput = ((UnconditionalFlowInfoTestHarness) output(
2687
						UnconditionalFlowInfoTestHarness.testUnconditionalFlowInfo(input1),
2688
						UnconditionalFlowInfoTestHarness.testUnconditionalFlowInfo(input2)))
2689
					.asState();
2690
				if (effectiveOutput != expectedOutput) {
2691
					fail();
2692
					System.out.println("\t\t" + input1.printableBitsField +
2693
						" + " + input2.printableBitsField +
2694
						" => " + effectiveOutput.printableBitsField + 
2695
						" instead of: " + expectedOutput.printableBitsField);
2696
				}
2697
			}
2698
		}
2699
	}
2700
	if (combinationTestsLoopsNb > 1) {
2701
		System.out.println(this.name + "...\t\t" + combinationTestsLoopsNb + "\t" + 
2702
				(System.currentTimeMillis() - start));
2703
	}
2704
	// PREMATURE optimize test (extraneous allocations and copies)
2705
	// PREMATURE optimize test (extraneous iterations - undup)
2706
	if (!skipHighOrderBits) {
2707
		UnconditionalFlowInfoTestHarness 
2708
			zero = UnconditionalFlowInfoTestHarness.
2709
					testUnconditionalFlowInfo(State.start),
2710
			left, right, left64, right64, left128, right128,
2711
			special = (UnconditionalFlowInfoTestHarness) zero.copy();
2712
			special.grow(64); // allocates one extra without adding null info
2713
			transitionsSetsIterator = this.initializedTransitions.entrySet().iterator();
2714
			while (transitionsSetsIterator.hasNext()) {
2715
				transitionsSet = (Map.Entry) transitionsSetsIterator.next();
2716
				input1 = (State) transitionsSet.getKey();
2717
				transitionsIterator = ((Map) transitionsSet.getValue()).
2718
					entrySet().iterator();
2719
				while (transitionsIterator.hasNext()) {
2720
					transition = (Map.Entry) transitionsIterator.next();
2721
					input2 = (State) transition.getKey();
2722
					expectedOutput = (State) transition.getValue();
2723
					left = UnconditionalFlowInfoTestHarness.
2724
							testUnconditionalFlowInfo(input1);
2725
					left64 = UnconditionalFlowInfoTestHarness.
2726
							testUnconditionalFlowInfo(input1, 64);
2727
					left128 = UnconditionalFlowInfoTestHarness.
2728
						testUnconditionalFlowInfo(input1, 128);
2729
					right = UnconditionalFlowInfoTestHarness.
2730
							testUnconditionalFlowInfo(input2);
2731
					right64 = UnconditionalFlowInfoTestHarness.
2732
							testUnconditionalFlowInfo(input2, 64);
2733
					right128 = UnconditionalFlowInfoTestHarness.
2734
							testUnconditionalFlowInfo(input2, 128);
2735
				if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
2736
						output(left64, right64)).asState(64)) != 
2737
							expectedOutput) {
2738
					fail();
2739
					System.out.println("\t\t" + input1.printableBitsField +
2740
						" + " + input2.printableBitsField +
2741
						" => " + effectiveOutput.printableBitsField + 
2742
						" (64, 64) - instead of: " + expectedOutput.printableBitsField);
2743
				}
2744
				if (input1 == State.start) {
2745
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
2746
							output(right128, right)).asState()) != expectedOutput) {
2747
						fail();
2748
						System.out.println("\t\t" + input1.printableBitsField +
2749
							" + " + input2.printableBitsField +
2750
							" => " + effectiveOutput.printableBitsField + 
2751
							" (zero 128, 1) - instead of: " + expectedOutput.printableBitsField);
2752
					}
2753
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
2754
							output(zero, right64)).asState(64)) != expectedOutput) {
2755
						fail();
2756
						System.out.println("\t\t" + input1.printableBitsField +
2757
							" + " + input2.printableBitsField +
2758
							" => " + effectiveOutput.printableBitsField + 
2759
							" (zero, 64) - instead of: " + expectedOutput.printableBitsField);
2760
					}
2761
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
2762
							output(right128, right64)).asState(64)) != expectedOutput) {
2763
						fail();
2764
						System.out.println("\t\t" + input1.printableBitsField +
2765
							" + " + input2.printableBitsField +
2766
							" => " + effectiveOutput.printableBitsField + 
2767
							" (zero 128, 64) - instead of: " + expectedOutput.printableBitsField);
2768
					}
2769
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
2770
							output(zero, right128)).asState(128)) != expectedOutput) {
2771
						fail();
2772
						System.out.println("\t\t" + input1.printableBitsField +
2773
							" + " + input2.printableBitsField +
2774
							" => " + effectiveOutput.printableBitsField + 
2775
							" (zero, 128) - instead of: " + expectedOutput.printableBitsField);
2776
					}
2777
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
2778
							output(right64, right128)).asState(128)) != expectedOutput) {
2779
						fail();
2780
						System.out.println("\t\t" + input1.printableBitsField +
2781
							" + " + input2.printableBitsField +
2782
							" => " + effectiveOutput.printableBitsField + 
2783
							" (zero 64, 128) - instead of: " + expectedOutput.printableBitsField);
2784
					}
2785
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
2786
							output(special, right128)).asState(128)) != expectedOutput) {
2787
						fail();
2788
						System.out.println("\t\t" + input1.printableBitsField +
2789
							" + " + input2.printableBitsField +
2790
							" => " + effectiveOutput.printableBitsField + 
2791
							" (special zero, 128) - instead of: " + expectedOutput.printableBitsField);
2792
					}
2793
				}
2794
				if (input2 == State.start) {
2795
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
2796
							output(left, left128)).asState()) != expectedOutput) {
2797
						fail();
2798
						System.out.println("\t\t" + input1.printableBitsField +
2799
							" + " + input2.printableBitsField +
2800
							" => " + effectiveOutput.printableBitsField + 
2801
							" (1, zero 128) - instead of: " + expectedOutput.printableBitsField);
2802
					}
2803
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
2804
							output(left64, zero)).asState(64)) != expectedOutput) {
2805
						fail();
2806
						System.out.println("\t\t" + input1.printableBitsField +
2807
							" + " + input2.printableBitsField +
2808
							" => " + effectiveOutput.printableBitsField + 
2809
							" (64, zero) - instead of: " + expectedOutput.printableBitsField);
2810
					}
2811
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
2812
							output(left64, left128)).asState(64)) != expectedOutput) {
2813
						fail();
2814
						System.out.println("\t\t" + input1.printableBitsField +
2815
							" + " + input2.printableBitsField +
2816
							" => " + effectiveOutput.printableBitsField + 
2817
							" (64, zero 128) - instead of: " + expectedOutput.printableBitsField);
2818
					}
2819
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
2820
							output(left128, zero)).asState(128)) != expectedOutput) {
2821
						fail();
2822
						System.out.println("\t\t" + input1.printableBitsField +
2823
							" + " + input2.printableBitsField +
2824
							" => " + effectiveOutput.printableBitsField + 
2825
							" (128, zero) - instead of: " + expectedOutput.printableBitsField);
2826
					}
2827
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
2828
							output(left128, left64)).asState(128)) != expectedOutput) {
2829
						fail();
2830
						System.out.println("\t\t" + input1.printableBitsField +
2831
							" + " + input2.printableBitsField +
2832
							" => " + effectiveOutput.printableBitsField + 
2833
							" (128, zero 64) - instead of: " + expectedOutput.printableBitsField);
2834
					}
2835
				}
2836
			}
2837
		}
2838
	}
2839
	return this.failuresNb;
2840
}
2841
}
2842
2843
public abstract static class SymmetricalThreeDimensionalTransformation 
2844
		extends ThreeDimensionalTransformation{
2845
SymmetricalThreeDimensionalTransformation(String name, byte[][] transitions) {
2846
	super(name);
2847
	int length;
2848
	this.initializedTransitions = new HashMap((length = transitions.length) * 2 - 1);
2849
	State input1, input2;
2850
	for (int i = 0; i < length; i++) {
2851
		if (transitions[i].length != 3) {
2852
			throw new IllegalArgumentException("transitions should have three entries");
2853
		}
2854
		if (transitions[i][0] <= transitions[i][1]) {
2855
			input1 = State.states[transitions[i][0]]; // array out of bounds exception if broken
2856
			input2 = State.states[transitions[i][1]];
2857
		}
2858
		else {
2859
			input1 = State.states[transitions[i][1]];
2860
			input2 = State.states[transitions[i][0]];
2861
		}
2862
		Map transitionsForInput1 = (Map) this.initializedTransitions.get(input1);
2863
		if (transitionsForInput1 == null) {
2864
			transitionsForInput1 = new HashMap(length);
2865
			this.initializedTransitions.put(input1, transitionsForInput1);
2866
		}
2867
		if (transitionsForInput1.get(input2) != null) {
2868
			throw new IllegalArgumentException("duplicate entry");
2869
		}
2870
		transitionsForInput1.put(input2, State.states[transitions[i][2]]);
2871
	}
2872
}
2873
void hydrate() {
2874
	super.hydrate();
2875
	checkSymmetry(this.computedTransitions);
2876
}
2877
private void checkSymmetry(Map map) {
2878
	State input1, input2, result;
2879
	Map.Entry entry1, entry2;
2880
	Map transition;
2881
	Iterator transitions1 = map.entrySet().iterator(), transitions2;
2882
	while (transitions1.hasNext()) {
2883
		entry1 = (Map.Entry) transitions1.next();
2884
		input1 = (State) entry1.getKey();
2885
		transition = (Map) entry1.getValue();
2886
		transitions2 = transition.entrySet().iterator();
2887
		while (transitions2.hasNext()) {
2888
			entry2 = (Map.Entry) transitions2.next();
2889
			input2 = (State) entry2.getKey();
2890
			result = (State) entry2.getValue();
2891
			if (result != ((Map) map.get(input2)).get(input1) && input1.symbolic && input2.symbolic) {
2892
				System.err.println("symmetry mismatch: " + input1 + " + " +
2893
						input2 + " -> " + result + "/" + ((Map) map.get(input2)).get(input1));
2894
			}
2895
		}
2896
	}
2897
}
2898
void mark(char truthValues[][], boolean keepRow[], boolean keepColumn[],
2899
		int row, int column, char value) {
2900
	truthValues[row][column] = truthValues[column][row] = value;
2901
	keepRow[row] = true;
2902
	keepColumn[column] = true;
2903
	keepRow[column] = true;
2904
	keepColumn[row] = true;
2905
}
2906
void printDefinitions(BufferedWriter output, State[] consideredStates, String tab)
2907
		throws IOException {
2908
	// only difference with parent is that we print only half of possible 
2909
	// combinations
2910
	int i, j, length;
2911
	State result;
2912
	for (i = 0, length = consideredStates.length; i < length; i++) {
2913
		for (j = i; j < length; j++) {
2914
			output.write(tab);
2915
			output.write("// ");
2916
			output.write(consideredStates[i].name);
2917
			output.write(" + ");
2918
			output.write(consideredStates[j].name);
2919
			output.write(" => ");
2920
			output.write(
2921
				(result = (State)
2922
					((Map) this.computedTransitions.get(consideredStates[i])).get(consideredStates[j])).name);
2923
			if (!result.symbolic ||
2924
				result != this.initializedTransitions.get(consideredStates[i])) {
2925
				output.write("\t\t CHECK");
2926
			}
2927
			output.write('\n');
2928
		}
2929
	}
2930
}
2931
void printInitializers(BufferedWriter output, State[] consideredStates, String tab)
2932
		throws IOException {
2933
	// only difference with parent is that we print only half of possible 
2934
	// combinations
2935
	int i, j, length;
2936
	for (i = 0, length = consideredStates.length; i < length; i++) {
2937
		for (j = i; j < length; j++) {
2938
			output.write(tab);
2939
			output.write('{');
2940
			output.write(consideredStates[i].hexString);
2941
			output.write(',');
2942
			output.write(consideredStates[j].hexString);
2943
			output.write(',');
2944
			output.write(
2945
				((State)
2946
					((Map) this.computedTransitions.get(consideredStates[i])).get(consideredStates[j])).hexString);
2947
			output.write("},");
2948
			output.write('\n');
2949
		}
2950
	}
2951
}
2952
void printMissingEntries(BufferedWriter output, String tab) throws IOException {
2953
	Iterator firsts = State.symbolicStates(), seconds;
2954
	State first, second;
2955
	while (firsts.hasNext()) {
2956
		first = (State) firsts.next();
2957
		seconds = State.symbolicStates();
2958
		while (seconds.hasNext()) {
2959
			second = (State) seconds.next();
2960
			if (!checkPair(first, second)) {
2961
				addPair(first, second);
2962
				System.err.println("Adding missing transition for states (" + first + ", " + second + ")");
2963
				output.write(tab);
2964
				output.write("// ");
2965
				output.write(first.toString());
2966
				output.write(" + ");
2967
				output.write(second.toString());
2968
				output.write(" => start\t\t CHECK\n");
2969
			}
2970
		}
2971
	}
2972
}
2973
private boolean checkPair(State s1, State s2) {
2974
	Map transitions;
2975
	if ((transitions = (Map) this.initializedTransitions.get(s1)) != null) {
2976
		if (transitions.get(s2) != null) {
2977
			return true;
2978
		}
2979
	}
2980
	if ((transitions = (Map) this.initializedTransitions.get(s2)) != null) {
2981
		if (transitions.get(s1) != null) {
2982
			return true;
2983
		}
2984
	}
2985
	return false;
2986
}
2987
private void addPair(State s1, State s2) {
2988
	Map transitions;
2989
	if ((transitions = (Map) this.initializedTransitions.get(s1)) == null) {
2990
		transitions = new HashMap();
2991
		this.initializedTransitions.put(s1, transitions);
2992
	}
2993
	transitions.put(s2, s2); // dummy, non null value
2994
}
2995
// PREMATURE factorize upward
2996
int test(int combinationTestsLoopsNb, boolean skipHighOrderBits) {
2997
	Iterator transitionsSetsIterator, transitionsIterator;
2998
	State input1, input2, expectedOutput, effectiveOutput;
2999
	Map.Entry transition, transitionsSet;
3000
	this.failuresNb = 0; // reset
3001
	this.failuresNb = 0; // reset
3002
	long start = 0;
3003
	if (combinationTestsLoopsNb > 1) {
3004
		start = System.currentTimeMillis();
3005
	}
3006
	for (int l = 0; l < combinationTestsLoopsNb ; l++) {
3007
		transitionsSetsIterator = this.initializedTransitions.entrySet().iterator();
3008
		while (transitionsSetsIterator.hasNext()) {
3009
			transitionsSet = (Map.Entry) transitionsSetsIterator.next();
3010
			input1 = (State) transitionsSet.getKey();
3011
			transitionsIterator = ((Map) transitionsSet.getValue()).
3012
				entrySet().iterator();
3013
			while (transitionsIterator.hasNext()) {
3014
				transition = (Map.Entry) transitionsIterator.next();
3015
				input2 = (State) transition.getKey();
3016
				expectedOutput = (State) transition.getValue();
3017
				effectiveOutput = ((UnconditionalFlowInfoTestHarness) output(
3018
						UnconditionalFlowInfoTestHarness.testUnconditionalFlowInfo(input1),
3019
						UnconditionalFlowInfoTestHarness.testUnconditionalFlowInfo(input2)))
3020
					.asState();
3021
				if (effectiveOutput != expectedOutput) {
3022
					fail();
3023
					System.out.println("\t\t" + input1.printableBitsField +
3024
						" + " + input2.printableBitsField +
3025
						" => " + effectiveOutput.printableBitsField + 
3026
						" instead of: " + expectedOutput.printableBitsField);
3027
				}
3028
				effectiveOutput = ((UnconditionalFlowInfoTestHarness) output(
3029
						UnconditionalFlowInfoTestHarness.testUnconditionalFlowInfo(input2),
3030
						UnconditionalFlowInfoTestHarness.testUnconditionalFlowInfo(input1)))
3031
					.asState();
3032
				if (effectiveOutput != expectedOutput) {
3033
					fail();
3034
					System.out.println("\t\t" + input2.printableBitsField +
3035
						" + " + input1.printableBitsField +
3036
						" => " + effectiveOutput.printableBitsField + 
3037
						" instead of: " + expectedOutput.printableBitsField);
3038
				}
3039
			}
3040
		}
3041
	}
3042
	if (combinationTestsLoopsNb > 1) {
3043
		System.out.println(this.name + "...\t\t" + combinationTestsLoopsNb + "\t" + 
3044
				(System.currentTimeMillis() - start));
3045
	}
3046
	// PREMATURE optimize test (extraneous allocations and copies)
3047
	// PREMATURE optimize test (extraneous iterations - undup)
3048
	if (!skipHighOrderBits) {
3049
		UnconditionalFlowInfoTestHarness 
3050
			zero = UnconditionalFlowInfoTestHarness.
3051
					testUnconditionalFlowInfo(State.start),
3052
			right, left64, right64, right128;
3053
			transitionsSetsIterator = this.initializedTransitions.entrySet().iterator();
3054
			while (transitionsSetsIterator.hasNext()) {
3055
				transitionsSet = (Map.Entry) transitionsSetsIterator.next();
3056
				input1 = (State) transitionsSet.getKey();
3057
				transitionsIterator = ((Map) transitionsSet.getValue()).
3058
					entrySet().iterator();
3059
				while (transitionsIterator.hasNext()) {
3060
					transition = (Map.Entry) transitionsIterator.next();
3061
					input2 = (State) transition.getKey();
3062
					expectedOutput = (State) transition.getValue();
3063
					left64 = UnconditionalFlowInfoTestHarness.
3064
							testUnconditionalFlowInfo(input1, 64);
3065
					right = UnconditionalFlowInfoTestHarness.
3066
							testUnconditionalFlowInfo(input2);
3067
					right64 = UnconditionalFlowInfoTestHarness.
3068
							testUnconditionalFlowInfo(input2, 64);
3069
					right128 = UnconditionalFlowInfoTestHarness.
3070
							testUnconditionalFlowInfo(input2, 128);
3071
				if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
3072
						output(left64, right64)).asState(64)) != 
3073
							expectedOutput) {
3074
					fail();
3075
					System.out.println("\t\t" + input1.printableBitsField +
3076
						" + " + input2.printableBitsField +
3077
						" => " + effectiveOutput.printableBitsField + 
3078
						" (64, 64) - instead of: " + expectedOutput.printableBitsField);
3079
				}
3080
				if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
3081
						output(right64, left64)).asState(64)) != 
3082
							expectedOutput) {
3083
					fail();
3084
					System.out.println("\t\t" + input2.printableBitsField +
3085
						" + " + input1.printableBitsField +
3086
						" => " + effectiveOutput.printableBitsField + 
3087
						" (64, 64) - instead of: " + expectedOutput.printableBitsField);
3088
				}
3089
				if (input1 == State.start) {
3090
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
3091
							output(right128, right)).asState()) != expectedOutput) {
3092
						fail();
3093
						System.out.println("\t\t" + input1.printableBitsField +
3094
							" + " + input2.printableBitsField +
3095
							" => " + effectiveOutput.printableBitsField + 
3096
							" (zero 128, 1) - instead of: " + expectedOutput.printableBitsField);
3097
					}
3098
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
3099
							output(zero, right64)).asState(64)) != expectedOutput) {
3100
						fail();
3101
						System.out.println("\t\t" + input1.printableBitsField +
3102
							" + " + input2.printableBitsField +
3103
							" => " + effectiveOutput.printableBitsField + 
3104
							" (zero, 64) - instead of: " + expectedOutput.printableBitsField);
3105
					}
3106
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
3107
							output(right128, right64)).asState(64)) != expectedOutput) {
3108
						fail();
3109
						System.out.println("\t\t" + input1.printableBitsField +
3110
							" + " + input2.printableBitsField +
3111
							" => " + effectiveOutput.printableBitsField + 
3112
							" (zero 128, 64) - instead of: " + expectedOutput.printableBitsField);
3113
					}
3114
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
3115
							output(zero, right128)).asState(128)) != expectedOutput) {
3116
						fail();
3117
						System.out.println("\t\t" + input1.printableBitsField +
3118
							" + " + input2.printableBitsField +
3119
							" => " + effectiveOutput.printableBitsField + 
3120
							" (zero, 128) - instead of: " + expectedOutput.printableBitsField);
3121
					}
3122
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
3123
							output(right64, right128)).asState(128)) != expectedOutput) {
3124
						fail();
3125
						System.out.println("\t\t" + input1.printableBitsField +
3126
							" + " + input2.printableBitsField +
3127
							" => " + effectiveOutput.printableBitsField + 
3128
							" (zero 64, 128) - instead of: " + expectedOutput.printableBitsField);
3129
					}
3130
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
3131
							output(right, right128)).asState()) != expectedOutput) {
3132
						fail();
3133
						System.out.println("\t\t" + input2.printableBitsField +
3134
							" + " + input1.printableBitsField +
3135
							" => " + effectiveOutput.printableBitsField + 
3136
							" (1, zero 128) - instead of: " + expectedOutput.printableBitsField);
3137
					}
3138
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
3139
							output(right64, zero)).asState(64)) != expectedOutput) {
3140
						fail();
3141
						System.out.println("\t\t" + input2.printableBitsField +
3142
							" + " + input1.printableBitsField +
3143
							" => " + effectiveOutput.printableBitsField + 
3144
							" (64, zero) - instead of: " + expectedOutput.printableBitsField);
3145
					}
3146
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
3147
							output(right64, right128)).asState(64)) != expectedOutput) {
3148
						fail();
3149
						System.out.println("\t\t" + input2.printableBitsField +
3150
							" + " + input1.printableBitsField +
3151
							" => " + effectiveOutput.printableBitsField + 
3152
							" (64, zero 128) - instead of: " + expectedOutput.printableBitsField);
3153
					}
3154
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
3155
							output(right128, zero)).asState(128)) != expectedOutput) {
3156
						fail();
3157
						System.out.println("\t\t" + input2.printableBitsField +
3158
							" + " + input1.printableBitsField +
3159
							" => " + effectiveOutput.printableBitsField + 
3160
							" (128, zero) - instead of: " + expectedOutput.printableBitsField);
3161
					}
3162
					if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness)
3163
							output(right128, right64)).asState(128)) != expectedOutput) {
3164
						fail();
3165
						System.out.println("\t\t" + input2.printableBitsField +
3166
							" + " + input1.printableBitsField +
3167
							" => " + effectiveOutput.printableBitsField + 
3168
							" (128, zero 64) - instead of: " + expectedOutput.printableBitsField);
3169
					}
3170
				}
3171
			}
3172
		}
3173
	}
3174
	return this.failuresNb;
3175
}
3176
}
3177
}
(-)src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java (+1866 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.jdt.core.tests.compiler.regression;
12
13
import java.io.BufferedReader;
14
import java.io.BufferedWriter;
15
import java.io.File;
16
import java.io.FileReader;
17
import java.io.FileWriter;
18
import java.io.IOException;
19
import java.util.ArrayList;
20
import java.util.HashMap;
21
import java.util.Iterator;
22
import java.util.List;
23
import java.util.Map;
24
import java.util.SortedMap;
25
import java.util.TreeMap;
26
27
import org.eclipse.jdt.internal.compiler.flow.FlowInfo;
28
import org.eclipse.jdt.internal.compiler.flow.NullInfoRegistry;
29
import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo;
30
import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo.AssertionFailedException;
31
import org.eclipse.jdt.internal.compiler.impl.Constant;
32
import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
33
import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
34
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
35
36
import junit.framework.AssertionFailedError;
37
import junit.framework.Test;
38
import junit.framework.TestSuite;
39
40
/**
41
 * A tests series especially meant to validate the internals of our null
42
 * reference analysis. See NullReferenceTest for tests targetted at 
43
 * the source code compiler behavior level.
44
 */
45
public class NullReferenceImplTests extends NullReferenceTest {
46
	// Static initializer to specify tests subset using TESTS_* static variables
47
  	// All specified tests which does not belong to the class are skipped...
48
  	// Only the highest compliance level is run; add the VM argument
49
  	// -Dcompliance=1.4 (for example) to lower it if needed
50
  	static {
51
//    	TESTS_NAMES = new String[] { "test2050" };
52
//    	TESTS_NUMBERS = new int[] { 2061 };   
53
//    	TESTS_NUMBERS = new int[] { 2999 };   
54
//    	TESTS_RANGE = new int[] { 2050, -1 }; 
55
  	}
56
57
/**
58
 * A class to hold states as seen by the low level validation tests and machinery.
59
 * State provides:
60
 * - singletons for all possible states given the number of bits for the said 
61
 *   states;
62
 * - semantic names for known states;
63
 * - printable representation of states as bit fields;
64
 * - coordination with other classes to perform transitive closure analysis, etc.
65
 */
66
	/*
67
		This is a tabular definition for states. It can be completed/leveraged by 
68
		the Generator class so as to smoothen the transition between differing encodings
69
		of the states.
70
	// STATES DEFINITION START
71
			000000	start
72
			000001
73
			000010
74
			000011
75
			000100	pot. unknown
76
			000101
77
			000110
78
			000111
79
			001000	pot. non null
80
			001001
81
			001010
82
			001011
83
			001100	pot. nn & pot. un
84
			001101
85
			001110
86
			001111
87
			010000	pot. null
88
			010001
89
			010010
90
			010011
91
			010100	pot. n & pot. un
92
			010101
93
			010110
94
			010111
95
			011000	pot. n & pot. nn
96
			011001
97
			011010
98
			011011
99
			011100
100
			011101
101
			011110
102
			011111
103
			100000
104
			100001
105
			100010
106
			100011
107
			100100	def. unknown
108
			100101
109
			100110
110
			100111
111
			101000	def. non null
112
			101001
113
			101010
114
			101011
115
			101100	pot. nn & prot. nn
116
			101101
117
			101110
118
			101111
119
			110000	def. null
120
			110001
121
			110010
122
			110011
123
			110100	pot. n & prot. n
124
			110101
125
			110110
126
			110111
127
			111000	prot. null
128
			111001
129
			111010
130
			111011
131
			111100	prot. non null
132
			111101
133
			111110
134
			111111
135
	// STATES DEFINITION END
136
	*/
137
	public static class State implements Comparable {
138
		// PREMATURE consider moving initialization to test setup/dispose
139
		public final static State[] states = {
140
			// STATES INITIALIZER START
141
			new State(0, "start"), // 000000
142
			new State(1), // 000001
143
			new State(2), // 000010
144
			new State(3), // 000011
145
			new State(4, "pot. unknown"), // 000100
146
			new State(5), // 000101
147
			new State(6), // 000110
148
			new State(7), // 000111
149
			new State(8, "pot. non null"), // 001000
150
			new State(9), // 001001
151
			new State(10), // 001010
152
			new State(11), // 001011
153
			new State(12, "pot. nn & pot. un"), // 001100
154
			new State(13), // 001101
155
			new State(14), // 001110
156
			new State(15), // 001111
157
			new State(16, "pot. null"), // 010000
158
			new State(17), // 010001
159
			new State(18), // 010010
160
			new State(19), // 010011
161
			new State(20, "pot. n & pot. un"), // 010100
162
			new State(21), // 010101
163
			new State(22), // 010110
164
			new State(23), // 010111
165
			new State(24, "pot. n & pot. nn"), // 011000
166
			new State(25), // 011001
167
			new State(26), // 011010
168
			new State(27), // 011011
169
			new State(28), // 011100
170
			new State(29), // 011101
171
			new State(30), // 011110
172
			new State(31), // 011111
173
			new State(32), // 100000
174
			new State(33), // 100001
175
			new State(34), // 100010
176
			new State(35), // 100011
177
			new State(36, "def. unknown"), // 100100
178
			new State(37), // 100101
179
			new State(38), // 100110
180
			new State(39), // 100111
181
			new State(40, "def. non null"), // 101000
182
			new State(41), // 101001
183
			new State(42), // 101010
184
			new State(43), // 101011
185
			new State(44, "pot. nn & prot. nn"), // 101100
186
			new State(45), // 101101
187
			new State(46), // 101110
188
			new State(47), // 101111
189
			new State(48, "def. null"), // 110000
190
			new State(49), // 110001
191
			new State(50), // 110010
192
			new State(51), // 110011
193
			new State(52, "pot. n & prot. n"), // 110100
194
			new State(53), // 110101
195
			new State(54), // 110110
196
			new State(55), // 110111
197
			new State(56, "prot. null"), // 111000
198
			new State(57), // 111001
199
			new State(58), // 111010
200
			new State(59), // 111011
201
			new State(60, "prot. non null"), // 111100
202
			new State(61), // 111101
203
			new State(62), // 111110
204
			new State(63), // 111111
205
			// STATES INITIALIZER END
206
		};
207
		public final static State start = states[0];
208
		public static final int 
209
			stateMaxValue = 0x3F,
210
			stateWidth = 6,
211
			statesNb = stateMaxValue + 1;
212
		String name, printableBitsField, hexString;
213
		public byte value;
214
		boolean symbolic;
215
	private State() {
216
	}
217
	private State(int numericValue) {
218
		this(numericValue, null);
219
	}
220
	private State(int numericValue, String publicName) {
221
		if (numericValue > stateMaxValue) {
222
			throw new IllegalArgumentException("state value overflow");
223
		}
224
		this.value = (byte) numericValue;
225
		StringBuffer printableValue = new StringBuffer(6);
226
		for (int i = stateWidth - 1; i >= 0; i--) {
227
			printableValue.append((numericValue >>> i & 1) != 0 ? '1' : '0');
228
		}
229
		this.printableBitsField = printableValue.toString();
230
		if (this.value > 0xF) {
231
			this.hexString = "0x" + Integer.toHexString(this.value).toUpperCase();
232
		}
233
		else {
234
			this.hexString = "0x0" + Integer.toHexString(this.value).toUpperCase();
235
		}
236
		if (publicName != null) {
237
			this.name = publicName;
238
			this.symbolic = true;
239
		}
240
		else {
241
			this.name = this.printableBitsField;
242
		}
243
	}
244
	private State(String commentLine) {
245
		char current = ' '; // keep the initialization status quiet
246
		int cursor, length;
247
		for (cursor = 0, length = commentLine.length(); 
248
			cursor < length;
249
			cursor++) {
250
			if ((current = commentLine.charAt(cursor)) == '0' ||
251
					current == '1') {
252
				break;
253
			}
254
		}
255
		if (cursor == length) {
256
			throw new RuntimeException("bad state definition format (missing bits field): " + commentLine); 
257
			// PREMATURE adopt consistent error policy
258
		}
259
		int valueDigits;
260
		for (valueDigits = 1; cursor < (length - 1) && valueDigits < stateWidth; valueDigits++) {
261
			this.value = (byte) ((this.value << 1) + (current - '0'));
262
			if ((current = commentLine.charAt(++cursor)) != '0' &&
263
					current != '1') {
264
				throw new RuntimeException("bad state definition format (inappropriate character in bits field): " + commentLine);
265
				// PREMATURE adopt consistent error policy
266
			}
267
		}
268
		if (valueDigits < stateWidth) {
269
			throw new RuntimeException("bad state definition format (bits field is too short): " + commentLine);
270
			// PREMATURE adopt consistent error policy
271
		}
272
		this.value = (byte) ((this.value << 1) + (current - '0'));
273
		this.printableBitsField = commentLine.substring(cursor - stateWidth + 1, cursor + 1);
274
		if (this.value > 0xF) {
275
			this.hexString = "0x" + Integer.toHexString(this.value).toUpperCase();
276
		}
277
		else {
278
			this.hexString = "0x0" + Integer.toHexString(this.value).toUpperCase();
279
		}
280
		while (++cursor < length && Character.isWhitespace(current = commentLine.charAt(++cursor)) && current != '\n') {
281
			// loop
282
		}
283
		if (cursor < length && current != '\n') {
284
			this.name = commentLine.substring(cursor, length);
285
		}
286
		if (this.name == null) {
287
			this.name = this.printableBitsField;
288
		} else {
289
			this.symbolic = true;
290
		}
291
	}
292
	private String asInitializer() {
293
		StringBuffer result = new StringBuffer(70);
294
		result.append("		new State(");
295
		result.append(this.value);
296
		char first;
297
		boolean nameIsSymbolic = (first = this.name.charAt(0)) != '0'
298
			&& first != '1';
299
		if (nameIsSymbolic) {
300
			result.append(", \"");
301
			result.append(this.name);
302
			result.append('"');
303
		}
304
		result.append("), // ");
305
		result.append(this.printableBitsField);
306
		return result.toString();
307
	}
308
	long [] asLongArray() {
309
		long[] result = new long[stateWidth];
310
		for (int i = 0; i < stateWidth; i++) {
311
			result[i] = ((this.value >> (stateWidth - i - 1)) & 1) == 0 ? 0 : 1;
312
		}
313
		return result;
314
	}
315
	private String asSourceComment() {
316
		StringBuffer result = new StringBuffer(70);
317
		result.append("\t\t");
318
		result.append(this.printableBitsField);
319
		char first;
320
		boolean nameIsSymbolic = (first = this.name.charAt(0)) != '0'
321
			&& first != '1';
322
		if (nameIsSymbolic) {
323
			result.append('\t');
324
			result.append(this.name);
325
		}
326
		return result.toString();
327
	}
328
	public int compareTo(Object o) {
329
		return this.value - ((State) o).value;
330
	}
331
	static State fromLongValues(long bit1, long bit2, long bit3, long bit4, long bit5, long bit6) {
332
		// PREMATURE consider taking an UnconditionalFlowInfo in parameter
333
		return states[(int)(
334
			(bit6 & 1) + 
335
				2 * ((bit5 & 1) +
336
					2 * ((bit4 & 1) +
337
						2 * ((bit3 & 1) +
338
							2 * ((bit2 & 1) +
339
								2 * (bit1 & 1))))))];
340
	}
341
	private static Map namesIndex; 
342
	static State fromSymbolicName (String name) {
343
		if (namesIndex == null) {
344
			namesIndex = new HashMap(states.length);
345
			for (int i = 0; i < states.length; i++) {
346
				if (states[i].name != null) {
347
					namesIndex.put(states[i].name, states[i]);
348
				}
349
			}
350
		}
351
		return (State) namesIndex.get(name);
352
	}
353
	private static void grabDefinitionFromComment(BufferedReader input) {
354
		String line;
355
		State current;
356
	// use when the initializer is incomplete, hence needs to be reinitialized
357
	//	states = new State[stateMaxValue + 1];
358
	// use when the states field is final, with the appropriate size:
359
		for (int i = 0; i <= stateMaxValue; i++) {
360
			states[i] = null;
361
		}
362
		try {
363
			while ((line = input.readLine()) != null && line.indexOf(definitionEndMarker) == -1) {
364
				current = new State(line);
365
				if (states[current.value] != null) {
366
					throw new RuntimeException("duplicate state for index: " + current.value);
367
				}
368
				else {
369
					states[current.value] = current;
370
				}
371
			}
372
		} catch (IOException e) {
373
			throw new RuntimeException(e);
374
		}
375
		for (int i = 0; i < stateMaxValue; i++) {
376
			if (states[i] == null) {
377
				states[i] = new State(i);
378
			}
379
		}
380
	}
381
	// PREMATURE may decide to remove
382
	//private static void printAsInitializer() {
383
	//	int i, length;
384
	//	System.out.println(initializerStartMarker);
385
	//	for (i = 0, length = states.length; i < length; i++) {
386
	//		System.out.println(states[i].asInitializer());
387
	//	}
388
	//	for (/* continue */; i <= stateMaxValue; i++) {
389
	//		System.out.println((new State(i)).asInitializer() + " CHECK");
390
	//	}
391
	//	System.out.println(initializerEndMarker);
392
	//}
393
	// PREMATURE may decide to remove
394
	//private static void printAsSourceComment() {
395
	//	int i, length;
396
	//	System.out.println("/*");
397
	//	System.out.println(definitionStartMarker);
398
	//	for (i = 0, length = states.length; i < length; i++) {
399
	//		System.out.println(states[i].asSourceComment());
400
	//	}
401
	//	for (/* continue */; i <= stateMaxValue; i++) {
402
	//		System.out.println((new State(i)).asSourceComment());
403
	//	}
404
	//	System.out.println(definitionEndMarker);
405
	//	System.out.println("*/");
406
	//}
407
	private final static String 
408
		definitionStartMarker = "// STATES " + CodeAnalysis.definitionStartMarker,
409
		definitionEndMarker = "// STATES " + CodeAnalysis.definitionEndMarker,
410
		initializerStartMarker = "// STATES " + CodeAnalysis.initializerStartMarker,
411
		initializerEndMarker = "// STATES " + CodeAnalysis.initializerEndMarker;
412
	static void reinitializeFromComment(BufferedReader input, BufferedWriter output) {
413
		String line, tab = "";
414
		int cursor;
415
		char c;
416
		try {
417
			while ((line = input.readLine()) != null) {
418
				output.write(line);
419
				output.write('\n');
420
				if ((cursor = line.indexOf(definitionStartMarker)) != -1) {
421
					// check the line format
422
					boolean reachedStart = true;
423
					for (int i = 0; i < cursor; i++) {
424
						if (!Character.isWhitespace(c = line.charAt(i))) {
425
							reachedStart = false;
426
							break;
427
						}
428
						else {
429
							tab += c;
430
						}
431
					}
432
					if (reachedStart) {
433
						grabDefinitionFromComment(input); // consumes up to the END line
434
						int i, length;
435
						for (i = 0, length = states.length; i < length; i++) {
436
							output.write(states[i].asSourceComment());
437
							output.write('\n');
438
						}
439
						output.write(tab + definitionEndMarker + "\n");
440
					}
441
				}
442
				if ((cursor = line.indexOf(initializerStartMarker)) != -1) {
443
					// check the line format
444
					boolean reachedStart = true;
445
					tab = "";
446
					for (int i = 0; i < cursor; i++) {
447
						if (!Character.isWhitespace(c = line.charAt(i))) {
448
							reachedStart = false;
449
							break;
450
						}
451
						else {
452
							tab += c;
453
						}
454
					}
455
					if (reachedStart) {
456
						while ((line = input.readLine()) != null && 
457
								line.indexOf(initializerEndMarker) == -1) {
458
							// loop
459
						}
460
						int i, length;
461
						for (i = 0, length = states.length; i < length; i++) {
462
							output.write(states[i].asInitializer());
463
							output.write('\n');
464
						}
465
						output.write(tab + initializerEndMarker + "\n");
466
					}
467
				}
468
			}
469
			output.flush();
470
			namesIndex = null;
471
		} catch (IOException e) {
472
			throw new RuntimeException(e);
473
		}
474
	}
475
	static Iterator symbolicStates() {
476
		return new Iterator() {
477
			int nextSymbolic = -1;
478
			public boolean hasNext() {
479
				if (nextSymbolic == -1) {
480
					for (nextSymbolic = 0; nextSymbolic < states.length; nextSymbolic++) {
481
						if (states[nextSymbolic].symbolic) {
482
							break;
483
						}
484
					}
485
				} else {
486
					for (; nextSymbolic < states.length; nextSymbolic++) {
487
						if (states[nextSymbolic].symbolic) {
488
							break;
489
						}
490
					}
491
				}
492
				return nextSymbolic < states.length;
493
			}
494
			public Object next() {
495
				State result = null;
496
				if (nextSymbolic < states.length) {
497
					result = states[nextSymbolic];
498
					nextSymbolic++;
499
				}
500
				return result;
501
			}
502
			public void remove() {
503
				throw new RuntimeException("unimplemented");
504
			}
505
		};
506
	}
507
	public String toString() {
508
		return this.name;
509
	}
510
	}
511
512
public NullReferenceImplTests(String name) {
513
    super(name);
514
}
515
516
  	// Tests tuning
517
	static final boolean 
518
		skipHighOrderBits = false; // define to true when tuning encoding
519
	static final int
520
		combinationTestsloopsNb = 1; // define to 10000s to measure performances
521
522
public static Test suite() {
523
	// we do not want to run for 1.3, 1.4, 1.5 but once only
524
    Class clazz = testClass();
525
    TestSuite all = new TestSuite(clazz.getName());
526
    List tests = buildTestsList(testClass());
527
    for (int i = 0, length = tests.size(); i < length; i++) {
528
    	all.addTest((Test) tests.get(i));
529
    }
530
	return all;
531
}
532
  
533
public static Class testClass() {
534
    return NullReferenceImplTests.class;
535
}
536
537
public void test2050_markAsComparedEqualToNonNull() {
538
	int failures = NullReferenceImplTransformations.markAsComparedEqualToNonNull.test();
539
	assertTrue("nb of failures: " + failures, failures == 0);
540
}
541
542
public void test2051_markAsComparedEqualToNull() {
543
	int failures = NullReferenceImplTransformations.markAsComparedEqualToNull.test();
544
	assertTrue("nb of failures: " + failures, failures == 0);
545
}
546
547
public void test2055_markAsDefinitelyNonNull() {
548
	int failures = NullReferenceImplTransformations.markAsDefinitelyNonNull.test();
549
	assertTrue("nb of failures: " + failures, failures == 0);
550
}
551
552
public void test2056_markAsDefinitelyNull() {
553
	int failures = NullReferenceImplTransformations.markAsDefinitelyNull.test();
554
	assertTrue("nb of failures: " + failures, failures == 0);
555
}
556
557
public void test2057_markAsDefinitelyUnknown() {
558
	int failures = NullReferenceImplTransformations.markAsDefinitelyUnknown.test();
559
	assertTrue("nb of failures: " + failures, failures == 0);
560
}
561
562
public void test2060_addInitializationsFrom() {
563
	int failures = NullReferenceImplTransformations.addInitializationsFrom.test();
564
	assertTrue("nb of failures: " + failures, failures == 0);
565
}
566
567
public void test2061_addPotentialInitializationsFrom() {
568
	int failures = NullReferenceImplTransformations.addPotentialInitializationsFrom.test();
569
	assertTrue("nb of failures: " + failures, failures == 0);
570
}
571
572
public void test2062_mergedWith() {
573
	int failures = NullReferenceImplTransformations.mergedWith.test();
574
	assertTrue("nb of failures: " + failures, failures == 0);
575
}
576
577
public void test2070_newNullInfoRegistry() {
578
	int failures = NullReferenceImplTransformations.newNullInfoRegistry.test();
579
	assertTrue("nb of failures: " + failures, failures == 0);
580
}
581
582
// PREMATURE rewrite from scratch
583
//public void _test2058_recode() {
584
//	long [][][] testData = transitionsTablesData[recode];
585
//	int failures = 0;
586
//	long start;
587
//	if (combinationTestsloopsNb > 1) {
588
//		start = System.currentTimeMillis();
589
//	}
590
//	String header = "recode failures: ";
591
//	for (int l = 0; l < combinationTestsloopsNb ; l++) {
592
//		for (int i = 0; i < testData.length; i++) {
593
//			UnconditionalFlowInfoTestHarness result;
594
//			result = UnconditionalFlowInfoTestHarness.
595
//						testUnconditionalFlowInfo(testData[i][0]);
596
//			result.encode();
597
//			result.decode();
598
//			
599
//			if (!result.testEquals(UnconditionalFlowInfoTestHarness.
600
//						testUnconditionalFlowInfo(testData[i][0]))) {
601
//				if (failures == 0) {
602
//					System.out.println(header);
603
//				}
604
//				failures++;
605
//				System.out.println("\t\t{" + result.testString() + 
606
//					"}, // instead of: " + testStringValueOf(testData[i][0]));
607
//			}
608
//		}
609
//	}
610
//	if (combinationTestsloopsNb > 1) {
611
//		System.out.println("mergedWith\t\t\t" + combinationTestsloopsNb + "\t" + 
612
//				(System.currentTimeMillis() - start));
613
//	}
614
//	for (int i = 0; i < testData.length; i++) {
615
//		UnconditionalFlowInfoTestHarness result;
616
//		result = UnconditionalFlowInfoTestHarness.
617
//					testUnconditionalFlowInfo(testData[i][0], 64);
618
//		result.encode();
619
//		result.decode();
620
//		
621
//		if (!result.testEquals(UnconditionalFlowInfoTestHarness.
622
//					testUnconditionalFlowInfo(testData[i][0], 64))) {
623
//			if (failures == 0) {
624
//				System.out.println(header);
625
//			}
626
//			failures++;
627
//			System.out.println("\t\t{" + result.testString() + 
628
//				"}, // (64) - instead of: " + testStringValueOf(testData[i][0]));
629
//		}
630
//	}
631
//	assertTrue("nb of failures: " + failures, failures == 0);
632
//}
633
634
public void test2400_state_consistency() {
635
	int failures = 0;
636
	long start;
637
	if (combinationTestsloopsNb > 1) {
638
		start = System.currentTimeMillis();
639
	}
640
	String header = "state consistency failures: ";
641
	for (int l = 0; l < combinationTestsloopsNb ; l++) {
642
		for (int i = 0; i < State.states.length; i++) {
643
			if (State.states[i].symbolic) {
644
				UnconditionalFlowInfoTestHarness 
645
					state = UnconditionalFlowInfoTestHarness.
646
							testUnconditionalFlowInfo(State.states[i]);
647
				boolean
648
					isDefinitelyNonNull = state.isDefinitelyNonNull(TestLocalVariableBinding.local0),
649
					isDefinitelyNull = state.isDefinitelyNull(TestLocalVariableBinding.local0),
650
					isDefinitelyUnknown = state.isDefinitelyUnknown(TestLocalVariableBinding.local0),
651
					isPotentiallyNull = state.isPotentiallyNull(TestLocalVariableBinding.local0),
652
					isPotentiallyUnknown = state.isPotentiallyUnknown(TestLocalVariableBinding.local0),
653
					isProtectedNonNull = state.isProtectedNonNull(TestLocalVariableBinding.local0),
654
					isProtectedNull = state.isProtectedNull(TestLocalVariableBinding.local0);
655
				if (isDefinitelyNonNull
656
							&& (isDefinitelyNull || isDefinitelyUnknown
657
									|| isPotentiallyNull
658
									|| isProtectedNull)) {
659
					if (failures == 0) {
660
						System.out.println(header);
661
					}
662
					failures++;
663
					System.out.println("\t\tconsistency breakage for definitely non null state " + State.states[i].name);
664
				}
665
				if (isDefinitelyNull
666
							&& (isDefinitelyNonNull || isDefinitelyUnknown
667
									|| isPotentiallyUnknown || isProtectedNonNull)) {
668
					if (failures == 0) {
669
						System.out.println(header);
670
					}
671
					failures++;
672
					System.out.println("\t\tconsistency breakage for definitely null state " + State.states[i].name);
673
				}
674
				if (isDefinitelyUnknown
675
							&& (isDefinitelyNonNull || isDefinitelyNull
676
									|| isPotentiallyNull || isProtectedNonNull
677
									|| isProtectedNull)) {
678
					if (failures == 0) {
679
						System.out.println(header);
680
					}
681
					failures++;
682
					System.out.println("\t\tconsistency breakage for definitely unknown state " + State.states[i].name);
683
				}
684
				if (isProtectedNonNull && !isDefinitelyNonNull
685
						|| isProtectedNull && !isDefinitelyNull
686
						|| i > 0 // not start
687
							&& !State.states[i].name.equals("pot. non null")
688
							&& !(isDefinitelyNonNull || isDefinitelyNull
689
									|| isDefinitelyUnknown || isPotentiallyNull
690
									|| isPotentiallyUnknown || isProtectedNonNull
691
									|| isProtectedNull)) {
692
					if (failures == 0) {
693
						System.out.println(header);
694
					}
695
					failures++;
696
					System.out.println("\t\tconsistency breakage for " + State.states[i].name);
697
				}
698
			}
699
		}
700
	}
701
	if (combinationTestsloopsNb > 1) {
702
		System.out.println("mergedWith\t\t\t" + combinationTestsloopsNb + "\t" + 
703
				(System.currentTimeMillis() - start));
704
	}
705
	for (int i = 0; i < State.states.length; i++) {
706
		if (State.states[i].symbolic) {
707
			UnconditionalFlowInfoTestHarness state;
708
			state = UnconditionalFlowInfoTestHarness.
709
						testUnconditionalFlowInfo(State.states[i], 64);
710
			boolean
711
				isDefinitelyNonNull = state.isDefinitelyNonNull(TestLocalVariableBinding.local64),
712
				isDefinitelyNull = state.isDefinitelyNull(TestLocalVariableBinding.local64),
713
				isDefinitelyUnknown = state.isDefinitelyUnknown(TestLocalVariableBinding.local64),
714
				isPotentiallyNull = state.isPotentiallyNull(TestLocalVariableBinding.local64),
715
				isPotentiallyUnknown = state.isPotentiallyUnknown(TestLocalVariableBinding.local64),
716
				isProtectedNonNull = state.isProtectedNonNull(TestLocalVariableBinding.local64),
717
				isProtectedNull = state.isProtectedNull(TestLocalVariableBinding.local64);
718
				if (isDefinitelyNonNull
719
							&& (isDefinitelyNull || isDefinitelyUnknown
720
									|| isPotentiallyNull
721
									|| isProtectedNull)) {
722
					if (failures == 0) {
723
						System.out.println(header);
724
					}
725
					failures++;
726
					System.out.println("\t\tconsistency breakage (64) for definitely non null state " + State.states[i].name);
727
				}
728
				if (isDefinitelyNull
729
							&& (isDefinitelyNonNull || isDefinitelyUnknown
730
									|| isPotentiallyUnknown || isProtectedNonNull)) {
731
					if (failures == 0) {
732
						System.out.println(header);
733
					}
734
					failures++;
735
					System.out.println("\t\tconsistency breakage (64) for definitely null state " + State.states[i].name);
736
				}
737
				if (isDefinitelyUnknown
738
							&& (isDefinitelyNonNull || isDefinitelyNull
739
									|| isPotentiallyNull || isProtectedNonNull
740
									|| isProtectedNull)) {
741
					if (failures == 0) {
742
						System.out.println(header);
743
					}
744
					failures++;
745
					System.out.println("\t\tconsistency breakage (64) for definitely unknown state " + State.states[i].name);
746
				}
747
				if (isProtectedNonNull && !isDefinitelyNonNull
748
						|| isProtectedNull && !isDefinitelyNull
749
						|| i > 0 // not start
750
							&& !State.states[i].name.equals("pot. non null")						
751
							&& !(isDefinitelyNonNull || isDefinitelyNull
752
									|| isDefinitelyUnknown || isPotentiallyNull
753
									|| isPotentiallyUnknown || isProtectedNonNull
754
									|| isProtectedNull)) {
755
					if (failures == 0) {
756
						System.out.println(header);
757
					}
758
					failures++;
759
					System.out.println("\t\tconsistency breakage (64) for " + State.states[i].name);
760
				}
761
		}
762
	}
763
	assertTrue("nb of failures: " + failures, failures == 0);
764
}
765
766
public void test2500_addInitializationsFrom_for_definites() {
767
	// when an added initialization is a def. something, it should
768
	// affect the left hand term as the markAsDefinite* method would
769
	// do
770
	int failures = 0;
771
	for (int i = 0; i < State.states.length; i++) {
772
		if (State.states[i].symbolic) {
773
			UnconditionalFlowInfoTestHarness source1, source2, result1, result2;
774
			source1 = UnconditionalFlowInfoTestHarness.
775
				testUnconditionalFlowInfo(State.states[i]);
776
			for (int j = 0; j < State.states.length; j++) {
777
				if (State.states[j].symbolic) {
778
					source2 = UnconditionalFlowInfoTestHarness.
779
						testUnconditionalFlowInfo(State.states[j]);
780
					result1 = (UnconditionalFlowInfoTestHarness) source1.copy();
781
					result2 = (UnconditionalFlowInfoTestHarness) source1.copy();
782
					if (source2.isDefinitelyNonNull(TestLocalVariableBinding.local0)) {
783
						if (! source2.isProtectedNonNull(TestLocalVariableBinding.local0)) {
784
							result1.markAsDefinitelyNonNull(TestLocalVariableBinding.local0);
785
						} else {
786
							continue;
787
						}
788
					}
789
					else if (source2.isDefinitelyNull(TestLocalVariableBinding.local0)) {
790
						if (! source2.isProtectedNull(TestLocalVariableBinding.local0)) {
791
							result1.markAsDefinitelyNull(TestLocalVariableBinding.local0);
792
						} else {
793
							continue;
794
						}
795
					}
796
					else if (source2.isDefinitelyUnknown(TestLocalVariableBinding.local0)) {
797
						result1.markAsDefinitelyUnknown(TestLocalVariableBinding.local0);
798
					}
799
					else if (source2.nullBit1 != 0) {
800
						if (failures == 0) {
801
							System.out.println("addInitializationsFrom_for_definites failures: "); //$NON-NLS-1$
802
						}
803
						failures++;
804
						System.out.println("\t\t" + State.states[j].name +
805
							" should answer true to at least one isDefinite* query");
806
						// PREMATURE move to specific queries test case
807
					}
808
					else {
809
						continue;
810
					}
811
					result2.addInitializationsFrom(source2);
812
					if (!result1.testEquals(result2)) {
813
						if (failures == 0) {
814
							System.out.println("addInitializationsFrom_for_definites failures: "); //$NON-NLS-1$
815
						}
816
						failures++;
817
						System.out.println("\t\t" + State.states[i].name + 
818
							" + " + State.states[j].name +
819
							" => " + result2.asState().name + 
820
							" instead of: " + result1.asState().name);
821
					}
822
				}
823
			}
824
		}
825
	}
826
	assertTrue("nb of failures: " + failures, failures == 0);
827
}
828
829
// Use for coverage tests only. Needs specific instrumentation of code,
830
// that is controled by UnconditionalFlowInfo#coverageTestFlag.
831
// Note: coverage tests tend to fill the console with messages, and the
832
//       instrumented code is slower, so never release code with active
833
//       coverage tests.
834
private static int coveragePointsNb = 39;
835
836
// PREMATURE reactivate coverage tests
837
// Coverage by state transition tables methods.
838
public void test2998_coverage() {
839
	if (UnconditionalFlowInfo.coverageTestFlag) {
840
		// sanity check: need to be sure that the tests execute properly when not
841
		// trying to check coverage
842
		UnconditionalFlowInfo.coverageTestId = 0;
843
		test0053_array();
844
		test0070_type_reference();
845
		test2050_markAsComparedEqualToNonNull();
846
		test2051_markAsComparedEqualToNull();
847
		test2055_markAsDefinitelyNonNull();
848
		test2056_markAsDefinitelyNull();
849
		test2057_markAsDefinitelyUnknown();
850
		test2060_addInitializationsFrom();
851
		test2061_addPotentialInitializationsFrom();
852
		test2062_mergedWith();
853
		// coverage check
854
		int failuresNb = 0;
855
		for (int i = 1; i <= coveragePointsNb; i++) {
856
			if (i == 11 || i == 12 || i == 14) {
857
				continue;
858
				// these can only be reached via a direct call to addPotentialNullInfoFrom,
859
				// which is not implemented in low level tests - all those go through
860
				// addPotentialInitsFrom
861
			}
862
			try {
863
				UnconditionalFlowInfo.coverageTestId = i;
864
				test0053_array();
865
				test0070_type_reference();
866
				test2050_markAsComparedEqualToNonNull();
867
				test2051_markAsComparedEqualToNull();
868
				test2055_markAsDefinitelyNonNull();
869
				test2056_markAsDefinitelyNull();
870
				test2057_markAsDefinitelyUnknown();
871
				test2060_addInitializationsFrom();
872
				test2061_addPotentialInitializationsFrom();
873
				test2062_mergedWith();
874
			}
875
			catch (AssertionFailedError e) {
876
				continue;
877
			}
878
			catch (AssertionFailedException e) {
879
				continue;
880
			}
881
			failuresNb++;
882
			System.out.println("Missing coverage point: " + i);
883
		}
884
		UnconditionalFlowInfo.coverageTestId = 0; // reset for other tests
885
		assertEquals(failuresNb + " missing coverage point(s)", failuresNb, 0);
886
	}
887
}
888
889
// Coverage by code samples.
890
public void test2999_coverage() {
891
	if (UnconditionalFlowInfo.coverageTestFlag) {
892
		// sanity check: need to be sure that the tests execute properly when not
893
		// trying to check coverage
894
		UnconditionalFlowInfo.coverageTestId = 0;
895
		test0001_simple_local();
896
		test0053_array();
897
		test0070_type_reference();
898
		test0327_if_else();
899
		test0401_while();
900
		test0420_while();
901
		test0509_try_finally_embedded();
902
		test2000_flow_info();
903
		test2004_flow_info();
904
		test2008_flow_info();
905
		test2011_flow_info();
906
		test2013_flow_info();
907
		test2018_flow_info();
908
		test2019_flow_info();
909
		test2020_flow_info();
910
		// coverage check
911
		int failuresNb = 0;
912
		for (int i = 1; i <= coveragePointsNb; i++) {
913
			if (i < 3
914
				|| 4 < i && i < 11
915
				|| 11 < i && i < 16
916
				|| 16 < i && i < 20
917
				|| i == 21
918
				|| 23 < i && i < 27
919
				|| 29 < i && i < 33
920
				|| 36 < i) { // TODO (maxime) complete coverage tests
921
				continue;
922
			}
923
			try {
924
				UnconditionalFlowInfo.coverageTestId = i;
925
				test0001_simple_local();
926
				test0053_array();
927
				test0070_type_reference();
928
				test0327_if_else();
929
				test0401_while();
930
				test0420_while();
931
				test0509_try_finally_embedded();
932
				test2000_flow_info();
933
				test2004_flow_info();
934
				test2008_flow_info();
935
				test2011_flow_info();
936
				test2013_flow_info();
937
				test2018_flow_info();
938
				test2019_flow_info();
939
				test2020_flow_info();
940
			}
941
			catch (AssertionFailedError e) {
942
				continue;
943
			}
944
			catch (AssertionFailedException e) {
945
				continue;
946
			}
947
			failuresNb++;
948
			System.out.println("Missing coverage point: " + i);
949
		}
950
		UnconditionalFlowInfo.coverageTestId = 0; // reset for other tests
951
		assertEquals(failuresNb + " missing coverage point(s)", failuresNb, 0);
952
	}
953
}
954
955
// only works for info coded on bit 0 - least significant
956
String testCodedValueOf(long[] data) {
957
	int length;
958
	StringBuffer result = new StringBuffer(length = data.length);
959
	for (int i = 0; i < length; i++) {
960
		result.append(data[i] == 0 ? '0' : '1');
961
	}
962
	return result.toString();
963
}
964
965
static String testStringValueOf(long[] data) {
966
	int length;
967
	StringBuffer result = new StringBuffer((length = data.length) * 2 + 1);
968
	result.append('{');
969
	for (int i = 0; i < length; i++) {
970
		if (i > 0) {
971
			result.append(',');
972
		}
973
		result.append(data[i]);
974
	}
975
	result.append('}');
976
	return result.toString();
977
}
978
}
979
980
/**
981
 * A specific extension of LocalVariableBinding suitable for flow info 
982
 * manipulation at an implementation level.
983
 */
984
class TestLocalVariableBinding extends LocalVariableBinding {
985
	static class TestTypeBinding extends TypeBinding {
986
		public TestTypeBinding() {
987
			tagBits = 0L;
988
		}
989
		public char[] constantPoolName() {
990
			return null;
991
		}
992
		public PackageBinding getPackage() {
993
			return null;
994
		}
995
		public boolean isCompatibleWith(TypeBinding right) {
996
			return false;
997
		}
998
		public char[] qualifiedSourceName() {
999
			return null;
1000
		}
1001
		public char[] sourceName() {
1002
			return null;
1003
		}
1004
		public char[] readableName() {
1005
			return null;
1006
		}
1007
	}
1008
	final static TypeBinding testTypeBinding = new TestTypeBinding();
1009
	final static char [] testName = {'t', 'e', 's', 't'};
1010
	TestLocalVariableBinding(int id) {
1011
		super(testName, testTypeBinding, 0, false);
1012
		this.id = id;
1013
	}
1014
	public Constant constant() {
1015
		return Constant.NotAConstant;
1016
	}
1017
	static final TestLocalVariableBinding 
1018
		local0 = new TestLocalVariableBinding(0),
1019
		local64 = new TestLocalVariableBinding(64),
1020
		local128 = new TestLocalVariableBinding(128);	
1021
}
1022
1023
/**
1024
 * A class meant to augment 
1025
 * @link{org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo} with
1026
 * capabilities in the test domain. It especially provides factories to build
1027
 * fake flow info instances for use in state transitions validation.
1028
 */
1029
/*
1030
 * Moreover, this class defines the implementation of key operations for the
1031
 * benefit of itself and NullInfoRegistryTestHarness. Given the fact that the
1032
 * latter could not extend UnconditionalFlowInfoTestHarness and
1033
 * NullInfoRegistry, the code is factorized into static methods.
1034
 */
1035
class UnconditionalFlowInfoTestHarness extends UnconditionalFlowInfo {
1036
	int testPosition;
1037
	// Interface
1038
/**
1039
 * Return the state represented by this.
1040
 * @return the state represented by this
1041
 */
1042
NullReferenceImplTests.State asState() {
1043
	return asState(this, 0);
1044
}
1045
1046
/**
1047
 * Return the state represented by this for a variable encoded at a given position.
1048
 * @param position - int the position of the considered variable
1049
 * @return the state represented by this for a variable encoded at a given position
1050
 */
1051
NullReferenceImplTests.State asState(int position) {
1052
	return asState(this, position);
1053
}
1054
1055
public FlowInfo copy() {
1056
	UnconditionalFlowInfoTestHarness copy = 
1057
		new UnconditionalFlowInfoTestHarness();
1058
	copy.testPosition = this.testPosition;
1059
	copy(this, copy);
1060
	return copy;
1061
}
1062
1063
public void markAsDefinitelyNonNull(LocalVariableBinding local) {
1064
	grow(local.id + this.maxFieldCount);
1065
	super.markAsDefinitelyNonNull(local);
1066
}
1067
1068
public void markAsDefinitelyNull(LocalVariableBinding local) {
1069
	grow(local.id + this.maxFieldCount);
1070
	super.markAsDefinitelyNull(local);
1071
}
1072
1073
public void markAsDefinitelyUnknown(LocalVariableBinding local) {
1074
	grow(local.id + this.maxFieldCount);
1075
	super.markAsDefinitelyUnknown(local);
1076
}
1077
1078
/**
1079
 * Return a fake unconditional flow info which bit fields represent the given
1080
 * null bits for a local variable of id 0 within a class that would have no
1081
 * field.
1082
 * @param nullBits the bits that must be set, given in the same order as the
1083
 *        nullAssignment* fields in UnconditionalFlowInfo definition; use 0
1084
 *        for a bit that is not set, 1 else
1085
 * @return a fake unconditional flow info which bit fields represent the
1086
 *         null bits given in parameter
1087
 */
1088
public static UnconditionalFlowInfoTestHarness testUnconditionalFlowInfo(
1089
		long [] nullBits) {
1090
	return testUnconditionalFlowInfo(nullBits, 0);
1091
}
1092
1093
/**
1094
 * Return a fake unconditional flow info which bit fields represent the given
1095
 * null bits for a local variable of id position within a class that would have 
1096
 * no field.
1097
 * @param nullBits the bits that must be set, given in the same order as the
1098
 *        nullAssignment* fields in UnconditionalFlowInfo definition; use 0
1099
 *        for a bit that is not set, 1 else
1100
 * @param position the position of the variable within the bit fields; use
1101
 *        various values to test different parts of the bit fields, within
1102
 *        or beyond BitCacheSize
1103
 * @return a fake unconditional flow info which bit fields represent the
1104
 *         null bits given in parameter
1105
 */
1106
public static UnconditionalFlowInfoTestHarness testUnconditionalFlowInfo(
1107
		long [] nullBits, int position) {
1108
 	UnconditionalFlowInfoTestHarness result = 
1109
 		new UnconditionalFlowInfoTestHarness();
1110
	result.testPosition = position;
1111
	init(result, nullBits, position);
1112
	return result;
1113
}
1114
1115
/**
1116
 * Return a fake unconditional flow info which bit fields represent the given
1117
 * state for a local variable of id 0 within a class that would have 
1118
 * no field.
1119
 * @param state - State the desired state for the variable
1120
 * @return a fake unconditional flow info which bit fields represent the
1121
 *         state given in parameter
1122
 */
1123
public static UnconditionalFlowInfoTestHarness testUnconditionalFlowInfo(NullReferenceImplTests.State state) {
1124
	return testUnconditionalFlowInfo(state, 0);
1125
}
1126
1127
/**
1128
 * Return a fake unconditional flow info which bit fields represent the given
1129
 * state for a local variable of id position within a class that would have 
1130
 * no field.
1131
 * @param state - State the desired state for the variable
1132
 * @param position the position of the variable within the bit fields; use
1133
 *        various values to test different parts of the bit fields, within
1134
 *        or beyond BitCacheSize
1135
 * @return a fake unconditional flow info which bit fields represent the
1136
 *         state given in parameter
1137
 */
1138
public static UnconditionalFlowInfoTestHarness testUnconditionalFlowInfo(
1139
		NullReferenceImplTests.State state, int position) {
1140
 	UnconditionalFlowInfoTestHarness result = 
1141
 		new UnconditionalFlowInfoTestHarness();
1142
 	long[] nullBits = state.asLongArray();
1143
	result.testPosition = position;
1144
	init(result, nullBits, position);
1145
	return result;
1146
}
1147
1148
/**
1149
 * Return true iff this flow info can be considered as equal to the one passed
1150
 * in parameter.
1151
 * @param other the flow info to compare to
1152
 * @return true iff this flow info compares equal to other
1153
 */
1154
public boolean testEquals(UnconditionalFlowInfo other) {
1155
	return testEquals(this, other);
1156
}
1157
1158
/**
1159
 * Return true iff this flow info can be considered as equal to the one passed
1160
 * in parameter in respect with a single local variable which id would be
1161
 * position in a class with no field.
1162
 * @param other the flow info to compare to
1163
 * @param position the position of the local to consider
1164
 * @return true iff this flow info compares equal to other for a given local
1165
 */
1166
public boolean testEquals(UnconditionalFlowInfo other, int position) {
1167
	return testEquals(this, other, position);
1168
}
1169
1170
/**
1171
 * Return a string suitable for use as a representation of this flow info
1172
 * within test series.
1173
 * @return a string suitable for use as a representation of this flow info
1174
 */
1175
public String testString() {
1176
	if (this == DEAD_END) {
1177
		return "FlowInfo.DEAD_END"; //$NON-NLS-1$
1178
	}
1179
	return testString(this, this.testPosition);
1180
}
1181
1182
/**
1183
 * Return a string suitable for use as a representation of this flow info
1184
 * within test series.
1185
 * @param position a position to consider instead of this flow info default
1186
 *                 test position
1187
 * @return a string suitable for use as a representation of this flow info
1188
 */
1189
public String testString(int position) {
1190
	return testString(this, position);
1191
}
1192
	
1193
	// Factorized implementation
1194
static NullReferenceImplTests.State asState(UnconditionalFlowInfo zis, int position) {
1195
	if ((zis.tagBits & NULL_FLAG_MASK) == 0) {
1196
		return NullReferenceImplTests.State.start;
1197
	}
1198
	if (position < BitCacheSize) {
1199
		return NullReferenceImplTests.State.fromLongValues(
1200
				(zis.nullBit1 >> position) & 1,
1201
				(zis.nullBit2 >> position) & 1,
1202
				(zis.nullBit3 >> position) & 1,
1203
				(zis.nullBit4 >> position) & 1,
1204
				0,
1205
				0);
1206
	} 
1207
 	else {
1208
		int vectorIndex = (position / BitCacheSize) - 1;
1209
        position %= BitCacheSize;
1210
        if (vectorIndex >= zis.extra[2].length) {
1211
        	return NullReferenceImplTests.State.start;
1212
        }
1213
		return NullReferenceImplTests.State.fromLongValues(
1214
				(zis.extra[2][vectorIndex] >> position) & 1,
1215
				(zis.extra[3][vectorIndex] >> position) & 1,
1216
				(zis.extra[4][vectorIndex] >> position) & 1,
1217
				(zis.extra[5][vectorIndex] >> position) & 1,
1218
				0 //(zis.extra[6][vectorIndex] >> position) & 1,
1219
				, 0 //(zis.extra[7][vectorIndex] >> position) & 1
1220
				);
1221
	}
1222
}
1223
1224
static void copy(UnconditionalFlowInfo source, UnconditionalFlowInfo target) {
1225
	target.definiteInits = source.definiteInits;
1226
	target.potentialInits = source.potentialInits;
1227
	boolean hasNullInfo = (source.tagBits & NULL_FLAG_MASK) != 0;
1228
	if (hasNullInfo) { 
1229
		target.nullBit1 = source.nullBit1;
1230
		target.nullBit2 = source.nullBit2;
1231
		target.nullBit3 = source.nullBit3;
1232
		target.nullBit4 = source.nullBit4;
1233
//		target.nullBit5 = source.nullBit5;
1234
//		target.nullBit6 = source.nullBit6;
1235
	}
1236
	target.tagBits = source.tagBits;
1237
	target.maxFieldCount = source.maxFieldCount;
1238
	if (source.extra != null) {
1239
		int length;
1240
        target.extra = new long[extraLength][];
1241
		System.arraycopy(source.extra[0], 0, 
1242
			(target.extra[0] = new long[length = source.extra[0].length]), 0, length);
1243
		System.arraycopy(source.extra[1], 0, 
1244
			(target.extra[1] = new long[length]), 0, length);
1245
		if (hasNullInfo) {
1246
            for (int j = 0; j < extraLength; j++) {
1247
			    System.arraycopy(source.extra[j], 0, 
1248
				    (target.extra[j] = new long[length]), 0, length);
1249
            }
1250
		}
1251
		else {
1252
            for (int j = 0; j < extraLength; j++) {
1253
			    target.extra[j] = new long[length];
1254
            }
1255
		}
1256
	}
1257
}
1258
1259
public void grow(int position) {
1260
	int vectorIndex = ((position) / BitCacheSize) - 1;
1261
	int length = vectorIndex + 1, oldLength;
1262
	if (this.extra == null) {
1263
		this.extra = new long[extraLength][];
1264
		for (int j = 0; j < extraLength; j++) {
1265
			this.extra[j] = new long[length];
1266
		}
1267
	} else if (length > (oldLength = this.extra[2].length)) {
1268
		for (int j = 0; j < extraLength; j++) {
1269
			System.arraycopy(this.extra[j], 0, 
1270
				this.extra[j] = new long[length], 0, oldLength);
1271
		}
1272
	}
1273
}
1274
1275
static void init(UnconditionalFlowInfo zis, long [] nullBits, int position) {
1276
	if (position < BitCacheSize) {
1277
		zis.nullBit1 = nullBits[0] << position;
1278
		zis.nullBit2 = nullBits[1] << position;
1279
		zis.nullBit3 = nullBits[2] << position;
1280
		zis.nullBit4 = nullBits[3] << position;
1281
//		zis.nullBit5 = nullBits[4] << position;
1282
//		zis.nullBit6 = nullBits[5] << position;
1283
	}
1284
 	else {
1285
		int vectorIndex = (position / BitCacheSize) - 1,
1286
			length = vectorIndex + 1;
1287
        position %= BitCacheSize;
1288
        zis.extra = new long[extraLength][];
1289
		zis.extra[0] = new long[length];
1290
		zis.extra[1] = new long[length];
1291
        for (int j = 2; j < extraLength; j++) {
1292
		    zis.extra[j] = new long[length];
1293
		    zis.extra[j][vectorIndex] = nullBits[j - 2] << position;
1294
        }
1295
	}
1296
	if (nullBits[0] != 0 || nullBits[1] != 0
1297
	        || nullBits[2] != 0 || nullBits[3] != 0
1298
	        || nullBits[4] != 0 || nullBits[5] != 0) { 
1299
		// cascade better than nullBits[0] | nullBits[1] | nullBits[2] | nullBits[3]
1300
		// by 10%+
1301
		// TODO (maxime) run stats to determine which is the better order
1302
		zis.tagBits |= NULL_FLAG_MASK;
1303
	}
1304
	zis.maxFieldCount = 0;
1305
}
1306
1307
static boolean testEquals(UnconditionalFlowInfo zis, UnconditionalFlowInfo other) {
1308
	if (zis.tagBits != other.tagBits) {
1309
		return false;
1310
	}
1311
	if (zis.nullBit1 != other.nullBit1 
1312
			|| zis.nullBit2 != other.nullBit2 
1313
			|| zis.nullBit3 != other.nullBit3 
1314
			|| zis.nullBit4 != other.nullBit4
1315
			/* || zis.nullBit5 != other.nullBit5 
1316
			|| zis.nullBit6 != other.nullBit6 */) {
1317
		return false;
1318
	}
1319
	int left = zis.extra == null ? 0 : zis.extra[2].length,
1320
			right = other.extra == null ? 0 : other.extra[2].length,
1321
			both = 0, i;
1322
	if (left > right) {
1323
		both = right;
1324
	}
1325
	else {
1326
		both = left;
1327
	}
1328
	for (i = 0; i < both ; i++) {
1329
		for (int j = 2; j < extraLength; j++) { 
1330
			if (zis.extra[j][i] != 
1331
					other.extra[j][i]) {
1332
				return false;
1333
			}
1334
		}
1335
	}
1336
	for (; i < left; i++) {
1337
		for (int j = 2; j < extraLength; j++) { 
1338
			if (zis.extra[j][i] != 0) {
1339
				return false;
1340
			}
1341
		}
1342
	}
1343
	for (; i < right; i++) {
1344
		for (int j = 2; j < extraLength; j++) { 
1345
			if (other.extra[j][i] != 0) {
1346
				return false;
1347
			}
1348
		}
1349
	}
1350
	return true;
1351
}
1352
1353
static boolean testEquals(UnconditionalFlowInfo zis, UnconditionalFlowInfo other,
1354
		int position) {
1355
	int vectorIndex = position / BitCacheSize - 1;
1356
	if ((zis.tagBits & other.tagBits & NULL_FLAG_MASK) == 0) {
1357
		return true;
1358
	}
1359
	long mask;
1360
	if (vectorIndex < 0) {
1361
		return ((zis.nullBit1 & (mask = (1L << position))) ^
1362
					(other.nullBit1 & mask)) == 0 &&
1363
				((zis.nullBit2 & mask) ^
1364
					(other.nullBit2 & mask)) == 0 &&
1365
				((zis.nullBit3 & mask) ^
1366
					(other.nullBit3 & mask)) == 0 &&
1367
				((zis.nullBit4 & mask) ^
1368
					(other.nullBit4 & mask)) == 0 /* &&
1369
				((zis.nullBit5 & mask) ^
1370
					(other.nullBit5 & mask)) == 0 &&
1371
				((zis.nullBit6 & mask) ^
1372
					(other.nullBit6 & mask)) == 0 */;
1373
	}
1374
	else {
1375
		int left = zis.extra == null ?
1376
				0 :
1377
				zis.extra[0].length;
1378
		int right = other.extra == null ?
1379
				0 :
1380
				other.extra[0].length;
1381
		int both = left < right ? left : right;
1382
		if (vectorIndex < both) {
1383
			mask = (1L << (position % BitCacheSize));
1384
			for (int j = 2; j < extraLength; j++) {
1385
				if (((zis.extra[j][vectorIndex] & mask) 
1386
						^ (other.extra[j][vectorIndex] & mask)) != 0) {
1387
					return false;
1388
				}
1389
			}
1390
			return true;
1391
		}
1392
		if (vectorIndex < left) {
1393
			return ((zis.extra[2][vectorIndex] |
1394
					zis.extra[3][vectorIndex] |
1395
					zis.extra[4][vectorIndex] |
1396
					zis.extra[5][vectorIndex] |
1397
					zis.extra[6][vectorIndex] |
1398
					zis.extra[7][vectorIndex]) &
1399
					(1L << (position % BitCacheSize))) == 0;
1400
		}
1401
		return ((other.extra[2][vectorIndex] |
1402
				other.extra[3][vectorIndex] |
1403
				other.extra[4][vectorIndex] |
1404
				other.extra[5][vectorIndex] |
1405
				other.extra[6][vectorIndex] |
1406
				other.extra[7][vectorIndex]) &
1407
				(1L << (position % BitCacheSize))) == 0;
1408
	}
1409
}
1410
1411
static String testString(UnconditionalFlowInfo zis, int position) {
1412
	if (zis == DEAD_END) {
1413
		return "FlowInfo.DEAD_END"; //$NON-NLS-1$
1414
	}
1415
	if (position < BitCacheSize) {
1416
		return "{" + (zis.nullBit1 >> position) //$NON-NLS-1$
1417
					+ "," + (zis.nullBit2 >> position) //$NON-NLS-1$
1418
					+ "," + (zis.nullBit3 >> position) //$NON-NLS-1$
1419
					+ "," + (zis.nullBit4 >> position) //$NON-NLS-1$
1420
//					+ "," + (zis.nullBit5 >> position) //$NON-NLS-1$
1421
//					+ "," + (zis.nullBit6 >> position) //$NON-NLS-1$
1422
					+ "}"; //$NON-NLS-1$
1423
	}
1424
	else {
1425
		int vectorIndex = position / BitCacheSize - 1,
1426
			shift = position % BitCacheSize;
1427
			return "{" + (zis.extra[2][vectorIndex] //$NON-NLS-1$
1428
			               >> shift) 
1429
						+ "," + (zis.extra[3][vectorIndex] //$NON-NLS-1$
1430
						   >> shift)
1431
						+ "," + (zis.extra[4][vectorIndex] //$NON-NLS-1$
1432
						   >> shift)
1433
						+ "," + (zis.extra[5][vectorIndex] //$NON-NLS-1$
1434
						   >> shift)
1435
//						+ "," + (zis.extra[6][vectorIndex] //$NON-NLS-1$
1436
//						   >> shift)
1437
//						+ "," + (zis.extra[7][vectorIndex] //$NON-NLS-1$
1438
//						   >> shift)
1439
						+ "}"; //$NON-NLS-1$
1440
	}
1441
}
1442
}
1443
/**
1444
 * A class meant to augment 
1445
 * @link{org.eclipse.jdt.internal.compiler.flow.NullInfoRegistry} with
1446
 * capabilities in the test domain. It especially provides factories to build
1447
 * fake flow info instances for use in state transitions validation.
1448
 */
1449
/*
1450
 * The reason why UnconditionalFlowInfoTestHarness and this class were 
1451
 * separated is that NullInfoRegistry redefines part of the markAs* methods,
1452
 * in effect preventing a harness extending NullInfoRegistry to access 
1453
 * UnconditionalFlowInfo implementations of the said methods.
1454
 */
1455
class NullInfoRegistryTestHarness extends NullInfoRegistry {
1456
	private int testPosition;
1457
1458
private NullInfoRegistryTestHarness() {
1459
	super(FlowInfo.DEAD_END);
1460
}
1461
	
1462
	// Interface
1463
/**
1464
 * Return the state represented by this.
1465
 * @return the state represented by this
1466
 */
1467
NullReferenceImplTests.State asState() {
1468
	return UnconditionalFlowInfoTestHarness.asState(this, 0);
1469
}
1470
1471
/**
1472
 * Return the state represented by this for a variable encoded at a given position.
1473
 * @param position - int the position of the considered variable
1474
 * @return the state represented by this for a variable encoded at a given position
1475
 */
1476
NullReferenceImplTests.State asState(int position) {
1477
	return UnconditionalFlowInfoTestHarness.asState(this, position);
1478
}
1479
1480
public FlowInfo copy() {
1481
	NullInfoRegistryTestHarness copy = 
1482
		new NullInfoRegistryTestHarness();
1483
	copy.testPosition = this.testPosition;
1484
	UnconditionalFlowInfoTestHarness.copy(this, copy);
1485
	return copy;
1486
}
1487
1488
/**
1489
 * Return a fake null info registry derived from an unconditional flow
1490
 * info.
1491
 * @param upstream - UnconditionalFlowInfoTestHarness the upstream flow info
1492
 * @return a fake null info registry derived from upstream
1493
 */
1494
public static NullInfoRegistryTestHarness testNullInfoRegistry(
1495
		UnconditionalFlowInfoTestHarness upstream) {
1496
	NullInfoRegistry nullInfoRegistry = new NullInfoRegistry(upstream);
1497
 	NullInfoRegistryTestHarness result = 
1498
 		new NullInfoRegistryTestHarness();
1499
	result.testPosition = upstream.testPosition;
1500
	if (result.testPosition < BitCacheSize) {
1501
		result.nullBit1 = nullInfoRegistry.nullBit1;
1502
		result.nullBit2 = nullInfoRegistry.nullBit2;
1503
		result.nullBit3 = nullInfoRegistry.nullBit3;
1504
		result.nullBit4 = nullInfoRegistry.nullBit4;
1505
//		result.nullBit5 = nullInfoRegistry.nullBit5;
1506
//		result.nullBit6 = nullInfoRegistry.nullBit6;
1507
	} 
1508
 	else if ((nullInfoRegistry.tagBits & NULL_FLAG_MASK) != 0){
1509
		int vectorIndex = (result.testPosition / BitCacheSize) - 1,
1510
			length = vectorIndex + 1;
1511
        result.extra = new long[extraLength][];
1512
		result.extra[0] = new long[length];
1513
		result.extra[1] = new long[length];
1514
        for (int j = 2; j < extraLength; j++) {
1515
		    result.extra[j] = new long[length];
1516
		    result.extra[j][vectorIndex] = nullInfoRegistry.extra[j][vectorIndex];
1517
        }
1518
	}
1519
	if ((nullInfoRegistry.tagBits & NULL_FLAG_MASK) != 0) { 
1520
		result.tagBits |= NULL_FLAG_MASK;
1521
	}
1522
	result.maxFieldCount = 0;
1523
	return result;
1524
}
1525
1526
/**
1527
 * Return true iff this flow info can be considered as equal to the one passed
1528
 * in parameter.
1529
 * @param other the flow info to compare to
1530
 * @return true iff this flow info compares equal to other
1531
 */
1532
public boolean testEquals(UnconditionalFlowInfo other) {
1533
	return UnconditionalFlowInfoTestHarness.testEquals(this, other);
1534
}
1535
1536
/**
1537
 * Return true iff this flow info can be considered as equal to the one passed
1538
 * in parameter in respect with a single local variable which id would be
1539
 * position in a class with no field.
1540
 * @param other the flow info to compare to
1541
 * @param position the position of the local to consider
1542
 * @return true iff this flow info compares equal to other for a given local
1543
 */
1544
public boolean testEquals(UnconditionalFlowInfo other, int position) {
1545
	return UnconditionalFlowInfoTestHarness.testEquals(this, other, position);
1546
}
1547
1548
/**
1549
 * Return a string suitable for use as a representation of this flow info
1550
 * within test series.
1551
 * @return a string suitable for use as a representation of this flow info
1552
 */
1553
public String testString() {
1554
	if (this == DEAD_END) {
1555
		return "FlowInfo.DEAD_END"; //$NON-NLS-1$
1556
	}
1557
	return UnconditionalFlowInfoTestHarness.testString(this, this.testPosition);
1558
}
1559
1560
/**
1561
 * Return a string suitable for use as a representation of this flow info
1562
 * within test series.
1563
 * @param position a position to consider instead of this flow info default
1564
 *                 test position
1565
 * @return a string suitable for use as a representation of this flow info
1566
 */
1567
public String testString(int position) {
1568
	return UnconditionalFlowInfoTestHarness.testString(this, position);
1569
}
1570
}
1571
1572
interface CodeAnalysis {
1573
	public static final String
1574
		definitionStartMarker = "DEFINITION START",
1575
		definitionEndMarker = "DEFINITION END",
1576
		initializerStartMarker = "INITIALIZER START",
1577
		initializerEndMarker = "INITIALIZER END";
1578
}
1579
class TransitiveClosureHolder {
1580
static class Element {
1581
	NullReferenceImplTests.State value;
1582
	boolean alreadyKnown;
1583
	Element(NullReferenceImplTests.State value) {
1584
		if (value == null) {
1585
			throw new IllegalArgumentException("not a valid element");
1586
		}
1587
		this.value = value;
1588
	}
1589
}
1590
Map elements = new TreeMap();
1591
public TransitiveClosureHolder() {
1592
	Element start = new Element(NullReferenceImplTests.State.start);
1593
	this.elements.put(start.value, start);
1594
}
1595
void add(NullReferenceImplTests.State value) {
1596
	if (value == null) {
1597
		throw new IllegalArgumentException("not a valid state");
1598
	}
1599
	if (! this.elements.containsKey(value)) {
1600
		this.elements.put(value, new Element(value));
1601
	}
1602
}
1603
void add(NullReferenceImplTests.State[] values) {
1604
	if (values == null) {
1605
		throw new IllegalArgumentException("not a valid states set");
1606
	}
1607
	for (int i = 0, length = values.length; i < length; i++) {
1608
		add(values[i]);
1609
	}
1610
}
1611
NullReferenceImplTests.State[] asArray() {
1612
	int length;
1613
	NullReferenceImplTests.State[] result = new NullReferenceImplTests.State[length = this.elements.size()];
1614
	Iterator elementsIterator = this.elements.keySet().iterator();
1615
	for (int j = 0; j < length; j++) {
1616
		result[j] = (NullReferenceImplTests.State) elementsIterator.next();
1617
	}
1618
	return result;
1619
}
1620
NullReferenceImplTests.State[] notAlreadyKnowns() {
1621
	List resultAccumulator = new ArrayList(this.elements.size());
1622
	Iterator i = this.elements.values().iterator();
1623
	Element current;
1624
	while (i.hasNext()) {
1625
		if (! (current = (Element) i.next()).alreadyKnown) {
1626
			resultAccumulator.add(current.value);
1627
		}
1628
	}
1629
	int length;
1630
	NullReferenceImplTests.State[] result = new NullReferenceImplTests.State[length = resultAccumulator.size()];
1631
	for (int j = 0; j < length; j++) {
1632
		result[j] = (NullReferenceImplTests.State) resultAccumulator.get(j);
1633
	}
1634
	return result;
1635
}
1636
void markAllAsAlreadyKnown() {
1637
	Iterator i = this.elements.values().iterator();
1638
	while (i.hasNext()) {
1639
		((Element) i.next()).alreadyKnown = true;
1640
	}
1641
}
1642
public String toString() {
1643
	StringBuffer output = new StringBuffer();
1644
	output.append("Transitive closure:\n");
1645
	SortedMap sorted = new TreeMap(this.elements);
1646
	Iterator i = sorted.keySet().iterator();
1647
	while (i.hasNext()) {
1648
		output.append(i.next().toString());
1649
		output.append('\n');
1650
	}
1651
	return output.toString();
1652
}
1653
}
1654
1655
// PREMATURE segregate pure tooling into a separate project, keep tests only here
1656
/**
1657
 * The Generator class is meant to generate the tabular data needed by the
1658
 * flow information implementation level tests. While the tests should ensure
1659
 * non regression by leveraging their initialization tables only, any change 
1660
 * into the flow information logic or encoding is due to yield considerable
1661
 * changes into the literal values sets of the initializers themselves. 
1662
 * Tooling the production of those literals buys us flexibility.
1663
 * {@link #printHelp printHelp} for details.
1664
 */
1665
class Generator {
1666
static NullReferenceImplTests.State[] computeTransitiveClosure() {
1667
	TransitiveClosureHolder transitiveClosure = new TransitiveClosureHolder();
1668
	NullReferenceImplTests.State[] unknowns;
1669
	unknowns = transitiveClosure.notAlreadyKnowns();
1670
	while (unknowns.length != 0) {
1671
		transitiveClosure.markAllAsAlreadyKnown();
1672
		for (int i = 0, length = NullReferenceImplTransformations.transformations.length;	i < length; i ++) {
1673
			transitiveClosure.add(
1674
				NullReferenceImplTransformations.transformations[i].
1675
					computeOutputs(transitiveClosure.asArray()));
1676
		}
1677
		unknowns = transitiveClosure.notAlreadyKnowns();
1678
	} 
1679
	return transitiveClosure.asArray();
1680
}
1681
public static void main(String[] args) {
1682
	if (args.length == 0) {
1683
		printHelp(false);
1684
		System.exit(1);
1685
	}
1686
	switch (args.length) {
1687
		case 1:
1688
			if (args[0].equals("--help")) {
1689
				printHelp(true);
1690
				System.exit(0);
1691
			}
1692
			else {
1693
				printHelp(false);
1694
				System.exit(1);
1695
			}
1696
		case 2:
1697
			if (args[0].equals("--printTruthTables")) {
1698
				File outputDir = new File(args[1]);
1699
				if (outputDir.isDirectory()) {
1700
					for (int i = 0, length = NullReferenceImplTransformations.transformations.length; i < length; i++) {
1701
						NullReferenceImplTransformations.transformations[i].printTruthTables(outputDir);
1702
					}
1703
				}
1704
				else {
1705
					// PREMATURE error handling
1706
				}
1707
				System.exit(0);
1708
			}
1709
			else {
1710
				printHelp(false);
1711
				System.exit(1);
1712
			}
1713
		case 3:
1714
			if (args[0].equals("--reinitializeFromComputedValues")) {
1715
				reinitializeFromComputedValues(args[1], args[2]);
1716
				System.out.println("Generator generated new file into " + args[2]);
1717
				System.exit(0);
1718
			}
1719
		case 5:
1720
			if (args[0].equals("--reinitializeFromComments")) {
1721
				reinitializeFromComments(args[1], args[2], args[3], args[4]);
1722
				System.out.println("Generator generated new files into " + args[2]
1723
					+ " and " + args[4]);
1724
				System.exit(0);
1725
			}
1726
		default:
1727
			printHelp(false);
1728
			System.exit(1);
1729
	}
1730
}
1731
	
1732
private static void reinitializeFromComments(
1733
		String statesSource, String statesTarget,
1734
		String transformationsSource, String transformationsTarget) {
1735
	if (statesSource.equals(transformationsSource) ||
1736
			statesTarget.equals(transformationsTarget)) {
1737
		throw new RuntimeException();
1738
	}
1739
	try {
1740
		BufferedReader in;
1741
		BufferedWriter out;
1742
		NullReferenceImplTests.State.reinitializeFromComment(
1743
			in = new BufferedReader(
1744
				new FileReader(statesSource)), 
1745
			out = new BufferedWriter(new FileWriter(statesTarget)));
1746
		in.close();
1747
		out.close();
1748
		File[] tempFiles = new File[2];
1749
		tempFiles[0] = File.createTempFile("generator", "java");
1750
		tempFiles[1] = File.createTempFile("generator", "java");
1751
		NullReferenceImplTransformations.transformations[0].reinitializeFromComments(
1752
			in = new BufferedReader(
1753
				new FileReader(transformationsSource)), 
1754
			out = new BufferedWriter(new FileWriter(tempFiles[0])));
1755
		in.close();
1756
		out.close();
1757
		int i, length;
1758
		for (i = 1, length = NullReferenceImplTransformations.transformations.length - 1; i < length; i++) {
1759
			NullReferenceImplTransformations.transformations[i].reinitializeFromComments(
1760
				in = new BufferedReader(
1761
					new FileReader(tempFiles[(i + 1) % 2])), 
1762
				out = new BufferedWriter(new FileWriter(tempFiles[i % 2])));
1763
			in.close();
1764
			out.close();
1765
		}
1766
		NullReferenceImplTransformations.transformations[i].reinitializeFromComments(
1767
			in = new BufferedReader(
1768
				new FileReader(tempFiles[(i + 1) % 2])), 
1769
			out = new BufferedWriter(new FileWriter(transformationsTarget)));
1770
		in.close();
1771
		out.close();
1772
	} catch (Throwable t) {
1773
		System.err.println("Generator error:");
1774
		t.printStackTrace(System.err);
1775
		System.exit(2);
1776
	}
1777
}
1778
1779
private static void reinitializeFromComputedValues(String source, String target) {
1780
	for (int i = 0, length = NullReferenceImplTransformations.transformations.length;
1781
			i < length; i++) {
1782
		NullReferenceImplTransformations.transformations[i].hydrate();
1783
	}
1784
	NullReferenceImplTests.State[] transitiveClosure = computeTransitiveClosure();
1785
	try {
1786
		BufferedReader in;
1787
		BufferedWriter out;
1788
		File[] tempFiles = new File[2];
1789
		tempFiles[0] = File.createTempFile("generator", "java");
1790
		tempFiles[1] = File.createTempFile("generator", "java");
1791
		NullReferenceImplTransformations.transformations[0].reinitializeFromComputedValues(
1792
			in = new BufferedReader(
1793
				new FileReader(source)), 
1794
			out = new BufferedWriter(new FileWriter(tempFiles[0])),
1795
			transitiveClosure);
1796
		in.close();
1797
		out.close();
1798
		int i, length;
1799
		for (i = 1, length = NullReferenceImplTransformations.transformations.length - 1; i < length; i++) {
1800
			NullReferenceImplTransformations.transformations[i].reinitializeFromComputedValues(
1801
				in = new BufferedReader(
1802
					new FileReader(tempFiles[(i + 1) % 2])), 
1803
				out = new BufferedWriter(new FileWriter(tempFiles[i % 2])),
1804
				transitiveClosure);
1805
			in.close();
1806
			out.close();
1807
		}
1808
		NullReferenceImplTransformations.transformations[i].reinitializeFromComputedValues(
1809
			in = new BufferedReader(
1810
				new FileReader(tempFiles[(i + 1) % 2])), 
1811
			out = new BufferedWriter(new FileWriter(target)),
1812
			transitiveClosure);
1813
		in.close();
1814
		out.close();
1815
	} catch (Throwable t) {
1816
		System.err.println("Generator error:");
1817
		t.printStackTrace(System.err);
1818
		System.exit(2);
1819
	}
1820
}
1821
1822
private static void printHelp(boolean longText) {
1823
	if (longText) {
1824
		System.out.println(
1825
			"Generator use cases\n" +
1826
			" - when a brand new logic is experimented for the transitions, the best\n" +
1827
			"   way to go is to write explicit (inefficient) transformation code within\n" +
1828
			"   UnconditionalFlowInfo, then generate the literal initializers from\n" +
1829
			"   there; use the command\n" +
1830
			"   --reinitializeFromComputedValues <source file> <target file>\n" +
1831
			"   to this effect; in case of inconsistencies or errors, messages are\n" +
1832
			"   printed to the error output stream and the result should be considered as non reliable;\n" +
1833
			" - when only a few changes are made to state names or a specific\n" +
1834
			"   transitions, it should be possible to get the test initializers fixed\n" +
1835
			"   before UnconditionalFlowInfo implements those changes; use the command\n" +
1836
	        "   --reinitializeFromComments <states source file> <states target file> <transformations source file> <transformations target file>\n" +
1837
	        "   to this effect;\n" +
1838
	        " - the same command can be used when, while the semantics of the system\n" +
1839
	        "   are unchanged, the encoding is modified; it should then produce the\n" +
1840
	        "   initializers according to the new encoding, as defined by the comment\n" +
1841
	        "   for State.states, and the transformations as defined by their\n" +
1842
	        "   respective comment;\n" +
1843
	        " - when a given encoding is retained, its optimization may leverage truth\n" +
1844
	        "   tables; use the --printTruthTables command to this effect.\n" +
1845
	        "   \n\n");
1846
		printHelp(false);
1847
	}
1848
	else {
1849
		System.out.println(
1850
	        "Usage:\n" +
1851
	        "Generator --help\n" +
1852
	        "  prints a more detailed help message\n" +
1853
	        "Generator --printTruthTables\n" +
1854
	        "  prints the truth tables of the transformations\n" +
1855
	        "Generator --reinitializeFromComments <source file> <target file>\n" +
1856
	        "  generates into target file a copy of source file into which\n" +
1857
	        "  transformations initializers have been reset from their definitions\n" +
1858
			"Generator --reinitializeFromComputedValues <source file> <target file>\n"  +
1859
	        "  generates into target file a copy of source file into which\n" +
1860
	        "  transformations definitions and initializers have been reset\n" +
1861
	        "  according to the behavior of the current UnconditionalFlowInfo\n"
1862
	        );
1863
	}
1864
}
1865
}
1866

Return to bug 127570