RFR: 8194743: Compiler implementation for Statements before super() [v16]

Maurizio Cimadamore mcimadamore at openjdk.org
Mon Sep 25 17:02:17 UTC 2023

On Mon, 25 Sep 2023 16:04:09 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.
> Archie Cobbs has updated the pull request incrementally with one additional commit since the last revision:
>   Have RefBeforeCtorCalledError extend StaticError and customize debug strings.

src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java line 3971:

> 3969: 
> 3970:         // Match this scan stack: 1=JCMethodDecl, 2=JCExpressionStatement, 3=JCMethodInvocation
> 3971:         private static final int MATCH_SCAN_DEPTH = 3;

This logic seems a bit fragile in that it relies on the shape of the AST. Also, in principle you can create something that will overflow the int, and will cause the check to spuriously pass for a very very very large number of nested expressions :-)

That said, I understand that, in order to make this code "tighter", you would need to override al visitors that can "nest" code inside other code, which is also not great.


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

More information about the compiler-dev mailing list