| /* | |
| * Copyright 2025 WebAssembly Community Group participants | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #include "ir/gc-type-utils.h" | |
| #include "type-test.h" | |
| #include "wasm-type.h" | |
| #include "gtest/gtest.h" | |
| namespace wasm { | |
| using namespace GCTypeUtils; | |
| class CastCheckTest : public TypeTest { | |
| protected: | |
| HeapType super, sub, subFinal; | |
| void SetUp() override { | |
| TypeBuilder builder(3); | |
| builder[0] = Struct(); | |
| builder[0].setOpen(); | |
| builder[1] = Struct(); | |
| builder[1].subTypeOf(builder[0]).setOpen(); | |
| builder[2] = Struct(); | |
| builder[2].subTypeOf(builder[0]); | |
| auto built = builder.build(); | |
| ASSERT_TRUE(built); | |
| super = (*built)[0]; | |
| sub = (*built)[1]; | |
| subFinal = (*built)[2]; | |
| } | |
| }; | |
| TEST_F(CastCheckTest, CastToSelfNonFinal) { | |
| #define EXPECT_CAST( \ | |
| srcNullability, srcExactness, castNullability, castExactness, result) \ | |
| EXPECT_EQ(evaluateCastCheck(Type(super, srcNullability, srcExactness), \ | |
| Type(super, castNullability, castExactness)), \ | |
| result); | |
| EXPECT_CAST(Nullable, Inexact, Nullable, Inexact, Success); | |
| EXPECT_CAST(Nullable, Inexact, Nullable, Exact, Unknown); | |
| EXPECT_CAST(Nullable, Inexact, NonNullable, Inexact, SuccessOnlyIfNonNull); | |
| EXPECT_CAST(Nullable, Inexact, NonNullable, Exact, Unknown); | |
| EXPECT_CAST(Nullable, Exact, Nullable, Inexact, Success); | |
| EXPECT_CAST(Nullable, Exact, Nullable, Exact, Success); | |
| EXPECT_CAST(Nullable, Exact, NonNullable, Inexact, SuccessOnlyIfNonNull); | |
| EXPECT_CAST(Nullable, Exact, NonNullable, Exact, SuccessOnlyIfNonNull); | |
| EXPECT_CAST(NonNullable, Inexact, Nullable, Inexact, Success); | |
| EXPECT_CAST(NonNullable, Inexact, Nullable, Exact, Unknown); | |
| EXPECT_CAST(NonNullable, Inexact, NonNullable, Inexact, Success); | |
| EXPECT_CAST(NonNullable, Inexact, NonNullable, Exact, Unknown); | |
| EXPECT_CAST(NonNullable, Exact, Nullable, Inexact, Success); | |
| EXPECT_CAST(NonNullable, Exact, Nullable, Exact, Success); | |
| EXPECT_CAST(NonNullable, Exact, NonNullable, Inexact, Success); | |
| EXPECT_CAST(NonNullable, Exact, NonNullable, Exact, Success); | |
| #undef EXPECT_CAST | |
| } | |
| TEST_F(CastCheckTest, CastToSelfFinal) { | |
| #define EXPECT_CAST( \ | |
| srcNullability, srcExactness, castNullability, castExactness, result) \ | |
| EXPECT_EQ(evaluateCastCheck(Type(subFinal, srcNullability, srcExactness), \ | |
| Type(subFinal, castNullability, castExactness)), \ | |
| result); | |
| EXPECT_CAST(Nullable, Inexact, Nullable, Inexact, Success); | |
| EXPECT_CAST(Nullable, Inexact, Nullable, Exact, Success); | |
| EXPECT_CAST(Nullable, Inexact, NonNullable, Inexact, SuccessOnlyIfNonNull); | |
| EXPECT_CAST(Nullable, Inexact, NonNullable, Exact, SuccessOnlyIfNonNull); | |
| EXPECT_CAST(Nullable, Exact, Nullable, Inexact, Success); | |
| EXPECT_CAST(Nullable, Exact, Nullable, Exact, Success); | |
| EXPECT_CAST(Nullable, Exact, NonNullable, Inexact, SuccessOnlyIfNonNull); | |
| EXPECT_CAST(Nullable, Exact, NonNullable, Exact, SuccessOnlyIfNonNull); | |
| EXPECT_CAST(NonNullable, Inexact, Nullable, Inexact, Success); | |
| EXPECT_CAST(NonNullable, Inexact, Nullable, Exact, Success); | |
| EXPECT_CAST(NonNullable, Inexact, NonNullable, Inexact, Success); | |
| EXPECT_CAST(NonNullable, Inexact, NonNullable, Exact, Success); | |
| EXPECT_CAST(NonNullable, Exact, Nullable, Inexact, Success); | |
| EXPECT_CAST(NonNullable, Exact, Nullable, Exact, Success); | |
| EXPECT_CAST(NonNullable, Exact, NonNullable, Inexact, Success); | |
| EXPECT_CAST(NonNullable, Exact, NonNullable, Exact, Success); | |
| #undef EXPECT_CAST | |
| } | |
| TEST_F(CastCheckTest, CastToSuper) { | |
| #define EXPECT_CAST( \ | |
| srcNullability, srcExactness, castNullability, castExactness, result) \ | |
| EXPECT_EQ(evaluateCastCheck(Type(sub, srcNullability, srcExactness), \ | |
| Type(super, castNullability, castExactness)), \ | |
| result); | |
| EXPECT_CAST(Nullable, Inexact, Nullable, Inexact, Success); | |
| EXPECT_CAST(Nullable, Inexact, Nullable, Exact, SuccessOnlyIfNull); | |
| EXPECT_CAST(Nullable, Inexact, NonNullable, Inexact, SuccessOnlyIfNonNull); | |
| EXPECT_CAST(Nullable, Inexact, NonNullable, Exact, Failure); | |
| EXPECT_CAST(Nullable, Exact, Nullable, Inexact, Success); | |
| EXPECT_CAST(Nullable, Exact, Nullable, Exact, SuccessOnlyIfNull); | |
| EXPECT_CAST(Nullable, Exact, NonNullable, Inexact, SuccessOnlyIfNonNull); | |
| EXPECT_CAST(Nullable, Exact, NonNullable, Exact, Failure); | |
| EXPECT_CAST(NonNullable, Inexact, Nullable, Inexact, Success); | |
| EXPECT_CAST(NonNullable, Inexact, Nullable, Exact, Failure); | |
| EXPECT_CAST(NonNullable, Inexact, NonNullable, Inexact, Success); | |
| EXPECT_CAST(NonNullable, Inexact, NonNullable, Exact, Failure); | |
| EXPECT_CAST(NonNullable, Exact, Nullable, Inexact, Success); | |
| EXPECT_CAST(NonNullable, Exact, Nullable, Exact, Failure); | |
| EXPECT_CAST(NonNullable, Exact, NonNullable, Inexact, Success); | |
| EXPECT_CAST(NonNullable, Exact, NonNullable, Exact, Failure); | |
| #undef EXPECT_CAST | |
| } | |
| TEST_F(CastCheckTest, CastToSub) { | |
| #define EXPECT_CAST( \ | |
| srcNullability, srcExactness, castNullability, castExactness, result) \ | |
| EXPECT_EQ(evaluateCastCheck(Type(super, srcNullability, srcExactness), \ | |
| Type(sub, castNullability, castExactness)), \ | |
| result); | |
| EXPECT_CAST(Nullable, Inexact, Nullable, Inexact, Unknown); | |
| EXPECT_CAST(Nullable, Inexact, Nullable, Exact, Unknown); | |
| EXPECT_CAST(Nullable, Inexact, NonNullable, Inexact, Unknown); | |
| EXPECT_CAST(Nullable, Inexact, NonNullable, Exact, Unknown); | |
| EXPECT_CAST(Nullable, Exact, Nullable, Inexact, SuccessOnlyIfNull); | |
| EXPECT_CAST(Nullable, Exact, Nullable, Exact, SuccessOnlyIfNull); | |
| EXPECT_CAST(Nullable, Exact, NonNullable, Inexact, Failure); | |
| EXPECT_CAST(Nullable, Exact, NonNullable, Exact, Failure); | |
| EXPECT_CAST(NonNullable, Inexact, Nullable, Inexact, Unknown); | |
| EXPECT_CAST(NonNullable, Inexact, Nullable, Exact, Unknown); | |
| EXPECT_CAST(NonNullable, Inexact, NonNullable, Inexact, Unknown); | |
| EXPECT_CAST(NonNullable, Inexact, NonNullable, Exact, Unknown); | |
| EXPECT_CAST(NonNullable, Exact, Nullable, Inexact, Failure); | |
| EXPECT_CAST(NonNullable, Exact, Nullable, Exact, Failure); | |
| EXPECT_CAST(NonNullable, Exact, NonNullable, Inexact, Failure); | |
| EXPECT_CAST(NonNullable, Exact, NonNullable, Exact, Failure); | |
| #undef EXPECT_CAST | |
| } | |
| TEST_F(CastCheckTest, CastToSibling) { | |
| #define EXPECT_CAST( \ | |
| srcNullability, srcExactness, castNullability, castExactness, result) \ | |
| EXPECT_EQ(evaluateCastCheck(Type(sub, srcNullability, srcExactness), \ | |
| Type(subFinal, castNullability, castExactness)), \ | |
| result); | |
| EXPECT_CAST(Nullable, Inexact, Nullable, Inexact, SuccessOnlyIfNull); | |
| EXPECT_CAST(Nullable, Inexact, Nullable, Exact, SuccessOnlyIfNull); | |
| EXPECT_CAST(Nullable, Inexact, NonNullable, Inexact, Failure); | |
| EXPECT_CAST(Nullable, Inexact, NonNullable, Exact, Failure); | |
| EXPECT_CAST(Nullable, Exact, Nullable, Inexact, SuccessOnlyIfNull); | |
| EXPECT_CAST(Nullable, Exact, Nullable, Exact, SuccessOnlyIfNull); | |
| EXPECT_CAST(Nullable, Exact, NonNullable, Inexact, Failure); | |
| EXPECT_CAST(Nullable, Exact, NonNullable, Exact, Failure); | |
| EXPECT_CAST(NonNullable, Inexact, Nullable, Inexact, Failure); | |
| EXPECT_CAST(NonNullable, Inexact, Nullable, Exact, Failure); | |
| EXPECT_CAST(NonNullable, Inexact, NonNullable, Inexact, Failure); | |
| EXPECT_CAST(NonNullable, Inexact, NonNullable, Exact, Failure); | |
| EXPECT_CAST(NonNullable, Exact, Nullable, Inexact, Failure); | |
| EXPECT_CAST(NonNullable, Exact, Nullable, Exact, Failure); | |
| EXPECT_CAST(NonNullable, Exact, NonNullable, Inexact, Failure); | |
| EXPECT_CAST(NonNullable, Exact, NonNullable, Exact, Failure); | |
| #undef EXPECT_CAST | |
| } | |
| TEST_F(CastCheckTest, CastToBottom) { | |
| #define EXPECT_CAST(srcNullability, srcExactness, castNullability, result) \ | |
| EXPECT_EQ(evaluateCastCheck(Type(super, srcNullability, srcExactness), \ | |
| Type(HeapType::none, castNullability, Inexact)), \ | |
| result); | |
| EXPECT_CAST(Nullable, Inexact, Nullable, SuccessOnlyIfNull); | |
| EXPECT_CAST(Nullable, Inexact, NonNullable, Failure); | |
| EXPECT_CAST(Nullable, Exact, Nullable, SuccessOnlyIfNull); | |
| EXPECT_CAST(Nullable, Exact, NonNullable, Failure); | |
| EXPECT_CAST(NonNullable, Inexact, Nullable, Failure); | |
| EXPECT_CAST(NonNullable, Inexact, NonNullable, Failure); | |
| EXPECT_CAST(NonNullable, Exact, Nullable, Failure); | |
| EXPECT_CAST(NonNullable, Exact, NonNullable, Failure); | |
| #undef EXPECT_CAST | |
| } | |
| TEST_F(CastCheckTest, CastFromBottom) { | |
| #define EXPECT_CAST(srcNullability, castNullability, castExactness, result) \ | |
| EXPECT_EQ(evaluateCastCheck(Type(HeapType::none, srcNullability, Inexact), \ | |
| Type(super, castNullability, castExactness)), \ | |
| result); | |
| EXPECT_CAST(Nullable, Nullable, Inexact, Success); | |
| EXPECT_CAST(Nullable, Nullable, Exact, Success); | |
| EXPECT_CAST(Nullable, NonNullable, Inexact, Failure); | |
| EXPECT_CAST(Nullable, NonNullable, Exact, Failure); | |
| EXPECT_CAST(NonNullable, Nullable, Inexact, GCTypeUtils::Unreachable); | |
| EXPECT_CAST(NonNullable, Nullable, Exact, GCTypeUtils::Unreachable); | |
| EXPECT_CAST(NonNullable, NonNullable, Inexact, GCTypeUtils::Unreachable); | |
| EXPECT_CAST(NonNullable, NonNullable, Exact, GCTypeUtils::Unreachable); | |
| #undef EXPECT_CAST | |
| } | |
| } // namespace wasm |