Skip to content

Commit 8533194

Browse files
committed
8361570: Incorrect 'sealed is not allowed here' compile-time error
Reviewed-by: mcimadamore, vromero
1 parent 63e08d4 commit 8533194

File tree

4 files changed

+113
-13
lines changed

4 files changed

+113
-13
lines changed

src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ public static EnumSet<Flag> asFlagSet(long flags) {
250250
/**
251251
* Flag that marks either a default method or an interface containing default methods.
252252
*/
253-
public static final long DEFAULT = 1L<<43;
253+
public static final long DEFAULT = 1L<<43; // part of ExtendedStandardFlags, cannot be reused
254254

255255
/**
256256
* Flag that marks class as auxiliary, ie a non-public class following
@@ -278,9 +278,10 @@ public static EnumSet<Flag> asFlagSet(long flags) {
278278
*/
279279
public static final long THROWS = 1L<<47;
280280

281-
/*
282-
* Currently available: Bit 48.
281+
/**
282+
* Flag to indicate sealed class/interface declaration.
283283
*/
284+
public static final long SEALED = 1L<<48; // part of ExtendedStandardFlags, cannot be reused
284285

285286
/**
286287
* Flag that marks a synthetic method body for a lambda expression
@@ -389,11 +390,6 @@ public static EnumSet<Flag> asFlagSet(long flags) {
389390
*/
390391
public static final int GENERATED_MEMBER = 1<<24; // MethodSymbols and VarSymbols
391392

392-
/**
393-
* Flag to indicate sealed class/interface declaration.
394-
*/
395-
public static final long SEALED = 1L<<62; // ClassSymbols
396-
397393
/**
398394
* Flag to indicate restricted method declaration.
399395
*/
@@ -412,7 +408,7 @@ public static EnumSet<Flag> asFlagSet(long flags) {
412408
/**
413409
* Flag to indicate that the class/interface was declared with the non-sealed modifier.
414410
*/
415-
public static final long NON_SEALED = 1L<<63; // ClassSymbols
411+
public static final long NON_SEALED = 1L<<63; // part of ExtendedStandardFlags, cannot be reused
416412

417413
/**
418414
* Describe modifier flags as they might appear in source code, i.e.,
@@ -443,6 +439,7 @@ public static String toSource(long flags) {
443439
RecordMethodFlags = AccessFlags | ABSTRACT | STATIC |
444440
SYNCHRONIZED | FINAL | STRICTFP;
445441
public static final long
442+
//NOTE: flags in ExtendedStandardFlags cannot be overlayed across Symbol kinds:
446443
ExtendedStandardFlags = (long)StandardFlags | DEFAULT | SEALED | NON_SEALED,
447444
ExtendedMemberClassFlags = (long)MemberClassFlags | SEALED | NON_SEALED,
448445
ExtendedMemberStaticClassFlags = (long) MemberStaticClassFlags | SEALED | NON_SEALED,
@@ -550,7 +547,7 @@ public enum Flag {
550547
DEPRECATED_ANNOTATION(Flags.DEPRECATED_ANNOTATION),
551548
DEPRECATED_REMOVAL(Flags.DEPRECATED_REMOVAL),
552549
HAS_RESOURCE(Flags.HAS_RESOURCE),
553-
// Bit 48 is currently available
550+
SEALED(Flags.SEALED),
554551
ANONCONSTR_BASED(Flags.ANONCONSTR_BASED),
555552
NAME_FILLED(Flags.NAME_FILLED),
556553
PREVIEW_API(Flags.PREVIEW_API),
@@ -559,7 +556,7 @@ public enum Flag {
559556
MATCH_BINDING_TO_OUTER(Flags.MATCH_BINDING_TO_OUTER),
560557
RECORD(Flags.RECORD),
561558
RECOVERABLE(Flags.RECOVERABLE),
562-
SEALED(Flags.SEALED),
559+
RESTRICTED(Flags.RESTRICTED),
563560
NON_SEALED(Flags.NON_SEALED) {
564561
@Override
565562
public String toString() {
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
/*
25+
* @test
26+
* @bug 8361570
27+
* @summary Verify no flags in ExtendedStandardFlags have overlays for different
28+
* Symbol kinds.
29+
* @library /tools/lib
30+
* @modules jdk.compiler/com.sun.tools.javac.code
31+
* @compile ExtendedStandardFlagsOverlayFlagsConflict.java
32+
* @run main ExtendedStandardFlagsOverlayFlagsConflict
33+
*/
34+
35+
import com.sun.tools.javac.code.Flags;
36+
import java.lang.reflect.Field;
37+
import java.lang.reflect.Modifier;
38+
import java.util.ArrayList;
39+
import java.util.HashMap;
40+
import java.util.List;
41+
import java.util.Map;
42+
43+
/* Flags in ExtendedStandardFlags are checked using masks, and if they have
44+
* Symbol-kind specific meaning, they can lead to confusing errors. Hence,
45+
* Flags in ExtendedStandardFlags should have the same meaning for all Symbols.
46+
*/
47+
public class ExtendedStandardFlagsOverlayFlagsConflict {
48+
49+
public static void main(String... args) throws Exception {
50+
ExtendedStandardFlagsOverlayFlagsConflict t =
51+
new ExtendedStandardFlagsOverlayFlagsConflict();
52+
t.run();
53+
}
54+
55+
public void run() throws Exception {
56+
Map<Long, List<Field>> value2FlagFields = new HashMap<>();
57+
58+
for (Field f : Flags.class.getFields()) {
59+
if (!Modifier.isStatic(f.getModifiers())) {
60+
continue;
61+
}
62+
if (f.getName().startsWith("ACC_")) {
63+
continue;
64+
}
65+
long flag = ((Number) f.get(null)).longValue();
66+
value2FlagFields.computeIfAbsent(flag, _ -> new ArrayList<>())
67+
.add(f);
68+
}
69+
70+
long pendingFlags2Check = Flags.ExtendedStandardFlags;
71+
72+
while (pendingFlags2Check != 0) {
73+
long flag = Long.highestOneBit(pendingFlags2Check);
74+
List<Field> flagFields = value2FlagFields.get(flag);
75+
if (flagFields.size() != 1) {
76+
throw new AssertionError("Flag: " + flag +
77+
" has more than one flag field: " + flagFields);
78+
}
79+
pendingFlags2Check &= ~flag;
80+
}
81+
}
82+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* @test /nodynamiccopyright/
3+
* @bug 8361570
4+
* @summary Verify there's no fake sealed not allowed here error when sealed
5+
* and requires-identity Flags clash
6+
* @modules java.base/jdk.internal
7+
* @compile NoFalseSealedError.java
8+
*/
9+
10+
import java.lang.ref.WeakReference;
11+
import java.util.WeakHashMap;
12+
13+
void main(String[] args) {
14+
new RequiresIdentity(null) {};
15+
new WeakReference<>(null) {};
16+
new WeakHashMap<>() {};
17+
}
18+
19+
static class RequiresIdentity {
20+
RequiresIdentity(@jdk.internal.RequiresIdentity Object o) {}
21+
}

test/langtools/tools/javac/platform/RequiresIdentityTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public void testModel(Path base) throws Exception {
132132

133133
List<String> expected = List.of(
134134
"public class WeakHashMap<@jdk.internal.RequiresIdentity K, V> extends java.util.AbstractMap<K,V> implements java.util.Map<K,V> {",
135-
" public V put(@jdk.internal.RequiresIdentity sealed K key,"
135+
" public V put(@jdk.internal.RequiresIdentity K key,"
136136
);
137137
if (!expected.equals(printed)) {
138138
throw new AssertionError("Expected: " + expected +
@@ -154,7 +154,7 @@ public void testModel(Path base) throws Exception {
154154

155155
List<String> expected = List.of(
156156
"public class WeakHashMap<K, V> extends java.util.AbstractMap<K,V> implements java.util.Map<K,V> {",
157-
" public V put(sealed K arg0,"
157+
" public V put(K arg0,"
158158
);
159159
if (!expected.equals(printed)) {
160160
throw new AssertionError("Expected: " + expected +

0 commit comments

Comments
 (0)