From 1132058c34bcb074a7ae43d43b608e43f41e4e12 Mon Sep 17 00:00:00 2001 From: Musa Nazif Boya Date: Mon, 26 May 2025 23:43:10 +0300 Subject: [PATCH] fix: Reference comparison check Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICAND3 Reason: There is no comparsion check. Description: CTE should be issued on comparison between incompatible types. Tests: No new tests, old tests passing succesfully. Signed-off-by: Musa Nazif Boya --- ets2panda/checker/ETSchecker.h | 1 + ets2panda/checker/ets/arithmetic.cpp | 13 +++++++++++++ .../compiler/ets/referenceEqualityNotCastable_n.ets | 1 + ets2panda/test/ast/parser/ets/enum7.ets | 1 + ets2panda/test/ast/parser/ets/rest_parameter_13.ets | 2 ++ ets2panda/test/runtime/ets/RestTuple5.ets | 4 ++-- ets2panda/test/runtime/ets/RestTuple6.ets | 4 ++-- ets2panda/test/runtime/ets/RestTuple7.ets | 4 ++-- ets2panda/test/runtime/ets/RestTuple8.ets | 4 ++-- 9 files changed, 26 insertions(+), 8 deletions(-) diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 7de58a472e..9a2de056eb 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -363,6 +363,7 @@ public: checker::Type *CheckBinaryBitwiseOperatorForIntEnums(const checker::Type *const leftType, const checker::Type *const rightType); + bool CheckIsComparableClasses(const checker::Type *const leftType, const checker::Type *const rightType); checker::Type *CheckBinaryOperatorPlus( std::tuple op, bool isEqualOp, std::tuple types); diff --git a/ets2panda/checker/ets/arithmetic.cpp b/ets2panda/checker/ets/arithmetic.cpp index 8eebfe0d38..cb8de11f49 100644 --- a/ets2panda/checker/ets/arithmetic.cpp +++ b/ets2panda/checker/ets/arithmetic.cpp @@ -355,6 +355,13 @@ static checker::Type *CheckBinaryOperatorPlusForEnums(ETSChecker *checker, check return nullptr; } +bool ETSChecker::CheckIsComparableClasses(const checker::Type *const leftType, const checker::Type *const rightType) +{ + return (leftType->IsETSReferenceType() && !leftType->IsETSUnboxableObject()) && + (rightType->IsETSReferenceType() && !rightType->IsETSUnboxableObject()) && + !(leftType->IsETSTypeParameter() && rightType->IsETSTypeParameter()); +} + checker::Type *ETSChecker::CheckBinaryOperatorPlus( std::tuple op, bool isEqualOp, std::tuple types) @@ -603,6 +610,10 @@ bool ETSChecker::CheckValidEqualReferenceType(checker::Type *const leftType, che // NOTE (mxlgv): Skip for generic. Required implementation of the specification section: // 7.25.6 Reference Equality Based on Actual Type (Type Parameter Equality Operators) if (leftType->HasTypeFlag(TypeFlag::GENERIC) || rightType->HasTypeFlag(TypeFlag::GENERIC)) { + if (CheckIsComparableClasses(leftType, rightType) && + (leftType->HasTypeFlag(TypeFlag::ETS_OBJECT) || rightType->HasTypeFlag(TypeFlag::ETS_OBJECT))) { + return Relation()->IsComparableTo(rightType, leftType) || Relation()->IsCastableTo(rightType, leftType); + } return true; } @@ -615,6 +626,8 @@ bool ETSChecker::CheckValidEqualReferenceType(checker::Type *const leftType, che !Relation()->IsIdenticalTo(nonConstRhs, nonConstLhs)) { return false; } + } else if (CheckIsComparableClasses(leftType, rightType)) { + return Relation()->IsComparableTo(rightType, leftType) || Relation()->IsComparableTo(leftType, rightType); } if (FindOpArgsType(this, leftType, rightType, GetGlobalTypesHolder()->GlobalNumericBuiltinType()) && diff --git a/ets2panda/test/ast/compiler/ets/referenceEqualityNotCastable_n.ets b/ets2panda/test/ast/compiler/ets/referenceEqualityNotCastable_n.ets index 51f4fc103e..c101c77314 100644 --- a/ets2panda/test/ast/compiler/ets/referenceEqualityNotCastable_n.ets +++ b/ets2panda/test/ast/compiler/ets/referenceEqualityNotCastable_n.ets @@ -22,4 +22,5 @@ function main(): void { let c = /* @@ label */a === b; } +/* @@? 22:25 Error TypeError: Operator '===' cannot be applied to types 'A' and 'B'. */ /* @@@ label Node { "type": "BinaryExpression", "operator": "===" } */ diff --git a/ets2panda/test/ast/parser/ets/enum7.ets b/ets2panda/test/ast/parser/ets/enum7.ets index 0027570f04..45c1e01d54 100644 --- a/ets2panda/test/ast/parser/ets/enum7.ets +++ b/ets2panda/test/ast/parser/ets/enum7.ets @@ -22,3 +22,4 @@ function main(): void { } /* @@@ label Error TypeError: Bad operand type, the types of the operands must be numeric, same enumeration, or boolean type. */ +/* @@@ label Error TypeError: Operator '!=' cannot be applied to types 'Color' and 'Color2'. */ diff --git a/ets2panda/test/ast/parser/ets/rest_parameter_13.ets b/ets2panda/test/ast/parser/ets/rest_parameter_13.ets index 46f794926f..3a54a9dbf0 100644 --- a/ets2panda/test/ast/parser/ets/rest_parameter_13.ets +++ b/ets2panda/test/ast/parser/ets/rest_parameter_13.ets @@ -45,3 +45,5 @@ function main() { /* @@@ label3 Error TypeError: Expected 2 arguments, got 3. */ /* @@@ label3 Error TypeError: No matching construct signature for rest_parameter_13.C(A, B, B) */ /* @@? 34:37 Error TypeError: Type 'A' is not compatible with type 'Int' at index 1 */ +/* @@? 23:18 Error TypeError: Operator '==' cannot be applied to types 'A' and 'B'. */ +/* @@? 27:18 Error TypeError: Operator '==' cannot be applied to types 'A' and 'B'. */ diff --git a/ets2panda/test/runtime/ets/RestTuple5.ets b/ets2panda/test/runtime/ets/RestTuple5.ets index 888b16c712..74048bae7a 100644 --- a/ets2panda/test/runtime/ets/RestTuple5.ets +++ b/ets2panda/test/runtime/ets/RestTuple5.ets @@ -17,11 +17,11 @@ class A {} class B {} function foo(...p: [A, B]): boolean { - return p[0] == p[1] + return p[0] as Object == p[1] as Object } function moo(a:int, ...p: [A, B]): boolean { - return p[0] == p[1] + return p[0] as Object == p[1] as Object } function main() { diff --git a/ets2panda/test/runtime/ets/RestTuple6.ets b/ets2panda/test/runtime/ets/RestTuple6.ets index 5fc918e8e6..6e7a3a7450 100644 --- a/ets2panda/test/runtime/ets/RestTuple6.ets +++ b/ets2panda/test/runtime/ets/RestTuple6.ets @@ -18,11 +18,11 @@ class B {} class C { foo(...p: [A, B]): boolean { - return p[0] == p[1] + return p[0] as Object == p[1] as Object } moo(a:int, ...p: [A, B]): boolean { - return p[0] == p[1] + return p[0] as Object == p[1] as Object } } diff --git a/ets2panda/test/runtime/ets/RestTuple7.ets b/ets2panda/test/runtime/ets/RestTuple7.ets index 4368052ce6..528200c698 100644 --- a/ets2panda/test/runtime/ets/RestTuple7.ets +++ b/ets2panda/test/runtime/ets/RestTuple7.ets @@ -18,11 +18,11 @@ class B {} class C { static foo(...p: [A, B]): boolean { - return p[0] == p[1] + return p[0] as Object == p[1] as Object } static moo(a:int, ...p: [A, B]): boolean { - return p[0] == p[1] + return p[0] as Object == p[1] as Object } } diff --git a/ets2panda/test/runtime/ets/RestTuple8.ets b/ets2panda/test/runtime/ets/RestTuple8.ets index 3a802df408..cf62866d90 100644 --- a/ets2panda/test/runtime/ets/RestTuple8.ets +++ b/ets2panda/test/runtime/ets/RestTuple8.ets @@ -20,11 +20,11 @@ class C { public field : boolean constructor(...p: [A, B]) { - this.field = p[0] == p[1] + this.field = p[0] as Object == p[1] as Object } constructor(a: int, ...p: [A, B]) { - this.field = p[0] == p[1] + this.field = p[0] as Object == p[1] as Object } } -- Gitee