Skip to content

Commit

Permalink
8316971: Add Lint warning for restricted method calls
Browse files Browse the repository at this point in the history
Reviewed-by: ihse, vromero
  • Loading branch information
mcimadamore committed Oct 4, 2023
1 parent d4c904d commit 0d4de8a
Show file tree
Hide file tree
Showing 15 changed files with 119 additions and 4 deletions.
2 changes: 1 addition & 1 deletion make/modules/java.base/Java.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
# questions.
#

DISABLED_WARNINGS_java += this-escape
DISABLED_WARNINGS_java += this-escape restricted

DOCLINT += -Xdoclint:all/protected \
'-Xdoclint/package:java.*,javax.*'
Expand Down
2 changes: 1 addition & 1 deletion make/test/BuildMicrobenchmark.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \
TARGET_RELEASE := $(TARGET_RELEASE_NEWJDK_UPGRADED), \
SMALL_JAVA := false, \
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), \
BIN := $(MICROBENCHMARK_CLASSES), \
JAVAC_FLAGS := --add-exports java.base/sun.security.util=ALL-UNNAMED \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,13 +389,18 @@ public static EnumSet<Flag> asFlagSet(long flags) {
*/
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.
*/
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.
*/
public static String toSource(long flags) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,12 @@ public enum LintCategory {
/**
* Warn about use of preview features.
*/
PREVIEW("preview");
PREVIEW("preview"),

/**
* Warn about use of restricted methods.
*/
RESTRICTED("restricted");

LintCategory(String option) {
this(option, false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ public static Symtab instance(Context context) {
public final Type functionalInterfaceType;
public final Type previewFeatureType;
public final Type previewFeatureInternalType;
public final Type restrictedType;
public final Type typeDescriptorType;
public final Type recordType;
public final Type switchBootstrapsType;
Expand Down Expand Up @@ -610,6 +611,7 @@ public <R, P> R accept(ElementVisitor<R, P> v, P p) {
functionalInterfaceType = enterClass("java.lang.FunctionalInterface");
previewFeatureType = enterClass("jdk.internal.javac.PreviewFeature");
previewFeatureInternalType = enterSyntheticAnnotation("jdk.internal.PreviewFeature+Annotation");
restrictedType = enterClass("jdk.internal.javac.Restricted");
typeDescriptorType = enterClass("java.lang.invoke.TypeDescriptor");
recordType = enterClass("java.lang.Record");
switchBootstrapsType = enterClass("java.lang.runtime.SwitchBootstraps");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,11 @@ private <T extends Attribute.Compound> void annotateNow(Symbol toAnnotate,
&& types.isSameType(c.type, syms.valueBasedType)) {
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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4742,6 +4742,7 @@ else if (ownOuter.hasTag(CLASS) && site != ownOuter) {
new ResultInfo(resultInfo.pkind, resultInfo.pt.getReturnType(), resultInfo.checkContext, resultInfo.checkMode),
env, TreeInfo.args(env.tree), resultInfo.pt.getParameterTypes(),
resultInfo.pt.getTypeArguments());
chk.checkRestricted(tree.pos(), sym);
break;
}
case PCK: case ERR:
Expand Down
15 changes: 15 additions & 0 deletions src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,15 @@ public void warnDeclaredUsingPreview(DiagnosticPosition pos, Symbol 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.
* @param pos Position to be used for error reporting.
* @param msg A string describing the problem.
Expand Down Expand Up @@ -3850,6 +3859,12 @@ void checkPreview(DiagnosticPosition pos, Symbol other, Symbol s) {
}
}

void checkRestricted(DiagnosticPosition pos, Symbol s) {
if (s.kind == MTH && (s.flags() & RESTRICTED) != 0) {
deferredLintHandler.report(() -> warnRestrictedAPI(pos, s));
}
}

/* *************************************************************************
* Check for recursive annotation elements.
**************************************************************************/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1509,6 +1509,9 @@ else if (proxy.type.tsym.flatName() == syms.profileType.tsym.flatName()) {
} else if (proxy.type.tsym.flatName() == syms.valueBasedInternalType.tsym.flatName()) {
Assert.check(sym.kind == TYP);
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 {
if (proxy.type.tsym == syms.annotationTargetType.tsym) {
target = proxy;
Expand All @@ -1522,6 +1525,9 @@ else if (proxy.type.tsym.flatName() == syms.profileType.tsym.flatName()) {
setFlagIfAttributeTrue(proxy, sym, names.reflective, PREVIEW_REFLECTIVE);
} else if (proxy.type.tsym == syms.valueBasedType.tsym && sym.kind == TYP) {
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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1917,6 +1917,11 @@ compiler.err.is.preview=\
compiler.warn.is.preview.reflective=\
{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
compiler.warn.has.been.deprecated.module=\
module {0} has been deprecated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ javac.opt.Xlint.desc.varargs=\
javac.opt.Xlint.desc.preview=\
Warn about use of preview language features.

javac.opt.Xlint.desc.restricted=\
Warn about use of restricted methods.

javac.opt.Xlint.desc.synchronization=\
Warn about synchronization attempts on instances of value-based classes.

Expand Down
1 change: 1 addition & 0 deletions src/jdk.compiler/share/classes/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@
* <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 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-transitive-automatic} <td>automatic modules in {@code requires transitive}
* <tr><th scope="row">{@code serial} <td>{@link java.base/java.io.Serializable Serializable} classes
Expand Down
55 changes: 55 additions & 0 deletions test/langtools/tools/javac/RestrictedMethods.java
Original file line number Diff line number Diff line change
@@ -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 changes: 9 additions & 0 deletions test/langtools/tools/javac/RestrictedMethods.out
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions test/langtools/tools/javac/diags/examples.not-yet.txt
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,6 @@ compiler.misc.illegal.signature # the compiler can

# this one needs a forged class file to be reproduced
compiler.err.annotation.unrecognized.attribute.name

# this one is transitional (waiting for FFM API to exit preview)
compiler.warn.restricted.method

1 comment on commit 0d4de8a

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.