PageRenderTime 44ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/dev/core/test/com/google/gwt/dev/jjs/impl/gflow/cfg/CfgBuilderTest.java

https://github.com/gkamal/scalagwt-gwt
Java | 1397 lines | 1319 code | 75 blank | 3 comment | 4 complexity | d275fb7cc3e80c95a7d4c36334e58b93 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0
  1. package com.google.gwt.dev.jjs.impl.gflow.cfg;
  2. import com.google.gwt.core.ext.UnableToCompleteException;
  3. import com.google.gwt.dev.jjs.ast.JMethodBody;
  4. import com.google.gwt.dev.jjs.ast.JProgram;
  5. import com.google.gwt.dev.jjs.impl.OptimizerTestBase;
  6. import com.google.gwt.dev.jjs.impl.gflow.cfg.CfgBuilder;
  7. import com.google.gwt.dev.jjs.impl.gflow.cfg.CfgEdge;
  8. import com.google.gwt.dev.jjs.impl.gflow.cfg.Cfg;
  9. import com.google.gwt.dev.jjs.impl.gflow.cfg.CfgNode;
  10. import com.google.gwt.dev.util.Strings;
  11. import java.util.List;
  12. /**
  13. * Test class for CfgBuilfer.
  14. */
  15. public class CfgBuilderTest extends OptimizerTestBase {
  16. @Override
  17. protected void setUp() throws Exception {
  18. super.setUp();
  19. addSnippetClassDecl("static boolean b;");
  20. addSnippetClassDecl("static boolean b1;");
  21. addSnippetClassDecl("static boolean b2;");
  22. addSnippetClassDecl("static boolean b3;");
  23. addSnippetClassDecl("static int i;");
  24. addSnippetClassDecl("static int j;");
  25. addSnippetClassDecl("static int k;");
  26. addSnippetClassDecl("static int l;");
  27. addSnippetClassDecl("static int m;");
  28. addSnippetClassDecl("static class CheckedException extends Exception {}");
  29. addSnippetClassDecl(
  30. "static class UncheckedException1 extends RuntimeException {}");
  31. addSnippetClassDecl(
  32. "static class UncheckedException2 extends RuntimeException {}");
  33. addSnippetClassDecl("static RuntimeException runtimeException;");
  34. addSnippetClassDecl("static CheckedException checkedException;");
  35. addSnippetClassDecl("static UncheckedException1 uncheckedException1;");
  36. addSnippetClassDecl("static UncheckedException2 uncheckedException2;");
  37. addSnippetClassDecl("static int[] ii;");
  38. addSnippetClassDecl("static int[] jj;");
  39. addSnippetClassDecl("static void throwCheckedException() " +
  40. "throws CheckedException {}");
  41. addSnippetClassDecl("static void throwUncheckedException() {}");
  42. addSnippetClassDecl("static void throwSeveralExceptions() " +
  43. "throws CheckedException, UncheckedException1 {}");
  44. addSnippetClassDecl("static class Foo { int i; int j; int k; }");
  45. addSnippetClassDecl("static Foo createFoo() {return null;}");
  46. }
  47. public void testConstantAssignment() throws Exception {
  48. assertCfg("void", "i = 1;").is(
  49. "BLOCK -> [*]",
  50. "STMT -> [*]",
  51. "WRITE(i, 1) -> [*]",
  52. "END");
  53. }
  54. public void testReferenceAssignment() throws Exception {
  55. assertCfg("void", "i = j;").is(
  56. "BLOCK -> [*]",
  57. "STMT -> [*]",
  58. "READ(j) -> [*]",
  59. "WRITE(i, EntryPoint.j) -> [*]",
  60. "END");
  61. }
  62. public void testModAssignment() throws Exception {
  63. assertCfg("void", "i += 1;").is(
  64. "BLOCK -> [*]",
  65. "STMT -> [*]",
  66. "READWRITE(i, null) -> [*]",
  67. "END");
  68. }
  69. public void testDeclarationWithInitializer() throws Exception {
  70. assertCfg("void", "int i = 1;").is(
  71. "BLOCK -> [*]",
  72. "STMT -> [*]",
  73. "WRITE(i, 1) -> [*]",
  74. "END");
  75. }
  76. public void testDeclarationWithInitializerRead() throws Exception {
  77. assertCfg("void", "int i = j + k;").is(
  78. "BLOCK -> [*]",
  79. "STMT -> [*]",
  80. "READ(j) -> [*]",
  81. "READ(k) -> [*]",
  82. "WRITE(i, EntryPoint.j + EntryPoint.k) -> [*]",
  83. "END");
  84. }
  85. public void testDeclarationWithoutInitializer() throws Exception {
  86. assertCfg("void", "int i;").is(
  87. "BLOCK -> [*]",
  88. "STMT -> [*]",
  89. "END");
  90. }
  91. public void testBinopAssignment() throws Exception {
  92. assertCfg("void", "i = j + k;").is(
  93. "BLOCK -> [*]",
  94. "STMT -> [*]",
  95. "READ(j) -> [*]",
  96. "READ(k) -> [*]",
  97. "WRITE(i, EntryPoint.j + EntryPoint.k) -> [*]",
  98. "END");
  99. }
  100. public void testPostIncrement() throws Exception {
  101. assertCfg("void", "i++;").is(
  102. "BLOCK -> [*]",
  103. "STMT -> [*]",
  104. "READWRITE(i, null) -> [*]",
  105. "END");
  106. }
  107. public void testPreIncrement() throws Exception {
  108. assertCfg("void", "++i;").is(
  109. "BLOCK -> [*]",
  110. "STMT -> [*]",
  111. "READWRITE(i, null) -> [*]",
  112. "END");
  113. }
  114. public void testConditional() throws Exception {
  115. assertCfg("void", "i = b1 ? j : k;").is(
  116. "BLOCK -> [*]",
  117. "STMT -> [*]",
  118. "READ(b1) -> [*]",
  119. "COND (EntryPoint.b1) -> [THEN=*, ELSE=1]",
  120. "READ(j) -> [2]",
  121. "1: READ(k) -> [*]",
  122. "2: WRITE(i, EntryPoint.b1 ? EntryPoint.j : EntryPoint.k) -> [*]",
  123. "END");
  124. }
  125. public void testAnd() throws Exception {
  126. assertCfg("void", "b3 = b1 && b2;").is(
  127. "BLOCK -> [*]",
  128. "STMT -> [*]",
  129. "READ(b1) -> [*]",
  130. "COND (EntryPoint.b1) -> [THEN=*, ELSE=1]",
  131. "READ(b2) -> [*]",
  132. "1: WRITE(b3, EntryPoint.b1 && EntryPoint.b2) -> [*]",
  133. "END");
  134. }
  135. public void testOr() throws Exception {
  136. assertCfg("void", "b3 = b1 || b2;").is(
  137. "BLOCK -> [*]",
  138. "STMT -> [*]",
  139. "READ(b1) -> [*]",
  140. "COND (EntryPoint.b1) -> [ELSE=*, THEN=1]",
  141. "READ(b2) -> [*]",
  142. "1: WRITE(b3, EntryPoint.b1 || EntryPoint.b2) -> [*]",
  143. "END");
  144. }
  145. public void testMultipleExpressionStatements() throws Exception {
  146. assertCfg("void",
  147. "i = 1;",
  148. "j = 2;",
  149. "m = k = j;").is(
  150. "BLOCK -> [*]",
  151. "STMT -> [*]",
  152. "WRITE(i, 1) -> [*]",
  153. "STMT -> [*]",
  154. "WRITE(j, 2) -> [*]",
  155. "STMT -> [*]",
  156. "READ(j) -> [*]",
  157. "WRITE(k, EntryPoint.j) -> [*]",
  158. "WRITE(m, EntryPoint.k = EntryPoint.j) -> [*]",
  159. "END");
  160. }
  161. public void testIfStatement1() throws Exception {
  162. assertCfg("void",
  163. "if (i == 1) {",
  164. " j = 2;",
  165. "}",
  166. "k = j;").is(
  167. "BLOCK -> [*]",
  168. "STMT -> [*]",
  169. "READ(i) -> [*]",
  170. "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=1]",
  171. "BLOCK -> [*]",
  172. "STMT -> [*]",
  173. "WRITE(j, 2) -> [*]",
  174. "1: STMT -> [*]",
  175. "READ(j) -> [*]",
  176. "WRITE(k, EntryPoint.j) -> [*]",
  177. "END");
  178. }
  179. public void testIfStatement2() throws Exception {
  180. assertCfg("void",
  181. "if ((i = 1) == 2) {",
  182. " j = 2;",
  183. "} else {",
  184. " k = j;",
  185. "}").is(
  186. "BLOCK -> [*]",
  187. "STMT -> [*]",
  188. "WRITE(i, 1) -> [*]",
  189. "COND ((EntryPoint.i = 1) == 2) -> [THEN=*, ELSE=1]",
  190. "BLOCK -> [*]",
  191. "STMT -> [*]",
  192. "WRITE(j, 2) -> [2]",
  193. "1: BLOCK -> [*]",
  194. "STMT -> [*]",
  195. "READ(j) -> [*]",
  196. "WRITE(k, EntryPoint.j) -> [*]",
  197. "2: END");
  198. }
  199. public void testIfStatement3() throws Exception {
  200. assertCfg("void", "if (b1 || b2) {j = 2;}").is(
  201. "BLOCK -> [*]",
  202. "STMT -> [*]",
  203. "READ(b1) -> [*]",
  204. "COND (EntryPoint.b1) -> [ELSE=*, THEN=1]",
  205. "READ(b2) -> [*]",
  206. "1: COND (EntryPoint.b1 || EntryPoint.b2) -> [THEN=*, ELSE=2]",
  207. "BLOCK -> [*]",
  208. "STMT -> [*]",
  209. "WRITE(j, 2) -> [*]",
  210. "2: END");
  211. }
  212. public void testWhileStatement() throws Exception {
  213. assertCfg("void", "while (i == 1) {j = 2;} k = j;").is(
  214. "BLOCK -> [*]",
  215. "STMT -> [*]",
  216. "1: READ(i) -> [*]",
  217. "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=2]",
  218. "BLOCK -> [*]",
  219. "STMT -> [*]",
  220. "WRITE(j, 2) -> [1]",
  221. "2: STMT -> [*]",
  222. "READ(j) -> [*]",
  223. "WRITE(k, EntryPoint.j) -> [*]",
  224. "END");
  225. }
  226. public void testDoStatement() throws Exception {
  227. assertCfg("void", "do { j = 2; } while (i == 1);").is(
  228. "BLOCK -> [*]",
  229. "STMT -> [*]",
  230. "1: BLOCK -> [*]",
  231. "STMT -> [*]",
  232. "WRITE(j, 2) -> [*]",
  233. "READ(i) -> [*]",
  234. "COND (EntryPoint.i == 1) -> [THEN=1, ELSE=*]",
  235. "END");
  236. }
  237. public void testReturn1() throws Exception {
  238. assertCfg("void", "return;").is(
  239. "BLOCK -> [*]",
  240. "STMT -> [*]",
  241. "GOTO -> [*]",
  242. "END");
  243. }
  244. public void testReturn2() throws Exception {
  245. assertCfg("boolean", "i = 1; return i == 2;").is(
  246. "BLOCK -> [*]",
  247. "STMT -> [*]",
  248. "WRITE(i, 1) -> [*]",
  249. "STMT -> [*]",
  250. "READ(i) -> [*]",
  251. "GOTO -> [*]",
  252. "END");
  253. }
  254. public void testReturn3() throws Exception {
  255. assertCfg("boolean",
  256. "i = 1;",
  257. "if (i == 1) {",
  258. " i = 2;",
  259. " return true;",
  260. "} else {",
  261. " i = 3;",
  262. " return false;",
  263. "}").is(
  264. "BLOCK -> [*]",
  265. "STMT -> [*]",
  266. "WRITE(i, 1) -> [*]",
  267. "STMT -> [*]",
  268. "READ(i) -> [*]",
  269. "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=1]",
  270. "BLOCK -> [*]",
  271. "STMT -> [*]",
  272. "WRITE(i, 2) -> [*]",
  273. "STMT -> [*]",
  274. "GOTO -> [2]",
  275. "1: BLOCK -> [*]",
  276. "STMT -> [*]",
  277. "WRITE(i, 3) -> [*]",
  278. "STMT -> [*]",
  279. "GOTO -> [*]",
  280. "2: END");
  281. }
  282. public void testForStatement() throws Exception {
  283. assertCfg("int",
  284. "int j = 0;",
  285. "for (int i = 0; i < 10; ++i) { j++; }",
  286. "return j;").is(
  287. "BLOCK -> [*]",
  288. "STMT -> [*]",
  289. "WRITE(j, 0) -> [*]",
  290. "STMT -> [*]",
  291. "STMT -> [*]",
  292. "WRITE(i, 0) -> [*]",
  293. "1: READ(i) -> [*]",
  294. "COND (i < 10) -> [THEN=*, ELSE=2]",
  295. "BLOCK -> [*]",
  296. "STMT -> [*]",
  297. "READWRITE(j, null) -> [*]",
  298. "STMT -> [*]",
  299. "READWRITE(i, null) -> [1]",
  300. "2: STMT -> [*]",
  301. "READ(j) -> [*]",
  302. "GOTO -> [*]",
  303. "END");
  304. }
  305. public void testEmptyForStatement() throws Exception {
  306. assertCfg("void",
  307. "for (;;) { j++; }").is(
  308. "BLOCK -> [*]",
  309. "STMT -> [*]",
  310. "1: BLOCK -> [*]",
  311. "STMT -> [*]",
  312. "READWRITE(j, null) -> [1]",
  313. "END");
  314. }
  315. public void testThrowWithoutCatch1() throws Exception {
  316. assertCfg("void", "throw runtimeException;").is(
  317. "BLOCK -> [*]",
  318. "STMT -> [*]",
  319. "READ(runtimeException) -> [*]",
  320. "THROW -> [*]",
  321. "END");
  322. }
  323. public void testThrowWithoutCatch2() throws Exception {
  324. assertCfg("void", "if (b1) { throw runtimeException; } b1 = true;").is(
  325. "BLOCK -> [*]",
  326. "STMT -> [*]",
  327. "READ(b1) -> [*]",
  328. "COND (EntryPoint.b1) -> [THEN=*, ELSE=1]",
  329. "BLOCK -> [*]",
  330. "STMT -> [*]",
  331. "READ(runtimeException) -> [*]",
  332. "THROW -> [2]",
  333. "1: STMT -> [*]",
  334. "WRITE(b1, true) -> [*]",
  335. "2: END"
  336. );
  337. }
  338. public void testWhileContinueNoLabel() throws Exception {
  339. assertCfg("void", "while (b1) { if (b2) { continue; } i++; }").is(
  340. "BLOCK -> [*]",
  341. "STMT -> [*]",
  342. "1: READ(b1) -> [*]",
  343. "COND (EntryPoint.b1) -> [THEN=*, ELSE=3]",
  344. "BLOCK -> [*]",
  345. "STMT -> [*]",
  346. "READ(b2) -> [*]",
  347. "COND (EntryPoint.b2) -> [THEN=*, ELSE=2]",
  348. "BLOCK -> [*]",
  349. "STMT -> [*]",
  350. "GOTO -> [1]",
  351. "2: STMT -> [*]",
  352. "READWRITE(i, null) -> [1]",
  353. "3: END");
  354. }
  355. public void testWhileContinueWithLabel1() throws Exception {
  356. assertCfg("void",
  357. "nextLoop: while(b3)",
  358. " while (b1) {",
  359. " if (b2) { continue; }",
  360. " i++;" +
  361. " }").is(
  362. "BLOCK -> [*]",
  363. "STMT -> [*]",
  364. "1: READ(b3) -> [*]",
  365. "COND (EntryPoint.b3) -> [THEN=*, ELSE=4]",
  366. "STMT -> [*]",
  367. "2: READ(b1) -> [*]",
  368. "COND (EntryPoint.b1) -> [THEN=*, ELSE=1]",
  369. "BLOCK -> [*]",
  370. "STMT -> [*]",
  371. "READ(b2) -> [*]",
  372. "COND (EntryPoint.b2) -> [THEN=*, ELSE=3]",
  373. "BLOCK -> [*]",
  374. "STMT -> [*]",
  375. "GOTO -> [2]",
  376. "3: STMT -> [*]",
  377. "READWRITE(i, null) -> [2]",
  378. "4: END");
  379. }
  380. public void testWhileContinueWithLabel2() throws Exception {
  381. assertCfg("void",
  382. "nextLoop: while(b3)",
  383. " while (b1) {",
  384. " if (b2) { continue nextLoop; }",
  385. " i++;",
  386. " }").is(
  387. "BLOCK -> [*]",
  388. "STMT -> [*]",
  389. "1: READ(b3) -> [*]",
  390. "COND (EntryPoint.b3) -> [THEN=*, ELSE=4]",
  391. "STMT -> [*]",
  392. "2: READ(b1) -> [*]",
  393. "COND (EntryPoint.b1) -> [THEN=*, ELSE=1]",
  394. "BLOCK -> [*]",
  395. "STMT -> [*]",
  396. "READ(b2) -> [*]",
  397. "COND (EntryPoint.b2) -> [THEN=*, ELSE=3]",
  398. "BLOCK -> [*]",
  399. "STMT -> [*]",
  400. "GOTO -> [1]",
  401. "3: STMT -> [*]",
  402. "READWRITE(i, null) -> [2]",
  403. "4: END");
  404. }
  405. public void testWhileContinueWithLabel3() throws Exception {
  406. assertCfg("void",
  407. "nextLoop: while (b1) {",
  408. " if (b2) { continue; }",
  409. " i++;",
  410. "}").is(
  411. "BLOCK -> [*]",
  412. "STMT -> [*]",
  413. "1: READ(b1) -> [*]",
  414. "COND (EntryPoint.b1) -> [THEN=*, ELSE=3]",
  415. "BLOCK -> [*]",
  416. "STMT -> [*]",
  417. "READ(b2) -> [*]",
  418. "COND (EntryPoint.b2) -> [THEN=*, ELSE=2]",
  419. "BLOCK -> [*]",
  420. "STMT -> [*]",
  421. "GOTO -> [1]",
  422. "2: STMT -> [*]",
  423. "READWRITE(i, null) -> [1]",
  424. "3: END");
  425. }
  426. public void testWhileBreakNoLabel() throws Exception {
  427. assertCfg("void", "while (b1) { if (b2) { break; } i++; }").is(
  428. "BLOCK -> [*]",
  429. "STMT -> [*]",
  430. "1: READ(b1) -> [*]",
  431. "COND (EntryPoint.b1) -> [THEN=*, ELSE=3]",
  432. "BLOCK -> [*]",
  433. "STMT -> [*]",
  434. "READ(b2) -> [*]",
  435. "COND (EntryPoint.b2) -> [THEN=*, ELSE=2]",
  436. "BLOCK -> [*]",
  437. "STMT -> [*]",
  438. "GOTO -> [3]",
  439. "2: STMT -> [*]",
  440. "READWRITE(i, null) -> [1]",
  441. "3: END");
  442. }
  443. public void testWhileBreakWithLabel1() throws Exception {
  444. assertCfg("void",
  445. "nextLoop: while(b3)",
  446. " while (b1) {",
  447. " if (b2) { break; }",
  448. " i++;",
  449. " }").is(
  450. "BLOCK -> [*]",
  451. "STMT -> [*]",
  452. "1: READ(b3) -> [*]",
  453. "COND (EntryPoint.b3) -> [THEN=*, ELSE=4]",
  454. "STMT -> [*]",
  455. "2: READ(b1) -> [*]",
  456. "COND (EntryPoint.b1) -> [THEN=*, ELSE=1]",
  457. "BLOCK -> [*]",
  458. "STMT -> [*]",
  459. "READ(b2) -> [*]",
  460. "COND (EntryPoint.b2) -> [THEN=*, ELSE=3]",
  461. "BLOCK -> [*]",
  462. "STMT -> [*]",
  463. "GOTO -> [1]",
  464. "3: STMT -> [*]",
  465. "READWRITE(i, null) -> [2]",
  466. "4: END");
  467. }
  468. public void testWhileBreakWithLabel2() throws Exception {
  469. assertCfg("void",
  470. "nextLoop: while(b3)",
  471. " while (b1) {",
  472. " if (b2) { break nextLoop; }",
  473. " i++;",
  474. " }").is(
  475. "BLOCK -> [*]",
  476. "STMT -> [*]",
  477. "1: READ(b3) -> [*]",
  478. "COND (EntryPoint.b3) -> [THEN=*, ELSE=4]",
  479. "STMT -> [*]",
  480. "2: READ(b1) -> [*]",
  481. "COND (EntryPoint.b1) -> [THEN=*, ELSE=1]",
  482. "BLOCK -> [*]",
  483. "STMT -> [*]",
  484. "READ(b2) -> [*]",
  485. "COND (EntryPoint.b2) -> [THEN=*, ELSE=3]",
  486. "BLOCK -> [*]",
  487. "STMT -> [*]",
  488. "GOTO -> [4]",
  489. "3: STMT -> [*]",
  490. "READWRITE(i, null) -> [2]",
  491. "4: END");
  492. }
  493. public void testWhileBreakWithLabel3() throws Exception {
  494. assertCfg("void",
  495. "nextLoop: while (b1) { if (b2) { break; } i++; }").is(
  496. "BLOCK -> [*]",
  497. "STMT -> [*]",
  498. "1: READ(b1) -> [*]",
  499. "COND (EntryPoint.b1) -> [THEN=*, ELSE=3]",
  500. "BLOCK -> [*]",
  501. "STMT -> [*]",
  502. "READ(b2) -> [*]",
  503. "COND (EntryPoint.b2) -> [THEN=*, ELSE=2]",
  504. "BLOCK -> [*]",
  505. "STMT -> [*]",
  506. "GOTO -> [3]",
  507. "2: STMT -> [*]",
  508. "READWRITE(i, null) -> [1]",
  509. "3: END");
  510. }
  511. public void testForContinueNoLabel() throws Exception {
  512. assertCfg("void",
  513. "for(int i = 0; i < 10; i++) { if (b2) { continue; } i++; }").is(
  514. "BLOCK -> [*]",
  515. "STMT -> [*]",
  516. "STMT -> [*]",
  517. "WRITE(i, 0) -> [*]",
  518. "1: READ(i) -> [*]",
  519. "COND (i < 10) -> [THEN=*, ELSE=4]",
  520. "BLOCK -> [*]",
  521. "STMT -> [*]",
  522. "READ(b2) -> [*]",
  523. "COND (EntryPoint.b2) -> [THEN=*, ELSE=2]",
  524. "BLOCK -> [*]",
  525. "STMT -> [*]",
  526. "GOTO -> [3]",
  527. "2: STMT -> [*]",
  528. "READWRITE(i, null) -> [*]",
  529. "3: STMT -> [*]",
  530. "READWRITE(i, null) -> [1]",
  531. "4: END");
  532. }
  533. public void testCatchThrowException1() throws Exception {
  534. assertCfg("void",
  535. "try {",
  536. " if (b) throw checkedException;",
  537. " k++;",
  538. "} catch (CheckedException e) {",
  539. " i++;",
  540. "}",
  541. "j++;").is(
  542. "BLOCK -> [*]",
  543. "TRY -> [*]",
  544. "BLOCK -> [*]",
  545. "STMT -> [*]",
  546. "READ(b) -> [*]",
  547. "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
  548. "STMT -> [*]",
  549. "READ(checkedException) -> [*]",
  550. "THROW -> [2]",
  551. "1: STMT -> [*]",
  552. "READWRITE(k, null) -> [3]",
  553. "2: BLOCK -> [*]",
  554. "STMT -> [*]",
  555. "READWRITE(i, null) -> [*]",
  556. "3: STMT -> [*]",
  557. "READWRITE(j, null) -> [*]",
  558. "END"
  559. );
  560. }
  561. public void testCatchThrowUncatchedException() throws Exception {
  562. assertCfg("void",
  563. "try {",
  564. " if (b) throw uncheckedException2;",
  565. " k++;",
  566. "} catch (UncheckedException1 e) {",
  567. " i++;",
  568. "}",
  569. "j++;").is(
  570. "BLOCK -> [*]",
  571. "TRY -> [*]",
  572. "BLOCK -> [*]",
  573. "STMT -> [*]",
  574. "READ(b) -> [*]",
  575. "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
  576. "STMT -> [*]",
  577. "READ(uncheckedException2) -> [*]",
  578. "THROW -> [3]",
  579. "1: STMT -> [*]",
  580. "READWRITE(k, null) -> [2]",
  581. "BLOCK -> [*]",
  582. "STMT -> [*]",
  583. "READWRITE(i, null) -> [*]",
  584. "2: STMT -> [*]",
  585. "READWRITE(j, null) -> [*]",
  586. "3: END"
  587. );
  588. }
  589. public void testCatchThrowSupertype() throws Exception {
  590. assertCfg("void",
  591. "try {",
  592. " if (b) throw runtimeException;",
  593. " k++;",
  594. "} catch (UncheckedException1 e) {",
  595. " i++;",
  596. "}",
  597. "j++;").is(
  598. "BLOCK -> [*]",
  599. "TRY -> [*]",
  600. "BLOCK -> [*]",
  601. "STMT -> [*]",
  602. "READ(b) -> [*]",
  603. "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
  604. "STMT -> [*]",
  605. "READ(runtimeException) -> [*]",
  606. "THROW -> [2, 4]",
  607. "1: STMT -> [*]",
  608. "READWRITE(k, null) -> [3]",
  609. "2: BLOCK -> [*]",
  610. "STMT -> [*]",
  611. "READWRITE(i, null) -> [*]",
  612. "3: STMT -> [*]",
  613. "READWRITE(j, null) -> [*]",
  614. "4: END"
  615. );
  616. }
  617. public void testCatchSupertype() throws Exception {
  618. assertCfg("void",
  619. "try {",
  620. " if (b) throw uncheckedException1;",
  621. " k++;",
  622. "} catch (RuntimeException e) {",
  623. " i++;",
  624. "}",
  625. "j++;").is(
  626. "BLOCK -> [*]",
  627. "TRY -> [*]",
  628. "BLOCK -> [*]",
  629. "STMT -> [*]",
  630. "READ(b) -> [*]",
  631. "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
  632. "STMT -> [*]",
  633. "READ(uncheckedException1) -> [*]",
  634. "THROW -> [2]",
  635. "1: STMT -> [*]",
  636. "READWRITE(k, null) -> [3]",
  637. "2: BLOCK -> [*]",
  638. "STMT -> [*]",
  639. "READWRITE(i, null) -> [*]",
  640. "3: STMT -> [*]",
  641. "READWRITE(j, null) -> [*]",
  642. "END"
  643. );
  644. }
  645. public void testCatchReturn() throws Exception {
  646. assertCfg("void",
  647. "try { try {",
  648. " if (b) return;",
  649. " k++;",
  650. "} catch (RuntimeException e) {",
  651. " i++;",
  652. "} } catch (UncheckedException1 e) { j++; }").is(
  653. "BLOCK -> [*]",
  654. "TRY -> [*]",
  655. "BLOCK -> [*]",
  656. "TRY -> [*]",
  657. "BLOCK -> [*]",
  658. "STMT -> [*]",
  659. "READ(b) -> [*]",
  660. "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
  661. "STMT -> [*]",
  662. "GOTO -> [2]",
  663. "1: STMT -> [*]",
  664. "READWRITE(k, null) -> [2]",
  665. "BLOCK -> [*]",
  666. "STMT -> [*]",
  667. "READWRITE(i, null) -> [2]",
  668. "BLOCK -> [*]",
  669. "STMT -> [*]",
  670. "READWRITE(j, null) -> [*]",
  671. "2: END"
  672. );
  673. }
  674. public void testRethrow() throws Exception {
  675. assertCfg("void",
  676. "try {",
  677. " if (b) throw uncheckedException1;",
  678. " k++;",
  679. "} catch (UncheckedException1 e) {",
  680. " i++;",
  681. " throw e;",
  682. "}",
  683. "j++;").is(
  684. "BLOCK -> [*]",
  685. "TRY -> [*]",
  686. "BLOCK -> [*]",
  687. "STMT -> [*]",
  688. "READ(b) -> [*]",
  689. "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
  690. "STMT -> [*]",
  691. "READ(uncheckedException1) -> [*]",
  692. "THROW -> [2]",
  693. "1: STMT -> [*]",
  694. "READWRITE(k, null) -> [3]",
  695. "2: BLOCK -> [*]",
  696. "STMT -> [*]",
  697. "READWRITE(i, null) -> [*]",
  698. "STMT -> [*]",
  699. "READ(e) -> [*]",
  700. "THROW -> [4]",
  701. "3: STMT -> [*]",
  702. "READWRITE(j, null) -> [*]",
  703. "4: END"
  704. );
  705. }
  706. public void testCatchMethodCall1() throws Exception {
  707. assertCfg("void",
  708. "try {",
  709. " if (b) throwCheckedException();",
  710. " k++;",
  711. "} catch (CheckedException e) {",
  712. " i++;",
  713. "}",
  714. "j++;").is(
  715. "BLOCK -> [*]",
  716. "TRY -> [*]",
  717. "BLOCK -> [*]",
  718. "STMT -> [*]",
  719. "READ(b) -> [*]",
  720. "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
  721. "STMT -> [*]",
  722. "OPTTHROW(throwCheckedException()) -> [NOTHROW=*, 2, RE=4]",
  723. "CALL(throwCheckedException) -> [*]",
  724. "1: STMT -> [*]",
  725. "READWRITE(k, null) -> [3]",
  726. "2: BLOCK -> [*]",
  727. "STMT -> [*]",
  728. "READWRITE(i, null) -> [*]",
  729. "3: STMT -> [*]",
  730. "READWRITE(j, null) -> [*]",
  731. "4: END"
  732. );
  733. }
  734. public void testCatchMethodCall2() throws Exception {
  735. assertCfg("void",
  736. "try {",
  737. " if (b) throwCheckedException();",
  738. " k++;",
  739. "} catch (CheckedException e) {",
  740. " i++;",
  741. "} catch (RuntimeException e) {",
  742. " l++;",
  743. "}",
  744. "j++;").is(
  745. "BLOCK -> [*]",
  746. "TRY -> [*]",
  747. "BLOCK -> [*]",
  748. "STMT -> [*]",
  749. "READ(b) -> [*]",
  750. "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
  751. "STMT -> [*]",
  752. "OPTTHROW(throwCheckedException()) -> [NOTHROW=*, 2, RE=3]",
  753. "CALL(throwCheckedException) -> [*]",
  754. "1: STMT -> [*]",
  755. "READWRITE(k, null) -> [4]",
  756. "2: BLOCK -> [*]",
  757. "STMT -> [*]",
  758. "READWRITE(i, null) -> [4]",
  759. "3: BLOCK -> [*]",
  760. "STMT -> [*]",
  761. "READWRITE(l, null) -> [*]",
  762. "4: STMT -> [*]",
  763. "READWRITE(j, null) -> [*]",
  764. "END"
  765. );
  766. }
  767. public void testCatchMethodCallUnchecked() throws Exception {
  768. assertCfg("void",
  769. "try {",
  770. " if (b) throwUncheckedException();",
  771. " k++;",
  772. "} catch (UncheckedException1 e) {",
  773. " i++;",
  774. "} catch (RuntimeException e) {",
  775. " l++;",
  776. "}",
  777. "j++;").is(
  778. "BLOCK -> [*]",
  779. "TRY -> [*]",
  780. "BLOCK -> [*]",
  781. "STMT -> [*]",
  782. "READ(b) -> [*]",
  783. "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
  784. "STMT -> [*]",
  785. "OPTTHROW(throwUncheckedException()) -> [NOTHROW=*, RE=2, RE=3]",
  786. "CALL(throwUncheckedException) -> [*]",
  787. "1: STMT -> [*]",
  788. "READWRITE(k, null) -> [4]",
  789. "2: BLOCK -> [*]",
  790. "STMT -> [*]",
  791. "READWRITE(i, null) -> [4]",
  792. "3: BLOCK -> [*]",
  793. "STMT -> [*]",
  794. "READWRITE(l, null) -> [*]",
  795. "4: STMT -> [*]",
  796. "READWRITE(j, null) -> [*]",
  797. "END"
  798. );
  799. }
  800. public void testFinallyReturn1() throws Exception {
  801. assertCfg("void",
  802. "try {",
  803. " if (b) return;",
  804. " j++;",
  805. "} finally {",
  806. " i++;",
  807. "}").is(
  808. "BLOCK -> [*]",
  809. "TRY -> [*]",
  810. "BLOCK -> [*]",
  811. "STMT -> [*]",
  812. "READ(b) -> [*]",
  813. "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
  814. "STMT -> [*]",
  815. "GOTO -> [2]",
  816. "1: STMT -> [*]",
  817. "READWRITE(j, null) -> [*]",
  818. "2: BLOCK -> [*]",
  819. "STMT -> [*]",
  820. "READWRITE(i, null) -> [*, *]",
  821. "END"
  822. );
  823. }
  824. public void testThrowFromFinally() throws Exception {
  825. assertCfg("void",
  826. "try {",
  827. " return;",
  828. "} finally {",
  829. " throw runtimeException;",
  830. "}").is(
  831. "BLOCK -> [*]",
  832. "TRY -> [*]",
  833. "BLOCK -> [*]",
  834. "STMT -> [*]",
  835. "GOTO -> [*]",
  836. "BLOCK -> [*]",
  837. "STMT -> [*]",
  838. "READ(runtimeException) -> [*]",
  839. "THROW -> [*]",
  840. "END"
  841. );
  842. }
  843. public void testFinallyReturn2() throws Exception {
  844. assertCfg("void",
  845. "try {",
  846. " return;",
  847. "} finally {",
  848. " i++;",
  849. "}").is(
  850. "BLOCK -> [*]",
  851. "TRY -> [*]",
  852. "BLOCK -> [*]",
  853. "STMT -> [*]",
  854. "GOTO -> [*]",
  855. "BLOCK -> [*]",
  856. "STMT -> [*]",
  857. "READWRITE(i, null) -> [*, *]",
  858. "END"
  859. );
  860. }
  861. public void testFinallyReturn3() throws Exception {
  862. assertCfg("void",
  863. "try {",
  864. "try {",
  865. " if (b) return;",
  866. " k++;",
  867. "} finally {",
  868. " i++;",
  869. "} m++; } finally {",
  870. " j++;",
  871. "}").is(
  872. "BLOCK -> [*]",
  873. "TRY -> [*]",
  874. "BLOCK -> [*]",
  875. "TRY -> [*]",
  876. "BLOCK -> [*]",
  877. "STMT -> [*]",
  878. "READ(b) -> [*]",
  879. "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
  880. "STMT -> [*]",
  881. "GOTO -> [2]",
  882. "1: STMT -> [*]",
  883. "READWRITE(k, null) -> [*]",
  884. "2: BLOCK -> [*]",
  885. "STMT -> [*]",
  886. "READWRITE(i, null) -> [*, 3]",
  887. "STMT -> [*]",
  888. "READWRITE(m, null) -> [*]",
  889. "3: BLOCK -> [*]",
  890. "STMT -> [*]",
  891. "READWRITE(j, null) -> [*, *]",
  892. "END"
  893. );
  894. }
  895. public void testFinallyContinue() throws Exception {
  896. assertCfg("void",
  897. "while (b) {",
  898. "try {",
  899. " if (b) continue;",
  900. "} finally {",
  901. " i++;",
  902. "} j++; }").is(
  903. "BLOCK -> [*]",
  904. "STMT -> [*]",
  905. "1: READ(b) -> [*]",
  906. "COND (EntryPoint.b) -> [THEN=*, ELSE=3]",
  907. "BLOCK -> [*]",
  908. "TRY -> [*]",
  909. "BLOCK -> [*]",
  910. "STMT -> [*]",
  911. "READ(b) -> [*]",
  912. "COND (EntryPoint.b) -> [THEN=*, ELSE=2]",
  913. "STMT -> [*]",
  914. "GOTO -> [*]",
  915. "2: BLOCK -> [*]",
  916. "STMT -> [*]",
  917. "READWRITE(i, null) -> [*, 1]",
  918. "STMT -> [*]",
  919. "READWRITE(j, null) -> [1]",
  920. "3: END"
  921. );
  922. }
  923. public void testCatchFinally() throws Exception {
  924. assertCfg("void",
  925. "try {",
  926. " if (b) throw checkedException;",
  927. " k++;",
  928. "} catch (CheckedException e) {",
  929. " i++;",
  930. "} finally {",
  931. " j++;",
  932. "}"
  933. ).is(
  934. "BLOCK -> [*]",
  935. "TRY -> [*]",
  936. "BLOCK -> [*]",
  937. "STMT -> [*]",
  938. "READ(b) -> [*]",
  939. "COND (EntryPoint.b) -> [THEN=*, ELSE=1]",
  940. "STMT -> [*]",
  941. "READ(checkedException) -> [*]",
  942. "THROW -> [2]",
  943. "1: STMT -> [*]",
  944. "READWRITE(k, null) -> [3]",
  945. "2: BLOCK -> [*]",
  946. "STMT -> [*]",
  947. "READWRITE(i, null) -> [*]",
  948. "3: BLOCK -> [*]",
  949. "STMT -> [*]",
  950. "READWRITE(j, null) -> [*]",
  951. "END"
  952. );
  953. }
  954. public void testFieldWrite() throws Exception {
  955. assertCfg("void",
  956. "Foo foo = createFoo();",
  957. "foo.i = 1;"
  958. ).is(
  959. "BLOCK -> [*]",
  960. "STMT -> [*]",
  961. "OPTTHROW(createFoo()) -> [NOTHROW=*, RE=1]",
  962. "CALL(createFoo) -> [*]",
  963. "WRITE(foo, EntryPoint.createFoo()) -> [*]",
  964. "STMT -> [*]",
  965. "READ(foo) -> [*]",
  966. "WRITE(i, 1) -> [*]",
  967. "1: END"
  968. );
  969. }
  970. public void testFieldUnary() throws Exception {
  971. assertCfg("void",
  972. "Foo foo = createFoo();",
  973. "++foo.i;"
  974. ).is(
  975. "BLOCK -> [*]",
  976. "STMT -> [*]",
  977. "OPTTHROW(createFoo()) -> [NOTHROW=*, RE=1]",
  978. "CALL(createFoo) -> [*]",
  979. "WRITE(foo, EntryPoint.createFoo()) -> [*]",
  980. "STMT -> [*]",
  981. "READ(foo) -> [*]",
  982. "READWRITE(i, null) -> [*]",
  983. "1: END"
  984. );
  985. }
  986. public void testArrayRead() throws Exception {
  987. assertCfg("void",
  988. "i = ii[j];"
  989. ).is(
  990. "BLOCK -> [*]",
  991. "STMT -> [*]",
  992. "READ(ii) -> [*]",
  993. "READ(j) -> [*]",
  994. "WRITE(i, EntryPoint.ii[EntryPoint.j]) -> [*]",
  995. "END"
  996. );
  997. }
  998. public void testArrayWrite() throws Exception {
  999. assertCfg("void",
  1000. "ii[i] = j;"
  1001. ).is(
  1002. "BLOCK -> [*]",
  1003. "STMT -> [*]",
  1004. "READ(j) -> [*]",
  1005. "READ(ii) -> [*]",
  1006. "READ(i) -> [*]",
  1007. "WRITE(EntryPoint.ii[EntryPoint.i], EntryPoint.j) -> [*]",
  1008. "END"
  1009. );
  1010. }
  1011. public void testArrayUnary() throws Exception {
  1012. assertCfg("void",
  1013. "++ii[i];"
  1014. ).is(
  1015. "BLOCK -> [*]",
  1016. "STMT -> [*]",
  1017. "READ(ii) -> [*]",
  1018. "READ(i) -> [*]",
  1019. "READWRITE(EntryPoint.ii[EntryPoint.i], null) -> [*]",
  1020. "END"
  1021. );
  1022. }
  1023. public void testSwitch() throws Exception {
  1024. assertCfg("void",
  1025. "switch(i) {",
  1026. " case 1: ",
  1027. " return;",
  1028. " case 2: ",
  1029. " case 3: ",
  1030. " j = 1;",
  1031. " break;",
  1032. " case 4: ",
  1033. " j = 2;",
  1034. " default:",
  1035. " j = 4;",
  1036. " case 5: ",
  1037. " j = 3;",
  1038. " break;",
  1039. "}"
  1040. ).is(
  1041. "BLOCK -> [*]",
  1042. "STMT -> [*]",
  1043. "READ(i) -> [*]",
  1044. "GOTO -> [*]",
  1045. "STMT -> [*]",
  1046. "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=1]",
  1047. "STMT -> [*]",
  1048. "GOTO -> [7]",
  1049. "1: STMT -> [*]",
  1050. "COND (EntryPoint.i == 2) -> [ELSE=*, THEN=2]",
  1051. "STMT -> [*]",
  1052. "COND (EntryPoint.i == 3) -> [THEN=*, ELSE=3]",
  1053. "2: STMT -> [*]",
  1054. "WRITE(j, 1) -> [*]",
  1055. "STMT -> [*]",
  1056. "GOTO -> [7]",
  1057. "3: STMT -> [*]",
  1058. "COND (EntryPoint.i == 4) -> [THEN=*, ELSE=5]",
  1059. "STMT -> [*]",
  1060. "WRITE(j, 2) -> [*]",
  1061. "4: STMT -> [*]",
  1062. "STMT -> [*]",
  1063. "WRITE(j, 4) -> [6]",
  1064. "5: STMT -> [*]",
  1065. "COND (EntryPoint.i == 5) -> [THEN=*, ELSE=4]",
  1066. "6: STMT -> [*]",
  1067. "WRITE(j, 3) -> [*]",
  1068. "STMT -> [*]",
  1069. "GOTO -> [*]",
  1070. "7: END"
  1071. );
  1072. }
  1073. public void testSwitch_FallThrough() throws Exception {
  1074. assertCfg("void",
  1075. "switch(i) {",
  1076. " case 1: ",
  1077. " j = 1;",
  1078. " case 2: ",
  1079. " j = 2;",
  1080. " case 3: ",
  1081. " j = 3;",
  1082. "}"
  1083. ).is(
  1084. "BLOCK -> [*]",
  1085. "STMT -> [*]",
  1086. "READ(i) -> [*]",
  1087. "GOTO -> [*]",
  1088. "STMT -> [*]",
  1089. "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=1]",
  1090. "STMT -> [*]",
  1091. "WRITE(j, 1) -> [2]",
  1092. "1: STMT -> [*]",
  1093. "COND (EntryPoint.i == 2) -> [THEN=*, ELSE=3]",
  1094. "2: STMT -> [*]",
  1095. "WRITE(j, 2) -> [4]",
  1096. "3: STMT -> [*]",
  1097. "COND (EntryPoint.i == 3) -> [THEN=*, ELSE=5]",
  1098. "4: STMT -> [*]",
  1099. "WRITE(j, 3) -> [*]",
  1100. "5: END");
  1101. }
  1102. public void testSwitch_FirstDefault() throws Exception {
  1103. assertCfg("void",
  1104. "switch(i) {",
  1105. " default: j = 1; return;",
  1106. " case 1: j = 2; return;",
  1107. "}"
  1108. ).is(
  1109. "BLOCK -> [*]",
  1110. "STMT -> [*]",
  1111. "READ(i) -> [*]",
  1112. "GOTO -> [2]",
  1113. "1: STMT -> [*]",
  1114. "STMT -> [*]",
  1115. "WRITE(j, 1) -> [*]",
  1116. "STMT -> [*]",
  1117. "GOTO -> [3]",
  1118. "2: STMT -> [*]",
  1119. "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=1]",
  1120. "STMT -> [*]",
  1121. "WRITE(j, 2) -> [*]",
  1122. "STMT -> [*]",
  1123. "GOTO -> [*]",
  1124. "3: END"
  1125. );
  1126. }
  1127. public void testSwitch_Empty() throws Exception {
  1128. assertCfg("void",
  1129. "switch(i) {",
  1130. "}"
  1131. ).is(
  1132. "BLOCK -> [*]",
  1133. "STMT -> [*]",
  1134. "READ(i) -> [*]",
  1135. "GOTO -> [*]",
  1136. "END"
  1137. );
  1138. }
  1139. public void testSwitch_OnlyDefault() throws Exception {
  1140. assertCfg("void",
  1141. "switch(i) {",
  1142. " default: j = 0; return;",
  1143. "}"
  1144. ).is(
  1145. "BLOCK -> [*]",
  1146. "STMT -> [*]",
  1147. "READ(i) -> [*]",
  1148. "GOTO -> [*]",
  1149. "STMT -> [*]",
  1150. "STMT -> [*]",
  1151. "WRITE(j, 0) -> [*]",
  1152. "STMT -> [*]",
  1153. "GOTO -> [*]",
  1154. "END"
  1155. );
  1156. }
  1157. public void testNestedSwitch() throws Exception {
  1158. assertCfg("void",
  1159. "switch(i) {",
  1160. " case 1: ",
  1161. " switch (j) {",
  1162. " case 0: k = 1; break;",
  1163. " case 1: k = 2; break;",
  1164. " }",
  1165. " break;",
  1166. " case 2: ",
  1167. " switch (j) {",
  1168. " case 0: k = 3; break;",
  1169. " case 1: k = 4; break;",
  1170. " }",
  1171. " break;",
  1172. " case 3: ",
  1173. " switch (j) {",
  1174. " case 0: k = 5; break;",
  1175. " case 1: k = 6; break;",
  1176. " }",
  1177. " break;",
  1178. "}"
  1179. ).is(
  1180. "BLOCK -> [*]",
  1181. "STMT -> [*]",
  1182. "READ(i) -> [*]",
  1183. "GOTO -> [*]",
  1184. "STMT -> [*]",
  1185. "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=3]",
  1186. "STMT -> [*]",
  1187. "READ(j) -> [*]",
  1188. "GOTO -> [*]",
  1189. "STMT -> [*]",
  1190. "COND (EntryPoint.j == 0) -> [THEN=*, ELSE=1]",
  1191. "STMT -> [*]",
  1192. "WRITE(k, 1) -> [*]",
  1193. "STMT -> [*]",
  1194. "GOTO -> [2]",
  1195. "1: STMT -> [*]",
  1196. "COND (EntryPoint.j == 1) -> [THEN=*, ELSE=2]",
  1197. "STMT -> [*]",
  1198. "WRITE(k, 2) -> [*]",
  1199. "STMT -> [*]",
  1200. "GOTO -> [*]",
  1201. "2: STMT -> [*]",
  1202. "GOTO -> [9]",
  1203. "3: STMT -> [*]",
  1204. "COND (EntryPoint.i == 2) -> [THEN=*, ELSE=6]",
  1205. "STMT -> [*]",
  1206. "READ(j) -> [*]",
  1207. "GOTO -> [*]",
  1208. "STMT -> [*]",
  1209. "COND (EntryPoint.j == 0) -> [THEN=*, ELSE=4]",
  1210. "STMT -> [*]",
  1211. "WRITE(k, 3) -> [*]",
  1212. "STMT -> [*]",
  1213. "GOTO -> [5]",
  1214. "4: STMT -> [*]",
  1215. "COND (EntryPoint.j == 1) -> [THEN=*, ELSE=5]",
  1216. "STMT -> [*]",
  1217. "WRITE(k, 4) -> [*]",
  1218. "STMT -> [*]",
  1219. "GOTO -> [*]",
  1220. "5: STMT -> [*]",
  1221. "GOTO -> [9]",
  1222. "6: STMT -> [*]",
  1223. "COND (EntryPoint.i == 3) -> [THEN=*, ELSE=9]",
  1224. "STMT -> [*]",
  1225. "READ(j) -> [*]",
  1226. "GOTO -> [*]",
  1227. "STMT -> [*]",
  1228. "COND (EntryPoint.j == 0) -> [THEN=*, ELSE=7]",
  1229. "STMT -> [*]",
  1230. "WRITE(k, 5) -> [*]",
  1231. "STMT -> [*]",
  1232. "GOTO -> [8]",
  1233. "7: STMT -> [*]",
  1234. "COND (EntryPoint.j == 1) -> [THEN=*, ELSE=8]",
  1235. "STMT -> [*]",
  1236. "WRITE(k, 6) -> [*]",
  1237. "STMT -> [*]",
  1238. "GOTO -> [*]",
  1239. "8: STMT -> [*]",
  1240. "GOTO -> [*]",
  1241. "9: END"
  1242. );
  1243. }
  1244. public void testSwitchWithLoopAndBreak() throws Exception {
  1245. assertCfg("void",
  1246. "switch(i) {",
  1247. " case 1: ",
  1248. " i = 1;" +
  1249. " break;",
  1250. " case 2: ",
  1251. " while (b) { i = 2; break; }",
  1252. " j = 3;",
  1253. "}"
  1254. ).is(
  1255. "BLOCK -> [*]",
  1256. "STMT -> [*]",
  1257. "READ(i) -> [*]",
  1258. "GOTO -> [*]",
  1259. "STMT -> [*]",
  1260. "COND (EntryPoint.i == 1) -> [THEN=*, ELSE=1]",
  1261. "STMT -> [*]",
  1262. "WRITE(i, 1) -> [*]",
  1263. "STMT -> [*]",
  1264. "GOTO -> [3]",
  1265. "1: STMT -> [*]",
  1266. "COND (EntryPoint.i == 2) -> [THEN=*, ELSE=3]",
  1267. "STMT -> [*]",
  1268. "READ(b) -> [*]",
  1269. "COND (EntryPoint.b) -> [THEN=*, ELSE=2]",
  1270. "BLOCK -> [*]",
  1271. "STMT -> [*]",
  1272. "WRITE(i, 2) -> [*]",
  1273. "STMT -> [*]",
  1274. "GOTO -> [*]",
  1275. "2: STMT -> [*]",
  1276. "WRITE(j, 3) -> [*]",
  1277. "3: END"
  1278. );
  1279. }
  1280. private CfgBuilderResult assertCfg(String returnType, String ...codeSnippet)
  1281. throws UnableToCompleteException {
  1282. JProgram program = compileSnippet(returnType,
  1283. Strings.join(codeSnippet, "\n"));
  1284. JMethodBody body = (JMethodBody) findMainMethod(program).getBody();
  1285. Cfg cfgGraph = CfgBuilder.build(program, body.getBlock());
  1286. return new CfgBuilderResult(cfgGraph);
  1287. }
  1288. static class CfgBuilderResult {
  1289. private final Cfg cfg;
  1290. public CfgBuilderResult(Cfg cfgGraph) {
  1291. assertNotNull("Can't build cfg", cfgGraph);
  1292. this.cfg = cfgGraph;
  1293. validateGraph();
  1294. }
  1295. private void validateGraph() {
  1296. for (CfgNode<?> node : cfg.getNodes()) {
  1297. List<CfgEdge> incomingEdges = cfg.getInEdges(node);
  1298. for (CfgEdge e : incomingEdges) {
  1299. CfgNode<?> start = e.getStart();
  1300. if (cfg.getGraphInEdges().contains(e)) {
  1301. assertNull(start);
  1302. continue;
  1303. }
  1304. assertNotNull("No start in edge " + e.getRole() + " to " + node,
  1305. start);
  1306. assertTrue(start + " doesn't have outgoing edge to " + node,
  1307. cfg.getOutEdges(start).contains(e));
  1308. }
  1309. List<CfgEdge> outcomingEdges = cfg.getOutEdges(node);
  1310. for (CfgEdge e : outcomingEdges) {
  1311. CfgNode<?> end = e.getEnd();
  1312. assertNotNull("No end in edge " + e.getRole() + " from " + node, end);
  1313. assertTrue(end + " doesn't have incoming edge from " + node,
  1314. cfg.getInEdges(end).contains(e));
  1315. }
  1316. }
  1317. }
  1318. public void is(String... expected) {
  1319. assertEquals(Strings.join(expected, "\n"), cfg.print());
  1320. }
  1321. }
  1322. }