diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index 4c9a28102e0..e36280ca018 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -481,7 +481,6 @@ public class Flow { } // Do something with all static or non-static field initializers and initialization blocks. - // Note: This method also sends nested class definitions to the handler. protected void forEachInitializer(JCClassDecl classDef, boolean isStatic, Consumer handler) { if (classDef == initScanClass) // avoid infinite loops return; @@ -490,6 +489,11 @@ public class Flow { try { for (List defs = classDef.defs; defs.nonEmpty(); defs = defs.tail) { JCTree def = defs.head; + + // Don't recurse into nested classes + if (def.hasTag(CLASSDEF)) + continue; + /* we need to check for flags in the symbol too as there could be cases for which implicit flags are * represented in the symbol but not in the tree modifiers as they were not originally in the source * code @@ -566,6 +570,13 @@ public class Flow { lint = lint.augment(tree.sym); try { + // process all the nested classes + for (List l = tree.defs; l.nonEmpty(); l = l.tail) { + if (l.head.hasTag(CLASSDEF)) { + scan(l.head); + } + } + // process all the static initializers forEachInitializer(tree, true, def -> { scanDef(def); @@ -1459,6 +1470,13 @@ public class Flow { lint = lint.augment(tree.sym); try { + // process all the nested classes + for (List l = tree.defs; l.nonEmpty(); l = l.tail) { + if (l.head.hasTag(CLASSDEF)) { + scan(l.head); + } + } + // process all the static initializers forEachInitializer(tree, true, def -> { scan(def); @@ -2168,15 +2186,7 @@ public class Flow { @Override protected void markDead() { - if (!isConstructor) { - inits.inclRange(returnadr, nextadr); - } else { - for (int address = returnadr; address < nextadr; address++) { - if (!(isFinalUninitializedStaticField(vardecls[address].sym))) { - inits.incl(address); - } - } - } + inits.inclRange(returnadr, nextadr); uninits.inclRange(returnadr, nextadr); } @@ -2198,10 +2208,6 @@ public class Flow { classDef.sym.isEnclosedBy((ClassSymbol)sym.owner)); } - boolean isFinalUninitializedStaticField(VarSymbol sym) { - return isFinalUninitializedField(sym) && sym.isStatic(); - } - /** Initialize new trackable variable by setting its address field * to the next available sequence number and entering it under that * index into the vars array. @@ -2420,7 +2426,7 @@ public class Flow { clearPendingExits(false); }); - // verify all static final fields got initailized + // verify all static final fields got initialized for (int i = firstadr; i < nextadr; i++) { JCVariableDecl vardecl = vardecls[i]; VarSymbol var = vardecl.sym; @@ -2448,6 +2454,13 @@ public class Flow { scan(l.head); } } + + // process all the nested classes + for (List l = tree.defs; l.nonEmpty(); l = l.tail) { + if (l.head.hasTag(CLASSDEF)) { + scan(l.head); + } + } } finally { pendingExits = pendingExitsPrev; nextadr = nextadrPrev; diff --git a/test/langtools/tools/javac/DefiniteAssignment/StaticFinalNestedClass.java b/test/langtools/tools/javac/DefiniteAssignment/StaticFinalNestedClass.java new file mode 100644 index 00000000000..57ffe9e6a55 --- /dev/null +++ b/test/langtools/tools/javac/DefiniteAssignment/StaticFinalNestedClass.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8329595 + * @summary Verify spurious "might not have been initialized" error on static final field + * @run main StaticFinalNestedClass + */ +public class StaticFinalNestedClass { + public class Inner { // note this inner class is NOT static + public static final String NAME; + static { + try { + NAME = "bob"; + } catch (Exception e) { + throw new Error(e); + } + } + } + + public static void main(String[] args) { + new StaticFinalNestedClass().new Inner(); + } +}