6993978: Project Coin: Compiler support of annotation to reduce varargs warnings
authormcimadamore
Mon, 13 Dec 2010 15:11:00 -0800
changeset 7643 a067a0cda531
parent 7642 9ca5d29b34f7
child 7644 00e80d00deea
child 7839 a1ca72d05b20
6993978: Project Coin: Compiler support of annotation to reduce varargs warnings Reviewed-by: jjg, darcy
langtools/src/share/classes/com/sun/tools/javac/code/Source.java
langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java
langtools/src/share/classes/com/sun/tools/javac/code/Type.java
langtools/src/share/classes/com/sun/tools/javac/code/Types.java
langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java
langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java
langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties
langtools/src/share/classes/com/sun/tools/javac/util/List.java
langtools/src/share/classes/com/sun/tools/javac/util/Warner.java
langtools/test/tools/javac/diags/CheckExamples.java
langtools/test/tools/javac/diags/RunExamples.java
langtools/test/tools/javac/diags/examples/TrustMeOnNonVarargsMeth.java
langtools/test/tools/javac/diags/examples/TrustMeOnReifiableVarargsParam.java
langtools/test/tools/javac/diags/examples/TrustMeOnVirtualMethod.java
langtools/test/tools/javac/diags/examples/UncheckedGenericArrayCreation.java
langtools/test/tools/javac/diags/examples/UnsafeUseOfVarargsParam.java
langtools/test/tools/javac/diags/examples/VarargsFilename.java
langtools/test/tools/javac/diags/examples/VarargsFilenameAdditional.java
langtools/test/tools/javac/diags/examples/VarargsNonReifiableType.java
langtools/test/tools/javac/diags/examples/VarargsPlural/VarargsFilename.java
langtools/test/tools/javac/diags/examples/VarargsPlural/VarargsPlural.java
langtools/test/tools/javac/diags/examples/VarargsPluralAdditional/VarargsFilename.java
langtools/test/tools/javac/diags/examples/VarargsPluralAdditional/VarargsPlural.java
langtools/test/tools/javac/diags/examples/VarargsPluralAdditional/VarargsPluralAdditional.java
langtools/test/tools/javac/varargs/6730476/T6730476a.java
langtools/test/tools/javac/varargs/6806876/T6806876.out
langtools/test/tools/javac/varargs/6993978/T6993978neg.java
langtools/test/tools/javac/varargs/6993978/T6993978neg.out
langtools/test/tools/javac/varargs/warning/Warn4.java
langtools/test/tools/javac/varargs/warning/Warn5.java
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java	Mon Dec 13 15:11:00 2010 -0800
@@ -177,6 +177,9 @@
     public boolean allowStringsInSwitch() {
         return compareTo(JDK1_7) >= 0;
     }
+    public boolean allowSimplifiedVarargs() {
+        return compareTo(JDK1_7) >= 0;
+    }
     public static SourceVersion toSourceVersion(Source source) {
         switch(source) {
         case JDK1_2:
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java	Mon Dec 13 15:11:00 2010 -0800
@@ -154,6 +154,7 @@
     public final Type proprietaryType;
     public final Type systemType;
     public final Type autoCloseableType;
+    public final Type trustMeType;
 
     /** The symbol representing the length field of an array.
      */
@@ -461,6 +462,7 @@
                              new MethodType(List.<Type>nil(), voidType,
                                             List.of(exceptionType), methodClass),
                              autoCloseableType.tsym);
+        trustMeType = enterClass("java.lang.SafeVarargs");
 
         synthesizeEmptyInterfaceIfMissing(cloneableType);
         synthesizeEmptyInterfaceIfMissing(serializableType);
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java	Mon Dec 13 15:11:00 2010 -0800
@@ -754,6 +754,10 @@
             return (ARRAY << 5) + elemtype.hashCode();
         }
 
+        public boolean isVarargs() {
+            return false;
+        }
+
         public List<Type> allparams() { return elemtype.allparams(); }
 
         public boolean isErroneous() {
@@ -768,6 +772,15 @@
             return elemtype.isRaw();
         }
 
+        public ArrayType makeVarargs() {
+            return new ArrayType(elemtype, tsym) {
+                @Override
+                public boolean isVarargs() {
+                    return true;
+                }
+            };
+        }
+
         public Type map(Mapping f) {
             Type elemtype1 = f.apply(elemtype);
             if (elemtype1 == elemtype) return this;
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java	Mon Dec 13 15:11:00 2010 -0800
@@ -33,6 +33,7 @@
 
 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.comp.Check;
 
 import static com.sun.tools.javac.code.Type.*;
@@ -272,13 +273,36 @@
     public boolean isConvertible(Type t, Type s, Warner warn) {
         boolean tPrimitive = t.isPrimitive();
         boolean sPrimitive = s.isPrimitive();
-        if (tPrimitive == sPrimitive)
+        if (tPrimitive == sPrimitive) {
+            checkUnsafeVarargsConversion(t, s, warn);
             return isSubtypeUnchecked(t, s, warn);
+        }
         if (!allowBoxing) return false;
         return tPrimitive
             ? isSubtype(boxedClass(t).type, s)
             : isSubtype(unboxedType(t), s);
     }
+    //where
+    private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) {
+        if (t.tag != ARRAY || isReifiable(t)) return;
+        ArrayType from = (ArrayType)t;
+        boolean shouldWarn = false;
+        switch (s.tag) {
+            case ARRAY:
+                ArrayType to = (ArrayType)s;
+                shouldWarn = from.isVarargs() &&
+                        !to.isVarargs() &&
+                        !isReifiable(from);
+                break;
+            case CLASS:
+                shouldWarn = from.isVarargs() &&
+                        isSubtype(from, s);
+                break;
+        }
+        if (shouldWarn) {
+            warn.warn(LintCategory.VARARGS);
+        }
+    }
 
     /**
      * Is t a subtype of or convertiable via boxing/unboxing
@@ -301,9 +325,18 @@
      */
     public boolean isSubtypeUnchecked(Type t, Type s, Warner warn) {
         if (t.tag == ARRAY && s.tag == ARRAY) {
-            return (((ArrayType)t).elemtype.tag <= lastBaseTag)
-                ? isSameType(elemtype(t), elemtype(s))
-                : isSubtypeUnchecked(elemtype(t), elemtype(s), warn);
+            if (((ArrayType)t).elemtype.tag <= lastBaseTag) {
+                return isSameType(elemtype(t), elemtype(s));
+            } else {
+                ArrayType from = (ArrayType)t;
+                ArrayType to = (ArrayType)s;
+                if (from.isVarargs() &&
+                        !to.isVarargs() &&
+                        !isReifiable(from)) {
+                    warn.warn(LintCategory.VARARGS);
+                }
+                return isSubtypeUnchecked(elemtype(t), elemtype(s), warn);
+            }
         } else if (isSubtype(t, s)) {
             return true;
         }
@@ -319,9 +352,9 @@
             Type t2 = asSuper(t, s.tsym);
             if (t2 != null && t2.isRaw()) {
                 if (isReifiable(s))
-                    warn.silentUnchecked();
+                    warn.silentWarn(LintCategory.UNCHECKED);
                 else
-                    warn.warnUnchecked();
+                    warn.warn(LintCategory.UNCHECKED);
                 return true;
             }
         }
@@ -922,6 +955,7 @@
         if (warn != warnStack.head) {
             try {
                 warnStack = warnStack.prepend(warn);
+                checkUnsafeVarargsConversion(t, s, warn);
                 return isCastable.visit(t,s);
             } finally {
                 warnStack = warnStack.tail;
@@ -964,7 +998,7 @@
 
                 if (s.tag == TYPEVAR) {
                     if (isCastable(t, s.getUpperBound(), Warner.noWarnings)) {
-                        warnStack.head.warnUnchecked();
+                        warnStack.head.warn(LintCategory.UNCHECKED);
                         return true;
                     } else {
                         return false;
@@ -980,8 +1014,8 @@
                         if (!visit(intf, s))
                             return false;
                     }
-                    if (warnStack.head.unchecked == true)
-                        oldWarner.warnUnchecked();
+                    if (warnStack.head.hasLint(LintCategory.UNCHECKED))
+                        oldWarner.warn(LintCategory.UNCHECKED);
                     return true;
                 }
 
@@ -996,13 +1030,13 @@
                         || isSubtype(erasure(s), erasure(t))) {
                         if (!upcast && s.tag == ARRAY) {
                             if (!isReifiable(s))
-                                warnStack.head.warnUnchecked();
+                                warnStack.head.warn(LintCategory.UNCHECKED);
                             return true;
                         } else if (s.isRaw()) {
                             return true;
                         } else if (t.isRaw()) {
                             if (!isUnbounded(s))
-                                warnStack.head.warnUnchecked();
+                                warnStack.head.warn(LintCategory.UNCHECKED);
                             return true;
                         }
                         // Assume |a| <: |b|
@@ -1035,7 +1069,7 @@
                                 && !disjointTypes(aLow.allparams(), lowSub.allparams())) {
                                 if (upcast ? giveWarning(a, b) :
                                     giveWarning(b, a))
-                                    warnStack.head.warnUnchecked();
+                                    warnStack.head.warn(LintCategory.UNCHECKED);
                                 return true;
                             }
                         }
@@ -1072,7 +1106,7 @@
                     return true;
                 case TYPEVAR:
                     if (isCastable(s, t, Warner.noWarnings)) {
-                        warnStack.head.warnUnchecked();
+                        warnStack.head.warn(LintCategory.UNCHECKED);
                         return true;
                     } else {
                         return false;
@@ -1101,7 +1135,7 @@
                     if (isSubtype(t, s)) {
                         return true;
                     } else if (isCastable(t.bound, s, Warner.noWarnings)) {
-                        warnStack.head.warnUnchecked();
+                        warnStack.head.warn(LintCategory.UNCHECKED);
                         return true;
                     } else {
                         return false;
@@ -2906,7 +2940,7 @@
             return true;
         if (!isSubtype(r1.getReturnType(), erasure(r2res)))
             return false;
-        warner.warnUnchecked();
+        warner.warn(LintCategory.UNCHECKED);
         return true;
     }
 
@@ -3122,7 +3156,7 @@
             commonSupers = commonSupers.tail;
         }
         if (giveWarning && !isReifiable(reverse ? from : to))
-            warn.warnUnchecked();
+            warn.warn(LintCategory.UNCHECKED);
         if (!source.allowCovariantReturns())
             // reject if there is a common method signature with
             // incompatible return types.
@@ -3156,7 +3190,7 @@
             chk.checkCompatibleAbstracts(warn.pos(), from, to);
         if (!isReifiable(target) &&
             (reverse ? giveWarning(t2, t1) : giveWarning(t1, t2)))
-            warn.warnUnchecked();
+            warn.warn(LintCategory.UNCHECKED);
         return true;
     }
 
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Dec 13 15:11:00 2010 -0800
@@ -38,6 +38,7 @@
 import com.sun.tools.javac.util.List;
 
 import com.sun.tools.javac.jvm.Target;
+import com.sun.tools.javac.code.Lint.LintCategory;
 import com.sun.tools.javac.code.Symbol.*;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.code.Type.*;
@@ -669,6 +670,7 @@
 
         Lint lint = env.info.lint.augment(m.attributes_field, m.flags());
         Lint prevLint = chk.setLint(lint);
+        MethodSymbol prevMethod = chk.setMethod(m);
         try {
             chk.checkDeprecatedAnnotation(tree.pos(), m);
 
@@ -700,7 +702,7 @@
                 attribStat(l.head, localEnv);
             }
 
-            chk.checkVarargMethodDecl(tree);
+            chk.checkVarargsMethodDecl(localEnv, tree);
 
             // Check that type parameters are well-formed.
             chk.validate(tree.typarams, localEnv);
@@ -789,6 +791,7 @@
         }
         finally {
             chk.setLint(prevLint);
+            chk.setMethod(prevMethod);
         }
     }
 
@@ -2272,8 +2275,8 @@
                 ((VarSymbol)sitesym).isResourceVariable() &&
                 sym.kind == MTH &&
                 sym.overrides(syms.autoCloseableClose, sitesym.type.tsym, types, true) &&
-                env.info.lint.isEnabled(Lint.LintCategory.TRY)) {
-            log.warning(Lint.LintCategory.TRY, tree, "try.explicit.close.call");
+                env.info.lint.isEnabled(LintCategory.TRY)) {
+            log.warning(LintCategory.TRY, tree, "try.explicit.close.call");
         }
 
         // Disallow selecting a type from an expression
@@ -2700,7 +2703,7 @@
         // For methods, we need to compute the instance type by
         // Resolve.instantiate from the symbol's type as well as
         // any type arguments and value arguments.
-        noteWarner.warned = false;
+        noteWarner.clear();
         Type owntype = rs.instantiate(env,
                                       site,
                                       sym,
@@ -2709,7 +2712,7 @@
                                       true,
                                       useVarargs,
                                       noteWarner);
-        boolean warned = noteWarner.warned;
+        boolean warned = noteWarner.hasNonSilentLint(LintCategory.UNCHECKED);
 
         // If this fails, something went wrong; we should not have
         // found the identifier in the first place.
@@ -2734,7 +2737,7 @@
                 JCTree arg = args.head;
                 Warner warn = chk.convertWarner(arg.pos(), arg.type, formals.head);
                 assertConvertible(arg, arg.type, formals.head, warn);
-                warned |= warn.warned;
+                warned |= warn.hasNonSilentLint(LintCategory.UNCHECKED);
                 args = args.tail;
                 formals = formals.tail;
             }
@@ -2744,7 +2747,7 @@
                     JCTree arg = args.head;
                     Warner warn = chk.convertWarner(arg.pos(), arg.type, varArg);
                     assertConvertible(arg, arg.type, varArg, warn);
-                    warned |= warn.warned;
+                    warned |= warn.hasNonSilentLint(LintCategory.UNCHECKED);
                     args = args.tail;
                 }
             } else if ((sym.flags() & VARARGS) != 0 && allowVarargs) {
@@ -2776,7 +2779,7 @@
                 JCTree tree = env.tree;
                 Type argtype = owntype.getParameterTypes().last();
                 if (owntype.getReturnType().tag != FORALL || warned) {
-                    chk.checkVararg(env.tree.pos(), owntype.getParameterTypes(), sym, env);
+                    chk.checkVararg(env.tree.pos(), owntype.getParameterTypes(), sym);
                 }
                 Type elemtype = types.elemtype(argtype);
                 switch (tree.getTag()) {
@@ -3175,7 +3178,7 @@
         chk.checkNonCyclicElements(tree);
 
         // Check for proper use of serialVersionUID
-        if (env.info.lint.isEnabled(Lint.LintCategory.SERIAL) &&
+        if (env.info.lint.isEnabled(LintCategory.SERIAL) &&
             isSerializable(c) &&
             (c.flags() & Flags.ENUM) == 0 &&
             (c.flags() & ABSTRACT) == 0) {
@@ -3204,7 +3207,7 @@
             Scope.Entry e = c.members().lookup(names.serialVersionUID);
             while (e.scope != null && e.sym.kind != VAR) e = e.next();
             if (e.scope == null) {
-                log.warning(Lint.LintCategory.SERIAL,
+                log.warning(LintCategory.SERIAL,
                         tree.pos(), "missing.SVUID", c);
                 return;
             }
@@ -3213,17 +3216,17 @@
             VarSymbol svuid = (VarSymbol)e.sym;
             if ((svuid.flags() & (STATIC | FINAL)) !=
                 (STATIC | FINAL))
-                log.warning(Lint.LintCategory.SERIAL,
+                log.warning(LintCategory.SERIAL,
                         TreeInfo.diagnosticPositionFor(svuid, tree), "improper.SVUID", c);
 
             // check that it is long
             else if (svuid.type.tag != TypeTags.LONG)
-                log.warning(Lint.LintCategory.SERIAL,
+                log.warning(LintCategory.SERIAL,
                         TreeInfo.diagnosticPositionFor(svuid, tree), "long.SVUID", c);
 
             // check constant
             else if (svuid.getConstValue() == null)
-                log.warning(Lint.LintCategory.SERIAL,
+                log.warning(LintCategory.SERIAL,
                         TreeInfo.diagnosticPositionFor(svuid, tree), "constant.SVUID", c);
         }
 
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Dec 13 15:11:00 2010 -0800
@@ -75,6 +75,10 @@
     // visits all the various parts of the trees during attribution.
     private Lint lint;
 
+    // The method being analyzed in Attr - it is set/reset as needed by
+    // Attr as it visits new method declarations.
+    private MethodSymbol method;
+
     public static Check instance(Context context) {
         Check instance = context.get(checkKey);
         if (instance == null)
@@ -100,6 +104,7 @@
         allowGenerics = source.allowGenerics();
         allowAnnotations = source.allowAnnotations();
         allowCovariantReturns = source.allowCovariantReturns();
+        allowSimplifiedVarargs = source.allowSimplifiedVarargs();
         complexInference = options.isSet(COMPLEXINFERENCE);
         skipAnnotations = options.isSet("skipAnnotations");
         warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
@@ -136,6 +141,10 @@
      */
     boolean allowCovariantReturns;
 
+    /** Switch: simplified varargs enabled?
+     */
+    boolean allowSimplifiedVarargs;
+
     /** Switch: -complexinference option set?
      */
     boolean complexInference;
@@ -175,6 +184,12 @@
         return prev;
     }
 
+    MethodSymbol setMethod(MethodSymbol newMethod) {
+        MethodSymbol prev = method;
+        method = newMethod;
+        return prev;
+    }
+
     /** Warn about deprecated symbol.
      *  @param pos        Position to be used for error reporting.
      *  @param sym        The deprecated symbol.
@@ -197,9 +212,9 @@
      *  @param pos        Position to be used for error reporting.
      *  @param sym        The deprecated symbol.
      */
-    void warnUnsafeVararg(DiagnosticPosition pos, Type elemType) {
-        if (!lint.isSuppressed(LintCategory.VARARGS))
-            unsafeVarargsHandler.report(pos, "varargs.non.reifiable.type", elemType);
+    void warnUnsafeVararg(DiagnosticPosition pos, String key, Object... args) {
+        if (lint.isEnabled(LintCategory.VARARGS) && allowSimplifiedVarargs)
+            log.warning(LintCategory.VARARGS, pos, key, args);
     }
 
     /** Warn about using proprietary API.
@@ -222,7 +237,6 @@
     public void reportDeferredDiagnostics() {
         deprecationHandler.reportDeferredDiagnostic();
         uncheckedHandler.reportDeferredDiagnostic();
-        unsafeVarargsHandler.reportDeferredDiagnostic();
         sunApiHandler.reportDeferredDiagnostic();
     }
 
@@ -705,29 +719,56 @@
         }
     }
 
-    void checkVarargMethodDecl(JCMethodDecl tree) {
+    void checkVarargsMethodDecl(Env<AttrContext> env, JCMethodDecl tree) {
         MethodSymbol m = tree.sym;
-        //check the element type of the vararg
+        if (!allowSimplifiedVarargs) return;
+        boolean hasTrustMeAnno = m.attribute(syms.trustMeType.tsym) != null;
+        Type varargElemType = null;
         if (m.isVarArgs()) {
-            Type varargElemType = types.elemtype(tree.params.last().type);
-            if (!types.isReifiable(varargElemType)) {
-                warnUnsafeVararg(tree.params.head.pos(), varargElemType);
+            varargElemType = types.elemtype(tree.params.last().type);
+        }
+        if (hasTrustMeAnno && !isTrustMeAllowedOnMethod(m)) {
+            if (varargElemType != null) {
+                log.error(tree,
+                        "varargs.invalid.trustme.anno",
+                        syms.trustMeType.tsym,
+                        diags.fragment("varargs.trustme.on.virtual.varargs", m));
+            } else {
+                log.error(tree,
+                            "varargs.invalid.trustme.anno",
+                            syms.trustMeType.tsym,
+                            diags.fragment("varargs.trustme.on.non.varargs.meth", m));
             }
+        } else if (hasTrustMeAnno && varargElemType != null &&
+                            types.isReifiable(varargElemType)) {
+            warnUnsafeVararg(tree,
+                            "varargs.redundant.trustme.anno",
+                            syms.trustMeType.tsym,
+                            diags.fragment("varargs.trustme.on.reifiable.varargs", varargElemType));
+        }
+        else if (!hasTrustMeAnno && varargElemType != null &&
+                !types.isReifiable(varargElemType)) {
+            warnUnchecked(tree.params.head.pos(), "unchecked.varargs.non.reifiable.type", varargElemType);
         }
     }
+    //where
+        private boolean isTrustMeAllowedOnMethod(Symbol s) {
+            return (s.flags() & VARARGS) != 0 &&
+                (s.isConstructor() ||
+                    (s.flags() & (STATIC | FINAL)) != 0);
+        }
 
     /**
      * Check that vararg method call is sound
      * @param pos Position to be used for error reporting.
      * @param argtypes Actual arguments supplied to vararg method.
      */
-    void checkVararg(DiagnosticPosition pos, List<Type> argtypes, Symbol msym, Env<AttrContext> env) {
-        Env<AttrContext> calleeLintEnv = env;
-        while (calleeLintEnv.info.lint == null)
-            calleeLintEnv = calleeLintEnv.next;
-        Lint calleeLint = calleeLintEnv.info.lint.augment(msym.attributes_field, msym.flags());
+    void checkVararg(DiagnosticPosition pos, List<Type> argtypes, Symbol msym) {
         Type argtype = argtypes.last();
-        if (!types.isReifiable(argtype) && !calleeLint.isSuppressed(Lint.LintCategory.VARARGS)) {
+        if (!types.isReifiable(argtype) &&
+                (!allowSimplifiedVarargs ||
+                msym.attribute(syms.trustMeType.tsym) == null ||
+                !isTrustMeAllowedOnMethod(msym))) {
             warnUnchecked(pos,
                               "unchecked.generic.array.creation",
                               argtype);
@@ -1075,12 +1116,12 @@
         }
 
         void checkRaw(JCTree tree, Env<AttrContext> env) {
-            if (lint.isEnabled(Lint.LintCategory.RAW) &&
+            if (lint.isEnabled(LintCategory.RAW) &&
                 tree.type.tag == CLASS &&
                 !TreeInfo.isDiamond(tree) &&
                 !env.enclClass.name.isEmpty() &&  //anonymous or intersection
                 tree.type.isRaw()) {
-                log.warning(Lint.LintCategory.RAW,
+                log.warning(LintCategory.RAW,
                         tree.pos(), "raw.class.use", tree.type, tree.type.tsym.type);
             }
         }
@@ -1347,7 +1388,7 @@
         Type mtres = mt.getReturnType();
         Type otres = types.subst(ot.getReturnType(), otvars, mtvars);
 
-        overrideWarner.warned = false;
+        overrideWarner.clear();
         boolean resultTypesOK =
             types.returnTypeSubstitutable(mt, ot, otres, overrideWarner);
         if (!resultTypesOK) {
@@ -1362,7 +1403,7 @@
                           mtres, otres);
                 return;
             }
-        } else if (overrideWarner.warned) {
+        } else if (overrideWarner.hasNonSilentLint(LintCategory.UNCHECKED)) {
             warnUnchecked(TreeInfo.diagnosticPositionFor(m, tree),
                     "override.unchecked.ret",
                     uncheckedOverrides(m, other),
@@ -1391,7 +1432,7 @@
 
         // Optional warning if varargs don't agree
         if ((((m.flags() ^ other.flags()) & Flags.VARARGS) != 0)
-            && lint.isEnabled(Lint.LintCategory.OVERRIDES)) {
+            && lint.isEnabled(LintCategory.OVERRIDES)) {
             log.warning(TreeInfo.diagnosticPositionFor(m, tree),
                         ((m.flags() & Flags.VARARGS) != 0)
                         ? "override.varargs.missing"
@@ -2380,11 +2421,11 @@
 
     void checkDeprecatedAnnotation(DiagnosticPosition pos, Symbol s) {
         if (allowAnnotations &&
-            lint.isEnabled(Lint.LintCategory.DEP_ANN) &&
+            lint.isEnabled(LintCategory.DEP_ANN) &&
             (s.flags() & DEPRECATED) != 0 &&
             !syms.deprecatedType.isErroneous() &&
             s.attribute(syms.deprecatedType.tsym) == null) {
-            log.warning(Lint.LintCategory.DEP_ANN,
+            log.warning(LintCategory.DEP_ANN,
                     pos, "missing.deprecated.annotation");
         }
     }
@@ -2530,13 +2571,13 @@
      */
     void checkDivZero(DiagnosticPosition pos, Symbol operator, Type operand) {
         if (operand.constValue() != null
-            && lint.isEnabled(Lint.LintCategory.DIVZERO)
+            && lint.isEnabled(LintCategory.DIVZERO)
             && operand.tag <= LONG
             && ((Number) (operand.constValue())).longValue() == 0) {
             int opc = ((OperatorSymbol)operator).opcode;
             if (opc == ByteCodes.idiv || opc == ByteCodes.imod
                 || opc == ByteCodes.ldiv || opc == ByteCodes.lmod) {
-                log.warning(Lint.LintCategory.DIVZERO, pos, "div.zero");
+                log.warning(LintCategory.DIVZERO, pos, "div.zero");
             }
         }
     }
@@ -2545,8 +2586,8 @@
      * Check for empty statements after if
      */
     void checkEmptyIf(JCIf tree) {
-        if (tree.thenpart.getTag() == JCTree.SKIP && tree.elsepart == null && lint.isEnabled(Lint.LintCategory.EMPTY))
-            log.warning(Lint.LintCategory.EMPTY, tree.thenpart.pos(), "empty.if");
+        if (tree.thenpart.getTag() == JCTree.SKIP && tree.elsepart == null && lint.isEnabled(LintCategory.EMPTY))
+            log.warning(LintCategory.EMPTY, tree.thenpart.pos(), "empty.if");
     }
 
     /** Check that symbol is unique in given scope.
@@ -2654,23 +2695,36 @@
         }
 
     private class ConversionWarner extends Warner {
-        final String key;
+        final String uncheckedKey;
         final Type found;
         final Type expected;
-        public ConversionWarner(DiagnosticPosition pos, String key, Type found, Type expected) {
+        public ConversionWarner(DiagnosticPosition pos, String uncheckedKey, Type found, Type expected) {
             super(pos);
-            this.key = key;
+            this.uncheckedKey = uncheckedKey;
             this.found = found;
             this.expected = expected;
         }
 
         @Override
-        public void warnUnchecked() {
+        public void warn(LintCategory lint) {
             boolean warned = this.warned;
-            super.warnUnchecked();
+            super.warn(lint);
             if (warned) return; // suppress redundant diagnostics
-            Object problem = diags.fragment(key);
-            Check.this.warnUnchecked(pos(), "prob.found.req", problem, found, expected);
+            switch (lint) {
+                case UNCHECKED:
+                    Check.this.warnUnchecked(pos(), "prob.found.req", diags.fragment(uncheckedKey), found, expected);
+                    break;
+                case VARARGS:
+                    if (method != null &&
+                            method.attribute(syms.trustMeType.tsym) != null &&
+                            isTrustMeAllowedOnMethod(method) &&
+                            !types.isReifiable(method.type.getParameterTypes().last())) {
+                        Check.this.warnUnsafeVararg(pos(), "varargs.unsafe.use.varargs.param", method.params.last());
+                    }
+                    break;
+                default:
+                    throw new AssertionError("Unexpected lint: " + lint);
+            }
         }
     }
 
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Dec 13 15:11:00 2010 -0800
@@ -481,7 +481,7 @@
                     checkWithinBounds(all_tvars,
                            types.subst(inferredTypes, tvars, inferred), warn);
                     if (useVarargs) {
-                        chk.checkVararg(env.tree.pos(), formals, msym, env);
+                        chk.checkVararg(env.tree.pos(), formals, msym);
                     }
                     return super.inst(inferred, types);
             }};
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Mon Dec 13 15:11:00 2010 -0800
@@ -77,6 +77,7 @@
     private final Target target;
 
     private final boolean skipAnnotations;
+    private final boolean allowSimplifiedVarargs;
 
     public static MemberEnter instance(Context context) {
         MemberEnter instance = context.get(memberEnterKey);
@@ -103,6 +104,8 @@
         target = Target.instance(context);
         Options options = Options.instance(context);
         skipAnnotations = options.isSet("skipAnnotations");
+        Source source = Source.instance(context);
+        allowSimplifiedVarargs = source.allowSimplifiedVarargs();
     }
 
     /** A queue for classes whose members still need to be entered into the
@@ -617,6 +620,14 @@
             localEnv.info.staticLevel++;
         }
         attr.attribType(tree.vartype, localEnv);
+        if ((tree.mods.flags & VARARGS) != 0) {
+            //if we are entering a varargs parameter, we need to replace its type
+            //(a plain array type) with the more precise VarargsType --- we need
+            //to do it this way because varargs is represented in the tree as a modifier
+            //on the parameter declaration, and not as a distinct type of array node.
+            ArrayType atype = (ArrayType)tree.vartype.type;
+            tree.vartype.type = atype.makeVarargs();
+        }
         Scope enclScope = enter.enterScope(env);
         VarSymbol v =
             new VarSymbol(0, tree.name, tree.vartype.type, enclScope.owner);
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Dec 13 15:11:00 2010 -0800
@@ -815,13 +815,13 @@
     }
     //where
     private boolean signatureMoreSpecific(Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean allowBoxing, boolean useVarargs) {
+        noteWarner.clear();
         Type mtype1 = types.memberType(site, adjustVarargs(m1, m2, useVarargs));
-        noteWarner.unchecked = false;
         return (instantiate(env, site, adjustVarargs(m2, m1, useVarargs), types.lowerBoundArgtypes(mtype1), null,
                              allowBoxing, false, noteWarner) != null ||
                  useVarargs && instantiate(env, site, adjustVarargs(m2, m1, useVarargs), types.lowerBoundArgtypes(mtype1), null,
                                            allowBoxing, true, noteWarner) != null) &&
-                !noteWarner.unchecked;
+                !noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
     }
     //where
     private Symbol adjustVarargs(Symbol to, Symbol from, boolean useVarargs) {
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Dec 13 15:11:00 2010 -0800
@@ -105,10 +105,15 @@
      */
     boolean allowAnnotations;
 
-    /** Lint option: warn about classfile issues
+    /** Switch: allow simplified varargs.
+     */
+    boolean allowSimplifiedVarargs;
+
+   /** Lint option: warn about classfile issues
      */
     boolean lintClassfile;
 
+
     /** Switch: preserve parameter names from the variable table.
      */
     public boolean saveParameterNames;
@@ -279,6 +284,7 @@
         allowGenerics    = source.allowGenerics();
         allowVarargs     = source.allowVarargs();
         allowAnnotations = source.allowAnnotations();
+        allowSimplifiedVarargs = source.allowSimplifiedVarargs();
         saveParameterNames = options.isSet("save-parameter-names");
         cacheCompletionFailure = options.isUnset("dev");
         preferSource = "source".equals(options.get("-Xprefer"));
@@ -1883,7 +1889,7 @@
             // instance, however, there is no reliable way to tell so
             // we never strip this$n
             if (!currentOwner.name.isEmpty())
-                type = new MethodType(type.getParameterTypes().tail,
+                type = new MethodType(adjustMethodParams(flags, type.getParameterTypes()),
                                       type.getReturnType(),
                                       type.getThrownTypes(),
                                       syms.methodClass);
@@ -1903,6 +1909,21 @@
         return m;
     }
 
+    private List<Type> adjustMethodParams(long flags, List<Type> args) {
+        boolean isVarargs = (flags & VARARGS) != 0;
+        if (isVarargs) {
+            Type varargsElem = args.last();
+            ListBuffer<Type> adjustedArgs = ListBuffer.lb();
+            for (Type t : args) {
+                adjustedArgs.append(t != varargsElem ?
+                    t :
+                    ((ArrayType)t).makeVarargs());
+            }
+            args = adjustedArgs.toList();
+        }
+        return args.tail;
+    }
+
     /**
      * Init the parameter names array.
      * Parameter names are currently inferred from the names in the
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Dec 13 15:11:00 2010 -0800
@@ -516,6 +516,15 @@
 compiler.err.var.might.be.assigned.in.loop=\
     variable {0} might be assigned in loop
 
+compiler.err.varargs.invalid.trustme.anno=\
+    Invalid {0} annotation. {1}
+compiler.misc.varargs.trustme.on.reifiable.varargs=\
+    Varargs element type {0} is reifiable.
+compiler.misc.varargs.trustme.on.non.varargs.meth=\
+    Method {0} is not a varargs method.
+compiler.misc.varargs.trustme.on.virtual.varargs=\
+    Instance method {0} is not final.
+
 # In the following string, {1} will always be the detail message from
 # java.io.IOException.
 compiler.err.class.cant.write=\
@@ -600,20 +609,6 @@
 compiler.note.unchecked.plural.additional=\
     Some input files additionally use unchecked or unsafe operations.
 
-compiler.note.varargs.filename=\
-    {0} declares unsafe vararg methods.
-compiler.note.varargs.plural=\
-    Some input files declare unsafe vararg methods.
-# The following string may appear after one of the above unsafe varargs
-# messages.
-compiler.note.varargs.recompile=\
-    Recompile with -Xlint:varargs for details.
-
-compiler.note.varargs.filename.additional=\
-    {0} declares additional unsafe vararg methods.
-compiler.note.varargs.plural.additional=\
-    Some input files additionally declares unsafe vararg methods.
-
 compiler.note.sunapi.filename=\
     {0} uses internal proprietary API that may be removed in a future release.
 compiler.note.sunapi.plural=\
@@ -841,9 +836,12 @@
 compiler.warn.unchecked.generic.array.creation=\
     unchecked generic array creation for varargs parameter of type {0}
 
-compiler.warn.varargs.non.reifiable.type=\
+compiler.warn.unchecked.varargs.non.reifiable.type=\
     Possible heap pollution from parameterized vararg type {0}
 
+compiler.warn.varargs.unsafe.use.varargs.param=\
+    Varargs method could cause heap pollution from non-reifiable varargs parameter {0}
+
 compiler.warn.missing.deprecated.annotation=\
     deprecated item is not annotated with @Deprecated
 
@@ -876,6 +874,9 @@
     explicit: {0}\n\
     inferred: {1}
 
+compiler.warn.varargs.redundant.trustme.anno=\
+    Redundant {0} annotation. {1}
+
 #####
 
 ## The following are tokens which are non-terminals in the language. They should
--- a/langtools/src/share/classes/com/sun/tools/javac/util/List.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/List.java	Mon Dec 13 15:11:00 2010 -0800
@@ -103,7 +103,7 @@
 
     /** Construct a list consisting of given elements.
      */
-    @SuppressWarnings("varargs")
+    @SuppressWarnings({"varargs", "unchecked"})
     public static <A> List<A> of(A x1, A x2, A x3, A... rest) {
         return new List<A>(x1, new List<A>(x2, new List<A>(x3, from(rest))));
     }
--- a/langtools/src/share/classes/com/sun/tools/javac/util/Warner.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/src/share/classes/com/sun/tools/javac/util/Warner.java	Mon Dec 13 15:11:00 2010 -0800
@@ -25,7 +25,9 @@
 
 package com.sun.tools.javac.util;
 
+import com.sun.tools.javac.code.Lint.LintCategory;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import java.util.EnumSet;
 
 /**
  * An interface to support optional warnings, needed for support of
@@ -40,25 +42,45 @@
     public static final Warner noWarnings = new Warner();
 
     private DiagnosticPosition pos = null;
-    public boolean warned = false;
-    public boolean unchecked = false;
+    protected boolean warned = false;
+    private EnumSet<LintCategory> nonSilentLintSet = EnumSet.noneOf(LintCategory.class);
+    private EnumSet<LintCategory> silentLintSet = EnumSet.noneOf(LintCategory.class);
 
     public DiagnosticPosition pos() {
         return pos;
     }
 
-    public void warnUnchecked() {
-        warned = true;
-        unchecked = true;
+    public void warn(LintCategory lint) {
+        nonSilentLintSet.add(lint);
     }
-    public void silentUnchecked() {
-        unchecked = true;
+
+    public void silentWarn(LintCategory lint) {
+        silentLintSet.add(lint);
     }
 
     public Warner(DiagnosticPosition pos) {
         this.pos = pos;
     }
 
+    public boolean hasSilentLint(LintCategory lint) {
+        return silentLintSet.contains(lint);
+    }
+
+    public boolean hasNonSilentLint(LintCategory lint) {
+        return nonSilentLintSet.contains(lint);
+    }
+
+    public boolean hasLint(LintCategory lint) {
+        return hasSilentLint(lint) ||
+                hasNonSilentLint(lint);
+    }
+
+    public void clear() {
+        nonSilentLintSet.clear();
+        silentLintSet.clear();
+        this.warned = false;
+    }
+
     public Warner() {
         this(null);
     }
--- a/langtools/test/tools/javac/diags/CheckExamples.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/test/tools/javac/diags/CheckExamples.java	Mon Dec 13 15:11:00 2010 -0800
@@ -129,12 +129,17 @@
         File testSrc = new File(System.getProperty("test.src"));
         File examples = new File(testSrc, "examples");
         for (File f: examples.listFiles()) {
-            if (f.isDirectory() || f.isFile() && f.getName().endsWith(".java"))
+            if (isValidExample(f))
                 results.add(new Example(f));
         }
         return results;
     }
 
+    boolean isValidExample(File f) {
+        return (f.isDirectory() && f.list().length > 0) ||
+                (f.isFile() && f.getName().endsWith(".java"));
+    }
+
     /**
      * Get the contents of the "not-yet" list.
      */
--- a/langtools/test/tools/javac/diags/RunExamples.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/test/tools/javac/diags/RunExamples.java	Mon Dec 13 15:11:00 2010 -0800
@@ -52,7 +52,7 @@
  */
 public class RunExamples {
     public static void main(String... args) throws Exception {
-        boolean jtreg = (System.getProperty("test.src") != null);
+        jtreg = (System.getProperty("test.src") != null);
         File tmpDir;
         if (jtreg) {
             // use standard jtreg scratch directory: the current directory
@@ -166,12 +166,17 @@
     Set<Example> getExamples(File examplesDir) {
         Set<Example> results = new TreeSet<Example>();
         for (File f: examplesDir.listFiles()) {
-            if (f.isDirectory() || f.isFile() && f.getName().endsWith(".java"))
+            if (isValidExample(f))
                 results.add(new Example(f));
         }
         return results;
     }
 
+    boolean isValidExample(File f) {
+        return (f.isDirectory() && (!jtreg || f.list().length > 0)) ||
+                (f.isFile() && f.getName().endsWith(".java"));
+    }
+
     /**
      * Report an error.
      */
@@ -180,6 +185,8 @@
         errors++;
     }
 
+    static boolean jtreg;
+
     int errors;
 
     /**
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/TrustMeOnNonVarargsMeth.java	Mon Dec 13 15:11:00 2010 -0800
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.err.varargs.invalid.trustme.anno
+// key: compiler.misc.varargs.trustme.on.non.varargs.meth
+// options: -Xlint:varargs
+
+class TrustMeOnNonVarargsMeth {
+    @SafeVarargs static void m(String[] args) { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/TrustMeOnReifiableVarargsParam.java	Mon Dec 13 15:11:00 2010 -0800
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.warn.varargs.redundant.trustme.anno
+// key: compiler.misc.varargs.trustme.on.reifiable.varargs
+// options: -Xlint:varargs
+
+class TrustMeOnReifiableVarargsParam {
+    @SafeVarargs static void m(String... args) { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/TrustMeOnVirtualMethod.java	Mon Dec 13 15:11:00 2010 -0800
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.err.varargs.invalid.trustme.anno
+// key: compiler.misc.varargs.trustme.on.virtual.varargs
+// options: -Xlint:varargs,unchecked
+
+import java.util.List;
+
+class TrustMeOnVirtualMethod {
+    @SafeVarargs void m(List<String>... args) { }
+}
--- a/langtools/test/tools/javac/diags/examples/UncheckedGenericArrayCreation.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/test/tools/javac/diags/examples/UncheckedGenericArrayCreation.java	Mon Dec 13 15:11:00 2010 -0800
@@ -22,10 +22,8 @@
  */
 
 // key: compiler.warn.unchecked.generic.array.creation
-// key: compiler.warn.varargs.non.reifiable.type
-// options: -Xlint:unchecked,varargs
-
-import java.util.*;
+// key: compiler.warn.unchecked.varargs.non.reifiable.type
+// options: -Xlint:unchecked
 
 class UncheckedGenericArrayCreation<T> {
     void m(T t1, T t2, T t3) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/UnsafeUseOfVarargsParam.java	Mon Dec 13 15:11:00 2010 -0800
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.warn.varargs.unsafe.use.varargs.param
+// options: -Xlint:varargs
+
+class UnsafeUseOfVarargsParam {
+    @SafeVarargs static <X> void m(X... x) {
+        Object[] o = x;
+    }
+}
--- a/langtools/test/tools/javac/diags/examples/VarargsFilename.java	Mon Dec 13 14:08:01 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// key: compiler.note.varargs.filename
-// key: compiler.note.varargs.recompile
-
-class VarargsFilename<T> {
-    void m(T... items) { }
-}
--- a/langtools/test/tools/javac/diags/examples/VarargsFilenameAdditional.java	Mon Dec 13 14:08:01 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// key: compiler.note.varargs.filename.additional
-// key: compiler.warn.varargs.non.reifiable.type
-// options: -Xlint:varargs -Xmaxwarns 1
-
-class VarargsFilenameAdditional<T> {
-    void m1(T... items) { }
-    void m2(T... items) { }
-}
--- a/langtools/test/tools/javac/diags/examples/VarargsNonReifiableType.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/test/tools/javac/diags/examples/VarargsNonReifiableType.java	Mon Dec 13 15:11:00 2010 -0800
@@ -21,10 +21,8 @@
  * questions.
  */
 
-// key: compiler.warn.varargs.non.reifiable.type
-// options: -Xlint:varargs
-
-import java.util.*;
+// key: compiler.warn.unchecked.varargs.non.reifiable.type
+// options: -Xlint:unchecked
 
 class VarargsNonReifiableType<T> {
     void m(T... items) {
--- a/langtools/test/tools/javac/diags/examples/VarargsPlural/VarargsFilename.java	Mon Dec 13 14:08:01 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-class VarargsFilename<T> {
-    void m(T... items) { }
-}
--- a/langtools/test/tools/javac/diags/examples/VarargsPlural/VarargsPlural.java	Mon Dec 13 14:08:01 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// key: compiler.note.varargs.plural
-// key: compiler.note.varargs.recompile
-
-class VarargsPlural<T> {
-    void m(T... items) { }
-}
--- a/langtools/test/tools/javac/diags/examples/VarargsPluralAdditional/VarargsFilename.java	Mon Dec 13 14:08:01 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-class VarargsFilename<T> {
-    void m(T... items) { }
-}
--- a/langtools/test/tools/javac/diags/examples/VarargsPluralAdditional/VarargsPlural.java	Mon Dec 13 14:08:01 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,26 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-class VarargsPlural<T> {
-    void m(T... items) { }
-}
--- a/langtools/test/tools/javac/diags/examples/VarargsPluralAdditional/VarargsPluralAdditional.java	Mon Dec 13 14:08:01 2010 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// key: compiler.note.varargs.plural.additional
-// key: compiler.warn.varargs.non.reifiable.type
-// options: -Xlint:varargs -Xmaxwarns 1
-
-class VarargsPluralAdditional<T> {
-    void m(T... items) { }
-}
--- a/langtools/test/tools/javac/varargs/6730476/T6730476a.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/test/tools/javac/varargs/6730476/T6730476a.java	Mon Dec 13 15:11:00 2010 -0800
@@ -32,6 +32,7 @@
  */
 
 class T6730476a {
+    @SuppressWarnings("unchecked")
     <T> void f(int i, T ... x) {}
     void g() {
       f(1);
--- a/langtools/test/tools/javac/varargs/6806876/T6806876.out	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/test/tools/javac/varargs/6806876/T6806876.out	Mon Dec 13 15:11:00 2010 -0800
@@ -1,6 +1,5 @@
 T6806876.java:11:32: compiler.warn.unchecked.generic.array.creation: java.lang.Number&java.lang.Comparable<? extends java.lang.Number&java.lang.Comparable<?>>[]
+T6806876.java:14:19: compiler.warn.unchecked.varargs.non.reifiable.type: T
 - compiler.err.warnings.and.werror
-- compiler.note.varargs.filename: T6806876.java
-- compiler.note.varargs.recompile
 1 error
-1 warning
+2 warnings
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/varargs/6993978/T6993978neg.java	Mon Dec 13 15:11:00 2010 -0800
@@ -0,0 +1,17 @@
+/*
+ * @test /nodynamiccopyright/
+ * @bug     6993978
+ * @author mcimadamore
+ * @summary  ClassCastException occurs in assignment expressions without any heap pollutions
+ * @compile/fail/ref=T6993978neg.out -Xlint:unchecked -Werror -XDrawDiagnostics T6993978neg.java
+ */
+
+import java.util.List;
+
+class T6993978neg {
+   @SuppressWarnings({"varargs","unchecked"})
+   static <X> void m(X... x) {  }
+   static void test(List<String> ls) {
+       m(ls); //compiler should still give unchecked here
+   }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/varargs/6993978/T6993978neg.out	Mon Dec 13 15:11:00 2010 -0800
@@ -0,0 +1,4 @@
+T6993978neg.java:15:9: compiler.warn.unchecked.generic.array.creation: java.util.List<java.lang.String>[]
+- compiler.err.warnings.and.werror
+1 error
+1 warning
--- a/langtools/test/tools/javac/varargs/warning/Warn4.java	Mon Dec 13 14:08:01 2010 -0800
+++ b/langtools/test/tools/javac/varargs/warning/Warn4.java	Mon Dec 13 15:11:00 2010 -0800
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug     6945418
+ * @bug     6945418 6993978
  * @summary Project Coin: Simplified Varargs Method Invocation
  * @author  mcimadamore
  * @run main Warn4
@@ -48,96 +48,95 @@
     final static Warning[] both = new Warning[] { Warning.VARARGS, Warning.UNCHECKED };
 
     enum Warning {
-        UNCHECKED("unchecked"),
-        VARARGS("varargs");
+        UNCHECKED("generic.array.creation"),
+        VARARGS("varargs.non.reifiable.type");
 
-        String category;
+        String key;
 
-        Warning(String category) {
-            this.category = category;
+        Warning(String key) {
+            this.key = key;
         }
 
-        boolean isEnabled(XlintOption xlint, SuppressLevel suppressLevel) {
-            return Arrays.asList(xlint.enabledWarnings).contains(this);
-        }
+        boolean isSuppressed(TrustMe trustMe, SourceLevel source, SuppressLevel suppressLevelClient,
+                SuppressLevel suppressLevelDecl, ModifierKind modKind) {
+            switch(this) {
+                case VARARGS:
+                    return source == SourceLevel.JDK_6 ||
+                            suppressLevelDecl == SuppressLevel.UNCHECKED ||
+                            trustMe == TrustMe.TRUST;
+                case UNCHECKED:
+                    return suppressLevelClient == SuppressLevel.UNCHECKED ||
+                        (trustMe == TrustMe.TRUST && modKind != ModifierKind.NONE && source == SourceLevel.JDK_7);
+            }
 
-        boolean isSuppressed(SuppressLevel suppressLevel) {
-            return Arrays.asList(suppressLevel.suppressedWarnings).contains(VARARGS);
+            SuppressLevel supLev = this == VARARGS ?
+                suppressLevelDecl :
+                suppressLevelClient;
+            return supLev == SuppressLevel.UNCHECKED ||
+                    (trustMe == TrustMe.TRUST && modKind != ModifierKind.NONE);
         }
     }
 
-    enum XlintOption {
-        NONE(),
-        UNCHECKED(Warning.UNCHECKED),
-        VARARGS(Warning.VARARGS),
-        ALL(Warning.UNCHECKED, Warning.VARARGS);
+    enum SourceLevel {
+        JDK_6("6"),
+        JDK_7("7");
 
-        Warning[] enabledWarnings;
+        String sourceKey;
 
-        XlintOption(Warning... enabledWarnings) {
-            this.enabledWarnings = enabledWarnings;
+        SourceLevel(String sourceKey) {
+            this.sourceKey = sourceKey;
         }
+    }
 
-        String getXlintOption() {
-            StringBuilder buf = new StringBuilder();
-            String sep = "";
-            for (Warning w : enabledWarnings) {
-                buf.append(sep);
-                buf.append(w.category);
-                sep=",";
-            }
-            return "-Xlint:" +
-                    (this == NONE ? "none" : buf.toString());
+    enum TrustMe {
+        DONT_TRUST(""),
+        TRUST("@java.lang.SafeVarargs");
+
+        String anno;
+
+        TrustMe(String anno) {
+            this.anno = anno;
+        }
+    }
+
+    enum ModifierKind {
+        NONE(" "),
+        FINAL("final "),
+        STATIC("static ");
+
+        String mod;
+
+        ModifierKind(String mod) {
+            this.mod = mod;
         }
     }
 
     enum SuppressLevel {
-        NONE(),
-        UNCHECKED(Warning.UNCHECKED),
-        VARARGS(Warning.VARARGS),
-        ALL(Warning.UNCHECKED, Warning.VARARGS);
+        NONE(""),
+        UNCHECKED("unchecked");
 
-        Warning[] suppressedWarnings;
+        String lint;
 
-        SuppressLevel(Warning... suppressedWarnings) {
-            this.suppressedWarnings = suppressedWarnings;
+        SuppressLevel(String lint) {
+            this.lint = lint;
         }
 
-        String getSuppressAnnotation() {
-            StringBuilder buf = new StringBuilder();
-            String sep = "";
-            for (Warning w : suppressedWarnings) {
-                buf.append(sep);
-                buf.append("\"");
-                buf.append(w.category);
-                buf.append("\"");
-                sep=",";
-            }
-            return this == NONE ? "" :
-                "@SuppressWarnings({" + buf.toString() + "})";
+        String getSuppressAnno() {
+            return "@SuppressWarnings(\"" + lint + "\")";
         }
     }
 
     enum Signature {
-
-        EXTENDS_TVAR("<Z> void #name(List<? extends Z>#arity arg) { #body }",
-            new Warning[][] {both, both, both, both, error, both, both, both, error}),
-        SUPER_TVAR("<Z> void #name(List<? super Z>#arity arg) { #body }",
-            new Warning[][] {error, both, error, both, error, error, both, both, error}),
         UNBOUND("void #name(List<?>#arity arg) { #body }",
-            new Warning[][] {none, none, none, none, none, none, none, none, error}),
+            new Warning[][] {none, none, none, none, error}),
         INVARIANT_TVAR("<Z> void #name(List<Z>#arity arg) { #body }",
-            new Warning[][] {both, both, both, both, error, both, both, both, error}),
+            new Warning[][] {both, both, error, both, error}),
         TVAR("<Z> void #name(Z#arity arg) { #body }",
-            new Warning[][] {both, both, both, both, both, both, both, both, vararg}),
-        EXTENDS("void #name(List<? extends String>#arity arg) { #body }",
-            new Warning[][] {error, error, error, error, error, both, error, both, error}),
-        SUPER("void #name(List<? super String>#arity arg) { #body }",
-            new Warning[][] {error, error, error, error, error, error, both, both, error}),
+            new Warning[][] {both, both, both, both, vararg}),
         INVARIANT("void #name(List<String>#arity arg) { #body }",
-            new Warning[][] {error, error, error, error, error, error, error, both, error}),
+            new Warning[][] {error, error, error, both, error}),
         UNPARAMETERIZED("void #name(String#arity arg) { #body }",
-            new Warning[][] {error, error, error, error, error, error, error, error, none});
+            new Warning[][] {error, error, error, error, none});
 
         String template;
         Warning[][] warnings;
@@ -163,15 +162,24 @@
     }
 
     public static void main(String... args) throws Exception {
-        for (XlintOption xlint : XlintOption.values()) {
-            for (SuppressLevel suppressLevel : SuppressLevel.values()) {
-                for (Signature vararg_meth : Signature.values()) {
-                    for (Signature client_meth : Signature.values()) {
-                        if (vararg_meth.isApplicableTo(client_meth)) {
-                            test(xlint,
-                                    suppressLevel,
-                                    vararg_meth,
-                                    client_meth);
+        for (SourceLevel sourceLevel : SourceLevel.values()) {
+            for (TrustMe trustMe : TrustMe.values()) {
+                for (SuppressLevel suppressLevelClient : SuppressLevel.values()) {
+                    for (SuppressLevel suppressLevelDecl : SuppressLevel.values()) {
+                        for (ModifierKind modKind : ModifierKind.values()) {
+                            for (Signature vararg_meth : Signature.values()) {
+                                for (Signature client_meth : Signature.values()) {
+                                    if (vararg_meth.isApplicableTo(client_meth)) {
+                                        test(sourceLevel,
+                                                trustMe,
+                                                suppressLevelClient,
+                                                suppressLevelDecl,
+                                                modKind,
+                                                vararg_meth,
+                                                client_meth);
+                                    }
+                                }
+                            }
                         }
                     }
                 }
@@ -179,37 +187,37 @@
         }
     }
 
-    static void test(XlintOption xlint, SuppressLevel suppressLevel,
-            Signature vararg_meth, Signature client_meth) throws Exception {
+    static void test(SourceLevel sourceLevel, TrustMe trustMe, SuppressLevel suppressLevelClient,
+            SuppressLevel suppressLevelDecl, ModifierKind modKind, Signature vararg_meth, Signature client_meth) throws Exception {
         final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
-        JavaSource source = new JavaSource(suppressLevel, vararg_meth, client_meth);
+        JavaSource source = new JavaSource(trustMe, suppressLevelClient, suppressLevelDecl, modKind, vararg_meth, client_meth);
         DiagnosticChecker dc = new DiagnosticChecker();
         JavacTask ct = (JavacTask)tool.getTask(null, null, dc,
-                Arrays.asList(xlint.getXlintOption()), null, Arrays.asList(source));
+                Arrays.asList("-Xlint:unchecked", "-source", sourceLevel.sourceKey),
+                null, Arrays.asList(source));
         ct.generate(); //to get mandatory notes
-        check(dc.warnings,
-                dc.notes,
+        check(dc.warnings, sourceLevel,
                 new boolean[] {vararg_meth.giveUnchecked(client_meth),
                                vararg_meth.giveVarargs(client_meth)},
-                source, xlint, suppressLevel);
+                source, trustMe, suppressLevelClient, suppressLevelDecl, modKind);
     }
 
-    static void check(Set<Warning> warnings, Set<Warning> notes, boolean[] warnArr, JavaSource source, XlintOption xlint, SuppressLevel suppressLevel) {
+    static void check(Set<Warning> warnings, SourceLevel sourceLevel, boolean[] warnArr, JavaSource source,
+            TrustMe trustMe, SuppressLevel suppressLevelClient, SuppressLevel suppressLevelDecl, ModifierKind modKind) {
         boolean badOutput = false;
         for (Warning wkind : Warning.values()) {
-            badOutput |= (warnArr[wkind.ordinal()] && !wkind.isSuppressed(suppressLevel)) !=
-                    (wkind.isEnabled(xlint, suppressLevel) ?
-                        warnings.contains(wkind) :
-                        notes.contains(wkind));
+            boolean isSuppressed = wkind.isSuppressed(trustMe, sourceLevel,
+                    suppressLevelClient, suppressLevelDecl, modKind);
+            System.out.println("SUPPRESSED = " + isSuppressed);
+            badOutput |= (warnArr[wkind.ordinal()] && !isSuppressed) != warnings.contains(wkind);
         }
         if (badOutput) {
             throw new Error("invalid diagnostics for source:\n" +
                     source.getCharContent(true) +
-                    "\nOptions: " + xlint.getXlintOption() +
                     "\nExpected unchecked warning: " + warnArr[0] +
                     "\nExpected unsafe vararg warning: " + warnArr[1] +
                     "\nWarnings: " + warnings +
-                    "\nNotes: " + notes);
+                    "\nSource level: " + sourceLevel);
         }
     }
 
@@ -217,18 +225,20 @@
 
         String source;
 
-        public JavaSource(SuppressLevel suppressLevel, Signature vararg_meth, Signature client_meth) {
+        public JavaSource(TrustMe trustMe, SuppressLevel suppressLevelClient, SuppressLevel suppressLevelDecl,
+                ModifierKind modKind, Signature vararg_meth, Signature client_meth) {
             super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
             String meth1 = vararg_meth.template.replace("#arity", "...");
             meth1 = meth1.replace("#name", "m");
             meth1 = meth1.replace("#body", "");
-            meth1 = suppressLevel.getSuppressAnnotation() + meth1;
+            meth1 = trustMe.anno + "\n" + suppressLevelDecl.getSuppressAnno() + modKind.mod + meth1;
             String meth2 = client_meth.template.replace("#arity", "");
             meth2 = meth2.replace("#name", "test");
             meth2 = meth2.replace("#body", "m(arg);");
+            meth2 = suppressLevelClient.getSuppressAnno() + meth2;
             source = "import java.util.List;\n" +
-               "class Test {\n" + meth1 +
-               "\n" + meth2 + "\n}\n";
+                     "class Test {\n" + meth1 +
+                     "\n" + meth2 + "\n}\n";
         }
 
         @Override
@@ -240,19 +250,15 @@
     static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
 
         Set<Warning> warnings = new HashSet<>();
-        Set<Warning> notes = new HashSet<>();
 
         public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
             if (diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING ||
                     diagnostic.getKind() == Diagnostic.Kind.WARNING) {
-                warnings.add(diagnostic.getCode().contains("varargs") ?
-                    Warning.VARARGS :
-                    Warning.UNCHECKED);
-            }
-            else if (diagnostic.getKind() == Diagnostic.Kind.NOTE) {
-                notes.add(diagnostic.getCode().contains("varargs") ?
-                    Warning.VARARGS :
-                    Warning.UNCHECKED);
+                if (diagnostic.getCode().contains(Warning.VARARGS.key)) {
+                    warnings.add(Warning.VARARGS);
+                } else if(diagnostic.getCode().contains(Warning.UNCHECKED.key)) {
+                    warnings.add(Warning.UNCHECKED);
+                }
             }
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/varargs/warning/Warn5.java	Mon Dec 13 15:11:00 2010 -0800
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug     6993978
+ * @summary Project Coin: Annotation to reduce varargs warnings
+ * @author  mcimadamore
+ * @run main Warn5
+ */
+import com.sun.source.util.JavacTask;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import javax.tools.Diagnostic;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+
+public class Warn5 {
+
+    enum XlintOption {
+        NONE("none"),
+        ALL("all");
+
+        String opt;
+
+        XlintOption(String opt) {
+            this.opt = opt;
+        }
+
+        String getXlintOption() {
+            return "-Xlint:" + opt;
+        }
+    }
+
+    enum TrustMe {
+        DONT_TRUST(""),
+        TRUST("@java.lang.SafeVarargs");
+
+        String anno;
+
+        TrustMe(String anno) {
+            this.anno = anno;
+        }
+    }
+
+    enum SuppressLevel {
+        NONE,
+        VARARGS;
+
+        String getSuppressAnno() {
+            return this == VARARGS ?
+                "@SuppressWarnings(\"varargs\")" :
+                "";
+        }
+    }
+
+    enum ModifierKind {
+        NONE(""),
+        FINAL("final"),
+        STATIC("static");
+
+        String mod;
+
+        ModifierKind(String mod) {
+            this.mod = mod;
+        }
+    }
+
+    enum MethodKind {
+        METHOD("void m"),
+        CONSTRUCTOR("Test");
+
+
+        String name;
+
+        MethodKind(String name) {
+            this.name = name;
+        }
+    }
+
+    enum SourceLevel {
+        JDK_6("6"),
+        JDK_7("7");
+
+        String sourceKey;
+
+        SourceLevel(String sourceKey) {
+            this.sourceKey = sourceKey;
+        }
+    }
+
+    enum SignatureKind {
+        VARARGS_X("#K <X>#N(X... x)", false, true),
+        VARARGS_STRING("#K #N(String... x)", true, true),
+        ARRAY_X("#K <X>#N(X[] x)", false, false),
+        ARRAY_STRING("#K #N(String[] x)", true, false);
+
+        String stub;
+        boolean isReifiableArg;
+        boolean isVarargs;
+
+        SignatureKind(String stub, boolean isReifiableArg, boolean isVarargs) {
+            this.stub = stub;
+            this.isReifiableArg = isReifiableArg;
+            this.isVarargs = isVarargs;
+        }
+
+        String getSignature(ModifierKind modKind, MethodKind methKind) {
+            return methKind != MethodKind.CONSTRUCTOR ?
+                stub.replace("#K", modKind.mod).replace("#N", methKind.name) :
+                stub.replace("#K", "").replace("#N", methKind.name);
+        }
+    }
+
+    enum BodyKind {
+        ASSIGN("Object o = x;", true),
+        CAST("Object o = (Object)x;", true),
+        METH("test(x);", true),
+        PRINT("System.out.println(x.toString());", false),
+        ARRAY_ASSIGN("Object[] o = x;", true),
+        ARRAY_CAST("Object[] o = (Object[])x;", true),
+        ARRAY_METH("testArr(x);", true);
+
+        String body;
+        boolean hasAliasing;
+
+        BodyKind(String body, boolean hasAliasing) {
+            this.body = body;
+            this.hasAliasing = hasAliasing;
+        }
+    }
+
+    static class JavaSource extends SimpleJavaFileObject {
+
+        String template = "import com.sun.tools.javac.api.*;\n" +
+                          "import java.util.List;\n" +
+                          "class Test {\n" +
+                          "   static void test(Object o) {}\n" +
+                          "   static void testArr(Object[] o) {}\n" +
+                          "   #T \n #S #M { #B }\n" +
+                          "}\n";
+
+        String source;
+
+        public JavaSource(TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind,
+                MethodKind methKind, SignatureKind meth, BodyKind body) {
+            super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+            source = template.replace("#T", trustMe.anno).
+                    replace("#S", suppressLevel.getSuppressAnno()).
+                    replace("#M", meth.getSignature(modKind, methKind)).
+                    replace("#B", body.body);
+        }
+
+        @Override
+        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+            return source;
+        }
+    }
+
+    public static void main(String... args) throws Exception {
+        for (SourceLevel sourceLevel : SourceLevel.values()) {
+            for (XlintOption xlint : XlintOption.values()) {
+                for (TrustMe trustMe : TrustMe.values()) {
+                    for (SuppressLevel suppressLevel : SuppressLevel.values()) {
+                        for (ModifierKind modKind : ModifierKind.values()) {
+                            for (MethodKind methKind : MethodKind.values()) {
+                                for (SignatureKind sig : SignatureKind.values()) {
+                                    for (BodyKind body : BodyKind.values()) {
+                                        test(sourceLevel,
+                                                xlint,
+                                                trustMe,
+                                                suppressLevel,
+                                                modKind,
+                                                methKind,
+                                                sig,
+                                                body);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    static void test(SourceLevel sourceLevel, XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel,
+            ModifierKind modKind, MethodKind methKind, SignatureKind sig, BodyKind body) throws Exception {
+        final JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
+        JavaSource source = new JavaSource(trustMe, suppressLevel, modKind, methKind, sig, body);
+        DiagnosticChecker dc = new DiagnosticChecker();
+        JavacTask ct = (JavacTask)tool.getTask(null, null, dc,
+                Arrays.asList(xlint.getXlintOption(), "-source", sourceLevel.sourceKey), null, Arrays.asList(source));
+        ct.analyze();
+        check(sourceLevel, dc, source, xlint, trustMe,
+                suppressLevel, modKind, methKind, sig, body);
+    }
+
+    static void check(SourceLevel sourceLevel, DiagnosticChecker dc, JavaSource source,
+            XlintOption xlint, TrustMe trustMe, SuppressLevel suppressLevel, ModifierKind modKind,
+            MethodKind methKind, SignatureKind meth, BodyKind body) {
+
+        boolean hasPotentiallyUnsafeBody = sourceLevel == SourceLevel.JDK_7 &&
+                trustMe == TrustMe.TRUST &&
+                suppressLevel != SuppressLevel.VARARGS &&
+                xlint != XlintOption.NONE &&
+                meth.isVarargs && !meth.isReifiableArg && body.hasAliasing &&
+                (methKind == MethodKind.CONSTRUCTOR || (methKind == MethodKind.METHOD && modKind != ModifierKind.NONE));
+
+        boolean hasPotentiallyPollutingDecl = sourceLevel == SourceLevel.JDK_7 &&
+                trustMe == TrustMe.DONT_TRUST &&
+                meth.isVarargs &&
+                !meth.isReifiableArg &&
+                xlint == XlintOption.ALL;
+
+        boolean hasMalformedAnnoInDecl = sourceLevel == SourceLevel.JDK_7 &&
+                trustMe == TrustMe.TRUST &&
+                (!meth.isVarargs ||
+                (modKind == ModifierKind.NONE && methKind == MethodKind.METHOD));
+
+        boolean hasRedundantAnnoInDecl = sourceLevel == SourceLevel.JDK_7 &&
+                trustMe == TrustMe.TRUST &&
+                xlint != XlintOption.NONE &&
+                suppressLevel != SuppressLevel.VARARGS &&
+                (modKind != ModifierKind.NONE || methKind == MethodKind.CONSTRUCTOR) &&
+                meth.isVarargs &&
+                meth.isReifiableArg;
+
+        if (hasPotentiallyUnsafeBody != dc.hasPotentiallyUnsafeBody ||
+                hasPotentiallyPollutingDecl != dc.hasPotentiallyPollutingDecl ||
+                hasMalformedAnnoInDecl != dc.hasMalformedAnnoInDecl ||
+                hasRedundantAnnoInDecl != dc.hasRedundantAnnoInDecl) {
+            throw new Error("invalid diagnostics for source:\n" +
+                    source.getCharContent(true) +
+                    "\nOptions: " + xlint.getXlintOption() +
+                    "\nExpected potentially unsafe body warning: " + hasPotentiallyUnsafeBody +
+                    "\nExpected potentially polluting decl warning: " + hasPotentiallyPollutingDecl +
+                    "\nExpected malformed anno error: " + hasMalformedAnnoInDecl +
+                    "\nExpected redundant anno warning: " + hasRedundantAnnoInDecl +
+                    "\nFound potentially unsafe body warning: " + dc.hasPotentiallyUnsafeBody +
+                    "\nFound potentially polluting decl warning: " + dc.hasPotentiallyPollutingDecl +
+                    "\nFound malformed anno error: " + dc.hasMalformedAnnoInDecl +
+                    "\nFound redundant anno warning: " + dc.hasRedundantAnnoInDecl);
+        }
+    }
+
+    static class DiagnosticChecker implements javax.tools.DiagnosticListener<JavaFileObject> {
+
+        boolean hasPotentiallyUnsafeBody = false;
+        boolean hasPotentiallyPollutingDecl = false;
+        boolean hasMalformedAnnoInDecl = false;
+        boolean hasRedundantAnnoInDecl = false;
+
+        public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+            if (diagnostic.getKind() == Diagnostic.Kind.WARNING) {
+                    if (diagnostic.getCode().contains("unsafe.use.varargs.param")) {
+                        hasPotentiallyUnsafeBody = true;
+                    } else if (diagnostic.getCode().contains("redundant.trustme")) {
+                        hasRedundantAnnoInDecl = true;
+                    }
+            } else if (diagnostic.getKind() == Diagnostic.Kind.MANDATORY_WARNING &&
+                    diagnostic.getCode().contains("varargs.non.reifiable.type")) {
+                hasPotentiallyPollutingDecl = true;
+            } else if (diagnostic.getKind() == Diagnostic.Kind.ERROR &&
+                    diagnostic.getCode().contains("invalid.trustme")) {
+                hasMalformedAnnoInDecl = true;
+            }
+        }
+    }
+}