changeset 56912:ccb9986a609c records-and-sealed

updating non-sealed, removing non-final, adding restrictions to the use of sealed modifiers
author vromero
date Fri, 28 Jun 2019 17:08:17 -0400
parents 5261a2b6a653
children 05e3221cdf2f
files src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties test/langtools/tools/javac/sealed/NotSealedTest.java test/langtools/tools/javac/sealed/NotSealedTest.out test/langtools/tools/javac/sealed/PermitsInNoSealedClass.java test/langtools/tools/javac/sealed/PermitsInNoSealedClass.out
diffstat 9 files changed, 97 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java	Thu Jun 27 14:45:22 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java	Fri Jun 28 17:08:17 2019 -0400
@@ -332,7 +332,7 @@
     /**
      * Flag to indicate that the class/interface has explicitly being annotated as not sealed.
      */
-    public static final long NON_FINAL = 1L<<60;
+    public static final long NON_SEALED = 1L<<60;
 
     /**
      * Flag to indicate that a class is a record. The flag is also used to mark fields that are
@@ -343,26 +343,31 @@
     /** Modifier masks.
      */
     public static final int
-        AccessFlags                 = PUBLIC | PROTECTED | PRIVATE,
-        LocalClassFlags             = FINAL | ABSTRACT | STRICTFP | ENUM | SYNTHETIC,
-        LocalRecordFlags            = LocalClassFlags | STATIC,
-        MemberClassFlags            = LocalClassFlags | INTERFACE | AccessFlags,
-        MemberRecordClassFlags      = MemberClassFlags | STATIC,
-        ClassFlags                  = LocalClassFlags | INTERFACE | PUBLIC | ANNOTATION,
-        InterfaceVarFlags           = FINAL | STATIC | PUBLIC,
-        VarFlags                    = AccessFlags | FINAL | STATIC |
-                                      VOLATILE | TRANSIENT | ENUM,
-        ConstructorFlags            = AccessFlags,
-        InterfaceMethodFlags        = ABSTRACT | PUBLIC,
-        MethodFlags                 = AccessFlags | ABSTRACT | STATIC | NATIVE |
-                                      SYNCHRONIZED | FINAL | STRICTFP;
+        AccessFlags                      = PUBLIC | PROTECTED | PRIVATE,
+        LocalClassFlags                  = FINAL | ABSTRACT | STRICTFP | ENUM | SYNTHETIC,
+        LocalRecordFlags                 = LocalClassFlags | STATIC,
+        MemberClassFlags                 = LocalClassFlags | INTERFACE | AccessFlags,
+        MemberRecordClassFlags           = MemberClassFlags | STATIC,
+        ClassFlags                       = LocalClassFlags | INTERFACE | PUBLIC | ANNOTATION,
+        InterfaceVarFlags                = FINAL | STATIC | PUBLIC,
+        VarFlags                         = AccessFlags | FINAL | STATIC |
+                                           VOLATILE | TRANSIENT | ENUM,
+        ConstructorFlags                 = AccessFlags,
+        InterfaceMethodFlags             = ABSTRACT | PUBLIC,
+        MethodFlags                      = AccessFlags | ABSTRACT | STATIC | NATIVE |
+                                           SYNCHRONIZED | FINAL | STRICTFP;
     public static final long
-        ExtendedStandardFlags       = (long)StandardFlags | DEFAULT,
-        ModifierFlags               = ((long)StandardFlags & ~INTERFACE) | DEFAULT,
-        InterfaceMethodMask         = ABSTRACT | PRIVATE | STATIC | PUBLIC | STRICTFP | DEFAULT,
-        AnnotationTypeElementMask   = ABSTRACT | PUBLIC,
-        LocalVarFlags               = FINAL | PARAMETER,
-        ReceiverParamFlags          = PARAMETER;
+        ExtendedStandardFlags            = (long)StandardFlags | DEFAULT | SEALED | NON_SEALED,
+        ExtendedLocalClassFlags          = (long)LocalClassFlags | SEALED | NON_SEALED,
+        ExtendedLocalRecordFlags         = (long)LocalRecordFlags | SEALED | NON_SEALED,
+        ExtendedMemberClassFlags         = (long)MemberClassFlags | SEALED | NON_SEALED,
+        ExtendedMemberRecordClassFlags   = (long)MemberRecordClassFlags | SEALED | NON_SEALED,
+        ExtendedClassFlags               = (long)ClassFlags | SEALED | NON_SEALED,
+        ModifierFlags                    = ((long)StandardFlags & ~INTERFACE) | DEFAULT | SEALED | NON_SEALED,
+        InterfaceMethodMask              = ABSTRACT | PRIVATE | STATIC | PUBLIC | STRICTFP | DEFAULT,
+        AnnotationTypeElementMask        = ABSTRACT | PUBLIC,
+        LocalVarFlags                    = FINAL | PARAMETER,
+        ReceiverParamFlags               = PARAMETER;
 
 
     public static Set<Modifier> asModifierSet(long flags) {
@@ -462,6 +467,7 @@
         ANONCONSTR_BASED(Flags.ANONCONSTR_BASED),
         NAME_FILLED(Flags.NAME_FILLED),
         SEALED(Flags.SEALED),
+        NON_SEALED(Flags.NON_SEALED),
         RECORD(Flags.RECORD);
 
         Flag(long flag) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Thu Jun 27 14:45:22 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Fri Jun 28 17:08:17 2019 -0400
@@ -94,6 +94,7 @@
     private final Target target;
     private final Profile profile;
     private final boolean warnOnAnyAccessToMembers;
+    private final boolean debug;
 
     // The set of lint options currently in effect. It is initialized
     // from the context, and then is set/reset as needed by Attr as it
@@ -155,6 +156,7 @@
                 enforceMandatoryWarnings, "sunapi", null);
 
         deferredLintHandler = DeferredLintHandler.instance(context);
+        debug = options.isSet("debug");
     }
 
     /** Character for synthetic names
@@ -1137,6 +1139,9 @@
                 mask = VarFlags;
             break;
         case MTH:
+            if (debug) {
+                System.out.println("checking method with flags " + Flags.toString(flags));
+            }
             if (sym.name == names.init) {
                 if ((sym.owner.flags_field & ENUM) != 0) {
                     // enum constructors cannot be declared public or
@@ -1168,8 +1173,11 @@
                 implicit |= sym.owner.flags_field & STRICTFP;
             break;
         case TYP:
+            if (debug) {
+                System.out.println("checking type with flags " + Flags.toString(flags));
+            }
             if (sym.isLocal()) {
-                mask = (flags & RECORD) != 0 ? LocalRecordFlags : LocalClassFlags;
+                mask = (flags & RECORD) != 0 ? LocalRecordFlags : ExtendedLocalClassFlags;
                 if ((sym.owner.flags_field & STATIC) == 0 &&
                     (flags & ENUM) != 0) {
                     log.error(pos, Errors.EnumsMustBeStatic);
@@ -1178,7 +1186,7 @@
                     log.error(pos, Errors.NestedRecordsMustBeStatic);
                 }
             } else if (sym.owner.kind == TYP) {
-                mask = (flags & RECORD) != 0 ? MemberRecordClassFlags : MemberClassFlags;
+                mask = (flags & RECORD) != 0 ? ExtendedMemberRecordClassFlags : ExtendedMemberClassFlags;
                 if (sym.owner.owner.kind == PCK ||
                     (sym.owner.flags_field & STATIC) != 0)
                     mask |= STATIC;
@@ -1188,7 +1196,7 @@
                 // Nested interfaces and enums are always STATIC (Spec ???)
                 if ((flags & (INTERFACE | ENUM)) != 0 ) implicit = STATIC;
             } else {
-                mask = ClassFlags;
+                mask = ExtendedClassFlags;
             }
             // Interfaces are always ABSTRACT
             if ((flags & INTERFACE) != 0) implicit |= ABSTRACT;
@@ -1209,6 +1217,9 @@
             throw new AssertionError();
         }
         long illegal = flags & ExtendedStandardFlags & ~mask;
+        if (debug) {
+            System.out.println("illegal flags: " + Flags.toString(illegal));
+        }
         if (illegal != 0) {
             if ((illegal & INTERFACE) != 0) {
                 log.error(pos, ((flags & ANNOTATION) != 0) ? Errors.AnnotationDeclNotAllowedHere : Errors.IntfNotAllowedHere);
@@ -1249,7 +1260,13 @@
                  (sym.kind == TYP ||
                   checkDisjoint(pos, flags,
                                 ABSTRACT | NATIVE,
-                                STRICTFP))) {
+                                STRICTFP))
+                 && checkDisjoint(pos, flags,
+                                FINAL,
+                           SEALED | NON_SEALED)
+                 && checkDisjoint(pos, flags,
+                                SEALED,
+                           FINAL | NON_SEALED)) {
             // skip
         }
         return flags & (mask | ~ExtendedStandardFlags) | implicit;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Thu Jun 27 14:45:22 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Fri Jun 28 17:08:17 2019 -0400
@@ -1101,10 +1101,14 @@
                 }
             }
 
-            if (anyParentIsSealed) {
+            if (anyParentIsSealed && ((tree.sym.flags_field & Flags.NON_SEALED) == 0) ) {
                 // once we have the non-final keyword this will change
                 tree.sym.flags_field |= (tree.sym.flags_field & ABSTRACT) != 0 ? SEALED : FINAL;
             }
+
+            if (!anyParentIsSealed && ((tree.sym.flags_field & Flags.NON_SEALED) != 0) ) {
+                log.error(tree, Errors.NonSealedWithNoSealedSupertype);
+            }
         }
 
         /** Add the accessors for fields to the symbol table.
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Thu Jun 27 14:45:22 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Fri Jun 28 17:08:17 2019 -0400
@@ -38,7 +38,6 @@
 import com.sun.tools.javac.parser.Tokens.*;
 import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle;
 import com.sun.tools.javac.resources.CompilerProperties.Errors;
-import com.sun.tools.javac.resources.CompilerProperties.Fragments;
 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.tree.JCTree.*;
@@ -106,6 +105,8 @@
     /** End position mappings container */
     protected final AbstractEndPosTable endPosTable;
 
+    private final boolean debug;
+
     // Because of javac's limited lookahead, some contexts are ambiguous in
     // the presence of type annotations even though they are not ambiguous
     // in the absence of type annotations.  Consider this code:
@@ -184,6 +185,7 @@
         endPosTable = newEndPosTable(keepEndPositions);
         this.allowYieldStatement = (!preview.isPreview(Feature.SWITCH_EXPRESSION) || preview.isEnabled()) &&
                 Feature.SWITCH_EXPRESSION.allowedInSource(source);
+        debug = fac.options.isSet("debug");
     }
 
     protected AbstractEndPosTable newEndPosTable(boolean keepEndPositions) {
@@ -3071,17 +3073,17 @@
             case DEFAULT     : checkSourceLevel(Feature.DEFAULT_METHODS); flag = Flags.DEFAULT; break;
             case ERROR       : flag = 0; nextToken(); break;
             case IDENTIFIER  : {
-                if (token.name() == names.non && peekToken(0, TokenKind.SUB, TokenKind.FINAL)) {
+                if (token.name() == names.non && peekToken(0, TokenKind.SUB, TokenKind.IDENTIFIER)) {
                     Token tokenSub = S.token(1);
-                    Token tokenFinal = S.token(2);
-                    if (token.endPos == tokenSub.pos && tokenSub.endPos == tokenFinal.pos) {
-                        flag = Flags.NON_FINAL;
+                    Token tokenSealed = S.token(2);
+                    if (token.endPos == tokenSub.pos && tokenSub.endPos == tokenSealed.pos && tokenSealed.name() == names.sealed) {
+                        flag = Flags.NON_SEALED;
                         nextToken();
                         nextToken();
                         break;
                     }
                 }
-                if (isSealedClassDeclaration()) {
+                if (token.name() == names.sealed) {
                     flag = Flags.SEALED;
                     break;
                 }
@@ -4040,6 +4042,9 @@
             Comment dc = token.comment(CommentStyle.JAVADOC);
             int pos = token.pos;
             JCModifiers mods = modifiersOpt();
+            if (debug) {
+                System.out.println("read flags " + Flags.toString(mods.flags));
+            }
             if (token.kind == CLASS ||
                 isRecordToken() ||
                 token.kind == INTERFACE ||
@@ -4132,15 +4137,6 @@
         return token.kind == IDENTIFIER && token.name() == names.record;
     }
 
-    boolean isSealedClassDeclaration() {
-        Token next = S.token(1);
-        return token.kind == IDENTIFIER && token.name() == names.sealed &&
-                (peekToken(TokenKind.CLASS) ||
-                        peekToken(TokenKind.INTERFACE) ||
-                        peekToken(TokenKind.ABSTRACT) ||
-                        next.kind == IDENTIFIER && next.name() == names.record);
-    }
-
     /** MethodDeclaratorRest =
      *      FormalParameters BracketsOpt [THROWS TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
      *  VoidMethodDeclaratorRest =
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Jun 27 14:45:22 2019 -0400
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Fri Jun 28 17:08:17 2019 -0400
@@ -3400,6 +3400,9 @@
 compiler.err.cant.inherit.from.sealed=\
     cannot inherit from sealed class: {0}
 
+compiler.err.non.sealed.with.no.sealed.supertype=\
+    non-sealed modifier applied to a class with no sealed supertype
+
 ###
 # errors related to records
 
--- a/test/langtools/tools/javac/sealed/NotSealedTest.java	Thu Jun 27 14:45:22 2019 -0400
+++ b/test/langtools/tools/javac/sealed/NotSealedTest.java	Fri Jun 28 17:08:17 2019 -0400
@@ -2,15 +2,19 @@
  * @test /nodynamiccopyright/
  * @summary smoke test for sealed classes
  * @compile/fail/ref=NotSealedTest.out -XDrawDiagnostics NotSealedTest.java
- * @ignore
  */
 
 import java.lang.annotation.*;
 
 class NotSealedTest {
-    @Sealed @NotSealed class AB {}
-    class NS {}
-    interface NSI {}
-    @NotSealed class SNS extends NS {}
-    @NotSealed class SNSI implements NSI {}
+    sealed class Super {}
+    sealed non-sealed class Sub extends Super {}
+
+    final sealed class Super2 {}
+
+    final non-sealed class Super3 {}
+
+    non-sealed class NoSealedSuper {}
+
+    sealed public void m() {}
 }
--- a/test/langtools/tools/javac/sealed/NotSealedTest.out	Thu Jun 27 14:45:22 2019 -0400
+++ b/test/langtools/tools/javac/sealed/NotSealedTest.out	Fri Jun 28 17:08:17 2019 -0400
@@ -1,6 +1,6 @@
-NotSealedTest.java:10:24: compiler.err.cant.applied.sealed.and.not.sealed.ann: NotSealedTest.AB
-NotSealedTest.java:10:24: compiler.warn.incorrect.application.of.not.sealed.ann: NotSealedTest.AB
-NotSealedTest.java:13:16: compiler.warn.incorrect.application.of.not.sealed.ann: NotSealedTest.SNS
-NotSealedTest.java:14:16: compiler.warn.incorrect.application.of.not.sealed.ann: NotSealedTest.SNSI
-1 error
-3 warnings
+NotSealedTest.java:11:23: compiler.err.illegal.combination.of.modifiers: sealed, non_sealed
+NotSealedTest.java:13:18: compiler.err.illegal.combination.of.modifiers: final, sealed
+NotSealedTest.java:15:22: compiler.err.illegal.combination.of.modifiers: final, non_sealed
+NotSealedTest.java:19:24: compiler.err.mod.not.allowed.here: sealed
+NotSealedTest.java:17:16: compiler.err.non.sealed.with.no.sealed.supertype
+5 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/sealed/PermitsInNoSealedClass.java	Fri Jun 28 17:08:17 2019 -0400
@@ -0,0 +1,13 @@
+/*
+ * @test /nodynamiccopyright/
+ * @summary smoke test for sealed classes
+ * @compile/fail/ref=PermitsInNoSealedClass.out -XDrawDiagnostics PermitsInNoSealedClass.java
+ */
+
+import java.lang.annotation.*;
+
+class PermitsInNoSealedClass {
+    class NotSealed permits Sub3 {}
+
+    class Sub3 extends NotSealed {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/sealed/PermitsInNoSealedClass.out	Fri Jun 28 17:08:17 2019 -0400
@@ -0,0 +1,2 @@
+PermitsInNoSealedClass.java:10:21: compiler.err.permits.in.no.sealed.class
+1 error