| 243 | } |
| 244 | |
| 245 | Status IsNodeStateful(const FunctionLibraryDefinition& library, |
| 246 | const NodeDef& node) { |
| 247 | const OpDef* op_def; |
| 248 | |
| 249 | // TODO(jsimsa): Fix C++ unit tests so that we do not have to ignore |
| 250 | // `LookUpOpDef` errors here. |
| 251 | if (!OpRegistry::Global()->LookUpOpDef(node.op(), &op_def).ok() || |
| 252 | IsOpWhitelisted(op_def) || !op_def->is_stateful() || |
| 253 | op_def->name() == "Assert") { |
| 254 | return Status::OK(); |
| 255 | } |
| 256 | |
| 257 | if (op_def->name() == "If") { |
| 258 | const FunctionDef* then_func = |
| 259 | library.Find(node.attr().at("then_branch").func().name()); |
| 260 | const FunctionDef* else_func = |
| 261 | library.Find(node.attr().at("else_branch").func().name()); |
| 262 | if (then_func != nullptr) { |
| 263 | TF_RETURN_IF_ERROR(IsFunctionStateful(library, *then_func)); |
| 264 | } |
| 265 | if (else_func != nullptr) { |
| 266 | TF_RETURN_IF_ERROR(IsFunctionStateful(library, *else_func)); |
| 267 | } |
| 268 | return Status::OK(); |
| 269 | } |
| 270 | |
| 271 | if (op_def->name() == "While") { |
| 272 | const FunctionDef* cond_func = |
| 273 | library.Find(node.attr().at("cond").func().name()); |
| 274 | const FunctionDef* body_func = |
| 275 | library.Find(node.attr().at("body").func().name()); |
| 276 | if (cond_func != nullptr) { |
| 277 | TF_RETURN_IF_ERROR(IsFunctionStateful(library, *cond_func)); |
| 278 | } |
| 279 | if (body_func != nullptr) { |
| 280 | TF_RETURN_IF_ERROR(IsFunctionStateful(library, *body_func)); |
| 281 | } |
| 282 | return Status::OK(); |
| 283 | } |
| 284 | |
| 285 | return errors::FailedPrecondition(op_def->name(), " is stateful."); |
| 286 | } |
| 287 | |
| 288 | } // namespace |
| 289 |
no test coverage detected