diff --git a/src/ScriptValidation.cc b/src/ScriptValidation.cc index 91c4d77c19..1510e1f53a 100644 --- a/src/ScriptValidation.cc +++ b/src/ScriptValidation.cc @@ -58,6 +58,15 @@ public: return TC_CONTINUE; } + TraversalCode PreType(const Type* t) override { + if ( types_seen.count(t) > 0 ) + return TC_ABORTSTMT; + + types_seen.insert(t); + + return TC_CONTINUE; + } + void SetHookDepth(int hd) { hook_depth = hd; } bool IsValid() const { return valid_script; } @@ -83,6 +92,7 @@ private: } std::unordered_map stmt_depths; + std::unordered_set types_seen; int hook_depth = 0; bool report; // whether to report problems via "reporter" bool valid_script = true; diff --git a/src/script_opt/CSE.h b/src/script_opt/CSE.h index 56d6572d9a..60b1ad45bc 100644 --- a/src/script_opt/CSE.h +++ b/src/script_opt/CSE.h @@ -24,6 +24,13 @@ public: TraversalCode PreExpr(const Expr*) override; TraversalCode PostExpr(const Expr*) override; + TraversalCode PreType(const Type* t) override { + if ( types_seen.count(t) > 0 ) + return TC_ABORTSTMT; + types_seen.insert(t); + return TC_CONTINUE; + } + // Returns the ultimate verdict re safety. bool IsValid() const { if ( ! is_valid ) @@ -105,6 +112,9 @@ protected: // // A count to allow for nesting. int in_aggr_mod_expr = 0; + + // Used to limit traversal of recursive types. + std::unordered_set types_seen; }; // Used for debugging, to communicate which expression wasn't