|
16 | 16 | module module_analyser; |
17 | 17 |
|
18 | 18 | import ast local; |
| 19 | +import c2_prec local; |
19 | 20 | import conversion_checker; |
20 | 21 | import ctv_analyser; |
21 | 22 |
|
@@ -400,6 +401,70 @@ const u8[elemsof(TypeKind)][elemsof(TypeKind)] BinOpConvComparision = { |
400 | 401 | // Alias + Module are zero |
401 | 402 | } |
402 | 403 |
|
| 404 | +const Prec[elemsof(BinaryOpcode)] Prec_table = { |
| 405 | + [BinaryOpcode.Multiply] = Multiplicative, |
| 406 | + [BinaryOpcode.Divide] = Multiplicative, |
| 407 | + [BinaryOpcode.Remainder] = Multiplicative, |
| 408 | + [BinaryOpcode.Add] = Additive, |
| 409 | + [BinaryOpcode.Subtract] = Additive, |
| 410 | + [BinaryOpcode.ShiftLeft] = Shift, |
| 411 | + [BinaryOpcode.ShiftRight] = Shift, |
| 412 | + [BinaryOpcode.LessThan] = Relational, |
| 413 | + [BinaryOpcode.GreaterThan] = Relational, |
| 414 | + [BinaryOpcode.LessEqual] = Relational, |
| 415 | + [BinaryOpcode.GreaterEqual] = Relational, |
| 416 | + [BinaryOpcode.Equal] = Relational, |
| 417 | + [BinaryOpcode.NotEqual] = Relational, |
| 418 | + [BinaryOpcode.And] = Bitwise, |
| 419 | + [BinaryOpcode.Xor] = Bitwise, |
| 420 | + [BinaryOpcode.Or] = Bitwise, |
| 421 | + [BinaryOpcode.LAnd] = LogicalAndOr, |
| 422 | + [BinaryOpcode.LOr] = LogicalAndOr, |
| 423 | + [BinaryOpcode.Assign] = Assignment, |
| 424 | + [BinaryOpcode.MulAssign] = Assignment, |
| 425 | + [BinaryOpcode.DivAssign] = Assignment, |
| 426 | + [BinaryOpcode.RemAssign] = Assignment, |
| 427 | + [BinaryOpcode.AddAssign] = Assignment, |
| 428 | + [BinaryOpcode.SubAssign] = Assignment, |
| 429 | + [BinaryOpcode.ShlAssign] = Assignment, |
| 430 | + [BinaryOpcode.ShrAssign] = Assignment, |
| 431 | + [BinaryOpcode.AndAssign] = Assignment, |
| 432 | + [BinaryOpcode.XorAssign] = Assignment, |
| 433 | + [BinaryOpcode.OrAssign] = Assignment, |
| 434 | +} |
| 435 | + |
| 436 | +const C_Prec[elemsof(BinaryOpcode)] C_Prec_table = { |
| 437 | + [BinaryOpcode.Multiply] = Multiplicative, |
| 438 | + [BinaryOpcode.Divide] = Multiplicative, |
| 439 | + [BinaryOpcode.Remainder] = Multiplicative, |
| 440 | + [BinaryOpcode.Add] = Additive, |
| 441 | + [BinaryOpcode.Subtract] = Additive, |
| 442 | + [BinaryOpcode.ShiftLeft] = Shift, |
| 443 | + [BinaryOpcode.ShiftRight] = Shift, |
| 444 | + [BinaryOpcode.LessThan] = Relative, |
| 445 | + [BinaryOpcode.GreaterThan] = Relative, |
| 446 | + [BinaryOpcode.LessEqual] = Relative, |
| 447 | + [BinaryOpcode.GreaterEqual] = Relative, |
| 448 | + [BinaryOpcode.Equal] = Equality, |
| 449 | + [BinaryOpcode.NotEqual] = Equality, |
| 450 | + [BinaryOpcode.And] = And, |
| 451 | + [BinaryOpcode.Xor] = Xor, |
| 452 | + [BinaryOpcode.Or] = Or, |
| 453 | + [BinaryOpcode.LAnd] = LogicalAnd, |
| 454 | + [BinaryOpcode.LOr] = LogicalOr, |
| 455 | + [BinaryOpcode.Assign] = Assignment, |
| 456 | + [BinaryOpcode.MulAssign] = Assignment, |
| 457 | + [BinaryOpcode.DivAssign] = Assignment, |
| 458 | + [BinaryOpcode.RemAssign] = Assignment, |
| 459 | + [BinaryOpcode.AddAssign] = Assignment, |
| 460 | + [BinaryOpcode.SubAssign] = Assignment, |
| 461 | + [BinaryOpcode.ShlAssign] = Assignment, |
| 462 | + [BinaryOpcode.ShrAssign] = Assignment, |
| 463 | + [BinaryOpcode.AndAssign] = Assignment, |
| 464 | + [BinaryOpcode.XorAssign] = Assignment, |
| 465 | + [BinaryOpcode.OrAssign] = Assignment, |
| 466 | +} |
| 467 | + |
403 | 468 | fn QualType Analyser.checkBinopComparison(Analyser* ma, BinaryOperator* b, QualType lhs, QualType rhs) { |
404 | 469 | QualType lcanon = lhs.getCanonicalType(); |
405 | 470 | QualType rcanon = rhs.getCanonicalType(); |
@@ -475,6 +540,16 @@ fn QualType Analyser.checkPointerFuncComparison(Analyser* ma, BinaryOperator* b, |
475 | 540 | return QualType_Invalid; |
476 | 541 | } |
477 | 542 |
|
| 543 | +fn bool incompatible_opcodes(BinaryOpcode op1, BinaryOpcode op2) { |
| 544 | + C_Prec c_p1 = C_Prec_table[op1]; |
| 545 | + C_Prec c_p2 = C_Prec_table[op2]; |
| 546 | + Prec c2_p1 = Prec_table[op1]; |
| 547 | + Prec c2_p2 = Prec_table[op2]; |
| 548 | + if (c2_p1 == c2_p2) return c2_p1 == Relational || c_p1 != c_p2; |
| 549 | + if (c2_p1 < c2_p2) return c_p1 >= c_p2; |
| 550 | + return c_p1 <= c_p2; |
| 551 | +} |
| 552 | + |
478 | 553 | fn QualType Analyser.analyseBinaryOperator(Analyser* ma, Expr** e_ptr) { |
479 | 554 | Expr* e = *e_ptr; |
480 | 555 | BinaryOperator* b = (BinaryOperator*)e; |
@@ -510,6 +585,23 @@ fn QualType Analyser.analyseBinaryOperator(Analyser* ma, Expr** e_ptr) { |
510 | 585 | Expr* lhs = b.getLHS(); |
511 | 586 | Expr* rhs = b.getRHS(); |
512 | 587 |
|
| 588 | + if (lhs.isBinaryOperator()) { |
| 589 | + BinaryOpcode op1 = cast<BinaryOperator*>(lhs).getOpcode(); |
| 590 | + if (incompatible_opcodes(opcode, op1)) { |
| 591 | + ma.error(lhs.getLoc(), "operators '%s' and '%s' do not combine without parentheses", |
| 592 | + opcode.str(), op1.str()); |
| 593 | + return QualType_Invalid; |
| 594 | + } |
| 595 | + } |
| 596 | + if (rhs.isBinaryOperator()) { |
| 597 | + BinaryOpcode op2 = cast<BinaryOperator*>(rhs).getOpcode(); |
| 598 | + if (incompatible_opcodes(opcode, op2)) { |
| 599 | + ma.error(rhs.getLoc(), "operators '%s' and '%s' do not combine without parentheses", |
| 600 | + opcode.str(), op2.str()); |
| 601 | + return QualType_Invalid; |
| 602 | + } |
| 603 | + } |
| 604 | + |
513 | 605 | if (!validBinOpKind(ltype) || ltype.isVoid()) { |
514 | 606 | QualType tl = lhs.getType(); |
515 | 607 | ma.error(lhs.getLoc(), "invalid operand to binary expression '%s'", tl.diagName()); |
|
0 commit comments