sem: Add Behavior to Statement and Expression

Nothing currently does the analysis to calculate these.

Change-Id: Ia2103102fbf36109f357aebf32cdfda24d6d8155
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/68407
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: David Neto <dneto@google.com>
Commit-Queue: Ben Clayton <bclayton@chromium.org>
diff --git a/src/BUILD.gn b/src/BUILD.gn
index 6ccac4a..9dab4d3 100644
--- a/src/BUILD.gn
+++ b/src/BUILD.gn
@@ -380,6 +380,7 @@
     "scope_stack.h",
     "sem/array.h",
     "sem/atomic_type.h",
+    "sem/behavior.h",
     "sem/binding_point.h",
     "sem/bool_type.h",
     "sem/call.h",
@@ -520,6 +521,8 @@
     "sem/array.h",
     "sem/atomic_type.cc",
     "sem/atomic_type.h",
+    "sem/behavior.cc",
+    "sem/behavior.h",
     "sem/binding_point.h",
     "sem/block_statement.cc",
     "sem/bool_type.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fc5d3f2..e587fb5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -249,6 +249,8 @@
   sem/array.h
   sem/atomic_type.cc
   sem/atomic_type.h
+  sem/behavior.cc
+  sem/behavior.h
   sem/binding_point.h
   sem/block_statement.cc
   sem/block_statement.h
diff --git a/src/sem/behavior.cc b/src/sem/behavior.cc
new file mode 100644
index 0000000..2d6f15c
--- /dev/null
+++ b/src/sem/behavior.cc
@@ -0,0 +1,39 @@
+// Copyright 2021 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/sem/behavior.h"
+
+namespace tint {
+namespace sem {
+
+std::ostream& operator<<(std::ostream& out, Behavior behavior) {
+  switch (behavior) {
+    case Behavior::kReturn:
+      return out << "Return";
+    case Behavior::kDiscard:
+      return out << "Discard";
+    case Behavior::kBreak:
+      return out << "Break";
+    case Behavior::kContinue:
+      return out << "Continue";
+    case Behavior::kFallthrough:
+      return out << "Fallthrough";
+    case Behavior::kNext:
+      return out << "Next";
+  }
+  return out << "<unknown>";
+}
+
+}  // namespace sem
+}  // namespace tint
diff --git a/src/sem/behavior.h b/src/sem/behavior.h
new file mode 100644
index 0000000..1e318c1
--- /dev/null
+++ b/src/sem/behavior.h
@@ -0,0 +1,46 @@
+// Copyright 2021 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.
+
+#ifndef SRC_SEM_BEHAVIOR_H_
+#define SRC_SEM_BEHAVIOR_H_
+
+#include "src/utils/enum_set.h"
+
+namespace tint {
+namespace sem {
+
+/// Behavior enumerates the possible behaviors of an expression or statement.
+/// @see https://www.w3.org/TR/WGSL/#behaviors
+enum class Behavior {
+  kReturn,
+  kDiscard,
+  kBreak,
+  kContinue,
+  kFallthrough,
+  kNext,
+};
+
+/// Behaviors is a set of Behavior
+using Behaviors = utils::EnumSet<Behavior>;
+
+/// Writes the Behavior to the std::ostream.
+/// @param out the std::ostream to write to
+/// @param behavior the Behavior to write
+/// @returns out so calls can be chained
+std::ostream& operator<<(std::ostream& out, Behavior behavior);
+
+}  // namespace sem
+}  // namespace tint
+
+#endif  // SRC_SEM_BEHAVIOR_H_
diff --git a/src/sem/expression.h b/src/sem/expression.h
index 4fc6e82..06ae10b 100644
--- a/src/sem/expression.h
+++ b/src/sem/expression.h
@@ -16,6 +16,7 @@
 #define SRC_SEM_EXPRESSION_H_
 
 #include "src/ast/expression.h"
+#include "src/sem/behavior.h"
 #include "src/sem/constant.h"
 #include "src/sem/node.h"
 
@@ -53,6 +54,12 @@
   /// @return the constant value of this expression
   const Constant& ConstantValue() const { return constant_; }
 
+  /// @return the behaviors of this statement
+  const sem::Behaviors& Behaviors() const { return behaviors_; }
+
+  /// @return the behaviors of this statement
+  sem::Behaviors& Behaviors() { return behaviors_; }
+
  protected:
   /// The AST expression node for this semantic expression
   const ast::Expression* const declaration_;
@@ -61,6 +68,7 @@
   const sem::Type* const type_;
   const Statement* const statement_;
   const Constant constant_;
+  sem::Behaviors behaviors_;
 };
 
 }  // namespace sem
diff --git a/src/sem/statement.cc b/src/sem/statement.cc
index 098fe14..cc60668 100644
--- a/src/sem/statement.cc
+++ b/src/sem/statement.cc
@@ -31,6 +31,8 @@
                      const sem::Function* function)
     : declaration_(declaration), parent_(parent), function_(function) {}
 
+Statement::~Statement() = default;
+
 const BlockStatement* Statement::Block() const {
   return FindFirstParent<BlockStatement>();
 }
diff --git a/src/sem/statement.h b/src/sem/statement.h
index e5297dc..e1c5160 100644
--- a/src/sem/statement.h
+++ b/src/sem/statement.h
@@ -15,6 +15,7 @@
 #ifndef SRC_SEM_STATEMENT_H_
 #define SRC_SEM_STATEMENT_H_
 
+#include "src/sem/behavior.h"
 #include "src/sem/node.h"
 
 // Forward declarations
@@ -70,6 +71,9 @@
             const CompoundStatement* parent,
             const sem::Function* function);
 
+  /// Destructor
+  ~Statement() override;
+
   /// @return the AST node for this statement
   const ast::Statement* Declaration() const { return declaration_; }
 
@@ -96,10 +100,18 @@
   /// @returns the function that owns this statement
   const sem::Function* Function() const { return function_; }
 
+  /// @return the behaviors of this statement
+  const sem::Behaviors& Behaviors() const { return behaviors_; }
+
+  /// @return the behaviors of this statement
+  sem::Behaviors& Behaviors() { return behaviors_; }
+
  private:
   const ast::Statement* const declaration_;
   const CompoundStatement* const parent_;
   const sem::Function* const function_;
+
+  sem::Behaviors behaviors_;
 };
 
 /// CompoundStatement is the base class of statements that can hold other