< prev index next > src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
Print this page
return (t.hasTag(TYPEVAR))
? diags.fragment(Fragments.TypeParameter(t))
: t;
}
+ void checkConstraintsOfValueClass(JCClassDecl tree, ClassSymbol c) {
+ DiagnosticPosition pos = tree.pos();
+ for (Type st : types.closure(c.type)) {
+ if (st == null || st.tsym == null || st.tsym.kind == ERR)
+ continue;
+ if (st.tsym == syms.objectType.tsym || st.tsym == syms.recordType.tsym || st.isInterface())
+ continue;
+ if (!st.tsym.isAbstract()) {
+ if (c != st.tsym) {
+ log.error(pos, Errors.ConcreteSupertypeForValueClass(c, st));
+ }
+ continue;
+ }
+ // dealing with an abstract value or value super class below.
+ for (Symbol s : st.tsym.members().getSymbols(NON_RECURSIVE)) {
+ if (s.kind == MTH) {
+ if ((s.flags() & (SYNCHRONIZED | STATIC)) == SYNCHRONIZED) {
+ log.error(pos, Errors.SuperClassMethodCannotBeSynchronized(s, c, st));
+ }
+ break;
+ }
+ }
+ }
+ }
+
/** Check that type is a valid qualifier for a constructor reference expression
*/
Type checkConstructorRefType(DiagnosticPosition pos, Type t) {
t = checkClassOrArrayType(pos, t);
if (t.hasTag(CLASS)) {
return typeTagError(pos,
diags.fragment(Fragments.TypeReqRef),
t);
}
+ /** Check that type is an identity type, i.e. not a value type.
+ * When not discernible statically, give it the benefit of doubt
+ * and defer to runtime.
+ *
+ * @param pos Position to be used for error reporting.
+ * @param t The type to be checked.
+ */
+ void checkIdentityType(DiagnosticPosition pos, Type t) {
+ if (t.hasTag(TYPEVAR)) {
+ t = types.skipTypeVars(t, false);
+ }
+ if (t.isIntersection()) {
+ IntersectionClassType ict = (IntersectionClassType)t;
+ for (Type component : ict.getExplicitComponents()) {
+ checkIdentityType(pos, component);
+ }
+ return;
+ }
+ if (t.isPrimitive() || (t.isValueClass() && !t.tsym.isAbstract()))
+ typeTagError(pos, diags.fragment(Fragments.TypeReqIdentity), t);
+ }
+
/** Check that each type is a reference type, i.e. a class, interface or array type
* or a type variable.
* @param trees Original trees, used for error reporting.
* @param types The types to be checked.
*/
mask = ReceiverParamFlags;
else if (sym.owner.kind != TYP)
mask = LocalVarFlags;
else if ((sym.owner.flags_field & INTERFACE) != 0)
mask = implicit = InterfaceVarFlags;
! else
! mask = VarFlags;
break;
case MTH:
if (sym.name == names.init) {
if ((sym.owner.flags_field & ENUM) != 0) {
// enum constructors cannot be declared public or
mask = ReceiverParamFlags;
else if (sym.owner.kind != TYP)
mask = LocalVarFlags;
else if ((sym.owner.flags_field & INTERFACE) != 0)
mask = implicit = InterfaceVarFlags;
! else {
! boolean isInstanceFieldOfValueClass = sym.owner.type.isValueClass() && (flags & STATIC) == 0;
+ mask = !isInstanceFieldOfValueClass ? VarFlags : ExtendedVarFlags;
+ if (isInstanceFieldOfValueClass) {
+ implicit |= FINAL | STRICT;
+ }
+ }
break;
case MTH:
if (sym.name == names.init) {
if ((sym.owner.flags_field & ENUM) != 0) {
// enum constructors cannot be declared public or
}
} else {
mask = implicit = InterfaceMethodFlags;
}
} else if ((sym.owner.flags_field & RECORD) != 0) {
! mask = RecordMethodFlags;
} else {
! mask = MethodFlags;
}
if ((flags & STRICTFP) != 0) {
warnOnExplicitStrictfp(pos);
}
// Imply STRICTFP if owner has STRICTFP set.
}
} else {
mask = implicit = InterfaceMethodFlags;
}
} else if ((sym.owner.flags_field & RECORD) != 0) {
! mask = ((sym.owner.flags_field & VALUE_CLASS) != 0 && (flags & Flags.STATIC) == 0) ?
+ RecordMethodFlags & ~SYNCHRONIZED : RecordMethodFlags;
} else {
! // value objects do not have an associated monitor/lock
+ mask = ((sym.owner.flags_field & VALUE_CLASS) != 0 && (flags & Flags.STATIC) == 0) ?
+ MethodFlags & ~SYNCHRONIZED : MethodFlags;
}
if ((flags & STRICTFP) != 0) {
warnOnExplicitStrictfp(pos);
}
// Imply STRICTFP if owner has STRICTFP set.
(sym.isDirectlyOrIndirectlyLocal() && (flags & ANNOTATION) != 0)) {
boolean implicitlyStatic = !sym.isAnonymous() &&
((flags & RECORD) != 0 || (flags & ENUM) != 0 || (flags & INTERFACE) != 0);
boolean staticOrImplicitlyStatic = (flags & STATIC) != 0 || implicitlyStatic;
// local statics are allowed only if records are allowed too
! mask = staticOrImplicitlyStatic && allowRecords && (flags & ANNOTATION) == 0 ? StaticLocalFlags : LocalClassFlags;
implicit = implicitlyStatic ? STATIC : implicit;
} else if (sym.owner.kind == TYP) {
// statics in inner classes are allowed only if records are allowed too
mask = ((flags & STATIC) != 0) && allowRecords && (flags & ANNOTATION) == 0 ? ExtendedMemberStaticClassFlags : ExtendedMemberClassFlags;
if (sym.owner.owner.kind == PCK ||
(sym.isDirectlyOrIndirectlyLocal() && (flags & ANNOTATION) != 0)) {
boolean implicitlyStatic = !sym.isAnonymous() &&
((flags & RECORD) != 0 || (flags & ENUM) != 0 || (flags & INTERFACE) != 0);
boolean staticOrImplicitlyStatic = (flags & STATIC) != 0 || implicitlyStatic;
// local statics are allowed only if records are allowed too
! mask = staticOrImplicitlyStatic && allowRecords && (flags & ANNOTATION) == 0 ? ExtendedStaticLocalClassFlags : ExtendedLocalClassFlags;
implicit = implicitlyStatic ? STATIC : implicit;
} else if (sym.owner.kind == TYP) {
// statics in inner classes are allowed only if records are allowed too
mask = ((flags & STATIC) != 0) && allowRecords && (flags & ANNOTATION) == 0 ? ExtendedMemberStaticClassFlags : ExtendedMemberClassFlags;
if (sym.owner.owner.kind == PCK ||
mask = ExtendedClassFlags;
}
// Interfaces are always ABSTRACT
if ((flags & INTERFACE) != 0) implicit |= ABSTRACT;
if ((flags & ENUM) != 0) {
! // enums can't be declared abstract, final, sealed or non-sealed
! mask &= ~(ABSTRACT | FINAL | SEALED | NON_SEALED);
implicit |= implicitEnumFinalFlag(tree);
}
if ((flags & RECORD) != 0) {
// records can't be declared abstract
mask &= ~ABSTRACT;
mask = ExtendedClassFlags;
}
// Interfaces are always ABSTRACT
if ((flags & INTERFACE) != 0) implicit |= ABSTRACT;
+ if ((flags & (INTERFACE | VALUE_CLASS)) == 0) {
+ implicit |= IDENTITY_TYPE;
+ }
+
if ((flags & ENUM) != 0) {
! // enums can't be declared abstract, final, sealed or non-sealed or value
! mask &= ~(ABSTRACT | FINAL | SEALED | NON_SEALED | VALUE_CLASS);
implicit |= implicitEnumFinalFlag(tree);
}
if ((flags & RECORD) != 0) {
// records can't be declared abstract
mask &= ~ABSTRACT;
if ((flags & STRICTFP) != 0) {
warnOnExplicitStrictfp(pos);
}
// Imply STRICTFP if owner has STRICTFP set.
implicit |= sym.owner.flags_field & STRICTFP;
+
+ // concrete value classes are implicitly final
+ if ((flags & (ABSTRACT | INTERFACE | VALUE_CLASS)) == VALUE_CLASS) {
+ implicit |= FINAL;
+ }
+
+ // TYPs can't be declared synchronized
+ mask &= ~SYNCHRONIZED;
break;
default:
throw new AssertionError();
}
long illegal = flags & ExtendedStandardFlags & ~mask;
&&
checkDisjoint(pos, flags,
ABSTRACT | INTERFACE,
FINAL | NATIVE | SYNCHRONIZED)
&&
checkDisjoint(pos, flags,
PUBLIC,
PRIVATE | PROTECTED)
&&
checkDisjoint(pos, flags,
PRIVATE,
PUBLIC | PROTECTED)
&&
! checkDisjoint(pos, flags,
FINAL,
VOLATILE)
&&
(sym.kind == TYP ||
checkDisjoint(pos, flags,
&&
checkDisjoint(pos, flags,
ABSTRACT | INTERFACE,
FINAL | NATIVE | SYNCHRONIZED)
&&
+ checkDisjoint(pos, flags,
+ INTERFACE,
+ VALUE_CLASS)
+ &&
checkDisjoint(pos, flags,
PUBLIC,
PRIVATE | PROTECTED)
&&
checkDisjoint(pos, flags,
PRIVATE,
PUBLIC | PROTECTED)
&&
! checkDisjoint(pos, (flags | implicit), // complain against volatile & implcitly final entities too.
FINAL,
VOLATILE)
&&
(sym.kind == TYP ||
checkDisjoint(pos, flags,
&& checkDisjoint(pos, flags,
SEALED,
FINAL | NON_SEALED)
&& checkDisjoint(pos, flags,
SEALED,
! ANNOTATION)) {
// skip
}
return flags & (mask | ~ExtendedStandardFlags) | implicit;
}
&& checkDisjoint(pos, flags,
SEALED,
FINAL | NON_SEALED)
&& checkDisjoint(pos, flags,
SEALED,
! ANNOTATION)
+ && checkDisjoint(pos, flags,
+ VALUE_CLASS,
+ ANNOTATION)
+ && checkDisjoint(pos, flags,
+ VALUE_CLASS,
+ NON_SEALED)
+ && checkDisjoint(pos, flags,
+ VALUE_CLASS,
+ INTERFACE) ) {
// skip
}
return flags & (mask | ~ExtendedStandardFlags) | implicit;
}
for (List<Type> m = supertypes; m != l; m = m.tail)
if (!checkCompatibleAbstracts(pos, l.head, m.head, c))
return;
}
checkCompatibleConcretes(pos, c);
+
+ boolean cIsValue = (c.tsym.flags() & VALUE_CLASS) != 0;
+ Type identitySuper = null, valueSuper = null;
+ for (Type t : types.closure(c)) {
+ if (t != c) {
+ if ((t.tsym.flags() & IDENTITY_TYPE) != 0 && (t.tsym.flags() & VALUE_BASED) == 0)
+ identitySuper = t;
+ else if ((t.tsym.flags() & VALUE_CLASS) != 0)
+ valueSuper = t;
+ if (cIsValue && identitySuper != null && identitySuper.tsym != syms.objectType.tsym) { // Object is special
+ log.error(pos, Errors.ValueTypeHasIdentitySuperType(c, identitySuper));
+ break;
+ }
+ }
+ }
}
/** Check that all non-override equivalent methods accessible from 'site'
* are mutually compatible (JLS 8.4.8/9.4.1).
*
if (initCall != null) {
log.error(apply.pos(), Errors.RedundantSuperclassInit);
break;
}
// If super()/this() isn't first, require "statements before super()" feature
! if (!firstStatement)
preview.checkSourceLevel(apply.pos(), Feature.SUPER_INIT);
// We found a legitimate super()/this() call; remember it
initCall = methodName;
} while (false);
if (initCall != null) {
log.error(apply.pos(), Errors.RedundantSuperclassInit);
break;
}
+ // valhalla is using this feature so commenting this code for now so that the
+ // build doesn't depend on preview code
// If super()/this() isn't first, require "statements before super()" feature
! /*if (!firstStatement) {
preview.checkSourceLevel(apply.pos(), Feature.SUPER_INIT);
+ }*/
// We found a legitimate super()/this() call; remember it
initCall = methodName;
} while (false);
< prev index next >