diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 391c999a69..d2c061f69d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -225,6 +225,7 @@ set(TINT_TEST_SRCS ast/member_accessor_expression_test.cc ast/module_test.cc ast/nop_statement_test.cc + ast/regardless_statement_test.cc ast/set_decoration_test.cc ast/struct_member_test.cc ast/struct_member_offset_decoration_test.cc diff --git a/src/ast/regardless_statement.cc b/src/ast/regardless_statement.cc index 2ad7bb42b4..052ea3d42a 100644 --- a/src/ast/regardless_statement.cc +++ b/src/ast/regardless_statement.cc @@ -17,6 +17,8 @@ namespace tint { namespace ast { +RegardlessStatement::RegardlessStatement() : Statement() {} + RegardlessStatement::RegardlessStatement( std::unique_ptr condition, std::vector> body) @@ -33,7 +35,16 @@ RegardlessStatement::RegardlessStatement( RegardlessStatement::~RegardlessStatement() = default; bool RegardlessStatement::IsValid() const { - return condition_ != nullptr; + if (condition_ == nullptr || !condition_->IsValid()) { + return false; + } + for (const auto& stmt : body_) { + if (stmt == nullptr || !stmt->IsValid()) { + return false; + } + } + + return true; } void RegardlessStatement::to_str(std::ostream& out, size_t indent) const { @@ -41,14 +52,14 @@ void RegardlessStatement::to_str(std::ostream& out, size_t indent) const { out << "Regardless{" << std::endl; condition_->to_str(out, indent + 2); - make_indent(out, indent); + make_indent(out, indent + 2); out << "{" << std::endl; for (const auto& stmt : body_) stmt->to_str(out, indent + 4); make_indent(out, indent + 2); - out << "}"; + out << "}" << std::endl; make_indent(out, indent); out << "}" << std::endl; diff --git a/src/ast/regardless_statement.h b/src/ast/regardless_statement.h index 54e9c60919..cada546fea 100644 --- a/src/ast/regardless_statement.h +++ b/src/ast/regardless_statement.h @@ -28,6 +28,8 @@ namespace ast { /// A regardless statement class RegardlessStatement : public Statement { public: + /// Constructor + RegardlessStatement(); /// Constructor /// @param condition the condition expression /// @param body the body statements diff --git a/src/ast/regardless_statement_test.cc b/src/ast/regardless_statement_test.cc new file mode 100644 index 0000000000..4c34bdb372 --- /dev/null +++ b/src/ast/regardless_statement_test.cc @@ -0,0 +1,126 @@ +// Copyright 2020 The Tint Authors. +// +// 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 "src/ast/regardless_statement.h" + +#include + +#include "gtest/gtest.h" +#include "src/ast/identifier_expression.h" +#include "src/ast/if_statement.h" +#include "src/ast/kill_statement.h" + +namespace tint { +namespace ast { + +using RegardlessStatementTest = testing::Test; + +TEST_F(RegardlessStatementTest, Creation) { + auto ident = std::make_unique("ident"); + std::vector> stmts; + stmts.push_back(std::make_unique()); + + auto ident_ptr = ident.get(); + auto kill_ptr = stmts[0].get(); + + RegardlessStatement r(std::move(ident), std::move(stmts)); + EXPECT_EQ(r.condition(), ident_ptr); + ASSERT_EQ(r.body().size(), 1); + EXPECT_EQ(r.body()[0].get(), kill_ptr); +} + +TEST_F(RegardlessStatementTest, Creation_WithSource) { + auto ident = std::make_unique("ident"); + std::vector> stmts; + stmts.push_back(std::make_unique()); + + RegardlessStatement r(Source{20, 2}, std::move(ident), std::move(stmts)); + auto src = r.source(); + EXPECT_EQ(src.line, 20); + EXPECT_EQ(src.column, 2); +} + +TEST_F(RegardlessStatementTest, IsRegardless) { + RegardlessStatement r; + EXPECT_TRUE(r.IsRegardless()); +} + +TEST_F(RegardlessStatementTest, IsValid) { + auto ident = std::make_unique("ident"); + std::vector> stmts; + stmts.push_back(std::make_unique()); + + RegardlessStatement r(std::move(ident), std::move(stmts)); + EXPECT_TRUE(r.IsValid()); +} + +TEST_F(RegardlessStatementTest, IsValid_NullCondition) { + std::vector> stmts; + stmts.push_back(std::make_unique()); + + RegardlessStatement r; + r.set_body(std::move(stmts)); + EXPECT_FALSE(r.IsValid()); +} + +TEST_F(RegardlessStatementTest, IsValid_InvalidCondition) { + auto ident = std::make_unique(""); + std::vector> stmts; + stmts.push_back(std::make_unique()); + + RegardlessStatement r(std::move(ident), std::move(stmts)); + EXPECT_FALSE(r.IsValid()); +} + +TEST_F(RegardlessStatementTest, IsValid_NullBodyStatement) { + auto ident = std::make_unique("ident"); + std::vector> stmts; + stmts.push_back(std::make_unique()); + stmts.push_back(nullptr); + + RegardlessStatement r; + r.set_condition(std::move(ident)); + r.set_body(std::move(stmts)); + EXPECT_FALSE(r.IsValid()); +} + +TEST_F(RegardlessStatementTest, IsValid_InvalidBodyStatement) { + auto ident = std::make_unique("ident"); + std::vector> stmts; + stmts.push_back(std::make_unique()); + stmts.push_back(std::make_unique()); + + RegardlessStatement r(std::move(ident), std::move(stmts)); + EXPECT_FALSE(r.IsValid()); +} + +TEST_F(RegardlessStatementTest, ToStr) { + auto ident = std::make_unique("ident"); + std::vector> stmts; + stmts.push_back(std::make_unique()); + + RegardlessStatement r(std::move(ident), std::move(stmts)); + std::ostringstream out; + r.to_str(out, 2); + EXPECT_EQ(out.str(), R"( Regardless{ + Identifier{ident} + { + Kill{} + } + } +)"); +} + +} // namespace ast +} // namespace tint