< prev index next > src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
Print this page
import com.sun.tools.javac.file.BaseFileManager;
import com.sun.tools.javac.file.PathFileObject;
import com.sun.tools.javac.jvm.ClassFile.Version;
import com.sun.tools.javac.jvm.PoolConstant.NameAndType;
import com.sun.tools.javac.main.Option;
+ import com.sun.tools.javac.resources.CompilerProperties;
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.JCTree;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.ByteBuffer.UnderflowException;
import com.sun.tools.javac.util.DefinedBy.Api;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.JCDiagnostic.Fragment;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Kinds.Kind.*;
import com.sun.tools.javac.code.Scope.LookupKind;
+ import static com.sun.tools.javac.code.Scope.LookupKind.NON_RECURSIVE;
import static com.sun.tools.javac.code.TypeTag.ARRAY;
import static com.sun.tools.javac.code.TypeTag.CLASS;
import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
import static com.sun.tools.javac.jvm.ClassFile.*;
import static com.sun.tools.javac.jvm.ClassFile.Version.*;
/** Switch: allow modules.
*/
boolean allowModules;
+ /** Switch: allow value classes.
+ */
+ boolean allowValueClasses;
+
/** Switch: allow sealed
*/
boolean allowSealedTypes;
/** Switch: allow records
verbose = options.isSet(Option.VERBOSE);
Source source = Source.instance(context);
preview = Preview.instance(context);
allowModules = Feature.MODULES.allowedInSource(source);
+ allowValueClasses = (!preview.isPreview(Feature.VALUE_CLASSES) || preview.isEnabled()) &&
+ Feature.VALUE_CLASSES.allowedInSource(source);
allowRecords = Feature.RECORDS.allowedInSource(source);
allowSealedTypes = Feature.SEALED_CLASSES.allowedInSource(source);
warnOnIllegalUtf8 = Feature.WARN_ON_ILLEGAL_UTF8.allowedInSource(source);
saveParameterNames = options.isSet(PARAMETERS);
ClassSymbol t = enterClass(readName(signatureBuffer,
startSbp,
sbp - startSbp));
try {
! return (outer == Type.noType) ?
! t.erasure(types) :
! new ClassType(outer, List.nil(), t);
} finally {
sbp = startSbp;
}
}
ClassSymbol t = enterClass(readName(signatureBuffer,
startSbp,
sbp - startSbp));
try {
! if (outer == Type.noType) {
! ClassType et = (ClassType) t.erasure(types);
! return new ClassType(et.getEnclosingType(), List.nil(), et.tsym, et.getMetadata());
+ }
+ return new ClassType(outer, List.nil(), t, List.nil());
} finally {
sbp = startSbp;
}
}
* this additional local variable and depend on field ClassType::typarams_field which `actuals` is
* assigned to but then we would have a dependendy on the internal representation of ClassType which
* could change in the future
*/
final List<Type> actualsCp = actuals;
! outer = new ClassType(outer, actuals, t) {
boolean completed = false;
boolean typeArgsSet = false;
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public Type getEnclosingType() {
if (!completed) {
* this additional local variable and depend on field ClassType::typarams_field which `actuals` is
* assigned to but then we would have a dependendy on the internal representation of ClassType which
* could change in the future
*/
final List<Type> actualsCp = actuals;
! outer = new ClassType(outer, actuals, t, List.nil()) {
boolean completed = false;
boolean typeArgsSet = false;
@Override @DefinedBy(Api.LANGUAGE_MODEL)
public Type getEnclosingType() {
if (!completed) {
//we have seen an enclosing non-generic class
if (outer != Type.noType) {
t = enterClass(readName(signatureBuffer,
startSbp,
sbp - startSbp));
! outer = new ClassType(outer, List.nil(), t);
}
signatureBuffer[sbp++] = (byte)'$';
continue;
case '/':
signatureBuffer[sbp++] = (byte)'.';
//we have seen an enclosing non-generic class
if (outer != Type.noType) {
t = enterClass(readName(signatureBuffer,
startSbp,
sbp - startSbp));
! outer = new ClassType(outer, List.nil(), t, List.nil());
}
signatureBuffer[sbp++] = (byte)'$';
continue;
case '/':
signatureBuffer[sbp++] = (byte)'.';
sym.flags_field |= PREVIEW_API;
setFlagIfAttributeTrue(proxy, sym, names.reflective, PREVIEW_REFLECTIVE);
} else if (proxy.type.tsym.flatName() == syms.valueBasedInternalType.tsym.flatName()) {
Assert.check(sym.kind == TYP);
sym.flags_field |= VALUE_BASED;
+ } else if (proxy.type.tsym.flatName() == syms.migratedValueClassInternalType.tsym.flatName()) {
+ Assert.check(sym.kind == TYP);
+ sym.flags_field |= MIGRATED_VALUE_CLASS;
+ if (needsValueFlag(sym, sym.flags_field)) {
+ sym.flags_field |= VALUE_CLASS;
+ sym.flags_field &= ~IDENTITY_TYPE;
+ }
} else if (proxy.type.tsym.flatName() == syms.restrictedInternalType.tsym.flatName()) {
Assert.check(sym.kind == MTH);
sym.flags_field |= RESTRICTED;
} else {
if (proxy.type.tsym == syms.annotationTargetType.tsym) {
} else if (proxy.type.tsym == syms.previewFeatureType.tsym) {
sym.flags_field |= PREVIEW_API;
setFlagIfAttributeTrue(proxy, sym, names.reflective, PREVIEW_REFLECTIVE);
} else if (proxy.type.tsym == syms.valueBasedType.tsym && sym.kind == TYP) {
sym.flags_field |= VALUE_BASED;
+ } else if (proxy.type.tsym == syms.migratedValueClassType.tsym && sym.kind == TYP) {
+ sym.flags_field |= MIGRATED_VALUE_CLASS;
+ if (needsValueFlag(sym, sym.flags_field)) {
+ sym.flags_field |= VALUE_CLASS;
+ sym.flags_field &= ~IDENTITY_TYPE;
+ }
} else if (proxy.type.tsym == syms.restrictedType.tsym) {
Assert.check(sym.kind == MTH);
sym.flags_field |= RESTRICTED;
}
proxies.append(proxy);
if (ct.getEnclosingType().hasTag(CLASS))
enterTypevars(c.owner, ct.getEnclosingType());
// read flags, or skip if this is an inner class
long f = nextChar();
! long flags = adjustClassFlags(f);
if ((flags & MODULE) == 0) {
if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags;
// read own class name and check that it matches
currentModule = c.packge().modle;
ClassSymbol self = poolReader.getClass(nextChar());
if (ct.getEnclosingType().hasTag(CLASS))
enterTypevars(c.owner, ct.getEnclosingType());
// read flags, or skip if this is an inner class
long f = nextChar();
! long flags = adjustClassFlags(c, f);
if ((flags & MODULE) == 0) {
if (c.owner.kind == PCK || c.owner.kind == ERR) c.flags_field = flags;
// read own class name and check that it matches
currentModule = c.packge().modle;
ClassSymbol self = poolReader.getClass(nextChar());
int outerIdx = nextChar();
int nameIdx = nextChar();
ClassSymbol outer = optPoolEntry(outerIdx, poolReader::getClass, null);
Name name = optPoolEntry(nameIdx, poolReader::getName, names.empty);
if (name == null) name = names.empty;
! long flags = adjustClassFlags(nextChar());
if (outer != null) { // we have a member class
if (name == names.empty)
name = names.one;
ClassSymbol member = enterClass(name, outer);
if ((flags & STATIC) == 0) {
int outerIdx = nextChar();
int nameIdx = nextChar();
ClassSymbol outer = optPoolEntry(outerIdx, poolReader::getClass, null);
Name name = optPoolEntry(nameIdx, poolReader::getName, names.empty);
if (name == null) name = names.empty;
! long flags = adjustClassFlags(c, nextChar());
if (outer != null) { // we have a member class
if (name == names.empty)
name = names.one;
ClassSymbol member = enterClass(name, outer);
if ((flags & STATIC) == 0) {
/* **********************************************************************
* Adjusting flags
***********************************************************************/
long adjustFieldFlags(long flags) {
+ boolean previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
+ if (allowValueClasses && previewClassFile && (flags & ACC_STRICT) != 0) {
+ flags &= ~ACC_STRICT;
+ flags |= STRICT;
+ }
return flags;
}
long adjustMethodFlags(long flags) {
if ((flags & ACC_BRIDGE) != 0) {
flags |= VARARGS;
}
return flags;
}
! long adjustClassFlags(long flags) {
if ((flags & ACC_MODULE) != 0) {
flags &= ~ACC_MODULE;
flags |= MODULE;
}
! return flags & ~ACC_SUPER; // SUPER and SYNCHRONIZED bits overloaded
}
/**
* A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
* The attribute is only the last component of the original filename, so is unlikely
flags |= VARARGS;
}
return flags;
}
! long adjustClassFlags(ClassSymbol c, long flags) {
if ((flags & ACC_MODULE) != 0) {
flags &= ~ACC_MODULE;
flags |= MODULE;
}
! if (((flags & ACC_IDENTITY) != 0 && !isMigratedValueClass(flags)) || (majorVersion < V67.major && (flags & INTERFACE) == 0)) {
+ flags |= IDENTITY_TYPE;
+ } else if (needsValueFlag(c, flags)) {
+ flags |= VALUE_CLASS;
+ flags &= ~IDENTITY_TYPE;
+ }
+ flags &= ~ACC_IDENTITY; // ACC_IDENTITY and SYNCHRONIZED bits overloaded
+ return flags;
+ }
+
+ private boolean needsValueFlag(Symbol c, long flags) {
+ boolean previewClassFile = minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
+ if (allowValueClasses) {
+ if (previewClassFile && majorVersion >= V67.major && (flags & INTERFACE) == 0 ||
+ majorVersion >= V67.major && isMigratedValueClass(flags)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isMigratedValueClass(long flags) {
+ return allowValueClasses && ((flags & MIGRATED_VALUE_CLASS) != 0);
}
/**
* A subclass of JavaFileObject for the sourcefile attribute found in a classfile.
* The attribute is only the last component of the original filename, so is unlikely
< prev index next >