### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java,v retrieving revision 1.55 diff -u -r1.55 UnconditionalFlowInfo.java --- compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java 19 Apr 2006 12:26:59 -0000 1.55 +++ compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java 21 Apr 2006 14:13:20 -0000 @@ -42,27 +42,36 @@ // never release with the coverageTestFlag set to true public static int coverageTestId; + // assignment bits - first segment public long definiteInits; public long potentialInits; - public long nullAssignmentStatusBit1; - public long nullAssignmentStatusBit2; - // 0 0 is potential (bit 1 is leftmost here) - // 1 0 is assigned - // 0 1 is protected null (aka if (o == null) { // here o protected null...) - // 1 1 is protected non null - public long nullAssignmentValueBit1; - public long nullAssignmentValueBit2; - // information only relevant for potential and assigned - // 0 0 is start -- nothing known at all - // 0 1 is assigned non null or potential anything but null - // 1 0 is assigned null or potential null - // 1 1 is potential null and potential anything but null or definite unknown - // consider reintroducing the difference between potential non null and potential - // unknown; if this is done, rename to nullAssignmentBit[1-4] since the semantics - // would be ever less clear - // went public in order to grant access to tests; do not like it... - + // null bits - first segment + public long + nullBit1, + nullBit2, + nullBit3, + nullBit4; +/* + nullBit1 + nullBit2... + 0000 start + 0001 pot. unknown + 0010 pot. non null + 0011 pot. nn & pot. un + 0100 pot. null + 0101 pot. n & pot. un + 0110 pot. n & pot. nn + 1001 def. unknown + 1010 def. non null + 1011 pot. nn & prot. nn + 1100 def. null + 1101 pot. n & prot. n + 1110 prot. null + 1111 prot. non null + */ + + // extra segments public static final int extraLength = 6; public long extra[][]; // extra bit fields for larger numbers of fields/variables @@ -71,7 +80,7 @@ // arrays which have the same size public int maxFieldCount; // limit between fields and locals - + // Constants public static final int BitCacheSize = 64; // 64 bits in a long. @@ -87,50 +96,54 @@ // union of potentially set ones this.potentialInits |= otherInits.potentialInits; // combine null information - // note: we may have both forms of protection (null and non null) - // coming with otherInits, because of loops - boolean considerNulls = (otherInits.tagBits & NULL_FLAG_MASK) != 0; - long a1, na1, a2, na2, a3, a4, na4, b1, b2, nb2, b3, nb3, b4, nb4; - if (considerNulls) { - if ((this.tagBits & NULL_FLAG_MASK) == 0) { - this.nullAssignmentStatusBit1 = otherInits.nullAssignmentStatusBit1; - this.nullAssignmentStatusBit2 = otherInits.nullAssignmentStatusBit2; - this.nullAssignmentValueBit1 = otherInits.nullAssignmentValueBit1; - this.nullAssignmentValueBit2 = otherInits.nullAssignmentValueBit2; + boolean thisHadNulls = (this.tagBits & NULL_FLAG_MASK) != 0, + otherHasNulls = (otherInits.tagBits & NULL_FLAG_MASK) != 0; + long + a1, a2, a3, a4, + na1, na2, na3, na4, + b1, b2, b3, b4, + nb1, nb2, nb3, nb4; + if (otherHasNulls) { + if (!thisHadNulls) { + this.nullBit1 = otherInits.nullBit1; + this.nullBit2 = otherInits.nullBit2; + this.nullBit3 = otherInits.nullBit3; + this.nullBit4 = otherInits.nullBit4; if (coverageTestFlag && coverageTestId == 1) { - this.nullAssignmentValueBit2 = ~0; + this.nullBit4 = ~0; } } else { - this.nullAssignmentStatusBit1 = - (b1 = otherInits.nullAssignmentStatusBit1) - | ((a1 = this.nullAssignmentStatusBit1) - & (((nb2 = ~(b2 = otherInits.nullAssignmentStatusBit2)) - & (nb3 = ~(b3 = otherInits.nullAssignmentValueBit1)) - & ((nb4 = ~(b4 = otherInits.nullAssignmentValueBit2)) - | ((a2 = this.nullAssignmentStatusBit2) - ^ (a4 = this.nullAssignmentValueBit2)))) - | nb4 & (na2 = ~a2) & (na4 = ~a4))); - this.nullAssignmentStatusBit2 = - (b1 & b2) - | (~b1 - & ((((na1 = ~a1) | a4) & b2) - | (a2 - & (b2 - | (a1 & (na4 = ~a4) & nb2 & nb3) - | ((~(a3 = this.nullAssignmentValueBit1) & nb3) - | (na1 & na4)) - & nb4)))); - this.nullAssignmentValueBit1 = - nb2 & b3 | - ~b1 & ((a1 & na2 & na4 | na1 & a3) & (nb2 | nb4) | - a1 & na2 & a3 & nb2 | - (a1 | a2 | na4) & b3); - this.nullAssignmentValueBit2 = - b4 | - a4 & (nb2 & nb3 | ~(b1 ^ b2)); + this.nullBit1 = (b1 = otherInits.nullBit1) + | (a1 = this.nullBit1) & ((a3 = this.nullBit3) + & (a4 = this.nullBit4) & (nb2 = ~(b2 = otherInits.nullBit2)) + & (nb4 = ~(b4 = otherInits.nullBit4)) + | ((na4 = ~a4) | (na3 = ~a3)) + & ((na2 = ~(a2 = this.nullBit2)) & nb2 + | a2 & (nb3 = ~(b3 = otherInits.nullBit3)) & nb4)); + this.nullBit2 = b2 & (nb4 | nb3) + | na3 & na4 & b2 + | a2 & (nb3 & nb4 + | (nb1 = ~b1) & (na3 | (na1 = ~a1)) + | a1 & b2); + this.nullBit3 = b3 & (nb1 & (b2 | a2 | na1) + | b1 & (b4 | nb2 | a1 & a3) + | na1 & na2 & na4) + | a3 & nb2 & nb4 + | nb1 & ((na2 & a4 | na1) & a3 + | a1 & na2 & na4 & b2); + this.nullBit4 = nb1 & (a4 & (na3 & nb3 | (a3 | na2) & nb2) + | a1 & (a3 & nb2 & b4 + | a2 & b2 & (b4 | a3 & na4 & nb3))) + | b1 & (a3 & a4 & b4 + | na2 & na4 & nb3 & b4 + | a2 & ((b3 | a4) & b4 + | na3 & a4 & b2 & b3) + | na1 & (b4 | (a4 | a2) & b2 & b3)) + | (na1 & (na3 & nb3 | na2 & nb2) + | a1 & (nb2 & nb3 | a2 & a3)) & b4; if (coverageTestFlag && coverageTestId == 2) { - this.nullAssignmentValueBit2 = ~0; + this.nullBit4 = ~0; } } this.tagBits |= NULL_FLAG_MASK; // in all cases - avoid forgetting extras @@ -144,9 +157,6 @@ int length, otherLength; if ((length = this.extra[0].length) < (otherLength = otherInits.extra[0].length)) { - if (coverageTestFlag && coverageTestId == 3) { - throw new AssertionFailedException("COVERAGE 3"); //$NON-NLS-1$ - } // current storage is shorter -> grow current for (int j = 0; j < extraLength; j++) { System.arraycopy(this.extra[j], 0, @@ -154,16 +164,18 @@ } mergeLimit = length; copyLimit = otherLength; + if (coverageTestFlag && coverageTestId == 3) { + throw new AssertionFailedException("COVERAGE 3"); //$NON-NLS-1$ + } } else { + // current storage is longer + mergeLimit = otherLength; if (coverageTestFlag && coverageTestId == 4) { throw new AssertionFailedException("COVERAGE 4"); //$NON-NLS-1$ } - // current storage is longer - mergeLimit = otherLength; } } - } - else if (otherInits.extra != null) { + } else if (otherInits.extra != null) { // no storage here, but other has extra storage. // shortcut regular copy because array copy is better int otherLength; @@ -173,7 +185,7 @@ otherInits.extra[0].length]), 0, otherLength); System.arraycopy(otherInits.extra[1], 0, (this.extra[1] = new long[otherLength]), 0, otherLength); - if (considerNulls) { + if (otherHasNulls) { for (int j = 2; j < extraLength; j++) { System.arraycopy(otherInits.extra[j], 0, (this.extra[j] = new long[otherLength]), 0, otherLength); @@ -187,66 +199,70 @@ this.extra[j] = new long[otherLength]; } if (coverageTestFlag && coverageTestId == 6) { - this.extra[5][otherLength - 1] = ~0; + throw new AssertionFailedException("COVERAGE 6"); //$NON-NLS-1$ } } } - int i = 0; - for (; i < mergeLimit; i++) { + int i; + // manage definite assignment info + for (i = 0; i < mergeLimit; i++) { this.extra[0][i] |= otherInits.extra[0][i]; this.extra[1][i] |= otherInits.extra[1][i]; - if (considerNulls) { // could consider pushing the test outside the loop - if (this.extra[2][i] == 0 && - this.extra[3][i] == 0 && - this.extra[4][i] == 0 && - this.extra[5][i] == 0) { - for (int j = 2; j < extraLength; j++) { - this.extra[j][i] = otherInits.extra[j][i]; - } - if (coverageTestFlag && coverageTestId == 7) { - this.extra[5][i] = ~0; - } - } - else { - this.extra[2][i] = - (b1 = otherInits.extra[2][i]) | - (a1 = this.extra[2][i]) & - ((nb2 = ~(b2 = otherInits.extra[3][i])) & - (nb3 = ~(b3 = otherInits.extra[4][i])) & - ((nb4 = ~(b4 = otherInits.extra[5][i])) | - ((a2 = this.extra[3][i]) ^ - (a4 = this.extra[5][i]))) | - nb4 & (na2 = ~a2) & (na4 = ~a4)); - this.extra[3][i] = - b1 & b2 | - ~b1 & (((na1 = ~a1) | a4) & b2 | - a2 & (b2 | - a1 & (na4 = ~a4) & nb2 & nb3 | - (~(a3 = this.extra[4][i]) & nb3 | na1 & na4) & nb4)); - this.extra[4][i] = - nb2 & b3 | - ~b1 & ((a1 & na2 & na4 | na1 & a3) & (nb2 | nb4) | - a1 & na2 & a3 & nb2 | - (a1 | a2 | na4) & b3); - this.extra[5][i] = - b4 | - a4 & (nb2 & nb3 | ~(b1 ^ b2)); - if (coverageTestFlag && coverageTestId == 8) { - this.extra[5][i] = ~0; - } - } - } } for (; i < copyLimit; i++) { this.extra[0][i] = otherInits.extra[0][i]; this.extra[1][i] = otherInits.extra[1][i]; - if (considerNulls) { - for (int j = 2; j < extraLength; j++) { - this.extra[j][i] = otherInits.extra[j][i]; - } - if (coverageTestFlag && coverageTestId == 9) { - this.extra[5][i] = ~0; - } + } + // tweak limits for nulls + if (!thisHadNulls) { + if (copyLimit < mergeLimit) { + copyLimit = mergeLimit; + } + mergeLimit = 0; + } + if (!otherHasNulls) { + copyLimit = 0; + mergeLimit = 0; + } + for (i = 0; i < mergeLimit; i++) { + this.extra[1 + 1][i] = (b1 = otherInits.extra[1 + 1][i]) + | (a1 = this.extra[1 + 1][i]) & ((a3 = this.extra[3 + 1][i]) + & (a4 = this.extra[4 + 1][i]) & (nb2 = ~(b2 = otherInits.extra[2 + 1][i])) + & (nb4 = ~(b4 = otherInits.extra[4 + 1][i])) + | ((na4 = ~a4) | (na3 = ~a3)) + & ((na2 = ~(a2 = this.extra[2 + 1][i])) & nb2 + | a2 & (nb3 = ~(b3 = otherInits.extra[3 + 1][i])) & nb4)); + this.extra[2 + 1][i] = b2 & (nb4 | nb3) + | na3 & na4 & b2 + | a2 & (nb3 & nb4 + | (nb1 = ~b1) & (na3 | (na1 = ~a1)) + | a1 & b2); + this.extra[3 + 1][i] = b3 & (nb1 & (b2 | a2 | na1) + | b1 & (b4 | nb2 | a1 & a3) + | na1 & na2 & na4) + | a3 & nb2 & nb4 + | nb1 & ((na2 & a4 | na1) & a3 + | a1 & na2 & na4 & b2); + this.extra[4 + 1][i] = nb1 & (a4 & (na3 & nb3 | (a3 | na2) & nb2) + | a1 & (a3 & nb2 & b4 + | a2 & b2 & (b4 | a3 & na4 & nb3))) + | b1 & (a3 & a4 & b4 + | na2 & na4 & nb3 & b4 + | a2 & ((b3 | a4) & b4 + | na3 & a4 & b2 & b3) + | na1 & (b4 | (a4 | a2) & b2 & b3)) + | (na1 & (na3 & nb3 | na2 & nb2) + | a1 & (nb2 & nb3 | a2 & a3)) & b4; + if (coverageTestFlag && coverageTestId == 7) { + this.extra[5][i] = ~0; + } + } + for (; i < copyLimit; i++) { + for (int j = 2; j < extraLength; j++) { + this.extra[j][i] = otherInits.extra[j][i]; + } + if (coverageTestFlag && coverageTestId == 8) { + this.extra[5][i] = ~0; } } } @@ -322,206 +338,126 @@ return this; } // if we get here, otherInits has some null info - boolean thisHasNulls = (this.tagBits & NULL_FLAG_MASK) != 0; - if (thisHasNulls) { - long a1, a2, na2, a3, na3, a4, na4, b1, nb1, b2, nb2, b3, nb3, b4, nb4; - this.nullAssignmentStatusBit1 = - ((a1 = this.nullAssignmentStatusBit1) & - (na4 = ~(a4 = this.nullAssignmentValueBit2)) & - ((na3 = ~(a3 = this.nullAssignmentValueBit1)) | - (a2 = this.nullAssignmentStatusBit2)) | - a2 & na3 & a4) & - (nb3 = ~(b3 = otherInits.nullAssignmentValueBit1)) & - ((b2 = otherInits.nullAssignmentStatusBit2) | - (nb4 = ~(b4 = otherInits.nullAssignmentValueBit2))) | - a1 & (na2 = ~a2) & - (a4 & ((nb1 = ~(b1 = otherInits.nullAssignmentStatusBit1)) & - nb3 | b1 & - (b4 | b2)) | - na4 & (nb1 & (((nb2 = ~b2) & nb4 | b2) & nb3 | b3 & nb4) | - b1 & nb4 & (nb2 | nb3))); - this.nullAssignmentStatusBit2 = - a2 & (~a1 & na4 & nb4 | - a1 & na3 & nb3 & (nb1 & (nb2 & nb4 | b2) | - b1 & (nb4 |b2 & b4))); - this.nullAssignmentValueBit1 = - a3 | - b1 & nb2 & nb4 | - nb1 & b3 | - a1 & na2 & (b1 & b3 | nb1 & b4); -// b1 & (~b2 & ~b4 | a1 & ~a2 & b3) | -// ~b1 & (b3 | a1 & ~a2 & b4); -- same op nb - this.nullAssignmentValueBit2 = - a4 & (na2 | a2 & na3) | - b4 & (nb2 | b2 & nb3); - if (coverageTestFlag && coverageTestId == 15) { - this.nullAssignmentValueBit2 = ~0; - } - // extra storage management - if (otherInits.extra != null) { - int mergeLimit = 0, copyLimit = 0; - int otherLength = otherInits.extra[0].length; - if (this.extra == null) { - this.extra = new long[extraLength][]; - for (int j = 0; j < extraLength; j++) { - this.extra[j] = new long[otherLength]; - } - copyLimit = otherLength; - if (coverageTestFlag && coverageTestId == 16) { - this.extra[2][0] = ~0; thisHasNulls = true; - } - } - else { - mergeLimit = otherLength; - if (mergeLimit > this.extra[0].length) { - copyLimit = mergeLimit; - mergeLimit = this.extra[0].length; - for (int j = 0; j < extraLength; j++) { - System.arraycopy(this.extra[j], 0, - this.extra[j] = new long[otherLength], 0, - mergeLimit); - } - } - int i; - for (i = 0; i < mergeLimit; i++) { - this.extra[2][i] = - ((a1 = this.extra[2][i]) & - (na4 = ~(a4 = this.extra[5][i])) & - ((na3 = ~(a3 = this.extra[4][i])) | - (a2 = this.extra[3][i])) | - a2 & na3 & a4) & - (nb3 = ~(b3 = otherInits.extra[4][i])) & - ((b2 = otherInits.extra[3][i]) | - (nb4 = ~(b4 = otherInits.extra[5][i]))) | - a1 & (na2 = ~a2) & - (a4 & ((nb1 = ~(b1 = otherInits.extra[2][i])) & - nb3 | b1 & - (b4 | b2)) | - na4 & (nb1 & (((nb2 = ~b2) & nb4 | b2) & nb3 | b3 & nb4) | - b1 & nb4 & (nb2 | nb3))); - this.extra[3][i] = - a2 & (~a1 & na4 & nb4 | - a1 & na3 & nb3 & (nb1 & (nb2 & nb4 | b2) | - b1 & (nb4 |b2 & b4))); - this.extra[4][i] = - a3 | - b1 & nb2 & nb4 | - nb1 & b3 | - a1 & na2 & (b1 & b3 | nb1 & b4); - this.extra[5][i] = - a4 & (na2 | a2 & na3) | - b4 & (nb2 | b2 & nb3); - if (coverageTestFlag && coverageTestId == 17) { - this.nullAssignmentValueBit2 = ~0; - } - } - for (; i < copyLimit; i++) { - if (otherInits.extra[4][i] != 0 || - otherInits.extra[5][i] != 0) { - this.tagBits |= NULL_FLAG_MASK; - this.extra[4][i] = - otherInits.extra[4][i] & - ~(otherInits.extra[2][i] & - ~otherInits.extra[3][i] & - otherInits.extra[5][i]); - this.extra[5][i] = - otherInits.extra[5][i]; - if (coverageTestFlag && coverageTestId == 18) { - this.extra[5][i] = ~0; - } - } - } + boolean thisHadNulls = (this.tagBits & NULL_FLAG_MASK) != 0, + thisHasNulls = false; + long a1, a2, a3, a4, + na1, na2, na3, na4, + b1, b2, b3, b4, + nb1, nb2, nb3, nb4; + if (thisHadNulls) { + this.nullBit1 = (a1 = this.nullBit1) + & ((a3 = this.nullBit3) & (a4 = this.nullBit4) + & ((nb2 = ~(b2 = otherInits.nullBit2)) + & (nb4 = ~(b4 = otherInits.nullBit4)) + | (b1 = otherInits.nullBit1) & (b3 = otherInits.nullBit3)) + | (na2 = ~(a2 = this.nullBit2)) + & (b1 & b3 | ((na4 = ~a4) | (na3 = ~a3)) & nb2) + | a2 & ((na4 | na3) & ((nb3 = ~b3) & nb4 | b1 & b2))); + this.nullBit2 = b2 & (nb3 | (nb1 = ~b1)) + | a2 & (nb3 & nb4 | b2 | na3 | (na1 = ~a1)); + this.nullBit3 = b3 & (nb1 & b2 + | a2 & (nb2 | a3) + | na1 & nb2 + | a1 & na2 & na4 & b1) + | a3 & (nb2 & nb4 | na2 & a4 | na1) + | a1 & na2 & na4 & b2; + this.nullBit4 = na3 & (nb1 & nb3 & b4 + | a4 & (nb3 | b1 & b2)) + | nb2 & (na3 & b1 & nb3 | na2 & (nb1 & b4 | b1 & nb3 | a4)) + | a3 & (a4 & (nb2 | b1 & b3) + | a1 & a2 & (nb1 & b4 | na4 & (b2 | b1) & nb3)); + if (coverageTestFlag && coverageTestId == 9) { + this.nullBit4 = ~0; + } + if ((this.nullBit2 | this.nullBit3 | this.nullBit4) != 0) { // bit1 is redundant + thisHasNulls = true; + } + } else { + this.nullBit1 = 0; + this.nullBit2 = (b2 = otherInits.nullBit2) + & ((nb3 = ~(b3 = otherInits.nullBit3)) | + (nb1 = ~(b1 = otherInits.nullBit1))); + this.nullBit3 = b3 & (nb1 | (nb2 = ~b2)); + this.nullBit4 = ~b1 & ~b3 & (b4 = otherInits.nullBit4) | ~b2 & (b1 & ~b3 | ~b1 & b4); + if (coverageTestFlag && coverageTestId == 10) { + this.nullBit4 = ~0; + } + if ((this.nullBit2 | this.nullBit3 | this.nullBit4) != 0) { // bit1 is redundant + thisHasNulls = true; + } + } + // extra storage management + if (otherInits.extra != null) { + int mergeLimit = 0, copyLimit = otherInits.extra[0].length; + if (this.extra == null) { + this.extra = new long[extraLength][]; + for (int j = 0; j < extraLength; j++) { + this.extra[j] = new long[copyLimit]; } - } - } - else { - if (otherInits.nullAssignmentValueBit1 != 0 || - otherInits.nullAssignmentValueBit2 != 0) { - // add potential values - this.nullAssignmentValueBit1 = - otherInits.nullAssignmentValueBit1 & - ~(otherInits.nullAssignmentStatusBit1 & - ~otherInits.nullAssignmentStatusBit2 & - otherInits.nullAssignmentValueBit2); // exclude assigned unknown - this.nullAssignmentValueBit2 = - otherInits.nullAssignmentValueBit2; - thisHasNulls = - this.nullAssignmentValueBit1 != 0 || - this.nullAssignmentValueBit2 != 0; - if (coverageTestFlag && coverageTestId == 10) { - this.nullAssignmentValueBit2 = ~0; + if (coverageTestFlag && coverageTestId == 11) { + throw new AssertionFailedException("COVERAGE 11"); //$NON-NLS-1$ } - } - // extra storage management - if (otherInits.extra != null) { - int mergeLimit = 0, copyLimit = 0; - int otherLength = otherInits.extra[0].length; - if (this.extra == null) { - copyLimit = otherLength; - // cannot happen when called from addPotentialInitializationsFrom - this.extra = new long[extraLength][]; + } else { + mergeLimit = copyLimit; + if (mergeLimit > this.extra[0].length) { + mergeLimit = this.extra[0].length; for (int j = 0; j < extraLength; j++) { - this.extra[j] = new long[otherLength]; - } - if (coverageTestFlag && coverageTestId == 11) { - this.extra[5][0] = ~0; this.tagBits |= NULL_FLAG_MASK; - } - } - else { - mergeLimit = otherLength; - if (mergeLimit > this.extra[0].length) { - copyLimit = mergeLimit; - mergeLimit = this.extra[0].length; - System.arraycopy(this.extra[0], 0, - this.extra[0] = new long[otherLength], 0, + System.arraycopy(this.extra[j], 0, + this.extra[j] = new long[copyLimit], 0, mergeLimit); - System.arraycopy(this.extra[1], 0, - this.extra[1] = new long[otherLength], 0, - mergeLimit); - for (int j = 2; j < extraLength; j++) { - this.extra[j] = new long[otherLength]; - } - if (coverageTestFlag && coverageTestId == 12) { + } + if (! thisHadNulls) { + mergeLimit = 0; + // will do with a copy -- caveat: only valid because definite assignment bits copied above + if (coverageTestFlag && coverageTestId == 12) { throw new AssertionFailedException("COVERAGE 12"); //$NON-NLS-1$ - } + } } } - int i; - for (i = 0; i < mergeLimit; i++) { - if (otherInits.extra[4][i] != 0 || - otherInits.extra[5][i] != 0) { - this.extra[4][i] |= - otherInits.extra[4][i] & - ~(otherInits.extra[2][i] & - ~otherInits.extra[3][i] & - otherInits.extra[5][i]); - this.extra[5][i] |= - otherInits.extra[5][i]; - thisHasNulls = thisHasNulls || - this.extra[4][i] != 0 || - this.extra[5][i] != 0; - if (coverageTestFlag && coverageTestId == 13) { - this.extra[5][i] = ~0; - } - } + } + // PREMATURE skip operations for fields + int i; + for (i = 0 ; i < mergeLimit ; i++) { + this.extra[1 + 1][i] = (a1 = this.extra[1 + 1][i]) + & ((a3 = this.extra[3 + 1][i]) & (a4 = this.extra[4 + 1][i]) + & ((nb2 = ~(b2 = otherInits.extra[2 + 1][i])) + & (nb4 = ~(b4 = otherInits.extra[4 + 1][i])) + | (b1 = otherInits.extra[1 + 1][i]) & (b3 = otherInits.extra[3 + 1][i])) + | (na2 = ~(a2 = this.extra[2 + 1][i])) + & (b1 & b3 | ((na4 = ~a4) | (na3 = ~a3)) & nb2) + | a2 & ((na4 | na3) & ((nb3 = ~b3) & nb4 | b1 & b2))); + this.extra[2 + 1][i] = b2 & (nb3 | (nb1 = ~b1)) + | a2 & (nb3 & nb4 | b2 | na3 | (na1 = ~a1)); + this.extra[3 + 1][i] = b3 & (nb1 & b2 + | a2 & (nb2 | a3) + | na1 & nb2 + | a1 & na2 & na4 & b1) + | a3 & (nb2 & nb4 | na2 & a4 | na1) + | a1 & na2 & na4 & b2; + this.extra[4 + 1][i] = na3 & (nb1 & nb3 & b4 + | a4 & (nb3 | b1 & b2)) + | nb2 & (na3 & b1 & nb3 | na2 & (nb1 & b4 | b1 & nb3 | a4)) + | a3 & (a4 & (nb2 | b1 & b3) + | a1 & a2 & (nb1 & b4 | na4 & (b2 | b1) & nb3)); + if ((this.extra[2 + 1][i] | this.extra[3 + 1][i] | this.extra[4 + 1][i]) != 0) { // bit1 is redundant + thisHasNulls = true; + } + if (coverageTestFlag && coverageTestId == 13) { + this.nullBit4 = ~0; } - for (; i < copyLimit; i++) { - if (otherInits.extra[4][i] != 0 || - otherInits.extra[5][i] != 0) { - this.extra[4][i] = - otherInits.extra[4][i] & - ~(otherInits.extra[2][i] & - ~otherInits.extra[3][i] & - otherInits.extra[5][i]); - this.extra[5][i] = - otherInits.extra[5][i]; - thisHasNulls = thisHasNulls || - this.extra[4][i] != 0 || - this.extra[5][i] != 0; - if (coverageTestFlag && coverageTestId == 14) { - this.extra[5][i] = ~0; - } - } + } + for (; i < copyLimit; i++) { + this.extra[1 + 1][i] = 0; + 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]))); + this.extra[3 + 1][i] = b3 & (nb1 | (nb2 = ~b2)); + this.extra[4 + 1][i] = ~b1 & ~b3 & (b4 = otherInits.extra[4 + 1][i]) | ~b2 & (b1 & ~b3 | ~b1 & b4); + if ((this.extra[2 + 1][i] | this.extra[3 + 1][i] | this.extra[4 + 1][i]) != 0) { // bit1 is redundant + thisHasNulls = true; + } + if (coverageTestFlag && coverageTestId == 14) { + this.extra[5][i] = ~0; } } } @@ -545,10 +481,10 @@ copy.potentialInits = this.potentialInits; boolean hasNullInfo = (this.tagBits & NULL_FLAG_MASK) != 0; if (hasNullInfo) { - copy.nullAssignmentStatusBit1 = this.nullAssignmentStatusBit1; - copy.nullAssignmentStatusBit2 = this.nullAssignmentStatusBit2; - copy.nullAssignmentValueBit1 = this.nullAssignmentValueBit1; - copy.nullAssignmentValueBit2 = this.nullAssignmentValueBit2; + copy.nullBit1 = this.nullBit1; + copy.nullBit2 = this.nullBit2; + copy.nullBit3 = this.nullBit3; + copy.nullBit4 = this.nullBit4; } copy.tagBits = this.tagBits; copy.maxFieldCount = this.maxFieldCount; @@ -604,10 +540,10 @@ long mask = (1L << limit)-1; this.definiteInits &= mask; this.potentialInits &= mask; - this.nullAssignmentStatusBit1 &= mask; - this.nullAssignmentStatusBit2 &= mask; - this.nullAssignmentValueBit1 &= mask; - this.nullAssignmentValueBit2 &= mask; + this.nullBit1 &= mask; + this.nullBit2 &= mask; + this.nullBit3 &= mask; + this.nullBit4 &= mask; } // use extra vector if (this.extra == null) { @@ -694,15 +630,9 @@ return true; } int position = local.id + this.maxFieldCount; - long mask; if (position < BitCacheSize) { // use bits - return - (this.nullAssignmentStatusBit2 & - (mask = 1L << position)) != 0 ? - (this.nullAssignmentStatusBit1 & mask) != 0 : - (this.nullAssignmentStatusBit1 & - this.nullAssignmentValueBit2 & mask) != 0 && - (this.nullAssignmentValueBit1 & mask) == 0; + return ((this.nullBit1 & this.nullBit3 & (~this.nullBit2 | this.nullBit4)) + & (1L << position)) != 0; } // use extra vector if (this.extra == null) { @@ -713,13 +643,9 @@ >= this.extra[0].length) { return false; // if not enough room in vector, then not initialized } - return - (this.extra[3][vectorIndex] & - (mask = 1L << (position % BitCacheSize))) != 0 ? - (this.extra[2][vectorIndex] & mask) != 0 : - (this.extra[2][vectorIndex] & - this.extra[5][vectorIndex] & mask) != 0 && - (this.extra[4][vectorIndex] & mask) == 0; + return ((this.extra[2][vectorIndex] & this.extra[4][vectorIndex] + & (~this.extra[3][vectorIndex] | this.extra[5][vectorIndex])) + & (1L << (position % BitCacheSize))) != 0; } final public boolean isDefinitelyNull(LocalVariableBinding local) { @@ -730,14 +656,10 @@ return false; } int position = local.id + this.maxFieldCount; - long mask; if (position < BitCacheSize) { // use bits - return - (this.nullAssignmentStatusBit2 & (mask = 1L << position)) != 0 ? - (this.nullAssignmentStatusBit1 & mask) == 0 : - (this.nullAssignmentStatusBit1 & - this.nullAssignmentValueBit1 & mask) != 0 && - (this.nullAssignmentValueBit2 & mask) == 0; + return ((this.nullBit1 & this.nullBit2 + & (~this.nullBit3 | ~this.nullBit4)) + & (1L << position)) != 0; } // use extra vector if (this.extra == null) { @@ -748,13 +670,9 @@ this.extra[0].length) { return false; // if not enough room in vector, then not initialized } - return - (this.extra[3][vectorIndex] & - (mask = 1L << (position % BitCacheSize))) != 0 ? - (this.extra[2][vectorIndex] & mask) == 0 : - (this.extra[2][vectorIndex] & - this.extra[4][vectorIndex] & mask) != 0 && - (this.extra[5][vectorIndex] & mask) == 0; + return ((this.extra[2][vectorIndex] & this.extra[3][vectorIndex] + & (~this.extra[4][vectorIndex] | ~this.extra[5][vectorIndex])) + & (1L << (position % BitCacheSize))) != 0; } final public boolean isDefinitelyUnknown(LocalVariableBinding local) { @@ -764,14 +682,9 @@ return false; } int position = local.id + this.maxFieldCount; - long mask; if (position < BitCacheSize) { // use bits - return - (this.nullAssignmentStatusBit2 & (mask = 1L << position)) != 0 ? - false : - (this.nullAssignmentStatusBit1 & - this.nullAssignmentValueBit1 & - this.nullAssignmentValueBit2 & mask) != 0; + return ((this.nullBit1 & this.nullBit4 + & ~this.nullBit2 & ~this.nullBit3) & (1L << position)) != 0; } // use extra vector if (this.extra == null) { @@ -782,14 +695,9 @@ this.extra[0].length) { return false; // if not enough room in vector, then not initialized } - return - (this.extra[3][vectorIndex] & - (mask = 1L << (position % BitCacheSize))) != 0 ? - false : - (this.extra[2][vectorIndex] & - this.extra[4][vectorIndex] & - this.extra[5][vectorIndex] & - mask) != 0; + return ((this.extra[2][vectorIndex] & this.extra[5][vectorIndex] + & ~this.extra[3][vectorIndex] & ~this.extra[4][vectorIndex]) + & (1L << (position % BitCacheSize))) != 0; } /** @@ -826,22 +734,41 @@ return isPotentiallyAssigned(local.id + this.maxFieldCount); } +final public boolean isPotentiallyNonNull(LocalVariableBinding local) { + if ((this.tagBits & NULL_FLAG_MASK) == 0 || + (local.type.tagBits & TagBits.IsBaseType) != 0) { + return false; + } + int position; + if ((position = local.id + this.maxFieldCount) < BitCacheSize) { + // use bits + return ((this.nullBit3 & (~this.nullBit1 | ~this.nullBit2)) + & (1L << position)) != 0; + } + // use extra vector + if (this.extra == null) { + return false; // if vector not yet allocated, then not initialized + } + int vectorIndex; + if ((vectorIndex = (position / BitCacheSize) - 1) >= + this.extra[0].length) { + return false; // if not enough room in vector, then not initialized + } + return ((this.extra[4][vectorIndex] + & (~this.extra[2][vectorIndex] | ~this.extra[3][vectorIndex])) + & (1L << (position % BitCacheSize))) != 0; +} + final public boolean isPotentiallyNull(LocalVariableBinding local) { if ((this.tagBits & NULL_FLAG_MASK) == 0 || (local.type.tagBits & TagBits.IsBaseType) != 0) { return false; } int position; - long mask; if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits - return - (this.nullAssignmentStatusBit2 & (mask = 1L << position)) != 0 ? - (this.nullAssignmentStatusBit1 & mask) == 0 : // protected null - (this.nullAssignmentValueBit1 & mask) != 0 && // null bit set and - ((this.nullAssignmentStatusBit1 & mask) == 0 || // (potential or - (this.nullAssignmentValueBit2 & mask) == 0); - // assigned, but not unknown) + return ((this.nullBit2 & (~this.nullBit1 | ~this.nullBit3)) + & (1L << position)) != 0; } // use extra vector if (this.extra == null) { @@ -852,13 +779,9 @@ this.extra[0].length) { return false; // if not enough room in vector, then not initialized } - return - (this.extra[3][vectorIndex] & - (mask = 1L << (position % BitCacheSize))) != 0 ? - (this.extra[2][vectorIndex] & mask) == 0 : - (this.extra[4][vectorIndex] & mask) != 0 && - ((this.extra[2][vectorIndex] & mask) == 0 || - (this.extra[5][vectorIndex] & mask) == 0); + return ((this.extra[3][vectorIndex] + & (~this.extra[2][vectorIndex] | ~this.extra[4][vectorIndex])) + & (1L << (position % BitCacheSize))) != 0; } final public boolean isPotentiallyUnknown(LocalVariableBinding local) { @@ -868,16 +791,10 @@ return false; } int position = local.id + this.maxFieldCount; - long mask; if (position < BitCacheSize) { // use bits - return - (this.nullAssignmentStatusBit2 & (mask = 1L << position)) != 0 ? - false : - ((this.nullAssignmentStatusBit1 & - this.nullAssignmentValueBit1 | - ~this.nullAssignmentStatusBit1 & - ~this.nullAssignmentValueBit1) & - this.nullAssignmentValueBit2 & mask) != 0; + return (this.nullBit4 + & (~this.nullBit1 | ~this.nullBit2 & ~this.nullBit3) + & (1L << position)) != 0; } // use extra vector if (this.extra == null) { @@ -888,16 +805,10 @@ this.extra[0].length) { return false; // if not enough room in vector, then not initialized } - return - (this.extra[3][vectorIndex] & - (mask = 1L << (position % BitCacheSize))) != 0 ? - false : - ((this.extra[2][vectorIndex] & - this.extra[4][vectorIndex] | - ~this.extra[2][vectorIndex] & - ~this.extra[4][vectorIndex]) & - this.extra[5][vectorIndex] & - mask) != 0; + return (this.extra[5][vectorIndex] + & (~this.extra[2][vectorIndex] + | ~this.extra[3][vectorIndex] & ~this.extra[4][vectorIndex]) + & (1L << (position % BitCacheSize))) != 0; } final public boolean isProtectedNonNull(LocalVariableBinding local) { @@ -908,8 +819,7 @@ int position; if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits - return (this.nullAssignmentStatusBit1 & - this.nullAssignmentStatusBit2 & (1L << position)) != 0; + return (this.nullBit1 & this.nullBit3 & this.nullBit4 & (1L << position)) != 0; } // use extra vector if (this.extra == null) { @@ -920,9 +830,10 @@ this.extra[0].length) { return false; // if not enough room in vector, then not initialized } - return (this.extra[2][vectorIndex] & - this.extra[3][vectorIndex] & - (1L << (position % BitCacheSize))) != 0; + return (this.extra[2][vectorIndex] + & this.extra[4][vectorIndex] + & this.extra[5][vectorIndex] + & (1L << (position % BitCacheSize))) != 0; } final public boolean isProtectedNull(LocalVariableBinding local) { @@ -933,8 +844,9 @@ int position; if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits - return (~this.nullAssignmentStatusBit1 & - this.nullAssignmentStatusBit2 & (1L << position)) != 0; + return (this.nullBit1 & this.nullBit2 + & (this.nullBit3 ^ this.nullBit4) + & (1L << position)) != 0; } // use extra vector if (this.extra == null) { @@ -945,9 +857,9 @@ this.extra[0].length) { return false; // if not enough room in vector, then not initialized } - return (~this.extra[2][vectorIndex] & - this.extra[3][vectorIndex] & - (1L << (position % BitCacheSize))) != 0; + return (this.extra[2][vectorIndex] & this.extra[3][vectorIndex] + & (this.extra[4][vectorIndex] ^ this.extra[5][vectorIndex]) + & (1L << (position % BitCacheSize))) != 0; } public void markAsComparedEqualToNonNull(LocalVariableBinding local) { @@ -956,25 +868,32 @@ this.tagBits |= NULL_FLAG_MASK; int position; long mask; + long a1, a2, a3, a4, na2; // position is zero-based if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits - if (((mask = 1L << position) & // leave assigned non null unchanged - this.nullAssignmentStatusBit1 & - ~this.nullAssignmentStatusBit2 & - ~this.nullAssignmentValueBit1 & - this.nullAssignmentValueBit2) == 0) { - // set protected non null - this.nullAssignmentStatusBit1 |= mask; - this.nullAssignmentStatusBit2 |= mask; - // clear potential null - this.nullAssignmentValueBit1 &= ~mask; - if (coverageTestFlag && coverageTestId == 19) { - this.nullAssignmentValueBit2 = ~0; - } - } - if (coverageTestFlag && coverageTestId == 20) { - this.nullAssignmentValueBit2 = ~0; + if (((mask = 1L << position) + & (a1 = this.nullBit1) + & (na2 = ~(a2 = this.nullBit2)) + & ~(a3 = this.nullBit3) + & (a4 = this.nullBit4)) + != 0) { + this.nullBit4 &= ~mask; + } else if ((mask & a1 & na2 & a3) == 0) { + this.nullBit4 |= mask; + if ((mask & a1) == 0) { + if ((mask & a2 & (a3 ^ a4)) != 0) { + this.nullBit2 &= ~mask; + } + else if ((mask & (a2 | a3 | a4)) == 0) { + this.nullBit2 |= mask; + } + } + } + this.nullBit1 |= mask; + this.nullBit3 |= mask; + if (coverageTestFlag && coverageTestId == 15) { + this.nullBit4 = ~0; } } else { @@ -986,8 +905,8 @@ for (int j = 0; j < extraLength; j++) { this.extra[j] = new long[length]; } - if (coverageTestFlag && coverageTestId == 21) { - throw new AssertionFailedException("COVERAGE 21"); //$NON-NLS-1$ + if (coverageTestFlag && coverageTestId == 16) { + throw new AssertionFailedException("COVERAGE 16"); //$NON-NLS-1$ } } else { @@ -999,22 +918,34 @@ (this.extra[j] = new long[newLength]), 0, oldLength); } - if (coverageTestFlag && coverageTestId == 22) { - throw new AssertionFailedException("COVERAGE 22"); //$NON-NLS-1$ + if (coverageTestFlag && coverageTestId == 17) { + throw new AssertionFailedException("COVERAGE 17"); //$NON-NLS-1$ } } } - if (((mask = 1L << (position % BitCacheSize)) & - this.extra[2][vectorIndex] & - ~this.extra[3][vectorIndex] & - ~this.extra[4][vectorIndex] & - this.extra[5][vectorIndex]) == 0) { - this.extra[2][vectorIndex] |= mask; - this.extra[3][vectorIndex] |= mask; - this.extra[4][vectorIndex] &= ~mask; - if (coverageTestFlag && coverageTestId == 23) { - this.extra[5][vectorIndex] = ~0; - } + // MACRO :'b,'es/nullBit\(.\)/extra[\1 + 1][vectorIndex]/gc + if (((mask = 1L << (position % BitCacheSize)) + & (a1 = this.extra[1 + 1][vectorIndex]) + & (na2 = ~(a2 = this.extra[2 + 1][vectorIndex])) + & ~(a3 = this.extra[3 + 1][vectorIndex]) + & (a4 = this.extra[4 + 1][vectorIndex])) + != 0) { + this.extra[4 + 1][vectorIndex] &= ~mask; + } else if ((mask & a1 & na2 & a3) == 0) { + this.extra[4 + 1][vectorIndex] |= mask; + if ((mask & a1) == 0) { + if ((mask & a2 & (a3 ^ a4)) != 0) { + this.extra[2 + 1][vectorIndex] &= ~mask; + } + else if ((mask & (a2 | a3 | a4)) == 0) { + this.extra[2 + 1][vectorIndex] |= mask; + } + } + } + this.extra[1 + 1][vectorIndex] |= mask; + this.extra[3 + 1][vectorIndex] |= mask; + if (coverageTestFlag && coverageTestId == 18) { + this.extra[5][vectorIndex] = ~0; } } } @@ -1025,33 +956,30 @@ if (this != DEAD_END) { this.tagBits |= NULL_FLAG_MASK; int position; - long mask, unknownAssigned; + long mask; // position is zero-based if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits - mask = 1L << position; - if ((mask & // leave assigned null unchanged - this.nullAssignmentStatusBit1 & - ~this.nullAssignmentStatusBit2 & - this.nullAssignmentValueBit1 & - ~this.nullAssignmentValueBit2) == 0) { - unknownAssigned = this.nullAssignmentStatusBit1 & - ~this.nullAssignmentStatusBit2 & - this.nullAssignmentValueBit1 & - this.nullAssignmentValueBit2; - // set protected - this.nullAssignmentStatusBit2 |= mask; - this.nullAssignmentStatusBit1 &= (mask = ~mask); - // protected is null - this.nullAssignmentValueBit1 &= mask | ~unknownAssigned; - this.nullAssignmentValueBit2 &= mask; - // clear potential anything but null - if (coverageTestFlag && coverageTestId == 24) { - this.nullAssignmentValueBit2 = ~0; - } - } - if (coverageTestFlag && coverageTestId == 25) { - this.nullAssignmentValueBit2 = ~0; + if (((mask = 1L << position) & this.nullBit1) != 0) { + if ((mask + & (~this.nullBit2 | this.nullBit3 + | ~this.nullBit4)) != 0) { + this.nullBit4 &= ~mask; + } + } else if ((mask & this.nullBit4) != 0) { + this.nullBit3 &= ~mask; + } else { + if ((mask & this.nullBit2) != 0) { + this.nullBit3 &= ~mask; + this.nullBit4 |= mask; + } else { + this.nullBit3 |= mask; + } + } + this.nullBit1 |= mask; + this.nullBit2 |= mask; + if (coverageTestFlag && coverageTestId == 19) { + this.nullBit4 = ~0; } } else { @@ -1064,8 +992,8 @@ for (int j = 0; j < extraLength; j++) { this.extra[j] = new long[length ]; } - if (coverageTestFlag && coverageTestId == 26) { - throw new AssertionFailedException("COVERAGE 26"); //$NON-NLS-1$ + if (coverageTestFlag && coverageTestId == 20) { + throw new AssertionFailedException("COVERAGE 20"); //$NON-NLS-1$ } } else { @@ -1077,28 +1005,29 @@ (this.extra[j] = new long[newLength]), 0, oldLength); } - if (coverageTestFlag && coverageTestId == 27) { - throw new AssertionFailedException("COVERAGE 27"); //$NON-NLS-1$ + if (coverageTestFlag && coverageTestId == 21) { + throw new AssertionFailedException("COVERAGE 21"); //$NON-NLS-1$ } } } - if ((mask & - this.extra[2][vectorIndex] & - ~this.extra[3][vectorIndex] & - this.extra[4][vectorIndex] & - ~this.extra[5][vectorIndex]) == 0) { - unknownAssigned = this.extra[2][vectorIndex] & - ~this.extra[3][vectorIndex] & - this.extra[4][vectorIndex] & - this.extra[5][vectorIndex]; - this.extra[3][vectorIndex] |= mask; - this.extra[2][vectorIndex] &= (mask = ~mask); - this.extra[4][vectorIndex] &= mask | ~unknownAssigned; - this.extra[5][vectorIndex] &= mask; - if (coverageTestFlag && coverageTestId == 28) { - this.extra[5][vectorIndex] = ~0; - } + if ((mask & this.extra[1 + 1][vectorIndex]) != 0) { + if ((mask + & (~this.extra[2 + 1][vectorIndex] | this.extra[3 + 1][vectorIndex] + | ~this.extra[4 + 1][vectorIndex])) != 0) { + this.extra[4 + 1][vectorIndex] &= ~mask; + } + } else if ((mask & this.extra[4 + 1][vectorIndex]) != 0) { + this.extra[3 + 1][vectorIndex] &= ~mask; + } else { + if ((mask & this.extra[2 + 1][vectorIndex]) != 0) { + this.extra[3 + 1][vectorIndex] &= ~mask; + this.extra[4 + 1][vectorIndex] |= mask; + } else { + this.extra[3 + 1][vectorIndex] |= mask; + } } + this.extra[1 + 1][vectorIndex] |= mask; + this.extra[2 + 1][vectorIndex] |= mask; } } } @@ -1157,62 +1086,66 @@ public void markAsDefinitelyNonNull(LocalVariableBinding local) { // protected from non-object locals in calling methods if (this != DEAD_END) { - this.tagBits |= NULL_FLAG_MASK; - int position; - long mask; - // position is zero-based - if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits - this.nullAssignmentStatusBit1 |= (mask = 1L << position); - this.nullAssignmentValueBit2 |= mask; // set non null - this.nullAssignmentStatusBit2 &= ~mask; // clear protection - this.nullAssignmentValueBit1 &= ~mask; // clear null - if (coverageTestFlag && coverageTestId == 29) { - this.nullAssignmentStatusBit1 = 0; - } - } - else { - // use extra vector - int vectorIndex = (position / BitCacheSize) - 1; - this.extra[2][vectorIndex] |= - (mask = 1L << (position % BitCacheSize)); - this.extra[5][vectorIndex] |= mask; - this.extra[3][vectorIndex] &= ~mask; - this.extra[4][vectorIndex] &= ~mask; - if (coverageTestFlag && coverageTestId == 30) { - this.extra[5][vectorIndex] = ~0; - } - } + this.tagBits |= NULL_FLAG_MASK; + long mask; + int position; + // position is zero-based + if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits + // set assigned non null + this.nullBit1 |= (mask = 1L << position); + this.nullBit3 |= mask; + // clear others + this.nullBit2 &= (mask = ~mask); + this.nullBit4 &= mask; + if (coverageTestFlag && coverageTestId == 22) { + this.nullBit1 = 0; + } + } + else { + // use extra vector + int vectorIndex ; + this.extra[2][vectorIndex = (position / BitCacheSize) - 1] + |= (mask = 1L << (position % BitCacheSize)); + this.extra[4][vectorIndex] |= mask; + this.extra[3][vectorIndex] &= (mask = ~mask); + this.extra[5][vectorIndex] &= mask; + if (coverageTestFlag && coverageTestId == 23) { + this.extra[2][vectorIndex] = 0; + } + } } } public void markAsDefinitelyNull(LocalVariableBinding local) { // protected from non-object locals in calling methods if (this != DEAD_END) { - this.tagBits |= NULL_FLAG_MASK; - int position; - long mask; - // position is zero-based - if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits - this.nullAssignmentStatusBit1 |= (mask = 1L << position); // set assignment - this.nullAssignmentStatusBit2 &= ~mask; // clear protection - this.nullAssignmentValueBit1 |= mask; // set null - this.nullAssignmentValueBit2 &= ~mask; // clear non null - if (coverageTestFlag && coverageTestId == 31) { - this.nullAssignmentValueBit2 = ~0; - } - } - else { - // use extra vector - int vectorIndex = (position / BitCacheSize) - 1; - this.extra[2][vectorIndex] |= - (mask = 1L << (position % BitCacheSize)); - this.extra[3][vectorIndex] &= ~mask; - this.extra[4][vectorIndex] |= mask; - this.extra[5][vectorIndex] &= ~mask; - if (coverageTestFlag && coverageTestId == 32) { - this.extra[5][vectorIndex] = ~0; - } - } + this.tagBits |= NULL_FLAG_MASK; + long mask; + int position; + // position is zero-based + if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits + // mark assigned null + this.nullBit1 |= (mask = 1L << position); + this.nullBit2 |= mask; + // clear others + this.nullBit3 &= (mask = ~mask); + this.nullBit4 &= mask; + if (coverageTestFlag && coverageTestId == 24) { + this.nullBit4 = ~0; + } + } + else { + // use extra vector + int vectorIndex ; + this.extra[2][vectorIndex = (position / BitCacheSize) - 1] + |= (mask = 1L << (position % BitCacheSize)); + this.extra[3][vectorIndex] |= mask; + this.extra[4][vectorIndex] &= (mask = ~mask); + this.extra[5][vectorIndex] &= mask; + if (coverageTestFlag && coverageTestId == 25) { + this.extra[5][vectorIndex] = ~0; + } + } } } @@ -1231,27 +1164,26 @@ // position is zero-based if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits - this.nullAssignmentValueBit1 |= (mask = 1L << position); - this.nullAssignmentValueBit2 |= mask; - // set unknown - this.nullAssignmentStatusBit1 |= mask; - // set assignment - this.nullAssignmentStatusBit2 &= ~mask; - // clear protection - if (coverageTestFlag && coverageTestId == 33) { - this.nullAssignmentValueBit2 = ~0; + // mark assigned null + this.nullBit1 |= (mask = 1L << position); + this.nullBit4 |= mask; + // clear others + this.nullBit2 &= (mask = ~mask); + this.nullBit3 &= mask; + if (coverageTestFlag && coverageTestId == 26) { + this.nullBit4 = 0; } } else { // use extra vector - int vectorIndex = (position / BitCacheSize) - 1; - this.extra[4][vectorIndex] |= - (mask = 1L << (position % BitCacheSize)); + int vectorIndex ; + this.extra[2][vectorIndex = (position / BitCacheSize) - 1] + |= (mask = 1L << (position % BitCacheSize)); this.extra[5][vectorIndex] |= mask; - this.extra[2][vectorIndex] |= mask; - this.extra[3][vectorIndex] &= ~mask; - if (coverageTestFlag && coverageTestId == 34) { - this.extra[5][vectorIndex] = ~0; + this.extra[3][vectorIndex] &= (mask = ~mask); + this.extra[4][vectorIndex] &= mask; + if (coverageTestFlag && coverageTestId == 27) { + this.extra[5][vectorIndex] = 0; } } } @@ -1259,15 +1191,14 @@ public UnconditionalFlowInfo mergedWith(UnconditionalFlowInfo otherInits) { if ((otherInits.tagBits & UNREACHABLE) != 0 && this != DEAD_END) { - if (coverageTestFlag && coverageTestId == 35) { - throw new AssertionFailedException("COVERAGE 35"); //$NON-NLS-1$ + if (coverageTestFlag && coverageTestId == 28) { + throw new AssertionFailedException("COVERAGE 28"); //$NON-NLS-1$ } - // DEAD_END + unreachable other -> other return this; } if ((this.tagBits & UNREACHABLE) != 0) { - if (coverageTestFlag && coverageTestId == 36) { - throw new AssertionFailedException("COVERAGE 36"); //$NON-NLS-1$ + if (coverageTestFlag && coverageTestId == 29) { + throw new AssertionFailedException("COVERAGE 29"); //$NON-NLS-1$ } return (UnconditionalFlowInfo) otherInits.copy(); // make sure otherInits won't be affected } @@ -1278,69 +1209,75 @@ this.potentialInits |= otherInits.potentialInits; // null combinations - boolean otherHasNulls = (otherInits.tagBits & NULL_FLAG_MASK) != 0, - thisHasNulls = false; - long a1, a2, na2, a3, na3, a4, na4, b1, nb1, b2, nb2, b3, nb3, b4, nb4; - if (otherHasNulls) { - this.nullAssignmentStatusBit1 = - (a1 = this.nullAssignmentStatusBit1) & - (b1 = otherInits.nullAssignmentStatusBit1) & ( - (nb4 = ~(b4 = otherInits.nullAssignmentValueBit2)) & - ((b2 = otherInits.nullAssignmentStatusBit2) & - (nb3 = ~(b3 = otherInits.nullAssignmentValueBit1)) & - (na3 = ~(a3 = this.nullAssignmentValueBit1)) & - ((a2 = this.nullAssignmentStatusBit2) & - (na4 = ~(a4 = this.nullAssignmentValueBit2)) | a4) | - (na2 = ~a2) & a3 & na4 & (nb2 = ~b2) & b3 ) | - b4 & (na3 & nb3 & (na4 & a2 | a4) | - na2 & a4 & nb2)); - this.nullAssignmentStatusBit2 = - a2 & b2 & ~(a1 ^ b1) & (na3 & nb3 | na4 & nb4) | - a1 & b1 & (a2 ^ b2) & na3 & nb3 | - (a1 & na2 & (nb1 = ~b1) & b2 | ~a1 & a2 & b1 & nb2) & na4 & nb4; - this.nullAssignmentValueBit1 = - b1 & nb2 & nb4 | - ~a1 & (a3 | - a2 & na3 & (b1 | nb2)) | - (a1 | na2) & nb1 & b2 & nb3 | - nb1 & b3 | - a1 & na2 & (na4 | - b1 & nb2 & (a3 | b3)); - this.nullAssignmentValueBit2 = - a4 | b4; - - // WORK recode if tests succeed - this.nullAssignmentValueBit1 &= - ~(a1 & na2 & na3 & a4 & nb1 & b2 & nb3 & nb4 - | ~a1 & a2 & na3 & na4 & b1 & nb2 & nb3 & b4); - - if (coverageTestFlag && coverageTestId == 37) { - this.nullAssignmentValueBit2 = ~0; - } + boolean + thisHasNulls = (this.tagBits & NULL_FLAG_MASK) != 0, + otherHasNulls = (otherInits.tagBits & NULL_FLAG_MASK) != 0, + thisHadNulls = thisHasNulls; + long + a1, a2, a3, a4, + na1, na2, na3, na4, + nb1, nb2, nb3, nb4, + b1, b2, b3, b4; + if (thisHadNulls) { + if (otherHasNulls) { + this.nullBit1 = (a2 = this.nullBit2) & (a3 = this.nullBit3) + & (a4 = this.nullBit4) & (b1 = otherInits.nullBit1) + & (nb2 = ~(b2 = otherInits.nullBit2)) + | (a1 = this.nullBit1) & (b1 & (a3 & a4 & (b3 = otherInits.nullBit3) + & (b4 = otherInits.nullBit4) + | (na2 = ~a2) & nb2 + & ((nb4 = ~b4) | (na4 = ~a4) + | (na3 = ~a3) & (nb3 = ~b3)) + | a2 & b2 & ((na4 | na3) & (nb4 | nb3))) + | na2 & b2 & b3 & b4); + this.nullBit2 = b2 & (nb3 | (nb1 = ~b1) | a3 & (a4 | (na1 = ~a1)) & nb4) + | a2 & (b2 | na4 & b3 & (b4 | nb1) | na3 | na1); + this.nullBit3 = b3 & (nb2 & b4 | nb1 | a3 & (na4 & nb4 | a4 & b4)) + | a3 & (na2 & a4 | na1) + | (a2 | na1) & b1 & nb2 & nb4 + | a1 & na2 & na4 & (b2 | nb1); + this.nullBit4 = na3 & (nb1 & nb3 & b4 + | b1 & (nb2 & nb3 | a4 & b2 & nb4) + | na1 & a4 & (nb3 | b1 & b2)) + | a3 & a4 & (b3 & b4 | b1 & nb2) + | na2 & (nb1 & b4 | b1 & nb3 | na1 & a4) & nb2 + | a1 & (na3 & (nb3 & b4 + | b1 & b2 & b3 & nb4 + | na2 & (nb3 | nb2)) + | na2 & b3 & b4 + | a2 & (nb1 & b4 | a3 & na4 & b1) & nb3); + if (coverageTestFlag && coverageTestId == 30) { + this.nullBit4 = ~0; + } + } else { // other has no null info + a1 = this.nullBit1; + this.nullBit1 = 0; + this.nullBit2 = (a2 = this.nullBit2) & (na3 = ~(a3 = this.nullBit3) | (na1 = ~a1)); + this.nullBit3 = a3 & ((na2 = ~a2) & (a4 = this.nullBit4) | na1) | a1 & na2 & ~a4; + this.nullBit4 = (na3 | na2) & na1 & a4 | a1 & na3 & na2; + if (coverageTestFlag && coverageTestId == 31) { + this.nullBit4 = ~0; + } + } + } else if (otherHasNulls) { // only other had nulls + this.nullBit1 = 0; + this.nullBit2 = (b2 = otherInits.nullBit2) & (nb3 = ~(b3 = otherInits.nullBit3) | (nb1 = ~(b1 = otherInits.nullBit1))); + this.nullBit3 = b3 & ((nb2 = ~b2) & (b4 = otherInits.nullBit4) | nb1) | b1 & nb2 & ~b4; + this.nullBit4 = (nb3 | nb2) & nb1 & b4 | b1 & nb3 & nb2; + if (coverageTestFlag && coverageTestId == 32) { + this.nullBit4 = ~0; + } + thisHasNulls = + // redundant with the three following ones + this.nullBit2 != 0 || + this.nullBit3 != 0 || + this.nullBit4 != 0; } - else { - // tune potentials - this.nullAssignmentValueBit1 = - ~(~this.nullAssignmentStatusBit1 & - ~this.nullAssignmentStatusBit2 & - ~this.nullAssignmentValueBit1) & - ~(this.nullAssignmentStatusBit1 & - (this.nullAssignmentStatusBit2 | this.nullAssignmentValueBit2)); - // reset assignment and protected - this.nullAssignmentStatusBit1 = - this.nullAssignmentStatusBit2 = 0; - if (coverageTestFlag && coverageTestId == 38) { - this.nullAssignmentValueBit2 = ~0; - } - } - thisHasNulls = this.nullAssignmentStatusBit1 != 0 || - this.nullAssignmentStatusBit2 != 0 || - this.nullAssignmentValueBit1 != 0 || - this.nullAssignmentValueBit2 != 0; // treating extra storage if (this.extra != null || otherInits.extra != null) { int mergeLimit = 0, copyLimit = 0, resetLimit = 0; + int i; if (this.extra != null) { if (otherInits.extra != null) { // both sides have extra storage @@ -1354,23 +1291,23 @@ } mergeLimit = length; copyLimit = otherLength; - if (coverageTestFlag && coverageTestId == 39) { - throw new AssertionFailedException("COVERAGE 39"); //$NON-NLS-1$ + if (coverageTestFlag && coverageTestId == 33) { + throw new AssertionFailedException("COVERAGE 33"); //$NON-NLS-1$ } } else { // current storage is longer mergeLimit = otherLength; resetLimit = length; - if (coverageTestFlag && coverageTestId == 40) { - throw new AssertionFailedException("COVERAGE 40"); //$NON-NLS-1$ + if (coverageTestFlag && coverageTestId == 34) { + throw new AssertionFailedException("COVERAGE 34"); //$NON-NLS-1$ } } } else { resetLimit = this.extra[0].length; - if (coverageTestFlag && coverageTestId == 41) { - throw new AssertionFailedException("COVERAGE 41"); //$NON-NLS-1$ + if (coverageTestFlag && coverageTestId == 35) { + throw new AssertionFailedException("COVERAGE 35"); //$NON-NLS-1$ } } } @@ -1384,114 +1321,93 @@ System.arraycopy(otherInits.extra[1], 0, this.extra[1], 0, otherLength); copyLimit = otherLength; - if (coverageTestFlag && coverageTestId == 42) { - throw new AssertionFailedException("COVERAGE 42"); //$NON-NLS-1$ + if (coverageTestFlag && coverageTestId == 36) { + throw new AssertionFailedException("COVERAGE 36"); //$NON-NLS-1$ } } - int i; - if (otherHasNulls) { - for (i = 0; i < mergeLimit; i++) { - this.extra[0][i] &= - otherInits.extra[0][i]; - this.extra[1][i] |= - otherInits.extra[1][i]; - this.extra[2][i] = - (a1 = this.extra[2][i]) & - (b1 = otherInits.extra[2][i]) & ( - (nb4 = ~(b4 = otherInits.extra[5][i])) & - ((b2 = otherInits.extra[3][i]) & - (nb3 = ~(b3 = otherInits.extra[4][i])) & - (na3 = ~(a3 = this.extra[4][i])) & - ((a2 = this.extra[3][i]) & - (na4 = ~(a4 = this.extra[5][i])) | a4) | - (na2 = ~a2) & a3 & na4 & (nb2 = ~b2) & b3 ) | - b4 & (na3 & nb3 & (na4 & a2 | a4) | - na2 & a4 & nb2)); - this.extra[3][i] = - a2 & b2 & ~(a1 ^ b1) & (na3 & nb3 | na4 & nb4) | - a1 & b1 & (a2 ^ b2) & na3 & nb3 | - (a1 & na2 & (nb1 = ~b1) & b2 | ~a1 & a2 & b1 & nb2) & na4 & nb4; - this.extra[4][i] = - b1 & nb2 & nb4 | - ~a1 & (a3 | - a2 & na3 & (b1 | nb2)) | - (a1 | na2) & nb1 & b2 & nb3 | - nb1 & b3 | - a1 & na2 & (na4 | - b1 & nb2 & (a3 | b3)); - this.extra[5][i] = - a4 | b4; - - // WORK recode if tests succeed - this.extra[4][i] &= - ~(a1 & na2 & na3 & a4 & nb1 & b2 & nb3 & nb4 - | ~a1 & a2 & na3 & na4 & b1 & nb2 & nb3 & b4); - - thisHasNulls = thisHasNulls || - this.extra[5][i] != 0 || - this.extra[2][i] != 0 || - this.extra[3][i] != 0 || - this.extra[4][i] != 0; - if (coverageTestFlag && coverageTestId == 43) { - this.extra[5][i] = ~0; - } - } + // MACRO :'b,'es/nullBit\(.\)/extra[\1 + 1][i]/g + // manage definite assignment + for (i = 0; i < mergeLimit; i++) { + this.extra[0][i] &= otherInits.extra[0][i]; + this.extra[1][i] |= otherInits.extra[1][i]; } - else { - for (i = 0; i < mergeLimit; i++) { - this.extra[0][i] &= - otherInits.extra[0][i]; - this.extra[1][i] |= - otherInits.extra[1][i]; - this.extra[4][i] = - ~(~this.extra[2][i] & - ~this.extra[3][i] & - ~this.extra[4][i]) & - ~(this.extra[2][i] & - (this.extra[3][i] | - this.extra[5][i])); - this.extra[2][i] = - this.extra[3][i] = 0; - thisHasNulls = thisHasNulls || - this.extra[4][i] != 0 || - this.extra[5][i] != 0; - if (coverageTestFlag && coverageTestId == 44) { - this.extra[5][i] = ~0; - } + for (; i < copyLimit; i++) { + this.extra[1][i] = otherInits.extra[1][i]; + } + for (; i < resetLimit; i++) { + this.extra[0][i] = 0; + } + // refine null bits requirements + if (!otherHasNulls) { + if (resetLimit < mergeLimit) { + resetLimit = mergeLimit; + } + copyLimit = 0; // no need to carry inexisting nulls + mergeLimit = 0; + } + if (!thisHadNulls) { + resetLimit = 0; // no need to reset anything + } + // compose nulls + for (i = 0; i < mergeLimit; i++) { + this.extra[1 + 1][i] = (a2 = this.extra[2 + 1][i]) & (a3 = this.extra[3 + 1][i]) + & (a4 = this.extra[4 + 1][i]) & (b1 = otherInits.extra[1 + 1][i]) + & (nb2 = ~(b2 = otherInits.extra[2 + 1][i])) + | (a1 = this.extra[1 + 1][i]) & (b1 & (a3 & a4 & (b3 = otherInits.extra[3 + 1][i]) + & (b4 = otherInits.extra[4 + 1][i]) + | (na2 = ~a2) & nb2 + & ((nb4 = ~b4) | (na4 = ~a4) + | (na3 = ~a3) & (nb3 = ~b3)) + | a2 & b2 & ((na4 | na3) & (nb4 | nb3))) + | na2 & b2 & b3 & b4); + this.extra[2 + 1][i] = b2 & (nb3 | (nb1 = ~b1) | a3 & (a4 | (na1 = ~a1)) & nb4) + | a2 & (b2 | na4 & b3 & (b4 | nb1) | na3 | na1); + this.extra[3 + 1][i] = b3 & (nb2 & b4 | nb1 | a3 & (na4 & nb4 | a4 & b4)) + | a3 & (na2 & a4 | na1) + | (a2 | na1) & b1 & nb2 & nb4 + | a1 & na2 & na4 & (b2 | nb1); + this.extra[4 + 1][i] = na3 & (nb1 & nb3 & b4 + | b1 & (nb2 & nb3 | a4 & b2 & nb4) + | na1 & a4 & (nb3 | b1 & b2)) + | a3 & a4 & (b3 & b4 | b1 & nb2) + | na2 & (nb1 & b4 | b1 & nb3 | na1 & a4) & nb2 + | a1 & (na3 & (nb3 & b4 + | b1 & b2 & b3 & nb4 + | na2 & (nb3 | nb2)) + | na2 & b3 & b4 + | a2 & (nb1 & b4 | a3 & na4 & b1) & nb3); + thisHasNulls = thisHasNulls || + this.extra[3][i] != 0 || + this.extra[4][i] != 0 || + this.extra[5][i] != 0 ; + if (coverageTestFlag && coverageTestId == 37) { + this.extra[5][i] = ~0; } } for (; i < copyLimit; i++) { - this.extra[1][i] = otherInits.extra[1][i]; - this.extra[4][i] = - ~(~otherInits.extra[2][i] & - ~otherInits.extra[3][i] & - ~otherInits.extra[4][i]) & - ~(otherInits.extra[2][i] & - (otherInits.extra[3][i] | - otherInits.extra[5][i])); - this.extra[5][i] = otherInits.extra[5][i]; + this.extra[1 + 1][i] = 0; + 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]))); + this.extra[3 + 1][i] = b3 & ((nb2 = ~b2) & (b4 = otherInits.extra[4 + 1][i]) | nb1) | b1 & nb2 & ~b4; + this.extra[4 + 1][i] = (nb3 | nb2) & nb1 & b4 | b1 & nb3 & nb2; thisHasNulls = thisHasNulls || + this.extra[3][i] != 0 || this.extra[4][i] != 0 || this.extra[5][i] != 0; - if (coverageTestFlag && coverageTestId == 45) { + if (coverageTestFlag && coverageTestId == 38) { this.extra[5][i] = ~0; } } for (; i < resetLimit; i++) { - this.extra[4][i] = - ~(~this.extra[2][i] & - ~this.extra[3][i] & - ~this.extra[4][i]) & - ~(this.extra[2][i] & - (this.extra[3][i] | - this.extra[5][i])); - this.extra[0][i] = - this.extra[2][i] = - this.extra[3][i] = 0; + a1 = this.extra[1 + 1][i]; + this.extra[1 + 1][i] = 0; + this.extra[2 + 1][i] = (a2 = this.extra[2 + 1][i]) & (na3 = ~(a3 = this.extra[3 + 1][i]) | (na1 = ~a1)); + this.extra[3 + 1][i] = a3 & ((na2 = ~a2) & (a4 = this.extra[4 + 1][i]) | na1) | a1 & na2 & ~a4; + this.extra[4 + 1][i] = (na3 | na2) & na1 & a4 | a1 & na3 & na2; thisHasNulls = thisHasNulls || + this.extra[3][i] != 0 || this.extra[4][i] != 0 || this.extra[5][i] != 0; - if (coverageTestFlag && coverageTestId == 46) { + if (coverageTestFlag && coverageTestId == 39) { this.extra[5][i] = ~0; } } @@ -1577,19 +1493,15 @@ return "FlowInfo"; //$NON-NLS-1$ } else { String def = "FlowInfo 3 ? 3 : @@ -1597,22 +1509,17 @@ i < ceil; i++) { def += "," + this.extra[0][i]; //$NON-NLS-1$ pot += "," + this.extra[1][i]; //$NON-NLS-1$ - nullS1 += "," + this.extra[2][i]; //$NON-NLS-1$ - nullS2 += "," + this.extra[3][i]; //$NON-NLS-1$ - nullV1 += "," + this.extra[4][i]; //$NON-NLS-1$ - nullV2 += "," + this.extra[5][i]; //$NON-NLS-1$ + nullS += "," + this.extra[2][i] //$NON-NLS-1$ + + this.extra[3][i] + this.extra[4][i] + this.extra[5][i]; } if (ceil < this.extra[0].length) { def += ",..."; //$NON-NLS-1$ pot += ",..."; //$NON-NLS-1$ - nullS1 += ",..."; //$NON-NLS-1$ - nullS2 += ",..."; //$NON-NLS-1$ - nullV1 += ",..."; //$NON-NLS-1$ - nullV2 += ",..."; //$NON-NLS-1$ + nullS += ",..."; //$NON-NLS-1$ } return def + pot + "], reachable:" + ((this.tagBits & UNREACHABLE) == 0) //$NON-NLS-1$ - + nullS1 + nullS2 + nullV1 + nullV2 + + nullS + "]>"; //$NON-NLS-1$ } } @@ -1659,10 +1566,10 @@ long mask; copy.definiteInits = this.definiteInits & (mask = ~((1L << limit)-1)); copy.potentialInits = this.potentialInits & mask; - copy.nullAssignmentStatusBit1 = this.nullAssignmentStatusBit1 & mask; - copy.nullAssignmentStatusBit2 = this.nullAssignmentStatusBit2 & mask; - copy.nullAssignmentValueBit1 = this.nullAssignmentValueBit1 & mask; - copy.nullAssignmentValueBit2 = this.nullAssignmentValueBit2 & mask; + copy.nullBit1 = this.nullBit1 & mask; + copy.nullBit2 = this.nullBit2 & mask; + copy.nullBit3 = this.nullBit3 & mask; + copy.nullBit4 = this.nullBit4 & mask; } // use extra vector if (this.extra == null) { Index: compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java,v retrieving revision 1.31 diff -u -r1.31 FlowInfo.java --- compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java 28 Mar 2006 20:32:37 -0000 1.31 +++ compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java 21 Apr 2006 14:13:19 -0000 @@ -141,6 +141,15 @@ /** * Check status of potential null assignment for a local. Return true if there + * is a reasonable expectation that the variable be non null at this point. + * @param local LocalVariableBinding - the binding for the checked local + * @return true if there is a reasonable expectation that local be non null at + * this point + */ +public abstract boolean isPotentiallyNonNull(LocalVariableBinding local); + +/** + * Check status of potential null assignment for a local. Return true if there * is a reasonable expectation that the variable be null at this point. This * includes the protected null case, so as to augment diagnostics, but does not * really check that someone deliberately assigned to null on any specific @@ -184,7 +193,7 @@ * @param local the checked local variable */ abstract public void markAsComparedEqualToNull(LocalVariableBinding local); - + /** * Record a field got definitely assigned. */ Index: compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java,v retrieving revision 1.25 diff -u -r1.25 ConditionalFlowInfo.java --- compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java 8 Mar 2006 09:54:00 -0000 1.25 +++ compiler/org/eclipse/jdt/internal/compiler/flow/ConditionalFlowInfo.java 21 Apr 2006 14:13:19 -0000 @@ -102,6 +102,11 @@ || initsWhenFalse.isPotentiallyAssigned(local); } +public boolean isPotentiallyNonNull(LocalVariableBinding local) { + return initsWhenTrue.isPotentiallyNonNull(local) + || initsWhenFalse.isPotentiallyNonNull(local); +} + public boolean isPotentiallyNull(LocalVariableBinding local) { return initsWhenTrue.isPotentiallyNull(local) || initsWhenFalse.isPotentiallyNull(local); Index: compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java,v retrieving revision 1.33 diff -u -r1.33 LoopingFlowContext.java --- compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java 28 Mar 2006 20:32:37 -0000 1.33 +++ compiler/org/eclipse/jdt/internal/compiler/flow/LoopingFlowContext.java 21 Apr 2006 14:13:19 -0000 @@ -121,12 +121,25 @@ Expression expression = this.nullReferences[i]; // final local variable switch (this.nullCheckTypes[i]) { + case CAN_ONLY_NON_NULL : + if (flowInfo.isDefinitelyNonNull(local)) { + this.nullReferences[i] = null; + scope.problemReporter().localVariableCannotBeNull(local, expression); + continue; + } + break; case CAN_ONLY_NULL_NON_NULL : if (flowInfo.isDefinitelyNonNull(local)) { this.nullReferences[i] = null; scope.problemReporter().localVariableCannotBeNull(local, expression); continue; } + if (flowInfo.isDefinitelyNull(local)) { + this.nullReferences[i] = null; + scope.problemReporter().localVariableCanOnlyBeNull(local, expression); + continue; + } + break; case CAN_ONLY_NULL : if (flowInfo.isDefinitelyNull(local)) { this.nullReferences[i] = null; @@ -311,11 +324,8 @@ } switch (checkType) { case CAN_ONLY_NULL_NON_NULL : - case CAN_ONLY_NULL: if (flowInfo.isDefinitelyNonNull(local)) { - if (checkType == CAN_ONLY_NULL_NON_NULL) { - scope.problemReporter().localVariableCannotBeNull(local, reference); - } + scope.problemReporter().localVariableCannotBeNull(local, reference); return; } if (flowInfo.isDefinitelyNull(local)) { @@ -325,6 +335,21 @@ if (flowInfo.isPotentiallyUnknown(local)) { return; } + if (flowInfo.isPotentiallyNonNull(local)) { + recordNullReference(local, reference,CAN_ONLY_NON_NULL); + } else { + recordNullReference(local, reference, checkType); + } + return; + case CAN_ONLY_NULL: + if (flowInfo.isPotentiallyNonNull(local) + || flowInfo.isPotentiallyUnknown(local)) { + return; + } + if (flowInfo.isDefinitelyNull(local)) { + scope.problemReporter().localVariableCanOnlyBeNull(local, reference); + return; + } recordNullReference(local, reference, checkType); return; case MAY_NULL : Index: compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java,v retrieving revision 1.51 diff -u -r1.51 FlowContext.java --- compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java 28 Mar 2006 20:32:37 -0000 1.51 +++ compiler/org/eclipse/jdt/internal/compiler/flow/FlowContext.java 21 Apr 2006 14:13:19 -0000 @@ -36,13 +36,6 @@ // preempt marks looping contexts public final static FlowContext NotContinuableContext = new FlowContext(null, null); - public static final int - CAN_ONLY_NULL_NON_NULL = 20, - // check against null and non null, with definite values -- comparisons - CAN_ONLY_NULL = 21, - // check against null, with definite values -- assignment to null - MAY_NULL = 22; - // check against null, with potential values -- NPE guard public ASTNode associatedNode; public FlowContext parent; public NullInfoRegistry initsOnFinally; @@ -468,6 +461,17 @@ } } +public static final int + CAN_ONLY_NULL_NON_NULL = 20, + // check against null and non null, with definite values -- comparisons + CAN_ONLY_NULL = 21, + // check against null, with definite values -- assignment to null + MAY_NULL = 22, + // check against null, with potential values -- NPE guard + CAN_ONLY_NON_NULL = 23; + // subcase of CAN_ONLY_NULL_NON_NULL, in which we know that the local + // may be non null + /** * Record a null reference for use by deferred checks. Only looping or * finally contexts really record that information. The context may Index: compiler/org/eclipse/jdt/internal/compiler/flow/NullInfoRegistry.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/NullInfoRegistry.java,v retrieving revision 1.3 diff -u -r1.3 NullInfoRegistry.java --- compiler/org/eclipse/jdt/internal/compiler/flow/NullInfoRegistry.java 16 Mar 2006 11:59:44 -0000 1.3 +++ compiler/org/eclipse/jdt/internal/compiler/flow/NullInfoRegistry.java 21 Apr 2006 14:13:20 -0000 @@ -24,15 +24,8 @@ * flow info presented in input of finally blocks. */ public class NullInfoRegistry extends UnconditionalFlowInfo { - // encoding of null status at this level: -// public long nullAssignmentStatusBit1; - // assigned null -// public long nullAssignmentStatusBit2; - // assigned non null -// public long nullAssignmentValueBit1; - // assigned unknown -// public long nullAssignmentValueBit2; - // message send (no NPE) + // significant states at this level: + // def. non null, def. null, def. unknown, prot. non null // PREMATURE implement coverage and low level tests @@ -46,38 +39,32 @@ */ public NullInfoRegistry(UnconditionalFlowInfo upstream) { if ((upstream.tagBits & NULL_FLAG_MASK) != 0) { - long a1, a2, a3, b1nb2, b3, b4; - a1 = this.nullAssignmentStatusBit1 = - (b1nb2 = upstream.nullAssignmentStatusBit1 - & ~upstream.nullAssignmentStatusBit2) - & (b3 = upstream.nullAssignmentValueBit1) - & ~(b4 = upstream.nullAssignmentValueBit2); - a2 = this.nullAssignmentStatusBit2 = - b1nb2 & ~b3 & b4; - a3 = this.nullAssignmentValueBit1 = - b1nb2 & b3 & b4; - if ((a1 | a2 | a3) != 0) { + long u1, u2, u3, u4, nu2, nu3, nu4; + this.nullBit2 = (u1 = upstream.nullBit1) + & (u2 = upstream.nullBit2) + & (nu3 = ~(u3 = upstream.nullBit3)) + & (nu4 = ~(u4 = upstream.nullBit4)); + this.nullBit3 = u1 & (nu2 = ~u2) & u3 & nu4; + this.nullBit4 = u1 & nu2 &nu3 & u4; + if ((this.nullBit2 | this.nullBit3 | this.nullBit4) != 0) { this.tagBits |= NULL_FLAG_MASK; } if (upstream.extra != null) { this.extra = new long[extraLength][]; - int length= upstream.extra[2].length; + int length = upstream.extra[2].length; for (int i = 2; i < extraLength; i++) { this.extra[i] = new long[length]; } for (int i = 0; i < length; i++) { - a1 = this.extra[2][i] = - (b1nb2 = upstream.extra[2][i] - & ~upstream.extra[3][i]) - & (b3 = upstream.extra[4][i]) - & ~(b4 = upstream.extra[5][i]); - a2 = this.extra[3][i] = - b1nb2 & ~b3 & b4; - a3 = this.extra[4][i] = - b1nb2 & b3 & b4; - if ((a1 | a2 | a3) != 0) { - this.tagBits |= NULL_FLAG_MASK; - } + this.extra[2 + 1][i] = (u1 = upstream.extra[1 + 1][i]) + & (u2 = upstream.extra[2 + 1][i]) + & (nu3 = ~(u3 = upstream.extra[3 + 1][i])) + & (nu4 = ~(u4 = upstream.extra[4 + 1][i])); + this.extra[3 + 1][i] = u1 & (nu2 = ~u2) & u3 & nu4; + this.extra[4 + 1][i] = u1 & nu2 &nu3 & u4; + if ((this.extra[2 + 1][i] | this.extra[3 + 1][i] | this.extra[4 + 1][i]) != 0) { + this.tagBits |= NULL_FLAG_MASK; + } } } } @@ -94,10 +81,10 @@ return this; } this.tagBits |= NULL_FLAG_MASK; - this.nullAssignmentStatusBit1 |= other.nullAssignmentStatusBit1; - this.nullAssignmentStatusBit2 |= other.nullAssignmentStatusBit2; - this.nullAssignmentValueBit1 |= other.nullAssignmentValueBit1; - this.nullAssignmentValueBit2 |= other.nullAssignmentValueBit2; + this.nullBit1 |= other.nullBit1; + this.nullBit2 |= other.nullBit2; + this.nullBit3 |= other.nullBit3; + this.nullBit4 |= other.nullBit4; if (other.extra != null) { if (this.extra == null) { this.extra = new long[extraLength][]; @@ -128,142 +115,167 @@ } public void markAsComparedEqualToNonNull(LocalVariableBinding local) { - this.tagBits |= NULL_FLAG_MASK; - int position; - // position is zero-based - if ((position = local.id + this.maxFieldCount) < BitCacheSize) { - // use bits - this.nullAssignmentValueBit2 |= (1L << position); - } - else { - // use extra vector - int vectorIndex = (position / BitCacheSize) - 1; - if (this.extra == null) { - int length = vectorIndex + 1; - this.extra = new long[extraLength][]; - for (int j = 2 /* do not care about non null info */; - j < extraLength; j++) { - this.extra[j] = new long[length]; - } - } - else { - int oldLength; - if (vectorIndex >= (oldLength = this.extra[2].length)) { - int newLength = vectorIndex + 1; - for (int j = 2 /* do not care about non null info */; - j < extraLength; j++) { - System.arraycopy(this.extra[j], 0, - (this.extra[j] = new long[newLength]), 0, - oldLength); + // protected from non-object locals in calling methods + if (this != DEAD_END) { + this.tagBits |= NULL_FLAG_MASK; + int position; + // position is zero-based + if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits + // set protected non null + this.nullBit1 |= (1L << position); + if (coverageTestFlag && coverageTestId == 290) { + this.nullBit1 = 0; + } + } + else { + // use extra vector + int vectorIndex = (position / BitCacheSize) - 1; + if (this.extra == null) { + int length = vectorIndex + 1; + this.extra = new long[extraLength][]; + for (int j = 2; j < extraLength; j++) { + this.extra[j] = new long[length]; + } + } + else { + int oldLength; // might need to grow the arrays + if (vectorIndex >= (oldLength = this.extra[2].length)) { + for (int j = 2; j < extraLength; j++) { + System.arraycopy(this.extra[j], 0, + (this.extra[j] = new long[vectorIndex + 1]), 0, + oldLength); + } } } - } - this.extra[5][vectorIndex] |= (1L << (position % BitCacheSize)); + this.extra[2][vectorIndex] |= (1L << (position % BitCacheSize)); + if (coverageTestFlag && coverageTestId == 300) { + this.extra[5][vectorIndex] = ~0; + } + } } } public void markAsDefinitelyNonNull(LocalVariableBinding local) { - this.tagBits |= NULL_FLAG_MASK; - int position; - // position is zero-based - if ((position = local.id + this.maxFieldCount) < BitCacheSize) { - // use bits - this.nullAssignmentStatusBit2 |= (1L << position); - } - else { - // use extra vector - int vectorIndex = (position / BitCacheSize) - 1; - if (this.extra == null) { - int length = vectorIndex + 1; - this.extra = new long[extraLength][]; - for (int j = 2 /* do not care about non null info */; - j < extraLength; j++) { - this.extra[j] = new long[length]; - } - } - else { - int oldLength; - if (vectorIndex >= (oldLength = this.extra[2].length)) { - int newLength = vectorIndex + 1; - for (int j = 2 /* do not care about non null info */; - j < extraLength; j++) { - System.arraycopy(this.extra[j], 0, - (this.extra[j] = new long[newLength]), 0, - oldLength); + // protected from non-object locals in calling methods + if (this != DEAD_END) { + this.tagBits |= NULL_FLAG_MASK; + int position; + // position is zero-based + if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits + // set assigned non null + this.nullBit3 |= (1L << position); + if (coverageTestFlag && coverageTestId == 290) { + this.nullBit1 = 0; + } + } + else { + // use extra vector + int vectorIndex = (position / BitCacheSize) - 1; + if (this.extra == null) { + int length = vectorIndex + 1; + this.extra = new long[extraLength][]; + for (int j = 2; j < extraLength; j++) { + this.extra[j] = new long[length]; + } + } + else { + int oldLength; // might need to grow the arrays + if (vectorIndex >= (oldLength = this.extra[2].length)) { + for (int j = 2; j < extraLength; j++) { + System.arraycopy(this.extra[j], 0, + (this.extra[j] = new long[vectorIndex + 1]), 0, + oldLength); + } } } - } - this.extra[3][vectorIndex] |= (1L << (position % BitCacheSize)); + this.extra[4][vectorIndex] |= (1L << (position % BitCacheSize)); + if (coverageTestFlag && coverageTestId == 300) { + this.extra[5][vectorIndex] = ~0; + } + } } } - +// PREMATURE consider ignoring extra 0 to 2 included - means a1 should not be used either +// PREMATURE project protected non null onto something else public void markAsDefinitelyNull(LocalVariableBinding local) { - this.tagBits |= NULL_FLAG_MASK; - int position; - // position is zero-based - if ((position = local.id + this.maxFieldCount) < BitCacheSize) { - // use bits - this.nullAssignmentStatusBit1 |= (1L << position); - } - else { - // use extra vector - int vectorIndex = (position / BitCacheSize) - 1; - if (this.extra == null) { - int length = vectorIndex + 1; - this.extra = new long[extraLength][]; - for (int j = 2 /* do not care about non null info */; - j < extraLength; j++) { - this.extra[j] = new long[length]; - } - } - else { - int oldLength; - if (vectorIndex >= (oldLength = this.extra[2].length)) { - int newLength = vectorIndex + 1; - for (int j = 2 /* do not care about non null info */; - j < extraLength; j++) { - System.arraycopy(this.extra[j], 0, - (this.extra[j] = new long[newLength]), 0, - oldLength); + // protected from non-object locals in calling methods + if (this != DEAD_END) { + this.tagBits |= NULL_FLAG_MASK; + int position; + // position is zero-based + if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits + // set assigned null + this.nullBit2 |= (1L << position); + if (coverageTestFlag && coverageTestId == 290) { + this.nullBit1 = 0; + } + } + else { + // use extra vector + int vectorIndex = (position / BitCacheSize) - 1; + if (this.extra == null) { + int length = vectorIndex + 1; + this.extra = new long[extraLength][]; + for (int j = 2; j < extraLength; j++) { + this.extra[j] = new long[length]; + } + } + else { + int oldLength; // might need to grow the arrays + if (vectorIndex >= (oldLength = this.extra[2].length)) { + for (int j = 2; j < extraLength; j++) { + System.arraycopy(this.extra[j], 0, + (this.extra[j] = new long[vectorIndex + 1]), 0, + oldLength); + } } } - } - this.extra[2][vectorIndex] |= (1L << (position % BitCacheSize)); + this.extra[3][vectorIndex] |= (1L << (position % BitCacheSize)); + if (coverageTestFlag && coverageTestId == 300) { + this.extra[5][vectorIndex] = ~0; + } + } } } public void markAsDefinitelyUnknown(LocalVariableBinding local) { - this.tagBits |= NULL_FLAG_MASK; - int position; - // position is zero-based - if ((position = local.id + this.maxFieldCount) < BitCacheSize) { - // use bits - this.nullAssignmentValueBit1 |= (1L << position); - } - else { - // use extra vector - int vectorIndex = (position / BitCacheSize) - 1; - if (this.extra == null) { - int length = vectorIndex + 1; - this.extra = new long[extraLength][]; - for (int j = 2 /* do not care about non null info */; - j < extraLength; j++) { - this.extra[j] = new long[length]; - } - } - else { - int oldLength; - if (vectorIndex >= (oldLength = this.extra[2].length)) { - int newLength = vectorIndex + 1; - for (int j = 2 /* do not care about non null info */; - j < extraLength; j++) { - System.arraycopy(this.extra[j], 0, - (this.extra[j] = new long[newLength]), 0, - oldLength); + // protected from non-object locals in calling methods + if (this != DEAD_END) { + this.tagBits |= NULL_FLAG_MASK; + int position; + // position is zero-based + if ((position = local.id + this.maxFieldCount) < BitCacheSize) { // use bits + // set assigned unknown + this.nullBit4 |= (1L << position); + if (coverageTestFlag && coverageTestId == 290) { + this.nullBit1 = 0; + } + } + else { + // use extra vector + int vectorIndex = (position / BitCacheSize) - 1; + if (this.extra == null) { + int length = vectorIndex + 1; + this.extra = new long[extraLength][]; + for (int j = 2; j < extraLength; j++) { + this.extra[j] = new long[length]; + } + } + else { + int oldLength; // might need to grow the arrays + if (vectorIndex >= (oldLength = this.extra[2].length)) { + for (int j = 2; j < extraLength; j++) { + System.arraycopy(this.extra[j], 0, + (this.extra[j] = new long[vectorIndex + 1]), 0, + oldLength); + } } } - } - this.extra[4][vectorIndex] |= (1L << (position % BitCacheSize)); + this.extra[5][vectorIndex] |= (1L << (position % BitCacheSize)); + if (coverageTestFlag && coverageTestId == 300) { + this.extra[5][vectorIndex] = ~0; + } + } } } @@ -281,58 +293,32 @@ if ((this.tagBits & NULL_FLAG_MASK) == 0) { return flowInfo.unconditionalInits(); } -// // Reference implementation -// UnconditionalFlowInfo source = flowInfo.unconditionalCopy(); -// long mask; -// // clear uncompatible protections -// mask = source.nullAssignmentStatusBit1 & source.nullAssignmentStatusBit2 -// // prot. non null -// & (this.nullAssignmentStatusBit1 | this.nullAssignmentValueBit1); -// // null or unknown -// source.nullAssignmentStatusBit1 &= ~mask; -// source.nullAssignmentStatusBit2 &= ~mask; -// mask = ~source.nullAssignmentStatusBit1 & source.nullAssignmentStatusBit2 -// // prot. null -// & (this.nullAssignmentStatusBit2 | this.nullAssignmentValueBit1 -// | this.nullAssignmentValueBit2); -// // non null or unknown -// source.nullAssignmentStatusBit2 &= ~mask; -// // clear uncompatible assignments -// mask = source.nullAssignmentStatusBit1 & ~source.nullAssignmentStatusBit2 -// & (source.nullAssignmentValueBit1 & ~source.nullAssignmentValueBit2 -// & (this.nullAssignmentStatusBit2 | this.nullAssignmentValueBit1 -// | this.nullAssignmentValueBit2) -// | ~source.nullAssignmentValueBit1 & source.nullAssignmentValueBit2 -// & (this.nullAssignmentStatusBit1 | this.nullAssignmentValueBit1) -// | source.nullAssignmentValueBit1 & source.nullAssignmentValueBit2 -// & (this.nullAssignmentStatusBit1)); -// source.nullAssignmentStatusBit1 &= ~mask; - long m1, m2, m3, a1, a2, a3, a4, s1, s2, s3, s4; + long m, m1, nm1, m2, nm2, m3, a2, a3, a4, s1, s2, ns2, s3, ns3, s4, ns4; boolean newCopy = false; UnconditionalFlowInfo source = flowInfo.unconditionalInits(); - // clear uncompatible protections - m1 = (s1 = source.nullAssignmentStatusBit1) - & (s2 = source.nullAssignmentStatusBit2) + // clear incompatible protections + m1 = (s1 = source.nullBit1) & (s3 = source.nullBit3) + & (s4 = source.nullBit4) // prot. non null - & ((a1 = this.nullAssignmentStatusBit1) - | (a3 = this.nullAssignmentValueBit1)); + & ((a2 = this.nullBit2) | (a4 = this.nullBit4)); // null or unknown - m2 = ~s1 & s2 + m2 = s1 & (s2 = this.nullBit2) & (s3 ^ s4) // prot. null - & ((a2 = this.nullAssignmentStatusBit2) | a3 - | (a4 = this.nullAssignmentValueBit2)); + & ((a3 = this.nullBit3) | a4); // non null or unknown - // clear uncompatible assignments - m3 = s1 & ~s2 - & ((s3 = source.nullAssignmentValueBit1) - & ~(s4 = source.nullAssignmentValueBit2) - & (a2 | a3 | a4) - | s4 & (~s3 & a3 | a1)); - if ((m1 | m2 | m3) != 0) { + // clear incompatible assignments + // PREMATURE check effect of protected non null (no NPE on call) + // TODO (maxime) code extensive implementation tests + m3 = s1 & (s2 & (ns3 = ~s3) & (ns4 = ~s4) & (a3 | a4) + | (ns2 = ~s2) & s3 & ns4 & (a2 | a4) + | ns2 & ns3 & s4 & (a2 | a3)); + if ((m = (m1 | m2 | m3)) != 0) { newCopy = true; source = source.unconditionalCopy(); - source.nullAssignmentStatusBit1 &= ~(m1 | m3); - source.nullAssignmentStatusBit2 &= ~(m1 | m2); + source.nullBit1 &= ~m; + source.nullBit2 &= (nm1 = ~m1) & ((nm2 = ~m2) | a4); + source.nullBit3 &= (nm1 | a2) & nm2; + source.nullBit4 &= nm1 & nm2; } if (this.extra != null && source.extra != null) { int length = this.extra[2].length, sourceLength = source.extra[0].length; @@ -340,29 +326,24 @@ length = sourceLength; } for (int i = 0; i < length; i++) { - // clear uncompatible protections - m1 = (s1 = source.extra[2][i]) & (s2 = source.extra[3][i]) - // prot. non null - & ((a1 = this.extra[2][i]) | (a3 = this.extra[4][i])); - // null or unknown - m2 = ~s1 & s2 - // prot. null - & ((a2 = this.extra[3][i]) | a3 - | (a4 = this.extra[5][i])); - // non null or unknown - // clear uncompatible assignments - m3 = s1 & ~s2 - & ((s3 = source.extra[4][i]) & ~(s4 = source.extra[5][i]) - & (a2 | a3 | a4) - | s4 & (~s3 & a3 | a1)); - if ((m1 | m2 | m3) != 0) { - if (!newCopy) { - newCopy = true; - source = source.unconditionalCopy(); - } - source.extra[2][i] &= ~(m1 | m3); - source.extra[3][i] &= ~(m1 | m2); - } + m1 = (s1 = source.extra[1 + 1][i]) & (s3 = source.extra[3 + 1][i]) + & (s4 = source.extra[4 + 1][i]) + & ((a2 = this.extra[2 + 1][i]) | (a4 = this.extra[4 + 1][i])); + m2 = s1 & (s2 = this.extra[2 + 1][i]) & (s3 ^ s4) + & ((a3 = this.extra[3 + 1][i]) | a4); + m3 = s1 & (s2 & (ns3 = ~s3) & (ns4 = ~s4) & (a3 | a4) + | (ns2 = ~s2) & s3 & ns4 & (a2 | a4) + | ns2 & ns3 & s4 & (a2 | a3)); + if ((m = (m1 | m2 | m3)) != 0) { + if (! newCopy) { + newCopy = true; + source = source.unconditionalCopy(); + } + source.extra[1 + 1][i] &= ~m; + source.extra[2 + 1][i] &= (nm1 = ~m1) & ((nm2 = ~m2) | a4); + source.extra[3 + 1][i] &= (nm1 | a2) & nm2; + source.extra[4 + 1][i] &= nm1 & nm2; + } } } return source; @@ -370,35 +351,25 @@ public String toString(){ if (this.extra == null) { - return "NullInfoRegistry"; //$NON-NLS-1$ + return "NullInfoRegistry<" + this.nullBit1 //$NON-NLS-1$ + + this.nullBit2 + this.nullBit3 + this.nullBit4 + + ">"; //$NON-NLS-1$ } else { - String nullS1 = "NullInfoRegistry 3 ? - 3 : - this.extra[0].length; - i < ceil; i++) { - nullS1 += "," + this.extra[2][i]; //$NON-NLS-1$ - nullS2 += "," + this.extra[3][i]; //$NON-NLS-1$ - nullV1 += "," + this.extra[4][i]; //$NON-NLS-1$ - nullV2 += "," + this.extra[5][i]; //$NON-NLS-1$ - } - if (ceil < this.extra[0].length) { - nullS1 += ",..."; //$NON-NLS-1$ - nullS2 += ",..."; //$NON-NLS-1$ - nullV1 += ",..."; //$NON-NLS-1$ - nullV2 += ",..."; //$NON-NLS-1$ - } - return nullS1 + nullS2 + nullV1 + nullV2 - + "]>"; //$NON-NLS-1$ + String nullS = "NullInfoRegistry<[" + this.nullBit1 //$NON-NLS-1$ + + this.nullBit2 + this.nullBit3 + this.nullBit4; + int i, ceil; + for (i = 0, ceil = this.extra[0].length > 3 ? + 3 : + this.extra[0].length; + i < ceil; i++) { + nullS += "," + this.extra[2][i] //$NON-NLS-1$ + + this.extra[3][i] + this.extra[4][i] + this.extra[5][i]; + } + if (ceil < this.extra[0].length) { + nullS += ",..."; //$NON-NLS-1$ + } + return nullS + "]>"; //$NON-NLS-1$ } } } Index: compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java,v retrieving revision 1.64 diff -u -r1.64 EqualExpression.java --- compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java 28 Mar 2006 20:29:56 -0000 1.64 +++ compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java 21 Apr 2006 14:13:19 -0000 @@ -113,7 +113,8 @@ } if (result instanceof UnconditionalFlowInfo && (result.tagBits & FlowInfo.UNREACHABLE) == 0) { // the flow info is flat - result = FlowInfo.conditional(result, result.copy()); + result = FlowInfo.conditional(result.copy(), result.copy()); + // TODO (maxime) check, reintroduced copy } checkNullComparison(currentScope, flowContext, result, result.initsWhenTrue(), result.initsWhenFalse()); return result; Index: compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java,v retrieving revision 1.48 diff -u -r1.48 InstanceOfExpression.java --- compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java 28 Mar 2006 20:29:56 -0000 1.48 +++ compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java 21 Apr 2006 14:13:19 -0000 @@ -41,10 +41,10 @@ this.expression, FlowContext.CAN_ONLY_NULL, flowInfo); flowInfo = expression.analyseCode(currentScope, flowContext, flowInfo). unconditionalInits(); - FlowInfo initsWhenFalse = flowInfo.copy(); - flowInfo.markAsComparedEqualToNonNull(local); + FlowInfo initsWhenTrue = flowInfo.copy(); + initsWhenTrue.markAsComparedEqualToNonNull(local); // no impact upon enclosing try context - return FlowInfo.conditional(flowInfo, initsWhenFalse); + return FlowInfo.conditional(initsWhenTrue, flowInfo.copy()); } return expression.analyseCode(currentScope, flowContext, flowInfo). unconditionalInits(); Index: .settings/org.eclipse.jdt.core.prefs =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/.settings/org.eclipse.jdt.core.prefs,v retrieving revision 1.7 diff -u -r1.7 org.eclipse.jdt.core.prefs --- .settings/org.eclipse.jdt.core.prefs 17 Feb 2006 16:06:06 -0000 1.7 +++ .settings/org.eclipse.jdt.core.prefs 21 Apr 2006 14:13:19 -0000 @@ -1,4 +1,4 @@ -#Fri Feb 17 16:48:15 CET 2006 +#Mon Mar 20 16:28:55 CET 2006 eclipse.preferences.version=1 org.eclipse.jdt.core.builder.cleanOutputFolder=clean org.eclipse.jdt.core.builder.duplicateResourceTask=warning #P org.eclipse.jdt.core.tests.compiler Index: .settings/org.eclipse.jdt.core.prefs =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/.settings/org.eclipse.jdt.core.prefs,v retrieving revision 1.10 diff -u -r1.10 org.eclipse.jdt.core.prefs --- .settings/org.eclipse.jdt.core.prefs 30 Sep 2005 14:41:40 -0000 1.10 +++ .settings/org.eclipse.jdt.core.prefs 21 Apr 2006 14:13:23 -0000 @@ -1,4 +1,4 @@ -#Fri Sep 30 16:39:41 CEST 2005 +#Thu Feb 23 14:36:02 CET 2006 eclipse.preferences.version=1 org.eclipse.jdt.core.builder.cleanOutputFolder=clean org.eclipse.jdt.core.builder.duplicateResourceTask=warning @@ -66,5 +66,251 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning org.eclipse.jdt.core.compiler.source=1.3 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=1 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false +org.eclipse.jdt.core.formatter.comment.format_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=80 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false org.eclipse.jdt.core.incompatibleJDKLevel=ignore org.eclipse.jdt.core.incompleteClasspath=error Index: src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java,v retrieving revision 1.60 diff -u -r1.60 AbstractRegressionTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java 7 Apr 2006 09:03:47 -0000 1.60 +++ src/org/eclipse/jdt/core/tests/compiler/regression/AbstractRegressionTest.java 21 Apr 2006 14:13:23 -0000 @@ -832,7 +832,8 @@ // start with the current directory which contains the source files Process compileProcess = Runtime.getRuntime().exec( cmdLineHeader.toString() + " -version", null, null); - Logger versionLogger = new Logger(compileProcess.getErrorStream(), ""); // WORK + Logger versionLogger = new Logger(compileProcess.getErrorStream(), ""); + // PREMATURE implement consistent error policy versionLogger.start(); compileProcess.waitFor(); versionLogger.join(); // make sure we get the whole output @@ -1148,8 +1149,9 @@ javaCmdLine.append(' ').append(testFiles[0].substring(0, testFiles[0].indexOf('.'))); // assume executable class is name of first test file - PREMATURE check if this is also the case in other test fwk classes execProcess = Runtime.getRuntime().exec(javaCmdLine.toString(), null, this.outputTestDirectoryPath.toFile()); - Logger logger = new Logger(execProcess.getInputStream(), ""); // WORK - logger.start(); + Logger logger = new Logger(execProcess.getInputStream(), ""); + // PREMATURE implement consistent error policy + logger.start(); exitValue = execProcess.waitFor(); logger.join(); // make sure we get the whole output String javaOutput = logger.buffer.toString().trim(); Index: src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java,v retrieving revision 1.33 diff -u -r1.33 NullReferenceTest.java --- src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java 6 Apr 2006 08:38:51 -0000 1.33 +++ src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceTest.java 21 Apr 2006 14:13:24 -0000 @@ -11,16 +11,11 @@ package org.eclipse.jdt.core.tests.compiler.regression; import java.util.Map; - -import org.eclipse.jdt.internal.compiler.flow.FlowInfo; -import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo; -import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo.AssertionFailedException; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; -import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; - -import junit.framework.AssertionFailedError; import junit.framework.Test; +/* See also NullReferenceImplTests for low level, implementation dependent + * tests. */ public class NullReferenceTest extends AbstractRegressionTest { public NullReferenceTest(String name) { @@ -1730,15 +1725,6 @@ } // null analysis - if/else -// PMT: exactly the case we talked about; what happens is that the first -// if shade doubts upon o; what we could do is to avoid marking in case -// of error? not sure this is appropriate though, because of inner code -// into the if itself; I believe I somewhat did that on purpose: the latest -// wins; completed with o.toString()... -// basically, the choice is about what we should do in case of error: -// neglect the effect of the error, or propagate this effect; the second -// tends to produce less repeated errors (I believe) than the first... -// PREMATURE could refine adding a null-dependent reachable mark... not urgent public void test0312_if_else() { this.runNegativeTest( new String[] { @@ -1748,8 +1734,8 @@ " void foo() {\n" + " Object o = new Object();\n" + " if (o == null) { /* */ }\n" + // complain - " if (o != null) { /* */ }\n" + // quiet - " o.toString();\n" + // complain + " if (o != null) { /* */ }\n" + + " o.toString();\n" + " }\n" + "}\n"}, "----------\n" + @@ -2376,6 +2362,100 @@ ""); } +// null analysis - if/else nested with unknown protection: unknown cannot protect +public void test0339_if_else_nested() { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo(Object o, boolean b) {\n" + + " if (o == null || b) {\n" + + " if (bar() == o) {\n" + + " o.toString();\n" + + " }\n" + + " }\n" + + " }\n" + + " Object bar() {\n" + + " return new Object();\n" + + " }\n" + + "}"}, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + " o.toString();\n" + + " ^\n" + + "The variable o may be null\n" + + "----------\n"); +} + +// null analysis - if/else nested +public void test0340_if_else_nested() { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo(Object o) {\n" + + " if (o == null) {\n" + + " if (bar() == o) {\n" + + " o.toString();\n" + + " }\n" + + " }\n" + + " }\n" + + " Object bar() {\n" + + " return new Object();\n" + + " }\n" + + "}"}, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + " o.toString();\n" + + " ^\n" + + "The variable o can only be null; it was either set to null or checked for null when last used\n" + + "----------\n"); +} + +// null analysis - if/else nested +public void test0341_if_else_nested() { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo(Object o1, Object o2, boolean b) {\n" + + " if (o1 == null || b) {\n" + + " if (o1 == o2) {\n" + + " o1.toString();\n" + + " }\n" + + " }\n" + + " }\n" + + "}"}, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + " o1.toString();\n" + + " ^^\n" + + "The variable o1 may be null\n" + + "----------\n"); +} + +// null analysis - if/else nested +public void test0342_if_else_nested() { + this.runNegativeTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo(Object o1, Object o2, boolean b) {\n" + + " if (o1 == null || b) {\n" + + " if (o2 == o1) {\n" + + " o1.toString();\n" + + " }\n" + + " }\n" + + " }\n" + + "}"}, + "----------\n" + + "1. ERROR in X.java (at line 5)\n" + + " o1.toString();\n" + + " ^^\n" + + "The variable o1 may be null\n" + + "----------\n"); +} + // null analysis -- while public void test0401_while() { this.runNegativeTest( @@ -3511,7 +3591,8 @@ // null analysis - while // TODO (maxime) https://bugs.eclipse.org/bugs/show_bug.cgi?id=133131 -public void _test0451_while_nested() { +// fixed along 127570, do the reporting +public void test0451_while_nested() { this.runNegativeTest( new String[] { "X.java", @@ -3526,7 +3607,12 @@ " if (o != null) { /* */ }\n" + " }\n" + "}"}, - "ERR"); + "----------\n" + + "1. ERROR in X.java (at line 9)\n" + + " if (o != null) { /* */ }\n" + + " ^\n" + + "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" + + "----------\n"); } // TODO (maxime) https://bugs.eclipse.org/bugs/show_bug.cgi?id=123399 @@ -5357,9 +5443,10 @@ } // null analysis -- for -// contrast this with #311 +// changed with https://bugs.eclipse.org/bugs/show_bug.cgi?id=127570 +// we are now able to see that x2 is reinitialized with x1, which is unknown public void test0726_for() { - this.runNegativeTest( + this.runConformTest( new String[] { "X.java", "public class X {\n" + @@ -5373,12 +5460,7 @@ " }\n" + " }\n" + "}\n"}, - "----------\n" + - "1. ERROR in X.java (at line 8)\n" + - " x2.toString();\n" + - " ^^\n" + - "The variable x2 may be null\n" + - "----------\n"); + ""); } // null analysis -- for @@ -5587,6 +5669,89 @@ } } +// null analysis - for +// https://bugs.eclipse.org/bugs/show_bug.cgi?id=127570 +public void test0736_for_embedded_lazy_init() { + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " public boolean foo() {\n" + + " Boolean b = null;\n" + + " for (int i = 0; i < 1; i++) {\n" + + " if (b == null) {\n" + + " b = Boolean.TRUE;\n" + + " }\n" + + " if (b.booleanValue()) {\n" + // quiet + " return b.booleanValue();\n" + + " }\n" + + " }\n" + + " return false;\n" + + " }\n" + + "}"}, + ""); +} + +// null analysis - for with unknown protection: unknown cannot protect anything +// suggested by https://bugs.eclipse.org/bugs/show_bug.cgi?id=127570 +public void test0737_for_unknown_protection() { + this.runNegativeTest( + new String[] { + "X.java", + "class X {\n" + + " public boolean foo(Boolean p) {\n" + + " Boolean b = null;\n" + + " for (int i = 0; i < 1; i++) {\n" + + " if (b == p) {\n" + // tells us that p is null as well + " // empty\n" + + " }\n" + + " else {\n" + + " continue;\n" + + " }\n" + + " if (b.booleanValue()) {\n" + // complain b can only be null + " return b.booleanValue();\n" + + " }\n" + + " }\n" + + " return false;\n" + + " }\n" + + "}"}, + "----------\n" + + "1. ERROR in X.java (at line 11)\n" + + " if (b.booleanValue()) {\n" + + " ^\n" + + "The variable b can only be null; it was either set to null or checked for null when last used\n" + + "----------\n"); +} + +// null analysis - for with unknown protection +// suggested by https://bugs.eclipse.org/bugs/show_bug.cgi?id=127570 +// the issue is that we cannot do less than full aliasing analysis to +// catch this one +// TODO (maxime) reconsider when/if we bring full aliasing in +public void _test0738_for_unknown_protection() { + this.runConformTest( + new String[] { + "X.java", + "class X {\n" + + " public boolean foo(Boolean p) {\n" + + " Boolean b = null;\n" + + " for (int i = 0; i < 1; i++) {\n" + + " if (b == p) {\n" + + " // empty\n" + + " }\n" + + " else {\n" + + " b = p;\n" + + " }\n" + + " if (b.booleanValue()) {\n" + // quiet because b is an alias for p, unknown + " return b.booleanValue();\n" + + " }\n" + + " }\n" + + " return false;\n" + + " }\n" + + "}"}, + ""); +} + // null analysis -- switch public void test0800_switch() { this.runConformTest( @@ -7035,6 +7200,109 @@ "----------\n"); } +// encoding validation +public void test1500() { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo(Object o, int i, boolean b, Object u) {\n" + + " o.toString();\n" + + " switch (i) {\n" + + " case 0:\n" + + " if (b) {\n" + + " o = u;\n" + + " } else {\n" + + " o = new Object();\n" + + " }\n" + + " break;\n" + + " }\n" + + " if (o == null) { /* empty */ }\n" + + " }\n" + + "}\n"}, + ""); +} + +// encoding validation +public void test1501() { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo(Object o, int i, boolean b, Object u) {\n" + + " if (b) {\n" + + " o = new Object();\n" + + " }\n" + + " o.toString();\n" + + " switch (i) {\n" + + " case 0:\n" + + " if (b) {\n" + + " o = u;\n" + + " } else {\n" + + " o = new Object();\n" + + " }\n" + + " break;\n" + + " }\n" + + " if (o == null) { /* empty */ }\n" + + " }\n" + + "}\n"}, + ""); +} + +// encoding validation +public void test1502() { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo(Object o, int i, boolean b, Object u) {\n" + + " if (b) {\n" + + " o = u;\n" + + " }\n" + + " o.toString();\n" + + " switch (i) {\n" + + " case 0:\n" + + " if (b) {\n" + + " o = u;\n" + + " } else {\n" + + " o = new Object();\n" + + " }\n" + + " break;\n" + + " }\n" + + " if (o == null) { /* empty */ }\n" + + " }\n" + + "}\n"}, + ""); +} + +// encoding validation +public void test1503() { + this.runConformTest( + new String[] { + "X.java", + "public class X {\n" + + " void foo(Object o, int i, boolean b, Object u) {\n" + + " if (b) {\n" + + " o = u;\n" + + " } else {\n" + + " o = new Object();\n" + + " }\n" + + " o.toString();\n" + + " switch (i) {\n" + + " case 0:\n" + + " if (b) {\n" + + " o = u;\n" + + " } else {\n" + + " o = new Object();\n" + + " }\n" + + " break;\n" + + " }\n" + + " if (o == null) { /* empty */ }\n" + + " }\n" + + "}\n"}, + ""); +} + // flow info low-level validation public void test2000_flow_info() { this.runNegativeTest( @@ -7058,7 +7326,7 @@ " o60 = o0, o61 = o0, o62 = o0, o63 = o0, o64 = o0,\n" + " o65 = o0, o66 = o0, o67 = o0, o68 = o0, o69 = o0;\n" + " if (o65 == null) { /* */ }\n" + // complain - " if (o65 != null) { /* */ }\n" + // quiet (already reported) + " if (o65 != null) { /* */ }\n" + " }\n" + "}\n"}, "----------\n" + @@ -7782,2197 +8050,4 @@ "The variable o1 may be null\n" + "----------\n"); } - -// Technical tests -- only available with patched sources -static final boolean - printTablesAsNames = false, - printTablesAsCodes = false, - printTruthMaps = false; -static final int - combinationTestsloopsNb = 1; // define to 10000s to measure performances - - -public void test2050_markAsComparedEqualToNonNull() { - long [][][] testData = { - {{0,0,0,0},{1,1,0,0}}, - {{0,0,0,1},{1,1,0,1}}, - {{0,0,1,0},{1,1,0,0}}, - {{0,0,1,1},{1,1,0,1}}, - {{0,1,0,0},{1,1,0,0}}, - {{0,1,0,1},{1,1,0,1}}, - {{0,1,1,0},{1,1,0,0}}, - {{0,1,1,1},{1,1,0,1}}, - {{1,0,0,0},{1,1,0,0}}, - {{1,0,0,1},{1,0,0,1}}, - {{1,0,1,0},{1,1,0,0}}, - {{1,0,1,1},{1,1,0,1}}, - {{1,1,0,0},{1,1,0,0}}, - {{1,1,0,1},{1,1,0,1}}, - {{1,1,1,0},{1,1,0,0}}, - {{1,1,1,1},{1,1,0,1}}, - }; - int failures = 0; - LocalVariableBinding local = new TestLocalVariableBinding(0); - for (int i = 0; i < testData.length; i++) { - UnconditionalFlowInfoTestHarness - result = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0]); - result.markAsComparedEqualToNonNull(local); - if (!(result.testEquals(UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1])))) { - if (failures == 0) { - System.out.println("markAsComparedEqualToNonNull failures: "); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + result.testString() + - "}, // instead of: " + testStringValueOf(testData[i][1])); - } - } - local = new TestLocalVariableBinding(64); - for (int i = 0; i < testData.length; i++) { - UnconditionalFlowInfoTestHarness - result = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0], 64), - expected = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1], 64); - result.markAsComparedEqualToNonNull(local); - if (!(result.testEquals(expected))) { - if (failures == 0) { - System.out.println("markAsComparedEqualToNonNull failures: "); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + result.testString() + - "}, // (64) instead of: " + testStringValueOf(testData[i][1])); - } - if (testData[i][0][0] == 0 && - testData[i][0][1] == 0 && - testData[i][0][2] == 0 && - testData[i][0][3] == 0) { - result = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1]); - result.markAsComparedEqualToNonNull(local); - if (!result.testEquals(expected, 64)) { - if (failures == 0) { - System.out.println("markAsComparedEqualToNonNull failures: "); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + result.testString() + - "}, // (zero 64) instead of: " + testStringValueOf(testData[i][1])); - } - } - } - local = new TestLocalVariableBinding(128); - for (int i = 0; i < testData.length; i++) { - if (testData[i][0][0] == 0 && - testData[i][0][1] == 0 && - testData[i][0][2] == 0 && - testData[i][0][3] == 0) { - UnconditionalFlowInfoTestHarness - result = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1], 64), - expected = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1], 128); - result.markAsComparedEqualToNonNull(local); - if (!result.testEquals(expected, 128)) { - if (failures == 0) { - System.out.println("markAsComparedEqualToNonNull failures: "); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + result.testString() + - "}, // (zero 128) instead of: " + testStringValueOf(testData[i][1])); - } - } - } - if (printTablesAsNames) { - System.out.println("RECAP TABLE FOR MARK COMPARED NON NULL"); - for (int i = 0; i < testData.length; i++) { - System.out.println(testSymbolicValueOf(testData[i][0]) + " -> " + - testSymbolicValueOf(testData[i][1])); - } - } - if (printTablesAsCodes) { - System.out.println("RECAP TABLE FOR MARK COMPARED NON NULL"); - for (int i = 0; i < testData.length; i++) { - System.out.println(testCodedValueOf(testData[i][0]) + " " + - testCodedValueOf(testData[i][1])); - } - } - assertTrue("nb of failures: " + failures, failures == 0); -} - -public void test2051_markAsComparedEqualToNull() { - long [][][] testData = { - {{0,0,0,0},{0,1,0,0}}, - {{0,0,0,1},{0,1,0,0}}, - {{0,0,1,0},{0,1,1,0}}, - {{0,0,1,1},{0,1,1,0}}, - {{0,1,0,0},{0,1,0,0}}, - {{0,1,0,1},{0,1,0,0}}, - {{0,1,1,0},{0,1,1,0}}, - {{0,1,1,1},{0,1,1,0}}, - {{1,0,0,0},{0,1,0,0}}, - {{1,0,0,1},{0,1,0,0}}, - {{1,0,1,0},{1,0,1,0}}, - {{1,0,1,1},{0,1,0,0}}, - {{1,1,0,0},{0,1,0,0}}, - {{1,1,0,1},{0,1,0,0}}, - {{1,1,1,0},{0,1,1,0}}, - {{1,1,1,1},{0,1,1,0}}, - }; - int failures = 0; - LocalVariableBinding local = new TestLocalVariableBinding(0); - for (int i = 0; i < testData.length; i++) { - UnconditionalFlowInfoTestHarness - result = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0]); - result.markAsComparedEqualToNull(local); - if (!(result.testEquals(UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1])))) { - if (failures == 0) { - System.out.println("markAsComparedEqualToNull failures: "); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + result.testString() + - "}, // instead of: " + testStringValueOf(testData[i][1])); - } - } - local = new TestLocalVariableBinding(64); - for (int i = 0; i < testData.length; i++) { - UnconditionalFlowInfoTestHarness - result = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0], 64), - expected = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1], 64); - result.markAsComparedEqualToNull(local); - if (!(result.testEquals(expected))) { - if (failures == 0) { - System.out.println("markAsComparedEqualToNull failures: "); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + result.testString() + - "}, // (64) instead of: " + testStringValueOf(testData[i][1])); - } - if (testData[i][0][0] == 0 && - testData[i][0][1] == 0 && - testData[i][0][2] == 0 && - testData[i][0][3] == 0) { - result = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1]); - result.markAsComparedEqualToNull(local); - if (!result.testEquals(expected, 64)) { - if (failures == 0) { - System.out.println("markAsComparedEqualToNull failures: "); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + result.testString() + - "}, // (zero 64) instead of: " + testStringValueOf(testData[i][1])); - } - } - } - local = new TestLocalVariableBinding(128); - for (int i = 0; i < testData.length; i++) { - if (testData[i][0][0] == 0 && - testData[i][0][1] == 0 && - testData[i][0][2] == 0 && - testData[i][0][3] == 0) { - UnconditionalFlowInfoTestHarness - result = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1], 64), - expected = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1], 128); - result.markAsComparedEqualToNull(local); - if (!result.testEquals(expected, 128)) { - if (failures == 0) { - System.out.println("markAsComparedEqualToNull failures: "); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + result.testString() + - "}, // (zero 128) instead of: " + testStringValueOf(testData[i][1])); - } - } - } - if (printTablesAsNames) { - System.out.println("RECAP TABLE FOR MARK COMPARED NULL"); - for (int i = 0; i < testData.length; i++) { - System.out.println(testSymbolicValueOf(testData[i][0]) + " -> " + - testSymbolicValueOf(testData[i][1])); - } - } - if (printTablesAsCodes) { - System.out.println("RECAP TABLE FOR MARK COMPARED NULL"); - for (int i = 0; i < testData.length; i++) { - System.out.println(testCodedValueOf(testData[i][0]) + " " + - testCodedValueOf(testData[i][1])); - } - } - assertTrue("nb of failures: " + failures, failures == 0); -} - -public void test2052_markAsDefinitelyNonNull() { - long [][][] testData = { - {{0,0,0,0},{1,0,0,1}}, - {{0,0,0,1},{1,0,0,1}}, - {{0,0,1,0},{1,0,0,1}}, - {{0,0,1,1},{1,0,0,1}}, - {{0,1,0,0},{1,0,0,1}}, - {{0,1,0,1},{1,0,0,1}}, - {{0,1,1,0},{1,0,0,1}}, - {{0,1,1,1},{1,0,0,1}}, - {{1,0,0,0},{1,0,0,1}}, - {{1,0,0,1},{1,0,0,1}}, - {{1,0,1,0},{1,0,0,1}}, - {{1,0,1,1},{1,0,0,1}}, - {{1,1,0,0},{1,0,0,1}}, - {{1,1,0,1},{1,0,0,1}}, - {{1,1,1,0},{1,0,0,1}}, - {{1,1,1,1},{1,0,0,1}}, - }; - int failures = 0; - LocalVariableBinding local = new TestLocalVariableBinding(0); - for (int i = 0; i < testData.length; i++) { - UnconditionalFlowInfoTestHarness - result = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0]); - result.markAsDefinitelyNonNull(local); - if (!(result.testEquals(UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1])))) { - if (failures == 0) { - System.out.println("markAsDefinitelyNonNull failures: "); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + result.testString() + - "}, // instead of: " + testStringValueOf(testData[i][1])); - } - } - local = new TestLocalVariableBinding(64); - for (int i = 0; i < testData.length; i++) { - UnconditionalFlowInfoTestHarness - result = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0], 64); - result.markAsDefinitelyNonNull(local); - if (!(result.testEquals(UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1], 64)))) { - if (failures == 0) { - System.out.println("markAsDefinitelyNonNull failures: "); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + result.testString() + - "}, // (64) instead of: " + testStringValueOf(testData[i][1])); - } - } - if (printTablesAsNames) { - System.out.println("RECAP TABLE FOR MARK DEFINITELY NON NULL"); - for (int i = 0; i < testData.length; i++) { - System.out.println(testSymbolicValueOf(testData[i][0]) + " -> " + - testSymbolicValueOf(testData[i][1])); - } - } - if (printTablesAsCodes) { - System.out.println("RECAP TABLE FOR MARK DEFINITELY NON NULL"); - for (int i = 0; i < testData.length; i++) { - System.out.println(testCodedValueOf(testData[i][0]) + " " + - testCodedValueOf(testData[i][1])); - } - } - assertTrue("nb of failures: " + failures, failures == 0); -} - -public void test2053_markAsDefinitelyNull() { - long [][][] testData = { - {{0,0,0,0},{1,0,1,0}}, - {{0,0,0,1},{1,0,1,0}}, - {{0,0,1,0},{1,0,1,0}}, - {{0,0,1,1},{1,0,1,0}}, - {{0,1,0,0},{1,0,1,0}}, - {{0,1,0,1},{1,0,1,0}}, - {{0,1,1,0},{1,0,1,0}}, - {{0,1,1,1},{1,0,1,0}}, - {{1,0,0,0},{1,0,1,0}}, - {{1,0,0,1},{1,0,1,0}}, - {{1,0,1,0},{1,0,1,0}}, - {{1,0,1,1},{1,0,1,0}}, - {{1,1,0,0},{1,0,1,0}}, - {{1,1,0,1},{1,0,1,0}}, - {{1,1,1,0},{1,0,1,0}}, - {{1,1,1,1},{1,0,1,0}}, - }; - int failures = 0; - LocalVariableBinding local = new TestLocalVariableBinding(0); - for (int i = 0; i < testData.length; i++) { - UnconditionalFlowInfoTestHarness - result = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0]); - result.markAsDefinitelyNull(local); - if (!(result.testEquals(UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1])))) { - if (failures == 0) { - System.out.println("markAsDefinitelyNull failures: "); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + result.testString() + - "}, // instead of: " + testStringValueOf(testData[i][1])); - } - } - local = new TestLocalVariableBinding(64); - for (int i = 0; i < testData.length; i++) { - UnconditionalFlowInfoTestHarness - result = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0], 64); - result.markAsDefinitelyNull(local); - if (!(result.testEquals(UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1], 64)))) { - if (failures == 0) { - System.out.println("markAsDefinitelyNull failures: "); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + result.testString() + - "}, // (64) instead of: " + testStringValueOf(testData[i][1])); - } - } - if (printTablesAsNames) { - System.out.println("RECAP TABLE FOR MARK DEFINITELY NULL"); - for (int i = 0; i < testData.length; i++) { - System.out.println(testSymbolicValueOf(testData[i][0]) + " -> " + - testSymbolicValueOf(testData[i][1])); - } - } - if (printTablesAsCodes) { - System.out.println("RECAP TABLE FOR MARK DEFINITELY NULL"); - for (int i = 0; i < testData.length; i++) { - System.out.println(testCodedValueOf(testData[i][0]) + " " + - testCodedValueOf(testData[i][1])); - } - } - assertTrue("nb of failures: " + failures, failures == 0); -} - -public void test2054_markAsDefinitelyUnknown() { - long [][][] testData = { - {{0,0,0,0},{1,0,1,1}}, - {{0,0,0,1},{1,0,1,1}}, - {{0,0,1,0},{1,0,1,1}}, - {{0,0,1,1},{1,0,1,1}}, - {{0,1,0,0},{1,0,1,1}}, - {{0,1,0,1},{1,0,1,1}}, - {{0,1,1,0},{1,0,1,1}}, - {{0,1,1,1},{1,0,1,1}}, - {{1,0,0,0},{1,0,1,1}}, - {{1,0,0,1},{1,0,1,1}}, - {{1,0,1,0},{1,0,1,1}}, - {{1,0,1,1},{1,0,1,1}}, - {{1,1,0,0},{1,0,1,1}}, - {{1,1,0,1},{1,0,1,1}}, - {{1,1,1,0},{1,0,1,1}}, - {{1,1,1,1},{1,0,1,1}}, - }; - int failures = 0; - LocalVariableBinding local = new TestLocalVariableBinding(0); - for (int i = 0; i < testData.length; i++) { - UnconditionalFlowInfoTestHarness - result = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0]); - result.markAsDefinitelyUnknown(local); - if (!(result.testEquals(UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1])))) { - if (failures == 0) { - System.out.println("markAsDefinitelyUnknown failures: "); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + result.testString() + - "}, // instead of: " + testStringValueOf(testData[i][1])); - } - } - local = new TestLocalVariableBinding(64); - for (int i = 0; i < testData.length; i++) { - UnconditionalFlowInfoTestHarness - result = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0], 64); - result.markAsDefinitelyUnknown(local); - if (!(result.testEquals(UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1], 64)))) { - if (failures == 0) { - System.out.println("markAsDefinitelyUnknown failures: "); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + result.testString() + - "}, // (64) instead of: " + testStringValueOf(testData[i][1])); - } - } - if (printTablesAsNames) { - System.out.println("RECAP TABLE FOR MARK DEFINITELY UNKNOWN"); - for (int i = 0; i < testData.length; i++) { - System.out.println(testSymbolicValueOf(testData[i][0]) + " -> " + - testSymbolicValueOf(testData[i][1])); - } - } - if (printTablesAsCodes) { - System.out.println("RECAP TABLE FOR MARK DEFINITELY UNKNOWN"); - for (int i = 0; i < testData.length; i++) { - System.out.println(testCodedValueOf(testData[i][0]) + " " + - testCodedValueOf(testData[i][1])); - } - } - assertTrue("nb of failures: " + failures, failures == 0); -} - -public void test2055_addInitializationsFrom() { - long [][][] testData = { - {{0,0,0,0},{0,0,0,0},{0,0,0,0}}, - {{0,0,0,0},{0,0,0,1},{0,0,0,1}}, - {{0,0,0,0},{0,0,1,0},{0,0,1,0}}, - {{0,0,0,0},{0,0,1,1},{0,0,1,1}}, - {{0,0,0,0},{0,1,0,0},{0,1,0,0}}, - {{0,0,0,0},{0,1,1,0},{0,1,1,0}}, - {{0,0,0,0},{1,0,0,1},{1,0,0,1}}, - {{0,0,0,0},{1,0,1,0},{1,0,1,0}}, - {{0,0,0,0},{1,0,1,1},{1,0,1,1}}, - {{0,0,0,0},{1,1,0,0},{1,1,0,0}}, - {{0,0,0,0},{1,1,0,1},{1,1,0,1}}, - {{0,0,0,1},{0,0,0,0},{0,0,0,1}}, - {{0,0,0,1},{0,0,0,1},{0,0,0,1}}, - {{0,0,0,1},{0,0,1,0},{0,0,1,1}}, - {{0,0,0,1},{0,0,1,1},{0,0,1,1}}, - {{0,0,0,1},{0,1,0,0},{0,1,0,0}}, - {{0,0,0,1},{0,1,1,0},{0,1,0,0}}, - {{0,0,0,1},{1,0,0,1},{1,0,0,1}}, - {{0,0,0,1},{1,0,1,0},{1,0,1,0}}, - {{0,0,0,1},{1,0,1,1},{1,0,1,1}}, - {{0,0,0,1},{1,1,0,0},{1,1,0,1}}, - {{0,0,0,1},{1,1,0,1},{1,1,0,1}}, - {{0,0,1,0},{0,0,0,0},{0,0,1,0}}, - {{0,0,1,0},{0,0,0,1},{0,0,1,1}}, - {{0,0,1,0},{0,0,1,0},{0,0,1,0}}, - {{0,0,1,0},{0,0,1,1},{0,0,1,1}}, - {{0,0,1,0},{0,1,0,0},{0,1,1,0}}, - {{0,0,1,0},{0,1,1,0},{0,1,1,0}}, - {{0,0,1,0},{1,0,0,1},{1,0,0,1}}, - {{0,0,1,0},{1,0,1,0},{1,0,1,0}}, - {{0,0,1,0},{1,0,1,1},{1,0,1,1}}, - {{0,0,1,0},{1,1,0,0},{1,1,0,0}}, - {{0,0,1,0},{1,1,0,1},{1,1,0,1}}, - {{0,0,1,1},{0,0,0,0},{0,0,1,1}}, - {{0,0,1,1},{0,0,0,1},{0,0,1,1}}, - {{0,0,1,1},{0,0,1,0},{0,0,1,1}}, - {{0,0,1,1},{0,0,1,1},{0,0,1,1}}, - {{0,0,1,1},{0,1,0,0},{0,1,1,0}}, - {{0,0,1,1},{0,1,1,0},{0,1,1,0}}, - {{0,0,1,1},{1,0,0,1},{1,0,0,1}}, - {{0,0,1,1},{1,0,1,0},{1,0,1,0}}, - {{0,0,1,1},{1,0,1,1},{1,0,1,1}}, - {{0,0,1,1},{1,1,0,0},{1,1,0,1}}, - {{0,0,1,1},{1,1,0,1},{1,1,0,1}}, - {{0,1,0,0},{0,0,0,0},{0,1,0,0}}, - {{0,1,0,0},{0,0,0,1},{0,0,0,1}}, - {{0,1,0,0},{0,0,1,0},{0,1,1,0}}, - {{0,1,0,0},{0,0,1,1},{0,0,1,1}}, - {{0,1,0,0},{0,1,0,0},{0,1,0,0}}, - {{0,1,0,0},{0,1,1,0},{0,1,1,0}}, - {{0,1,0,0},{1,0,0,1},{1,0,0,1}}, - {{0,1,0,0},{1,0,1,0},{1,0,1,0}}, - {{0,1,0,0},{1,0,1,1},{1,0,1,1}}, - {{0,1,0,0},{1,1,0,0},{1,1,0,0}}, - {{0,1,0,0},{1,1,0,1},{1,1,0,1}}, - {{0,1,1,0},{0,0,0,0},{0,1,1,0}}, - {{0,1,1,0},{0,0,0,1},{0,0,1,1}}, - {{0,1,1,0},{0,0,1,0},{0,1,1,0}}, - {{0,1,1,0},{0,0,1,1},{0,0,1,1}}, - {{0,1,1,0},{0,1,0,0},{0,1,1,0}}, - {{0,1,1,0},{0,1,1,0},{0,1,1,0}}, - {{0,1,1,0},{1,0,0,1},{1,0,0,1}}, - {{0,1,1,0},{1,0,1,0},{1,0,1,0}}, - {{0,1,1,0},{1,0,1,1},{1,0,1,1}}, - {{0,1,1,0},{1,1,0,0},{1,1,0,0}}, - {{0,1,1,0},{1,1,0,1},{1,1,0,1}}, - {{1,0,0,1},{0,0,0,0},{1,0,0,1}}, - {{1,0,0,1},{0,0,0,1},{1,0,0,1}}, - {{1,0,0,1},{0,0,1,0},{0,0,1,1}}, - {{1,0,0,1},{0,0,1,1},{0,0,1,1}}, - {{1,0,0,1},{0,1,0,0},{0,1,0,0}}, - {{1,0,0,1},{0,1,1,0},{0,1,1,0}}, - {{1,0,0,1},{1,0,0,1},{1,0,0,1}}, - {{1,0,0,1},{1,0,1,0},{1,0,1,0}}, - {{1,0,0,1},{1,0,1,1},{1,0,1,1}}, - {{1,0,0,1},{1,1,0,0},{1,1,0,1}}, - {{1,0,0,1},{1,1,0,1},{1,1,0,1}}, - {{1,0,1,0},{0,0,0,0},{1,0,1,0}}, - {{1,0,1,0},{0,0,0,1},{0,0,1,1}}, - {{1,0,1,0},{0,0,1,0},{1,0,1,0}}, - {{1,0,1,0},{0,0,1,1},{0,0,1,1}}, - {{1,0,1,0},{0,1,0,0},{1,0,1,0}}, - {{1,0,1,0},{0,1,1,0},{1,0,1,0}}, - {{1,0,1,0},{1,0,0,1},{1,0,0,1}}, - {{1,0,1,0},{1,0,1,0},{1,0,1,0}}, - {{1,0,1,0},{1,0,1,1},{1,0,1,1}}, - {{1,0,1,0},{1,1,0,0},{1,1,0,0}}, - {{1,0,1,0},{1,1,0,1},{1,1,0,1}}, - {{1,0,1,1},{0,0,0,0},{1,0,1,1}}, - {{1,0,1,1},{0,0,0,1},{1,0,1,1}}, - {{1,0,1,1},{0,0,1,0},{0,0,1,1}}, - {{1,0,1,1},{0,0,1,1},{0,0,1,1}}, - {{1,0,1,1},{0,1,0,0},{0,1,0,0}}, - {{1,0,1,1},{0,1,1,0},{0,1,1,0}}, - {{1,0,1,1},{1,0,0,1},{1,0,0,1}}, - {{1,0,1,1},{1,0,1,0},{1,0,1,0}}, - {{1,0,1,1},{1,0,1,1},{1,0,1,1}}, - {{1,0,1,1},{1,1,0,0},{1,1,0,1}}, - {{1,0,1,1},{1,1,0,1},{1,1,0,1}}, - {{1,1,0,0},{0,0,0,0},{1,1,0,0}}, - {{1,1,0,0},{0,0,0,1},{1,1,0,1}}, - {{1,1,0,0},{0,0,1,0},{0,0,1,0}}, - {{1,1,0,0},{0,0,1,1},{0,0,1,1}}, - {{1,1,0,0},{0,1,0,0},{0,1,0,0}}, - {{1,1,0,0},{0,1,1,0},{0,1,1,0}}, - {{1,1,0,0},{1,0,0,1},{1,0,0,1}}, - {{1,1,0,0},{1,0,1,0},{1,0,1,0}}, - {{1,1,0,0},{1,0,1,1},{1,0,1,1}}, - {{1,1,0,0},{1,1,0,0},{1,1,0,0}}, - {{1,1,0,0},{1,1,0,1},{1,1,0,1}}, - {{1,1,0,1},{0,0,0,0},{1,1,0,1}}, - {{1,1,0,1},{0,0,0,1},{0,0,0,1}}, - {{1,1,0,1},{0,0,1,0},{0,0,1,1}}, - {{1,1,0,1},{0,0,1,1},{0,0,1,1}}, - {{1,1,0,1},{0,1,0,0},{0,1,0,0}}, - {{1,1,0,1},{0,1,1,0},{0,1,1,0}}, - {{1,1,0,1},{1,0,0,1},{1,0,0,1}}, - {{1,1,0,1},{1,0,1,0},{1,0,1,0}}, - {{1,1,0,1},{1,0,1,1},{1,0,1,1}}, - {{1,1,0,1},{1,1,0,0},{1,1,0,1}}, - {{1,1,0,1},{1,1,0,1},{1,1,0,1}}, - }; - int failures = 0; - long start; - if (combinationTestsloopsNb > 1) { - start = System.currentTimeMillis(); - } - String header = "addInitializationsFrom failures: "; //$NON-NLS-1$ - for (int l = 0; l < combinationTestsloopsNb ; l++) { - for (int i = 0; i < testData.length; i++) { - UnconditionalFlowInfoTestHarness result; - if (!(result = (UnconditionalFlowInfoTestHarness)( - UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0])). - addInitializationsFrom( - UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1]))). - testEquals(UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][2]))) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // instead of: " + testStringValueOf(testData[i][2])); - } - } - } - if (combinationTestsloopsNb > 1) { - System.out.println("addInitial...\t\t" + combinationTestsloopsNb + "\t" + - (System.currentTimeMillis() - start)); - } - // PREMATURE optimize test (extraneous allocations and copies) - // PREMATURE optimize test (extraneous iterations - undup) - UnconditionalFlowInfoTestHarness - zero = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(new long[] {0,0,0,0}), - left0, left1, right1, left2, right2, - expected0, expected1, expected2, result; - for (int i = 0; i < testData.length; i++) { - left0 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0]); - left1 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0], 64); - left2 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0], 128); - right1 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1], 64); - right2 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1], 128); - expected0 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][2]); - expected1 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][2], 64); - expected2 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][2], 128); - if (!(result = (UnconditionalFlowInfoTestHarness) - left1.copy().addInitializationsFrom(right1)). - testEquals(expected1)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (64, 64) - instead of: " + testStringValueOf(testData[i][2])); - } - if ((testData[i][0][0] | testData[i][0][1] | - testData[i][0][2] | testData[i][0][3]) == 0) { - if (!(result = (UnconditionalFlowInfoTestHarness) - zero.copy().addInitializationsFrom(right1)). - testEquals(expected1)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (zero, 64) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) right2.copy(). - addInitializationsFrom(right1)). - testEquals(expected1, 64)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (zero 128, 64) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - zero.copy().addInitializationsFrom(right2)). - testEquals(expected2, 128)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString(128) + - "}, // (zero, 128) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - right1.copy().addInitializationsFrom(right2)). - testEquals(expected2, 128)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString(128) + - "}, // (zero 64, 128) - instead of: " + testStringValueOf(testData[i][2])); - } - } - if ((testData[i][1][0] | testData[i][1][1] | - testData[i][1][2] | testData[i][1][3]) == 0) { - if (!(result = (UnconditionalFlowInfoTestHarness) - left0.copy().addInitializationsFrom(left2)). - testEquals(expected0, 0)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (1, zero 128) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - left1.copy().addInitializationsFrom(zero)). - testEquals(expected1)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (64, zero) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - left1.copy().addInitializationsFrom(left2)). - testEquals(expected1, 64)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (64, zero 128) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - left2.copy().addInitializationsFrom(zero)). - testEquals(expected2, 128)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (128, zero) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - left2.addInitializationsFrom(left1)). - testEquals(expected2, 128)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (128, zero 64) - instead of: " + testStringValueOf(testData[i][2])); - } - } - } - if (printTablesAsNames) { - System.out.println("RECAP TABLE FOR ADD"); - for (int i = 0; i < testData.length; i++) { - System.out.println(testSymbolicValueOf(testData[i][0]) + " + " + - testSymbolicValueOf(testData[i][1]) + " -> " + - testSymbolicValueOf(testData[i][2])); - } - } - if (printTablesAsCodes) { - System.out.println("RECAP TABLE FOR ADD"); - for (int i = 0; i < testData.length; i++) { - System.out.println(testCodedValueOf(testData[i][0]) + " " + - testCodedValueOf(testData[i][1]) + " " + - testCodedValueOf(testData[i][2])); - } - } - if (printTruthMaps) { - for (int i = 0; i < 4; i++) { - System.out.println("======================================================"); - System.out.println("Truth map for addInitializationsFrom null bit " + (i + 1)); - System.out.println(); - printTruthMap(testData, i); - } - } - assertTrue("nb of failures: " + failures, failures == 0); -} - -public void test2056_addPotentialInitializationsFrom() { - long [][][] testData = { - {{0,0,0,0},{0,0,0,0},{0,0,0,0}}, - {{0,0,0,0},{0,0,0,1},{0,0,0,1}}, - {{0,0,0,0},{0,0,1,0},{0,0,1,0}}, - {{0,0,0,0},{0,0,1,1},{0,0,1,1}}, - {{0,0,0,0},{0,1,0,0},{0,0,0,0}}, - {{0,0,0,0},{0,1,1,0},{0,0,1,0}}, - {{0,0,0,0},{1,0,0,1},{0,0,0,1}}, - {{0,0,0,0},{1,0,1,0},{0,0,1,0}}, - {{0,0,0,0},{1,0,1,1},{0,0,0,1}}, - {{0,0,0,0},{1,1,0,0},{0,0,0,0}}, - {{0,0,0,0},{1,1,0,1},{0,0,0,1}}, - {{0,0,0,1},{0,0,0,0},{0,0,0,1}}, - {{0,0,0,1},{0,0,0,1},{0,0,0,1}}, - {{0,0,0,1},{0,0,1,0},{0,0,1,1}}, - {{0,0,0,1},{0,0,1,1},{0,0,1,1}}, - {{0,0,0,1},{0,1,0,0},{0,0,0,1}}, - {{0,0,0,1},{0,1,1,0},{0,0,1,1}}, - {{0,0,0,1},{1,0,0,1},{0,0,0,1}}, - {{0,0,0,1},{1,0,1,0},{0,0,1,1}}, - {{0,0,0,1},{1,0,1,1},{0,0,0,1}}, - {{0,0,0,1},{1,1,0,0},{0,0,0,1}}, - {{0,0,0,1},{1,1,0,1},{0,0,0,1}}, - {{0,0,1,0},{0,0,0,0},{0,0,1,0}}, - {{0,0,1,0},{0,0,0,1},{0,0,1,1}}, - {{0,0,1,0},{0,0,1,0},{0,0,1,0}}, - {{0,0,1,0},{0,0,1,1},{0,0,1,1}}, - {{0,0,1,0},{0,1,0,0},{0,0,1,0}}, - {{0,0,1,0},{0,1,1,0},{0,0,1,0}}, - {{0,0,1,0},{1,0,0,1},{0,0,1,1}}, - {{0,0,1,0},{1,0,1,0},{0,0,1,0}}, - {{0,0,1,0},{1,0,1,1},{0,0,1,1}}, - {{0,0,1,0},{1,1,0,0},{0,0,1,0}}, - {{0,0,1,0},{1,1,0,1},{0,0,1,1}}, - {{0,0,1,1},{0,0,0,0},{0,0,1,1}}, - {{0,0,1,1},{0,0,0,1},{0,0,1,1}}, - {{0,0,1,1},{0,0,1,0},{0,0,1,1}}, - {{0,0,1,1},{0,0,1,1},{0,0,1,1}}, - {{0,0,1,1},{0,1,0,0},{0,0,1,1}}, - {{0,0,1,1},{0,1,1,0},{0,0,1,1}}, - {{0,0,1,1},{1,0,0,1},{0,0,1,1}}, - {{0,0,1,1},{1,0,1,0},{0,0,1,1}}, - {{0,0,1,1},{1,0,1,1},{0,0,1,1}}, - {{0,0,1,1},{1,1,0,0},{0,0,1,1}}, - {{0,0,1,1},{1,1,0,1},{0,0,1,1}}, - {{0,1,0,0},{0,0,0,0},{0,1,0,0}}, - {{0,1,0,0},{0,0,0,1},{0,0,0,1}}, - {{0,1,0,0},{0,0,1,0},{0,1,1,0}}, - {{0,1,0,0},{0,0,1,1},{0,0,1,1}}, - {{0,1,0,0},{0,1,0,0},{0,1,0,0}}, - {{0,1,0,0},{0,1,1,0},{0,1,1,0}}, - {{0,1,0,0},{1,0,0,1},{0,0,0,1}}, - {{0,1,0,0},{1,0,1,0},{0,1,1,0}}, - {{0,1,0,0},{1,0,1,1},{0,0,0,1}}, - {{0,1,0,0},{1,1,0,0},{0,1,0,0}}, - {{0,1,0,0},{1,1,0,1},{0,0,0,1}}, - {{0,1,1,0},{0,0,0,0},{0,1,1,0}}, - {{0,1,1,0},{0,0,0,1},{0,0,1,1}}, - {{0,1,1,0},{0,0,1,0},{0,1,1,0}}, - {{0,1,1,0},{0,0,1,1},{0,0,1,1}}, - {{0,1,1,0},{0,1,0,0},{0,1,1,0}}, - {{0,1,1,0},{0,1,1,0},{0,1,1,0}}, - {{0,1,1,0},{1,0,0,1},{0,0,1,1}}, - {{0,1,1,0},{1,0,1,0},{0,1,1,0}}, - {{0,1,1,0},{1,0,1,1},{0,0,1,1}}, - {{0,1,1,0},{1,1,0,0},{0,1,1,0}}, - {{0,1,1,0},{1,1,0,1},{0,0,1,1}}, - {{1,0,0,1},{0,0,0,0},{1,0,0,1}}, - {{1,0,0,1},{0,0,0,1},{1,0,1,1}}, - {{1,0,0,1},{0,0,1,0},{0,0,1,1}}, - {{1,0,0,1},{0,0,1,1},{0,0,1,1}}, - {{1,0,0,1},{0,1,0,0},{1,0,0,1}}, - {{1,0,0,1},{0,1,1,0},{0,0,1,1}}, - {{1,0,0,1},{1,0,0,1},{1,0,0,1}}, - {{1,0,0,1},{1,0,1,0},{0,0,1,1}}, - {{1,0,0,1},{1,0,1,1},{1,0,1,1}}, - {{1,0,0,1},{1,1,0,0},{1,0,0,1}}, - {{1,0,0,1},{1,1,0,1},{1,0,0,1}}, - {{1,0,1,0},{0,0,0,0},{1,0,1,0}}, - {{1,0,1,0},{0,0,0,1},{0,0,1,1}}, - {{1,0,1,0},{0,0,1,0},{1,0,1,0}}, - {{1,0,1,0},{0,0,1,1},{0,0,1,1}}, - {{1,0,1,0},{0,1,0,0},{1,0,1,0}}, - {{1,0,1,0},{0,1,1,0},{1,0,1,0}}, - {{1,0,1,0},{1,0,0,1},{0,0,1,1}}, - {{1,0,1,0},{1,0,1,0},{1,0,1,0}}, - {{1,0,1,0},{1,0,1,1},{0,0,1,1}}, - {{1,0,1,0},{1,1,0,0},{1,0,1,0}}, - {{1,0,1,0},{1,1,0,1},{0,0,1,1}}, - {{1,0,1,1},{0,0,0,0},{1,0,1,1}}, - {{1,0,1,1},{0,0,0,1},{1,0,1,1}}, - {{1,0,1,1},{0,0,1,0},{0,0,1,1}}, - {{1,0,1,1},{0,0,1,1},{0,0,1,1}}, - {{1,0,1,1},{0,1,0,0},{1,0,1,1}}, - {{1,0,1,1},{0,1,1,0},{0,0,1,1}}, - {{1,0,1,1},{1,0,0,1},{1,0,1,1}}, - {{1,0,1,1},{1,0,1,0},{0,0,1,1}}, - {{1,0,1,1},{1,0,1,1},{1,0,1,1}}, - {{1,0,1,1},{1,1,0,0},{1,0,1,1}}, - {{1,0,1,1},{1,1,0,1},{1,0,1,1}}, - {{1,1,0,0},{0,0,0,0},{1,1,0,0}}, - {{1,1,0,0},{0,0,0,1},{0,0,0,1}}, - {{1,1,0,0},{0,0,1,0},{0,0,1,0}}, - {{1,1,0,0},{0,0,1,1},{0,0,1,1}}, - {{1,1,0,0},{0,1,0,0},{1,1,0,0}}, - {{1,1,0,0},{0,1,1,0},{0,0,1,0}}, - {{1,1,0,0},{1,0,0,1},{0,0,0,1}}, - {{1,1,0,0},{1,0,1,0},{0,0,1,0}}, - {{1,1,0,0},{1,0,1,1},{0,0,0,1}}, - {{1,1,0,0},{1,1,0,0},{1,1,0,0}}, - {{1,1,0,0},{1,1,0,1},{1,1,0,1}}, - {{1,1,0,1},{0,0,0,0},{1,1,0,1}}, - {{1,1,0,1},{0,0,0,1},{0,0,0,1}}, - {{1,1,0,1},{0,0,1,0},{0,0,1,1}}, - {{1,1,0,1},{0,0,1,1},{0,0,1,1}}, - {{1,1,0,1},{0,1,0,0},{1,1,0,1}}, - {{1,1,0,1},{0,1,1,0},{0,0,1,1}}, - {{1,1,0,1},{1,0,0,1},{0,0,0,1}}, - {{1,1,0,1},{1,0,1,0},{0,0,1,1}}, - {{1,1,0,1},{1,0,1,1},{0,0,0,1}}, - {{1,1,0,1},{1,1,0,0},{1,1,0,1}}, - {{1,1,0,1},{1,1,0,1},{1,1,0,1}}, - }; - int failures = 0; - long start; - if (combinationTestsloopsNb > 1) { - start = System.currentTimeMillis(); - } - String header = "addPotentialInitializationsFrom failures: "; //$NON-NLS-1$ - for (int l = 0; l < combinationTestsloopsNb ; l++) { - for (int i = 0; i < testData.length; i++) { - UnconditionalFlowInfoTestHarness result; - if (!(result = (UnconditionalFlowInfoTestHarness)( - UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0])). - addPotentialInitializationsFrom( - UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1]))). - testEquals(UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][2]))) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // instead of: " + testStringValueOf(testData[i][2])); - } - if (combinationTestsloopsNb < 2 && - !(result = (UnconditionalFlowInfoTestHarness)( - UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0])). - addPotentialNullInfoFrom( - UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1], 128))). - testEquals(UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[14][0], 65), 64)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString(64) + - "}, // bit 64 only, instead of: {0,0,0,0}"); - } - } - } - if (combinationTestsloopsNb > 1) { - System.out.println("addPotential...\t" + combinationTestsloopsNb + "\t" + - (System.currentTimeMillis() - start)); - } - UnconditionalFlowInfoTestHarness - zero = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(new long[] {0,0,0,0}), - left0, left1, right1, left2, right2, - expected0, expected1, expected2, result; - for (int i = 0; i < testData.length; i++) { - left0 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0]); - left1 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0], 64); - left2 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0], 128); - right1 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1], 64); - right2 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1], 128); - expected0 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][2]); - expected1 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][2], 64); - expected2 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][2], 128); - if (!(result = (UnconditionalFlowInfoTestHarness) - left1.copy().addPotentialInitializationsFrom(right1)). - testEquals(expected1)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (64, 64) - instead of: " + testStringValueOf(testData[i][2])); - } - if (testData[i][0][0] + testData[i][0][1] + - testData[i][0][2] + testData[i][0][3] == 0) { - if (!(result = (UnconditionalFlowInfoTestHarness) - zero.copy().addPotentialInitializationsFrom(right1)). - testEquals(expected1)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (zero, 64) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - right2.copy().addPotentialInitializationsFrom(right1)). - testEquals(expected1, 64)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (zero 128, 64) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - (UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(new long[] {0,0,0,0}, 64)). - // make just in time to get the needed structure - addPotentialNullInfoFrom(right2)). - testEquals(expected2, 128)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (zero extra, 128) null only - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - ((UnconditionalFlowInfo)right2.copy()). - addPotentialNullInfoFrom(right1)). - testEquals(expected1, 64)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (zero 128, 64) null only - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - ((UnconditionalFlowInfo)zero.copy()). - addPotentialNullInfoFrom(right2)). - testEquals(expected2, 128)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString(128) + - "}, // (zero, 128) null only - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - ((UnconditionalFlowInfo)right1.copy()). - addPotentialNullInfoFrom(right2)). - testEquals(expected2, 128)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString(128) + - "}, // (zero 64, 128) null only - instead of: " + testStringValueOf(testData[i][2])); - } } - if (testData[i][1][0] + testData[i][1][1] + - testData[i][1][2] + testData[i][1][3] == 0) { - if (!(result = (UnconditionalFlowInfoTestHarness) - ((UnconditionalFlowInfoTestHarness)left0.copy()). - addPotentialNullInfoFrom(left2)). - testEquals(expected0, 1)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (1, zero 128) null only - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - left1.copy().addPotentialInitializationsFrom(zero)). - testEquals(expected1)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (64, zero) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - left1.copy().addPotentialInitializationsFrom(left2)). - testEquals(expected1, 64)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (64, zero 128) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - ((UnconditionalFlowInfo)left1.copy()). - addPotentialNullInfoFrom(left2)). - testEquals(expected1, 64)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (64, zero 128) null only - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - ((UnconditionalFlowInfo)left2.copy()). - addPotentialNullInfoFrom(zero)). - testEquals(expected2, 128)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (128, zero) null only - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - left2.addPotentialNullInfoFrom(left1)). - testEquals(expected2, 128)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (128, zero 64) null only - instead of: " + testStringValueOf(testData[i][2])); - } - } - } - if (printTablesAsNames) { - System.out.println("RECAP TABLE FOR ADD POTENTIAL"); - for (int i = 0; i < testData.length; i++) { - System.out.println(testSymbolicValueOf(testData[i][0]) + " + " + - testSymbolicValueOf(testData[i][1]) + " -> " + - testSymbolicValueOf(testData[i][2])); - } - } - if (printTablesAsCodes) { - System.out.println("RECAP TABLE FOR ADD POTENTIAL"); - for (int i = 0; i < testData.length; i++) { - System.out.println(testCodedValueOf(testData[i][0]) + " " + - testCodedValueOf(testData[i][1]) + " " + - testCodedValueOf(testData[i][2])); - } - } - if (printTruthMaps) { - for (int i = 0; i < 4; i++) { - System.out.println("======================================================"); - System.out.println("Truth map for addPotentialInitializationsFrom null bit " + (i + 1)); - System.out.println(); - } - } - assertTrue("nb of failures: " + failures, failures == 0); -} - -public void test2057_mergedWith() { - long [][][] testData = { - {{0,0,0,0},{0,0,0,0},{0,0,0,0}}, - {{0,0,0,0},{0,0,0,1},{0,0,0,1}}, - {{0,0,0,0},{0,0,1,0},{0,0,1,0}}, - {{0,0,0,0},{0,0,1,1},{0,0,1,1}}, - {{0,0,0,0},{0,1,0,0},{0,0,1,0}}, - {{0,0,0,0},{0,1,1,0},{0,0,1,0}}, - {{0,0,0,0},{1,0,0,1},{0,0,0,1}}, - {{0,0,0,0},{1,0,1,0},{0,0,1,0}}, - {{0,0,0,0},{1,0,1,1},{0,0,0,1}}, - {{0,0,0,0},{1,1,0,0},{0,0,0,0}}, - {{0,0,0,0},{1,1,0,1},{0,0,0,1}}, - {{0,0,0,1},{0,0,0,0},{0,0,0,1}}, - {{0,0,0,1},{0,0,0,1},{0,0,0,1}}, - {{0,0,0,1},{0,0,1,0},{0,0,1,1}}, - {{0,0,0,1},{0,0,1,1},{0,0,1,1}}, - {{0,0,0,1},{0,1,0,0},{0,0,1,1}}, - {{0,0,0,1},{0,1,1,0},{0,0,1,1}}, - {{0,0,0,1},{1,0,0,1},{0,0,0,1}}, - {{0,0,0,1},{1,0,1,0},{0,0,1,1}}, - {{0,0,0,1},{1,0,1,1},{0,0,0,1}}, - {{0,0,0,1},{1,1,0,0},{0,0,0,1}}, - {{0,0,0,1},{1,1,0,1},{0,0,0,1}}, - {{0,0,1,0},{0,0,0,0},{0,0,1,0}}, - {{0,0,1,0},{0,0,0,1},{0,0,1,1}}, - {{0,0,1,0},{0,0,1,0},{0,0,1,0}}, - {{0,0,1,0},{0,0,1,1},{0,0,1,1}}, - {{0,0,1,0},{0,1,0,0},{0,0,1,0}}, - {{0,0,1,0},{0,1,1,0},{0,0,1,0}}, - {{0,0,1,0},{1,0,0,1},{0,0,1,1}}, - {{0,0,1,0},{1,0,1,0},{0,0,1,0}}, - {{0,0,1,0},{1,0,1,1},{0,0,1,1}}, - {{0,0,1,0},{1,1,0,0},{0,0,1,0}}, - {{0,0,1,0},{1,1,0,1},{0,0,1,1}}, - {{0,0,1,1},{0,0,0,0},{0,0,1,1}}, - {{0,0,1,1},{0,0,0,1},{0,0,1,1}}, - {{0,0,1,1},{0,0,1,0},{0,0,1,1}}, - {{0,0,1,1},{0,0,1,1},{0,0,1,1}}, - {{0,0,1,1},{0,1,0,0},{0,0,1,1}}, - {{0,0,1,1},{0,1,1,0},{0,0,1,1}}, - {{0,0,1,1},{1,0,0,1},{0,0,1,1}}, - {{0,0,1,1},{1,0,1,0},{0,0,1,1}}, - {{0,0,1,1},{1,0,1,1},{0,0,1,1}}, - {{0,0,1,1},{1,1,0,0},{0,0,1,1}}, - {{0,0,1,1},{1,1,0,1},{0,0,1,1}}, - {{0,1,0,0},{0,0,0,0},{0,0,1,0}}, - {{0,1,0,0},{0,0,0,1},{0,0,1,1}}, - {{0,1,0,0},{0,0,1,0},{0,0,1,0}}, - {{0,1,0,0},{0,0,1,1},{0,0,1,1}}, - {{0,1,0,0},{0,1,0,0},{0,1,0,0}}, - {{0,1,0,0},{0,1,1,0},{0,1,1,0}}, - {{0,1,0,0},{1,0,0,1},{0,0,0,1}}, - {{0,1,0,0},{1,0,1,0},{0,1,1,0}}, - {{0,1,0,0},{1,0,1,1},{0,0,1,1}}, - {{0,1,0,0},{1,1,0,0},{0,0,1,0}}, - {{0,1,0,0},{1,1,0,1},{0,0,1,1}}, - {{0,1,1,0},{0,0,0,0},{0,0,1,0}}, - {{0,1,1,0},{0,0,0,1},{0,0,1,1}}, - {{0,1,1,0},{0,0,1,0},{0,0,1,0}}, - {{0,1,1,0},{0,0,1,1},{0,0,1,1}}, - {{0,1,1,0},{0,1,0,0},{0,1,1,0}}, - {{0,1,1,0},{0,1,1,0},{0,1,1,0}}, - {{0,1,1,0},{1,0,0,1},{0,0,1,1}}, - {{0,1,1,0},{1,0,1,0},{0,1,1,0}}, - {{0,1,1,0},{1,0,1,1},{0,0,1,1}}, - {{0,1,1,0},{1,1,0,0},{0,0,1,0}}, - {{0,1,1,0},{1,1,0,1},{0,0,1,1}}, - {{1,0,0,1},{0,0,0,0},{0,0,0,1}}, - {{1,0,0,1},{0,0,0,1},{0,0,0,1}}, - {{1,0,0,1},{0,0,1,0},{0,0,1,1}}, - {{1,0,0,1},{0,0,1,1},{0,0,1,1}}, - {{1,0,0,1},{0,1,0,0},{0,0,0,1}}, - {{1,0,0,1},{0,1,1,0},{0,0,1,1}}, - {{1,0,0,1},{1,0,0,1},{1,0,0,1}}, - {{1,0,0,1},{1,0,1,0},{0,0,1,1}}, - {{1,0,0,1},{1,0,1,1},{1,0,1,1}}, - {{1,0,0,1},{1,1,0,0},{1,1,0,1}}, - {{1,0,0,1},{1,1,0,1},{1,1,0,1}}, - {{1,0,1,0},{0,0,0,0},{0,0,1,0}}, - {{1,0,1,0},{0,0,0,1},{0,0,1,1}}, - {{1,0,1,0},{0,0,1,0},{0,0,1,0}}, - {{1,0,1,0},{0,0,1,1},{0,0,1,1}}, - {{1,0,1,0},{0,1,0,0},{0,1,1,0}}, - {{1,0,1,0},{0,1,1,0},{0,1,1,0}}, - {{1,0,1,0},{1,0,0,1},{0,0,1,1}}, - {{1,0,1,0},{1,0,1,0},{1,0,1,0}}, - {{1,0,1,0},{1,0,1,1},{0,0,1,1}}, - {{1,0,1,0},{1,1,0,0},{0,0,1,0}}, - {{1,0,1,0},{1,1,0,1},{0,0,1,1}}, - {{1,0,1,1},{0,0,0,0},{0,0,0,1}}, - {{1,0,1,1},{0,0,0,1},{0,0,0,1}}, - {{1,0,1,1},{0,0,1,0},{0,0,1,1}}, - {{1,0,1,1},{0,0,1,1},{0,0,1,1}}, - {{1,0,1,1},{0,1,0,0},{0,0,1,1}}, - {{1,0,1,1},{0,1,1,0},{0,0,1,1}}, - {{1,0,1,1},{1,0,0,1},{1,0,1,1}}, - {{1,0,1,1},{1,0,1,0},{0,0,1,1}}, - {{1,0,1,1},{1,0,1,1},{1,0,1,1}}, - {{1,0,1,1},{1,1,0,0},{0,0,0,1}}, - {{1,0,1,1},{1,1,0,1},{0,0,0,1}}, - {{1,1,0,0},{0,0,0,0},{0,0,0,0}}, - {{1,1,0,0},{0,0,0,1},{0,0,0,1}}, - {{1,1,0,0},{0,0,1,0},{0,0,1,0}}, - {{1,1,0,0},{0,0,1,1},{0,0,1,1}}, - {{1,1,0,0},{0,1,0,0},{0,0,1,0}}, - {{1,1,0,0},{0,1,1,0},{0,0,1,0}}, - {{1,1,0,0},{1,0,0,1},{1,1,0,1}}, - {{1,1,0,0},{1,0,1,0},{0,0,1,0}}, - {{1,1,0,0},{1,0,1,1},{0,0,0,1}}, - {{1,1,0,0},{1,1,0,0},{1,1,0,0}}, - {{1,1,0,0},{1,1,0,1},{1,1,0,1}}, - {{1,1,0,1},{0,0,0,0},{0,0,0,1}}, - {{1,1,0,1},{0,0,0,1},{0,0,0,1}}, - {{1,1,0,1},{0,0,1,0},{0,0,1,1}}, - {{1,1,0,1},{0,0,1,1},{0,0,1,1}}, - {{1,1,0,1},{0,1,0,0},{0,0,1,1}}, - {{1,1,0,1},{0,1,1,0},{0,0,1,1}}, - {{1,1,0,1},{1,0,0,1},{1,1,0,1}}, - {{1,1,0,1},{1,0,1,0},{0,0,1,1}}, - {{1,1,0,1},{1,0,1,1},{0,0,0,1}}, - {{1,1,0,1},{1,1,0,0},{1,1,0,1}}, - {{1,1,0,1},{1,1,0,1},{1,1,0,1}} - }; - int failures = 0; - long start; - if (combinationTestsloopsNb > 1) { - start = System.currentTimeMillis(); - } - String header = "mergedWith failures: "; - for (int l = 0; l < combinationTestsloopsNb ; l++) { - for (int i = 0; i < testData.length; i++) { - UnconditionalFlowInfoTestHarness result; - if (!(result = (UnconditionalFlowInfoTestHarness) - UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0]). - mergedWith( - UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1]))). - testEquals(UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][2]))) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // instead of: " + testStringValueOf(testData[i][2])); - } - } - } - if (combinationTestsloopsNb > 1) { - System.out.println("mergedWith\t\t\t" + combinationTestsloopsNb + "\t" + - (System.currentTimeMillis() - start)); - } - UnconditionalFlowInfoTestHarness - zero = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(new long[] {0,0,0,0}), - left1, right1, left2, right2, - expected1, expected2, result; - for (int i = 0; i < testData.length; i++) { - left1 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0], 64); - left2 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][0], 128); - right1 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1], 64); - right2 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][1], 128); - expected1 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][2], 64); - expected2 = UnconditionalFlowInfoTestHarness. - testUnconditionalFlowInfo(testData[i][2], 128); - if (!(result = (UnconditionalFlowInfoTestHarness) - left1.copy().mergedWith(right1)).testEquals(expected1)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (64, 64) - instead of: " + testStringValueOf(testData[i][2])); - } - if (testData[i][0][0] + testData[i][0][1] + - testData[i][0][2] + testData[i][0][3] == 0) { - if (!(result = (UnconditionalFlowInfoTestHarness) - zero.copy().mergedWith(right1)).testEquals(expected1)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (zero, 64) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - right2.copy().mergedWith(right1)). - testEquals(expected1, 64)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (zero 128, 64) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - zero.copy().mergedWith(right2)). - testEquals(expected2, 128)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (zero, 128) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - right1.copy().mergedWith(right2)). - testEquals(expected2, 128)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (zero 64, 128) - instead of: " + testStringValueOf(testData[i][2])); - } - } - if (testData[i][1][0] + testData[i][1][1] + - testData[i][1][2] + testData[i][1][3] == 0) { - if (!(result = (UnconditionalFlowInfoTestHarness) - left1.copy().mergedWith(zero)).testEquals(expected1)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (64, zero) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - left1.mergedWith(left2)). - testEquals(expected1, 64)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (64, zero 128) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - left2.copy().mergedWith(zero)). - testEquals(expected2, 128)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (128, zero) - instead of: " + testStringValueOf(testData[i][2])); - } - if (!(result = (UnconditionalFlowInfoTestHarness) - left2.mergedWith(left1)). - testEquals(expected2, 128)) { - if (failures == 0) { - System.out.println(header); - } - failures++; - System.out.println("\t\t{" + testStringValueOf(testData[i][0]) + - ',' + testStringValueOf(testData[i][1]) + - ',' + result.testString() + - "}, // (128, zero 64) - instead of: " + testStringValueOf(testData[i][2])); - } - } - } - if (printTablesAsNames) { - System.out.println("RECAP TABLE FOR MERGE"); - for (int i = 0; i < testData.length; i++) { - System.out.println(testSymbolicValueOf(testData[i][0]) + " + " + - testSymbolicValueOf(testData[i][1]) + " -> " + - testSymbolicValueOf(testData[i][2])); - } - - } - if (printTablesAsCodes) { - System.out.println("RECAP TABLE FOR MERGE"); - for (int i = 0; i < testData.length; i++) { - System.out.println(testCodedValueOf(testData[i][0]) + " " + - testCodedValueOf(testData[i][1]) + " " + - testCodedValueOf(testData[i][2])); - } - } - if (printTruthMaps) { - for (int i = 0; i < 4; i++) { - System.out.println("======================================================"); - System.out.println("Truth map for mergedWith null bit " + (i + 1)); - System.out.println(); - } - } - assertTrue("nb of failures: " + failures, failures == 0); -} - -// Use for coverage tests only. Needs specific instrumentation of code, -// that is controled by UnconditionalFlowInfo#coverageTestFlag. -// Note: coverage tests tend to fill the console with messages, and the -// instrumented code is slower, so never release code with active -// coverage tests. -private static int coveragePointsNb = 46; - -// Coverage by state transition tables methods. -public void test2998_coverage() { - if (UnconditionalFlowInfo.coverageTestFlag) { - // sanity check: need to be sure that the tests execute properly when not - // trying to check coverage - UnconditionalFlowInfo.coverageTestId = 0; - test0053_array(); - test0070_type_reference(); - test2050_markAsComparedEqualToNonNull(); - test2051_markAsComparedEqualToNull(); - test2052_markAsDefinitelyNonNull(); - test2053_markAsDefinitelyNull(); - test2054_markAsDefinitelyUnknown(); - test2055_addInitializationsFrom(); - test2056_addPotentialInitializationsFrom(); - test2057_mergedWith(); - // coverage check - int failuresNb = 0; - for (int i = 1; i <= coveragePointsNb; i++) { - try { - UnconditionalFlowInfo.coverageTestId = i; - test0053_array(); - test0070_type_reference(); - test2050_markAsComparedEqualToNonNull(); - test2051_markAsComparedEqualToNull(); - test2052_markAsDefinitelyNonNull(); - test2053_markAsDefinitelyNull(); - test2054_markAsDefinitelyUnknown(); - test2055_addInitializationsFrom(); - test2056_addPotentialInitializationsFrom(); - test2057_mergedWith(); - } - catch (AssertionFailedError e) { - continue; - } - catch (AssertionFailedException e) { - continue; - } - failuresNb++; - System.out.println("Missing coverage point: " + i); - } - UnconditionalFlowInfo.coverageTestId = 0; // reset for other tests - assertEquals(failuresNb + " missing coverage point(s)", failuresNb, 0); - } -} - -// Coverage by code samples. -public void test2999_coverage() { - if (UnconditionalFlowInfo.coverageTestFlag) { - // sanity check: need to be sure that the tests execute properly when not - // trying to check coverage - UnconditionalFlowInfo.coverageTestId = 0; - test0001_simple_local(); - test0053_array(); - test0070_type_reference(); - test0327_if_else(); - test0401_while(); - test0420_while(); - test0509_try_finally_embedded(); - test2000_flow_info(); - test2004_flow_info(); - test2008_flow_info(); - test2011_flow_info(); - test2013_flow_info(); - test2018_flow_info(); - test2019_flow_info(); - test2020_flow_info(); - // coverage check - int failuresNb = 0; - for (int i = 1; i <= coveragePointsNb; i++) { - if (i > 4 && i < 15 || - i > 15 && i < 19 || - i == 22 || - i == 23 || - i == 27 || - i == 28 || - i == 30 || - i == 33 || - i == 34 || - i == 38 || - i >= 43 - ) { // TODO (maxime) complete coverage tests - continue; - } - try { - UnconditionalFlowInfo.coverageTestId = i; - test0001_simple_local(); - test0053_array(); - test0070_type_reference(); - test0327_if_else(); - test0401_while(); - test0420_while(); - test0509_try_finally_embedded(); - test2000_flow_info(); - test2004_flow_info(); - test2008_flow_info(); - test2011_flow_info(); - test2013_flow_info(); - test2018_flow_info(); - test2019_flow_info(); - test2020_flow_info(); - } - catch (AssertionFailedError e) { - continue; - } - catch (AssertionFailedException e) { - continue; - } - failuresNb++; - System.out.println("Missing coverage point: " + i); - } - UnconditionalFlowInfo.coverageTestId = 0; // reset for other tests - assertEquals(failuresNb + " missing coverage point(s)", failuresNb, 0); - } -} - -// only works for info coded on bit 0 - least significant -String testCodedValueOf(long[] data) { - StringBuffer result = new StringBuffer(4); - for (int i = 0; i < data.length; i++) { - result.append(data[i] == 0 ? '0' : '1'); - } - return result.toString(); -} - -String testStringValueOf(long[] data) { - StringBuffer result = new StringBuffer(9); - result.append('{'); - for (int j = 0; j < 4; j++) { - if (j > 0) { - result.append(','); - } - result.append(data[j]); - } - result.append('}'); - return result.toString(); -} - -String testStringValueOf(long[][] data) { - StringBuffer result = new StringBuffer(25); - result.append('{'); - for (int i = 0; i < 3; i++) { - if (i > 0) { - result.append(','); - } - result.append('{'); - for (int j = 0; j < 4; j++) { - if (j > 0) { - result.append(','); - } - result.append(data[i][j]); - } - result.append('}'); - } - result.append('}'); - return result.toString(); -} - -// only works for info coded on bit 0 - least significant -String testSymbolicValueOf(long[] data) { - if (data[0] == 0) { - if (data[1] == 0) { - if (data[2] == 0) { - if (data[3] == 0) { - return "start "; //$NON-NLS1$ - } - else { - return "pot. nn/unknown "; //$NON-NLS1$ - } - } - else { - if (data[3] == 0) { - return "pot. null "; //$NON-NLS1$ - } - else { - return "pot. n/nn/unkn. "; //$NON-NLS1$ - } - } - } - else { - if (data[2] == 0) { - if (data[3] == 0) { - return "prot. null "; //$NON-NLS1$ - } - else { - return "0101 "; //$NON-NLS1$ - } - } - else { - if (data[3] == 0) { - return "prot. null + pot. null"; //$NON-NLS1$ - } - else { - return "0111 "; //$NON-NLS1$ - } - } - } - } - else { - if (data[1] == 0) { - if (data[2] == 0) { - if (data[3] == 0) { - return "1000 "; //$NON-NLS1$ - } - else { - return "assigned non null "; //$NON-NLS1$ - } - } - else { - if (data[3] == 0) { - return "assigned null "; //$NON-NLS1$ - } - else { - return "assigned unknown "; //$NON-NLS1$ - } - } - } - else { - if (data[2] == 0) { - if (data[3] == 0) { - return "protected non null "; //$NON-NLS1$ - } - else { - return "prot. nn + pot. nn/unknown"; //$NON-NLS1$ - } - } - else { - if (data[3] == 0) { - return "1110 "; //$NON-NLS1$ - } - else { - return "1111 "; //$NON-NLS1$ - } - } - } - } -} - -private void printTruthMap(long data[][][], int bit) { - final int dimension = 16; - printTruthMapHeader(); - char truthValues[][] = new char[dimension][dimension]; - int row, column; - for (row = 0; row < dimension; row++) { - for (column = 0; column < dimension; column++) { - truthValues[row][column] = '.'; - } - } - String rows[] = { - "0000", - "0001", - "0011", - "0111", - "1111", - "1110", - "1100", - "1000", - "1010", - "1011", - "1001", - "1101", - "0101", - "0100", - "0110", - "0010" - }; - if (false) { // checking row names - for (row = 0; row < dimension; row++) { - long [] state = new long [4]; - for (int i = 0; i < 4; i++) { - state[i] = rows[row].charAt(i) - '0'; - } - System.out.println(row + " " + rows[row] + " " + rankForState(state)); - } - } - for (int i = 0; i < data.length; i++) { - truthValues[rankForState(data[i][0])][rankForState(data[i][1])] = - (char) ('0' + data[i][2][bit]); - } - for (row = 0; row < dimension; row++) { - StringBuffer line = new StringBuffer(120); - line.append(rows[row]); - line.append(" | "); - for (column = 0; column < dimension; column++) { - line.append(truthValues[row][column]); - line.append(' '); - } - System.out.println(line); - } -} - -private void printTruthMapHeader() { - System.out.println(" 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0"); - System.out.println(" 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0"); - System.out.println(" 0 0 1 1 1 1 0 0 1 1 0 0 0 0 1 1"); - System.out.println(" 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0"); - System.out.println(" --------------------------------"); -} - -private int rankForState(long [] state) { - if (state[0] == 0) { - if (state[1] == 0) { - if (state[2] == 0) { - if (state[3] == 0) { - return 0; // 0000 - } - else { - return 1; // 0001 - } - } - else { - if (state[3] == 0) { - return 15; // 0010 - } - else { - return 2; // 0011 - } - } - } - else { - if (state[2] == 0) { - if (state[3] == 0) { - return 13; // 0100 - } - else { - return 12; // 0101 - } - } - else { - if (state[3] == 0) { - return 14; // 0110 - } - else { - return 3; // 0111 - } - } - } - } - else { - if (state[1] == 0) { - if (state[2] == 0) { - if (state[3] == 0) { - return 7; // 1000 - } - else { - return 10; // 1001 - } - } - else { - if (state[3] == 0) { - return 8; // 1010 - } - else { - return 9; // 1011 - } - } - } - else { - if (state[2] == 0) { - if (state[3] == 0) { - return 6; // 1100 - } - else { - return 11; // 1101 - } - } - else { - if (state[3] == 0) { - return 5; // 1110 - } - else { - return 4; // 1111 - } - } - } - } -} -} - -class TestLocalVariableBinding extends LocalVariableBinding { - final static char [] testName = {'t', 'e', 's', 't'}; - TestLocalVariableBinding(int id) { - super(testName, null, 0, false); - this.id = id; - } -} - -/** - * A class meant to augment - * @link{org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo} with - * capabilities in the test domain. It especially provides factories to build - * fake flow info instances for use in state transition tables validation. - */ -class UnconditionalFlowInfoTestHarness extends UnconditionalFlowInfo { - private int testPosition; - -/** - * Return a fake unconditional flow info which bit fields represent the given - * null bits for a local variable of id 0 within a class that would have no - * field. - * @param nullBits the bits that must be set, given in the same order as the - * nullAssignment* fields in UnconditionalFlowInfo definition; use 0 - * for a bit that is not set, 1 else - * @return a fake unconditional flow info which bit fields represent the - * null bits given in parameter - */ -public static UnconditionalFlowInfoTestHarness testUnconditionalFlowInfo( - long [] nullBits) { - return testUnconditionalFlowInfo(nullBits, 0); -} - -public FlowInfo copy() { - UnconditionalFlowInfoTestHarness copy = - new UnconditionalFlowInfoTestHarness(); - copy.testPosition = this.testPosition; - copy.definiteInits = this.definiteInits; - copy.potentialInits = this.potentialInits; - boolean hasNullInfo = (this.tagBits & NULL_FLAG_MASK) != 0; - if (hasNullInfo) { - copy.nullAssignmentStatusBit1 = this.nullAssignmentStatusBit1; - copy.nullAssignmentStatusBit2 = this.nullAssignmentStatusBit2; - copy.nullAssignmentValueBit1 = this.nullAssignmentValueBit1; - copy.nullAssignmentValueBit2 = this.nullAssignmentValueBit2; - } - copy.tagBits = this.tagBits; - copy.maxFieldCount = this.maxFieldCount; - if (this.extra != null) { - int length; - copy.extra = new long[extraLength][]; - System.arraycopy(this.extra[0], 0, - (copy.extra[0] = new long[length = extra[0].length]), 0, length); - System.arraycopy(this.extra[1], 0, - (copy.extra[1] = new long[length]), 0, length); - if (hasNullInfo) { - for (int j = 0; j < extraLength; j++) { - System.arraycopy(this.extra[j], 0, - (copy.extra[j] = new long[length]), 0, length); - } - } - else { - for (int j = 0; j < extraLength; j++) { - copy.extra[j] = new long[length]; - } - } - } - return copy; -} - -/** - * Return a fake unconditional flow info which bit fields represent the given - * null bits for a local variable of id position within a class that would have - * no field. - * @param nullBits the bits that must be set, given in the same order as the - * nullAssignment* fields in UnconditionalFlowInfo definition; use 0 - * for a bit that is not set, 1 else - * @param position the position of the variable within the bit fields; use - * various values to test different parts of the bit fields, within - * or beyond BitCacheSize - * @return a fake unconditional flow info which bit fields represent the - * null bits given in parameter - */ -public static UnconditionalFlowInfoTestHarness testUnconditionalFlowInfo( - long [] nullBits, int position) { - UnconditionalFlowInfoTestHarness result = - new UnconditionalFlowInfoTestHarness(); - result.testPosition = position; - if (position < BitCacheSize) { - result.nullAssignmentStatusBit1 = nullBits[0] << position; - result.nullAssignmentStatusBit2 = nullBits[1] << position; - result.nullAssignmentValueBit1 = nullBits[2] << position; - result.nullAssignmentValueBit2 = nullBits[3] << position; - } - else { - int vectorIndex = (position / BitCacheSize) - 1, - length = vectorIndex + 1; - position %= BitCacheSize; - result.extra = new long[extraLength][]; - result.extra[0] = new long[length]; - result.extra[1] = new long[length]; - for (int j = 2; j < extraLength; j++) { - result.extra[j] = new long[length]; - result.extra[j][vectorIndex] = nullBits[j - 2] << - position; - } - } - if ((nullBits[0] | nullBits[1] | nullBits[2] | nullBits[3]) != 0) { - result.tagBits |= NULL_FLAG_MASK; - } - result.maxFieldCount = 0; - return result; -} - -/** - * Return a fake unconditional flow info which bit fields represent the given - * null bits for a pair of local variables of id position and position + - * extra * BitCacheSize within a class that would have no field. - * @param nullBits the bits that must be set, given in the same order as the - * nullAssignment* fields in UnconditionalFlowInfo definition; use 0 - * for a bit that is not set, 1 else - * @param position the position of the variable within the bit fields; use - * various values to test different parts of the bit fields, within - * or beyond BitCacheSize - * @param extra the length of the allocated extra bit fields, if position is - * beyond BitCacheSize; unused otherwise; make sure it is big enough to - * match position (that is, extra > position - BitCacheSize) - * @return a fake unconditional flow info which bit fields represent the - * null bits given in parameter - */ -public static UnconditionalFlowInfoTestHarness testUnconditionalFlowInfo( - long [] nullBits, int position, int extra) { - UnconditionalFlowInfoTestHarness result = - new UnconditionalFlowInfoTestHarness(); - result.testPosition = position; - if (position < BitCacheSize) { - result.nullAssignmentStatusBit1 = nullBits[0] << position; - result.nullAssignmentStatusBit2 = nullBits[1] << position; - result.nullAssignmentValueBit1 = nullBits[2] << position; - result.nullAssignmentValueBit2 = nullBits[3] << position; - } - else { - int vectorIndex = (position / BitCacheSize) - 1, - length = extra / BitCacheSize; - position %= BitCacheSize; - result.extra = new long[extraLength][]; - result.extra[0] = new long[length]; - result.extra[1] = new long[length]; - for (int j = 2; j < extraLength; j++) { - result.extra[j] = new long[length]; - result.extra[j] [vectorIndex]= nullBits[j - 2] << position; - } - } - if (nullBits[1] != 0 || nullBits[3] != 0 || nullBits[0] != 0 || nullBits[2] != 0 ) { - // cascade better than nullBits[0] | nullBits[1] | nullBits[2] | nullBits[3] - // by 10%+ - // TODO (maxime) run stats to determine which is the better order - result.tagBits |= NULL_FLAG_MASK; - } - result.maxFieldCount = 0; - return result; -} - -/** - * Return true iff this flow info can be considered as equal to the one passed - * in parameter. - * @param other the flow info to compare to - * @return true iff this flow info compares equal to other - */ -public boolean testEquals(UnconditionalFlowInfo other) { - if (this.tagBits != other.tagBits) { - return false; - } - if (this.nullAssignmentStatusBit1 != other.nullAssignmentStatusBit1 || - this.nullAssignmentStatusBit2 != other.nullAssignmentStatusBit2 || - this.nullAssignmentValueBit1 != other.nullAssignmentValueBit1 || - this.nullAssignmentValueBit2 != other.nullAssignmentValueBit2) { - return false; - } - int left = this.extra == null ? 0 : this.extra[0].length, - right = other.extra == null ? 0 : other.extra[0].length, - both = 0, i; - if (left > right) { - both = right; - } - else { - both = left; - } - for (i = 0; i < both ; i++) { - if (this.extra[2][i] != - other.extra[2][i] || - this.extra[3][i] != - other.extra[3][i] || - this.extra[4][i] != - other.extra[4][i] || - this.extra[5][i] != - other.extra[5][i]) { - return false; - } - } - for (; i < left; i++) { - if (this.extra[2][i] != 0 || - this.extra[3][i] != 0 || - this.extra[4][i] != 0 || - this.extra[5][i] != 0) { - return false; - } - } - for (; i < right; i++) { - if (other.extra[2][i] != 0 || - other.extra[3][i] != 0 || - other.extra[4][i] != 0 || - other.extra[5][i] != 0) { - return false; - } - } - return true; -} - -/** - * Return true iff this flow info can be considered as equal to the one passed - * in parameter in respect with a single local variable which id would be - * position in a class with no field. - * @param other the flow info to compare to - * @param position the position of the local to consider - * @return true iff this flow info compares equal to other for a given local - */ -public boolean testEquals(UnconditionalFlowInfo other, int position) { - int vectorIndex = position / BitCacheSize - 1; - if ((this.tagBits & other.tagBits & NULL_FLAG_MASK) == 0) { - return true; - } - long mask; - if (vectorIndex < 0) { - return ((this.nullAssignmentStatusBit1 & (mask = (1L << position))) ^ - (other.nullAssignmentStatusBit1 & mask)) == 0 && - ((this.nullAssignmentStatusBit2 & mask) ^ - (other.nullAssignmentStatusBit2 & mask)) == 0 && - ((this.nullAssignmentValueBit1 & mask) ^ - (other.nullAssignmentValueBit1 & mask)) == 0 && - ((this.nullAssignmentValueBit2 & mask) ^ - (other.nullAssignmentValueBit2 & mask)) == 0; - } - else { - int left = this.extra == null ? - 0 : - this.extra[0].length; - int right = other.extra == null ? - 0 : - other.extra[0].length; - int both = left < right ? left : right; - if (vectorIndex < both) { - return ((this.extra[2][vectorIndex] & - (mask = (1L << (position % BitCacheSize)))) ^ - (other.extra[2][vectorIndex] & mask)) == 0 && - ((this.extra[3][vectorIndex] & mask) ^ - (other.extra[3][vectorIndex] & mask)) == 0 && - ((this.extra[4][vectorIndex] & mask) ^ - (other.extra[4][vectorIndex] & mask)) == 0 && - ((this.extra[5][vectorIndex] & mask) ^ - (other.extra[5][vectorIndex] & mask)) == 0; - } - if (vectorIndex < left) { - return ((this.extra[2][vectorIndex] | - this.extra[3][vectorIndex] | - this.extra[4][vectorIndex] | - this.extra[5][vectorIndex]) & - (1L << (position % BitCacheSize))) == 0; - } - return ((other.extra[2][vectorIndex] | - other.extra[3][vectorIndex] | - other.extra[4][vectorIndex] | - other.extra[5][vectorIndex]) & - (1L << (position % BitCacheSize))) == 0; - } -} - -/** - * Return a string suitable for use as a representation of this flow info - * within test series. - * @return a string suitable for use as a representation of this flow info - */ -public String testString() { - if (this == DEAD_END) { - return "FlowInfo.DEAD_END"; //$NON-NLS-1$ - } - return testString(this.testPosition); -} - -/** - * Return a string suitable for use as a representation of this flow info - * within test series. - * @param position a position to consider instead of this flow info default - * test position - * @return a string suitable for use as a representation of this flow info - */ -public String testString(int position) { - if (this == DEAD_END) { - return "FlowInfo.DEAD_END"; //$NON-NLS-1$ - } - if (position < BitCacheSize) { - return "{" + (this.nullAssignmentStatusBit1 >> position) //$NON-NLS-1$ - + "," + (this.nullAssignmentStatusBit2 >> position) //$NON-NLS-1$ - + "," + (this.nullAssignmentValueBit1 >> position) //$NON-NLS-1$ - + "," + (this.nullAssignmentValueBit2 >> position) //$NON-NLS-1$ - + "}"; //$NON-NLS-1$ - } - else { - int vectorIndex = position / BitCacheSize - 1, - shift = position % BitCacheSize; - return "{" + (this.extra[2][vectorIndex] //$NON-NLS-1$ - >> shift) - + "," + (this.extra[3][vectorIndex] //$NON-NLS-1$ - >> shift) - + "," + (this.extra[4][vectorIndex] //$NON-NLS-1$ - >> shift) - + "," + (this.extra[5][vectorIndex] //$NON-NLS-1$ - >> shift) - + "}"; //$NON-NLS-1$ - } -} } Index: .settings/org.eclipse.jdt.ui.prefs =================================================================== RCS file: .settings/org.eclipse.jdt.ui.prefs diff -N .settings/org.eclipse.jdt.ui.prefs --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ .settings/org.eclipse.jdt.ui.prefs 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,5 @@ +#Thu Feb 23 14:36:02 CET 2006 +eclipse.preferences.version=1 +formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile +formatter_settings_version=10 +internal.default.compliance=user Index: src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTransformations.java =================================================================== RCS file: src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTransformations.java diff -N src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTransformations.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTransformations.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,3177 @@ +/******************************************************************************* + * Copyright (c) 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.tests.compiler.regression; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.eclipse.jdt.core.tests.compiler.regression.NullReferenceImplTests.State; +import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo; +public class NullReferenceImplTransformations { + public static final Transformation + markAsComparedEqualToNonNull = + // markAsComparedEqualToNonNull DEFINITION START + // start => prot. non null + // prot. non null => prot. non null + // prot. null => prot. non null + // pot. unknown => pot. nn & prot. nn + // pot. non null => pot. nn & prot. nn + // pot. nn & prot. nn => pot. nn & prot. nn + // pot. nn & pot. un => pot. nn & prot. nn + // pot. null => prot. non null + // pot. n & prot. n => prot. non null + // pot. n & pot. un => pot. nn & prot. nn + // pot. n & pot. nn => pot. nn & prot. nn + // def. unknown => def. non null + // def. non null => def. non null + // def. null => prot. non null + // markAsComparedEqualToNonNull DEFINITION END + new TwoDimensionalTransformation("markAsComparedEqualToNonNull", + new byte[][] { + // markAsComparedEqualToNonNull INITIALIZER START + {0x00,0x3C}, + {0x04,0x2C}, + {0x08,0x2C}, + {0x0C,0x2C}, + {0x10,0x3C}, + {0x14,0x2C}, + {0x18,0x2C}, + {0x24,0x28}, + {0x28,0x28}, + {0x2C,0x2C}, + {0x30,0x3C}, + {0x34,0x3C}, + {0x38,0x3C}, + {0x3C,0x3C}, + // markAsComparedEqualToNonNull INITIALIZER END + }) { + UnconditionalFlowInfo output(UnconditionalFlowInfo input, + TestLocalVariableBinding local) { + UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy(); + result.markAsComparedEqualToNonNull(local); + return result; + } + }, + markAsComparedEqualToNull = + // markAsComparedEqualToNull DEFINITION START + // start => prot. null + // prot. non null => prot. null + // prot. null => prot. null + // pot. unknown => pot. n & prot. n + // pot. non null => prot. null + // pot. nn & prot. nn => prot. null + // pot. nn & pot. un => pot. n & prot. n + // pot. null => pot. n & prot. n + // pot. n & prot. n => pot. n & prot. n + // pot. n & pot. un => pot. n & prot. n + // pot. n & pot. nn => pot. n & prot. n + // def. unknown => def. null + // def. non null => prot. null + // def. null => def. null + // markAsComparedEqualToNull DEFINITION END + new TwoDimensionalTransformation("markAsComparedEqualToNull", + new byte[][] { + // markAsComparedEqualToNull INITIALIZER START + {0x00,0x38}, + {0x04,0x34}, + {0x08,0x38}, + {0x0C,0x34}, + {0x10,0x34}, + {0x14,0x34}, + {0x18,0x34}, + {0x24,0x30}, + {0x28,0x38}, + {0x2C,0x38}, + {0x30,0x30}, + {0x34,0x34}, + {0x38,0x38}, + {0x3C,0x38}, + // markAsComparedEqualToNull INITIALIZER END + }) { + UnconditionalFlowInfo output(UnconditionalFlowInfo input, + TestLocalVariableBinding local) { + UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy(); + result.markAsComparedEqualToNull(local); + return result; + } + }, + markAsDefinitelyNonNull = + // markAsDefinitelyNonNull DEFINITION START + // start => def. non null + // prot. non null => def. non null + // prot. null => def. non null + // pot. unknown => def. non null + // pot. non null => def. non null + // pot. nn & prot. nn => def. non null + // pot. nn & pot. un => def. non null + // pot. null => def. non null + // pot. n & prot. n => def. non null + // pot. n & pot. un => def. non null + // pot. n & pot. nn => def. non null + // def. unknown => def. non null + // def. non null => def. non null + // def. null => def. non null + // markAsDefinitelyNonNull DEFINITION END + new TwoDimensionalTransformation("markAsDefinitelyNonNull", + new byte[][] { + // markAsDefinitelyNonNull INITIALIZER START + {0x00,0x28}, + {0x04,0x28}, + {0x08,0x28}, + {0x0C,0x28}, + {0x10,0x28}, + {0x14,0x28}, + {0x18,0x28}, + {0x24,0x28}, + {0x28,0x28}, + {0x2C,0x28}, + {0x30,0x28}, + {0x34,0x28}, + {0x38,0x28}, + {0x3C,0x28}, + // markAsDefinitelyNonNull INITIALIZER END + }) { + UnconditionalFlowInfo output(UnconditionalFlowInfo input, + TestLocalVariableBinding local) { + UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy(); + result.markAsDefinitelyNonNull(local); + return result; + } + }, + markAsDefinitelyNull = + // markAsDefinitelyNull DEFINITION START + // start => def. null + // prot. non null => def. null + // prot. null => def. null + // pot. unknown => def. null + // pot. non null => def. null + // pot. nn & prot. nn => def. null + // pot. nn & pot. un => def. null + // pot. null => def. null + // pot. n & prot. n => def. null + // pot. n & pot. un => def. null + // pot. n & pot. nn => def. null + // def. unknown => def. null + // def. non null => def. null + // def. null => def. null + // markAsDefinitelyNull DEFINITION END + // PREMATURE add 'catch rules' + new TwoDimensionalTransformation("markAsDefinitelyNull", + new byte[][] { + // markAsDefinitelyNull INITIALIZER START + {0x00,0x30}, + {0x04,0x30}, + {0x08,0x30}, + {0x0C,0x30}, + {0x10,0x30}, + {0x14,0x30}, + {0x18,0x30}, + {0x24,0x30}, + {0x28,0x30}, + {0x2C,0x30}, + {0x30,0x30}, + {0x34,0x30}, + {0x38,0x30}, + {0x3C,0x30}, + // markAsDefinitelyNull INITIALIZER END + }) { + UnconditionalFlowInfo output(UnconditionalFlowInfo input, + TestLocalVariableBinding local) { + UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy(); + result.markAsDefinitelyNull(local); + return result; + } + }, + markAsDefinitelyUnknown = + // markAsDefinitelyUnknown DEFINITION START + // start => def. unknown + // prot. non null => def. unknown + // prot. null => def. unknown + // pot. unknown => def. unknown + // pot. non null => def. unknown + // pot. nn & prot. nn => def. unknown + // pot. nn & pot. un => def. unknown + // pot. null => def. unknown + // pot. n & prot. n => def. unknown + // pot. n & pot. un => def. unknown + // pot. n & pot. nn => def. unknown + // def. unknown => def. unknown + // def. non null => def. unknown + // def. null => def. unknown + // markAsDefinitelyUnknown DEFINITION END + new TwoDimensionalTransformation("markAsDefinitelyUnknown", + new byte[][] { + // markAsDefinitelyUnknown INITIALIZER START + {0x00,0x24}, + {0x04,0x24}, + {0x08,0x24}, + {0x0C,0x24}, + {0x10,0x24}, + {0x14,0x24}, + {0x18,0x24}, + {0x24,0x24}, + {0x28,0x24}, + {0x2C,0x24}, + {0x30,0x24}, + {0x34,0x24}, + {0x38,0x24}, + {0x3C,0x24}, + // markAsDefinitelyUnknown INITIALIZER END + }) { + UnconditionalFlowInfo output(UnconditionalFlowInfo input, + TestLocalVariableBinding local) { + UnconditionalFlowInfo result = (UnconditionalFlowInfo)input.copy(); + result.markAsDefinitelyUnknown(local); + return result; + } + }, + addInitializationsFrom = + // addInitializationsFrom DEFINITION START + // def. non null + def. non null => def. non null + // def. non null + def. null => def. null + // def. non null + def. unknown => def. unknown + // def. non null + pot. n & pot. nn => pot. n & pot. nn + // def. non null + pot. n & pot. un => pot. n & pot. nn + // def. non null + pot. n & prot. n => pot. n & prot. n + // def. non null + pot. nn & pot. un => def. unknown + // def. non null + pot. nn & prot. nn => def. non null + // def. non null + pot. non null => def. non null + // def. non null + pot. null => pot. n & pot. nn + // def. non null + pot. unknown => def. unknown // priv. + // def. non null + prot. non null => def. non null + // def. non null + prot. null => prot. null + // def. non null + start => def. non null + // def. null + def. non null => def. non null + // def. null + def. null => def. null + // def. null + def. unknown => def. unknown + // def. null + pot. n & pot. nn => pot. n & pot. nn + // def. null + pot. n & pot. un => pot. n & pot. un + // def. null + pot. n & prot. n => def. null + // def. null + pot. nn & pot. un => pot. n & pot. nn + // def. null + pot. nn & prot. nn => pot. nn & prot. nn + // def. null + pot. non null => pot. n & pot. nn + // def. null + pot. null => def. null + // def. null + pot. unknown => pot. n & pot. un // pot. null privileged over def. unknown + // def. null + prot. non null => prot. non null + // def. null + prot. null => def. null + // def. null + start => def. null + // def. unknown + def. non null => def. non null + // def. unknown + def. null => def. null + // def. unknown + def. unknown => def. unknown + // def. unknown + pot. n & pot. nn => pot. n & pot. nn + // def. unknown + pot. n & pot. un => pot. n & pot. un // we loose the def here, but we need the pot. null + // def. unknown + pot. n & prot. n => def. null + // def. unknown + pot. nn & pot. un => def. unknown // priv. + // def. unknown + pot. nn & prot. nn => def. non null + // def. unknown + pot. non null => def. unknown // privileging over pot. nn & pot. un + // def. unknown + pot. null => pot. n & pot. un + // def. unknown + pot. unknown => def. unknown + // def. unknown + prot. non null => def. non null + // def. unknown + prot. null => def. null + // def. unknown + start => def. unknown + // pot. n & pot. nn + def. non null => def. non null + // pot. n & pot. nn + def. null => def. null + // pot. n & pot. nn + def. unknown => def. unknown + // pot. n & pot. nn + pot. n & pot. nn => pot. n & pot. nn + // pot. n & pot. nn + pot. n & pot. un => pot. n & pot. nn + // pot. n & pot. nn + pot. n & prot. n => pot. n & prot. n + // pot. n & pot. nn + pot. nn & pot. un => pot. n & pot. nn + // pot. n & pot. nn + pot. nn & prot. nn => pot. nn & prot. nn + // pot. n & pot. nn + pot. non null => pot. n & pot. nn + // pot. n & pot. nn + pot. null => pot. n & pot. nn + // pot. n & pot. nn + pot. unknown => pot. n & pot. nn + // pot. n & pot. nn + prot. non null => pot. nn & prot. nn + // pot. n & pot. nn + prot. null => pot. n & prot. n + // pot. n & pot. nn + start => pot. n & pot. nn + // pot. n & pot. un + def. non null => def. non null + // pot. n & pot. un + def. null => def. null + // pot. n & pot. un + def. unknown => def. unknown + // pot. n & pot. un + pot. n & pot. nn => pot. n & pot. nn + // pot. n & pot. un + pot. n & pot. un => pot. n & pot. un + // pot. n & pot. un + pot. n & prot. n => pot. n & prot. n + // pot. n & pot. un + pot. nn & pot. un => pot. n & pot. nn + // pot. n & pot. un + pot. nn & prot. nn => pot. nn & prot. nn + // pot. n & pot. un + pot. non null => pot. n & pot. nn + // pot. n & pot. un + pot. null => pot. n & pot. un + // pot. n & pot. un + pot. unknown => pot. n & pot. un + // pot. n & pot. un + prot. non null => pot. nn & prot. nn + // pot. n & pot. un + prot. null => pot. n & prot. n + // pot. n & pot. un + start => pot. n & pot. un + // pot. n & prot. n + def. non null => def. non null + // pot. n & prot. n + def. null => def. null + // pot. n & prot. n + def. unknown => def. unknown + // pot. n & prot. n + pot. n & pot. nn => pot. n & pot. nn + // pot. n & prot. n + pot. n & pot. un => pot. n & pot. un + // pot. n & prot. n + pot. n & prot. n => pot. n & prot. n + // pot. n & prot. n + pot. nn & pot. un => pot. n & pot. nn + // pot. n & prot. n + pot. nn & prot. nn => pot. nn & prot. nn + // pot. n & prot. n + pot. non null => pot. n & pot. nn + // pot. n & prot. n + pot. null => pot. n & prot. n + // pot. n & prot. n + pot. unknown => pot. n & pot. un + // pot. n & prot. n + prot. non null => prot. non null + // pot. n & prot. n + prot. null => pot. n & prot. n + // pot. n & prot. n + start => pot. n & prot. n + // pot. nn & pot. un + def. non null => def. non null + // pot. nn & pot. un + def. null => def. null + // pot. nn & pot. un + def. unknown => def. unknown + // pot. nn & pot. un + pot. n & pot. nn => pot. n & pot. nn + // pot. nn & pot. un + pot. n & pot. un => pot. n & pot. nn + // pot. nn & pot. un + pot. n & prot. n => pot. n & prot. n + // pot. nn & pot. un + pot. nn & pot. un => pot. nn & pot. un + // pot. nn & pot. un + pot. nn & prot. nn => pot. nn & prot. nn + // pot. nn & pot. un + pot. non null => pot. nn & pot. un + // pot. nn & pot. un + pot. null => pot. n & pot. nn + // pot. nn & pot. un + pot. unknown => pot. nn & pot. un + // pot. nn & pot. un + prot. non null => pot. nn & prot. nn + // pot. nn & pot. un + prot. null => pot. n & prot. n + // pot. nn & pot. un + start => pot. nn & pot. un + // pot. nn & prot. nn + def. non null => def. non null + // pot. nn & prot. nn + def. null => def. null + // pot. nn & prot. nn + def. unknown => def. unknown + // pot. nn & prot. nn + pot. n & pot. nn => pot. n & pot. nn + // pot. nn & prot. nn + pot. n & pot. un => pot. n & pot. nn + // pot. nn & prot. nn + pot. n & prot. n => pot. n & prot. n + // pot. nn & prot. nn + pot. nn & pot. un => pot. nn & pot. un + // pot. nn & prot. nn + pot. nn & prot. nn => pot. nn & prot. nn + // pot. nn & prot. nn + pot. non null => pot. nn & prot. nn + // pot. nn & prot. nn + pot. null => pot. n & pot. nn + // pot. nn & prot. nn + pot. unknown => pot. nn & pot. un + // pot. nn & prot. nn + prot. non null => pot. nn & prot. nn + // pot. nn & prot. nn + prot. null => prot. null + // pot. nn & prot. nn + start => pot. nn & prot. nn + // pot. non null + def. non null => def. non null + // pot. non null + def. null => def. null + // pot. non null + def. unknown => def. unknown + // pot. non null + pot. n & pot. nn => pot. n & pot. nn + // pot. non null + pot. n & pot. un => pot. n & pot. nn + // pot. non null + pot. n & prot. n => pot. n & prot. n + // pot. non null + pot. nn & pot. un => pot. nn & pot. un + // pot. non null + pot. nn & prot. nn => pot. nn & prot. nn + // pot. non null + pot. non null => pot. non null + // pot. non null + pot. null => pot. n & pot. nn + // pot. non null + pot. unknown => pot. nn & pot. un + // pot. non null + prot. non null => pot. nn & prot. nn + // pot. non null + prot. null => prot. null + // pot. non null + start => pot. non null + // pot. null + def. non null => def. non null + // pot. null + def. null => def. null + // pot. null + def. unknown => def. unknown + // pot. null + pot. n & pot. nn => pot. n & pot. nn + // pot. null + pot. n & pot. un => pot. n & pot. un + // pot. null + pot. n & prot. n => pot. n & prot. n + // pot. null + pot. nn & pot. un => pot. n & pot. nn + // pot. null + pot. nn & prot. nn => pot. nn & prot. nn + // pot. null + pot. non null => pot. n & pot. nn + // pot. null + pot. null => pot. null + // pot. null + pot. unknown => pot. n & pot. un + // pot. null + prot. non null => prot. non null + // pot. null + prot. null => pot. n & prot. n + // pot. null + start => pot. null + // pot. unknown + def. non null => def. non null + // pot. unknown + def. null => def. null + // pot. unknown + def. unknown => def. unknown + // pot. unknown + pot. n & pot. nn => pot. n & pot. nn + // pot. unknown + pot. n & pot. un => pot. n & pot. un + // pot. unknown + pot. n & prot. n => pot. n & prot. n + // pot. unknown + pot. nn & pot. un => pot. nn & pot. un + // pot. unknown + pot. nn & prot. nn => pot. nn & prot. nn + // pot. unknown + pot. non null => pot. nn & pot. un + // pot. unknown + pot. null => pot. n & pot. un + // pot. unknown + pot. unknown => pot. unknown + // pot. unknown + prot. non null => pot. nn & prot. nn + // pot. unknown + prot. null => pot. n & prot. n + // pot. unknown + start => pot. unknown + // prot. non null + def. non null => def. non null + // prot. non null + def. null => def. null + // prot. non null + def. unknown => def. unknown + // prot. non null + pot. n & pot. nn => pot. n & pot. nn + // prot. non null + pot. n & pot. un => pot. n & pot. un + // prot. non null + pot. n & prot. n => pot. n & prot. n + // prot. non null + pot. nn & pot. un => pot. nn & pot. un + // prot. non null + pot. nn & prot. nn => pot. nn & prot. nn + // prot. non null + pot. non null => pot. nn & prot. nn + // prot. non null + pot. null => pot. null + // prot. non null + pot. unknown => pot. unknown + // prot. non null + prot. non null => prot. non null + // prot. non null + prot. null => prot. null + // prot. non null + start => prot. non null + // prot. null + def. non null => def. non null + // prot. null + def. null => def. null + // prot. null + def. unknown => def. unknown + // prot. null + pot. n & pot. nn => pot. n & pot. nn + // prot. null + pot. n & pot. un => pot. n & pot. un + // prot. null + pot. n & prot. n => pot. n & prot. n + // prot. null + pot. nn & pot. un => pot. nn & pot. un + // prot. null + pot. nn & prot. nn => pot. nn & prot. nn + // prot. null + pot. non null => pot. non null + // prot. null + pot. null => pot. n & prot. n + // prot. null + pot. unknown => pot. unknown + // prot. null + prot. non null => prot. non null + // prot. null + prot. null => prot. null + // prot. null + start => prot. null + // start + def. non null => def. non null + // start + def. null => def. null + // start + def. unknown => def. unknown + // start + pot. n & pot. nn => pot. n & pot. nn + // start + pot. n & pot. un => pot. n & pot. un + // start + pot. n & prot. n => pot. n & prot. n + // start + pot. nn & pot. un => pot. nn & pot. un + // start + pot. nn & prot. nn => pot. nn & prot. nn + // start + pot. non null => pot. non null + // start + pot. null => pot. null + // start + pot. unknown => pot. unknown + // start + prot. non null => prot. non null + // start + prot. null => prot. null + // start + start => start + // addInitializationsFrom DEFINITION END + new ThreeDimensionalTransformation("addInitializationsFrom", + new byte[][] { + // addInitializationsFrom INITIALIZER START + {0x00,0x00,0x00}, + {0x00,0x04,0x04}, + {0x00,0x08,0x08}, + {0x00,0x0C,0x0C}, + {0x00,0x10,0x10}, + {0x00,0x14,0x14}, + {0x00,0x18,0x18}, + {0x00,0x24,0x24}, + {0x00,0x28,0x28}, + {0x00,0x2C,0x2C}, + {0x00,0x30,0x30}, + {0x00,0x34,0x34}, + {0x00,0x38,0x38}, + {0x00,0x3C,0x3C}, + {0x04,0x00,0x04}, + {0x04,0x04,0x04}, + {0x04,0x08,0x0C}, + {0x04,0x0C,0x0C}, + {0x04,0x10,0x14}, + {0x04,0x14,0x14}, + {0x04,0x18,0x18}, + {0x04,0x24,0x24}, + {0x04,0x28,0x28}, + {0x04,0x2C,0x2C}, + {0x04,0x30,0x30}, + {0x04,0x34,0x34}, + {0x04,0x38,0x34}, + {0x04,0x3C,0x2C}, + {0x08,0x00,0x08}, + {0x08,0x04,0x0C}, + {0x08,0x08,0x08}, + {0x08,0x0C,0x0C}, + {0x08,0x10,0x18}, + {0x08,0x14,0x18}, + {0x08,0x18,0x18}, + {0x08,0x24,0x24}, + {0x08,0x28,0x28}, + {0x08,0x2C,0x2C}, + {0x08,0x30,0x30}, + {0x08,0x34,0x34}, + {0x08,0x38,0x38}, + {0x08,0x3C,0x2C}, + {0x0C,0x00,0x0C}, + {0x0C,0x04,0x0C}, + {0x0C,0x08,0x0C}, + {0x0C,0x0C,0x0C}, + {0x0C,0x10,0x18}, + {0x0C,0x14,0x18}, + {0x0C,0x18,0x18}, + {0x0C,0x24,0x24}, + {0x0C,0x28,0x28}, + {0x0C,0x2C,0x2C}, + {0x0C,0x30,0x30}, + {0x0C,0x34,0x34}, + {0x0C,0x38,0x34}, + {0x0C,0x3C,0x2C}, + {0x10,0x00,0x10}, + {0x10,0x04,0x14}, + {0x10,0x08,0x18}, + {0x10,0x0C,0x18}, + {0x10,0x10,0x10}, + {0x10,0x14,0x14}, + {0x10,0x18,0x18}, + {0x10,0x24,0x24}, + {0x10,0x28,0x28}, + {0x10,0x2C,0x2C}, + {0x10,0x30,0x30}, + {0x10,0x34,0x34}, + {0x10,0x38,0x34}, + {0x10,0x3C,0x3C}, + {0x14,0x00,0x14}, + {0x14,0x04,0x14}, + {0x14,0x08,0x18}, + {0x14,0x0C,0x18}, + {0x14,0x10,0x14}, + {0x14,0x14,0x14}, + {0x14,0x18,0x18}, + {0x14,0x24,0x24}, + {0x14,0x28,0x28}, + {0x14,0x2C,0x2C}, + {0x14,0x30,0x30}, + {0x14,0x34,0x34}, + {0x14,0x38,0x34}, + {0x14,0x3C,0x2C}, + {0x18,0x00,0x18}, + {0x18,0x04,0x18}, + {0x18,0x08,0x18}, + {0x18,0x0C,0x18}, + {0x18,0x10,0x18}, + {0x18,0x14,0x18}, + {0x18,0x18,0x18}, + {0x18,0x24,0x24}, + {0x18,0x28,0x28}, + {0x18,0x2C,0x2C}, + {0x18,0x30,0x30}, + {0x18,0x34,0x34}, + {0x18,0x38,0x34}, + {0x18,0x3C,0x2C}, + {0x24,0x00,0x24}, + {0x24,0x04,0x24}, + {0x24,0x08,0x24}, + {0x24,0x0C,0x24}, + {0x24,0x10,0x14}, + {0x24,0x14,0x14}, + {0x24,0x18,0x18}, + {0x24,0x24,0x24}, + {0x24,0x28,0x28}, + {0x24,0x2C,0x28}, + {0x24,0x30,0x30}, + {0x24,0x34,0x30}, + {0x24,0x38,0x30}, + {0x24,0x3C,0x28}, + {0x28,0x00,0x28}, + {0x28,0x04,0x24}, + {0x28,0x08,0x28}, + {0x28,0x0C,0x24}, + {0x28,0x10,0x18}, + {0x28,0x14,0x18}, + {0x28,0x18,0x18}, + {0x28,0x24,0x24}, + {0x28,0x28,0x28}, + {0x28,0x2C,0x28}, + {0x28,0x30,0x30}, + {0x28,0x34,0x34}, + {0x28,0x38,0x38}, + {0x28,0x3C,0x28}, + {0x2C,0x00,0x2C}, + {0x2C,0x04,0x0C}, + {0x2C,0x08,0x2C}, + {0x2C,0x0C,0x0C}, + {0x2C,0x10,0x18}, + {0x2C,0x14,0x18}, + {0x2C,0x18,0x18}, + {0x2C,0x24,0x24}, + {0x2C,0x28,0x28}, + {0x2C,0x2C,0x2C}, + {0x2C,0x30,0x30}, + {0x2C,0x34,0x34}, + {0x2C,0x38,0x38}, + {0x2C,0x3C,0x2C}, + {0x30,0x00,0x30}, + {0x30,0x04,0x14}, + {0x30,0x08,0x18}, + {0x30,0x0C,0x18}, + {0x30,0x10,0x30}, + {0x30,0x14,0x14}, + {0x30,0x18,0x18}, + {0x30,0x24,0x24}, + {0x30,0x28,0x28}, + {0x30,0x2C,0x2C}, + {0x30,0x30,0x30}, + {0x30,0x34,0x30}, + {0x30,0x38,0x30}, + {0x30,0x3C,0x3C}, + {0x34,0x00,0x34}, + {0x34,0x04,0x14}, + {0x34,0x08,0x18}, + {0x34,0x0C,0x18}, + {0x34,0x10,0x34}, + {0x34,0x14,0x14}, + {0x34,0x18,0x18}, + {0x34,0x24,0x24}, + {0x34,0x28,0x28}, + {0x34,0x2C,0x2C}, + {0x34,0x30,0x30}, + {0x34,0x34,0x34}, + {0x34,0x38,0x34}, + {0x34,0x3C,0x3C}, + {0x38,0x00,0x38}, + {0x38,0x04,0x04}, + {0x38,0x08,0x08}, + {0x38,0x0C,0x0C}, + {0x38,0x10,0x34}, + {0x38,0x14,0x14}, + {0x38,0x18,0x18}, + {0x38,0x24,0x24}, + {0x38,0x28,0x28}, + {0x38,0x2C,0x2C}, + {0x38,0x30,0x30}, + {0x38,0x34,0x34}, + {0x38,0x38,0x38}, + {0x38,0x3C,0x3C}, + {0x3C,0x00,0x3C}, + {0x3C,0x04,0x04}, + {0x3C,0x08,0x2C}, + {0x3C,0x0C,0x0C}, + {0x3C,0x10,0x10}, + {0x3C,0x14,0x14}, + {0x3C,0x18,0x18}, + {0x3C,0x24,0x24}, + {0x3C,0x28,0x28}, + {0x3C,0x2C,0x2C}, + {0x3C,0x30,0x30}, + {0x3C,0x34,0x34}, + {0x3C,0x38,0x38}, + {0x3C,0x3C,0x3C}, + // addInitializationsFrom INITIALIZER END + }) { + UnconditionalFlowInfo output(UnconditionalFlowInfo input1, + UnconditionalFlowInfo input2) { + return (UnconditionalFlowInfo) + input1.copy().addInitializationsFrom(input2); + } + }, + // addPotentialInitializationsFrom DEFINITION START + // def. non null + def. non null => def. non null + // def. non null + def. null => pot. n & pot. nn + // def. non null + def. unknown => def. unknown + // def. non null + pot. n & pot. nn => pot. n & pot. nn + // def. non null + pot. n & pot. un => pot. n & pot. nn + // def. non null + pot. n & prot. n => pot. n & pot. nn + // def. non null + pot. nn & pot. un => def. unknown + // def. non null + pot. nn & prot. nn => def. non null + // def. non null + pot. non null => def. non null + // def. non null + pot. null => pot. n & pot. nn + // def. non null + pot. unknown => def. unknown + // def. non null + prot. non null => def. non null + // def. non null + prot. null => def. non null + // def. non null + start => def. non null + // def. null + def. non null => pot. n & pot. nn + // def. null + def. null => def. null + // def. null + def. unknown => pot. n & pot. un + // def. null + pot. n & pot. nn => pot. n & pot. nn + // def. null + pot. n & pot. un => pot. n & pot. un + // def. null + pot. n & prot. n => def. null + // def. null + pot. nn & pot. un => pot. n & pot. nn + // def. null + pot. nn & prot. nn => pot. n & pot. nn + // def. null + pot. non null => pot. n & pot. nn + // def. null + pot. null => def. null + // def. null + pot. unknown => pot. n & pot. un + // def. null + prot. non null => def. null + // def. null + prot. null => def. null + // def. null + start => def. null + // def. unknown + def. non null => def. unknown + // def. unknown + def. null => pot. n & pot. un + // def. unknown + def. unknown => def. unknown + // def. unknown + pot. n & pot. nn => pot. n & pot. nn + // def. unknown + pot. n & pot. un => pot. n & pot. un + // def. unknown + pot. n & prot. n => pot. n & pot. un + // def. unknown + pot. nn & pot. un => def. unknown + // def. unknown + pot. nn & prot. nn => def. unknown + // def. unknown + pot. non null => def. unknown + // def. unknown + pot. null => pot. n & pot. un + // def. unknown + pot. unknown => def. unknown + // def. unknown + prot. non null => def. unknown + // def. unknown + prot. null => def. unknown + // def. unknown + start => def. unknown + // pot. n & pot. nn + def. non null => pot. n & pot. nn + // pot. n & pot. nn + def. null => pot. n & pot. nn + // pot. n & pot. nn + def. unknown => pot. n & pot. nn + // pot. n & pot. nn + pot. n & pot. nn => pot. n & pot. nn + // pot. n & pot. nn + pot. n & pot. un => pot. n & pot. nn + // pot. n & pot. nn + pot. n & prot. n => pot. n & pot. nn + // pot. n & pot. nn + pot. nn & pot. un => pot. n & pot. nn + // pot. n & pot. nn + pot. nn & prot. nn => pot. n & pot. nn + // pot. n & pot. nn + pot. non null => pot. n & pot. nn + // pot. n & pot. nn + pot. null => pot. n & pot. nn + // pot. n & pot. nn + pot. unknown => pot. n & pot. nn + // pot. n & pot. nn + prot. non null => pot. n & pot. nn + // pot. n & pot. nn + prot. null => pot. n & pot. nn + // pot. n & pot. nn + start => pot. n & pot. nn + // pot. n & pot. un + def. non null => pot. n & pot. nn + // pot. n & pot. un + def. null => pot. n & pot. un + // pot. n & pot. un + def. unknown => pot. n & pot. un + // pot. n & pot. un + pot. n & pot. nn => pot. n & pot. nn + // pot. n & pot. un + pot. n & pot. un => pot. n & pot. un + // pot. n & pot. un + pot. n & prot. n => pot. n & pot. un + // pot. n & pot. un + pot. nn & pot. un => pot. n & pot. nn + // pot. n & pot. un + pot. nn & prot. nn => pot. n & pot. nn + // pot. n & pot. un + pot. non null => pot. n & pot. nn + // pot. n & pot. un + pot. null => pot. n & pot. un + // pot. n & pot. un + pot. unknown => pot. n & pot. un + // pot. n & pot. un + prot. non null => pot. n & pot. un + // pot. n & pot. un + prot. null => pot. n & pot. un + // pot. n & pot. un + start => pot. n & pot. un + // pot. n & prot. n + def. non null => pot. n & pot. nn + // pot. n & prot. n + def. null => pot. n & prot. n + // pot. n & prot. n + def. unknown => pot. n & pot. un + // pot. n & prot. n + pot. n & pot. nn => pot. n & pot. nn + // pot. n & prot. n + pot. n & pot. un => pot. n & pot. un + // pot. n & prot. n + pot. n & prot. n => pot. n & prot. n + // pot. n & prot. n + pot. nn & pot. un => pot. n & pot. nn + // pot. n & prot. n + pot. nn & prot. nn => pot. n & pot. nn + // pot. n & prot. n + pot. non null => pot. n & pot. nn + // pot. n & prot. n + pot. null => pot. n & prot. n + // pot. n & prot. n + pot. unknown => pot. n & pot. un + // pot. n & prot. n + prot. non null => pot. n & prot. n + // pot. n & prot. n + prot. null => pot. n & prot. n + // pot. n & prot. n + start => pot. n & prot. n + // pot. nn & pot. un + def. non null => pot. nn & pot. un + // pot. nn & pot. un + def. null => pot. n & pot. nn + // pot. nn & pot. un + def. unknown => pot. nn & pot. un + // pot. nn & pot. un + pot. n & pot. nn => pot. n & pot. nn + // pot. nn & pot. un + pot. n & pot. un => pot. n & pot. nn + // pot. nn & pot. un + pot. n & prot. n => pot. n & pot. nn + // pot. nn & pot. un + pot. nn & pot. un => pot. nn & pot. un + // pot. nn & pot. un + pot. nn & prot. nn => pot. nn & pot. un + // pot. nn & pot. un + pot. non null => pot. nn & pot. un + // pot. nn & pot. un + pot. null => pot. n & pot. nn + // pot. nn & pot. un + pot. unknown => pot. nn & pot. un + // pot. nn & pot. un + prot. non null => pot. nn & pot. un + // pot. nn & pot. un + prot. null => pot. nn & pot. un + // pot. nn & pot. un + start => pot. nn & pot. un + // pot. nn & prot. nn + def. non null => pot. nn & prot. nn + // pot. nn & prot. nn + def. null => pot. n & pot. nn + // pot. nn & prot. nn + def. unknown => pot. nn & pot. un + // pot. nn & prot. nn + pot. n & pot. nn => pot. n & pot. nn + // pot. nn & prot. nn + pot. n & pot. un => pot. n & pot. nn + // pot. nn & prot. nn + pot. n & prot. n => pot. n & pot. nn + // pot. nn & prot. nn + pot. nn & pot. un => pot. nn & pot. un // see test1501 + // pot. nn & prot. nn + pot. nn & prot. nn => pot. nn & prot. nn + // pot. nn & prot. nn + pot. non null => pot. nn & prot. nn + // pot. nn & prot. nn + pot. null => pot. n & pot. nn + // pot. nn & prot. nn + pot. unknown => pot. nn & pot. un + // pot. nn & prot. nn + prot. non null => pot. nn & prot. nn + // pot. nn & prot. nn + prot. null => pot. nn & prot. nn + // pot. nn & prot. nn + start => pot. nn & prot. nn + // pot. non null + def. non null => pot. non null + // pot. non null + def. null => pot. n & pot. nn + // pot. non null + def. unknown => pot. nn & pot. un + // pot. non null + pot. n & pot. nn => pot. n & pot. nn + // pot. non null + pot. n & pot. un => pot. n & pot. nn + // pot. non null + pot. n & prot. n => pot. n & pot. nn + // pot. non null + pot. nn & pot. un => pot. nn & pot. un + // pot. non null + pot. nn & prot. nn => pot. non null + // pot. non null + pot. non null => pot. non null + // pot. non null + pot. null => pot. n & pot. nn + // pot. non null + pot. unknown => pot. nn & pot. un + // pot. non null + prot. non null => pot. non null + // pot. non null + prot. null => pot. non null + // pot. non null + start => pot. non null + // pot. null + def. non null => pot. n & pot. nn + // pot. null + def. null => pot. null + // pot. null + def. unknown => pot. n & pot. un + // pot. null + pot. n & pot. nn => pot. n & pot. nn + // pot. null + pot. n & pot. un => pot. n & pot. un + // pot. null + pot. n & prot. n => pot. null + // pot. null + pot. nn & pot. un => pot. n & pot. nn + // pot. null + pot. nn & prot. nn => pot. n & pot. nn + // pot. null + pot. non null => pot. n & pot. nn + // pot. null + pot. null => pot. null + // pot. null + pot. unknown => pot. n & pot. un + // pot. null + prot. non null => pot. null + // pot. null + prot. null => pot. null + // pot. null + start => pot. null + // pot. unknown + def. non null => pot. nn & pot. un + // pot. unknown + def. null => pot. n & pot. un + // pot. unknown + def. unknown => pot. unknown + // pot. unknown + pot. n & pot. nn => pot. n & pot. nn + // pot. unknown + pot. n & pot. un => pot. n & pot. un + // pot. unknown + pot. n & prot. n => pot. n & pot. un + // pot. unknown + pot. nn & pot. un => pot. nn & pot. un + // pot. unknown + pot. nn & prot. nn => pot. nn & pot. un + // pot. unknown + pot. non null => pot. nn & pot. un + // pot. unknown + pot. null => pot. n & pot. un + // pot. unknown + pot. unknown => pot. unknown + // pot. unknown + prot. non null => pot. unknown + // pot. unknown + prot. null => pot. unknown + // pot. unknown + start => pot. unknown + // prot. non null + def. non null => pot. nn & prot. nn + // prot. non null + def. null => pot. null + // prot. non null + def. unknown => pot. unknown + // prot. non null + pot. n & pot. nn => pot. n & pot. nn + // prot. non null + pot. n & pot. un => pot. n & pot. un + // prot. non null + pot. n & prot. n => pot. null + // prot. non null + pot. nn & pot. un => pot. nn & pot. un // see test1500 + // prot. non null + pot. nn & prot. nn => pot. nn & prot. nn + // prot. non null + pot. non null => pot. nn & prot. nn + // prot. non null + pot. null => pot. null + // prot. non null + pot. unknown => pot. unknown + // prot. non null + prot. non null => prot. non null + // prot. non null + prot. null => prot. non null + // prot. non null + start => prot. non null + // prot. null + def. non null => pot. non null + // prot. null + def. null => pot. n & prot. n + // prot. null + def. unknown => pot. unknown + // prot. null + pot. n & pot. nn => pot. n & pot. nn + // prot. null + pot. n & pot. un => pot. n & pot. un + // prot. null + pot. n & prot. n => pot. n & prot. n + // prot. null + pot. nn & pot. un => pot. nn & pot. un + // prot. null + pot. nn & prot. nn => pot. non null + // prot. null + pot. non null => pot. non null + // prot. null + pot. null => pot. n & prot. n + // prot. null + pot. unknown => pot. unknown + // prot. null + prot. non null => prot. null + // prot. null + prot. null => prot. null + // prot. null + start => prot. null + // start + def. non null => pot. non null + // start + def. null => pot. null + // start + def. unknown => pot. unknown + // start + pot. n & pot. nn => pot. n & pot. nn + // start + pot. n & pot. un => pot. n & pot. un + // start + pot. n & prot. n => pot. null + // start + pot. nn & pot. un => pot. nn & pot. un + // start + pot. nn & prot. nn => pot. non null + // start + pot. non null => pot. non null + // start + pot. null => pot. null + // start + pot. unknown => pot. unknown + // start + prot. non null => start // PREMATURE may need to be tainted? + // start + prot. null => start // PREMATURE may need to be tainted? + // start + start => start + // addPotentialInitializationsFrom DEFINITION END + addPotentialInitializationsFrom = + new ThreeDimensionalTransformation("addPotentialInitializationsFrom", + new byte[][] { + // addPotentialInitializationsFrom INITIALIZER START + {0x00,0x00,0x00}, + {0x00,0x04,0x04}, + {0x00,0x08,0x08}, + {0x00,0x0C,0x0C}, + {0x00,0x10,0x10}, + {0x00,0x14,0x14}, + {0x00,0x18,0x18}, + {0x00,0x24,0x04}, + {0x00,0x28,0x08}, + {0x00,0x2C,0x08}, + {0x00,0x30,0x10}, + {0x00,0x34,0x10}, + {0x00,0x38,0x00}, + {0x00,0x3C,0x00}, + {0x04,0x00,0x04}, + {0x04,0x04,0x04}, + {0x04,0x08,0x0C}, + {0x04,0x0C,0x0C}, + {0x04,0x10,0x14}, + {0x04,0x14,0x14}, + {0x04,0x18,0x18}, + {0x04,0x24,0x04}, + {0x04,0x28,0x0C}, + {0x04,0x2C,0x0C}, + {0x04,0x30,0x14}, + {0x04,0x34,0x14}, + {0x04,0x38,0x04}, + {0x04,0x3C,0x04}, + {0x08,0x00,0x08}, + {0x08,0x04,0x0C}, + {0x08,0x08,0x08}, + {0x08,0x0C,0x0C}, + {0x08,0x10,0x18}, + {0x08,0x14,0x18}, + {0x08,0x18,0x18}, + {0x08,0x24,0x0C}, + {0x08,0x28,0x08}, + {0x08,0x2C,0x08}, + {0x08,0x30,0x18}, + {0x08,0x34,0x18}, + {0x08,0x38,0x08}, + {0x08,0x3C,0x08}, + {0x0C,0x00,0x0C}, + {0x0C,0x04,0x0C}, + {0x0C,0x08,0x0C}, + {0x0C,0x0C,0x0C}, + {0x0C,0x10,0x18}, + {0x0C,0x14,0x18}, + {0x0C,0x18,0x18}, + {0x0C,0x24,0x0C}, + {0x0C,0x28,0x0C}, + {0x0C,0x2C,0x0C}, + {0x0C,0x30,0x18}, + {0x0C,0x34,0x18}, + {0x0C,0x38,0x0C}, + {0x0C,0x3C,0x0C}, + {0x10,0x00,0x10}, + {0x10,0x04,0x14}, + {0x10,0x08,0x18}, + {0x10,0x0C,0x18}, + {0x10,0x10,0x10}, + {0x10,0x14,0x14}, + {0x10,0x18,0x18}, + {0x10,0x24,0x14}, + {0x10,0x28,0x18}, + {0x10,0x2C,0x18}, + {0x10,0x30,0x10}, + {0x10,0x34,0x10}, + {0x10,0x38,0x10}, + {0x10,0x3C,0x10}, + {0x14,0x00,0x14}, + {0x14,0x04,0x14}, + {0x14,0x08,0x18}, + {0x14,0x0C,0x18}, + {0x14,0x10,0x14}, + {0x14,0x14,0x14}, + {0x14,0x18,0x18}, + {0x14,0x24,0x14}, + {0x14,0x28,0x18}, + {0x14,0x2C,0x18}, + {0x14,0x30,0x14}, + {0x14,0x34,0x14}, + {0x14,0x38,0x14}, + {0x14,0x3C,0x14}, + {0x18,0x00,0x18}, + {0x18,0x04,0x18}, + {0x18,0x08,0x18}, + {0x18,0x0C,0x18}, + {0x18,0x10,0x18}, + {0x18,0x14,0x18}, + {0x18,0x18,0x18}, + {0x18,0x24,0x18}, + {0x18,0x28,0x18}, + {0x18,0x2C,0x18}, + {0x18,0x30,0x18}, + {0x18,0x34,0x18}, + {0x18,0x38,0x18}, + {0x18,0x3C,0x18}, + {0x24,0x00,0x24}, + {0x24,0x04,0x24}, + {0x24,0x08,0x24}, + {0x24,0x0C,0x24}, + {0x24,0x10,0x14}, + {0x24,0x14,0x14}, + {0x24,0x18,0x18}, + {0x24,0x24,0x24}, + {0x24,0x28,0x24}, + {0x24,0x2C,0x24}, + {0x24,0x30,0x14}, + {0x24,0x34,0x14}, + {0x24,0x38,0x24}, + {0x24,0x3C,0x24}, + {0x28,0x00,0x28}, + {0x28,0x04,0x24}, + {0x28,0x08,0x28}, + {0x28,0x0C,0x24}, + {0x28,0x10,0x18}, + {0x28,0x14,0x18}, + {0x28,0x18,0x18}, + {0x28,0x24,0x24}, + {0x28,0x28,0x28}, + {0x28,0x2C,0x28}, + {0x28,0x30,0x18}, + {0x28,0x34,0x18}, + {0x28,0x38,0x28}, + {0x28,0x3C,0x28}, + {0x2C,0x00,0x2C}, + {0x2C,0x04,0x0C}, + {0x2C,0x08,0x2C}, + {0x2C,0x0C,0x0C}, + {0x2C,0x10,0x18}, + {0x2C,0x14,0x18}, + {0x2C,0x18,0x18}, + {0x2C,0x24,0x0C}, + {0x2C,0x28,0x2C}, + {0x2C,0x2C,0x2C}, + {0x2C,0x30,0x18}, + {0x2C,0x34,0x18}, + {0x2C,0x38,0x2C}, + {0x2C,0x3C,0x2C}, + {0x30,0x00,0x30}, + {0x30,0x04,0x14}, + {0x30,0x08,0x18}, + {0x30,0x0C,0x18}, + {0x30,0x10,0x30}, + {0x30,0x14,0x14}, + {0x30,0x18,0x18}, + {0x30,0x24,0x14}, + {0x30,0x28,0x18}, + {0x30,0x2C,0x18}, + {0x30,0x30,0x30}, + {0x30,0x34,0x30}, + {0x30,0x38,0x30}, + {0x30,0x3C,0x30}, + {0x34,0x00,0x34}, + {0x34,0x04,0x14}, + {0x34,0x08,0x18}, + {0x34,0x0C,0x18}, + {0x34,0x10,0x34}, + {0x34,0x14,0x14}, + {0x34,0x18,0x18}, + {0x34,0x24,0x14}, + {0x34,0x28,0x18}, + {0x34,0x2C,0x18}, + {0x34,0x30,0x34}, + {0x34,0x34,0x34}, + {0x34,0x38,0x34}, + {0x34,0x3C,0x34}, + {0x38,0x00,0x38}, + {0x38,0x04,0x04}, + {0x38,0x08,0x08}, + {0x38,0x0C,0x0C}, + {0x38,0x10,0x34}, + {0x38,0x14,0x14}, + {0x38,0x18,0x18}, + {0x38,0x24,0x04}, + {0x38,0x28,0x08}, + {0x38,0x2C,0x08}, + {0x38,0x30,0x34}, + {0x38,0x34,0x34}, + {0x38,0x38,0x38}, + {0x38,0x3C,0x38}, + {0x3C,0x00,0x3C}, + {0x3C,0x04,0x04}, + {0x3C,0x08,0x2C}, + {0x3C,0x0C,0x0C}, + {0x3C,0x10,0x10}, + {0x3C,0x14,0x14}, + {0x3C,0x18,0x18}, + {0x3C,0x24,0x04}, + {0x3C,0x28,0x2C}, + {0x3C,0x2C,0x2C}, + {0x3C,0x30,0x10}, + {0x3C,0x34,0x10}, + {0x3C,0x38,0x3C}, + {0x3C,0x3C,0x3C}, + // addPotentialInitializationsFrom INITIALIZER END + }) { + UnconditionalFlowInfo output(UnconditionalFlowInfo input1, + UnconditionalFlowInfo input2) { + return (UnconditionalFlowInfo) + input1.copy().addPotentialInitializationsFrom(input2); + } + }, + mergedWith = + // mergedWith DEFINITION START + // def. non null + def. non null => def. non null + // def. non null + def. null => pot. n & pot. nn + // def. null + def. null => def. null + // def. unknown + def. non null => def. unknown + // def. unknown + def. null => pot. n & pot. un // pot. n priv. over def. unknown + // def. unknown + def. unknown => def. unknown + // pot. n & pot. nn + def. non null => pot. n & pot. nn + // pot. n & pot. nn + def. null => pot. n & pot. nn + // pot. n & pot. nn + def. unknown => pot. n & pot. nn + // pot. n & pot. nn + pot. n & pot. nn => pot. n & pot. nn + // pot. n & pot. un + def. non null => pot. n & pot. nn + // pot. n & pot. un + def. null => pot. n & pot. un + // pot. n & pot. un + def. unknown => pot. n & pot. un + // pot. n & pot. un + pot. n & pot. nn => pot. n & pot. nn + // pot. n & pot. un + pot. n & pot. un => pot. n & pot. un + // pot. n & prot. n + def. non null => pot. n & pot. nn + // pot. n & prot. n + def. null => pot. n & prot. n + // pot. n & prot. n + def. unknown => pot. n & pot. un + // pot. n & prot. n + pot. n & pot. nn => pot. n & pot. nn + // pot. n & prot. n + pot. n & pot. un => pot. n & pot. un + // pot. n & prot. n + pot. n & prot. n => pot. n & prot. n + // pot. nn & pot. un + def. non null => pot. nn & pot. un + // pot. nn & pot. un + def. null => pot. n & pot. nn + // pot. nn & pot. un + def. unknown => pot. nn & pot. un + // pot. nn & pot. un + pot. n & pot. nn => pot. n & pot. nn + // pot. nn & pot. un + pot. n & pot. un => pot. n & pot. nn + // pot. nn & pot. un + pot. n & prot. n => pot. n & pot. nn + // pot. nn & pot. un + pot. nn & pot. un => pot. nn & pot. un + // pot. nn & pot. un + pot. null => pot. n & pot. nn + // pot. nn & prot. nn + def. non null => pot. nn & prot. nn + // pot. nn & prot. nn + def. null => pot. n & pot. nn + // pot. nn & prot. nn + def. unknown => pot. nn & pot. un + // pot. nn & prot. nn + pot. n & pot. nn => pot. n & pot. nn + // pot. nn & prot. nn + pot. n & pot. un => pot. n & pot. nn + // pot. nn & prot. nn + pot. n & prot. n => pot. n & pot. nn + // pot. nn & prot. nn + pot. nn & pot. un => pot. nn & pot. un + // pot. nn & prot. nn + pot. nn & prot. nn => pot. nn & prot. nn + // pot. nn & prot. nn + pot. null => pot. n & pot. nn + // pot. non null + def. non null => pot. non null + // pot. non null + def. null => pot. n & pot. nn + // pot. non null + def. unknown => pot. nn & pot. un + // pot. non null + pot. n & pot. nn => pot. n & pot. nn + // pot. non null + pot. n & pot. un => pot. n & pot. nn + // pot. non null + pot. n & prot. n => pot. n & pot. nn + // pot. non null + pot. nn & pot. un => pot. nn & pot. un + // pot. non null + pot. nn & prot. nn => pot. non null + // pot. non null + pot. non null => pot. non null + // pot. non null + pot. null => pot. n & pot. nn + // pot. null + def. non null => pot. n & pot. nn + // pot. null + def. null => pot. null + // pot. null + def. unknown => pot. n & pot. un + // pot. null + pot. n & pot. nn => pot. n & pot. nn + // pot. null + pot. n & pot. un => pot. n & pot. un + // pot. null + pot. n & prot. n => pot. null + // pot. null + pot. null => pot. null + // pot. unknown + def. non null => pot. nn & pot. un + // pot. unknown + def. null => pot. n & pot. un + // pot. unknown + def. unknown => pot. unknown + // pot. unknown + pot. n & pot. nn => pot. n & pot. nn + // pot. unknown + pot. n & pot. un => pot. n & pot. un + // pot. unknown + pot. n & prot. n => pot. n & pot. un + // pot. unknown + pot. nn & pot. un => pot. nn & pot. un + // pot. unknown + pot. nn & prot. nn => pot. nn & pot. un + // pot. unknown + pot. non null => pot. nn & pot. un + // pot. unknown + pot. null => pot. n & pot. un + // pot. unknown + pot. unknown => pot. unknown + // prot. non null + def. non null => pot. nn & prot. nn + // prot. non null + def. null => pot. null + // prot. non null + def. unknown => def. unknown // test726 + // prot. non null + pot. n & pot. nn => pot. n & pot. nn + // prot. non null + pot. n & pot. un => pot. n & pot. un + // prot. non null + pot. n & prot. n => pot. null + // prot. non null + pot. nn & pot. un => pot. nn & pot. un + // prot. non null + pot. nn & prot. nn => pot. nn & prot. nn + // prot. non null + pot. non null => pot. non null + // prot. non null + pot. null => pot. null + // prot. non null + pot. unknown => pot. unknown + // prot. non null + prot. non null => prot. non null + // prot. non null + prot. null => pot. null // PREMATURE use tainted instead + // 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) + // prot. null + def. null => pot. n & prot. n + // prot. null + def. unknown => pot. unknown // PREMATURE possibly wrong, but no test case yet + // prot. null + pot. n & pot. nn => pot. n & pot. nn + // prot. null + pot. n & pot. un => pot. n & pot. un + // prot. null + pot. n & prot. n => pot. n & prot. n + // prot. null + pot. nn & pot. un => pot. n & pot. nn + // prot. null + pot. nn & prot. nn => pot. n & pot. nn + // prot. null + pot. non null => pot. n & pot. nn + // prot. null + pot. null => pot. null + // prot. null + pot. unknown => pot. unknown // PREMATURE possibly wrong, but no test case yet + // prot. null + prot. null => prot. null + // start + def. non null => pot. non null + // start + def. null => pot. null + // start + def. unknown => pot. unknown + // start + pot. n & pot. nn => pot. n & pot. nn + // start + pot. n & pot. un => pot. n & pot. un + // start + pot. n & prot. n => pot. null + // start + pot. nn & pot. un => pot. nn & pot. un + // start + pot. nn & prot. nn => pot. non null + // start + pot. non null => pot. non null + // start + pot. null => pot. null + // start + pot. unknown => pot. unknown + // start + prot. non null => start // PREMATURE should it taint? + // start + prot. null => start + // start + start => start + // mergedWith DEFINITION END + new SymmetricalThreeDimensionalTransformation("mergedWith", + new byte[][] { + // mergedWith INITIALIZER START + {0x00,0x00,0x00}, + {0x00,0x04,0x04}, + {0x00,0x08,0x08}, + {0x00,0x0C,0x0C}, + {0x00,0x10,0x10}, + {0x00,0x14,0x14}, + {0x00,0x18,0x18}, + {0x00,0x24,0x04}, + {0x00,0x28,0x08}, + {0x00,0x2C,0x08}, + {0x00,0x30,0x10}, + {0x00,0x34,0x10}, + {0x00,0x38,0x00}, + {0x00,0x3C,0x00}, + {0x04,0x04,0x04}, + {0x04,0x08,0x0C}, + {0x04,0x0C,0x0C}, + {0x04,0x10,0x14}, + {0x04,0x14,0x14}, + {0x04,0x18,0x18}, + {0x04,0x24,0x04}, + {0x04,0x28,0x0C}, + {0x04,0x2C,0x0C}, + {0x04,0x30,0x14}, + {0x04,0x34,0x14}, + {0x08,0x08,0x08}, + {0x08,0x0C,0x0C}, + {0x08,0x10,0x18}, + {0x08,0x14,0x18}, + {0x08,0x18,0x18}, + {0x08,0x24,0x0C}, + {0x08,0x28,0x08}, + {0x08,0x2C,0x08}, + {0x08,0x30,0x18}, + {0x08,0x34,0x18}, + {0x0C,0x0C,0x0C}, + {0x0C,0x10,0x18}, + {0x0C,0x14,0x18}, + {0x0C,0x18,0x18}, + {0x0C,0x24,0x0C}, + {0x0C,0x28,0x0C}, + {0x0C,0x30,0x18}, + {0x0C,0x34,0x18}, + {0x10,0x10,0x10}, + {0x10,0x14,0x14}, + {0x10,0x18,0x18}, + {0x10,0x24,0x14}, + {0x10,0x28,0x18}, + {0x10,0x30,0x10}, + {0x10,0x34,0x10}, + {0x14,0x14,0x14}, + {0x14,0x18,0x18}, + {0x14,0x24,0x14}, + {0x14,0x28,0x18}, + {0x14,0x30,0x14}, + {0x18,0x18,0x18}, + {0x18,0x24,0x18}, + {0x18,0x28,0x18}, + {0x18,0x30,0x18}, + {0x24,0x24,0x24}, + {0x24,0x28,0x24}, + {0x24,0x30,0x14}, + {0x28,0x28,0x28}, + {0x28,0x30,0x18}, + {0x2C,0x0C,0x0C}, + {0x2C,0x10,0x18}, + {0x2C,0x14,0x18}, + {0x2C,0x18,0x18}, + {0x2C,0x24,0x0C}, + {0x2C,0x28,0x2C}, + {0x2C,0x2C,0x2C}, + {0x2C,0x30,0x18}, + {0x2C,0x34,0x18}, + {0x30,0x30,0x30}, + {0x34,0x14,0x14}, + {0x34,0x18,0x18}, + {0x34,0x24,0x14}, + {0x34,0x28,0x18}, + {0x34,0x30,0x34}, + {0x34,0x34,0x34}, + {0x38,0x04,0x04}, + {0x38,0x08,0x18}, + {0x38,0x0C,0x18}, + {0x38,0x10,0x10}, + {0x38,0x14,0x14}, + {0x38,0x18,0x18}, + {0x38,0x24,0x04}, + {0x38,0x28,0x08}, + {0x38,0x2C,0x18}, + {0x38,0x30,0x34}, + {0x38,0x34,0x34}, + {0x38,0x38,0x38}, + {0x3C,0x04,0x04}, + {0x3C,0x08,0x08}, + {0x3C,0x0C,0x0C}, + {0x3C,0x10,0x10}, + {0x3C,0x14,0x14}, + {0x3C,0x18,0x18}, + {0x3C,0x24,0x24}, + {0x3C,0x28,0x2C}, + {0x3C,0x2C,0x2C}, + {0x3C,0x30,0x10}, + {0x3C,0x34,0x10}, + {0x3C,0x38,0x10}, + {0x3C,0x3C,0x3C}, + // mergedWith INITIALIZER END + }) { + UnconditionalFlowInfo output(UnconditionalFlowInfo input1, + UnconditionalFlowInfo input2) { + return input1.copy().mergedWith(input2); + } + }, + newNullInfoRegistry = + // newNullInfoRegistry DEFINITION START + // start => start + // prot. non null => start + // prot. null => start + // pot. unknown => start + // pot. non null => start + // pot. nn & prot. nn => start + // pot. nn & pot. un => start + // pot. null => start + // pot. n & prot. n => start + // pot. n & pot. un => start + // pot. n & pot. nn => start + // def. unknown => pot. unknown + // def. non null => pot. non null + // def. null => pot. null + // newNullInfoRegistry DEFINITION END + new CreationalTransformation("newNullInfoRegistry", + new byte[][] { + // newNullInfoRegistry INITIALIZER START + {0x00,0x00}, + {0x04,0x00}, + {0x08,0x00}, + {0x0C,0x00}, + {0x10,0x00}, + {0x14,0x00}, + {0x18,0x00}, + {0x24,0x04}, + {0x28,0x08}, + {0x2C,0x00}, + {0x30,0x10}, + {0x34,0x00}, + {0x38,0x00}, + {0x3C,0x00}, + // newNullInfoRegistry INITIALIZER END + }) { + UnconditionalFlowInfo output(UnconditionalFlowInfo input) { + return NullInfoRegistryTestHarness. + testNullInfoRegistry((UnconditionalFlowInfoTestHarness) input); + } + }; + public static final Transformation[] transformations = { + markAsComparedEqualToNonNull, + markAsComparedEqualToNull, + markAsDefinitelyNonNull, + markAsDefinitelyNull, + markAsDefinitelyUnknown, + addInitializationsFrom, + addPotentialInitializationsFrom, + mergedWith, + newNullInfoRegistry + }; +public abstract static class Transformation { + public String name; + String definitionStartMarker, definitionEndMarker, + initializerStartMarker, initializerEndMarker; + int dimension; + public Map initializedTransitions, computedTransitions; + // PREMATURE limit public access + int failuresNb; // transient +// PREMATURE complete the test coverage for NullInfoRegistry (need to consider several classes +// of transitions so as to avoid considering NullInfoRegistry states and +// UnconditionalFlowInfo states into the same pool; moreover, cross classes +// transformations exist. +Transformation(String name) { + this.name = name; + this.definitionStartMarker = "// " + name + " " + CodeAnalysis.definitionStartMarker; + this.definitionEndMarker = "// " + name + " " + CodeAnalysis.definitionEndMarker; + this.initializerStartMarker = "// " + name + " " + CodeAnalysis.initializerStartMarker; + this.initializerEndMarker = "// " + name + " " + CodeAnalysis.initializerEndMarker; +} +abstract State[] computeOutputs(State[] inputs); +abstract void hydrate(); +void fail() { + if (this.failuresNb == 0) { + System.out.println(this.name + " failures: "); + } + this.failuresNb++; +} +abstract void printTruthTables(File outputDirectory); + +static boolean checkContiguity(String a, String b) { + int aLength; + if ((aLength = a.length()) != b.length()) { + System.out.println("inappropriate string length: " + a + " vs " + b); + return false; + } + int status = 0; + for (int i = 0; i < aLength; i++) { + if (a.charAt(i) != b.charAt(i)) { + status++; + } + } + if (status != 1) { + System.out.println("non contiguous strings: " + a + " vs " + b); + return false; + } + return true; +} + +final static String truthTableRowNames[] = { // need a specific order to yield simplication opportunities + "000000", + "000100", + "001100", + "001000", + "011000", + "011100", + "010100", + "010000", + "110000", + "110100", + "111100", + "111000", + "101000", + "101100", + "100100", + "100000", + // PREMATURE cheated to group first four bits... reconsider + "000001", + "000011", + "000010", + "000110", + "000111", + "000101", + "001101", + "001111", + "001110", + "001010", + "001011", + "001001", + "011001", + "011011", + "011010", + "011110", + "011111", + "011101", + "010101", + "010111", + "010110", + "010010", + "010011", + "010001", + "110001", + "110011", + "110010", + "110110", + "110111", + "110101", + "111101", + "111111", + "111110", + "111010", + "111011", + "111001", + "101001", + "101011", + "101010", + "101110", + "101111", + "101101", + "100101", + "100111", + "100110", + "100010", + "100011", + "100001", + }; + +private static Map ranksForStates; +int rankForState(State state) { + int length; + if (ranksForStates == null) { + ranksForStates = new HashMap(length = truthTableRowNames.length); + for (int i = 0; i < length; i++) { + ranksForStates.put(truthTableRowNames[i], new Integer(i)); + } + } + Integer rank; + if ((rank = (Integer) ranksForStates.get(state.printableBitsField)) != null) { + return rank.intValue(); + } + return 0; +} + +abstract void reinitializeFromComments(BufferedReader input, BufferedWriter output); +abstract void reinitializeFromComputedValues(BufferedReader input, BufferedWriter output, + State[] consideredStates); +/** + * Run a test against UnconditionalFlowInfo by comparing the transitions as memorized + * into the initializer and as delivered by UnconditionalFlowInfo for various positions + * in the encoding and return the number of failures. + * @return the number of failures, that is 0 if the results match the expectations + */ +abstract int test(); +} +abstract static class TwoDimensionalTransformation extends Transformation { +TwoDimensionalTransformation(String name, byte[][] transitions) { + super(name); + this.dimension = 2; + int length; + this.initializedTransitions = new HashMap(length = transitions.length); + State input1; + for (int i = 0; i < length; i++) { + if (transitions[i].length != 2) { + throw new IllegalArgumentException("transitions should have two entries"); + } + input1 = State.states[transitions[i][0]]; // array out of bounds exception if broken + if (this.initializedTransitions.get(input1) != null) { + throw new IllegalArgumentException("duplicate entry"); + } + this.initializedTransitions.put(input1, State.states[transitions[i][1]]); + } +} +State[] computeOutputs(State[] inputs) { + Map resultAccumulator = new HashMap(State.stateMaxValue + 1); + hydrate(); // pre-compute all possible combinations, then cache them + for (int i = 0, inputsLength = inputs.length; i < inputsLength; i++) { + resultAccumulator.put(this.computedTransitions.get(inputs[i]), null); + } + int length; + State[] result = new State[length = resultAccumulator.size()]; + Iterator resultIterator = resultAccumulator.keySet().iterator(); + for (int j = 0; j < length; j++) { + result[j] = (State) resultIterator.next(); + } + return result; +} +void hydrate() { + if (this.computedTransitions == null) { + State input, output; + this.computedTransitions = new HashMap(State.stateMaxValue + 1); + for (int i = 0, length = State.states.length; i < length; i++) { + output = ((UnconditionalFlowInfoTestHarness) + output(UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input = State.states[i]), + TestLocalVariableBinding.local0)).asState(); + if (input.symbolic && !output.symbolic) { + System.err.println(this.name + " generates non-symbolic state " + + output + " upon entry: " + input); + } + this.computedTransitions.put(input, output); + } + } +} +abstract UnconditionalFlowInfo output(UnconditionalFlowInfo input, TestLocalVariableBinding local); + +void printTruthTables(File outputDirectory) { + try { + String outputFileName = outputDirectory.getPath() + File.separator + this.name + ".txt"; + PrintWriter out = new PrintWriter(new FileOutputStream( + new File(outputFileName))); + System.out.println("Printing " + outputFileName); + out.println("======================================================"); + out.println("Truth table for " + this.name ); + char truthValues[][] = new char[State.statesNb][State.stateWidth]; + int row, column; + for (row = 0; row < State.statesNb; row++) { + for (column = 0; column < State.stateWidth; column++) { + truthValues[row][column] = '.'; + } + } + boolean keepRow[] = new boolean[State.statesNb]; + Iterator i1 = this.initializedTransitions.entrySet().iterator(); + while (i1.hasNext()) { + Map.Entry transitionsSet = (Map.Entry) i1.next(); + State input = (State) transitionsSet.getKey(); + keepRow[row = rankForState(input)] = true; + for (int bit = 0; bit < State.stateWidth; bit++) { + truthValues[row][bit] = + ((State) transitionsSet.getValue()).printableBitsField.charAt(bit); + } + } + StringBuffer line; + line = new StringBuffer(140); + line.append(" "); + for (int i = 1; i <= State.stateWidth; i++) { + line.append(i); + line.append(' '); + } + out.println(line); + line = new StringBuffer(140); + line.append(" ---------------------"); + out.println(line); + for (row = 0; row < State.statesNb; row++) { + if (keepRow[row]) { + line = new StringBuffer(140); + line.append(truthTableRowNames[row]); + line.append(" | "); + for (int i = 0; i < State.stateWidth; i++) { + line.append(truthValues[row][i]); + line.append(' '); + } + out.println(line); + } + } + out.println("======================================================"); + out.flush(); + out.close(); + } + catch (Throwable t) { + // PREMATURE improve error handling + } +} + +void reinitializeFromComments(BufferedReader input, BufferedWriter output) { + String line, tab = ""; + int cursor; + char c; + this.initializedTransitions = new HashMap(State.stateMaxValue); + int lineNumber = 0; + try { + while ((line = input.readLine()) != null) { + lineNumber++; + output.write(line); + output.write('\n'); + if ((cursor = line.indexOf(definitionStartMarker)) != -1) { + // check the line format + boolean reachedStart = true; + for (int i = 0; i < cursor; i++) { + if (!Character.isWhitespace(c = line.charAt(i))) { + reachedStart = false; + break; + } + else { + tab += c; + } + } + if (reachedStart) { + while ((line = input.readLine()) != null && + line.indexOf(definitionEndMarker) == -1) { + lineNumber++; + final int + start = 0, + commentStart = 1, + commentFound = 2, + firstState = 10, + firstStateWS = 11, + implies = 20, + impliesWS = 21, + secondState = 30, + secondStateWS = 31, // caveat, multi-state + error = 99; + int state = start, + firstStateStart = 0, firstStateEnd = 0, firstStateWhiteSpace = 0, + secondStateStart = 0, secondStateEnd = 0, secondStateWhiteSpace = 0; + char current; + analysis: for (int i = 0, length = line.length(); i < length; i++) { + current = line.charAt(i); + switch (state) { + case start: + if (current == '/') { + state = commentStart; + } else if (! Character.isWhitespace(current)) { + state = error; + break analysis; + } + break; + case commentStart: + if (current == '/') { + state = commentFound; + } else { + state = error; + break analysis; + } + break; + case commentFound: + if (! Character.isWhitespace(current)) { + firstStateStart = firstStateEnd = i; + state = firstState; + } + break; + case firstState: + if (Character.isWhitespace(current)) { + state = firstStateWS; + firstStateWhiteSpace = 1; + } else { + firstStateEnd++; + } + break; + case firstStateWS: + if (current == '=') { + state = implies; + } else if (Character.isWhitespace(current)) { + firstStateWhiteSpace++; + } else { + state = firstState; + firstStateEnd += firstStateWhiteSpace + 1; + } + break; + case implies: + if (current == '>') { + state = impliesWS; + } else { + state = error; + break analysis; + } + break; + case impliesWS: + if (! Character.isWhitespace(current)) { + secondStateStart = secondStateEnd = i; + state = secondState; + } + break; + case secondState: + if (current == '/') { + break analysis; + } else if (Character.isWhitespace(current)) { + state = secondStateWS; + secondStateWhiteSpace = 1; + } else { + secondStateEnd++; + } + break; + case secondStateWS: + if (current == '/') { + state = secondState; + break analysis; + } else if (current == 'C') { + state++; + } else if (Character.isWhitespace(current)) { + secondStateWhiteSpace++; + } else { + state = secondState; + secondStateEnd += secondStateWhiteSpace + 1; + } + break; + case secondStateWS + 1: + if (current == '/') { + state = secondState; + break analysis; + } else if (current == 'H') { + state++; + } else { + state = secondState; + secondStateEnd += secondStateWhiteSpace + 2; + } + break; + case secondStateWS + 2: + if (current == '/') { + state = secondState; + break analysis; + } else if (current == 'E') { + state++; + } else { + state = secondState; + secondStateEnd += secondStateWhiteSpace + 3; + } + break; + case secondStateWS + 3: + if (current == '/') { + state = secondState; + break analysis; + } else if (current == 'C') { + state++; + } else { + state = secondState; + secondStateEnd += secondStateWhiteSpace + 4; + } + break; + case secondStateWS + 4: + if (current == '/' || current == 'K') { + state = secondState; + break analysis; + } else { + state = secondState; + secondStateEnd += secondStateWhiteSpace + 5; + } + break; + + } + } + if (state == error || state < secondState) { + System.err.println("Could not interpret comment definition"); // PREMATURE improve diagnostic + } else { + if (state > secondStateWS) { + secondStateEnd += (state - secondState); + } + String stateName; + State first, second; + if ((first = State.fromSymbolicName( + stateName = line.substring(firstStateStart, firstStateEnd + 1))) + == null) { + System.err.println("Could not find state: " + stateName); // PREMATURE improve diagnostic + } + if ((second = State.fromSymbolicName( + stateName = line.substring(secondStateStart, secondStateEnd + 1))) + == null) { + System.err.println("Could not find state: " + stateName); // PREMATURE improve diagnostic + } + if (first != null && second != null) { + if (this.initializedTransitions.get(first) != null) { + System.err.println("Line " + lineNumber + ": Skipping duplicate entry for state: " + first); // PREMATURE improve diagnostic + } else { + this.initializedTransitions.put(first, second); + } + } + } + output.write(line); + output.write('\n'); + } + Iterator firsts = State.symbolicStates(); + State first; + while (firsts.hasNext()) { + first = (State) firsts.next(); + if (this.initializedTransitions.get(first) == null) { + System.err.println("Adding missing transition for state: " + first); + output.write(tab); + output.write("// "); + output.write(first.toString()); + output.write(" => start\t\t CHECK\n"); + } + } + } + output.write(tab + definitionEndMarker + "\n"); + } + if (line != null && (cursor = line.indexOf(initializerStartMarker)) != -1) { + // check the line format + boolean reachedStart = true; + tab = ""; + for (int i = 0; i < cursor; i++) { + if (!Character.isWhitespace(c = line.charAt(i))) { + reachedStart = false; + break; + } + else { + tab += c; + } + } + if (reachedStart) { + while ((line = input.readLine()) != null && + line.indexOf(initializerEndMarker) == -1) { + // loop + } + SortedMap sorted = new TreeMap(this.initializedTransitions); + Iterator transitions = sorted.entrySet().iterator(); + Map.Entry transition; + while (transitions.hasNext()) { + transition = (Map.Entry) transitions.next(); + output.write(tab); + output.write('{'); + output.write(((State)transition.getKey()).hexString); + output.write(','); + output.write(((State)transition.getValue()).hexString); + output.write("},"); + output.write('\n'); + } + output.write(tab + initializerEndMarker + "\n"); + } + } + } + output.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } +} + +void reinitializeFromComputedValues(BufferedReader input, BufferedWriter output, + State[] consideredStates) { + String line, tab = ""; + int cursor; + char c; + State result; + try { + while ((line = input.readLine()) != null) { + output.write(line); + output.write('\n'); + if ((cursor = line.indexOf(definitionStartMarker)) != -1) { + // check the line format + boolean reachedStart = true; + for (int i = 0; i < cursor; i++) { + if (!Character.isWhitespace(c = line.charAt(i))) { + reachedStart = false; + break; + } + else { + tab += c; + } + } + if (reachedStart) { + while ((line = input.readLine()) != null && + line.indexOf(definitionEndMarker) == -1) { + // loop + } + int i, length; + for (i = 0, length = consideredStates.length; i < length; i++) { + output.write(tab); + output.write("// "); + output.write(consideredStates[i].name); + output.write(" => "); + output.write( + (result = (State) this.computedTransitions.get(consideredStates[i])).name); + if (!result.symbolic || + result != this.initializedTransitions.get(consideredStates[i])) { + output.write("\t\t CHECK"); + } + output.write('\n'); + } + output.write(tab + definitionEndMarker + "\n"); + } + } + if (line != null && (cursor = line.indexOf(initializerStartMarker)) != -1) { + // check the line format + boolean reachedStart = true; + tab = ""; + for (int i = 0; i < cursor; i++) { + if (!Character.isWhitespace(c = line.charAt(i))) { + reachedStart = false; + break; + } + else { + tab += c; + } + } + if (reachedStart) { + while ((line = input.readLine()) != null && + line.indexOf(initializerEndMarker) == -1) { + // loop + } + int i, length; + for (i = 0, length = consideredStates.length; i < length; i++) { + output.write(tab); + output.write('{'); + output.write(consideredStates[i].hexString); + output.write(','); + output.write( + ((State) this.computedTransitions.get(consideredStates[i])).hexString); + output.write("},"); + output.write('\n'); + } + output.write(tab + initializerEndMarker + "\n"); + } + } + } + output.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } +} +int test() { + Iterator transitions = this.initializedTransitions.entrySet().iterator(); + State input, expectedOutput, effectiveOutput; + Map.Entry transition; + this.failuresNb = 0; // reset + while (transitions.hasNext()) { + transition = (Map.Entry) transitions.next(); + input = (State) transition.getKey(); + expectedOutput = (State) transition.getValue(); + effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input), + TestLocalVariableBinding.local0)).asState(); + if (effectiveOutput != expectedOutput) { + fail(); + System.out.println("\t\t" + input.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " instead of: " + expectedOutput.printableBitsField); + } + } + transitions = this.initializedTransitions.entrySet().iterator(); + while (transitions.hasNext()) { + transition = (Map.Entry) transitions.next(); + input = (State) transition.getKey(); + expectedOutput = (State) transition.getValue(); + effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input, 64), + TestLocalVariableBinding.local64)).asState(64); + if (effectiveOutput != expectedOutput) { + fail(); + System.out.println("\t\t" + input.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (64) instead of: " + expectedOutput.printableBitsField); + } + if (input == State.start) { + effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(expectedOutput), + TestLocalVariableBinding.local64)).asState(64); + if (effectiveOutput != expectedOutput) { + fail(); + System.out.println("\t\t" + input.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (zero 64) instead of: " + expectedOutput.printableBitsField); + } + } + } + transitions = this.initializedTransitions.entrySet().iterator(); + while (transitions.hasNext()) { + transition = (Map.Entry) transitions.next(); + input = (State) transition.getKey(); + if (input == State.start) { + expectedOutput = (State) transition.getValue(); + effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(expectedOutput, 64), + TestLocalVariableBinding.local128)).asState(128); + if (effectiveOutput != expectedOutput) { + fail(); + System.out.println("\t\t" + input.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (zero 128) instead of: " + expectedOutput.printableBitsField); + } + } + } + return this.failuresNb; +} +} +abstract static class CreationalTransformation extends TwoDimensionalTransformation { +CreationalTransformation(String name, byte[][] transitions) { + super(name, transitions); +} +void hydrate() { + if (this.computedTransitions == null) { + State input, output; + this.computedTransitions = new HashMap(State.stateMaxValue + 1); + for (int i = 0, length = State.states.length; i < length; i++) { + output = ((NullInfoRegistryTestHarness) + output(UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input = State.states[i]), + TestLocalVariableBinding.local0)).asState(); + if (input.symbolic && !output.symbolic) { + System.err.println(this.name + " generates non-symbolic state " + + output + " upon entry: " + input); + } + this.computedTransitions.put(input, output); + } + } +} +UnconditionalFlowInfo output(UnconditionalFlowInfo input, TestLocalVariableBinding local) { + return output(input); +} +abstract UnconditionalFlowInfo output(UnconditionalFlowInfo input); +int test() { + Iterator transitions = this.initializedTransitions.entrySet().iterator(); + State input, expectedOutput, effectiveOutput; + Map.Entry transition; + this.failuresNb = 0; // reset + while (transitions.hasNext()) { + transition = (Map.Entry) transitions.next(); + input = (State) transition.getKey(); + expectedOutput = (State) transition.getValue(); + effectiveOutput = ((NullInfoRegistryTestHarness) + output(UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input), + TestLocalVariableBinding.local0)).asState(); + if (effectiveOutput != expectedOutput) { + fail(); + System.out.println("\t\t" + input.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " instead of: " + expectedOutput.printableBitsField); + } + } + transitions = this.initializedTransitions.entrySet().iterator(); + while (transitions.hasNext()) { + transition = (Map.Entry) transitions.next(); + input = (State) transition.getKey(); + expectedOutput = (State) transition.getValue(); + effectiveOutput = ((NullInfoRegistryTestHarness) + output(UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input, 64))).asState(64); + if (effectiveOutput != expectedOutput) { + fail(); + System.out.println("\t\t" + input.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (64) instead of: " + expectedOutput.printableBitsField); + } + } + return this.failuresNb; +} +} +public abstract static class ThreeDimensionalTransformation extends Transformation { +ThreeDimensionalTransformation(String name) { + super(name); + this.dimension = 3; +} +ThreeDimensionalTransformation(String name, byte[][] transitions) { + super(name); + this.dimension = 3; + int length; + this.initializedTransitions = new HashMap(length = transitions.length); + State input1, input2; + for (int i = 0; i < length; i++) { + if (transitions[i].length != 3) { + throw new IllegalArgumentException("transitions should have three entries"); + } + input1 = State.states[transitions[i][0]]; // array out of bounds exception if broken + input2 = State.states[transitions[i][1]]; + Map transitionsForInput1 = (Map) this.initializedTransitions.get(input1); + if (transitionsForInput1 == null) { + transitionsForInput1 = new HashMap(length); + this.initializedTransitions.put(input1, transitionsForInput1); + } + if (transitionsForInput1.get(input2) != null) { + throw new IllegalArgumentException("duplicate entry"); + } + transitionsForInput1.put(input2, State.states[transitions[i][2]]); + } +} +State[] computeOutputs(State[] inputs) { + Map resultAccumulator = new HashMap(State.stateMaxValue + 1); + hydrate(); // pre-compute all possible combinations, then cache them + for (int i = 0, inputsLength = inputs.length; i < inputsLength; i++) { + for (int i2 = 0; i2 < inputsLength; i2++) { + resultAccumulator.put( + ((Map) this.computedTransitions.get(inputs[i])).get(inputs[i2]), null); + } + } + int length; + State[] result = new State[length = resultAccumulator.size()]; + Iterator resultIterator = resultAccumulator.keySet().iterator(); + for (int j = 0; j < length; j++) { + result[j] = (State) resultIterator.next(); + } + return result; +} +void hydrate() { + if (this.computedTransitions == null) { + State input1, input2, output; + this.computedTransitions = new HashMap(State.stateMaxValue + 1); + Map entry; + for (int i = 0, length = State.states.length; i < length; i++) { + entry = new HashMap(State.stateMaxValue + 1); + this.computedTransitions.put(input1 = State.states[i], entry); + for (int j = 0; j < length; j++) { + output = ((UnconditionalFlowInfoTestHarness) + output(UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input1), + UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input2 = State.states[j]))).asState(); + if (input1.symbolic && input2.symbolic && !output.symbolic) { + System.err.println(this.name + " generates non-symbolic state " + + output + " upon entry: " + input1 + " + " + input2); + } + entry.put(input2, output); + } + } + } +} +abstract UnconditionalFlowInfo output(UnconditionalFlowInfo input1, UnconditionalFlowInfo input2); +void printDefinitions(BufferedWriter output, State[] consideredStates, String tab) + throws IOException { + int i, j, length; + State result; + for (i = 0, length = consideredStates.length; i < length; i++) { + for (j = 0; j < length; j++) { + output.write(tab); + output.write("// "); + output.write(consideredStates[i].name); + output.write(" + "); + output.write(consideredStates[j].name); + output.write(" => "); + output.write( + (result = (State) + ((Map) this.computedTransitions.get(consideredStates[i])).get(consideredStates[j])).name); + if (!result.symbolic || + result != this.initializedTransitions.get(consideredStates[i])) { + output.write("\t\t CHECK"); + } + output.write('\n'); + } + } +} +void printInitializers(BufferedWriter output, State[] consideredStates, String tab) + throws IOException { + int i, j, length; + for (i = 0, length = consideredStates.length; i < length; i++) { + for (j = 0; j < length; j++) { + output.write(tab); + output.write('{'); + output.write(consideredStates[i].hexString); + output.write(','); + output.write(consideredStates[j].hexString); + output.write(','); + output.write( + ((State) + ((Map) this.computedTransitions.get(consideredStates[i])).get(consideredStates[j])).hexString); + output.write("},"); + output.write('\n'); + } + } +} +void printMissingEntries(BufferedWriter output, String tab) throws IOException { + Iterator firsts = State.symbolicStates(), seconds; + State first, second; + Map transitions; + while (firsts.hasNext()) { + first = (State) firsts.next(); + seconds = State.symbolicStates(); + if ((transitions = (Map) this.initializedTransitions.get(first)) + == null) { + while (seconds.hasNext()) { + second = (State) seconds.next(); + System.err.println("Adding missing transition for states (" + first + ", " + second + ")"); + output.write(tab); + output.write("// "); + output.write(first.toString()); + output.write(" + "); + output.write(second.toString()); + output.write(" => start\t\t CHECK\n"); + } + } else { + while (seconds.hasNext()) { + second = (State) seconds.next(); + if (transitions.get(second) == null) { + System.err.println("Adding missing transition for states (" + first + ", " + second + ")"); + output.write(tab); + output.write("// "); + output.write(first.toString()); + output.write(" + "); + output.write(second.toString()); + output.write(" => start\t\t CHECK\n"); + } + } + } + } +} +void printTruthTables(File outputDirectory) { + for (int bit = 1; bit <= State.stateWidth; bit++) { + try { + String outputFileName = outputDirectory.getPath() + File.separator + this.name + "_" + bit + ".txt"; + PrintWriter out = new PrintWriter(new FileOutputStream( + new File(outputFileName))); + System.out.println("Printing " + outputFileName); + out.println("======================================================"); + out.println("Truth table for " + this.name + " null bit " + bit); + char truthValues[][] = new char[State.statesNb][State.statesNb]; + int row, column; + for (row = 0; row < State.statesNb; row++) { + for (column = 0; column < State.statesNb; column++) { + truthValues[row][column] = '.'; + } + } + if (false) { // checking row names + boolean gotProblem = false; + if (truthTableRowNames.length > State.statesNb) { + System.out.println("row names table contains too many rows"); + gotProblem = true; + } + else if (truthTableRowNames.length < State.statesNb) { + System.out.println("row names table contains too few rows"); + gotProblem = true; + } + Map check = new HashMap(State.statesNb); + for (row = 0; row < truthTableRowNames.length; row++) { + if (check.containsKey(truthTableRowNames[row])) { + System.out.println("duplicate row: " + truthTableRowNames[row]); + gotProblem = true; + } + else { + check.put(truthTableRowNames[row], null); + } + if (row > 0 && !checkContiguity(truthTableRowNames[row - 1], truthTableRowNames[row])) { + gotProblem = true; + } + } + // assertFalse("invalid rows table", gotProblem); + } + boolean keepRow[] = new boolean[State.statesNb], + keepColumn[] = new boolean[State.statesNb]; + Iterator i1 = this.initializedTransitions.entrySet().iterator(); + while (i1.hasNext()) { + Map.Entry transitionsSet = (Map.Entry) i1.next(); + State first = (State) transitionsSet.getKey(); + Iterator i2 = ((Map) transitionsSet.getValue()).entrySet().iterator(); + while (i2.hasNext()) { + Map.Entry transition = (Map.Entry) i2.next(); + mark(truthValues, keepRow, keepColumn, rankForState(first), + rankForState((State) transition.getKey()), + ((State) transition.getValue()).printableBitsField.charAt(bit - 1)); + } + } + for (row = 0; row < State.statesNb; row += 2) { + if (keepRow[row]) { + keepRow[row + 1] = true; + } + else if (keepRow[row + 1]) { + keepRow[row] = true; + } + if (keepColumn[row]) { + keepColumn[row + 1] = true; + } + else if (keepColumn[row + 1]) { + keepColumn[row] = true; + } + } + StringBuffer line; + for (int i = 0; i < State.stateWidth; i++) { + line = new StringBuffer(140); + line.append(" "); + for (column = 0; column < State.statesNb; column++) { + if (keepColumn[column]) { + line.append(truthTableRowNames[column].charAt(i)); + line.append(' '); + } + } + out.println(line); + } + line = new StringBuffer(140); + line.append(" --"); + for (column = 0; column < State.statesNb; column++) { + if (keepColumn[column]) { + line.append('-'); + line.append('-'); + } + } + out.println(line); + for (row = 0; row < State.statesNb; row++) { + if (keepRow[row]) { + line = new StringBuffer(140); + line.append(truthTableRowNames[row]); + line.append(" | "); + for (column = 0; column < State.statesNb; column++) { + if (keepColumn[column]) { + line.append(truthValues[row][column]); + line.append(' '); + } + } + out.println(line); + } + } + out.println("======================================================"); + out.flush(); + out.close(); + } + catch (Throwable t) { + // PREMATURE improve error handling + } + } +} + +void mark(char truthValues[][], boolean keepRow[], boolean keepColumn[], + int row, int column, char value) { + truthValues[row][column] = value; + keepRow[row] = true; + keepColumn[column] = true; +} + +void reinitializeFromComments(BufferedReader input, BufferedWriter output) { + String line, tab = ""; + int cursor; + char c; + this.initializedTransitions = new HashMap(State.stateMaxValue); + int lineNumber = 0; + try { + while ((line = input.readLine()) != null) { + lineNumber++; + output.write(line); + output.write('\n'); + if ((cursor = line.indexOf(definitionStartMarker)) != -1) { + // check the line format + boolean reachedStart = true; + for (int i = 0; i < cursor; i++) { + if (!Character.isWhitespace(c = line.charAt(i))) { + reachedStart = false; + break; + } + else { + tab += c; + } + } + if (reachedStart) { + while ((line = input.readLine()) != null && + line.indexOf(definitionEndMarker) == -1) { + lineNumber++; + final int + start = 0, + commentStart = 1, + commentFound = 2, + firstState = 10, + firstStateWS = 11, + plus = 20, + secondState = 30, + secondStateWS = 31, + implies = 40, + impliesWS = 41, + thirdState = 50, + thirdStateWS = 51, // caveat, multi-state + error = 99; + int state = start, + firstStateStart = 0, firstStateEnd = 0, firstStateWhiteSpace = 0, + secondStateStart = 0, secondStateEnd = 0, secondStateWhiteSpace = 0, + thirdStateStart = 0, thirdStateEnd = 0, thirdStateWhiteSpace = 0; + char current; + analysis: for (int i = 0, length = line.length(); i < length; i++) { + current = line.charAt(i); + switch (state) { + case start: + if (current == '/') { + state = commentStart; + } else if (! Character.isWhitespace(current)) { + state = error; + break analysis; + } + break; + case commentStart: + if (current == '/') { + state = commentFound; + } else { + state = error; + break analysis; + } + break; + case commentFound: + if (! Character.isWhitespace(current)) { + firstStateStart = firstStateEnd = i; + state = firstState; + } + break; + case firstState: + if (Character.isWhitespace(current)) { + state = firstStateWS; + firstStateWhiteSpace = 1; + } else { + firstStateEnd++; + } + break; + case firstStateWS: + if (current == '+') { + state = plus; + } else if (Character.isWhitespace(current)) { + firstStateWhiteSpace++; + } else { + state = firstState; + firstStateEnd += firstStateWhiteSpace + 1; + } + break; + case plus: + if (! Character.isWhitespace(current)) { + secondStateStart = secondStateEnd = i; + state = secondState; + } + break; + case secondState: + if (Character.isWhitespace(current)) { + state = secondStateWS; + secondStateWhiteSpace = 1; + } else { + secondStateEnd++; + } + break; + case secondStateWS: + if (current == '=') { + state = implies; + } else if (Character.isWhitespace(current)) { + secondStateWhiteSpace++; + } else { + state = secondState; + secondStateEnd += secondStateWhiteSpace + 1; + } + break; + case implies: + if (current == '>') { + state = impliesWS; + } else { + state = error; + break analysis; + } + break; + case impliesWS: + if (! Character.isWhitespace(current)) { + thirdStateStart = thirdStateEnd = i; + state = thirdState; + } + break; + case thirdState: + if (current == '/') { + break analysis; + } else if (Character.isWhitespace(current)) { + state = thirdStateWS; + thirdStateWhiteSpace = 1; + } else { + thirdStateEnd++; + } + break; + case thirdStateWS: + if (current == '/') { + state = thirdState; + break analysis; + } else if (current == 'C') { + state++; + } else if (Character.isWhitespace(current)) { + thirdStateWhiteSpace++; + } else { + state = thirdState; + thirdStateEnd += thirdStateWhiteSpace + 1; + } + break; + case thirdStateWS + 1: + if (current == '/') { + state = thirdState; + break analysis; + } else if (current == 'H') { + state++; + } else { + state = thirdState; + thirdStateEnd += thirdStateWhiteSpace + 2; + } + break; + case thirdStateWS + 2: + if (current == '/') { + state = thirdState; + break analysis; + } else if (current == 'E') { + state++; + } else { + state = thirdState; + thirdStateEnd += thirdStateWhiteSpace + 3; + } + break; + case thirdStateWS + 3: + if (current == '/') { + state = thirdState; + break analysis; + } else if (current == 'C') { + state++; + } else { + state = thirdState; + thirdStateEnd += thirdStateWhiteSpace + 4; + } + break; + case thirdStateWS + 4: + if (current == '/' || current == 'K') { + state = thirdState; + break analysis; + } else { + state = thirdState; + thirdStateEnd += thirdStateWhiteSpace + 5; + } + break; + + } + } + if (state == error || state < thirdState) { + System.err.println("Could not interpret comment definition"); // PREMATURE improve diagnostic + } else { + if (state > thirdStateWS) { + thirdStateEnd += (state - thirdState); + } + String stateName; + State first, second, third; + if ((first = State.fromSymbolicName( + stateName = line.substring(firstStateStart, firstStateEnd + 1))) + == null) { + System.err.println("Could not find state: " + stateName); // PREMATURE improve diagnostic + } + if ((second = State.fromSymbolicName( + stateName = line.substring(secondStateStart, secondStateEnd + 1))) + == null) { + System.err.println("Could not find state: " + stateName); // PREMATURE improve diagnostic + } + if ((third = State.fromSymbolicName( + stateName = line.substring(thirdStateStart, thirdStateEnd + 1))) + == null) { + System.err.println("Could not find state: " + stateName); // PREMATURE improve diagnostic + } + if (first != null && second != null && third != null) { + Map transitions; + if ((transitions = (Map) this.initializedTransitions.get(first)) == null) { + transitions = new HashMap(State.stateMaxValue + 1); + this.initializedTransitions.put(first, transitions); + } + if (transitions.get(second) != null) { + System.err.println("Line " + lineNumber + ": Skipping duplicate entry for states: (" + first + + ", " + second + ")"); // PREMATURE improve diagnostic + } else { + transitions.put(second, third); + } + } + } + output.write(line); + output.write('\n'); + } + } + printMissingEntries(output, tab); + output.write(tab + definitionEndMarker + "\n"); + } + if (line != null && (cursor = line.indexOf(initializerStartMarker)) != -1) { + // check the line format + boolean reachedStart = true; + tab = ""; + for (int i = 0; i < cursor; i++) { + if (!Character.isWhitespace(c = line.charAt(i))) { + reachedStart = false; + break; + } + else { + tab += c; + } + } + if (reachedStart) { + while ((line = input.readLine()) != null && + line.indexOf(initializerEndMarker) == -1) { + // loop + } + SortedMap sortedTransitionsSet = new TreeMap(this.initializedTransitions); + Iterator transitionsSets = sortedTransitionsSet.entrySet().iterator(); + Map.Entry transitionsSet; + while (transitionsSets.hasNext()) { + transitionsSet = (Map.Entry) transitionsSets.next(); + SortedMap sortedTransitions = new TreeMap((Map) transitionsSet.getValue()); + Iterator transitions = sortedTransitions.entrySet().iterator(); + Map.Entry transition; + while (transitions.hasNext()) { + transition = (Map.Entry) transitions.next(); + output.write(tab); + output.write('{'); + output.write(((State)transitionsSet.getKey()).hexString); + output.write(','); + output.write(((State)transition.getKey()).hexString); + output.write(','); + output.write(((State)transition.getValue()).hexString); + output.write("},"); + output.write('\n'); + } + } + output.write(tab + initializerEndMarker + "\n"); + } + } + } + output.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } +} +void reinitializeFromComputedValues(BufferedReader input, BufferedWriter output, + State[] consideredStates) { + String line, tab = ""; + int cursor; + char c; + try { + while ((line = input.readLine()) != null) { + output.write(line); + output.write('\n'); + if ((cursor = line.indexOf(definitionStartMarker)) != -1) { + // check the line format + boolean reachedStart = true; + for (int i = 0; i < cursor; i++) { + if (!Character.isWhitespace(c = line.charAt(i))) { + reachedStart = false; + break; + } + else { + tab += c; + } + } + if (reachedStart) { + while ((line = input.readLine()) != null && + line.indexOf(definitionEndMarker) == -1) { + // loop + } + printDefinitions(output, consideredStates, tab); + output.write(tab + definitionEndMarker + "\n"); + } + } + if (line != null && (cursor = line.indexOf(initializerStartMarker)) != -1) { + // check the line format + boolean reachedStart = true; + tab = ""; + for (int i = 0; i < cursor; i++) { + if (!Character.isWhitespace(c = line.charAt(i))) { + reachedStart = false; + break; + } + else { + tab += c; + } + } + if (reachedStart) { + while ((line = input.readLine()) != null && + line.indexOf(initializerEndMarker) == -1) { + // loop + } + printInitializers(output, consideredStates, tab); + output.write(tab + initializerEndMarker + "\n"); + } + } + } + output.flush(); + } catch (IOException e) { + throw new RuntimeException(e); + } +} +int test() { + return test(1, false); +} +int test(int combinationTestsLoopsNb, boolean skipHighOrderBits) { + Iterator transitionsSetsIterator, transitionsIterator; + State input1, input2, expectedOutput, effectiveOutput; + Map.Entry transition, transitionsSet; + this.failuresNb = 0; // reset + this.failuresNb = 0; // reset + long start = 0; + if (combinationTestsLoopsNb > 1) { + start = System.currentTimeMillis(); + } + for (int l = 0; l < combinationTestsLoopsNb ; l++) { + transitionsSetsIterator = this.initializedTransitions.entrySet().iterator(); + while (transitionsSetsIterator.hasNext()) { + transitionsSet = (Map.Entry) transitionsSetsIterator.next(); + input1 = (State) transitionsSet.getKey(); + transitionsIterator = ((Map) transitionsSet.getValue()). + entrySet().iterator(); + while (transitionsIterator.hasNext()) { + transition = (Map.Entry) transitionsIterator.next(); + input2 = (State) transition.getKey(); + expectedOutput = (State) transition.getValue(); + effectiveOutput = ((UnconditionalFlowInfoTestHarness) output( + UnconditionalFlowInfoTestHarness.testUnconditionalFlowInfo(input1), + UnconditionalFlowInfoTestHarness.testUnconditionalFlowInfo(input2))) + .asState(); + if (effectiveOutput != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " instead of: " + expectedOutput.printableBitsField); + } + } + } + } + if (combinationTestsLoopsNb > 1) { + System.out.println(this.name + "...\t\t" + combinationTestsLoopsNb + "\t" + + (System.currentTimeMillis() - start)); + } + // PREMATURE optimize test (extraneous allocations and copies) + // PREMATURE optimize test (extraneous iterations - undup) + if (!skipHighOrderBits) { + UnconditionalFlowInfoTestHarness + zero = UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(State.start), + left, right, left64, right64, left128, right128, + special = (UnconditionalFlowInfoTestHarness) zero.copy(); + special.grow(64); // allocates one extra without adding null info + transitionsSetsIterator = this.initializedTransitions.entrySet().iterator(); + while (transitionsSetsIterator.hasNext()) { + transitionsSet = (Map.Entry) transitionsSetsIterator.next(); + input1 = (State) transitionsSet.getKey(); + transitionsIterator = ((Map) transitionsSet.getValue()). + entrySet().iterator(); + while (transitionsIterator.hasNext()) { + transition = (Map.Entry) transitionsIterator.next(); + input2 = (State) transition.getKey(); + expectedOutput = (State) transition.getValue(); + left = UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input1); + left64 = UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input1, 64); + left128 = UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input1, 128); + right = UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input2); + right64 = UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input2, 64); + right128 = UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input2, 128); + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(left64, right64)).asState(64)) != + expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (64, 64) - instead of: " + expectedOutput.printableBitsField); + } + if (input1 == State.start) { + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(right128, right)).asState()) != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (zero 128, 1) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(zero, right64)).asState(64)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (zero, 64) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(right128, right64)).asState(64)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (zero 128, 64) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(zero, right128)).asState(128)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (zero, 128) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(right64, right128)).asState(128)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (zero 64, 128) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(special, right128)).asState(128)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (special zero, 128) - instead of: " + expectedOutput.printableBitsField); + } + } + if (input2 == State.start) { + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(left, left128)).asState()) != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (1, zero 128) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(left64, zero)).asState(64)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (64, zero) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(left64, left128)).asState(64)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (64, zero 128) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(left128, zero)).asState(128)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (128, zero) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(left128, left64)).asState(128)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (128, zero 64) - instead of: " + expectedOutput.printableBitsField); + } + } + } + } + } + return this.failuresNb; +} +} + +public abstract static class SymmetricalThreeDimensionalTransformation + extends ThreeDimensionalTransformation{ +SymmetricalThreeDimensionalTransformation(String name, byte[][] transitions) { + super(name); + int length; + this.initializedTransitions = new HashMap((length = transitions.length) * 2 - 1); + State input1, input2; + for (int i = 0; i < length; i++) { + if (transitions[i].length != 3) { + throw new IllegalArgumentException("transitions should have three entries"); + } + if (transitions[i][0] <= transitions[i][1]) { + input1 = State.states[transitions[i][0]]; // array out of bounds exception if broken + input2 = State.states[transitions[i][1]]; + } + else { + input1 = State.states[transitions[i][1]]; + input2 = State.states[transitions[i][0]]; + } + Map transitionsForInput1 = (Map) this.initializedTransitions.get(input1); + if (transitionsForInput1 == null) { + transitionsForInput1 = new HashMap(length); + this.initializedTransitions.put(input1, transitionsForInput1); + } + if (transitionsForInput1.get(input2) != null) { + throw new IllegalArgumentException("duplicate entry"); + } + transitionsForInput1.put(input2, State.states[transitions[i][2]]); + } +} +void hydrate() { + super.hydrate(); + checkSymmetry(this.computedTransitions); +} +private void checkSymmetry(Map map) { + State input1, input2, result; + Map.Entry entry1, entry2; + Map transition; + Iterator transitions1 = map.entrySet().iterator(), transitions2; + while (transitions1.hasNext()) { + entry1 = (Map.Entry) transitions1.next(); + input1 = (State) entry1.getKey(); + transition = (Map) entry1.getValue(); + transitions2 = transition.entrySet().iterator(); + while (transitions2.hasNext()) { + entry2 = (Map.Entry) transitions2.next(); + input2 = (State) entry2.getKey(); + result = (State) entry2.getValue(); + if (result != ((Map) map.get(input2)).get(input1) && input1.symbolic && input2.symbolic) { + System.err.println("symmetry mismatch: " + input1 + " + " + + input2 + " -> " + result + "/" + ((Map) map.get(input2)).get(input1)); + } + } + } +} +void mark(char truthValues[][], boolean keepRow[], boolean keepColumn[], + int row, int column, char value) { + truthValues[row][column] = truthValues[column][row] = value; + keepRow[row] = true; + keepColumn[column] = true; + keepRow[column] = true; + keepColumn[row] = true; +} +void printDefinitions(BufferedWriter output, State[] consideredStates, String tab) + throws IOException { + // only difference with parent is that we print only half of possible + // combinations + int i, j, length; + State result; + for (i = 0, length = consideredStates.length; i < length; i++) { + for (j = i; j < length; j++) { + output.write(tab); + output.write("// "); + output.write(consideredStates[i].name); + output.write(" + "); + output.write(consideredStates[j].name); + output.write(" => "); + output.write( + (result = (State) + ((Map) this.computedTransitions.get(consideredStates[i])).get(consideredStates[j])).name); + if (!result.symbolic || + result != this.initializedTransitions.get(consideredStates[i])) { + output.write("\t\t CHECK"); + } + output.write('\n'); + } + } +} +void printInitializers(BufferedWriter output, State[] consideredStates, String tab) + throws IOException { + // only difference with parent is that we print only half of possible + // combinations + int i, j, length; + for (i = 0, length = consideredStates.length; i < length; i++) { + for (j = i; j < length; j++) { + output.write(tab); + output.write('{'); + output.write(consideredStates[i].hexString); + output.write(','); + output.write(consideredStates[j].hexString); + output.write(','); + output.write( + ((State) + ((Map) this.computedTransitions.get(consideredStates[i])).get(consideredStates[j])).hexString); + output.write("},"); + output.write('\n'); + } + } +} +void printMissingEntries(BufferedWriter output, String tab) throws IOException { + Iterator firsts = State.symbolicStates(), seconds; + State first, second; + while (firsts.hasNext()) { + first = (State) firsts.next(); + seconds = State.symbolicStates(); + while (seconds.hasNext()) { + second = (State) seconds.next(); + if (!checkPair(first, second)) { + addPair(first, second); + System.err.println("Adding missing transition for states (" + first + ", " + second + ")"); + output.write(tab); + output.write("// "); + output.write(first.toString()); + output.write(" + "); + output.write(second.toString()); + output.write(" => start\t\t CHECK\n"); + } + } + } +} +private boolean checkPair(State s1, State s2) { + Map transitions; + if ((transitions = (Map) this.initializedTransitions.get(s1)) != null) { + if (transitions.get(s2) != null) { + return true; + } + } + if ((transitions = (Map) this.initializedTransitions.get(s2)) != null) { + if (transitions.get(s1) != null) { + return true; + } + } + return false; +} +private void addPair(State s1, State s2) { + Map transitions; + if ((transitions = (Map) this.initializedTransitions.get(s1)) == null) { + transitions = new HashMap(); + this.initializedTransitions.put(s1, transitions); + } + transitions.put(s2, s2); // dummy, non null value +} +// PREMATURE factorize upward +int test(int combinationTestsLoopsNb, boolean skipHighOrderBits) { + Iterator transitionsSetsIterator, transitionsIterator; + State input1, input2, expectedOutput, effectiveOutput; + Map.Entry transition, transitionsSet; + this.failuresNb = 0; // reset + this.failuresNb = 0; // reset + long start = 0; + if (combinationTestsLoopsNb > 1) { + start = System.currentTimeMillis(); + } + for (int l = 0; l < combinationTestsLoopsNb ; l++) { + transitionsSetsIterator = this.initializedTransitions.entrySet().iterator(); + while (transitionsSetsIterator.hasNext()) { + transitionsSet = (Map.Entry) transitionsSetsIterator.next(); + input1 = (State) transitionsSet.getKey(); + transitionsIterator = ((Map) transitionsSet.getValue()). + entrySet().iterator(); + while (transitionsIterator.hasNext()) { + transition = (Map.Entry) transitionsIterator.next(); + input2 = (State) transition.getKey(); + expectedOutput = (State) transition.getValue(); + effectiveOutput = ((UnconditionalFlowInfoTestHarness) output( + UnconditionalFlowInfoTestHarness.testUnconditionalFlowInfo(input1), + UnconditionalFlowInfoTestHarness.testUnconditionalFlowInfo(input2))) + .asState(); + if (effectiveOutput != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " instead of: " + expectedOutput.printableBitsField); + } + effectiveOutput = ((UnconditionalFlowInfoTestHarness) output( + UnconditionalFlowInfoTestHarness.testUnconditionalFlowInfo(input2), + UnconditionalFlowInfoTestHarness.testUnconditionalFlowInfo(input1))) + .asState(); + if (effectiveOutput != expectedOutput) { + fail(); + System.out.println("\t\t" + input2.printableBitsField + + " + " + input1.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " instead of: " + expectedOutput.printableBitsField); + } + } + } + } + if (combinationTestsLoopsNb > 1) { + System.out.println(this.name + "...\t\t" + combinationTestsLoopsNb + "\t" + + (System.currentTimeMillis() - start)); + } + // PREMATURE optimize test (extraneous allocations and copies) + // PREMATURE optimize test (extraneous iterations - undup) + if (!skipHighOrderBits) { + UnconditionalFlowInfoTestHarness + zero = UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(State.start), + right, left64, right64, right128; + transitionsSetsIterator = this.initializedTransitions.entrySet().iterator(); + while (transitionsSetsIterator.hasNext()) { + transitionsSet = (Map.Entry) transitionsSetsIterator.next(); + input1 = (State) transitionsSet.getKey(); + transitionsIterator = ((Map) transitionsSet.getValue()). + entrySet().iterator(); + while (transitionsIterator.hasNext()) { + transition = (Map.Entry) transitionsIterator.next(); + input2 = (State) transition.getKey(); + expectedOutput = (State) transition.getValue(); + left64 = UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input1, 64); + right = UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input2); + right64 = UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input2, 64); + right128 = UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(input2, 128); + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(left64, right64)).asState(64)) != + expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (64, 64) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(right64, left64)).asState(64)) != + expectedOutput) { + fail(); + System.out.println("\t\t" + input2.printableBitsField + + " + " + input1.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (64, 64) - instead of: " + expectedOutput.printableBitsField); + } + if (input1 == State.start) { + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(right128, right)).asState()) != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (zero 128, 1) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(zero, right64)).asState(64)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (zero, 64) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(right128, right64)).asState(64)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (zero 128, 64) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(zero, right128)).asState(128)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (zero, 128) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(right64, right128)).asState(128)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input1.printableBitsField + + " + " + input2.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (zero 64, 128) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(right, right128)).asState()) != expectedOutput) { + fail(); + System.out.println("\t\t" + input2.printableBitsField + + " + " + input1.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (1, zero 128) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(right64, zero)).asState(64)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input2.printableBitsField + + " + " + input1.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (64, zero) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(right64, right128)).asState(64)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input2.printableBitsField + + " + " + input1.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (64, zero 128) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(right128, zero)).asState(128)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input2.printableBitsField + + " + " + input1.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (128, zero) - instead of: " + expectedOutput.printableBitsField); + } + if ((effectiveOutput = ((UnconditionalFlowInfoTestHarness) + output(right128, right64)).asState(128)) != expectedOutput) { + fail(); + System.out.println("\t\t" + input2.printableBitsField + + " + " + input1.printableBitsField + + " => " + effectiveOutput.printableBitsField + + " (128, zero 64) - instead of: " + expectedOutput.printableBitsField); + } + } + } + } + } + return this.failuresNb; +} +} +} Index: src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java =================================================================== RCS file: src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java diff -N src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/jdt/core/tests/compiler/regression/NullReferenceImplTests.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,1866 @@ +/******************************************************************************* + * Copyright (c) 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.jdt.core.tests.compiler.regression; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.eclipse.jdt.internal.compiler.flow.FlowInfo; +import org.eclipse.jdt.internal.compiler.flow.NullInfoRegistry; +import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo; +import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo.AssertionFailedException; +import org.eclipse.jdt.internal.compiler.impl.Constant; +import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; +import org.eclipse.jdt.internal.compiler.lookup.PackageBinding; +import org.eclipse.jdt.internal.compiler.lookup.TypeBinding; + +import junit.framework.AssertionFailedError; +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * A tests series especially meant to validate the internals of our null + * reference analysis. See NullReferenceTest for tests targetted at + * the source code compiler behavior level. + */ +public class NullReferenceImplTests extends NullReferenceTest { + // Static initializer to specify tests subset using TESTS_* static variables + // All specified tests which does not belong to the class are skipped... + // Only the highest compliance level is run; add the VM argument + // -Dcompliance=1.4 (for example) to lower it if needed + static { +// TESTS_NAMES = new String[] { "test2050" }; +// TESTS_NUMBERS = new int[] { 2061 }; +// TESTS_NUMBERS = new int[] { 2999 }; +// TESTS_RANGE = new int[] { 2050, -1 }; + } + +/** + * A class to hold states as seen by the low level validation tests and machinery. + * State provides: + * - singletons for all possible states given the number of bits for the said + * states; + * - semantic names for known states; + * - printable representation of states as bit fields; + * - coordination with other classes to perform transitive closure analysis, etc. + */ + /* + This is a tabular definition for states. It can be completed/leveraged by + the Generator class so as to smoothen the transition between differing encodings + of the states. + // STATES DEFINITION START + 000000 start + 000001 + 000010 + 000011 + 000100 pot. unknown + 000101 + 000110 + 000111 + 001000 pot. non null + 001001 + 001010 + 001011 + 001100 pot. nn & pot. un + 001101 + 001110 + 001111 + 010000 pot. null + 010001 + 010010 + 010011 + 010100 pot. n & pot. un + 010101 + 010110 + 010111 + 011000 pot. n & pot. nn + 011001 + 011010 + 011011 + 011100 + 011101 + 011110 + 011111 + 100000 + 100001 + 100010 + 100011 + 100100 def. unknown + 100101 + 100110 + 100111 + 101000 def. non null + 101001 + 101010 + 101011 + 101100 pot. nn & prot. nn + 101101 + 101110 + 101111 + 110000 def. null + 110001 + 110010 + 110011 + 110100 pot. n & prot. n + 110101 + 110110 + 110111 + 111000 prot. null + 111001 + 111010 + 111011 + 111100 prot. non null + 111101 + 111110 + 111111 + // STATES DEFINITION END + */ + public static class State implements Comparable { + // PREMATURE consider moving initialization to test setup/dispose + public final static State[] states = { + // STATES INITIALIZER START + new State(0, "start"), // 000000 + new State(1), // 000001 + new State(2), // 000010 + new State(3), // 000011 + new State(4, "pot. unknown"), // 000100 + new State(5), // 000101 + new State(6), // 000110 + new State(7), // 000111 + new State(8, "pot. non null"), // 001000 + new State(9), // 001001 + new State(10), // 001010 + new State(11), // 001011 + new State(12, "pot. nn & pot. un"), // 001100 + new State(13), // 001101 + new State(14), // 001110 + new State(15), // 001111 + new State(16, "pot. null"), // 010000 + new State(17), // 010001 + new State(18), // 010010 + new State(19), // 010011 + new State(20, "pot. n & pot. un"), // 010100 + new State(21), // 010101 + new State(22), // 010110 + new State(23), // 010111 + new State(24, "pot. n & pot. nn"), // 011000 + new State(25), // 011001 + new State(26), // 011010 + new State(27), // 011011 + new State(28), // 011100 + new State(29), // 011101 + new State(30), // 011110 + new State(31), // 011111 + new State(32), // 100000 + new State(33), // 100001 + new State(34), // 100010 + new State(35), // 100011 + new State(36, "def. unknown"), // 100100 + new State(37), // 100101 + new State(38), // 100110 + new State(39), // 100111 + new State(40, "def. non null"), // 101000 + new State(41), // 101001 + new State(42), // 101010 + new State(43), // 101011 + new State(44, "pot. nn & prot. nn"), // 101100 + new State(45), // 101101 + new State(46), // 101110 + new State(47), // 101111 + new State(48, "def. null"), // 110000 + new State(49), // 110001 + new State(50), // 110010 + new State(51), // 110011 + new State(52, "pot. n & prot. n"), // 110100 + new State(53), // 110101 + new State(54), // 110110 + new State(55), // 110111 + new State(56, "prot. null"), // 111000 + new State(57), // 111001 + new State(58), // 111010 + new State(59), // 111011 + new State(60, "prot. non null"), // 111100 + new State(61), // 111101 + new State(62), // 111110 + new State(63), // 111111 + // STATES INITIALIZER END + }; + public final static State start = states[0]; + public static final int + stateMaxValue = 0x3F, + stateWidth = 6, + statesNb = stateMaxValue + 1; + String name, printableBitsField, hexString; + public byte value; + boolean symbolic; + private State() { + } + private State(int numericValue) { + this(numericValue, null); + } + private State(int numericValue, String publicName) { + if (numericValue > stateMaxValue) { + throw new IllegalArgumentException("state value overflow"); + } + this.value = (byte) numericValue; + StringBuffer printableValue = new StringBuffer(6); + for (int i = stateWidth - 1; i >= 0; i--) { + printableValue.append((numericValue >>> i & 1) != 0 ? '1' : '0'); + } + this.printableBitsField = printableValue.toString(); + if (this.value > 0xF) { + this.hexString = "0x" + Integer.toHexString(this.value).toUpperCase(); + } + else { + this.hexString = "0x0" + Integer.toHexString(this.value).toUpperCase(); + } + if (publicName != null) { + this.name = publicName; + this.symbolic = true; + } + else { + this.name = this.printableBitsField; + } + } + private State(String commentLine) { + char current = ' '; // keep the initialization status quiet + int cursor, length; + for (cursor = 0, length = commentLine.length(); + cursor < length; + cursor++) { + if ((current = commentLine.charAt(cursor)) == '0' || + current == '1') { + break; + } + } + if (cursor == length) { + throw new RuntimeException("bad state definition format (missing bits field): " + commentLine); + // PREMATURE adopt consistent error policy + } + int valueDigits; + for (valueDigits = 1; cursor < (length - 1) && valueDigits < stateWidth; valueDigits++) { + this.value = (byte) ((this.value << 1) + (current - '0')); + if ((current = commentLine.charAt(++cursor)) != '0' && + current != '1') { + throw new RuntimeException("bad state definition format (inappropriate character in bits field): " + commentLine); + // PREMATURE adopt consistent error policy + } + } + if (valueDigits < stateWidth) { + throw new RuntimeException("bad state definition format (bits field is too short): " + commentLine); + // PREMATURE adopt consistent error policy + } + this.value = (byte) ((this.value << 1) + (current - '0')); + this.printableBitsField = commentLine.substring(cursor - stateWidth + 1, cursor + 1); + if (this.value > 0xF) { + this.hexString = "0x" + Integer.toHexString(this.value).toUpperCase(); + } + else { + this.hexString = "0x0" + Integer.toHexString(this.value).toUpperCase(); + } + while (++cursor < length && Character.isWhitespace(current = commentLine.charAt(++cursor)) && current != '\n') { + // loop + } + if (cursor < length && current != '\n') { + this.name = commentLine.substring(cursor, length); + } + if (this.name == null) { + this.name = this.printableBitsField; + } else { + this.symbolic = true; + } + } + private String asInitializer() { + StringBuffer result = new StringBuffer(70); + result.append(" new State("); + result.append(this.value); + char first; + boolean nameIsSymbolic = (first = this.name.charAt(0)) != '0' + && first != '1'; + if (nameIsSymbolic) { + result.append(", \""); + result.append(this.name); + result.append('"'); + } + result.append("), // "); + result.append(this.printableBitsField); + return result.toString(); + } + long [] asLongArray() { + long[] result = new long[stateWidth]; + for (int i = 0; i < stateWidth; i++) { + result[i] = ((this.value >> (stateWidth - i - 1)) & 1) == 0 ? 0 : 1; + } + return result; + } + private String asSourceComment() { + StringBuffer result = new StringBuffer(70); + result.append("\t\t"); + result.append(this.printableBitsField); + char first; + boolean nameIsSymbolic = (first = this.name.charAt(0)) != '0' + && first != '1'; + if (nameIsSymbolic) { + result.append('\t'); + result.append(this.name); + } + return result.toString(); + } + public int compareTo(Object o) { + return this.value - ((State) o).value; + } + static State fromLongValues(long bit1, long bit2, long bit3, long bit4, long bit5, long bit6) { + // PREMATURE consider taking an UnconditionalFlowInfo in parameter + return states[(int)( + (bit6 & 1) + + 2 * ((bit5 & 1) + + 2 * ((bit4 & 1) + + 2 * ((bit3 & 1) + + 2 * ((bit2 & 1) + + 2 * (bit1 & 1))))))]; + } + private static Map namesIndex; + static State fromSymbolicName (String name) { + if (namesIndex == null) { + namesIndex = new HashMap(states.length); + for (int i = 0; i < states.length; i++) { + if (states[i].name != null) { + namesIndex.put(states[i].name, states[i]); + } + } + } + return (State) namesIndex.get(name); + } + private static void grabDefinitionFromComment(BufferedReader input) { + String line; + State current; + // use when the initializer is incomplete, hence needs to be reinitialized + // states = new State[stateMaxValue + 1]; + // use when the states field is final, with the appropriate size: + for (int i = 0; i <= stateMaxValue; i++) { + states[i] = null; + } + try { + while ((line = input.readLine()) != null && line.indexOf(definitionEndMarker) == -1) { + current = new State(line); + if (states[current.value] != null) { + throw new RuntimeException("duplicate state for index: " + current.value); + } + else { + states[current.value] = current; + } + } + } catch (IOException e) { + throw new RuntimeException(e); + } + for (int i = 0; i < stateMaxValue; i++) { + if (states[i] == null) { + states[i] = new State(i); + } + } + } + // PREMATURE may decide to remove + //private static void printAsInitializer() { + // int i, length; + // System.out.println(initializerStartMarker); + // for (i = 0, length = states.length; i < length; i++) { + // System.out.println(states[i].asInitializer()); + // } + // for (/* continue */; i <= stateMaxValue; i++) { + // System.out.println((new State(i)).asInitializer() + " CHECK"); + // } + // System.out.println(initializerEndMarker); + //} + // PREMATURE may decide to remove + //private static void printAsSourceComment() { + // int i, length; + // System.out.println("/*"); + // System.out.println(definitionStartMarker); + // for (i = 0, length = states.length; i < length; i++) { + // System.out.println(states[i].asSourceComment()); + // } + // for (/* continue */; i <= stateMaxValue; i++) { + // System.out.println((new State(i)).asSourceComment()); + // } + // System.out.println(definitionEndMarker); + // System.out.println("*/"); + //} + private final static String + definitionStartMarker = "// STATES " + CodeAnalysis.definitionStartMarker, + definitionEndMarker = "// STATES " + CodeAnalysis.definitionEndMarker, + initializerStartMarker = "// STATES " + CodeAnalysis.initializerStartMarker, + initializerEndMarker = "// STATES " + CodeAnalysis.initializerEndMarker; + static void reinitializeFromComment(BufferedReader input, BufferedWriter output) { + String line, tab = ""; + int cursor; + char c; + try { + while ((line = input.readLine()) != null) { + output.write(line); + output.write('\n'); + if ((cursor = line.indexOf(definitionStartMarker)) != -1) { + // check the line format + boolean reachedStart = true; + for (int i = 0; i < cursor; i++) { + if (!Character.isWhitespace(c = line.charAt(i))) { + reachedStart = false; + break; + } + else { + tab += c; + } + } + if (reachedStart) { + grabDefinitionFromComment(input); // consumes up to the END line + int i, length; + for (i = 0, length = states.length; i < length; i++) { + output.write(states[i].asSourceComment()); + output.write('\n'); + } + output.write(tab + definitionEndMarker + "\n"); + } + } + if ((cursor = line.indexOf(initializerStartMarker)) != -1) { + // check the line format + boolean reachedStart = true; + tab = ""; + for (int i = 0; i < cursor; i++) { + if (!Character.isWhitespace(c = line.charAt(i))) { + reachedStart = false; + break; + } + else { + tab += c; + } + } + if (reachedStart) { + while ((line = input.readLine()) != null && + line.indexOf(initializerEndMarker) == -1) { + // loop + } + int i, length; + for (i = 0, length = states.length; i < length; i++) { + output.write(states[i].asInitializer()); + output.write('\n'); + } + output.write(tab + initializerEndMarker + "\n"); + } + } + } + output.flush(); + namesIndex = null; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + static Iterator symbolicStates() { + return new Iterator() { + int nextSymbolic = -1; + public boolean hasNext() { + if (nextSymbolic == -1) { + for (nextSymbolic = 0; nextSymbolic < states.length; nextSymbolic++) { + if (states[nextSymbolic].symbolic) { + break; + } + } + } else { + for (; nextSymbolic < states.length; nextSymbolic++) { + if (states[nextSymbolic].symbolic) { + break; + } + } + } + return nextSymbolic < states.length; + } + public Object next() { + State result = null; + if (nextSymbolic < states.length) { + result = states[nextSymbolic]; + nextSymbolic++; + } + return result; + } + public void remove() { + throw new RuntimeException("unimplemented"); + } + }; + } + public String toString() { + return this.name; + } + } + +public NullReferenceImplTests(String name) { + super(name); +} + + // Tests tuning + static final boolean + skipHighOrderBits = false; // define to true when tuning encoding + static final int + combinationTestsloopsNb = 1; // define to 10000s to measure performances + +public static Test suite() { + // we do not want to run for 1.3, 1.4, 1.5 but once only + Class clazz = testClass(); + TestSuite all = new TestSuite(clazz.getName()); + List tests = buildTestsList(testClass()); + for (int i = 0, length = tests.size(); i < length; i++) { + all.addTest((Test) tests.get(i)); + } + return all; +} + +public static Class testClass() { + return NullReferenceImplTests.class; +} + +public void test2050_markAsComparedEqualToNonNull() { + int failures = NullReferenceImplTransformations.markAsComparedEqualToNonNull.test(); + assertTrue("nb of failures: " + failures, failures == 0); +} + +public void test2051_markAsComparedEqualToNull() { + int failures = NullReferenceImplTransformations.markAsComparedEqualToNull.test(); + assertTrue("nb of failures: " + failures, failures == 0); +} + +public void test2055_markAsDefinitelyNonNull() { + int failures = NullReferenceImplTransformations.markAsDefinitelyNonNull.test(); + assertTrue("nb of failures: " + failures, failures == 0); +} + +public void test2056_markAsDefinitelyNull() { + int failures = NullReferenceImplTransformations.markAsDefinitelyNull.test(); + assertTrue("nb of failures: " + failures, failures == 0); +} + +public void test2057_markAsDefinitelyUnknown() { + int failures = NullReferenceImplTransformations.markAsDefinitelyUnknown.test(); + assertTrue("nb of failures: " + failures, failures == 0); +} + +public void test2060_addInitializationsFrom() { + int failures = NullReferenceImplTransformations.addInitializationsFrom.test(); + assertTrue("nb of failures: " + failures, failures == 0); +} + +public void test2061_addPotentialInitializationsFrom() { + int failures = NullReferenceImplTransformations.addPotentialInitializationsFrom.test(); + assertTrue("nb of failures: " + failures, failures == 0); +} + +public void test2062_mergedWith() { + int failures = NullReferenceImplTransformations.mergedWith.test(); + assertTrue("nb of failures: " + failures, failures == 0); +} + +public void test2070_newNullInfoRegistry() { + int failures = NullReferenceImplTransformations.newNullInfoRegistry.test(); + assertTrue("nb of failures: " + failures, failures == 0); +} + +// PREMATURE rewrite from scratch +//public void _test2058_recode() { +// long [][][] testData = transitionsTablesData[recode]; +// int failures = 0; +// long start; +// if (combinationTestsloopsNb > 1) { +// start = System.currentTimeMillis(); +// } +// String header = "recode failures: "; +// for (int l = 0; l < combinationTestsloopsNb ; l++) { +// for (int i = 0; i < testData.length; i++) { +// UnconditionalFlowInfoTestHarness result; +// result = UnconditionalFlowInfoTestHarness. +// testUnconditionalFlowInfo(testData[i][0]); +// result.encode(); +// result.decode(); +// +// if (!result.testEquals(UnconditionalFlowInfoTestHarness. +// testUnconditionalFlowInfo(testData[i][0]))) { +// if (failures == 0) { +// System.out.println(header); +// } +// failures++; +// System.out.println("\t\t{" + result.testString() + +// "}, // instead of: " + testStringValueOf(testData[i][0])); +// } +// } +// } +// if (combinationTestsloopsNb > 1) { +// System.out.println("mergedWith\t\t\t" + combinationTestsloopsNb + "\t" + +// (System.currentTimeMillis() - start)); +// } +// for (int i = 0; i < testData.length; i++) { +// UnconditionalFlowInfoTestHarness result; +// result = UnconditionalFlowInfoTestHarness. +// testUnconditionalFlowInfo(testData[i][0], 64); +// result.encode(); +// result.decode(); +// +// if (!result.testEquals(UnconditionalFlowInfoTestHarness. +// testUnconditionalFlowInfo(testData[i][0], 64))) { +// if (failures == 0) { +// System.out.println(header); +// } +// failures++; +// System.out.println("\t\t{" + result.testString() + +// "}, // (64) - instead of: " + testStringValueOf(testData[i][0])); +// } +// } +// assertTrue("nb of failures: " + failures, failures == 0); +//} + +public void test2400_state_consistency() { + int failures = 0; + long start; + if (combinationTestsloopsNb > 1) { + start = System.currentTimeMillis(); + } + String header = "state consistency failures: "; + for (int l = 0; l < combinationTestsloopsNb ; l++) { + for (int i = 0; i < State.states.length; i++) { + if (State.states[i].symbolic) { + UnconditionalFlowInfoTestHarness + state = UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(State.states[i]); + boolean + isDefinitelyNonNull = state.isDefinitelyNonNull(TestLocalVariableBinding.local0), + isDefinitelyNull = state.isDefinitelyNull(TestLocalVariableBinding.local0), + isDefinitelyUnknown = state.isDefinitelyUnknown(TestLocalVariableBinding.local0), + isPotentiallyNull = state.isPotentiallyNull(TestLocalVariableBinding.local0), + isPotentiallyUnknown = state.isPotentiallyUnknown(TestLocalVariableBinding.local0), + isProtectedNonNull = state.isProtectedNonNull(TestLocalVariableBinding.local0), + isProtectedNull = state.isProtectedNull(TestLocalVariableBinding.local0); + if (isDefinitelyNonNull + && (isDefinitelyNull || isDefinitelyUnknown + || isPotentiallyNull + || isProtectedNull)) { + if (failures == 0) { + System.out.println(header); + } + failures++; + System.out.println("\t\tconsistency breakage for definitely non null state " + State.states[i].name); + } + if (isDefinitelyNull + && (isDefinitelyNonNull || isDefinitelyUnknown + || isPotentiallyUnknown || isProtectedNonNull)) { + if (failures == 0) { + System.out.println(header); + } + failures++; + System.out.println("\t\tconsistency breakage for definitely null state " + State.states[i].name); + } + if (isDefinitelyUnknown + && (isDefinitelyNonNull || isDefinitelyNull + || isPotentiallyNull || isProtectedNonNull + || isProtectedNull)) { + if (failures == 0) { + System.out.println(header); + } + failures++; + System.out.println("\t\tconsistency breakage for definitely unknown state " + State.states[i].name); + } + if (isProtectedNonNull && !isDefinitelyNonNull + || isProtectedNull && !isDefinitelyNull + || i > 0 // not start + && !State.states[i].name.equals("pot. non null") + && !(isDefinitelyNonNull || isDefinitelyNull + || isDefinitelyUnknown || isPotentiallyNull + || isPotentiallyUnknown || isProtectedNonNull + || isProtectedNull)) { + if (failures == 0) { + System.out.println(header); + } + failures++; + System.out.println("\t\tconsistency breakage for " + State.states[i].name); + } + } + } + } + if (combinationTestsloopsNb > 1) { + System.out.println("mergedWith\t\t\t" + combinationTestsloopsNb + "\t" + + (System.currentTimeMillis() - start)); + } + for (int i = 0; i < State.states.length; i++) { + if (State.states[i].symbolic) { + UnconditionalFlowInfoTestHarness state; + state = UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(State.states[i], 64); + boolean + isDefinitelyNonNull = state.isDefinitelyNonNull(TestLocalVariableBinding.local64), + isDefinitelyNull = state.isDefinitelyNull(TestLocalVariableBinding.local64), + isDefinitelyUnknown = state.isDefinitelyUnknown(TestLocalVariableBinding.local64), + isPotentiallyNull = state.isPotentiallyNull(TestLocalVariableBinding.local64), + isPotentiallyUnknown = state.isPotentiallyUnknown(TestLocalVariableBinding.local64), + isProtectedNonNull = state.isProtectedNonNull(TestLocalVariableBinding.local64), + isProtectedNull = state.isProtectedNull(TestLocalVariableBinding.local64); + if (isDefinitelyNonNull + && (isDefinitelyNull || isDefinitelyUnknown + || isPotentiallyNull + || isProtectedNull)) { + if (failures == 0) { + System.out.println(header); + } + failures++; + System.out.println("\t\tconsistency breakage (64) for definitely non null state " + State.states[i].name); + } + if (isDefinitelyNull + && (isDefinitelyNonNull || isDefinitelyUnknown + || isPotentiallyUnknown || isProtectedNonNull)) { + if (failures == 0) { + System.out.println(header); + } + failures++; + System.out.println("\t\tconsistency breakage (64) for definitely null state " + State.states[i].name); + } + if (isDefinitelyUnknown + && (isDefinitelyNonNull || isDefinitelyNull + || isPotentiallyNull || isProtectedNonNull + || isProtectedNull)) { + if (failures == 0) { + System.out.println(header); + } + failures++; + System.out.println("\t\tconsistency breakage (64) for definitely unknown state " + State.states[i].name); + } + if (isProtectedNonNull && !isDefinitelyNonNull + || isProtectedNull && !isDefinitelyNull + || i > 0 // not start + && !State.states[i].name.equals("pot. non null") + && !(isDefinitelyNonNull || isDefinitelyNull + || isDefinitelyUnknown || isPotentiallyNull + || isPotentiallyUnknown || isProtectedNonNull + || isProtectedNull)) { + if (failures == 0) { + System.out.println(header); + } + failures++; + System.out.println("\t\tconsistency breakage (64) for " + State.states[i].name); + } + } + } + assertTrue("nb of failures: " + failures, failures == 0); +} + +public void test2500_addInitializationsFrom_for_definites() { + // when an added initialization is a def. something, it should + // affect the left hand term as the markAsDefinite* method would + // do + int failures = 0; + for (int i = 0; i < State.states.length; i++) { + if (State.states[i].symbolic) { + UnconditionalFlowInfoTestHarness source1, source2, result1, result2; + source1 = UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(State.states[i]); + for (int j = 0; j < State.states.length; j++) { + if (State.states[j].symbolic) { + source2 = UnconditionalFlowInfoTestHarness. + testUnconditionalFlowInfo(State.states[j]); + result1 = (UnconditionalFlowInfoTestHarness) source1.copy(); + result2 = (UnconditionalFlowInfoTestHarness) source1.copy(); + if (source2.isDefinitelyNonNull(TestLocalVariableBinding.local0)) { + if (! source2.isProtectedNonNull(TestLocalVariableBinding.local0)) { + result1.markAsDefinitelyNonNull(TestLocalVariableBinding.local0); + } else { + continue; + } + } + else if (source2.isDefinitelyNull(TestLocalVariableBinding.local0)) { + if (! source2.isProtectedNull(TestLocalVariableBinding.local0)) { + result1.markAsDefinitelyNull(TestLocalVariableBinding.local0); + } else { + continue; + } + } + else if (source2.isDefinitelyUnknown(TestLocalVariableBinding.local0)) { + result1.markAsDefinitelyUnknown(TestLocalVariableBinding.local0); + } + else if (source2.nullBit1 != 0) { + if (failures == 0) { + System.out.println("addInitializationsFrom_for_definites failures: "); //$NON-NLS-1$ + } + failures++; + System.out.println("\t\t" + State.states[j].name + + " should answer true to at least one isDefinite* query"); + // PREMATURE move to specific queries test case + } + else { + continue; + } + result2.addInitializationsFrom(source2); + if (!result1.testEquals(result2)) { + if (failures == 0) { + System.out.println("addInitializationsFrom_for_definites failures: "); //$NON-NLS-1$ + } + failures++; + System.out.println("\t\t" + State.states[i].name + + " + " + State.states[j].name + + " => " + result2.asState().name + + " instead of: " + result1.asState().name); + } + } + } + } + } + assertTrue("nb of failures: " + failures, failures == 0); +} + +// Use for coverage tests only. Needs specific instrumentation of code, +// that is controled by UnconditionalFlowInfo#coverageTestFlag. +// Note: coverage tests tend to fill the console with messages, and the +// instrumented code is slower, so never release code with active +// coverage tests. +private static int coveragePointsNb = 39; + +// PREMATURE reactivate coverage tests +// Coverage by state transition tables methods. +public void test2998_coverage() { + if (UnconditionalFlowInfo.coverageTestFlag) { + // sanity check: need to be sure that the tests execute properly when not + // trying to check coverage + UnconditionalFlowInfo.coverageTestId = 0; + test0053_array(); + test0070_type_reference(); + test2050_markAsComparedEqualToNonNull(); + test2051_markAsComparedEqualToNull(); + test2055_markAsDefinitelyNonNull(); + test2056_markAsDefinitelyNull(); + test2057_markAsDefinitelyUnknown(); + test2060_addInitializationsFrom(); + test2061_addPotentialInitializationsFrom(); + test2062_mergedWith(); + // coverage check + int failuresNb = 0; + for (int i = 1; i <= coveragePointsNb; i++) { + if (i == 11 || i == 12 || i == 14) { + continue; + // these can only be reached via a direct call to addPotentialNullInfoFrom, + // which is not implemented in low level tests - all those go through + // addPotentialInitsFrom + } + try { + UnconditionalFlowInfo.coverageTestId = i; + test0053_array(); + test0070_type_reference(); + test2050_markAsComparedEqualToNonNull(); + test2051_markAsComparedEqualToNull(); + test2055_markAsDefinitelyNonNull(); + test2056_markAsDefinitelyNull(); + test2057_markAsDefinitelyUnknown(); + test2060_addInitializationsFrom(); + test2061_addPotentialInitializationsFrom(); + test2062_mergedWith(); + } + catch (AssertionFailedError e) { + continue; + } + catch (AssertionFailedException e) { + continue; + } + failuresNb++; + System.out.println("Missing coverage point: " + i); + } + UnconditionalFlowInfo.coverageTestId = 0; // reset for other tests + assertEquals(failuresNb + " missing coverage point(s)", failuresNb, 0); + } +} + +// Coverage by code samples. +public void test2999_coverage() { + if (UnconditionalFlowInfo.coverageTestFlag) { + // sanity check: need to be sure that the tests execute properly when not + // trying to check coverage + UnconditionalFlowInfo.coverageTestId = 0; + test0001_simple_local(); + test0053_array(); + test0070_type_reference(); + test0327_if_else(); + test0401_while(); + test0420_while(); + test0509_try_finally_embedded(); + test2000_flow_info(); + test2004_flow_info(); + test2008_flow_info(); + test2011_flow_info(); + test2013_flow_info(); + test2018_flow_info(); + test2019_flow_info(); + test2020_flow_info(); + // coverage check + int failuresNb = 0; + for (int i = 1; i <= coveragePointsNb; i++) { + if (i < 3 + || 4 < i && i < 11 + || 11 < i && i < 16 + || 16 < i && i < 20 + || i == 21 + || 23 < i && i < 27 + || 29 < i && i < 33 + || 36 < i) { // TODO (maxime) complete coverage tests + continue; + } + try { + UnconditionalFlowInfo.coverageTestId = i; + test0001_simple_local(); + test0053_array(); + test0070_type_reference(); + test0327_if_else(); + test0401_while(); + test0420_while(); + test0509_try_finally_embedded(); + test2000_flow_info(); + test2004_flow_info(); + test2008_flow_info(); + test2011_flow_info(); + test2013_flow_info(); + test2018_flow_info(); + test2019_flow_info(); + test2020_flow_info(); + } + catch (AssertionFailedError e) { + continue; + } + catch (AssertionFailedException e) { + continue; + } + failuresNb++; + System.out.println("Missing coverage point: " + i); + } + UnconditionalFlowInfo.coverageTestId = 0; // reset for other tests + assertEquals(failuresNb + " missing coverage point(s)", failuresNb, 0); + } +} + +// only works for info coded on bit 0 - least significant +String testCodedValueOf(long[] data) { + int length; + StringBuffer result = new StringBuffer(length = data.length); + for (int i = 0; i < length; i++) { + result.append(data[i] == 0 ? '0' : '1'); + } + return result.toString(); +} + +static String testStringValueOf(long[] data) { + int length; + StringBuffer result = new StringBuffer((length = data.length) * 2 + 1); + result.append('{'); + for (int i = 0; i < length; i++) { + if (i > 0) { + result.append(','); + } + result.append(data[i]); + } + result.append('}'); + return result.toString(); +} +} + +/** + * A specific extension of LocalVariableBinding suitable for flow info + * manipulation at an implementation level. + */ +class TestLocalVariableBinding extends LocalVariableBinding { + static class TestTypeBinding extends TypeBinding { + public TestTypeBinding() { + tagBits = 0L; + } + public char[] constantPoolName() { + return null; + } + public PackageBinding getPackage() { + return null; + } + public boolean isCompatibleWith(TypeBinding right) { + return false; + } + public char[] qualifiedSourceName() { + return null; + } + public char[] sourceName() { + return null; + } + public char[] readableName() { + return null; + } + } + final static TypeBinding testTypeBinding = new TestTypeBinding(); + final static char [] testName = {'t', 'e', 's', 't'}; + TestLocalVariableBinding(int id) { + super(testName, testTypeBinding, 0, false); + this.id = id; + } + public Constant constant() { + return Constant.NotAConstant; + } + static final TestLocalVariableBinding + local0 = new TestLocalVariableBinding(0), + local64 = new TestLocalVariableBinding(64), + local128 = new TestLocalVariableBinding(128); +} + +/** + * A class meant to augment + * @link{org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo} with + * capabilities in the test domain. It especially provides factories to build + * fake flow info instances for use in state transitions validation. + */ +/* + * Moreover, this class defines the implementation of key operations for the + * benefit of itself and NullInfoRegistryTestHarness. Given the fact that the + * latter could not extend UnconditionalFlowInfoTestHarness and + * NullInfoRegistry, the code is factorized into static methods. + */ +class UnconditionalFlowInfoTestHarness extends UnconditionalFlowInfo { + int testPosition; + // Interface +/** + * Return the state represented by this. + * @return the state represented by this + */ +NullReferenceImplTests.State asState() { + return asState(this, 0); +} + +/** + * Return the state represented by this for a variable encoded at a given position. + * @param position - int the position of the considered variable + * @return the state represented by this for a variable encoded at a given position + */ +NullReferenceImplTests.State asState(int position) { + return asState(this, position); +} + +public FlowInfo copy() { + UnconditionalFlowInfoTestHarness copy = + new UnconditionalFlowInfoTestHarness(); + copy.testPosition = this.testPosition; + copy(this, copy); + return copy; +} + +public void markAsDefinitelyNonNull(LocalVariableBinding local) { + grow(local.id + this.maxFieldCount); + super.markAsDefinitelyNonNull(local); +} + +public void markAsDefinitelyNull(LocalVariableBinding local) { + grow(local.id + this.maxFieldCount); + super.markAsDefinitelyNull(local); +} + +public void markAsDefinitelyUnknown(LocalVariableBinding local) { + grow(local.id + this.maxFieldCount); + super.markAsDefinitelyUnknown(local); +} + +/** + * Return a fake unconditional flow info which bit fields represent the given + * null bits for a local variable of id 0 within a class that would have no + * field. + * @param nullBits the bits that must be set, given in the same order as the + * nullAssignment* fields in UnconditionalFlowInfo definition; use 0 + * for a bit that is not set, 1 else + * @return a fake unconditional flow info which bit fields represent the + * null bits given in parameter + */ +public static UnconditionalFlowInfoTestHarness testUnconditionalFlowInfo( + long [] nullBits) { + return testUnconditionalFlowInfo(nullBits, 0); +} + +/** + * Return a fake unconditional flow info which bit fields represent the given + * null bits for a local variable of id position within a class that would have + * no field. + * @param nullBits the bits that must be set, given in the same order as the + * nullAssignment* fields in UnconditionalFlowInfo definition; use 0 + * for a bit that is not set, 1 else + * @param position the position of the variable within the bit fields; use + * various values to test different parts of the bit fields, within + * or beyond BitCacheSize + * @return a fake unconditional flow info which bit fields represent the + * null bits given in parameter + */ +public static UnconditionalFlowInfoTestHarness testUnconditionalFlowInfo( + long [] nullBits, int position) { + UnconditionalFlowInfoTestHarness result = + new UnconditionalFlowInfoTestHarness(); + result.testPosition = position; + init(result, nullBits, position); + return result; +} + +/** + * Return a fake unconditional flow info which bit fields represent the given + * state for a local variable of id 0 within a class that would have + * no field. + * @param state - State the desired state for the variable + * @return a fake unconditional flow info which bit fields represent the + * state given in parameter + */ +public static UnconditionalFlowInfoTestHarness testUnconditionalFlowInfo(NullReferenceImplTests.State state) { + return testUnconditionalFlowInfo(state, 0); +} + +/** + * Return a fake unconditional flow info which bit fields represent the given + * state for a local variable of id position within a class that would have + * no field. + * @param state - State the desired state for the variable + * @param position the position of the variable within the bit fields; use + * various values to test different parts of the bit fields, within + * or beyond BitCacheSize + * @return a fake unconditional flow info which bit fields represent the + * state given in parameter + */ +public static UnconditionalFlowInfoTestHarness testUnconditionalFlowInfo( + NullReferenceImplTests.State state, int position) { + UnconditionalFlowInfoTestHarness result = + new UnconditionalFlowInfoTestHarness(); + long[] nullBits = state.asLongArray(); + result.testPosition = position; + init(result, nullBits, position); + return result; +} + +/** + * Return true iff this flow info can be considered as equal to the one passed + * in parameter. + * @param other the flow info to compare to + * @return true iff this flow info compares equal to other + */ +public boolean testEquals(UnconditionalFlowInfo other) { + return testEquals(this, other); +} + +/** + * Return true iff this flow info can be considered as equal to the one passed + * in parameter in respect with a single local variable which id would be + * position in a class with no field. + * @param other the flow info to compare to + * @param position the position of the local to consider + * @return true iff this flow info compares equal to other for a given local + */ +public boolean testEquals(UnconditionalFlowInfo other, int position) { + return testEquals(this, other, position); +} + +/** + * Return a string suitable for use as a representation of this flow info + * within test series. + * @return a string suitable for use as a representation of this flow info + */ +public String testString() { + if (this == DEAD_END) { + return "FlowInfo.DEAD_END"; //$NON-NLS-1$ + } + return testString(this, this.testPosition); +} + +/** + * Return a string suitable for use as a representation of this flow info + * within test series. + * @param position a position to consider instead of this flow info default + * test position + * @return a string suitable for use as a representation of this flow info + */ +public String testString(int position) { + return testString(this, position); +} + + // Factorized implementation +static NullReferenceImplTests.State asState(UnconditionalFlowInfo zis, int position) { + if ((zis.tagBits & NULL_FLAG_MASK) == 0) { + return NullReferenceImplTests.State.start; + } + if (position < BitCacheSize) { + return NullReferenceImplTests.State.fromLongValues( + (zis.nullBit1 >> position) & 1, + (zis.nullBit2 >> position) & 1, + (zis.nullBit3 >> position) & 1, + (zis.nullBit4 >> position) & 1, + 0, + 0); + } + else { + int vectorIndex = (position / BitCacheSize) - 1; + position %= BitCacheSize; + if (vectorIndex >= zis.extra[2].length) { + return NullReferenceImplTests.State.start; + } + return NullReferenceImplTests.State.fromLongValues( + (zis.extra[2][vectorIndex] >> position) & 1, + (zis.extra[3][vectorIndex] >> position) & 1, + (zis.extra[4][vectorIndex] >> position) & 1, + (zis.extra[5][vectorIndex] >> position) & 1, + 0 //(zis.extra[6][vectorIndex] >> position) & 1, + , 0 //(zis.extra[7][vectorIndex] >> position) & 1 + ); + } +} + +static void copy(UnconditionalFlowInfo source, UnconditionalFlowInfo target) { + target.definiteInits = source.definiteInits; + target.potentialInits = source.potentialInits; + boolean hasNullInfo = (source.tagBits & NULL_FLAG_MASK) != 0; + if (hasNullInfo) { + target.nullBit1 = source.nullBit1; + target.nullBit2 = source.nullBit2; + target.nullBit3 = source.nullBit3; + target.nullBit4 = source.nullBit4; +// target.nullBit5 = source.nullBit5; +// target.nullBit6 = source.nullBit6; + } + target.tagBits = source.tagBits; + target.maxFieldCount = source.maxFieldCount; + if (source.extra != null) { + int length; + target.extra = new long[extraLength][]; + System.arraycopy(source.extra[0], 0, + (target.extra[0] = new long[length = source.extra[0].length]), 0, length); + System.arraycopy(source.extra[1], 0, + (target.extra[1] = new long[length]), 0, length); + if (hasNullInfo) { + for (int j = 0; j < extraLength; j++) { + System.arraycopy(source.extra[j], 0, + (target.extra[j] = new long[length]), 0, length); + } + } + else { + for (int j = 0; j < extraLength; j++) { + target.extra[j] = new long[length]; + } + } + } +} + +public void grow(int position) { + int vectorIndex = ((position) / BitCacheSize) - 1; + int length = vectorIndex + 1, oldLength; + if (this.extra == null) { + this.extra = new long[extraLength][]; + for (int j = 0; j < extraLength; j++) { + this.extra[j] = new long[length]; + } + } else if (length > (oldLength = this.extra[2].length)) { + for (int j = 0; j < extraLength; j++) { + System.arraycopy(this.extra[j], 0, + this.extra[j] = new long[length], 0, oldLength); + } + } +} + +static void init(UnconditionalFlowInfo zis, long [] nullBits, int position) { + if (position < BitCacheSize) { + zis.nullBit1 = nullBits[0] << position; + zis.nullBit2 = nullBits[1] << position; + zis.nullBit3 = nullBits[2] << position; + zis.nullBit4 = nullBits[3] << position; +// zis.nullBit5 = nullBits[4] << position; +// zis.nullBit6 = nullBits[5] << position; + } + else { + int vectorIndex = (position / BitCacheSize) - 1, + length = vectorIndex + 1; + position %= BitCacheSize; + zis.extra = new long[extraLength][]; + zis.extra[0] = new long[length]; + zis.extra[1] = new long[length]; + for (int j = 2; j < extraLength; j++) { + zis.extra[j] = new long[length]; + zis.extra[j][vectorIndex] = nullBits[j - 2] << position; + } + } + if (nullBits[0] != 0 || nullBits[1] != 0 + || nullBits[2] != 0 || nullBits[3] != 0 + || nullBits[4] != 0 || nullBits[5] != 0) { + // cascade better than nullBits[0] | nullBits[1] | nullBits[2] | nullBits[3] + // by 10%+ + // TODO (maxime) run stats to determine which is the better order + zis.tagBits |= NULL_FLAG_MASK; + } + zis.maxFieldCount = 0; +} + +static boolean testEquals(UnconditionalFlowInfo zis, UnconditionalFlowInfo other) { + if (zis.tagBits != other.tagBits) { + return false; + } + if (zis.nullBit1 != other.nullBit1 + || zis.nullBit2 != other.nullBit2 + || zis.nullBit3 != other.nullBit3 + || zis.nullBit4 != other.nullBit4 + /* || zis.nullBit5 != other.nullBit5 + || zis.nullBit6 != other.nullBit6 */) { + return false; + } + int left = zis.extra == null ? 0 : zis.extra[2].length, + right = other.extra == null ? 0 : other.extra[2].length, + both = 0, i; + if (left > right) { + both = right; + } + else { + both = left; + } + for (i = 0; i < both ; i++) { + for (int j = 2; j < extraLength; j++) { + if (zis.extra[j][i] != + other.extra[j][i]) { + return false; + } + } + } + for (; i < left; i++) { + for (int j = 2; j < extraLength; j++) { + if (zis.extra[j][i] != 0) { + return false; + } + } + } + for (; i < right; i++) { + for (int j = 2; j < extraLength; j++) { + if (other.extra[j][i] != 0) { + return false; + } + } + } + return true; +} + +static boolean testEquals(UnconditionalFlowInfo zis, UnconditionalFlowInfo other, + int position) { + int vectorIndex = position / BitCacheSize - 1; + if ((zis.tagBits & other.tagBits & NULL_FLAG_MASK) == 0) { + return true; + } + long mask; + if (vectorIndex < 0) { + return ((zis.nullBit1 & (mask = (1L << position))) ^ + (other.nullBit1 & mask)) == 0 && + ((zis.nullBit2 & mask) ^ + (other.nullBit2 & mask)) == 0 && + ((zis.nullBit3 & mask) ^ + (other.nullBit3 & mask)) == 0 && + ((zis.nullBit4 & mask) ^ + (other.nullBit4 & mask)) == 0 /* && + ((zis.nullBit5 & mask) ^ + (other.nullBit5 & mask)) == 0 && + ((zis.nullBit6 & mask) ^ + (other.nullBit6 & mask)) == 0 */; + } + else { + int left = zis.extra == null ? + 0 : + zis.extra[0].length; + int right = other.extra == null ? + 0 : + other.extra[0].length; + int both = left < right ? left : right; + if (vectorIndex < both) { + mask = (1L << (position % BitCacheSize)); + for (int j = 2; j < extraLength; j++) { + if (((zis.extra[j][vectorIndex] & mask) + ^ (other.extra[j][vectorIndex] & mask)) != 0) { + return false; + } + } + return true; + } + if (vectorIndex < left) { + return ((zis.extra[2][vectorIndex] | + zis.extra[3][vectorIndex] | + zis.extra[4][vectorIndex] | + zis.extra[5][vectorIndex] | + zis.extra[6][vectorIndex] | + zis.extra[7][vectorIndex]) & + (1L << (position % BitCacheSize))) == 0; + } + return ((other.extra[2][vectorIndex] | + other.extra[3][vectorIndex] | + other.extra[4][vectorIndex] | + other.extra[5][vectorIndex] | + other.extra[6][vectorIndex] | + other.extra[7][vectorIndex]) & + (1L << (position % BitCacheSize))) == 0; + } +} + +static String testString(UnconditionalFlowInfo zis, int position) { + if (zis == DEAD_END) { + return "FlowInfo.DEAD_END"; //$NON-NLS-1$ + } + if (position < BitCacheSize) { + return "{" + (zis.nullBit1 >> position) //$NON-NLS-1$ + + "," + (zis.nullBit2 >> position) //$NON-NLS-1$ + + "," + (zis.nullBit3 >> position) //$NON-NLS-1$ + + "," + (zis.nullBit4 >> position) //$NON-NLS-1$ +// + "," + (zis.nullBit5 >> position) //$NON-NLS-1$ +// + "," + (zis.nullBit6 >> position) //$NON-NLS-1$ + + "}"; //$NON-NLS-1$ + } + else { + int vectorIndex = position / BitCacheSize - 1, + shift = position % BitCacheSize; + return "{" + (zis.extra[2][vectorIndex] //$NON-NLS-1$ + >> shift) + + "," + (zis.extra[3][vectorIndex] //$NON-NLS-1$ + >> shift) + + "," + (zis.extra[4][vectorIndex] //$NON-NLS-1$ + >> shift) + + "," + (zis.extra[5][vectorIndex] //$NON-NLS-1$ + >> shift) +// + "," + (zis.extra[6][vectorIndex] //$NON-NLS-1$ +// >> shift) +// + "," + (zis.extra[7][vectorIndex] //$NON-NLS-1$ +// >> shift) + + "}"; //$NON-NLS-1$ + } +} +} +/** + * A class meant to augment + * @link{org.eclipse.jdt.internal.compiler.flow.NullInfoRegistry} with + * capabilities in the test domain. It especially provides factories to build + * fake flow info instances for use in state transitions validation. + */ +/* + * The reason why UnconditionalFlowInfoTestHarness and this class were + * separated is that NullInfoRegistry redefines part of the markAs* methods, + * in effect preventing a harness extending NullInfoRegistry to access + * UnconditionalFlowInfo implementations of the said methods. + */ +class NullInfoRegistryTestHarness extends NullInfoRegistry { + private int testPosition; + +private NullInfoRegistryTestHarness() { + super(FlowInfo.DEAD_END); +} + + // Interface +/** + * Return the state represented by this. + * @return the state represented by this + */ +NullReferenceImplTests.State asState() { + return UnconditionalFlowInfoTestHarness.asState(this, 0); +} + +/** + * Return the state represented by this for a variable encoded at a given position. + * @param position - int the position of the considered variable + * @return the state represented by this for a variable encoded at a given position + */ +NullReferenceImplTests.State asState(int position) { + return UnconditionalFlowInfoTestHarness.asState(this, position); +} + +public FlowInfo copy() { + NullInfoRegistryTestHarness copy = + new NullInfoRegistryTestHarness(); + copy.testPosition = this.testPosition; + UnconditionalFlowInfoTestHarness.copy(this, copy); + return copy; +} + +/** + * Return a fake null info registry derived from an unconditional flow + * info. + * @param upstream - UnconditionalFlowInfoTestHarness the upstream flow info + * @return a fake null info registry derived from upstream + */ +public static NullInfoRegistryTestHarness testNullInfoRegistry( + UnconditionalFlowInfoTestHarness upstream) { + NullInfoRegistry nullInfoRegistry = new NullInfoRegistry(upstream); + NullInfoRegistryTestHarness result = + new NullInfoRegistryTestHarness(); + result.testPosition = upstream.testPosition; + if (result.testPosition < BitCacheSize) { + result.nullBit1 = nullInfoRegistry.nullBit1; + result.nullBit2 = nullInfoRegistry.nullBit2; + result.nullBit3 = nullInfoRegistry.nullBit3; + result.nullBit4 = nullInfoRegistry.nullBit4; +// result.nullBit5 = nullInfoRegistry.nullBit5; +// result.nullBit6 = nullInfoRegistry.nullBit6; + } + else if ((nullInfoRegistry.tagBits & NULL_FLAG_MASK) != 0){ + int vectorIndex = (result.testPosition / BitCacheSize) - 1, + length = vectorIndex + 1; + result.extra = new long[extraLength][]; + result.extra[0] = new long[length]; + result.extra[1] = new long[length]; + for (int j = 2; j < extraLength; j++) { + result.extra[j] = new long[length]; + result.extra[j][vectorIndex] = nullInfoRegistry.extra[j][vectorIndex]; + } + } + if ((nullInfoRegistry.tagBits & NULL_FLAG_MASK) != 0) { + result.tagBits |= NULL_FLAG_MASK; + } + result.maxFieldCount = 0; + return result; +} + +/** + * Return true iff this flow info can be considered as equal to the one passed + * in parameter. + * @param other the flow info to compare to + * @return true iff this flow info compares equal to other + */ +public boolean testEquals(UnconditionalFlowInfo other) { + return UnconditionalFlowInfoTestHarness.testEquals(this, other); +} + +/** + * Return true iff this flow info can be considered as equal to the one passed + * in parameter in respect with a single local variable which id would be + * position in a class with no field. + * @param other the flow info to compare to + * @param position the position of the local to consider + * @return true iff this flow info compares equal to other for a given local + */ +public boolean testEquals(UnconditionalFlowInfo other, int position) { + return UnconditionalFlowInfoTestHarness.testEquals(this, other, position); +} + +/** + * Return a string suitable for use as a representation of this flow info + * within test series. + * @return a string suitable for use as a representation of this flow info + */ +public String testString() { + if (this == DEAD_END) { + return "FlowInfo.DEAD_END"; //$NON-NLS-1$ + } + return UnconditionalFlowInfoTestHarness.testString(this, this.testPosition); +} + +/** + * Return a string suitable for use as a representation of this flow info + * within test series. + * @param position a position to consider instead of this flow info default + * test position + * @return a string suitable for use as a representation of this flow info + */ +public String testString(int position) { + return UnconditionalFlowInfoTestHarness.testString(this, position); +} +} + +interface CodeAnalysis { + public static final String + definitionStartMarker = "DEFINITION START", + definitionEndMarker = "DEFINITION END", + initializerStartMarker = "INITIALIZER START", + initializerEndMarker = "INITIALIZER END"; +} +class TransitiveClosureHolder { +static class Element { + NullReferenceImplTests.State value; + boolean alreadyKnown; + Element(NullReferenceImplTests.State value) { + if (value == null) { + throw new IllegalArgumentException("not a valid element"); + } + this.value = value; + } +} +Map elements = new TreeMap(); +public TransitiveClosureHolder() { + Element start = new Element(NullReferenceImplTests.State.start); + this.elements.put(start.value, start); +} +void add(NullReferenceImplTests.State value) { + if (value == null) { + throw new IllegalArgumentException("not a valid state"); + } + if (! this.elements.containsKey(value)) { + this.elements.put(value, new Element(value)); + } +} +void add(NullReferenceImplTests.State[] values) { + if (values == null) { + throw new IllegalArgumentException("not a valid states set"); + } + for (int i = 0, length = values.length; i < length; i++) { + add(values[i]); + } +} +NullReferenceImplTests.State[] asArray() { + int length; + NullReferenceImplTests.State[] result = new NullReferenceImplTests.State[length = this.elements.size()]; + Iterator elementsIterator = this.elements.keySet().iterator(); + for (int j = 0; j < length; j++) { + result[j] = (NullReferenceImplTests.State) elementsIterator.next(); + } + return result; +} +NullReferenceImplTests.State[] notAlreadyKnowns() { + List resultAccumulator = new ArrayList(this.elements.size()); + Iterator i = this.elements.values().iterator(); + Element current; + while (i.hasNext()) { + if (! (current = (Element) i.next()).alreadyKnown) { + resultAccumulator.add(current.value); + } + } + int length; + NullReferenceImplTests.State[] result = new NullReferenceImplTests.State[length = resultAccumulator.size()]; + for (int j = 0; j < length; j++) { + result[j] = (NullReferenceImplTests.State) resultAccumulator.get(j); + } + return result; +} +void markAllAsAlreadyKnown() { + Iterator i = this.elements.values().iterator(); + while (i.hasNext()) { + ((Element) i.next()).alreadyKnown = true; + } +} +public String toString() { + StringBuffer output = new StringBuffer(); + output.append("Transitive closure:\n"); + SortedMap sorted = new TreeMap(this.elements); + Iterator i = sorted.keySet().iterator(); + while (i.hasNext()) { + output.append(i.next().toString()); + output.append('\n'); + } + return output.toString(); +} +} + +// PREMATURE segregate pure tooling into a separate project, keep tests only here +/** + * The Generator class is meant to generate the tabular data needed by the + * flow information implementation level tests. While the tests should ensure + * non regression by leveraging their initialization tables only, any change + * into the flow information logic or encoding is due to yield considerable + * changes into the literal values sets of the initializers themselves. + * Tooling the production of those literals buys us flexibility. + * {@link #printHelp printHelp} for details. + */ +class Generator { +static NullReferenceImplTests.State[] computeTransitiveClosure() { + TransitiveClosureHolder transitiveClosure = new TransitiveClosureHolder(); + NullReferenceImplTests.State[] unknowns; + unknowns = transitiveClosure.notAlreadyKnowns(); + while (unknowns.length != 0) { + transitiveClosure.markAllAsAlreadyKnown(); + for (int i = 0, length = NullReferenceImplTransformations.transformations.length; i < length; i ++) { + transitiveClosure.add( + NullReferenceImplTransformations.transformations[i]. + computeOutputs(transitiveClosure.asArray())); + } + unknowns = transitiveClosure.notAlreadyKnowns(); + } + return transitiveClosure.asArray(); +} +public static void main(String[] args) { + if (args.length == 0) { + printHelp(false); + System.exit(1); + } + switch (args.length) { + case 1: + if (args[0].equals("--help")) { + printHelp(true); + System.exit(0); + } + else { + printHelp(false); + System.exit(1); + } + case 2: + if (args[0].equals("--printTruthTables")) { + File outputDir = new File(args[1]); + if (outputDir.isDirectory()) { + for (int i = 0, length = NullReferenceImplTransformations.transformations.length; i < length; i++) { + NullReferenceImplTransformations.transformations[i].printTruthTables(outputDir); + } + } + else { + // PREMATURE error handling + } + System.exit(0); + } + else { + printHelp(false); + System.exit(1); + } + case 3: + if (args[0].equals("--reinitializeFromComputedValues")) { + reinitializeFromComputedValues(args[1], args[2]); + System.out.println("Generator generated new file into " + args[2]); + System.exit(0); + } + case 5: + if (args[0].equals("--reinitializeFromComments")) { + reinitializeFromComments(args[1], args[2], args[3], args[4]); + System.out.println("Generator generated new files into " + args[2] + + " and " + args[4]); + System.exit(0); + } + default: + printHelp(false); + System.exit(1); + } +} + +private static void reinitializeFromComments( + String statesSource, String statesTarget, + String transformationsSource, String transformationsTarget) { + if (statesSource.equals(transformationsSource) || + statesTarget.equals(transformationsTarget)) { + throw new RuntimeException(); + } + try { + BufferedReader in; + BufferedWriter out; + NullReferenceImplTests.State.reinitializeFromComment( + in = new BufferedReader( + new FileReader(statesSource)), + out = new BufferedWriter(new FileWriter(statesTarget))); + in.close(); + out.close(); + File[] tempFiles = new File[2]; + tempFiles[0] = File.createTempFile("generator", "java"); + tempFiles[1] = File.createTempFile("generator", "java"); + NullReferenceImplTransformations.transformations[0].reinitializeFromComments( + in = new BufferedReader( + new FileReader(transformationsSource)), + out = new BufferedWriter(new FileWriter(tempFiles[0]))); + in.close(); + out.close(); + int i, length; + for (i = 1, length = NullReferenceImplTransformations.transformations.length - 1; i < length; i++) { + NullReferenceImplTransformations.transformations[i].reinitializeFromComments( + in = new BufferedReader( + new FileReader(tempFiles[(i + 1) % 2])), + out = new BufferedWriter(new FileWriter(tempFiles[i % 2]))); + in.close(); + out.close(); + } + NullReferenceImplTransformations.transformations[i].reinitializeFromComments( + in = new BufferedReader( + new FileReader(tempFiles[(i + 1) % 2])), + out = new BufferedWriter(new FileWriter(transformationsTarget))); + in.close(); + out.close(); + } catch (Throwable t) { + System.err.println("Generator error:"); + t.printStackTrace(System.err); + System.exit(2); + } +} + +private static void reinitializeFromComputedValues(String source, String target) { + for (int i = 0, length = NullReferenceImplTransformations.transformations.length; + i < length; i++) { + NullReferenceImplTransformations.transformations[i].hydrate(); + } + NullReferenceImplTests.State[] transitiveClosure = computeTransitiveClosure(); + try { + BufferedReader in; + BufferedWriter out; + File[] tempFiles = new File[2]; + tempFiles[0] = File.createTempFile("generator", "java"); + tempFiles[1] = File.createTempFile("generator", "java"); + NullReferenceImplTransformations.transformations[0].reinitializeFromComputedValues( + in = new BufferedReader( + new FileReader(source)), + out = new BufferedWriter(new FileWriter(tempFiles[0])), + transitiveClosure); + in.close(); + out.close(); + int i, length; + for (i = 1, length = NullReferenceImplTransformations.transformations.length - 1; i < length; i++) { + NullReferenceImplTransformations.transformations[i].reinitializeFromComputedValues( + in = new BufferedReader( + new FileReader(tempFiles[(i + 1) % 2])), + out = new BufferedWriter(new FileWriter(tempFiles[i % 2])), + transitiveClosure); + in.close(); + out.close(); + } + NullReferenceImplTransformations.transformations[i].reinitializeFromComputedValues( + in = new BufferedReader( + new FileReader(tempFiles[(i + 1) % 2])), + out = new BufferedWriter(new FileWriter(target)), + transitiveClosure); + in.close(); + out.close(); + } catch (Throwable t) { + System.err.println("Generator error:"); + t.printStackTrace(System.err); + System.exit(2); + } +} + +private static void printHelp(boolean longText) { + if (longText) { + System.out.println( + "Generator use cases\n" + + " - when a brand new logic is experimented for the transitions, the best\n" + + " way to go is to write explicit (inefficient) transformation code within\n" + + " UnconditionalFlowInfo, then generate the literal initializers from\n" + + " there; use the command\n" + + " --reinitializeFromComputedValues \n" + + " to this effect; in case of inconsistencies or errors, messages are\n" + + " printed to the error output stream and the result should be considered as non reliable;\n" + + " - when only a few changes are made to state names or a specific\n" + + " transitions, it should be possible to get the test initializers fixed\n" + + " before UnconditionalFlowInfo implements those changes; use the command\n" + + " --reinitializeFromComments \n" + + " to this effect;\n" + + " - the same command can be used when, while the semantics of the system\n" + + " are unchanged, the encoding is modified; it should then produce the\n" + + " initializers according to the new encoding, as defined by the comment\n" + + " for State.states, and the transformations as defined by their\n" + + " respective comment;\n" + + " - when a given encoding is retained, its optimization may leverage truth\n" + + " tables; use the --printTruthTables command to this effect.\n" + + " \n\n"); + printHelp(false); + } + else { + System.out.println( + "Usage:\n" + + "Generator --help\n" + + " prints a more detailed help message\n" + + "Generator --printTruthTables\n" + + " prints the truth tables of the transformations\n" + + "Generator --reinitializeFromComments \n" + + " generates into target file a copy of source file into which\n" + + " transformations initializers have been reset from their definitions\n" + + "Generator --reinitializeFromComputedValues \n" + + " generates into target file a copy of source file into which\n" + + " transformations definitions and initializers have been reset\n" + + " according to the behavior of the current UnconditionalFlowInfo\n" + ); + } +} +} +