Summary
In JDK versions up to 24, the effect of specifying a conflicting pair of lint flags for the options
category, for example -Xlint:options -Xlint:-options
or -Xlint:options -Xlint:none
, was that the "negative" flag always took precedence. In other words, both of those combinations would result in no warning.
This was inadvertently flipped in the fix for JDK-8354556, in combination with JDK-8352612, both of which are included in JDK 25.
This CSR seeks to revert to the prior behavior in JDK 25 and above.
Problem
The compiler's behavior when both positive and negative -Xlint
flags for the same lint category are given is unspecified. Moreover, the undocumented behavior is not even consistent - it depends on how a particular warning is implemented.
In any case, the fix for JDK-8354556 changed how some of these warnings behave, so that -Xlint:options
now wins whereas previously -Xlint:-options
or -Xlint:none
would win.
Although this is something of a weird corner case, many build systems add flags in multiple stages and this can easily result in both flags being added, and so the behavior in this scenario needs to stay consistent.
Solution
Revert to the prior behavior in the master branch (JDK 26) and not-yet-released JDK 25.
This will ensure this change in behavior does not escape into any official release.
Specification
Using this warning as an example:
warning: [options] location of system modules is not set in conjunction with -source 21
The code that produces this warning was changed by JDK-8354556 as follows:
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java
@@ -577,7 +576,7 @@ public boolean validate() {
reportDiag(Errors.SourcepathModulesourcepathConflict);
}
- boolean lintOptions = options.isUnset(Option.XLINT_CUSTOM, "-" + LintCategory.OPTIONS.option);
+ boolean lintOptions = !options.isExplicitlyDisabled(Option.XLINT, LintCategory.OPTIONS);
if (lintOptions && source.compareTo(Source.DEFAULT) < 0 && !options.isSet(Option.RELEASE)) {
if (fm instanceof BaseFileManager baseFileManager) {
if (source.compareTo(Source.JDK8) <= 0) {
if (baseFileManager.isDefaultBootClassPath())
log.warning(LintWarnings.SourceNoBootclasspath(source.name, releaseNote(source, targetString)));
In other words, previously there was a check for an explicit Xlint:-options
flag and all other -Xlint
flags (including -Xlint:options
) were being ignored.
The current implementation of Options.isExplicitlyDisabled()
checks for -Xlint:-options
but also checks for competing -Xlint
, -Xlint:all
and -Xlint:options
flags. So this changes the behavior when conflicting flags are given.
The fix is to change the code to invoke a new method Options.isDisabled()
which does what the prior code did, i.e., check for an explicit Xlint:-options
flag and ignore all other -Xlint
flags that might also have appeared.
The new Options.isDisabled()
method also checks for or a -Xlint:none
flag, which as you can the the prior code did not explicitly do, but was being done for it implicitly by the pre-JDK-8352612 behavior whereby -Xlint:none
implied -nowarn
. The upshot is that Options.isDisabled()
in 25 performs the same checks as options.isUnset(...)
did in 24.
This will also fix similar issues with a few other warnings that are using the same code pattern and had their behavior change for the same reason.
- csr of
-
JDK-8359596 Behavior change when both -Xlint:options and -Xlint:-options flags are given
-
- Open
-