changeset 2027:4ce8148ffc4f

8021112: Spurious unchecked warning reported by javac 6480588: No way to suppress deprecation warnings when implementing deprecated interface Summary: Fixing DeferredLintHandler configuration, so lint warnings are reported with correct @SuppressWarnings settings Reviewed-by: jjg, vromero
author jlahoda
date Mon, 16 Sep 2013 14:13:44 +0200
parents 4932bb04c4b8
children 252f872b8a2f fdfbc5f0c4ed
files src/share/classes/com/sun/tools/javac/code/DeferredLintHandler.java src/share/classes/com/sun/tools/javac/code/Symbol.java src/share/classes/com/sun/tools/javac/comp/Attr.java src/share/classes/com/sun/tools/javac/comp/Check.java src/share/classes/com/sun/tools/javac/comp/MemberEnter.java test/tools/javac/depDocComment/SuppressDeprecation.out test/tools/javac/warnings/6594914/T6594914a.out test/tools/javac/warnings/6594914/T6594914b.out test/tools/javac/warnings/suppress/ImplicitTest.java test/tools/javac/warnings/suppress/ImplicitTest.out test/tools/javac/warnings/suppress/PackageInfo.java test/tools/javac/warnings/suppress/PackageInfo.out test/tools/javac/warnings/suppress/T6480588.java test/tools/javac/warnings/suppress/T6480588.out test/tools/javac/warnings/suppress/T8021112a.java test/tools/javac/warnings/suppress/T8021112b.java test/tools/javac/warnings/suppress/T8021112b.out test/tools/javac/warnings/suppress/TypeAnnotations.java test/tools/javac/warnings/suppress/TypeAnnotations.out test/tools/javac/warnings/suppress/VerifySuppressWarnings.java test/tools/javac/warnings/suppress/pack/DeprecatedClass.java test/tools/javac/warnings/suppress/pack/ImplicitMain.java test/tools/javac/warnings/suppress/pack/ImplicitUse.java test/tools/javac/warnings/suppress/pack/package-info.java
diffstat 24 files changed, 687 insertions(+), 91 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/javac/code/DeferredLintHandler.java	Sat Sep 14 19:04:47 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/code/DeferredLintHandler.java	Mon Sep 16 14:13:44 2013 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,8 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import com.sun.tools.javac.tree.EndPosTable;
+import com.sun.tools.javac.tree.JCTree;
 import com.sun.tools.javac.util.Assert;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@@ -53,10 +55,13 @@
 
     protected DeferredLintHandler(Context context) {
         context.put(deferredLintHandlerKey, this);
+        this.currentPos = IMMEDIATE_POSITION;
     }
 
-    private DeferredLintHandler() {}
-
+    /**An interface for deferred lint reporting - loggers passed to
+     * {@link #report(LintLogger) } will be called when
+     * {@link #flush(DiagnosticPosition) } is invoked.
+     */
     public interface LintLogger {
         void report();
     }
@@ -64,12 +69,26 @@
     private DiagnosticPosition currentPos;
     private Map<DiagnosticPosition, ListBuffer<LintLogger>> loggersQueue = new HashMap<DiagnosticPosition, ListBuffer<LintLogger>>();
 
+    /**Associate the given logger with the current position as set by {@link #setPos(DiagnosticPosition) }.
+     * Will be invoked when {@link #flush(DiagnosticPosition) } will be invoked with the same position.
+     * <br>
+     * Will invoke the logger synchronously if {@link #immediate() } was called
+     * instead of {@link #setPos(DiagnosticPosition) }.
+     */
     public void report(LintLogger logger) {
-        ListBuffer<LintLogger> loggers = loggersQueue.get(currentPos);
-        Assert.checkNonNull(loggers);
-        loggers.append(logger);
+        if (currentPos == IMMEDIATE_POSITION) {
+            logger.report();
+        } else {
+            ListBuffer<LintLogger> loggers = loggersQueue.get(currentPos);
+            if (loggers == null) {
+                loggersQueue.put(currentPos, loggers = ListBuffer.<LintLogger>lb());
+            }
+            loggers.append(logger);
+        }
     }
 
+    /**Invoke all {@link LintLogger}s that were associated with the provided {@code pos}.
+     */
     public void flush(DiagnosticPosition pos) {
         ListBuffer<LintLogger> loggers = loggersQueue.get(pos);
         if (loggers != null) {
@@ -80,16 +99,46 @@
         }
     }
 
-    public DeferredLintHandler setPos(DiagnosticPosition currentPos) {
+    /**Sets the current position to the provided {@code currentPos}. {@link LintLogger}s
+     * passed to subsequent invocations of {@link #report(LintLogger) } will be associated
+     * with the given position.
+     */
+    public DiagnosticPosition setPos(DiagnosticPosition currentPos) {
+        DiagnosticPosition prevPosition = this.currentPos;
         this.currentPos = currentPos;
-        loggersQueue.put(currentPos, ListBuffer.<LintLogger>lb());
-        return this;
+        return prevPosition;
     }
 
-    public static final DeferredLintHandler immediateHandler = new DeferredLintHandler() {
+    /**{@link LintLogger}s passed to subsequent invocations of
+     * {@link #report(LintLogger) } will be invoked immediately.
+     */
+    public DiagnosticPosition immediate() {
+        return setPos(IMMEDIATE_POSITION);
+    }
+
+    private static final DiagnosticPosition IMMEDIATE_POSITION = new DiagnosticPosition() {
         @Override
-        public void report(LintLogger logger) {
-            logger.report();
+        public JCTree getTree() {
+            Assert.error();
+            return null;
+        }
+
+        @Override
+        public int getStartPosition() {
+            Assert.error();
+            return -1;
+        }
+
+        @Override
+        public int getPreferredPosition() {
+            Assert.error();
+            return -1;
+        }
+
+        @Override
+        public int getEndPosition(EndPosTable endPosTable) {
+            Assert.error();
+            return -1;
         }
     };
 }
--- a/src/share/classes/com/sun/tools/javac/code/Symbol.java	Sat Sep 14 19:04:47 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java	Mon Sep 16 14:13:44 2013 +0200
@@ -46,6 +46,7 @@
 import static com.sun.tools.javac.code.TypeTag.CLASS;
 import static com.sun.tools.javac.code.TypeTag.FORALL;
 import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
+import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
 
 /** Root class for Java symbols. It contains subclasses
  *  for specific sorts of symbols, such as variables, methods and operators,
@@ -1167,11 +1168,11 @@
 
         public void setLazyConstValue(final Env<AttrContext> env,
                                       final Attr attr,
-                                      final JCTree.JCExpression initializer)
+                                      final JCVariableDecl variable)
         {
             setData(new Callable<Object>() {
                 public Object call() {
-                    return attr.attribLazyConstantValue(env, initializer, type);
+                    return attr.attribLazyConstantValue(env, variable, type);
                 }
             });
         }
--- a/src/share/classes/com/sun/tools/javac/comp/Attr.java	Sat Sep 14 19:04:47 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Sep 16 14:13:44 2013 +0200
@@ -748,19 +748,11 @@
      *  @see VarSymbol#setLazyConstValue
      */
     public Object attribLazyConstantValue(Env<AttrContext> env,
-                                      JCTree.JCExpression initializer,
+                                      JCVariableDecl variable,
                                       Type type) {
 
-        /*  When this env was created, it didn't have the correct lint nor had
-         *  annotations has been processed.
-         *  But now at this phase we have already processed annotations and the
-         *  correct lint must have been set in chk, so we should use that one to
-         *  attribute the initializer.
-         */
-        Lint prevLint = env.info.lint;
-        env.info.lint = chk.getLint();
-
-        JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile);
+        DiagnosticPosition prevLintPos
+                = deferredLintHandler.setPos(variable.pos());
 
         try {
             // Use null as symbol to not attach the type annotation to any symbol.
@@ -768,17 +760,16 @@
             // to the symbol.
             // This prevents having multiple type annotations, just because of
             // lazy constant value evaluation.
-            memberEnter.typeAnnotate(initializer, env, null);
+            memberEnter.typeAnnotate(variable.init, env, null, variable.pos());
             annotate.flush();
-            Type itype = attribExpr(initializer, env, type);
+            Type itype = attribExpr(variable.init, env, type);
             if (itype.constValue() != null) {
                 return coerce(itype, type).constValue();
             } else {
                 return null;
             }
         } finally {
-            env.info.lint = prevLint;
-            log.useSource(prevSource);
+            deferredLintHandler.setPos(prevLintPos);
         }
     }
 
@@ -1012,7 +1003,7 @@
                 }
 
                 // Attribute all type annotations in the body
-                memberEnter.typeAnnotate(tree.body, localEnv, m);
+                memberEnter.typeAnnotate(tree.body, localEnv, m, null);
                 annotate.flush();
 
                 // Attribute method body.
@@ -1042,7 +1033,7 @@
         } else {
             if (tree.init != null) {
                 // Field initializer expression need to be entered.
-                memberEnter.typeAnnotate(tree.init, env, tree.sym);
+                memberEnter.typeAnnotate(tree.init, env, tree.sym, tree.pos());
                 annotate.flush();
             }
         }
@@ -1056,18 +1047,16 @@
                 ((JCLambda)env.tree).paramKind == JCLambda.ParameterKind.IMPLICIT &&
                 (tree.sym.flags() & PARAMETER) != 0;
         chk.validate(tree.vartype, env, !isImplicitLambdaParameter);
-        deferredLintHandler.flush(tree.pos());
 
         try {
+            v.getConstValue(); // ensure compile-time constant initializer is evaluated
+            deferredLintHandler.flush(tree.pos());
             chk.checkDeprecatedAnnotation(tree.pos(), v);
 
             if (tree.init != null) {
-                if ((v.flags_field & FINAL) != 0 &&
-                    memberEnter.needsLazyConstValue(tree.init)) {
-                    // In this case, `v' is final.  Ensure that it's initializer is
-                    // evaluated.
-                    v.getConstValue(); // ensure initializer is evaluated
-                } else {
+                if ((v.flags_field & FINAL) == 0 ||
+                    !memberEnter.needsLazyConstValue(tree.init)) {
+                    // Not a compile-time constant
                     // Attribute initializer in a new environment
                     // with the declared variable as owner.
                     // Check that initializer conforms to variable's declared type.
@@ -1106,7 +1095,7 @@
             if ((tree.flags & STATIC) != 0) localEnv.info.staticLevel++;
 
             // Attribute all type annotations in the block
-            memberEnter.typeAnnotate(tree, localEnv, localEnv.info.scope.owner);
+            memberEnter.typeAnnotate(tree, localEnv, localEnv.info.scope.owner, null);
             annotate.flush();
 
             {
@@ -4209,6 +4198,7 @@
             ResultInfo prevReturnRes = env.info.returnResult;
 
             try {
+                deferredLintHandler.flush(env.tree);
                 env.info.returnResult = null;
                 // java.lang.Enum may not be subclassed by a non-enum
                 if (st.tsym == syms.enumSym &&
--- a/src/share/classes/com/sun/tools/javac/comp/Check.java	Sat Sep 14 19:04:47 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/Check.java	Mon Sep 16 14:13:44 2013 +0200
@@ -148,7 +148,7 @@
         sunApiHandler = new MandatoryWarningHandler(log, verboseSunApi,
                 enforceMandatoryWarnings, "sunapi", null);
 
-        deferredLintHandler = DeferredLintHandler.immediateHandler;
+        deferredLintHandler = DeferredLintHandler.instance(context);
     }
 
     /** Switch: generics enabled?
@@ -218,20 +218,6 @@
         return prev;
     }
 
-    /*  This idiom should be used only in cases when it is needed to set the lint
-     *  of an environment that has been created in a phase previous to annotations
-     *  processing.
-     */
-    Lint getLint() {
-        return lint;
-    }
-
-    DeferredLintHandler setDeferredLintHandler(DeferredLintHandler newDeferredLintHandler) {
-        DeferredLintHandler prev = deferredLintHandler;
-        deferredLintHandler = newDeferredLintHandler;
-        return prev;
-    }
-
     MethodSymbol setMethod(MethodSymbol newMethod) {
         MethodSymbol prev = method;
         method = newMethod;
@@ -582,14 +568,19 @@
     /** Check for redundant casts (i.e. where source type is a subtype of target type)
      * The problem should only be reported for non-292 cast
      */
-    public void checkRedundantCast(Env<AttrContext> env, JCTypeCast tree) {
-        if (!tree.type.isErroneous() &&
-                (env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST))
+    public void checkRedundantCast(Env<AttrContext> env, final JCTypeCast tree) {
+        if (!tree.type.isErroneous()
                 && types.isSameType(tree.expr.type, tree.clazz.type)
                 && !(ignoreAnnotatedCasts && TreeInfo.containsTypeAnnotation(tree.clazz))
                 && !is292targetTypeCast(tree)) {
-            log.warning(Lint.LintCategory.CAST,
-                    tree.pos(), "redundant.cast", tree.expr.type);
+            deferredLintHandler.report(new DeferredLintHandler.LintLogger() {
+                @Override
+                public void report() {
+                    if (lint.isEnabled(Lint.LintCategory.CAST))
+                        log.warning(Lint.LintCategory.CAST,
+                                tree.pos(), "redundant.cast", tree.expr.type);
+                }
+            });
         }
     }
     //where
--- a/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Sat Sep 14 19:04:47 2013 +0100
+++ b/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java	Mon Sep 16 14:13:44 2013 +0200
@@ -84,6 +84,7 @@
     private final Source source;
     private final Target target;
     private final DeferredLintHandler deferredLintHandler;
+    private final Lint lint;
 
     public static MemberEnter instance(Context context) {
         MemberEnter instance = context.get(memberEnterKey);
@@ -109,6 +110,7 @@
         source = Source.instance(context);
         target = Target.instance(context);
         deferredLintHandler = DeferredLintHandler.instance(context);
+        lint = Lint.instance(context);
         allowTypeAnnos = source.allowTypeAnnotations();
     }
 
@@ -506,9 +508,10 @@
         }
 
         // process package annotations
-        annotateLater(tree.packageAnnotations, env, tree.packge);
+        annotateLater(tree.packageAnnotations, env, tree.packge, null);
 
-        DeferredLintHandler prevLintHandler = chk.setDeferredLintHandler(DeferredLintHandler.immediateHandler);
+        DiagnosticPosition prevLintPos = deferredLintHandler.immediate();
+        Lint prevLint = chk.setLint(lint);
 
         try {
             // Import-on-demand java.lang.
@@ -517,7 +520,8 @@
             // Process all import clauses.
             memberEnter(tree.defs, env);
         } finally {
-            chk.setDeferredLintHandler(prevLintHandler);
+            chk.setLint(prevLint);
+            deferredLintHandler.setPos(prevLintPos);
         }
     }
 
@@ -564,8 +568,7 @@
 
         Env<AttrContext> localEnv = methodEnv(tree, env);
 
-        DeferredLintHandler prevLintHandler =
-                chk.setDeferredLintHandler(deferredLintHandler.setPos(tree.pos()));
+        DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
         try {
             // Compute the method type
             m.type = signature(m, tree.typarams, tree.params,
@@ -573,7 +576,7 @@
                                tree.thrown,
                                localEnv);
         } finally {
-            chk.setDeferredLintHandler(prevLintHandler);
+            deferredLintHandler.setPos(prevLintPos);
         }
 
         if (types.isSignaturePolymorphic(m)) {
@@ -597,10 +600,10 @@
         if (chk.checkUnique(tree.pos(), m, enclScope)) {
             enclScope.enter(m);
         }
-        annotateLater(tree.mods.annotations, localEnv, m);
+        annotateLater(tree.mods.annotations, localEnv, m, tree.pos());
         // Visit the signature of the method. Note that
         // TypeAnnotate doesn't descend into the body.
-        typeAnnotate(tree, localEnv, m);
+        typeAnnotate(tree, localEnv, m, tree.pos());
 
         if (tree.defaultValue != null)
             annotateDefaultValueLater(tree.defaultValue, localEnv, m);
@@ -630,15 +633,14 @@
             localEnv = env.dup(tree, env.info.dup());
             localEnv.info.staticLevel++;
         }
-        DeferredLintHandler prevLintHandler =
-                chk.setDeferredLintHandler(deferredLintHandler.setPos(tree.pos()));
+        DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
         try {
             if (TreeInfo.isEnumInit(tree)) {
                 attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype);
             } else {
                 // Make sure type annotations are processed.
                 // But we don't have a symbol to attach them to yet - use null.
-                typeAnnotate(tree.vartype, env, null);
+                typeAnnotate(tree.vartype, env, null, tree.pos());
                 attr.attribType(tree.vartype, localEnv);
                 if (tree.nameexpr != null) {
                     attr.attribExpr(tree.nameexpr, localEnv);
@@ -658,7 +660,7 @@
                 }
             }
         } finally {
-            chk.setDeferredLintHandler(prevLintHandler);
+            deferredLintHandler.setPos(prevLintPos);
         }
 
         if ((tree.mods.flags & VARARGS) != 0) {
@@ -680,15 +682,15 @@
                 needsLazyConstValue(tree.init)) {
                 Env<AttrContext> initEnv = getInitEnv(tree, env);
                 initEnv.info.enclVar = v;
-                v.setLazyConstValue(initEnv(tree, initEnv), attr, tree.init);
+                v.setLazyConstValue(initEnv(tree, initEnv), attr, tree);
             }
         }
         if (chk.checkUnique(tree.pos(), v, enclScope)) {
             chk.checkTransparentVar(tree.pos(), v, enclScope);
             enclScope.enter(v);
         }
-        annotateLater(tree.mods.annotations, localEnv, v);
-        typeAnnotate(tree.vartype, env, v);
+        annotateLater(tree.mods.annotations, localEnv, v, tree.pos());
+        typeAnnotate(tree.vartype, env, v, tree.pos());
         annotate.flush();
         v.pos = tree.pos;
     }
@@ -720,6 +722,11 @@
         }
 
         @Override
+        public void visitNewArray(JCNewArray that) {
+            result = false;
+        }
+
+        @Override
         public void visitLambda(JCLambda that) {
             result = false;
         }
@@ -730,6 +737,11 @@
         }
 
         @Override
+        public void visitApply(JCMethodInvocation that) {
+            result = false;
+        }
+
+        @Override
         public void visitSelect(JCFieldAccess tree) {
             tree.selected.accept(this);
         }
@@ -820,7 +832,8 @@
     /** Queue annotations for later processing. */
     void annotateLater(final List<JCAnnotation> annotations,
                        final Env<AttrContext> localEnv,
-                       final Symbol s) {
+                       final Symbol s,
+                       final DiagnosticPosition deferPos) {
         if (annotations.isEmpty()) {
             return;
         }
@@ -837,6 +850,11 @@
                 public void enterAnnotation() {
                     Assert.check(s.kind == PCK || s.annotationsPendingCompletion());
                     JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
+                    DiagnosticPosition prevLintPos =
+                        deferPos != null
+                        ? deferredLintHandler.setPos(deferPos)
+                        : deferredLintHandler.immediate();
+                    Lint prevLint = deferPos != null ? null : chk.setLint(lint);
                     try {
                         if (s.hasAnnotations() &&
                             annotations.nonEmpty())
@@ -845,6 +863,9 @@
                                       kindName(s), s);
                         actualEnterAnnotations(annotations, localEnv, s);
                     } finally {
+                        if (prevLint != null)
+                            chk.setLint(prevLint);
+                        deferredLintHandler.setPos(prevLintPos);
                         log.useSource(prev);
                     }
                 }
@@ -964,6 +985,7 @@
         isFirst = false;
 
         JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
+        DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
         try {
             // Save class environment for later member enter (2) processing.
             halfcompleted.append(env);
@@ -985,9 +1007,9 @@
             Env<AttrContext> baseEnv = baseEnv(tree, env);
 
             if (tree.extending != null)
-                typeAnnotate(tree.extending, baseEnv, sym);
+                typeAnnotate(tree.extending, baseEnv, sym, tree.pos());
             for (JCExpression impl : tree.implementing)
-                typeAnnotate(impl, baseEnv, sym);
+                typeAnnotate(impl, baseEnv, sym, tree.pos());
             annotate.flush();
 
             // Determine supertype.
@@ -1048,7 +1070,7 @@
             attr.attribAnnotationTypes(tree.mods.annotations, baseEnv);
             if (hasDeprecatedAnnotation(tree.mods.annotations))
                 c.flags_field |= DEPRECATED;
-            annotateLater(tree.mods.annotations, baseEnv, c);
+            annotateLater(tree.mods.annotations, baseEnv, c, tree.pos());
             // class type parameters use baseEnv but everything uses env
 
             chk.checkNonCyclicDecl(tree);
@@ -1056,7 +1078,7 @@
             attr.attribTypeVariables(tree.typarams, baseEnv);
             // Do this here, where we have the symbol.
             for (JCTypeParameter tp : tree.typarams)
-                typeAnnotate(tp, baseEnv, sym);
+                typeAnnotate(tp, baseEnv, sym, tree.pos());
             annotate.flush();
 
             // Add default constructor if needed.
@@ -1126,6 +1148,7 @@
         } catch (CompletionFailure ex) {
             chk.completionError(tree.pos(), ex);
         } finally {
+            deferredLintHandler.setPos(prevLintPos);
             log.useSource(prev);
         }
 
@@ -1186,9 +1209,9 @@
         }
     }
 
-    public void typeAnnotate(final JCTree tree, final Env<AttrContext> env, final Symbol sym) {
+    public void typeAnnotate(final JCTree tree, final Env<AttrContext> env, final Symbol sym, DiagnosticPosition deferPos) {
         if (allowTypeAnnos) {
-            tree.accept(new TypeAnnotate(env, sym));
+            tree.accept(new TypeAnnotate(env, sym, deferPos));
         }
     }
 
@@ -1199,10 +1222,12 @@
     private class TypeAnnotate extends TreeScanner {
         private Env<AttrContext> env;
         private Symbol sym;
+        private DiagnosticPosition deferPos;
 
-        public TypeAnnotate(final Env<AttrContext> env, final Symbol sym) {
+        public TypeAnnotate(final Env<AttrContext> env, final Symbol sym, DiagnosticPosition deferPos) {
             this.env = env;
             this.sym = sym;
+            this.deferPos = deferPos;
         }
 
         void annotateTypeLater(final List<JCAnnotation> annotations) {
@@ -1210,6 +1235,8 @@
                 return;
             }
 
+            final DiagnosticPosition deferPos = this.deferPos;
+
             annotate.normal(new Annotate.Annotator() {
                 @Override
                 public String toString() {
@@ -1218,9 +1245,16 @@
                 @Override
                 public void enterAnnotation() {
                     JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
+                    DiagnosticPosition prevLintPos = null;
+
+                    if (deferPos != null) {
+                        prevLintPos = deferredLintHandler.setPos(deferPos);
+                    }
                     try {
                         actualEnterTypeAnnotations(annotations, env, sym);
                     } finally {
+                        if (prevLintPos != null)
+                            deferredLintHandler.setPos(prevLintPos);
                         log.useSource(prev);
                     }
                 }
@@ -1262,13 +1296,19 @@
 
         @Override
         public void visitVarDef(final JCVariableDecl tree) {
-            if (sym != null && sym.kind == Kinds.VAR) {
-                // Don't visit a parameter once when the sym is the method
-                // and once when the sym is the parameter.
-                scan(tree.mods);
-                scan(tree.vartype);
+            DiagnosticPosition prevPos = deferPos;
+            deferPos = tree.pos();
+            try {
+                if (sym != null && sym.kind == Kinds.VAR) {
+                    // Don't visit a parameter once when the sym is the method
+                    // and once when the sym is the parameter.
+                    scan(tree.mods);
+                    scan(tree.vartype);
+                }
+                scan(tree.init);
+            } finally {
+                deferPos = prevPos;
             }
-            scan(tree.init);
         }
 
         @Override
--- a/test/tools/javac/depDocComment/SuppressDeprecation.out	Sat Sep 14 19:04:47 2013 +0100
+++ b/test/tools/javac/depDocComment/SuppressDeprecation.out	Mon Sep 16 14:13:44 2013 +0200
@@ -1,8 +1,8 @@
-SuppressDeprecation.java:130:17: compiler.warn.has.been.deprecated: X, compiler.misc.unnamed.package
 SuppressDeprecation.java:82:10: compiler.warn.has.been.deprecated: g(), T
 SuppressDeprecation.java:83:14: compiler.warn.has.been.deprecated: g(), T
 SuppressDeprecation.java:84:9: compiler.warn.has.been.deprecated: var, T
 SuppressDeprecation.java:87:9: compiler.warn.has.been.deprecated: T(), T
 SuppressDeprecation.java:90:9: compiler.warn.has.been.deprecated: T(int), T
 SuppressDeprecation.java:98:1: compiler.warn.has.been.deprecated: T(), T
+SuppressDeprecation.java:130:17: compiler.warn.has.been.deprecated: X, compiler.misc.unnamed.package
 7 warnings
--- a/test/tools/javac/warnings/6594914/T6594914a.out	Sat Sep 14 19:04:47 2013 +0100
+++ b/test/tools/javac/warnings/6594914/T6594914a.out	Mon Sep 16 14:13:44 2013 +0200
@@ -1,7 +1,7 @@
 T6594914a.java:11:5: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
 T6594914a.java:16:16: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
-T6594914a.java:16:52: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
 T6594914a.java:16:33: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
 T6594914a.java:17:20: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6594914a.java:16:52: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
 T6594914a.java:24:9: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
 6 warnings
--- a/test/tools/javac/warnings/6594914/T6594914b.out	Sat Sep 14 19:04:47 2013 +0100
+++ b/test/tools/javac/warnings/6594914/T6594914b.out	Mon Sep 16 14:13:44 2013 +0200
@@ -1,7 +1,7 @@
 T6594914b.java:11:13: compiler.warn.sun.proprietary: sun.misc.Lock
 T6594914b.java:16:24: compiler.warn.sun.proprietary: sun.misc.Lock
-T6594914b.java:16:56: compiler.warn.sun.proprietary: sun.misc.Lock
 T6594914b.java:16:39: compiler.warn.sun.proprietary: sun.misc.Lock
 T6594914b.java:17:28: compiler.warn.sun.proprietary: sun.misc.CEFormatException
+T6594914b.java:16:56: compiler.warn.sun.proprietary: sun.misc.Lock
 T6594914b.java:24:17: compiler.warn.sun.proprietary: sun.misc.Lock
 6 warnings
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/warnings/suppress/ImplicitTest.java	Mon Sep 16 14:13:44 2013 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8021112
+ * @summary Verify that deprecated warning is printed correctly for import
+ *          statement when processing a file on demand while attributing another file.
+ * @clean pack.ImplicitUse pack.ImplicitMain pack.Dep
+ * @compile/ref=ImplicitTest.out -XDrawDiagnostics -Xlint:deprecation pack/ImplicitMain.java
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/warnings/suppress/ImplicitTest.out	Mon Sep 16 14:13:44 2013 +0200
@@ -0,0 +1,2 @@
+ImplicitUse.java:4:12: compiler.warn.has.been.deprecated: pack.Dep, pack
+1 warning
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/warnings/suppress/PackageInfo.java	Mon Sep 16 14:13:44 2013 +0200
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8021112
+ * @summary Verify that deprecated warnings are printed correctly for package-info.java
+ * @clean pack.package-info pack.DeprecatedClass
+ * @compile/ref=PackageInfo.out -XDrawDiagnostics -Xlint:deprecation pack/package-info.java pack/DeprecatedClass.java
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/warnings/suppress/PackageInfo.out	Mon Sep 16 14:13:44 2013 +0200
@@ -0,0 +1,3 @@
+package-info.java:5:12: compiler.warn.has.been.deprecated: pack.DeprecatedClass, pack
+package-info.java:2:2: compiler.warn.has.been.deprecated: pack.DeprecatedClass, pack
+2 warnings
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/warnings/suppress/T6480588.java	Mon Sep 16 14:13:44 2013 +0200
@@ -0,0 +1,36 @@
+/**
+ * @test /nodynamiccopyright/
+ * @bug 6470588
+ * @summary Verify that \\@SuppressWarnings("deprecation") works OK for all parts
+ *          of class/method/field "header", including (declaration) annotations
+ * @build VerifySuppressWarnings
+ * @compile/ref=T6480588.out -XDrawDiagnostics -Xlint:unchecked,deprecation,cast T6480588.java
+ * @run main VerifySuppressWarnings T6480588.java
+ */
+
+@DeprecatedAnnotation
+class T6480588 extends DeprecatedClass implements DeprecatedInterface {
+    @DeprecatedAnnotation
+    public DeprecatedClass method(DeprecatedClass param) throws DeprecatedClass {
+        DeprecatedClass lv = new DeprecatedClass();
+        @Deprecated
+        DeprecatedClass lvd = new DeprecatedClass();
+        return null;
+    }
+
+    @Deprecated
+    public void methodD() {
+    }
+
+    @DeprecatedAnnotation
+    DeprecatedClass field = new DeprecatedClass();
+
+    @DeprecatedAnnotation
+    class Inner extends DeprecatedClass implements DeprecatedInterface {
+    }
+
+}
+
+@Deprecated class DeprecatedClass extends Throwable { }
+@Deprecated interface DeprecatedInterface { }
+@Deprecated @interface DeprecatedAnnotation { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/warnings/suppress/T6480588.out	Mon Sep 16 14:13:44 2013 +0200
@@ -0,0 +1,18 @@
+T6480588.java:12:24: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6480588.java:12:51: compiler.warn.has.been.deprecated: DeprecatedInterface, compiler.misc.unnamed.package
+T6480588.java:11:2: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package
+T6480588.java:14:12: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6480588.java:14:65: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6480588.java:13:6: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package
+T6480588.java:14:35: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6480588.java:15:9: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6480588.java:15:34: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6480588.java:17:9: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6480588.java:17:35: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6480588.java:26:5: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6480588.java:25:6: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package
+T6480588.java:26:33: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6480588.java:29:25: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package
+T6480588.java:29:52: compiler.warn.has.been.deprecated: DeprecatedInterface, compiler.misc.unnamed.package
+T6480588.java:28:6: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package
+17 warnings
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/warnings/suppress/T8021112a.java	Mon Sep 16 14:13:44 2013 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test;
+
+/**
+ * @test
+ * @bug 8021112
+ * @summary Verify that \\@SuppressWarnings work even if the value is defined
+ *          inside the suppressed class itself, and verify that "unnecessary cast"
+ *          lint can be properly suppressed.
+ * @compile -Xlint:cast -Werror T8021112a.java
+ */
+
+import static test.T8021112a.D;
+
+@SuppressWarnings(D)
+public class T8021112a {
+    public static final String D = (String) "cast";
+}
+
+class Other {
+    public static final String D = "cast";
+    @SuppressWarnings(D)
+    public static final String D2 = (String) "cast";
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/warnings/suppress/T8021112b.java	Mon Sep 16 14:13:44 2013 +0200
@@ -0,0 +1,22 @@
+/**
+ * @test /nodynamiccopyright/
+ * @bug 8021112
+ * @summary Verify that \\@SuppressWarnings("unchecked") works correctly for lazy attrib values
+ * @build VerifySuppressWarnings
+ * @compile/ref=T8021112b.out -XDrawDiagnostics -Xlint:unchecked,deprecation,cast T8021112b.java
+ * @run main VerifySuppressWarnings T8021112b.java
+ */
+
+public class T8021112b {
+    public static final String D1 = Dep.D;
+    public static final String D2 = "";
+    public static final Object[] o = {
+        new Object() {
+            Dep d;
+        }
+    };
+}
+
+@Deprecated class Dep {
+    public static final String D = T8021112b.D2;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/warnings/suppress/T8021112b.out	Mon Sep 16 14:13:44 2013 +0200
@@ -0,0 +1,3 @@
+T8021112b.java:11:37: compiler.warn.has.been.deprecated: Dep, compiler.misc.unnamed.package
+T8021112b.java:15:13: compiler.warn.has.been.deprecated: Dep, compiler.misc.unnamed.package
+2 warnings
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/warnings/suppress/TypeAnnotations.java	Mon Sep 16 14:13:44 2013 +0200
@@ -0,0 +1,51 @@
+/**
+ * @test /nodynamiccopyright/
+ * @bug 8021112
+ * @summary Verify that \\@SuppressWarnings("unchecked") works for type annotations
+ * @build VerifySuppressWarnings
+ * @compile/ref=TypeAnnotations.out -XDrawDiagnostics -Xlint:unchecked,deprecation,cast TypeAnnotations.java
+ * @run main VerifySuppressWarnings TypeAnnotations.java
+ */
+
+import java.lang.annotation.*;
+
+public class TypeAnnotations extends @TA Object implements @TA Runnable {
+
+    public @TA String @TA [] m(@TA String @TA [] p) throws @TA Throwable {
+        Runnable r = () -> {
+            @TA Object tested = null;
+            @TA boolean isAnnotated = tested instanceof @TA String;
+        };
+
+        @TA Object tested = null;
+        @TA boolean isAnnotated = tested instanceof @TA String;
+
+        return (@TA String @TA []) null;
+    }
+
+    {
+        Runnable r = () -> {
+            @TA Object tested = null;
+            @TA boolean isAnnotated = tested instanceof @TA String;
+        };
+
+        @TA Object tested = null;
+        @TA boolean isAnnotated = tested instanceof @TA String;
+
+        @TA String @TA [] ret = (@TA String @TA []) null;
+    }
+
+    @TA String @TA [] f = new @TA String @TA[0];
+
+    @Override public void run() { }
+
+    public static class Inner extends @TA Object implements @TA Runnable {
+        @Override public void run() { }
+    }
+}
+
+@Target({ElementType.TYPE_USE, ElementType.TYPE})
+@Deprecated
+@interface TA {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/warnings/suppress/TypeAnnotations.out	Mon Sep 16 14:13:44 2013 +0200
@@ -0,0 +1,41 @@
+TypeAnnotations.java:12:39: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:12:61: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:14:24: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:14:61: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:14:13: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:14:44: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:14:33: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:23:29: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:23:18: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:16:14: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:17:58: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:17:14: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:17:58: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:20:10: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:21:54: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:21:10: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:21:54: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:23:18: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:23:29: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:28:14: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:29:58: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:29:14: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:29:58: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:32:10: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:33:54: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:33:10: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:33:54: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:35:46: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:35:35: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:35:21: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:35:10: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:35:35: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:35:46: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:38:17: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:38:6: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:38:43: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:38:32: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:38:32: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:42:40: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+TypeAnnotations.java:42:62: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package
+40 warnings
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/warnings/suppress/VerifySuppressWarnings.java	Mon Sep 16 14:13:44 2013 +0200
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import com.sun.source.tree.ClassTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.MethodTree;
+import com.sun.source.tree.NewClassTree;
+import com.sun.source.tree.Tree;
+import com.sun.source.tree.VariableTree;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.TreeScanner;
+import com.sun.source.util.Trees;
+import com.sun.tools.javac.api.JavacTool;
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.file.JavacFileManager;
+import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import javax.tools.Diagnostic;
+import javax.tools.DiagnosticListener;
+import javax.tools.FileObject;
+import javax.tools.ForwardingJavaFileManager;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+
+/**Takes a source file, parses it once to get the warnings inside the file and
+ * then for each and every declaration in the file, it tries to place
+ * the @SuppressWarnings annotation on the declaration and verifies than no
+ * warnings are produced inside the declaration, but all are produced outside it.
+ *
+ * Currently only works with <code>unchecked,deprecation,cast</code> warnings.
+ */
+public class VerifySuppressWarnings {
+
+    private static final List<String> STANDARD_PARAMS = Arrays.asList("-Xlint:unchecked,deprecation,cast", "-Xjcov");
+
+    public static void main(String... args) throws IOException, URISyntaxException {
+        if (args.length != 1) throw new IllegalStateException("Must provide class name!");
+        String testContent = null;
+        List<File> sourcePath = new ArrayList<>();
+        for (String sourcePaths : System.getProperty("test.src.path").split(":")) {
+            sourcePath.add(new File(sourcePaths));
+        }
+        JavacFileManager fm = JavacTool.create().getStandardFileManager(null, null, null);
+        for (File sp : sourcePath) {
+            File inp = new File(sp, args[0]);
+
+            if (inp.canRead()) {
+                testContent = fm.getRegularFile(inp).getCharContent(true).toString();
+            }
+        }
+        if (testContent == null) throw new IllegalStateException();
+        final List<Diagnostic<?>> diagnostics = new ArrayList<>();
+        DiagnosticListener<JavaFileObject> collectDiagnostics = new DiagnosticListener<JavaFileObject>() {
+            @Override public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+                diagnostics.add(diagnostic);
+            }
+        };
+        JavaFileObject testFile = new TestFO(new URI("mem://" + args[0]), testContent);
+        JavacTask task = JavacTool.create().getTask(null,
+                                                    new TestFM(fm),
+                                                    collectDiagnostics,
+                                                    STANDARD_PARAMS,
+                                                    null,
+                                                    Arrays.asList(testFile));
+        final Trees trees = Trees.instance(task);
+        final CompilationUnitTree cut = task.parse().iterator().next();
+        task.analyze();
+
+        final List<int[]> declarationSpans = new ArrayList<>();
+
+        new TreeScanner<Void, Void>() {
+            @Override public Void visitClass(ClassTree node, Void p) {
+                handleDeclaration(node);
+                return super.visitClass(node, p);
+            }
+            @Override public Void visitMethod(MethodTree node, Void p) {
+                handleDeclaration(node);
+                return super.visitMethod(node, p);
+            }
+            @Override public Void visitVariable(VariableTree node, Void p) {
+                handleDeclaration(node);
+                return super.visitVariable(node, p);
+            }
+
+            @Override
+            public Void visitNewClass(NewClassTree node, Void p) {
+                if (node.getClassBody() != null) {
+                    scan(node.getClassBody().getMembers(), null);
+                }
+                return null;
+            }
+
+            private void handleDeclaration(Tree node) {
+                int endPos = (int) trees.getSourcePositions().getEndPosition(cut, node);
+
+                if (endPos == (-1)) {
+                    if (node.getKind() == Tree.Kind.METHOD && (((JCMethodDecl) node).getModifiers().flags & Flags.GENERATEDCONSTR) != 0) {
+                        return ;
+                    }
+                    throw new IllegalStateException();
+                }
+
+                declarationSpans.add(new int[] {(int) trees.getSourcePositions().getStartPosition(cut, node), endPos});
+            }
+        }.scan(cut, null);
+
+        for (final int[] declarationSpan : declarationSpans) {
+            final String suppressWarnings = "@SuppressWarnings({\"deprecation\", \"unchecked\", \"serial\"})";
+            final String updatedContent = testContent.substring(0, declarationSpan[0]) + suppressWarnings + testContent.substring(declarationSpan[0]);
+            final List<Diagnostic<?>> foundErrors = new ArrayList<>(diagnostics);
+            DiagnosticListener<JavaFileObject> verifyDiagnostics = new DiagnosticListener<JavaFileObject>() {
+                @Override public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
+                    long adjustedPos = diagnostic.getPosition();
+
+                    if (adjustedPos >= declarationSpan[0]) adjustedPos -= suppressWarnings.length();
+
+                    if (declarationSpan[0] <= adjustedPos && adjustedPos <= declarationSpan[1]) {
+                        throw new IllegalStateException("unsuppressed: " + diagnostic.getMessage(null));
+                    }
+
+                    boolean found = false;
+
+                    for (Iterator<Diagnostic<?>> it = foundErrors.iterator(); it.hasNext();) {
+                        Diagnostic<?> d = it.next();
+                        if (d.getPosition() == adjustedPos && d.getCode().equals(diagnostic.getCode())) {
+                            it.remove();
+                            found = true;
+                            break;
+                        }
+                    }
+
+                    if (!found) {
+                        throw new IllegalStateException("diagnostic not originally reported: " + diagnostic.getMessage(null));
+                    }
+                }
+            };
+
+            JavaFileObject updatedFile = new TestFO(new URI("mem://" + args[0]), updatedContent);
+            JavacTask testTask = JavacTool.create().getTask(null,
+                                                            new TestFM(fm),
+                                                            verifyDiagnostics,
+                                                            STANDARD_PARAMS,
+                                                            null,
+                                                            Arrays.asList(updatedFile));
+
+            testTask.analyze();
+
+            for (Diagnostic<?> d : foundErrors) {
+                if (d.getPosition() < declarationSpan[0] || declarationSpan[1] < d.getPosition()) {
+                    throw new IllegalStateException("missing: " + d.getMessage(null));
+                }
+            }
+        }
+    }
+
+    private static final class TestFO extends SimpleJavaFileObject {
+        private final String content;
+        public TestFO(URI uri, String content) {
+            super(uri, Kind.SOURCE);
+            this.content = content;
+        }
+
+        @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+            return content;
+        }
+
+        @Override public boolean isNameCompatible(String simpleName, Kind kind) {
+            return true;
+        }
+    }
+
+    private static final class TestFM extends ForwardingJavaFileManager<JavaFileManager> {
+
+        public TestFM(JavaFileManager fileManager) {
+            super(fileManager);
+        }
+
+        @Override
+        public boolean isSameFile(FileObject a, FileObject b) {
+            return a.equals(b);
+        }
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/warnings/suppress/pack/DeprecatedClass.java	Mon Sep 16 14:13:44 2013 +0200
@@ -0,0 +1,5 @@
+/* /nodynamiccopyright/ */
+package pack;
+@Deprecated
+@interface DeprecatedClass {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/warnings/suppress/pack/ImplicitMain.java	Mon Sep 16 14:13:44 2013 +0200
@@ -0,0 +1,14 @@
+/* /nodynamiccopyright/ */
+package pack;
+
+@SuppressWarnings("deprecation")
+public class ImplicitMain {
+    private Object test() {
+        return new ImplicitUse();
+    }
+}
+
+@Deprecated
+class Dep {
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/warnings/suppress/pack/ImplicitUse.java	Mon Sep 16 14:13:44 2013 +0200
@@ -0,0 +1,7 @@
+/* /nodynamiccopyright/ */
+package pack;
+
+import pack.Dep;
+
+public class ImplicitUse {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/tools/javac/warnings/suppress/pack/package-info.java	Mon Sep 16 14:13:44 2013 +0200
@@ -0,0 +1,5 @@
+/* /nodynamiccopyright/ */
+@DeprecatedClass
+package pack;
+
+import pack.DeprecatedClass;