Skip to content

Commit 474177c

Browse files
committed
[AST] Improve overflow diagnostics for fixed-point constant evaluation.
Summary: Diagnostics for overflow were not being produced for fixed-point evaluation. This patch refactors a bit of the evaluator and adds a proper diagnostic for these cases. Reviewers: rjmccall, leonardchan, bjope Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D73188
1 parent 94e8ec6 commit 474177c

File tree

3 files changed

+56
-33
lines changed

3 files changed

+56
-33
lines changed

clang/include/clang/Basic/DiagnosticASTKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,9 @@ def err_experimental_clang_interp_failed : Error<
346346
def warn_integer_constant_overflow : Warning<
347347
"overflow in expression; result is %0 with type %1">,
348348
InGroup<DiagGroup<"integer-overflow">>;
349+
def warn_fixedpoint_constant_overflow : Warning<
350+
"overflow in expression; result is %0 with type %1">,
351+
InGroup<DiagGroup<"fixed-point-overflow">>;
349352

350353
// This is a temporary diagnostic, and shall be removed once our
351354
// implementation is complete, and like the preceding constexpr notes belongs

clang/lib/AST/ExprConstant.cpp

Lines changed: 39 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12881,8 +12881,14 @@ bool FixedPointExprEvaluator::VisitCastExpr(const CastExpr *E) {
1288112881
return false;
1288212882
bool Overflowed;
1288312883
APFixedPoint Result = Src.convert(DestFXSema, &Overflowed);
12884-
if (Overflowed && !HandleOverflow(Info, E, Result, DestType))
12885-
return false;
12884+
if (Overflowed) {
12885+
if (Info.checkingForUndefinedBehavior())
12886+
Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
12887+
diag::warn_fixedpoint_constant_overflow)
12888+
<< Result.toString() << E->getType();
12889+
else if (!HandleOverflow(Info, E, Result, E->getType()))
12890+
return false;
12891+
}
1288612892
return Success(Result, E);
1288712893
}
1288812894
case CK_IntegralToFixedPoint: {
@@ -12894,8 +12900,14 @@ bool FixedPointExprEvaluator::VisitCastExpr(const CastExpr *E) {
1289412900
APFixedPoint IntResult = APFixedPoint::getFromIntValue(
1289512901
Src, Info.Ctx.getFixedPointSemantics(DestType), &Overflowed);
1289612902

12897-
if (Overflowed && !HandleOverflow(Info, E, IntResult, DestType))
12898-
return false;
12903+
if (Overflowed) {
12904+
if (Info.checkingForUndefinedBehavior())
12905+
Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
12906+
diag::warn_fixedpoint_constant_overflow)
12907+
<< IntResult.toString() << E->getType();
12908+
else if (!HandleOverflow(Info, E, IntResult, E->getType()))
12909+
return false;
12910+
}
1289912911

1290012912
return Success(IntResult, E);
1290112913
}
@@ -12920,47 +12932,41 @@ bool FixedPointExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
1292012932
if (!EvaluateFixedPointOrInteger(RHS, RHSFX, Info))
1292112933
return false;
1292212934

12935+
bool OpOverflow = false, ConversionOverflow = false;
12936+
APFixedPoint Result(LHSFX.getSemantics());
1292312937
switch (E->getOpcode()) {
1292412938
case BO_Add: {
12925-
bool AddOverflow, ConversionOverflow;
12926-
APFixedPoint Result = LHSFX.add(RHSFX, &AddOverflow)
12927-
.convert(ResultFXSema, &ConversionOverflow);
12928-
if ((AddOverflow || ConversionOverflow) &&
12929-
!HandleOverflow(Info, E, Result, E->getType()))
12930-
return false;
12931-
return Success(Result, E);
12939+
Result = LHSFX.add(RHSFX, &OpOverflow)
12940+
.convert(ResultFXSema, &ConversionOverflow);
12941+
break;
1293212942
}
1293312943
case BO_Sub: {
12934-
bool AddOverflow, ConversionOverflow;
12935-
APFixedPoint Result = LHSFX.sub(RHSFX, &AddOverflow)
12936-
.convert(ResultFXSema, &ConversionOverflow);
12937-
if ((AddOverflow || ConversionOverflow) &&
12938-
!HandleOverflow(Info, E, Result, E->getType()))
12939-
return false;
12940-
return Success(Result, E);
12944+
Result = LHSFX.sub(RHSFX, &OpOverflow)
12945+
.convert(ResultFXSema, &ConversionOverflow);
12946+
break;
1294112947
}
1294212948
case BO_Mul: {
12943-
bool AddOverflow, ConversionOverflow;
12944-
APFixedPoint Result = LHSFX.mul(RHSFX, &AddOverflow)
12945-
.convert(ResultFXSema, &ConversionOverflow);
12946-
if ((AddOverflow || ConversionOverflow) &&
12947-
!HandleOverflow(Info, E, Result, E->getType()))
12948-
return false;
12949-
return Success(Result, E);
12949+
Result = LHSFX.mul(RHSFX, &OpOverflow)
12950+
.convert(ResultFXSema, &ConversionOverflow);
12951+
break;
1295012952
}
1295112953
case BO_Div: {
12952-
bool AddOverflow, ConversionOverflow;
12953-
APFixedPoint Result = LHSFX.div(RHSFX, &AddOverflow)
12954-
.convert(ResultFXSema, &ConversionOverflow);
12955-
if ((AddOverflow || ConversionOverflow) &&
12956-
!HandleOverflow(Info, E, Result, E->getType()))
12957-
return false;
12958-
return Success(Result, E);
12954+
Result = LHSFX.div(RHSFX, &OpOverflow)
12955+
.convert(ResultFXSema, &ConversionOverflow);
12956+
break;
1295912957
}
1296012958
default:
1296112959
return false;
1296212960
}
12963-
llvm_unreachable("Should've exited before this");
12961+
if (OpOverflow || ConversionOverflow) {
12962+
if (Info.checkingForUndefinedBehavior())
12963+
Info.Ctx.getDiagnostics().Report(E->getExprLoc(),
12964+
diag::warn_fixedpoint_constant_overflow)
12965+
<< Result.toString() << E->getType();
12966+
else if (!HandleOverflow(Info, E, Result, E->getType()))
12967+
return false;
12968+
}
12969+
return Success(Result, E);
1296412970
}
1296512971

1296612972
//===----------------------------------------------------------------------===//

clang/test/Frontend/fixed_point_errors.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,3 +250,17 @@ unsigned u_const = -2.5hk; // expected-warning{{implicit conversi
250250
char c_const = 256.0uk; // expected-warning{{implicit conversion from 256.0 cannot fit within the range of values for 'char'}}
251251
short _Accum sa_const5 = 256; // expected-warning{{implicit conversion from 256 cannot fit within the range of values for 'short _Accum'}}
252252
unsigned short _Accum usa_const2 = -2; // expected-warning{{implicit conversion from -2 cannot fit within the range of values for 'unsigned short _Accum'}}
253+
254+
short _Accum add_ovf1 = 255.0hk + 20.0hk; // expected-warning {{overflow in expression; result is -237.0 with type 'short _Accum'}}
255+
short _Accum add_ovf2 = 10 + 0.5hr; // expected-warning {{overflow in expression; result is 0.5 with type 'short _Fract'}}
256+
short _Accum sub_ovf1 = 16.0uhk - 32.0uhk; // expected-warning {{overflow in expression; result is 240.0 with type 'unsigned short _Accum'}}
257+
short _Accum sub_ovf2 = -255.0hk - 20; // expected-warning {{overflow in expression; result is 237.0 with type 'short _Accum'}}
258+
short _Accum mul_ovf1 = 200.0uhk * 10.0uhk; // expected-warning {{overflow in expression; result is 208.0 with type 'unsigned short _Accum'}}
259+
short _Accum mul_ovf2 = (-0.5hr - 0.5hr) * (-0.5hr - 0.5hr); // expected-warning {{overflow in expression; result is -1.0 with type 'short _Fract'}}
260+
short _Accum div_ovf1 = 255.0hk / 0.5hk; // expected-warning {{overflow in expression; result is -2.0 with type 'short _Accum'}}
261+
262+
// No warnings for saturation
263+
short _Fract add_sat = (_Sat short _Fract)0.5hr + 0.5hr;
264+
short _Accum sub_sat = (_Sat short _Accum)-200.0hk - 80.0hk;
265+
short _Accum mul_sat = (_Sat short _Accum)80.0hk * 10.0hk;
266+
short _Fract div_sat = (_Sat short _Fract)0.9hr / 0.1hr;

0 commit comments

Comments
 (0)