All operations A op= B, where A is real or imaginary and A op B is complex, should be illegal, as they are mathematically nonsensical. Sending these operations to the back-end is responsible for at least two internal compiler errors. The operations +=, -=, *=, /=, and %= are all affected. Applies to both D1 and D2. TEST CASE: void main() { ireal x = 3.0i; double y=3; y /= 2.0 + 6i; x *= 7.0i; x *= 3.0i+2; x %= (2+ 6.0i); x += 2.0; x -= 1+4i; y -= 3.0i; } Patch (expression.c): This patch fixes makes the nonsensical operations illegal. Where possible, the error message suggests an alternative. This also fixes two ICE bugs: bug 718 and bug 2839. ===================== @@ -8313,6 +8340,35 @@ return this; } +// generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary +void checkComplexMulAssign(char *opstr, Loc loc, Expression *e1, Expression *e2) { + // Any multiplication by an imaginary or complex number yields a complex result. + // r *= c, i*=c, r*=i, i*=i are all forbidden operations. + if ( e1->type->isreal() && e2->type->iscomplex()) { + error(loc, "%s %s= %s is undefined. Did you mean %s %s= %s.re ?", + e1->type->toChars(), opstr, e2->type->toChars(), + e1->type->toChars(), opstr, e2->type->toChars()); + } else if (e1->type->isimaginary() && e2->type->iscomplex()) { + error(loc, "%s %s= %s is undefined. Did you mean %s %s= %s.im ?", + e1->type->toChars(), opstr, e2->type->toChars(), + e1->type->toChars(), opstr, e2->type->toChars()); + } else if ((e1->type->isreal() || e1->type->isimaginary()) && e2->type->isimaginary()) { + error(loc, "%s %s= %s is an undefined operation", e1->type->toChars(), opstr, e2->type->toChars()); + } +} + +// generate an error if this is a nonsensical += or -=, eg real += imaginary +void checkComplexAddAssign(char *opstr, Loc loc, Expression *e1, Expression *e2) { + // Addition or subtraction of a real and an imaginary is a complex result. + // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations. + if ( (e1->type->isreal() && (e2->type->isimaginary() || e2->type->iscomplex())) || + (e1->type->isimaginary() && (e2->type->isreal() || e2->type->iscomplex())) + ) { + error(loc, "%s %s= %s is undefined (result is complex)", e1->type->toChars(), opstr, e2->type->toChars()); + } +} + + AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2) @@ -8408,6 +8472,7 @@ typeCombine(sc); e1->checkArithmetic(); e2->checkArithmetic(); + checkComplexAddAssign("+", loc, e1, e2); if (type->isreal() || type->isimaginary()) { assert(global.errors || e2->type->isfloating()); @@ -8455,6 +8520,7 @@ { e1 = e1->checkArithmetic(); e2 = e2->checkArithmetic(); + checkComplexAddAssign("-", loc, e1, e2); type = e1->type; typeCombine(sc); if (type->isreal() || type->isimaginary()) @@ -8556,6 +8622,7 @@ typeCombine(sc); e1->checkArithmetic(); e2->checkArithmetic(); + checkComplexMulAssign("*", loc, e1, e2); if (e2->type->isfloating()) { Type *t1; Type *t2; @@ -8619,6 +8686,7 @@ typeCombine(sc); e1->checkArithmetic(); e2->checkArithmetic(); + checkComplexMulAssign("/", loc, e1, e2); if (e2->type->isimaginary()) { Type *t1; Type *t2; @@ -8662,6 +8730,8 @@ Expression *ModAssignExp::semantic(Scope *sc) { + BinExp::semantic(sc); + checkComplexMulAssign("%", loc, e1, e2); return commonSemanticAssign(sc); }
Fixed dmd 1.048 and 2.033
AltStyle によって変換されたページ (->オリジナル) / アドレス: モード: デフォルト 音声ブラウザ ルビ付き 配色反転 文字拡大 モバイル