RFR: 8194743: Compiler implementation for Statements before super()

ExE Boss duke at openjdk.org
Wed Apr 26 01:22:23 UTC 2023


On Tue, 25 Apr 2023 20:40:18 GMT, Archie Cobbs <acobbs at openjdk.org> wrote:

> This is a first draft of a patch for JEP 447.
> 
> Summary of changes:
> 
> 1. Track when we're within a constructor "prologue" via new flag `AttrContext.ctorPrologue`
> 1. Add checks for illegal early access to `this` in constructor prologues, and update existing checks to distinguish between static context vs. constructor prologue context
> 1. Verify allowed placement of `super()`/`this()` calls via new method `Check.checkSuperInitCalls()`
> 1. Remove/refactor assumptions in several places that `super()`/`this()` was always the first statement
> 
> The changes in `Flow.java` are an example of <span>#</span>4. `Flow.FlowAnalyzer` checks for uncaught checked exceptions. For initializer blocks, this was previously done by requiring that any checked exceptions thrown be declared as thrown by all constructors containing `super()`. This list of checked exceptions was being pre-calculated before recursing into the initial constructors. This worked because initializer blocks were executed at the beginning of each initial constructor right after `super()` is called.
> 
> Now initializer blocks are traversed as each `super()` invocation is encountered, reflecting what actually happens at runtime. Similarly, final fields are marked as DA after encountering `this()`, not automatically at the beginning of those  constructors. These changes produce equivalent checks, but are compatible with the new flexibility of placement of `super()`/`this()` as well as possible future changes that could occur along these same lines.

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java line 5591:

> 5589:         }
> 5590: 
> 5591:         // Check for proper placement of super()/init() calls.

Suggestion:

        // Check for proper placement of super()/this() calls.

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java line 2859:

> 2857:                         letInit(tree.pos(), sym);
> 2858:                 }
> 2859:             }

The common `isConstructor` check can be moved to an enclosing `if` statement:

Suggestion:

            if (isConstructor) {
                // If super(): at this point all initialization blocks will execute
                Name name = TreeInfo.name(tree.meth);
                if (name == names._super) {
                    forEachInitializer(classDef, false, def -> {
                        scan(def);
                        clearPendingExits(false);
                    });
                }

                // If this(): at this point all final uninitialized fields will get initialized
                else if (name == names._this) {
                    for (int address = firstadr; address < nextadr; address++) {
                        VarSymbol sym = vardecls[address].sym;
                        if (isFinalUninitializedField(sym) && !sym.isStatic())
                            letInit(tree.pos(), sym);
                    }
                }
            }

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/13656#discussion_r1177207245
PR Review Comment: https://git.openjdk.org/jdk/pull/13656#discussion_r1177209992


More information about the compiler-dev mailing list