Skip to content

Properly interpolate negative AP literals #11286

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

Merged
merged 1 commit into from
Aug 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,7 @@ class IntegerLiteralExpr : public NumberLiteralExpr {
{}

APInt getValue() const;
static APInt getValue(StringRef Text, unsigned BitWidth);
static APInt getValue(StringRef Text, unsigned BitWidth, bool Negative);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you 're going to store a sign you should use APSInt.


static bool classof(const Expr *E) {
return E->getKind() == ExprKind::IntegerLiteral;
Expand All @@ -910,7 +910,8 @@ class FloatLiteralExpr : public NumberLiteralExpr {
{}

APFloat getValue() const;
static APFloat getValue(StringRef Text, const llvm::fltSemantics &Semantics);
static APFloat getValue(StringRef Text, const llvm::fltSemantics &Semantics,
bool Negative);

static bool classof(const Expr *E) {
return E->getKind() == ExprKind::FloatLiteral;
Expand Down
9 changes: 5 additions & 4 deletions lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1005,8 +1005,8 @@ static APInt getIntegerLiteralValue(bool IsNegative, StringRef Text,
return Value;
}

APInt IntegerLiteralExpr::getValue(StringRef Text, unsigned BitWidth) {
return getIntegerLiteralValue(/*IsNegative=*/false, Text, BitWidth);
APInt IntegerLiteralExpr::getValue(StringRef Text, unsigned BitWidth, bool Negative) {
return getIntegerLiteralValue(Negative, Text, BitWidth);
}

APInt IntegerLiteralExpr::getValue() const {
Expand Down Expand Up @@ -1035,8 +1035,9 @@ static APFloat getFloatLiteralValue(bool IsNegative, StringRef Text,
}

APFloat FloatLiteralExpr::getValue(StringRef Text,
const llvm::fltSemantics &Semantics) {
return getFloatLiteralValue(/*IsNegative*/false, Text, Semantics);
const llvm::fltSemantics &Semantics,
bool Negative) {
return getFloatLiteralValue(Negative, Text, Semantics);
}

llvm::APFloat FloatLiteralExpr::getValue() const {
Expand Down
6 changes: 2 additions & 4 deletions lib/IRGen/GenEnum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1027,10 +1027,8 @@ namespace {
auto intType = getDiscriminatorType();

APInt intValue = IntegerLiteralExpr::getValue(intExpr->getDigitsText(),
intType->getBitWidth());

if (intExpr->isNegative())
intValue = -intValue;
intType->getBitWidth(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember offhand but I think you need an extra bit for the negative.

intExpr->isNegative());

return intValue.getZExtValue();
}
Expand Down
4 changes: 2 additions & 2 deletions lib/Sema/TypeCheckSwitchStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -980,7 +980,7 @@ namespace {
auto *ILE = cast<IntegerLiteralExpr>(EL);
auto cacheVal =
IntLiteralCache.insert(
{ILE->getValue(ILE->getDigitsText(), 128), ILE});
{ILE->getValue(ILE->getDigitsText(), 128, ILE->isNegative()), ILE});
PrevPattern = (cacheVal.first != IntLiteralCache.end())
? cacheVal.first->getSecond()
: nullptr;
Expand All @@ -993,7 +993,7 @@ namespace {
auto cacheVal =
FloatLiteralCache.insert(
{FLE->getValue(FLE->getDigitsText(),
APFloat::IEEEquad()), FLE});
APFloat::IEEEquad(), FLE->isNegative()), FLE});
PrevPattern = (cacheVal.first != FloatLiteralCache.end())
? cacheVal.first->getSecond()
: nullptr;
Expand Down
18 changes: 16 additions & 2 deletions test/Sema/exhaustive_switch.swift
Original file line number Diff line number Diff line change
Expand Up @@ -559,8 +559,7 @@ func infinitelySized() -> Bool {
}
}

// Literal Duplicate checks
func checkLiterals() {
func diagnoseDuplicateLiterals() {
let str = "def"
let int = 2
let dbl = 2.5
Expand Down Expand Up @@ -614,13 +613,18 @@ func checkLiterals() {

// No Diagnostics
switch int {
case -2: break
case -1: break
case 0: break
case 1: break
case 2: break
case 3: break
default: break
}

switch int {
case -2: break // expected-note {{first occurrence of identical literal pattern is here}}
case -2: break // expected-warning {{literal value is already handled by previous pattern; consider removing it}}
case 1: break
case 2: break // expected-note {{first occurrence of identical literal pattern is here}}
case 2: break // expected-warning {{literal value is already handled by previous pattern; consider removing it}}
Expand All @@ -629,6 +633,7 @@ func checkLiterals() {
}

switch int {
case -2, -2: break // expected-note {{first occurrence of identical literal pattern is here}} expected-warning {{literal value is already handled by previous pattern; consider removing it}}
case 1, 2: break // expected-note 3 {{first occurrence of identical literal pattern is here}}
case 2, 3: break // expected-warning {{literal value is already handled by previous pattern; consider removing it}}
case 1, 2: break // expected-warning 2 {{literal value is already handled by previous pattern; consider removing it}}
Expand All @@ -655,10 +660,12 @@ func checkLiterals() {
switch int {
case 10: break
case 0b10: break // expected-note {{first occurrence of identical literal pattern is here}}
case -0b10: break // expected-note {{first occurrence of identical literal pattern is here}}
case 3000: break
case 0x12: break // expected-note {{first occurrence of identical literal pattern is here}}
case 400: break
case 2: break // expected-warning {{literal value is already handled by previous pattern; consider removing it}}
case -2: break // expected-warning {{literal value is already handled by previous pattern; consider removing it}}
case 18: break // expected-warning {{literal value is already handled by previous pattern; consider removing it}}
default: break
}
Expand All @@ -681,13 +688,20 @@ func checkLiterals() {

// No Diagnostics
switch dbl {
case -3.5: break
case -2.5: break
case -1.5: break
case 1.5: break
case 2.5: break
case 3.5: break
default: break
}

switch dbl {
case -3.5: break
case -2.5: break // expected-note {{first occurrence of identical literal pattern is here}}
case -2.5: break // expected-warning {{literal value is already handled by previous pattern; consider removing it}}
case -1.5: break
case 1.5: break
case 2.5: break // expected-note {{first occurrence of identical literal pattern is here}}
case 2.5: break // expected-warning {{literal value is already handled by previous pattern; consider removing it}}
Expand Down