diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc index cc454908b6..d9be7f8880 100644 --- a/src/tint/resolver/resolver.cc +++ b/src/tint/resolver/resolver.cc @@ -870,10 +870,13 @@ sem::CaseStatement* Resolver::CaseStatement(const ast::CaseStatement* stmt) { auto* sem = builder_->create(stmt, current_compound_statement_, current_function_); return StatementScope(stmt, sem, [&] { + sem->Selectors().reserve(stmt->selectors.size()); for (auto* sel : stmt->selectors) { - if (!Expression(sel)) { + auto* expr = Expression(sel); + if (!expr) { return false; } + sem->Selectors().emplace_back(expr); } Mark(stmt->body); auto* body = BlockStatement(stmt->body); @@ -2140,6 +2143,7 @@ sem::SwitchStatement* Resolver::SwitchStatement(const ast::SwitchStatement* stmt return false; } behaviors.Add(c->Behaviors()); + sem->Cases().emplace_back(c); } if (behaviors.Contains(sem::Behavior::kBreak)) { diff --git a/src/tint/resolver/resolver_behavior_test.cc b/src/tint/resolver/resolver_behavior_test.cc index 9cb26dc974..3a3b14f4c6 100644 --- a/src/tint/resolver/resolver_behavior_test.cc +++ b/src/tint/resolver/resolver_behavior_test.cc @@ -19,6 +19,7 @@ #include "src/tint/sem/expression.h" #include "src/tint/sem/for_loop_statement.h" #include "src/tint/sem/if_statement.h" +#include "src/tint/sem/switch_statement.h" using namespace tint::number_suffixes; // NOLINT diff --git a/src/tint/resolver/resolver_test.cc b/src/tint/resolver/resolver_test.cc index 02e43fc564..07c661cab6 100644 --- a/src/tint/resolver/resolver_test.cc +++ b/src/tint/resolver/resolver_test.cc @@ -42,6 +42,7 @@ #include "src/tint/sem/reference.h" #include "src/tint/sem/sampled_texture.h" #include "src/tint/sem/statement.h" +#include "src/tint/sem/switch_statement.h" #include "src/tint/sem/variable.h" using ::testing::ElementsAre; @@ -111,11 +112,11 @@ TEST_F(ResolverTest, Stmt_Case) { auto* assign = Assign(lhs, rhs); auto* block = Block(assign); - ast::CaseSelectorList lit; - lit.push_back(Expr(3_i)); - auto* cse = create(lit, block); + auto* sel = Expr(3_i); + auto* cse = Case(sel, block); + auto* def = DefaultCase(); auto* cond_var = Var("c", ty.i32()); - auto* sw = Switch(cond_var, cse, DefaultCase()); + auto* sw = Switch(cond_var, cse, def); WrapInFunction(v, cond_var, sw); EXPECT_TRUE(r()->Resolve()) << r()->error(); @@ -127,6 +128,13 @@ TEST_F(ResolverTest, Stmt_Case) { EXPECT_EQ(StmtOf(lhs), assign); EXPECT_EQ(StmtOf(rhs), assign); EXPECT_EQ(BlockOf(assign), block); + auto* sem = Sem().Get(sw); + ASSERT_EQ(sem->Cases().size(), 2u); + EXPECT_EQ(sem->Cases()[0]->Declaration(), cse); + ASSERT_EQ(sem->Cases()[0]->Selectors().size(), 1u); + EXPECT_EQ(sem->Cases()[0]->Selectors()[0]->Declaration(), sel); + EXPECT_EQ(sem->Cases()[1]->Declaration(), def); + EXPECT_EQ(sem->Cases()[1]->Selectors().size(), 0u); } TEST_F(ResolverTest, Stmt_Block) { diff --git a/src/tint/sem/switch_statement.h b/src/tint/sem/switch_statement.h index a5ef6598e1..a6b5c00f92 100644 --- a/src/tint/sem/switch_statement.h +++ b/src/tint/sem/switch_statement.h @@ -15,6 +15,8 @@ #ifndef SRC_TINT_SEM_SWITCH_STATEMENT_H_ #define SRC_TINT_SEM_SWITCH_STATEMENT_H_ +#include + #include "src/tint/sem/block_statement.h" // Forward declarations @@ -22,6 +24,10 @@ namespace tint::ast { class CaseStatement; class SwitchStatement; } // namespace tint::ast +namespace tint::sem { +class CaseStatement; +class Expression; +} // namespace tint::sem namespace tint::sem { @@ -41,6 +47,15 @@ class SwitchStatement final : public Castable& Cases() { return cases_; } + + /// @returns the case statements for this switch + const std::vector& Cases() const { return cases_; } + + private: + std::vector cases_; }; /// Holds semantic information about a switch case statement @@ -66,8 +81,15 @@ class CaseStatement final : public Castable { /// @returns the case body block statement const BlockStatement* Body() const { return body_; } + /// @returns the selectors for the case + std::vector& Selectors() { return selectors_; } + + /// @returns the selectors for the case + const std::vector& Selectors() const { return selectors_; } + private: const BlockStatement* body_ = nullptr; + std::vector selectors_; }; } // namespace tint::sem diff --git a/src/tint/sem/type_mappings.h b/src/tint/sem/type_mappings.h index e66acdd0bb..0e54eed759 100644 --- a/src/tint/sem/type_mappings.h +++ b/src/tint/sem/type_mappings.h @@ -30,6 +30,7 @@ class Node; class Statement; class Struct; class StructMember; +class SwitchStatement; class Type; class TypeDecl; class Variable; @@ -46,6 +47,7 @@ class Node; class Statement; class Struct; class StructMember; +class SwitchStatement; class Type; class Variable; } // namespace tint::sem @@ -68,6 +70,7 @@ struct TypeMappings { Statement* operator()(ast::Statement*); Struct* operator()(ast::Struct*); StructMember* operator()(ast::StructMember*); + SwitchStatement* operator()(ast::SwitchStatement*); Type* operator()(ast::Type*); Type* operator()(ast::TypeDecl*); Variable* operator()(ast::Variable*);