Skip to content

Commit

Permalink
Properly interpolate negative AP literals
Browse files Browse the repository at this point in the history
Integer and Floating literals are aware of their negation but
do not store the sign in the text of the value.  Retrieve the
sign bit and properly interpolate the text of the literal value
with it to distinguish negative and positive literals.
  • Loading branch information
CodaFi committed Aug 1, 2017
1 parent 6133ffe commit 2823a69
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 14 deletions.
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);

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(),
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

0 comments on commit 2823a69

Please sign in to comment.