Commit 9d7d33ac by Iain Buclaw

Merge dmd upstream e2fe2687b

Backports VRP fixes from the D front-end implementation to the C++ port,
and fixes errors reported by ubsan build where the conversion from D
didn't include adjusting integer suffixes from 'UL' to 'ULL'.

Fixes https://gcc.gnu.org/PR88366

Reviewed-on: https://github.com/dlang/dmd/pull/9046

From-SVN: r266925
parent 5d62bfc3
5220ad51eebe06754e6881d9bd5aab89dba2b065
e2fe2687b817a201528abaa3aa882333e04db01b
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
......@@ -446,13 +446,13 @@ UnionExp Div(Loc loc, Type *type, Expression *e1, Expression *e2)
if (n2 == -1 && !type->isunsigned())
{
// Check for int.min / -1
if ((dinteger_t)n1 == 0xFFFFFFFF80000000UL && type->toBasetype()->ty != Tint64)
if ((dinteger_t)n1 == 0xFFFFFFFF80000000ULL && type->toBasetype()->ty != Tint64)
{
e2->error("integer overflow: int.min / -1");
new(&ue) ErrorExp();
return ue;
}
else if ((dinteger_t)n1 == 0x8000000000000000L) // long.min / -1
else if ((dinteger_t)n1 == 0x8000000000000000LL) // long.min / -1
{
e2->error("integer overflow: long.min / -1");
new(&ue) ErrorExp();
......
......@@ -1191,12 +1191,12 @@ void ScopeDsymbol::importScope(Dsymbol *s, Prot protection)
static void bitArraySet(BitArray *array, size_t idx)
{
array->ptr[idx / (sizeof(size_t) * CHAR_BIT)] |= 1 << (idx & (sizeof(size_t) * CHAR_BIT - 1));
array->ptr[idx / (sizeof(size_t) * CHAR_BIT)] |= 1ULL << (idx & (sizeof(size_t) * CHAR_BIT - 1));
}
static bool bitArrayGet(BitArray *array, size_t idx)
{
return (array->ptr[idx / (sizeof(size_t) * CHAR_BIT)] & (1 << (idx & (sizeof(size_t) * CHAR_BIT - 1)))) != 0;
return (array->ptr[idx / (sizeof(size_t) * CHAR_BIT)] & (1ULL << (idx & (sizeof(size_t) * CHAR_BIT - 1)))) != 0;
}
static void bitArrayLength(BitArray *array, size_t len)
......
......@@ -60,13 +60,23 @@ struct SignExtendedNumber
bool operator<=(const SignExtendedNumber& a) const { return !(a < *this); }
bool operator>=(const SignExtendedNumber& a) const { return !(*this < a); }
/// Increase the sign-extended number by 1 (saturated).
SignExtendedNumber& operator++();
/// Compute the saturated complement of a sign-extended number.
SignExtendedNumber operator~() const;
/// Compute the saturated negation of a sign-extended number.
SignExtendedNumber operator-() const;
/// Compute the saturated binary and of two sign-extended number.
SignExtendedNumber operator&(const SignExtendedNumber&) const;
/// Compute the saturated binary or of two sign-extended number.
SignExtendedNumber operator|(const SignExtendedNumber&) const;
/// Compute the saturated binary xor of two sign-extended number.
SignExtendedNumber operator^(const SignExtendedNumber&) const;
/// Compute the saturated sum of two sign-extended number.
SignExtendedNumber operator+(const SignExtendedNumber&) const;
/// Compute the saturated difference of two sign-extended number.
SignExtendedNumber operator-(const SignExtendedNumber& a) const;
SignExtendedNumber operator-(const SignExtendedNumber&) const;
/// Compute the saturated product of two sign-extended number.
SignExtendedNumber operator*(const SignExtendedNumber&) const;
/// Compute the saturated quotient of two sign-extended number.
......@@ -74,9 +84,6 @@ struct SignExtendedNumber
/// Compute the saturated modulus of two sign-extended number.
SignExtendedNumber operator%(const SignExtendedNumber&) const;
/// Increase the sign-extended number by 1 (saturated).
SignExtendedNumber& operator++();
/// Compute the saturated shifts of two sign-extended number.
SignExtendedNumber operator<<(const SignExtendedNumber&) const;
SignExtendedNumber operator>>(const SignExtendedNumber&) const;
......@@ -146,4 +153,25 @@ struct IntRange
/// Split the range into two nonnegative- and negative-only subintervals.
void splitBySign(IntRange& negRange, bool& hasNegRange,
IntRange& nonNegRange, bool& hasNonNegRange) const;
/// Credits to Timon Gehr maxOr, minOr, maxAnd, minAnd
/// https://github.com/tgehr/d-compiler/blob/master/vrange.d
static SignExtendedNumber maxOr(const IntRange&, const IntRange&);
static SignExtendedNumber minOr(const IntRange&, const IntRange&);
static SignExtendedNumber maxAnd(const IntRange&, const IntRange&);
static SignExtendedNumber minAnd(const IntRange&, const IntRange&);
static void swap(IntRange&, IntRange&);
IntRange operator~() const;
IntRange operator-() const;
IntRange operator&(const IntRange&) const;
IntRange operator|(const IntRange&) const;
IntRange operator^(const IntRange&) const;
IntRange operator+(const IntRange&) const;
IntRange operator-(const IntRange&) const;
IntRange operator*(const IntRange&) const;
IntRange operator/(const IntRange&) const;
IntRange operator%(const IntRange&) const;
IntRange operator<<(const IntRange&) const;
IntRange operator>>(const IntRange&) const;
};
......@@ -3832,6 +3832,7 @@ MATCH TypeVector::implicitConvTo(Type *to)
//printf("TypeVector::implicitConvTo(%s) from %s\n", to->toChars(), toChars());
if (this == to)
return MATCHexact;
#ifdef IN_GCC
if (to->ty == Tvector)
{
TypeVector *tv = (TypeVector *)to;
......@@ -3848,6 +3849,10 @@ MATCH TypeVector::implicitConvTo(Type *to)
// Otherwise implicitly convertible only if basetypes are.
return basetype->implicitConvTo(tv->basetype);
}
#else
if (ty == to->ty)
return MATCHconvert;
#endif
return MATCHnomatch;
}
......
// PERMUTE_ARGS: -O -inline
// Test value-range propagation.
// See Bug 3147, Bug 6000, Bug 5225.
// https://issues.dlang.org/show_bug.cgi?id=3147
// https://issues.dlang.org/show_bug.cgi?id=6000
// https://issues.dlang.org/show_bug.cgi?id=5225
void add() {
void add()
{
byte x, y;
short a = x + y;
}
void leftShift() {
void leftShift()
{
byte x, y;
short z = x << 1;
}
void leftShiftFail() {
ubyte x, y;
ushort z;
static assert(!__traits(compiles, z = x << y));
// 1 << 31 surely overflows the range of 'ushort'.
void leftShiftFail()
{
{
ubyte x, y;
ushort z;
static assert(!__traits(compiles, z = x << y));
// 1 << 31 surely overflows the range of 'ushort'.
}
{
ulong a, b;
int res;
static assert(!__traits(compiles, res = a << (b % 65U)));
}
}
void rightShiftFail() {
short x;
byte y, z;
static assert(!__traits(compiles, z = x >> y));
// [this passes in 2.053.]
void rightShiftFail()
{
{
short x;
byte y, z;
static assert(!__traits(compiles, z = x >> y));
// [this passes in 2.053.]
}
{
ulong a, b;
int res;
static assert(!__traits(compiles, res = a >> (b % 65U)));
}
}
void rightShift() {
void rightShift()
{
ushort x;
ubyte y = x >> 16;
}
void unsignedRightShiftFail() {
void unsignedRightShiftFail()
{
int x;
ubyte y;
static assert(!__traits(compiles, y = x >>> 2));
// [this passes in 2.053.]
}
void subtract() {
void subtract()
{
ubyte x, y;
short z = x - y;
}
void multiply() {
void multiply()
{
byte x, y;
short z = x * y;
}
void subMulFail() {
void subMulFail()
{
ubyte x, y;
ubyte z;
static assert(!__traits(compiles, z = x - y));
......@@ -57,65 +82,82 @@ void subMulFail() {
// [these pass in 2.053.]
}
void multiplyNeg1() {
void multiplyNeg1()
{
byte b;
b = -1 + (b * -1);
static assert(!__traits(compiles, b = -1 + b * ulong.max));
}
void divide() {
void divide()
{
short w;
byte y = w / 300;
}
void divideFail() {
void divideFail()
{
short w;
byte y;
static assert(!__traits(compiles, y = w / -1));
}
void plus1Fail() {
void plus1Fail()
{
byte u, v;
static assert(!__traits(compiles, v = u + 1));
// [these pass in 2.053.]
}
void modulus() {
void modulus()
{
int x;
byte u = x % 128;
}
void modulus_bug6000a() {
void modulus_bug6000a()
{
ulong t;
uint u = t % 16;
}
void modulus_bug6000b() {
void modulus_bug6000b()
{
long n = 10520;
ubyte b;
static assert(!__traits(compiles, b = n % 10));
}
void modulus2() {
void modulus2()
{
short s;
byte b = byte.max;
byte c = s % b;
}
void modulus3() {
void modulus3()
{
int i;
short s = short.max;
short t = i % s;
}
void modulus4() {
void modulus4()
{
uint i;
ushort s;
short t;
static assert(!__traits(compiles, t = i % s));
}
void modulusFail() {
void modulus5()
{
short a;
byte foo = (a - short.max - 1) % 127;
}
void modulusFail()
{
int i;
short s;
byte b;
......@@ -124,7 +166,8 @@ void modulusFail() {
// [these pass in 2.053.]
}
void bitwise() {
void bitwise()
{
ubyte a, b, c;
uint d;
c = a & b;
......@@ -134,56 +177,159 @@ void bitwise() {
// [these pass in 2.053.]
}
void bitAnd() {
void bitAnd()
{
byte c;
int d;
c = (0x3ff_ffffU << (0&c)) & (0x4000_0000U << (0&c));
// the result of the above is always 0 :).
}
void bitOrFail() {
ubyte c;
static assert(!__traits(compiles, c = c | 0x100));
// [this passes in 2.053.]
void bitAndTest()
{
{
ushort a, b;
byte res = ((a % 7) - 6) & ((b % 7) - 6);
}
{
// rhs[-128..127] outside range of lhs[0..255]
// -> calls byte.implicitConvTo(ubyte) => MATCH.convert
byte a, b;
ubyte res;
res = cast(byte)(a + 5) & b;
res = cast(byte)(a - 5) & b;
res = cast(byte)(a / 5) & b;
res = cast(byte)(a * 5) & b;
res = cast(byte)(a % 5) & b;
}
}
void bitOrFail()
{
{
ubyte c;
static assert(!__traits(compiles, c = c | 0x100));
// [this passes in 2.053.]
}
{
byte a, b;
ubyte res;
static assert(!__traits(compiles, res = (a + 5) | b)); // [-128..255]
static assert(!__traits(compiles, res = (a - 5) | b)); // [-133..127]
static assert(!__traits(compiles, res = (a / 5) | b)); // [-128..127]
static assert(!__traits(compiles, res = (a * 5) | b)); // [-640..639]
static assert(!__traits(compiles, res = (a % 5) | b)); // [-128..127]
}
}
void bitAndOr() {
void bitAndOr()
{
ubyte c;
c = (c | 0x1000) & ~0x1000;
}
void bitAndFail() {
int d;
short s;
byte c;
static assert(!__traits(compiles, c = d & s));
static assert(!__traits(compiles, c = d & 256));
// [these pass in 2.053.]
void bitOrTest()
{
{
// Tests condition for different signs between min & max
// ((imin.negative ^ imax.negative) == 1 && (rhs.imin.negative ^ rhs.imax.negative) == 1
ushort a, b;
byte res = ((a % 127) - 126) | ((b % 6) - 5);
}
{
// rhs[-128..127] outside range of lhs[0..255]
// -> calls byte.implicitConvTo(ubyte) => MATCH.convert
byte a, b, c;
ubyte res;
res = cast(byte)(a + 5) | b;
res = cast(byte)(a - 5) | b;
res = cast(byte)(a / 5) | b;
res = cast(byte)(a * 5) | b;
res = cast(byte)(a % 5) | b;
}
}
void bitXor() {
ushort s;
ubyte c;
c = (0xffff << (s&0)) ^ 0xff00;
void bitAndFail()
{
{
int d;
short s;
byte c;
static assert(!__traits(compiles, c = d & s));
static assert(!__traits(compiles, c = d & 256));
// [these pass in 2.053.]
}
{
byte a, b;
ubyte res;
static assert(!__traits(compiles, res = (a + 5) & b)); // [-128..132]
static assert(!__traits(compiles, res = (a - 5) & b)); // [-256..127]
static assert(!__traits(compiles, res = (a / 5) & b)); // [-128..127]
static assert(!__traits(compiles, res = (a * 5) & b)); // [-640..635]
static assert(!__traits(compiles, res = (a % 5) & b)); // [-128..127]
}
}
void bitXor()
{
{
ushort s;
ubyte c;
c = (0xffff << (s & 0)) ^ 0xff00;
}
{
// rhs[-128..127] outside range of lhs[0..255]
// -> calls byte.implicitConvTo(ubyte) => MATCH.convert
byte a, b, c;
ubyte res;
res = cast(byte)(a + 5) ^ b;
res = cast(byte)(a - 5) ^ b;
res = cast(byte)(a / 5) ^ b;
res = cast(byte)(a * 5) ^ b;
res = cast(byte)(a % 5) ^ b;
}
}
void bitComplement() {
void bitXorFail()
{
{
byte a, b;
ubyte res;
static assert(!__traits(compiles, res = (a + 5) ^ b)); // [-256..255]
static assert(!__traits(compiles, res = (a - 5) ^ b)); // [-256..255]
static assert(!__traits(compiles, res = (a / 5) ^ b)); // [-128..127]
static assert(!__traits(compiles, res = (a * 5) ^ b)); // [-640..1023]
static assert(!__traits(compiles, res = (a % 5) ^ b)); // [-128..127]
}
}
void bitComplement()
{
int i;
ubyte b = ~(i | ~0xff);
}
void bitComplementFail() {
void bitComplementFail()
{
ubyte b;
static assert(!__traits(compiles, b = ~(b | 1)));
// [this passes in 2.053.]
}
void negation() {
void negation()
{
int x;
byte b = -(x & 0x7);
}
void negationFail() {
void negationFail()
{
int x;
byte b;
static assert(!__traits(compiles, b = -(x & 255)));
......@@ -200,7 +346,8 @@ short bug1977_comment5(byte i) {
return o;
}
void testDchar() {
void testDchar()
{
dchar d;
uint i;
/+
......@@ -210,13 +357,15 @@ void testDchar() {
d = i % 0x110000;
}
void bug1977_comment11() {
void bug1977_comment11()
{
uint a;
byte b = a & 1;
// [this passes in 2.053.]
}
void bug1977_comment20() {
void bug1977_comment20()
{
long a;
int b = a % 1000;
}
......@@ -329,3 +478,32 @@ void test13001(bool unknown)
static assert(!__traits(compiles, b = i + 254));
}
}
void test10310()
{
int y;
ubyte x = ((y & 252) ^ 2) + 1;
}
// https://issues.dlang.org/show_bug.cgi?id=15289
void test15289a()
{
int [] arr = [1, 2, 3, 4];
uint foo = 50 / arr.length;
}
void test15289b()
{
int [] arr = [1, 2, 3, 4];
uint foo = 50 % arr.length;
}
void testShiftRightOnNegative()
{
int neg = -1;
uint[] arr = [1, 2, 3];
ubyte b;
// Shift with negative value returns value in range [0, ulong.max]
static assert(!__traits(compiles, b = arr.length >> neg));
static assert(!__traits(compiles, b = arr.length << neg));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment