--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nb-javac/dyncast.patch Thu Mar 26 19:55:19 2009 -0500
@@ -0,0 +1,159 @@
+0000000: writing libraries in Java for non-Java languages requires permissive Dynamic type
+MQ base = 4d206181439a in http://hg.netbeans.org/main/nb-javac [release65_base] + meth.patch
+
+diff --git a/src/share/classes/com/sun/tools/javac/code/Symtab.java b/src/share/classes/com/sun/tools/javac/code/Symtab.java
+--- a/src/share/classes/com/sun/tools/javac/code/Symtab.java
++++ b/src/share/classes/com/sun/tools/javac/code/Symtab.java
+@@ -119,6 +119,7 @@
+ public final Type stringBuilderType;
+ public final Type cloneableType;
+ public final Type serializableType;
++ public final Type voidWrapperType;
+ public final Type methodHandleType;
+ public final Type dynamicType;
+ public final Type throwableType;
+@@ -353,8 +354,11 @@
+ cloneableType = enterClass("java.lang.Cloneable");
+ throwableType = enterClass("java.lang.Throwable");
+ serializableType = enterClass("java.io.Serializable");
++ voidWrapperType = enterClass("java.lang.Void");
+ methodHandleType = enterClass("java.dyn.MethodHandle");
+ dynamicType = enterClass("java.dyn.Dynamic");
++ // interface Dynamic does *not* inherit members from Object:
++ ((ClassType)dynamicType).supertype_field = Type.noType;
+ errorType = enterClass("java.lang.Error");
+ illegalArgumentExceptionType = enterClass("java.lang.IllegalArgumentException");
+ exceptionType = enterClass("java.lang.Exception");
+diff --git a/src/share/classes/com/sun/tools/javac/code/Types.java b/src/share/classes/com/sun/tools/javac/code/Types.java
+--- a/src/share/classes/com/sun/tools/javac/code/Types.java
++++ b/src/share/classes/com/sun/tools/javac/code/Types.java
+@@ -269,6 +269,7 @@
+ * convertions to s?
+ */
+ public boolean isConvertible(Type t, Type s, Warner warn) {
++ if (s.tsym == syms.dynamicType.tsym) return true;
+ boolean tPrimitive = t.isPrimitive();
+ boolean sPrimitive = s.isPrimitive();
+ if (tPrimitive == sPrimitive)
+@@ -879,6 +880,8 @@
+ if (t == s)
+ return true;
+
++ if (t.tsym == syms.dynamicType.tsym || s.tsym == syms.dynamicType.tsym) return true;
++
+ if (t.isPrimitive() != s.isPrimitive())
+ return allowBoxing && isConvertible(t, s, warn);
+
+@@ -1472,6 +1475,7 @@
+ * (not defined for Method and ForAll types)
+ */
+ public boolean isAssignable(Type t, Type s, Warner warn) {
++ if (s.tsym == syms.dynamicType.tsym) return true;
+ if (t.tag == ERROR)
+ return t.tsym != null && t.tsym.name == names.any;
+ if (t.tag <= INT && t.constValue() != null) {
+diff --git a/src/share/classes/com/sun/tools/javac/comp/Lower.java b/src/share/classes/com/sun/tools/javac/comp/Lower.java
+--- a/src/share/classes/com/sun/tools/javac/comp/Lower.java
++++ b/src/share/classes/com/sun/tools/javac/comp/Lower.java
+@@ -2614,6 +2614,12 @@
+ Type unboxedType = types.unboxedType(tree.type);
+ // note: the "primitive" parameter is not used. There muse be
+ // a conversion from unboxedType to primitive.
++ if (tree.type.tsym == syms.dynamicType.tsym) {
++ // use primitive target typing if the source is java.dyn.Dynamic
++ unboxedType = primitive;
++ ClassSymbol boxedClass = types.boxedClass(unboxedType);
++ tree = make.TypeCast(boxedClass.type, tree);
++ }
+ if (unboxedType.tsym == null)
+ return tree;
+ make_at(tree.pos());
+diff --git a/src/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/share/classes/com/sun/tools/javac/comp/Resolve.java
+--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java
++++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java
+@@ -874,7 +874,7 @@
+ }
+ Type restype;
+ if (typeargtypes.isEmpty()) {
+- restype = syms.objectType;
++ restype = syms.dynamicType;
+ } else {
+ restype = typeargtypes.head;
+ if (!typeargtypes.tail.isEmpty())
+@@ -914,9 +914,18 @@
+ };
+ Type implicitArgType(Type argType) {
+ argType = types.erasure(argType);
+- if (argType.tag == BOT)
+- // nulls type as Object
+- argType = syms.objectType;
++ if (argType.tag == BOT) {
++ // Null arguments type as java.lang.Void, which is a
++ // reference that only takes a null value.
++ // The signature for this dynamic call will mention Void,
++ // and bootstrap methods will have to recognize this
++ // specially as a signal for ambiguous nulls (if they care).
++ // Even beyond the odd name, this is imperfect, since the
++ // conversion rules for real null (to any reference type T)
++ // do not match the reference conversion rules for Void
++ // (which of course only converts to Object).
++ argType = syms.voidWrapperType;
++ }
+ return argType;
+ }
+
+diff --git a/src/share/classes/com/sun/tools/javac/jvm/Gen.java b/src/share/classes/com/sun/tools/javac/jvm/Gen.java
+--- a/src/share/classes/com/sun/tools/javac/jvm/Gen.java
++++ b/src/share/classes/com/sun/tools/javac/jvm/Gen.java
+@@ -2070,6 +2070,7 @@
+ // For basic types, the coerce(...) in genExpr(...) will do
+ // the conversion.
+ if (tree.clazz.type.tag > lastBaseTag &&
++ !types.isSameType(tree.clazz.type, syms.dynamicType) &&
+ types.asSuper(tree.expr.type, tree.clazz.type.tsym) == null) {
+ code.emitop2(checkcast, makeRef(tree.pos(), tree.clazz.type));
+ }
+@@ -2153,9 +2154,21 @@
+ }
+ result = items.
+ makeImmediateItem(sym.type, ((VarSymbol) sym).getConstValue());
+- } else if (allowInvokedynamic && sym.kind == MTH && ssym == syms.dynamicType.tsym) {
+- base.drop();
+- result = items.makeDynamicItem(sym);
++ } else if (allowInvokedynamic && sym.kind == MTH && sym.owner == syms.dynamicType.tsym) {
++ if (ssym == syms.dynamicType.tsym) {
++ base.drop();
++ result = items.makeDynamicItem(sym);
++ } else {
++ // There is a receiver value here; let's mix it into the argument list.
++ Symbol sym1 = sym.clone(sym.owner);
++ MethodType type1 = (MethodType) sym1.type.clone();
++ type1.argtypes = type1.argtypes.prepend(tree.selected.type);
++ sym1.type = type1;
++ // TODO: find a way to memoize sym1 as derived from sym
++ base.load();
++ result = items.makeDynamicItem(sym1);
++ // Since invokedynamic allows null first argument, do not call genNullCheck.
++ }
+ } else {
+ if (!accessSuper)
+ sym = binaryQualifier(sym, tree.selected.type);
+diff --git a/src/share/classes/com/sun/tools/javac/util/Name.java b/src/share/classes/com/sun/tools/javac/util/Name.java
+--- a/src/share/classes/com/sun/tools/javac/util/Name.java
++++ b/src/share/classes/com/sun/tools/javac/util/Name.java
+@@ -443,6 +443,7 @@
+ java_lang_Cloneable = fromString("java.lang.Cloneable");
+ java_io_Serializable = fromString("java.io.Serializable");
+ java_lang_Enum = fromString("java.lang.Enum");
++ java_lang_Void = fromString("java.lang.Void");
+ java_dyn_MethodHandle = fromString("java.dyn.MethodHandle");
+ java_dyn_Dynamic = fromString("java.dyn.Dynamic");
+ package_info = fromString("package-info");
+@@ -584,6 +585,7 @@
+ public final Name java_io_Serializable;
+ public final Name serialVersionUID;
+ public final Name java_lang_Enum;
++ public final Name java_lang_Void;
+ public final Name java_dyn_MethodHandle;
+ public final Name java_dyn_Dynamic;
+ public final Name package_info;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nb-javac/meth.patch Thu Mar 26 19:55:19 2009 -0500
@@ -0,0 +1,734 @@
+6754038: writing libraries in Java for non-Java languages requires method handle invocation
+MQ base = 4d206181439a in http://hg.netbeans.org/main/nb-javac [release65_base]
+
+diff --git a/src/share/classes/com/sun/tools/javac/code/Symtab.java b/src/share/classes/com/sun/tools/javac/code/Symtab.java
+--- a/src/share/classes/com/sun/tools/javac/code/Symtab.java
++++ b/src/share/classes/com/sun/tools/javac/code/Symtab.java
+@@ -119,6 +119,8 @@
+ public final Type stringBuilderType;
+ public final Type cloneableType;
+ public final Type serializableType;
++ public final Type methodHandleType;
++ public final Type dynamicType;
+ public final Type throwableType;
+ public final Type errorType;
+ public final Type illegalArgumentExceptionType;
+@@ -351,6 +353,8 @@
+ cloneableType = enterClass("java.lang.Cloneable");
+ throwableType = enterClass("java.lang.Throwable");
+ serializableType = enterClass("java.io.Serializable");
++ methodHandleType = enterClass("java.dyn.MethodHandle");
++ dynamicType = enterClass("java.dyn.Dynamic");
+ errorType = enterClass("java.lang.Error");
+ illegalArgumentExceptionType = enterClass("java.lang.IllegalArgumentException");
+ exceptionType = enterClass("java.lang.Exception");
+diff --git a/src/share/classes/com/sun/tools/javac/comp/Attr.java b/src/share/classes/com/sun/tools/javac/comp/Attr.java
+--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java
++++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java
+@@ -118,6 +118,8 @@
+ relax = (options.get("-retrofit") != null ||
+ options.get("-relax") != null);
+ useBeforeDeclarationWarning = options.get("useBeforeDeclarationWarning") != null;
++ allowInvokedynamic = options.get("invokedynamic") != null;
++ if (options.get("ide") != null) allowInvokedynamic = true;
+ cancelService = CancelService.instance(context);
+ isBackgroundCompilation = options.get("backgroundCompilation") != null; //NOI18N
+ }
+@@ -151,6 +153,10 @@
+ */
+ boolean allowAnonOuterThis;
+
++ /** Switch: allow invokedynamic syntax
++ */
++ boolean allowInvokedynamic;
++
+ /**
+ * Switch: warn about use of variable before declaration?
+ * RFE: 6425594
+@@ -455,14 +461,22 @@
+ }
+
+ /** Attribute a type argument list, returning a list of types.
++ * Caller is responsible for calling checkRefTypes.
+ */
+- List<Type> attribTypes(List<JCExpression> trees, Env<AttrContext> env) {
++ List<Type> attribAnyTypes(List<JCExpression> trees, Env<AttrContext> env) {
+ ListBuffer<Type> argtypes = new ListBuffer<Type>();
+ for (List<JCExpression> l = trees; l.nonEmpty(); l = l.tail)
+- argtypes.append(chk.checkRefType(l.head.pos(), attribType(l.head, env)));
++ argtypes.append(attribType(l.head, env));
+ return argtypes.toList();
+ }
+
++ /** Attribute a type argument list, returning a list of types.
++ * Check that all the types are references.
++ */
++ List<Type> attribTypes(List<JCExpression> trees, Env<AttrContext> env) {
++ List<Type> types = attribAnyTypes(trees, env);
++ return chk.checkRefTypes(trees, types);
++ }
+
+ /**
+ * Attribute type variables (of generic classes or methods).
+@@ -1232,6 +1246,7 @@
+
+ // The types of the actual method type arguments.
+ List<Type> typeargtypes = null;
++ boolean typeargtypesNonRefOK = false;
+
+ Name methName = TreeInfo.name(tree.meth);
+
+@@ -1318,7 +1333,7 @@
+ // Attribute the arguments, yielding list of argument types, ...
+ try {
+ argtypes = attribArgs(tree.args, localEnv);
+- typeargtypes = attribTypes(tree.typeargs, localEnv);
++ typeargtypes = attribAnyTypes(tree.typeargs, localEnv);
+ } catch (BreakAttr bae) {
+ attribExpr(tree.meth, localEnv);
+ throw bae;
+@@ -1359,6 +1374,20 @@
+ restype.tsym);
+ }
+
++ // as a special case, MethodHandle.<T>invoke(abc) and Dynamic.<T>foo(abc)
++ // has type <T>, and T can be a primitive type.
++ if (tree.meth.getTag() == JCTree.SELECT && !typeargtypes.isEmpty()) {
++ Type selt = ((JCFieldAccess) tree.meth).selected.type;
++ if ((selt == syms.methodHandleType && methName == names.invoke) || selt == syms.dynamicType) {
++ assert types.isSameType(restype, typeargtypes.head) : mtype;
++ typeargtypesNonRefOK = true;
++ }
++ }
++
++ if (!typeargtypesNonRefOK) {
++ chk.checkRefTypes(tree.typeargs, typeargtypes);
++ }
++
+ // Check that value of resulting type is admissible in the
+ // current context. Also, capture the return type
+ result = check(tree, capture(restype), VAL, pkind, pt);
+@@ -1968,7 +1997,8 @@
+ // Check if type-qualified fields or methods are static (JLS)
+ if ((sym.flags() & STATIC) == 0 &&
+ sym.name != names._super &&
+- (sym.kind == VAR || sym.kind == MTH)) {
++ (sym.kind == VAR || sym.kind == MTH) &&
++ !(allowInvokedynamic && sym.owner == syms.dynamicType.tsym)) {
+ rs.access(rs.new StaticError(sym),
+ tree.pos(), site, sym.name, true);
+ }
+diff --git a/src/share/classes/com/sun/tools/javac/comp/Check.java b/src/share/classes/com/sun/tools/javac/comp/Check.java
+--- a/src/share/classes/com/sun/tools/javac/comp/Check.java
++++ b/src/share/classes/com/sun/tools/javac/comp/Check.java
+@@ -207,6 +207,12 @@
+ * @param found The type that was found.
+ */
+ Type typeTagError(DiagnosticPosition pos, Object required, Object found) {
++ // this error used to be raised by the parser,
++ // but has been delayed to this point:
++ if (found instanceof Type && ((Type)found).tag == VOID) {
++ log.error(pos, "illegal.start.of.type");
++ return syms.errType;
++ }
+ log.error(pos, "type.found.req", found, required);
+ return syms.errType;
+ }
+@@ -537,6 +543,20 @@
+ }
+ }
+
++ /** Check that each type is a reference type, i.e. a class, interface or array type
++ * or a type variable.
++ * @param trees Original trees, used for error reporting.
++ * @param types The types to be checked.
++ */
++ List<Type> checkRefTypes(List<JCExpression> trees, List<Type> types) {
++ List<JCExpression> tl = trees;
++ for (List<Type> l = types; l.nonEmpty(); l = l.tail) {
++ l.head = checkRefType(tl.head.pos(), l.head);
++ tl = tl.tail;
++ }
++ return types;
++ }
++
+ /** Check that type is a null or reference type.
+ * @param pos Position to be used for error reporting.
+ * @param t The type to be checked.
+diff --git a/src/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/share/classes/com/sun/tools/javac/comp/Resolve.java
+--- a/src/share/classes/com/sun/tools/javac/comp/Resolve.java
++++ b/src/share/classes/com/sun/tools/javac/comp/Resolve.java
+@@ -61,6 +61,7 @@
+ Types types;
+ public final boolean boxingEnabled; // = source.allowBoxing();
+ public final boolean varargsEnabled; // = source.allowVarargs();
++ public final boolean allowInvokedynamic; // = options.get("invokedynamic");
+ private final boolean debugResolve;
+ private final boolean ideMode;
+
+@@ -99,6 +100,7 @@
+ Options options = Options.instance(context);
+ debugResolve = options.get("debugresolve") != null;
+ this.ideMode = options.get("ide") != null;
++ allowInvokedynamic = ideMode || options.get("invokedynamic") != null;
+ }
+
+ /** error symbols, which are returned when resolution fails
+@@ -848,6 +850,76 @@
+ return bestSoFar;
+ }
+
++ /** Find or create an implicit method of exactly the given type (after erasure).
++ * Searches in a side table, not the main scope of the site.
++ * This emulates the lookup process required by JSR 292 in JVM.
++ * @param env The current environment.
++ * @param site The original type from where the selection
++ * takes place.
++ * @param name The method's name.
++ * @param argtypes The method's value arguments.
++ * @param typeargtypes The method's type arguments
++ */
++ Symbol findImplicitMethod(Env<AttrContext> env,
++ Type site,
++ Name name,
++ List<Type> argtypes,
++ List<Type> typeargtypes) {
++ assert allowInvokedynamic;
++ assert site == syms.dynamicType || (site == syms.methodHandleType && name == names.invoke);
++ ClassSymbol c = (ClassSymbol) site.tsym;
++ Scope implicit = c.members().next;
++ if (implicit == null) {
++ c.members().next = implicit = new Scope(c);
++ }
++ Type restype;
++ if (typeargtypes.isEmpty()) {
++ restype = syms.objectType;
++ } else {
++ restype = typeargtypes.head;
++ if (!typeargtypes.tail.isEmpty())
++ return methodNotFound;
++ }
++ List<Type> paramtypes = Type.map(argtypes, implicitArgType);
++ MethodType mtype = new MethodType(paramtypes,
++ restype,
++ List.<Type>nil(),
++ syms.methodClass);
++ int flags = PUBLIC | ABSTRACT;
++ Symbol m = null;
++ for (Scope.Entry e = implicit.lookup(name);
++ e.scope != null;
++ e = e.next()) {
++ Symbol sym = e.sym;
++ assert sym.kind == MTH;
++ if (types.isSameType(mtype, sym.type)
++ && (sym.flags() & STATIC) == (flags & STATIC)) {
++ m = sym;
++ break;
++ }
++ }
++ if (m == null) {
++ // create the desired method
++ m = new MethodSymbol(flags, name, mtype, c);
++ implicit.enter(m);
++ }
++ assert argumentsAcceptable(argtypes, types.memberType(site, m).getParameterTypes(),
++ false, false, Warner.noWarnings);
++ assert null != instantiate(env, site, m, argtypes, typeargtypes, false, false, Warner.noWarnings);
++ return m;
++ }
++ //where
++ Mapping implicitArgType = new Mapping ("implicitArgType") {
++ public Type apply(Type t) { return implicitArgType(t); }
++ };
++ Type implicitArgType(Type argType) {
++ argType = types.erasure(argType);
++ if (argType.tag == BOT)
++ // nulls type as Object
++ argType = syms.objectType;
++ return argType;
++ }
++
+ /** Load toplevel or member class with given fully qualified name and
+ * verify that it is accessible.
+ * @param env The current environment.
+@@ -1244,6 +1316,14 @@
+ sym = findMethod(env, site, name, argtypes, typeargtypes, true,
+ env.info.varArgs=true, false);
+ }
++ if (sym.kind >= AMBIGUOUS &&
++ allowInvokedynamic &&
++ (site == syms.dynamicType ||
++ (site == syms.methodHandleType && name == names.invoke))) {
++ // lookup failed; supply an exactly-typed implicit method
++ sym = findImplicitMethod(env, site, name, argtypes, typeargtypes);
++ env.info.varArgs = false;
++ }
+ if (sym.kind >= AMBIGUOUS) {
+ sym = access(sym, pos, site, name, true, argtypes, typeargtypes);
+ }
+diff --git a/src/share/classes/com/sun/tools/javac/jvm/ByteCodes.java b/src/share/classes/com/sun/tools/javac/jvm/ByteCodes.java
+--- a/src/share/classes/com/sun/tools/javac/jvm/ByteCodes.java
++++ b/src/share/classes/com/sun/tools/javac/jvm/ByteCodes.java
+@@ -225,7 +225,7 @@
+ invokespecial = 183,
+ invokestatic = 184,
+ invokeinterface = 185,
+- // ___unused___ = 186,
++ invokedynamic = 186,
+ new_ = 187,
+ newarray = 188,
+ anewarray = 189,
+diff --git a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
+--- a/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
++++ b/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java
+@@ -494,6 +494,7 @@
+ if (value instanceof MethodSymbol) {
+ MethodSymbol m = (MethodSymbol)value;
+ poolbuf.appendByte((m.owner.flags() & INTERFACE) != 0
++ && (m.flags() & STATIC) == 0 // JSR 292, transitional
+ ? CONSTANT_InterfaceMethodref
+ : CONSTANT_Methodref);
+ poolbuf.appendChar(pool.put(m.owner));
+diff --git a/src/share/classes/com/sun/tools/javac/jvm/Code.java b/src/share/classes/com/sun/tools/javac/jvm/Code.java
+--- a/src/share/classes/com/sun/tools/javac/jvm/Code.java
++++ b/src/share/classes/com/sun/tools/javac/jvm/Code.java
+@@ -457,6 +457,19 @@
+ state.push(mtype.getReturnType());
+ }
+
++ /** Emit an invokedynamic instruction.
++ */
++ public void emitInvokedynamic(int desc, Type mtype) {
++ // N.B. this format is under consideration by the JSR 292 EG
++ int argsize = width(mtype.getParameterTypes());
++ emitop(invokedynamic);
++ if (!alive) return;
++ emit2(desc);
++ emit2(0);
++ state.pop(argsize);
++ state.push(mtype.getReturnType());
++ }
++
+ /** Emit an opcode with no operand field.
+ */
+ public void emitop0(int op) {
+diff --git a/src/share/classes/com/sun/tools/javac/jvm/Gen.java b/src/share/classes/com/sun/tools/javac/jvm/Gen.java
+--- a/src/share/classes/com/sun/tools/javac/jvm/Gen.java
++++ b/src/share/classes/com/sun/tools/javac/jvm/Gen.java
+@@ -116,6 +116,7 @@
+ : options.get("-g:vars") != null;
+ genCrt = options.get("-Xjcov") != null;
+ debugCode = options.get("debugcode") != null;
++ allowInvokedynamic = options.get("ide") != null || options.get("invokedynamic") != null;
+
+ generateIproxies =
+ target.requiresIproxy() ||
+@@ -166,6 +167,7 @@
+ private final boolean varDebugInfo;
+ private final boolean genCrt;
+ private final boolean debugCode;
++ private final boolean allowInvokedynamic;
+
+ /** Default limit of (approximate) size of finalizer to inline.
+ * Zero means always use jsr. 100 or greater means never use
+@@ -2151,6 +2153,9 @@
+ }
+ result = items.
+ makeImmediateItem(sym.type, ((VarSymbol) sym).getConstValue());
++ } else if (allowInvokedynamic && sym.kind == MTH && ssym == syms.dynamicType.tsym) {
++ base.drop();
++ result = items.makeDynamicItem(sym);
+ } else {
+ if (!accessSuper)
+ sym = binaryQualifier(sym, tree.selected.type);
+diff --git a/src/share/classes/com/sun/tools/javac/jvm/Items.java b/src/share/classes/com/sun/tools/javac/jvm/Items.java
+--- a/src/share/classes/com/sun/tools/javac/jvm/Items.java
++++ b/src/share/classes/com/sun/tools/javac/jvm/Items.java
+@@ -141,6 +141,13 @@
+ return new StaticItem(member);
+ }
+
++ /** Make an item representing a dynamically invoked method.
++ * @param member The represented symbol.
++ */
++ Item makeDynamicItem(Symbol member) {
++ return new DynamicItem(member);
++ }
++
+ /** Make an item representing an instance variable or method.
+ * @param member The represented symbol.
+ * @param nonvirtual Is the reference not virtual? (true for constructors
+@@ -461,6 +468,38 @@
+ }
+ }
+
++ /** An item representing a dynamic call site.
++ */
++ class DynamicItem extends StaticItem {
++ DynamicItem(Symbol member) {
++ super(member);
++ assert member.owner == syms.dynamicType.tsym;
++ }
++
++ Item load() {
++ assert false;
++ return null;
++ }
++
++ void store() {
++ assert false;
++ }
++
++ Item invoke() {
++ // assert target.hasNativeInvokeDynamic();
++ MethodType mtype = (MethodType)member.erasure(types);
++ int rescode = Code.typecode(mtype.restype);
++ ClassFile.NameAndType descr = new ClassFile.NameAndType(member.name, mtype);
++ code.emitInvokedynamic(pool.put(descr), mtype);
++ return stackItem[rescode];
++ }
++
++ public String toString() {
++ return "dynamic(" + member + ")";
++ }
++ }
++
++
+ /** An item representing an instance variable or method.
+ */
+ class MemberItem extends Item {
+diff --git a/src/share/classes/com/sun/tools/javac/jvm/Target.java b/src/share/classes/com/sun/tools/javac/jvm/Target.java
+--- a/src/share/classes/com/sun/tools/javac/jvm/Target.java
++++ b/src/share/classes/com/sun/tools/javac/jvm/Target.java
+@@ -253,6 +253,12 @@
+ return compareTo(JDK1_5) >= 0;
+ }
+
++ /** Does the VM support an invokedynamic instruction?
++ */
++ public boolean hasInvokedynamic() {
++ return compareTo(JDK1_7) >= 0;
++ }
++
+ /** Although we may not have support for class literals, should we
+ * avoid initializing the class that the literal refers to?
+ * See 4468823
+diff --git a/src/share/classes/com/sun/tools/javac/main/Main.java b/src/share/classes/com/sun/tools/javac/main/Main.java
+--- a/src/share/classes/com/sun/tools/javac/main/Main.java
++++ b/src/share/classes/com/sun/tools/javac/main/Main.java
+@@ -267,14 +267,19 @@
+ }
+ return null;
+ } else {
+- options.put("-target", source.requiredTarget().name);
++ target = source.requiredTarget();
++ options.put("-target", target.name);
+ }
+ } else {
+ if (targetString == null && !source.allowGenerics()) {
+- options.put("-target", Target.JDK1_4.name);
++ target = Target.JDK1_4;
++ options.put("-target", target.name);
+ }
+ }
+ }
++ if (target.hasInvokedynamic()) {
++ options.put("invokedynamic", "invokedynamic");
++ }
+ return filenames.toList();
+ }
+ // where
+diff --git a/src/share/classes/com/sun/tools/javac/parser/Parser.java b/src/share/classes/com/sun/tools/javac/parser/Parser.java
+--- a/src/share/classes/com/sun/tools/javac/parser/Parser.java
++++ b/src/share/classes/com/sun/tools/javac/parser/Parser.java
+@@ -1190,7 +1190,13 @@
+ return illegal(pos);
+ }
+ } else {
+- return illegal();
++ // Support the corner case of myMethodHandle.<void>invoke() by passing
++ // a void type (like other primitive types) to the next phase.
++ // The error will be reported in Attr.attribTypes or Attr.visitApply.
++ JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID));
++ S.nextToken();
++ return ti;
++ //return illegal();
+ }
+ break;
+ default:
+diff --git a/src/share/classes/com/sun/tools/javac/util/Name.java b/src/share/classes/com/sun/tools/javac/util/Name.java
+--- a/src/share/classes/com/sun/tools/javac/util/Name.java
++++ b/src/share/classes/com/sun/tools/javac/util/Name.java
+@@ -443,6 +443,8 @@
+ java_lang_Cloneable = fromString("java.lang.Cloneable");
+ java_io_Serializable = fromString("java.io.Serializable");
+ java_lang_Enum = fromString("java.lang.Enum");
++ java_dyn_MethodHandle = fromString("java.dyn.MethodHandle");
++ java_dyn_Dynamic = fromString("java.dyn.Dynamic");
+ package_info = fromString("package-info");
+ serialVersionUID = fromString("serialVersionUID");
+ ConstantValue = fromString("ConstantValue");
+@@ -488,6 +490,7 @@
+ value = fromString("value");
+ getMessage = fromString("getMessage");
+ getClass = fromString("getClass");
++ invoke = fromString("invoke");
+
+ TYPE = fromString("TYPE");
+ FIELD = fromString("FIELD");
+@@ -581,6 +584,8 @@
+ public final Name java_io_Serializable;
+ public final Name serialVersionUID;
+ public final Name java_lang_Enum;
++ public final Name java_dyn_MethodHandle;
++ public final Name java_dyn_Dynamic;
+ public final Name package_info;
+ public final Name ConstantValue;
+ public final Name LineNumberTable;
+@@ -626,6 +631,7 @@
+ public final Name value;
+ public final Name getMessage;
+ public final Name getClass;
++ public final Name invoke;
+
+ public final Name TYPE;
+ public final Name FIELD;
+diff --git a/test/tools/javac/meth/InvokeDyn.java b/test/tools/javac/meth/InvokeDyn.java
+new file mode 100644
+--- /dev/null
++++ b/test/tools/javac/meth/InvokeDyn.java
+@@ -0,0 +1,55 @@
++/*
++ * Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
++ * CA 95054 USA or visit www.sun.com if you need additional information or
++ * have any questions.
++ */
++
++/*
++ * @test
++ * @bug 6754038
++ * @summary Generate call sites for method handle
++ * @author jrose
++ *
++ * Standalone testing:
++ * <code>
++ * $ cd $MY_REPO_DIR/langtools
++ * $ (cd make; make)
++ * $ ./dist/bootstrap/bin/javac -d dist test/tools/javac/meth/InvokeDyn.java
++ * $ javap -c -classpath dist meth.InvokeDyn
++ * </code>
++ *
++ * @compile InvokeDyn.java
++ */
++
++package meth;
++
++import java.dyn.Dynamic;
++
++public class InvokeDyn {
++ void test() {
++ Object x = "hello";
++ Dynamic.greet(x, "world", 123);
++ Dynamic.greet(x, "mundus", 456);
++ Dynamic.greet(x, "kosmos", 789);
++ Dynamic.<String>cogitate(10.11121, 3.14);
++ Dynamic.<void>#"yow: what I mean to say is, please treat this one specially"(null);
++ Dynamic.<int>invoke("goodbye");
++ }
++}
+diff --git a/test/tools/javac/meth/InvokeMH.java b/test/tools/javac/meth/InvokeMH.java
+new file mode 100644
+--- /dev/null
++++ b/test/tools/javac/meth/InvokeMH.java
+@@ -0,0 +1,73 @@
++/*
++ * Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
++ * CA 95054 USA or visit www.sun.com if you need additional information or
++ * have any questions.
++ */
++
++/*
++ * @test
++ * @bug 6754038
++ * @summary Generate call sites for method handle
++ * @author jrose
++ *
++ * Standalone testing:
++ * <code>
++ * $ cd $MY_REPO_DIR/langtools
++ * $ (cd make; make)
++ * $ ./dist/bootstrap/bin/javac -d dist test/tools/javac/meth/InvokeMH.java
++ * $ javap -c -classpath dist meth.InvokeMH
++ * </code>
++ *
++ * @compile InvokeMH.java
++ */
++
++package meth;
++
++import java.dyn.MethodHandle;
++
++public class InvokeMH {
++ void test(MethodHandle mh_SiO,
++ MethodHandle mh_vS,
++ MethodHandle mh_vi,
++ MethodHandle mh_vv) {
++ Object o; String s; int i; // for return type testing
++
++ // next five must have sig = (String,int)Object
++ mh_SiO.invoke("world", 123);
++ mh_SiO.invoke("mundus", 456);
++ Object k = "kosmos";
++ mh_SiO.invoke((String)k, 789);
++ o = mh_SiO.invoke((String)null, 000);
++ o = mh_SiO.<Object>invoke("arda", -123);
++
++ // sig = ()String
++ s = mh_vS.<String>invoke();
++
++ // sig = ()int
++ i = mh_vi.<int>invoke();
++ o = mh_vi.<int>invoke();
++ //s = mh_vi.<int>invoke(); //BAD
++ mh_vi.<int>invoke();
++
++ // sig = ()void
++ //o = mh_vv.<void>invoke(); //BAD
++ mh_vv.<void>invoke();
++ }
++}
+diff --git a/test/tools/javac/meth/MakeNegTests.sh b/test/tools/javac/meth/MakeNegTests.sh
+new file mode 100644
+--- /dev/null
++++ b/test/tools/javac/meth/MakeNegTests.sh
+@@ -0,0 +1,96 @@
++#!/bin/sh
++
++#
++# Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
++# CA 95054 USA or visit www.sun.com if you need additional information or
++# have any questions.
++#
++
++# @test
++# @bug 6754038
++# @summary Verify correct rejection of strongly typed return values
++# @run shell MakeNegTests.sh
++
++default_template=InvokeMH.java
++javacflags='-target 7'
++# the rest of this file is a generic "//BAD"-line tester
++
++: ${TESTSRC=.} ${TESTCLASSES=.}
++javac="${TESTJAVA+${TESTJAVA}/bin/}javac"
++
++verbose=false quiet=false
++
++main() {
++ case "${@-}" in
++ *.java*)
++ for template; do
++ expand_and_test "$template"
++ done;;
++ *) expand_and_test "${TESTSRC}/$default_template";;
++ esac
++}
++
++expand_and_test() {
++ template=$1
++ expand "$@"
++ testneg "$@"
++}
++
++expand() {
++ template=$1
++ badlines=` grep -n < "$template" '//BAD' `
++ badcount=` echo "$badlines" | wc -l `
++ [ $badcount -gt 0 ] || { echo "No negative test cases in $template"; exit 1; }
++ $quiet || echo "Expanding $badcount negative test cases from $template:"
++ $quiet || echo "$badlines"
++ badnums=` echo "$badlines" | sed 's/:.*//' `
++ casestem=` getcasestem "$template" `
++ tclassname=` basename "$template" .java `
++ rm -f "$casestem"*.java
++ for badnum in $badnums; do
++ casefile="$casestem"${badnum}.java
++ cclassname=` basename "$casefile" .java `
++ sed < "$template" > "$casefile" "
++ ${badnum}s:^ *[/*]*: :
++ s/${tclassname}/${cclassname}/g
++ "
++ $verbose && diff -u "$template" "$casefile"
++ done
++}
++
++getcasestem() {
++ echo "$1" | sed 's/\.java$//;s/_BAD[0-9]*$//;s/$/_BAD/'
++}
++
++testneg() {
++ template=$1
++ for casefile in ` getcasestem "$template" `*.java; do
++ $quiet || echo -------- $javac $javacflags "$casefile"
++ $javac $javacflags "$casefile" > "$casefile".errlog 2>&1 && {
++ echo "*** Compilation unexpectedly succeeded: $casefile"
++ exit 1
++ }
++ $quiet || echo "Compilation failed as expected"
++ $quiet || head ` $verbose || echo -3 ` < "$casefile".errlog
++ rm "$casefile".errlog
++ done
++}
++
++main "$@"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nb-javac/netbeans.txt Thu Mar 26 19:55:19 2009 -0500
@@ -0,0 +1,35 @@
+Instructions:
+
+Make a workspace for the NetBeans javac parser.
+
+$ hg clone http://hg.netbeans.org/main/nb-javac
+
+Install these patches.
+
+$ hg qinit -R nb-javac
+$ cp davinci/patches/langtools/nb-javac/* nb-javac/.hg/patches
+
+Verify the revision guard and apply the patches.
+
+$ cd nb-javac
+$ hg co release65_base
+$ hg qselect 4d206181439a
+$ hg qpush --all
+
+Build:
+
+$ (cd make/netbeans/nb-javac; ant clean jar)
+
+Deploy the updated javac into a scratch copy of NetBeans 6.5:
+
+$ nborig="/Applications/NetBeans/NetBeans 6.5.app"
+$ nbcopy="/Applications/NetBeans/NetBeans 6.5 Experimental.app"
+$ nbres="Contents/Resources/NetBeans/java2/modules/ext/javac-api-nb-7.0-b07.jar"
+$ cp -pr "$nborig" "$nbcopy"
+$ cp make/netbeans/nb-javac/dist/javac-impl.jar "$nbcopy/$nbres"
+
+(There is probably a better way to plug this in; ask any NetBeans expert and let me know.)
+
+Enjoy:
+
+$ open "$nbcopy"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nb-javac/quid.patch Thu Mar 26 19:55:19 2009 -0500
@@ -0,0 +1,445 @@
+6746458: writing libraries in Java for non-Java languages requires support for exotic identifiers
+MQ base = 4d206181439a in http://hg.netbeans.org/main/nb-javac [release65_base]
+
+diff --git a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
+--- a/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
++++ b/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
+@@ -2247,6 +2247,7 @@
+ for (String binaryName : binaryNames) {
+ String simpleName = binaryName.substring(binaryName.lastIndexOf(".") + 1);
+ if (SourceVersion.isIdentifier(simpleName) ||
++ fo.getKind() == JavaFileObject.Kind.CLASS ||
+ simpleName.equals("package-info")) {
+ includeClassFile(p, fo, binaryName);
+ }
+diff --git a/src/share/classes/com/sun/tools/javac/parser/Scanner.java b/src/share/classes/com/sun/tools/javac/parser/Scanner.java
+--- a/src/share/classes/com/sun/tools/javac/parser/Scanner.java
++++ b/src/share/classes/com/sun/tools/javac/parser/Scanner.java
+@@ -323,7 +323,7 @@
+
+ /** Read next character in character or string literal and copy into sbuf.
+ */
+- private void scanLitChar() {
++ private void scanLitChar(boolean forBytecodeName) {
+ if (ch == '\\') {
+ if (buf[bp+1] == '\\' && unicodeConversionBp != bp) {
+ bp++;
+@@ -363,6 +363,18 @@
+ putChar('\"'); scanChar(); break;
+ case '\\':
+ putChar('\\'); scanChar(); break;
++ case '|': case ',': case '?': case '%':
++ case '^': case '_': case '{': case '}':
++ case '!': case '-': case '=':
++ if (forBytecodeName) {
++ // Accept escape sequences for dangerous bytecode chars.
++ // This is illegal in normal Java string or character literals.
++ // Note that the escape sequence itself is passed through.
++ putChar('\\'); putChar(ch); scanChar();
++ } else {
++ lexError(bp, "illegal.esc.char");
++ }
++ break;
+ default:
+ lexError(bp, "illegal.esc.char");
+ }
+@@ -371,6 +383,24 @@
+ putChar(ch); scanChar();
+ }
+ }
++ private void scanLitChar() {
++ scanLitChar(false);
++ }
++
++ /** Read next character in an exotic name #"foo"
++ */
++ private void scanBytecodeNameChar() {
++ switch (ch) {
++ // reject any "dangerous" char which is illegal somewhere in the JVM spec
++ // cf. http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm
++ case '/': case '.': case ';': // illegal everywhere
++ case '<': case '>': // illegal in methods, dangerous in classes
++ case '[': // illegal in classes
++ lexError(bp, "illegal.bytecode.ident.char", String.valueOf((int)ch));
++ break;
++ }
++ scanLitChar(true);
++ }
+
+ /** Read fractional part of hexadecimal floating point number.
+ */
+@@ -923,6 +953,26 @@
+ lexError(pos, "unclosed.str.lit");
+ }
+ return;
++ case '#':
++ scanChar();
++ if (ch == '\"') {
++ scanChar();
++ if (ch == '\"')
++ lexError(pos, "empty.bytecode.ident");
++ while (ch != '\"' && ch != CR && ch != LF && bp < buflen) {
++ scanBytecodeNameChar();
++ }
++ if (ch == '\"') {
++ name = names.fromChars(sbuf, 0, sp);
++ token = IDENTIFIER; // even if #"int" or #"do"
++ scanChar();
++ } else {
++ lexError(pos, "unclosed.bytecode.ident");
++ }
++ } else {
++ lexError("illegal.char", String.valueOf((int)'#'));
++ }
++ return;
+ default:
+ if (isSpecial(ch)) {
+ scanOperator();
+diff --git a/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/share/classes/com/sun/tools/javac/resources/compiler.properties
+--- a/src/share/classes/com/sun/tools/javac/resources/compiler.properties
++++ b/src/share/classes/com/sun/tools/javac/resources/compiler.properties
+@@ -139,6 +139,8 @@
+
+ compiler.err.else.without.if=\
+ ''else'' without ''if''
++compiler.err.empty.bytecode.ident=\
++ empty bytecode identifier
+ compiler.err.empty.char.lit=\
+ empty character literal
+ compiler.err.encl.class.required=\
+@@ -181,6 +183,8 @@
+
+ compiler.err.icls.cant.have.static.decl=\
+ inner classes cannot have static declarations
++compiler.err.illegal.bytecode.ident.char=\
++ illegal bytecode identifier character: \\{0}
+ compiler.err.illegal.char=\
+ illegal character: \\{0}
+ compiler.err.illegal.char.for.encoding=\
+@@ -433,6 +437,8 @@
+ compiler.err.types.incompatible.diff.ret=\
+ types {0} and {1} are incompatible; both define {2}, but with unrelated return types
+
++compiler.err.unclosed.bytecode.ident=\
++ unclosed bytecode identifier
+ compiler.err.unclosed.char.lit=\
+ unclosed character literal
+ compiler.err.unclosed.comment=\
+diff --git a/test/tools/javac/quid/MakeNegTests.sh b/test/tools/javac/quid/MakeNegTests.sh
+new file mode 100644
+--- /dev/null
++++ b/test/tools/javac/quid/MakeNegTests.sh
+@@ -0,0 +1,95 @@
++#!/bin/sh
++
++#
++# Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
++# CA 95054 USA or visit www.sun.com if you need additional information or
++# have any questions.
++#
++
++# @test
++# @bug 6746458
++# @summary Verify correct rejection of illegal quoted identifiers.
++# @run shell MakeNegTests.sh
++
++default_template=QuotedIdent.java
++# the rest of this file is a generic "//BAD"-line tester
++
++: ${TESTSRC=.} ${TESTCLASSES=.}
++javac="${TESTJAVA+${TESTJAVA}/bin/}javac"
++
++verbose=false quiet=false
++
++main() {
++ case "${@-}" in
++ *.java*)
++ for template; do
++ expand_and_test "$template"
++ done;;
++ *) expand_and_test "${TESTSRC}/$default_template";;
++ esac
++}
++
++expand_and_test() {
++ template=$1
++ expand "$@"
++ testneg "$@"
++}
++
++expand() {
++ template=$1
++ badlines=` grep -n < "$template" '//BAD' `
++ badcount=` echo "$badlines" | wc -l `
++ [ $badcount -gt 0 ] || { echo "No negative test cases in $template"; exit 1; }
++ $quiet || echo "Expanding $badcount negative test cases from $template:"
++ $quiet || echo "$badlines"
++ badnums=` echo "$badlines" | sed 's/:.*//' `
++ casestem=` getcasestem "$template" `
++ tclassname=` basename "$template" .java `
++ rm "$casestem"*.java
++ for badnum in $badnums; do
++ casefile="$casestem"${badnum}.java
++ cclassname=` basename "$casefile" .java `
++ sed < "$template" > "$casefile" "
++ ${badnum}s:^ *[/*]*: :
++ s/${tclassname}/${cclassname}/g
++ "
++ $verbose && diff -u "$template" "$casefile"
++ done
++}
++
++getcasestem() {
++ echo "$1" | sed 's/\.java$//;s/_BAD[0-9]*$//;s/$/_BAD/'
++}
++
++testneg() {
++ template=$1
++ for casefile in ` getcasestem "$template" `*.java; do
++ $quiet || echo -------- $javac "$casefile"
++ $javac "$casefile" > "$casefile".errlog 2>&1 && {
++ echo "*** Compilation unexpectedly succeeded: $casefile"
++ exit 1
++ }
++ $quiet || echo "Compilation failed as expected"
++ $quiet || head ` $verbose || echo -3 ` < "$casefile".errlog
++ rm "$casefile".errlog
++ done
++}
++
++main "$@"
+diff --git a/test/tools/javac/quid/QuotedIdent.java b/test/tools/javac/quid/QuotedIdent.java
+new file mode 100644
+--- /dev/null
++++ b/test/tools/javac/quid/QuotedIdent.java
+@@ -0,0 +1,129 @@
++/*
++ * Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
++ * CA 95054 USA or visit www.sun.com if you need additional information or
++ * have any questions.
++ */
++
++/*
++ * @test
++ * @bug 6746458
++ * @summary Verify correct lexing of quoted identifiers.
++ * @author jrose
++ *
++ * Standalone testing:
++ * <code>
++ * $ cd $MY_REPO_DIR/langtools
++ * $ (cd make; make)
++ * $ ./dist/bootstrap/bin/javac -d dist test/tools/javac/quid/QuotedIdent.java
++ * $ java -version # should print 1.6 or later
++ * $ java -cp dist quid.QuotedIdent
++ * </code>
++ *
++ * @run main QuotedIdent
++ */
++
++package quid;
++
++public class QuotedIdent {
++ static void check(int testid, String have, String expect)
++ throws RuntimeException {
++ if ((have == null && have != expect) ||
++ (have != null && !have.equals(expect))) {
++ String msg =
++ "TEST " + testid + ": HAVE \"" +
++ have + "\" EXPECT \"" + expect + "\"";
++ System.out.println("StringConversion: " + msg);
++ throw new RuntimeException(msg);
++ }
++ }
++
++ // negative tests:
++ //static class #"" { } //BAD empty ident name
++ //static class #"<foo>" { } //BAD bad char in ident name
++ /*static class /*(//BAD ident name interrupted by newline) #"jump:
++ " { } /* uncomment previous line to attempt class w/ bad name */
++
++ static class #"int" extends Number {
++ final int #"int";
++ #"int"(int #"int") {
++ this.#"int" = #"int";
++ }
++ static #"int" valueOf(int #"int") {
++ return new #"int"(#"int");
++ }
++ public int intValue() { return #"int"; }
++ public long longValue() { return #"int"; }
++ public float floatValue() { return #"int"; }
++ public double doubleValue() { return #"int"; }
++ public String toString() { return String.valueOf(#"int"); }
++ }
++
++ class #"*86" {
++ String #"555-1212"() { return "[*86.555-1212]"; }
++ }
++ static#"*86"#"MAKE-*86"() { // note close spacing
++ return new QuotedIdent().new#"*86"();
++ }
++
++ static String bar() { return "[bar]"; }
++
++ public static void main(String[] args) throws Exception {
++ String s;
++
++ String #"sticky \' wicket" = "wicked ' stick";
++ s = #"sticky ' wicket";
++ check(11, s, "wicked \' stick");
++ check(12, #"s", s);
++ check(13, #"\163", s);
++
++ s = #"QuotedIdent".bar();
++ check(21, s, "[bar]");
++
++ s = #"int".valueOf(123).toString();
++ check(22, s, "123");
++
++ s = #"MAKE-*86"().#"555-1212"();
++ check(23, s, "[*86.555-1212]");
++
++ class#"{{{inmost}}}" { }
++ s = new#"{{{inmost}}}"().getClass().getName();
++ if (!s.endsWith("{{{inmost}}}"))
++ check(24, s, "should end with \"{{{inmost}}}\"");
++
++ s = #"Yog-Shoggoth".#"(nameless ululation)";
++ check(25, s, "Tekeli-li!");
++
++ s = #"int".class.getName();
++ check(31, s, QuotedIdent.class.getName()+"$int");
++
++ Class x86 = Class.forName(QuotedIdent.class.getName()+"$*86");
++ if (x86 != #"*86".class)
++ check(32, "reflected "+x86, "static "+#"*86".class);
++
++ s = (String) x86.getDeclaredMethod("555-1212").invoke(#"MAKE-*86"());
++ check(31, s, "[*86.555-1212]");
++
++ System.out.println("OK");
++ }
++}
++
++interface #"Yog-Shoggoth" {
++ final String #"(nameless ululation)" = "Tekeli-li!";
++}
+diff --git a/test/tools/javac/quid/QuotedIdent2.java b/test/tools/javac/quid/QuotedIdent2.java
+new file mode 100644
+--- /dev/null
++++ b/test/tools/javac/quid/QuotedIdent2.java
+@@ -0,0 +1,79 @@
++/*
++ * Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
++ * CA 95054 USA or visit www.sun.com if you need additional information or
++ * have any questions.
++ */
++
++/*
++ * @test
++ * @bug 6746458
++ * @summary Verify correct separate compilation of classes with extended identifiers.
++ * @author jrose
++ *
++ * Standalone testing:
++ * <code>
++ * $ cd $MY_REPO_DIR/langtools
++ * $ (cd make; make)
++ * $ ./dist/bootstrap/bin/javac -d dist test/tools/javac/quid/QuotedIdent.java
++ * $ ./dist/bootstrap/bin/javac -d dist -cp dist test/tools/javac/quid/QuotedIdent2.java
++ * $ java -version # should print 1.6 or later
++ * $ java -cp dist QuotedIdent2
++ * </code>
++ *
++ * @run main QuotedIdent2
++ */
++
++package quid;
++
++import quid.QuotedIdent.*;
++import quid.QuotedIdent.#"*86";
++import static quid.QuotedIdent.#"MAKE-*86";
++
++public class QuotedIdent2 {
++ static void check(int testid, String have, String expect)
++ throws RuntimeException {
++ QuotedIdent.check(testid, have, expect);
++ }
++
++ public static void main(String[] args) throws Exception {
++ String s;
++
++ s = #"int".valueOf(123).toString();
++ check(22, s, "123");
++
++ s = #"MAKE-*86"().#"555-1212"();
++ check(23, s, "[*86.555-1212]");
++
++ s = #"Yog-Shoggoth".#"(nameless ululation)";
++ check(25, s, "Tekeli-li!");
++
++ s = QuotedIdent.#"int".class.getName();
++ check(31, s, QuotedIdent.class.getName()+"$int");
++
++ Class x86 = Class.forName(QuotedIdent.class.getName()+"$*86");
++ if (x86 != #"*86".class)
++ check(32, "reflected "+x86, "static "+#"*86".class);
++
++ s = (String) x86.getDeclaredMethod("555-1212").invoke(QuotedIdent.#"MAKE-*86"());
++ check(31, s, "[*86.555-1212]");
++
++ System.out.println("OK");
++ }
++}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/nb-javac/series Thu Mar 26 19:55:19 2009 -0500
@@ -0,0 +1,4 @@
+# base = 4d206181439a in http://hg.netbeans.org/main/nb-javac [release65_base]
+quid.patch #-/quid #+4d206181439a #+release65_base
+meth.patch #-/meth #+4d206181439a #+release65_base
+dyncast.patch #-/dyncast #+4d206181439a #+release65_base