--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java Thu Feb 19 16:38:54 2015 -0800
@@ -200,9 +200,6 @@
*/
public final VarSymbol lengthVar;
- /** The null check operator. */
- public final OperatorSymbol nullcheck;
-
/** The symbol representing the final finalize method on enums */
public final MethodSymbol enumFinalFinalize;
@@ -217,10 +214,6 @@
*/
public final Name[] boxedName = new Name[TypeTag.getTypeTagCount()];
- /** A set containing all operator names.
- */
- public final Set<Name> operatorNames = new HashSet<>();
-
/** A hashtable containing the encountered top-level and member classes,
* indexed by flat names. The table does not contain local classes.
* It should be updated from the outside to reflect classes defined
@@ -255,85 +248,6 @@
*/
public final ClassSymbol predefClass;
- /** Enter a constant into symbol table.
- * @param name The constant's name.
- * @param type The constant's type.
- */
- private VarSymbol enterConstant(String name, Type type) {
- VarSymbol c = new VarSymbol(
- PUBLIC | STATIC | FINAL,
- names.fromString(name),
- type,
- predefClass);
- c.setData(type.constValue());
- predefClass.members().enter(c);
- return c;
- }
-
- /** Enter a binary operation into symbol table.
- * @param name The name of the operator.
- * @param left The type of the left operand.
- * @param right The type of the left operand.
- * @param res The operation's result type.
- * @param opcode The operation's bytecode instruction.
- */
- private void enterBinop(String name,
- Type left, Type right, Type res,
- int opcode) {
- predefClass.members().enter(
- new OperatorSymbol(
- makeOperatorName(name),
- new MethodType(List.of(left, right), res,
- List.<Type>nil(), methodClass),
- opcode,
- predefClass));
- }
-
- /** Enter a binary operation, as above but with two opcodes,
- * which get encoded as
- * {@code (opcode1 << ByteCodeTags.preShift) + opcode2 }.
- * @param opcode1 First opcode.
- * @param opcode2 Second opcode.
- */
- private void enterBinop(String name,
- Type left, Type right, Type res,
- int opcode1, int opcode2) {
- enterBinop(
- name, left, right, res, (opcode1 << ByteCodes.preShift) | opcode2);
- }
-
- /** Enter a unary operation into symbol table.
- * @param name The name of the operator.
- * @param arg The type of the operand.
- * @param res The operation's result type.
- * @param opcode The operation's bytecode instruction.
- */
- private OperatorSymbol enterUnop(String name,
- Type arg,
- Type res,
- int opcode) {
- OperatorSymbol sym =
- new OperatorSymbol(makeOperatorName(name),
- new MethodType(List.of(arg),
- res,
- List.<Type>nil(),
- methodClass),
- opcode,
- predefClass);
- predefClass.members().enter(sym);
- return sym;
- }
-
- /**
- * Create a new operator name from corresponding String representation
- * and add the name to the set of known operator names.
- */
- private Name makeOperatorName(String name) {
- Name opName = names.fromString(name);
- operatorNames.add(opName);
- return opName;
- }
-
/** Enter a class into symbol table.
* @param s The name of the class.
*/
@@ -591,163 +505,6 @@
List.<Type>nil(), methodClass),
arrayClass);
arrayClass.members().enter(arrayCloneMethod);
-
- // Enter operators.
- /* Internally we use +++, --- for unary +, - to reduce +, - operators
- * overloading
- */
- enterUnop("+++", doubleType, doubleType, nop);
- enterUnop("+++", floatType, floatType, nop);
- enterUnop("+++", longType, longType, nop);
- enterUnop("+++", intType, intType, nop);
-
- enterUnop("---", doubleType, doubleType, dneg);
- enterUnop("---", floatType, floatType, fneg);
- enterUnop("---", longType, longType, lneg);
- enterUnop("---", intType, intType, ineg);
-
- enterUnop("~", longType, longType, lxor);
- enterUnop("~", intType, intType, ixor);
-
- enterUnop("++", doubleType, doubleType, dadd);
- enterUnop("++", floatType, floatType, fadd);
- enterUnop("++", longType, longType, ladd);
- enterUnop("++", intType, intType, iadd);
- enterUnop("++", charType, charType, iadd);
- enterUnop("++", shortType, shortType, iadd);
- enterUnop("++", byteType, byteType, iadd);
-
- enterUnop("--", doubleType, doubleType, dsub);
- enterUnop("--", floatType, floatType, fsub);
- enterUnop("--", longType, longType, lsub);
- enterUnop("--", intType, intType, isub);
- enterUnop("--", charType, charType, isub);
- enterUnop("--", shortType, shortType, isub);
- enterUnop("--", byteType, byteType, isub);
-
- enterUnop("!", booleanType, booleanType, bool_not);
- nullcheck = enterUnop("<*nullchk*>", objectType, objectType, nullchk);
-
- // string concatenation
- enterBinop("+", stringType, objectType, stringType, string_add);
- enterBinop("+", objectType, stringType, stringType, string_add);
- enterBinop("+", stringType, stringType, stringType, string_add);
- enterBinop("+", stringType, intType, stringType, string_add);
- enterBinop("+", stringType, longType, stringType, string_add);
- enterBinop("+", stringType, floatType, stringType, string_add);
- enterBinop("+", stringType, doubleType, stringType, string_add);
- enterBinop("+", stringType, booleanType, stringType, string_add);
- enterBinop("+", stringType, botType, stringType, string_add);
- enterBinop("+", intType, stringType, stringType, string_add);
- enterBinop("+", longType, stringType, stringType, string_add);
- enterBinop("+", floatType, stringType, stringType, string_add);
- enterBinop("+", doubleType, stringType, stringType, string_add);
- enterBinop("+", booleanType, stringType, stringType, string_add);
- enterBinop("+", botType, stringType, stringType, string_add);
-
- // these errors would otherwise be matched as string concatenation
- enterBinop("+", botType, botType, botType, error);
- enterBinop("+", botType, intType, botType, error);
- enterBinop("+", botType, longType, botType, error);
- enterBinop("+", botType, floatType, botType, error);
- enterBinop("+", botType, doubleType, botType, error);
- enterBinop("+", botType, booleanType, botType, error);
- enterBinop("+", botType, objectType, botType, error);
- enterBinop("+", intType, botType, botType, error);
- enterBinop("+", longType, botType, botType, error);
- enterBinop("+", floatType, botType, botType, error);
- enterBinop("+", doubleType, botType, botType, error);
- enterBinop("+", booleanType, botType, botType, error);
- enterBinop("+", objectType, botType, botType, error);
-
- enterBinop("+", doubleType, doubleType, doubleType, dadd);
- enterBinop("+", floatType, floatType, floatType, fadd);
- enterBinop("+", longType, longType, longType, ladd);
- enterBinop("+", intType, intType, intType, iadd);
-
- enterBinop("-", doubleType, doubleType, doubleType, dsub);
- enterBinop("-", floatType, floatType, floatType, fsub);
- enterBinop("-", longType, longType, longType, lsub);
- enterBinop("-", intType, intType, intType, isub);
-
- enterBinop("*", doubleType, doubleType, doubleType, dmul);
- enterBinop("*", floatType, floatType, floatType, fmul);
- enterBinop("*", longType, longType, longType, lmul);
- enterBinop("*", intType, intType, intType, imul);
-
- enterBinop("/", doubleType, doubleType, doubleType, ddiv);
- enterBinop("/", floatType, floatType, floatType, fdiv);
- enterBinop("/", longType, longType, longType, ldiv);
- enterBinop("/", intType, intType, intType, idiv);
-
- enterBinop("%", doubleType, doubleType, doubleType, dmod);
- enterBinop("%", floatType, floatType, floatType, fmod);
- enterBinop("%", longType, longType, longType, lmod);
- enterBinop("%", intType, intType, intType, imod);
-
- enterBinop("&", booleanType, booleanType, booleanType, iand);
- enterBinop("&", longType, longType, longType, land);
- enterBinop("&", intType, intType, intType, iand);
-
- enterBinop("|", booleanType, booleanType, booleanType, ior);
- enterBinop("|", longType, longType, longType, lor);
- enterBinop("|", intType, intType, intType, ior);
-
- enterBinop("^", booleanType, booleanType, booleanType, ixor);
- enterBinop("^", longType, longType, longType, lxor);
- enterBinop("^", intType, intType, intType, ixor);
-
- enterBinop("<<", longType, longType, longType, lshll);
- enterBinop("<<", intType, longType, intType, ishll);
- enterBinop("<<", longType, intType, longType, lshl);
- enterBinop("<<", intType, intType, intType, ishl);
-
- enterBinop(">>", longType, longType, longType, lshrl);
- enterBinop(">>", intType, longType, intType, ishrl);
- enterBinop(">>", longType, intType, longType, lshr);
- enterBinop(">>", intType, intType, intType, ishr);
-
- enterBinop(">>>", longType, longType, longType, lushrl);
- enterBinop(">>>", intType, longType, intType, iushrl);
- enterBinop(">>>", longType, intType, longType, lushr);
- enterBinop(">>>", intType, intType, intType, iushr);
-
- enterBinop("<", doubleType, doubleType, booleanType, dcmpg, iflt);
- enterBinop("<", floatType, floatType, booleanType, fcmpg, iflt);
- enterBinop("<", longType, longType, booleanType, lcmp, iflt);
- enterBinop("<", intType, intType, booleanType, if_icmplt);
-
- enterBinop(">", doubleType, doubleType, booleanType, dcmpl, ifgt);
- enterBinop(">", floatType, floatType, booleanType, fcmpl, ifgt);
- enterBinop(">", longType, longType, booleanType, lcmp, ifgt);
- enterBinop(">", intType, intType, booleanType, if_icmpgt);
-
- enterBinop("<=", doubleType, doubleType, booleanType, dcmpg, ifle);
- enterBinop("<=", floatType, floatType, booleanType, fcmpg, ifle);
- enterBinop("<=", longType, longType, booleanType, lcmp, ifle);
- enterBinop("<=", intType, intType, booleanType, if_icmple);
-
- enterBinop(">=", doubleType, doubleType, booleanType, dcmpl, ifge);
- enterBinop(">=", floatType, floatType, booleanType, fcmpl, ifge);
- enterBinop(">=", longType, longType, booleanType, lcmp, ifge);
- enterBinop(">=", intType, intType, booleanType, if_icmpge);
-
- enterBinop("==", objectType, objectType, booleanType, if_acmpeq);
- enterBinop("==", booleanType, booleanType, booleanType, if_icmpeq);
- enterBinop("==", doubleType, doubleType, booleanType, dcmpl, ifeq);
- enterBinop("==", floatType, floatType, booleanType, fcmpl, ifeq);
- enterBinop("==", longType, longType, booleanType, lcmp, ifeq);
- enterBinop("==", intType, intType, booleanType, if_icmpeq);
-
- enterBinop("!=", objectType, objectType, booleanType, if_acmpne);
- enterBinop("!=", booleanType, booleanType, booleanType, if_icmpne);
- enterBinop("!=", doubleType, doubleType, booleanType, dcmpl, ifne);
- enterBinop("!=", floatType, floatType, booleanType, fcmpl, ifne);
- enterBinop("!=", longType, longType, booleanType, lcmp, ifne);
- enterBinop("!=", intType, intType, booleanType, if_icmpne);
-
- enterBinop("&&", booleanType, booleanType, booleanType, bool_and);
- enterBinop("||", booleanType, booleanType, booleanType, bool_or);
}
/** Define a new class given its name and owner.
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java Thu Feb 19 16:38:54 2015 -0800
@@ -1445,26 +1445,6 @@
}
// </editor-fold>
- /**
- * Can t and s be compared for equality? Any primitive ==
- * primitive or primitive == object comparisons here are an error.
- * Unboxing and correct primitive == primitive comparisons are
- * already dealt with in Attr.visitBinary.
- *
- */
- public boolean isEqualityComparable(Type s, Type t, Warner warn) {
- if (t.isNumeric() && s.isNumeric())
- return true;
-
- boolean tPrimitive = t.isPrimitive();
- boolean sPrimitive = s.isPrimitive();
- if (!tPrimitive && !sPrimitive) {
- return isCastable(s, t, warn) || isCastable(t, s, warn);
- } else {
- return false;
- }
- }
-
// <editor-fold defaultstate="collapsed" desc="isCastable">
public boolean isCastable(Type t, Type s) {
return isCastable(t, s, noWarnings);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Feb 19 16:38:54 2015 -0800
@@ -82,6 +82,7 @@
final Log log;
final Symtab syms;
final Resolve rs;
+ final Operators operators;
final Infer infer;
final Analyzer analyzer;
final DeferredAttr deferredAttr;
@@ -115,6 +116,7 @@
log = Log.instance(context);
syms = Symtab.instance(context);
rs = Resolve.instance(context);
+ operators = Operators.instance(context);
chk = Check.instance(context);
flow = Flow.instance(context);
memberEnter = MemberEnter.instance(context);
@@ -1467,7 +1469,7 @@
* @param thentype The type of the expression's then-part.
* @param elsetype The type of the expression's else-part.
*/
- private Type condType(DiagnosticPosition pos,
+ Type condType(DiagnosticPosition pos,
Type thentype, Type elsetype) {
// If same type, that is the result
if (types.isSameType(thentype, elsetype))
@@ -2142,7 +2144,7 @@
JCTree.Tag optag = NULLCHK;
JCUnary tree = make.at(arg.pos).Unary(optag, arg);
- tree.operator = syms.nullcheck;
+ tree.operator = operators.resolveUnary(arg, optag, arg.type);
tree.type = arg.type;
return tree;
}
@@ -2903,18 +2905,10 @@
Type owntype = attribTree(tree.lhs, env, varAssignmentInfo);
Type operand = attribExpr(tree.rhs, env);
// Find operator.
- Symbol operator = tree.operator = rs.resolveBinaryOperator(
- tree.pos(), tree.getTag().noAssignOp(), env,
- owntype, operand);
-
+ Symbol operator = tree.operator = operators.resolveBinary(tree, tree.getTag().noAssignOp(), owntype, operand);
if (operator.kind == MTH &&
!owntype.isErroneous() &&
!operand.isErroneous()) {
- chk.checkOperator(tree.pos(),
- (OperatorSymbol)operator,
- tree.getTag().noAssignOp(),
- owntype,
- operand);
chk.checkDivZero(tree.rhs.pos(), operator, operand);
chk.checkCastable(tree.rhs.pos(),
operator.type.getReturnType(),
@@ -2930,9 +2924,7 @@
: chk.checkNonVoid(tree.arg.pos(), attribExpr(tree.arg, env));
// Find operator.
- Symbol operator = tree.operator =
- rs.resolveUnaryOperator(tree.pos(), tree.getTag(), env, argtype);
-
+ Symbol operator = tree.operator = operators.resolveUnary(tree, tree.getTag(), argtype);
Type owntype = types.createErrorType(tree.type);
if (operator.kind == MTH &&
!argtype.isErroneous()) {
@@ -2957,22 +2949,13 @@
Type left = chk.checkNonVoid(tree.lhs.pos(), attribExpr(tree.lhs, env));
Type right = chk.checkNonVoid(tree.lhs.pos(), attribExpr(tree.rhs, env));
// Find operator.
- Symbol operator = tree.operator =
- rs.resolveBinaryOperator(tree.pos(), tree.getTag(), env, left, right);
-
+ Symbol operator = tree.operator = operators.resolveBinary(tree, tree.getTag(), left, right);
Type owntype = types.createErrorType(tree.type);
if (operator.kind == MTH &&
!left.isErroneous() &&
!right.isErroneous()) {
owntype = operator.type.getReturnType();
- // This will figure out when unboxing can happen and
- // choose the right comparison operator.
- int opc = chk.checkOperator(tree.lhs.pos(),
- (OperatorSymbol)operator,
- tree.getTag(),
- left,
- right);
-
+ int opc = ((OperatorSymbol)operator).opcode;
// If both arguments are constants, fold them.
if (left.constValue() != null && right.constValue() != null) {
Type ctype = cfolder.fold2(opc, left, right);
@@ -2985,8 +2968,7 @@
// castable to each other, (JLS 15.21). Note: unboxing
// comparisons will not have an acmp* opc at this point.
if ((opc == ByteCodes.if_acmpeq || opc == ByteCodes.if_acmpne)) {
- if (!types.isEqualityComparable(left, right,
- new Warner(tree.pos()))) {
+ if (!types.isCastable(left, right, new Warner(tree.pos()))) {
log.error(tree.pos(), "incomparable.types", left, right);
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Thu Feb 19 16:38:54 2015 -0800
@@ -83,7 +83,6 @@
private boolean warnOnSyntheticConflicts;
private boolean suppressAbortOnBadClassFile;
private boolean enableSunApiLintControl;
- private final TreeInfo treeinfo;
private final JavaFileManager fileManager;
private final Profile profile;
private final boolean warnOnAccessToSensitiveMembers;
@@ -121,7 +120,6 @@
diags = JCDiagnostic.Factory.instance(context);
Options options = Options.instance(context);
lint = Lint.instance(context);
- treeinfo = TreeInfo.instance(context);
fileManager = context.get(JavaFileManager.class);
Source source = Source.instance(context);
@@ -3265,30 +3263,6 @@
**************************************************************************/
/**
- * Return the opcode of the operator but emit an error if it is an
- * error.
- * @param pos position for error reporting.
- * @param operator an operator
- * @param tag a tree tag
- * @param left type of left hand side
- * @param right type of right hand side
- */
- int checkOperator(DiagnosticPosition pos,
- OperatorSymbol operator,
- JCTree.Tag tag,
- Type left,
- Type right) {
- if (operator.opcode == ByteCodes.error) {
- log.error(pos,
- "operator.cant.be.applied.1",
- treeinfo.operatorName(tag),
- left, right);
- }
- return operator.opcode;
- }
-
-
- /**
* Check for division by integer constant zero
* @param pos Position for error reporting.
* @param operator The operator for the expression
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/DeferredAttr.java Thu Feb 19 16:38:54 2015 -0800
@@ -1386,7 +1386,7 @@
Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
return rec == null ?
rs.findFun(env, name, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) :
- rs.findMethod(env, site, name, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired(), false);
+ rs.findMethod(env, site, name, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired());
}
@Override
Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java Thu Feb 19 16:38:54 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -353,17 +353,17 @@
this.tree = tree;
}
- void resolveJump(JCTree tree) {
+ void resolveJump() {
//do nothing
}
}
- abstract void markDead(JCTree tree);
+ abstract void markDead();
/** Record an outward transfer of control. */
- void recordExit(JCTree tree, P pe) {
+ void recordExit(P pe) {
pendingExits.append(pe);
- markDead(tree);
+ markDead();
}
/** Resolve all jumps of this statement. */
@@ -377,7 +377,7 @@
P exit = exits.head;
if (exit.tree.hasTag(jk.treeTag) &&
jk.getTarget(exit.tree) == tree) {
- exit.resolveJump(tree);
+ exit.resolveJump();
resolved = true;
} else {
pendingExits.append(exit);
@@ -424,7 +424,7 @@
private boolean alive;
@Override
- void markDead(JCTree tree) {
+ void markDead() {
alive = false;
}
@@ -692,21 +692,21 @@
}
public void visitBreak(JCBreak tree) {
- recordExit(tree, new PendingExit(tree));
+ recordExit(new PendingExit(tree));
}
public void visitContinue(JCContinue tree) {
- recordExit(tree, new PendingExit(tree));
+ recordExit(new PendingExit(tree));
}
public void visitReturn(JCReturn tree) {
scan(tree.expr);
- recordExit(tree, new PendingExit(tree));
+ recordExit(new PendingExit(tree));
}
public void visitThrow(JCThrow tree) {
scan(tree.expr);
- markDead(tree);
+ markDead();
}
public void visitApply(JCMethodInvocation tree) {
@@ -803,7 +803,7 @@
}
@Override
- void markDead(JCTree tree) {
+ void markDead() {
//do nothing
}
@@ -1201,16 +1201,16 @@
}
public void visitBreak(JCBreak tree) {
- recordExit(tree, new FlowPendingExit(tree, null));
+ recordExit(new FlowPendingExit(tree, null));
}
public void visitContinue(JCContinue tree) {
- recordExit(tree, new FlowPendingExit(tree, null));
+ recordExit(new FlowPendingExit(tree, null));
}
public void visitReturn(JCReturn tree) {
scan(tree.expr);
- recordExit(tree, new FlowPendingExit(tree, null));
+ recordExit(new FlowPendingExit(tree, null));
}
public void visitThrow(JCThrow tree) {
@@ -1228,7 +1228,7 @@
else {
markThrown(tree, tree.expr.type);
}
- markDead(tree);
+ markDead();
}
public void visitApply(JCMethodInvocation tree) {
@@ -1375,12 +1375,11 @@
* effectively-final local variables/parameters.
*/
- public abstract class AbstractAssignAnalyzer<P extends AbstractAssignAnalyzer<P>.AbstractAssignPendingExit>
- extends BaseAnalyzer<P> {
+ public class AssignAnalyzer extends BaseAnalyzer<AssignAnalyzer.AssignPendingExit> {
/** The set of definitely assigned variables.
*/
- protected Bits inits;
+ final Bits inits;
/** The set of definitely unassigned variables.
*/
@@ -1428,20 +1427,20 @@
*/
WriteableScope unrefdResources;
- /** Set when processing a loop body the second time for DU analysis. */
+ /** Modified when processing a loop body the second time for DU analysis. */
FlowKind flowKind = FlowKind.NORMAL;
- /** The starting position of the analysed tree */
+ /** The starting position of the analyzed tree */
int startPos;
- public class AbstractAssignPendingExit extends BaseAnalyzer.PendingExit {
+ public class AssignPendingExit extends BaseAnalyzer.PendingExit {
final Bits inits;
final Bits uninits;
final Bits exit_inits = new Bits(true);
final Bits exit_uninits = new Bits(true);
- public AbstractAssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
+ public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
super(tree);
this.inits = inits;
this.uninits = uninits;
@@ -1450,13 +1449,13 @@
}
@Override
- public void resolveJump(JCTree tree) {
+ public void resolveJump() {
inits.andSet(exit_inits);
uninits.andSet(exit_uninits);
}
}
- public AbstractAssignAnalyzer() {
+ public AssignAnalyzer() {
this.inits = new Bits();
uninits = new Bits();
uninitsTry = new Bits();
@@ -1469,7 +1468,7 @@
private boolean isInitialConstructor = false;
@Override
- protected void markDead(JCTree tree) {
+ protected void markDead() {
if (!isInitialConstructor) {
inits.inclRange(returnadr, nextadr);
} else {
@@ -1516,35 +1515,43 @@
}
sym.adr = nextadr;
vardecls[nextadr] = varDecl;
- exclVarFromInits(varDecl, nextadr);
+ inits.excl(nextadr);
uninits.incl(nextadr);
nextadr++;
}
- protected void exclVarFromInits(JCTree tree, int adr) {
- inits.excl(adr);
- }
-
- protected void assignToInits(JCTree tree, Bits bits) {
- inits.assign(bits);
- }
-
- protected void andSetInits(JCTree tree, Bits bits) {
- inits.andSet(bits);
- }
-
- protected void orSetInits(JCTree tree, Bits bits) {
- inits.orSet(bits);
- }
-
/** Record an initialization of a trackable variable.
*/
void letInit(DiagnosticPosition pos, VarSymbol sym) {
if (sym.adr >= firstadr && trackable(sym)) {
- if (uninits.isMember(sym.adr)) {
- uninit(sym);
+ if ((sym.flags() & EFFECTIVELY_FINAL) != 0) {
+ if (!uninits.isMember(sym.adr)) {
+ //assignment targeting an effectively final variable
+ //makes the variable lose its status of effectively final
+ //if the variable is _not_ definitively unassigned
+ sym.flags_field &= ~EFFECTIVELY_FINAL;
+ } else {
+ uninit(sym);
+ }
+ }
+ else if ((sym.flags() & FINAL) != 0) {
+ if ((sym.flags() & PARAMETER) != 0) {
+ if ((sym.flags() & UNION) != 0) { //multi-catch parameter
+ log.error(pos, "multicatch.parameter.may.not.be.assigned", sym);
+ }
+ else {
+ log.error(pos, "final.parameter.may.not.be.assigned",
+ sym);
+ }
+ } else if (!uninits.isMember(sym.adr)) {
+ log.error(pos, flowKind.errKey, sym);
+ } else {
+ uninit(sym);
+ }
}
inits.incl(sym.adr);
+ } else if ((sym.flags() & FINAL) != 0) {
+ log.error(pos, "var.might.already.be.assigned", sym);
}
}
//where
@@ -1579,7 +1586,14 @@
checkInit(pos, sym, "var.might.not.have.been.initialized");
}
- void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {}
+ void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {
+ if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
+ trackable(sym) &&
+ !inits.isMember(sym.adr)) {
+ log.error(pos, errkey, sym);
+ inits.incl(sym.adr);
+ }
+ }
/** Utility method to reset several Bits instances.
*/
@@ -1603,7 +1617,7 @@
/** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets.
*/
- protected void merge(JCTree tree) {
+ protected void merge() {
inits.assign(initsWhenFalse.andSet(initsWhenTrue));
uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue));
}
@@ -1619,7 +1633,7 @@
if (tree != null) {
scan(tree);
if (inits.isReset()) {
- merge(tree);
+ merge();
}
}
}
@@ -1637,7 +1651,7 @@
*/
void scanCond(JCTree tree) {
if (tree.type.isFalse()) {
- if (inits.isReset()) merge(tree);
+ if (inits.isReset()) merge();
initsWhenTrue.assign(inits);
initsWhenTrue.inclRange(firstadr, nextadr);
uninitsWhenTrue.assign(uninits);
@@ -1645,7 +1659,7 @@
initsWhenFalse.assign(inits);
uninitsWhenFalse.assign(uninits);
} else if (tree.type.isTrue()) {
- if (inits.isReset()) merge(tree);
+ if (inits.isReset()) merge();
initsWhenFalse.assign(inits);
initsWhenFalse.inclRange(firstadr, nextadr);
uninitsWhenFalse.assign(uninits);
@@ -1664,173 +1678,203 @@
/* ------------ Visitor methods for various sorts of trees -------------*/
- @Override
public void visitClassDef(JCClassDecl tree) {
if (tree.sym == null) {
return;
}
- JCClassDecl classDefPrev = classDef;
- int firstadrPrev = firstadr;
- int nextadrPrev = nextadr;
- ListBuffer<P> pendingExitsPrev = pendingExits;
+ Lint lintPrev = lint;
+ lint = lint.augment(tree.sym);
+ try {
+ if (tree.sym == null) {
+ return;
+ }
+
+ JCClassDecl classDefPrev = classDef;
+ int firstadrPrev = firstadr;
+ int nextadrPrev = nextadr;
+ ListBuffer<AssignPendingExit> pendingExitsPrev = pendingExits;
- pendingExits = new ListBuffer<>();
- if (tree.name != names.empty) {
- firstadr = nextadr;
- }
- classDef = tree;
- try {
- // define all the static fields
- for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
- if (l.head.hasTag(VARDEF)) {
- JCVariableDecl def = (JCVariableDecl)l.head;
- if ((def.mods.flags & STATIC) != 0) {
- VarSymbol sym = def.sym;
- if (trackable(sym)) {
- newVar(def);
+ pendingExits = new ListBuffer<>();
+ if (tree.name != names.empty) {
+ firstadr = nextadr;
+ }
+ classDef = tree;
+ try {
+ // define all the static fields
+ for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
+ if (l.head.hasTag(VARDEF)) {
+ JCVariableDecl def = (JCVariableDecl)l.head;
+ if ((def.mods.flags & STATIC) != 0) {
+ VarSymbol sym = def.sym;
+ if (trackable(sym)) {
+ newVar(def);
+ }
}
}
}
- }
- // process all the static initializers
- for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
- if (!l.head.hasTag(METHODDEF) &&
- (TreeInfo.flags(l.head) & STATIC) != 0) {
- scan(l.head);
+ // process all the static initializers
+ for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
+ if (!l.head.hasTag(METHODDEF) &&
+ (TreeInfo.flags(l.head) & STATIC) != 0) {
+ scan(l.head);
+ }
}
- }
- // define all the instance fields
- for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
- if (l.head.hasTag(VARDEF)) {
- JCVariableDecl def = (JCVariableDecl)l.head;
- if ((def.mods.flags & STATIC) == 0) {
- VarSymbol sym = def.sym;
- if (trackable(sym)) {
- newVar(def);
+ // define all the instance fields
+ for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
+ if (l.head.hasTag(VARDEF)) {
+ JCVariableDecl def = (JCVariableDecl)l.head;
+ if ((def.mods.flags & STATIC) == 0) {
+ VarSymbol sym = def.sym;
+ if (trackable(sym)) {
+ newVar(def);
+ }
}
}
}
- }
- // process all the instance initializers
- for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
- if (!l.head.hasTag(METHODDEF) &&
- (TreeInfo.flags(l.head) & STATIC) == 0) {
- scan(l.head);
+ // process all the instance initializers
+ for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
+ if (!l.head.hasTag(METHODDEF) &&
+ (TreeInfo.flags(l.head) & STATIC) == 0) {
+ scan(l.head);
+ }
}
- }
- // process all the methods
- for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
- if (l.head.hasTag(METHODDEF)) {
- scan(l.head);
+ // process all the methods
+ for (List<JCTree> l = tree.defs; l.nonEmpty(); l = l.tail) {
+ if (l.head.hasTag(METHODDEF)) {
+ scan(l.head);
+ }
}
+ } finally {
+ pendingExits = pendingExitsPrev;
+ nextadr = nextadrPrev;
+ firstadr = firstadrPrev;
+ classDef = classDefPrev;
}
} finally {
- pendingExits = pendingExitsPrev;
- nextadr = nextadrPrev;
- firstadr = firstadrPrev;
- classDef = classDefPrev;
+ lint = lintPrev;
}
}
- @Override
public void visitMethodDef(JCMethodDecl tree) {
if (tree.body == null) {
return;
}
- /* Ignore synthetic methods, except for translated lambda methods.
+
+ /* MemberEnter can generate synthetic methods ignore them
*/
- if ((tree.sym.flags() & (SYNTHETIC | LAMBDA_METHOD)) == SYNTHETIC) {
+ if ((tree.sym.flags() & SYNTHETIC) != 0) {
return;
}
- final Bits initsPrev = new Bits(inits);
- final Bits uninitsPrev = new Bits(uninits);
- int nextadrPrev = nextadr;
- int firstadrPrev = firstadr;
- int returnadrPrev = returnadr;
-
- Assert.check(pendingExits.isEmpty());
- boolean lastInitialConstructor = isInitialConstructor;
+ Lint lintPrev = lint;
+ lint = lint.augment(tree.sym);
try {
- isInitialConstructor = TreeInfo.isInitialConstructor(tree);
-
- if (!isInitialConstructor) {
- firstadr = nextadr;
+ if (tree.body == null) {
+ return;
+ }
+ /* Ignore synthetic methods, except for translated lambda methods.
+ */
+ if ((tree.sym.flags() & (SYNTHETIC | LAMBDA_METHOD)) == SYNTHETIC) {
+ return;
}
- for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
- JCVariableDecl def = l.head;
- scan(def);
- Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag");
- /* If we are executing the code from Gen, then there can be
- * synthetic or mandated variables, ignore them.
- */
- initParam(def);
- }
- // else we are in an instance initializer block;
- // leave caught unchanged.
- scan(tree.body);
+
+ final Bits initsPrev = new Bits(inits);
+ final Bits uninitsPrev = new Bits(uninits);
+ int nextadrPrev = nextadr;
+ int firstadrPrev = firstadr;
+ int returnadrPrev = returnadr;
+
+ Assert.check(pendingExits.isEmpty());
+ boolean lastInitialConstructor = isInitialConstructor;
+ try {
+ isInitialConstructor = TreeInfo.isInitialConstructor(tree);
- if (isInitialConstructor) {
- boolean isSynthesized = (tree.sym.flags() &
- GENERATEDCONSTR) != 0;
- for (int i = firstadr; i < nextadr; i++) {
- JCVariableDecl vardecl = vardecls[i];
- VarSymbol var = vardecl.sym;
- if (var.owner == classDef.sym) {
- // choose the diagnostic position based on whether
- // the ctor is default(synthesized) or not
- if (isSynthesized) {
- checkInit(TreeInfo.diagnosticPositionFor(var, vardecl),
- var, "var.not.initialized.in.default.constructor");
- } else {
- checkInit(TreeInfo.diagEndPos(tree.body), var);
+ if (!isInitialConstructor) {
+ firstadr = nextadr;
+ }
+ for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
+ JCVariableDecl def = l.head;
+ scan(def);
+ Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag");
+ /* If we are executing the code from Gen, then there can be
+ * synthetic or mandated variables, ignore them.
+ */
+ initParam(def);
+ }
+ // else we are in an instance initializer block;
+ // leave caught unchanged.
+ scan(tree.body);
+
+ if (isInitialConstructor) {
+ boolean isSynthesized = (tree.sym.flags() &
+ GENERATEDCONSTR) != 0;
+ for (int i = firstadr; i < nextadr; i++) {
+ JCVariableDecl vardecl = vardecls[i];
+ VarSymbol var = vardecl.sym;
+ if (var.owner == classDef.sym) {
+ // choose the diagnostic position based on whether
+ // the ctor is default(synthesized) or not
+ if (isSynthesized) {
+ checkInit(TreeInfo.diagnosticPositionFor(var, vardecl),
+ var, "var.not.initialized.in.default.constructor");
+ } else {
+ checkInit(TreeInfo.diagEndPos(tree.body), var);
+ }
}
}
}
- }
- List<P> exits = pendingExits.toList();
- pendingExits = new ListBuffer<>();
- while (exits.nonEmpty()) {
- P exit = exits.head;
- exits = exits.tail;
- Assert.check(exit.tree.hasTag(RETURN), exit.tree);
- if (isInitialConstructor) {
- assignToInits(exit.tree, exit.exit_inits);
- for (int i = firstadr; i < nextadr; i++) {
- checkInit(exit.tree.pos(), vardecls[i].sym);
+ List<AssignPendingExit> exits = pendingExits.toList();
+ pendingExits = new ListBuffer<>();
+ while (exits.nonEmpty()) {
+ AssignPendingExit exit = exits.head;
+ exits = exits.tail;
+ Assert.check(exit.tree.hasTag(RETURN), exit.tree);
+ if (isInitialConstructor) {
+ inits.assign(exit.exit_inits);
+ for (int i = firstadr; i < nextadr; i++) {
+ checkInit(exit.tree.pos(), vardecls[i].sym);
+ }
}
}
+ } finally {
+ inits.assign(initsPrev);
+ uninits.assign(uninitsPrev);
+ nextadr = nextadrPrev;
+ firstadr = firstadrPrev;
+ returnadr = returnadrPrev;
+ isInitialConstructor = lastInitialConstructor;
}
} finally {
- assignToInits(tree, initsPrev);
- uninits.assign(uninitsPrev);
- nextadr = nextadrPrev;
- firstadr = firstadrPrev;
- returnadr = returnadrPrev;
- isInitialConstructor = lastInitialConstructor;
+ lint = lintPrev;
}
}
protected void initParam(JCVariableDecl def) {
inits.incl(def.sym.adr);
uninits.excl(def.sym.adr);
- }
+ }
public void visitVarDef(JCVariableDecl tree) {
- boolean track = trackable(tree.sym);
- if (track && tree.sym.owner.kind == MTH) {
- newVar(tree);
- }
- if (tree.init != null) {
- scanExpr(tree.init);
- if (track) {
- letInit(tree.pos(), tree.sym);
+ Lint lintPrev = lint;
+ lint = lint.augment(tree.sym);
+ try{
+ boolean track = trackable(tree.sym);
+ if (track && tree.sym.owner.kind == MTH) {
+ newVar(tree);
}
+ if (tree.init != null) {
+ scanExpr(tree.init);
+ if (track) {
+ letInit(tree.pos(), tree.sym);
+ }
+ }
+ } finally {
+ lint = lintPrev;
}
}
@@ -1840,18 +1884,14 @@
nextadr = nextadrPrev;
}
- int getLogNumberOfErrors() {
- return 0;
- }
-
public void visitDoLoop(JCDoWhileLoop tree) {
- ListBuffer<P> prevPendingExits = pendingExits;
+ ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
FlowKind prevFlowKind = flowKind;
flowKind = FlowKind.NORMAL;
final Bits initsSkip = new Bits(true);
final Bits uninitsSkip = new Bits(true);
pendingExits = new ListBuffer<>();
- int prevErrors = getLogNumberOfErrors();
+ int prevErrors = log.nerrors;
do {
final Bits uninitsEntry = new Bits(uninits);
uninitsEntry.excludeFrom(nextadr);
@@ -1862,28 +1902,28 @@
initsSkip.assign(initsWhenFalse);
uninitsSkip.assign(uninitsWhenFalse);
}
- if (getLogNumberOfErrors() != prevErrors ||
+ if (log.nerrors != prevErrors ||
flowKind.isFinal() ||
new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1)
break;
- assignToInits(tree.cond, initsWhenTrue);
+ inits.assign(initsWhenTrue);
uninits.assign(uninitsEntry.andSet(uninitsWhenTrue));
flowKind = FlowKind.SPECULATIVE_LOOP;
} while (true);
flowKind = prevFlowKind;
- assignToInits(tree, initsSkip);
+ inits.assign(initsSkip);
uninits.assign(uninitsSkip);
resolveBreaks(tree, prevPendingExits);
}
public void visitWhileLoop(JCWhileLoop tree) {
- ListBuffer<P> prevPendingExits = pendingExits;
+ ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
FlowKind prevFlowKind = flowKind;
flowKind = FlowKind.NORMAL;
final Bits initsSkip = new Bits(true);
final Bits uninitsSkip = new Bits(true);
pendingExits = new ListBuffer<>();
- int prevErrors = getLogNumberOfErrors();
+ int prevErrors = log.nerrors;
final Bits uninitsEntry = new Bits(uninits);
uninitsEntry.excludeFrom(nextadr);
do {
@@ -1892,11 +1932,11 @@
initsSkip.assign(initsWhenFalse) ;
uninitsSkip.assign(uninitsWhenFalse);
}
- assignToInits(tree, initsWhenTrue);
+ inits.assign(initsWhenTrue);
uninits.assign(uninitsWhenTrue);
scan(tree.body);
resolveContinues(tree);
- if (getLogNumberOfErrors() != prevErrors ||
+ if (log.nerrors != prevErrors ||
flowKind.isFinal() ||
new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) {
break;
@@ -1907,13 +1947,13 @@
flowKind = prevFlowKind;
//a variable is DA/DU after the while statement, if it's DA/DU assuming the
//branch is not taken AND if it's DA/DU before any break statement
- assignToInits(tree.body, initsSkip);
+ inits.assign(initsSkip);
uninits.assign(uninitsSkip);
resolveBreaks(tree, prevPendingExits);
}
public void visitForLoop(JCForLoop tree) {
- ListBuffer<P> prevPendingExits = pendingExits;
+ ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
FlowKind prevFlowKind = flowKind;
flowKind = FlowKind.NORMAL;
int nextadrPrev = nextadr;
@@ -1921,7 +1961,7 @@
final Bits initsSkip = new Bits(true);
final Bits uninitsSkip = new Bits(true);
pendingExits = new ListBuffer<>();
- int prevErrors = getLogNumberOfErrors();
+ int prevErrors = log.nerrors;
do {
final Bits uninitsEntry = new Bits(uninits);
uninitsEntry.excludeFrom(nextadr);
@@ -1931,7 +1971,7 @@
initsSkip.assign(initsWhenFalse);
uninitsSkip.assign(uninitsWhenFalse);
}
- assignToInits(tree.body, initsWhenTrue);
+ inits.assign(initsWhenTrue);
uninits.assign(uninitsWhenTrue);
} else if (!flowKind.isFinal()) {
initsSkip.assign(inits);
@@ -1942,7 +1982,7 @@
scan(tree.body);
resolveContinues(tree);
scan(tree.step);
- if (getLogNumberOfErrors() != prevErrors ||
+ if (log.nerrors != prevErrors ||
flowKind.isFinal() ||
new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
break;
@@ -1952,7 +1992,7 @@
flowKind = prevFlowKind;
//a variable is DA/DU after a for loop, if it's DA/DU assuming the
//branch is not taken AND if it's DA/DU before any break statement
- assignToInits(tree.body, initsSkip);
+ inits.assign(initsSkip);
uninits.assign(uninitsSkip);
resolveBreaks(tree, prevPendingExits);
nextadr = nextadrPrev;
@@ -1961,7 +2001,7 @@
public void visitForeachLoop(JCEnhancedForLoop tree) {
visitVarDef(tree.var);
- ListBuffer<P> prevPendingExits = pendingExits;
+ ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
FlowKind prevFlowKind = flowKind;
flowKind = FlowKind.NORMAL;
int nextadrPrev = nextadr;
@@ -1971,13 +2011,13 @@
letInit(tree.pos(), tree.var.sym);
pendingExits = new ListBuffer<>();
- int prevErrors = getLogNumberOfErrors();
+ int prevErrors = log.nerrors;
do {
final Bits uninitsEntry = new Bits(uninits);
uninitsEntry.excludeFrom(nextadr);
scan(tree.body);
resolveContinues(tree);
- if (getLogNumberOfErrors() != prevErrors ||
+ if (log.nerrors != prevErrors ||
flowKind.isFinal() ||
new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1)
break;
@@ -1985,21 +2025,21 @@
flowKind = FlowKind.SPECULATIVE_LOOP;
} while (true);
flowKind = prevFlowKind;
- assignToInits(tree.body, initsStart);
+ inits.assign(initsStart);
uninits.assign(uninitsStart.andSet(uninits));
resolveBreaks(tree, prevPendingExits);
nextadr = nextadrPrev;
}
public void visitLabelled(JCLabeledStatement tree) {
- ListBuffer<P> prevPendingExits = pendingExits;
+ ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
pendingExits = new ListBuffer<>();
scan(tree.body);
resolveBreaks(tree, prevPendingExits);
}
public void visitSwitch(JCSwitch tree) {
- ListBuffer<P> prevPendingExits = pendingExits;
+ ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
pendingExits = new ListBuffer<>();
int nextadrPrev = nextadr;
scanExpr(tree.selector);
@@ -2007,7 +2047,7 @@
final Bits uninitsSwitch = new Bits(uninits);
boolean hasDefault = false;
for (List<JCCase> l = tree.cases; l.nonEmpty(); l = l.tail) {
- assignToInits(l.head, initsSwitch);
+ inits.assign(initsSwitch);
uninits.assign(uninits.andSet(uninitsSwitch));
JCCase c = l.head;
if (c.pat == null) {
@@ -2016,19 +2056,19 @@
scanExpr(c.pat);
}
if (hasDefault) {
- assignToInits(null, initsSwitch);
+ inits.assign(initsSwitch);
uninits.assign(uninits.andSet(uninitsSwitch));
}
scan(c.stats);
addVars(c.stats, initsSwitch, uninitsSwitch);
if (!hasDefault) {
- assignToInits(l.head.stats.last(), initsSwitch);
+ inits.assign(initsSwitch);
uninits.assign(uninits.andSet(uninitsSwitch));
}
// Warn about fall-through if lint switch fallthrough enabled.
}
if (!hasDefault) {
- andSetInits(null, initsSwitch);
+ inits.andSet(initsSwitch);
}
resolveBreaks(tree, prevPendingExits);
nextadr = nextadrPrev;
@@ -2047,16 +2087,10 @@
}
}
- boolean isEnabled(Lint.LintCategory lc) {
- return false;
- }
-
- void reportWarning(Lint.LintCategory lc, DiagnosticPosition pos, String key, Object ... args) {}
-
public void visitTry(JCTry tree) {
ListBuffer<JCVariableDecl> resourceVarDecls = new ListBuffer<>();
final Bits uninitsTryPrev = new Bits(uninitsTry);
- ListBuffer<P> prevPendingExits = pendingExits;
+ ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
pendingExits = new ListBuffer<>();
final Bits initsTry = new Bits(inits);
uninitsTry.assign(uninits);
@@ -2079,10 +2113,10 @@
int nextadrCatch = nextadr;
if (!resourceVarDecls.isEmpty() &&
- isEnabled(Lint.LintCategory.TRY)) {
+ lint.isEnabled(Lint.LintCategory.TRY)) {
for (JCVariableDecl resVar : resourceVarDecls) {
if (unrefdResources.includes(resVar.sym)) {
- reportWarning(Lint.LintCategory.TRY, resVar.pos(),
+ log.warning(Lint.LintCategory.TRY, resVar.pos(),
"try.resource.not.referenced", resVar.sym);
unrefdResources.remove(resVar.sym);
}
@@ -2098,7 +2132,7 @@
for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
JCVariableDecl param = l.head.param;
- assignToInits(tree.body, initsCatchPrev);
+ inits.assign(initsCatchPrev);
uninits.assign(uninitsCatchPrev);
scan(param);
/* If this is a TWR and we are executing the code from Gen,
@@ -2111,9 +2145,9 @@
nextadr = nextadrCatch;
}
if (tree.finalizer != null) {
- assignToInits(tree.finalizer, initsTry);
+ inits.assign(initsTry);
uninits.assign(uninitsTry);
- ListBuffer<P> exits = pendingExits;
+ ListBuffer<AssignPendingExit> exits = pendingExits;
pendingExits = prevPendingExits;
scan(tree.finalizer);
if (!tree.finallyCanCompleteNormally) {
@@ -2123,19 +2157,19 @@
// FIX: this doesn't preserve source order of exits in catch
// versus finally!
while (exits.nonEmpty()) {
- P exit = exits.next();
+ AssignPendingExit exit = exits.next();
if (exit.exit_inits != null) {
exit.exit_inits.orSet(inits);
exit.exit_uninits.andSet(uninits);
}
pendingExits.append(exit);
}
- orSetInits(tree, initsEnd);
+ inits.orSet(initsEnd);
}
} else {
- assignToInits(tree, initsEnd);
+ inits.assign(initsEnd);
uninits.assign(uninitsEnd);
- ListBuffer<P> exits = pendingExits;
+ ListBuffer<AssignPendingExit> exits = pendingExits;
pendingExits = prevPendingExits;
while (exits.nonEmpty()) pendingExits.append(exits.next());
}
@@ -2146,7 +2180,7 @@
scanCond(tree.cond);
final Bits initsBeforeElse = new Bits(initsWhenFalse);
final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
- assignToInits(tree.cond, initsWhenTrue);
+ inits.assign(initsWhenTrue);
uninits.assign(uninitsWhenTrue);
if (tree.truepart.type.hasTag(BOOLEAN) &&
tree.falsepart.type.hasTag(BOOLEAN)) {
@@ -2159,7 +2193,7 @@
final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse);
final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue);
final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse);
- assignToInits(tree.truepart, initsBeforeElse);
+ inits.assign(initsBeforeElse);
uninits.assign(uninitsBeforeElse);
scanCond(tree.falsepart);
initsWhenTrue.andSet(initsAfterThenWhenTrue);
@@ -2170,10 +2204,10 @@
scanExpr(tree.truepart);
final Bits initsAfterThen = new Bits(inits);
final Bits uninitsAfterThen = new Bits(uninits);
- assignToInits(tree.truepart, initsBeforeElse);
+ inits.assign(initsBeforeElse);
uninits.assign(uninitsBeforeElse);
scanExpr(tree.falsepart);
- andSetInits(tree.falsepart, initsAfterThen);
+ inits.andSet(initsAfterThen);
uninits.andSet(uninitsAfterThen);
}
}
@@ -2182,46 +2216,42 @@
scanCond(tree.cond);
final Bits initsBeforeElse = new Bits(initsWhenFalse);
final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse);
- assignToInits(tree.cond, initsWhenTrue);
+ inits.assign(initsWhenTrue);
uninits.assign(uninitsWhenTrue);
scan(tree.thenpart);
if (tree.elsepart != null) {
final Bits initsAfterThen = new Bits(inits);
final Bits uninitsAfterThen = new Bits(uninits);
- assignToInits(tree.thenpart, initsBeforeElse);
+ inits.assign(initsBeforeElse);
uninits.assign(uninitsBeforeElse);
scan(tree.elsepart);
- andSetInits(tree.elsepart, initsAfterThen);
+ inits.andSet(initsAfterThen);
uninits.andSet(uninitsAfterThen);
} else {
- andSetInits(tree.thenpart, initsBeforeElse);
+ inits.andSet(initsBeforeElse);
uninits.andSet(uninitsBeforeElse);
}
}
- protected P createNewPendingExit(JCTree tree, Bits inits, Bits uninits) {
- return null;
- }
-
@Override
public void visitBreak(JCBreak tree) {
- recordExit(tree, createNewPendingExit(tree, inits, uninits));
+ recordExit(new AssignPendingExit(tree, inits, uninits));
}
@Override
public void visitContinue(JCContinue tree) {
- recordExit(tree, createNewPendingExit(tree, inits, uninits));
+ recordExit(new AssignPendingExit(tree, inits, uninits));
}
@Override
public void visitReturn(JCReturn tree) {
scanExpr(tree.expr);
- recordExit(tree, createNewPendingExit(tree, inits, uninits));
+ recordExit(new AssignPendingExit(tree, inits, uninits));
}
public void visitThrow(JCThrow tree) {
scanExpr(tree.expr);
- markDead(tree.expr);
+ markDead();
}
public void visitApply(JCMethodInvocation tree) {
@@ -2240,7 +2270,7 @@
final Bits prevUninits = new Bits(uninits);
final Bits prevInits = new Bits(inits);
int returnadrPrev = returnadr;
- ListBuffer<P> prevPending = pendingExits;
+ ListBuffer<AssignPendingExit> prevPending = pendingExits;
try {
returnadr = nextadr;
pendingExits = new ListBuffer<>();
@@ -2259,7 +2289,7 @@
finally {
returnadr = returnadrPrev;
uninits.assign(prevUninits);
- assignToInits(tree, prevInits);
+ inits.assign(prevInits);
pendingExits = prevPending;
}
}
@@ -2275,11 +2305,11 @@
scanCond(tree.cond);
uninitsExit.andSet(uninitsWhenTrue);
if (tree.detail != null) {
- assignToInits(tree, initsWhenFalse);
+ inits.assign(initsWhenFalse);
uninits.assign(uninitsWhenFalse);
scanExpr(tree.detail);
}
- assignToInits(tree, initsExit);
+ inits.assign(initsExit);
uninits.assign(uninitsExit);
}
@@ -2308,8 +2338,7 @@
if (enforceThisDotInit &&
tree.selected.hasTag(IDENT) &&
((JCIdent)tree.selected).name == names._this &&
- tree.sym.kind == VAR)
- {
+ tree.sym.kind == VAR) {
checkInit(tree.pos(), (VarSymbol)tree.sym);
}
}
@@ -2347,7 +2376,7 @@
scanCond(tree.lhs);
final Bits initsWhenFalseLeft = new Bits(initsWhenFalse);
final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse);
- assignToInits(tree.lhs, initsWhenTrue);
+ inits.assign(initsWhenTrue);
uninits.assign(uninitsWhenTrue);
scanCond(tree.rhs);
initsWhenFalse.andSet(initsWhenFalseLeft);
@@ -2357,7 +2386,7 @@
scanCond(tree.lhs);
final Bits initsWhenTrueLeft = new Bits(initsWhenTrue);
final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue);
- assignToInits(tree.lhs, initsWhenFalse);
+ inits.assign(initsWhenFalse);
uninits.assign(uninitsWhenFalse);
scanCond(tree.rhs);
initsWhenTrue.andSet(initsWhenTrueLeft);
@@ -2428,136 +2457,6 @@
}
}
- public class AssignAnalyzer extends AbstractAssignAnalyzer<AssignAnalyzer.AssignPendingExit> {
-
- public class AssignPendingExit extends AbstractAssignAnalyzer<AssignPendingExit>.AbstractAssignPendingExit {
-
- public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
- super(tree, inits, uninits);
- }
- }
-
- @Override
- protected AssignPendingExit createNewPendingExit(JCTree tree,
- Bits inits, Bits uninits) {
- return new AssignPendingExit(tree, inits, uninits);
- }
-
- /** Record an initialization of a trackable variable.
- */
- @Override
- void letInit(DiagnosticPosition pos, VarSymbol sym) {
- if (sym.adr >= firstadr && trackable(sym)) {
- if ((sym.flags() & EFFECTIVELY_FINAL) != 0) {
- if (!uninits.isMember(sym.adr)) {
- //assignment targeting an effectively final variable
- //makes the variable lose its status of effectively final
- //if the variable is _not_ definitively unassigned
- sym.flags_field &= ~EFFECTIVELY_FINAL;
- } else {
- uninit(sym);
- }
- }
- else if ((sym.flags() & FINAL) != 0) {
- if ((sym.flags() & PARAMETER) != 0) {
- if ((sym.flags() & UNION) != 0) { //multi-catch parameter
- log.error(pos, "multicatch.parameter.may.not.be.assigned", sym);
- }
- else {
- log.error(pos, "final.parameter.may.not.be.assigned",
- sym);
- }
- } else if (!uninits.isMember(sym.adr)) {
- log.error(pos, flowKind.errKey, sym);
- } else {
- uninit(sym);
- }
- }
- inits.incl(sym.adr);
- } else if ((sym.flags() & FINAL) != 0) {
- log.error(pos, "var.might.already.be.assigned", sym);
- }
- }
-
- @Override
- void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {
- if ((sym.adr >= firstadr || sym.owner.kind != TYP) &&
- trackable(sym) &&
- !inits.isMember(sym.adr)) {
- log.error(pos, errkey, sym);
- inits.incl(sym.adr);
- }
- }
-
- @Override
- void reportWarning(Lint.LintCategory lc, DiagnosticPosition pos,
- String key, Object ... args) {
- log.warning(lc, pos, key, args);
- }
-
- @Override
- int getLogNumberOfErrors() {
- return log.nerrors;
- }
-
- @Override
- boolean isEnabled(Lint.LintCategory lc) {
- return lint.isEnabled(lc);
- }
-
- @Override
- public void visitClassDef(JCClassDecl tree) {
- if (tree.sym == null) {
- return;
- }
-
- Lint lintPrev = lint;
- lint = lint.augment(tree.sym);
- try {
- super.visitClassDef(tree);
- } finally {
- lint = lintPrev;
- }
- }
-
- @Override
- public void visitMethodDef(JCMethodDecl tree) {
- if (tree.body == null) {
- return;
- }
-
- /* MemberEnter can generate synthetic methods ignore them
- */
- if ((tree.sym.flags() & SYNTHETIC) != 0) {
- return;
- }
-
- Lint lintPrev = lint;
- lint = lint.augment(tree.sym);
- try {
- super.visitMethodDef(tree);
- } finally {
- lint = lintPrev;
- }
- }
-
- @Override
- public void visitVarDef(JCVariableDecl tree) {
- if (tree.init == null) {
- super.visitVarDef(tree);
- } else {
- Lint lintPrev = lint;
- lint = lint.augment(tree.sym);
- try{
- super.visitVarDef(tree);
- } finally {
- lint = lintPrev;
- }
- }
- }
-
- }
-
/**
* This pass implements the last step of the dataflow analysis, namely
* the effectively-final analysis check. This checks that every local variable
@@ -2572,7 +2471,7 @@
JCTree currentTree; //local class or lambda
@Override
- void markDead(JCTree tree) {
+ void markDead() {
//do nothing
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java Thu Feb 19 16:38:54 2015 -0800
@@ -80,6 +80,7 @@
private Names names;
private Symtab syms;
private Resolve rs;
+ private Operators operators;
private TreeMaker make;
private Types types;
private TransTypes transTypes;
@@ -130,6 +131,7 @@
names = Names.instance(context);
syms = Symtab.instance(context);
rs = Resolve.instance(context);
+ operators = Operators.instance(context);
make = TreeMaker.instance(context);
types = Types.instance(context);
transTypes = TransTypes.instance(context);
@@ -654,7 +656,7 @@
private JCExpression eqTest(Type argType, JCExpression arg1, JCExpression arg2) {
JCBinary testExpr = make.Binary(JCTree.Tag.EQ, arg1, arg2);
- testExpr.operator = rs.resolveBinaryOperator(null, JCTree.Tag.EQ, attrEnv, argType, argType);
+ testExpr.operator = operators.resolveBinary(testExpr, JCTree.Tag.EQ, argType, argType);
testExpr.setType(syms.booleanType);
return testExpr;
}
@@ -668,7 +670,7 @@
List.<JCExpression>of(make.Literal(lit)));
eqtest.setType(syms.booleanType);
JCBinary compound = make.Binary(JCTree.Tag.AND, prev, eqtest);
- compound.operator = rs.resolveBinaryOperator(null, JCTree.Tag.AND, attrEnv, syms.booleanType, syms.booleanType);
+ compound.operator = operators.resolveBinary(compound, JCTree.Tag.AND, syms.booleanType, syms.booleanType);
compound.setType(syms.booleanType);
return compound;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java Thu Feb 19 16:38:54 2015 -0800
@@ -74,6 +74,7 @@
private final Log log;
private final Symtab syms;
private final Resolve rs;
+ private final Operators operators;
private final Check chk;
private final Attr attr;
private TreeMaker make;
@@ -95,6 +96,7 @@
log = Log.instance(context);
syms = Symtab.instance(context);
rs = Resolve.instance(context);
+ operators = Operators.instance(context);
chk = Check.instance(context);
attr = Attr.instance(context);
make = TreeMaker.instance(context);
@@ -575,8 +577,7 @@
*/
JCUnary makeUnary(JCTree.Tag optag, JCExpression arg) {
JCUnary tree = make.Unary(optag, arg);
- tree.operator = rs.resolveUnaryOperator(
- make_pos, optag, attrEnv, arg.type);
+ tree.operator = operators.resolveUnary(tree, optag, arg.type);
tree.type = tree.operator.type.getReturnType();
return tree;
}
@@ -588,8 +589,7 @@
*/
JCBinary makeBinary(JCTree.Tag optag, JCExpression lhs, JCExpression rhs) {
JCBinary tree = make.Binary(optag, lhs, rhs);
- tree.operator = rs.resolveBinaryOperator(
- make_pos, optag, attrEnv, lhs.type, rhs.type);
+ tree.operator = operators.resolveBinary(tree, optag, lhs.type, rhs.type);
tree.type = tree.operator.type.getReturnType();
return tree;
}
@@ -601,8 +601,7 @@
*/
JCAssignOp makeAssignop(JCTree.Tag optag, JCTree lhs, JCTree rhs) {
JCAssignOp tree = make.Assignop(optag, lhs, rhs);
- tree.operator = rs.resolveBinaryOperator(
- make_pos, tree.getTag().noAssignOp(), attrEnv, lhs.type, rhs.type);
+ tree.operator = operators.resolveBinary(tree, tree.getTag().noAssignOp(), lhs.type, rhs.type);
tree.type = lhs.type;
return tree;
}
@@ -2644,7 +2643,6 @@
MethodSymbol m = tree.sym;
tree.params = tree.params.prepend(ordParam).prepend(nameParam);
- incrementParamTypeAnnoIndexes(m, 2);
m.extraParams = m.extraParams.prepend(ordParam.sym);
m.extraParams = m.extraParams.prepend(nameParam.sym);
@@ -2667,17 +2665,6 @@
currentMethodSym = prevMethodSym;
}
}
- //where
- private void incrementParamTypeAnnoIndexes(MethodSymbol m,
- int amount) {
- for (final Attribute.TypeCompound anno : m.getRawTypeAttributes()) {
- // Increment the parameter_index of any existing formal
- // parameter annotations.
- if (anno.position.type == TargetType.METHOD_FORMAL_PARAMETER) {
- anno.position.parameter_index += amount;
- }
- }
- }
private void visitMethodDefInternal(JCMethodDecl tree) {
if (tree.name == names.init &&
@@ -2711,7 +2698,6 @@
tree.params = tree.params.appendList(fvdefs);
if (currentClass.hasOuterInstance()) {
tree.params = tree.params.prepend(otdef);
- incrementParamTypeAnnoIndexes(m, 1);
}
// If this is an initial constructor, i.e., it does not start with
@@ -3206,9 +3192,8 @@
// tree.lhs. However, we can still get the
// unerased type of tree.lhs as it is stored
// in tree.type in Attr.
- Symbol newOperator = rs.resolveBinaryOperator(tree.pos(),
+ Symbol newOperator = operators.resolveBinary(tree,
newTag,
- attrEnv,
tree.type,
tree.rhs.type);
JCExpression expr = (JCExpression)lhs;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Operators.java Thu Feb 19 16:38:54 2015 -0800
@@ -0,0 +1,850 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.tools.javac.comp;
+
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symbol.OperatorSymbol;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Type.MethodType;
+import com.sun.tools.javac.code.TypeTag;
+import com.sun.tools.javac.code.Types;
+import com.sun.tools.javac.jvm.ByteCodes;
+import com.sun.tools.javac.resources.CompilerProperties.Errors;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.Tag;
+import com.sun.tools.javac.util.Assert;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Names;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.function.BiPredicate;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.stream.Stream;
+
+import static com.sun.tools.javac.jvm.ByteCodes.*;
+import static com.sun.tools.javac.comp.Operators.OperatorType.*;
+
+/**
+ * This class contains the logic for unary and binary operator resolution/lookup.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class Operators {
+ protected static final Context.Key<Operators> operatorsKey = new Context.Key<>();
+
+ private final Names names;
+ private final Log log;
+ private final Symtab syms;
+ private final Types types;
+
+ /** Unary operators map. */
+ private Map<Name, List<UnaryOperatorHelper>> unaryOperators = new HashMap<>(Tag.getNumberOfOperators());
+
+ /** Binary operators map. */
+ private Map<Name, List<BinaryOperatorHelper>> binaryOperators = new HashMap<>(Tag.getNumberOfOperators());
+
+ /** The names of all operators. */
+ private Name[] opname = new Name[Tag.getNumberOfOperators()];
+
+ public static Operators instance(Context context) {
+ Operators instance = context.get(operatorsKey);
+ if (instance == null)
+ instance = new Operators(context);
+ return instance;
+ }
+
+ protected Operators(Context context) {
+ context.put(operatorsKey, this);
+ syms = Symtab.instance(context);
+ names = Names.instance(context);
+ log = Log.instance(context);
+ types = Types.instance(context);
+ initOperatorNames();
+ initUnaryOperators();
+ initBinaryOperators();
+ }
+
+ /**
+ * Perform unary promotion of a type; this routine implements JLS 5.6.1.
+ * If the input type is not supported by unary promotion, it is returned unaltered.
+ */
+ Type unaryPromotion(Type t) {
+ Type unboxed = types.unboxedTypeOrType(t);
+ switch (unboxed.getTag()) {
+ case BYTE:
+ case SHORT:
+ case CHAR:
+ return syms.intType;
+ default:
+ return unboxed;
+ }
+ }
+
+ /**
+ * Perform binary promotion of a pair of types; this routine implements JLS 5.6.2.
+ * If the input types are not supported by unary promotion, if such types are identical to
+ * a type C, then C is returned, otherwise Object is returned.
+ */
+ Type binaryPromotion(Type t1, Type t2) {
+ Type unboxedT1 = types.unboxedTypeOrType(t1);
+ Type unboxedT2 = types.unboxedTypeOrType(t2);
+
+ if (unboxedT1.isNumeric() && unboxedT2.isNumeric()) {
+ if (unboxedT1.hasTag(TypeTag.DOUBLE) || unboxedT2.hasTag(TypeTag.DOUBLE)) {
+ return syms.doubleType;
+ } else if (unboxedT1.hasTag(TypeTag.FLOAT) || unboxedT2.hasTag(TypeTag.FLOAT)) {
+ return syms.floatType;
+ } else if (unboxedT1.hasTag(TypeTag.LONG) || unboxedT2.hasTag(TypeTag.LONG)) {
+ return syms.longType;
+ } else {
+ return syms.intType;
+ }
+ } else if (types.isSameType(unboxedT1, unboxedT2)) {
+ return unboxedT1;
+ } else {
+ return syms.objectType;
+ }
+ }
+
+ /**
+ * Entry point for resolving a unary operator given an operator tag and an argument type.
+ */
+ Symbol resolveUnary(DiagnosticPosition pos, JCTree.Tag tag, Type op) {
+ return resolve(tag,
+ unaryOperators,
+ unop -> unop.test(op),
+ unop -> unop.resolve(op),
+ () -> reportErrorIfNeeded(pos, tag, op));
+ }
+
+ /**
+ * Entry point for resolving a binary operator given an operator tag and a pair of argument types.
+ */
+ Symbol resolveBinary(DiagnosticPosition pos, JCTree.Tag tag, Type op1, Type op2) {
+ return resolve(tag,
+ binaryOperators,
+ binop -> binop.test(op1, op2),
+ binop -> binop.resolve(op1, op2),
+ () -> reportErrorIfNeeded(pos, tag, op1, op2));
+ }
+
+ /**
+ * Main operator lookup routine; lookup an operator (either unary or binary) in its corresponding
+ * map. If there's a matching operator, its resolve routine is called and the result is returned;
+ * otherwise the result of a fallback function is returned.
+ */
+ private <O> Symbol resolve(Tag tag, Map<Name, List<O>> opMap, Predicate<O> opTestFunc,
+ Function<O, Symbol> resolveFunc, Supplier<Symbol> noResultFunc) {
+ return opMap.get(operatorName(tag)).stream()
+ .filter(opTestFunc)
+ .map(resolveFunc)
+ .findFirst()
+ .orElseGet(noResultFunc);
+ }
+
+ /**
+ * Creates an operator symbol.
+ */
+ private Symbol makeOperator(Name name, List<OperatorType> formals, OperatorType res, int... opcodes) {
+ MethodType opType = new MethodType(
+ formals.stream()
+ .map(o -> o.asType(syms))
+ .collect(List.collector()),
+ res.asType(syms), List.nil(), syms.methodClass);
+ return new OperatorSymbol(name, opType, mergeOpcodes(opcodes), syms.noSymbol);
+ }
+
+ /**
+ * Fold two opcodes in a single int value (if required).
+ */
+ private int mergeOpcodes(int... opcodes) {
+ int opcodesLen = opcodes.length;
+ Assert.check(opcodesLen == 1 || opcodesLen == 2);
+ return (opcodesLen == 1) ?
+ opcodes[0] :
+ ((opcodes[0] << ByteCodes.preShift) | opcodes[1]);
+ }
+
+ /**
+ * Report an operator lookup error.
+ */
+ private Symbol reportErrorIfNeeded(DiagnosticPosition pos, Tag tag, Type... args) {
+ if (Stream.of(args).noneMatch(Type::isErroneous)) {
+ Name opName = operatorName(tag);
+ JCDiagnostic.Error opError = (args.length) == 1 ?
+ Errors.OperatorCantBeApplied(opName, args[0]) :
+ Errors.OperatorCantBeApplied1(opName, args[0], args[1]);
+ log.error(pos, opError);
+ }
+ return syms.noSymbol;
+ }
+
+ /**
+ * Return name of operator with given tree tag.
+ */
+ public Name operatorName(JCTree.Tag tag) {
+ return opname[tag.operatorIndex()];
+ }
+
+ /**
+ * The constants in this enum represent the types upon which all the operator helpers
+ * operate upon. This allows lazy and consise mapping between a type name and a type instance.
+ */
+ enum OperatorType {
+ BYTE(syms -> syms.byteType),
+ SHORT(syms -> syms.shortType),
+ INT(syms -> syms.intType),
+ LONG(syms -> syms.longType),
+ FLOAT(syms -> syms.floatType),
+ DOUBLE(syms -> syms.doubleType),
+ CHAR(syms -> syms.charType),
+ BOOLEAN(syms -> syms.booleanType),
+ OBJECT(syms -> syms.objectType),
+ STRING(syms -> syms.stringType),
+ BOT(syms -> syms.botType);
+
+ final Function<Symtab, Type> asTypeFunc;
+
+ OperatorType(Function<Symtab, Type> asTypeFunc) {
+ this.asTypeFunc = asTypeFunc;
+ }
+
+ Type asType(Symtab syms) {
+ return asTypeFunc.apply(syms);
+ }
+ }
+
+ /**
+ * Common root for all operator helpers. An operator helper instance is associated with a
+ * given operator (i.e. '+'); it contains routines to perform operator lookup, i.e. find
+ * which version of the '+' operator is the best given an argument type list. Supported
+ * operator symbols are initialized lazily upon first lookup request - this is in order to avoid
+ * initialization circularities between this class and {@code Symtab}.
+ */
+ abstract class OperatorHelper {
+
+ /** The operator name. */
+ final Name name;
+
+ /** The list of symbols associated with this operator (lazily populated). */
+ Optional<Symbol[]> alternatives = Optional.empty();
+
+ /** An array of operator symbol suppliers (used to lazily populate the symbol list). */
+ List<Supplier<Symbol>> operatorSuppliers = List.nil();
+
+ @SuppressWarnings("varargs")
+ OperatorHelper(Tag tag) {
+ this.name = operatorName(tag);
+ }
+
+ /**
+ * This routine implements the main operator lookup process. Each operator is tested
+ * using an applicability predicate; if the test suceeds that same operator is returned,
+ * otherwise a dummy symbol is returned.
+ */
+ final Symbol doLookup(Predicate<Symbol> applicabilityTest) {
+ return Stream.of(alternatives.orElseGet(this::initOperators))
+ .filter(applicabilityTest)
+ .findFirst()
+ .orElse(syms.noSymbol);
+ }
+
+ /**
+ * This routine performs lazy instantiation of the operator symbols supported by this helper.
+ * After initialization is done, the suppliers are cleared, to free up memory.
+ */
+ private Symbol[] initOperators() {
+ Symbol[] operators = operatorSuppliers.stream()
+ .map(op -> op.get())
+ .toArray(Symbol[]::new);
+ alternatives = Optional.of(operators);
+ operatorSuppliers = null; //let GC do its work
+ return operators;
+ }
+ }
+
+ /**
+ * Common superclass for all unary operator helpers.
+ */
+ abstract class UnaryOperatorHelper extends OperatorHelper implements Predicate<Type> {
+
+ UnaryOperatorHelper(Tag tag) {
+ super(tag);
+ }
+
+ /**
+ * This routine implements the unary operator lookup process. It customizes the behavior
+ * of the shared lookup routine in {@link OperatorHelper}, by using an unary applicability test
+ * (see {@link UnaryOperatorHelper#isUnaryOperatorApplicable(OperatorSymbol, Type)}
+ */
+ final Symbol doLookup(Type t) {
+ return doLookup(op -> isUnaryOperatorApplicable((OperatorSymbol)op, t));
+ }
+
+ /**
+ * Unary operator applicability test - is the input type the same as the expected operand type?
+ */
+ boolean isUnaryOperatorApplicable(OperatorSymbol op, Type t) {
+ return types.isSameType(op.type.getParameterTypes().head, t);
+ }
+
+ /**
+ * Adds a unary operator symbol.
+ */
+ final UnaryOperatorHelper addUnaryOperator(OperatorType arg, OperatorType res, int... opcode) {
+ operatorSuppliers = operatorSuppliers.prepend(() -> makeOperator(name, List.of(arg), res, opcode));
+ return this;
+ }
+
+ /**
+ * This method will be overridden by unary operator helpers to provide custom resolution
+ * logic.
+ */
+ abstract Symbol resolve(Type t);
+ }
+
+ abstract class BinaryOperatorHelper extends OperatorHelper implements BiPredicate<Type, Type> {
+
+ BinaryOperatorHelper(Tag tag) {
+ super(tag);
+ }
+
+ /**
+ * This routine implements the binary operator lookup process. It customizes the behavior
+ * of the shared lookup routine in {@link OperatorHelper}, by using an unary applicability test
+ * (see {@link BinaryOperatorHelper#isBinaryOperatorApplicable(OperatorSymbol, Type, Type)}
+ */
+ final Symbol doLookup(Type t1, Type t2) {
+ return doLookup(op -> isBinaryOperatorApplicable((OperatorSymbol)op, t1, t2));
+ }
+
+ /**
+ * Binary operator applicability test - are the input types the same as the expected operand types?
+ */
+ boolean isBinaryOperatorApplicable(OperatorSymbol op, Type t1, Type t2) {
+ List<Type> formals = op.type.getParameterTypes();
+ return types.isSameType(formals.head, t1) &&
+ types.isSameType(formals.tail.head, t2);
+ }
+
+ /**
+ * Adds a binary operator symbol.
+ */
+ final BinaryOperatorHelper addBinaryOperator(OperatorType arg1, OperatorType arg2, OperatorType res, int... opcode) {
+ operatorSuppliers = operatorSuppliers.prepend(() -> makeOperator(name, List.of(arg1, arg2), res, opcode));
+ return this;
+ }
+
+ /**
+ * This method will be overridden by binary operator helpers to provide custom resolution
+ * logic.
+ */
+ abstract Symbol resolve(Type t1, Type t2);
+ }
+
+ /**
+ * Class representing unary operator helpers that operate on reference types.
+ */
+ class UnaryReferenceOperator extends UnaryOperatorHelper {
+
+ UnaryReferenceOperator(Tag tag) {
+ super(tag);
+ }
+
+ @Override
+ public boolean test(Type type) {
+ return type.isNullOrReference();
+ }
+
+ @Override
+ public Symbol resolve(Type arg) {
+ return doLookup(syms.objectType);
+ }
+ }
+
+ /**
+ * Class representing unary operator helpers that operate on numeric types (either boxed or unboxed).
+ * Operator lookup is performed after applying numeric promotion of the input type.
+ */
+ class UnaryNumericOperator extends UnaryOperatorHelper {
+
+ UnaryNumericOperator(Tag tag) {
+ super(tag);
+ }
+
+ @Override
+ public boolean test(Type type) {
+ return unaryPromotion(type).isNumeric();
+ }
+
+ @Override
+ public Symbol resolve(Type arg) {
+ return doLookup(unaryPromotion(arg));
+ }
+ }
+
+ /**
+ * Class representing unary operator helpers that operate on boolean types (either boxed or unboxed).
+ * Operator lookup is performed assuming the input type is a boolean type.
+ */
+ class UnaryBooleanOperator extends UnaryOperatorHelper {
+
+ UnaryBooleanOperator(Tag tag) {
+ super(tag);
+ }
+
+ @Override
+ public boolean test(Type type) {
+ return types.unboxedTypeOrType(type).hasTag(TypeTag.BOOLEAN);
+ }
+
+ @Override
+ public Symbol resolve(Type arg) {
+ return doLookup(syms.booleanType);
+ }
+ }
+
+ /**
+ * Class representing prefix/postfix unary operator helpers. Operates on numeric types (either
+ * boxed or unboxed). Operator lookup is performed on the unboxed version of the input type.
+ */
+ class UnaryPrefixPostfixOperator extends UnaryNumericOperator {
+
+ UnaryPrefixPostfixOperator(Tag tag) {
+ super(tag);
+ }
+
+ @Override
+ public Symbol resolve(Type arg) {
+ return doLookup(types.unboxedTypeOrType(arg));
+ }
+ }
+
+ /**
+ * Class representing binary operator helpers that operate on numeric types (either boxed or unboxed).
+ * Operator lookup is performed after applying binary numeric promotion of the input types.
+ */
+ class BinaryNumericOperator extends BinaryOperatorHelper {
+
+ BinaryNumericOperator(Tag tag) {
+ super(tag);
+ }
+
+ @Override
+ public Symbol resolve(Type arg1, Type arg2) {
+ Type t = binaryPromotion(arg1, arg2);
+ return doLookup(t, t);
+ }
+
+ @Override
+ public boolean test(Type arg1, Type arg2) {
+ return unaryPromotion(arg1).isNumeric() && unaryPromotion(arg2).isNumeric();
+ }
+ }
+
+ /**
+ * Class representing bitwise operator helpers that operate on all primitive types (either boxed or unboxed).
+ * Operator lookup is performed after applying binary numeric promotion of the input types.
+ */
+ class BinaryBitwiseOperator extends BinaryNumericOperator {
+
+ BinaryBitwiseOperator(Tag tag) {
+ super(tag);
+ }
+
+ @Override
+ public boolean test(Type arg1, Type arg2) {
+ return unaryPromotion(arg1).isPrimitive() && unaryPromotion(arg2).isPrimitive();
+ }
+ }
+
+ /**
+ * Class representing bitwise operator helpers that operate on boolean types (either boxed or unboxed).
+ * Operator lookup is performed assuming both input types are boolean types.
+ */
+ class BinaryBooleanOperator extends BinaryOperatorHelper {
+
+ BinaryBooleanOperator(Tag tag) {
+ super(tag);
+ }
+
+ @Override
+ public Symbol resolve(Type arg1, Type arg2) {
+ return doLookup(syms.booleanType, syms.booleanType);
+ }
+
+ @Override
+ public boolean test(Type arg1, Type arg2) {
+ return types.unboxedTypeOrType(arg1).hasTag(TypeTag.BOOLEAN) &&
+ types.unboxedTypeOrType(arg2).hasTag(TypeTag.BOOLEAN);
+ }
+ }
+
+ /**
+ * Class representing string concatenation operator helper that operates on at least an
+ * string operand. Input types subject to an operator lookup undergoes a special string promotion
+ * (see {@link BinaryStringOperator#stringPromotion(Type)}.
+ */
+ class BinaryStringOperator extends BinaryOperatorHelper {
+
+ BinaryStringOperator(Tag tag) {
+ super(tag);
+ }
+
+ @Override
+ public Symbol resolve(Type arg1, Type arg2) {
+ return doLookup(stringPromotion(arg1), stringPromotion(arg2));
+ }
+
+ @Override
+ public boolean test(Type arg1, Type arg2) {
+ return types.isSameType(arg1, syms.stringType) ||
+ types.isSameType(arg2, syms.stringType);
+ }
+
+ /**
+ * This routine applies following mappings:
+ * - if input type is primitive, apply numeric promotion
+ * - if input type is either 'null' or 'String' leave it untouched
+ * - otherwise return 'Object'
+ */
+ private Type stringPromotion(Type t) {
+ if (t.isPrimitive()) {
+ return unaryPromotion(t);
+ } else if (t.hasTag(TypeTag.BOT) ||
+ types.isSameType(t, syms.stringType)) {
+ return t;
+ } else if (t.hasTag(TypeTag.TYPEVAR)) {
+ return stringPromotion(t.getUpperBound());
+ } else {
+ return syms.objectType;
+ }
+ }
+ }
+
+ /**
+ * Class representing shift operator helper that operates on integral operand types (either boxed
+ * or unboxed). Operator lookup is performed after applying unary numeric promotion to each input type.
+ */
+ class BinaryShiftOperator extends BinaryOperatorHelper {
+
+ BinaryShiftOperator(Tag tag) {
+ super(tag);
+ }
+
+ @Override
+ public Symbol resolve(Type arg1, Type arg2) {
+ return doLookup(unaryPromotion(arg1), unaryPromotion(arg2));
+ }
+
+ @Override
+ public boolean test(Type arg1, Type arg2) {
+ TypeTag op1 = unaryPromotion(arg1).getTag();
+ TypeTag op2 = unaryPromotion(arg2).getTag();
+ return (op1 == TypeTag.LONG || op1 == TypeTag.INT) &&
+ (op2 == TypeTag.LONG || op2 == TypeTag.INT);
+ }
+ }
+
+ /**
+ * This enum represent the possible kinds of an comparison test ('==' and '!=').
+ */
+ enum ComparisonKind {
+ /** equality between numeric or boolean operands. */
+ NUMERIC_OR_BOOLEAN,
+ /** equality between reference operands. */
+ REFERENCE,
+ /** erroneous equality */
+ INVALID
+ }
+
+ /**
+ * Class representing equality operator helper that operates on either numeric, boolean or reference
+ * types. Operator lookup for numeric/boolean equality test is performed after binary numeric
+ * promotion to the input types. Operator lookup for reference equality test is performed assuming
+ * the input type is 'Object'.
+ */
+ class BinaryEqualityOperator extends BinaryOperatorHelper {
+
+ BinaryEqualityOperator(Tag tag) {
+ super(tag);
+ }
+
+ @Override
+ public boolean test(Type arg1, Type arg2) {
+ return getKind(arg1, arg2) != ComparisonKind.INVALID;
+ }
+
+ @Override
+ public Symbol resolve(Type t1, Type t2) {
+ ComparisonKind kind = getKind(t1, t2);
+ Type t = (kind == ComparisonKind.NUMERIC_OR_BOOLEAN) ?
+ binaryPromotion(t1, t2) :
+ syms.objectType;
+ return doLookup(t, t);
+ }
+
+ /**
+ * Retrieve the comparison kind associated with the given argument type pair.
+ */
+ private ComparisonKind getKind(Type arg1, Type arg2) {
+ boolean arg1Primitive = arg1.isPrimitive();
+ boolean arg2Primitive = arg2.isPrimitive();
+ if (arg1Primitive && arg2Primitive) {
+ return ComparisonKind.NUMERIC_OR_BOOLEAN;
+ } else if (arg1Primitive) {
+ return unaryPromotion(arg2).isPrimitive() ?
+ ComparisonKind.NUMERIC_OR_BOOLEAN : ComparisonKind.INVALID;
+ } else if (arg2Primitive) {
+ return unaryPromotion(arg1).isPrimitive() ?
+ ComparisonKind.NUMERIC_OR_BOOLEAN : ComparisonKind.INVALID;
+ } else {
+ return arg1.isNullOrReference() && arg2.isNullOrReference() ?
+ ComparisonKind.REFERENCE : ComparisonKind.INVALID;
+ }
+ }
+ }
+
+ /**
+ * Initialize all unary operators.
+ */
+ private void initUnaryOperators() {
+ initOperators(unaryOperators,
+ new UnaryNumericOperator(Tag.POS)
+ .addUnaryOperator(DOUBLE, DOUBLE, nop)
+ .addUnaryOperator(FLOAT, FLOAT, nop)
+ .addUnaryOperator(LONG, LONG, nop)
+ .addUnaryOperator(INT, INT, nop),
+ new UnaryNumericOperator(Tag.NEG)
+ .addUnaryOperator(DOUBLE, DOUBLE, dneg)
+ .addUnaryOperator(FLOAT, FLOAT, fneg)
+ .addUnaryOperator(LONG, LONG, lneg)
+ .addUnaryOperator(INT, INT, ineg),
+ new UnaryNumericOperator(Tag.COMPL)
+ .addUnaryOperator(LONG, LONG, lxor)
+ .addUnaryOperator(INT, INT, ixor),
+ new UnaryPrefixPostfixOperator(Tag.POSTINC)
+ .addUnaryOperator(DOUBLE, DOUBLE, dadd)
+ .addUnaryOperator(FLOAT, FLOAT, fadd)
+ .addUnaryOperator(LONG, LONG, ladd)
+ .addUnaryOperator(INT, INT, iadd)
+ .addUnaryOperator(CHAR, CHAR, iadd)
+ .addUnaryOperator(SHORT, SHORT, iadd)
+ .addUnaryOperator(BYTE, BYTE, iadd),
+ new UnaryPrefixPostfixOperator(Tag.POSTDEC)
+ .addUnaryOperator(DOUBLE, DOUBLE, dsub)
+ .addUnaryOperator(FLOAT, FLOAT, fsub)
+ .addUnaryOperator(LONG, LONG, lsub)
+ .addUnaryOperator(INT, INT, isub)
+ .addUnaryOperator(CHAR, CHAR, isub)
+ .addUnaryOperator(SHORT, SHORT, isub)
+ .addUnaryOperator(BYTE, BYTE, isub),
+ new UnaryBooleanOperator(Tag.NOT)
+ .addUnaryOperator(BOOLEAN, BOOLEAN, bool_not),
+ new UnaryReferenceOperator(Tag.NULLCHK)
+ .addUnaryOperator(OBJECT, OBJECT, nullchk));
+ }
+
+ /**
+ * Initialize all binary operators.
+ */
+ private void initBinaryOperators() {
+ initOperators(binaryOperators,
+ new BinaryStringOperator(Tag.PLUS)
+ .addBinaryOperator(STRING, OBJECT, STRING, string_add)
+ .addBinaryOperator(OBJECT, STRING, STRING, string_add)
+ .addBinaryOperator(STRING, STRING, STRING, string_add)
+ .addBinaryOperator(STRING, INT, STRING, string_add)
+ .addBinaryOperator(STRING, LONG, STRING, string_add)
+ .addBinaryOperator(STRING, FLOAT, STRING, string_add)
+ .addBinaryOperator(STRING, DOUBLE, STRING, string_add)
+ .addBinaryOperator(STRING, BOOLEAN, STRING, string_add)
+ .addBinaryOperator(STRING, BOT, STRING, string_add)
+ .addBinaryOperator(INT, STRING, STRING, string_add)
+ .addBinaryOperator(LONG, STRING, STRING, string_add)
+ .addBinaryOperator(FLOAT, STRING, STRING, string_add)
+ .addBinaryOperator(DOUBLE, STRING, STRING, string_add)
+ .addBinaryOperator(BOOLEAN, STRING, STRING, string_add)
+ .addBinaryOperator(BOT, STRING, STRING, string_add),
+ new BinaryNumericOperator(Tag.PLUS)
+ .addBinaryOperator(DOUBLE, DOUBLE, DOUBLE, dadd)
+ .addBinaryOperator(FLOAT, FLOAT, FLOAT, fadd)
+ .addBinaryOperator(LONG, LONG, LONG, ladd)
+ .addBinaryOperator(INT, INT, INT, iadd),
+ new BinaryNumericOperator(Tag.MINUS)
+ .addBinaryOperator(DOUBLE, DOUBLE, DOUBLE, dsub)
+ .addBinaryOperator(FLOAT, FLOAT, FLOAT, fsub)
+ .addBinaryOperator(LONG, LONG, LONG, lsub)
+ .addBinaryOperator(INT, INT, INT, isub),
+ new BinaryNumericOperator(Tag.MUL)
+ .addBinaryOperator(DOUBLE, DOUBLE, DOUBLE, dmul)
+ .addBinaryOperator(FLOAT, FLOAT, FLOAT, fmul)
+ .addBinaryOperator(LONG, LONG, LONG, lmul)
+ .addBinaryOperator(INT, INT, INT, imul),
+ new BinaryNumericOperator(Tag.DIV)
+ .addBinaryOperator(DOUBLE, DOUBLE, DOUBLE, ddiv)
+ .addBinaryOperator(FLOAT, FLOAT, FLOAT, fdiv)
+ .addBinaryOperator(LONG, LONG, LONG, ldiv)
+ .addBinaryOperator(INT, INT, INT, idiv),
+ new BinaryNumericOperator(Tag.MOD)
+ .addBinaryOperator(DOUBLE, DOUBLE, DOUBLE, dmod)
+ .addBinaryOperator(FLOAT, FLOAT, FLOAT, fmod)
+ .addBinaryOperator(LONG, LONG, LONG, lmod)
+ .addBinaryOperator(INT, INT, INT, imod),
+ new BinaryBitwiseOperator(Tag.BITAND)
+ .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, iand)
+ .addBinaryOperator(LONG, LONG, LONG, land)
+ .addBinaryOperator(INT, INT, INT, iand),
+ new BinaryBitwiseOperator(Tag.BITOR)
+ .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, ior)
+ .addBinaryOperator(LONG, LONG, LONG, lor)
+ .addBinaryOperator(INT, INT, INT, ior),
+ new BinaryBitwiseOperator(Tag.BITXOR)
+ .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, ixor)
+ .addBinaryOperator(LONG, LONG, LONG, lxor)
+ .addBinaryOperator(INT, INT, INT, ixor),
+ new BinaryShiftOperator(Tag.SL)
+ .addBinaryOperator(INT, INT, INT, ishl)
+ .addBinaryOperator(INT, LONG, INT, ishll)
+ .addBinaryOperator(LONG, INT, LONG, lshl)
+ .addBinaryOperator(LONG, LONG, LONG, lshll),
+ new BinaryShiftOperator(Tag.SR)
+ .addBinaryOperator(INT, INT, INT, ishr)
+ .addBinaryOperator(INT, LONG, INT, ishrl)
+ .addBinaryOperator(LONG, INT, LONG, lshr)
+ .addBinaryOperator(LONG, LONG, LONG, lshrl),
+ new BinaryShiftOperator(Tag.USR)
+ .addBinaryOperator(INT, INT, INT, iushr)
+ .addBinaryOperator(INT, LONG, INT, iushrl)
+ .addBinaryOperator(LONG, INT, LONG, lushr)
+ .addBinaryOperator(LONG, LONG, LONG, lushrl),
+ new BinaryNumericOperator(Tag.LT)
+ .addBinaryOperator(DOUBLE, DOUBLE, BOOLEAN, dcmpg, iflt)
+ .addBinaryOperator(FLOAT, FLOAT, BOOLEAN, fcmpg, iflt)
+ .addBinaryOperator(LONG, LONG, BOOLEAN, lcmp, iflt)
+ .addBinaryOperator(INT, INT, BOOLEAN, if_icmplt),
+ new BinaryNumericOperator(Tag.GT)
+ .addBinaryOperator(DOUBLE, DOUBLE, BOOLEAN, dcmpl, ifgt)
+ .addBinaryOperator(FLOAT, FLOAT, BOOLEAN, fcmpl, ifgt)
+ .addBinaryOperator(LONG, LONG, BOOLEAN, lcmp, ifgt)
+ .addBinaryOperator(INT, INT, BOOLEAN, if_icmpgt),
+ new BinaryNumericOperator(Tag.LE)
+ .addBinaryOperator(DOUBLE, DOUBLE, BOOLEAN, dcmpg, ifle)
+ .addBinaryOperator(FLOAT, FLOAT, BOOLEAN, fcmpg, ifle)
+ .addBinaryOperator(LONG, LONG, BOOLEAN, lcmp, ifle)
+ .addBinaryOperator(INT, INT, BOOLEAN, if_icmple),
+ new BinaryNumericOperator(Tag.GE)
+ .addBinaryOperator(DOUBLE, DOUBLE, BOOLEAN, dcmpl, ifge)
+ .addBinaryOperator(FLOAT, FLOAT, BOOLEAN, fcmpl, ifge)
+ .addBinaryOperator(LONG, LONG, BOOLEAN, lcmp, ifge)
+ .addBinaryOperator(INT, INT, BOOLEAN, if_icmpge),
+ new BinaryEqualityOperator(Tag.EQ)
+ .addBinaryOperator(OBJECT, OBJECT, BOOLEAN, if_acmpeq)
+ .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, if_icmpeq)
+ .addBinaryOperator(DOUBLE, DOUBLE, BOOLEAN, dcmpl, ifeq)
+ .addBinaryOperator(FLOAT, FLOAT, BOOLEAN, fcmpl, ifeq)
+ .addBinaryOperator(LONG, LONG, BOOLEAN, lcmp, ifeq)
+ .addBinaryOperator(INT, INT, BOOLEAN, if_icmpeq),
+ new BinaryEqualityOperator(Tag.NE)
+ .addBinaryOperator(OBJECT, OBJECT, BOOLEAN, if_acmpne)
+ .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, if_icmpne)
+ .addBinaryOperator(DOUBLE, DOUBLE, BOOLEAN, dcmpl, ifne)
+ .addBinaryOperator(FLOAT, FLOAT, BOOLEAN, fcmpl, ifne)
+ .addBinaryOperator(LONG, LONG, BOOLEAN, lcmp, ifne)
+ .addBinaryOperator(INT, INT, BOOLEAN, if_icmpne),
+ new BinaryBooleanOperator(Tag.AND)
+ .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, bool_and),
+ new BinaryBooleanOperator(Tag.OR)
+ .addBinaryOperator(BOOLEAN, BOOLEAN, BOOLEAN, bool_or));
+ }
+
+ /**
+ * Complete the initialization of an operator helper by storing it into the corresponding operator map.
+ */
+ @SafeVarargs
+ private final <O extends OperatorHelper> void initOperators(Map<Name, List<O>> opsMap, O... ops) {
+ for (O o : ops) {
+ Name opName = o.name;
+ List<O> helpers = opsMap.getOrDefault(opName, List.nil());
+ opsMap.put(opName, helpers.prepend(o));
+ }
+ }
+
+ /**
+ * Initialize operator name array.
+ */
+ private void initOperatorNames() {
+ setOperatorName(Tag.POS, "+");
+ setOperatorName(Tag.NEG, "-");
+ setOperatorName(Tag.NOT, "!");
+ setOperatorName(Tag.COMPL, "~");
+ setOperatorName(Tag.PREINC, "++");
+ setOperatorName(Tag.PREDEC, "--");
+ setOperatorName(Tag.POSTINC, "++");
+ setOperatorName(Tag.POSTDEC, "--");
+ setOperatorName(Tag.NULLCHK, "<*nullchk*>");
+ setOperatorName(Tag.OR, "||");
+ setOperatorName(Tag.AND, "&&");
+ setOperatorName(Tag.EQ, "==");
+ setOperatorName(Tag.NE, "!=");
+ setOperatorName(Tag.LT, "<");
+ setOperatorName(Tag.GT, ">");
+ setOperatorName(Tag.LE, "<=");
+ setOperatorName(Tag.GE, ">=");
+ setOperatorName(Tag.BITOR, "|");
+ setOperatorName(Tag.BITXOR, "^");
+ setOperatorName(Tag.BITAND, "&");
+ setOperatorName(Tag.SL, "<<");
+ setOperatorName(Tag.SR, ">>");
+ setOperatorName(Tag.USR, ">>>");
+ setOperatorName(Tag.PLUS, "+");
+ setOperatorName(Tag.MINUS, names.hyphen);
+ setOperatorName(Tag.MUL, names.asterisk);
+ setOperatorName(Tag.DIV, names.slash);
+ setOperatorName(Tag.MOD, "%");
+ }
+ //where
+ private void setOperatorName(Tag tag, String name) {
+ setOperatorName(tag, names.fromString(name));
+ }
+
+ private void setOperatorName(Tag tag, Name name) {
+ opname[tag.operatorIndex()] = name;
+ }
+}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Feb 19 16:38:54 2015 -0800
@@ -90,7 +90,6 @@
Check chk;
Infer infer;
ClassFinder finder;
- TreeInfo treeinfo;
Types types;
JCDiagnostic.Factory diags;
public final boolean allowMethodHandles;
@@ -118,7 +117,6 @@
chk = Check.instance(context);
infer = Infer.instance(context);
finder = ClassFinder.instance(context);
- treeinfo = TreeInfo.instance(context);
types = Types.instance(context);
diags = JCDiagnostic.Factory.instance(context);
Source source = Source.instance(context);
@@ -652,7 +650,7 @@
* Retrieve the method check object that will be used during a
* most specific check.
*/
- MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict);
+ MethodCheck mostSpecificCheck(List<Type> actuals);
}
/**
@@ -698,7 +696,7 @@
//do nothing - method always applicable regardless of actuals
}
- public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
+ public MethodCheck mostSpecificCheck(List<Type> actuals) {
return this;
}
};
@@ -773,7 +771,7 @@
throw ex.setMessage(diags.create(DiagnosticType.FRAGMENT, log.currentSource(), pos, key, args));
}
- public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
+ public MethodCheck mostSpecificCheck(List<Type> actuals) {
return nilMethodCheck;
}
@@ -881,8 +879,8 @@
}
@Override
- public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
- return new MostSpecificCheck(strict, actuals);
+ public MethodCheck mostSpecificCheck(List<Type> actuals) {
+ return new MostSpecificCheck(actuals);
}
@Override
@@ -935,8 +933,8 @@
}
@Override
- public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
- return new MostSpecificCheck(strict, actuals);
+ public MethodCheck mostSpecificCheck(List<Type> actuals) {
+ return new MostSpecificCheck(actuals);
}
@Override
@@ -1047,11 +1045,9 @@
*/
class MostSpecificCheck implements MethodCheck {
- boolean strict;
List<Type> actuals;
- MostSpecificCheck(boolean strict, List<Type> actuals) {
- this.strict = strict;
+ MostSpecificCheck(List<Type> actuals) {
this.actuals = actuals;
}
@@ -1077,7 +1073,7 @@
ResultInfo methodCheckResult(Type to, DeferredAttr.DeferredAttrContext deferredAttrContext,
Warner rsWarner, Type actual) {
return attr.new ResultInfo(KindSelector.VAL, to,
- new MostSpecificCheckContext(strict, deferredAttrContext, rsWarner, actual));
+ new MostSpecificCheckContext(deferredAttrContext, rsWarner, actual));
}
/**
@@ -1089,8 +1085,8 @@
Type actual;
- public MostSpecificCheckContext(boolean strict, DeferredAttrContext deferredAttrContext, Warner rsWarner, Type actual) {
- super(strict, deferredAttrContext, rsWarner);
+ public MostSpecificCheckContext(DeferredAttrContext deferredAttrContext, Warner rsWarner, Type actual) {
+ super(true, deferredAttrContext, rsWarner);
this.actual = actual;
}
@@ -1236,7 +1232,7 @@
}
- public MethodCheck mostSpecificCheck(List<Type> actuals, boolean strict) {
+ public MethodCheck mostSpecificCheck(List<Type> actuals) {
Assert.error("Cannot get here!");
return null;
}
@@ -1427,8 +1423,7 @@
Symbol sym,
Symbol bestSoFar,
boolean allowBoxing,
- boolean useVarargs,
- boolean operator) {
+ boolean useVarargs) {
if (sym.kind == ERR ||
!sym.isInheritedIn(site.tsym, types)) {
return bestSoFar;
@@ -1441,16 +1436,13 @@
try {
Type mt = rawInstantiate(env, site, sym, null, argtypes, typeargtypes,
allowBoxing, useVarargs, types.noWarnings);
- if (!operator || verboseResolutionMode.contains(VerboseResolutionMode.PREDEF))
- currentResolutionContext.addApplicableCandidate(sym, mt);
+ currentResolutionContext.addApplicableCandidate(sym, mt);
} catch (InapplicableMethodException ex) {
- if (!operator)
- currentResolutionContext.addInapplicableCandidate(sym, ex.getDiagnostic());
+ currentResolutionContext.addInapplicableCandidate(sym, ex.getDiagnostic());
switch (bestSoFar.kind) {
case ABSENT_MTH:
return new InapplicableSymbolError(currentResolutionContext);
case WRONG_MTH:
- if (operator) return bestSoFar;
bestSoFar = new InapplicableSymbolsError(currentResolutionContext);
default:
return bestSoFar;
@@ -1463,8 +1455,7 @@
}
return (bestSoFar.kind.isOverloadError() && bestSoFar.kind != AMBIGUOUS)
? sym
- : mostSpecific(argtypes, sym, bestSoFar, env, site,
- allowBoxing && operator, useVarargs);
+ : mostSpecific(argtypes, sym, bestSoFar, env, site, useVarargs);
}
/* Return the most specific of the two methods for a call,
@@ -1481,15 +1472,14 @@
Symbol m2,
Env<AttrContext> env,
final Type site,
- boolean allowBoxing,
boolean useVarargs) {
switch (m2.kind) {
case MTH:
if (m1 == m2) return m1;
boolean m1SignatureMoreSpecific =
- signatureMoreSpecific(argtypes, env, site, m1, m2, allowBoxing, useVarargs);
+ signatureMoreSpecific(argtypes, env, site, m1, m2, useVarargs);
boolean m2SignatureMoreSpecific =
- signatureMoreSpecific(argtypes, env, site, m2, m1, allowBoxing, useVarargs);
+ signatureMoreSpecific(argtypes, env, site, m2, m1, useVarargs);
if (m1SignatureMoreSpecific && m2SignatureMoreSpecific) {
Type mt1 = types.memberType(site, m1);
Type mt2 = types.memberType(site, m2);
@@ -1531,7 +1521,7 @@
boolean m1MoreSpecificThanAnyAmbiguous = true;
boolean allAmbiguousMoreSpecificThanM1 = true;
for (Symbol s : e.ambiguousSyms) {
- Symbol moreSpecific = mostSpecific(argtypes, m1, s, env, site, allowBoxing, useVarargs);
+ Symbol moreSpecific = mostSpecific(argtypes, m1, s, env, site, useVarargs);
m1MoreSpecificThanAnyAmbiguous &= moreSpecific == m1;
allAmbiguousMoreSpecificThanM1 &= moreSpecific == s;
}
@@ -1547,7 +1537,7 @@
}
}
//where
- private boolean signatureMoreSpecific(List<Type> actuals, Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean allowBoxing, boolean useVarargs) {
+ private boolean signatureMoreSpecific(List<Type> actuals, Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean useVarargs) {
noteWarner.clear();
int maxLength = Math.max(
Math.max(m1.type.getParameterTypes().length(), actuals.length()),
@@ -1557,10 +1547,10 @@
currentResolutionContext = new MethodResolutionContext();
currentResolutionContext.step = prevResolutionContext.step;
currentResolutionContext.methodCheck =
- prevResolutionContext.methodCheck.mostSpecificCheck(actuals, !allowBoxing);
+ prevResolutionContext.methodCheck.mostSpecificCheck(actuals);
Type mst = instantiate(env, site, m2, null,
adjustArgs(types.cvarLowerBounds(types.memberType(site, m1).getParameterTypes()), m1, maxLength, useVarargs), null,
- allowBoxing, useVarargs, noteWarner);
+ false, useVarargs, noteWarner);
return mst != null &&
!noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
} finally {
@@ -1623,11 +1613,10 @@
Symbol bestSoFar,
boolean allowBoxing,
boolean useVarargs,
- boolean operator,
boolean abstractok) {
for (Symbol s : sc.getSymbolsByName(name, new LookupFilter(abstractok))) {
bestSoFar = selectBest(env, site, argtypes, typeargtypes, s,
- bestSoFar, allowBoxing, useVarargs, operator);
+ bestSoFar, allowBoxing, useVarargs);
}
return bestSoFar;
}
@@ -1667,8 +1656,7 @@
List<Type> argtypes,
List<Type> typeargtypes,
boolean allowBoxing,
- boolean useVarargs,
- boolean operator) {
+ boolean useVarargs) {
Symbol bestSoFar = methodNotFound;
bestSoFar = findMethod(env,
site,
@@ -1678,8 +1666,7 @@
site.tsym.type,
bestSoFar,
allowBoxing,
- useVarargs,
- operator);
+ useVarargs);
return bestSoFar;
}
// where
@@ -1691,15 +1678,14 @@
Type intype,
Symbol bestSoFar,
boolean allowBoxing,
- boolean useVarargs,
- boolean operator) {
+ boolean useVarargs) {
@SuppressWarnings({"unchecked","rawtypes"})
List<Type>[] itypes = (List<Type>[])new List[] { List.<Type>nil(), List.<Type>nil() };
InterfaceLookupPhase iphase = InterfaceLookupPhase.ABSTRACT_OK;
for (TypeSymbol s : superclasses(intype)) {
bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes,
- s.members(), bestSoFar, allowBoxing, useVarargs, operator, true);
+ s.members(), bestSoFar, allowBoxing, useVarargs, true);
if (name == names.init) return bestSoFar;
iphase = (iphase == null) ? null : iphase.update(s, this);
if (iphase != null) {
@@ -1720,7 +1706,7 @@
if (iphase2 == InterfaceLookupPhase.DEFAULT_OK &&
(itype.tsym.flags() & DEFAULT) == 0) continue;
bestSoFar = findMethodInScope(env, site, name, argtypes, typeargtypes,
- itype.tsym.members(), bestSoFar, allowBoxing, useVarargs, operator, true);
+ itype.tsym.members(), bestSoFar, allowBoxing, useVarargs, true);
if (concrete != bestSoFar &&
concrete.kind.isValid() &&
bestSoFar.kind.isValid() &&
@@ -1833,7 +1819,7 @@
if (isStatic(env1)) staticOnly = true;
Symbol sym = findMethod(
env1, env1.enclClass.sym.type, name, argtypes, typeargtypes,
- allowBoxing, useVarargs, false);
+ allowBoxing, useVarargs);
if (sym.exists()) {
if (staticOnly &&
sym.kind == MTH &&
@@ -1848,7 +1834,7 @@
}
Symbol sym = findMethod(env, syms.predefClass.type, name, argtypes,
- typeargtypes, allowBoxing, useVarargs, false);
+ typeargtypes, allowBoxing, useVarargs);
if (sym.exists())
return sym;
@@ -1862,7 +1848,7 @@
bestSoFar = selectBest(env, origin.type,
argtypes, typeargtypes,
currentSym, bestSoFar,
- allowBoxing, useVarargs, false);
+ allowBoxing, useVarargs);
}
}
if (bestSoFar.exists())
@@ -1878,7 +1864,7 @@
bestSoFar = selectBest(env, origin.type,
argtypes, typeargtypes,
currentSym, bestSoFar,
- allowBoxing, useVarargs, false);
+ allowBoxing, useVarargs);
}
}
return bestSoFar;
@@ -2269,9 +2255,7 @@
(typeargtypes == null || !Type.isErroneous(typeargtypes));
}
public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) {
- return (syms.operatorNames.contains(name)) ?
- argtypes :
- Type.map(argtypes, new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step));
+ return Type.map(argtypes, new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step));
}
};
@@ -2375,7 +2359,7 @@
Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) {
return findMethod(env, site, name, argtypes, typeargtypes,
phase.isBoxingRequired(),
- phase.isVarargsRequired(), false);
+ phase.isVarargsRequired());
}
@Override
Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
@@ -2506,7 +2490,7 @@
Symbol sym = findMethod(env, site,
names.init, argtypes,
typeargtypes, allowBoxing,
- useVarargs, false);
+ useVarargs);
chk.checkDeprecated(pos, env.info.scope.owner, sym);
return sym;
}
@@ -2587,71 +2571,12 @@
newConstr,
bestSoFar,
allowBoxing,
- useVarargs,
- false);
+ useVarargs);
}
}
return bestSoFar;
}
-
-
- /** Resolve operator.
- * @param pos The position to use for error reporting.
- * @param optag The tag of the operation tree.
- * @param env The environment current at the operation.
- * @param argtypes The types of the operands.
- */
- Symbol resolveOperator(DiagnosticPosition pos, JCTree.Tag optag,
- Env<AttrContext> env, List<Type> argtypes) {
- MethodResolutionContext prevResolutionContext = currentResolutionContext;
- try {
- currentResolutionContext = new MethodResolutionContext();
- Name name = treeinfo.operatorName(optag);
- return lookupMethod(env, pos, syms.predefClass, currentResolutionContext,
- new BasicLookupHelper(name, syms.predefClass.type, argtypes, null, BOX) {
- @Override
- Symbol doLookup(Env<AttrContext> env, MethodResolutionPhase phase) {
- return findMethod(env, site, name, argtypes, typeargtypes,
- phase.isBoxingRequired(),
- phase.isVarargsRequired(), true);
- }
- @Override
- Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
- return accessMethod(sym, pos, env.enclClass.sym.type, name,
- false, argtypes, null);
- }
- });
- } finally {
- currentResolutionContext = prevResolutionContext;
- }
- }
-
- /** Resolve operator.
- * @param pos The position to use for error reporting.
- * @param optag The tag of the operation tree.
- * @param env The environment current at the operation.
- * @param arg The type of the operand.
- */
- Symbol resolveUnaryOperator(DiagnosticPosition pos, JCTree.Tag optag, Env<AttrContext> env, Type arg) {
- return resolveOperator(pos, optag, env, List.of(arg));
- }
-
- /** Resolve binary operator.
- * @param pos The position to use for error reporting.
- * @param optag The tag of the operation tree.
- * @param env The environment current at the operation.
- * @param left The types of the left operand.
- * @param right The types of the right operand.
- */
- Symbol resolveBinaryOperator(DiagnosticPosition pos,
- JCTree.Tag optag,
- Env<AttrContext> env,
- Type left,
- Type right) {
- return resolveOperator(pos, optag, env, List.of(left, right));
- }
-
Symbol getMemberReference(DiagnosticPosition pos,
Env<AttrContext> env,
JCMemberReference referenceTree,
@@ -3122,7 +3047,7 @@
@Override
final Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
return findMethod(env, site, name, argtypes, typeargtypes,
- phase.isBoxingRequired(), phase.isVarargsRequired(), syms.operatorNames.contains(name));
+ phase.isBoxingRequired(), phase.isVarargsRequired());
}
@Override
@@ -3217,7 +3142,7 @@
MethodSymbol arrayConstr = new MethodSymbol(PUBLIC, name, null, site.tsym);
arrayConstr.type = new MethodType(List.<Type>of(syms.intType), site, List.<Type>nil(), syms.methodClass);
sc.enter(arrayConstr);
- return findMethodInScope(env, site, name, argtypes, typeargtypes, sc, methodNotFound, phase.isBoxingRequired(), phase.isVarargsRequired(), false, false);
+ return findMethodInScope(env, site, name, argtypes, typeargtypes, sc, methodNotFound, phase.isBoxingRequired(), phase.isVarargsRequired(), false);
}
@Override
@@ -3252,7 +3177,7 @@
Symbol sym = needsInference ?
findDiamond(env, site, argtypes, typeargtypes, phase.isBoxingRequired(), phase.isVarargsRequired()) :
findMethod(env, site, name, argtypes, typeargtypes,
- phase.isBoxingRequired(), phase.isVarargsRequired(), syms.operatorNames.contains(name));
+ phase.isBoxingRequired(), phase.isVarargsRequired());
return (sym.kind != MTH ||
site.getEnclosingType().hasTag(NONE) ||
hasEnclosingInstance(env, site)) ?
@@ -3607,16 +3532,6 @@
if (name == names.error)
return null;
- if (syms.operatorNames.contains(name)) {
- boolean isUnaryOp = argtypes.size() == 1;
- String key = argtypes.size() == 1 ?
- "operator.cant.be.applied" :
- "operator.cant.be.applied.1";
- Type first = argtypes.head;
- Type second = !isUnaryOp ? argtypes.tail.head : null;
- return diags.create(dkind, log.currentSource(), pos,
- key, name, first, second);
- }
boolean hasLocation = false;
if (location == null) {
location = site.tsym;
@@ -3716,36 +3631,24 @@
if (name == names.error)
return null;
- if (syms.operatorNames.contains(name)) {
- boolean isUnaryOp = argtypes.size() == 1;
- String key = argtypes.size() == 1 ?
- "operator.cant.be.applied" :
- "operator.cant.be.applied.1";
- Type first = argtypes.head;
- Type second = !isUnaryOp ? argtypes.tail.head : null;
- return diags.create(dkind, log.currentSource(), pos,
- key, name, first, second);
+ Pair<Symbol, JCDiagnostic> c = errCandidate();
+ if (compactMethodDiags) {
+ JCDiagnostic simpleDiag =
+ MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, c.snd);
+ if (simpleDiag != null) {
+ return simpleDiag;
+ }
}
- else {
- Pair<Symbol, JCDiagnostic> c = errCandidate();
- if (compactMethodDiags) {
- JCDiagnostic simpleDiag =
- MethodResolutionDiagHelper.rewrite(diags, pos, log.currentSource(), dkind, c.snd);
- if (simpleDiag != null) {
- return simpleDiag;
- }
- }
- Symbol ws = c.fst.asMemberOf(site, types);
- return diags.create(dkind, log.currentSource(), pos,
- "cant.apply.symbol",
- kindName(ws),
- ws.name == names.init ? ws.owner.name : ws.name,
- methodArguments(ws.type.getParameterTypes()),
- methodArguments(argtypes),
- kindName(ws.owner),
- ws.owner.type,
- c.snd);
- }
+ Symbol ws = c.fst.asMemberOf(site, types);
+ return diags.create(dkind, log.currentSource(), pos,
+ "cant.apply.symbol",
+ kindName(ws),
+ ws.name == names.init ? ws.owner.name : ws.name,
+ methodArguments(ws.type.getParameterTypes()),
+ methodArguments(argtypes),
+ kindName(ws.owner),
+ ws.owner.type,
+ c.snd);
}
@Override
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Thu Feb 19 16:38:54 2015 -0800
@@ -678,29 +678,43 @@
boolean haveJImageFiles =
files.anyMatch(f -> f.getFileName().toString().endsWith(".jimage"));
if (haveJImageFiles) {
- return Collections.singleton(JRT_MARKER_FILE);
+ return addAdditionalBootEntries(Collections.singleton(JRT_MARKER_FILE));
}
}
}
- // Temporary: if no .jimage files, return individual modules
- if (Files.exists(libModules.resolve("java.base"))) {
- return Files.list(libModules)
- .map(d -> d.resolve("classes"))
- .collect(Collectors.toList());
- }
-
// Exploded module image
Path modules = Paths.get(java_home, "modules");
if (Files.isDirectory(modules.resolve("java.base"))) {
- return Files.list(modules)
- .collect(Collectors.toList());
+ try (Stream<Path> listedModules = Files.list(modules)) {
+ return addAdditionalBootEntries(listedModules.collect(Collectors.toList()));
+ }
}
// not a modular image that we know about
return null;
}
+ //ensure bootclasspath prepends/appends are reflected in the systemClasses
+ private Collection<Path> addAdditionalBootEntries(Collection<Path> modules) throws IOException {
+ String files = System.getProperty("sun.boot.class.path");
+
+ if (files == null)
+ return modules;
+
+ Set<Path> paths = new LinkedHashSet<>();
+
+ for (String s : files.split(Pattern.quote(File.pathSeparator))) {
+ if (s.endsWith(".jimage")) {
+ paths.addAll(modules);
+ } else if (!s.isEmpty()) {
+ paths.add(Paths.get(s));
+ }
+ }
+
+ return paths;
+ }
+
private void lazy() {
if (searchPath == null) {
try {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java Thu Feb 19 16:38:54 2015 -0800
@@ -656,8 +656,7 @@
private void writeParamAnnotations(MethodSymbol m,
RetentionPolicy retention) {
- databuf.appendByte(m.params.length() + m.extraParams.length());
- writeParamAnnotations(m.extraParams, retention);
+ databuf.appendByte(m.params.length());
writeParamAnnotations(m.params, retention);
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Feb 19 16:38:54 2015 -0800
@@ -828,7 +828,7 @@
compiler.err.not.encl.class=\
not an enclosing class: {0}
-# 0: name, 1: type, 2: unused
+# 0: name, 1: type
compiler.err.operator.cant.be.applied=\
bad operand type {1} for unary operator ''{0}''
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java Thu Feb 19 16:38:54 2015 -0800
@@ -51,62 +51,6 @@
* deletion without notice.</b>
*/
public class TreeInfo {
- protected static final Context.Key<TreeInfo> treeInfoKey = new Context.Key<>();
-
- public static TreeInfo instance(Context context) {
- TreeInfo instance = context.get(treeInfoKey);
- if (instance == null)
- instance = new TreeInfo(context);
- return instance;
- }
-
- /** The names of all operators.
- */
- private Name[] opname = new Name[Tag.getNumberOfOperators()];
-
- private void setOpname(Tag tag, String name, Names names) {
- setOpname(tag, names.fromString(name));
- }
- private void setOpname(Tag tag, Name name) {
- opname[tag.operatorIndex()] = name;
- }
-
- private TreeInfo(Context context) {
- context.put(treeInfoKey, this);
-
- Names names = Names.instance(context);
- /* Internally we use +++, --- for unary +, - to reduce +, - operators
- * overloading
- */
- setOpname(POS, "+++", names);
- setOpname(NEG, "---", names);
- setOpname(NOT, "!", names);
- setOpname(COMPL, "~", names);
- setOpname(PREINC, "++", names);
- setOpname(PREDEC, "--", names);
- setOpname(POSTINC, "++", names);
- setOpname(POSTDEC, "--", names);
- setOpname(NULLCHK, "<*nullchk*>", names);
- setOpname(OR, "||", names);
- setOpname(AND, "&&", names);
- setOpname(EQ, "==", names);
- setOpname(NE, "!=", names);
- setOpname(LT, "<", names);
- setOpname(GT, ">", names);
- setOpname(LE, "<=", names);
- setOpname(GE, ">=", names);
- setOpname(BITOR, "|", names);
- setOpname(BITXOR, "^", names);
- setOpname(BITAND, "&", names);
- setOpname(SL, "<<", names);
- setOpname(SR, ">>", names);
- setOpname(USR, ">>>", names);
- setOpname(PLUS, "+", names);
- setOpname(MINUS, names.hyphen);
- setOpname(MUL, names.asterisk);
- setOpname(DIV, names.slash);
- setOpname(MOD, "%", names);
- }
public static List<JCExpression> args(JCTree t) {
switch (t.getTag()) {
@@ -119,12 +63,6 @@
}
}
- /** Return name of operator with given tree tag.
- */
- public Name operatorName(JCTree.Tag tag) {
- return opname[tag.operatorIndex()];
- }
-
/** Is tree a constructor declaration?
*/
public static boolean isConstructor(JCTree tree) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Bits.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Bits.java Thu Feb 19 16:38:54 2015 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -84,20 +84,6 @@
}
- public enum BitsOpKind {
- INIT,
- CLEAR,
- INCL_BIT,
- EXCL_BIT,
- ASSIGN,
- AND_SET,
- OR_SET,
- DIFF_SET,
- XOR_SET,
- INCL_RANGE,
- EXCL_RANGE,
- }
-
private final static int wordlen = 32;
private final static int wordshift = 5;
private final static int wordmask = wordlen - 1;
--- a/langtools/test/tools/javac/7102515/T7102515.out Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/test/tools/javac/7102515/T7102515.out Thu Feb 19 16:38:54 2015 -0800
@@ -1,3 +1,3 @@
T7102515.java:9:41: compiler.err.operator.cant.be.applied.1: +, T7102515, T7102515
-T7102515.java:10:32: compiler.err.operator.cant.be.applied: ++, T7102515, null
+T7102515.java:10:32: compiler.err.operator.cant.be.applied: ++, T7102515
2 errors
--- a/langtools/test/tools/javac/annotations/SyntheticParameters.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/test/tools/javac/annotations/SyntheticParameters.java Thu Feb 19 16:38:54 2015 -0800
@@ -46,20 +46,11 @@
null,
new ExpectedParameterAnnotation[] {
(ExpectedParameterAnnotation)
- // Assert there is no annotation on the
- // this$0 parameter.
- new ExpectedParameterAnnotation(
- "<init>",
- 0,
- "A",
- true,
- 0),
- (ExpectedParameterAnnotation)
// Assert there is an annotation on the
// first parameter.
new ExpectedParameterAnnotation(
"<init>",
- 1,
+ 0,
"A",
true,
1),
@@ -71,27 +62,11 @@
true,
1),
(ExpectedParameterAnnotation)
- new ExpectedParameterAnnotation(
- "foo",
- 1,
- "A",
- true,
- 0),
- (ExpectedParameterAnnotation)
- // Assert there is no annotation on the
- // this$0 parameter.
- new ExpectedParameterAnnotation(
- "<init>",
- 0,
- "B",
- false,
- 0),
- (ExpectedParameterAnnotation)
// Assert there is an annotation on the
// first parameter.
new ExpectedParameterAnnotation(
"<init>",
- 1,
+ 0,
"B",
false,
1),
@@ -117,58 +92,22 @@
null,
new ExpectedParameterAnnotation[] {
(ExpectedParameterAnnotation)
- // Assert there is no annotation on the
- // $enum$name parameter.
+ // Assert there is an annotation on the
+ // first parameter.
new ExpectedParameterAnnotation(
"<init>",
0,
"A",
true,
- 0),
- (ExpectedParameterAnnotation)
- // Assert there is no annotation on the
- // $enum$ordinal parameter.
- new ExpectedParameterAnnotation(
- "<init>",
- 1,
- "A",
- true,
- 0),
+ 1),
(ExpectedParameterAnnotation)
// Assert there is an annotation on the
// first parameter.
new ExpectedParameterAnnotation(
"<init>",
- 2,
- "A",
- true,
- 1),
- (ExpectedParameterAnnotation)
- // Assert there is no annotation on the
- // $enum$name parameter.
- new ExpectedParameterAnnotation(
- "<init>",
0,
"B",
false,
- 0),
- (ExpectedParameterAnnotation)
- // Assert there is no annotation on the
- // $enum$ordinal parameter.
- new ExpectedParameterAnnotation(
- "<init>",
- 1,
- "B",
- false,
- 0),
- (ExpectedParameterAnnotation)
- // Assert there is an annotation on the
- // first parameter.
- new ExpectedParameterAnnotation(
- "<init>",
- 2,
- "B",
- false,
1)
},
null);
--- a/langtools/test/tools/javac/annotations/typeAnnotations/classfile/SyntheticParameters.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/classfile/SyntheticParameters.java Thu Feb 19 16:38:54 2015 -0800
@@ -44,15 +44,6 @@
null,
new ExpectedMethodTypeAnnotation[] {
(ExpectedMethodTypeAnnotation)
- // Assert there is no annotation on the
- // this$0 parameter.
- new ExpectedMethodTypeAnnotation.Builder(
- "<init>",
- "A",
- TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
- false,
- 0).setParameterIndex(0).build(),
- (ExpectedMethodTypeAnnotation)
// Assert there is an annotation on the
// first parameter.
new ExpectedMethodTypeAnnotation.Builder(
@@ -60,21 +51,7 @@
"A",
TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
false,
- 1).setParameterIndex(1).build(),
- (ExpectedMethodTypeAnnotation)
- new ExpectedMethodTypeAnnotation.Builder(
- "foo",
- "A",
- TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
- false,
- 1).setParameterIndex(0).build(),
- (ExpectedMethodTypeAnnotation)
- new ExpectedMethodTypeAnnotation.Builder(
- "foo",
- "A",
- TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
- false,
- 0).setParameterIndex(1).build()
+ 1).setParameterIndex(0).build()
},
null);
private static final Expected Foo_expected =
@@ -89,26 +66,7 @@
"A",
TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
false,
- 0).setParameterIndex(0).build(),
- (ExpectedMethodTypeAnnotation)
- // Assert there is no annotation on the
- // $enum$ordinal parameter.
- new ExpectedMethodTypeAnnotation.Builder(
- "<init>",
- "A",
- TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
- false,
- 0).setParameterIndex(1).build(),
- (ExpectedMethodTypeAnnotation)
- // Assert there is an annotation on the
- // first parameter.
- new ExpectedMethodTypeAnnotation.Builder(
- "<init>",
- "A",
- TypeAnnotation.TargetType.METHOD_FORMAL_PARAMETER,
- false,
- 1).setParameterIndex(2).build()
- },
+ 1).setParameterIndex(0).build() },
null);
public static void main(String... args) throws Exception {
--- a/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/test/tools/javac/annotations/typeAnnotations/referenceinfos/Constructors.java Thu Feb 19 16:38:54 2015 -0800
@@ -43,7 +43,7 @@
@TADescription(annotation = "TA", type = METHOD_RETURN, genericLocation = {1, 0})
@TADescription(annotation = "TB", type = METHOD_RETURN, genericLocation = {1, 0})
- @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
+ @TADescription(annotation = "TC", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
@TestClass("%TEST_CLASS_NAME%$Inner")
public String innerClass() {
return "class %TEST_CLASS_NAME% { class Inner {" +
@@ -56,7 +56,7 @@
@TADescription(annotation = "TB", type = METHOD_RETURN, genericLocation = {1, 0})
@TADescription(annotation = "TC", type = METHOD_RECEIVER)
@TADescription(annotation = "TD", type = METHOD_RETURN, genericLocation = {1, 0})
- @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
+ @TADescription(annotation = "TE", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
@TestClass("%TEST_CLASS_NAME%$Inner")
public String innerClass2() {
return "class %TEST_CLASS_NAME% { class Inner {" +
@@ -70,7 +70,7 @@
@TADescription(annotation = "TC", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0})
@TADescription(annotation = "TD", type = METHOD_RECEIVER, genericLocation = {1, 0})
@TADescription(annotation = "TE", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0})
- @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
+ @TADescription(annotation = "TF", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
@TestClass("Outer$Middle$Inner")
public String innerClass3() {
return "class Outer { class Middle { class Inner {" +
@@ -89,7 +89,7 @@
@TADescription(annotation = "RTAs", type = METHOD_RETURN, genericLocation = {1, 0})
@TADescription(annotation = "RTBs", type = METHOD_RETURN, genericLocation = {1, 0})
- @TADescription(annotation = "RTCs", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
+ @TADescription(annotation = "RTCs", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
@TestClass("%TEST_CLASS_NAME%$Inner")
public String innerClassRepeatableAnnotation() {
return "class %TEST_CLASS_NAME% { class Inner {" +
@@ -102,7 +102,7 @@
@TADescription(annotation = "RTBs", type = METHOD_RETURN, genericLocation = {1, 0})
@TADescription(annotation = "RTCs", type = METHOD_RECEIVER)
@TADescription(annotation = "RTDs", type = METHOD_RETURN, genericLocation = {1, 0})
- @TADescription(annotation = "RTEs", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
+ @TADescription(annotation = "RTEs", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
@TestClass("%TEST_CLASS_NAME%$Inner")
public String innerClassRepeatableAnnotation2() {
return "class %TEST_CLASS_NAME% { class Inner {" +
@@ -116,7 +116,7 @@
@TADescription(annotation = "RTCs", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0})
@TADescription(annotation = "RTDs", type = METHOD_RECEIVER, genericLocation = {1, 0})
@TADescription(annotation = "RTEs", type = METHOD_RETURN, genericLocation = {1, 0, 1, 0})
- @TADescription(annotation = "RTFs", type = METHOD_FORMAL_PARAMETER, paramIndex = 1)
+ @TADescription(annotation = "RTFs", type = METHOD_FORMAL_PARAMETER, paramIndex = 0)
@TestClass("Outer$Middle$Inner")
public String innerClassRepatableAnnotation3() {
return "class Outer { class Middle { class Inner {" +
--- a/langtools/test/tools/javac/diags/examples/IncomparableTypes.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/test/tools/javac/diags/examples/IncomparableTypes.java Thu Feb 19 16:38:54 2015 -0800
@@ -24,5 +24,5 @@
// key: compiler.err.incomparable.types
class X {
- boolean b = (this == 1);
+ boolean b = (this == "");
}
--- a/langtools/test/tools/javac/expression/NullAppend.out Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/test/tools/javac/expression/NullAppend.out Thu Feb 19 16:38:54 2015 -0800
@@ -1,2 +1,2 @@
-NullAppend.java:11:16: compiler.err.operator.cant.be.applied.1: +, compiler.misc.type.null, compiler.misc.type.null
+NullAppend.java:11:21: compiler.err.operator.cant.be.applied.1: +, compiler.misc.type.null, compiler.misc.type.null
1 error
--- a/langtools/test/tools/javac/expression/NullAppend2.out Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/test/tools/javac/expression/NullAppend2.out Thu Feb 19 16:38:54 2015 -0800
@@ -1,2 +1,2 @@
-NullAppend2.java:10:16: compiler.err.operator.cant.be.applied.1: +, compiler.misc.type.null, int
+NullAppend2.java:10:21: compiler.err.operator.cant.be.applied.1: +, compiler.misc.type.null, int
1 error
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/file/BootClassPathPrepend.java Thu Feb 19 16:38:54 2015 -0800
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8067445
+ * @summary Verify that file.Locations analyze sun.boot.class.path for BCP prepends/appends
+ * @library /tools/lib
+ */
+
+import java.io.IOException;
+import java.util.EnumSet;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+public class BootClassPathPrepend {
+ public static void main(String... args) throws IOException {
+ if (args.length == 0) {
+ new BootClassPathPrepend().reRun();
+ } else {
+ new BootClassPathPrepend().run();
+ }
+ }
+
+ void reRun() {
+ String testClasses = System.getProperty("test.classes");
+ ToolBox tb = new ToolBox();
+ tb.new JavaTask().vmOptions("-Xbootclasspath/p:" + testClasses)
+ .classArgs("real-run")
+ .className("BootClassPathPrepend")
+ .run()
+ .writeAll();
+ }
+
+ EnumSet<Kind> classKind = EnumSet.of(JavaFileObject.Kind.CLASS);
+
+ void run() throws IOException {
+ JavaCompiler toolProvider = ToolProvider.getSystemJavaCompiler();
+ try (JavaFileManager fm = toolProvider.getStandardFileManager(null, null, null)) {
+ Iterable<JavaFileObject> files =
+ fm.list(StandardLocation.PLATFORM_CLASS_PATH, "", classKind, false);
+ for (JavaFileObject fo : files) {
+ if (fo.isNameCompatible("BootClassPathPrepend", JavaFileObject.Kind.CLASS)) {
+ System.err.println("Found BootClassPathPrepend on bootclasspath");
+ return ;//found
+ }
+ }
+
+ throw new AssertionError("Cannot find class that was prepended on BCP");
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/file/ExplodedImage.java Thu Feb 19 16:38:54 2015 -0800
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.nio.file.DirectoryStream;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+import javax.tools.DiagnosticListener;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+/**
+ * @test
+ * @bug 8067138
+ * @summary Verify that compiling against the exploded JDK image works, and that Locations close
+ * the directory streams properly when working with exploded JDK image.
+ * @library /tools/lib
+ * @build ToolBox ExplodedImage
+ * @run main ExplodedImage
+ */
+
+public class ExplodedImage {
+ public static void main(String... args) throws IOException {
+ new ExplodedImage().run();
+ }
+
+ void run() throws IOException {
+ for (String moduleLocations : new String[] {"modules/*"}) {
+ System.setProperty("java.home", originalJavaHome);
+ testDirectoryStreamClosed(moduleLocations);
+ System.setProperty("java.home", originalJavaHome);
+ testCanCompileAgainstExplodedImage(moduleLocations);
+ }
+ }
+
+ void testDirectoryStreamClosed(String loc) throws IOException {
+ System.err.println("testDirectoryStreamClosed(" + loc + ")");
+ Path javaHome = prepareJavaHome();
+ Path targetPath = javaHome.resolve(loc.replace("*", "/java.base").replace("/", sep));
+ Path testClass = targetPath.resolve(("java/lang/" + TEST_FILE).replace("/", sep));
+ Files.createDirectories(testClass.getParent());
+ Files.createFile(testClass);
+ System.setProperty("java.home", javaHome.toString());
+
+ for (int i = 0; i < REPEATS; i++) {
+ try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
+ Iterable<JavaFileObject> javaLangContent =
+ fm.list(StandardLocation.PLATFORM_CLASS_PATH,
+ "java.lang",
+ EnumSet.allOf(JavaFileObject.Kind.class),
+ false);
+ boolean found = false;
+
+ for (JavaFileObject fo : javaLangContent) {
+ if (!fo.getName().endsWith(TEST_FILE)) {
+ throw new IllegalStateException("Wrong file: " + fo);
+ }
+ found = true;
+ }
+
+ if (!found)
+ throw new IllegalStateException("Could not find the expected file!");
+ }
+ }
+
+ System.err.println("finished.");
+ }
+ //where:
+ static final String TEST_FILE = "ExplodedImageTestFile.class";
+ static final int REPEATS = 16 * 1024 + 1;
+
+ void testCanCompileAgainstExplodedImage(String loc) throws IOException {
+ System.err.println("testCanCompileAgainstExplodedImage(" + loc + ")");
+ Path javaHome = prepareJavaHome();
+ Path targetPath = javaHome.resolve(loc.replace("*", "/java.base").replace("/", sep));
+ try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
+ for (String pack : REQUIRED_PACKAGES) {
+ Iterable<JavaFileObject> content = fm.list(StandardLocation.PLATFORM_CLASS_PATH,
+ pack,
+ EnumSet.allOf(JavaFileObject.Kind.class),
+ false);
+
+ for (JavaFileObject jfo : content) {
+ String name = jfo.getName();
+ int lastSlash = name.lastIndexOf('/');
+ name = lastSlash >= 0 ? name.substring(lastSlash + 1) : name;
+ Path target = targetPath.resolve(pack.replace(".", sep) + sep + name);
+ Files.createDirectories(target.getParent());
+ try (InputStream in = jfo.openInputStream()) {
+ Files.copy(in, target);
+ }
+ }
+ }
+ }
+
+ System.setProperty("java.home", javaHome.toString());
+
+ try (StandardJavaFileManager fm = javaCompiler.getStandardFileManager(null, null, null)) {
+ DiagnosticListener<JavaFileObject> noErrors = d -> {
+ if (d.getKind() == Diagnostic.Kind.ERROR)
+ throw new IllegalStateException("Unexpected error: " + d);
+ };
+ ToolBox.JavaSource inputFile =
+ new ToolBox.JavaSource("import java.util.List; class Test { List l; }");
+ List<JavaFileObject> inputFiles = Arrays.asList(inputFile);
+ boolean result =
+ javaCompiler.getTask(null, fm, noErrors, null, null, inputFiles).call();
+ if (!result) {
+ throw new IllegalStateException("Could not compile correctly!");
+ }
+ JavacTask task =
+ (JavacTask) javaCompiler.getTask(null, fm, noErrors, null, null, inputFiles);
+ task.parse();
+ TypeElement juList = task.getElements().getTypeElement("java.util.List");
+ if (juList == null)
+ throw new IllegalStateException("Cannot resolve java.util.List!");
+ URI listSource = ((ClassSymbol) juList).classfile.toUri();
+ if (!listSource.toString().startsWith(javaHome.toUri().toString()))
+ throw new IllegalStateException( "Did not load java.util.List from correct place, " +
+ "actual location: " + listSource.toString() +
+ "; expected prefix: " + javaHome.toUri());
+ }
+
+ System.err.println("finished.");
+ }
+ //where:
+ static final String[] REQUIRED_PACKAGES = {"java.lang", "java.io", "java.util"};
+
+ Path prepareJavaHome() throws IOException {
+ Path javaHome = new File("javahome").getAbsoluteFile().toPath();
+ delete(javaHome);
+ Files.createDirectory(javaHome);
+ return javaHome;
+ }
+
+ String sep = FileSystems.getDefault().getSeparator();
+ JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
+ String originalJavaHome = System.getProperty("java.home");
+
+ void delete(Path p) throws IOException {
+ if (!Files.exists(p))
+ return ;
+ if (Files.isDirectory(p)) {
+ try (DirectoryStream<Path> dir = Files.newDirectoryStream(p)) {
+ for (Path child : dir) {
+ delete(child);
+ }
+ }
+ }
+ Files.delete(p);
+ }
+}
--- a/langtools/test/tools/javac/lambda/8068399/T8068399.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/test/tools/javac/lambda/8068399/T8068399.java Thu Feb 19 16:38:54 2015 -0800
@@ -24,7 +24,7 @@
*/
/*
* @test
- * @bug 8068399
+ * @bug 8068399 8069545
* @summary structural most specific and stuckness
*/
--- a/langtools/test/tools/javac/lambda/8068430/T8068430.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/test/tools/javac/lambda/8068430/T8068430.java Thu Feb 19 16:38:54 2015 -0800
@@ -25,7 +25,7 @@
/*
* @test
- * @bug 8068430
+ * @bug 8068430 8069545
* @summary structural most specific and stuckness
*/
@@ -43,4 +43,4 @@
(i, e) -> i + e.getKey(),
(i1, i2) -> i1 + i2));
}
-}
\ No newline at end of file
+}
--- a/langtools/test/tools/javac/lambda/8071432/T8071432.java Thu Feb 19 11:24:07 2015 -0800
+++ b/langtools/test/tools/javac/lambda/8071432/T8071432.java Thu Feb 19 16:38:54 2015 -0800
@@ -1,6 +1,6 @@
/*
* @test /nodynamiccopyright/
- * @bug 8071432
+ * @bug 8071432 8069545
* @summary structural most specific and stuckness
* @compile/fail/ref=T8071432.out -XDrawDiagnostics T8071432.java
*/
--- a/langtools/test/tools/javac/resolve/tests/PrimitiveBinopOverload.java Thu Feb 19 11:24:07 2015 -0800
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-@TraceResolve
-class PrimitiveBinopOverload {
-
- @Candidate(applicable=Phase.BASIC, mostSpecific=true)
- int _plus(int x, int y) { return -1; }
- @Candidate(applicable=Phase.BASIC)
- long _plus(long x, long y) { return -1; }
- @Candidate(applicable=Phase.BASIC)
- float _plus(float x, float y) { return -1; }
- @Candidate(applicable=Phase.BASIC)
- double _plus(double x, double y) { return -1; }
- //not a candidate
- Object _plus(Object x, Object y) { return -1; }
-
- @Candidate(applicable= { Phase.BASIC, Phase.BOX }, mostSpecific=true)
- int _minus(int x, int y) { return -1; }
- @Candidate(applicable= { Phase.BASIC, Phase.BOX })
- long _minus(long x, long y) { return -1; }
- @Candidate(applicable= { Phase.BASIC, Phase.BOX })
- float _minus(float x, float y) { return -1; }
- @Candidate(applicable= { Phase.BASIC, Phase.BOX })
- double _minus(double x, double y) { return -1; }
-
- @Candidate(applicable= { Phase.BASIC, Phase.BOX }, mostSpecific=true)
- int _mul(int x, int y) { return -1; }
- @Candidate(applicable= { Phase.BASIC, Phase.BOX })
- long _mul(long x, long y) { return -1; }
- @Candidate(applicable= { Phase.BASIC, Phase.BOX })
- float _mul(float x, float y) { return -1; }
- @Candidate(applicable= { Phase.BASIC, Phase.BOX })
- double _mul(double x, double y) { return -1; }
-
- @Candidate(applicable= { Phase.BASIC, Phase.BOX }, mostSpecific=true)
- int _div(int x, int y) { return -1; }
- @Candidate(applicable= { Phase.BASIC, Phase.BOX })
- long _div(long x, long y) { return -1; }
- @Candidate(applicable= { Phase.BASIC, Phase.BOX })
- float _div(float x, float y) { return -1; }
- @Candidate(applicable= { Phase.BASIC, Phase.BOX })
- double _div(double x, double y) { return -1; }
-
- {
- int i1 = 1 + 1;
- int i2 = 5 - new Integer(3);
- int i3 = new Integer(5) * 3;
- int i4 = new Integer(6) / new Integer(2);
- }
-}