Skip to content

Commit 2823a69

Browse files
committed
Properly interpolate negative AP literals
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.
1 parent 6133ffe commit 2823a69

File tree

5 files changed

+28
-14
lines changed

5 files changed

+28
-14
lines changed

include/swift/AST/Expr.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,7 @@ class IntegerLiteralExpr : public NumberLiteralExpr {
893893
{}
894894

895895
APInt getValue() const;
896-
static APInt getValue(StringRef Text, unsigned BitWidth);
896+
static APInt getValue(StringRef Text, unsigned BitWidth, bool Negative);
897897

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

912912
APFloat getValue() const;
913-
static APFloat getValue(StringRef Text, const llvm::fltSemantics &Semantics);
913+
static APFloat getValue(StringRef Text, const llvm::fltSemantics &Semantics,
914+
bool Negative);
914915

915916
static bool classof(const Expr *E) {
916917
return E->getKind() == ExprKind::FloatLiteral;

lib/AST/Expr.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,8 +1005,8 @@ static APInt getIntegerLiteralValue(bool IsNegative, StringRef Text,
10051005
return Value;
10061006
}
10071007

1008-
APInt IntegerLiteralExpr::getValue(StringRef Text, unsigned BitWidth) {
1009-
return getIntegerLiteralValue(/*IsNegative=*/false, Text, BitWidth);
1008+
APInt IntegerLiteralExpr::getValue(StringRef Text, unsigned BitWidth, bool Negative) {
1009+
return getIntegerLiteralValue(Negative, Text, BitWidth);
10101010
}
10111011

10121012
APInt IntegerLiteralExpr::getValue() const {
@@ -1035,8 +1035,9 @@ static APFloat getFloatLiteralValue(bool IsNegative, StringRef Text,
10351035
}
10361036

10371037
APFloat FloatLiteralExpr::getValue(StringRef Text,
1038-
const llvm::fltSemantics &Semantics) {
1039-
return getFloatLiteralValue(/*IsNegative*/false, Text, Semantics);
1038+
const llvm::fltSemantics &Semantics,
1039+
bool Negative) {
1040+
return getFloatLiteralValue(Negative, Text, Semantics);
10401041
}
10411042

10421043
llvm::APFloat FloatLiteralExpr::getValue() const {

lib/IRGen/GenEnum.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,10 +1027,8 @@ namespace {
10271027
auto intType = getDiscriminatorType();
10281028

10291029
APInt intValue = IntegerLiteralExpr::getValue(intExpr->getDigitsText(),
1030-
intType->getBitWidth());
1031-
1032-
if (intExpr->isNegative())
1033-
intValue = -intValue;
1030+
intType->getBitWidth(),
1031+
intExpr->isNegative());
10341032

10351033
return intValue.getZExtValue();
10361034
}

lib/Sema/TypeCheckSwitchStmt.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,7 @@ namespace {
980980
auto *ILE = cast<IntegerLiteralExpr>(EL);
981981
auto cacheVal =
982982
IntLiteralCache.insert(
983-
{ILE->getValue(ILE->getDigitsText(), 128), ILE});
983+
{ILE->getValue(ILE->getDigitsText(), 128, ILE->isNegative()), ILE});
984984
PrevPattern = (cacheVal.first != IntLiteralCache.end())
985985
? cacheVal.first->getSecond()
986986
: nullptr;
@@ -993,7 +993,7 @@ namespace {
993993
auto cacheVal =
994994
FloatLiteralCache.insert(
995995
{FLE->getValue(FLE->getDigitsText(),
996-
APFloat::IEEEquad()), FLE});
996+
APFloat::IEEEquad(), FLE->isNegative()), FLE});
997997
PrevPattern = (cacheVal.first != FloatLiteralCache.end())
998998
? cacheVal.first->getSecond()
999999
: nullptr;

test/Sema/exhaustive_switch.swift

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -559,8 +559,7 @@ func infinitelySized() -> Bool {
559559
}
560560
}
561561

562-
// Literal Duplicate checks
563-
func checkLiterals() {
562+
func diagnoseDuplicateLiterals() {
564563
let str = "def"
565564
let int = 2
566565
let dbl = 2.5
@@ -614,13 +613,18 @@ func checkLiterals() {
614613

615614
// No Diagnostics
616615
switch int {
616+
case -2: break
617+
case -1: break
618+
case 0: break
617619
case 1: break
618620
case 2: break
619621
case 3: break
620622
default: break
621623
}
622624

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

631635
switch int {
636+
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}}
632637
case 1, 2: break // expected-note 3 {{first occurrence of identical literal pattern is here}}
633638
case 2, 3: break // expected-warning {{literal value is already handled by previous pattern; consider removing it}}
634639
case 1, 2: break // expected-warning 2 {{literal value is already handled by previous pattern; consider removing it}}
@@ -655,10 +660,12 @@ func checkLiterals() {
655660
switch int {
656661
case 10: break
657662
case 0b10: break // expected-note {{first occurrence of identical literal pattern is here}}
663+
case -0b10: break // expected-note {{first occurrence of identical literal pattern is here}}
658664
case 3000: break
659665
case 0x12: break // expected-note {{first occurrence of identical literal pattern is here}}
660666
case 400: break
661667
case 2: break // expected-warning {{literal value is already handled by previous pattern; consider removing it}}
668+
case -2: break // expected-warning {{literal value is already handled by previous pattern; consider removing it}}
662669
case 18: break // expected-warning {{literal value is already handled by previous pattern; consider removing it}}
663670
default: break
664671
}
@@ -681,13 +688,20 @@ func checkLiterals() {
681688

682689
// No Diagnostics
683690
switch dbl {
691+
case -3.5: break
692+
case -2.5: break
693+
case -1.5: break
684694
case 1.5: break
685695
case 2.5: break
686696
case 3.5: break
687697
default: break
688698
}
689699

690700
switch dbl {
701+
case -3.5: break
702+
case -2.5: break // expected-note {{first occurrence of identical literal pattern is here}}
703+
case -2.5: break // expected-warning {{literal value is already handled by previous pattern; consider removing it}}
704+
case -1.5: break
691705
case 1.5: break
692706
case 2.5: break // expected-note {{first occurrence of identical literal pattern is here}}
693707
case 2.5: break // expected-warning {{literal value is already handled by previous pattern; consider removing it}}

0 commit comments

Comments
 (0)