Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-10262] Floating Point Literal Parsing rounding issues #52662

Open
compnerd opened this issue Apr 2, 2019 · 8 comments
Open

[SR-10262] Floating Point Literal Parsing rounding issues #52662

compnerd opened this issue Apr 2, 2019 · 8 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself Windows Platform: Windows

Comments

@compnerd
Copy link
Collaborator

compnerd commented Apr 2, 2019

Previous ID SR-10262
Radar None
Original Reporter @compnerd
Type Bug
Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, Windows
Assignee None
Priority Medium

md5: 225f5eb4a5a89a7d6e90b3aa974ee49d

blocks:

  • SR-9161 fix up test suite for Windows

Issue Description:

The following sample:

enum E: Double {
  case V = 9223372036854775807
  case W = 9223372036854775807.0
}

fails to resolve the cases as equivalent. The integral value is processed correctly as 0x7fffffffffffffff The floating point case is processed as 0x8000000000000000 which causes the duplicate value to not be treated as a duplicate.

This reproduces on the Windows host.

@compnerd
Copy link
Collaborator Author

compnerd commented Apr 2, 2019

CC: @stephentyrone @belkadan

@stephentyrone
Copy link
Member

I suspect that this is just the long-standing issue with float parsing on Windows, not Swift-specific.

We would like to do our own float parsing for this and other reasons (SR-7124), but I believe that this is just an underlying platform bug (which MS may have finally fixed recently?)

@belkadan
Copy link
Contributor

belkadan commented Apr 2, 2019

I suspect it's not even that: I think our enum uniquing is based on the literal kinds, and we don't bother to turn integer literals into floating-point values during the uniquing.

@belkadan
Copy link
Contributor

belkadan commented Apr 2, 2019

Actually, it's not quite obvious how we would do this checking, since Double is both IntegerLiteralConvertible and FloatLiteralConvertible. Something like NSNumber would in fact treat these as distinct.

@belkadan
Copy link
Contributor

belkadan commented Apr 2, 2019

Some other edge cases:

enum E: Double {
  case V = 9223372036854775807.0
  case W = 9223372036854775808.0
}

enum E: Double {
  case V = 9223372036854775807
  case W = 9223372036854775806
}

enum E: NumberAsWritten {
  case V = 9223372036854775807.0
  case W = 9223372036854775807
}

@compnerd
Copy link
Collaborator Author

compnerd commented Apr 2, 2019

@stephentyrone, it seemed to be going through APSInt so, I would suspect that this is on our side and not the system side? This occurs in [TypeCheckDecl.cpp|

switch (expr->getKind()) {
case ExprKind::IntegerLiteral:
kind = Kind::Int;
intValue = IntValueTy(cast<IntegerLiteralExpr>(expr)->getValue());
return;
case ExprKind::FloatLiteral: {
APFloat value = cast<FloatLiteralExpr>(expr)->getValue();
llvm::APSInt asInt(127, /*isUnsigned=*/false);
bool isExact = false;
APFloat::opStatus status =
value.convertToInteger(asInt, APFloat::rmTowardZero, &isExact);
if (asInt.getBitWidth() <= 128 && status == APFloat::opOK && isExact) {
kind = Kind::Int;
intValue = IntValueTy(asInt);
return;
}
APInt bits = value.bitcastToAPInt();
const uint64_t *data = bits.getRawData();
if (bits.getBitWidth() == 80) {
kind = Kind::Float;
floatValue = FloatValueTy{ data[0], data[1] };
} else {
assert(bits.getBitWidth() == 64);
kind = Kind::Float;
floatValue = FloatValueTy{ data[0], 0 };
}
return;
}
] where the APSInt is converted to an integeral value (particularly L99 and L109). I'm confused as to how L112-L122 ever get executed though.

@compnerd
Copy link
Collaborator Author

compnerd commented Apr 8, 2019

TEST(APFloatTest, convertToInteger) {
{{ llvm::APSInt asInt(127, /isUnsigned=/false);}}
{{ bool isExact = false;}}
{{ // 2^63-1}}
{{ APFloat(APFloat::IEEEdouble(), "9223372036854775807.0")}}
{{ .convertToInteger(asInt, APFloat::rmTowardZero, &isExact);}}
{{ EXPECT_EQ(asInt.toString(10), "9223372036854775807");}}
{{ // 2^64-1}}
{{ APFloat(APFloat::IEEEdouble(), "18446744073709551615.0")}}
{{ .convertToInteger(asInt, APFloat::rmTowardZero, &isExact);}}
{{ EXPECT_EQ(asInt.toString(10), "18446744073709551615");}}
{{}}}

Okay, reduced this to a set of test cases which don't require swift at all. Seems like an issue in APFloat?

@compnerd
Copy link
Collaborator Author

compnerd commented Apr 8, 2019

Additionally, it seems that the conversion error occurs in the convertToInteger call. The APFloat conversion from the string representation retains the correct value.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself Windows Platform: Windows
Projects
None yet
Development

No branches or pull requests

3 participants