diff --git a/CHANGES b/CHANGES index 334df3c7dd..e54699b7ce 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,58 @@ +3.2.0-dev.190 | 2020-02-28 00:42:17 -0800 + + * Stmt: use class IntrusivePtr (Max Kellermann) + + * Stmt: remove unused default constructors and `friend` declarations (Max Kellermann) + + * Val: remove unimplemented prototype recover_val() (Max Kellermann) + + * Val: cast_value_to_type() returns IntrusivePtr (Max Kellermann) + + * Val: use IntrusivePtr in check_and_promote() (Max Kellermann) + + * Val: use nullptr instead of 0 (Max Kellermann) + + * zeekygen: use class IntrusivePtr (Max Kellermann) + + * ID: use class IntrusivePtr (Max Kellermann) + + * Expr: use class IntrusivePtr (Max Kellermann) + + * Var: copy Location to stack, to fix use-after-free crash bug (Max Kellermann) + + * Scope: lookup_ID() and install_ID() return IntrusivePtr (Max Kellermann) + + * Scope: delete duplicate locals (Max Kellermann) + + * EventRegistry: automatically delete EventHandlers (Max Kellermann) + + * main: destroy event_registry after iosource_mgr (Max Kellermann) + + Fixes use-after-free bugs because PcapSource::Close() queues an event. + + * zeekygen/IdentifierInfo: delete duplicate fields (Max Kellermann) + + * main: free the global scope in terminate_bro() (Max Kellermann) + + Make valgrind a bit happier. + + * Scope: pop_scope() returns IntrusivePtr<> (Max Kellermann) + + * Scope: unref all inits in destructor (Max Kellermann) + + * Var: pass IntrusivePtr to add_global(), add_local() etc. (Max Kellermann) + + * plugin/ComponentManager: hold a reference to the EnumType (Max Kellermann) + + Use class IntrusivePtr<>. + + * Type: fix use-after-free bug in VectorType::ShallowClone() (Max Kellermann) + + The new VectorType instance needs a new reference to the `yield_type`. + + * Var: fix crash when redeclaring a function with different args (Max Kellermann) + 3.2.0-dev.167 | 2020-02-27 14:24:55 -0800 * Expr: use fmt instead of sprintf (Tim Wojtulewicz, Corelight) diff --git a/VERSION b/VERSION index a55db9a55f..f3a3cc3bab 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.2.0-dev.167 +3.2.0-dev.190 diff --git a/src/Attr.cc b/src/Attr.cc index 09b17e1e6a..5e8fb4bd7b 100644 --- a/src/Attr.cc +++ b/src/Attr.cc @@ -6,6 +6,7 @@ #include "Expr.h" #include "Desc.h" #include "Val.h" +#include "IntrusivePtr.h" #include "threading/SerialTypes.h" const char* attr_name(attr_tag t) @@ -109,10 +110,8 @@ void Attr::DescribeReST(ODesc* d, bool shorten) const else { - Val* v = expr->Eval(0); ODesc dd; - v->Describe(&dd); - Unref(v); + expr->Eval(nullptr)->Describe(&dd); string s = dd.Description(); for ( size_t i = 0; i < s.size(); ++i ) diff --git a/src/DbgBreakpoint.cc b/src/DbgBreakpoint.cc index e26a8bb050..11033c789c 100644 --- a/src/DbgBreakpoint.cc +++ b/src/DbgBreakpoint.cc @@ -13,6 +13,7 @@ #include "Scope.h" #include "Frame.h" #include "Func.h" +#include "IntrusivePtr.h" #include "Val.h" #include "Stmt.h" #include "Timer.h" @@ -246,7 +247,7 @@ BreakCode DbgBreakpoint::HasHit() if ( condition.size() ) { // TODO: ### evaluate using debugger frame too - Val* yes = dbg_eval_expr(condition.c_str()); + auto yes = dbg_eval_expr(condition.c_str()); if ( ! yes ) { @@ -260,7 +261,6 @@ BreakCode DbgBreakpoint::HasHit() if ( ! IsIntegral(yes->Type()->Tag()) && ! IsBool(yes->Type()->Tag()) ) { - Unref(yes); PrintHitMsg(); debug_msg("Breakpoint condition should return an integral type"); return bcHitAndDelete; @@ -269,11 +269,8 @@ BreakCode DbgBreakpoint::HasHit() yes->CoerceToInt(); if ( yes->IsZero() ) { - Unref(yes); return bcNoHit; } - - Unref(yes); } int repcount = GetRepeatCount(); diff --git a/src/Debug.cc b/src/Debug.cc index e0f6ca33f5..d42cb9f71e 100644 --- a/src/Debug.cc +++ b/src/Debug.cc @@ -16,10 +16,12 @@ using namespace std; #include "DebugCmds.h" #include "DbgBreakpoint.h" #include "ID.h" +#include "IntrusivePtr.h" #include "Expr.h" #include "Stmt.h" #include "Frame.h" #include "Func.h" +#include "IntrusivePtr.h" #include "Scope.h" #include "PolicyFile.h" #include "Desc.h" @@ -195,13 +197,13 @@ void get_first_statement(Stmt* list, Stmt*& first, Location& loc) static void parse_function_name(vector& result, ParseLocationRec& plr, const string& s) { // function name - ID* id = lookup_ID(s.c_str(), current_module.c_str()); + auto id = lookup_ID(s.c_str(), current_module.c_str()); + if ( ! id ) { string fullname = make_full_var_name(current_module.c_str(), s.c_str()); debug_msg("Function %s not defined.\n", fullname.c_str()); plr.type = plrUnknown; - Unref(id); return; } @@ -209,7 +211,6 @@ static void parse_function_name(vector& result, { debug_msg("Function %s not declared.\n", id->Name()); plr.type = plrUnknown; - Unref(id); return; } @@ -217,7 +218,6 @@ static void parse_function_name(vector& result, { debug_msg("Function %s declared but not defined.\n", id->Name()); plr.type = plrUnknown; - Unref(id); return; } @@ -228,12 +228,9 @@ static void parse_function_name(vector& result, { debug_msg("Function %s is a built-in function\n", id->Name()); plr.type = plrUnknown; - Unref(id); return; } - Unref(id); - Stmt* body = 0; // the particular body we care about; 0 = all if ( bodies.size() == 1 ) @@ -951,7 +948,7 @@ extern YYLTYPE yylloc; // holds start line and column of token extern int line_number; extern const char* filename; -Val* dbg_eval_expr(const char* expr) +IntrusivePtr dbg_eval_expr(const char* expr) { // Push the current frame's associated scope. // Note: g_debugger_state.curr_frame_idx is the user-visible number, @@ -968,7 +965,10 @@ Val* dbg_eval_expr(const char* expr) const BroFunc* func = frame->GetFunction(); if ( func ) + { + Ref(func->GetScope()); push_existing_scope(func->GetScope()); + } // ### Possibly push a debugger-local scope? @@ -983,7 +983,7 @@ Val* dbg_eval_expr(const char* expr) yylloc.first_line = yylloc.last_line = line_number = 1; // Parse the thing into an expr. - Val* result = 0; + IntrusivePtr result; if ( yyparse() ) { if ( g_curr_debug_error ) diff --git a/src/Debug.h b/src/Debug.h index 45bb8ed470..676c587635 100644 --- a/src/Debug.h +++ b/src/Debug.h @@ -10,6 +10,7 @@ #include #include +template class IntrusivePtr; class Val; class Stmt; @@ -159,7 +160,7 @@ int dbg_handle_debug_input(); // read a line and then have it executed int dbg_execute_command(const char* cmd); // Interactive expression evaluation. -Val* dbg_eval_expr(const char* expr); +IntrusivePtr dbg_eval_expr(const char* expr); // Extra debugging facilities. // TODO: current connections, memory allocated, other internal data structures. diff --git a/src/DebugCmds.cc b/src/DebugCmds.cc index cc7d37bcb2..e9a6720dcd 100644 --- a/src/DebugCmds.cc +++ b/src/DebugCmds.cc @@ -15,6 +15,7 @@ #include "Desc.h" #include "DbgBreakpoint.h" #include "ID.h" +#include "IntrusivePtr.h" #include "Frame.h" #include "Func.h" #include "Stmt.h" @@ -564,13 +565,12 @@ int dbg_cmd_print(DebugCmd cmd, const vector& args) expr += " "; } - Val* val = dbg_eval_expr(expr.c_str()); + auto val = dbg_eval_expr(expr.c_str()); if ( val ) { ODesc d; val->Describe(&d); - Unref(val); debug_msg("%s\n", d.Description()); } else diff --git a/src/EventHandler.cc b/src/EventHandler.cc index 3f70a81b51..dc62971305 100644 --- a/src/EventHandler.cc +++ b/src/EventHandler.cc @@ -38,8 +38,8 @@ FuncType* EventHandler::FType(bool check_export) if ( type ) return type; - ID* id = lookup_ID(name, current_module.c_str(), false, false, - check_export); + auto id = lookup_ID(name, current_module.c_str(), false, false, + check_export); if ( ! id ) return 0; @@ -48,8 +48,6 @@ FuncType* EventHandler::FType(bool check_export) return 0; type = id->Type()->AsFuncType(); - Unref(id); - return type; } diff --git a/src/EventRegistry.cc b/src/EventRegistry.cc index 957f90efe0..44018421c0 100644 --- a/src/EventRegistry.cc +++ b/src/EventRegistry.cc @@ -3,16 +3,19 @@ #include "RE.h" #include "Reporter.h" +EventRegistry::EventRegistry() = default; +EventRegistry::~EventRegistry() noexcept = default; + void EventRegistry::Register(EventHandlerPtr handler) { - handlers[string(handler->Name())] = handler.Ptr(); + handlers[string(handler->Name())] = std::unique_ptr(handler.Ptr()); } EventHandler* EventRegistry::Lookup(const string& name) { auto it = handlers.find(name); if ( it != handlers.end() ) - return it->second; + return it->second.get(); return nullptr; } @@ -23,7 +26,7 @@ EventRegistry::string_list EventRegistry::Match(RE_Matcher* pattern) for ( const auto& entry : handlers ) { - EventHandler* v = entry.second; + EventHandler* v = entry.second.get(); if ( v->LocalHandler() && pattern->MatchExactly(v->Name()) ) names.push_back(entry.first); } @@ -37,7 +40,7 @@ EventRegistry::string_list EventRegistry::UnusedHandlers() for ( const auto& entry : handlers ) { - EventHandler* v = entry.second; + EventHandler* v = entry.second.get(); if ( v->LocalHandler() && ! v->Used() ) names.push_back(entry.first); } @@ -51,7 +54,7 @@ EventRegistry::string_list EventRegistry::UsedHandlers() for ( const auto& entry : handlers ) { - EventHandler* v = entry.second; + EventHandler* v = entry.second.get(); if ( v->LocalHandler() && v->Used() ) names.push_back(entry.first); } @@ -75,7 +78,7 @@ void EventRegistry::PrintDebug() { for ( const auto& entry : handlers ) { - EventHandler* v = entry.second; + EventHandler* v = entry.second.get(); fprintf(stderr, "Registered event %s (%s handler / %s)\n", v->Name(), v->LocalHandler()? "local" : "no", *v ? "active" : "not active" diff --git a/src/EventRegistry.h b/src/EventRegistry.h index e49366e0d3..2619f3e044 100644 --- a/src/EventRegistry.h +++ b/src/EventRegistry.h @@ -3,6 +3,7 @@ #pragma once #include +#include #include #include @@ -16,8 +17,8 @@ class RE_Matcher; // The registry keeps track of all events that we provide or handle. class EventRegistry { public: - EventRegistry() { } - ~EventRegistry() { } + EventRegistry(); + ~EventRegistry() noexcept; void Register(EventHandlerPtr handler); @@ -41,7 +42,7 @@ public: void PrintDebug(); private: - std::map handlers; + std::map> handlers; }; extern EventRegistry* event_registry; diff --git a/src/Expr.cc b/src/Expr.cc index 83ad450835..d419298ad8 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -18,7 +18,6 @@ #include "digest.h" #include "module_util.h" #include "DebugLogger.h" -#include "IntrusivePtr.h" #include "broker/Data.h" @@ -60,11 +59,6 @@ Expr::Expr(BroExprTag arg_tag) : tag(arg_tag), type(0), paren(false) SetLocationInfo(&start_location, &end_location); } -Expr::~Expr() - { - Unref(type); - } - bool Expr::CanAdd() const { return false; @@ -85,11 +79,12 @@ void Expr::Delete(Frame* /* f */) Internal("Expr::Delete called"); } -Expr* Expr::MakeLvalue() +IntrusivePtr Expr::MakeLvalue() { if ( ! IsError() ) ExprError("can't be assigned to"); - return this; + + return {NewRef{}, this}; } void Expr::EvalIntoAggregate(const BroType* /* t */, Val* /* aggr */, @@ -98,15 +93,14 @@ void Expr::EvalIntoAggregate(const BroType* /* t */, Val* /* aggr */, Internal("Expr::EvalIntoAggregate called"); } -void Expr::Assign(Frame* /* f */, Val* v) +void Expr::Assign(Frame* /* f */, IntrusivePtr /* v */) { - Unref(v); Internal("Expr::Assign called"); } -BroType* Expr::InitType() const +IntrusivePtr Expr::InitType() const { - return type->Ref(); + return type; } bool Expr::IsRecordElement(TypeDecl* /* td */) const @@ -119,18 +113,18 @@ bool Expr::IsPure() const return true; } -Val* Expr::InitVal(const BroType* t, Val* aggr) const +IntrusivePtr Expr::InitVal(const BroType* t, IntrusivePtr aggr) const { if ( aggr ) { Error("bad initializer"); - return 0; + return nullptr; } if ( IsError() ) - return 0; + return nullptr; - return check_and_promote(Eval(0), t, 1); + return check_and_promote(Eval(nullptr), t, 1); } bool Expr::IsError() const @@ -140,7 +134,7 @@ bool Expr::IsError() const void Expr::SetError() { - SetType(error_type()); + SetType({AdoptRef{}, error_type()}); } void Expr::SetError(const char* msg) @@ -185,15 +179,10 @@ void Expr::Canonicize() { } -void Expr::SetType(BroType* t) +void Expr::SetType(IntrusivePtr t) { if ( ! type || type->Tag() != TYPE_ERROR ) - { - Unref(type); - type = t; - } - else - Unref(t); + type = std::move(t); } void Expr::ExprError(const char msg[]) @@ -223,53 +212,48 @@ void Expr::RuntimeErrorWithCallStack(const std::string& msg) const } } -NameExpr::NameExpr(ID* arg_id, bool const_init) : Expr(EXPR_NAME) +NameExpr::NameExpr(IntrusivePtr arg_id, bool const_init) + : Expr(EXPR_NAME), id(std::move(arg_id)) { - id = arg_id; in_const_init = const_init; if ( id->AsType() ) - SetType(new TypeType(id->AsType())); + SetType(make_intrusive(id->AsType())); else - SetType(id->Type()->Ref()); + SetType({NewRef{}, id->Type()}); EventHandler* h = event_registry->Lookup(id->Name()); if ( h ) h->SetUsed(); } -NameExpr::~NameExpr() +IntrusivePtr NameExpr::Eval(Frame* f) const { - Unref(id); - } - -Val* NameExpr::Eval(Frame* f) const - { - Val* v; + IntrusivePtr v; if ( id->AsType() ) - return new Val(id->AsType(), true); + return make_intrusive(id->AsType(), true); if ( id->IsGlobal() ) - v = id->ID_Val(); + v = {NewRef{}, id->ID_Val()}; else if ( f ) - v = f->GetElement(id); + v = {NewRef{}, f->GetElement(id.get())}; else // No frame - evaluating for Simplify() purposes - return 0; + return nullptr; if ( v ) - return v->Ref(); + return v; else { RuntimeError("value used but not set"); - return 0; + return nullptr; } } -Expr* NameExpr::MakeLvalue() +IntrusivePtr NameExpr::MakeLvalue() { if ( id->AsType() ) ExprError("Type name is not an lvalue"); @@ -280,15 +264,15 @@ Expr* NameExpr::MakeLvalue() if ( id->IsOption() && ! in_const_init ) ExprError("option is not a modifiable lvalue"); - return new RefExpr(this); + return make_intrusive(IntrusivePtr{NewRef{}, this}); } -void NameExpr::Assign(Frame* f, Val* v) +void NameExpr::Assign(Frame* f, IntrusivePtr v) { if ( id->IsGlobal() ) - id->SetVal(v); + id->SetVal(std::move(v)); else - f->SetElement(id, v); + f->SetElement(id.get(), v.release()); } bool NameExpr::IsPure() const @@ -322,23 +306,13 @@ void NameExpr::ExprDescribe(ODesc* d) const } } -ConstExpr::ConstExpr(Val* arg_val) : Expr(EXPR_CONST) +ConstExpr::ConstExpr(IntrusivePtr arg_val) + : Expr(EXPR_CONST), val(std::move(arg_val)) { - val = arg_val; - if ( val->Type()->Tag() == TYPE_LIST && val->AsListVal()->Length() == 1 ) - { - val = val->AsListVal()->Index(0); - val->Ref(); - Unref(arg_val); - } + val = {NewRef{}, val->AsListVal()->Index(0)}; - SetType(val->Type()->Ref()); - } - -ConstExpr::~ConstExpr() - { - Unref(val); + SetType({NewRef{}, val->Type()}); } void ConstExpr::ExprDescribe(ODesc* d) const @@ -346,9 +320,9 @@ void ConstExpr::ExprDescribe(ODesc* d) const val->Describe(d); } -Val* ConstExpr::Eval(Frame* /* f */) const +IntrusivePtr ConstExpr::Eval(Frame* /* f */) const { - return Value()->Ref(); + return {NewRef{}, Value()}; } TraversalCode ConstExpr::Traverse(TraversalCallback* cb) const @@ -360,29 +334,24 @@ TraversalCode ConstExpr::Traverse(TraversalCallback* cb) const HANDLE_TC_EXPR_POST(tc); } -UnaryExpr::UnaryExpr(BroExprTag arg_tag, Expr* arg_op) : Expr(arg_tag) +UnaryExpr::UnaryExpr(BroExprTag arg_tag, IntrusivePtr arg_op) + : Expr(arg_tag), op(std::move(arg_op)) { - op = arg_op; if ( op->IsError() ) SetError(); } -UnaryExpr::~UnaryExpr() - { - Unref(op); - } - -Val* UnaryExpr::Eval(Frame* f) const +IntrusivePtr UnaryExpr::Eval(Frame* f) const { if ( IsError() ) - return 0; + return nullptr; - Val* v = op->Eval(f); + auto v = op->Eval(f); if ( ! v ) - return 0; + return nullptr; - if ( is_vector(v) && Tag() != EXPR_IS && Tag() != EXPR_CAST ) + if ( is_vector(v.get()) && Tag() != EXPR_IS && Tag() != EXPR_CAST ) { VectorVal* v_op = v->AsVectorVal(); VectorType* out_t; @@ -391,22 +360,19 @@ Val* UnaryExpr::Eval(Frame* f) const else out_t = Type()->AsVectorType(); - VectorVal* result = new VectorVal(out_t); + auto result = make_intrusive(out_t); for ( unsigned int i = 0; i < v_op->Size(); ++i ) { Val* v_i = v_op->Lookup(i); - result->Assign(i, v_i ? Fold(v_i) : 0); + result->Assign(i, v_i ? Fold(v_i).release() : 0); } - Unref(v); return result; } else { - Val* result = Fold(v); - Unref(v); - return result; + return Fold(v.get()); } } @@ -427,9 +393,9 @@ TraversalCode UnaryExpr::Traverse(TraversalCallback* cb) const HANDLE_TC_EXPR_POST(tc); } -Val* UnaryExpr::Fold(Val* v) const +IntrusivePtr UnaryExpr::Fold(Val* v) const { - return v->Ref(); + return {NewRef{}, v}; } void UnaryExpr::ExprDescribe(ODesc* d) const @@ -458,32 +424,23 @@ void UnaryExpr::ExprDescribe(ODesc* d) const } } -BinaryExpr::~BinaryExpr() - { - Unref(op1); - Unref(op2); - } - -Val* BinaryExpr::Eval(Frame* f) const +IntrusivePtr BinaryExpr::Eval(Frame* f) const { if ( IsError() ) - return 0; + return nullptr; + + auto v1 = op1->Eval(f); - Val* v1 = op1->Eval(f); if ( ! v1 ) - return 0; + return nullptr; + + auto v2 = op2->Eval(f); - Val* v2 = op2->Eval(f); if ( ! v2 ) - { - Unref(v1); - return 0; - } + return nullptr; - Val* result = 0; - - int is_vec1 = is_vector(v1); - int is_vec2 = is_vector(v2); + int is_vec1 = is_vector(v1.get()); + int is_vec2 = is_vector(v2.get()); if ( is_vec1 && is_vec2 ) { // fold pairs of elements @@ -492,59 +449,49 @@ Val* BinaryExpr::Eval(Frame* f) const if ( v_op1->Size() != v_op2->Size() ) { - Unref(v1); - Unref(v2); RuntimeError("vector operands are of different sizes"); - return 0; + return nullptr; } - VectorVal* v_result = new VectorVal(Type()->AsVectorType()); + auto v_result = make_intrusive(Type()->AsVectorType()); for ( unsigned int i = 0; i < v_op1->Size(); ++i ) { if ( v_op1->Lookup(i) && v_op2->Lookup(i) ) v_result->Assign(i, Fold(v_op1->Lookup(i), - v_op2->Lookup(i))); + v_op2->Lookup(i)).release()); else - v_result->Assign(i, 0); + v_result->Assign(i, nullptr); // SetError("undefined element in vector operation"); } - Unref(v1); - Unref(v2); return v_result; } if ( IsVector(Type()->Tag()) && (is_vec1 || is_vec2) ) { // fold vector against scalar VectorVal* vv = (is_vec1 ? v1 : v2)->AsVectorVal(); - VectorVal* v_result = new VectorVal(Type()->AsVectorType()); + auto v_result = make_intrusive(Type()->AsVectorType()); for ( unsigned int i = 0; i < vv->Size(); ++i ) { Val* vv_i = vv->Lookup(i); if ( vv_i ) - v_result->Assign(i, - is_vec1 ? - Fold(vv_i, v2) : Fold(v1, vv_i)); + v_result->Assign(i, is_vec1 ? + Fold(vv_i, v2.get()).release() : + Fold(v1.get(), vv_i).release()); else - v_result->Assign(i, 0); + v_result->Assign(i, nullptr); // SetError("Undefined element in vector operation"); } - Unref(v1); - Unref(v2); return v_result; } // scalar op scalar - result = Fold(v1, v2); - - Unref(v1); - Unref(v2); - return result; + return Fold(v1.get(), v2.get()); } bool BinaryExpr::IsPure() const @@ -578,7 +525,7 @@ void BinaryExpr::ExprDescribe(ODesc* d) const op2->Describe(d); } -Val* BinaryExpr::Fold(Val* v1, Val* v2) const +IntrusivePtr BinaryExpr::Fold(Val* v1, Val* v2) const { InternalTypeTag it = v1->Type()->InternalType(); @@ -729,23 +676,24 @@ Val* BinaryExpr::Fold(Val* v1, Val* v2) const BadTag("BinaryExpr::Fold", expr_name(tag)); } - BroType* ret_type = type; + BroType* ret_type = Type(); + if ( IsVector(ret_type->Tag()) ) ret_type = ret_type->YieldType(); if ( ret_type->Tag() == TYPE_INTERVAL ) - return new IntervalVal(d3, 1.0); + return make_intrusive(d3, 1.0); else if ( ret_type->InternalType() == TYPE_INTERNAL_DOUBLE ) - return new Val(d3, ret_type->Tag()); + return make_intrusive(d3, ret_type->Tag()); else if ( ret_type->InternalType() == TYPE_INTERNAL_UNSIGNED ) - return val_mgr->GetCount(u3); + return {AdoptRef{}, val_mgr->GetCount(u3)}; else if ( ret_type->Tag() == TYPE_BOOL ) - return val_mgr->GetBool(i3); + return {AdoptRef{}, val_mgr->GetBool(i3)}; else - return val_mgr->GetInt(i3); + return {AdoptRef{}, val_mgr->GetInt(i3)}; } -Val* BinaryExpr::StringFold(Val* v1, Val* v2) const +IntrusivePtr BinaryExpr::StringFold(Val* v1, Val* v2) const { const BroString* s1 = v1->AsString(); const BroString* s2 = v2->AsString(); @@ -769,18 +717,18 @@ Val* BinaryExpr::StringFold(Val* v1, Val* v2) const strings.push_back(s1); strings.push_back(s2); - return new StringVal(concatenate(strings)); + return make_intrusive(concatenate(strings)); } default: BadTag("BinaryExpr::StringFold", expr_name(tag)); } - return val_mgr->GetBool(result); + return {AdoptRef{}, val_mgr->GetBool(result)}; } -Val* BinaryExpr::PatternFold(Val* v1, Val* v2) const +IntrusivePtr BinaryExpr::PatternFold(Val* v1, Val* v2) const { const RE_Matcher* re1 = v1->AsPattern(); const RE_Matcher* re2 = v2->AsPattern(); @@ -792,10 +740,10 @@ Val* BinaryExpr::PatternFold(Val* v1, Val* v2) const RE_Matcher_conjunction(re1, re2) : RE_Matcher_disjunction(re1, re2); - return new PatternVal(res); + return make_intrusive(res); } -Val* BinaryExpr::SetFold(Val* v1, Val* v2) const +IntrusivePtr BinaryExpr::SetFold(Val* v1, Val* v2) const { TableVal* tv1 = v1->AsTableVal(); TableVal* tv2 = v2->AsTableVal(); @@ -804,21 +752,21 @@ Val* BinaryExpr::SetFold(Val* v1, Val* v2) const switch ( tag ) { case EXPR_AND: - return tv1->Intersect(tv2); + return {AdoptRef{}, tv1->Intersect(tv2)}; case EXPR_OR: result = v1->Clone()->AsTableVal(); if ( ! tv2->AddTo(result, false, false) ) reporter->InternalError("set union failed to type check"); - return result; + return {AdoptRef{}, result}; case EXPR_SUB: result = v1->Clone()->AsTableVal(); if ( ! tv2->RemoveFrom(result) ) reporter->InternalError("set difference failed to type check"); - return result; + return {AdoptRef{}, result}; case EXPR_EQ: res = tv1->EqualTo(tv2); @@ -844,13 +792,13 @@ Val* BinaryExpr::SetFold(Val* v1, Val* v2) const default: BadTag("BinaryExpr::SetFold", expr_name(tag)); - return 0; + return nullptr; } - return val_mgr->GetBool(res); + return {AdoptRef{}, val_mgr->GetBool(res)}; } -Val* BinaryExpr::AddrFold(Val* v1, Val* v2) const +IntrusivePtr BinaryExpr::AddrFold(Val* v1, Val* v2) const { IPAddr a1 = v1->AsAddr(); IPAddr a2 = v2->AsAddr(); @@ -881,10 +829,10 @@ Val* BinaryExpr::AddrFold(Val* v1, Val* v2) const BadTag("BinaryExpr::AddrFold", expr_name(tag)); } - return val_mgr->GetBool(result); + return {AdoptRef{}, val_mgr->GetBool(result)}; } -Val* BinaryExpr::SubNetFold(Val* v1, Val* v2) const +IntrusivePtr BinaryExpr::SubNetFold(Val* v1, Val* v2) const { const IPPrefix& n1 = v1->AsSubNet(); const IPPrefix& n2 = v2->AsSubNet(); @@ -894,15 +842,14 @@ Val* BinaryExpr::SubNetFold(Val* v1, Val* v2) const if ( tag == EXPR_NE ) result = ! result; - return val_mgr->GetBool(result); + return {AdoptRef{}, val_mgr->GetBool(result)}; } void BinaryExpr::SwapOps() { // We could check here whether the operator is commutative. - Expr* t = op1; - op1 = op2; - op2 = t; + using std::swap; + swap(op1, op2); } void BinaryExpr::PromoteOps(TypeTag t) @@ -922,49 +869,51 @@ void BinaryExpr::PromoteOps(TypeTag t) reporter->Warning("mixing vector and scalar operands is deprecated"); if ( bt1 != t ) - op1 = new ArithCoerceExpr(op1, t); + op1 = make_intrusive(op1, t); if ( bt2 != t ) - op2 = new ArithCoerceExpr(op2, t); + op2 = make_intrusive(op2, t); } void BinaryExpr::PromoteType(TypeTag t, bool is_vector) { PromoteOps(t); - SetType(is_vector ? new VectorType(base_type(t)) : base_type(t)); + + if ( is_vector) + SetType(make_intrusive(base_type(t))); + else + SetType(IntrusivePtr{AdoptRef{}, base_type(t)}); } -CloneExpr::CloneExpr(Expr* arg_op) : UnaryExpr(EXPR_CLONE, arg_op) +CloneExpr::CloneExpr(IntrusivePtr arg_op) + : UnaryExpr(EXPR_CLONE, std::move(arg_op)) { if ( IsError() ) return; BroType* t = op->Type(); - SetType(t->Ref()); + SetType({NewRef{}, t}); } -Val* CloneExpr::Eval(Frame* f) const +IntrusivePtr CloneExpr::Eval(Frame* f) const { if ( IsError() ) - return 0; + return nullptr; - Val* v = op->Eval(f); + auto v = op->Eval(f); if ( ! v ) - return 0; + return nullptr; - Val* result = Fold(v); - Unref(v); - - return result; + return Fold(v.get()); } -Val* CloneExpr::Fold(Val* v) const +IntrusivePtr CloneExpr::Fold(Val* v) const { - return v->Clone(); + return {AdoptRef{}, v->Clone()}; } -IncrExpr::IncrExpr(BroExprTag arg_tag, Expr* arg_op) -: UnaryExpr(arg_tag, arg_op->MakeLvalue()) +IncrExpr::IncrExpr(BroExprTag arg_tag, IntrusivePtr arg_op) + : UnaryExpr(arg_tag, arg_op->MakeLvalue()) { if ( IsError() ) return; @@ -978,7 +927,7 @@ IncrExpr::IncrExpr(BroExprTag arg_tag, Expr* arg_op) else { reporter->Warning("increment/decrement operations for vectors deprecated"); - SetType(t->Ref()); + SetType({NewRef{}, t}); } } else @@ -986,11 +935,11 @@ IncrExpr::IncrExpr(BroExprTag arg_tag, Expr* arg_op) if ( ! IsIntegral(t->Tag()) ) ExprError("requires an integral operand"); else - SetType(t->Ref()); + SetType({NewRef{}, t}); } } -Val* IncrExpr::DoSingleEval(Frame* f, Val* v) const +IntrusivePtr IncrExpr::DoSingleEval(Frame* f, Val* v) const { bro_int_t k = v->CoerceToInt(); @@ -1010,41 +959,41 @@ Val* IncrExpr::DoSingleEval(Frame* f, Val* v) const ret_type = Type()->YieldType(); if ( ret_type->Tag() == TYPE_INT ) - return val_mgr->GetInt(k); + return {AdoptRef{}, val_mgr->GetInt(k)}; else - return val_mgr->GetCount(k); + return {AdoptRef{}, val_mgr->GetCount(k)}; } -Val* IncrExpr::Eval(Frame* f) const +IntrusivePtr IncrExpr::Eval(Frame* f) const { - Val* v = op->Eval(f); - if ( ! v ) - return 0; + auto v = op->Eval(f); - if ( is_vector(v) ) + if ( ! v ) + return nullptr; + + if ( is_vector(v.get()) ) { - VectorVal* v_vec = v->AsVectorVal(); + IntrusivePtr v_vec{NewRef{}, v->AsVectorVal()}; + for ( unsigned int i = 0; i < v_vec->Size(); ++i ) { Val* elt = v_vec->Lookup(i); + if ( elt ) - { - Val* new_elt = DoSingleEval(f, elt); - v_vec->Assign(i, new_elt); - } + v_vec->Assign(i, DoSingleEval(f, elt).release()); else - v_vec->Assign(i, 0); + v_vec->Assign(i, nullptr); } - op->Assign(f, v_vec->Ref()); + + op->Assign(f, std::move(v_vec)); return v; } else { - auto new_v = DoSingleEval(f, v); - Unref(v); - op->Assign(f, new_v->Ref()); + auto new_v = DoSingleEval(f, v.get()); + op->Assign(f, new_v); return new_v; } } @@ -1054,7 +1003,8 @@ bool IncrExpr::IsPure() const return false; } -ComplementExpr::ComplementExpr(Expr* arg_op) : UnaryExpr(EXPR_COMPLEMENT, arg_op) +ComplementExpr::ComplementExpr(IntrusivePtr arg_op) + : UnaryExpr(EXPR_COMPLEMENT, std::move(arg_op)) { if ( IsError() ) return; @@ -1065,15 +1015,16 @@ ComplementExpr::ComplementExpr(Expr* arg_op) : UnaryExpr(EXPR_COMPLEMENT, arg_op if ( bt != TYPE_COUNT ) ExprError("requires \"count\" operand"); else - SetType(base_type(TYPE_COUNT)); + SetType({AdoptRef{}, base_type(TYPE_COUNT)}); } -Val* ComplementExpr::Fold(Val* v) const +IntrusivePtr ComplementExpr::Fold(Val* v) const { - return val_mgr->GetCount(~ v->InternalUnsigned()); + return {AdoptRef{}, val_mgr->GetCount(~ v->InternalUnsigned())}; } -NotExpr::NotExpr(Expr* arg_op) : UnaryExpr(EXPR_NOT, arg_op) +NotExpr::NotExpr(IntrusivePtr arg_op) + : UnaryExpr(EXPR_NOT, std::move(arg_op)) { if ( IsError() ) return; @@ -1084,24 +1035,26 @@ NotExpr::NotExpr(Expr* arg_op) : UnaryExpr(EXPR_NOT, arg_op) if ( ! IsIntegral(bt) && bt != TYPE_BOOL ) ExprError("requires an integral or boolean operand"); else - SetType(base_type(TYPE_BOOL)); + SetType({AdoptRef{}, base_type(TYPE_BOOL)}); } -Val* NotExpr::Fold(Val* v) const +IntrusivePtr NotExpr::Fold(Val* v) const { - return val_mgr->GetBool(! v->InternalInt()); + return {AdoptRef{}, val_mgr->GetBool(! v->InternalInt())}; } -PosExpr::PosExpr(Expr* arg_op) : UnaryExpr(EXPR_POSITIVE, arg_op) +PosExpr::PosExpr(IntrusivePtr arg_op) + : UnaryExpr(EXPR_POSITIVE, std::move(arg_op)) { if ( IsError() ) return; BroType* t = op->Type(); + if ( IsVector(t->Tag()) ) t = t->AsVectorType()->YieldType(); - TypeTag bt = t->Tag(); + TypeTag bt = t->Tag(); BroType* base_result_type = 0; if ( IsIntegral(bt) ) @@ -1112,32 +1065,34 @@ PosExpr::PosExpr(Expr* arg_op) : UnaryExpr(EXPR_POSITIVE, arg_op) else ExprError("requires an integral or double operand"); - if ( is_vector(op) ) - SetType(new VectorType(base_result_type)); + if ( is_vector(op.get()) ) + SetType(make_intrusive(base_result_type)); else - SetType(base_result_type); + SetType({AdoptRef{}, base_result_type}); } -Val* PosExpr::Fold(Val* v) const +IntrusivePtr PosExpr::Fold(Val* v) const { TypeTag t = v->Type()->Tag(); if ( t == TYPE_DOUBLE || t == TYPE_INTERVAL || t == TYPE_INT ) - return v->Ref(); + return {NewRef{}, v}; else - return val_mgr->GetInt(v->CoerceToInt()); + return {AdoptRef{}, val_mgr->GetInt(v->CoerceToInt())}; } -NegExpr::NegExpr(Expr* arg_op) : UnaryExpr(EXPR_NEGATE, arg_op) +NegExpr::NegExpr(IntrusivePtr arg_op) + : UnaryExpr(EXPR_NEGATE, std::move(arg_op)) { if ( IsError() ) return; BroType* t = op->Type(); + if ( IsVector(t->Tag()) ) t = t->AsVectorType()->YieldType(); - TypeTag bt = t->Tag(); + TypeTag bt = t->Tag(); BroType* base_result_type = 0; if ( IsIntegral(bt) ) @@ -1148,60 +1103,62 @@ NegExpr::NegExpr(Expr* arg_op) : UnaryExpr(EXPR_NEGATE, arg_op) else ExprError("requires an integral or double operand"); - if ( is_vector(op) ) - SetType(new VectorType(base_result_type)); + if ( is_vector(op.get()) ) + SetType(make_intrusive(base_result_type)); else - SetType(base_result_type); + SetType({AdoptRef{}, base_result_type}); } -Val* NegExpr::Fold(Val* v) const +IntrusivePtr NegExpr::Fold(Val* v) const { if ( v->Type()->Tag() == TYPE_DOUBLE ) - return new Val(- v->InternalDouble(), v->Type()->Tag()); + return make_intrusive(- v->InternalDouble(), v->Type()->Tag()); else if ( v->Type()->Tag() == TYPE_INTERVAL ) - return new IntervalVal(- v->InternalDouble(), 1.0); + return make_intrusive(- v->InternalDouble(), 1.0); else - return val_mgr->GetInt(- v->CoerceToInt()); + return {AdoptRef{}, val_mgr->GetInt(- v->CoerceToInt())}; } -SizeExpr::SizeExpr(Expr* arg_op) : UnaryExpr(EXPR_SIZE, arg_op) +SizeExpr::SizeExpr(IntrusivePtr arg_op) + : UnaryExpr(EXPR_SIZE, std::move(arg_op)) { if ( IsError() ) return; if ( op->Type()->InternalType() == TYPE_INTERNAL_DOUBLE ) - SetType(base_type(TYPE_DOUBLE)); + SetType({AdoptRef{}, base_type(TYPE_DOUBLE)}); else - SetType(base_type(TYPE_COUNT)); + SetType({AdoptRef{}, base_type(TYPE_COUNT)}); } -Val* SizeExpr::Eval(Frame* f) const +IntrusivePtr SizeExpr::Eval(Frame* f) const { - Val* v = op->Eval(f); + auto v = op->Eval(f); + if ( ! v ) - return 0; + return nullptr; - Val* result = Fold(v); - Unref(v); - return result; + return Fold(v.get()); } -Val* SizeExpr::Fold(Val* v) const +IntrusivePtr SizeExpr::Fold(Val* v) const { - return v->SizeVal(); + return {AdoptRef{}, v->SizeVal()}; } -AddExpr::AddExpr(Expr* arg_op1, Expr* arg_op2) -: BinaryExpr(EXPR_ADD, arg_op1, arg_op2) +AddExpr::AddExpr(IntrusivePtr arg_op1, IntrusivePtr arg_op2) + : BinaryExpr(EXPR_ADD, std::move(arg_op1), std::move(arg_op2)) { if ( IsError() ) return; TypeTag bt1 = op1->Type()->Tag(); + if ( IsVector(bt1) ) bt1 = op1->Type()->AsVectorType()->YieldType()->Tag(); TypeTag bt2 = op2->Type()->Tag(); + if ( IsVector(bt2) ) bt2 = op2->Type()->AsVectorType()->YieldType()->Tag(); @@ -1214,7 +1171,7 @@ AddExpr::AddExpr(Expr* arg_op1, Expr* arg_op2) else if ( bt1 == TYPE_INTERVAL && bt2 == TYPE_INTERVAL ) base_result_type = base_type(bt1); else if ( BothArithmetic(bt1, bt2) ) - PromoteType(max_type(bt1, bt2), is_vector(op1) || is_vector(op2)); + PromoteType(max_type(bt1, bt2), is_vector(op1.get()) || is_vector(op2.get())); else if ( BothString(bt1, bt2) ) base_result_type = base_type(bt1); else @@ -1222,25 +1179,26 @@ AddExpr::AddExpr(Expr* arg_op1, Expr* arg_op2) if ( base_result_type ) { - if ( is_vector(op1) || is_vector(op2) ) - SetType(new VectorType(base_result_type)); + if ( is_vector(op1.get()) || is_vector(op2.get()) ) + SetType(make_intrusive(base_result_type)); else - SetType(base_result_type); + SetType({AdoptRef{}, base_result_type}); } } void AddExpr::Canonicize() { - if ( expr_greater(op2, op1) || + if ( expr_greater(op2.get(), op1.get()) || (op1->Type()->Tag() == TYPE_INTERVAL && op2->Type()->Tag() == TYPE_TIME) || (op2->IsConst() && ! is_vector(op2->ExprVal()) && ! op1->IsConst())) SwapOps(); } -AddToExpr::AddToExpr(Expr* arg_op1, Expr* arg_op2) -: BinaryExpr(EXPR_ADD_TO, - is_vector(arg_op1) ? arg_op1 : arg_op1->MakeLvalue(), arg_op2) +AddToExpr::AddToExpr(IntrusivePtr arg_op1, IntrusivePtr arg_op2) + : BinaryExpr(EXPR_ADD_TO, is_vector(arg_op1.get()) ? + std::move(arg_op1) : arg_op1->MakeLvalue(), + std::move(arg_op2)) { if ( IsError() ) return; @@ -1249,11 +1207,11 @@ AddToExpr::AddToExpr(Expr* arg_op1, Expr* arg_op2) TypeTag bt2 = op2->Type()->Tag(); if ( BothArithmetic(bt1, bt2) ) - PromoteType(max_type(bt1, bt2), is_vector(op1) || is_vector(op2)); + PromoteType(max_type(bt1, bt2), is_vector(op1.get()) || is_vector(op2.get())); else if ( BothString(bt1, bt2) ) - SetType(base_type(bt1)); + SetType({AdoptRef{}, base_type(bt1)}); else if ( BothInterval(bt1, bt2) ) - SetType(base_type(bt1)); + SetType({AdoptRef{}, base_type(bt1)}); else if ( IsVector(bt1) ) { @@ -1264,9 +1222,9 @@ AddToExpr::AddToExpr(Expr* arg_op1, Expr* arg_op2) if ( IsArithmetic(bt2) ) { if ( bt2 != bt1 ) - op2 = new ArithCoerceExpr(op2, bt1); + op2 = make_intrusive(std::move(op2), bt1); - SetType(op1->Type()->Ref()); + SetType({NewRef{}, op1->Type()}); } else @@ -1278,49 +1236,48 @@ AddToExpr::AddToExpr(Expr* arg_op1, Expr* arg_op2) type_name(bt1), type_name(bt2))); else - SetType(op1->Type()->Ref()); + SetType({NewRef{}, op1->Type()}); } else ExprError("requires two arithmetic or two string operands"); } -Val* AddToExpr::Eval(Frame* f) const +IntrusivePtr AddToExpr::Eval(Frame* f) const { - Val* v1 = op1->Eval(f); + auto v1 = op1->Eval(f); + if ( ! v1 ) - return 0; + return nullptr; + + auto v2 = op2->Eval(f); - Val* v2 = op2->Eval(f); if ( ! v2 ) - { - Unref(v1); - return 0; - } + return nullptr; - if ( is_vector(v1) ) + if ( is_vector(v1.get()) ) { VectorVal* vv = v1->AsVectorVal(); - if ( ! vv->Assign(vv->Size(), v2) ) + + if ( ! vv->Assign(vv->Size(), v2.release()) ) RuntimeError("type-checking failed in vector append"); + return v1; } - Val* result = Fold(v1, v2); - Unref(v1); - Unref(v2); + auto result = Fold(v1.get(), v2.get()); if ( result ) { - op1->Assign(f, result->Ref()); + op1->Assign(f, result); return result; } else - return 0; + return nullptr; } -SubExpr::SubExpr(Expr* arg_op1, Expr* arg_op2) -: BinaryExpr(EXPR_SUB, arg_op1, arg_op2) +SubExpr::SubExpr(IntrusivePtr arg_op1, IntrusivePtr arg_op2) + : BinaryExpr(EXPR_SUB, std::move(arg_op1), std::move(arg_op2)) { if ( IsError() ) return; @@ -1342,7 +1299,7 @@ SubExpr::SubExpr(Expr* arg_op1, Expr* arg_op2) base_result_type = base_type(bt1); else if ( bt1 == TYPE_TIME && bt2 == TYPE_TIME ) - SetType(base_type(TYPE_INTERVAL)); + SetType({AdoptRef{}, base_type(TYPE_INTERVAL)}); else if ( bt1 == TYPE_INTERVAL && bt2 == TYPE_INTERVAL ) base_result_type = base_type(bt1); @@ -1350,28 +1307,29 @@ SubExpr::SubExpr(Expr* arg_op1, Expr* arg_op2) else if ( t1->IsSet() && t2->IsSet() ) { if ( same_type(t1, t2) ) - SetType(op1->Type()->Ref()); + SetType({NewRef{}, op1->Type()}); else ExprError("incompatible \"set\" operands"); } else if ( BothArithmetic(bt1, bt2) ) - PromoteType(max_type(bt1, bt2), is_vector(op1) || is_vector(op2)); + PromoteType(max_type(bt1, bt2), is_vector(op1.get()) || is_vector(op2.get())); else ExprError("requires arithmetic operands"); if ( base_result_type ) { - if ( is_vector(op1) || is_vector(op2) ) - SetType(new VectorType(base_result_type)); + if ( is_vector(op1.get()) || is_vector(op2.get()) ) + SetType(make_intrusive(base_result_type)); else - SetType(base_result_type); + SetType({AdoptRef{}, base_result_type}); } } -RemoveFromExpr::RemoveFromExpr(Expr* arg_op1, Expr* arg_op2) -: BinaryExpr(EXPR_REMOVE_FROM, arg_op1->MakeLvalue(), arg_op2) +RemoveFromExpr::RemoveFromExpr(IntrusivePtr arg_op1, + IntrusivePtr arg_op2) + : BinaryExpr(EXPR_REMOVE_FROM, arg_op1->MakeLvalue(), std::move(arg_op2)) { if ( IsError() ) return; @@ -1380,42 +1338,38 @@ RemoveFromExpr::RemoveFromExpr(Expr* arg_op1, Expr* arg_op2) TypeTag bt2 = op2->Type()->Tag(); if ( BothArithmetic(bt1, bt2) ) - PromoteType(max_type(bt1, bt2), is_vector(op1) || is_vector(op2)); + PromoteType(max_type(bt1, bt2), is_vector(op1.get()) || is_vector(op2.get())); else if ( BothInterval(bt1, bt2) ) - SetType(base_type(bt1)); + SetType({AdoptRef{}, base_type(bt1)}); else ExprError("requires two arithmetic operands"); } -Val* RemoveFromExpr::Eval(Frame* f) const +IntrusivePtr RemoveFromExpr::Eval(Frame* f) const { - Val* v1 = op1->Eval(f); + auto v1 = op1->Eval(f); + if ( ! v1 ) - return 0; + return nullptr; + + auto v2 = op2->Eval(f); - Val* v2 = op2->Eval(f); if ( ! v2 ) - { - Unref(v1); - return 0; - } + return nullptr; - Val* result = Fold(v1, v2); - - Unref(v1); - Unref(v2); + auto result = Fold(v1.get(), v2.get()); if ( result ) { - op1->Assign(f, result->Ref()); + op1->Assign(f, result); return result; } else - return 0; + return nullptr; } -TimesExpr::TimesExpr(Expr* arg_op1, Expr* arg_op2) -: BinaryExpr(EXPR_TIMES, arg_op1, arg_op2) +TimesExpr::TimesExpr(IntrusivePtr arg_op1, IntrusivePtr arg_op2) + : BinaryExpr(EXPR_TIMES, std::move(arg_op1), std::move(arg_op2)) { if ( IsError() ) return; @@ -1423,76 +1377,82 @@ TimesExpr::TimesExpr(Expr* arg_op1, Expr* arg_op2) Canonicize(); TypeTag bt1 = op1->Type()->Tag(); + if ( IsVector(bt1) ) bt1 = op1->Type()->AsVectorType()->YieldType()->Tag(); TypeTag bt2 = op2->Type()->Tag(); + if ( IsVector(bt2) ) bt2 = op2->Type()->AsVectorType()->YieldType()->Tag(); if ( bt1 == TYPE_INTERVAL || bt2 == TYPE_INTERVAL ) { if ( IsArithmetic(bt1) || IsArithmetic(bt2) ) - PromoteType(TYPE_INTERVAL, is_vector(op1) || is_vector(op2) ); + PromoteType(TYPE_INTERVAL, is_vector(op1.get()) || is_vector(op2.get()) ); else ExprError("multiplication with interval requires arithmetic operand"); } else if ( BothArithmetic(bt1, bt2) ) - PromoteType(max_type(bt1, bt2), is_vector(op1) || is_vector(op2)); + PromoteType(max_type(bt1, bt2), is_vector(op1.get()) || is_vector(op2.get())); else ExprError("requires arithmetic operands"); } void TimesExpr::Canonicize() { - if ( expr_greater(op2, op1) || op2->Type()->Tag() == TYPE_INTERVAL || + if ( expr_greater(op2.get(), op1.get()) || op2->Type()->Tag() == TYPE_INTERVAL || (op2->IsConst() && ! is_vector(op2->ExprVal()) && ! op1->IsConst()) ) SwapOps(); } -DivideExpr::DivideExpr(Expr* arg_op1, Expr* arg_op2) -: BinaryExpr(EXPR_DIVIDE, arg_op1, arg_op2) +DivideExpr::DivideExpr(IntrusivePtr arg_op1, + IntrusivePtr arg_op2) + : BinaryExpr(EXPR_DIVIDE, std::move(arg_op1), std::move(arg_op2)) { if ( IsError() ) return; TypeTag bt1 = op1->Type()->Tag(); + if ( IsVector(bt1) ) bt1 = op1->Type()->AsVectorType()->YieldType()->Tag(); TypeTag bt2 = op2->Type()->Tag(); + if ( IsVector(bt2) ) bt2 = op2->Type()->AsVectorType()->YieldType()->Tag(); if ( bt1 == TYPE_INTERVAL || bt2 == TYPE_INTERVAL ) { if ( IsArithmetic(bt1) || IsArithmetic(bt2) ) - PromoteType(TYPE_INTERVAL, is_vector(op1) || is_vector(op2)); + PromoteType(TYPE_INTERVAL, is_vector(op1.get()) || is_vector(op2.get())); else if ( bt1 == TYPE_INTERVAL && bt2 == TYPE_INTERVAL ) { - if ( is_vector(op1) || is_vector(op2) ) - SetType(new VectorType(base_type(TYPE_DOUBLE))); + if ( is_vector(op1.get()) || is_vector(op2.get()) ) + SetType(make_intrusive(base_type(TYPE_DOUBLE))); else - SetType(base_type(TYPE_DOUBLE)); + SetType({AdoptRef{}, base_type(TYPE_DOUBLE)}); } else ExprError("division of interval requires arithmetic operand"); } else if ( BothArithmetic(bt1, bt2) ) - PromoteType(max_type(bt1, bt2), is_vector(op1) || is_vector(op2)); + PromoteType(max_type(bt1, bt2), is_vector(op1.get()) || is_vector(op2.get())); - else if ( bt1 == TYPE_ADDR && ! is_vector(op2) && + else if ( bt1 == TYPE_ADDR && ! is_vector(op2.get()) && (bt2 == TYPE_COUNT || bt2 == TYPE_INT) ) - SetType(base_type(TYPE_SUBNET)); + SetType({AdoptRef{}, base_type(TYPE_SUBNET)}); else ExprError("requires arithmetic operands"); } -Val* DivideExpr::AddrFold(Val* v1, Val* v2) const +IntrusivePtr DivideExpr::AddrFold(Val* v1, Val* v2) const { uint32_t mask; + if ( v2->Type()->Tag() == TYPE_COUNT ) mask = static_cast(v2->InternalUnsigned()); else @@ -1511,169 +1471,157 @@ Val* DivideExpr::AddrFold(Val* v1, Val* v2) const RuntimeError(fmt("bad IPv6 subnet prefix length: %" PRIu32, mask)); } - return new SubNetVal(a, mask); + return make_intrusive(a, mask); } -ModExpr::ModExpr(Expr* arg_op1, Expr* arg_op2) -: BinaryExpr(EXPR_MOD, arg_op1, arg_op2) +ModExpr::ModExpr(IntrusivePtr arg_op1, IntrusivePtr arg_op2) + : BinaryExpr(EXPR_MOD, std::move(arg_op1), std::move(arg_op2)) { if ( IsError() ) return; TypeTag bt1 = op1->Type()->Tag(); + if ( IsVector(bt1) ) bt1 = op1->Type()->AsVectorType()->YieldType()->Tag(); TypeTag bt2 = op2->Type()->Tag(); + if ( IsVector(bt2) ) bt2 = op2->Type()->AsVectorType()->YieldType()->Tag(); if ( BothIntegral(bt1, bt2) ) - PromoteType(max_type(bt1, bt2), is_vector(op1) || is_vector(op2)); + PromoteType(max_type(bt1, bt2), is_vector(op1.get()) || is_vector(op2.get())); else ExprError("requires integral operands"); } -BoolExpr::BoolExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2) -: BinaryExpr(arg_tag, arg_op1, arg_op2) +BoolExpr::BoolExpr(BroExprTag arg_tag, + IntrusivePtr arg_op1, IntrusivePtr arg_op2) + : BinaryExpr(arg_tag, std::move(arg_op1), std::move(arg_op2)) { if ( IsError() ) return; TypeTag bt1 = op1->Type()->Tag(); + if ( IsVector(bt1) ) bt1 = op1->Type()->AsVectorType()->YieldType()->Tag(); TypeTag bt2 = op2->Type()->Tag(); + if ( IsVector(bt2) ) bt2 = op2->Type()->AsVectorType()->YieldType()->Tag(); if ( BothBool(bt1, bt2) ) { - if ( is_vector(op1) || is_vector(op2) ) + if ( is_vector(op1.get()) || is_vector(op2.get()) ) { - if ( ! (is_vector(op1) && is_vector(op2)) ) + if ( ! (is_vector(op1.get()) && is_vector(op2.get())) ) reporter->Warning("mixing vector and scalar operands is deprecated"); - SetType(new VectorType(base_type(TYPE_BOOL))); + SetType(make_intrusive(base_type(TYPE_BOOL))); } else - SetType(base_type(TYPE_BOOL)); + SetType({AdoptRef{}, base_type(TYPE_BOOL)}); } else ExprError("requires boolean operands"); } -Val* BoolExpr::DoSingleEval(Frame* f, Val* v1, Expr* op2) const +IntrusivePtr BoolExpr::DoSingleEval(Frame* f, IntrusivePtr v1, Expr* op2) const { if ( ! v1 ) - return 0; + return nullptr; if ( tag == EXPR_AND_AND ) { if ( v1->IsZero() ) return v1; else - { - Unref(v1); return op2->Eval(f); - } } else { if ( v1->IsZero() ) - { - Unref(v1); return op2->Eval(f); - } else return v1; } } - -Val* BoolExpr::Eval(Frame* f) const +IntrusivePtr BoolExpr::Eval(Frame* f) const { if ( IsError() ) - return 0; + return nullptr; + + auto v1 = op1->Eval(f); - Val* v1 = op1->Eval(f); if ( ! v1 ) - return 0; + return nullptr; - bool is_vec1 = is_vector(op1); - bool is_vec2 = is_vector(op2); + bool is_vec1 = is_vector(op1.get()); + bool is_vec2 = is_vector(op2.get()); // Handle scalar op scalar if ( ! is_vec1 && ! is_vec2 ) - return DoSingleEval(f, v1, op2); + return DoSingleEval(f, std::move(v1), op2.get()); // Handle scalar op vector or vector op scalar // We can't short-circuit everything since we need to eval // a vector in order to find out its length. if ( ! (is_vec1 && is_vec2) ) { // Only one is a vector. - Val* scalar_v = 0; - VectorVal* vector_v = 0; + IntrusivePtr scalar_v; + IntrusivePtr vector_v; if ( is_vec1 ) { scalar_v = op2->Eval(f); - vector_v = v1->AsVectorVal(); + vector_v = {AdoptRef{}, v1.release()->AsVectorVal()}; } else { - scalar_v = v1; - vector_v = op2->Eval(f)->AsVectorVal(); + scalar_v = std::move(v1); + vector_v = {AdoptRef{}, op2->Eval(f).release()->AsVectorVal()}; } if ( ! scalar_v || ! vector_v ) - { - Unref(v1); - return 0; - } + return nullptr; - VectorVal* result = 0; + IntrusivePtr result; // It's either an EXPR_AND_AND or an EXPR_OR_OR. bool is_and = (tag == EXPR_AND_AND); if ( scalar_v->IsZero() == is_and ) { - result = new VectorVal(Type()->AsVectorType()); + result = make_intrusive(Type()->AsVectorType()); result->Resize(vector_v->Size()); - result->AssignRepeat(0, result->Size(), - scalar_v); + result->AssignRepeat(0, result->Size(), scalar_v.get()); } else - result = vector_v->Ref()->AsVectorVal(); - - Unref(scalar_v); - Unref(vector_v); + result = std::move(vector_v); return result; } // Only case remaining: both are vectors. - Val* v2 = op2->Eval(f); + auto v2 = op2->Eval(f); + if ( ! v2 ) - { - Unref(v1); - return 0; - } + return nullptr; VectorVal* vec_v1 = v1->AsVectorVal(); VectorVal* vec_v2 = v2->AsVectorVal(); if ( vec_v1->Size() != vec_v2->Size() ) { - Unref(v1); - Unref(v2); RuntimeError("vector operands have different sizes"); - return 0; + return nullptr; } - VectorVal* result = new VectorVal(Type()->AsVectorType()); + auto result = make_intrusive(Type()->AsVectorType()); result->Resize(vec_v1->Size()); for ( unsigned int i = 0; i < vec_v1->Size(); ++i ) @@ -1692,14 +1640,12 @@ Val* BoolExpr::Eval(Frame* f) const result->Assign(i, 0); } - Unref(v1); - Unref(v2); - return result; } -BitExpr::BitExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2) -: BinaryExpr(arg_tag, arg_op1, arg_op2) +BitExpr::BitExpr(BroExprTag arg_tag, + IntrusivePtr arg_op1, IntrusivePtr arg_op2) + : BinaryExpr(arg_tag, std::move(arg_op1), std::move(arg_op2)) { if ( IsError() ) return; @@ -1708,10 +1654,12 @@ BitExpr::BitExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2) const BroType* t2 = op2->Type(); TypeTag bt1 = t1->Tag(); + if ( IsVector(bt1) ) bt1 = t1->AsVectorType()->YieldType()->Tag(); TypeTag bt2 = t2->Tag(); + if ( IsVector(bt2) ) bt2 = t2->AsVectorType()->YieldType()->Tag(); @@ -1720,10 +1668,10 @@ BitExpr::BitExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2) { if ( bt1 == TYPE_COUNTER && bt2 == TYPE_COUNTER ) ExprError("cannot apply a bitwise operator to two \"counter\" operands"); - else if ( is_vector(op1) || is_vector(op2) ) - SetType(new VectorType(base_type(TYPE_COUNT))); + else if ( is_vector(op1.get()) || is_vector(op2.get()) ) + SetType(make_intrusive(base_type(TYPE_COUNT))); else - SetType(base_type(TYPE_COUNT)); + SetType({AdoptRef{}, base_type(TYPE_COUNT)}); } else if ( bt1 == TYPE_PATTERN ) @@ -1733,13 +1681,13 @@ BitExpr::BitExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2) else if ( tag == EXPR_XOR ) ExprError("'^' operator does not apply to patterns"); else - SetType(base_type(TYPE_PATTERN)); + SetType({AdoptRef{}, base_type(TYPE_PATTERN)}); } else if ( t1->IsSet() && t2->IsSet() ) { if ( same_type(t1, t2) ) - SetType(op1->Type()->Ref()); + SetType({NewRef{}, op1->Type()}); else ExprError("incompatible \"set\" operands"); } @@ -1748,8 +1696,9 @@ BitExpr::BitExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2) ExprError("requires \"count\" or compatible \"set\" operands"); } -EqExpr::EqExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2) -: BinaryExpr(arg_tag, arg_op1, arg_op2) +EqExpr::EqExpr(BroExprTag arg_tag, + IntrusivePtr arg_op1, IntrusivePtr arg_op2) + : BinaryExpr(arg_tag, std::move(arg_op1), std::move(arg_op2)) { if ( IsError() ) return; @@ -1767,10 +1716,10 @@ EqExpr::EqExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2) if ( IsVector(bt2) ) bt2 = t2->AsVectorType()->YieldType()->Tag(); - if ( is_vector(op1) || is_vector(op2) ) - SetType(new VectorType(base_type(TYPE_BOOL))); + if ( is_vector(op1.get()) || is_vector(op2.get()) ) + SetType(make_intrusive(base_type(TYPE_BOOL))); else - SetType(base_type(TYPE_BOOL)); + SetType({AdoptRef{}, base_type(TYPE_BOOL)}); if ( BothArithmetic(bt1, bt2) ) PromoteOps(max_type(bt1, bt2)); @@ -1829,28 +1778,29 @@ void EqExpr::Canonicize() else if ( op1->Type()->Tag() == TYPE_PATTERN ) ; - else if ( expr_greater(op2, op1) ) + else if ( expr_greater(op2.get(), op1.get()) ) SwapOps(); } -Val* EqExpr::Fold(Val* v1, Val* v2) const +IntrusivePtr EqExpr::Fold(Val* v1, Val* v2) const { if ( op1->Type()->Tag() == TYPE_PATTERN ) { RE_Matcher* re = v1->AsPattern(); const BroString* s = v2->AsString(); if ( tag == EXPR_EQ ) - return val_mgr->GetBool(re->MatchExactly(s)); + return {AdoptRef{}, val_mgr->GetBool(re->MatchExactly(s))}; else - return val_mgr->GetBool(! re->MatchExactly(s)); + return {AdoptRef{}, val_mgr->GetBool(! re->MatchExactly(s))}; } else return BinaryExpr::Fold(v1, v2); } -RelExpr::RelExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2) -: BinaryExpr(arg_tag, arg_op1, arg_op2) +RelExpr::RelExpr(BroExprTag arg_tag, + IntrusivePtr arg_op1, IntrusivePtr arg_op2) + : BinaryExpr(arg_tag, std::move(arg_op1), std::move(arg_op2)) { if ( IsError() ) return; @@ -1868,10 +1818,10 @@ RelExpr::RelExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2) if ( IsVector(bt2) ) bt2 = t2->AsVectorType()->YieldType()->Tag(); - if ( is_vector(op1) || is_vector(op2) ) - SetType(new VectorType(base_type(TYPE_BOOL))); + if ( is_vector(op1.get()) || is_vector(op2.get()) ) + SetType(make_intrusive(base_type(TYPE_BOOL))); else - SetType(base_type(TYPE_BOOL)); + SetType({AdoptRef{}, base_type(TYPE_BOOL)}); if ( BothArithmetic(bt1, bt2) ) PromoteOps(max_type(bt1, bt2)); @@ -1906,14 +1856,13 @@ void RelExpr::Canonicize() } } -CondExpr::CondExpr(Expr* arg_op1, Expr* arg_op2, Expr* arg_op3) -: Expr(EXPR_COND) +CondExpr::CondExpr(IntrusivePtr arg_op1, IntrusivePtr arg_op2, + IntrusivePtr arg_op3) + : Expr(EXPR_COND), + op1(std::move(arg_op1)), op2(std::move(arg_op2)), op3(std::move(arg_op3)) { - op1 = arg_op1; - op2 = arg_op2; - op3 = arg_op3; - TypeTag bt1 = op1->Type()->Tag(); + if ( IsVector(bt1) ) bt1 = op1->Type()->AsVectorType()->YieldType()->Tag(); @@ -1926,14 +1875,16 @@ CondExpr::CondExpr(Expr* arg_op1, Expr* arg_op2, Expr* arg_op3) else { TypeTag bt2 = op2->Type()->Tag(); - if ( is_vector(op2) ) + + if ( is_vector(op2.get()) ) bt2 = op2->Type()->AsVectorType()->YieldType()->Tag(); TypeTag bt3 = op3->Type()->Tag(); + if ( IsVector(bt3) ) bt3 = op3->Type()->AsVectorType()->YieldType()->Tag(); - if ( is_vector(op1) && ! (is_vector(op2) && is_vector(op3)) ) + if ( is_vector(op1.get()) && ! (is_vector(op2.get()) && is_vector(op3.get())) ) { ExprError("vector conditional requires vector alternatives"); return; @@ -1943,14 +1894,14 @@ CondExpr::CondExpr(Expr* arg_op1, Expr* arg_op2, Expr* arg_op3) { TypeTag t = max_type(bt2, bt3); if ( bt2 != t ) - op2 = new ArithCoerceExpr(op2, t); + op2 = make_intrusive(std::move(op2), t); if ( bt3 != t ) - op3 = new ArithCoerceExpr(op3, t); + op3 = make_intrusive(std::move(op3), t); - if ( is_vector(op2) ) - SetType(new VectorType(base_type(t))); + if ( is_vector(op2.get()) ) + SetType(make_intrusive(base_type(t))); else - SetType(base_type(t)); + SetType({AdoptRef{}, base_type(t)}); } else if ( bt2 != bt3 ) @@ -1962,48 +1913,35 @@ CondExpr::CondExpr(Expr* arg_op1, Expr* arg_op2, Expr* arg_op3) ! same_type(op2->Type(), op3->Type()) ) ExprError("operands must be of the same type"); else - SetType(op2->Type()->Ref()); + SetType({NewRef{}, op2->Type()}); } } } -CondExpr::~CondExpr() +IntrusivePtr CondExpr::Eval(Frame* f) const { - Unref(op1); - Unref(op2); - Unref(op3); - } - -Val* CondExpr::Eval(Frame* f) const - { - if ( ! is_vector(op1) ) - { // scalar is easy - Val* v = op1->Eval(f); - int false_eval = v->IsZero(); - Unref(v); - + if ( ! is_vector(op1.get()) ) + { + // Scalar case + auto false_eval = op1->Eval(f)->IsZero(); return (false_eval ? op3 : op2)->Eval(f); } // Vector case: no mixed scalar/vector cases allowed - Val* v1 = op1->Eval(f); + auto v1 = op1->Eval(f); + if ( ! v1 ) - return 0; + return nullptr; + + auto v2 = op2->Eval(f); - Val* v2 = op2->Eval(f); if ( ! v2 ) - { - Unref(v1); - return 0; - } + return nullptr; + + auto v3 = op3->Eval(f); - Val* v3 = op3->Eval(f); if ( ! v3 ) - { - Unref(v1); - Unref(v2); - return 0; - } + return nullptr; VectorVal* cond = v1->AsVectorVal(); VectorVal* a = v2->AsVectorVal(); @@ -2011,19 +1949,17 @@ Val* CondExpr::Eval(Frame* f) const if ( cond->Size() != a->Size() || a->Size() != b->Size() ) { - Unref(v1); - Unref(v2); - Unref(v3); RuntimeError("vectors in conditional expression have different sizes"); - return 0; + return nullptr; } - VectorVal* result = new VectorVal(Type()->AsVectorType()); + auto result = make_intrusive(Type()->AsVectorType()); result->Resize(cond->Size()); for ( unsigned int i = 0; i < cond->Size(); ++i ) { Val* local_cond = cond->Lookup(i); + if ( local_cond ) { Val* v = local_cond->IsZero() ? b->Lookup(i) : a->Lookup(i); @@ -2033,10 +1969,6 @@ Val* CondExpr::Eval(Frame* f) const result->Assign(i, 0); } - Unref(v1); - Unref(v2); - Unref(v3); - return result; } @@ -2072,7 +2004,8 @@ void CondExpr::ExprDescribe(ODesc* d) const op3->Describe(d); } -RefExpr::RefExpr(Expr* arg_op) : UnaryExpr(EXPR_REF, arg_op) +RefExpr::RefExpr(IntrusivePtr arg_op) + : UnaryExpr(EXPR_REF, std::move(arg_op)) { if ( IsError() ) return; @@ -2080,23 +2013,25 @@ RefExpr::RefExpr(Expr* arg_op) : UnaryExpr(EXPR_REF, arg_op) if ( ! ::is_assignable(op->Type()) ) ExprError("illegal assignment target"); else - SetType(op->Type()->Ref()); + SetType({NewRef{}, op->Type()}); } -Expr* RefExpr::MakeLvalue() +IntrusivePtr RefExpr::MakeLvalue() { - return this; + return {NewRef{}, this}; } -void RefExpr::Assign(Frame* f, Val* v) +void RefExpr::Assign(Frame* f, IntrusivePtr v) { - op->Assign(f, v); + op->Assign(f, std::move(v)); } -AssignExpr::AssignExpr(Expr* arg_op1, Expr* arg_op2, int arg_is_init, - Val* arg_val, attr_list* arg_attrs) -: BinaryExpr(EXPR_ASSIGN, - arg_is_init ? arg_op1 : arg_op1->MakeLvalue(), arg_op2) +AssignExpr::AssignExpr(IntrusivePtr arg_op1, IntrusivePtr arg_op2, + int arg_is_init, IntrusivePtr arg_val, + attr_list* arg_attrs) + : BinaryExpr(EXPR_ASSIGN, arg_is_init ? + std::move(arg_op1) : arg_op1->MakeLvalue(), + std::move(arg_op2)) { val = 0; is_init = arg_is_init; @@ -2104,12 +2039,12 @@ AssignExpr::AssignExpr(Expr* arg_op1, Expr* arg_op2, int arg_is_init, if ( IsError() ) return; - SetType(arg_val ? arg_val->Type()->Ref() : op1->Type()->Ref()); + SetType({NewRef{}, arg_val ? arg_val->Type() : op1->Type()}); if ( is_init ) { - SetLocationInfo(arg_op1->GetLocationInfo(), - arg_op2->GetLocationInfo()); + SetLocationInfo(op1->GetLocationInfo(), + op2->GetLocationInfo()); return; } @@ -2117,14 +2052,9 @@ AssignExpr::AssignExpr(Expr* arg_op1, Expr* arg_op2, int arg_is_init, // generated error messages. (void) TypeCheck(arg_attrs); - val = arg_val ? arg_val->Ref() : 0; + val = std::move(arg_val); - SetLocationInfo(arg_op1->GetLocationInfo(), arg_op2->GetLocationInfo()); - } - -AssignExpr::~AssignExpr() - { - Unref(val); + SetLocationInfo(op1->GetLocationInfo(), op2->GetLocationInfo()); } bool AssignExpr::TypeCheck(attr_list* attrs) @@ -2148,20 +2078,22 @@ bool AssignExpr::TypeCheck(attr_list* attrs) if ( bt1 == TYPE_TIME && IsArithmetic(bt2) && op2->IsZero() ) { // Allow assignments to zero as a special case. - op2 = new ArithCoerceExpr(op2, bt1); + op2 = make_intrusive(std::move(op2), bt1); return true; } if ( bt1 == TYPE_TABLE && bt2 == bt1 && op2->Type()->AsTableType()->IsUnspecifiedTable() ) { - op2 = new TableCoerceExpr(op2, op1->Type()->AsTableType()); + op2 = make_intrusive(std::move(op2), + IntrusivePtr{NewRef{}, op1->Type()->AsTableType()}); return true; } if ( bt1 == TYPE_TABLE && op2->Tag() == EXPR_LIST ) { attr_list* attr_copy = 0; + if ( attrs ) { attr_copy = new attr_list(attrs->length()); @@ -2171,9 +2103,11 @@ bool AssignExpr::TypeCheck(attr_list* attrs) bool empty_list_assignment = (op2->AsListExpr()->Exprs().empty()); if ( op1->Type()->IsSet() ) - op2 = new SetConstructorExpr(op2->AsListExpr(), attr_copy); + op2 = make_intrusive( + IntrusivePtr{NewRef{}, op2->AsListExpr()}, attr_copy); else - op2 = new TableConstructorExpr(op2->AsListExpr(), attr_copy); + op2 = make_intrusive( + IntrusivePtr{NewRef{}, op2->AsListExpr()}, attr_copy); if ( ! empty_list_assignment && ! same_type(op1->Type(), op2->Type()) ) { @@ -2192,13 +2126,16 @@ bool AssignExpr::TypeCheck(attr_list* attrs) { if ( bt2 == bt1 && op2->Type()->AsVectorType()->IsUnspecifiedVector() ) { - op2 = new VectorCoerceExpr(op2, op1->Type()->AsVectorType()); + op2 = make_intrusive(std::move(op2), + IntrusivePtr{NewRef{}, op1->Type()->AsVectorType()}); return true; } if ( op2->Tag() == EXPR_LIST ) { - op2 = new VectorConstructorExpr(op2->AsListExpr(), op1->Type()); + op2 = make_intrusive( + IntrusivePtr{AdoptRef{}, op2.release()->AsListExpr()}, + IntrusivePtr{NewRef{}, op1->Type()}); return true; } } @@ -2224,7 +2161,8 @@ bool AssignExpr::TypeCheck(attr_list* attrs) } // Need to coerce. - op2 = new RecordCoerceExpr(op2, op1->Type()->AsRecordType()); + op2 = make_intrusive(std::move(op2), + IntrusivePtr{NewRef{}, op1->Type()->AsRecordType()}); return true; } @@ -2237,7 +2175,8 @@ bool AssignExpr::TypeCheck(attr_list* attrs) // Some elements in constructor list must not match, see if // we can create a new constructor now that the expected type // of LHS is known and let it do coercions where possible. - SetConstructorExpr* sce = dynamic_cast(op2); + SetConstructorExpr* sce = dynamic_cast(op2.get()); + if ( ! sce ) { ExprError("Failed typecast to SetConstructorExpr"); @@ -2245,6 +2184,7 @@ bool AssignExpr::TypeCheck(attr_list* attrs) } ListExpr* ctor_list = dynamic_cast(sce->Op()); + if ( ! ctor_list ) { ExprError("Failed typecast to ListExpr"); @@ -2261,7 +2201,9 @@ bool AssignExpr::TypeCheck(attr_list* attrs) } int errors_before = reporter->Errors(); - op2 = new SetConstructorExpr(ctor_list, attr_copy, op1->Type()); + op2 = make_intrusive( + IntrusivePtr{NewRef{}, ctor_list}, attr_copy, + IntrusivePtr{NewRef{}, op1->Type()}); int errors_after = reporter->Errors(); if ( errors_after > errors_before ) @@ -2299,7 +2241,7 @@ bool AssignExpr::TypeCheckArithmetics(TypeTag bt1, TypeTag bt2) if ( bt2 == TYPE_DOUBLE ) { Warn("dangerous assignment of double to integral"); - op2 = new ArithCoerceExpr(op2, bt1); + op2 = make_intrusive(std::move(op2), bt1); bt2 = op2->Type()->Tag(); } @@ -2310,7 +2252,7 @@ bool AssignExpr::TypeCheckArithmetics(TypeTag bt1, TypeTag bt2) if ( bt2 == TYPE_INT ) { Warn("dangerous assignment of integer to count"); - op2 = new ArithCoerceExpr(op2, bt1); + op2 = make_intrusive(std::move(op2), bt1); bt2 = op2->Type()->Tag(); } @@ -2323,45 +2265,42 @@ bool AssignExpr::TypeCheckArithmetics(TypeTag bt1, TypeTag bt2) } -Val* AssignExpr::Eval(Frame* f) const +IntrusivePtr AssignExpr::Eval(Frame* f) const { if ( is_init ) { RuntimeError("illegal assignment in initialization"); - return 0; + return nullptr; } - Val* v = op2->Eval(f); + auto v = op2->Eval(f); if ( v ) { - op1->Assign(f, v->Ref()); + op1->Assign(f, v); if ( val ) - { - Unref(v); - return val->Ref(); - } + return val; return v; } else - return 0; + return nullptr; } -BroType* AssignExpr::InitType() const +IntrusivePtr AssignExpr::InitType() const { if ( op1->Tag() != EXPR_LIST ) { Error("bad initializer"); - return 0; + return nullptr; } BroType* tl = op1->Type(); if ( tl->Tag() != TYPE_LIST ) Internal("inconsistent list expr in AssignExpr::InitType"); - return new TableType(tl->Ref()->AsTypeList(), op2->Type()->Ref()); + return make_intrusive(tl->Ref()->AsTypeList(), op2->Type()->Ref()); } void AssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) const @@ -2370,6 +2309,7 @@ void AssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) const return; TypeDecl td(0, 0); + if ( IsRecordElement(&td) ) { if ( t->Tag() != TYPE_RECORD ) @@ -2389,9 +2329,10 @@ void AssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) const RecordVal* aggr_r = aggr->AsRecordVal(); - Val* v = op2->Eval(f); + auto v = op2->Eval(f); + if ( v ) - aggr_r->Assign(field, v); + aggr_r->Assign(field, v.release()); return; } @@ -2401,56 +2342,55 @@ void AssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) const TableVal* tv = aggr->AsTableVal(); - Val* index = op1->Eval(f); - Val* v = check_and_promote(op2->Eval(f), t->YieldType(), 1); + auto index = op1->Eval(f); + auto v = check_and_promote(op2->Eval(f), t->YieldType(), 1); + if ( ! index || ! v ) - { - Unref(index); - Unref(v); return; - } - if ( ! tv->Assign(index, v) ) + if ( ! tv->Assign(index.get(), v.release()) ) RuntimeError("type clash in table assignment"); - - Unref(index); } -Val* AssignExpr::InitVal(const BroType* t, Val* aggr) const +IntrusivePtr AssignExpr::InitVal(const BroType* t, IntrusivePtr aggr) const { if ( ! aggr ) { Error("assignment in initialization"); - return 0; + return nullptr; } if ( IsError() ) - return 0; + return nullptr; TypeDecl td(0, 0); + if ( IsRecordElement(&td) ) { if ( t->Tag() != TYPE_RECORD ) { Error("not a record initializer", t); - return 0; + return nullptr; } + const RecordType* rt = t->AsRecordType(); int field = rt->FieldOffset(td.id); if ( field < 0 ) { Error("no such field"); - return 0; + return nullptr; } if ( aggr->Type()->Tag() != TYPE_RECORD ) Internal("bad aggregate in AssignExpr::InitVal"); + RecordVal* aggr_r = aggr->AsRecordVal(); - Val* v = op2->InitVal(rt->FieldType(td.id), 0); + auto v = op2->InitVal(rt->FieldType(td.id), nullptr); + if ( ! v ) - return 0; + return nullptr; aggr_r->Assign(field, v->Ref()); return v; @@ -2461,26 +2401,25 @@ Val* AssignExpr::InitVal(const BroType* t, Val* aggr) const if ( t->Tag() != TYPE_TABLE ) { Error("not a table initialization", t); - return 0; + return nullptr; } if ( aggr->Type()->Tag() != TYPE_TABLE ) Internal("bad aggregate in AssignExpr::InitVal"); - TableVal* tv = aggr->AsTableVal(); + // TODO: implement safer IntrusivePtr casts + IntrusivePtr tv{NewRef{}, aggr->AsTableVal()}; const TableType* tt = tv->Type()->AsTableType(); const BroType* yt = tv->Type()->YieldType(); - IntrusivePtr index{AdoptRef{}, op1->InitVal(tt->Indices(), 0)}; - IntrusivePtr v{AdoptRef{}, op2->InitVal(yt, 0)}; + + auto index = op1->InitVal(tt->Indices(), nullptr); + auto v = op2->InitVal(yt, nullptr); if ( ! index || ! v ) - return 0; + return nullptr; if ( ! tv->ExpandAndInit(std::move(index), std::move(v)) ) - { - Unref(tv); - return 0; - } + return nullptr; return tv; } @@ -2488,7 +2427,7 @@ Val* AssignExpr::InitVal(const BroType* t, Val* aggr) const else { Error("illegal initializer"); - return 0; + return nullptr; } } @@ -2498,7 +2437,7 @@ bool AssignExpr::IsRecordElement(TypeDecl* td) const { if ( td ) { - const NameExpr* n = (const NameExpr*) op1; + const NameExpr* n = (const NameExpr*) op1.get(); td->type = op2->Type()->Ref(); td->id = copy_string(n->Id()->Name()); } @@ -2514,29 +2453,32 @@ bool AssignExpr::IsPure() const return false; } -IndexSliceAssignExpr::IndexSliceAssignExpr(Expr* op1, Expr* op2, int is_init) - : AssignExpr(op1, op2, is_init) +IndexSliceAssignExpr::IndexSliceAssignExpr(IntrusivePtr op1, + IntrusivePtr op2, int is_init) + : AssignExpr(std::move(op1), std::move(op2), is_init) { } -Val* IndexSliceAssignExpr::Eval(Frame* f) const +IntrusivePtr IndexSliceAssignExpr::Eval(Frame* f) const { if ( is_init ) { RuntimeError("illegal assignment in initialization"); - return 0; + return nullptr; } - Val* v = op2->Eval(f); + auto v = op2->Eval(f); if ( v ) - op1->Assign(f, v); + op1->Assign(f, std::move(v)); - return 0; + return nullptr; } -IndexExpr::IndexExpr(Expr* arg_op1, ListExpr* arg_op2, bool arg_is_slice) -: BinaryExpr(EXPR_INDEX, arg_op1, arg_op2), is_slice(arg_is_slice) +IndexExpr::IndexExpr(IntrusivePtr arg_op1, + IntrusivePtr arg_op2, bool arg_is_slice) + : BinaryExpr(EXPR_INDEX, std::move(arg_op1), std::move(arg_op2)), + is_slice(arg_is_slice) { if ( IsError() ) return; @@ -2549,14 +2491,15 @@ IndexExpr::IndexExpr(Expr* arg_op1, ListExpr* arg_op2, bool arg_is_slice) else if ( IsString(op1->Type()->Tag()) ) { - if ( arg_op2->Exprs().length() != 1 ) + if ( op2->AsListExpr()->Exprs().length() != 1 ) ExprError("invalid string index expression"); } if ( IsError() ) return; - int match_type = op1->Type()->MatchesIndex(arg_op2); + int match_type = op1->Type()->MatchesIndex(op2->AsListExpr()); + if ( match_type == DOES_NOT_MATCH_INDEX ) { std::string error_msg = @@ -2568,20 +2511,20 @@ IndexExpr::IndexExpr(Expr* arg_op1, ListExpr* arg_op2, bool arg_is_slice) else if ( ! op1->Type()->YieldType() ) { if ( IsString(op1->Type()->Tag()) && match_type == MATCHES_INDEX_SCALAR ) - SetType(base_type(TYPE_STRING)); + SetType({AdoptRef{}, base_type(TYPE_STRING)}); else - // It's a set - so indexing it yields void. We don't - // directly generate an error message, though, since this - // expression might be part of an add/delete statement, - // rather than yielding a value. - SetType(base_type(TYPE_VOID)); + // It's a set - so indexing it yields void. We don't + // directly generate an error message, though, since this + // expression might be part of an add/delete statement, + // rather than yielding a value. + SetType({AdoptRef{}, base_type(TYPE_VOID)}); } else if ( match_type == MATCHES_INDEX_SCALAR ) - SetType(op1->Type()->YieldType()->Ref()); + SetType({NewRef{}, op1->Type()->YieldType()}); else if ( match_type == MATCHES_INDEX_VECTOR ) - SetType(new VectorType(op1->Type()->YieldType()->Ref())); + SetType(make_intrusive(op1->Type()->YieldType()->Ref())); else ExprError("Unknown MatchesIndex() return value"); @@ -2610,21 +2553,17 @@ void IndexExpr::Add(Frame* f) if ( IsError() ) return; - Val* v1 = op1->Eval(f); + auto v1 = op1->Eval(f); + if ( ! v1 ) return; - Val* v2 = op2->Eval(f); + auto v2 = op2->Eval(f); + if ( ! v2 ) - { - Unref(v1); return; - } - v1->AsTableVal()->Assign(v2, 0); - - Unref(v1); - Unref(v2); + v1->AsTableVal()->Assign(v2.get(), nullptr); } void IndexExpr::Delete(Frame* f) @@ -2632,53 +2571,46 @@ void IndexExpr::Delete(Frame* f) if ( IsError() ) return; - Val* v1 = op1->Eval(f); + auto v1 = op1->Eval(f); + if ( ! v1 ) return; - Val* v2 = op2->Eval(f); + auto v2 = op2->Eval(f); + if ( ! v2 ) - { - Unref(v1); return; - } - Unref(v1->AsTableVal()->Delete(v2)); - - Unref(v1); - Unref(v2); + Unref(v1->AsTableVal()->Delete(v2.get())); } -Expr* IndexExpr::MakeLvalue() +IntrusivePtr IndexExpr::MakeLvalue() { if ( IsString(op1->Type()->Tag()) ) ExprError("cannot assign to string index expression"); - return new RefExpr(this); + return make_intrusive(IntrusivePtr{NewRef{}, this}); } -Val* IndexExpr::Eval(Frame* f) const +IntrusivePtr IndexExpr::Eval(Frame* f) const { - Val* v1 = op1->Eval(f); + auto v1 = op1->Eval(f); + if ( ! v1 ) - return 0; + return nullptr; + + auto v2 = op2->Eval(f); - Val* v2 = op2->Eval(f); if ( ! v2 ) - { - Unref(v1); - return 0; - } - - Val* result; + return nullptr; Val* indv = v2->AsListVal()->Index(0); + if ( is_vector(indv) ) { VectorVal* v_v1 = v1->AsVectorVal(); VectorVal* v_v2 = indv->AsVectorVal(); - VectorVal* v_result = new VectorVal(Type()->AsVectorType()); - result = v_result; + auto v_result = make_intrusive(Type()->AsVectorType()); // Booleans select each element (or not). if ( IsBool(v_v2->Type()->YieldType()->Tag()) ) @@ -2686,8 +2618,7 @@ Val* IndexExpr::Eval(Frame* f) const if ( v_v1->Size() != v_v2->Size() ) { RuntimeError("size mismatch, boolean index and vector"); - Unref(v_result); - return 0; + return nullptr; } for ( unsigned int i = 0; i < v_v2->Size(); ++i ) @@ -2711,13 +2642,11 @@ Val* IndexExpr::Eval(Frame* f) const v_result->Assign(i, a ? a->Ref() : nullptr); } } + + return v_result; } else - result = Fold(v1, v2); - - Unref(v1); - Unref(v2); - return result; + return Fold(v1.get(), v2.get()); } static int get_slice_index(int idx, int len) @@ -2730,12 +2659,12 @@ static int get_slice_index(int idx, int len) return idx; } -Val* IndexExpr::Fold(Val* v1, Val* v2) const +IntrusivePtr IndexExpr::Fold(Val* v1, Val* v2) const { if ( IsError() ) - return 0; + return nullptr; - Val* v = 0; + IntrusivePtr v; switch ( v1->Type()->Tag() ) { case TYPE_VECTOR: @@ -2744,11 +2673,11 @@ Val* IndexExpr::Fold(Val* v1, Val* v2) const const ListVal* lv = v2->AsListVal(); if ( lv->Length() == 1 ) - v = vect->Lookup(v2); + v = {NewRef{}, vect->Lookup(v2)}; else { int len = vect->Size(); - VectorVal* result = new VectorVal(vect->Type()->AsVectorType()); + auto result = make_intrusive(vect->Type()->AsVectorType()); bro_int_t first = get_slice_index(lv->Index(0)->CoerceToInt(), len); bro_int_t last = get_slice_index(lv->Index(1)->CoerceToInt(), len); @@ -2771,7 +2700,7 @@ Val* IndexExpr::Fold(Val* v1, Val* v2) const break; case TYPE_TABLE: - v = v1->AsTableVal()->Lookup(v2); // Then, we jump into the TableVal here. + v = {NewRef{}, v1->AsTableVal()->Lookup(v2)}; // Then, we jump into the TableVal here. break; case TYPE_STRING: @@ -2803,7 +2732,7 @@ Val* IndexExpr::Fold(Val* v1, Val* v2) const substring = s->GetSubstring(first, substring_len); } - return new StringVal(substring ? substring : new BroString("")); + return make_intrusive(substring ? substring : new BroString("")); } default: @@ -2812,36 +2741,31 @@ Val* IndexExpr::Fold(Val* v1, Val* v2) const } if ( v ) - return v->Ref(); + return v; RuntimeError("no such index"); - return 0; + return nullptr; } -void IndexExpr::Assign(Frame* f, Val* arg_v) +void IndexExpr::Assign(Frame* f, IntrusivePtr v) { - IntrusivePtr v{AdoptRef{}, arg_v}; - if ( IsError() ) return; - Val* v1 = op1->Eval(f); + auto v1 = op1->Eval(f); + if ( ! v1 ) return; - Val* v2 = op2->Eval(f); + auto v2 = op2->Eval(f); if ( ! v1 || ! v2 ) - { - Unref(v1); - Unref(v2); return; - } // Hold an extra reference to 'arg_v' in case the ownership transfer to // the table/vector goes wrong and we still want to obtain diagnostic info // from the original value after the assignment already unref'd. - IntrusivePtr v_extra{NewRef{}, arg_v}; + auto v_extra = v; switch ( v1->Type()->Tag() ) { case TYPE_VECTOR: @@ -2865,9 +2789,9 @@ void IndexExpr::Assign(Frame* f, Val* arg_v) for ( auto idx = 0u; idx < v_vect->Size(); idx++, first++ ) v1_vect->Insert(first, v_vect->Lookup(idx)->Ref()); } - else if ( ! v1_vect->Assign(v2, v.release()) ) + else if ( ! v1_vect->Assign(v2.get(), v.release()) ) { - v = v_extra; + v = std::move(v_extra); if ( v ) { @@ -2887,9 +2811,9 @@ void IndexExpr::Assign(Frame* f, Val* arg_v) } case TYPE_TABLE: - if ( ! v1->AsTableVal()->Assign(v2, v.release()) ) + if ( ! v1->AsTableVal()->Assign(v2.get(), v.release()) ) { - v = v_extra; + v = std::move(v_extra); if ( v ) { @@ -2915,9 +2839,6 @@ void IndexExpr::Assign(Frame* f, Val* arg_v) RuntimeErrorWithCallStack("bad index expression type in assignment"); break; } - - Unref(v1); - Unref(v2); } void IndexExpr::ExprDescribe(ODesc* d) const @@ -2946,13 +2867,10 @@ TraversalCode IndexExpr::Traverse(TraversalCallback* cb) const HANDLE_TC_EXPR_POST(tc); } -FieldExpr::FieldExpr(Expr* arg_op, const char* arg_field_name) -: UnaryExpr(EXPR_FIELD, arg_op) +FieldExpr::FieldExpr(IntrusivePtr arg_op, const char* arg_field_name) + : UnaryExpr(EXPR_FIELD, std::move(arg_op)), + field_name(copy_string(arg_field_name)), td(0), field(0) { - field_name = copy_string(arg_field_name); - td = 0; - field = 0; - if ( IsError() ) return; @@ -2967,7 +2885,7 @@ FieldExpr::FieldExpr(Expr* arg_op, const char* arg_field_name) ExprError("no such field in record"); else { - SetType(rt->FieldType(field)->Ref()); + SetType({NewRef{}, rt->FieldType(field)}); td = rt->FieldDecl(field); if ( rt->IsFieldDeprecated(field) ) @@ -2981,9 +2899,9 @@ FieldExpr::~FieldExpr() delete [] field_name; } -Expr* FieldExpr::MakeLvalue() +IntrusivePtr FieldExpr::MakeLvalue() { - return new RefExpr(this); + return make_intrusive(IntrusivePtr{NewRef{}, this}); } bool FieldExpr::CanDel() const @@ -2991,23 +2909,18 @@ bool FieldExpr::CanDel() const return td->FindAttr(ATTR_DEFAULT) || td->FindAttr(ATTR_OPTIONAL); } -void FieldExpr::Assign(Frame* f, Val* v) +void FieldExpr::Assign(Frame* f, IntrusivePtr v) { if ( IsError() ) - { - Unref(v); return; - } - Val* op_v = op->Eval(f); + auto op_v = op->Eval(f); + if ( op_v ) { RecordVal* r = op_v->AsRecordVal(); - r->Assign(field, v); - Unref(r); + r->Assign(field, v.release()); } - else - Unref(v); } void FieldExpr::Delete(Frame* f) @@ -3015,21 +2928,23 @@ void FieldExpr::Delete(Frame* f) Assign(f, 0); } -Val* FieldExpr::Fold(Val* v) const +IntrusivePtr FieldExpr::Fold(Val* v) const { Val* result = v->AsRecordVal()->Lookup(field); + if ( result ) - return result->Ref(); + return {NewRef{}, result}; // Check for &default. const Attr* def_attr = td ? td->FindAttr(ATTR_DEFAULT) : 0; + if ( def_attr ) - return def_attr->AttrExpr()->Eval(0); + return def_attr->AttrExpr()->Eval(nullptr); else { RuntimeError("field value missing"); assert(false); - return 0; // Will never get here, but compiler can't tell. + return nullptr; // Will never get here, but compiler can't tell. } } @@ -3047,12 +2962,11 @@ void FieldExpr::ExprDescribe(ODesc* d) const d->Add(field); } -HasFieldExpr::HasFieldExpr(Expr* arg_op, const char* arg_field_name) -: UnaryExpr(EXPR_HAS_FIELD, arg_op) +HasFieldExpr::HasFieldExpr(IntrusivePtr arg_op, + const char* arg_field_name) + : UnaryExpr(EXPR_HAS_FIELD, std::move(arg_op)), + field_name(arg_field_name), field(0) { - field_name = arg_field_name; - field = 0; - if ( IsError() ) return; @@ -3068,7 +2982,7 @@ HasFieldExpr::HasFieldExpr(Expr* arg_op, const char* arg_field_name) else if ( rt->IsFieldDeprecated(field) ) reporter->Warning("%s", rt->GetFieldDeprecationWarning(field, true).c_str()); - SetType(base_type(TYPE_BOOL)); + SetType({AdoptRef{}, base_type(TYPE_BOOL)}); } } @@ -3077,20 +2991,10 @@ HasFieldExpr::~HasFieldExpr() delete field_name; } -Val* HasFieldExpr::Fold(Val* v) const +IntrusivePtr HasFieldExpr::Fold(Val* v) const { - RecordVal* rec_to_look_at; - - rec_to_look_at = v->AsRecordVal(); - - if ( ! rec_to_look_at ) - return val_mgr->GetBool(0); - - RecordVal* r = rec_to_look_at->Ref()->AsRecordVal(); - Val* ret = val_mgr->GetBool(r->Lookup(field) != 0); - Unref(r); - - return ret; + auto rv = v->AsRecordVal(); + return {AdoptRef{}, val_mgr->GetBool(rv->Lookup(field))}; } void HasFieldExpr::ExprDescribe(ODesc* d) const @@ -3108,8 +3012,8 @@ void HasFieldExpr::ExprDescribe(ODesc* d) const d->Add(field); } -RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list) -: UnaryExpr(EXPR_RECORD_CONSTRUCTOR, constructor_list) +RecordConstructorExpr::RecordConstructorExpr(IntrusivePtr constructor_list) + : UnaryExpr(EXPR_RECORD_CONSTRUCTOR, std::move(constructor_list)) { if ( IsError() ) return; @@ -3117,7 +3021,7 @@ RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list) // Spin through the list, which should be comprised only of // record-field-assign expressions, and build up a // record type to associate with this constructor. - const expr_list& exprs = constructor_list->Exprs(); + const expr_list& exprs = op->AsListExpr()->Exprs(); type_decl_list* record_types = new type_decl_list(exprs.length()); for ( const auto& e : exprs ) @@ -3135,32 +3039,32 @@ RecordConstructorExpr::RecordConstructorExpr(ListExpr* constructor_list) record_types->push_back(new TypeDecl(field_type, field_name)); } - SetType(new RecordType(record_types)); + SetType(make_intrusive(record_types)); } RecordConstructorExpr::~RecordConstructorExpr() { } -Val* RecordConstructorExpr::InitVal(const BroType* t, Val* aggr) const +IntrusivePtr RecordConstructorExpr::InitVal(const BroType* t, IntrusivePtr aggr) const { - Val* v = Eval(0); + auto v = Eval(nullptr); if ( v ) { RecordVal* rv = v->AsRecordVal(); - RecordVal* ar = rv->CoerceTo(t->AsRecordType(), aggr); - Unref(rv); + IntrusivePtr ar{AdoptRef{}, + rv->CoerceTo(t->AsRecordType(), aggr.get())}; if ( ar ) return ar; } Error("bad record initializer"); - return 0; + return nullptr; } -Val* RecordConstructorExpr::Fold(Val* v) const +IntrusivePtr RecordConstructorExpr::Fold(Val* v) const { ListVal* lv = v->AsListVal(); RecordType* rt = type->AsRecordType(); @@ -3168,7 +3072,7 @@ Val* RecordConstructorExpr::Fold(Val* v) const if ( lv->Length() != rt->NumFields() ) RuntimeErrorWithCallStack("inconsistency evaluating record constructor"); - RecordVal* rv = new RecordVal(rt); + auto rv = make_intrusive(rt); for ( int i = 0; i < lv->Length(); ++i ) rv->Assign(i, lv->Index(i)->Ref()); @@ -3183,12 +3087,12 @@ void RecordConstructorExpr::ExprDescribe(ODesc* d) const d->Add("]"); } -TableConstructorExpr::TableConstructorExpr(ListExpr* constructor_list, - attr_list* arg_attrs, BroType* arg_type) -: UnaryExpr(EXPR_TABLE_CONSTRUCTOR, constructor_list) +TableConstructorExpr::TableConstructorExpr(IntrusivePtr constructor_list, + attr_list* arg_attrs, + IntrusivePtr arg_type) + : UnaryExpr(EXPR_TABLE_CONSTRUCTOR, std::move(constructor_list)), + attrs(nullptr) { - attrs = 0; - if ( IsError() ) return; @@ -3196,20 +3100,20 @@ TableConstructorExpr::TableConstructorExpr(ListExpr* constructor_list, { if ( ! arg_type->IsTable() ) { - Error("bad table constructor type", arg_type); + Error("bad table constructor type", arg_type.get()); SetError(); return; } - SetType(arg_type->Ref()); + SetType(std::move(arg_type)); } else { - if ( constructor_list->Exprs().empty() ) - SetType(new TableType(new TypeList(base_type(TYPE_ANY)), 0)); + if ( op->AsListExpr()->Exprs().empty() ) + SetType(make_intrusive(new TypeList(base_type(TYPE_ANY)), nullptr)); else { - SetType(init_type(constructor_list)); + SetType({AdoptRef{}, init_type(op.get())}); if ( ! type ) SetError(); @@ -3220,10 +3124,10 @@ TableConstructorExpr::TableConstructorExpr(ListExpr* constructor_list, } } - attrs = arg_attrs ? new Attributes(arg_attrs, type, false, false) : 0; + attrs = arg_attrs ? new Attributes(arg_attrs, type.get(), false, false) : 0; type_list* indices = type->AsTableType()->Indices()->Types(); - const expr_list& cle = constructor_list->Exprs(); + const expr_list& cle = op->AsListExpr()->Exprs(); // check and promote all index expressions in ctor list for ( const auto& expr : cle ) @@ -3257,33 +3161,35 @@ TableConstructorExpr::TableConstructorExpr(ListExpr* constructor_list, } } -Val* TableConstructorExpr::Eval(Frame* f) const +IntrusivePtr TableConstructorExpr::Eval(Frame* f) const { if ( IsError() ) - return 0; + return nullptr; - Val* aggr = new TableVal(Type()->AsTableType(), attrs); + auto aggr = make_intrusive(Type()->AsTableType(), attrs); const expr_list& exprs = op->AsListExpr()->Exprs(); for ( const auto& expr : exprs ) - expr->EvalIntoAggregate(type, aggr, f); + expr->EvalIntoAggregate(type.get(), aggr.get(), f); - aggr->AsTableVal()->InitDefaultFunc(f); + aggr->InitDefaultFunc(f); return aggr; } -Val* TableConstructorExpr::InitVal(const BroType* t, Val* aggr) const +IntrusivePtr TableConstructorExpr::InitVal(const BroType* t, IntrusivePtr aggr) const { if ( IsError() ) - return 0; + return nullptr; TableType* tt = Type()->AsTableType(); - TableVal* tval = aggr ? aggr->AsTableVal() : new TableVal(tt, attrs); + auto tval = aggr ? + IntrusivePtr{AdoptRef{}, aggr.release()->AsTableVal()} : + make_intrusive(tt, attrs); const expr_list& exprs = op->AsListExpr()->Exprs(); for ( const auto& expr : exprs ) - expr->EvalIntoAggregate(t, tval, 0); + expr->EvalIntoAggregate(t, tval.get(), 0); return tval; } @@ -3295,12 +3201,12 @@ void TableConstructorExpr::ExprDescribe(ODesc* d) const d->Add(")"); } -SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list, - attr_list* arg_attrs, BroType* arg_type) -: UnaryExpr(EXPR_SET_CONSTRUCTOR, constructor_list) +SetConstructorExpr::SetConstructorExpr(IntrusivePtr constructor_list, + attr_list* arg_attrs, + IntrusivePtr arg_type) + : UnaryExpr(EXPR_SET_CONSTRUCTOR, std::move(constructor_list)), + attrs(nullptr) { - attrs = 0; - if ( IsError() ) return; @@ -3308,19 +3214,19 @@ SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list, { if ( ! arg_type->IsSet() ) { - Error("bad set constructor type", arg_type); + Error("bad set constructor type", arg_type.get()); SetError(); return; } - SetType(arg_type->Ref()); + SetType(std::move(arg_type)); } else { - if ( constructor_list->Exprs().empty() ) - SetType(new ::SetType(new TypeList(base_type(TYPE_ANY)), 0)); + if ( op->AsListExpr()->Exprs().empty() ) + SetType(make_intrusive<::SetType>(new TypeList(base_type(TYPE_ANY)), nullptr)); else - SetType(init_type(constructor_list)); + SetType({AdoptRef{}, init_type(op.get())}); } if ( ! type ) @@ -3329,14 +3235,14 @@ SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list, else if ( type->Tag() != TYPE_TABLE || ! type->AsTableType()->IsSet() ) SetError("values in set(...) constructor do not specify a set"); - attrs = arg_attrs ? new Attributes(arg_attrs, type, false, false) : 0; + attrs = arg_attrs ? new Attributes(arg_attrs, type.get(), false, false) : 0; type_list* indices = type->AsTableType()->Indices()->Types(); - expr_list& cle = constructor_list->Exprs(); + expr_list& cle = op->AsListExpr()->Exprs(); if ( indices->length() == 1 ) { - if ( ! check_and_promote_exprs_to_type(constructor_list, + if ( ! check_and_promote_exprs_to_type(op->AsListExpr(), (*indices)[0]) ) ExprError("inconsistent type in set constructor"); } @@ -3363,45 +3269,44 @@ SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list, } } -Val* SetConstructorExpr::Eval(Frame* f) const +IntrusivePtr SetConstructorExpr::Eval(Frame* f) const { if ( IsError() ) - return 0; + return nullptr; - TableVal* aggr = new TableVal(type->AsTableType(), attrs); + auto aggr = make_intrusive(type->AsTableType(), attrs); const expr_list& exprs = op->AsListExpr()->Exprs(); for ( const auto& expr : exprs ) { - Val* element = expr->Eval(f); - aggr->Assign(element, 0); - Unref(element); + auto element = expr->Eval(f); + aggr->Assign(element.get(), 0); } return aggr; } -Val* SetConstructorExpr::InitVal(const BroType* t, Val* aggr) const +IntrusivePtr SetConstructorExpr::InitVal(const BroType* t, IntrusivePtr aggr) const { if ( IsError() ) - return 0; + return nullptr; const BroType* index_type = t->AsTableType()->Indices(); TableType* tt = Type()->AsTableType(); - TableVal* tval = aggr ? aggr->AsTableVal() : new TableVal(tt, attrs); + auto tval = aggr ? + IntrusivePtr{AdoptRef{}, aggr.release()->AsTableVal()} : + make_intrusive(tt, attrs); const expr_list& exprs = op->AsListExpr()->Exprs(); for ( const auto& e : exprs ) { - Val* element = check_and_promote(e->Eval(0), index_type, 1); + auto element = check_and_promote(e->Eval(nullptr), index_type, 1); - if ( ! element || ! tval->Assign(element, 0) ) + if ( ! element || ! tval->Assign(element.get(), 0) ) { Error(fmt("initialization type mismatch in set"), e); - return 0; + return nullptr; } - - Unref(element); } return tval; @@ -3414,9 +3319,9 @@ void SetConstructorExpr::ExprDescribe(ODesc* d) const d->Add(")"); } -VectorConstructorExpr::VectorConstructorExpr(ListExpr* constructor_list, - BroType* arg_type) -: UnaryExpr(EXPR_VECTOR_CONSTRUCTOR, constructor_list) +VectorConstructorExpr::VectorConstructorExpr(IntrusivePtr constructor_list, + IntrusivePtr arg_type) + : UnaryExpr(EXPR_VECTOR_CONSTRUCTOR, std::move(constructor_list)) { if ( IsError() ) return; @@ -3425,29 +3330,29 @@ VectorConstructorExpr::VectorConstructorExpr(ListExpr* constructor_list, { if ( arg_type->Tag() != TYPE_VECTOR ) { - Error("bad vector constructor type", arg_type); + Error("bad vector constructor type", arg_type.get()); SetError(); return; } - SetType(arg_type->Ref()); + SetType(std::move(arg_type)); } else { - if ( constructor_list->Exprs().empty() ) + if ( op->AsListExpr()->Exprs().empty() ) { // vector(). // By default, assign VOID type here. A vector with // void type set is seen as an unspecified vector. - SetType(new ::VectorType(base_type(TYPE_VOID))); + SetType(make_intrusive<::VectorType>(base_type(TYPE_VOID))); return; } - BroType* t = merge_type_list(constructor_list); + BroType* t = merge_type_list(op->AsListExpr()); if ( t ) { - SetType(new VectorType(t->Ref())); + SetType(make_intrusive(t->Ref())); Unref(t); } else @@ -3457,53 +3362,54 @@ VectorConstructorExpr::VectorConstructorExpr(ListExpr* constructor_list, } } - if ( ! check_and_promote_exprs_to_type(constructor_list, + if ( ! check_and_promote_exprs_to_type(op->AsListExpr(), type->AsVectorType()->YieldType()) ) ExprError("inconsistent types in vector constructor"); } -Val* VectorConstructorExpr::Eval(Frame* f) const +IntrusivePtr VectorConstructorExpr::Eval(Frame* f) const { if ( IsError() ) - return 0; + return nullptr; - VectorVal* vec = new VectorVal(Type()->AsVectorType()); + auto vec = make_intrusive(Type()->AsVectorType()); const expr_list& exprs = op->AsListExpr()->Exprs(); loop_over_list(exprs, i) { Expr* e = exprs[i]; - Val* v = e->Eval(f); - if ( ! vec->Assign(i, v) ) + auto v = e->Eval(f); + + if ( ! vec->Assign(i, v.release()) ) { RuntimeError(fmt("type mismatch at index %d", i)); - return 0; + return nullptr; } } return vec; } -Val* VectorConstructorExpr::InitVal(const BroType* t, Val* aggr) const +IntrusivePtr VectorConstructorExpr::InitVal(const BroType* t, IntrusivePtr aggr) const { if ( IsError() ) - return 0; + return nullptr; VectorType* vt = Type()->AsVectorType(); - VectorVal* vec = aggr ? aggr->AsVectorVal() : new VectorVal(vt); + auto vec = aggr ? + IntrusivePtr{AdoptRef{}, aggr.release()->AsVectorVal()} : + make_intrusive(vt); const expr_list& exprs = op->AsListExpr()->Exprs(); loop_over_list(exprs, i) { Expr* e = exprs[i]; - Val* v = check_and_promote(e->Eval(0), t->YieldType(), 1); + auto v = check_and_promote(e->Eval(nullptr), t->YieldType(), 1); - if ( ! v || ! vec->Assign(i, v) ) + if ( ! v || ! vec->Assign(i, v.release()) ) { Error(fmt("initialization type mismatch at index %d", i), e); - if ( ! aggr ) - Unref(vec); - return 0; + return nullptr; } } @@ -3517,11 +3423,11 @@ void VectorConstructorExpr::ExprDescribe(ODesc* d) const d->Add(")"); } -FieldAssignExpr::FieldAssignExpr(const char* arg_field_name, Expr* value) -: UnaryExpr(EXPR_FIELD_ASSIGN, value), field_name(arg_field_name) +FieldAssignExpr::FieldAssignExpr(const char* arg_field_name, + IntrusivePtr value) + : UnaryExpr(EXPR_FIELD_ASSIGN, std::move(value)), field_name(arg_field_name) { - op->Ref(); - SetType(value->Type()->Ref()); + SetType({NewRef{}, op->Type()}); } void FieldAssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) @@ -3532,7 +3438,7 @@ void FieldAssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) RecordVal* rec = aggr->AsRecordVal(); const RecordType* rt = t->AsRecordType(); - Val* v = op->Eval(f); + auto v = op->Eval(f); if ( v ) { @@ -3542,7 +3448,7 @@ void FieldAssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) reporter->InternalError("Missing record field: %s", field_name.c_str()); - rec->Assign(idx, v); + rec->Assign(idx, v.release()); } } @@ -3565,8 +3471,8 @@ void FieldAssignExpr::ExprDescribe(ODesc* d) const op->Describe(d); } -ArithCoerceExpr::ArithCoerceExpr(Expr* arg_op, TypeTag t) -: UnaryExpr(EXPR_ARITH_COERCE, arg_op) +ArithCoerceExpr::ArithCoerceExpr(IntrusivePtr arg_op, TypeTag t) +: UnaryExpr(EXPR_ARITH_COERCE, std::move(arg_op)) { if ( IsError() ) return; @@ -3576,11 +3482,11 @@ ArithCoerceExpr::ArithCoerceExpr(Expr* arg_op, TypeTag t) if ( IsVector(bt) ) { - SetType(new VectorType(base_type(t))); + SetType(make_intrusive(base_type(t))); vbt = op->Type()->AsVectorType()->YieldType()->Tag(); } else - SetType(base_type(t)); + SetType({AdoptRef{}, base_type(t)}); if ( (bt == TYPE_ENUM) != (t == TYPE_ENUM) ) ExprError("can't convert to/from enumerated type"); @@ -3594,25 +3500,25 @@ ArithCoerceExpr::ArithCoerceExpr(Expr* arg_op, TypeTag t) ExprError("bad coercion value"); } -Val* ArithCoerceExpr::FoldSingleVal(Val* v, InternalTypeTag t) const +IntrusivePtr ArithCoerceExpr::FoldSingleVal(Val* v, InternalTypeTag t) const { switch ( t ) { case TYPE_INTERNAL_DOUBLE: - return new Val(v->CoerceToDouble(), TYPE_DOUBLE); + return make_intrusive(v->CoerceToDouble(), TYPE_DOUBLE); case TYPE_INTERNAL_INT: - return val_mgr->GetInt(v->CoerceToInt()); + return {AdoptRef{}, val_mgr->GetInt(v->CoerceToInt())}; case TYPE_INTERNAL_UNSIGNED: - return val_mgr->GetCount(v->CoerceToUnsigned()); + return {AdoptRef{}, val_mgr->GetCount(v->CoerceToUnsigned())}; default: RuntimeErrorWithCallStack("bad type in CoerceExpr::Fold"); - return 0; + return nullptr; } } -Val* ArithCoerceExpr::Fold(Val* v) const +IntrusivePtr ArithCoerceExpr::Fold(Val* v) const { InternalTypeTag t = type->InternalType(); @@ -3623,18 +3529,20 @@ Val* ArithCoerceExpr::Fold(Val* v) const // the whole vector. Correct the type tag if necessary. if ( type->Tag() == TYPE_VECTOR ) t = Type()->AsVectorType()->YieldType()->InternalType(); + return FoldSingleVal(v, t); } t = Type()->AsVectorType()->YieldType()->InternalType(); VectorVal* vv = v->AsVectorVal(); - VectorVal* result = new VectorVal(Type()->AsVectorType()); + auto result = make_intrusive(Type()->AsVectorType()); + for ( unsigned int i = 0; i < vv->Size(); ++i ) { Val* elt = vv->Lookup(i); if ( elt ) - result->Assign(i, FoldSingleVal(elt, t)); + result->Assign(i, FoldSingleVal(elt, t).release()); else result->Assign(i, 0); } @@ -3642,16 +3550,15 @@ Val* ArithCoerceExpr::Fold(Val* v) const return result; } -RecordCoerceExpr::RecordCoerceExpr(Expr* op, RecordType* r) -: UnaryExpr(EXPR_RECORD_COERCE, op) +RecordCoerceExpr::RecordCoerceExpr(IntrusivePtr arg_op, + IntrusivePtr r) + : UnaryExpr(EXPR_RECORD_COERCE, std::move(arg_op)), + map(nullptr), map_size(0) { - map_size = 0; - map = 0; - if ( IsError() ) return; - SetType(r->Ref()); + SetType(std::move(r)); if ( Type()->Tag() != TYPE_RECORD ) ExprError("coercion to non-record"); @@ -3756,44 +3663,43 @@ RecordCoerceExpr::~RecordCoerceExpr() delete [] map; } -Val* RecordCoerceExpr::InitVal(const BroType* t, Val* aggr) const +IntrusivePtr RecordCoerceExpr::InitVal(const BroType* t, IntrusivePtr aggr) const { - Val* v = Eval(0); + auto v = Eval(nullptr); if ( v ) { RecordVal* rv = v->AsRecordVal(); - RecordVal* ar = rv->CoerceTo(t->AsRecordType(), aggr); - Unref(rv); + IntrusivePtr ar{AdoptRef{}, + rv->CoerceTo(t->AsRecordType(), aggr.release())}; if ( ar ) return ar; } Error("bad record initializer"); - return 0; + return nullptr; } -Val* RecordCoerceExpr::Fold(Val* v) const +IntrusivePtr RecordCoerceExpr::Fold(Val* v) const { - RecordVal* val = new RecordVal(Type()->AsRecordType()); + auto val = make_intrusive(Type()->AsRecordType()); RecordVal* rv = v->AsRecordVal(); for ( int i = 0; i < map_size; ++i ) { if ( map[i] >= 0 ) { - Val* rhs = rv->Lookup(map[i]); + IntrusivePtr rhs{NewRef{}, rv->Lookup(map[i])}; + if ( ! rhs ) { const Attr* def = rv->Type()->AsRecordType()->FieldDecl( map[i])->FindAttr(ATTR_DEFAULT); if ( def ) - rhs = def->AttrExpr()->Eval(0); + rhs = def->AttrExpr()->Eval(nullptr); } - else - rhs = rhs->Ref(); assert(rhs || Type()->AsRecordType()->FieldDecl(i)->FindAttr(ATTR_OPTIONAL)); @@ -3812,30 +3718,22 @@ Val* RecordCoerceExpr::Fold(Val* v) const field_type->Tag() == TYPE_RECORD && ! same_type(rhs_type, field_type) ) { - Val* new_val = rhs->AsRecordVal()->CoerceTo( - field_type->AsRecordType()); + IntrusivePtr new_val{AdoptRef{}, + rhs->AsRecordVal()->CoerceTo(field_type->AsRecordType())}; + if ( new_val ) - { - Unref(rhs); - rhs = new_val; - } + rhs = std::move(new_val); } else if ( BothArithmetic(rhs_type->Tag(), field_type->Tag()) && ! same_type(rhs_type, field_type) ) { - if ( Val* new_val = check_and_promote(rhs, field_type, false, op->GetLocationInfo()) ) - { - // Don't call unref here on rhs because check_and_promote already called it. - rhs = new_val; - } + if ( auto new_val = check_and_promote(rhs, field_type, false, op->GetLocationInfo()) ) + rhs = std::move(new_val); else - { - Unref(val); RuntimeError("Failed type conversion"); - } } - val->Assign(i, rhs); + val->Assign(i, rhs.release()); } else { @@ -3844,7 +3742,7 @@ Val* RecordCoerceExpr::Fold(Val* v) const if ( def ) { - Val* def_val = def->AttrExpr()->Eval(0); + auto def_val = def->AttrExpr()->Eval(nullptr); BroType* def_type = def_val->Type(); BroType* field_type = Type()->AsRecordType()->FieldType(i); @@ -3856,13 +3754,10 @@ Val* RecordCoerceExpr::Fold(Val* v) const field_type->AsRecordType()); if ( tmp ) - { - Unref(def_val); - def_val = tmp; - } + def_val = {AdoptRef{}, tmp}; } - val->Assign(i, def_val); + val->Assign(i, def_val.release()); } else val->Assign(i, 0); @@ -3872,13 +3767,14 @@ Val* RecordCoerceExpr::Fold(Val* v) const return val; } -TableCoerceExpr::TableCoerceExpr(Expr* op, TableType* r) -: UnaryExpr(EXPR_TABLE_COERCE, op) +TableCoerceExpr::TableCoerceExpr(IntrusivePtr arg_op, + IntrusivePtr r) + : UnaryExpr(EXPR_TABLE_COERCE, std::move(arg_op)) { if ( IsError() ) return; - SetType(r->Ref()); + SetType(std::move(r)); if ( Type()->Tag() != TYPE_TABLE ) ExprError("coercion to non-table"); @@ -3892,23 +3788,24 @@ TableCoerceExpr::~TableCoerceExpr() { } -Val* TableCoerceExpr::Fold(Val* v) const +IntrusivePtr TableCoerceExpr::Fold(Val* v) const { TableVal* tv = v->AsTableVal(); if ( tv->Size() > 0 ) RuntimeErrorWithCallStack("coercion of non-empty table/set"); - return new TableVal(Type()->AsTableType(), tv->Attrs()); + return make_intrusive(Type()->AsTableType(), tv->Attrs()); } -VectorCoerceExpr::VectorCoerceExpr(Expr* op, VectorType* v) -: UnaryExpr(EXPR_VECTOR_COERCE, op) +VectorCoerceExpr::VectorCoerceExpr(IntrusivePtr arg_op, + IntrusivePtr v) + : UnaryExpr(EXPR_VECTOR_COERCE, std::move(arg_op)) { if ( IsError() ) return; - SetType(v->Ref()); + SetType(std::move(v)); if ( Type()->Tag() != TYPE_VECTOR ) ExprError("coercion to non-vector"); @@ -3922,41 +3819,43 @@ VectorCoerceExpr::~VectorCoerceExpr() { } -Val* VectorCoerceExpr::Fold(Val* v) const +IntrusivePtr VectorCoerceExpr::Fold(Val* v) const { VectorVal* vv = v->AsVectorVal(); if ( vv->Size() > 0 ) RuntimeErrorWithCallStack("coercion of non-empty vector"); - return new VectorVal(Type()->Ref()->AsVectorType()); + return make_intrusive(Type()->Ref()->AsVectorType()); } -FlattenExpr::FlattenExpr(Expr* arg_op) -: UnaryExpr(EXPR_FLATTEN, arg_op) +FlattenExpr::FlattenExpr(IntrusivePtr arg_op) + : UnaryExpr(EXPR_FLATTEN, std::move(arg_op)) { if ( IsError() ) return; BroType* t = op->Type(); + if ( t->Tag() != TYPE_RECORD ) Internal("bad type in FlattenExpr::FlattenExpr"); RecordType* rt = t->AsRecordType(); num_fields = rt->NumFields(); - TypeList* tl = new TypeList(); + auto tl = make_intrusive(); + for ( int i = 0; i < num_fields; ++i ) tl->Append(rt->FieldType(i)->Ref()); Unref(rt); - SetType(tl); + SetType(std::move(tl)); } -Val* FlattenExpr::Fold(Val* v) const +IntrusivePtr FlattenExpr::Fold(Val* v) const { RecordVal* rv = v->AsRecordVal(); - ListVal* l = new ListVal(TYPE_ANY); + auto l = make_intrusive(TYPE_ANY); for ( int i = 0; i < num_fields; ++i ) { @@ -3971,7 +3870,7 @@ Val* FlattenExpr::Fold(Val* v) const const RecordType* rv_t = rv->Type()->AsRecordType(); const Attr* fa = rv_t->FieldDecl(i)->FindAttr(ATTR_DEFAULT); if ( fa ) - l->Append(fa->AttrExpr()->Eval(0)); + l->Append(fa->AttrExpr()->Eval(nullptr).release()); else RuntimeError("missing field value"); @@ -3981,11 +3880,9 @@ Val* FlattenExpr::Fold(Val* v) const } ScheduleTimer::ScheduleTimer(EventHandlerPtr arg_event, val_list* arg_args, - double t, TimerMgr* arg_tmgr) + double t, TimerMgr* arg_tmgr) : Timer(t, TIMER_SCHEDULE), - event(arg_event), - args(std::move(*arg_args)), - tmgr(arg_tmgr) + event(arg_event), args(std::move(*arg_args)), tmgr(arg_tmgr) { delete arg_args; } @@ -3999,26 +3896,20 @@ void ScheduleTimer::Dispatch(double /* t */, int /* is_expire */) mgr.QueueEvent(event, std::move(args), SOURCE_LOCAL, 0, tmgr); } -ScheduleExpr::ScheduleExpr(Expr* arg_when, EventExpr* arg_event) -: Expr(EXPR_SCHEDULE) +ScheduleExpr::ScheduleExpr(IntrusivePtr arg_when, + IntrusivePtr arg_event) + : Expr(EXPR_SCHEDULE), + when(std::move(arg_when)), event(std::move(arg_event)) { - when = arg_when; - event = arg_event; - if ( IsError() || when->IsError() || event->IsError() ) return; TypeTag bt = when->Type()->Tag(); + if ( bt != TYPE_TIME && bt != TYPE_INTERVAL ) ExprError("schedule expression requires a time or time interval"); else - SetType(base_type(TYPE_TIMER)); - } - -ScheduleExpr::~ScheduleExpr() - { - Unref(when); - Unref(event); + SetType({AdoptRef{}, base_type(TYPE_TIMER)}); } bool ScheduleExpr::IsPure() const @@ -4026,16 +3917,18 @@ bool ScheduleExpr::IsPure() const return false; } -Val* ScheduleExpr::Eval(Frame* f) const +IntrusivePtr ScheduleExpr::Eval(Frame* f) const { if ( terminating ) - return 0; + return nullptr; + + auto when_val = when->Eval(f); - Val* when_val = when->Eval(f); if ( ! when_val ) - return 0; + return nullptr; double dt = when_val->InternalDouble(); + if ( when->Type()->Tag() == TYPE_INTERVAL ) dt += network_time; @@ -4051,9 +3944,7 @@ Val* ScheduleExpr::Eval(Frame* f) const tmgr->Add(new ScheduleTimer(event->Handler(), args, dt, tmgr)); } - Unref(when_val); - - return 0; + return nullptr; } TraversalCode ScheduleExpr::Traverse(TraversalCallback* cb) const @@ -4091,8 +3982,8 @@ void ScheduleExpr::ExprDescribe(ODesc* d) const event->Describe(d); } -InExpr::InExpr(Expr* arg_op1, Expr* arg_op2) -: BinaryExpr(EXPR_IN, arg_op1, arg_op2) +InExpr::InExpr(IntrusivePtr arg_op1, IntrusivePtr arg_op2) + : BinaryExpr(EXPR_IN, std::move(arg_op1), std::move(arg_op2)) { if ( IsError() ) return; @@ -4101,11 +3992,11 @@ InExpr::InExpr(Expr* arg_op1, Expr* arg_op2) { if ( op2->Type()->Tag() != TYPE_STRING ) { - op2->Type()->Error("pattern requires string index", op1); + op2->Type()->Error("pattern requires string index", op1.get()); SetError(); } else - SetType(base_type(TYPE_BOOL)); + SetType({AdoptRef{}, base_type(TYPE_BOOL)}); } else if ( op1->Type()->Tag() == TYPE_RECORD ) @@ -4128,13 +4019,13 @@ InExpr::InExpr(Expr* arg_op1, Expr* arg_op2) SetError(); } else - SetType(base_type(TYPE_BOOL)); + SetType({AdoptRef{}, base_type(TYPE_BOOL)}); } } else if ( op1->Type()->Tag() == TYPE_STRING && op2->Type()->Tag() == TYPE_STRING ) - SetType(base_type(TYPE_BOOL)); + SetType({AdoptRef{}, base_type(TYPE_BOOL)}); else { @@ -4145,40 +4036,37 @@ InExpr::InExpr(Expr* arg_op1, Expr* arg_op2) { if ( op2->Type()->Tag() == TYPE_SUBNET ) { - SetType(base_type(TYPE_BOOL)); + SetType({AdoptRef{}, base_type(TYPE_BOOL)}); return; } if ( op2->Type()->Tag() == TYPE_TABLE && op2->Type()->AsTableType()->IsSubNetIndex() ) { - SetType(base_type(TYPE_BOOL)); + SetType({AdoptRef{}, base_type(TYPE_BOOL)}); return; } } if ( op1->Tag() != EXPR_LIST ) - op1 = new ListExpr(op1); + op1 = make_intrusive(std::move(op1)); ListExpr* lop1 = op1->AsListExpr(); if ( ! op2->Type()->MatchesIndex(lop1) ) SetError("not an index type"); else - { - op1 = lop1; - SetType(base_type(TYPE_BOOL)); - } + SetType({AdoptRef{}, base_type(TYPE_BOOL)}); } } -Val* InExpr::Fold(Val* v1, Val* v2) const +IntrusivePtr InExpr::Fold(Val* v1, Val* v2) const { if ( v1->Type()->Tag() == TYPE_PATTERN ) { RE_Matcher* re = v1->AsPattern(); const BroString* s = v2->AsString(); - return val_mgr->GetBool(re->MatchAnywhere(s) != 0); + return {AdoptRef{}, val_mgr->GetBool(re->MatchAnywhere(s) != 0)}; } if ( v2->Type()->Tag() == TYPE_STRING ) @@ -4187,12 +4075,14 @@ Val* InExpr::Fold(Val* v1, Val* v2) const const BroString* s2 = v2->AsString(); // Could do better here e.g. Boyer-Moore if done repeatedly. - return val_mgr->GetBool(strstr_n(s2->Len(), s2->Bytes(), s1->Len(), reinterpret_cast(s1->CheckString())) != -1); + auto s = reinterpret_cast(s1->CheckString()); + auto res = strstr_n(s2->Len(), s2->Bytes(), s1->Len(), s) != -1; + return {AdoptRef{}, val_mgr->GetBool(res)}; } if ( v1->Type()->Tag() == TYPE_ADDR && v2->Type()->Tag() == TYPE_SUBNET ) - return val_mgr->GetBool(v2->AsSubNetVal()->Contains(v1->AsAddr())); + return {AdoptRef{}, val_mgr->GetBool(v2->AsSubNetVal()->Contains(v1->AsAddr()))}; Val* res; @@ -4201,18 +4091,13 @@ Val* InExpr::Fold(Val* v1, Val* v2) const else res = v2->AsTableVal()->Lookup(v1, false); - if ( res ) - return val_mgr->GetBool(1); - else - return val_mgr->GetBool(0); + return {AdoptRef{}, val_mgr->GetBool(res)}; } -CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args, bool in_hook) -: Expr(EXPR_CALL) +CallExpr::CallExpr(IntrusivePtr arg_func, + IntrusivePtr arg_args, bool in_hook) + : Expr(EXPR_CALL), func(std::move(arg_func)), args(std::move(arg_args)) { - func = arg_func; - args = arg_args; - if ( func->IsError() || args->IsError() ) { SetError(); @@ -4220,6 +4105,7 @@ CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args, bool in_hook) } BroType* func_type = func->Type(); + if ( ! IsFunc(func_type->Tag()) ) { func->Error("not a function"); @@ -4234,7 +4120,7 @@ CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args, bool in_hook) return; } - if ( ! func_type->MatchesIndex(args) ) + if ( ! func_type->MatchesIndex(args.get()) ) SetError("argument type mismatch in function call"); else { @@ -4266,22 +4152,22 @@ CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args, bool in_hook) } } else - SetType(yield->Ref()); + SetType({NewRef{}, yield}); + + // Check for call to built-ins that can be statically analyzed. + IntrusivePtr func_val; - // Check for call to built-ins that can be statically - // analyzed. - Val* func_val; if ( func->Tag() == EXPR_NAME && // This is cheating, but without it processing gets // quite confused regarding "value used but not set" // run-time errors when we apply this analysis during // parsing. Really we should instead do it after we've // parsed the entire set of scripts. - streq(((NameExpr*) func)->Id()->Name(), "fmt") && + streq(((NameExpr*) func.get())->Id()->Name(), "fmt") && // The following is needed because fmt might not yet // be bound as a name. did_builtin_init && - (func_val = func->Eval(0)) ) + (func_val = func->Eval(nullptr)) ) { ::Func* f = func_val->AsFunc(); if ( f->GetKind() == Func::BUILTIN_FUNC && @@ -4291,12 +4177,6 @@ CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args, bool in_hook) } } -CallExpr::~CallExpr() - { - Unref(func); - Unref(args); - } - bool CallExpr::IsPure() const { if ( IsError() ) @@ -4305,7 +4185,8 @@ bool CallExpr::IsPure() const if ( ! func->IsPure() ) return 0; - Val* func_val = func->Eval(0); + auto func_val = func->Eval(nullptr); + if ( ! func_val ) return 0; @@ -4316,17 +4197,17 @@ bool CallExpr::IsPure() const // called here happens to be recursive (either directly // or indirectly). int pure = 0; + if ( f->GetKind() == Func::BUILTIN_FUNC ) pure = f->IsPure() && args->IsPure(); - Unref(func_val); return pure; } -Val* CallExpr::Eval(Frame* f) const +IntrusivePtr CallExpr::Eval(Frame* f) const { if ( IsError() ) - return 0; + return nullptr; // If we are inside a trigger condition, we may have already been // called, delayed, and then produced a result which is now cached. @@ -4343,14 +4224,14 @@ Val* CallExpr::Eval(Frame* f) const DBG_LOG(DBG_NOTIFIERS, "%s: provides cached function result", trigger->Name()); - return v->Ref(); + return {NewRef{}, v}; } } } - Val* ret = 0; - Val* func_val = func->Eval(f); - val_list* v = eval_list(f, args); + IntrusivePtr ret; + auto func_val = func->Eval(f); + val_list* v = eval_list(f, args.get()); if ( func_val && v ) { @@ -4360,7 +4241,7 @@ Val* CallExpr::Eval(Frame* f) const if ( f ) f->SetCall(this); - ret = func->Call(v, f); + ret = {AdoptRef{}, func->Call(v, f)}; if ( f ) f->SetCall(current_call); @@ -4371,8 +4252,6 @@ Val* CallExpr::Eval(Frame* f) const else delete_vals(v); - Unref(func_val); - return ret; } @@ -4405,12 +4284,12 @@ void CallExpr::ExprDescribe(ODesc* d) const } LambdaExpr::LambdaExpr(std::unique_ptr arg_ing, - id_list arg_outer_ids) : Expr(EXPR_LAMBDA) + id_list arg_outer_ids) : Expr(EXPR_LAMBDA) { ingredients = std::move(arg_ing); outer_ids = std::move(arg_outer_ids); - SetType(ingredients->id->Type()->Ref()); + SetType({NewRef{}, ingredients->id->Type()}); // Install a dummy version of the function globally for use only // when broker provides a closure. @@ -4448,22 +4327,22 @@ LambdaExpr::LambdaExpr(std::unique_ptr arg_ing, } // Install that in the global_scope - ID* id = install_ID(my_name.c_str(), current_module.c_str(), true, false); + auto id = install_ID(my_name.c_str(), current_module.c_str(), true, false); // Update lamb's name dummy_func->SetName(my_name.c_str()); - Val* v = new Val(dummy_func); + auto v = make_intrusive(dummy_func); Unref(dummy_func); - id->SetVal(v); // id will unref v when its done. - id->SetType(ingredients->id->Type()->Ref()); + id->SetVal(std::move(v)); + id->SetType({NewRef{}, ingredients->id->Type()}); id->SetConst(); } -Val* LambdaExpr::Eval(Frame* f) const +IntrusivePtr LambdaExpr::Eval(Frame* f) const { ::Ref(ingredients->body); - BroFunc* lamb = new BroFunc( + auto lamb = make_intrusive( ingredients->id, ingredients->body, ingredients->inits, @@ -4476,9 +4355,7 @@ Val* LambdaExpr::Eval(Frame* f) const // Allows for lookups by the receiver. lamb->SetName(my_name.c_str()); - auto rval = new Val(lamb); - Unref(lamb); - return rval; + return make_intrusive(lamb.get()); } void LambdaExpr::ExprDescribe(ODesc* d) const @@ -4499,13 +4376,11 @@ TraversalCode LambdaExpr::Traverse(TraversalCallback* cb) const HANDLE_TC_EXPR_POST(tc); } -EventExpr::EventExpr(const char* arg_name, ListExpr* arg_args) -: Expr(EXPR_EVENT) +EventExpr::EventExpr(const char* arg_name, IntrusivePtr arg_args) + : Expr(EXPR_EVENT), name(arg_name), args(std::move(arg_args)) { - name = arg_name; - args = arg_args; - EventHandler* h = event_registry->Lookup(name); + if ( ! h ) { h = new EventHandler(name.c_str()); @@ -4530,7 +4405,7 @@ EventExpr::EventExpr(const char* arg_name, ListExpr* arg_args) return; } - if ( ! func_type->MatchesIndex(args) ) + if ( ! func_type->MatchesIndex(args.get()) ) SetError("argument type mismatch in event invocation"); else { @@ -4542,21 +4417,16 @@ EventExpr::EventExpr(const char* arg_name, ListExpr* arg_args) } } -EventExpr::~EventExpr() - { - Unref(args); - } - -Val* EventExpr::Eval(Frame* f) const +IntrusivePtr EventExpr::Eval(Frame* f) const { if ( IsError() ) - return 0; + return nullptr; - val_list* v = eval_list(f, args); + val_list* v = eval_list(f, args.get()); mgr.QueueEvent(handler, std::move(*v)); delete v; - return 0; + return nullptr; } TraversalCode EventExpr::Traverse(TraversalCallback* cb) const @@ -4586,13 +4456,13 @@ void EventExpr::ExprDescribe(ODesc* d) const ListExpr::ListExpr() : Expr(EXPR_LIST) { - SetType(new TypeList()); + SetType(make_intrusive()); } -ListExpr::ListExpr(Expr* e) : Expr(EXPR_LIST) +ListExpr::ListExpr(IntrusivePtr e) : Expr(EXPR_LIST) { - SetType(new TypeList()); - Append(e); + SetType(make_intrusive()); + Append(std::move(e)); } ListExpr::~ListExpr() @@ -4601,10 +4471,10 @@ ListExpr::~ListExpr() Unref(expr); } -void ListExpr::Append(Expr* e) +void ListExpr::Append(IntrusivePtr e) { - exprs.push_back(e); - ((TypeList*) type)->Append(e->Type()->Ref()); + exprs.push_back(e.release()); + ((TypeList*) type.get())->Append(exprs.back()->Type()->Ref()); } bool ListExpr::IsPure() const @@ -4625,32 +4495,32 @@ bool ListExpr::AllConst() const return true; } -Val* ListExpr::Eval(Frame* f) const +IntrusivePtr ListExpr::Eval(Frame* f) const { - ListVal* v = new ListVal(TYPE_ANY); + auto v = make_intrusive(TYPE_ANY); for ( const auto& expr : exprs ) { - Val* ev = expr->Eval(f); + auto ev = expr->Eval(f); + if ( ! ev ) { RuntimeError("uninitialized list value"); - Unref(v); - return 0; + return nullptr; } - v->Append(ev); + v->Append(ev.release()); } return v; } -BroType* ListExpr::InitType() const +IntrusivePtr ListExpr::InitType() const { if ( exprs.empty() ) { Error("empty list in untyped initialization"); - return 0; + return nullptr; } if ( exprs[0]->IsRecordElement(0) ) @@ -4664,19 +4534,20 @@ BroType* ListExpr::InitType() const expr->Error("record element expected"); delete td; delete types; - return 0; + return nullptr; } types->push_back(td); } - return new RecordType(types); + return make_intrusive(types); } else { - TypeList* tl = new TypeList(); + auto tl = make_intrusive(); + for ( const auto& e : exprs ) { BroType* ti = e->Type(); @@ -4702,40 +4573,37 @@ BroType* ListExpr::InitType() const } } -Val* ListExpr::InitVal(const BroType* t, Val* aggr) const +IntrusivePtr ListExpr::InitVal(const BroType* t, IntrusivePtr aggr) const { // While fairly similar to the EvalIntoAggregate() code, // we keep this separate since it also deals with initialization // idioms such as embedded aggregates and cross-product // expansion. if ( IsError() ) - return 0; + return nullptr; // Check whether each element of this list itself matches t, // in which case we should expand as a ListVal. if ( ! aggr && type->AsTypeList()->AllMatch(t, 1) ) { - ListVal* v = new ListVal(TYPE_ANY); - + auto v = make_intrusive(TYPE_ANY); const type_list* tl = type->AsTypeList()->Types(); + if ( exprs.length() != tl->length() ) { Error("index mismatch", t); - Unref(v); - return 0; + return nullptr; } loop_over_list(exprs, i) { - Val* vi = exprs[i]->InitVal((*tl)[i], 0); + auto vi = exprs[i]->InitVal((*tl)[i], nullptr); if ( ! vi ) - { - Unref(v); - return 0; - } + return nullptr; - v->Append(vi); + v->Append(vi.release()); } + return v; } @@ -4744,27 +4612,29 @@ Val* ListExpr::InitVal(const BroType* t, Val* aggr) const if ( aggr ) { Error("bad use of list in initialization", t); - return 0; + return nullptr; } const type_list* tl = t->AsTypeList()->Types(); + if ( exprs.length() != tl->length() ) { Error("index mismatch", t); - return 0; + return nullptr; } - ListVal* v = new ListVal(TYPE_ANY); + auto v = make_intrusive(TYPE_ANY); + loop_over_list(exprs, i) { - Val* vi = exprs[i]->InitVal((*tl)[i], 0); + auto vi = exprs[i]->InitVal((*tl)[i], nullptr); + if ( ! vi ) - { - Unref(v); - return 0; - } - v->Append(vi); + return nullptr; + + v->Append(vi.release()); } + return v; } @@ -4777,7 +4647,7 @@ Val* ListExpr::InitVal(const BroType* t, Val* aggr) const else { Error("aggregate initializer for scalar type", t); - return 0; + return nullptr; } } @@ -4785,7 +4655,7 @@ Val* ListExpr::InitVal(const BroType* t, Val* aggr) const Internal("missing aggregate in ListExpr::InitVal"); if ( t->IsSet() ) - return AddSetInit(t, aggr); + return AddSetInit(t, std::move(aggr)); if ( t->Tag() == TYPE_VECTOR ) { @@ -4796,11 +4666,12 @@ Val* ListExpr::InitVal(const BroType* t, Val* aggr) const { Expr* e = exprs[i]; check_and_promote_expr(e, vec->Type()->AsVectorType()->YieldType()); - Val* v = e->Eval(0); - if ( ! vec->Assign(i, v) ) + auto v = e->Eval(nullptr); + + if ( ! vec->Assign(i, v.release()) ) { e->Error(fmt("type mismatch at index %d", i)); - return 0; + return nullptr; } } @@ -4817,32 +4688,33 @@ Val* ListExpr::InitVal(const BroType* t, Val* aggr) const if ( e->Tag() == EXPR_ASSIGN || e->Tag() == EXPR_FIELD_ASSIGN ) { if ( ! e->InitVal(t, aggr) ) - return 0; + return nullptr; } else { if ( t->Tag() == TYPE_RECORD ) { e->Error("bad record initializer", t); - return 0; + return nullptr; } - Val* v = e->Eval(0); + auto v = e->Eval(nullptr); + if ( ! same_type(v->Type(), t) ) { v->Type()->Error("type clash in table initializer", t); - return 0; + return nullptr; } if ( ! v->AsTableVal()->AddTo(aggr->AsTableVal(), 1) ) - return 0; + return nullptr; } } return aggr; } -Val* ListExpr::AddSetInit(const BroType* t, Val* aggr) const +IntrusivePtr ListExpr::AddSetInit(const BroType* t, IntrusivePtr aggr) const { if ( aggr->Type()->Tag() != TYPE_TABLE ) Internal("bad aggregate in ListExpr::InitVal"); @@ -4853,50 +4725,47 @@ Val* ListExpr::AddSetInit(const BroType* t, Val* aggr) const for ( const auto& expr : exprs ) { - Val* element; + IntrusivePtr element; if ( expr->Type()->IsSet() ) // A set to flatten. - element = expr->Eval(0); + element = expr->Eval(nullptr); else if ( expr->Type()->Tag() == TYPE_LIST ) - element = expr->InitVal(it, 0); + element = expr->InitVal(it, nullptr); else - element = expr->InitVal((*it->Types())[0], 0); + element = expr->InitVal((*it->Types())[0], nullptr); if ( ! element ) - return 0; + return nullptr; if ( element->Type()->IsSet() ) { if ( ! same_type(element->Type(), t) ) { element->Error("type clash in set initializer", t); - return 0; + return nullptr; } if ( ! element->AsTableVal()->AddTo(tv, 1) ) - return 0; + return nullptr; continue; } if ( expr->Type()->Tag() == TYPE_LIST ) - element = check_and_promote(element, it, 1); + element = check_and_promote(std::move(element), it, 1); else - element = check_and_promote(element, (*it->Types())[0], 1); + element = check_and_promote(std::move(element), (*it->Types())[0], 1); if ( ! element ) - return 0; + return nullptr; - if ( ! tv->ExpandAndInit({AdoptRef{}, element}, 0) ) - { - Unref(tv); - return 0; - } + if ( ! tv->ExpandAndInit(std::move(element), nullptr) ) + return nullptr; } - return tv; + return aggr; } void ListExpr::ExprDescribe(ODesc* d) const @@ -4912,16 +4781,16 @@ void ListExpr::ExprDescribe(ODesc* d) const } } -Expr* ListExpr::MakeLvalue() +IntrusivePtr ListExpr::MakeLvalue() { for ( const auto & expr : exprs ) if ( expr->Tag() != EXPR_NAME ) ExprError("can only assign to list of identifiers"); - return new RefExpr(this); + return make_intrusive(IntrusivePtr{NewRef{}, this}); } -void ListExpr::Assign(Frame* f, Val* v) +void ListExpr::Assign(Frame* f, IntrusivePtr v) { ListVal* lv = v->AsListVal(); @@ -4929,9 +4798,7 @@ void ListExpr::Assign(Frame* f, Val* v) RuntimeError("mismatch in list lengths"); loop_over_list(exprs, i) - exprs[i]->Assign(f, (*lv->Vals())[i]->Ref()); - - Unref(v); + exprs[i]->Assign(f, {NewRef{}, (*lv->Vals())[i]}); } TraversalCode ListExpr::Traverse(TraversalCallback* cb) const @@ -4949,7 +4816,8 @@ TraversalCode ListExpr::Traverse(TraversalCallback* cb) const HANDLE_TC_EXPR_POST(tc); } -RecordAssignExpr::RecordAssignExpr(Expr* record, Expr* init_list, int is_init) +RecordAssignExpr::RecordAssignExpr(IntrusivePtr record, + IntrusivePtr init_list, int is_init) { const expr_list& inits = init_list->AsListExpr()->Exprs(); @@ -4974,9 +4842,9 @@ RecordAssignExpr::RecordAssignExpr(Expr* record, Expr* init_list, int is_init) if ( field >= 0 && same_type(lhs->FieldType(field), t->FieldType(j)) ) { - FieldExpr* fe_lhs = new FieldExpr(record, field_name); - FieldExpr* fe_rhs = new FieldExpr(init, field_name); - Append(get_assign_expr(fe_lhs->Ref(), fe_rhs->Ref(), is_init)); + auto fe_lhs = make_intrusive(record, field_name); + auto fe_rhs = make_intrusive(IntrusivePtr{NewRef{}, init}, field_name); + Append(get_assign_expr(std::move(fe_lhs), std::move(fe_rhs), is_init)); } } } @@ -4989,9 +4857,9 @@ RecordAssignExpr::RecordAssignExpr(Expr* record, Expr* init_list, int is_init) const char* field_name = ""; // rf->FieldName(); if ( lhs->HasField(field_name) ) { - FieldExpr* fe_lhs = new FieldExpr(record, field_name); - Expr* fe_rhs = rf->Op(); - Append(get_assign_expr(fe_lhs->Ref(), fe_rhs, is_init)); + auto fe_lhs = make_intrusive(record, field_name); + IntrusivePtr fe_rhs = {NewRef{}, rf->Op()}; + Append(get_assign_expr(std::move(fe_lhs), std::move(fe_rhs), is_init)); } else { @@ -5010,34 +4878,31 @@ RecordAssignExpr::RecordAssignExpr(Expr* record, Expr* init_list, int is_init) } } -CastExpr::CastExpr(Expr* arg_op, BroType* t) : UnaryExpr(EXPR_CAST, arg_op) +CastExpr::CastExpr(IntrusivePtr arg_op, IntrusivePtr t) + : UnaryExpr(EXPR_CAST, std::move(arg_op)) { auto stype = Op()->Type(); - ::Ref(t); - SetType(t); + SetType(std::move(t)); - if ( ! can_cast_value_to_type(stype, t) ) + if ( ! can_cast_value_to_type(stype, Type()) ) ExprError("cast not supported"); } -Val* CastExpr::Eval(Frame* f) const +IntrusivePtr CastExpr::Eval(Frame* f) const { if ( IsError() ) - return 0; + return nullptr; - Val* v = op->Eval(f); + auto v = op->Eval(f); if ( ! v ) - return 0; + return nullptr; - Val* nv = cast_value_to_type(v, Type()); + auto nv = cast_value_to_type(v.get(), Type()); if ( nv ) - { - Unref(v); return nv; - } ODesc d; d.Add("invalid cast of value with type '"); @@ -5050,9 +4915,8 @@ Val* CastExpr::Eval(Frame* f) const ! v->AsRecordVal()->Lookup(0) ) d.Add(" (nil $data field)"); - Unref(v); RuntimeError(d.Description()); - return 0; // not reached. + return nullptr; // not reached. } void CastExpr::ExprDescribe(ODesc* d) const @@ -5062,28 +4926,18 @@ void CastExpr::ExprDescribe(ODesc* d) const Type()->Describe(d); } -IsExpr::IsExpr(Expr* arg_op, BroType* arg_t) : UnaryExpr(EXPR_IS, arg_op) +IsExpr::IsExpr(IntrusivePtr arg_op, IntrusivePtr arg_t) + : UnaryExpr(EXPR_IS, std::move(arg_op)), t(std::move(arg_t)) { - t = arg_t; - ::Ref(t); - - SetType(base_type(TYPE_BOOL)); + SetType({AdoptRef{}, base_type(TYPE_BOOL)}); } -IsExpr::~IsExpr() - { - Unref(t); - } - -Val* IsExpr::Fold(Val* v) const +IntrusivePtr IsExpr::Fold(Val* v) const { if ( IsError() ) - return 0; + return nullptr; - if ( can_cast_value_to_type(v, t) ) - return val_mgr->GetBool(1); - else - return val_mgr->GetBool(0); + return {AdoptRef{}, val_mgr->GetBool(can_cast_value_to_type(v, t.get()))}; } void IsExpr::ExprDescribe(ODesc* d) const @@ -5093,15 +4947,21 @@ void IsExpr::ExprDescribe(ODesc* d) const t->Describe(d); } -Expr* get_assign_expr(Expr* op1, Expr* op2, int is_init) +IntrusivePtr get_assign_expr(IntrusivePtr op1, + IntrusivePtr op2, int is_init) { if ( op1->Type()->Tag() == TYPE_RECORD && op2->Type()->Tag() == TYPE_LIST ) - return new RecordAssignExpr(op1, op2, is_init); + return make_intrusive(std::move(op1), std::move(op2), + is_init); + else if ( op1->Tag() == EXPR_INDEX && op1->AsIndexExpr()->IsSlice() ) - return new IndexSliceAssignExpr(op1, op2, is_init); + return make_intrusive(std::move(op1), + std::move(op2), is_init); + else - return new AssignExpr(op1, op2, is_init); + return make_intrusive(std::move(op1), std::move(op2), + is_init); } int check_and_promote_expr(Expr*& e, BroType* t) @@ -5131,7 +4991,7 @@ int check_and_promote_expr(Expr*& e, BroType* t) return 0; } - e = new ArithCoerceExpr(e, t_tag); + e = new ArithCoerceExpr({AdoptRef{}, e}, t_tag); return 1; } @@ -5156,7 +5016,7 @@ int check_and_promote_expr(Expr*& e, BroType* t) if ( record_promotion_compatible(t_r, et_r) ) { - e = new RecordCoerceExpr(e, t_r); + e = new RecordCoerceExpr({AdoptRef{}, e}, {NewRef{}, t_r}); return 1; } @@ -5170,14 +5030,14 @@ int check_and_promote_expr(Expr*& e, BroType* t) if ( t->Tag() == TYPE_TABLE && et->Tag() == TYPE_TABLE && et->AsTableType()->IsUnspecifiedTable() ) { - e = new TableCoerceExpr(e, t->AsTableType()); + e = new TableCoerceExpr({AdoptRef{}, e}, {NewRef{}, t->AsTableType()}); return 1; } if ( t->Tag() == TYPE_VECTOR && et->Tag() == TYPE_VECTOR && et->AsVectorType()->IsUnspecifiedVector() ) { - e = new VectorCoerceExpr(e, t->AsVectorType()); + e = new VectorCoerceExpr({AdoptRef{}, e}, {NewRef{}, t->AsVectorType()}); return 1; } @@ -5289,25 +5149,28 @@ val_list* eval_list(Frame* f, const ListExpr* l) { const expr_list& e = l->Exprs(); val_list* v = new val_list(e.length()); - bool success = true; + for ( const auto& expr : e ) { - Val* ev = expr->Eval(f); + auto ev = expr->Eval(f); + if ( ! ev ) { success = false; break; } - v->push_back(ev); + + v->push_back(ev.release()); } if ( ! success ) - { // Failure. + { for ( const auto& val : *v ) Unref(val); + delete v; - return 0; + return nullptr; } else diff --git a/src/Expr.h b/src/Expr.h index ed9049652c..5874330306 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -2,9 +2,8 @@ #pragma once -// BRO expressions. - #include "BroList.h" +#include "IntrusivePtr.h" #include "Timer.h" #include "Type.h" #include "EventHandler.h" @@ -58,6 +57,7 @@ enum BroExprTag : int { extern const char* expr_name(BroExprTag t); +template class IntrusivePtr; class Stmt; class Frame; class ListExpr; @@ -72,16 +72,14 @@ struct function_ingredients; class Expr : public BroObj { public: - BroType* Type() const { return type; } + BroType* Type() const { return type.get(); } BroExprTag Tag() const { return tag; } - ~Expr() override; - Expr* Ref() { ::Ref(this); return this; } // Evaluates the expression and returns a corresponding Val*, // or nil if the expression's value isn't fixed. - virtual Val* Eval(Frame* f) const = 0; + virtual IntrusivePtr Eval(Frame* f) const = 0; // Same, but the context is that we are adding an element // into the given aggregate of the given type. Note that @@ -91,12 +89,11 @@ public: const; // Assign to the given value, if appropriate. - virtual void Assign(Frame* f, Val* v); + virtual void Assign(Frame* f, IntrusivePtr v); // Returns the type corresponding to this expression interpreted - // as an initialization. The type should be Unref()'d when done - // using it. Returns nil if the initialization is illegal. - virtual BroType* InitType() const; + // as an initialization. Returns nil if the initialization is illegal. + virtual IntrusivePtr InitType() const; // Returns true if this expression, interpreted as an initialization, // constitutes a record element, false otherwise. If the TypeDecl* @@ -109,7 +106,7 @@ public: // with the given type. If "aggr" is non-nil, then this expression // is an element of the given aggregate, and it is added to it // accordingly. - virtual Val* InitVal(const BroType* t, Val* aggr) const; + virtual IntrusivePtr InitVal(const BroType* t, IntrusivePtr aggr) const; // True if the expression has no side effects, false otherwise. virtual bool IsPure() const; @@ -145,7 +142,7 @@ public: // Return the expression converted to L-value form. If expr // cannot be used as an L-value, reports an error and returns // the current value of expr (this is the default method). - virtual Expr* MakeLvalue(); + virtual IntrusivePtr MakeLvalue(); // Marks the expression as one requiring (or at least appearing // with) parentheses. Used for pretty-printing. @@ -214,7 +211,7 @@ protected: // Puts the expression in canonical form. virtual void Canonicize(); - void SetType(BroType* t); + void SetType(IntrusivePtr t); // Reports the given error and sets the expression's type to // TYPE_ERROR. @@ -225,21 +222,19 @@ protected: void RuntimeErrorWithCallStack(const std::string& msg) const; BroExprTag tag; - BroType* type = nullptr; - + IntrusivePtr type; bool paren; }; class NameExpr : public Expr { public: - explicit NameExpr(ID* id, bool const_init = false); - ~NameExpr() override; + explicit NameExpr(IntrusivePtr id, bool const_init = false); - ID* Id() const { return id; } + ID* Id() const { return id.get(); } - Val* Eval(Frame* f) const override; - void Assign(Frame* f, Val* v) override; - Expr* MakeLvalue() override; + IntrusivePtr Eval(Frame* f) const override; + void Assign(Frame* f, IntrusivePtr v) override; + IntrusivePtr MakeLvalue() override; bool IsPure() const override; TraversalCode Traverse(TraversalCallback* cb) const override; @@ -247,91 +242,89 @@ public: protected: void ExprDescribe(ODesc* d) const override; - ID* id; + IntrusivePtr id; bool in_const_init; }; class ConstExpr : public Expr { public: - explicit ConstExpr(Val* val); - ~ConstExpr() override; + explicit ConstExpr(IntrusivePtr val); - Val* Value() const { return val; } + Val* Value() const { return val.get(); } - Val* Eval(Frame* f) const override; + IntrusivePtr Eval(Frame* f) const override; TraversalCode Traverse(TraversalCallback* cb) const override; protected: void ExprDescribe(ODesc* d) const override; - Val* val; + IntrusivePtr val; }; class UnaryExpr : public Expr { public: - Expr* Op() const { return op; } + Expr* Op() const { return op.get(); } // UnaryExpr::Eval correctly handles vector types. Any child // class that overrides Eval() should be modified to handle // vectors correctly as necessary. - Val* Eval(Frame* f) const override; + IntrusivePtr Eval(Frame* f) const override; bool IsPure() const override; TraversalCode Traverse(TraversalCallback* cb) const override; protected: - UnaryExpr(BroExprTag arg_tag, Expr* arg_op); - ~UnaryExpr() override; + UnaryExpr(BroExprTag arg_tag, IntrusivePtr arg_op); void ExprDescribe(ODesc* d) const override; // Returns the expression folded using the given constant. - virtual Val* Fold(Val* v) const; + virtual IntrusivePtr Fold(Val* v) const; - Expr* op; + IntrusivePtr op; }; class BinaryExpr : public Expr { public: - Expr* Op1() const { return op1; } - Expr* Op2() const { return op2; } + Expr* Op1() const { return op1.get(); } + Expr* Op2() const { return op2.get(); } bool IsPure() const override; // BinaryExpr::Eval correctly handles vector types. Any child // class that overrides Eval() should be modified to handle // vectors correctly as necessary. - Val* Eval(Frame* f) const override; + IntrusivePtr Eval(Frame* f) const override; TraversalCode Traverse(TraversalCallback* cb) const override; protected: - BinaryExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2) - : Expr(arg_tag), op1(arg_op1), op2(arg_op2) + BinaryExpr(BroExprTag arg_tag, + IntrusivePtr arg_op1, IntrusivePtr arg_op2) + : Expr(arg_tag), op1(std::move(arg_op1)), op2(std::move(arg_op2)) { - if ( ! (arg_op1 && arg_op2) ) + if ( ! (op1 && op2) ) return; if ( op1->IsError() || op2->IsError() ) SetError(); } - ~BinaryExpr() override; // Returns the expression folded using the given constants. - virtual Val* Fold(Val* v1, Val* v2) const; + virtual IntrusivePtr Fold(Val* v1, Val* v2) const; // Same for when the constants are strings. - virtual Val* StringFold(Val* v1, Val* v2) const; + virtual IntrusivePtr StringFold(Val* v1, Val* v2) const; // Same for when the constants are patterns. - virtual Val* PatternFold(Val* v1, Val* v2) const; + virtual IntrusivePtr PatternFold(Val* v1, Val* v2) const; // Same for when the constants are sets. - virtual Val* SetFold(Val* v1, Val* v2) const; + virtual IntrusivePtr SetFold(Val* v1, Val* v2) const; // Same for when the constants are addresses or subnets. - virtual Val* AddrFold(Val* v1, Val* v2) const; - virtual Val* SubNetFold(Val* v1, Val* v2) const; + virtual IntrusivePtr AddrFold(Val* v1, Val* v2) const; + virtual IntrusivePtr SubNetFold(Val* v1, Val* v2) const; int BothConst() const { return op1->IsConst() && op2->IsConst(); } @@ -347,149 +340,148 @@ protected: void ExprDescribe(ODesc* d) const override; - Expr* op1; - Expr* op2; + IntrusivePtr op1; + IntrusivePtr op2; }; class CloneExpr : public UnaryExpr { public: - explicit CloneExpr(Expr* op); - Val* Eval(Frame* f) const override; + explicit CloneExpr(IntrusivePtr op); + IntrusivePtr Eval(Frame* f) const override; protected: - Val* Fold(Val* v) const override; + IntrusivePtr Fold(Val* v) const override; }; class IncrExpr : public UnaryExpr { public: - IncrExpr(BroExprTag tag, Expr* op); + IncrExpr(BroExprTag tag, IntrusivePtr op); - Val* Eval(Frame* f) const override; - Val* DoSingleEval(Frame* f, Val* v) const; + IntrusivePtr Eval(Frame* f) const override; + IntrusivePtr DoSingleEval(Frame* f, Val* v) const; bool IsPure() const override; }; class ComplementExpr : public UnaryExpr { public: - explicit ComplementExpr(Expr* op); + explicit ComplementExpr(IntrusivePtr op); protected: - Val* Fold(Val* v) const override; + IntrusivePtr Fold(Val* v) const override; }; class NotExpr : public UnaryExpr { public: - explicit NotExpr(Expr* op); + explicit NotExpr(IntrusivePtr op); protected: - Val* Fold(Val* v) const override; + IntrusivePtr Fold(Val* v) const override; }; class PosExpr : public UnaryExpr { public: - explicit PosExpr(Expr* op); + explicit PosExpr(IntrusivePtr op); protected: - Val* Fold(Val* v) const override; + IntrusivePtr Fold(Val* v) const override; }; class NegExpr : public UnaryExpr { public: - explicit NegExpr(Expr* op); + explicit NegExpr(IntrusivePtr op); protected: - Val* Fold(Val* v) const override; + IntrusivePtr Fold(Val* v) const override; }; class SizeExpr : public UnaryExpr { public: - explicit SizeExpr(Expr* op); - Val* Eval(Frame* f) const override; + explicit SizeExpr(IntrusivePtr op); + IntrusivePtr Eval(Frame* f) const override; protected: - Val* Fold(Val* v) const override; + IntrusivePtr Fold(Val* v) const override; }; class AddExpr : public BinaryExpr { public: - AddExpr(Expr* op1, Expr* op2); + AddExpr(IntrusivePtr op1, IntrusivePtr op2); void Canonicize() override; }; class AddToExpr : public BinaryExpr { public: - AddToExpr(Expr* op1, Expr* op2); - Val* Eval(Frame* f) const override; + AddToExpr(IntrusivePtr op1, IntrusivePtr op2); + IntrusivePtr Eval(Frame* f) const override; }; class RemoveFromExpr : public BinaryExpr { public: - RemoveFromExpr(Expr* op1, Expr* op2); - Val* Eval(Frame* f) const override; + RemoveFromExpr(IntrusivePtr op1, IntrusivePtr op2); + IntrusivePtr Eval(Frame* f) const override; }; class SubExpr : public BinaryExpr { public: - SubExpr(Expr* op1, Expr* op2); + SubExpr(IntrusivePtr op1, IntrusivePtr op2); }; class TimesExpr : public BinaryExpr { public: - TimesExpr(Expr* op1, Expr* op2); + TimesExpr(IntrusivePtr op1, IntrusivePtr op2); void Canonicize() override; }; class DivideExpr : public BinaryExpr { public: - DivideExpr(Expr* op1, Expr* op2); + DivideExpr(IntrusivePtr op1, IntrusivePtr op2); protected: - Val* AddrFold(Val* v1, Val* v2) const override; + IntrusivePtr AddrFold(Val* v1, Val* v2) const override; }; class ModExpr : public BinaryExpr { public: - ModExpr(Expr* op1, Expr* op2); + ModExpr(IntrusivePtr op1, IntrusivePtr op2); }; class BoolExpr : public BinaryExpr { public: - BoolExpr(BroExprTag tag, Expr* op1, Expr* op2); + BoolExpr(BroExprTag tag, IntrusivePtr op1, IntrusivePtr op2); - Val* Eval(Frame* f) const override; - Val* DoSingleEval(Frame* f, Val* v1, Expr* op2) const; + IntrusivePtr Eval(Frame* f) const override; + IntrusivePtr DoSingleEval(Frame* f, IntrusivePtr v1, Expr* op2) const; }; class BitExpr : public BinaryExpr { public: - BitExpr(BroExprTag tag, Expr* op1, Expr* op2); + BitExpr(BroExprTag tag, IntrusivePtr op1, IntrusivePtr op2); }; class EqExpr : public BinaryExpr { public: - EqExpr(BroExprTag tag, Expr* op1, Expr* op2); + EqExpr(BroExprTag tag, IntrusivePtr op1, IntrusivePtr op2); void Canonicize() override; protected: - Val* Fold(Val* v1, Val* v2) const override; + IntrusivePtr Fold(Val* v1, Val* v2) const override; }; class RelExpr : public BinaryExpr { public: - RelExpr(BroExprTag tag, Expr* op1, Expr* op2); + RelExpr(BroExprTag tag, IntrusivePtr op1, IntrusivePtr op2); void Canonicize() override; }; class CondExpr : public Expr { public: - CondExpr(Expr* op1, Expr* op2, Expr* op3); - ~CondExpr() override; + CondExpr(IntrusivePtr op1, IntrusivePtr op2, IntrusivePtr op3); - const Expr* Op1() const { return op1; } - const Expr* Op2() const { return op2; } - const Expr* Op3() const { return op3; } + const Expr* Op1() const { return op1.get(); } + const Expr* Op2() const { return op2.get(); } + const Expr* Op3() const { return op3.get(); } - Val* Eval(Frame* f) const override; + IntrusivePtr Eval(Frame* f) const override; bool IsPure() const override; TraversalCode Traverse(TraversalCallback* cb) const override; @@ -497,31 +489,31 @@ public: protected: void ExprDescribe(ODesc* d) const override; - Expr* op1; - Expr* op2; - Expr* op3; + IntrusivePtr op1; + IntrusivePtr op2; + IntrusivePtr op3; }; class RefExpr : public UnaryExpr { public: - explicit RefExpr(Expr* op); + explicit RefExpr(IntrusivePtr op); - void Assign(Frame* f, Val* v) override; - Expr* MakeLvalue() override; + void Assign(Frame* f, IntrusivePtr v) override; + IntrusivePtr MakeLvalue() override; }; class AssignExpr : public BinaryExpr { public: // If val is given, evaluating this expression will always yield the val // yet still perform the assignment. Used for triggers. - AssignExpr(Expr* op1, Expr* op2, int is_init, Val* val = 0, attr_list* attrs = 0); - ~AssignExpr() override; + AssignExpr(IntrusivePtr op1, IntrusivePtr op2, int is_init, + IntrusivePtr val = nullptr, attr_list* attrs = nullptr); - Val* Eval(Frame* f) const override; + IntrusivePtr Eval(Frame* f) const override; void EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) const override; - BroType* InitType() const override; + IntrusivePtr InitType() const override; bool IsRecordElement(TypeDecl* td) const override; - Val* InitVal(const BroType* t, Val* aggr) const override; + IntrusivePtr InitVal(const BroType* t, IntrusivePtr aggr) const override; bool IsPure() const override; protected: @@ -529,18 +521,20 @@ protected: bool TypeCheckArithmetics(TypeTag bt1, TypeTag bt2); int is_init; - Val* val; // optional + IntrusivePtr val; // optional }; class IndexSliceAssignExpr : public AssignExpr { public: - IndexSliceAssignExpr(Expr* op1, Expr* op2, int is_init); - Val* Eval(Frame* f) const override; + IndexSliceAssignExpr(IntrusivePtr op1, + IntrusivePtr op2, int is_init); + IntrusivePtr Eval(Frame* f) const override; }; class IndexExpr : public BinaryExpr { public: - IndexExpr(Expr* op1, ListExpr* op2, bool is_slice = false); + IndexExpr(IntrusivePtr op1, + IntrusivePtr op2, bool is_slice = false); bool CanAdd() const override; bool CanDel() const override; @@ -548,19 +542,19 @@ public: void Add(Frame* f) override; void Delete(Frame* f) override; - void Assign(Frame* f, Val* v) override; - Expr* MakeLvalue() override; + void Assign(Frame* f, IntrusivePtr v) override; + IntrusivePtr MakeLvalue() override; // Need to override Eval since it can take a vector arg but does // not necessarily return a vector. - Val* Eval(Frame* f) const override; + IntrusivePtr Eval(Frame* f) const override; TraversalCode Traverse(TraversalCallback* cb) const override; bool IsSlice() const { return is_slice; } protected: - Val* Fold(Val* v1, Val* v2) const override; + IntrusivePtr Fold(Val* v1, Val* v2) const override; void ExprDescribe(ODesc* d) const override; @@ -569,7 +563,7 @@ protected: class FieldExpr : public UnaryExpr { public: - FieldExpr(Expr* op, const char* field_name); + FieldExpr(IntrusivePtr op, const char* field_name); ~FieldExpr() override; int Field() const { return field; } @@ -577,13 +571,13 @@ public: bool CanDel() const override; - void Assign(Frame* f, Val* v) override; + void Assign(Frame* f, IntrusivePtr v) override; void Delete(Frame* f) override; - Expr* MakeLvalue() override; + IntrusivePtr MakeLvalue() override; protected: - Val* Fold(Val* v) const override; + IntrusivePtr Fold(Val* v) const override; void ExprDescribe(ODesc* d) const override; @@ -596,13 +590,13 @@ protected: // "rec?$$attrname" is true if the attribute attrname is not nil. class HasFieldExpr : public UnaryExpr { public: - HasFieldExpr(Expr* op, const char* field_name); + HasFieldExpr(IntrusivePtr op, const char* field_name); ~HasFieldExpr() override; const char* FieldName() const { return field_name; } protected: - Val* Fold(Val* v) const override; + IntrusivePtr Fold(Val* v) const override; void ExprDescribe(ODesc* d) const override; @@ -612,28 +606,28 @@ protected: class RecordConstructorExpr : public UnaryExpr { public: - explicit RecordConstructorExpr(ListExpr* constructor_list); + explicit RecordConstructorExpr(IntrusivePtr constructor_list); ~RecordConstructorExpr() override; protected: - Val* InitVal(const BroType* t, Val* aggr) const override; - Val* Fold(Val* v) const override; + IntrusivePtr InitVal(const BroType* t, IntrusivePtr aggr) const override; + IntrusivePtr Fold(Val* v) const override; void ExprDescribe(ODesc* d) const override; }; class TableConstructorExpr : public UnaryExpr { public: - TableConstructorExpr(ListExpr* constructor_list, attr_list* attrs, - BroType* arg_type = 0); + TableConstructorExpr(IntrusivePtr constructor_list, attr_list* attrs, + IntrusivePtr arg_type = nullptr); ~TableConstructorExpr() override { Unref(attrs); } Attributes* Attrs() { return attrs; } - Val* Eval(Frame* f) const override; + IntrusivePtr Eval(Frame* f) const override; protected: - Val* InitVal(const BroType* t, Val* aggr) const override; + IntrusivePtr InitVal(const BroType* t, IntrusivePtr aggr) const override; void ExprDescribe(ODesc* d) const override; @@ -642,16 +636,16 @@ protected: class SetConstructorExpr : public UnaryExpr { public: - SetConstructorExpr(ListExpr* constructor_list, attr_list* attrs, - BroType* arg_type = 0); + SetConstructorExpr(IntrusivePtr constructor_list, attr_list* attrs, + IntrusivePtr arg_type = nullptr); ~SetConstructorExpr() override { Unref(attrs); } Attributes* Attrs() { return attrs; } - Val* Eval(Frame* f) const override; + IntrusivePtr Eval(Frame* f) const override; protected: - Val* InitVal(const BroType* t, Val* aggr) const override; + IntrusivePtr InitVal(const BroType* t, IntrusivePtr aggr) const override; void ExprDescribe(ODesc* d) const override; @@ -660,19 +654,20 @@ protected: class VectorConstructorExpr : public UnaryExpr { public: - explicit VectorConstructorExpr(ListExpr* constructor_list, BroType* arg_type = 0); + explicit VectorConstructorExpr(IntrusivePtr constructor_list, + IntrusivePtr arg_type = nullptr); - Val* Eval(Frame* f) const override; + IntrusivePtr Eval(Frame* f) const override; protected: - Val* InitVal(const BroType* t, Val* aggr) const override; + IntrusivePtr InitVal(const BroType* t, IntrusivePtr aggr) const override; void ExprDescribe(ODesc* d) const override; }; class FieldAssignExpr : public UnaryExpr { public: - FieldAssignExpr(const char* field_name, Expr* value); + FieldAssignExpr(const char* field_name, IntrusivePtr value); const char* FieldName() const { return field_name.c_str(); } @@ -687,21 +682,21 @@ protected: class ArithCoerceExpr : public UnaryExpr { public: - ArithCoerceExpr(Expr* op, TypeTag t); + ArithCoerceExpr(IntrusivePtr op, TypeTag t); protected: - Val* FoldSingleVal(Val* v, InternalTypeTag t) const; - Val* Fold(Val* v) const override; + IntrusivePtr FoldSingleVal(Val* v, InternalTypeTag t) const; + IntrusivePtr Fold(Val* v) const override; }; class RecordCoerceExpr : public UnaryExpr { public: - RecordCoerceExpr(Expr* op, RecordType* r); + RecordCoerceExpr(IntrusivePtr op, IntrusivePtr r); ~RecordCoerceExpr() override; protected: - Val* InitVal(const BroType* t, Val* aggr) const override; - Val* Fold(Val* v) const override; + IntrusivePtr InitVal(const BroType* t, IntrusivePtr aggr) const override; + IntrusivePtr Fold(Val* v) const override; // For each super-record slot, gives subrecord slot with which to // fill it. @@ -711,30 +706,30 @@ protected: class TableCoerceExpr : public UnaryExpr { public: - TableCoerceExpr(Expr* op, TableType* r); + TableCoerceExpr(IntrusivePtr op, IntrusivePtr r); ~TableCoerceExpr() override; protected: - Val* Fold(Val* v) const override; + IntrusivePtr Fold(Val* v) const override; }; class VectorCoerceExpr : public UnaryExpr { public: - VectorCoerceExpr(Expr* op, VectorType* v); + VectorCoerceExpr(IntrusivePtr op, IntrusivePtr v); ~VectorCoerceExpr() override; protected: - Val* Fold(Val* v) const override; + IntrusivePtr Fold(Val* v) const override; }; // An internal operator for flattening array indices that are records // into a list of individual values. class FlattenExpr : public UnaryExpr { public: - explicit FlattenExpr(Expr* op); + explicit FlattenExpr(IntrusivePtr op); protected: - Val* Fold(Val* v) const override; + IntrusivePtr Fold(Val* v) const override; int num_fields; }; @@ -755,53 +750,52 @@ protected: class ScheduleExpr : public Expr { public: - ScheduleExpr(Expr* when, EventExpr* event); - ~ScheduleExpr() override; + ScheduleExpr(IntrusivePtr when, IntrusivePtr event); bool IsPure() const override; - Val* Eval(Frame* f) const override; + IntrusivePtr Eval(Frame* f) const override; - Expr* When() const { return when; } - EventExpr* Event() const { return event; } + Expr* When() const { return when.get(); } + EventExpr* Event() const { return event.get(); } TraversalCode Traverse(TraversalCallback* cb) const override; protected: void ExprDescribe(ODesc* d) const override; - Expr* when; - EventExpr* event; + IntrusivePtr when; + IntrusivePtr event; }; class InExpr : public BinaryExpr { public: - InExpr(Expr* op1, Expr* op2); + InExpr(IntrusivePtr op1, IntrusivePtr op2); protected: - Val* Fold(Val* v1, Val* v2) const override; + IntrusivePtr Fold(Val* v1, Val* v2) const override; }; class CallExpr : public Expr { public: - CallExpr(Expr* func, ListExpr* args, bool in_hook = false); - ~CallExpr() override; + CallExpr(IntrusivePtr func, IntrusivePtr args, + bool in_hook = false); - Expr* Func() const { return func; } - ListExpr* Args() const { return args; } + Expr* Func() const { return func.get(); } + ListExpr* Args() const { return args.get(); } bool IsPure() const override; - Val* Eval(Frame* f) const override; + IntrusivePtr Eval(Frame* f) const override; TraversalCode Traverse(TraversalCallback* cb) const override; protected: void ExprDescribe(ODesc* d) const override; - Expr* func; - ListExpr* args; + IntrusivePtr func; + IntrusivePtr args; }; @@ -815,7 +809,7 @@ public: LambdaExpr(std::unique_ptr ingredients, id_list outer_ids); - Val* Eval(Frame* f) const override; + IntrusivePtr Eval(Frame* f) const override; TraversalCode Traverse(TraversalCallback* cb) const override; protected: @@ -830,14 +824,13 @@ private: class EventExpr : public Expr { public: - EventExpr(const char* name, ListExpr* args); - ~EventExpr() override; + EventExpr(const char* name, IntrusivePtr args); const char* Name() const { return name.c_str(); } - ListExpr* Args() const { return args; } + ListExpr* Args() const { return args.get(); } EventHandlerPtr Handler() const { return handler; } - Val* Eval(Frame* f) const override; + IntrusivePtr Eval(Frame* f) const override; TraversalCode Traverse(TraversalCallback* cb) const override; @@ -846,16 +839,16 @@ protected: string name; EventHandlerPtr handler; - ListExpr* args; + IntrusivePtr args; }; class ListExpr : public Expr { public: ListExpr(); - explicit ListExpr(Expr* e); + explicit ListExpr(IntrusivePtr e); ~ListExpr() override; - void Append(Expr* e); + void Append(IntrusivePtr e); const expr_list& Exprs() const { return exprs; } expr_list& Exprs() { return exprs; } @@ -866,17 +859,17 @@ public: // True if the entire list represents constant values. bool AllConst() const; - Val* Eval(Frame* f) const override; + IntrusivePtr Eval(Frame* f) const override; - BroType* InitType() const override; - Val* InitVal(const BroType* t, Val* aggr) const override; - Expr* MakeLvalue() override; - void Assign(Frame* f, Val* v) override; + IntrusivePtr InitType() const override; + IntrusivePtr InitVal(const BroType* t, IntrusivePtr aggr) const override; + IntrusivePtr MakeLvalue() override; + void Assign(Frame* f, IntrusivePtr v) override; TraversalCode Traverse(TraversalCallback* cb) const override; protected: - Val* AddSetInit(const BroType* t, Val* aggr) const; + IntrusivePtr AddSetInit(const BroType* t, IntrusivePtr aggr) const; void ExprDescribe(ODesc* d) const override; @@ -886,29 +879,28 @@ protected: class RecordAssignExpr : public ListExpr { public: - RecordAssignExpr(Expr* record, Expr* init_list, int is_init); + RecordAssignExpr(IntrusivePtr record, IntrusivePtr init_list, int is_init); }; class CastExpr : public UnaryExpr { public: - CastExpr(Expr* op, BroType* t); + CastExpr(IntrusivePtr op, IntrusivePtr t); protected: - Val* Eval(Frame* f) const override; + IntrusivePtr Eval(Frame* f) const override; void ExprDescribe(ODesc* d) const override; }; class IsExpr : public UnaryExpr { public: - IsExpr(Expr* op, BroType* t); - virtual ~IsExpr(); + IsExpr(IntrusivePtr op, IntrusivePtr t); protected: - Val* Fold(Val* v) const override; + IntrusivePtr Fold(Val* v) const override; void ExprDescribe(ODesc* d) const override; private: - BroType* t; + IntrusivePtr t; }; inline Val* Expr::ExprVal() const @@ -919,7 +911,8 @@ inline Val* Expr::ExprVal() const } // Decides whether to return an AssignExpr or a RecordAssignExpr. -Expr* get_assign_expr(Expr* op1, Expr* op2, int is_init); +IntrusivePtr get_assign_expr(IntrusivePtr op1, + IntrusivePtr op2, int is_init); // Type-check the given expression(s) against the given type(s). Complain // if the expression cannot match the given type, returning 0. If it can diff --git a/src/Func.cc b/src/Func.cc index ce7367d649..e6924a539f 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -387,7 +387,7 @@ Val* BroFunc::Call(val_list* args, Frame* parent) const try { - result = body.stmts->Exec(f, flow); + result = body.stmts->Exec(f, flow).release(); } catch ( InterpreterException& e ) @@ -606,15 +606,14 @@ BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name, name = make_full_var_name(GLOBAL_MODULE_NAME, arg_name); is_pure = arg_is_pure; - ID* id = lookup_ID(Name(), GLOBAL_MODULE_NAME, false); + auto id = lookup_ID(Name(), GLOBAL_MODULE_NAME, false); if ( ! id ) reporter->InternalError("built-in function %s missing", Name()); if ( id->HasVal() ) reporter->InternalError("built-in function %s multiply defined", Name()); type = id->Type()->Ref(); - id->SetVal(new Val(this)); - Unref(id); + id->SetVal(make_intrusive(this)); } BuiltinFunc::~BuiltinFunc() @@ -816,7 +815,7 @@ bool check_built_in_call(BuiltinFunc* f, CallExpr* call) return false; } - Val* fmt_str_val = fmt_str_arg->Eval(0); + auto fmt_str_val = fmt_str_arg->Eval(nullptr); if ( fmt_str_val ) { @@ -830,7 +829,6 @@ bool check_built_in_call(BuiltinFunc* f, CallExpr* call) if ( ! *fmt_str ) { - Unref(fmt_str_val); call->Error("format string ends with bare '%'"); return false; } @@ -842,13 +840,11 @@ bool check_built_in_call(BuiltinFunc* f, CallExpr* call) if ( args.length() != num_fmt + 1 ) { - Unref(fmt_str_val); call->Error("mismatch between format string to fmt() and number of arguments passed"); return false; } } - Unref(fmt_str_val); return true; } @@ -869,7 +865,8 @@ static int get_func_priority(const attr_list& attrs) continue; } - Val* v = a->AttrExpr()->Eval(0); + auto v = a->AttrExpr()->Eval(nullptr); + if ( ! v ) { a->Error("cannot evaluate attribute expression"); @@ -878,13 +875,11 @@ static int get_func_priority(const attr_list& attrs) if ( ! IsIntegral(v->Type()->Tag()) ) { - Unref(v); a->Error("expression is not of integral type"); continue; } priority = v->InternalInt(); - Unref(v); } return priority; diff --git a/src/ID.cc b/src/ID.cc index d6b949fc59..b506c99b46 100644 --- a/src/ID.cc +++ b/src/ID.cc @@ -26,9 +26,7 @@ ID::ID(const char* arg_name, IDScope arg_scope, bool arg_is_export) scope = arg_scope; is_export = arg_is_export; is_option = false; - type = 0; val = 0; - attrs = 0; is_const = false; is_enum_const = false; is_type = false; @@ -43,11 +41,6 @@ ID::ID(const char* arg_name, IDScope arg_scope, bool arg_is_export) ID::~ID() { delete [] name; - Unref(type); - Unref(attrs); - - for ( auto element : option_handlers ) - Unref(element.second); if ( ! weak_ref ) Unref(val); @@ -58,9 +51,9 @@ string ID::ModuleName() const return extract_module_name(name); } -void ID::SetType(BroType* t) +void ID::SetType(IntrusivePtr t) { - Unref(type); type = t; + type = std::move(t); } void ID::ClearVal() @@ -71,12 +64,12 @@ void ID::ClearVal() val = 0; } -void ID::SetVal(Val* v, bool arg_weak_ref) +void ID::SetVal(IntrusivePtr v, bool arg_weak_ref) { if ( ! weak_ref ) Unref(val); - val = v; + val = v.release(); weak_ref = arg_weak_ref; Modified(); @@ -104,11 +97,11 @@ void ID::SetVal(Val* v, bool arg_weak_ref) } } -void ID::SetVal(Val* v, init_class c) +void ID::SetVal(IntrusivePtr v, init_class c) { if ( c == INIT_NONE || c == INIT_FULL ) { - SetVal(v); + SetVal(std::move(v)); return; } @@ -117,9 +110,9 @@ void ID::SetVal(Val* v, init_class c) (type->Tag() != TYPE_VECTOR || c == INIT_REMOVE) ) { if ( c == INIT_EXTRA ) - Error("+= initializer only applies to tables, sets, vectors and patterns", v); + Error("+= initializer only applies to tables, sets, vectors and patterns", v.get()); else - Error("-= initializer only applies to tables and sets", v); + Error("-= initializer only applies to tables and sets", v.get()); } else @@ -128,7 +121,7 @@ void ID::SetVal(Val* v, init_class c) { if ( ! val ) { - SetVal(v); + SetVal(std::move(v)); return; } else @@ -140,11 +133,9 @@ void ID::SetVal(Val* v, init_class c) v->RemoveFrom(val); } } - - Unref(v); } -void ID::SetVal(Expr* ev, init_class c) +void ID::SetVal(IntrusivePtr ev, init_class c) { Attr* a = attrs->FindAttr(c == INIT_EXTRA ? ATTR_ADD_FUNC : ATTR_DEL_FUNC); @@ -152,7 +143,7 @@ void ID::SetVal(Expr* ev, init_class c) if ( ! a ) Internal("no add/delete function in ID::SetVal"); - EvalFunc(a->AttrExpr(), ev); + EvalFunc({NewRef{}, a->AttrExpr()}, std::move(ev)); } bool ID::IsRedefinable() const @@ -160,11 +151,10 @@ bool ID::IsRedefinable() const return FindAttr(ATTR_REDEF) != 0; } -void ID::SetAttrs(Attributes* a) +void ID::SetAttrs(IntrusivePtr a) { - Unref(attrs); attrs = 0; - AddAttrs(a); + AddAttrs(std::move(a)); } void ID::UpdateValAttrs() @@ -173,10 +163,10 @@ void ID::UpdateValAttrs() return; if ( val && val->Type()->Tag() == TYPE_TABLE ) - val->AsTableVal()->SetAttrs(attrs); + val->AsTableVal()->SetAttrs(attrs.get()); if ( val && val->Type()->Tag() == TYPE_FILE ) - val->AsFile()->SetAttrs(attrs); + val->AsFile()->SetAttrs(attrs.get()); if ( Type()->Tag() == TYPE_FUNC ) { @@ -222,7 +212,7 @@ void ID::MakeDeprecated(Expr* deprecation) return; attr_list* attr = new attr_list{new Attr(ATTR_DEPRECATED, deprecation)}; - AddAttrs(new Attributes(attr, Type(), false, IsGlobal())); + AddAttrs(make_intrusive(attr, Type(), false, IsGlobal())); } string ID::GetDeprecationWarning() const @@ -245,12 +235,12 @@ string ID::GetDeprecationWarning() const return fmt("deprecated (%s): %s", Name(), result.c_str()); } -void ID::AddAttrs(Attributes* a) +void ID::AddAttrs(IntrusivePtr a) { if ( attrs ) - attrs->AddAttrs(a); + attrs->AddAttrs(a.release()); else - attrs = a; + attrs = std::move(a); UpdateValAttrs(); } @@ -272,55 +262,20 @@ void ID::SetOption() if ( ! IsRedefinable() ) { attr_list* attr = new attr_list{new Attr(ATTR_REDEF)}; - AddAttrs(new Attributes(attr, Type(), false, IsGlobal())); + AddAttrs(make_intrusive(attr, Type(), false, IsGlobal())); } } -void ID::EvalFunc(Expr* ef, Expr* ev) +void ID::EvalFunc(IntrusivePtr ef, IntrusivePtr ev) { - Expr* arg1 = new ConstExpr(val->Ref()); - ListExpr* args = new ListExpr(); - args->Append(arg1); - args->Append(ev->Ref()); - - CallExpr* ce = new CallExpr(ef->Ref(), args); - - SetVal(ce->Eval(0)); - Unref(ce); + auto arg1 = make_intrusive(IntrusivePtr{NewRef{}, val}); + auto args = make_intrusive(); + args->Append(std::move(arg1)); + args->Append(std::move(ev)); + auto ce = make_intrusive(std::move(ef), std::move(args)); + SetVal(ce->Eval(nullptr)); } -#if 0 -void ID::CopyFrom(const ID* id) - { - is_export = id->is_export; - is_const = id->is_const; - is_enum_const = id->is_enum_const; - is_type = id->is_type; - offset = id->offset ; - infer_return_type = id->infer_return_type; - - if ( id->type ) - Ref(id->type); - if ( id->val && ! id->weak_ref ) - Ref(id->val); - if ( id->attrs ) - Ref(id->attrs); - - Unref(type); - Unref(attrs); - if ( ! weak_ref ) - Unref(val); - - type = id->type; - val = id->val; - attrs = id->attrs; - weak_ref = id->weak_ref; - -#ifdef DEBUG - UpdateValID(); -#endif -#endif - TraversalCode ID::Traverse(TraversalCallback* cb) const { TraversalCode tc = cb->PreID(this); @@ -359,7 +314,7 @@ TraversalCode ID::Traverse(TraversalCallback* cb) const void ID::Error(const char* msg, const BroObj* o2) { BroObj::Error(msg, o2, 1); - SetType(error_type()); + SetType({AdoptRef{}, error_type()}); } void ID::Describe(ODesc* d) const @@ -582,9 +537,9 @@ void ID::UpdateValID() } #endif -void ID::AddOptionHandler(Func* callback, int priority) +void ID::AddOptionHandler(IntrusivePtr callback, int priority) { - option_handlers.insert({priority, callback}); + option_handlers.emplace(priority, std::move(callback)); } vector ID::GetOptionHandlers() const @@ -594,6 +549,6 @@ vector ID::GetOptionHandlers() const // a lot... vector v; for ( auto& element : option_handlers ) - v.push_back(element.second); + v.push_back(element.second.get()); return v; } diff --git a/src/ID.h b/src/ID.h index 0eaf1d42b8..c3fba83235 100644 --- a/src/ID.h +++ b/src/ID.h @@ -2,6 +2,7 @@ #pragma once +#include "IntrusivePtr.h" #include "Obj.h" #include "Attr.h" #include "Notifier.h" @@ -35,9 +36,9 @@ public: std::string ModuleName() const; - void SetType(BroType* t); - BroType* Type() { return type; } - const BroType* Type() const { return type; } + void SetType(IntrusivePtr t); + BroType* Type() { return type.get(); } + const BroType* Type() const { return type.get(); } void MakeType() { is_type = true; } BroType* AsType() { return is_type ? Type() : 0; } @@ -51,10 +52,10 @@ public: // reference to the Val, the Val will be destroyed (naturally, // you have to take care that it will not be accessed via // the ID afterwards). - void SetVal(Val* v, bool weak_ref = false); + void SetVal(IntrusivePtr v, bool weak_ref = false); - void SetVal(Val* v, init_class c); - void SetVal(Expr* ev, init_class c); + void SetVal(IntrusivePtr v, init_class c); + void SetVal(IntrusivePtr ev, init_class c); bool HasVal() const { return val != 0; } Val* ID_Val() { return val; } @@ -75,11 +76,11 @@ public: bool IsRedefinable() const; - void SetAttrs(Attributes* attr); - void AddAttrs(Attributes* attr); + void SetAttrs(IntrusivePtr attr); + void AddAttrs(IntrusivePtr attr); void RemoveAttr(attr_tag a); void UpdateValAttrs(); - Attributes* Attrs() const { return attrs; } + Attributes* Attrs() const { return attrs.get(); } Attr* FindAttr(attr_tag t) const; @@ -108,12 +109,11 @@ public: bool HasOptionHandlers() const { return !option_handlers.empty(); } - // Takes ownership of callback. - void AddOptionHandler(Func* callback, int priority); + void AddOptionHandler(IntrusivePtr callback, int priority); std::vector GetOptionHandlers() const; protected: - void EvalFunc(Expr* ef, Expr* ev); + void EvalFunc(IntrusivePtr ef, IntrusivePtr ev); #ifdef DEBUG void UpdateValID(); @@ -122,13 +122,13 @@ protected: const char* name; IDScope scope; bool is_export; - BroType* type; + IntrusivePtr type; bool is_const, is_enum_const, is_type, is_option; int offset; Val* val; - Attributes* attrs; + IntrusivePtr attrs; // contains list of functions that are called when an option changes - std::multimap option_handlers; + std::multimap> option_handlers; bool infer_return_type; bool weak_ref; diff --git a/src/Net.cc b/src/Net.cc index 744bd8a811..6aa3177639 100644 --- a/src/Net.cc +++ b/src/Net.cc @@ -194,7 +194,7 @@ void net_init(const std::optional& interface, writefile, pkt_dumper->ErrorMsg()); if ( ID* id = global_scope()->Lookup("trace_output_file") ) - id->SetVal(new StringVal(writefile)); + id->SetVal(make_intrusive(writefile)); else reporter->Error("trace_output_file not defined in bro.init"); } diff --git a/src/RuleMatcher.cc b/src/RuleMatcher.cc index cc3e59448a..53e3dba055 100644 --- a/src/RuleMatcher.cc +++ b/src/RuleMatcher.cc @@ -9,6 +9,7 @@ #include "RuleCondition.h" #include "BroString.h" #include "ID.h" +#include "IntrusivePtr.h" #include "IntSet.h" #include "IP.h" #include "analyzer/Analyzer.h" @@ -1268,17 +1269,14 @@ void RuleMatcher::DumpStateStats(BroFile* f, RuleHdrTest* hdr_test) static Val* get_bro_val(const char* label) { - ID* id = lookup_ID(label, GLOBAL_MODULE_NAME, false); + auto id = lookup_ID(label, GLOBAL_MODULE_NAME, false); if ( ! id ) { rules_error("unknown script-level identifier", label); return 0; } - Val* rval = id->ID_Val(); - Unref(id); - - return rval; + return id->ID_Val(); } diff --git a/src/Scope.cc b/src/Scope.cc index dce70f7639..e72df4aa8d 100644 --- a/src/Scope.cc +++ b/src/Scope.cc @@ -5,6 +5,7 @@ #include "Scope.h" #include "Desc.h" #include "ID.h" +#include "IntrusivePtr.h" #include "Val.h" #include "Reporter.h" #include "module_util.h" @@ -56,7 +57,14 @@ Scope::~Scope() Unref(scope_id); Unref(return_type); - delete inits; + + if ( inits ) + { + for ( const auto& i : *inits ) + Unref(i); + + delete inits; + } } ID* Scope::GenerateTemporary(const char* name) @@ -119,8 +127,9 @@ TraversalCode Scope::Traverse(TraversalCallback* cb) const } -ID* lookup_ID(const char* name, const char* curr_module, bool no_global, - bool same_module_only, bool check_export) +IntrusivePtr lookup_ID(const char* name, const char* curr_module, + bool no_global, bool same_module_only, + bool check_export) { string fullname = make_full_var_name(curr_module, name); @@ -137,8 +146,7 @@ ID* lookup_ID(const char* name, const char* curr_module, bool no_global, reporter->Error("identifier is not exported: %s", fullname.c_str()); - Ref(id); - return id; + return {NewRef{}, id}; } } @@ -148,17 +156,14 @@ ID* lookup_ID(const char* name, const char* curr_module, bool no_global, string globalname = make_full_var_name(GLOBAL_MODULE_NAME, name); ID* id = global_scope()->Lookup(globalname); if ( id ) - { - Ref(id); - return id; - } + return {NewRef{}, id}; } return 0; } -ID* install_ID(const char* name, const char* module_name, - bool is_global, bool is_export) +IntrusivePtr install_ID(const char* name, const char* module_name, + bool is_global, bool is_export) { if ( scopes.empty() && ! is_global ) reporter->InternalError("local identifier in global scope"); @@ -175,13 +180,14 @@ ID* install_ID(const char* name, const char* module_name, string full_name = make_full_var_name(module_name, name); - ID* id = new ID(full_name.data(), scope, is_export); + auto id = make_intrusive(full_name.data(), scope, is_export); + if ( SCOPE_FUNCTION != scope ) - global_scope()->Insert(std::move(full_name), id); + global_scope()->Insert(std::move(full_name), IntrusivePtr{id}.release()); else { id->SetOffset(top_scope->Length()); - top_scope->Insert(std::move(full_name), id); + top_scope->Insert(std::move(full_name), IntrusivePtr{id}.release()); } return id; @@ -198,21 +204,17 @@ void push_scope(ID* id, attr_list* attrs) scopes.push_back(top_scope); } -Scope* pop_scope() +IntrusivePtr pop_scope() { if ( scopes.empty() ) reporter->InternalError("scope underflow"); scopes.pop_back(); Scope* old_top = top_scope; - // Don't delete the scope; keep it around for later name resolution - // in the debugger. - // ### SERIOUS MEMORY LEAK!? - // delete top_scope; top_scope = scopes.empty() ? nullptr : scopes.back(); - return old_top; + return {AdoptRef{}, old_top}; } Scope* current_scope() diff --git a/src/Scope.h b/src/Scope.h index 942d38ae1c..cc55c98fea 100644 --- a/src/Scope.h +++ b/src/Scope.h @@ -10,6 +10,7 @@ #include "BroList.h" #include "TraverseTypes.h" +template class IntrusivePtr; class ID; class BroType; class ListVal; @@ -20,9 +21,10 @@ public: ~Scope() override; template - ID* Lookup(N &&name) const + ID* Lookup(N&& name) const { const auto& entry = local.find(std::forward(name)); + if ( entry != local.end() ) return entry->second; @@ -30,12 +32,22 @@ public: } template - void Insert(N &&name, ID* id) { local[std::forward(name)] = id; } + void Insert(N&& name, ID* id) + { + auto [it, inserted] = local.emplace(std::forward(name), id); + + if ( ! inserted ) + { + Unref(it->second); + it->second = id; + } + } template - ID* Remove(N &&name) + ID* Remove(N&& name) { const auto& entry = local.find(std::forward(name)); + if ( entry != local.end() ) { ID* id = entry->second; @@ -78,18 +90,19 @@ protected: extern bool in_debug; // If no_global is true, don't search in the default "global" namespace. -// This passed ownership of a ref'ed ID to the caller. -extern ID* lookup_ID(const char* name, const char* module, - bool no_global = false, bool same_module_only = false, - bool check_export = true); -extern ID* install_ID(const char* name, const char* module_name, - bool is_global, bool is_export); +extern IntrusivePtr lookup_ID(const char* name, const char* module, + bool no_global = false, + bool same_module_only = false, + bool check_export = true); + +extern IntrusivePtr install_ID(const char* name, const char* module_name, + bool is_global, bool is_export); extern void push_scope(ID* id, attr_list* attrs); extern void push_existing_scope(Scope* scope); -// Returns the one popped off; it's not deleted. -extern Scope* pop_scope(); +// Returns the one popped off. +extern IntrusivePtr pop_scope(); extern Scope* current_scope(); extern Scope* global_scope(); diff --git a/src/Stmt.cc b/src/Stmt.cc index 76b31c07e4..a1df712eb7 100644 --- a/src/Stmt.cc +++ b/src/Stmt.cc @@ -130,11 +130,9 @@ void Stmt::AccessStats(ODesc* d) const } } -ExprListStmt::ExprListStmt(BroStmtTag t, ListExpr* arg_l) -: Stmt(t) +ExprListStmt::ExprListStmt(BroStmtTag t, IntrusivePtr arg_l) + : Stmt(t), l(std::move(arg_l)) { - l = arg_l; - const expr_list& e = l->Exprs(); for ( const auto& expr : e ) { @@ -143,28 +141,25 @@ ExprListStmt::ExprListStmt(BroStmtTag t, ListExpr* arg_l) Error("value of type void illegal"); } - SetLocationInfo(arg_l->GetLocationInfo()); + SetLocationInfo(l->GetLocationInfo()); } -ExprListStmt::~ExprListStmt() - { - Unref(l); - } +ExprListStmt::~ExprListStmt() = default; -Val* ExprListStmt::Exec(Frame* f, stmt_flow_type& flow) const +IntrusivePtr ExprListStmt::Exec(Frame* f, stmt_flow_type& flow) const { last_access = network_time; flow = FLOW_NEXT; - val_list* vals = eval_list(f, l); + val_list* vals = eval_list(f, l.get()); if ( vals ) { - Val* result = DoExec(vals, flow); + auto result = DoExec(vals, flow); delete_vals(vals); return result; } else - return 0; + return nullptr; } void ExprListStmt::Describe(ODesc* d) const @@ -199,7 +194,7 @@ static BroFile* print_stdout = 0; static IntrusivePtr lookup_enum_val(const char* module_name, const char* name) { - ID* id = lookup_ID(name, module_name); + auto id = lookup_ID(name, module_name); assert(id); assert(id->IsEnumConst()); @@ -212,7 +207,7 @@ static IntrusivePtr lookup_enum_val(const char* module_name, const char return rval; } -static Val* print_log(val_list* vals) +static void print_log(val_list* vals) { auto plval = lookup_enum_val("Log", "PRINTLOG"); auto record = make_intrusive(internal_type("Log::PrintLogInfo")->AsRecordType()); @@ -228,10 +223,9 @@ static Val* print_log(val_list* vals) record->Assign(0, new Val(current_time(), TYPE_TIME)); record->Assign(1, vec.release()); log_mgr->Write(plval.get(), record.get()); - return nullptr; } -Val* PrintStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */) const +IntrusivePtr PrintStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */) const { RegisterAccess(); @@ -245,7 +239,7 @@ Val* PrintStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */) const { f = (*vals)[0]->AsFile(); if ( ! f->IsOpen() ) - return 0; + return nullptr; ++offset; } @@ -257,12 +251,18 @@ Val* PrintStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */) const case BifEnum::Log::REDIRECT_NONE: break; case BifEnum::Log::REDIRECT_ALL: - return print_log(vals); + { + print_log(vals); + return nullptr; + } case BifEnum::Log::REDIRECT_STDOUT: if ( f->File() == stdout ) + { // Should catch even printing to a "manually opened" stdout file, // like "/dev/stdout" or "-". - return print_log(vals); + print_log(vals); + return nullptr; + } break; default: reporter->InternalError("unknown Log::PrintLogType value: %d", @@ -291,51 +291,41 @@ Val* PrintStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */) const f->Write("\n", 1); } - return 0; + return nullptr; } -ExprStmt::ExprStmt(Expr* arg_e) : Stmt(STMT_EXPR) +ExprStmt::ExprStmt(IntrusivePtr arg_e) : Stmt(STMT_EXPR), e(std::move(arg_e)) { - e = arg_e; if ( e && e->IsPure() ) Warn("expression value ignored"); - SetLocationInfo(arg_e->GetLocationInfo()); + SetLocationInfo(e->GetLocationInfo()); } -ExprStmt::ExprStmt(BroStmtTag t, Expr* arg_e) : Stmt(t) +ExprStmt::ExprStmt(BroStmtTag t, IntrusivePtr arg_e) : Stmt(t), e(std::move(arg_e)) { - e = arg_e; - if ( e ) SetLocationInfo(e->GetLocationInfo()); } -ExprStmt::~ExprStmt() - { - Unref(e); - } +ExprStmt::~ExprStmt() = default; -Val* ExprStmt::Exec(Frame* f, stmt_flow_type& flow) const +IntrusivePtr ExprStmt::Exec(Frame* f, stmt_flow_type& flow) const { RegisterAccess(); flow = FLOW_NEXT; - Val* v = e->Eval(f); + auto v = e->Eval(f); if ( v ) - { - Val* ret_val = DoExec(f, v, flow); - Unref(v); - return ret_val; - } + return DoExec(f, v.get(), flow); else - return 0; + return nullptr; } -Val* ExprStmt::DoExec(Frame* /* f */, Val* /* v */, stmt_flow_type& /* flow */) const +IntrusivePtr ExprStmt::DoExec(Frame* /* f */, Val* /* v */, stmt_flow_type& /* flow */) const { - return 0; + return nullptr; } int ExprStmt::IsPure() const @@ -379,29 +369,25 @@ TraversalCode ExprStmt::Traverse(TraversalCallback* cb) const HANDLE_TC_STMT_POST(tc); } -IfStmt::IfStmt(Expr* test, Stmt* arg_s1, Stmt* arg_s2) : ExprStmt(STMT_IF, test) +IfStmt::IfStmt(IntrusivePtr test, + IntrusivePtr arg_s1, IntrusivePtr arg_s2) + : ExprStmt(STMT_IF, std::move(test)), + s1(std::move(arg_s1)), s2(std::move(arg_s2)) { - s1 = arg_s1; - s2 = arg_s2; - if ( ! e->IsError() && ! IsBool(e->Type()->Tag()) ) e->Error("conditional in test must be boolean"); - const Location* loc1 = arg_s1->GetLocationInfo(); - const Location* loc2 = arg_s2->GetLocationInfo(); + const Location* loc1 = s1->GetLocationInfo(); + const Location* loc2 = s2->GetLocationInfo(); SetLocationInfo(loc1, loc2); } -IfStmt::~IfStmt() - { - Unref(s1); - Unref(s2); - } +IfStmt::~IfStmt() = default; -Val* IfStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const +IntrusivePtr IfStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const { // Treat 0 as false, but don't require 1 for true. - Stmt* do_stmt = v->IsZero() ? s2 : s1; + Stmt* do_stmt = v->IsZero() ? s2.get() : s1.get(); f->SetNextStmt(do_stmt); @@ -409,9 +395,9 @@ Val* IfStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const { // ### Abort or something } - Val* result = do_stmt->Exec(f, flow); + auto result = do_stmt->Exec(f, flow); - if ( ! post_execute_stmt(do_stmt, f, result, &flow) ) + if ( ! post_execute_stmt(do_stmt, f, result.get(), &flow) ) { // ### Abort or something } @@ -483,8 +469,10 @@ static BroStmtTag get_last_stmt_tag(const Stmt* stmt) return get_last_stmt_tag(stmts->Stmts()[len - 1]); } -Case::Case(ListExpr* arg_expr_cases, id_list* arg_type_cases, Stmt* arg_s) - : expr_cases(arg_expr_cases), type_cases(arg_type_cases), s(arg_s) +Case::Case(IntrusivePtr arg_expr_cases, id_list* arg_type_cases, + IntrusivePtr arg_s) + : expr_cases(std::move(arg_expr_cases)), type_cases(arg_type_cases), + s(std::move(arg_s)) { BroStmtTag t = get_last_stmt_tag(Body()); @@ -494,9 +482,6 @@ Case::Case(ListExpr* arg_expr_cases, id_list* arg_type_cases, Stmt* arg_s) Case::~Case() { - Unref(expr_cases); - Unref(s); - for ( const auto& id : *type_cases ) Unref(id); @@ -609,8 +594,9 @@ void SwitchStmt::Init() case_label_value_map.SetDeleteFunc(int_del_func); } -SwitchStmt::SwitchStmt(Expr* index, case_list* arg_cases) : - ExprStmt(STMT_SWITCH, index), cases(arg_cases), default_case_idx(-1) +SwitchStmt::SwitchStmt(IntrusivePtr index, case_list* arg_cases) + : ExprStmt(STMT_SWITCH, std::move(index)), + cases(arg_cases), default_case_idx(-1) { Init(); @@ -632,7 +618,7 @@ SwitchStmt::SwitchStmt(Expr* index, case_list* arg_cases) : if ( ! le->Type()->AsTypeList()->AllMatch(e->Type(), false) ) { - le->Error("case expression type differs from switch type", e); + le->Error("case expression type differs from switch type", e.get()); continue; } @@ -670,10 +656,10 @@ SwitchStmt::SwitchStmt(Expr* index, case_list* arg_cases) : if ( ne->Id()->IsConst() ) { - Val* v = ne->Eval(0); + auto v = ne->Eval(0); if ( v ) - Unref(exprs.replace(j, new ConstExpr(v))); + Unref(exprs.replace(j, new ConstExpr(std::move(v)))); } } break; @@ -820,16 +806,16 @@ std::pair SwitchStmt::FindCaseLabelMatch(const Val* v) const return std::make_pair(label_idx, label_id); } -Val* SwitchStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const +IntrusivePtr SwitchStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const { - Val* rval = 0; + IntrusivePtr rval; auto m = FindCaseLabelMatch(v); int matching_label_idx = m.first; ID* matching_id = m.second; if ( matching_label_idx == -1 ) - return 0; + return nullptr; for ( int i = matching_label_idx; i < cases->length(); ++i ) { @@ -838,7 +824,7 @@ Val* SwitchStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const if ( matching_id ) { auto cv = cast_value_to_type(v, matching_id->Type()); - f->SetElement(matching_id, cv); + f->SetElement(matching_id, cv.release()); } flow = FLOW_NEXT; @@ -905,7 +891,7 @@ TraversalCode SwitchStmt::Traverse(TraversalCallback* cb) const HANDLE_TC_STMT_POST(tc); } -AddStmt::AddStmt(Expr* arg_e) : ExprStmt(STMT_ADD, arg_e) +AddStmt::AddStmt(IntrusivePtr arg_e) : ExprStmt(STMT_ADD, std::move(arg_e)) { if ( ! e->CanAdd() ) Error("illegal add statement"); @@ -916,12 +902,12 @@ int AddStmt::IsPure() const return 0; } -Val* AddStmt::Exec(Frame* f, stmt_flow_type& flow) const +IntrusivePtr AddStmt::Exec(Frame* f, stmt_flow_type& flow) const { RegisterAccess(); flow = FLOW_NEXT; e->Add(f); - return 0; + return nullptr; } @@ -938,7 +924,7 @@ TraversalCode AddStmt::Traverse(TraversalCallback* cb) const HANDLE_TC_STMT_POST(tc); } -DelStmt::DelStmt(Expr* arg_e) : ExprStmt(STMT_DELETE, arg_e) +DelStmt::DelStmt(IntrusivePtr arg_e) : ExprStmt(STMT_DELETE, std::move(arg_e)) { if ( e->IsError() ) return; @@ -952,12 +938,12 @@ int DelStmt::IsPure() const return 0; } -Val* DelStmt::Exec(Frame* f, stmt_flow_type& flow) const +IntrusivePtr DelStmt::Exec(Frame* f, stmt_flow_type& flow) const { RegisterAccess(); flow = FLOW_NEXT; e->Delete(f); - return 0; + return nullptr; } TraversalCode DelStmt::Traverse(TraversalCallback* cb) const @@ -973,12 +959,12 @@ TraversalCode DelStmt::Traverse(TraversalCallback* cb) const HANDLE_TC_STMT_POST(tc); } -EventStmt::EventStmt(EventExpr* arg_e) : ExprStmt(STMT_EVENT, arg_e) +EventStmt::EventStmt(IntrusivePtr arg_e) + : ExprStmt(STMT_EVENT, arg_e), event_expr(std::move(arg_e)) { - event_expr = arg_e; } -Val* EventStmt::Exec(Frame* f, stmt_flow_type& flow) const +IntrusivePtr EventStmt::Exec(Frame* f, stmt_flow_type& flow) const { RegisterAccess(); val_list* args = eval_list(f, event_expr->Args()); @@ -990,8 +976,7 @@ Val* EventStmt::Exec(Frame* f, stmt_flow_type& flow) const } flow = FLOW_NEXT; - - return 0; + return nullptr; } TraversalCode EventStmt::Traverse(TraversalCallback* cb) const @@ -1007,19 +992,16 @@ TraversalCode EventStmt::Traverse(TraversalCallback* cb) const HANDLE_TC_STMT_POST(tc); } -WhileStmt::WhileStmt(Expr* arg_loop_condition, Stmt* arg_body) - : loop_condition(arg_loop_condition), body(arg_body) +WhileStmt::WhileStmt(IntrusivePtr arg_loop_condition, + IntrusivePtr arg_body) + : loop_condition(std::move(arg_loop_condition)), body(std::move(arg_body)) { if ( ! loop_condition->IsError() && ! IsBool(loop_condition->Type()->Tag()) ) loop_condition->Error("while conditional must be boolean"); } -WhileStmt::~WhileStmt() - { - Unref(loop_condition); - Unref(body); - } +WhileStmt::~WhileStmt() = default; int WhileStmt::IsPure() const { @@ -1060,23 +1042,20 @@ TraversalCode WhileStmt::Traverse(TraversalCallback* cb) const HANDLE_TC_STMT_POST(tc); } -Val* WhileStmt::Exec(Frame* f, stmt_flow_type& flow) const +IntrusivePtr WhileStmt::Exec(Frame* f, stmt_flow_type& flow) const { RegisterAccess(); flow = FLOW_NEXT; - Val* rval = 0; + IntrusivePtr rval; for ( ; ; ) { - Val* cond = loop_condition->Eval(f); + auto cond = loop_condition->Eval(f); if ( ! cond ) break; - bool cont = cond->AsBool(); - Unref(cond); - - if ( ! cont ) + if ( ! cond->AsBool() ) break; flow = FLOW_NEXT; @@ -1092,8 +1071,8 @@ Val* WhileStmt::Exec(Frame* f, stmt_flow_type& flow) const return rval; } -ForStmt::ForStmt(id_list* arg_loop_vars, Expr* loop_expr) -: ExprStmt(STMT_FOR, loop_expr) +ForStmt::ForStmt(id_list* arg_loop_vars, IntrusivePtr loop_expr) + : ExprStmt(STMT_FOR, std::move(loop_expr)) { loop_vars = arg_loop_vars; body = 0; @@ -1119,8 +1098,8 @@ ForStmt::ForStmt(id_list* arg_loop_vars, Expr* loop_expr) else { - delete add_local((*loop_vars)[i], - ind_type->Ref(), INIT_NONE, + add_local({NewRef{}, (*loop_vars)[i]}, + {NewRef{}, ind_type}, INIT_NONE, 0, 0, VAR_REGULAR); } } @@ -1136,7 +1115,7 @@ ForStmt::ForStmt(id_list* arg_loop_vars, Expr* loop_expr) BroType* t = (*loop_vars)[0]->Type(); if ( ! t ) - delete add_local((*loop_vars)[0], base_type(TYPE_COUNT), + add_local({NewRef{}, (*loop_vars)[0]}, {AdoptRef{}, base_type(TYPE_COUNT)}, INIT_NONE, 0, 0, VAR_REGULAR); else if ( ! IsIntegral(t->Tag()) ) @@ -1156,8 +1135,8 @@ ForStmt::ForStmt(id_list* arg_loop_vars, Expr* loop_expr) BroType* t = (*loop_vars)[0]->Type(); if ( ! t ) - delete add_local((*loop_vars)[0], - base_type(TYPE_STRING), + add_local({NewRef{}, (*loop_vars)[0]}, + {AdoptRef{}, base_type(TYPE_STRING)}, INIT_NONE, 0, 0, VAR_REGULAR); else if ( t->Tag() != TYPE_STRING ) @@ -1170,10 +1149,11 @@ ForStmt::ForStmt(id_list* arg_loop_vars, Expr* loop_expr) e->Error("target to iterate over must be a table, set, vector, or string"); } -ForStmt::ForStmt(id_list* arg_loop_vars, Expr* loop_expr, ID* val_var) - : ForStmt(arg_loop_vars, loop_expr) +ForStmt::ForStmt(id_list* arg_loop_vars, + IntrusivePtr loop_expr, IntrusivePtr val_var) + : ForStmt(arg_loop_vars, std::move(loop_expr)) { - value_var = val_var; + value_var = std::move(val_var); if ( e->Type()->IsTable() ) { @@ -1187,7 +1167,7 @@ ForStmt::ForStmt(id_list* arg_loop_vars, Expr* loop_expr, ID* val_var) } else { - delete add_local(value_var, yield_type->Ref(), INIT_NONE, + add_local(value_var, {NewRef{}, yield_type}, INIT_NONE, 0, 0, VAR_REGULAR); } } @@ -1200,14 +1180,11 @@ ForStmt::~ForStmt() for ( const auto& var : *loop_vars ) Unref(var); delete loop_vars; - - Unref(value_var); - Unref(body); } -Val* ForStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const +IntrusivePtr ForStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const { - Val* ret = 0; + IntrusivePtr ret; if ( v->Type()->Tag() == TYPE_TABLE ) { @@ -1215,7 +1192,7 @@ Val* ForStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const const PDict* loop_vals = tv->AsTable(); if ( ! loop_vals->Length() ) - return 0; + return nullptr; HashKey* k; TableEntryVal* current_tev; @@ -1226,7 +1203,7 @@ Val* ForStmt::DoExec(Frame* f, Val* v, stmt_flow_type& flow) const delete k; if ( value_var ) - f->SetElement(value_var, current_tev->Value()->Ref()); + f->SetElement(value_var.get(), current_tev->Value()->Ref()); for ( int i = 0; i < ind_lv->Length(); i++ ) f->SetElement((*loop_vars)[i], ind_lv->Index(i)->Ref()); @@ -1356,11 +1333,11 @@ TraversalCode ForStmt::Traverse(TraversalCallback* cb) const HANDLE_TC_STMT_POST(tc); } -Val* NextStmt::Exec(Frame* /* f */, stmt_flow_type& flow) const +IntrusivePtr NextStmt::Exec(Frame* /* f */, stmt_flow_type& flow) const { RegisterAccess(); flow = FLOW_LOOP; - return 0; + return nullptr; } int NextStmt::IsPure() const @@ -1383,11 +1360,11 @@ TraversalCode NextStmt::Traverse(TraversalCallback* cb) const HANDLE_TC_STMT_POST(tc); } -Val* BreakStmt::Exec(Frame* /* f */, stmt_flow_type& flow) const +IntrusivePtr BreakStmt::Exec(Frame* /* f */, stmt_flow_type& flow) const { RegisterAccess(); flow = FLOW_BREAK; - return 0; + return nullptr; } int BreakStmt::IsPure() const @@ -1410,11 +1387,11 @@ TraversalCode BreakStmt::Traverse(TraversalCallback* cb) const HANDLE_TC_STMT_POST(tc); } -Val* FallthroughStmt::Exec(Frame* /* f */, stmt_flow_type& flow) const +IntrusivePtr FallthroughStmt::Exec(Frame* /* f */, stmt_flow_type& flow) const { RegisterAccess(); flow = FLOW_FALLTHROUGH; - return 0; + return nullptr; } int FallthroughStmt::IsPure() const @@ -1437,7 +1414,8 @@ TraversalCode FallthroughStmt::Traverse(TraversalCallback* cb) const HANDLE_TC_STMT_POST(tc); } -ReturnStmt::ReturnStmt(Expr* arg_e) : ExprStmt(STMT_RETURN, arg_e) +ReturnStmt::ReturnStmt(IntrusivePtr arg_e) + : ExprStmt(STMT_RETURN, std::move(arg_e)) { Scope* s = current_scope(); @@ -1472,10 +1450,14 @@ ReturnStmt::ReturnStmt(Expr* arg_e) : ExprStmt(STMT_RETURN, arg_e) } else - (void) check_and_promote_expr(e, yt); + { + Expr* e_ = e.release(); + (void) check_and_promote_expr(e_, yt); + e = {AdoptRef{}, e_}; + } } -Val* ReturnStmt::Exec(Frame* f, stmt_flow_type& flow) const +IntrusivePtr ReturnStmt::Exec(Frame* f, stmt_flow_type& flow) const { RegisterAccess(); flow = FLOW_RETURN; @@ -1483,7 +1465,7 @@ Val* ReturnStmt::Exec(Frame* f, stmt_flow_type& flow) const if ( e ) return e->Eval(f); else - return 0; + return nullptr; } void ReturnStmt::Describe(ODesc* d) const @@ -1514,7 +1496,7 @@ StmtList::~StmtList() Unref(stmt); } -Val* StmtList::Exec(Frame* f, stmt_flow_type& flow) const +IntrusivePtr StmtList::Exec(Frame* f, stmt_flow_type& flow) const { RegisterAccess(); flow = FLOW_NEXT; @@ -1527,9 +1509,9 @@ Val* StmtList::Exec(Frame* f, stmt_flow_type& flow) const { // ### Abort or something } - Val* result = stmt->Exec(f, flow); + auto result = stmt->Exec(f, flow); - if ( ! post_execute_stmt(stmt, f, result, &flow) ) + if ( ! post_execute_stmt(stmt, f, result.get(), &flow) ) { // ### Abort or something } @@ -1537,7 +1519,7 @@ Val* StmtList::Exec(Frame* f, stmt_flow_type& flow) const return result; } - return 0; + return nullptr; } int StmtList::IsPure() const @@ -1593,7 +1575,7 @@ TraversalCode StmtList::Traverse(TraversalCallback* cb) const HANDLE_TC_STMT_POST(tc); } -Val* EventBodyList::Exec(Frame* f, stmt_flow_type& flow) const +IntrusivePtr EventBodyList::Exec(Frame* f, stmt_flow_type& flow) const { RegisterAccess(); flow = FLOW_NEXT; @@ -1610,9 +1592,9 @@ Val* EventBodyList::Exec(Frame* f, stmt_flow_type& flow) const { // ### Abort or something } - Val* result = stmt->Exec(f, flow); + auto result = stmt->Exec(f, flow); - if ( ! post_execute_stmt(stmt, f, result, &flow) ) + if ( ! post_execute_stmt(stmt, f, result.get(), &flow) ) { // ### Abort or something } } @@ -1621,7 +1603,7 @@ Val* EventBodyList::Exec(Frame* f, stmt_flow_type& flow) const stmt_flow_type ft = FLOW_RETURN; (void) post_execute_stmt(f->GetNextStmt(), f, 0, &ft); - return 0; + return nullptr; } void EventBodyList::Describe(ODesc* d) const @@ -1666,7 +1648,7 @@ InitStmt::~InitStmt() delete inits; } -Val* InitStmt::Exec(Frame* f, stmt_flow_type& flow) const +IntrusivePtr InitStmt::Exec(Frame* f, stmt_flow_type& flow) const { RegisterAccess(); flow = FLOW_NEXT; @@ -1694,7 +1676,7 @@ Val* InitStmt::Exec(Frame* f, stmt_flow_type& flow) const f->SetElement(aggr, v); } - return 0; + return nullptr; } void InitStmt::Describe(ODesc* d) const @@ -1730,11 +1712,11 @@ TraversalCode InitStmt::Traverse(TraversalCallback* cb) const HANDLE_TC_STMT_POST(tc); } -Val* NullStmt::Exec(Frame* /* f */, stmt_flow_type& flow) const +IntrusivePtr NullStmt::Exec(Frame* /* f */, stmt_flow_type& flow) const { RegisterAccess(); flow = FLOW_NEXT; - return 0; + return nullptr; } int NullStmt::IsPure() const @@ -1759,18 +1741,15 @@ TraversalCode NullStmt::Traverse(TraversalCallback* cb) const HANDLE_TC_STMT_POST(tc); } -WhenStmt::WhenStmt(Expr* arg_cond, Stmt* arg_s1, Stmt* arg_s2, - Expr* arg_timeout, bool arg_is_return) -: Stmt(STMT_WHEN) +WhenStmt::WhenStmt(IntrusivePtr arg_cond, + IntrusivePtr arg_s1, IntrusivePtr arg_s2, + IntrusivePtr arg_timeout, bool arg_is_return) + : Stmt(STMT_WHEN), + cond(std::move(arg_cond)), s1(std::move(arg_s1)), s2(std::move(arg_s2)), + timeout(std::move(arg_timeout)), is_return(arg_is_return) { - assert(arg_cond); - assert(arg_s1); - - cond = arg_cond; - s1 = arg_s1; - s2 = arg_s2; - timeout = arg_timeout; - is_return = arg_is_return; + assert(cond); + assert(s1); if ( ! cond->IsError() && ! IsBool(cond->Type()->Tag()) ) cond->Error("conditional in test must be boolean"); @@ -1786,29 +1765,20 @@ WhenStmt::WhenStmt(Expr* arg_cond, Stmt* arg_s1, Stmt* arg_s2, } } -WhenStmt::~WhenStmt() - { - Unref(cond); - Unref(s1); - Unref(s2); - } +WhenStmt::~WhenStmt() = default; -Val* WhenStmt::Exec(Frame* f, stmt_flow_type& flow) const +IntrusivePtr WhenStmt::Exec(Frame* f, stmt_flow_type& flow) const { RegisterAccess(); flow = FLOW_NEXT; - ::Ref(cond); - ::Ref(s1); - if ( s2 ) - ::Ref(s2); - if ( timeout ) - ::Ref(timeout); - // The new trigger object will take care of its own deletion. - new trigger::Trigger(cond, s1, s2, timeout, f, is_return, location); - - return 0; + new trigger::Trigger(IntrusivePtr{cond}.release(), + IntrusivePtr{s1}.release(), + IntrusivePtr{s2}.release(), + IntrusivePtr{timeout}.release(), + f, is_return, location); + return nullptr; } int WhenStmt::IsPure() const diff --git a/src/Stmt.h b/src/Stmt.h index a65af2ee88..950d733d78 100644 --- a/src/Stmt.h +++ b/src/Stmt.h @@ -26,7 +26,7 @@ public: ~Stmt() override; - virtual Val* Exec(Frame* f, stmt_flow_type& flow) const = 0; + virtual IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const = 0; Stmt* Ref() { ::Ref(this); return this; } @@ -85,116 +85,105 @@ protected: class ExprListStmt : public Stmt { public: - const ListExpr* ExprList() const { return l; } + const ListExpr* ExprList() const { return l.get(); } TraversalCode Traverse(TraversalCallback* cb) const override; protected: - ExprListStmt() { l = 0; } - ExprListStmt(BroStmtTag t, ListExpr* arg_l); + ExprListStmt(BroStmtTag t, IntrusivePtr arg_l); ~ExprListStmt() override; - Val* Exec(Frame* f, stmt_flow_type& flow) const override; - virtual Val* DoExec(val_list* vals, stmt_flow_type& flow) const = 0; + IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const override; + virtual IntrusivePtr DoExec(val_list* vals, stmt_flow_type& flow) const = 0; void Describe(ODesc* d) const override; void PrintVals(ODesc* d, val_list* vals, int offset) const; - ListExpr* l; + IntrusivePtr l; }; class PrintStmt : public ExprListStmt { public: - explicit PrintStmt(ListExpr* l) : ExprListStmt(STMT_PRINT, l) { } + template + explicit PrintStmt(L&& l) : ExprListStmt(STMT_PRINT, std::forward(l)) { } protected: - friend class Stmt; - PrintStmt() {} - - Val* DoExec(val_list* vals, stmt_flow_type& flow) const override; + IntrusivePtr DoExec(val_list* vals, stmt_flow_type& flow) const override; }; class ExprStmt : public Stmt { public: - explicit ExprStmt(Expr* e); + explicit ExprStmt(IntrusivePtr e); ~ExprStmt() override; - Val* Exec(Frame* f, stmt_flow_type& flow) const override; + IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const override; - const Expr* StmtExpr() const { return e; } + const Expr* StmtExpr() const { return e.get(); } void Describe(ODesc* d) const override; TraversalCode Traverse(TraversalCallback* cb) const override; protected: - friend class Stmt; - ExprStmt() { e = 0; } - ExprStmt(BroStmtTag t, Expr* e); + ExprStmt(BroStmtTag t, IntrusivePtr e); - virtual Val* DoExec(Frame* f, Val* v, stmt_flow_type& flow) const; + virtual IntrusivePtr DoExec(Frame* f, Val* v, stmt_flow_type& flow) const; int IsPure() const override; - Expr* e; + IntrusivePtr e; }; class IfStmt : public ExprStmt { public: - IfStmt(Expr* test, Stmt* s1, Stmt* s2); + IfStmt(IntrusivePtr test, IntrusivePtr s1, IntrusivePtr s2); ~IfStmt() override; - const Stmt* TrueBranch() const { return s1; } - const Stmt* FalseBranch() const { return s2; } + const Stmt* TrueBranch() const { return s1.get(); } + const Stmt* FalseBranch() const { return s2.get(); } void Describe(ODesc* d) const override; TraversalCode Traverse(TraversalCallback* cb) const override; protected: - friend class Stmt; - IfStmt() { s1 = s2 = 0; } - - Val* DoExec(Frame* f, Val* v, stmt_flow_type& flow) const override; + IntrusivePtr DoExec(Frame* f, Val* v, stmt_flow_type& flow) const override; int IsPure() const override; - Stmt* s1; - Stmt* s2; + IntrusivePtr s1; + IntrusivePtr s2; }; class Case : public BroObj { public: - Case(ListExpr* c, id_list* types, Stmt* arg_s); + Case(IntrusivePtr c, id_list* types, IntrusivePtr arg_s); ~Case() override; - const ListExpr* ExprCases() const { return expr_cases; } - ListExpr* ExprCases() { return expr_cases; } + const ListExpr* ExprCases() const { return expr_cases.get(); } + ListExpr* ExprCases() { return expr_cases.get(); } const id_list* TypeCases() const { return type_cases; } id_list* TypeCases() { return type_cases; } - const Stmt* Body() const { return s; } - Stmt* Body() { return s; } + const Stmt* Body() const { return s.get(); } + Stmt* Body() { return s.get(); } void Describe(ODesc* d) const override; TraversalCode Traverse(TraversalCallback* cb) const; protected: - friend class Stmt; - Case() { expr_cases = 0; type_cases = 0; s = 0; } - - ListExpr* expr_cases; + IntrusivePtr expr_cases; id_list* type_cases; - Stmt* s; + IntrusivePtr s; }; typedef PList case_list; class SwitchStmt : public ExprStmt { public: - SwitchStmt(Expr* index, case_list* cases); + SwitchStmt(IntrusivePtr index, case_list* cases); ~SwitchStmt() override; const case_list* Cases() const { return cases; } @@ -204,10 +193,7 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; protected: - friend class Stmt; - SwitchStmt() { cases = 0; default_case_idx = -1; comp_hash = 0; } - - Val* DoExec(Frame* f, Val* v, stmt_flow_type& flow) const override; + IntrusivePtr DoExec(Frame* f, Val* v, stmt_flow_type& flow) const override; int IsPure() const override; // Initialize composite hash and case label map. @@ -238,51 +224,40 @@ protected: class AddStmt : public ExprStmt { public: - explicit AddStmt(Expr* e); + explicit AddStmt(IntrusivePtr e); int IsPure() const override; - Val* Exec(Frame* f, stmt_flow_type& flow) const override; + IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const override; TraversalCode Traverse(TraversalCallback* cb) const override; - -protected: - friend class Stmt; - AddStmt() {} }; class DelStmt : public ExprStmt { public: - explicit DelStmt(Expr* e); + explicit DelStmt(IntrusivePtr e); int IsPure() const override; - Val* Exec(Frame* f, stmt_flow_type& flow) const override; + IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const override; TraversalCode Traverse(TraversalCallback* cb) const override; - -protected: - friend class Stmt; - DelStmt() {} }; class EventStmt : public ExprStmt { public: - explicit EventStmt(EventExpr* e); + explicit EventStmt(IntrusivePtr e); - Val* Exec(Frame* f, stmt_flow_type& flow) const override; + IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const override; TraversalCode Traverse(TraversalCallback* cb) const override; protected: - friend class Stmt; - EventStmt() { event_expr = 0; } - - EventExpr* event_expr; + IntrusivePtr event_expr; }; class WhileStmt : public Stmt { public: - WhileStmt(Expr* loop_condition, Stmt* body); + WhileStmt(IntrusivePtr loop_condition, IntrusivePtr body); ~WhileStmt() override; int IsPure() const override; @@ -292,29 +267,24 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; protected: - friend class Stmt; + IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const override; - WhileStmt() - { loop_condition = 0; body = 0; } - - Val* Exec(Frame* f, stmt_flow_type& flow) const override; - - Expr* loop_condition; - Stmt* body; + IntrusivePtr loop_condition; + IntrusivePtr body; }; class ForStmt : public ExprStmt { public: - ForStmt(id_list* loop_vars, Expr* loop_expr); + ForStmt(id_list* loop_vars, IntrusivePtr loop_expr); // Special constructor for key value for loop. - ForStmt(id_list* loop_vars, Expr* loop_expr, ID* val_var); + ForStmt(id_list* loop_vars, IntrusivePtr loop_expr, IntrusivePtr val_var); ~ForStmt() override; - void AddBody(Stmt* arg_body) { body = arg_body; } + void AddBody(IntrusivePtr arg_body) { body = std::move(arg_body); } const id_list* LoopVar() const { return loop_vars; } - const Expr* LoopExpr() const { return e; } - const Stmt* LoopBody() const { return body; } + const Expr* LoopExpr() const { return e.get(); } + const Stmt* LoopBody() const { return body.get(); } int IsPure() const override; @@ -323,23 +293,20 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; protected: - friend class Stmt; - ForStmt() { loop_vars = 0; body = 0; } - - Val* DoExec(Frame* f, Val* v, stmt_flow_type& flow) const override; + IntrusivePtr DoExec(Frame* f, Val* v, stmt_flow_type& flow) const override; id_list* loop_vars; - Stmt* body; + IntrusivePtr body; // Stores the value variable being used for a key value for loop. // Always set to nullptr unless special constructor is called. - ID* value_var = nullptr; + IntrusivePtr value_var; }; class NextStmt : public Stmt { public: NextStmt() : Stmt(STMT_NEXT) { } - Val* Exec(Frame* f, stmt_flow_type& flow) const override; + IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const override; int IsPure() const override; void Describe(ODesc* d) const override; @@ -353,7 +320,7 @@ class BreakStmt : public Stmt { public: BreakStmt() : Stmt(STMT_BREAK) { } - Val* Exec(Frame* f, stmt_flow_type& flow) const override; + IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const override; int IsPure() const override; void Describe(ODesc* d) const override; @@ -367,7 +334,7 @@ class FallthroughStmt : public Stmt { public: FallthroughStmt() : Stmt(STMT_FALLTHROUGH) { } - Val* Exec(Frame* f, stmt_flow_type& flow) const override; + IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const override; int IsPure() const override; void Describe(ODesc* d) const override; @@ -379,15 +346,11 @@ protected: class ReturnStmt : public ExprStmt { public: - explicit ReturnStmt(Expr* e); + explicit ReturnStmt(IntrusivePtr e); - Val* Exec(Frame* f, stmt_flow_type& flow) const override; + IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const override; void Describe(ODesc* d) const override; - -protected: - friend class Stmt; - ReturnStmt() {} }; class StmtList : public Stmt { @@ -395,7 +358,7 @@ public: StmtList(); ~StmtList() override; - Val* Exec(Frame* f, stmt_flow_type& flow) const override; + IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const override; const stmt_list& Stmts() const { return stmts; } stmt_list& Stmts() { return stmts; } @@ -415,7 +378,7 @@ public: EventBodyList() : StmtList() { topmost = false; tag = STMT_EVENT_BODY_LIST; } - Val* Exec(Frame* f, stmt_flow_type& flow) const override; + IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const override; void Describe(ODesc* d) const override; @@ -433,7 +396,7 @@ public: ~InitStmt() override; - Val* Exec(Frame* f, stmt_flow_type& flow) const override; + IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const override; const id_list* Inits() const { return inits; } @@ -442,9 +405,6 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; protected: - friend class Stmt; - InitStmt() { inits = 0; } - id_list* inits; }; @@ -452,7 +412,7 @@ class NullStmt : public Stmt { public: NullStmt() : Stmt(STMT_NULL) { } - Val* Exec(Frame* f, stmt_flow_type& flow) const override; + IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const override; int IsPure() const override; void Describe(ODesc* d) const override; @@ -463,27 +423,27 @@ public: class WhenStmt : public Stmt { public: // s2 is null if no timeout block given. - WhenStmt(Expr* cond, Stmt* s1, Stmt* s2, Expr* timeout, bool is_return); + WhenStmt(IntrusivePtr cond, + IntrusivePtr s1, IntrusivePtr s2, + IntrusivePtr timeout, bool is_return); ~WhenStmt() override; - Val* Exec(Frame* f, stmt_flow_type& flow) const override; + IntrusivePtr Exec(Frame* f, stmt_flow_type& flow) const override; int IsPure() const override; - const Expr* Cond() const { return cond; } - const Stmt* Body() const { return s1; } - const Expr* TimeoutExpr() const { return timeout; } - const Stmt* TimeoutBody() const { return s2; } + const Expr* Cond() const { return cond.get(); } + const Stmt* Body() const { return s1.get(); } + const Expr* TimeoutExpr() const { return timeout.get(); } + const Stmt* TimeoutBody() const { return s2.get(); } void Describe(ODesc* d) const override; TraversalCode Traverse(TraversalCallback* cb) const override; protected: - WhenStmt() { cond = 0; s1 = s2 = 0; timeout = 0; is_return = 0; } - - Expr* cond; - Stmt* s1; - Stmt* s2; - Expr* timeout; + IntrusivePtr cond; + IntrusivePtr s1; + IntrusivePtr s2; + IntrusivePtr timeout; bool is_return; }; diff --git a/src/Trigger.cc b/src/Trigger.cc index 5a600074a6..15d912fb2d 100644 --- a/src/Trigger.cc +++ b/src/Trigger.cc @@ -63,13 +63,10 @@ TraversalCode TriggerTraversalCallback::PreExpr(const Expr* expr) try { - Val* v = e->Eval(trigger->frame); + auto v = e->Eval(trigger->frame); if ( v ) - { - trigger->Register(v); - Unref(v); - } + trigger->Register(v.get()); } catch ( InterpreterException& ) { /* Already reported */ } @@ -157,7 +154,7 @@ Trigger::Trigger(Expr* arg_cond, Stmt* arg_body, Stmt* arg_timeout_stmts, arg_frame->SetDelayed(); } - Val* timeout_val = nullptr; + IntrusivePtr timeout_val; if ( arg_timeout ) { @@ -172,7 +169,6 @@ Trigger::Trigger(Expr* arg_cond, Stmt* arg_body, Stmt* arg_timeout_stmts, if ( timeout_val ) { timeout_value = timeout_val->AsInterval(); - Unref(timeout_val); } // Make sure we don't get deleted if somebody calls a method like @@ -271,7 +267,7 @@ bool Trigger::Eval() f->SetTrigger(this); - Val* v = nullptr; + IntrusivePtr v; try { @@ -294,7 +290,6 @@ bool Trigger::Eval() { // Not true. Perhaps next time... DBG_LOG(DBG_NOTIFIERS, "%s: trigger condition is false", Name()); - Unref(v); Unref(f); Init(); return false; @@ -303,8 +298,7 @@ bool Trigger::Eval() DBG_LOG(DBG_NOTIFIERS, "%s: trigger condition is true, executing", Name()); - Unref(v); - v = 0; + v = nullptr; stmt_flow_type flow; try @@ -327,12 +321,11 @@ bool Trigger::Eval() delete [] pname; #endif - trigger->Cache(frame->GetCall(), v); + trigger->Cache(frame->GetCall(), v.get()); trigger->Release(); frame->ClearTrigger(); } - Unref(v); Unref(f); if ( timer ) @@ -353,12 +346,12 @@ void Trigger::Timeout() if ( timeout_stmts ) { stmt_flow_type flow; - Frame* f = frame->Clone(); - Val* v = 0; + IntrusivePtr f{AdoptRef{}, frame->Clone()}; + IntrusivePtr v; try { - v = timeout_stmts->Exec(f, flow); + v = timeout_stmts->Exec(f.get(), flow); } catch ( InterpreterException& e ) { /* Already reported. */ } @@ -375,13 +368,10 @@ void Trigger::Timeout() DBG_LOG(DBG_NOTIFIERS, "%s: trigger has parent %s, caching timeout result", Name(), pname); delete [] pname; #endif - trigger->Cache(frame->GetCall(), v); + trigger->Cache(frame->GetCall(), v.get()); trigger->Release(); frame->ClearTrigger(); } - - Unref(v); - Unref(f); } Disable(); diff --git a/src/Type.cc b/src/Type.cc index 3cb6b09257..b855e0cbde 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -417,8 +417,7 @@ SetType::SetType(TypeList* ind, ListExpr* arg_elements) : TableType(ind, 0) for ( int i = 2; t && i < tl->length(); ++i ) { - BroType* t_new = - merge_types(t, (*tl)[i]); + BroType* t_new = merge_types(t, (*tl)[i]); Unref(t); t = t_new; } @@ -705,7 +704,7 @@ Val* RecordType::FieldDefault(int field) const const Attr* def_attr = td->attrs->FindAttr(ATTR_DEFAULT); - return def_attr ? def_attr->AttrExpr()->Eval(0) : 0; + return def_attr ? def_attr->AttrExpr()->Eval(nullptr).release() : nullptr; } int RecordType::FieldOffset(const char* field) const @@ -1172,18 +1171,18 @@ void EnumType::CheckAndAddName(const string& module_name, const char* name, return; } - ID* id = lookup_ID(name, module_name.c_str()); + auto id = lookup_ID(name, module_name.c_str()); if ( ! id ) { id = install_ID(name, module_name.c_str(), true, is_export); - id->SetType(this->Ref()); + id->SetType({NewRef{}, this}); id->SetEnumConst(); if ( deprecation ) id->MakeDeprecated(deprecation); - zeekygen_mgr->Identifier(id); + zeekygen_mgr->Identifier(std::move(id)); } else { @@ -1195,13 +1194,10 @@ void EnumType::CheckAndAddName(const string& module_name, const char* name, || (id->HasVal() && val != id->ID_Val()->AsEnum()) || (names.find(fullname) != names.end() && names[fullname] != val) ) { - Unref(id); reporter->Error("identifier or enumerator value in enumerated type definition already exists"); SetError(); return; } - - Unref(id); } AddNameInternal(module_name, name, val, is_export); @@ -1357,6 +1353,9 @@ VectorType::VectorType(BroType* element_type) VectorType* VectorType::ShallowClone() { + if ( yield_type ) + yield_type->Ref(); + return new VectorType(yield_type); } @@ -2065,19 +2064,19 @@ BroType* init_type(Expr* init) { if ( init->Tag() != EXPR_LIST ) { - BroType* t = init->InitType(); + auto t = init->InitType(); + if ( ! t ) - return 0; + return nullptr; if ( t->Tag() == TYPE_LIST && t->AsTypeList()->Types()->length() != 1 ) { init->Error("list used in scalar initialization"); - Unref(t); - return 0; + return nullptr; } - return t; + return t.release(); } ListExpr* init_list = init->AsListExpr(); @@ -2086,77 +2085,59 @@ BroType* init_type(Expr* init) if ( el.length() == 0 ) { init->Error("empty list in untyped initialization"); - return 0; + return nullptr; } // Could be a record, a set, or a list of table elements. Expr* e0 = el[0]; + if ( e0->IsRecordElement(0) ) // ListExpr's know how to build a record from their // components. - return init_list->InitType(); + return init_list->InitType().release(); + + auto t = e0->InitType(); - BroType* t = e0->InitType(); if ( t ) - { - BroType* old_t = t; - t = reduce_type(t); - - if ( t ) - // reduce_type() does not return a referenced pointer, but we want - // to own a reference, so create one here - Ref(t); - - // reduce_type() does not adopt our reference passed as parameter, so - // we need to release it (after the Ref() call above) - Unref(old_t); - } + t = {NewRef{}, reduce_type(t.get())}; if ( ! t ) - return 0; + return nullptr; for ( int i = 1; t && i < el.length(); ++i ) { - BroType* el_t = el[i]->InitType(); - BroType* ti = el_t ? reduce_type(el_t) : 0; + auto el_t = el[i]->InitType(); + BroType* ti = el_t ? reduce_type(el_t.get()) : 0; + if ( ! ti ) - { - Unref(t); - return 0; - } + return nullptr; - if ( same_type(t, ti) ) - { - Unref(ti); + if ( same_type(t.get(), ti) ) continue; - } - BroType* t_merge = merge_types(t, ti); - Unref(t); - Unref(ti); - t = t_merge; + t = IntrusivePtr{AdoptRef{}, merge_types(t.get(), ti)}; } if ( ! t ) { init->Error("type error in initialization"); - return 0; + return nullptr; } if ( t->Tag() == TYPE_TABLE && ! t->AsTableType()->IsSet() ) // A list of table elements. - return t; + return t.release(); // A set. If the index type isn't yet a type list, make // it one, as that's what's required for creating a set type. if ( t->Tag() != TYPE_LIST ) { - TypeList* tl = new TypeList(t); - tl->Append(t); - t = tl; + auto tl = make_intrusive(t.get()->Ref()); + tl->Append(t.release()); + t = std::move(tl); } - return new SetType(t->AsTypeList(), 0); + return new SetType(t.release()->AsTypeList(), 0); } bool is_atomic_type(const BroType* t) diff --git a/src/Type.h b/src/Type.h index 538d2871f5..5fe5c5b6be 100644 --- a/src/Type.h +++ b/src/Type.h @@ -699,16 +699,16 @@ extern OpaqueType* x509_opaque_type; extern OpaqueType* ocsp_resp_opaque_type; extern OpaqueType* paraglob_type; -// Returns the Bro basic (non-parameterized) type with the given type. +// Returns the basic (non-parameterized) type with the given type. // The reference count of the type is not increased. BroType* base_type_no_ref(TypeTag tag); -// Returns the BRO basic (non-parameterized) type with the given type. +// Returns the basic (non-parameterized) type with the given type. // The caller assumes responsibility for a reference to the type. inline BroType* base_type(TypeTag tag) { return base_type_no_ref(tag)->Ref(); } -// Returns the BRO basic error type. +// Returns the basic error type. inline BroType* error_type() { return base_type(TYPE_ERROR); } // True if the two types are equivalent. If is_init is true then the test is diff --git a/src/Val.cc b/src/Val.cc index 5bfa228e4b..4185e122e5 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -1745,14 +1745,14 @@ Val* TableVal::Default(Val* index) record_promotion_compatible(dtype->AsRecordType(), ytype->AsRecordType()) ) { - Expr* coerce = new RecordCoerceExpr(def_attr->AttrExpr()->Ref(), - ytype->AsRecordType()); - def_val = coerce->Eval(0); - Unref(coerce); + auto coerce = make_intrusive( + IntrusivePtr{NewRef{}, def_attr->AttrExpr()}, + IntrusivePtr{NewRef{}, ytype->AsRecordType()}); + def_val = coerce->Eval(0).release(); } else - def_val = def_attr->AttrExpr()->Eval(0); + def_val = def_attr->AttrExpr()->Eval(0).release(); } if ( ! def_val ) @@ -1958,7 +1958,7 @@ void TableVal::CallChangeFunc(const Val* index, Val* old_value, OnChangeType tpe try { - IntrusivePtr thefunc{AdoptRef{}, change_func->Eval(nullptr)}; + auto thefunc = change_func->Eval(nullptr); if ( ! thefunc ) { @@ -2250,7 +2250,7 @@ void TableVal::InitDefaultFunc(Frame* f) ytype->AsRecordType()) ) return; // TableVal::Default will handle this. - def_val = def_attr->AttrExpr()->Eval(f); + def_val = def_attr->AttrExpr()->Eval(f).release(); } void TableVal::InitTimer(double delay) @@ -2375,9 +2375,8 @@ double TableVal::GetExpireTime() try { - Val* timeout = expire_time->Eval(0); + auto timeout = expire_time->Eval(nullptr); interval = (timeout ? timeout->AsInterval() : -1); - Unref(timeout); } catch ( InterpreterException& e ) { @@ -2407,7 +2406,7 @@ double TableVal::CallExpireFunc(Val* idx) try { - Val* vf = expire_func->Eval(0); + auto vf = expire_func->Eval(nullptr); if ( ! vf ) { @@ -2419,7 +2418,6 @@ double TableVal::CallExpireFunc(Val* idx) if ( vf->Type()->Tag() != TYPE_FUNC ) { vf->Error("not a function"); - Unref(vf); Unref(idx); return 0; } @@ -2467,8 +2465,6 @@ double TableVal::CallExpireFunc(Val* idx) secs = result->AsInterval(); Unref(result); } - - Unref(vf); } catch ( InterpreterException& e ) @@ -2574,8 +2570,8 @@ RecordVal::RecordVal(RecordType* t, bool init_fields) : Val(t) for ( int i = 0; i < n; ++i ) { Attributes* a = t->FieldDecl(i)->attrs; - Attr* def_attr = a ? a->FindAttr(ATTR_DEFAULT) : 0; - Val* def = def_attr ? def_attr->AttrExpr()->Eval(0) : 0; + Attr* def_attr = a ? a->FindAttr(ATTR_DEFAULT) : nullptr; + auto def = def_attr ? def_attr->AttrExpr()->Eval(nullptr) : nullptr; BroType* type = t->FieldDecl(i)->type; if ( def && type->Tag() == TYPE_RECORD && @@ -2585,8 +2581,7 @@ RecordVal::RecordVal(RecordType* t, bool init_fields) : Val(t) Val* tmp = def->AsRecordVal()->CoerceTo(type->AsRecordType()); if ( tmp ) { - Unref(def); - def = tmp; + def = {AdoptRef{}, tmp}; } } @@ -2595,18 +2590,16 @@ RecordVal::RecordVal(RecordType* t, bool init_fields) : Val(t) TypeTag tag = type->Tag(); if ( tag == TYPE_RECORD ) - def = new RecordVal(type->AsRecordType()); + def = make_intrusive(type->AsRecordType()); else if ( tag == TYPE_TABLE ) - def = new TableVal(type->AsTableType(), a); + def = make_intrusive(type->AsTableType(), a); else if ( tag == TYPE_VECTOR ) - def = new VectorVal(type->AsVectorType()); + def = make_intrusive(type->AsVectorType()); } - vl->push_back(def ? def->Ref() : 0); - - Unref(def); + vl->push_back(def.release()); } } @@ -2707,12 +2700,13 @@ RecordVal* RecordVal::CoerceTo(const RecordType* t, Val* aggr, bool allow_orphan // Check for allowable optional fields is outside the loop, below. continue; - if ( ar_t->FieldType(t_i)->Tag() == TYPE_RECORD - && ! same_type(ar_t->FieldType(t_i), v->Type()) ) + if ( ar_t->FieldType(t_i)->Tag() == TYPE_RECORD && + ! same_type(ar_t->FieldType(t_i), v->Type()) ) { - Expr* rhs = new ConstExpr(v->Ref()); - Expr* e = new RecordCoerceExpr(rhs, ar_t->FieldType(t_i)->AsRecordType()); - ar->Assign(t_i, e->Eval(0)); + auto rhs = make_intrusive(IntrusivePtr{NewRef{}, v}); + auto e = make_intrusive(std::move(rhs), + IntrusivePtr{NewRef{}, ar_t->FieldType(t_i)->AsRecordType()}); + ar->Assign(t_i, e->Eval(nullptr).release()); continue; } @@ -3041,10 +3035,12 @@ void VectorVal::ValDescribe(ODesc* d) const d->Add("]"); } -Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* expr_location) +IntrusivePtr check_and_promote(IntrusivePtr v, const BroType* t, + int is_init, + const Location* expr_location) { if ( ! v ) - return 0; + return nullptr; BroType* vt = v->Type(); @@ -3065,20 +3061,18 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* ex if ( same_type(t, vt, is_init) ) return v; - t->Error("type clash", v, 0, expr_location); - Unref(v); - return 0; + t->Error("type clash", v.get(), 0, expr_location); + return nullptr; } if ( ! BothArithmetic(t_tag, v_tag) && (! IsArithmetic(v_tag) || t_tag != TYPE_TIME || ! v->IsZero()) ) { if ( t_tag == TYPE_LIST || v_tag == TYPE_LIST ) - t->Error("list mixed with scalar", v, 0, expr_location); + t->Error("list mixed with scalar", v.get(), 0, expr_location); else - t->Error("arithmetic mixed with non-arithmetic", v, 0, expr_location); - Unref(v); - return 0; + t->Error("arithmetic mixed with non-arithmetic", v.get(), 0, expr_location); + return nullptr; } if ( v_tag == t_tag ) @@ -3089,9 +3083,8 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* ex TypeTag mt = max_type(t_tag, v_tag); if ( mt != t_tag ) { - t->Error("over-promotion of arithmetic value", v, 0, expr_location); - Unref(v); - return 0; + t->Error("over-promotion of arithmetic value", v.get(), 0, expr_location); + return nullptr; } } @@ -3103,55 +3096,50 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* ex // Already has the right internal type. return v; - Val* promoted_v; + IntrusivePtr promoted_v; + switch ( it ) { case TYPE_INTERNAL_INT: - if ( ( vit == TYPE_INTERNAL_UNSIGNED || vit == TYPE_INTERNAL_DOUBLE ) && Val::WouldOverflow(vt, t, v) ) + if ( ( vit == TYPE_INTERNAL_UNSIGNED || vit == TYPE_INTERNAL_DOUBLE ) && Val::WouldOverflow(vt, t, v.get()) ) { - t->Error("overflow promoting from unsigned/double to signed arithmetic value", v, 0, expr_location); - Unref(v); - return 0; + t->Error("overflow promoting from unsigned/double to signed arithmetic value", v.get(), 0, expr_location); + return nullptr; } else if ( t_tag == TYPE_INT ) - promoted_v = val_mgr->GetInt(v->CoerceToInt()); + promoted_v = {AdoptRef{}, val_mgr->GetInt(v->CoerceToInt())}; else // enum { reporter->InternalError("bad internal type in check_and_promote()"); - Unref(v); - return 0; + return nullptr; } break; case TYPE_INTERNAL_UNSIGNED: - if ( ( vit == TYPE_INTERNAL_DOUBLE || vit == TYPE_INTERNAL_INT) && Val::WouldOverflow(vt, t, v) ) + if ( ( vit == TYPE_INTERNAL_DOUBLE || vit == TYPE_INTERNAL_INT) && Val::WouldOverflow(vt, t, v.get()) ) { - t->Error("overflow promoting from signed/double to unsigned arithmetic value", v, 0, expr_location); - Unref(v); - return 0; + t->Error("overflow promoting from signed/double to unsigned arithmetic value", v.get(), 0, expr_location); + return nullptr; } else if ( t_tag == TYPE_COUNT || t_tag == TYPE_COUNTER ) - promoted_v = val_mgr->GetCount(v->CoerceToUnsigned()); + promoted_v = {AdoptRef{}, val_mgr->GetCount(v->CoerceToUnsigned())}; else // port { reporter->InternalError("bad internal type in check_and_promote()"); - Unref(v); - return 0; + return nullptr; } break; case TYPE_INTERNAL_DOUBLE: - promoted_v = new Val(v->CoerceToDouble(), t_tag); + promoted_v = make_intrusive(v->CoerceToDouble(), t_tag); break; default: reporter->InternalError("bad internal type in check_and_promote()"); - Unref(v); - return 0; + return nullptr; } - Unref(v); return promoted_v; } @@ -3222,30 +3210,30 @@ void delete_vals(val_list* vals) } } -Val* cast_value_to_type(Val* v, BroType* t) +IntrusivePtr cast_value_to_type(Val* v, BroType* t) { // Note: when changing this function, adapt all three of // cast_value_to_type()/can_cast_value_to_type()/can_cast_value_to_type(). if ( ! v ) - return 0; + return nullptr; // Always allow casting to same type. This also covers casting 'any' // to the actual type. if ( same_type(v->Type(), t) ) - return v->Ref(); + return {NewRef{}, v}; if ( same_type(v->Type(), bro_broker::DataVal::ScriptDataType()) ) { auto dv = v->AsRecordVal()->Lookup(0); if ( ! dv ) - return 0; + return nullptr; - return static_cast(dv)->castTo(t).release(); + return static_cast(dv)->castTo(t); } - return 0; + return nullptr; } bool can_cast_value_to_type(const Val* v, BroType* t) diff --git a/src/Val.h b/src/Val.h index 0777d79779..ae8915fa08 100644 --- a/src/Val.h +++ b/src/Val.h @@ -29,6 +29,7 @@ using std::string; template class IntrusivePtr; template class PDict; +template class IntrusivePtr; class IterCookie; class Val; @@ -1018,13 +1019,9 @@ protected: // Unref()'ing the original. If not a match, generates an error message // and returns nil, also Unref()'ing v. If is_init is true, then // the checking is done in the context of an initialization. -extern Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* expr_location = nullptr); - -// Given a pointer to where a Val's core (i.e., its BRO value) resides, -// returns a corresponding newly-created or Ref()'d Val. ptr must already -// be properly aligned. Returns the size of the core in bytes in 'n'. -// If t corresponds to a variable-length type, n must give the size on entry. -Val* recover_val(void* ptr, BroType* t, int& n); +extern IntrusivePtr check_and_promote(IntrusivePtr v, + const BroType* t, int is_init, + const Location* expr_location = nullptr); extern int same_val(const Val* v1, const Val* v2); extern int same_atomic_val(const Val* v1, const Val* v2); @@ -1036,10 +1033,9 @@ extern void delete_vals(val_list* vals); inline bool is_vector(Val* v) { return v->Type()->Tag() == TYPE_VECTOR; } // Returns v casted to type T if the type supports that. Returns null if not. -// The returned value will be ref'ed. // // Note: This implements the script-level cast operator. -extern Val* cast_value_to_type(Val* v, BroType* t); +extern IntrusivePtr cast_value_to_type(Val* v, BroType* t); // Returns true if v can be casted to type T. If so, check_and_cast() will // succeed as well. diff --git a/src/Var.cc b/src/Var.cc index c1d9b61022..b520c1e498 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -8,6 +8,7 @@ #include "Val.h" #include "Expr.h" #include "Func.h" +#include "IntrusivePtr.h" #include "Stmt.h" #include "Scope.h" #include "Reporter.h" @@ -15,11 +16,12 @@ #include "Traverse.h" #include "module_util.h" -static Val* init_val(Expr* init, const BroType* t, Val* aggr) +static IntrusivePtr init_val(Expr* init, const BroType* t, + IntrusivePtr aggr) { try { - return init->InitVal(t, aggr); + return init->InitVal(t, std::move(aggr)); } catch ( InterpreterException& e ) { @@ -27,22 +29,22 @@ static Val* init_val(Expr* init, const BroType* t, Val* aggr) } } -static void make_var(ID* id, BroType* t, init_class c, Expr* init, - attr_list* attr, decl_type dt, int do_init) +static void make_var(ID* id, IntrusivePtr t, init_class c, + IntrusivePtr init, attr_list* attr, decl_type dt, + int do_init) { if ( id->Type() ) { if ( id->IsRedefinable() || (! init && attr) ) { - BroObj* redef_obj = init ? (BroObj*) init : (BroObj*) t; + BroObj* redef_obj = init ? (BroObj*) init.get() : (BroObj*) t.get(); if ( dt != VAR_REDEF ) id->Warn("redefinition requires \"redef\"", redef_obj, 1); } else if ( dt != VAR_REDEF || init || ! attr ) { - id->Error("already defined", init); - Unref(init); + id->Error("already defined", init.get()); return; } } @@ -52,29 +54,26 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init, if ( ! id->Type() ) { id->Error("\"redef\" used but not previously defined"); - Unref(init); return; } if ( ! t ) - t = id->Type(); + t = {NewRef{}, id->Type()}; } if ( id->Type() && id->Type()->Tag() != TYPE_ERROR ) { if ( dt != VAR_REDEF && - (! init || ! do_init || (! t && ! (t = init_type(init)))) ) + (! init || ! do_init || (! t && ! (t = {AdoptRef{}, init_type(init.get())}))) ) { - id->Error("already defined", init); - Unref(init); + id->Error("already defined", init.get()); return; } // Allow redeclaration in order to initialize. - if ( ! same_type(t, id->Type()) ) + if ( ! same_type(t.get(), id->Type()) ) { - id->Error("redefinition changes type", init); - Unref(init); + id->Error("redefinition changes type", init.get()); return; } } @@ -88,13 +87,11 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init, { if ( init ) { - id->Error("double initialization", init); - Unref(init); + id->Error("double initialization", init.get()); return; } - Ref(elements); - init = elements; + init = {NewRef{}, elements}; } } @@ -103,48 +100,38 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init, if ( ! init ) { id->Error("no type given"); - Unref(init); return; } - t = init_type(init); + t = {AdoptRef{}, init_type(init.get())}; if ( ! t ) { - id->SetType(error_type()); - Unref(init); + id->SetType({AdoptRef{}, error_type()}); return; } } - else - Ref(t); id->SetType(t); if ( attr ) - id->AddAttrs(new Attributes(attr, t, false, id->IsGlobal())); + id->AddAttrs(make_intrusive(attr, t.get(), false, id->IsGlobal())); if ( init ) { switch ( init->Tag() ) { case EXPR_TABLE_CONSTRUCTOR: { - TableConstructorExpr* ctor = (TableConstructorExpr*) init; + TableConstructorExpr* ctor = (TableConstructorExpr*) init.get(); if ( ctor->Attrs() ) - { - ::Ref(ctor->Attrs()); - id->AddAttrs(ctor->Attrs()); - } + id->AddAttrs({NewRef{}, ctor->Attrs()}); } break; case EXPR_SET_CONSTRUCTOR: { - SetConstructorExpr* ctor = (SetConstructorExpr*) init; + SetConstructorExpr* ctor = (SetConstructorExpr*) init.get(); if ( ctor->Attrs() ) - { - ::Ref(ctor->Attrs()); - id->AddAttrs(ctor->Attrs()); - } + id->AddAttrs({NewRef{}, ctor->Attrs()}); } break; @@ -168,40 +155,38 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init, else if ( dt != VAR_REDEF || init || ! attr ) { - Val* aggr; + IntrusivePtr aggr; + if ( t->Tag() == TYPE_RECORD ) { - aggr = new RecordVal(t->AsRecordType()); + aggr = make_intrusive(t->AsRecordType()); if ( init && t ) // Have an initialization and type is not deduced. - init = new RecordCoerceExpr(init, t->AsRecordType()); + init = make_intrusive(std::move(init), + IntrusivePtr{NewRef{}, t->AsRecordType()}); } else if ( t->Tag() == TYPE_TABLE ) - aggr = new TableVal(t->AsTableType(), id->Attrs()); + aggr = make_intrusive(t->AsTableType(), id->Attrs()); else if ( t->Tag() == TYPE_VECTOR ) - aggr = new VectorVal(t->AsVectorType()); + aggr = make_intrusive(t->AsVectorType()); - else - aggr = 0; + IntrusivePtr v; - Val* v = 0; if ( init ) { - v = init_val(init, t, aggr); + v = init_val(init.get(), t.get(), aggr); + if ( ! v ) - { - Unref(init); return; - } } if ( aggr ) - id->SetVal(aggr, c); + id->SetVal(std::move(aggr), c); else if ( v ) - id->SetVal(v, c); + id->SetVal(std::move(v), c); } } @@ -221,8 +206,6 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init, id->SetOption(); } - Unref(init); - id->UpdateValAttrs(); if ( t && t->Tag() == TYPE_FUNC && @@ -233,70 +216,77 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init, // we can later access the ID even if no implementations have been // defined. Func* f = new BroFunc(id, 0, 0, 0, 0); - id->SetVal(new Val(f)); + id->SetVal(make_intrusive(f)); } } -void add_global(ID* id, BroType* t, init_class c, Expr* init, - attr_list* attr, decl_type dt) +void add_global(ID* id, IntrusivePtr t, init_class c, + IntrusivePtr init, attr_list* attr, decl_type dt) { - make_var(id, t, c, init, attr, dt, 1); + make_var(id, std::move(t), c, std::move(init), attr, dt, 1); } -Stmt* add_local(ID* id, BroType* t, init_class c, Expr* init, - attr_list* attr, decl_type dt) +IntrusivePtr add_local(IntrusivePtr id, IntrusivePtr t, + init_class c, IntrusivePtr init, + attr_list* attr, decl_type dt) { - make_var(id, t, c, init ? init->Ref() : init, attr, dt, 0); + make_var(id.get(), std::move(t), c, init, attr, dt, 0); if ( init ) { if ( c != INIT_FULL ) id->Error("can't use += / -= for initializations of local variables"); - Ref(id); - - Expr* name_expr = new NameExpr(id, dt == VAR_CONST); - Stmt* stmt = - new ExprStmt(new AssignExpr(name_expr, init, 0, 0, - id->Attrs() ? id->Attrs()->Attrs() : 0 )); - stmt->SetLocationInfo(init->GetLocationInfo()); + // copy Location to the stack, because AssignExpr may free "init" + const Location location = init->GetLocationInfo() ? + *init->GetLocationInfo() : no_location; + auto name_expr = make_intrusive(id, dt == VAR_CONST); + auto attrs = id->Attrs() ? id->Attrs()->Attrs() : nullptr; + auto assign_expr = make_intrusive(std::move(name_expr), + std::move(init), 0, + nullptr, attrs); + auto stmt = make_intrusive(std::move(assign_expr)); + stmt->SetLocationInfo(&location); return stmt; } else { - current_scope()->AddInit(id); - return new NullStmt; + current_scope()->AddInit(id.release()); + return make_intrusive(); } } -extern Expr* add_and_assign_local(ID* id, Expr* init, Val* val) +extern IntrusivePtr add_and_assign_local(IntrusivePtr id, + IntrusivePtr init, + IntrusivePtr val) { - make_var(id, 0, INIT_FULL, init->Ref(), 0, VAR_REGULAR, 0); - Ref(id); - return new AssignExpr(new NameExpr(id), init, 0, val); + make_var(id.get(), 0, INIT_FULL, init, 0, VAR_REGULAR, 0); + auto name_expr = make_intrusive(std::move(id)); + return make_intrusive(std::move(name_expr), std::move(init), + 0, std::move(val)); } -void add_type(ID* id, BroType* t, attr_list* attr) +void add_type(ID* id, IntrusivePtr t, attr_list* attr) { string new_type_name = id->Name(); string old_type_name = t->GetName(); - BroType* tnew = 0; + IntrusivePtr tnew; if ( (t->Tag() == TYPE_RECORD || t->Tag() == TYPE_ENUM) && old_type_name.empty() ) // An extensible type (record/enum) being declared for first time. - tnew = t; + tnew = std::move(t); else // Clone the type to preserve type name aliasing. - tnew = t->ShallowClone(); + tnew = {AdoptRef{}, t->ShallowClone()}; - BroType::AddAlias(new_type_name, tnew); + BroType::AddAlias(new_type_name, tnew.get()); if ( new_type_name != old_type_name && ! old_type_name.empty() ) - BroType::AddAlias(old_type_name, tnew); + BroType::AddAlias(old_type_name, tnew.get()); tnew->SetName(id->Name()); @@ -304,7 +294,7 @@ void add_type(ID* id, BroType* t, attr_list* attr) id->MakeType(); if ( attr ) - id->SetAttrs(new Attributes(attr, tnew, false, false)); + id->SetAttrs(make_intrusive(attr, tnew.get(), false, false)); } static void transfer_arg_defaults(RecordType* args, RecordType* recv) @@ -348,27 +338,28 @@ static bool has_attr(const attr_list* al, attr_tag tag) } void begin_func(ID* id, const char* module_name, function_flavor flavor, - int is_redef, FuncType* t, attr_list* attrs) + int is_redef, IntrusivePtr t, attr_list* attrs) { if ( flavor == FUNC_FLAVOR_EVENT ) { const BroType* yt = t->YieldType(); if ( yt && yt->Tag() != TYPE_VOID ) - id->Error("event cannot yield a value", t); + id->Error("event cannot yield a value", t.get()); t->ClearYieldType(flavor); } if ( id->Type() ) { - if ( ! same_type(id->Type(), t) ) - id->Type()->Error("incompatible types", t); + if ( ! same_type(id->Type(), t.get()) ) + id->Type()->Error("incompatible types", t.get()); - // If a previous declaration of the function had &default params, - // automatically transfer any that are missing (convenience so that - // implementations don't need to specify the &default expression again). - transfer_arg_defaults(id->Type()->AsFuncType()->Args(), t->Args()); + else + // If a previous declaration of the function had &default params, + // automatically transfer any that are missing (convenience so that + // implementations don't need to specify the &default expression again). + transfer_arg_defaults(id->Type()->AsFuncType()->Args(), t->Args()); } else if ( is_redef ) @@ -379,7 +370,7 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor, function_flavor id_flavor = id->ID_Val()->AsFunc()->Flavor(); if ( id_flavor != flavor ) - id->Error("inconsistent function flavor", t); + id->Error("inconsistent function flavor", t.get()); switch ( id_flavor ) { @@ -411,15 +402,13 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor, for ( int i = 0; i < num_args; ++i ) { TypeDecl* arg_i = args->FieldDecl(i); - ID* arg_id = lookup_ID(arg_i->id, module_name); + auto arg_id = lookup_ID(arg_i->id, module_name); if ( arg_id && ! arg_id->IsGlobal() ) arg_id->Error("argument name used twice"); - Unref(arg_id); - arg_id = install_ID(arg_i->id, module_name, false, false); - arg_id->SetType(arg_i->type->Ref()); + arg_id->SetType({NewRef{}, arg_i->type}); } if ( Attr* depr_attr = find_attr(attrs, ATTR_DEPRECATED) ) @@ -482,9 +471,10 @@ TraversalCode OuterIDBindingFinder::PostExpr(const Expr* expr) return TC_CONTINUE; } -void end_func(Stmt* body) +void end_func(IntrusivePtr body) { - auto ingredients = std::make_unique(pop_scope(), body); + auto ingredients = std::make_unique( + pop_scope().release(), body.release()); if ( streq(ingredients->id->Name(), "anonymous-function") ) { @@ -511,7 +501,7 @@ void end_func(Stmt* body) ingredients->frame_size, ingredients->priority); - ingredients->id->SetVal(new Val(f)); + ingredients->id->SetVal(make_intrusive(f)); ingredients->id->SetConst(); } @@ -524,14 +514,12 @@ void end_func(Stmt* body) Val* internal_val(const char* name) { - ID* id = lookup_ID(name, GLOBAL_MODULE_NAME); + auto id = lookup_ID(name, GLOBAL_MODULE_NAME); if ( ! id ) reporter->InternalError("internal variable %s missing", name); - Val* rval = id->ID_Val(); - Unref(id); - return rval; + return id->ID_Val(); } id_list gather_outer_ids(Scope* scope, Stmt* body) @@ -556,24 +544,20 @@ id_list gather_outer_ids(Scope* scope, Stmt* body) Val* internal_const_val(const char* name) { - ID* id = lookup_ID(name, GLOBAL_MODULE_NAME); + auto id = lookup_ID(name, GLOBAL_MODULE_NAME); if ( ! id ) reporter->InternalError("internal variable %s missing", name); if ( ! id->IsConst() ) reporter->InternalError("internal variable %s is not constant", name); - Val* rval = id->ID_Val(); - Unref(id); - return rval; + return id->ID_Val(); } Val* opt_internal_val(const char* name) { - ID* id = lookup_ID(name, GLOBAL_MODULE_NAME); - Val* rval = id ? id->ID_Val() : 0; - Unref(id); - return rval; + auto id = lookup_ID(name, GLOBAL_MODULE_NAME); + return id ? id->ID_Val() : nullptr; } double opt_internal_double(const char* name) @@ -597,23 +581,22 @@ bro_uint_t opt_internal_unsigned(const char* name) StringVal* opt_internal_string(const char* name) { Val* v = opt_internal_val(name); - return v ? v->AsStringVal() : 0; + return v ? v->AsStringVal() : nullptr; } TableVal* opt_internal_table(const char* name) { Val* v = opt_internal_val(name); - return v ? v->AsTableVal() : 0; + return v ? v->AsTableVal() : nullptr; } ListVal* internal_list_val(const char* name) { - ID* id = lookup_ID(name, GLOBAL_MODULE_NAME); + auto id = lookup_ID(name, GLOBAL_MODULE_NAME); if ( ! id ) - return 0; + return nullptr; Val* v = id->ID_Val(); - Unref(id); if ( v ) { @@ -631,18 +614,16 @@ ListVal* internal_list_val(const char* name) reporter->InternalError("internal variable %s is not a list", name); } - return 0; + return nullptr; } BroType* internal_type(const char* name) { - ID* id = lookup_ID(name, GLOBAL_MODULE_NAME); + auto id = lookup_ID(name, GLOBAL_MODULE_NAME); if ( ! id ) reporter->InternalError("internal type %s missing", name); - BroType* rval = id->Type(); - Unref(id); - return rval; + return id->Type(); } Func* internal_func(const char* name) @@ -651,7 +632,7 @@ Func* internal_func(const char* name) if ( v ) return v->AsFunc(); else - return 0; + return nullptr; } EventHandlerPtr internal_handler(const char* name) diff --git a/src/Var.h b/src/Var.h index 0282c4a489..3d78515adc 100644 --- a/src/Var.h +++ b/src/Var.h @@ -2,6 +2,7 @@ #pragma once +#include "IntrusivePtr.h" #include "ID.h" #include "Type.h" @@ -16,17 +17,25 @@ class ListVal; typedef enum { VAR_REGULAR, VAR_CONST, VAR_REDEF, VAR_OPTION, } decl_type; -extern void add_global(ID* id, BroType* t, init_class c, Expr* init, - attr_list* attr, decl_type dt); -extern Stmt* add_local(ID* id, BroType* t, init_class c, Expr* init, - attr_list* attr, decl_type dt); -extern Expr* add_and_assign_local(ID* id, Expr* init, Val* val = 0); +extern void add_global(ID* id, IntrusivePtr t, init_class c, + IntrusivePtr init, attr_list* attr, decl_type dt); -extern void add_type(ID* id, BroType* t, attr_list* attr); +extern IntrusivePtr add_local(IntrusivePtr id, + IntrusivePtr t, init_class c, + IntrusivePtr init, attr_list* attr, + decl_type dt); + +extern IntrusivePtr add_and_assign_local(IntrusivePtr id, + IntrusivePtr init, + IntrusivePtr val = nullptr); + +extern void add_type(ID* id, IntrusivePtr t, attr_list* attr); extern void begin_func(ID* id, const char* module_name, function_flavor flavor, - int is_redef, FuncType* t, attr_list* attrs = nullptr); -extern void end_func(Stmt* body); + int is_redef, IntrusivePtr t, + attr_list* attrs = nullptr); + +extern void end_func(IntrusivePtr body); // Gather all IDs referenced inside a body that aren't part of a given scope. extern id_list gather_outer_ids(Scope* scope, Stmt* body); diff --git a/src/broker/Manager.cc b/src/broker/Manager.cc index e71612597d..0a24a5ebc4 100644 --- a/src/broker/Manager.cc +++ b/src/broker/Manager.cc @@ -1210,7 +1210,7 @@ bool Manager::ProcessIdentifierUpdate(broker::zeek::IdentifierUpdate iu) return false; } - id->SetVal(val.release()); + id->SetVal(std::move(val)); return true; } diff --git a/src/input/Manager.cc b/src/input/Manager.cc index c5e56f3830..c85bc82575 100644 --- a/src/input/Manager.cc +++ b/src/input/Manager.cc @@ -973,7 +973,7 @@ bool Manager::UnrollRecordType(vector *fields, const RecordType *rec, { string name = nameprepend + rec->FieldName(i); const char* secondary = 0; - Val* c = nullptr; + IntrusivePtr c; TypeTag ty = rec->FieldType(i)->Tag(); TypeTag st = TYPE_VOID; bool optional = false; @@ -1001,7 +1001,6 @@ bool Manager::UnrollRecordType(vector *fields, const RecordType *rec, optional = true; Field* field = new Field(name.c_str(), secondary, ty, st, optional); - Unref(c); fields->push_back(field); } } @@ -2622,7 +2621,7 @@ Val* Manager::ValueToVal(const Stream* i, const Value* val, bool& have_error) co string enum_string(val->val.string_val.data, val->val.string_val.length); // let's try looking it up by global ID. - ID* id = lookup_ID(enum_string.c_str(), GLOBAL_MODULE_NAME); + auto id = lookup_ID(enum_string.c_str(), GLOBAL_MODULE_NAME); if ( ! id || ! id->IsEnumConst() ) { Warning(i, "Value '%s' for stream '%s' is not a valid enum.", diff --git a/src/main.cc b/src/main.cc index 152e3c77e9..30334c5b3e 100644 --- a/src/main.cc +++ b/src/main.cc @@ -298,16 +298,19 @@ void terminate_bro() plugin_mgr->FinishPlugins(); delete zeekygen_mgr; - delete event_registry; delete analyzer_mgr; delete file_mgr; // broker_mgr, timer_mgr, and supervisor are deleted via iosource_mgr delete iosource_mgr; + delete event_registry; delete log_mgr; delete reporter; delete plugin_mgr; delete val_mgr; + // free the global scope + pop_scope(); + reporter = 0; } @@ -714,7 +717,7 @@ int main(int argc, char** argv) if ( ! id ) reporter->InternalError("global cmd_line_bpf_filter not defined"); - id->SetVal(new StringVal(*options.pcap_filter)); + id->SetVal(make_intrusive(*options.pcap_filter)); } auto all_signature_files = options.signature_files; diff --git a/src/option.bif b/src/option.bif index 8c56fe4c38..5355216ee7 100644 --- a/src/option.bif +++ b/src/option.bif @@ -33,7 +33,7 @@ static bool call_option_handlers_and_set_value(StringVal* name, ID* i, Val* val, } // clone to prevent changes - i->SetVal(val->Clone()); + i->SetVal({AdoptRef{}, val->Clone()}); Unref(val); // Either ref'd once or function call result. return true; } @@ -206,7 +206,6 @@ function Option::set_change_handler%(ID: string, on_change: any, priority: int & } auto* func = on_change->AsFunc(); - Ref(func); - i->AddOptionHandler(func, -priority); + i->AddOptionHandler({NewRef{}, func}, -priority); return val_mgr->GetBool(1); %} diff --git a/src/parse.y b/src/parse.y index 9033c08635..0e0145776c 100644 --- a/src/parse.y +++ b/src/parse.y @@ -82,6 +82,7 @@ #include "Desc.h" #include "Expr.h" #include "Func.h" +#include "IntrusivePtr.h" #include "Stmt.h" #include "Val.h" #include "Var.h" @@ -311,157 +312,157 @@ expr: | TOK_COPY '(' expr ')' { set_location(@1, @4); - $$ = new CloneExpr($3); + $$ = new CloneExpr({AdoptRef{}, $3}); } | TOK_INCR expr { set_location(@1, @2); - $$ = new IncrExpr(EXPR_INCR, $2); + $$ = new IncrExpr(EXPR_INCR, {AdoptRef{}, $2}); } | TOK_DECR expr { set_location(@1, @2); - $$ = new IncrExpr(EXPR_DECR, $2); + $$ = new IncrExpr(EXPR_DECR, {AdoptRef{}, $2}); } | '!' expr { set_location(@1, @2); - $$ = new NotExpr($2); + $$ = new NotExpr({AdoptRef{}, $2}); } | '~' expr { set_location(@1, @2); - $$ = new ComplementExpr($2); + $$ = new ComplementExpr({AdoptRef{}, $2}); } | '-' expr %prec '!' { set_location(@1, @2); - $$ = new NegExpr($2); + $$ = new NegExpr({AdoptRef{}, $2}); } | '+' expr %prec '!' { set_location(@1, @2); - $$ = new PosExpr($2); + $$ = new PosExpr({AdoptRef{}, $2}); } | expr '+' expr { set_location(@1, @3); - $$ = new AddExpr($1, $3); + $$ = new AddExpr({AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr TOK_ADD_TO expr { set_location(@1, @3); - $$ = new AddToExpr($1, $3); + $$ = new AddToExpr({AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr '-' expr { set_location(@1, @3); - $$ = new SubExpr($1, $3); + $$ = new SubExpr({AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr TOK_REMOVE_FROM expr { set_location(@1, @3); - $$ = new RemoveFromExpr($1, $3); + $$ = new RemoveFromExpr({AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr '*' expr { set_location(@1, @3); - $$ = new TimesExpr($1, $3); + $$ = new TimesExpr({AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr '/' expr { set_location(@1, @3); - $$ = new DivideExpr($1, $3); + $$ = new DivideExpr({AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr '%' expr { set_location(@1, @3); - $$ = new ModExpr($1, $3); + $$ = new ModExpr({AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr '&' expr { set_location(@1, @3); - $$ = new BitExpr(EXPR_AND, $1, $3); + $$ = new BitExpr(EXPR_AND, {AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr '|' expr { set_location(@1, @3); - $$ = new BitExpr(EXPR_OR, $1, $3); + $$ = new BitExpr(EXPR_OR, {AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr '^' expr { set_location(@1, @3); - $$ = new BitExpr(EXPR_XOR, $1, $3); + $$ = new BitExpr(EXPR_XOR, {AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr TOK_AND_AND expr { set_location(@1, @3); - $$ = new BoolExpr(EXPR_AND_AND, $1, $3); + $$ = new BoolExpr(EXPR_AND_AND, {AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr TOK_OR_OR expr { set_location(@1, @3); - $$ = new BoolExpr(EXPR_OR_OR, $1, $3); + $$ = new BoolExpr(EXPR_OR_OR, {AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr TOK_EQ expr { set_location(@1, @3); - $$ = new EqExpr(EXPR_EQ, $1, $3); + $$ = new EqExpr(EXPR_EQ, {AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr TOK_NE expr { set_location(@1, @3); - $$ = new EqExpr(EXPR_NE, $1, $3); + $$ = new EqExpr(EXPR_NE, {AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr '<' expr { set_location(@1, @3); - $$ = new RelExpr(EXPR_LT, $1, $3); + $$ = new RelExpr(EXPR_LT, {AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr TOK_LE expr { set_location(@1, @3); - $$ = new RelExpr(EXPR_LE, $1, $3); + $$ = new RelExpr(EXPR_LE, {AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr '>' expr { set_location(@1, @3); - $$ = new RelExpr(EXPR_GT, $1, $3); + $$ = new RelExpr(EXPR_GT, {AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr TOK_GE expr { set_location(@1, @3); - $$ = new RelExpr(EXPR_GE, $1, $3); + $$ = new RelExpr(EXPR_GE, {AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr '?' expr ':' expr { set_location(@1, @5); - $$ = new CondExpr($1, $3, $5); + $$ = new CondExpr({AdoptRef{}, $1}, {AdoptRef{}, $3}, {AdoptRef{}, $5}); } | expr '=' expr @@ -473,19 +474,20 @@ expr: " in arbitrary expression contexts, only" " as a statement"); - $$ = get_assign_expr($1, $3, in_init); + $$ = get_assign_expr({AdoptRef{}, $1}, {AdoptRef{}, $3}, in_init).release(); } | TOK_LOCAL local_id '=' expr { set_location(@2, @4); - $$ = add_and_assign_local($2, $4, val_mgr->GetBool(1)); + $$ = add_and_assign_local({AdoptRef{}, $2}, {AdoptRef{}, $4}, + {AdoptRef{}, val_mgr->GetBool(1)}).release(); } | expr '[' expr_list ']' { set_location(@1, @4); - $$ = new IndexExpr($1, $3); + $$ = new IndexExpr({AdoptRef{}, $1}, {AdoptRef{}, $3}); } | index_slice @@ -493,13 +495,13 @@ expr: | expr '$' TOK_ID { set_location(@1, @3); - $$ = new FieldExpr($1, $3); + $$ = new FieldExpr({AdoptRef{}, $1}, $3); } | '$' TOK_ID '=' expr { set_location(@1, @4); - $$ = new FieldAssignExpr($2, $4); + $$ = new FieldAssignExpr($2, {AdoptRef{}, $4}); } | '$' TOK_ID func_params '=' @@ -507,28 +509,29 @@ expr: func_hdr_location = @1; func_id = current_scope()->GenerateTemporary("anonymous-function"); func_id->SetInferReturnType(true); - begin_func(func_id, - current_module.c_str(), - FUNC_FLAVOR_FUNCTION, - 0, - $3); + begin_func(func_id, current_module.c_str(), FUNC_FLAVOR_FUNCTION, + 0, {AdoptRef{}, $3}); } func_body { - $$ = new FieldAssignExpr($2, new ConstExpr(func_id->ID_Val()->Ref())); + $$ = new FieldAssignExpr($2, + make_intrusive( + IntrusivePtr{NewRef{}, func_id->ID_Val()})); Unref(func_id); } | expr TOK_IN expr { set_location(@1, @3); - $$ = new InExpr($1, $3); + $$ = new InExpr({AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr TOK_NOT_IN expr { set_location(@1, @3); - $$ = new NotExpr(new InExpr($1, $3)); + $$ = new NotExpr(make_intrusive( + IntrusivePtr{AdoptRef{}, $1}, + IntrusivePtr{AdoptRef{}, $3})); } | '[' expr_list ']' @@ -551,7 +554,7 @@ expr: } if ( is_record_ctor ) - $$ = new RecordConstructorExpr($2); + $$ = new RecordConstructorExpr({AdoptRef{}, $2}); else $$ = $2; } @@ -559,33 +562,33 @@ expr: | '[' ']' { // We interpret this as an empty record constructor. - $$ = new RecordConstructorExpr(new ListExpr); + $$ = new RecordConstructorExpr(make_intrusive()); } | TOK_RECORD '(' expr_list ')' { set_location(@1, @4); - $$ = new RecordConstructorExpr($3); + $$ = new RecordConstructorExpr({AdoptRef{}, $3}); } | TOK_TABLE '(' { ++in_init; } opt_expr_list ')' { --in_init; } opt_attr { // the ++in_init fixes up the parsing of "[x] = y" set_location(@1, @5); - $$ = new TableConstructorExpr($4, $7); + $$ = new TableConstructorExpr({AdoptRef{}, $4}, $7); } | TOK_SET '(' opt_expr_list ')' opt_attr { set_location(@1, @4); - $$ = new SetConstructorExpr($3, $5); + $$ = new SetConstructorExpr({AdoptRef{}, $3}, $5); } | TOK_VECTOR '(' opt_expr_list ')' { set_location(@1, @4); - $$ = new VectorConstructorExpr($3); + $$ = new VectorConstructorExpr({AdoptRef{}, $3}); } | expr '(' @@ -611,20 +614,27 @@ expr: { switch ( ctor_type->Tag() ) { case TYPE_RECORD: - $$ = new RecordCoerceExpr(new RecordConstructorExpr($4), - ctor_type->AsRecordType()); + { + auto rce = make_intrusive( + IntrusivePtr{AdoptRef{}, $4}); + IntrusivePtr rt{NewRef{}, ctor_type->AsRecordType()}; + $$ = new RecordCoerceExpr(std::move(rce), std::move(rt)); + } break; case TYPE_TABLE: if ( ctor_type->IsTable() ) - $$ = new TableConstructorExpr($4, 0, ctor_type); + $$ = new TableConstructorExpr({AdoptRef{}, $4}, 0, + {NewRef{}, ctor_type}); else - $$ = new SetConstructorExpr($4, 0, ctor_type); + $$ = new SetConstructorExpr({AdoptRef{}, $4}, 0, + {NewRef{}, ctor_type}); break; case TYPE_VECTOR: - $$ = new VectorConstructorExpr($4, ctor_type); + $$ = new VectorConstructorExpr({AdoptRef{}, $4}, + {NewRef{}, ctor_type}); break; default: @@ -634,7 +644,7 @@ expr: } else - $$ = new CallExpr($1, $4, in_hook > 0); + $$ = new CallExpr({AdoptRef{}, $1}, {AdoptRef{}, $4}, in_hook > 0); } | TOK_HOOK { ++in_hook; } expr @@ -649,7 +659,7 @@ expr: | expr TOK_HAS_FIELD TOK_ID { set_location(@1, @3); - $$ = new HasFieldExpr($1, $3); + $$ = new HasFieldExpr({AdoptRef{}, $1}, $3); } | anonymous_function @@ -658,14 +668,14 @@ expr: | TOK_SCHEDULE expr '{' event '}' { set_location(@1, @5); - $$ = new ScheduleExpr($2, $4); + $$ = new ScheduleExpr({AdoptRef{}, $2}, {AdoptRef{}, $4}); } | TOK_ID { set_location(@1); + auto id = lookup_ID($1, current_module.c_str()); - ID* id = lookup_ID($1, current_module.c_str()); if ( ! id ) { if ( ! in_debug ) @@ -686,12 +696,14 @@ expr: } else { + if ( id->IsDeprecated() ) + reporter->Warning("%s", id->GetDeprecationWarning().c_str()); + if ( ! id->Type() ) { id->Error("undeclared variable"); - id->SetType(error_type()); - Ref(id); - $$ = new NameExpr(id); + id->SetType({AdoptRef{}, error_type()}); + $$ = new NameExpr(std::move(id)); } else if ( id->IsEnumConst() ) @@ -701,25 +713,19 @@ expr: id->Name()); if ( intval < 0 ) reporter->InternalError("enum value not found for %s", id->Name()); - $$ = new ConstExpr(t->GetVal(intval)); + $$ = new ConstExpr({AdoptRef{}, t->GetVal(intval)}); } else { - Ref(id); - $$ = new NameExpr(id); + $$ = new NameExpr(std::move(id)); } - - if ( id->IsDeprecated() ) - reporter->Warning("%s", id->GetDeprecationWarning().c_str()); - - Unref(id); } } | TOK_CONSTANT { set_location(@1); - $$ = new ConstExpr($1); + $$ = new ConstExpr({AdoptRef{}, $1}); } | '/' { begin_RE(); } TOK_PATTERN_TEXT TOK_PATTERN_END @@ -733,30 +739,30 @@ expr: re->MakeCaseInsensitive(); re->Compile(); - $$ = new ConstExpr(new PatternVal(re)); + $$ = new ConstExpr(make_intrusive(re)); } | '|' expr '|' %prec '(' { set_location(@1, @3); - auto e = $2; + IntrusivePtr e{AdoptRef{}, $2}; if ( IsIntegral(e->Type()->Tag()) ) - e = new ArithCoerceExpr(e, TYPE_INT); + e = make_intrusive(std::move(e), TYPE_INT); - $$ = new SizeExpr(e); + $$ = new SizeExpr(std::move(e)); } | expr TOK_AS type { set_location(@1, @3); - $$ = new CastExpr($1, $3); + $$ = new CastExpr({AdoptRef{}, $1}, {AdoptRef{}, $3}); } | expr TOK_IS type { set_location(@1, @3); - $$ = new IsExpr($1, $3); + $$ = new IsExpr({AdoptRef{}, $1}, {AdoptRef{}, $3}); } ; @@ -764,13 +770,13 @@ expr_list: expr_list ',' expr { set_location(@1, @3); - $1->Append($3); + $1->Append({AdoptRef{}, $3}); } | expr { set_location(@1); - $$ = new ListExpr($1); + $$ = new ListExpr({AdoptRef{}, $1}); } ; @@ -1089,27 +1095,31 @@ decl: | TOK_GLOBAL def_global_id opt_type init_class opt_init opt_attr ';' { - add_global($2, $3, $4, $5, $6, VAR_REGULAR); - zeekygen_mgr->Identifier($2); + IntrusivePtr id{AdoptRef{}, $2}; + add_global(id.get(), {AdoptRef{}, $3}, $4, {AdoptRef{}, $5}, $6, VAR_REGULAR); + zeekygen_mgr->Identifier(std::move(id)); } | TOK_OPTION def_global_id opt_type init_class opt_init opt_attr ';' { - add_global($2, $3, $4, $5, $6, VAR_OPTION); - zeekygen_mgr->Identifier($2); + IntrusivePtr id{AdoptRef{}, $2}; + add_global(id.get(), {AdoptRef{}, $3}, $4, {AdoptRef{}, $5}, $6, VAR_OPTION); + zeekygen_mgr->Identifier(std::move(id)); } | TOK_CONST def_global_id opt_type init_class opt_init opt_attr ';' { - add_global($2, $3, $4, $5, $6, VAR_CONST); - zeekygen_mgr->Identifier($2); + IntrusivePtr id{AdoptRef{}, $2}; + add_global(id.get(), {AdoptRef{}, $3}, $4, {AdoptRef{}, $5}, $6, VAR_CONST); + zeekygen_mgr->Identifier(std::move(id)); } | TOK_REDEF global_id opt_type init_class opt_init opt_attr ';' { - IntrusivePtr e{NewRef{}, $5}; - add_global($2, $3, $4, $5, $6, VAR_REDEF); - zeekygen_mgr->Redef($2, ::filename, $4, $5); + IntrusivePtr id{AdoptRef{}, $2}; + IntrusivePtr init{AdoptRef{}, $5}; + add_global(id.get(), {AdoptRef{}, $3}, $4, init, $6, VAR_REDEF); + zeekygen_mgr->Redef(id.get(), ::filename, $4, init.release()); } | TOK_REDEF TOK_ENUM global_id TOK_ADD_TO '{' @@ -1136,12 +1146,13 @@ decl: } | TOK_TYPE global_id ':' - { cur_decl_type_id = $2; zeekygen_mgr->StartType($2); } + { cur_decl_type_id = $2; zeekygen_mgr->StartType({NewRef{}, $2}); } type opt_attr ';' { cur_decl_type_id = 0; - add_type($2, $5, $6); - zeekygen_mgr->Identifier($2); + IntrusivePtr id{AdoptRef{}, $2}; + add_type(id.get(), {AdoptRef{}, $5}, $6); + zeekygen_mgr->Identifier(std::move(id)); } | func_hdr { func_hdr_location = @1; } func_body @@ -1171,10 +1182,11 @@ conditional: func_hdr: TOK_FUNCTION def_global_id func_params opt_attr { - begin_func($2, current_module.c_str(), - FUNC_FLAVOR_FUNCTION, 0, $3, $4); + IntrusivePtr id{AdoptRef{}, $2}; + begin_func(id.get(), current_module.c_str(), + FUNC_FLAVOR_FUNCTION, 0, {NewRef{}, $3}, $4); $$ = $3; - zeekygen_mgr->Identifier($2); + zeekygen_mgr->Identifier(std::move(id)); } | TOK_EVENT event_id func_params opt_attr { @@ -1186,7 +1198,7 @@ func_hdr: } begin_func($2, current_module.c_str(), - FUNC_FLAVOR_EVENT, 0, $3, $4); + FUNC_FLAVOR_EVENT, 0, {NewRef{}, $3}, $4); $$ = $3; } | TOK_HOOK def_global_id func_params opt_attr @@ -1194,13 +1206,13 @@ func_hdr: $3->ClearYieldType(FUNC_FLAVOR_HOOK); $3->SetYieldType(base_type(TYPE_BOOL)); begin_func($2, current_module.c_str(), - FUNC_FLAVOR_HOOK, 0, $3, $4); + FUNC_FLAVOR_HOOK, 0, {NewRef{}, $3}, $4); $$ = $3; } | TOK_REDEF TOK_EVENT event_id func_params opt_attr { begin_func($3, current_module.c_str(), - FUNC_FLAVOR_EVENT, 1, $4, $5); + FUNC_FLAVOR_EVENT, 1, {NewRef{}, $4}, $5); $$ = $4; } ; @@ -1221,7 +1233,7 @@ func_body: '}' { set_location(func_hdr_location, @5); - end_func($3); + end_func({AdoptRef{}, $3}); } ; @@ -1250,7 +1262,7 @@ anonymous_function: // Gather the ingredients for a BroFunc from the current scope auto ingredients = std::make_unique(current_scope(), $5); - id_list outer_ids = gather_outer_ids(pop_scope(), $5); + id_list outer_ids = gather_outer_ids(pop_scope().get(), $5); $$ = new LambdaExpr(std::move(ingredients), std::move(outer_ids)); } @@ -1260,7 +1272,7 @@ begin_func: func_params { $$ = current_scope()->GenerateTemporary("anonymous-function"); - begin_func($$, current_module.c_str(), FUNC_FLAVOR_FUNCTION, 0, $1); + begin_func($$, current_module.c_str(), FUNC_FLAVOR_FUNCTION, 0, {AdoptRef{}, $1}); } ; @@ -1304,15 +1316,21 @@ index_slice: expr '[' opt_expr ':' opt_expr ']' { set_location(@1, @6); - Expr* low = $3 ? $3 : new ConstExpr(val_mgr->GetCount(0)); - Expr* high = $5 ? $5 : new SizeExpr($1->Ref()); + + auto low = $3 ? IntrusivePtr{AdoptRef{}, $3} : + make_intrusive( + IntrusivePtr{AdoptRef{}, val_mgr->GetCount(0)}); + + auto high = $5 ? IntrusivePtr{AdoptRef{}, $5} : + make_intrusive( + IntrusivePtr{NewRef{}, $1}); if ( ! IsIntegral(low->Type()->Tag()) || ! IsIntegral(high->Type()->Tag()) ) reporter->Error("slice notation must have integral values as indexes"); - ListExpr* le = new ListExpr(low); - le->Append(high); - $$ = new IndexExpr($1, le, true); + auto le = make_intrusive(std::move(low)); + le->Append(std::move(high)); + $$ = new IndexExpr({AdoptRef{}, $1}, std::move(le), true); } opt_attr: @@ -1367,7 +1385,7 @@ attr: | TOK_ATTR_DEPRECATED '=' TOK_CONSTANT { if ( IsString($3->Type()->Tag()) ) - $$ = new Attr(ATTR_DEPRECATED, new ConstExpr($3)); + $$ = new Attr(ATTR_DEPRECATED, new ConstExpr({AdoptRef{}, $3})); else { ODesc d; @@ -1392,7 +1410,7 @@ stmt: | TOK_PRINT expr_list ';' opt_no_test { set_location(@1, @3); - $$ = new PrintStmt($2); + $$ = new PrintStmt(IntrusivePtr{AdoptRef{}, $2}); if ( ! $4 ) brofiler.AddStmt($$); } @@ -1400,7 +1418,7 @@ stmt: | TOK_EVENT event ';' opt_no_test { set_location(@1, @3); - $$ = new EventStmt($2); + $$ = new EventStmt({AdoptRef{}, $2}); if ( ! $4 ) brofiler.AddStmt($$); } @@ -1408,29 +1426,29 @@ stmt: | TOK_IF '(' expr ')' stmt { set_location(@1, @4); - $$ = new IfStmt($3, $5, new NullStmt()); + $$ = new IfStmt({AdoptRef{}, $3}, {AdoptRef{}, $5}, make_intrusive()); } | TOK_IF '(' expr ')' stmt TOK_ELSE stmt { set_location(@1, @4); - $$ = new IfStmt($3, $5, $7); + $$ = new IfStmt({AdoptRef{}, $3}, {AdoptRef{}, $5}, {AdoptRef{}, $7}); } | TOK_SWITCH expr '{' case_list '}' { set_location(@1, @2); - $$ = new SwitchStmt($2, $4); + $$ = new SwitchStmt({AdoptRef{}, $2}, $4); } | for_head stmt { - $1->AsForStmt()->AddBody($2); + $1->AsForStmt()->AddBody({AdoptRef{}, $2}); } | TOK_WHILE '(' expr ')' stmt { - $$ = new WhileStmt($3, $5); + $$ = new WhileStmt({AdoptRef{}, $3}, {AdoptRef{}, $5}); } | TOK_NEXT ';' opt_no_test @@ -1468,7 +1486,7 @@ stmt: | TOK_RETURN expr ';' opt_no_test { set_location(@1, @2); - $$ = new ReturnStmt($2); + $$ = new ReturnStmt({AdoptRef{}, $2}); if ( ! $4 ) brofiler.AddStmt($$); } @@ -1476,7 +1494,7 @@ stmt: | TOK_ADD expr ';' opt_no_test { set_location(@1, @3); - $$ = new AddStmt($2); + $$ = new AddStmt({AdoptRef{}, $2}); if ( ! $4 ) brofiler.AddStmt($$); } @@ -1484,7 +1502,7 @@ stmt: | TOK_DELETE expr ';' opt_no_test { set_location(@1, @3); - $$ = new DelStmt($2); + $$ = new DelStmt({AdoptRef{}, $2}); if ( ! $4 ) brofiler.AddStmt($$); } @@ -1492,7 +1510,8 @@ stmt: | TOK_LOCAL local_id opt_type init_class opt_init opt_attr ';' opt_no_test { set_location(@1, @7); - $$ = add_local($2, $3, $4, $5, $6, VAR_REGULAR); + $$ = add_local({AdoptRef{}, $2}, {AdoptRef{}, $3}, $4, + {AdoptRef{}, $5}, $6, VAR_REGULAR).release(); if ( ! $8 ) brofiler.AddStmt($$); } @@ -1500,7 +1519,8 @@ stmt: | TOK_CONST local_id opt_type init_class opt_init opt_attr ';' opt_no_test { set_location(@1, @6); - $$ = add_local($2, $3, $4, $5, $6, VAR_CONST); + $$ = add_local({AdoptRef{}, $2}, {AdoptRef{}, $3}, $4, + {AdoptRef{}, $5}, $6, VAR_CONST).release(); if ( ! $8 ) brofiler.AddStmt($$); } @@ -1508,13 +1528,15 @@ stmt: | TOK_WHEN '(' expr ')' stmt { set_location(@3, @5); - $$ = new WhenStmt($3, $5, 0, 0, false); + $$ = new WhenStmt({AdoptRef{}, $3}, {AdoptRef{}, $5}, + nullptr, nullptr, false); } | TOK_WHEN '(' expr ')' stmt TOK_TIMEOUT expr '{' opt_no_test_block stmt_list '}' { set_location(@3, @9); - $$ = new WhenStmt($3, $5, $10, $7, false); + $$ = new WhenStmt({AdoptRef{}, $3}, {AdoptRef{}, $5}, + {AdoptRef{}, $10}, {AdoptRef{}, $7}, false); if ( $9 ) brofiler.DecIgnoreDepth(); } @@ -1523,13 +1545,15 @@ stmt: | TOK_RETURN TOK_WHEN '(' expr ')' stmt { set_location(@4, @6); - $$ = new WhenStmt($4, $6, 0, 0, true); + $$ = new WhenStmt({AdoptRef{}, $4}, {AdoptRef{}, $6}, nullptr, + nullptr, true); } | TOK_RETURN TOK_WHEN '(' expr ')' stmt TOK_TIMEOUT expr '{' opt_no_test_block stmt_list '}' { set_location(@4, @10); - $$ = new WhenStmt($4, $6, $11, $8, true); + $$ = new WhenStmt({AdoptRef{}, $4}, {AdoptRef{}, $6}, + {AdoptRef{}, $11}, {AdoptRef{}, $8}, true); if ( $10 ) brofiler.DecIgnoreDepth(); } @@ -1537,7 +1561,8 @@ stmt: | index_slice '=' expr ';' opt_no_test { set_location(@1, @4); - $$ = new ExprStmt(get_assign_expr($1, $3, in_init)); + $$ = new ExprStmt(get_assign_expr({AdoptRef{}, $1}, + {AdoptRef{}, $3}, in_init)); if ( ! $5 ) brofiler.AddStmt($$); @@ -1546,7 +1571,7 @@ stmt: | expr ';' opt_no_test { set_location(@1, @2); - $$ = new ExprStmt($1); + $$ = new ExprStmt({AdoptRef{}, $1}); if ( ! $3 ) brofiler.AddStmt($$); } @@ -1576,8 +1601,8 @@ event: TOK_ID '(' opt_expr_list ')' { set_location(@1, @4); + auto id = lookup_ID($1, current_module.c_str()); - ID* id = lookup_ID($1, current_module.c_str()); if ( id ) { if ( ! id->IsGlobal() ) @@ -1585,13 +1610,12 @@ event: yyerror(fmt("local identifier \"%s\" cannot be used to reference an event", $1)); YYERROR; } + if ( id->IsDeprecated() ) reporter->Warning("%s", id->GetDeprecationWarning().c_str()); - - Unref(id); } - $$ = new EventExpr($1, $3); + $$ = new EventExpr($1, {AdoptRef{}, $3}); } ; @@ -1604,13 +1628,13 @@ case_list: case: TOK_CASE expr_list ':' stmt_list - { $$ = new Case($2, 0, $4); } + { $$ = new Case({AdoptRef{}, $2}, 0, {AdoptRef{}, $4}); } | TOK_CASE case_type_list ':' stmt_list - { $$ = new Case(0, $2, $4); } + { $$ = new Case(nullptr, $2, {AdoptRef{}, $4}); } | TOK_DEFAULT ':' stmt_list - { $$ = new Case(0, 0, $3); } + { $$ = new Case(nullptr, 0, {AdoptRef{}, $3}); } ; case_type_list: @@ -1628,25 +1652,22 @@ case_type: TOK_TYPE type { $$ = new ID(0, SCOPE_FUNCTION, 0); - $$->SetType($2); + $$->SetType({AdoptRef{}, $2}); } | TOK_TYPE type TOK_AS TOK_ID { const char* name = $4; - BroType* type = $2; - ID* case_var = lookup_ID(name, current_module.c_str()); + IntrusivePtr type{AdoptRef{}, $2}; + auto case_var = lookup_ID(name, current_module.c_str()); if ( case_var && case_var->IsGlobal() ) case_var->Error("already a global identifier"); else - { - Unref(case_var); case_var = install_ID(name, current_module.c_str(), false, false); - } - add_local(case_var, type, INIT_NONE, 0, 0, VAR_REGULAR); - $$ = case_var; + add_local(case_var, std::move(type), INIT_NONE, 0, 0, VAR_REGULAR); + $$ = case_var.release(); } for_head: @@ -1658,7 +1679,7 @@ for_head: // body so that we execute these actions - defining // the local variable - prior to parsing the body, // which might refer to the variable. - ID* loop_var = lookup_ID($3, current_module.c_str()); + auto loop_var = lookup_ID($3, current_module.c_str()); if ( loop_var ) { @@ -1668,20 +1689,19 @@ for_head: else { - Unref(loop_var); loop_var = install_ID($3, current_module.c_str(), false, false); } id_list* loop_vars = new id_list; - loop_vars->push_back(loop_var); + loop_vars->push_back(loop_var.release()); - $$ = new ForStmt(loop_vars, $5); + $$ = new ForStmt(loop_vars, {AdoptRef{}, $5}); } | TOK_FOR '(' '[' local_id_list ']' TOK_IN expr ')' { - $$ = new ForStmt($4, $7); + $$ = new ForStmt($4, {AdoptRef{}, $7}); } | TOK_FOR '(' TOK_ID ',' TOK_ID TOK_IN expr ')' @@ -1691,8 +1711,8 @@ for_head: // Check for previous definitions of key and // value variables. - ID* key_var = lookup_ID($3, module); - ID* val_var = lookup_ID($5, module); + auto key_var = lookup_ID($3, module); + auto val_var = lookup_ID($5, module); // Validate previous definitions as needed. if ( key_var ) @@ -1712,9 +1732,9 @@ for_head: val_var = install_ID($5, module, false, false); id_list* loop_vars = new id_list; - loop_vars->push_back(key_var); + loop_vars->push_back(key_var.release()); - $$ = new ForStmt(loop_vars, $7, val_var); + $$ = new ForStmt(loop_vars, {AdoptRef{}, $7}, std::move(val_var)); } | TOK_FOR '(' '[' local_id_list ']' ',' TOK_ID TOK_IN expr ')' @@ -1723,7 +1743,7 @@ for_head: const char* module = current_module.c_str(); // Validate value variable - ID* val_var = lookup_ID($7, module); + auto val_var = lookup_ID($7, module); if ( val_var ) { @@ -1733,7 +1753,7 @@ for_head: else val_var = install_ID($7, module, false, false); - $$ = new ForStmt($4, $9, val_var); + $$ = new ForStmt($4, {AdoptRef{}, $9}, std::move(val_var)); } ; @@ -1751,8 +1771,8 @@ local_id: TOK_ID { set_location(@1); + $$ = lookup_ID($1, current_module.c_str()).release(); - $$ = lookup_ID($1, current_module.c_str()); if ( $$ ) { if ( $$->IsGlobal() ) @@ -1763,7 +1783,7 @@ local_id: else { $$ = install_ID($1, current_module.c_str(), - false, is_export); + false, is_export).release(); } } ; @@ -1787,8 +1807,9 @@ global_or_event_id: TOK_ID { set_location(@1); + $$ = lookup_ID($1, current_module.c_str(), false, + defining_global_ID).release(); - $$ = lookup_ID($1, current_module.c_str(), false, defining_global_ID); if ( $$ ) { if ( ! $$->IsGlobal() ) @@ -1813,7 +1834,7 @@ global_or_event_id: current_module.c_str() : 0; $$ = install_ID($1, module_name, - true, is_export); + true, is_export).release(); } } ; @@ -1823,7 +1844,7 @@ resolve_id: TOK_ID { set_location(@1); - $$ = lookup_ID($1, current_module.c_str()); + $$ = lookup_ID($1, current_module.c_str()).release(); if ( ! $$ ) reporter->Error("identifier not defined: %s", $1); @@ -1846,19 +1867,19 @@ opt_no_test_block: opt_deprecated: TOK_ATTR_DEPRECATED - { $$ = new ConstExpr(new StringVal("")); } + { $$ = new ConstExpr(make_intrusive("")); } | TOK_ATTR_DEPRECATED '=' TOK_CONSTANT { if ( IsString($3->Type()->Tag()) ) - $$ = new ConstExpr($3); + $$ = new ConstExpr({AdoptRef{}, $3}); else { ODesc d; $3->Describe(&d); reporter->Error("'&deprecated=%s' must use a string literal", d.Description()); - $$ = new ConstExpr(new StringVal("")); + $$ = new ConstExpr(make_intrusive("")); } } | diff --git a/src/plugin/ComponentManager.h b/src/plugin/ComponentManager.h index c8ff1d2791..87d22fc189 100644 --- a/src/plugin/ComponentManager.h +++ b/src/plugin/ComponentManager.h @@ -4,6 +4,7 @@ #include #include +#include "IntrusivePtr.h" #include "Type.h" #include "Var.h" // for add_type() #include "Val.h" @@ -121,7 +122,7 @@ public: private: string module; /**< Script layer module in which component tags live. */ - EnumType* tag_enum_type; /**< Enum type of component tags. */ + IntrusivePtr tag_enum_type; /**< Enum type of component tags. */ map components_by_name; map components_by_tag; map components_by_val; @@ -129,12 +130,12 @@ private: template ComponentManager::ComponentManager(const string& arg_module, const string& local_id) - : module(arg_module) + : module(arg_module), + tag_enum_type(make_intrusive(module + "::" + local_id)) { - tag_enum_type = new EnumType(module + "::" + local_id); - ::ID* id = install_ID(local_id.c_str(), module.c_str(), true, true); - add_type(id, tag_enum_type, 0); - zeekygen_mgr->Identifier(id); + auto id = install_ID(local_id.c_str(), module.c_str(), true, true); + add_type(id.get(), tag_enum_type, 0); + zeekygen_mgr->Identifier(std::move(id)); } template @@ -158,7 +159,7 @@ list ComponentManager::GetComponents() const template EnumType* ComponentManager::GetTagEnumType() const { - return tag_enum_type; + return tag_enum_type.get(); } template diff --git a/src/scan.l b/src/scan.l index 50f035fa2f..778615dba6 100644 --- a/src/scan.l +++ b/src/scan.l @@ -20,6 +20,7 @@ #include "Expr.h" #include "Func.h" #include "Stmt.h" +#include "IntrusivePtr.h" #include "Val.h" #include "Var.h" #include "Debug.h" @@ -746,10 +747,10 @@ void do_atif(Expr* expr) LocalNameFinder cb; expr->Traverse(&cb); - Val* val = 0; + IntrusivePtr val; if ( cb.local_names.empty() ) - val = expr->Eval(0); + val = expr->Eval(nullptr); else { for ( size_t i = 0; i < cb.local_names.size(); ++i ) @@ -767,38 +768,32 @@ void do_atif(Expr* expr) if_stack.push_back(current_depth); BEGIN(IGNORE); } - - Unref(val); } void do_atifdef(const char* id) { ++current_depth; - ID* i; + auto i = lookup_ID(id, current_module.c_str()); - if ( ! (i = lookup_ID(id, current_module.c_str())) ) + if ( ! i ) { if_stack.push_back(current_depth); BEGIN(IGNORE); } - - Unref(i); } void do_atifndef(const char *id) { ++current_depth; - ID* i; + auto i = lookup_ID(id, current_module.c_str()); - if ( (i = lookup_ID(id, current_module.c_str())) ) + if ( i ) { if_stack.push_back(current_depth); BEGIN(IGNORE); } - - Unref(i); } void do_atelse() diff --git a/src/supervisor/Supervisor.cc b/src/supervisor/Supervisor.cc index 097724665b..3d91725b26 100644 --- a/src/supervisor/Supervisor.cc +++ b/src/supervisor/Supervisor.cc @@ -1233,7 +1233,7 @@ bool Supervisor::SupervisedNode::InitCluster() const cluster_nodes->Assign(key.get(), val.release()); } - cluster_manager_is_logger_id->SetVal(val_mgr->GetBool(! has_logger)); + cluster_manager_is_logger_id->SetVal({AdoptRef{}, val_mgr->GetBool(! has_logger)}); return true; } diff --git a/src/zeekygen/IdentifierInfo.cc b/src/zeekygen/IdentifierInfo.cc index 36f5036f73..49ae1ad856 100644 --- a/src/zeekygen/IdentifierInfo.cc +++ b/src/zeekygen/IdentifierInfo.cc @@ -11,22 +11,17 @@ using namespace std; using namespace zeekygen; -IdentifierInfo::IdentifierInfo(ID* arg_id, ScriptInfo* script) +IdentifierInfo::IdentifierInfo(IntrusivePtr arg_id, ScriptInfo* script) : Info(), - comments(), id(arg_id), initial_val(), redefs(), fields(), + comments(), id(std::move(arg_id)), initial_val(), redefs(), fields(), last_field_seen(), declaring_script(script) { - Ref(id); - if ( id->ID_Val() && (id->IsOption() || id->IsRedefinable()) ) - initial_val = id->ID_Val()->Clone(); + initial_val = {AdoptRef{}, id->ID_Val()->Clone()}; } IdentifierInfo::~IdentifierInfo() { - Unref(id); - Unref(initial_val); - for ( redef_list::const_iterator it = redefs.begin(); it != redefs.end(); ++it ) delete *it; @@ -51,7 +46,15 @@ void IdentifierInfo::AddRecordField(const TypeDecl* field, rf->field = new TypeDecl(*field); rf->from_script = script; rf->comments = comments; - fields[rf->field->id] = rf; + + auto [it, inserted] = fields.emplace(rf->field->id, rf); + + if ( ! inserted ) + { + delete it->second; + it->second = rf; + } + last_field_seen = rf; } diff --git a/src/zeekygen/IdentifierInfo.h b/src/zeekygen/IdentifierInfo.h index 56ae00f0b8..947378d1f0 100644 --- a/src/zeekygen/IdentifierInfo.h +++ b/src/zeekygen/IdentifierInfo.h @@ -3,6 +3,7 @@ #pragma once #include "Info.h" +#include "IntrusivePtr.h" #include "ID.h" #include @@ -31,7 +32,7 @@ public: * @param script The info object associated with the script in which \a id * is declared. */ - IdentifierInfo(ID* id, ScriptInfo* script); + IdentifierInfo(IntrusivePtr id, ScriptInfo* script); /** * Dtor. Releases any references to script-level objects. @@ -42,7 +43,7 @@ public: * Returns the initial value of the identifier. */ Val* InitialVal() const - { return initial_val; } + { return initial_val.get(); } /** * Add a comment associated with the identifier. If the identifier is a @@ -96,7 +97,7 @@ public: * @return the script-level ID tracked by this info object. */ ID* GetID() const - { return id; } + { return id.get(); } /** * @return The script which declared the script-level identifier. @@ -177,8 +178,8 @@ private: typedef std::map record_field_map; std::vector comments; - ID* id; - Val* initial_val; + IntrusivePtr id; + IntrusivePtr initial_val; redef_list redefs; record_field_map fields; RecordField* last_field_seen; diff --git a/src/zeekygen/Manager.cc b/src/zeekygen/Manager.cc index 3029d1640f..f9e4e48585 100644 --- a/src/zeekygen/Manager.cc +++ b/src/zeekygen/Manager.cc @@ -215,7 +215,7 @@ void Manager::ModuleUsage(const string& path, const string& module) module.c_str(), name.c_str()); } -IdentifierInfo* Manager::CreateIdentifierInfo(ID* id, ScriptInfo* script) +IdentifierInfo* Manager::CreateIdentifierInfo(IntrusivePtr id, ScriptInfo* script) { auto prev = identifiers.GetInfo(id->Name()); IdentifierInfo* rval = prev ? prev : new IdentifierInfo(id, script); @@ -245,7 +245,7 @@ IdentifierInfo* Manager::CreateIdentifierInfo(ID* id, ScriptInfo* script) return rval; } -void Manager::StartType(ID* id) +void Manager::StartType(IntrusivePtr id) { if ( disabled ) return; @@ -262,7 +262,7 @@ void Manager::StartType(ID* id) if ( ! script_info ) { - WarnMissingScript("identifier", id, script); + WarnMissingScript("identifier", id.get(), script); return; } @@ -276,7 +276,7 @@ static bool IsEnumType(ID* id) return id->AsType() ? id->AsType()->Tag() == TYPE_ENUM : false; } -void Manager::Identifier(ID* id) +void Manager::Identifier(IntrusivePtr id) { if ( disabled ) return; @@ -326,7 +326,7 @@ void Manager::Identifier(ID* id) if ( ! script_info ) { - WarnMissingScript("identifier", id, script); + WarnMissingScript("identifier", id.get(), script); return; } diff --git a/src/zeekygen/Manager.h b/src/zeekygen/Manager.h index 988d641370..a22dada278 100644 --- a/src/zeekygen/Manager.h +++ b/src/zeekygen/Manager.h @@ -109,14 +109,14 @@ public: * Signal that a record or enum type is now being parsed. * @param id The record or enum type identifier. */ - void StartType(ID* id); + void StartType(IntrusivePtr id); /** * Register a script-level identifier for which information/documentation * will be gathered. * @param id The script-level identifier. */ - void Identifier(ID* id); + void Identifier(IntrusivePtr id); /** * Register a record-field for which information/documentation will be @@ -214,7 +214,7 @@ private: typedef std::vector comment_buffer_t; typedef std::map comment_buffer_map_t; - IdentifierInfo* CreateIdentifierInfo(ID* id, ScriptInfo* script); + IdentifierInfo* CreateIdentifierInfo(IntrusivePtr id, ScriptInfo* script); bool disabled; comment_buffer_t comment_buffer; // For whatever next identifier comes in. diff --git a/src/zeekygen/ScriptInfo.cc b/src/zeekygen/ScriptInfo.cc index 6e8afda0ef..a2c41bb300 100644 --- a/src/zeekygen/ScriptInfo.cc +++ b/src/zeekygen/ScriptInfo.cc @@ -258,12 +258,12 @@ void ScriptInfo::DoInitPostScript() if ( name == "base/frameworks/input/main.zeek" ) { auto id = global_scope()->Lookup("Input::Reader"); - types.push_back(new IdentifierInfo(id, this)); + types.push_back(new IdentifierInfo({NewRef{}, id}, this)); } else if ( name == "base/frameworks/logging/main.zeek" ) { auto id = global_scope()->Lookup("Log::Writer"); - types.push_back(new IdentifierInfo(id, this)); + types.push_back(new IdentifierInfo({NewRef{}, id}, this)); } }