Skip to content

Commit

Permalink
8244681: Add a warning for possibly lossy conversion in compound assi…
Browse files Browse the repository at this point in the history
…gnments

8293797: Release Note: Javac warns about type casts in compound assignments with possible lossy conversions

Reviewed-by: erikj, prr
  • Loading branch information
asotona committed Sep 15, 2022
1 parent 15cb1fb commit aff5ff1
Show file tree
Hide file tree
Showing 13 changed files with 438 additions and 1 deletion.
2 changes: 1 addition & 1 deletion make/CompileDemos.gmk
Expand Up @@ -189,7 +189,7 @@ $(eval $(call SetupBuildDemo, Font2DTest, \
$(eval $(call SetupBuildDemo, J2Ddemo, \
DEMO_SUBDIR := jfc, \
MAIN_CLASS := java2d.J2Ddemo, \
DISABLED_WARNINGS := rawtypes deprecation unchecked cast, \
DISABLED_WARNINGS := rawtypes deprecation unchecked cast lossy-conversions, \
JAR_NAME := J2Ddemo, \
))

Expand Down
1 change: 1 addition & 0 deletions make/modules/java.desktop/Java.gmk
Expand Up @@ -23,6 +23,7 @@
# questions.
#

DISABLED_WARNINGS_java += lossy-conversions
DOCLINT += -Xdoclint:all/protected \
'-Xdoclint/package:java.*,javax.*'
COPY += .gif .png .wav .txt .xml .css .pf
Expand Down
1 change: 1 addition & 0 deletions make/modules/java.xml/Java.gmk
Expand Up @@ -23,6 +23,7 @@
# questions.
#

DISABLED_WARNINGS_java += lossy-conversions
DOCLINT += -Xdoclint:all/protected \
'-Xdoclint/package:$(call CommaList, javax.xml.catalog javax.xml.datatype \
javax.xml.transform javax.xml.validation javax.xml.xpath)'
Expand Down
1 change: 1 addition & 0 deletions make/modules/jdk.naming.dns/Java.gmk
@@ -0,0 +1 @@
DISABLED_WARNINGS_java += lossy-conversions
Expand Up @@ -214,6 +214,11 @@ public enum LintCategory {
*/
FINALLY("finally"),

/**
* Warn about compiler possible lossy conversions.
*/
LOSSY_CONVERSIONS("lossy-conversions"),

/**
* Warn about compiler generation of a default constructor.
*/
Expand Down
Expand Up @@ -3941,6 +3941,7 @@ public void visitAssignop(JCAssignOp tree) {
chk.checkCastable(tree.rhs.pos(),
operator.type.getReturnType(),
owntype);
chk.checkLossOfPrecision(tree.rhs.pos(), operand, owntype);
}
result = check(tree, owntype, KindSelector.VAL, resultInfo);
}
Expand Down
16 changes: 16 additions & 0 deletions src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
Expand Up @@ -3751,6 +3751,22 @@ void checkDivZero(final DiagnosticPosition pos, Symbol operator, Type operand) {
}
}

/**
* Check for possible loss of precission
* @param pos Position for error reporting.
* @param found The computed type of the tree
* @param req The computed type of the tree
*/
void checkLossOfPrecision(final DiagnosticPosition pos, Type found, Type req) {
if (found.isNumeric() && req.isNumeric() && !types.isAssignable(found, req)) {
deferredLintHandler.report(() -> {
if (lint.isEnabled(LintCategory.LOSSY_CONVERSIONS))
log.warning(LintCategory.LOSSY_CONVERSIONS,
pos, Warnings.PossibleLossOfPrecision(found, req));
});
}
}

/**
* Check for empty statements after if
*/
Expand Down
Expand Up @@ -2527,6 +2527,10 @@ compiler.misc.not.applicable.types=\
compiler.misc.possible.loss.of.precision=\
possible lossy conversion from {0} to {1}

# 0: type, 1: type
compiler.warn.possible.loss.of.precision=\
implicit cast from {0} to {1} in compound assignment is possibly lossy

compiler.misc.unchecked.assign=\
unchecked conversion

Expand Down
Expand Up @@ -210,6 +210,9 @@ javac.opt.Xlint.desc.fallthrough=\
javac.opt.Xlint.desc.finally=\
Warn about finally clauses that do not terminate normally.

javac.opt.Xlint.desc.lossy-conversions=\
Warn about possible lossy conversions in compound assignment.

javac.opt.Xlint.desc.module=\
Warn about module system related issues.

Expand Down
3 changes: 3 additions & 0 deletions src/jdk.compiler/share/man/javac.1
Expand Up @@ -783,6 +783,9 @@ switch statement to the next.
\f[CB]finally\f[R]: Warns about \f[CB]finally\f[R] clauses that do not
terminate normally.
.IP \[bu] 2
\f[CB]lossy\-conversions\f[R]: Warns about possible lossy conversions
in compound assignment.
.IP \[bu] 2
\f[CB]missing\-explicit\-ctor\f[R]: Warns about missing explicit
constructors in public and protected classes in exported packages.
.IP \[bu] 2
Expand Down
31 changes: 31 additions & 0 deletions test/langtools/tools/javac/diags/examples/LossyConversion.java
@@ -0,0 +1,31 @@
/*
* Copyright (c) 2022, 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.warn.possible.loss.of.precision
// options: -Xlint:lossy-conversions

class LossyConversion {
void m(int a) {
a += 1.0;
}
}
192 changes: 192 additions & 0 deletions test/langtools/tools/javac/lint/LossyConversions.java
@@ -0,0 +1,192 @@
/*
* @test /nodynamiccopyright/
* @bug 8244681
* @summary Test for -Xlint:lossy-conversions
*
* @compile/fail/ref=LossyConversions.out -XDrawDiagnostics -Xmaxwarns 200 -Xlint:lossy-conversions -Werror LossyConversions.java
*/

public class LossyConversions {

public void lossyConversions() {
byte a = 0;
a += 1.0; a -= 2.0; a *= 3.0; a /= 4.0;
a += 11; a -= 12; a *= 13; a /= 14; //no warnings - within range
a |= 15; a &= 16; a ^= 17; a %= 18; //no warnings - within range
a += 21l; a -= 22l; a *= 23l; a /= 24l;
a |= 25l; a &= 26l; a ^= 27l; a %= 28l;
a += 1001; a -= 1002; a *= 1003; a /= 1004;
a |= 1005; a &= 1006; a ^= 1007; a %= 1008;
a += 100_001; a -= 100_002; a *= 100_003; a /= 100_004;
a |= 100_005; a &= 100_006; a ^= 100_007; a %= 100_008;
a += 10_000_000_001l; a -= 10_000_000_002l; a *= 10_000_000_003l; a /= 10_000_000_004l;
a |= 10_000_000_005l; a &= 10_000_000_006l; a ^= 10_000_000_007l; a %= 10_000_000_008l;

short b = 0;
b += 1.0; b -= 2.0; b *= 3.0; b /= 4.0;
b += 11; b -= 12; b *= 13; b /= 14; //no warnings - within range
b |= 15; b &= 16; b ^= 17; b %= 18; //no warnings - within range
b += 21l; b -= 22l; b *= 23l; b /= 24l;
b |= 25l; b &= 26l; b ^= 27l; b %= 28l;
b += 1001; b -= 1002; b *= 1003; b /= 1004; //no warnings - within range
b |= 1005; b &= 1006; b ^= 1007; b %= 1008; //no warnings - within range
b += 100_001; b -= 100_002; b *= 100_003; b /= 100_004;
b |= 100_005; b &= 100_006; b ^= 100_007; b %= 100_008;
b += 10_000_000_001l; b -= 10_000_000_002l; b *= 10_000_000_003l; b /= 10_000_000_004l;
b |= 10_000_000_005l; b &= 10_000_000_006l; b ^= 10_000_000_007l; b %= 10_000_000_008l;

int c = 0;
c += 1.0; c -= 2.0; c *= 3.0; c /= 4.0;
c += 11; c -= 12; c *= 13; c /= 14; //no warnings
c |= 15; c &= 16; c ^= 17; c %= 18; //no warnings
c += 21l; c -= 22l; c *= 23l; c /= 24l;
c |= 25l; c &= 26l; c ^= 27l; c %= 28l;
c += 1001; c -= 1002; c *= 1003; c /= 1004; //no warnings
c |= 1005; c &= 1006; c ^= 1007; c %= 1008; //no warnings
c += 100_001; c -= 100_002; c *= 100_003; c /= 100_004; //no warnings
c |= 100_005; c &= 100_006; c ^= 100_007; c %= 100_008; //no warnings
c += 10_000_000_001l; c -= 10_000_000_002l; c *= 10_000_000_003l; c /= 10_000_000_004l;
c |= 10_000_000_005l; c &= 10_000_000_006l; c ^= 10_000_000_007l; c %= 10_000_000_008l;

long d = 0;
d += 1.0; d -= 2.0; d *= 3.0; d /= 4.0;
d += 11; d -= 12; d *= 13; d /= 14; //no warnings
d |= 15; d &= 16; d ^= 17; d %= 18; //no warnings
d += 21l; d -= 22l; d *= 23l; d /= 24l; //no warnings
d |= 25l; d &= 26l; d ^= 27l; d %= 28l; //no warnings
d += 1001; d -= 1002; d *= 1003; d /= 1004; //no warnings
d |= 1005; d &= 1006; d ^= 1007; d %= 1008; //no warnings
d += 100_001; d -= 100_002; d *= 100_003; d /= 100_004; //no warnings
d |= 100_005; d &= 100_006; d ^= 100_007; d %= 100_008; //no warnings
d += 10_000_000_001l; d -= 10_000_000_002l; d *= 10_000_000_003l; d /= 10_000_000_004l; //no warnings
d |= 10_000_000_005l; d &= 10_000_000_006l; d ^= 10_000_000_007l; d %= 10_000_000_008l; //no warnings

float e = 0;
e += 1.0; e -= 2.0; e *= 3.0; e /= 4.0;

double f = 1.0;
f += 1.0; f -= 2.0; f *= 3.0; f /= 4.0; //no warnings

a += a; a -= a; a *= a; a /= a; //no warnings
a |= a; a &= a; a ^= a; a %= a; //no warnings
a += b; a -= b; a *= b; a /= b;
a |= b; a &= b; a ^= b; a %= b;
a += c; a -= c; a *= c; a /= c;
a |= c; a &= c; a ^= c; a %= c;
a += d; a -= d; a *= d; a /= d;
a |= d; a &= d; a ^= d; a %= d;
a += e; a -= e; a *= e; a /= e;
a += f; a -= f; a *= f; a /= f;

b += a; b -= a; b *= a; b /= a; //no warnings
b |= a; b &= a; b ^= a; b %= a; //no warnings
b += b; b -= b; b *= b; b /= b; //no warnings
b |= b; b &= b; b ^= b; b %= b; //no warnings
b += c; b -= c; b *= c; b /= c;
b |= c; b &= c; b ^= c; b %= c;
b += d; b -= d; b *= d; b /= d;
b |= d; b &= d; b ^= d; b %= d;
b += e; b -= e; b *= e; b /= e;
b += f; b -= f; b *= f; b /= f;

c += a; c -= a; c *= a; c /= a; //no warnings
c |= a; c &= a; c ^= a; c %= a; //no warnings
c += b; c -= b; c *= b; c /= b; //no warnings
c |= b; c &= b; c ^= b; c %= b; //no warnings
c += c; c -= c; c *= c; c /= c; //no warnings
c |= c; c &= c; c ^= c; c %= c; //no warnings
c += d; c -= d; c *= d; c /= d;
c |= d; c &= d; c ^= d; c %= d;
c += e; c -= e; c *= e; c /= e;
c += f; c -= f; c *= f; c /= f;

d += a; d -= a; d *= a; d /= a; //no warnings
d |= a; d &= a; d ^= a; d %= a; //no warnings
d += b; d -= b; d *= b; d /= b; //no warnings
d |= b; d &= b; d ^= b; d %= b; //no warnings
d += c; d -= c; d *= c; d /= c; //no warnings
d |= c; d &= c; d ^= c; d %= c; //no warnings
d += d; d -= d; d *= d; d /= d; //no warnings
d |= d; d &= d; d ^= d; d %= d; //no warnings
d += e; d -= e; d *= e; d /= e;
d += f; d -= f; d *= f; d /= f;

e += a; e -= a; e *= a; e /= a; //no warnings
e += b; e -= b; e *= b; e /= b; //no warnings
e += c; e -= c; e *= c; e /= c; //no warnings
e += d; e -= d; e *= d; e /= d; //no warnings
e += e; e -= e; e *= e; e /= e; //no warnings
e += f; e -= f; e *= f; e /= f;

f += a; f -= a; f *= a; f /= a; //no warnings
f += b; f -= b; f *= b; f /= b; //no warnings
f += c; f -= c; f *= c; f /= c; //no warnings
f += d; f -= d; f *= d; f /= d; //no warnings
f += e; f -= e; f *= e; f /= e; //no warnings
f += f; f -= f; f *= f; f /= f; //no warnings
}

@SuppressWarnings("lossy-conversions")
public void suppressedLossyConversions() {
byte a = 0;
a += 1.0; a -= 2.0; a *= 3.0; a /= 4.0;
a += 21l; a -= 22l; a *= 23l; a /= 24l;
a |= 25l; a &= 26l; a ^= 27l; a %= 28l;
a += 1001; a -= 1002; a *= 1003; a /= 1004;
a |= 1005; a &= 1006; a ^= 1007; a %= 1008;
a += 100_001; a -= 100_002; a *= 100_003; a /= 100_004;
a |= 100_005; a &= 100_006; a ^= 100_007; a %= 100_008;
a += 10_000_000_001l; a -= 10_000_000_002l; a *= 10_000_000_003l; a /= 10_000_000_004l;
a |= 10_000_000_005l; a &= 10_000_000_006l; a ^= 10_000_000_007l; a %= 10_000_000_008l;

short b = 0;
b += 1.0; b -= 2.0; b *= 3.0; b /= 4.0;
b += 21l; b -= 22l; b *= 23l; b /= 24l;
b |= 25l; b &= 26l; b ^= 27l; b %= 28l;
b += 100_001; b -= 100_002; b *= 100_003; b /= 100_004;
b |= 100_005; b &= 100_006; b ^= 100_007; b %= 100_008;
b += 10_000_000_001l; b -= 10_000_000_002l; b *= 10_000_000_003l; b /= 10_000_000_004l;
b |= 10_000_000_005l; b &= 10_000_000_006l; b ^= 10_000_000_007l; b %= 10_000_000_008l;

int c = 0;
c += 1.0; c -= 2.0; c *= 3.0; c /= 4.0;
c += 21l; c -= 22l; c *= 23l; c /= 24l;
c |= 25l; c &= 26l; c ^= 27l; c %= 28l;
c += 10_000_000_001l; c -= 10_000_000_002l; c *= 10_000_000_003l; c /= 10_000_000_004l;
c |= 10_000_000_005l; c &= 10_000_000_006l; c ^= 10_000_000_007l; c %= 10_000_000_008l;

long d = 0;
d += 1.0; d -= 2.0; d *= 3.0; d /= 4.0;

float e = 0;
e += 1.0; e -= 2.0; e *= 3.0; e /= 4.0;

double f = 1.0;

a += b; a -= b; a *= b; a /= b;
a |= b; a &= b; a ^= b; a %= b;
a += c; a -= c; a *= c; a /= c;
a |= c; a &= c; a ^= c; a %= c;
a += d; a -= d; a *= d; a /= d;
a |= d; a &= d; a ^= d; a %= d;
a += e; a -= e; a *= e; a /= e;
a += f; a -= f; a *= f; a /= f;

b += c; b -= c; b *= c; b /= c;
b |= c; b &= c; b ^= c; b %= c;
b += d; b -= d; b *= d; b /= d;
b |= d; b &= d; b ^= d; b %= d;
b += e; b -= e; b *= e; b /= e;
b += f; b -= f; b *= f; b /= f;

c += d; c -= d; c *= d; c /= d;
c |= d; c &= d; c ^= d; c %= d;
c += e; c -= e; c *= e; c /= e;
c += f; c -= f; c *= f; c /= f;

d += e; d -= e; d *= e; d /= e;
d += f; d -= f; d *= f; d /= f;

e += f; e -= f; e *= f; e /= f;
}
}

1 comment on commit aff5ff1

@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.