blob: 253a7a54ceb193e33d7a9650a53f073366a962fa [file] [log] [blame]
/*
RUN_OUTPUT:
---
i = 1
Writer.opShl(char[])
BinaryWriter.opShl(int)
a + 1 = 2
1 + a = 2
a + b = 3
b + a = 3
i = 64
12
534
A::opShl(int 4)
4A::opShl(char[])
A::opShl(int 12)
12A::opShl(char[])
B::opShl_r(A)
Success
---
*/
// Test operator overloading
// Ignore deprecation warnings for D1 style operator overloading
// TRANSFORM_OUTPUT: remove_lines("Deprecation: `op")
import core.stdc.stdio;
/**************************************/
class A1
{
int opBinary(string op)(int i) if (op == "+") { return 7 + i; }
alias opBinaryRight = opBinary;
}
void test1()
{
A1 a = new A1();
int i;
i = a + 3;
assert(i == 10);
i = 4 + a;
assert(i == 11);
}
/**************************************/
class A2
{
int opBinary(string op)(int i) if (op == "/") { return 9 + i; }
int opBinaryRight(string op)(int i) if (op == "/") { return 17 + i; }
}
void test2()
{
A2 a = new A2();
int i;
i = a / 3;
assert(i == 12);
i = 4 / a;
assert(i == 21);
}
/**************************************/
class C1
{
}
class C2
{
int opBinary(string op)(D1 d) if (op == "+") { return 1; }
int opBinary(string op)(D2 d) if (op == "+") { return 2; }
int opBinary(string op)(D3 d) if (op == "+") { return 3; }
int opBinary(string op)(D4 d) if (op == "+") { return 4; }
}
class C3
{
int opBinaryRight(string op)(D1 d) if (op == "+") { return 5; }
int opBinaryRight(string op)(D2 d) if (op == "+") { return 6; }
int opBinaryRight(string op)(D3 d) if (op == "+") { return 7; }
int opBinaryRight(string op)(D4 d) if (op == "+") { return 8; }
}
class C4
{
int opBinary(string op)(D1 d) if (op == "+") { return 9; }
int opBinary(string op)(D2 d) if (op == "+") { return 10; }
int opBinary(string op)(D3 d) if (op == "+") { return 11; }
int opBinary(string op)(D4 d) if (op == "+") { return 12; }
int opBinaryRight(string op)(D1 d) if (op == "+") { return 13; }
int opBinaryRight(string op)(D2 d) if (op == "+") { return 14; }
int opBinaryRight(string op)(D3 d) if (op == "+") { return 15; }
int opBinaryRight(string op)(D4 d) if (op == "+") { return 16; }
}
class D1
{
}
class D2
{
int opBinary(string op)(C1 d) if (op == "+") { return 17; }
int opBinary(string op)(C2 d) if (op == "+") { return 18; }
int opBinary(string op)(C3 d) if (op == "+") { return 19; }
int opBinary(string op)(C4 d) if (op == "+") { return 20; }
}
class D3
{
int opBinaryRight(string op)(C1 d) if (op == "+") { return 21; }
int opBinaryRight(string op)(C2 d) if (op == "+") { return 22; }
int opBinaryRight(string op)(C3 d) if (op == "+") { return 23; }
int opBinaryRight(string op)(C4 d) if (op == "+") { return 24; }
}
class D4
{
int opBinary(string op)(C1 d) if (op == "+") { return 25; }
int opBinary(string op)(C2 d) if (op == "+") { return 26; }
int opBinary(string op)(C3 d) if (op == "+") { return 27; }
int opBinary(string op)(C4 d) if (op == "+") { return 28; }
int opBinaryRight(string op)(C1 d) if (op == "+") { return 29; }
int opBinaryRight(string op)(C2 d) if (op == "+") { return 30; }
int opBinaryRight(string op)(C3 d) if (op == "+") { return 31; }
int opBinaryRight(string op)(C4 d) if (op == "+") { return 32; }
}
void test3()
{
C1 c1 = new C1();
C2 c2 = new C2();
C3 c3 = new C3();
C4 c4 = new C4();
D1 d1 = new D1();
D2 d2 = new D2();
D3 d3 = new D3();
D4 d4 = new D4();
int i;
//i = c1 + d1; assert(i == );
//i = c1 + d2; assert(i == );
i = c1 + d3; assert(i == 21);
i = c1 + d4; assert(i == 29);
i = c2 + d1; assert(i == 1);
i = c2 + d2; assert(i == 2);
i = c2 + d3; assert(i == 22);
i = c2 + d4; assert(i == 30);
//i = c3 + d1; assert(i == );
//i = c3 + d2; assert(i == );
i = c3 + d3; assert(i == 23);
i = c3 + d4; assert(i == 31);
i = c4 + d1; assert(i == 9);
i = c4 + d2; assert(i == 10);
i = c4 + d3; assert(i == 24);
i = c4 + d4; assert(i == 32);
//i = d1 + c1; assert(i == );
//i = d1 + c2; assert(i == );
i = d1 + c3; assert(i == 5);
i = d1 + c4; assert(i == 13);
i = d2 + c1; assert(i == 17);
i = d2 + c2; assert(i == 18);
i = d2 + c3; assert(i == 6);
i = d2 + c4; assert(i == 14);
//i = d3 + c1; assert(i == );
//i = d3 + c2; assert(i == );
i = d3 + c3; assert(i == 7);
i = d3 + c4; assert(i == 15);
i = d4 + c1; assert(i == 25);
i = d4 + c2; assert(i == 26);
i = d4 + c3; assert(i == 8);
i = d4 + c4; assert(i == 16);
}
/**************************************/
struct Foo4
{
int a;
int opCmp(Foo4 b)
{
return a < b.a;
}
}
void test4()
{
Foo4 a;
Foo4 b;
assert(a <= b);
}
/**************************************/
class A5
{
int opUnary(string op)() if (op == "-") { return 10; }
int opUnary(string op)() if (op == "~") { return 11; }
int opUnary(string op)() if (op == "++") { return 12; }
int opUnary(string op)() if (op == "--") { return 13; }
int opBinary(string op)(int j) if (op == "+") { return 14; }
int opBinary(string op)(int j) if (op == "-") { return 15; }
int opBinaryRight(string op)(int j) if (op == "-") { return 16; }
int opBinary(string op)(int j) if (op == "*") { return 17; }
int opBinary(string op)(int j) if (op == "/") { return 18; }
int opBinaryRight(string op)(int j) if (op == "/") { return 19; }
int opBinary(string op)(int j) if (op == "%") { return 20; }
int opBinaryRight(string op)(int j) if (op == "%") { return 21; }
int opBinary(string op)(int j) if (op == "&") { return 22; }
int opBinary(string op)(int j) if (op == "|") { return 23; }
int opBinary(string op)(int j) if (op == "^") { return 24; }
int opBinary(string op)(int j) if (op == "<<") { return 25; }
int opBinaryRight(string op)(int j) if (op == "<<") { return 26; }
int opBinary(string op)(int j) if (op == ">>") { return 27; }
int opBinaryRight(string op)(int j) if (op == ">>") { return 28; }
int opBinary(string op)(int j) if (op == ">>>") { return 29; }
int opBinaryRight(string op)(int j) if (op == ">>>") { return 30; }
int opBinary(string op)(int j) if (op == "~") { return 31; }
int opBinaryRight(string op)(int j) if (op == "~") { return 32; }
int opEquals(int j) { return 33; }
int opCmp(int j) { return 34; }
int opOpAssign(string op)(int j) if (op == "+") { return 35; }
int opOpAssign(string op)(int j) if (op == "-") { return 36; }
int opOpAssign(string op)(int j) if (op == "*") { return 37; }
int opOpAssign(string op)(int j) if (op == "/") { return 38; }
int opOpAssign(string op)(int j) if (op == "%") { return 39; }
int opOpAssign(string op)(int j) if (op == "&") { return 40; }
int opOpAssign(string op)(int j) if (op == "|") { return 41; }
int opOpAssign(string op)(int j) if (op == "^") { return 42; }
int opOpAssign(string op)(int j) if (op == "<<") { return 43; }
int opOpAssign(string op)(int j) if (op == ">>") { return 44; }
int opOpAssign(string op)(int j) if (op == ">>>") { return 45; }
int opOpAssign(string op)(int j) if (op == "~") { return 46; }
}
void test5()
{
A5 a = new A5();
int i;
i = -a;
assert(i == 10);
i = ~a;
assert(i == 11);
i = ++a;
assert(i == 12);
i = --a;
assert(i == 13);
i = a + 1;
assert(i == 14);
i = a - 1;
assert(i == 15);
i = 1 - a;
assert(i == 16);
i = a * 1;
assert(i == 17);
i = a / 1;
assert(i == 18);
i = 1 / a;
assert(i == 19);
i = a % 1;
assert(i == 20);
i = 1 % a;
assert(i == 21);
i = a & 1;
assert(i == 22);
i = a | 1;
assert(i == 23);
i = a ^ 1;
assert(i == 24);
i = a << 1;
assert(i == 25);
i = 1 << a;
assert(i == 26);
i = a >> 1;
assert(i == 27);
i = 1 >> a;
assert(i == 28);
i = a >>> 1;
assert(i == 29);
i = 1 >>> a;
assert(i == 30);
i = a ~ 1;
assert(i == 31);
i = 1 ~ a;
assert(i == 32);
i = a == 1;
assert(i == 33);
i = 1 == a;
assert(i == 33);
i = a != 1;
assert(i == 0);
i = 1 != a;
assert(i == 0);
i = a < 1;
assert(i == 0);
i = a <= 1;
assert(i == 0);
i = a > 1;
assert(i == 1);
i = a >= 1;
assert(i == 1);
i = 1 < a;
printf("i = %d\n", i);
assert(i == 1);
i = 1 <= a;
assert(i == 1);
i = 1 > a;
assert(i == 0);
i = 1 >= a;
assert(i == 0);
i = (a += 1);
assert(i == 35);
i = (a -= 1);
assert(i == 36);
i = (a *= 1);
assert(i == 37);
i = (a /= 1);
assert(i == 38);
i = (a %= 1);
assert(i == 39);
i = (a &= 1);
assert(i == 40);
i = (a |= 1);
assert(i == 41);
i = (a ^= 1);
assert(i == 42);
i = (a <<= 1);
assert(i == 43);
i = (a >>= 1);
assert(i == 44);
i = (a >>>= 1);
assert(i == 45);
i = (a ~= 1);
assert(i == 46);
}
/*********************************/
struct A6
{
int opUnary(string op)() if (op == "-") { return 10; }
int opUnary(string op)() if (op == "~") { return 11; }
int opUnary(string op)() if (op == "++") { return 12; }
int opUnary(string op)() if (op == "--") { return 13; }
int opBinary(string op)(int j) if (op == "+") { return 14; }
int opBinary(string op)(int j) if (op == "-") { return 15; }
int opBinaryRight(string op)(int j) if (op == "-") { return 16; }
int opBinary(string op)(int j) if (op == "*") { return 17; }
int opBinary(string op)(int j) if (op == "/") { return 18; }
int opBinaryRight(string op)(int j) if (op == "/") { return 19; }
int opBinary(string op)(int j) if (op == "%") { return 20; }
int opBinaryRight(string op)(int j) if (op == "%") { return 21; }
int opBinary(string op)(int j) if (op == "&") { return 22; }
int opBinary(string op)(int j) if (op == "|") { return 23; }
int opBinary(string op)(int j) if (op == "^") { return 24; }
int opBinary(string op)(int j) if (op == "<<") { return 25; }
int opBinaryRight(string op)(int j) if (op == "<<") { return 26; }
int opBinary(string op)(int j) if (op == ">>") { return 27; }
int opBinaryRight(string op)(int j) if (op == ">>") { return 28; }
int opBinary(string op)(int j) if (op == ">>>") { return 29; }
int opBinaryRight(string op)(int j) if (op == ">>>") { return 30; }
int opBinary(string op)(int j) if (op == "~") { return 31; }
int opBinaryRight(string op)(int j) if (op == "~") { return 32; }
int opEquals(int j) { return 33; }
const bool opEquals(const ref A6) { return false; }
int opCmp(int j) { return 34; }
int opOpAssign(string op)(int j) if (op == "+") { return 35; }
int opOpAssign(string op)(int j) if (op == "-") { return 36; }
int opOpAssign(string op)(int j) if (op == "*") { return 37; }
int opOpAssign(string op)(int j) if (op == "/") { return 38; }
int opOpAssign(string op)(int j) if (op == "%") { return 39; }
int opOpAssign(string op)(int j) if (op == "&") { return 40; }
int opOpAssign(string op)(int j) if (op == "|") { return 41; }
int opOpAssign(string op)(int j) if (op == "^") { return 42; }
int opOpAssign(string op)(int j) if (op == "<<") { return 43; }
int opOpAssign(string op)(int j) if (op == ">>") { return 44; }
int opOpAssign(string op)(int j) if (op == ">>>") { return 45; }
int opOpAssign(string op)(int j) if (op == "~") { return 46; }
}
void test6()
{
A6 a;
int i;
i = -a;
assert(i == 10);
i = ~a;
assert(i == 11);
i = ++a;
assert(i == 12);
i = --a;
assert(i == 13);
i = a + 1;
assert(i == 14);
i = a - 1;
assert(i == 15);
i = 1 - a;
assert(i == 16);
i = a * 1;
assert(i == 17);
i = a / 1;
assert(i == 18);
i = 1 / a;
assert(i == 19);
i = a % 1;
assert(i == 20);
i = 1 % a;
assert(i == 21);
i = a & 1;
assert(i == 22);
i = a | 1;
assert(i == 23);
i = a ^ 1;
assert(i == 24);
i = a << 1;
assert(i == 25);
i = 1 << a;
assert(i == 26);
i = a >> 1;
assert(i == 27);
i = 1 >> a;
assert(i == 28);
i = a >>> 1;
assert(i == 29);
i = 1 >>> a;
assert(i == 30);
i = a ~ 1;
assert(i == 31);
i = 1 ~ a;
assert(i == 32);
i = a == 1;
assert(i == 33);
i = 1 == a;
assert(i == 33);
i = a != 1;
assert(i == 0);
i = 1 != a;
assert(i == 0);
i = a < 1;
assert(i == 0);
i = a <= 1;
assert(i == 0);
i = a > 1;
assert(i == 1);
i = a >= 1;
assert(i == 1);
i = 1 < a;
assert(i == 1);
i = 1 <= a;
assert(i == 1);
i = 1 > a;
assert(i == 0);
i = 1 >= a;
assert(i == 0);
i = (a += 1);
assert(i == 35);
i = (a -= 1);
assert(i == 36);
i = (a *= 1);
assert(i == 37);
i = (a /= 1);
assert(i == 38);
i = (a %= 1);
assert(i == 39);
i = (a &= 1);
assert(i == 40);
i = (a |= 1);
assert(i == 41);
i = (a ^= 1);
assert(i == 42);
i = (a <<= 1);
assert(i == 43);
i = (a >>= 1);
assert(i == 44);
i = (a >>>= 1);
assert(i == 45);
i = (a ~= 1);
assert(i == 46);
}
/**************************************/
struct Foo7
{
int opSlice() { return 7; }
int opSlice(int i, int j) { return i * (j + 1); }
}
void test7()
{
Foo7 f;
int i;
i = f[];
assert(i == 7);
i = f[3..4];
assert(i == 15);
}
/**************************************/
interface IWriter
{
int opBinary(string op)(string i) if (op == "<<");
int opBinary(string op)(int i) if (op == "<<");
}
class Writer : IWriter
{
int opBinary(string op)(string i) if (op == "<<")
{
printf("Writer.opShl(char[])\n");
return 1;
}
int opBinary(string op)(int i) if (op == "<<")
{
printf("Writer.opShl(int)\n");
return 2;
}
}
class BinaryWriter : Writer
{
int opBinary(string op)(string i) if (op == "<<")
{
printf("Writer.opShl(char[])\n");
return 1;
}
int opBinary(string op)(int i) if (op == "<<")
{
printf("BinaryWriter.opShl(int)\n");
return 3;
}
}
void test8()
{
BinaryWriter bw = new BinaryWriter();
int i;
i = bw << "test";
assert(i == 1);
i = bw << 1;
assert(i == 3);
}
/**************************************/
struct A9
{
int opCast() { return 28; }
}
void test9()
{
A9 a;
long i = cast(long)a;
assert(i == 28);
}
/**************************************/
class A10
{
int opBinary(string op)(int i) if (op == "+") { return i + 1; }
alias opBinaryRight = opBinary;
}
class B10
{
int opBinaryRight(string op)(A10 a) if (op == "+") { return 3; }
alias opBinary = opBinaryRight;
}
void test10()
{
int i;
A10 a = new A10();
i = a + 1;
printf("a + 1 = %d\n", i);
assert(i == 2);
i = 1 + a;
printf("1 + a = %d\n", i);
assert(i == 2);
B10 b = new B10();
i = a + b;
printf("a + b = %d\n", i);
assert(i == 3);
i = b + a;
printf("b + a = %d\n", i);
assert(i == 3);
// i = b + 3;
}
/**************************************/
class A11
{
int opIndex(int i) { return i; }
int opIndexAssign(int value, int i) { return value * 10 + i; }
}
void test11()
{
int i;
A11 a = new A11();
i = a[5];
assert(i == 5);
i = (a[4] = 6);
printf("i = %d\n", i);
assert(i == 64);
}
/**************************************/
class A12
{
int opIndex(int i1, int i2) { return i1 * 10 + i2; }
int opIndexAssign(int value, int i1, int i2) { return value * 100 + i1 * 10 + i2; }
}
void test12()
{
A12 a = new A12();
int i;
printf("%d\n", a[1, 2]);
assert(a[1, 2] == 12);
i = (a[3, 4] = 5);
printf("%d\n", i);
assert(i == 534);
}
/**************************************/
class A13
{
A13 opBinary(string op)(int x) if (op == "<<")
{
printf("A::opShl(int %d)\n", x);
printf("%d",x);
return this;
}
A13 opBinary(string op)(string x) if (op == "<<")
{
printf("A::opShl(char[])\n");
printf("%.*s", cast(int)x.length, x.ptr);
return this;
}
}
class B13
{
A13 opBinaryRight(string op)(A13 a) if (op == "<<")
{
printf("B::opShl_r(A)\n");
return a;
}
}
void test13()
{
A13 a = new A13();
a << 4 << " " << 12 << "\n";
B13 b = new B13();
a << b;
}
/**************************************/
class Foo14
{ int a;
int opBinary(string op)(int x) if (op == "in")
{
return a + x;
}
}
void test14()
{
auto f = new Foo14;
f.a = 3;
auto i = f in 7;
assert(i == 10);
}
/**************************************/
// https://issues.dlang.org/show_bug.cgi?id=3983
struct Fug
{
bool opEquals(ref const Fug y) const {
return false;
}
}
struct Fig
{
Fug f;
bool opEquals(Tdummy=void)(ref const Fig y) const {
return false;
}
bool opEquals(T: int)(T y) const {
return false;
}
}
void test15()
{
Fig fx, fy;
if (fx==2) {}
}
/**************************************/
// https://issues.dlang.org/show_bug.cgi?id=4953
struct S4953a
{
short _x;
bool opBinaryRight(string op)(short x) if (op == "in")
{
return x == _x;
}
}
void test4953a()
{
S4953a s;
5 in s;
}
struct S4953b
{
void opBinary(string op)(short x)
{}
}
void test4953b()
{
S4953b s;
s + 5;
}
struct S4953c
{
void funOpAssign(float[1u] data) { }
void opOpAssign(string op)(float[1u] data) if(op=="<<") { }
}
void test4953c()
{
// dmd v2.054, v2.055
S4953c s;
float[1u] a = [1.0f]; // OK: Implicit cast from float[] compiles
s.funOpAssign([1.0f]); // OK: Implicit cast from float[] compiles
s <<= [1.0f]; // Issue: Implicit cast from float[] does not compile
s <<= cast(float[1u])[1.0f]; // OK: Explicit cast from float[] compiles
}
void f4953d1 (dstring d) { dstring e = d; }
void f4953d2()(dstring d) { dstring e = d; }
void f4953d3 ( byte[] b) { byte[] c = b; }
void f4953d4()( byte[] b) { byte[] c = b; }
void test4953d()
{
f4953d1("abc"); // OK
f4953d2("abc"); // OK
f4953d3([1,2,3]); // OK
f4953d4([1,2,3]);
// Error: template test2.f() does not match any function template declaration
// Error: template test2.f() cannot deduce template function from argument types !()(int[])
}
/**************************************/
// https://issues.dlang.org/show_bug.cgi?id=4993
// reduced from the bug report
struct Bar4993
{
void opIndexAssign(int value, size_t index) {}
}
@property auto bar4993()
{
return Bar4993();
}
void test4993()
{
bar4993[3] = 42;
}
/**************************************/
// https://issues.dlang.org/show_bug.cgi?id=8133
void test8133()
{
struct S
{
int opCall() { return 1; }
}
struct A
{
S s;
alias s this;
}
A f = A();
assert(f() == 1);
}
/**************************************/
// https://issues.dlang.org/show_bug.cgi?id=8522
struct Point8522
{
bool opEquals(R)(R rhs) { return true; }
bool opEquals(R)(R rhs) const { return true; }
}
void test8522()
{
Point8522 mp;
const Point8522 cp;
assert(mp == mp);
assert(mp == cp);
assert(cp == mp); // doesn't work
assert(cp == cp); // doesn't work
}
/**************************************/
// https://issues.dlang.org/show_bug.cgi?id=12778
struct Vec12778X
{
Vec12778X opBinary(string op)(Vec12778X b) const
if (op == "+")
{
mixin("return Vec12778X(this.x " ~ op ~ " b.x, this.y " ~ op ~ " b.y);");
}
alias opBinaryRight = opBinary;
float x = 0, y = 0;
}
void test12778()
{
struct S
{
void test1()
{
Vec12778X vx = vx1 + vx2; // ok
}
void test2() const
{
Vec12778X vx = vx1 + vx2; // ok <- error
}
Vec12778X vx1, vx2;
}
}
/**************************************/
// https://issues.dlang.org/show_bug.cgi?id=14343
struct S14343a
{
int i;
immutable(Object) o;
S14343a opUnary(string op)() { return this; }
void opAssign(S14343a other) {}
}
struct S14343b
{
int i;
immutable(Object) o;
void opOpAssign(string op)(int j) if (op == "+") { i += j; }
S14343b opUnary(string op)() if (op == "++") { ++i; return this; }
void opAssign(S14343b other) {}
}
void test14343()
{
{
S14343a s, t;
t = s; // OK
++s; // OK
s++; // OK <- Error: cannot modify struct s S with immutable members
}
{
S14343b s;
++s;
assert(s.i == 1);
s++;
assert(s.i == 2);
}
}
/**************************************/
// https://issues.dlang.org/show_bug.cgi?id=14344
struct S14344
{
S14344 opBinary(string op)(S14344 v)
{
static assert(0);
}
S14344 opAssign()(S14344 v)
{
static assert(0);
}
}
struct S14344Mix
{
S14344 s;
alias s this;
}
class C14344
{
S14344Mix height() { return S14344Mix(); }
void update()
{
S14344 height = this.height;
}
}
/**************************************/
// https://issues.dlang.org/show_bug.cgi?id=1547
struct A
{
int b;
static A opCall(int k)
{
assert(0);
}
this(int) {}
}
void fun(A k = 2) {}
void test1547()
{
fun();
}
/**************************************/
// https://issues.dlang.org/show_bug.cgi?id=20475
struct S20475
{
string[2] x;
}
void test20475()
{
auto s = S20475(["abc", "bcd"]);
auto t = S20475(["abc", ""]);
string u = "abcd";
t.x[1] = u[1..$];
assert(s == t);
}
/**************************************/
int main()
{
test1();
test2();
test3();
test4();
test5();
test6();
test7();
test8();
test9();
test10();
test11();
test12();
test13();
test14();
test15();
test1547();
test4953a();
test4953b();
test4953c();
test4953d();
test4993();
test8133();
test8522();
test20475();
printf("Success\n");
return 0;
}