提交 17a7f52f 编写于 作者: L lana

Merge

/*
* Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2012, 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
......@@ -195,10 +195,7 @@ public class ClassUseWriter extends SubWriterHolderWriter {
ClassUseWriter clsgen;
String path = DirectoryManager.getDirectoryPath(classdoc.
containingPackage());
if (path.length() > 0) {
path += File.separator;
}
path += "class-use";
path += "class-use" + DirectoryManager.URL_FILE_SEPARATOR;
String filename = classdoc.name() + ".html";
String pkgname = classdoc.containingPackage().name();
pkgname += (pkgname.length() > 0)? ".class-use": "class-use";
......
/*
* Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2012, 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
......@@ -302,7 +302,9 @@ public class HelpWriter extends HtmlDocletWriter {
Content constHead = HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING,
getResource("doclet.Constants_Summary"));
Content liConst = HtmlTree.LI(HtmlStyle.blockList, constHead);
Content line29 = getResource("doclet.Help_line_29");
Content line29 = getResource("doclet.Help_line_29",
getHyperLinkString("constant-values.html",
configuration.getText("doclet.Constants_Summary")));
Content constPara = HtmlTree.P(line29);
liConst.addContent(constPara);
ul.addContent(liConst);
......
......@@ -160,7 +160,7 @@ doclet.Help_line_25=Frames/No Frames
doclet.Help_line_26=These links show and hide the HTML frames. All pages are available with or without frames.
doclet.Help_line_27=The {0} link shows all classes and interfaces except non-static nested types.
doclet.Help_line_28=Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.
doclet.Help_line_29=The <a href="constant-values.html">Constant Field Values</a> page lists the static final fields and their values.
doclet.Help_line_29=The {0} page lists the static final fields and their values.
doclet.Help_line_30=This help file applies to API documentation generated using the standard doclet.
doclet.Help_enum_line_1=Each enum has its own separate page with the following sections:
doclet.Help_enum_line_2=Enum declaration
......
......@@ -488,17 +488,18 @@ public abstract class Configuration {
}
/**
* Add a traliling file separator, if not found or strip off extra trailing
* file separators if any.
* Add a trailing file separator, if not found. Remove superfluous
* file separators if any. Preserve the front double file separator for
* UNC paths.
*
* @param path Path under consideration.
* @return String Properly constructed path string.
*/
String addTrailingFileSep(String path) {
public static String addTrailingFileSep(String path) {
String fs = System.getProperty("file.separator");
String dblfs = fs + fs;
int indexDblfs;
while ((indexDblfs = path.indexOf(dblfs)) >= 0) {
while ((indexDblfs = path.indexOf(dblfs, 1)) >= 0) {
path = path.substring(0, indexDblfs) +
path.substring(indexDblfs + fs.length());
}
......
......@@ -262,11 +262,7 @@ public class TagletManager {
urls[count++] = url;
}
}
if (urls.length != count) {
URL[] tmp = new URL[count];
System.arraycopy(urls, 0, tmp, 0, count);
urls = tmp;
}
urls = Arrays.copyOf(urls, count);
return urls;
}
......
......@@ -136,4 +136,11 @@ public class BasicJavacTask extends JavacTask {
throw new IllegalStateException();
}
/**
* For internal use only. This method will be
* removed without warning.
*/
public void updateContext(Context newContext) {
context = newContext;
}
}
......@@ -79,10 +79,8 @@ public class MultiTaskListener implements TaskListener {
if (ccw.unwrap(l) == listener)
throw new IllegalStateException();
}
TaskListener[] newListeners = new TaskListener[listeners.length + 1];
System.arraycopy(listeners, 0, newListeners, 0, listeners.length);
newListeners[newListeners.length - 1] = ccw.wrap(listener);
listeners = newListeners;
listeners = Arrays.copyOf(listeners, listeners.length + 1);
listeners[listeners.length - 1] = ccw.wrap(listener);
}
public void remove(TaskListener listener) {
......
......@@ -28,6 +28,7 @@ package com.sun.tools.javac.code;
import java.util.EnumSet;
import java.util.Locale;
import com.sun.source.tree.MemberReferenceTree;
import com.sun.tools.javac.api.Formattable;
import com.sun.tools.javac.api.Messages;
......@@ -85,11 +86,12 @@ public class Kinds {
public static final int AMBIGUOUS = ERRONEOUS+1; // ambiguous reference
public static final int HIDDEN = ERRONEOUS+2; // hidden method or field
public static final int STATICERR = ERRONEOUS+3; // nonstatic member from static context
public static final int ABSENT_VAR = ERRONEOUS+4; // missing variable
public static final int WRONG_MTHS = ERRONEOUS+5; // methods with wrong arguments
public static final int WRONG_MTH = ERRONEOUS+6; // one method with wrong arguments
public static final int ABSENT_MTH = ERRONEOUS+7; // missing method
public static final int ABSENT_TYP = ERRONEOUS+8; // missing type
public static final int MISSING_ENCL = ERRONEOUS+4; // missing enclosing class
public static final int ABSENT_VAR = ERRONEOUS+5; // missing variable
public static final int WRONG_MTHS = ERRONEOUS+6; // methods with wrong arguments
public static final int WRONG_MTH = ERRONEOUS+7; // one method with wrong arguments
public static final int ABSENT_MTH = ERRONEOUS+8; // missing method
public static final int ABSENT_TYP = ERRONEOUS+9; // missing type
public enum KindName implements Formattable {
ANNOTATION("kindname.annotation"),
......@@ -140,6 +142,14 @@ public class Kinds {
}
}
public static KindName kindName(MemberReferenceTree.ReferenceMode mode) {
switch (mode) {
case INVOKE: return KindName.METHOD;
case NEW: return KindName.CONSTRUCTOR;
default : throw new AssertionError("Unexpected mode: "+ mode);
}
}
/** A KindName representing a given symbol
*/
public static KindName kindName(Symbol sym) {
......
......@@ -30,6 +30,10 @@ import java.util.Locale;
import com.sun.tools.javac.api.Messages;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.DeferredAttr.DeferredType;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.Pretty;
import com.sun.tools.javac.util.Assert;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
......@@ -51,6 +55,8 @@ public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Vi
List<Type> seenCaptured = List.nil();
static final int PRIME = 997; // largest prime less than 1000
protected Printer() { }
/**
* This method should be overriden in order to provide proper i18n support.
*
......
......@@ -194,6 +194,9 @@ public enum Source {
public boolean allowObjectToPrimitiveCast() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowPoly() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowLambda() {
return compareTo(JDK1_8) >= 0;
}
......
......@@ -168,6 +168,10 @@ public abstract class Symbol implements Element {
return owner;
}
public Symbol baseSymbol() {
return this;
}
/** The symbol's erased type.
*/
public Type erasure(Types types) {
......@@ -918,7 +922,12 @@ public abstract class Symbol implements Element {
/** Clone this symbol with new owner.
*/
public VarSymbol clone(Symbol newOwner) {
VarSymbol v = new VarSymbol(flags_field, name, type, newOwner);
VarSymbol v = new VarSymbol(flags_field, name, type, newOwner) {
@Override
public Symbol baseSymbol() {
return VarSymbol.this;
}
};
v.pos = pos;
v.adr = adr;
v.data = data;
......@@ -1045,7 +1054,12 @@ public abstract class Symbol implements Element {
/** Clone this symbol with new owner.
*/
public MethodSymbol clone(Symbol newOwner) {
MethodSymbol m = new MethodSymbol(flags_field, name, type, newOwner);
MethodSymbol m = new MethodSymbol(flags_field, name, type, newOwner) {
@Override
public Symbol baseSymbol() {
return MethodSymbol.this;
}
};
m.code = code;
return m;
}
......@@ -1068,6 +1082,10 @@ public abstract class Symbol implements Element {
}
}
public boolean isDynamic() {
return false;
}
/** find a symbol that this (proxy method) symbol implements.
* @param c The class whose members are searched for
* implementations
......@@ -1356,6 +1374,27 @@ public abstract class Symbol implements Element {
}
}
/** A class for invokedynamic method calls.
*/
public static class DynamicMethodSymbol extends MethodSymbol {
public Object[] staticArgs;
public Symbol bsm;
public int bsmKind;
public DynamicMethodSymbol(Name name, Symbol owner, int bsmKind, MethodSymbol bsm, Type type, Object[] staticArgs) {
super(0, name, type, owner);
this.bsm = bsm;
this.bsmKind = bsmKind;
this.staticArgs = staticArgs;
}
@Override
public boolean isDynamic() {
return true;
}
}
/** A class for predefined operators.
*/
public static class OperatorSymbol extends MethodSymbol {
......
......@@ -126,6 +126,7 @@ public class Symtab {
public final Type cloneableType;
public final Type serializableType;
public final Type methodHandleType;
public final Type methodTypeType;
public final Type nativeHeaderType;
public final Type throwableType;
public final Type errorType;
......@@ -182,6 +183,10 @@ public class Symtab {
*/
public final Name[] boxedName = new Name[TypeTags.TypeTagCount];
/** A set containing all operator names.
*/
public final Set<Name> operatorNames = new HashSet<Name>();
/** 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
......@@ -243,7 +248,7 @@ public class Symtab {
int opcode) {
predefClass.members().enter(
new OperatorSymbol(
names.fromString(name),
makeOperatorName(name),
new MethodType(List.of(left, right), res,
List.<Type>nil(), methodClass),
opcode,
......@@ -274,7 +279,7 @@ public class Symtab {
Type res,
int opcode) {
OperatorSymbol sym =
new OperatorSymbol(names.fromString(name),
new OperatorSymbol(makeOperatorName(name),
new MethodType(List.of(arg),
res,
List.<Type>nil(),
......@@ -285,6 +290,16 @@ public class Symtab {
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 The name of the class.
*/
......@@ -440,6 +455,7 @@ public class Symtab {
throwableType = enterClass("java.lang.Throwable");
serializableType = enterClass("java.io.Serializable");
methodHandleType = enterClass("java.lang.invoke.MethodHandle");
methodTypeType = enterClass("java.lang.invoke.MethodType");
errorType = enterClass("java.lang.Error");
illegalArgumentExceptionType = enterClass("java.lang.IllegalArgumentException");
interruptedExceptionType = enterClass("java.lang.InterruptedException");
......
......@@ -27,14 +27,19 @@ package com.sun.tools.javac.code;
import java.util.Collections;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.util.*;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
import javax.lang.model.type.*;
import static com.sun.tools.javac.code.BoundKind.*;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Kinds.*;
import static com.sun.tools.javac.code.BoundKind.*;
import static com.sun.tools.javac.code.TypeTags.*;
/** This class represents Java types. The class itself defines the behavior of
......@@ -70,6 +75,9 @@ public class Type implements PrimitiveType {
/** Constant type: no type at all. */
public static final JCNoType noType = new JCNoType(NONE);
/** Constant type: special type to be used during recovery of deferred expressions. */
public static final JCNoType recoveryType = new JCNoType(NONE);
/** If this switch is turned on, the names of type variables
* and anonymous classes are printed with hashcodes appended.
*/
......@@ -1168,22 +1176,59 @@ public class Type implements PrimitiveType {
}
}
/** A class for instantiatable variables, for use during type
* inference.
/** A class for inference variables, for use during method/diamond type
* inference. An inference variable has upper/lower bounds and a set
* of equality constraints. Such bounds are set during subtyping, type-containment,
* type-equality checks, when the types being tested contain inference variables.
* A change listener can be attached to an inference variable, to receive notifications
* whenever the bounds of an inference variable change.
*/
public static class UndetVar extends DelegatedType {
public List<Type> lobounds = List.nil();
public List<Type> hibounds = List.nil();
public List<Type> eq = List.nil();
/** Inference variable change listener. The listener method is called
* whenever a change to the inference variable's bounds occurs
*/
public interface UndetVarListener {
/** called when some inference variable bounds (of given kinds ibs) change */
void varChanged(UndetVar uv, Set<InferenceBound> ibs);
}
/**
* Inference variable bound kinds
*/
public enum InferenceBound {
/** upper bounds */
UPPER,
/** lower bounds */
LOWER,
/** equality constraints */
EQ;
}
/** inference variable bounds */
private Map<InferenceBound, List<Type>> bounds;
/** inference variable's inferred type (set from Infer.java) */
public Type inst = null;
/** inference variable's change listener */
public UndetVarListener listener = null;
@Override
public <R,S> R accept(Type.Visitor<R,S> v, S s) {
return v.visitUndetVar(this, s);
}
public UndetVar(Type origin) {
public UndetVar(TypeVar origin, Types types) {
this(origin, types, true);
}
public UndetVar(TypeVar origin, Types types, boolean includeBounds) {
super(UNDETVAR, origin);
bounds = new EnumMap<InferenceBound, List<Type>>(InferenceBound.class);
bounds.put(InferenceBound.UPPER, includeBounds ? types.getBounds(origin) : List.<Type>nil());
bounds.put(InferenceBound.LOWER, List.<Type>nil());
bounds.put(InferenceBound.EQ, List.<Type>nil());
}
public String toString() {
......@@ -1195,6 +1240,48 @@ public class Type implements PrimitiveType {
if (inst != null) return inst.baseType();
else return this;
}
/** get all bounds of a given kind */
public List<Type> getBounds(InferenceBound ib) {
return bounds.get(ib);
}
/** add a bound of a given kind - this might trigger listener notification */
public void addBound(InferenceBound ib, Type bound, Types types) {
List<Type> prevBounds = bounds.get(ib);
for (Type b : prevBounds) {
if (types.isSameType(b, bound)) {
return;
}
}
bounds.put(ib, prevBounds.prepend(bound));
notifyChange(EnumSet.of(ib));
}
/** replace types in all bounds - this might trigger listener notification */
public void substBounds(List<Type> from, List<Type> to, Types types) {
EnumSet<InferenceBound> changed = EnumSet.noneOf(InferenceBound.class);
Map<InferenceBound, List<Type>> bounds2 = new EnumMap<InferenceBound, List<Type>>(InferenceBound.class);
for (Map.Entry<InferenceBound, List<Type>> _entry : bounds.entrySet()) {
InferenceBound ib = _entry.getKey();
List<Type> prevBounds = _entry.getValue();
List<Type> newBounds = types.subst(prevBounds, from, to);
bounds2.put(ib, newBounds);
if (prevBounds != newBounds) {
changed.add(ib);
}
}
if (!changed.isEmpty()) {
bounds = bounds2;
notifyChange(changed);
}
}
private void notifyChange(EnumSet<InferenceBound> ibs) {
if (listener != null) {
listener.varChanged(this, ibs);
}
}
}
/** Represents VOID or NONE.
......
......@@ -102,9 +102,13 @@ public class TypeTags {
*/
public static final int FORALL = WILDCARD+1;
/** The tag of deferred expression types in method context
*/
public static final int DEFERRED = FORALL+1;
/** The tag of the bottom type <null>.
*/
public static final int BOT = FORALL+1;
public static final int BOT = DEFERRED+1;
/** The tag of a missing type.
*/
......
......@@ -34,6 +34,7 @@ import com.sun.tools.javac.util.List;
import com.sun.tools.javac.jvm.ClassReader;
import com.sun.tools.javac.code.Attribute.RetentionPolicy;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
import com.sun.tools.javac.comp.Check;
import static com.sun.tools.javac.code.Scope.*;
......@@ -78,8 +79,10 @@ public class Types {
final boolean allowObjectToPrimitiveCast;
final ClassReader reader;
final Check chk;
JCDiagnostic.Factory diags;
List<Warner> warnStack = List.nil();
final Name capturedName;
private final FunctionDescriptorLookupError functionDescriptorLookupError;
// <editor-fold defaultstate="collapsed" desc="Instantiating">
public static Types instance(Context context) {
......@@ -101,6 +104,8 @@ public class Types {
chk = Check.instance(context);
capturedName = names.fromString("<captured wildcard>");
messages = JavacMessages.instance(context);
diags = JCDiagnostic.Factory.instance(context);
functionDescriptorLookupError = new FunctionDescriptorLookupError();
}
// </editor-fold>
......@@ -295,6 +300,294 @@ public class Types {
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="findSam">
/**
* Exception used to report a function descriptor lookup failure. The exception
* wraps a diagnostic that can be used to generate more details error
* messages.
*/
public static class FunctionDescriptorLookupError extends RuntimeException {
private static final long serialVersionUID = 0;
JCDiagnostic diagnostic;
FunctionDescriptorLookupError() {
this.diagnostic = null;
}
FunctionDescriptorLookupError setMessage(JCDiagnostic diag) {
this.diagnostic = diag;
return this;
}
public JCDiagnostic getDiagnostic() {
return diagnostic;
}
}
/**
* A cache that keeps track of function descriptors associated with given
* functional interfaces.
*/
class DescriptorCache {
private WeakHashMap<TypeSymbol, Entry> _map = new WeakHashMap<TypeSymbol, Entry>();
class FunctionDescriptor {
Symbol descSym;
FunctionDescriptor(Symbol descSym) {
this.descSym = descSym;
}
public Symbol getSymbol() {
return descSym;
}
public Type getType(Type origin) {
return memberType(origin, descSym);
}
}
class Entry {
final FunctionDescriptor cachedDescRes;
final int prevMark;
public Entry(FunctionDescriptor cachedDescRes,
int prevMark) {
this.cachedDescRes = cachedDescRes;
this.prevMark = prevMark;
}
boolean matches(int mark) {
return this.prevMark == mark;
}
}
FunctionDescriptor get(TypeSymbol origin) throws FunctionDescriptorLookupError {
Entry e = _map.get(origin);
CompoundScope members = membersClosure(origin.type, false);
if (e == null ||
!e.matches(members.getMark())) {
FunctionDescriptor descRes = findDescriptorInternal(origin, members);
_map.put(origin, new Entry(descRes, members.getMark()));
return descRes;
}
else {
return e.cachedDescRes;
}
}
/**
* Scope filter used to skip methods that should be ignored during
* function interface conversion (such as methods overridden by
* j.l.Object)
*/
class DescriptorFilter implements Filter<Symbol> {
TypeSymbol origin;
DescriptorFilter(TypeSymbol origin) {
this.origin = origin;
}
@Override
public boolean accepts(Symbol sym) {
return sym.kind == Kinds.MTH &&
(sym.flags() & ABSTRACT) != 0 &&
!overridesObjectMethod(origin, sym) &&
notOverridden(sym);
}
private boolean notOverridden(Symbol msym) {
Symbol impl = ((MethodSymbol)msym).implementation(origin, Types.this, false);
return impl == null || (impl.flags() & ABSTRACT) != 0;
}
};
/**
* Compute the function descriptor associated with a given functional interface
*/
public FunctionDescriptor findDescriptorInternal(TypeSymbol origin, CompoundScope membersCache) throws FunctionDescriptorLookupError {
if (!origin.isInterface()) {
//t must be an interface
throw failure("not.a.functional.intf");
}
final ListBuffer<Symbol> abstracts = ListBuffer.lb();
for (Symbol sym : membersCache.getElements(new DescriptorFilter(origin))) {
Type mtype = memberType(origin.type, sym);
if (abstracts.isEmpty() ||
(sym.name == abstracts.first().name &&
overrideEquivalent(mtype, memberType(origin.type, abstracts.first())))) {
abstracts.append(sym);
} else {
//the target method(s) should be the only abstract members of t
throw failure("not.a.functional.intf.1",
diags.fragment("incompatible.abstracts", Kinds.kindName(origin), origin));
}
}
if (abstracts.isEmpty()) {
//t must define a suitable non-generic method
throw failure("not.a.functional.intf.1",
diags.fragment("no.abstracts", Kinds.kindName(origin), origin));
} else if (abstracts.size() == 1) {
if (abstracts.first().type.tag == FORALL) {
throw failure("invalid.generic.desc.in.functional.intf",
abstracts.first(),
Kinds.kindName(origin),
origin);
} else {
return new FunctionDescriptor(abstracts.first());
}
} else { // size > 1
for (Symbol msym : abstracts) {
if (msym.type.tag == FORALL) {
throw failure("invalid.generic.desc.in.functional.intf",
abstracts.first(),
Kinds.kindName(origin),
origin);
}
}
FunctionDescriptor descRes = mergeDescriptors(origin, abstracts.toList());
if (descRes == null) {
//we can get here if the functional interface is ill-formed
ListBuffer<JCDiagnostic> descriptors = ListBuffer.lb();
for (Symbol desc : abstracts) {
String key = desc.type.getThrownTypes().nonEmpty() ?
"descriptor.throws" : "descriptor";
descriptors.append(diags.fragment(key, desc.name,
desc.type.getParameterTypes(),
desc.type.getReturnType(),
desc.type.getThrownTypes()));
}
JCDiagnostic.MultilineDiagnostic incompatibleDescriptors =
new JCDiagnostic.MultilineDiagnostic(diags.fragment("incompatible.descs.in.functional.intf",
Kinds.kindName(origin), origin), descriptors.toList());
throw failure(incompatibleDescriptors);
}
return descRes;
}
}
/**
* Compute a synthetic type for the target descriptor given a list
* of override-equivalent methods in the functional interface type.
* The resulting method type is a method type that is override-equivalent
* and return-type substitutable with each method in the original list.
*/
private FunctionDescriptor mergeDescriptors(TypeSymbol origin, List<Symbol> methodSyms) {
//pick argument types - simply take the signature that is a
//subsignature of all other signatures in the list (as per JLS 8.4.2)
List<Symbol> mostSpecific = List.nil();
outer: for (Symbol msym1 : methodSyms) {
Type mt1 = memberType(origin.type, msym1);
for (Symbol msym2 : methodSyms) {
Type mt2 = memberType(origin.type, msym2);
if (!isSubSignature(mt1, mt2)) {
continue outer;
}
}
mostSpecific = mostSpecific.prepend(msym1);
}
if (mostSpecific.isEmpty()) {
return null;
}
//pick return types - this is done in two phases: (i) first, the most
//specific return type is chosen using strict subtyping; if this fails,
//a second attempt is made using return type substitutability (see JLS 8.4.5)
boolean phase2 = false;
Symbol bestSoFar = null;
while (bestSoFar == null) {
outer: for (Symbol msym1 : mostSpecific) {
Type mt1 = memberType(origin.type, msym1);
for (Symbol msym2 : methodSyms) {
Type mt2 = memberType(origin.type, msym2);
if (phase2 ?
!returnTypeSubstitutable(mt1, mt2) :
!isSubtypeInternal(mt1.getReturnType(), mt2.getReturnType())) {
continue outer;
}
}
bestSoFar = msym1;
}
if (phase2) {
break;
} else {
phase2 = true;
}
}
if (bestSoFar == null) return null;
//merge thrown types - form the intersection of all the thrown types in
//all the signatures in the list
List<Type> thrown = null;
for (Symbol msym1 : methodSyms) {
Type mt1 = memberType(origin.type, msym1);
thrown = (thrown == null) ?
mt1.getThrownTypes() :
chk.intersect(mt1.getThrownTypes(), thrown);
}
final List<Type> thrown1 = thrown;
return new FunctionDescriptor(bestSoFar) {
@Override
public Type getType(Type origin) {
Type mt = memberType(origin, getSymbol());
return new MethodType(mt.getParameterTypes(), mt.getReturnType(), thrown1, syms.methodClass);
}
};
}
boolean isSubtypeInternal(Type s, Type t) {
return (s.isPrimitive() && t.isPrimitive()) ?
isSameType(t, s) :
isSubtype(s, t);
}
FunctionDescriptorLookupError failure(String msg, Object... args) {
return failure(diags.fragment(msg, args));
}
FunctionDescriptorLookupError failure(JCDiagnostic diag) {
return functionDescriptorLookupError.setMessage(diag);
}
}
private DescriptorCache descCache = new DescriptorCache();
/**
* Find the method descriptor associated to this class symbol - if the
* symbol 'origin' is not a functional interface, an exception is thrown.
*/
public Symbol findDescriptorSymbol(TypeSymbol origin) throws FunctionDescriptorLookupError {
return descCache.get(origin).getSymbol();
}
/**
* Find the type of the method descriptor associated to this class symbol -
* if the symbol 'origin' is not a functional interface, an exception is thrown.
*/
public Type findDescriptorType(Type origin) throws FunctionDescriptorLookupError {
return descCache.get(origin.tsym).getType(origin);
}
/**
* Is given type a functional interface?
*/
public boolean isFunctionalInterface(TypeSymbol tsym) {
try {
findDescriptorSymbol(tsym);
return true;
} catch (FunctionDescriptorLookupError ex) {
return false;
}
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="isSubtype">
/**
* Is t an unchecked subtype of s?
......@@ -510,7 +803,7 @@ public class Types {
return false;
}
t.hibounds = t.hibounds.prepend(s);
t.addBound(InferenceBound.UPPER, s, Types.this);
return true;
}
......@@ -578,7 +871,7 @@ public class Types {
undet.qtype == s ||
s.tag == ERROR ||
s.tag == BOT) return true;
undet.lobounds = undet.lobounds.prepend(s);
undet.addBound(InferenceBound.LOWER, s, this);
return true;
}
default:
......@@ -723,7 +1016,7 @@ public class Types {
if (t == s || t.qtype == s || s.tag == ERROR || s.tag == UNKNOWN)
return true;
t.eq = t.eq.prepend(s);
t.addBound(InferenceBound.EQ, s, Types.this);
return true;
}
......@@ -735,19 +1028,6 @@ public class Types {
};
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="fromUnknownFun">
/**
* A mapping that turns all unknown types in this type to fresh
* unknown variables.
*/
public Mapping fromUnknownFun = new Mapping("fromUnknownFun") {
public Type apply(Type t) {
if (t.tag == UNKNOWN) return new UndetVar(t);
else return t.map(this);
}
};
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Contains Type">
public boolean containedBy(Type t, Type s) {
switch (t.tag) {
......@@ -759,12 +1039,12 @@ public class Types {
case UNBOUND: //similar to ? extends Object
case EXTENDS: {
Type bound = upperBound(s);
undetvar.hibounds = undetvar.hibounds.prepend(bound);
undetvar.addBound(InferenceBound.UPPER, bound, this);
break;
}
case SUPER: {
Type bound = lowerBound(s);
undetvar.lobounds = undetvar.lobounds.prepend(bound);
undetvar.addBound(InferenceBound.LOWER, bound, this);
break;
}
}
......@@ -1227,7 +1507,10 @@ public class Types {
* Returns the lower bounds of the formals of a method.
*/
public List<Type> lowerBoundArgtypes(Type t) {
return map(t.getParameterTypes(), lowerBoundMapping);
return lowerBounds(t.getParameterTypes());
}
public List<Type> lowerBounds(List<Type> ts) {
return map(ts, lowerBoundMapping);
}
private final Mapping lowerBoundMapping = new Mapping("lowerBound") {
public Type apply(Type t) {
......@@ -2019,6 +2302,15 @@ public class Types {
hasSameArgs(t, erasure(s)) || hasSameArgs(erasure(t), s);
}
public boolean overridesObjectMethod(TypeSymbol origin, Symbol msym) {
for (Scope.Entry e = syms.objectType.tsym.members().lookup(msym.name) ; e.scope != null ; e = e.next()) {
if (msym.overrides(e.sym, origin, Types.this, true)) {
return true;
}
}
return false;
}
// <editor-fold defaultstate="collapsed" desc="Determining method implementation in given site">
class ImplementationCache {
......@@ -3166,6 +3458,14 @@ public class Types {
}
return Type.noType;
}
/**
* Return the unboxed type if 't' is a boxed class, otherwise return 't' itself.
*/
public Type unboxedTypeOrType(Type t) {
Type unboxedType = unboxedType(t);
return unboxedType.tag == NONE ? t : unboxedType;
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Capture conversion">
......
......@@ -514,22 +514,6 @@ public class Annotate {
expectedType);
fatalError = true;
}
// validate that all other elements of containing type has defaults
scope = targetContainerType.tsym.members();
error = false;
for(Symbol elm : scope.getElements()) {
if (elm.name != names.value &&
elm.kind == Kinds.MTH &&
((MethodSymbol)elm).defaultValue == null) {
log.error(pos,
"invalid.containedby.annotation.elem.nondefault",
targetContainerType,
elm);
containerValueSymbol = null;
error = true;
}
}
if (error) {
fatalError = true;
}
......
......@@ -56,7 +56,7 @@ public class AttrContext {
/** Are arguments to current function applications boxed into an array for varargs?
*/
boolean varArgs = false;
Resolve.MethodResolutionPhase pendingResolutionPhase = null;
/** A record of the lint/SuppressWarnings currently in effect
*/
......@@ -67,6 +67,11 @@ public class AttrContext {
*/
Symbol enclVar = null;
/** ResultInfo to be used for attributing 'return' statement expressions
* (set by Attr.visitMethod and Attr.visitLambda)
*/
Attr.ResultInfo returnResult = null;
/** Duplicate this context, replacing scope field and copying all others.
*/
AttrContext dup(Scope scope) {
......@@ -75,9 +80,10 @@ public class AttrContext {
info.staticLevel = staticLevel;
info.isSelfCall = isSelfCall;
info.selectSuper = selectSuper;
info.varArgs = varArgs;
info.pendingResolutionPhase = pendingResolutionPhase;
info.lint = lint;
info.enclVar = enclVar;
info.returnResult = returnResult;
return info;
}
......@@ -93,6 +99,11 @@ public class AttrContext {
return scope.getElements();
}
boolean lastResolveVarargs() {
return pendingResolutionPhase != null &&
pendingResolutionPhase.isVarargsRequired();
}
public String toString() {
return "AttrContext[" + scope.toString() + "]";
}
......
......@@ -40,6 +40,9 @@ import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
import com.sun.tools.javac.comp.Infer.InferenceContext;
import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Flags.ANNOTATION;
......@@ -66,6 +69,7 @@ public class Check {
private final Resolve rs;
private final Symtab syms;
private final Enter enter;
private final DeferredAttr deferredAttr;
private final Infer infer;
private final Types types;
private final JCDiagnostic.Factory diags;
......@@ -98,6 +102,7 @@ public class Check {
rs = Resolve.instance(context);
syms = Symtab.instance(context);
enter = Enter.instance(context);
deferredAttr = DeferredAttr.instance(context);
infer = Infer.instance(context);
this.types = Types.instance(context);
diags = JCDiagnostic.Factory.instance(context);
......@@ -416,7 +421,7 @@ public class Check {
* checks - depending on the check context, meaning of 'compatibility' might
* vary significantly.
*/
interface CheckContext {
public interface CheckContext {
/**
* Is type 'found' compatible with type 'req' in given context
*/
......@@ -429,6 +434,12 @@ public class Check {
* Obtain a warner for this check context
*/
public Warner checkWarner(DiagnosticPosition pos, Type found, Type req);
public Infer.InferenceContext inferenceContext();
public DeferredAttr.DeferredAttrContext deferredAttrContext();
public boolean allowBoxing();
}
/**
......@@ -455,6 +466,18 @@ public class Check {
public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
return enclosingContext.checkWarner(pos, found, req);
}
public Infer.InferenceContext inferenceContext() {
return enclosingContext.inferenceContext();
}
public DeferredAttrContext deferredAttrContext() {
return enclosingContext.deferredAttrContext();
}
public boolean allowBoxing() {
return enclosingContext.allowBoxing();
}
}
/**
......@@ -471,6 +494,18 @@ public class Check {
public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
return convertWarner(pos, found, req);
}
public InferenceContext inferenceContext() {
return infer.emptyContext;
}
public DeferredAttrContext deferredAttrContext() {
return deferredAttr.emptyDeferredAttrContext;
}
public boolean allowBoxing() {
return true;
}
};
/** Check that a given type is assignable to a given proto-type.
......@@ -483,7 +518,16 @@ public class Check {
return checkType(pos, found, req, basicHandler);
}
Type checkType(final DiagnosticPosition pos, Type found, Type req, CheckContext checkContext) {
Type checkType(final DiagnosticPosition pos, final Type found, final Type req, final CheckContext checkContext) {
final Infer.InferenceContext inferenceContext = checkContext.inferenceContext();
if (inferenceContext.free(req)) {
inferenceContext.addFreeTypeListener(List.of(req), new FreeTypeListener() {
@Override
public void typesInferred(InferenceContext inferenceContext) {
checkType(pos, found, inferenceContext.asInstType(req, types), checkContext);
}
});
}
if (req.tag == ERROR)
return req;
if (req.tag == NONE)
......@@ -523,9 +567,9 @@ public class Check {
*/
public void checkRedundantCast(Env<AttrContext> env, JCTypeCast tree) {
if (!tree.type.isErroneous() &&
(env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST))
&& types.isSameType(tree.expr.type, tree.clazz.type)
&& !is292targetTypeCast(tree)) {
(env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST))
&& types.isSameType(tree.expr.type, tree.clazz.type)
&& !is292targetTypeCast(tree)) {
log.warning(Lint.LintCategory.CAST,
tree.pos(), "redundant.cast", tree.expr.type);
}
......@@ -604,6 +648,22 @@ public class Check {
return t;
}
/** Check that type is a valid qualifier for a constructor reference expression
*/
Type checkConstructorRefType(DiagnosticPosition pos, Type t) {
t = checkClassType(pos, t);
if (t.tag == CLASS) {
if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
log.error(pos, "abstract.cant.be.instantiated");
t = types.createErrorType(t);
} else if ((t.tsym.flags() & ENUM) != 0) {
log.error(pos, "enum.cant.be.instantiated");
t = types.createErrorType(t);
}
}
return t;
}
/** Check that type is a class or interface type.
* @param pos Position to be used for error reporting.
* @param t The type to be checked.
......@@ -796,29 +856,34 @@ public class Check {
sym.owner == syms.enumSym)
formals = formals.tail.tail;
List<JCExpression> args = argtrees;
while (formals.head != last) {
JCTree arg = args.head;
Warner warn = convertWarner(arg.pos(), arg.type, formals.head);
assertConvertible(arg, arg.type, formals.head, warn);
args = args.tail;
formals = formals.tail;
}
if (useVarargs) {
Type varArg = types.elemtype(last);
while (args.tail != null) {
DeferredAttr.DeferredTypeMap checkDeferredMap =
deferredAttr.new DeferredTypeMap(DeferredAttr.AttrMode.CHECK, sym, env.info.pendingResolutionPhase);
if (args != null) {
//this is null when type-checking a method reference
while (formals.head != last) {
JCTree arg = args.head;
Warner warn = convertWarner(arg.pos(), arg.type, varArg);
assertConvertible(arg, arg.type, varArg, warn);
Warner warn = convertWarner(arg.pos(), arg.type, formals.head);
assertConvertible(arg, arg.type, formals.head, warn);
args = args.tail;
formals = formals.tail;
}
if (useVarargs) {
Type varArg = types.elemtype(last);
while (args.tail != null) {
JCTree arg = args.head;
Warner warn = convertWarner(arg.pos(), arg.type, varArg);
assertConvertible(arg, arg.type, varArg, warn);
args = args.tail;
}
} else if ((sym.flags() & VARARGS) != 0 && allowVarargs) {
// non-varargs call to varargs method
Type varParam = owntype.getParameterTypes().last();
Type lastArg = checkDeferredMap.apply(argtypes.last());
if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) &&
!types.isSameType(types.erasure(varParam), types.erasure(lastArg)))
log.warning(argtrees.last().pos(), "inexact.non-varargs.call",
types.elemtype(varParam), varParam);
}
} else if ((sym.flags() & VARARGS) != 0 && allowVarargs) {
// non-varargs call to varargs method
Type varParam = owntype.getParameterTypes().last();
Type lastArg = argtypes.last();
if (types.isSubtypeUnchecked(lastArg, types.elemtype(varParam)) &&
!types.isSameType(types.erasure(varParam), types.erasure(lastArg)))
log.warning(argtrees.last().pos(), "inexact.non-varargs.call",
types.elemtype(varParam), varParam);
}
if (unchecked) {
warnUnchecked(env.tree.pos(),
......@@ -826,7 +891,7 @@ public class Check {
kindName(sym),
sym.name,
rs.methodArguments(sym.type.getParameterTypes()),
rs.methodArguments(argtypes),
rs.methodArguments(Type.map(argtypes, checkDeferredMap)),
kindName(sym.location()),
sym.location());
owntype = new MethodType(owntype.getParameterTypes(),
......@@ -853,6 +918,9 @@ public class Check {
case NEWCLASS:
((JCNewClass) tree).varargsElement = elemtype;
break;
case REFERENCE:
((JCMemberReference) tree).varargsElement = elemtype;
break;
default:
throw new AssertionError(""+tree);
}
......@@ -870,6 +938,65 @@ public class Check {
return;
}
void checkAccessibleFunctionalDescriptor(DiagnosticPosition pos, Env<AttrContext> env, Type desc) {
AccessChecker accessChecker = new AccessChecker(env);
//check args accessibility (only if implicit parameter types)
for (Type arg : desc.getParameterTypes()) {
if (!accessChecker.visit(arg)) {
log.error(pos, "cant.access.arg.type.in.functional.desc", arg);
return;
}
}
//check return type accessibility
if (!accessChecker.visit(desc.getReturnType())) {
log.error(pos, "cant.access.return.in.functional.desc", desc.getReturnType());
return;
}
//check thrown types accessibility
for (Type thrown : desc.getThrownTypes()) {
if (!accessChecker.visit(thrown)) {
log.error(pos, "cant.access.thrown.in.functional.desc", thrown);
return;
}
}
}
class AccessChecker extends Types.UnaryVisitor<Boolean> {
Env<AttrContext> env;
AccessChecker(Env<AttrContext> env) {
this.env = env;
}
Boolean visit(List<Type> ts) {
for (Type t : ts) {
if (!visit(t))
return false;
}
return true;
}
public Boolean visitType(Type t, Void s) {
return true;
}
@Override
public Boolean visitArrayType(ArrayType t, Void s) {
return visit(t.elemtype);
}
@Override
public Boolean visitClassType(ClassType t, Void s) {
return rs.isAccessible(env, t, true) &&
visit(t.getTypeArguments());
}
@Override
public Boolean visitWildcardType(WildcardType t, Void s) {
return visit(t.type);
}
};
/**
* Check that type 't' is a valid instantiation of a generic class
* (see JLS 4.5)
......@@ -2470,6 +2597,7 @@ public class Check {
validateDocumented(t.tsym, s, pos);
validateInherited(t.tsym, s, pos);
validateTarget(t.tsym, s, pos);
validateDefault(t.tsym, s, pos);
}
/**
......@@ -2650,6 +2778,21 @@ public class Check {
return true;
}
private void validateDefault(Symbol container, Symbol contained, DiagnosticPosition pos) {
// validate that all other elements of containing type has defaults
Scope scope = container.members();
for(Symbol elm : scope.getElements()) {
if (elm.name != names.value &&
elm.kind == Kinds.MTH &&
((MethodSymbol)elm).defaultValue == null) {
log.error(pos,
"invalid.containedby.annotation.elem.nondefault",
container,
elm);
}
}
}
/** Is s a method symbol that overrides a method in a superclass? */
boolean isOverrider(Symbol s) {
if (s.kind != MTH || s.isStatic())
......
......@@ -50,8 +50,8 @@ import static com.sun.tools.javac.tree.JCTree.Tag.*;
* (see AssignAnalyzer) ensures that each variable is assigned when used. Definite
* unassignment analysis (see AssignAnalyzer) in ensures that no final variable
* is assigned more than once. Finally, local variable capture analysis (see CaptureAnalyzer)
* determines that local variables accessed within the scope of an inner class are
* either final or effectively-final.
* determines that local variables accessed within the scope of an inner class/lambda
* are either final or effectively-final.
*
* <p>The JLS has a number of problems in the
* specification of these flow analysis problems. This implementation
......@@ -211,6 +211,29 @@ public class Flow {
new CaptureAnalyzer().analyzeTree(env, make);
}
public void analyzeLambda(Env<AttrContext> env, JCLambda that, TreeMaker make, boolean speculative) {
java.util.Queue<JCDiagnostic> prevDeferredDiagnostics = log.deferredDiagnostics;
Filter<JCDiagnostic> prevDeferDiagsFilter = log.deferredDiagFilter;
//we need to disable diagnostics temporarily; the problem is that if
//a lambda expression contains e.g. an unreachable statement, an error
//message will be reported and will cause compilation to skip the flow analyis
//step - if we suppress diagnostics, we won't stop at Attr for flow-analysis
//related errors, which will allow for more errors to be detected
if (!speculative) {
log.deferAll();
log.deferredDiagnostics = ListBuffer.lb();
}
try {
new AliveAnalyzer().analyzeTree(env, that, make);
new FlowAnalyzer().analyzeTree(env, that, make);
} finally {
if (!speculative) {
log.deferredDiagFilter = prevDeferDiagsFilter;
log.deferredDiagnostics = prevDeferredDiagnostics;
}
}
}
/**
* Definite assignment scan mode
*/
......@@ -659,6 +682,27 @@ public class Flow {
}
}
@Override
public void visitLambda(JCLambda tree) {
if (tree.type != null &&
tree.type.isErroneous()) {
return;
}
ListBuffer<PendingExit> prevPending = pendingExits;
boolean prevAlive = alive;
try {
pendingExits = ListBuffer.lb();
alive = true;
scanStat(tree.body);
tree.canCompleteNormally = alive;
}
finally {
pendingExits = prevPending;
alive = prevAlive;
}
}
public void visitTopLevel(JCCompilationUnit tree) {
// Do nothing for TopLevel since each class is visited individually
}
......@@ -670,6 +714,9 @@ public class Flow {
/** Perform definite assignment/unassignment analysis on a tree.
*/
public void analyzeTree(Env<AttrContext> env, TreeMaker make) {
analyzeTree(env, env.tree, make);
}
public void analyzeTree(Env<AttrContext> env, JCTree tree, TreeMaker make) {
try {
attrEnv = env;
Flow.this.make = make;
......@@ -1185,6 +1232,29 @@ public class Flow {
}
}
@Override
public void visitLambda(JCLambda tree) {
if (tree.type != null &&
tree.type.isErroneous()) {
return;
}
List<Type> prevCaught = caught;
List<Type> prevThrown = thrown;
ListBuffer<FlowPendingExit> prevPending = pendingExits;
try {
pendingExits = ListBuffer.lb();
caught = List.of(syms.throwableType); //inhibit exception checking
thrown = List.nil();
scan(tree.body);
tree.inferredThrownTypes = thrown;
}
finally {
pendingExits = prevPending;
caught = prevCaught;
thrown = prevThrown;
}
}
public void visitTopLevel(JCCompilationUnit tree) {
// Do nothing for TopLevel since each class is visited individually
}
......@@ -1267,6 +1337,10 @@ public class Flow {
*/
int nextadr;
/** The first variable sequence number in a block that can return.
*/
int returnadr;
/** The list of unreferenced automatic resources.
*/
Scope unrefdResources;
......@@ -1296,8 +1370,8 @@ public class Flow {
@Override
void markDead() {
inits.inclRange(firstadr, nextadr);
uninits.inclRange(firstadr, nextadr);
inits.inclRange(returnadr, nextadr);
uninits.inclRange(returnadr, nextadr);
}
/*-------------- Processing variables ----------------------*/
......@@ -1318,11 +1392,7 @@ public class Flow {
* index into the vars array.
*/
void newVar(VarSymbol sym) {
if (nextadr == vars.length) {
VarSymbol[] newvars = new VarSymbol[nextadr * 2];
System.arraycopy(vars, 0, newvars, 0, nextadr);
vars = newvars;
}
vars = ArrayUtils.ensureCapacity(vars, nextadr);
if ((sym.flags() & FINAL) == 0) {
sym.flags_field |= EFFECTIVELY_FINAL;
}
......@@ -1556,6 +1626,7 @@ public class Flow {
Bits uninitsPrev = uninits.dup();
int nextadrPrev = nextadr;
int firstadrPrev = firstadr;
int returnadrPrev = returnadr;
Lint lintPrev = lint;
lint = lint.augment(tree.sym.annotations);
......@@ -1600,6 +1671,7 @@ public class Flow {
uninits = uninitsPrev;
nextadr = nextadrPrev;
firstadr = firstadrPrev;
returnadr = returnadrPrev;
lint = lintPrev;
}
}
......@@ -1984,6 +2056,35 @@ public class Flow {
scan(tree.def);
}
@Override
public void visitLambda(JCLambda tree) {
Bits prevUninits = uninits;
Bits prevInits = inits;
int returnadrPrev = returnadr;
ListBuffer<AssignPendingExit> prevPending = pendingExits;
try {
returnadr = nextadr;
pendingExits = new ListBuffer<AssignPendingExit>();
for (List<JCVariableDecl> l = tree.params; l.nonEmpty(); l = l.tail) {
JCVariableDecl def = l.head;
scan(def);
inits.incl(def.sym.adr);
uninits.excl(def.sym.adr);
}
if (tree.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
scanExpr(tree.body);
} else {
scan(tree.body);
}
}
finally {
returnadr = returnadrPrev;
uninits = prevUninits;
inits = prevInits;
pendingExits = prevPending;
}
}
public void visitNewArray(JCNewArray tree) {
scanExprs(tree.dims);
scanExprs(tree.elems);
......
......@@ -1998,7 +1998,7 @@ public class Lower extends TreeTranslator {
// replace with <BoxedClass>.TYPE
ClassSymbol c = types.boxedClass(type);
Symbol typeSym =
rs.access(
rs.accessBase(
rs.findIdentInType(attrEnv, c.type, names.TYPE, VAR),
pos, c.type, names.TYPE, true);
if (typeSym.kind == VAR)
......
......@@ -604,6 +604,10 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
env.dup(tree, env.info.dup(env.info.scope.dupUnshared()));
localEnv.enclMethod = tree;
localEnv.info.scope.owner = tree.sym;
if (tree.sym.type != null) {
//when this is called in the enter stage, there's no type to be set
localEnv.info.returnResult = attr.new ResultInfo(VAL, tree.sym.type.getReturnType());
}
if ((tree.mods.flags & STATIC) != 0) localEnv.info.staticLevel++;
return localEnv;
}
......@@ -642,7 +646,9 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
tree.sym = v;
if (tree.init != null) {
v.flags_field |= HASINIT;
if ((v.flags_field & FINAL) != 0 && !tree.init.hasTag(NEWCLASS)) {
if ((v.flags_field & FINAL) != 0 &&
!tree.init.hasTag(NEWCLASS) &&
!tree.init.hasTag(LAMBDA)) {
Env<AttrContext> initEnv = getInitEnv(tree, env);
initEnv.info.enclVar = v;
v.setLazyConstValue(initEnv(tree, initEnv), attr, tree.init);
......@@ -667,7 +673,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
Env<AttrContext> initEnv(JCVariableDecl tree, Env<AttrContext> env) {
Env<AttrContext> localEnv = env.dupto(new AttrContextEnv(tree, env.info.dup()));
if (tree.sym.owner.kind == TYP) {
localEnv.info.scope = new Scope.DelegatedScope(env.info.scope);
localEnv.info.scope = env.info.scope.dupUnshared();
localEnv.info.scope.owner = tree.sym;
}
if ((tree.mods.flags & STATIC) != 0 ||
......@@ -970,9 +976,11 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
List<Type> thrown = List.nil();
long ctorFlags = 0;
boolean based = false;
boolean addConstructor = true;
if (c.name.isEmpty()) {
JCNewClass nc = (JCNewClass)env.next.tree;
if (nc.constructor != null) {
addConstructor = nc.constructor.kind != ERR;
Type superConstrType = types.memberType(c.type,
nc.constructor);
argtypes = superConstrType.getParameterTypes();
......@@ -985,10 +993,12 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
thrown = superConstrType.getThrownTypes();
}
}
JCTree constrDef = DefaultConstructor(make.at(tree.pos), c,
typarams, argtypes, thrown,
ctorFlags, based);
tree.defs = tree.defs.prepend(constrDef);
if (addConstructor) {
JCTree constrDef = DefaultConstructor(make.at(tree.pos), c,
typarams, argtypes, thrown,
ctorFlags, based);
tree.defs = tree.defs.prepend(constrDef);
}
}
// If this is a class, enter symbols for this and super into
......
......@@ -627,6 +627,16 @@ public class TransTypes extends TreeTranslator {
result = tree;
}
@Override
public void visitLambda(JCLambda tree) {
Assert.error("Translation of lambda expression not supported yet");
}
@Override
public void visitReference(JCMemberReference tree) {
Assert.error("Translation of method reference not supported yet");
}
public void visitParens(JCParens tree) {
tree.expr = translate(tree.expr, pt);
tree.type = erasure(tree.type);
......
......@@ -733,11 +733,7 @@ public class Locations {
urls[count++] = url;
}
}
if (urls.length != count) {
URL[] tmp = new URL[count];
System.arraycopy(urls, 0, tmp, 0, count);
urls = tmp;
}
urls = Arrays.copyOf(urls, count);
return urls;
}
......
......@@ -84,6 +84,16 @@ public class ClassFile {
public final static int CONSTANT_MethodType = 16;
public final static int CONSTANT_InvokeDynamic = 18;
public final static int REF_getField = 1;
public final static int REF_getStatic = 2;
public final static int REF_putField = 3;
public final static int REF_putStatic = 4;
public final static int REF_invokeVirtual = 5;
public final static int REF_invokeStatic = 6;
public final static int REF_invokeSpecial = 7;
public final static int REF_newInvokeSpecial = 8;
public final static int REF_invokeInterface = 9;
public final static int MAX_PARAMETERS = 0xff;
public final static int MAX_DIMENSIONS = 0xff;
public final static int MAX_CODE = 0xffff;
......
......@@ -2103,6 +2103,8 @@ public class Gen extends JCTree.Visitor {
result = res;
} else if (sym.kind == VAR && sym.owner.kind == MTH) {
result = items.makeLocalItem((VarSymbol)sym);
} else if (isInvokeDynamic(sym)) {
result = items.makeDynamicItem(sym);
} else if ((sym.flags() & STATIC) != 0) {
if (!isAccessSuper(env.enclMethod))
sym = binaryQualifier(sym, env.enclClass.type);
......@@ -2152,8 +2154,12 @@ public class Gen extends JCTree.Visitor {
result = items.
makeImmediateItem(sym.type, ((VarSymbol) sym).getConstValue());
} else {
if (!accessSuper)
if (isInvokeDynamic(sym)) {
result = items.makeDynamicItem(sym);
return;
} else if (!accessSuper) {
sym = binaryQualifier(sym, tree.selected.type);
}
if ((sym.flags() & STATIC) != 0) {
if (!selectSuper && (ssym == null || ssym.kind != TYP))
base = base.load();
......@@ -2174,6 +2180,10 @@ public class Gen extends JCTree.Visitor {
}
}
public boolean isInvokeDynamic(Symbol sym) {
return sym.kind == MTH && ((MethodSymbol)sym).isDynamic();
}
public void visitLiteral(JCLiteral tree) {
if (tree.type.tag == TypeTags.BOT) {
code.emitop0(aconst_null);
......
......@@ -638,10 +638,6 @@ public class JavaTokenizer {
lexError(pos, "unclosed.str.lit");
}
break loop;
case '#':
reader.scanChar();
tk = TokenKind.HASH;
break loop;
default:
if (isSpecial(reader.ch)) {
scanOperator();
......
......@@ -177,7 +177,7 @@ public class Tokens {
FALSE("false", Tag.NAMED),
NULL("null", Tag.NAMED),
ARROW("->"),
HASH("#"),
COLCOL("::"),
LPAREN("("),
RPAREN(")"),
LBRACE("{"),
......
......@@ -118,6 +118,7 @@ public class Names {
// attribute names
public final Name Annotation;
public final Name AnnotationDefault;
public final Name BootstrapMethods;
public final Name Bridge;
public final Name CharacterRangeTable;
public final Name Code;
......@@ -246,6 +247,7 @@ public class Names {
// attribute names
Annotation = fromString("Annotation");
AnnotationDefault = fromString("AnnotationDefault");
BootstrapMethods = fromString("BootstrapMethods");
Bridge = fromString("Bridge");
CharacterRangeTable = fromString("CharacterRangeTable");
Code = fromString("Code");
......
此差异已折叠。
T6722234a.java:12:9: compiler.err.cant.apply.symbol.1: kindname.method, m, compiler.misc.type.var: T, 1, compiler.misc.type.var: T, 2, kindname.class, T6722234a<compiler.misc.type.var: T, 1>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: compiler.misc.type.var: T, 2, compiler.misc.type.var: T, 1))
T6722234a.java:12:9: compiler.err.cant.apply.symbol: kindname.method, m, compiler.misc.type.var: T, 1, compiler.misc.type.var: T, 2, kindname.class, T6722234a<compiler.misc.type.var: T, 1>, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: compiler.misc.type.var: T, 2, compiler.misc.type.var: T, 1))
1 error
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册