src/share/classes/com/sun/tools/javac/comp/Flow.java

changeset 2376
12f99d1f23d9
parent 2370
acd64168cf8b
child 2408
716f2466ddd0
equal deleted inserted replaced
2375:3a2ebbad5911 2376:12f99d1f23d9
195 private Env<AttrContext> attrEnv; 195 private Env<AttrContext> attrEnv;
196 private Lint lint; 196 private Lint lint;
197 private final boolean allowImprovedRethrowAnalysis; 197 private final boolean allowImprovedRethrowAnalysis;
198 private final boolean allowImprovedCatchAnalysis; 198 private final boolean allowImprovedCatchAnalysis;
199 private final boolean allowEffectivelyFinalInInnerClasses; 199 private final boolean allowEffectivelyFinalInInnerClasses;
200 private final boolean enforceThisDotInit;
200 201
201 public static Flow instance(Context context) { 202 public static Flow instance(Context context) {
202 Flow instance = context.get(flowKey); 203 Flow instance = context.get(flowKey);
203 if (instance == null) 204 if (instance == null)
204 instance = new Flow(context); 205 instance = new Flow(context);
205 return instance; 206 return instance;
206 } 207 }
207 208
208 public void analyzeTree(Env<AttrContext> env, TreeMaker make) { 209 public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
209 new AliveAnalyzer().analyzeTree(env, make); 210 new AliveAnalyzer().analyzeTree(env, make);
210 new AssignAnalyzer(log, syms, lint, names).analyzeTree(env); 211 new AssignAnalyzer(log, syms, lint, names, enforceThisDotInit).analyzeTree(env);
211 new FlowAnalyzer().analyzeTree(env, make); 212 new FlowAnalyzer().analyzeTree(env, make);
212 new CaptureAnalyzer().analyzeTree(env, make); 213 new CaptureAnalyzer().analyzeTree(env, make);
213 } 214 }
214 215
215 public void analyzeLambda(Env<AttrContext> env, JCLambda that, TreeMaker make, boolean speculative) { 216 public void analyzeLambda(Env<AttrContext> env, JCLambda that, TreeMaker make, boolean speculative) {
237 //message will be reported and will cause compilation to skip the flow analyis 238 //message will be reported and will cause compilation to skip the flow analyis
238 //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis 239 //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis
239 //related errors, which will allow for more errors to be detected 240 //related errors, which will allow for more errors to be detected
240 Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); 241 Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log);
241 try { 242 try {
242 new AssignAnalyzer(log, syms, lint, names).analyzeTree(env); 243 new AssignAnalyzer(log, syms, lint, names, enforceThisDotInit).analyzeTree(env);
243 LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer(); 244 LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer();
244 flowAnalyzer.analyzeTree(env, that, make); 245 flowAnalyzer.analyzeTree(env, that, make);
245 return flowAnalyzer.inferredThrownTypes; 246 return flowAnalyzer.inferredThrownTypes;
246 } finally { 247 } finally {
247 log.popDiagnosticHandler(diagHandler); 248 log.popDiagnosticHandler(diagHandler);
287 diags = JCDiagnostic.Factory.instance(context); 288 diags = JCDiagnostic.Factory.instance(context);
288 Source source = Source.instance(context); 289 Source source = Source.instance(context);
289 allowImprovedRethrowAnalysis = source.allowImprovedRethrowAnalysis(); 290 allowImprovedRethrowAnalysis = source.allowImprovedRethrowAnalysis();
290 allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis(); 291 allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis();
291 allowEffectivelyFinalInInnerClasses = source.allowEffectivelyFinalInInnerClasses(); 292 allowEffectivelyFinalInInnerClasses = source.allowEffectivelyFinalInInnerClasses();
293 enforceThisDotInit = source.enforceThisDotInit();
292 } 294 }
293 295
294 /** 296 /**
295 * Base visitor class for all visitors implementing dataflow analysis logic. 297 * Base visitor class for all visitors implementing dataflow analysis logic.
296 * This class define the shared logic for handling jumps (break/continue statements). 298 * This class define the shared logic for handling jumps (break/continue statements).
1425 1427
1426 final Symtab syms; 1428 final Symtab syms;
1427 1429
1428 protected Names names; 1430 protected Names names;
1429 1431
1432 final boolean enforceThisDotInit;
1433
1430 public static class AbstractAssignPendingExit extends BaseAnalyzer.PendingExit { 1434 public static class AbstractAssignPendingExit extends BaseAnalyzer.PendingExit {
1431 1435
1432 final Bits inits; 1436 final Bits inits;
1433 final Bits uninits; 1437 final Bits uninits;
1434 final Bits exit_inits = new Bits(true); 1438 final Bits exit_inits = new Bits(true);
1447 inits.andSet(exit_inits); 1451 inits.andSet(exit_inits);
1448 uninits.andSet(exit_uninits); 1452 uninits.andSet(exit_uninits);
1449 } 1453 }
1450 } 1454 }
1451 1455
1452 public AbstractAssignAnalyzer(Bits inits, Symtab syms, Names names) { 1456 public AbstractAssignAnalyzer(Bits inits, Symtab syms, Names names, boolean enforceThisDotInit) {
1453 this.inits = inits; 1457 this.inits = inits;
1454 uninits = new Bits(); 1458 uninits = new Bits();
1455 uninitsTry = new Bits(); 1459 uninitsTry = new Bits();
1456 initsWhenTrue = new Bits(true); 1460 initsWhenTrue = new Bits(true);
1457 initsWhenFalse = new Bits(true); 1461 initsWhenFalse = new Bits(true);
1458 uninitsWhenTrue = new Bits(true); 1462 uninitsWhenTrue = new Bits(true);
1459 uninitsWhenFalse = new Bits(true); 1463 uninitsWhenFalse = new Bits(true);
1460 this.syms = syms; 1464 this.syms = syms;
1461 this.names = names; 1465 this.names = names;
1466 this.enforceThisDotInit = enforceThisDotInit;
1462 } 1467 }
1463 1468
1464 private boolean isInitialConstructor = false; 1469 private boolean isInitialConstructor = false;
1465 1470
1466 @Override 1471 @Override
2278 uninits.assign(uninitsExit); 2283 uninits.assign(uninitsExit);
2279 } 2284 }
2280 2285
2281 public void visitAssign(JCAssign tree) { 2286 public void visitAssign(JCAssign tree) {
2282 JCTree lhs = TreeInfo.skipParens(tree.lhs); 2287 JCTree lhs = TreeInfo.skipParens(tree.lhs);
2283 if (!(lhs instanceof JCIdent)) { 2288 if (!isIdentOrThisDotIdent(lhs))
2284 scanExpr(lhs); 2289 scanExpr(lhs);
2285 }
2286 scanExpr(tree.rhs); 2290 scanExpr(tree.rhs);
2287 letInit(lhs); 2291 letInit(lhs);
2292 }
2293 private boolean isIdentOrThisDotIdent(JCTree lhs) {
2294 if (lhs.hasTag(IDENT))
2295 return true;
2296 if (!lhs.hasTag(SELECT))
2297 return false;
2298
2299 JCFieldAccess fa = (JCFieldAccess)lhs;
2300 return fa.selected.hasTag(IDENT) &&
2301 ((JCIdent)fa.selected).name == names._this;
2302 }
2303
2304 // check fields accessed through this.<field> are definitely
2305 // assigned before reading their value
2306 public void visitSelect(JCFieldAccess tree) {
2307 super.visitSelect(tree);
2308 if (enforceThisDotInit &&
2309 tree.selected.hasTag(IDENT) &&
2310 ((JCIdent)tree.selected).name == names._this &&
2311 tree.sym.kind == VAR)
2312 {
2313 checkInit(tree.pos(), (VarSymbol)tree.sym);
2314 }
2288 } 2315 }
2289 2316
2290 public void visitAssignop(JCAssignOp tree) { 2317 public void visitAssignop(JCAssignOp tree) {
2291 scanExpr(tree.lhs); 2318 scanExpr(tree.lhs);
2292 scanExpr(tree.rhs); 2319 scanExpr(tree.rhs);
2417 public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { 2444 public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
2418 super(tree, inits, uninits); 2445 super(tree, inits, uninits);
2419 } 2446 }
2420 } 2447 }
2421 2448
2422 public AssignAnalyzer(Log log, Symtab syms, Lint lint, Names names) { 2449 public AssignAnalyzer(Log log, Symtab syms, Lint lint, Names names, boolean enforceThisDotInit) {
2423 super(new Bits(), syms, names); 2450 super(new Bits(), syms, names, enforceThisDotInit);
2424 this.log = log; 2451 this.log = log;
2425 this.lint = lint; 2452 this.lint = lint;
2426 } 2453 }
2427 2454
2428 @Override 2455 @Override

mercurial