8316971: Add Lint warning for restricted method calls
Reviewed-by: ihse, vromero
This commit is contained in:
parent
d4c904d819
commit
0d4de8a71f
@ -23,7 +23,7 @@
|
|||||||
# questions.
|
# questions.
|
||||||
#
|
#
|
||||||
|
|
||||||
DISABLED_WARNINGS_java += this-escape
|
DISABLED_WARNINGS_java += this-escape restricted
|
||||||
|
|
||||||
DOCLINT += -Xdoclint:all/protected \
|
DOCLINT += -Xdoclint:all/protected \
|
||||||
'-Xdoclint/package:java.*,javax.*'
|
'-Xdoclint/package:java.*,javax.*'
|
||||||
|
@ -91,7 +91,7 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \
|
|||||||
TARGET_RELEASE := $(TARGET_RELEASE_NEWJDK_UPGRADED), \
|
TARGET_RELEASE := $(TARGET_RELEASE_NEWJDK_UPGRADED), \
|
||||||
SMALL_JAVA := false, \
|
SMALL_JAVA := false, \
|
||||||
CLASSPATH := $(MICROBENCHMARK_CLASSPATH), \
|
CLASSPATH := $(MICROBENCHMARK_CLASSPATH), \
|
||||||
DISABLED_WARNINGS := this-escape processing rawtypes cast serial preview, \
|
DISABLED_WARNINGS := restricted this-escape processing rawtypes cast serial preview, \
|
||||||
SRC := $(MICROBENCHMARK_SRC), \
|
SRC := $(MICROBENCHMARK_SRC), \
|
||||||
BIN := $(MICROBENCHMARK_CLASSES), \
|
BIN := $(MICROBENCHMARK_CLASSES), \
|
||||||
JAVAC_FLAGS := --add-exports java.base/sun.security.util=ALL-UNNAMED \
|
JAVAC_FLAGS := --add-exports java.base/sun.security.util=ALL-UNNAMED \
|
||||||
|
@ -389,13 +389,18 @@ public class Flags {
|
|||||||
*/
|
*/
|
||||||
public static final long SEALED = 1L<<62; // ClassSymbols
|
public static final long SEALED = 1L<<62; // ClassSymbols
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flag to indicate restricted method declaration.
|
||||||
|
*/
|
||||||
|
public static final long RESTRICTED = 1L<<62; // MethodSymbols
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag to indicate that the class/interface was declared with the non-sealed modifier.
|
* Flag to indicate that the class/interface was declared with the non-sealed modifier.
|
||||||
*/
|
*/
|
||||||
public static final long NON_SEALED = 1L<<63; // ClassSymbols
|
public static final long NON_SEALED = 1L<<63; // ClassSymbols
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Describe modifier flags as they migh appear in source code, i.e.,
|
* Describe modifier flags as they might appear in source code, i.e.,
|
||||||
* separated by spaces and in the order suggested by JLS 8.1.1.
|
* separated by spaces and in the order suggested by JLS 8.1.1.
|
||||||
*/
|
*/
|
||||||
public static String toSource(long flags) {
|
public static String toSource(long flags) {
|
||||||
|
@ -335,7 +335,12 @@ public class Lint
|
|||||||
/**
|
/**
|
||||||
* Warn about use of preview features.
|
* Warn about use of preview features.
|
||||||
*/
|
*/
|
||||||
PREVIEW("preview");
|
PREVIEW("preview"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warn about use of restricted methods.
|
||||||
|
*/
|
||||||
|
RESTRICTED("restricted");
|
||||||
|
|
||||||
LintCategory(String option) {
|
LintCategory(String option) {
|
||||||
this(option, false);
|
this(option, false);
|
||||||
|
@ -220,6 +220,7 @@ public class Symtab {
|
|||||||
public final Type functionalInterfaceType;
|
public final Type functionalInterfaceType;
|
||||||
public final Type previewFeatureType;
|
public final Type previewFeatureType;
|
||||||
public final Type previewFeatureInternalType;
|
public final Type previewFeatureInternalType;
|
||||||
|
public final Type restrictedType;
|
||||||
public final Type typeDescriptorType;
|
public final Type typeDescriptorType;
|
||||||
public final Type recordType;
|
public final Type recordType;
|
||||||
public final Type switchBootstrapsType;
|
public final Type switchBootstrapsType;
|
||||||
@ -610,6 +611,7 @@ public class Symtab {
|
|||||||
functionalInterfaceType = enterClass("java.lang.FunctionalInterface");
|
functionalInterfaceType = enterClass("java.lang.FunctionalInterface");
|
||||||
previewFeatureType = enterClass("jdk.internal.javac.PreviewFeature");
|
previewFeatureType = enterClass("jdk.internal.javac.PreviewFeature");
|
||||||
previewFeatureInternalType = enterSyntheticAnnotation("jdk.internal.PreviewFeature+Annotation");
|
previewFeatureInternalType = enterSyntheticAnnotation("jdk.internal.PreviewFeature+Annotation");
|
||||||
|
restrictedType = enterClass("jdk.internal.javac.Restricted");
|
||||||
typeDescriptorType = enterClass("java.lang.invoke.TypeDescriptor");
|
typeDescriptorType = enterClass("java.lang.invoke.TypeDescriptor");
|
||||||
recordType = enterClass("java.lang.Record");
|
recordType = enterClass("java.lang.Record");
|
||||||
switchBootstrapsType = enterClass("java.lang.runtime.SwitchBootstraps");
|
switchBootstrapsType = enterClass("java.lang.runtime.SwitchBootstraps");
|
||||||
|
@ -379,6 +379,11 @@ public class Annotate {
|
|||||||
&& types.isSameType(c.type, syms.valueBasedType)) {
|
&& types.isSameType(c.type, syms.valueBasedType)) {
|
||||||
toAnnotate.flags_field |= Flags.VALUE_BASED;
|
toAnnotate.flags_field |= Flags.VALUE_BASED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!c.type.isErroneous()
|
||||||
|
&& types.isSameType(c.type, syms.restrictedType)) {
|
||||||
|
toAnnotate.flags_field |= Flags.RESTRICTED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<T> buf = List.nil();
|
List<T> buf = List.nil();
|
||||||
|
@ -4742,6 +4742,7 @@ public class Attr extends JCTree.Visitor {
|
|||||||
new ResultInfo(resultInfo.pkind, resultInfo.pt.getReturnType(), resultInfo.checkContext, resultInfo.checkMode),
|
new ResultInfo(resultInfo.pkind, resultInfo.pt.getReturnType(), resultInfo.checkContext, resultInfo.checkMode),
|
||||||
env, TreeInfo.args(env.tree), resultInfo.pt.getParameterTypes(),
|
env, TreeInfo.args(env.tree), resultInfo.pt.getParameterTypes(),
|
||||||
resultInfo.pt.getTypeArguments());
|
resultInfo.pt.getTypeArguments());
|
||||||
|
chk.checkRestricted(tree.pos(), sym);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PCK: case ERR:
|
case PCK: case ERR:
|
||||||
|
@ -283,6 +283,15 @@ public class Check {
|
|||||||
preview.reportPreviewWarning(pos, Warnings.DeclaredUsingPreview(kindName(sym), sym));
|
preview.reportPreviewWarning(pos, Warnings.DeclaredUsingPreview(kindName(sym), sym));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Log a preview warning.
|
||||||
|
* @param pos Position to be used for error reporting.
|
||||||
|
* @param msg A Warning describing the problem.
|
||||||
|
*/
|
||||||
|
public void warnRestrictedAPI(DiagnosticPosition pos, Symbol sym) {
|
||||||
|
if (lint.isEnabled(LintCategory.RESTRICTED))
|
||||||
|
log.warning(LintCategory.RESTRICTED, pos, Warnings.RestrictedMethod(sym.enclClass(), sym));
|
||||||
|
}
|
||||||
|
|
||||||
/** Warn about unchecked operation.
|
/** Warn about unchecked operation.
|
||||||
* @param pos Position to be used for error reporting.
|
* @param pos Position to be used for error reporting.
|
||||||
* @param msg A string describing the problem.
|
* @param msg A string describing the problem.
|
||||||
@ -3850,6 +3859,12 @@ public class Check {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void checkRestricted(DiagnosticPosition pos, Symbol s) {
|
||||||
|
if (s.kind == MTH && (s.flags() & RESTRICTED) != 0) {
|
||||||
|
deferredLintHandler.report(() -> warnRestrictedAPI(pos, s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* *************************************************************************
|
/* *************************************************************************
|
||||||
* Check for recursive annotation elements.
|
* Check for recursive annotation elements.
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
@ -1509,6 +1509,9 @@ public class ClassReader {
|
|||||||
} else if (proxy.type.tsym.flatName() == syms.valueBasedInternalType.tsym.flatName()) {
|
} else if (proxy.type.tsym.flatName() == syms.valueBasedInternalType.tsym.flatName()) {
|
||||||
Assert.check(sym.kind == TYP);
|
Assert.check(sym.kind == TYP);
|
||||||
sym.flags_field |= VALUE_BASED;
|
sym.flags_field |= VALUE_BASED;
|
||||||
|
} else if (proxy.type.tsym.flatName() == syms.restrictedType.tsym.flatName()) {
|
||||||
|
Assert.check(sym.kind == MTH);
|
||||||
|
sym.flags_field |= RESTRICTED;
|
||||||
} else {
|
} else {
|
||||||
if (proxy.type.tsym == syms.annotationTargetType.tsym) {
|
if (proxy.type.tsym == syms.annotationTargetType.tsym) {
|
||||||
target = proxy;
|
target = proxy;
|
||||||
@ -1522,6 +1525,9 @@ public class ClassReader {
|
|||||||
setFlagIfAttributeTrue(proxy, sym, names.reflective, PREVIEW_REFLECTIVE);
|
setFlagIfAttributeTrue(proxy, sym, names.reflective, PREVIEW_REFLECTIVE);
|
||||||
} else if (proxy.type.tsym == syms.valueBasedType.tsym && sym.kind == TYP) {
|
} else if (proxy.type.tsym == syms.valueBasedType.tsym && sym.kind == TYP) {
|
||||||
sym.flags_field |= VALUE_BASED;
|
sym.flags_field |= VALUE_BASED;
|
||||||
|
} else if (proxy.type.tsym == syms.restrictedType.tsym) {
|
||||||
|
Assert.check(sym.kind == MTH);
|
||||||
|
sym.flags_field |= RESTRICTED;
|
||||||
}
|
}
|
||||||
proxies.append(proxy);
|
proxies.append(proxy);
|
||||||
}
|
}
|
||||||
|
@ -1917,6 +1917,11 @@ compiler.err.is.preview=\
|
|||||||
compiler.warn.is.preview.reflective=\
|
compiler.warn.is.preview.reflective=\
|
||||||
{0} is a reflective preview API and may be removed in a future release.
|
{0} is a reflective preview API and may be removed in a future release.
|
||||||
|
|
||||||
|
# 0: symbol, 1: symbol
|
||||||
|
compiler.warn.restricted.method=\
|
||||||
|
{0}.{1} is a restricted method.\n\
|
||||||
|
(Restricted methods are unsafe and, if used incorrectly, might crash the Java runtime or corrupt memory)
|
||||||
|
|
||||||
# 0: symbol
|
# 0: symbol
|
||||||
compiler.warn.has.been.deprecated.module=\
|
compiler.warn.has.been.deprecated.module=\
|
||||||
module {0} has been deprecated
|
module {0} has been deprecated
|
||||||
|
@ -282,6 +282,9 @@ javac.opt.Xlint.desc.varargs=\
|
|||||||
javac.opt.Xlint.desc.preview=\
|
javac.opt.Xlint.desc.preview=\
|
||||||
Warn about use of preview language features.
|
Warn about use of preview language features.
|
||||||
|
|
||||||
|
javac.opt.Xlint.desc.restricted=\
|
||||||
|
Warn about use of restricted methods.
|
||||||
|
|
||||||
javac.opt.Xlint.desc.synchronization=\
|
javac.opt.Xlint.desc.synchronization=\
|
||||||
Warn about synchronization attempts on instances of value-based classes.
|
Warn about synchronization attempts on instances of value-based classes.
|
||||||
|
|
||||||
|
@ -173,6 +173,7 @@ import javax.tools.StandardLocation;
|
|||||||
* <tr><th scope="row">{@code preview} <td>use of preview language features
|
* <tr><th scope="row">{@code preview} <td>use of preview language features
|
||||||
* <tr><th scope="row">{@code rawtypes} <td>use of raw types
|
* <tr><th scope="row">{@code rawtypes} <td>use of raw types
|
||||||
* <tr><th scope="row">{@code removal} <td>use of API that has been marked for removal
|
* <tr><th scope="row">{@code removal} <td>use of API that has been marked for removal
|
||||||
|
* <tr><th scope="row">{@code restricted} <td>use of restricted methods
|
||||||
* <tr><th scope="row">{@code requires-automatic} <td>use of automatic modules in the {@code requires} clauses
|
* <tr><th scope="row">{@code requires-automatic} <td>use of automatic modules in the {@code requires} clauses
|
||||||
* <tr><th scope="row">{@code requires-transitive-automatic} <td>automatic modules in {@code requires transitive}
|
* <tr><th scope="row">{@code requires-transitive-automatic} <td>automatic modules in {@code requires transitive}
|
||||||
* <tr><th scope="row">{@code serial} <td>{@link java.base/java.io.Serializable Serializable} classes
|
* <tr><th scope="row">{@code serial} <td>{@link java.base/java.io.Serializable Serializable} classes
|
||||||
|
55
test/langtools/tools/javac/RestrictedMethods.java
Normal file
55
test/langtools/tools/javac/RestrictedMethods.java
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* @test /nodynamiccopyright/
|
||||||
|
* @bug 8316971
|
||||||
|
* @summary Smoke test for restricted method call warnings
|
||||||
|
* @compile/fail/ref=RestrictedMethods.out -Xlint:restricted -Werror -XDrawDiagnostics --enable-preview --source ${jdk.version} RestrictedMethods.java
|
||||||
|
* @compile -Werror --enable-preview --source ${jdk.version} RestrictedMethods.java
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.lang.foreign.MemorySegment;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
class RestrictedMethods {
|
||||||
|
|
||||||
|
MemorySegment warn = MemorySegment.NULL.reinterpret(10); // warning here
|
||||||
|
@SuppressWarnings("restricted")
|
||||||
|
MemorySegment suppressed = MemorySegment.NULL.reinterpret(10); // no warning here
|
||||||
|
|
||||||
|
Function<Integer, MemorySegment> warn_ref = MemorySegment.NULL::reinterpret; // warning here
|
||||||
|
|
||||||
|
@SuppressWarnings("restricted")
|
||||||
|
Function<Integer, MemorySegment> suppressed_ref = MemorySegment.NULL::reinterpret; // no warning here
|
||||||
|
|
||||||
|
void testWarn() {
|
||||||
|
MemorySegment.NULL.reinterpret(10); // warning here
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("restricted")
|
||||||
|
void testSuppressed() {
|
||||||
|
MemorySegment.NULL.reinterpret(10); // no warning here
|
||||||
|
}
|
||||||
|
|
||||||
|
Function<Integer, MemorySegment> testWarnRef() {
|
||||||
|
return MemorySegment.NULL::reinterpret; // warning here
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("restricted")
|
||||||
|
Function<Integer, MemorySegment> testSuppressedRef() {
|
||||||
|
return MemorySegment.NULL::reinterpret; // no warning here
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("restricted")
|
||||||
|
static class Nested {
|
||||||
|
MemorySegment suppressedNested = MemorySegment.NULL.reinterpret(10); // no warning here
|
||||||
|
|
||||||
|
Function<Integer, MemorySegment> suppressedNested_ref = MemorySegment.NULL::reinterpret; // no warning here
|
||||||
|
|
||||||
|
void testSuppressedNested() {
|
||||||
|
MemorySegment.NULL.reinterpret(10); // no warning here
|
||||||
|
}
|
||||||
|
|
||||||
|
Function<Integer, MemorySegment> testSuppressedNestedRef() {
|
||||||
|
return MemorySegment.NULL::reinterpret; // no warning here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
test/langtools/tools/javac/RestrictedMethods.out
Normal file
9
test/langtools/tools/javac/RestrictedMethods.out
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
RestrictedMethods.java:14:44: compiler.warn.restricted.method: java.lang.foreign.MemorySegment, reinterpret(long)
|
||||||
|
RestrictedMethods.java:18:49: compiler.warn.restricted.method: java.lang.foreign.MemorySegment, reinterpret(long)
|
||||||
|
RestrictedMethods.java:24:27: compiler.warn.restricted.method: java.lang.foreign.MemorySegment, reinterpret(long)
|
||||||
|
RestrictedMethods.java:33:16: compiler.warn.restricted.method: java.lang.foreign.MemorySegment, reinterpret(long)
|
||||||
|
- compiler.err.warnings.and.werror
|
||||||
|
- compiler.note.preview.filename: RestrictedMethods.java, DEFAULT
|
||||||
|
- compiler.note.preview.recompile
|
||||||
|
1 error
|
||||||
|
4 warnings
|
@ -215,3 +215,6 @@ compiler.misc.illegal.signature # the compiler can
|
|||||||
|
|
||||||
# this one needs a forged class file to be reproduced
|
# this one needs a forged class file to be reproduced
|
||||||
compiler.err.annotation.unrecognized.attribute.name
|
compiler.err.annotation.unrecognized.attribute.name
|
||||||
|
|
||||||
|
# this one is transitional (waiting for FFM API to exit preview)
|
||||||
|
compiler.warn.restricted.method
|
||||||
|
Loading…
x
Reference in New Issue
Block a user