--- a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java Tue Jun 24 16:04:46 2014 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java Tue Jun 24 10:51:00 2014 -0700
@@ -240,6 +240,9 @@
public boolean allowPostApplicabilityVarargsAccessCheck() {
return compareTo(JDK1_8) >= 0;
}
+ public boolean allowPrivateSafeVarargs() {
+ return compareTo(JDK1_9) >= 0;
+ }
public static SourceVersion toSourceVersion(Source source) {
switch(source) {
case JDK1_2:
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Jun 24 16:04:46 2014 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Tue Jun 24 10:51:00 2014 -0700
@@ -127,6 +127,7 @@
allowSimplifiedVarargs = source.allowSimplifiedVarargs();
allowDefaultMethods = source.allowDefaultMethods();
allowStrictMethodClashCheck = source.allowStrictMethodClashCheck();
+ allowPrivateSafeVarargs = source.allowPrivateSafeVarargs();
complexInference = options.isSet("complexinference");
warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts");
suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile");
@@ -181,6 +182,10 @@
*/
boolean allowStrictMethodClashCheck;
+ /** Switch: can the @SafeVarargs annotation be applied to private methods?
+ */
+ boolean allowPrivateSafeVarargs;
+
/** Switch: -complexinference option set?
*/
boolean complexInference;
@@ -816,8 +821,10 @@
if (varargElemType != null) {
log.error(tree,
"varargs.invalid.trustme.anno",
- syms.trustMeType.tsym,
- diags.fragment("varargs.trustme.on.virtual.varargs", m));
+ syms.trustMeType.tsym,
+ allowPrivateSafeVarargs ?
+ diags.fragment("varargs.trustme.on.virtual.varargs", m) :
+ diags.fragment("varargs.trustme.on.virtual.varargs.final.only", m));
} else {
log.error(tree,
"varargs.invalid.trustme.anno",
@@ -840,7 +847,8 @@
private boolean isTrustMeAllowedOnMethod(Symbol s) {
return (s.flags() & VARARGS) != 0 &&
(s.isConstructor() ||
- (s.flags() & (STATIC | FINAL)) != 0);
+ (s.flags() & (STATIC | FINAL |
+ (allowPrivateSafeVarargs ? PRIVATE : 0) )) != 0);
}
Type checkMethod(final Type mtype,
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Jun 24 16:04:46 2014 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Tue Jun 24 10:51:00 2014 -0700
@@ -1101,6 +1101,10 @@
# 0: symbol
compiler.misc.varargs.trustme.on.virtual.varargs=\
+ Instance method {0} is neither final nor private.
+
+# 0: symbol
+compiler.misc.varargs.trustme.on.virtual.varargs.final.only=\
Instance method {0} is not final.
# 0: type, 1: symbol kind, 2: symbol
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/VarargsFinalOnly.java Tue Jun 24 10:51:00 2014 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// key: compiler.err.varargs.invalid.trustme.anno
+// key: compiler.misc.varargs.trustme.on.virtual.varargs.final.only
+// options: -source 1.8 -Xlint:varargs,-options,-unchecked
+
+import java.util.List;
+
+class VarargsFinalOnly {
+ @SafeVarargs void m(List<String>... args) { }
+}
--- a/langtools/test/tools/javac/varargs/warning/Warn4.java Tue Jun 24 16:04:46 2014 +0100
+++ b/langtools/test/tools/javac/varargs/warning/Warn4.java Tue Jun 24 10:51:00 2014 -0700
@@ -73,13 +73,15 @@
ModifierKind modKind) {
switch(this) {
case VARARGS:
- return source == SourceLevel.JDK_6 ||
+ return source.compareTo(SourceLevel.JDK_7) < 0 ||
suppressLevelDecl == SuppressLevel.UNCHECKED ||
trustMe == TrustMe.TRUST;
case UNCHECKED:
return suppressLevelClient == SuppressLevel.UNCHECKED ||
- (trustMe == TrustMe.TRUST && modKind !=
- ModifierKind.NONE && source == SourceLevel.JDK_7);
+ (trustMe == TrustMe.TRUST &&
+ (((modKind == ModifierKind.FINAL || modKind == ModifierKind.STATIC) &&
+ source.compareTo( SourceLevel.JDK_7) >= 0 ) ||
+ (modKind == ModifierKind.PRIVATE && source.compareTo( SourceLevel.JDK_9) >= 0 )));
}
SuppressLevel supLev = this == VARARGS ?
@@ -92,7 +94,8 @@
enum SourceLevel {
JDK_6("6"),
- JDK_7("7");
+ JDK_7("7"),
+ JDK_9("9");
String sourceKey;
@@ -115,7 +118,8 @@
enum ModifierKind {
NONE(" "),
FINAL("final "),
- STATIC("static ");
+ STATIC("static "),
+ PRIVATE("private ");
String mod;
--- a/langtools/test/tools/javac/varargs/warning/Warn5.java Tue Jun 24 16:04:46 2014 +0100
+++ b/langtools/test/tools/javac/varargs/warning/Warn5.java Tue Jun 24 10:51:00 2014 -0700
@@ -89,7 +89,8 @@
enum ModifierKind {
NONE(""),
FINAL("final"),
- STATIC("static");
+ STATIC("static"),
+ PRIVATE("private");
String mod;
@@ -111,7 +112,8 @@
enum SourceLevel {
JDK_6("6"),
- JDK_7("7");
+ JDK_7("7"),
+ JDK_9("9");
String sourceKey;
@@ -238,7 +240,7 @@
EnumSet<WarningKind> expectedWarnings =
EnumSet.noneOf(WarningKind.class);
- if (sourceLevel == SourceLevel.JDK_7 &&
+ if (sourceLevel.compareTo(SourceLevel.JDK_7) >= 0 &&
trustMe == TrustMe.TRUST &&
suppressLevel != SuppressLevel.VARARGS &&
xlint != XlintOption.NONE &&
@@ -247,11 +249,12 @@
body.hasAliasing &&
(methKind == MethodKind.CONSTRUCTOR ||
(methKind == MethodKind.METHOD &&
- modKind != ModifierKind.NONE))) {
+ modKind == ModifierKind.FINAL || modKind == ModifierKind.STATIC ||
+ (modKind == ModifierKind.PRIVATE && sourceLevel.compareTo(SourceLevel.JDK_9) >= 0)))) {
expectedWarnings.add(WarningKind.UNSAFE_BODY);
}
- if (sourceLevel == SourceLevel.JDK_7 &&
+ if (sourceLevel.compareTo(SourceLevel.JDK_7) >= 0 &&
trustMe == TrustMe.DONT_TRUST &&
sig.isVarargs &&
!sig.isReifiableArg &&
@@ -259,20 +262,22 @@
expectedWarnings.add(WarningKind.UNSAFE_DECL);
}
- if (sourceLevel == SourceLevel.JDK_7 &&
+ if (sourceLevel.compareTo(SourceLevel.JDK_7) >= 0 &&
trustMe == TrustMe.TRUST &&
(!sig.isVarargs ||
- (modKind == ModifierKind.NONE &&
- methKind == MethodKind.METHOD))) {
+ ((modKind == ModifierKind.NONE ||
+ modKind == ModifierKind.PRIVATE && sourceLevel.compareTo(SourceLevel.JDK_9) < 0 ) &&
+ methKind == MethodKind.METHOD))) {
expectedWarnings.add(WarningKind.MALFORMED_SAFEVARARGS);
}
- if (sourceLevel == SourceLevel.JDK_7 &&
+ if (sourceLevel.compareTo(SourceLevel.JDK_7) >= 0 &&
trustMe == TrustMe.TRUST &&
xlint != XlintOption.NONE &&
suppressLevel != SuppressLevel.VARARGS &&
- (modKind != ModifierKind.NONE ||
- methKind == MethodKind.CONSTRUCTOR) &&
+ (modKind == ModifierKind.FINAL || modKind == ModifierKind.STATIC ||
+ (modKind == ModifierKind.PRIVATE && sourceLevel.compareTo(SourceLevel.JDK_9) >= 0) ||
+ methKind == MethodKind.CONSTRUCTOR) &&
sig.isVarargs &&
sig.isReifiableArg) {
expectedWarnings.add(WarningKind.REDUNDANT_SAFEVARARGS);
@@ -283,6 +288,7 @@
throw new Error("invalid diagnostics for source:\n" +
source.getCharContent(true) +
"\nOptions: " + xlint.getXlintOption() +
+ "\nSource Level: " + sourceLevel +
"\nExpected warnings: " + expectedWarnings +
"\nFound warnings: " + dc.warnings);
}