# HG changeset patch # User pgovereau # Date 1398896983 -3600 # Node ID 12f99d1f23d97e10f76df03663d1ea561862d3a0 # Parent 3a2ebbad5911efdb6c1507b77b190ddacaddaab4 8039026: Definitely unassigned field can be accessed Reviewed-by: vromero, jlahoda diff -r 3a2ebbad5911 -r 12f99d1f23d9 src/share/classes/com/sun/tools/javac/code/Source.java --- a/src/share/classes/com/sun/tools/javac/code/Source.java Wed Apr 30 23:26:43 2014 +0100 +++ b/src/share/classes/com/sun/tools/javac/code/Source.java Wed Apr 30 23:29:43 2014 +0100 @@ -191,6 +191,9 @@ public boolean allowObjectToPrimitiveCast() { return compareTo(JDK1_7) >= 0; } + public boolean enforceThisDotInit() { + return compareTo(JDK1_7) >= 0; + } public boolean allowPoly() { return compareTo(JDK1_8) >= 0; } diff -r 3a2ebbad5911 -r 12f99d1f23d9 src/share/classes/com/sun/tools/javac/comp/Flow.java --- a/src/share/classes/com/sun/tools/javac/comp/Flow.java Wed Apr 30 23:26:43 2014 +0100 +++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java Wed Apr 30 23:29:43 2014 +0100 @@ -197,6 +197,7 @@ private final boolean allowImprovedRethrowAnalysis; private final boolean allowImprovedCatchAnalysis; private final boolean allowEffectivelyFinalInInnerClasses; + private final boolean enforceThisDotInit; public static Flow instance(Context context) { Flow instance = context.get(flowKey); @@ -207,7 +208,7 @@ public void analyzeTree(Env env, TreeMaker make) { new AliveAnalyzer().analyzeTree(env, make); - new AssignAnalyzer(log, syms, lint, names).analyzeTree(env); + new AssignAnalyzer(log, syms, lint, names, enforceThisDotInit).analyzeTree(env); new FlowAnalyzer().analyzeTree(env, make); new CaptureAnalyzer().analyzeTree(env, make); } @@ -239,7 +240,7 @@ //related errors, which will allow for more errors to be detected Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); try { - new AssignAnalyzer(log, syms, lint, names).analyzeTree(env); + new AssignAnalyzer(log, syms, lint, names, enforceThisDotInit).analyzeTree(env); LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer(); flowAnalyzer.analyzeTree(env, that, make); return flowAnalyzer.inferredThrownTypes; @@ -289,6 +290,7 @@ allowImprovedRethrowAnalysis = source.allowImprovedRethrowAnalysis(); allowImprovedCatchAnalysis = source.allowImprovedCatchAnalysis(); allowEffectivelyFinalInInnerClasses = source.allowEffectivelyFinalInInnerClasses(); + enforceThisDotInit = source.enforceThisDotInit(); } /** @@ -1427,6 +1429,8 @@ protected Names names; + final boolean enforceThisDotInit; + public static class AbstractAssignPendingExit extends BaseAnalyzer.PendingExit { final Bits inits; @@ -1449,7 +1453,7 @@ } } - public AbstractAssignAnalyzer(Bits inits, Symtab syms, Names names) { + public AbstractAssignAnalyzer(Bits inits, Symtab syms, Names names, boolean enforceThisDotInit) { this.inits = inits; uninits = new Bits(); uninitsTry = new Bits(); @@ -1459,6 +1463,7 @@ uninitsWhenFalse = new Bits(true); this.syms = syms; this.names = names; + this.enforceThisDotInit = enforceThisDotInit; } private boolean isInitialConstructor = false; @@ -2280,12 +2285,34 @@ public void visitAssign(JCAssign tree) { JCTree lhs = TreeInfo.skipParens(tree.lhs); - if (!(lhs instanceof JCIdent)) { + if (!isIdentOrThisDotIdent(lhs)) scanExpr(lhs); - } scanExpr(tree.rhs); letInit(lhs); } + private boolean isIdentOrThisDotIdent(JCTree lhs) { + if (lhs.hasTag(IDENT)) + return true; + if (!lhs.hasTag(SELECT)) + return false; + + JCFieldAccess fa = (JCFieldAccess)lhs; + return fa.selected.hasTag(IDENT) && + ((JCIdent)fa.selected).name == names._this; + } + + // check fields accessed through this. are definitely + // assigned before reading their value + public void visitSelect(JCFieldAccess tree) { + super.visitSelect(tree); + if (enforceThisDotInit && + tree.selected.hasTag(IDENT) && + ((JCIdent)tree.selected).name == names._this && + tree.sym.kind == VAR) + { + checkInit(tree.pos(), (VarSymbol)tree.sym); + } + } public void visitAssignop(JCAssignOp tree) { scanExpr(tree.lhs); @@ -2419,8 +2446,8 @@ } } - public AssignAnalyzer(Log log, Symtab syms, Lint lint, Names names) { - super(new Bits(), syms, names); + public AssignAnalyzer(Log log, Symtab syms, Lint lint, Names names, boolean enforceThisDotInit) { + super(new Bits(), syms, names, enforceThisDotInit); this.log = log; this.lint = lint; } diff -r 3a2ebbad5911 -r 12f99d1f23d9 src/share/classes/com/sun/tools/javac/jvm/Gen.java --- a/src/share/classes/com/sun/tools/javac/jvm/Gen.java Wed Apr 30 23:26:43 2014 +0100 +++ b/src/share/classes/com/sun/tools/javac/jvm/Gen.java Wed Apr 30 23:29:43 2014 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2818,7 +2818,7 @@ } private LVTAssignAnalyzer(LVTRanges lvtRanges, Symtab syms, Names names) { - super(new LVTBits(), syms, names); + super(new LVTBits(), syms, names, false); lvtInits = (LVTBits)inits; this.lvtRanges = lvtRanges; } diff -r 3a2ebbad5911 -r 12f99d1f23d9 test/tools/javac/DefiniteAssignment/T8039026.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/DefiniteAssignment/T8039026.java Wed Apr 30 23:29:43 2014 +0100 @@ -0,0 +1,21 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8039026 + * @summary Definitely unassigned field can be accessed + * @compile/fail/ref=T8039026.out -XDrawDiagnostics T8039026.java + */ + +public class T8039026 { + final int x,y,z; + final int a = this.y; // <- error + { + int b = true ? this.x : 0; // <- error + System.out.println(this.x); // <- error + this.y = 1; + } + T8039026() { + this.x = 1; // <- no error! + this.y = 1; // <- error + this.z = this.x; // <- no error + } +} diff -r 3a2ebbad5911 -r 12f99d1f23d9 test/tools/javac/DefiniteAssignment/T8039026.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/DefiniteAssignment/T8039026.out Wed Apr 30 23:29:43 2014 +0100 @@ -0,0 +1,4 @@ +T8039026.java:10:23: compiler.err.var.might.not.have.been.initialized: y +T8039026.java:12:28: compiler.err.var.might.not.have.been.initialized: x +T8039026.java:18:13: compiler.err.var.might.already.be.assigned: y +3 errors