diff --git a/src/script_opt/DefPoint.h b/src/script_opt/DefPoint.h new file mode 100644 index 0000000000..e231d72dc3 --- /dev/null +++ b/src/script_opt/DefPoint.h @@ -0,0 +1,105 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#pragma once + +#include "zeek/Expr.h" +#include "zeek/Func.h" +#include "zeek/Stmt.h" + +namespace zeek::detail { + +// A DefinitionPoint is a location where a variable, or possibly a record +// field, is defined (i.e., assigned to). The class tracks the type of +// definition (a statement, inside an expression, an aggregate passed to +// a function or hook, or at the start of a function). + +typedef enum { + // Used to capture the notion "the variable may have no definition + // at this point" (or "has no definition", depending on whether we're + // concerned with minimal or maximal RDs). + NO_DEF, + + // Assigned at the given statement. + STMT_DEF, + + // The following includes assignments, +=, vec+=, $, ?$ ... + // ... plus names (for implicit creation of records upon + // seeing use) and calls (for aggregates). + // + // Note that ?$ does not in fact create a definition. We include + // it as a heuristic meaning "code after this point can assume + // that the given record field is defined". The heuristic can + // fail if the ?$ predicate is ultimately negated, something that + // we don't try to identify. Basically, the idea is that if the + // script writer is cognizant of needing to check for the existence + // of a field, most likely they got the check correct. Any errors + // we make in this regard only lead to mistakes in identify usage + // problems, not in actual run-time execution. + EXPR_DEF, + + // The variable is assigned when the function begins executing, + // either through an explicit initialization for a local, or because + // it's a function parameter. + FUNC_DEF, + +} DefPointType; + +class DefinitionPoint { +public: + DefinitionPoint() + { + o = nullptr; + t = NO_DEF; + } + + DefinitionPoint(const Stmt* s) + { + o = s; + t = STMT_DEF; + } + + DefinitionPoint(const Expr* e) + { + o = e; + t = EXPR_DEF; + } + + DefinitionPoint(const Func* f) + { + o = f; + t = FUNC_DEF; + } + + DefPointType Tag() const { return t; } + + const Obj* OpaqueVal() const { return o; } + + const Stmt* StmtVal() const + { + ASSERT(t == STMT_DEF); + return (const Stmt*) o; + } + + const Expr* ExprVal() const + { + ASSERT(t == EXPR_DEF); + return (const Expr*) o; + } + + const Func* FuncVal() const + { + ASSERT(t == FUNC_DEF); + return (const Func*) o; + } + + bool SameAs(const DefinitionPoint& dp) const + { + return dp.Tag() == Tag() && dp.OpaqueVal() == OpaqueVal(); + } + +protected: + DefPointType t; + const Obj* o; +}; + +} // zeek::detail