1 // Copyright 2021 The Tint Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef SRC_SEM_STATEMENT_H_ 16 #define SRC_SEM_STATEMENT_H_ 17 18 #include "src/sem/behavior.h" 19 #include "src/sem/node.h" 20 21 // Forward declarations 22 namespace tint { 23 namespace ast { 24 class Function; 25 class Statement; 26 } // namespace ast 27 namespace sem { 28 class BlockStatement; 29 } // namespace sem 30 } // namespace tint 31 32 namespace tint { 33 namespace sem { 34 35 /// Forward declaration 36 class CompoundStatement; 37 class Function; 38 39 namespace detail { 40 /// FindFirstParentReturn is a traits helper for determining the return type for 41 /// the template member function Statement::FindFirstParent(). 42 /// For zero or multiple template arguments, FindFirstParentReturn::type 43 /// resolves to CompoundStatement. 44 template <typename... TYPES> 45 struct FindFirstParentReturn { 46 /// The pointer type returned by Statement::FindFirstParent() 47 using type = CompoundStatement; 48 }; 49 50 /// A specialization of FindFirstParentReturn for a single template argument. 51 /// FindFirstParentReturn::type resolves to the single template argument. 52 template <typename T> 53 struct FindFirstParentReturn<T> { 54 /// The pointer type returned by Statement::FindFirstParent() 55 using type = T; 56 }; 57 58 template <typename... TYPES> 59 using FindFirstParentReturnType = 60 typename FindFirstParentReturn<TYPES...>::type; 61 } // namespace detail 62 63 /// Statement holds the semantic information for a statement. 64 class Statement : public Castable<Statement, Node> { 65 public: 66 /// Constructor 67 /// @param declaration the AST node for this statement 68 /// @param parent the owning statement 69 /// @param function the owning function 70 Statement(const ast::Statement* declaration, 71 const CompoundStatement* parent, 72 const sem::Function* function); 73 74 /// Destructor 75 ~Statement() override; 76 77 /// @return the AST node for this statement 78 const ast::Statement* Declaration() const { return declaration_; } 79 80 /// @return the statement that encloses this statement 81 const CompoundStatement* Parent() const { return parent_; } 82 83 /// @returns the closest enclosing parent that satisfies the given predicate, 84 /// which may be the statement itself, or nullptr if no match is found. 85 /// @param pred a predicate that the resulting block must satisfy 86 template <typename Pred> 87 const CompoundStatement* FindFirstParent(Pred&& pred) const; 88 89 /// @returns the closest enclosing parent that is of one of the types in 90 /// `TYPES`, which may be the statement itself, or nullptr if no match is 91 /// found. If `TYPES` is a single template argument, the return type is a 92 /// pointer to that template argument type, otherwise a CompoundStatement 93 /// pointer is returned. 94 template <typename... TYPES> 95 const detail::FindFirstParentReturnType<TYPES...>* FindFirstParent() const; 96 97 /// @return the closest enclosing block for this statement 98 const BlockStatement* Block() const; 99 100 /// @returns the function that owns this statement 101 const sem::Function* Function() const { return function_; } 102 103 /// @return the behaviors of this statement 104 const sem::Behaviors& Behaviors() const { return behaviors_; } 105 106 /// @return the behaviors of this statement 107 sem::Behaviors& Behaviors() { return behaviors_; } 108 109 /// @returns true if this statement is reachable by control flow according to 110 /// the behavior analysis 111 bool IsReachable() const { return is_reachable_; } 112 113 /// @param is_reachable whether this statement is reachable by control flow 114 /// according to the behavior analysis 115 void SetIsReachable(bool is_reachable) { is_reachable_ = is_reachable; } 116 117 private: 118 const ast::Statement* const declaration_; 119 const CompoundStatement* const parent_; 120 const sem::Function* const function_; 121 sem::Behaviors behaviors_{sem::Behavior::kNext}; 122 bool is_reachable_ = true; 123 }; 124 125 /// CompoundStatement is the base class of statements that can hold other 126 /// statements. 127 class CompoundStatement : public Castable<Statement, Statement> { 128 public: 129 /// Constructor 130 /// @param declaration the AST node for this statement 131 /// @param statement the owning statement 132 /// @param function the owning function 133 CompoundStatement(const ast::Statement* declaration, 134 const CompoundStatement* statement, 135 const sem::Function* function); 136 137 /// Destructor 138 ~CompoundStatement() override; 139 }; 140 141 template <typename Pred> 142 const CompoundStatement* Statement::FindFirstParent(Pred&& pred) const { 143 if (auto* self = As<CompoundStatement>()) { 144 if (pred(self)) { 145 return self; 146 } 147 } 148 const auto* curr = parent_; 149 while (curr && !pred(curr)) { 150 curr = curr->Parent(); 151 } 152 return curr; 153 } 154 155 template <typename... TYPES> 156 const detail::FindFirstParentReturnType<TYPES...>* Statement::FindFirstParent() 157 const { 158 using ReturnType = detail::FindFirstParentReturnType<TYPES...>; 159 if (sizeof...(TYPES) == 1) { 160 if (auto* p = As<ReturnType>()) { 161 return p; 162 } 163 const auto* curr = parent_; 164 while (curr) { 165 if (auto* p = curr->As<ReturnType>()) { 166 return p; 167 } 168 curr = curr->Parent(); 169 } 170 } else { 171 if (IsAnyOf<TYPES...>()) { 172 return As<ReturnType>(); 173 } 174 const auto* curr = parent_; 175 while (curr) { 176 if (curr->IsAnyOf<TYPES...>()) { 177 return curr->As<ReturnType>(); 178 } 179 curr = curr->Parent(); 180 } 181 } 182 return nullptr; 183 } 184 185 } // namespace sem 186 } // namespace tint 187 188 #endif // SRC_SEM_STATEMENT_H_ 189