Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8359844

Behavior change when both -Xlint:options and -Xlint:-options flags are given

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Unresolved
    • Icon: P2 P2
    • 25, 26
    • tools
    • None
    • behavioral
    • low
    • Hide
      No behavior change should be seen by anyone using only official JDK releases.

      People already doing testing with JDK 25 early access releases may see the behavior change back the original behavior.
      Show
      No behavior change should be seen by anyone using only official JDK releases. People already doing testing with JDK 25 early access releases may see the behavior change back the original behavior.
    • add/remove/modify command line option
    • JDK

      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.

            acobbs Archie Cobbs
            uschindler Uwe Schindler
            Chen Liang
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: