This repository has been archived on 2023-06-18. You can view files and clone it, but cannot push or open issues or pull requests.
ima02/resources/defects4j-checkout-closure-1f/test/com/google/javascript/jscomp/DeadAssignmentsEliminationTest.java

535 lines
17 KiB
Java
Raw Permalink Normal View History

2023-04-25 11:33:41 +00:00
/*
* Copyright 2008 The Closure Compiler Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.javascript.jscomp;
import com.google.javascript.rhino.Node;
/**
* Tests for {@link DeadAssignmentsElimination}.
*
*/
public class DeadAssignmentsEliminationTest extends CompilerTestCase {
public DeadAssignmentsEliminationTest() {
super("var extern;");
}
@Override
public void setUp() {
super.enableLineNumberCheck(true);
}
@Override
public CompilerPass getProcessor(final Compiler compiler) {
return new CompilerPass() {
@Override
public void process(Node externs, Node js) {
NodeTraversal.traverse(
compiler, js, new DeadAssignmentsElimination(compiler));
}
};
}
@Override
protected int getNumRepetitions() {
return 1;
}
public void testSimple() {
inFunction("var a; a=1", "var a; 1");
inFunction("var a; a=1+1", "var a; 1+1");
inFunction("var a; a=foo();", "var a; foo()");
inFunction("a=1; var a; a=foo();", "1; var a; foo();");
// This should be: "var a; (function f(){})", but we don't mess with
// functions with inner functions.
inFunction("var a; a=function f(){}");
}
public void testLoops() {
inFunction("for(var a=0; a<10; a++) {}");
inFunction("var x; for(var a=0; a<10; a++) {x=a}; a(x)");
inFunction("var x; for(var a=0; x=a<10; a++) {}",
"var x; for(var a=0; a<10; a++) {}");
inFunction("var x; for(var a=0; a<10; x=a) {}",
"var x; for(var a=0; a<10; a) {}");
inFunction("var x; for(var a=0; a<10; x=a,a++) {}",
"var x; for(var a=0; a<10; a,a++) {}");
inFunction("var x; for(var a=0; a<10; a++,x=a) {}",
"var x; for(var a=0; a<10; a++,a) {}");
inFunction("var x;for(var a=0; a<10; a++) {x=1}",
"var x;for(var a=0; a<10; a++) {1}");
inFunction("var x; x=1; do{x=2}while(0); x",
"var x; 1; do{x=2}while(0); x");
inFunction("var x; x=1; while(1){x=2}; x");
}
public void testMultiPaths() {
inFunction("var x,y; if(x)y=1;", "var x,y; if(x)1;");
inFunction("var x,y; if(x)y=1; y=2; x(y)", "var x,y; if(x)1; y=2; x(y)");
inFunction("var x; switch(x) { case(1): x=1; break; } x");
inFunction("var x; switch(x) { case(1): x=1; break; }",
"var x; switch(x) { case(1): 1; break; }");
}
public void testUsedAsConditions() {
inFunction("var x; while(x=1){}", "var x; while(1){}");
inFunction("var x; if(x=1){}", "var x; if(1){}");
inFunction("var x; do{}while(x=1)", "var x; do{}while(1)");
inFunction("var x; if(x=1==4&&1){}", "var x; if(1==4&&1) {}");
inFunction("var x; if(0&&(x=1)){}", "var x; if(0&&1){}");
inFunction("var x; if((x=2)&&(x=1)){}", "var x; if(2&&1){}");
inFunction("var x; x=2; if(0&&(x=1)){}; x");
inFunction("var x,y; if( (x=1)+(y=2) > 3){}",
"var x,y; if( 1+2 > 3){}");
}
public void testUsedAsConditionsInSwitchStatements() {
inFunction("var x; switch(x=1){}","var x; switch(1){}");
inFunction("var x; switch(x){case(x=1):break;}",
"var x; switch(x){case(1):break;}");
inFunction("var x,y; switch(y) { case (x += 1): break; case (x): break;}");
inFunction("var x,y; switch(y) { case (x = 1): break; case (2): break;}",
"var x,y; switch(y) { case (1): break; case (2): break;}");
inFunction("var x,y; switch(y) { case (x+=1): break; case (x=2): break;}",
"var x,y; switch(y) { case (x+1): break; case (2): break;}");
}
public void testAssignmentInReturn() {
inFunction("var x; return x = 1;", "var x; return 1");
inFunction("var x; return");
}
public void testAssignmentSamples() {
// We want this to be "var x" in these cases.
inFunction("var x = 2;");
inFunction("var x = 2; x++;", "var x=2; void 0");
inFunction("var x; x=x++;", "var x;x++");
inFunction("var x; x+=1;", "var x;x+1");
}
public void testAssignmentInArgs() {
inFunction("var x; foo(x = 1);", "var x; foo(1);");
inFunction("var x; return foo(x = 1);", "var x; return foo(1);");
}
/**
* BUG #1358904
*/
public void testAssignAndReadInCondition() {
inFunction("var a, b; if ((a = 1) && (b = a)) {b}");
inFunction("var a, b; if ((b = a) && (a = 1)) {b}",
"var a, b; if ((b = a) && (1)) {b}");
}
public void testParameters() {
inFunction("param1=1; param1=2; param2(param1)",
"1; param1=2; param2(param1)");
inFunction("param1=param2()", "param2()");
}
public void testErrorHandling() {
inFunction("var x; try{ x=1 } catch(e){ x=2 }; x");
inFunction("var x; try{ x=1 } catch(e){ x=2 }",
"var x;try{ 1 } catch(e) { 2 }");
inFunction("var x; try{ x=1 } finally { x=2 }; x",
"var x;try{ 1 } finally{ x=2 }; x");
inFunction("var x; while(1) { try{x=1;break}finally{x} }");
inFunction("var x; try{throw 1} catch(e){x=2} finally{x}");
inFunction("var x; try{x=1;throw 1;x} finally{x=2}; x",
"var x; try{1;throw 1;x} finally{x=2}; x");
}
public void testDeadVarDeclarations() {
// Dead assignments in VAR is _NOT_ supported yet.
inFunction("var x=1;");
inFunction("var x=1; x=2; x");
}
public void testGlobal() {
// Doesn't do any work on global scope yet.
test("var x; x=1; x=2; x=3;", "var x; x=1; x=2; x=3;");
}
public void testInnerFunctions() {
inFunction("var x = function() { var x; x=1; }",
"var x = function() { var x; 1; }");
}
public void testInnerFunctions2() {
// Give up DCE if there is a inner function.
inFunction("var x = 0; print(x); x = 1; var y = function(){}; y()");
}
public void testSelfReAssignment() {
inFunction("var x; x = x;", "var x; x");
}
public void testSelfIncrement() {
inFunction("var x; x = x + 1;", "var x; x + 1");
}
public void testAssignmentOp() {
// We have remove constant expressions that cleans this one up.
inFunction("var x; x += foo()", "var x; x + foo()");
}
public void testAssignmentOpUsedAsLhs() {
inFunction("var x,y; y = x += foo(); print(y)",
"var x,y; y = x + foo(); print(y)");
}
public void testAssignmentOpUsedAsCondition() {
inFunction("var x; if(x += foo()) {}",
"var x; if(x + foo()) {}");
inFunction("var x; if((x += foo()) > 1) {}",
"var x; if((x + foo()) > 1) {}");
// Not in a while because this happens every loop.
inFunction("var x; while((x += foo()) > 1) {}");
inFunction("var x; for(;--x;){}");
inFunction("var x; for(;x--;){}");
inFunction("var x; for(;x -= 1;){}");
inFunction("var x; for(;x = 0;){}", "var x; for(;0;){}");
inFunction("var x; for(;;--x){}");
inFunction("var x; for(;;x--){}");
inFunction("var x; for(;;x -= 1){}");
inFunction("var x; for(;;x = 0){}", "var x; for(;;0){}");
inFunction("var x; for(--x;;){}", "var x; for(;;){}");
inFunction("var x; for(x--;;){}", "var x; for(;;){}");
inFunction("var x; for(x -= 1;;){}", "var x; for(x - 1;;){}");
inFunction("var x; for(x = 0;;){}", "var x; for(0;;){}");
}
public void testDeadIncrement() {
// TODO(user): Optimize this.
inFunction("var x; x ++", "var x; void 0");
inFunction("var x; x --", "var x; void 0");
}
public void testDeadButAlivePartiallyWithinTheExpression() {
inFunction("var x; x = 100, print(x), x = 101;",
"var x; x = 100, print(x), 101;");
inFunction("var x; x = 100, print(x), print(x), x = 101;",
"var x; x = 100, print(x), print(x), 101;");
inFunction("var x; x = 100, print(x), x = 0, print(x), x = 101;",
"var x; x = 100, print(x), x = 0, print(x), 101;");
}
public void testMutipleDeadAssignmentsButAlivePartiallyWithinTheExpression() {
inFunction("var x; x = 1, x = 2, x = 3, x = 4, x = 5," +
" print(x), x = 0, print(x), x = 101;",
"var x; 1, 2, 3, 4, x = 5, print(x), x = 0, print(x), 101;");
}
public void testDeadPartiallyWithinTheExpression() {
// Sadly, this is not covered. We don't suspect this would happen too
// often.
inFunction("var x; x = 100, x = 101; print(x);");
}
public void testAssignmentChain() {
inFunction("var a,b,c,d,e; a = b = c = d = e = 1",
"var a,b,c,d,e; 1");
inFunction("var a,b,c,d,e; a = b = c = d = e = 1; print(c)",
"var a,b,c,d,e; c = 1 ; print(c)");
inFunction("var a,b,c,d,e; a = b = c = d = e = 1; print(a + e)",
"var a,b,c,d,e; a = e = 1; print(a + e)");
inFunction("var a,b,c,d,e; a = b = c = d = e = 1; print(b + d)",
"var a,b,c,d,e; b = d = 1; print(b + d)");
inFunction("var a,b,c,d,e; a = b = c = d = e = 1; print(a + b + d + e)",
"var a,b,c,d,e; a = b = d = e = 1; print(a + b + d + e)");
inFunction("var a,b,c,d,e; a = b = c = d = e = 1; print(a+b+c+d+e)");
}
public void testAssignmentOpChain() {
inFunction("var a,b,c,d,e; a = b = c += d = e = 1",
"var a,b,c,d,e; c + 1");
inFunction("var a,b,c,d,e; a = b = c += d = e = 1; print(e)",
"var a,b,c,d,e; c + (e = 1); print(e)");
inFunction("var a,b,c,d,e; a = b = c += d = e = 1; print(d)",
"var a,b,c,d,e; c + (d = 1) ; print(d)");
inFunction("var a,b,c,d,e; a = b = c += d = e = 1; print(a)",
"var a,b,c,d,e; a = c + 1; print(a)");
}
public void testIncDecInSubExpressions() {
inFunction("var a; a = 1, a++; a");
inFunction("var a; a = 1, ++a; a");
inFunction("var a; a = 1, a--; a");
inFunction("var a; a = 1, --a; a");
inFunction("var a; a = 1, a++, print(a)");
inFunction("var a; a = 1, ++a, print(a)");
inFunction("var a; a = 1, a--, print(a)");
inFunction("var a; a = 1, --a, print(a)");
inFunction("var a; a = 1, print(a++)");
inFunction("var a; a = 1, print(++a)");
inFunction("var a; a = 1, print(a++)");
inFunction("var a; a = 1, print(++a)");
inFunction("var a; a = 1, print(a--)");
inFunction("var a; a = 1, print(--a)");
}
public void testNestedReassignments() {
inFunction("var a; a = (a = 1)", "var a; 1");
inFunction("var a; a = (a *= 2)", "var a; a*2");
// Note a = (a++) is not same as a++. Only if 'a' is dead.
inFunction("var a; a = (a++)", "var a; a++"); // Preferred: "var a"
inFunction("var a; a = (++a)", "var a; ++a"); // Preferred: "var a"
inFunction("var a; a = (b = (a = 1))", "var a; b = 1");
inFunction("var a; a = (b = (a *= 2))", "var a; b = a * 2");
inFunction("var a; a = (b = (a++))", "var a; b=a++");
inFunction("var a; a = (b = (++a))", "var a; b=++a");
// Include b as local.
inFunction("var a,b; a = (b = (a = 1))", "var a,b; 1");
inFunction("var a,b; a = (b = (a *= 2))", "var a,b; a * 2");
inFunction("var a,b; a = (b = (a++))",
"var a,b; a++"); // Preferred: "var a,b"
inFunction("var a,b; a = (b = (++a))",
"var a,b; ++a"); // Preferred: "var a,b"
inFunction("var a; a += (a++)", "var a; a + a++");
inFunction("var a; a += (++a)", "var a; a+ (++a)");
// Include b as local.
inFunction("var a,b; a += (b = (a = 1))", "var a,b; a + 1");
inFunction("var a,b; a += (b = (a *= 2))", "var a,b; a + (a * 2)");
inFunction("var a,b; a += (b = (a++))", "var a,b; a + a++");
inFunction("var a,b; a += (b = (++a))", "var a,b; a+(++a)");
}
public void testIncrementalReassignmentInForLoops() {
inFunction("for(;x+=1;x+=1) {}");
inFunction("for(;x;x+=1){}");
inFunction("for(;x+=1;){foo(x)}");
inFunction("for(;1;x+=1){foo(x)}");
}
public void testIdentityAssignments() {
inFunction("var x; x=x", "var x; x");
}
private void inFunction(String src) {
inFunction(src, src);
}
private void inFunction(String src, String expected) {
test("function FUNC(param1, param2){" + src + "}",
"function FUNC(param1, param2){" + expected + "}");
}
public void testBug8730257() {
inFunction(
" try {" +
" var sortIndices = {};" +
" sortIndices = bar();" +
" for (var i = 0; i < 100; i++) {" +
" var sortIndex = sortIndices[i];" +
" bar(sortIndex);" +
" }" +
" } finally {" +
" bar();" +
" }" );
}
public void testAssignToExtern() {
inFunction("extern = true;");
}
public void testIssue297a() {
testSame("function f(p) {" +
" var x;" +
" return ((x=p.id) && (x=parseInt(x.substr(1))) && x>0);" +
"}; f('');");
}
public void testIssue297b() {
test("function f() {" +
" var x;" +
" return (x='') && (x = x.substr(1));" +
"};",
"function f() {" +
" var x;" +
" return (x='') && (x.substr(1));" +
"};");
}
public void testIssue297c() {
test("function f() {" +
" var x;" +
" return (x=1) && (x = f(x));" +
"};",
"function f() {" +
" var x;" +
" return (x=1) && f(x);" +
"};");
}
public void testIssue297d() {
test("function f(a) {" +
" return (a=1) && (a = f(a));" +
"};",
"function f(a) {" +
" return (a=1) && (f(a));" +
"};");
}
public void testIssue297e() {
test("function f(a) {" +
" return (a=1) - (a = g(a));" +
"};",
"function f(a) {" +
" return (a=1) - (g(a));" +
"};");
}
public void testIssue297f() {
test("function f(a) {" +
" h((a=1) - (a = g(a)));" +
"};",
"function f(a) {" +
" h((a=1) - (g(a)));" +
"};");
}
public void testIssue297g() {
test("function f(a) {" +
" var b = h((b=1) - (b = g(b)));" +
" return b;" +
"};",
// The last assignment in the initializer should be eliminated
"function f(a) {" +
" var b = h((b=1) - (b = g(b)));" +
" return b;" +
"};");
}
public void testIssue297h() {
test("function f(a) {" +
" var b = b=1;" +
" return b;" +
"};",
// The assignment in the initializer should be eliminated
"function f(a) {" +
" var b = b = 1;" +
" return b;" +
"};");
}
public void testInExpression1() {
inFunction("var a; return a=(a=(a=3));", "var a; return 3;");
inFunction("var a; return a=(a=(a=a));", "var a; return a;");
inFunction("var a; return a=(a=(a=a+1)+1);", "var a; return a+1+1;");
inFunction("var a; return a=(a=(a=f(a)+1)+1);", "var a; return f(a)+1+1;");
inFunction("var a; return a=f(a=f(a=f(a)));", "var a; return f(f(f(a)));");
}
public void testInExpression2() {
// This can be improved. "a = 1" is dead but "a" is read in the following
// expression.
inFunction(
"var a; a = 1; if ((a = 2) || (a = 3) || (a)) {}",
"var a; a = 1; if (( 2) || (a = 3) || (a)) {}");
inFunction(
"var a; (a = 1) || (a = 2)",
"var a; 1 || 2");
inFunction("var a; (a = 1) || (a = 2); return a");
inFunction(
"var a; a = 1; a ? a = 2 : a;",
"var a; a = 1; a ? 2 : a;");
inFunction("var a; a = 1; a ? a = 2 : a; return a");
inFunction(
"var a; a = 1; a ? a : a = 2;",
"var a; a = 1; a ? a : 2;");
inFunction("var a; a = 1; a ? a : a =2; return a");
inFunction(
"var a; (a = 1) ? a = 2 : a = 3;",
"var a; 1 ? 2 : 3;");
// This can be improved. "a = 1" is dead but "a" is read in the following
// expression.
inFunction("var a; (a = 1) ? a = 2 : a = 3; return a");
}
public void testIssue384a() {
inFunction(
" var a, b;\n" +
" if (f(b = true) || f(b = false))\n" +
" a = b;\n" +
" else\n" +
" a = null;\n" +
" return a;");
}
public void testIssue384b() {
inFunction(
" var a, b;\n" +
" (f(b = true) || f(b = false)) ? (a = b) : (a = null);\n" +
" return a;");
}
public void testIssue384c() {
inFunction(
" var a, b;\n" +
" (a ? f(b = true) : f(b = false)) && (a = b);\n" +
" return a;");
}
public void testIssue384d() {
inFunction(
" var a, b;\n" +
" (f(b = true) || f(b = false)) && (a = b);\n" +
" return a;");
}
public void testForIn() {
inFunction("var x = {}; for (var y in x) { y() }");
inFunction("var x, y, z; x = {}; z = {}; for (y in x = z) { y() }",
"var x, y, z; ({}); z = {}; for (y in z) { y() }");
inFunction("var x, y, z; x = {}; z = {}; for (y[z=1] in z) { y() }",
"var x, y, z; ({}); z = {}; for (y[z=1] in z) { y() }");
// "x in z" doesn't overwrite x if z is empty.
// TODO(user): If you look outside of just liveness, x = {} is dead.
// That probably requires value numbering or SSA to detect that case.
inFunction("var x, y, z; x = {}; z = {}; for (x in z) { x() }");
}
}