From 7c80b577f106656fb88fac60f0ff135f9b00f62f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 27 Feb 2020 11:50:25 +0100 Subject: [PATCH 01/22] Var: fix crash when redeclaring a function with different args The following source code: function foo(foo: int) {} function foo() {} ... first produces this error: error in crash.zeek, line 1 and crash.zeek, line 2: incompatible types (function(foo:int;) : void and function() : void) ... and then crashes: Thread 1 "zeek" received signal SIGSEGV, Segmentation fault. 0x000055555617d970 in RecordType::FieldDecl (this=0x555557cbdd80, field=0) at ../src/Type.cc:735 735 return (*types)[field]; (gdb) bt #0 0x000055555617d970 in RecordType::FieldDecl (this=0x555557cbdd80, field=0) at ../src/Type.cc:735 #1 0x000055555619c0e2 in transfer_arg_defaults (args=0x555557cbf270, recv=0x555557cbdd80) at ../src/Var.cc:315 #2 0x000055555619c40c in begin_func (id=0x555557cbf070, module_name=0x5555579dd4a0 "GLOBAL", flavor=FUNC_FLAVOR_FUNCTION, is_redef=0, t=0x555557cbde00, attrs=0x0) at ../src/Var.cc:371 #3 0x0000555555f5723b in yyparse () at parse.y:1174 #4 0x0000555556038bf6 in main (argc=5, argv=0x7fffffffe658) at ../src/main.cc:646 This is because `begin_func()` checks if the old and new functions have the same type via same_type(), but continues anyway, and then transfer_arg_defaults() crashes because both `Args()` have different lengths. --- src/Var.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Var.cc b/src/Var.cc index c1d9b61022..1e9f7668ad 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -364,11 +364,11 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor, { if ( ! same_type(id->Type(), t) ) id->Type()->Error("incompatible types", t); - - // 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 ) From db4f449382040ea5bce39903f7e28173e27bc194 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 26 Feb 2020 10:09:15 +0100 Subject: [PATCH 02/22] Type: fix use-after-free bug in VectorType::ShallowClone() The new VectorType instance needs a new reference to the `yield_type`. --- src/Type.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Type.cc b/src/Type.cc index 3cb6b09257..210f48a493 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -1357,6 +1357,9 @@ VectorType::VectorType(BroType* element_type) VectorType* VectorType::ShallowClone() { + if ( yield_type ) + yield_type->Ref(); + return new VectorType(yield_type); } From 17a2f1a3ab62cfa39cd2942a660c96be3a4ae1be Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 26 Feb 2020 05:40:44 +0100 Subject: [PATCH 03/22] plugin/ComponentManager: hold a reference to the EnumType Use class IntrusivePtr<>. This reference is necessary because add_type() may discard the reference and hold only a reference to a clone of our EnumType. --- src/plugin/ComponentManager.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/plugin/ComponentManager.h b/src/plugin/ComponentManager.h index c8ff1d2791..848d989faa 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,11 +130,11 @@ 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); + add_type(id, tag_enum_type.get(), 0); zeekygen_mgr->Identifier(id); } @@ -158,7 +159,7 @@ list ComponentManager::GetComponents() const template EnumType* ComponentManager::GetTagEnumType() const { - return tag_enum_type; + return tag_enum_type.get(); } template From 2c0ece737656693fa7ca2b837c2b150a7212ef76 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 26 Feb 2020 05:28:21 +0100 Subject: [PATCH 04/22] Var: pass IntrusivePtr to add_global(), add_local() etc. Those functions don't have a well-defined reference passing API, and we had lots of memory leaks here. By using IntrusivePtr, reference ownership is well-defined. --- src/Stmt.cc | 12 ++-- src/Var.cc | 114 +++++++++++++++------------------- src/Var.h | 13 ++-- src/parse.y | 45 +++++++------- src/plugin/ComponentManager.h | 2 +- 5 files changed, 85 insertions(+), 101 deletions(-) diff --git a/src/Stmt.cc b/src/Stmt.cc index 76b31c07e4..da31fa5a4b 100644 --- a/src/Stmt.cc +++ b/src/Stmt.cc @@ -1119,8 +1119,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 +1136,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 +1156,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 ) @@ -1187,7 +1187,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({NewRef{}, value_var}, {NewRef{}, yield_type}, INIT_NONE, 0, 0, VAR_REGULAR); } } diff --git a/src/Var.cc b/src/Var.cc index 1e9f7668ad..1088a67dad 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -27,22 +27,21 @@ static Val* init_val(Expr* init, const BroType* t, Val* aggr) } } -static void make_var(ID* id, BroType* t, init_class c, Expr* 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 +51,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 +84,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,32 +97,28 @@ 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); return; } } - else - Ref(t); - id->SetType(t); + id->SetType(t->Ref()); if ( attr ) - id->AddAttrs(new Attributes(attr, t, false, id->IsGlobal())); + id->AddAttrs(new Attributes(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()); @@ -139,7 +129,7 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init, case EXPR_SET_CONSTRUCTOR: { - SetConstructorExpr* ctor = (SetConstructorExpr*) init; + SetConstructorExpr* ctor = (SetConstructorExpr*) init.get(); if ( ctor->Attrs() ) { ::Ref(ctor->Attrs()); @@ -164,7 +154,7 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init, if ( init && ((c == INIT_EXTRA && id->FindAttr(ATTR_ADD_FUNC)) || (c == INIT_REMOVE && id->FindAttr(ATTR_DEL_FUNC)) )) // Just apply the function. - id->SetVal(init, c); + id->SetVal(init->Ref(), c); else if ( dt != VAR_REDEF || init || ! attr ) { @@ -175,7 +165,7 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init, if ( init && t ) // Have an initialization and type is not deduced. - init = new RecordCoerceExpr(init, t->AsRecordType()); + init = make_intrusive(init.release(), t->AsRecordType()); } else if ( t->Tag() == TYPE_TABLE ) @@ -190,12 +180,9 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init, 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 ) @@ -221,8 +208,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 && @@ -238,73 +223,71 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init, } -void add_global(ID* id, BroType* t, init_class c, Expr* init, +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, t, c, std::move(init), attr, dt, 1); } -Stmt* add_local(ID* id, BroType* t, init_class c, Expr* init, +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(), 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, + const Location* location = init->GetLocationInfo(); + Expr* name_expr = new NameExpr(IntrusivePtr{id}.release(), dt == VAR_CONST); + auto stmt = + make_intrusive(new AssignExpr(name_expr, init.release(), 0, 0, id->Attrs() ? id->Attrs()->Attrs() : 0 )); - stmt->SetLocationInfo(init->GetLocationInfo()); + 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, IntrusivePtr{init}, 0, VAR_REGULAR, 0); + return make_intrusive(new NameExpr(id.release()), init.release(), 0, val.release()); } -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()); - id->SetType(tnew); + id->SetType(IntrusivePtr{tnew}.release()); id->MakeType(); if ( attr ) - id->SetAttrs(new Attributes(attr, tnew, false, false)); + id->SetAttrs(new Attributes(attr, tnew.get(), false, false)); } static void transfer_arg_defaults(RecordType* args, RecordType* recv) @@ -348,22 +331,23 @@ 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()); + else // If a previous declaration of the function had &default params, // automatically transfer any that are missing (convenience so that @@ -379,7 +363,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 ) { @@ -401,7 +385,7 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor, } } else - id->SetType(t); + id->SetType(IntrusivePtr{t}.release()); push_scope(id, attrs); @@ -482,9 +466,9 @@ 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(), body.release()); if ( streq(ingredients->id->Name(), "anonymous-function") ) { diff --git a/src/Var.h b/src/Var.h index 0282c4a489..f7b5303f79 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,17 @@ 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, +extern void add_global(ID* id, IntrusivePtr t, init_class c, IntrusivePtr init, attr_list* attr, decl_type dt); -extern Stmt* add_local(ID* id, BroType* t, init_class c, Expr* init, +extern IntrusivePtr add_local(IntrusivePtr id, IntrusivePtr t, init_class c, IntrusivePtr init, attr_list* attr, decl_type dt); -extern Expr* add_and_assign_local(ID* id, Expr* init, Val* val = 0); +extern IntrusivePtr add_and_assign_local(IntrusivePtr id, IntrusivePtr init, IntrusivePtr val = nullptr); -extern void add_type(ID* id, BroType* t, attr_list* attr); +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/parse.y b/src/parse.y index 9033c08635..47dc9ed2d7 100644 --- a/src/parse.y +++ b/src/parse.y @@ -479,7 +479,7 @@ expr: | 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 ']' @@ -511,7 +511,7 @@ expr: current_module.c_str(), FUNC_FLAVOR_FUNCTION, 0, - $3); + {AdoptRef{}, $3}); } func_body { @@ -1089,27 +1089,27 @@ decl: | TOK_GLOBAL def_global_id opt_type init_class opt_init opt_attr ';' { - add_global($2, $3, $4, $5, $6, VAR_REGULAR); + add_global($2, {AdoptRef{}, $3}, $4, {AdoptRef{}, $5}, $6, VAR_REGULAR); zeekygen_mgr->Identifier($2); } | TOK_OPTION def_global_id opt_type init_class opt_init opt_attr ';' { - add_global($2, $3, $4, $5, $6, VAR_OPTION); + add_global($2, {AdoptRef{}, $3}, $4, {AdoptRef{}, $5}, $6, VAR_OPTION); zeekygen_mgr->Identifier($2); } | TOK_CONST def_global_id opt_type init_class opt_init opt_attr ';' { - add_global($2, $3, $4, $5, $6, VAR_CONST); + add_global($2, {AdoptRef{}, $3}, $4, {AdoptRef{}, $5}, $6, VAR_CONST); zeekygen_mgr->Identifier($2); } | 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 init{AdoptRef{}, $5}; + add_global($2, {AdoptRef{}, $3}, $4, init, $6, VAR_REDEF); + zeekygen_mgr->Redef($2, ::filename, $4, init.release()); } | TOK_REDEF TOK_ENUM global_id TOK_ADD_TO '{' @@ -1140,7 +1140,7 @@ decl: type opt_attr ';' { cur_decl_type_id = 0; - add_type($2, $5, $6); + add_type($2, {AdoptRef{}, $5}, $6); zeekygen_mgr->Identifier($2); } @@ -1172,7 +1172,7 @@ func_hdr: TOK_FUNCTION def_global_id func_params opt_attr { begin_func($2, current_module.c_str(), - FUNC_FLAVOR_FUNCTION, 0, $3, $4); + FUNC_FLAVOR_FUNCTION, 0, {NewRef{}, $3}, $4); $$ = $3; zeekygen_mgr->Identifier($2); } @@ -1186,7 +1186,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 +1194,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 +1221,7 @@ func_body: '}' { set_location(func_hdr_location, @5); - end_func($3); + end_func({AdoptRef{}, $3}); } ; @@ -1260,7 +1260,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}); } ; @@ -1492,7 +1492,7 @@ 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 +1500,7 @@ 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($$); } @@ -1634,19 +1634,18 @@ case_type: | 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}; + IntrusivePtr case_var{AdoptRef{}, 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); + case_var = {NewRef{}, 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: diff --git a/src/plugin/ComponentManager.h b/src/plugin/ComponentManager.h index 848d989faa..ba3ae39c47 100644 --- a/src/plugin/ComponentManager.h +++ b/src/plugin/ComponentManager.h @@ -134,7 +134,7 @@ ComponentManager::ComponentManager(const string& arg_module, const string& tag_enum_type(make_intrusive(module + "::" + local_id)) { ::ID* id = install_ID(local_id.c_str(), module.c_str(), true, true); - add_type(id, tag_enum_type.get(), 0); + add_type(id, tag_enum_type, 0); zeekygen_mgr->Identifier(id); } From 8ea1d895292fdb0186caebeca2198248c2abb326 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 26 Feb 2020 05:39:01 +0100 Subject: [PATCH 05/22] Scope: unref all inits in destructor Fixes memory leak. Proof that the Scope class is responsible for freeing those objects can be found infunction_ingredients::~function_ingredients(). --- src/Scope.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Scope.cc b/src/Scope.cc index dce70f7639..1d919ea2c9 100644 --- a/src/Scope.cc +++ b/src/Scope.cc @@ -56,7 +56,13 @@ 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) From 875bfc09a2ca9c5c28598723cc01631aebbeeb5f Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 26 Feb 2020 05:48:38 +0100 Subject: [PATCH 06/22] Scope: pop_scope() returns IntrusivePtr<> Make sure unused scopes are freed to fix memory leaks. The comment inside pop_scope() is now obsolete and I deleted it, because this commit implements the real solution. Note that this requires us to add a reference to the push_existing_scope() call in dbg_eval_expr(), because it never owned the reference. --- src/Debug.cc | 4 ++++ src/Scope.cc | 9 +++------ src/Scope.h | 3 ++- src/Var.cc | 3 ++- src/parse.y | 3 ++- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/Debug.cc b/src/Debug.cc index e0f6ca33f5..130783bbd7 100644 --- a/src/Debug.cc +++ b/src/Debug.cc @@ -20,6 +20,7 @@ using namespace std; #include "Stmt.h" #include "Frame.h" #include "Func.h" +#include "IntrusivePtr.h" #include "Scope.h" #include "PolicyFile.h" #include "Desc.h" @@ -968,7 +969,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? diff --git a/src/Scope.cc b/src/Scope.cc index 1d919ea2c9..99332f7b8d 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" @@ -204,21 +205,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..83772e1b9f 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; @@ -89,7 +90,7 @@ 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(); +extern IntrusivePtr pop_scope(); extern Scope* current_scope(); extern Scope* global_scope(); diff --git a/src/Var.cc b/src/Var.cc index 1088a67dad..56e00432e6 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" @@ -468,7 +469,7 @@ TraversalCode OuterIDBindingFinder::PostExpr(const Expr* expr) void end_func(IntrusivePtr body) { - auto ingredients = std::make_unique(pop_scope(), body.release()); + auto ingredients = std::make_unique(pop_scope().release(), body.release()); if ( streq(ingredients->id->Name(), "anonymous-function") ) { diff --git a/src/parse.y b/src/parse.y index 47dc9ed2d7..37e47429a4 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" @@ -1250,7 +1251,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)); } From b654a68c86441069996f2f2cdf96a09d40b8139e Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 26 Feb 2020 05:45:36 +0100 Subject: [PATCH 07/22] main: free the global scope in terminate_bro() Make valgrind a bit happier. --- src/main.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main.cc b/src/main.cc index 152e3c77e9..e8f414fe32 100644 --- a/src/main.cc +++ b/src/main.cc @@ -308,6 +308,9 @@ void terminate_bro() delete plugin_mgr; delete val_mgr; + // free the global scope + pop_scope(); + reporter = 0; } From b60cccc63753afe0229bf398f11cfa648647138a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 26 Feb 2020 05:43:19 +0100 Subject: [PATCH 08/22] zeekygen/IdentifierInfo: delete duplicate fields Fixes memory leak. --- src/zeekygen/IdentifierInfo.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/zeekygen/IdentifierInfo.cc b/src/zeekygen/IdentifierInfo.cc index 36f5036f73..c94dd7fb99 100644 --- a/src/zeekygen/IdentifierInfo.cc +++ b/src/zeekygen/IdentifierInfo.cc @@ -51,7 +51,14 @@ void IdentifierInfo::AddRecordField(const TypeDecl* field, rf->field = new TypeDecl(*field); rf->from_script = script; rf->comments = comments; - fields[rf->field->id] = rf; + + auto i = fields.emplace(rf->field->id, rf); + if ( ! i.second ) + { + delete i.first->second; + i.first->second = rf; + } + last_field_seen = rf; } From 56e8a5f11688a19f784a712ed0c3d32b8ce947d9 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 26 Feb 2020 10:46:09 +0100 Subject: [PATCH 09/22] main: destroy event_registry after iosource_mgr Fixes use-after-free bugs because PcapSource::Close() queues an event. --- src/main.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cc b/src/main.cc index e8f414fe32..b47d2fcf59 100644 --- a/src/main.cc +++ b/src/main.cc @@ -298,11 +298,11 @@ 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; From 783f833d5f059a0faa83507d903e7139def40d85 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 26 Feb 2020 05:31:15 +0100 Subject: [PATCH 10/22] EventRegistry: automatically delete EventHandlers Fixes memory leak. --- src/EventRegistry.cc | 15 +++++++++------ src/EventRegistry.h | 7 ++++--- 2 files changed, 13 insertions(+), 9 deletions(-) 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; From cbb6f097261edbfa43d2affea04fba573c785b55 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 26 Feb 2020 07:56:26 +0100 Subject: [PATCH 11/22] Scope: delete duplicate locals --- src/Scope.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Scope.h b/src/Scope.h index 83772e1b9f..ea96422c2c 100644 --- a/src/Scope.h +++ b/src/Scope.h @@ -31,7 +31,15 @@ public: } template - void Insert(N &&name, ID* id) { local[std::forward(name)] = id; } + void Insert(N &&name, ID* id) + { + auto i = local.emplace(std::forward(name), id); + if ( ! i.second ) + { + Unref(i.first->second); + i.first->second = id; + } + } template ID* Remove(N &&name) From 528cf11a5cc1dadc3948b3c49e11c73558785bef Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 26 Feb 2020 07:58:06 +0100 Subject: [PATCH 12/22] Scope: lookup_ID() and install_ID() return IntrusivePtr This fixes several memory leaks and double free bugs. --- src/Debug.cc | 8 +----- src/EventHandler.cc | 6 ++--- src/Expr.cc | 2 +- src/Func.cc | 3 +-- src/RuleMatcher.cc | 8 +++--- src/Scope.cc | 18 +++++-------- src/Scope.h | 4 +-- src/Stmt.cc | 2 +- src/Type.cc | 7 ++--- src/Var.cc | 31 +++++++-------------- src/input/Manager.cc | 2 +- src/parse.y | 51 +++++++++++++++-------------------- src/plugin/ComponentManager.h | 6 ++--- src/scan.l | 12 +++------ 14 files changed, 60 insertions(+), 100 deletions(-) diff --git a/src/Debug.cc b/src/Debug.cc index 130783bbd7..d592e69b73 100644 --- a/src/Debug.cc +++ b/src/Debug.cc @@ -196,13 +196,12 @@ 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; } @@ -210,7 +209,6 @@ static void parse_function_name(vector& result, { debug_msg("Function %s not declared.\n", id->Name()); plr.type = plrUnknown; - Unref(id); return; } @@ -218,7 +216,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; } @@ -229,12 +226,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 ) 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/Expr.cc b/src/Expr.cc index b1f43c5536..4821330e16 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -4455,7 +4455,7 @@ 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()); diff --git a/src/Func.cc b/src/Func.cc index ce7367d649..47993ba03b 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -606,7 +606,7 @@ 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() ) @@ -614,7 +614,6 @@ BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name, type = id->Type()->Ref(); id->SetVal(new Val(this)); - Unref(id); } BuiltinFunc::~BuiltinFunc() 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 99332f7b8d..ed251111f4 100644 --- a/src/Scope.cc +++ b/src/Scope.cc @@ -126,7 +126,7 @@ TraversalCode Scope::Traverse(TraversalCallback* cb) const } -ID* lookup_ID(const char* name, const char* curr_module, bool no_global, +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); @@ -144,8 +144,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}; } } @@ -155,16 +154,13 @@ 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, +IntrusivePtr install_ID(const char* name, const char* module_name, bool is_global, bool is_export) { if ( scopes.empty() && ! is_global ) @@ -182,13 +178,13 @@ 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; diff --git a/src/Scope.h b/src/Scope.h index ea96422c2c..1db9681e79 100644 --- a/src/Scope.h +++ b/src/Scope.h @@ -88,10 +88,10 @@ 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, +extern IntrusivePtr 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, +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); diff --git a/src/Stmt.cc b/src/Stmt.cc index da31fa5a4b..e9a54917f9 100644 --- a/src/Stmt.cc +++ b/src/Stmt.cc @@ -199,7 +199,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()); diff --git a/src/Type.cc b/src/Type.cc index 210f48a493..31ee469b64 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -1172,7 +1172,7 @@ 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 ) { @@ -1183,7 +1183,7 @@ void EnumType::CheckAndAddName(const string& module_name, const char* name, if ( deprecation ) id->MakeDeprecated(deprecation); - zeekygen_mgr->Identifier(id); + zeekygen_mgr->Identifier(id.get()); } else { @@ -1195,13 +1195,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); diff --git a/src/Var.cc b/src/Var.cc index 56e00432e6..671eb6f524 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -396,13 +396,11 @@ 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()); } @@ -509,14 +507,12 @@ void end_func(IntrusivePtr 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) @@ -541,24 +537,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() : 0; } double opt_internal_double(const char* name) @@ -593,12 +585,11 @@ TableVal* opt_internal_table(const char* name) 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; Val* v = id->ID_Val(); - Unref(id); if ( v ) { @@ -621,13 +612,11 @@ ListVal* internal_list_val(const char* name) 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) diff --git a/src/input/Manager.cc b/src/input/Manager.cc index c5e56f3830..fcd574647f 100644 --- a/src/input/Manager.cc +++ b/src/input/Manager.cc @@ -2622,7 +2622,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/parse.y b/src/parse.y index 37e47429a4..a7c5b1e980 100644 --- a/src/parse.y +++ b/src/parse.y @@ -666,7 +666,7 @@ expr: { set_location(@1); - ID* id = lookup_ID($1, current_module.c_str()); + auto id = lookup_ID($1, current_module.c_str()); if ( ! id ) { if ( ! in_debug ) @@ -687,12 +687,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); + $$ = new NameExpr(id.release()); } else if ( id->IsEnumConst() ) @@ -706,14 +708,8 @@ expr: } else { - Ref(id); - $$ = new NameExpr(id); + $$ = new NameExpr(id.release()); } - - if ( id->IsDeprecated() ) - reporter->Warning("%s", id->GetDeprecationWarning().c_str()); - - Unref(id); } } @@ -1578,7 +1574,7 @@ event: { set_location(@1, @4); - ID* id = lookup_ID($1, current_module.c_str()); + auto id = lookup_ID($1, current_module.c_str()); if ( id ) { if ( ! id->IsGlobal() ) @@ -1588,8 +1584,6 @@ event: } if ( id->IsDeprecated() ) reporter->Warning("%s", id->GetDeprecationWarning().c_str()); - - Unref(id); } $$ = new EventExpr($1, $3); @@ -1636,13 +1630,13 @@ case_type: { const char* name = $4; IntrusivePtr type{AdoptRef{}, $2}; - IntrusivePtr case_var{AdoptRef{}, lookup_ID(name, current_module.c_str())}; + auto case_var = lookup_ID(name, current_module.c_str()); if ( case_var && case_var->IsGlobal() ) case_var->Error("already a global identifier"); else { - case_var = {NewRef{}, install_ID(name, current_module.c_str(), false, false)}; + case_var = install_ID(name, current_module.c_str(), false, false); } add_local(case_var, std::move(type), INIT_NONE, 0, 0, VAR_REGULAR); @@ -1658,7 +1652,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,13 +1662,12 @@ 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); } @@ -1691,8 +1684,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 +1705,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, $7, val_var.release()); } | TOK_FOR '(' '[' local_id_list ']' ',' TOK_ID TOK_IN expr ')' @@ -1723,7 +1716,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 +1726,7 @@ for_head: else val_var = install_ID($7, module, false, false); - $$ = new ForStmt($4, $9, val_var); + $$ = new ForStmt($4, $9, val_var.release()); } ; @@ -1752,7 +1745,7 @@ local_id: { set_location(@1); - $$ = lookup_ID($1, current_module.c_str()); + $$ = lookup_ID($1, current_module.c_str()).release(); if ( $$ ) { if ( $$->IsGlobal() ) @@ -1763,7 +1756,7 @@ local_id: else { $$ = install_ID($1, current_module.c_str(), - false, is_export); + false, is_export).release(); } } ; @@ -1788,7 +1781,7 @@ global_or_event_id: { set_location(@1); - $$ = lookup_ID($1, current_module.c_str(), false, defining_global_ID); + $$ = lookup_ID($1, current_module.c_str(), false, defining_global_ID).release(); if ( $$ ) { if ( ! $$->IsGlobal() ) @@ -1813,7 +1806,7 @@ global_or_event_id: current_module.c_str() : 0; $$ = install_ID($1, module_name, - true, is_export); + true, is_export).release(); } } ; @@ -1823,7 +1816,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); diff --git a/src/plugin/ComponentManager.h b/src/plugin/ComponentManager.h index ba3ae39c47..8740e376b3 100644 --- a/src/plugin/ComponentManager.h +++ b/src/plugin/ComponentManager.h @@ -133,9 +133,9 @@ ComponentManager::ComponentManager(const string& arg_module, const string& : module(arg_module), tag_enum_type(make_intrusive(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(id.get()); } template diff --git a/src/scan.l b/src/scan.l index 50f035fa2f..ca197501d6 100644 --- a/src/scan.l +++ b/src/scan.l @@ -775,30 +775,26 @@ 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() From 7be3641f1d2805b3a4b5ca57046fdc49c474b3fc Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 27 Feb 2020 11:12:08 +0100 Subject: [PATCH 13/22] Var: copy Location to stack, to fix use-after-free crash bug The AssignExpr constructor may free the "init" pointer via AssignExpr::TypeCheck(), resulting in a crash due to use-after-free. To fix the crash bug, this patch copies the `Location` to the stack instead of using a potentially-dangling pointer. --- src/Var.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Var.cc b/src/Var.cc index 671eb6f524..05bdfbfc7e 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -240,12 +240,15 @@ IntrusivePtr add_local(IntrusivePtr id, IntrusivePtr t, init_ if ( c != INIT_FULL ) id->Error("can't use += / -= for initializations of local variables"); - const Location* location = init->GetLocationInfo(); + // copy the Location to the stack, because AssignExpr + // may free "init" + const Location location = init->GetLocationInfo() != nullptr ? *init->GetLocationInfo() : no_location; + Expr* name_expr = new NameExpr(IntrusivePtr{id}.release(), dt == VAR_CONST); auto stmt = make_intrusive(new AssignExpr(name_expr, init.release(), 0, 0, id->Attrs() ? id->Attrs()->Attrs() : 0 )); - stmt->SetLocationInfo(location); + stmt->SetLocationInfo(&location); return stmt; } From c3ea2462375d7f73b0ff8998161bbc7b21a81f76 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 26 Feb 2020 19:12:57 +0100 Subject: [PATCH 14/22] Expr: use class IntrusivePtr As a side effect, this fixes lots of memory leaks in `*Expr::InitVal()` because in most implementations, the `aggr` parameter leaks. --- src/Attr.cc | 5 +- src/DbgBreakpoint.cc | 7 +- src/Debug.cc | 5 +- src/Debug.h | 3 +- src/DebugCmds.cc | 4 +- src/Expr.cc | 1391 +++++++++++++++++------------------------- src/Expr.h | 339 +++++----- src/Func.cc | 9 +- src/ID.cc | 13 +- src/Stmt.cc | 21 +- src/Trigger.cc | 21 +- src/Type.cc | 53 +- src/Val.cc | 41 +- src/Var.cc | 31 +- src/input/Manager.cc | 3 +- src/parse.y | 140 ++--- src/scan.l | 5 +- 17 files changed, 885 insertions(+), 1206 deletions(-) diff --git a/src/Attr.cc b/src/Attr.cc index 09b17e1e6a..6c5fdfc31f 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(0)->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 d592e69b73..ddfab0a5e4 100644 --- a/src/Debug.cc +++ b/src/Debug.cc @@ -16,6 +16,7 @@ using namespace std; #include "DebugCmds.h" #include "DbgBreakpoint.h" #include "ID.h" +#include "IntrusivePtr.h" #include "Expr.h" #include "Stmt.h" #include "Frame.h" @@ -946,7 +947,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, @@ -981,7 +982,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/Expr.cc b/src/Expr.cc index 4821330e16..7b33a141d8 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" @@ -64,11 +63,6 @@ Expr::Expr(BroExprTag arg_tag) SetLocationInfo(&start_location, &end_location); } -Expr::~Expr() - { - Unref(type); - } - int Expr::CanAdd() const { return 0; @@ -89,11 +83,11 @@ 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 */, @@ -102,15 +96,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; } int Expr::IsRecordElement(TypeDecl* /* td */) const @@ -123,7 +116,7 @@ int Expr::IsPure() const return 1; } -Val* Expr::InitVal(const BroType* t, Val* aggr) const +IntrusivePtr Expr::InitVal(const BroType* t, IntrusivePtr aggr) const { if ( aggr ) { @@ -134,7 +127,7 @@ Val* Expr::InitVal(const BroType* t, Val* aggr) const if ( IsError() ) return 0; - return check_and_promote(Eval(0), t, 1); + return {AdoptRef{}, check_and_promote(Eval(0).release(), t, 1)}; } int Expr::IsError() const @@ -144,7 +137,7 @@ int Expr::IsError() const void Expr::SetError() { - SetType(error_type()); + SetType({AdoptRef{}, error_type()}); } void Expr::SetError(const char* msg) @@ -189,15 +182,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[]) @@ -227,45 +215,39 @@ 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; if ( v ) - return v->Ref(); + return v; else { RuntimeError("value used but not set"); @@ -273,7 +255,7 @@ Val* NameExpr::Eval(Frame* f) const } } -Expr* NameExpr::MakeLvalue() +IntrusivePtr NameExpr::MakeLvalue() { if ( id->AsType() ) ExprError("Type name is not an lvalue"); @@ -284,15 +266,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(v.release()); else - f->SetElement(id, v); + f->SetElement(id.get(), v.release()); } int NameExpr::IsPure() const @@ -326,23 +308,14 @@ 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 @@ -350,9 +323,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 @@ -364,29 +337,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(std::move(arg_tag)) { 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; - Val* v = op->Eval(f); + auto v = op->Eval(f); if ( ! v ) return 0; - 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; @@ -395,22 +363,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()); } } @@ -431,9 +396,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 @@ -462,32 +427,21 @@ 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; - Val* v1 = op1->Eval(f); + auto v1 = op1->Eval(f); if ( ! v1 ) return 0; - Val* v2 = op2->Eval(f); + auto v2 = op2->Eval(f); if ( ! v2 ) - { - Unref(v1); return 0; - } - 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 @@ -496,34 +450,30 @@ 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; } - 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); // 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 ) { @@ -531,24 +481,18 @@ Val* BinaryExpr::Eval(Frame* f) const if ( vv_i ) v_result->Assign(i, is_vec1 ? - Fold(vv_i, v2) : Fold(v1, vv_i)); + Fold(vv_i, v2.get()).release() : Fold(v1.get(), vv_i).release()); else v_result->Assign(i, 0); // 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()); } int BinaryExpr::IsPure() const @@ -582,7 +526,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(); @@ -733,23 +677,23 @@ 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(); @@ -773,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(); @@ -796,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(); @@ -808,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); @@ -851,10 +795,10 @@ Val* BinaryExpr::SetFold(Val* v1, Val* v2) const return 0; } - 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(); @@ -885,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(); @@ -898,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) @@ -926,48 +869,45 @@ 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)); + SetType(is_vector ? make_intrusive(base_type(t)) : IntrusivePtr{NewRef{}, 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; - Val* v = op->Eval(f); + auto v = op->Eval(f); if ( ! v ) return 0; - 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) +IncrExpr::IncrExpr(BroExprTag arg_tag, IntrusivePtr arg_op) : UnaryExpr(arg_tag, arg_op->MakeLvalue()) { if ( IsError() ) @@ -982,7 +922,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 @@ -990,11 +930,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(); @@ -1014,41 +954,39 @@ 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); + auto v = op->Eval(f); if ( ! v ) return 0; - if ( is_vector(v) ) + 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); } - 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; } } @@ -1058,7 +996,7 @@ int IncrExpr::IsPure() const return 0; } -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; @@ -1069,15 +1007,15 @@ 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; @@ -1088,15 +1026,15 @@ 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; @@ -1116,23 +1054,23 @@ 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; @@ -1152,51 +1090,49 @@ 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; - 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; @@ -1218,7 +1154,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 @@ -1226,25 +1162,25 @@ 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) +AddToExpr::AddToExpr(IntrusivePtr arg_op1, IntrusivePtr arg_op2) : BinaryExpr(EXPR_ADD_TO, - is_vector(arg_op1) ? arg_op1 : arg_op1->MakeLvalue(), arg_op2) + is_vector(arg_op1.get()) ? std::move(arg_op1) : arg_op1->MakeLvalue(), std::move(arg_op2)) { if ( IsError() ) return; @@ -1253,11 +1189,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) ) { @@ -1268,9 +1204,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 @@ -1282,49 +1218,44 @@ 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; - Val* v2 = op2->Eval(f); + auto v2 = op2->Eval(f); if ( ! v2 ) - { - Unref(v1); return 0; - } - 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; } -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; @@ -1346,7 +1277,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); @@ -1354,28 +1285,28 @@ 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; @@ -1384,42 +1315,36 @@ 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; - Val* v2 = op2->Eval(f); + auto v2 = op2->Eval(f); if ( ! v2 ) - { - Unref(v1); return 0; - } - 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; } -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; @@ -1437,25 +1362,25 @@ TimesExpr::TimesExpr(Expr* arg_op1, Expr* arg_op2) 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; @@ -1471,30 +1396,30 @@ DivideExpr::DivideExpr(Expr* arg_op1, Expr* arg_op2) 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 ) @@ -1515,11 +1440,11 @@ 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; @@ -1533,13 +1458,13 @@ ModExpr::ModExpr(Expr* arg_op1, Expr* arg_op2) 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; @@ -1554,20 +1479,20 @@ BoolExpr::BoolExpr(BroExprTag arg_tag, Expr* arg_op1, Expr* arg_op2) 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; @@ -1577,107 +1502,90 @@ Val* BoolExpr::DoSingleEval(Frame* f, Val* v1, Expr* op2) const 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; - Val* v1 = op1->Eval(f); + auto v1 = op1->Eval(f); if ( ! v1 ) return 0; - int is_vec1 = is_vector(op1); - int is_vec2 = is_vector(op2); + int is_vec1 = is_vector(op1.get()); + int 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; - } - 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); + 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; - } 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; } - 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 ) @@ -1696,14 +1604,11 @@ 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; @@ -1724,10 +1629,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 ) @@ -1737,13 +1642,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"); } @@ -1752,8 +1657,8 @@ 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; @@ -1771,10 +1676,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)); @@ -1833,28 +1738,28 @@ 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; @@ -1872,10 +1777,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)); @@ -1910,13 +1815,9 @@ 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(); @@ -1930,14 +1831,14 @@ 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; @@ -1947,14 +1848,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 ) @@ -1966,48 +1867,32 @@ 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) ) + if ( ! is_vector(op1.get()) ) { // scalar is easy - Val* v = op1->Eval(f); - int false_eval = v->IsZero(); - Unref(v); + int 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; - Val* v2 = op2->Eval(f); + auto v2 = op2->Eval(f); if ( ! v2 ) - { - Unref(v1); return 0; - } - Val* v3 = op3->Eval(f); + auto v3 = op3->Eval(f); if ( ! v3 ) - { - Unref(v1); - Unref(v2); return 0; - } VectorVal* cond = v1->AsVectorVal(); VectorVal* a = v2->AsVectorVal(); @@ -2015,14 +1900,11 @@ 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; } - 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 ) @@ -2037,10 +1919,6 @@ Val* CondExpr::Eval(Frame* f) const result->Assign(i, 0); } - Unref(v1); - Unref(v2); - Unref(v3); - return result; } @@ -2076,7 +1954,7 @@ 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; @@ -2084,23 +1962,23 @@ 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) +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 ? arg_op1 : arg_op1->MakeLvalue(), arg_op2) + arg_is_init ? std::move(arg_op1) : arg_op1->MakeLvalue(), std::move(arg_op2)) { val = 0; is_init = arg_is_init; @@ -2108,12 +1986,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; } @@ -2121,14 +1999,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) @@ -2152,14 +2025,14 @@ 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; } @@ -2175,9 +2048,9 @@ bool AssignExpr::TypeCheck(attr_list* attrs) bool empty_list_assignment = (op2->AsListExpr()->Exprs().length() == 0); 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()) ) { @@ -2196,13 +2069,13 @@ 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; } } @@ -2228,7 +2101,7 @@ 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; } @@ -2241,7 +2114,7 @@ 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"); @@ -2265,7 +2138,7 @@ 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 ) @@ -2306,7 +2179,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(); } @@ -2317,7 +2190,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(); } @@ -2330,7 +2203,7 @@ bool AssignExpr::TypeCheckArithmetics(TypeTag bt1, TypeTag bt2) } -Val* AssignExpr::Eval(Frame* f) const +IntrusivePtr AssignExpr::Eval(Frame* f) const { if ( is_init ) { @@ -2338,17 +2211,14 @@ Val* AssignExpr::Eval(Frame* f) const return 0; } - 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; } @@ -2356,7 +2226,7 @@ Val* AssignExpr::Eval(Frame* f) const return 0; } -BroType* AssignExpr::InitType() const +IntrusivePtr AssignExpr::InitType() const { if ( op1->Tag() != EXPR_LIST ) { @@ -2368,7 +2238,7 @@ BroType* AssignExpr::InitType() const 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 @@ -2396,9 +2266,9 @@ 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; } @@ -2408,22 +2278,16 @@ 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); + IntrusivePtr v{AdoptRef{}, check_and_promote(op2->Eval(f).release(), 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 ) { @@ -2455,7 +2319,7 @@ Val* AssignExpr::InitVal(const BroType* t, Val* aggr) const 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), 0); if ( ! v ) return 0; @@ -2474,20 +2338,17 @@ Val* AssignExpr::InitVal(const BroType* t, Val* aggr) const if ( aggr->Type()->Tag() != TYPE_TABLE ) Internal("bad aggregate in AssignExpr::InitVal"); - TableVal* tv = aggr->AsTableVal(); + IntrusivePtr tv{NewRef{}, aggr->AsTableVal()}; // TODO: implement safer IntrusivePtr casts 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(), 0); + auto v = op2->InitVal(yt, 0); if ( ! index || ! v ) return 0; if ( ! tv->ExpandAndInit(std::move(index), std::move(v)) ) - { - Unref(tv); return 0; - } return tv; } @@ -2505,7 +2366,7 @@ int 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()); } @@ -2521,12 +2382,12 @@ int AssignExpr::IsPure() const return 0; } -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 ) { @@ -2534,16 +2395,16 @@ Val* IndexSliceAssignExpr::Eval(Frame* f) const return 0; } - Val* v = op2->Eval(f); + auto v = op2->Eval(f); if ( v ) - op1->Assign(f, v); + op1->Assign(f, std::move(v)); return 0; } -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; @@ -2556,14 +2417,14 @@ 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 = @@ -2575,20 +2436,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)); + 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"); @@ -2617,21 +2478,15 @@ 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(), 0); } void IndexExpr::Delete(Frame* f) @@ -2639,53 +2494,41 @@ 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; - Val* v2 = op2->Eval(f); + auto v2 = op2->Eval(f); if ( ! v2 ) - { - Unref(v1); return 0; - } - - Val* result; 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()) ) @@ -2693,7 +2536,6 @@ 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; } @@ -2718,13 +2560,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) @@ -2737,12 +2577,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; - Val* v = 0; + IntrusivePtr v; switch ( v1->Type()->Tag() ) { case TYPE_VECTOR: @@ -2751,11 +2591,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); @@ -2778,7 +2618,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: @@ -2810,7 +2650,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: @@ -2818,37 +2658,31 @@ Val* IndexExpr::Fold(Val* v1, Val* v2) const break; } - if ( v ) - return v->Ref(); + if (v) + return v; RuntimeError("no such index"); return 0; } -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}; + const auto v_extra = v; switch ( v1->Type()->Tag() ) { case TYPE_VECTOR: @@ -2872,9 +2706,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 ) { @@ -2894,9 +2728,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 ) { @@ -2922,9 +2756,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 @@ -2953,8 +2784,8 @@ 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; @@ -2974,7 +2805,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) ) @@ -2988,9 +2819,9 @@ FieldExpr::~FieldExpr() delete [] field_name; } -Expr* FieldExpr::MakeLvalue() +IntrusivePtr FieldExpr::MakeLvalue() { - return new RefExpr(this); + return make_intrusive(IntrusivePtr{NewRef{}, this}); } int FieldExpr::CanDel() const @@ -2998,23 +2829,17 @@ int 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) @@ -3022,11 +2847,11 @@ 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; @@ -3054,8 +2879,8 @@ 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; @@ -3075,7 +2900,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)}); } } @@ -3084,20 +2909,17 @@ 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); + return {AdoptRef{}, 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; + IntrusivePtr r{NewRef{}, rec_to_look_at->AsRecordVal()}; + return {AdoptRef{}, val_mgr->GetBool(r->Lookup(field) != 0)}; } void HasFieldExpr::ExprDescribe(ODesc* d) const @@ -3115,8 +2937,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; @@ -3124,7 +2946,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 ) @@ -3142,22 +2964,21 @@ 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(0); 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; @@ -3167,7 +2988,7 @@ Val* RecordConstructorExpr::InitVal(const BroType* t, Val* aggr) const return 0; } -Val* RecordConstructorExpr::Fold(Val* v) const +IntrusivePtr RecordConstructorExpr::Fold(Val* v) const { ListVal* lv = v->AsListVal(); RecordType* rt = type->AsRecordType(); @@ -3175,7 +2996,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()); @@ -3190,9 +3011,9 @@ 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 = 0; @@ -3203,20 +3024,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().length() == 0 ) - SetType(new TableType(new TypeList(base_type(TYPE_ANY)), 0)); + if ( op->AsListExpr()->Exprs().length() == 0 ) + 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(); @@ -3227,10 +3048,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 ) @@ -3264,33 +3085,33 @@ TableConstructorExpr::TableConstructorExpr(ListExpr* constructor_list, } } -Val* TableConstructorExpr::Eval(Frame* f) const +IntrusivePtr TableConstructorExpr::Eval(Frame* f) const { if ( IsError() ) return 0; - 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; 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; } @@ -3302,9 +3123,9 @@ 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 = 0; @@ -3315,19 +3136,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().length() == 0 ) - SetType(new ::SetType(new TypeList(base_type(TYPE_ANY)), 0)); + if ( op->AsListExpr()->Exprs().length() == 0 ) + 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 ) @@ -3336,14 +3157,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"); } @@ -3370,45 +3191,42 @@ SetConstructorExpr::SetConstructorExpr(ListExpr* constructor_list, } } -Val* SetConstructorExpr::Eval(Frame* f) const +IntrusivePtr SetConstructorExpr::Eval(Frame* f) const { if ( IsError() ) return 0; - 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; 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); + IntrusivePtr element = {AdoptRef{}, check_and_promote(e->Eval(0).release(), 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; } - - Unref(element); } return tval; @@ -3421,9 +3239,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; @@ -3432,29 +3250,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().length() == 0 ) + if ( op->AsListExpr()->Exprs().length() == 0 ) { // 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 @@ -3464,24 +3282,24 @@ 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; - 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; @@ -3491,25 +3309,23 @@ Val* VectorConstructorExpr::Eval(Frame* f) const return vec; } -Val* VectorConstructorExpr::InitVal(const BroType* t, Val* aggr) const +IntrusivePtr VectorConstructorExpr::InitVal(const BroType* t, IntrusivePtr aggr) const { if ( IsError() ) return 0; 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); + IntrusivePtr v{AdoptRef{}, check_and_promote(e->Eval(0).release(), 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; } } @@ -3524,11 +3340,10 @@ 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) @@ -3539,7 +3354,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 ) { @@ -3549,7 +3364,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()); } } @@ -3572,8 +3387,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; @@ -3583,11 +3398,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"); @@ -3601,17 +3416,17 @@ 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"); @@ -3619,7 +3434,7 @@ Val* ArithCoerceExpr::FoldSingleVal(Val* v, InternalTypeTag t) const } } -Val* ArithCoerceExpr::Fold(Val* v) const +IntrusivePtr ArithCoerceExpr::Fold(Val* v) const { InternalTypeTag t = type->InternalType(); @@ -3636,12 +3451,12 @@ Val* ArithCoerceExpr::Fold(Val* v) const 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); } @@ -3649,8 +3464,8 @@ 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_size = 0; map = 0; @@ -3658,7 +3473,7 @@ RecordCoerceExpr::RecordCoerceExpr(Expr* op, RecordType* r) if ( IsError() ) return; - SetType(r->Ref()); + SetType(std::move(r)); if ( Type()->Tag() != TYPE_RECORD ) ExprError("coercion to non-record"); @@ -3763,15 +3578,14 @@ 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(0); 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; @@ -3781,16 +3595,16 @@ Val* RecordCoerceExpr::InitVal(const BroType* t, Val* aggr) const return 0; } -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( @@ -3799,8 +3613,6 @@ Val* RecordCoerceExpr::Fold(Val* v) const if ( def ) rhs = def->AttrExpr()->Eval(0); } - else - rhs = rhs->Ref(); assert(rhs || Type()->AsRecordType()->FieldDecl(i)->FindAttr(ATTR_OPTIONAL)); @@ -3819,30 +3631,26 @@ 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()) ) + if ( Val* new_val = check_and_promote(rhs.release(), field_type, false, op->GetLocationInfo()) ) { - // Don't call unref here on rhs because check_and_promote already called it. - rhs = new_val; + rhs = {AdoptRef{}, new_val}; } else { - Unref(val); RuntimeError("Failed type conversion"); } } - val->Assign(i, rhs); + val->Assign(i, rhs.release()); } else { @@ -3851,7 +3659,7 @@ Val* RecordCoerceExpr::Fold(Val* v) const if ( def ) { - Val* def_val = def->AttrExpr()->Eval(0); + auto def_val = def->AttrExpr()->Eval(0); BroType* def_type = def_val->Type(); BroType* field_type = Type()->AsRecordType()->FieldType(i); @@ -3864,12 +3672,11 @@ Val* RecordCoerceExpr::Fold(Val* v) const 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); @@ -3879,13 +3686,13 @@ 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"); @@ -3899,23 +3706,23 @@ 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"); @@ -3929,18 +3736,18 @@ 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; @@ -3952,18 +3759,18 @@ FlattenExpr::FlattenExpr(Expr* arg_op) 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 ) { @@ -3978,7 +3785,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(0).release()); else RuntimeError("missing field value"); @@ -4006,12 +3813,9 @@ 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; @@ -4019,13 +3823,7 @@ ScheduleExpr::ScheduleExpr(Expr* arg_when, EventExpr* arg_event) 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)}); } int ScheduleExpr::IsPure() const @@ -4033,12 +3831,12 @@ int ScheduleExpr::IsPure() const return 0; } -Val* ScheduleExpr::Eval(Frame* f) const +IntrusivePtr ScheduleExpr::Eval(Frame* f) const { if ( terminating ) return 0; - Val* when_val = when->Eval(f); + auto when_val = when->Eval(f); if ( ! when_val ) return 0; @@ -4058,8 +3856,6 @@ Val* ScheduleExpr::Eval(Frame* f) const tmgr->Add(new ScheduleTimer(event->Handler(), args, dt, tmgr)); } - Unref(when_val); - return 0; } @@ -4098,8 +3894,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; @@ -4108,11 +3904,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 ) @@ -4135,13 +3931,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 { @@ -4152,40 +3948,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 ) @@ -4194,12 +3987,12 @@ 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); + return {AdoptRef{}, val_mgr->GetBool(strstr_n(s2->Len(), s2->Bytes(), s1->Len(), reinterpret_cast(s1->CheckString())) != -1)}; } 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; @@ -4209,17 +4002,14 @@ Val* InExpr::Fold(Val* v1, Val* v2) const res = v2->AsTableVal()->Lookup(v1, false); if ( res ) - return val_mgr->GetBool(1); + return {AdoptRef{}, val_mgr->GetBool(1)}; else - return val_mgr->GetBool(0); + return {AdoptRef{}, val_mgr->GetBool(0)}; } -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(); @@ -4241,7 +4031,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 { @@ -4273,18 +4063,18 @@ 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. - Val* func_val; + IntrusivePtr 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 && @@ -4298,12 +4088,6 @@ CallExpr::CallExpr(Expr* arg_func, ListExpr* arg_args, bool in_hook) } } -CallExpr::~CallExpr() - { - Unref(func); - Unref(args); - } - int CallExpr::IsPure() const { if ( IsError() ) @@ -4312,7 +4096,7 @@ int CallExpr::IsPure() const if ( ! func->IsPure() ) return 0; - Val* func_val = func->Eval(0); + auto func_val = func->Eval(0); if ( ! func_val ) return 0; @@ -4325,12 +4109,11 @@ int CallExpr::IsPure() const 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; @@ -4350,14 +4133,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 ) { @@ -4367,7 +4150,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); @@ -4378,8 +4161,6 @@ Val* CallExpr::Eval(Frame* f) const else delete_vals(v); - Unref(func_val); - return ret; } @@ -4417,7 +4198,7 @@ LambdaExpr::LambdaExpr(std::unique_ptr arg_ing, 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. @@ -4467,10 +4248,10 @@ LambdaExpr::LambdaExpr(std::unique_ptr arg_ing, 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, @@ -4483,9 +4264,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 @@ -4506,11 +4285,10 @@ 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), args(std::move(arg_args)) { name = arg_name; - args = arg_args; EventHandler* h = event_registry->Lookup(name); if ( ! h ) @@ -4537,7 +4315,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 { @@ -4549,17 +4327,12 @@ 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; - val_list* v = eval_list(f, args); + val_list* v = eval_list(f, args.get()); mgr.QueueEvent(handler, std::move(*v)); delete v; @@ -4593,13 +4366,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() @@ -4608,10 +4381,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()); } int ListExpr::IsPure() const @@ -4632,27 +4405,26 @@ int ListExpr::AllConst() const return 1; } -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; } - v->Append(ev); + v->Append(ev.release()); } return v; } -BroType* ListExpr::InitType() const +IntrusivePtr ListExpr::InitType() const { if ( exprs.length() == 0 ) { @@ -4678,12 +4450,12 @@ BroType* ListExpr::InitType() const } - 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(); @@ -4709,7 +4481,7 @@ 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 @@ -4722,26 +4494,22 @@ Val* ListExpr::InitVal(const BroType* t, Val* aggr) const // 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; } loop_over_list(exprs, i) { - Val* vi = exprs[i]->InitVal((*tl)[i], 0); + auto vi = exprs[i]->InitVal((*tl)[i], 0); if ( ! vi ) - { - Unref(v); return 0; - } - v->Append(vi); + v->Append(vi.release()); } return v; } @@ -4761,16 +4529,13 @@ Val* ListExpr::InitVal(const BroType* t, Val* aggr) const return 0; } - 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], 0); if ( ! vi ) - { - Unref(v); return 0; - } - v->Append(vi); + v->Append(vi.release()); } return v; } @@ -4792,7 +4557,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 ) { @@ -4803,15 +4568,15 @@ 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(0); + if ( ! vec->Assign(i, v.release()) ) { e->Error(fmt("type mismatch at index %d", i)); return 0; } } - return aggr; + return std::move(aggr); } // If we got this far, then it's either a table or record @@ -4834,7 +4599,7 @@ Val* ListExpr::InitVal(const BroType* t, Val* aggr) const return 0; } - Val* v = e->Eval(0); + auto v = e->Eval(0); if ( ! same_type(v->Type(), t) ) { v->Type()->Error("type clash in table initializer", t); @@ -4849,7 +4614,7 @@ Val* ListExpr::InitVal(const BroType* t, Val* aggr) const 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"); @@ -4860,7 +4625,7 @@ 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. @@ -4888,22 +4653,19 @@ Val* ListExpr::AddSetInit(const BroType* t, Val* aggr) const } if ( expr->Type()->Tag() == TYPE_LIST ) - element = check_and_promote(element, it, 1); + element = {AdoptRef{}, check_and_promote(element.release(), it, 1)}; else - element = check_and_promote(element, (*it->Types())[0], 1); + element = {AdoptRef{}, check_and_promote(element.release(), (*it->Types())[0], 1)}; if ( ! element ) return 0; - if ( ! tv->ExpandAndInit({AdoptRef{}, element}, 0) ) - { - Unref(tv); + if ( ! tv->ExpandAndInit(std::move(element), 0) ) return 0; - } } - return tv; + return std::move(aggr); } void ListExpr::ExprDescribe(ODesc* d) const @@ -4919,16 +4681,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(); @@ -4936,9 +4698,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 @@ -4956,7 +4716,7 @@ 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(); @@ -4981,9 +4741,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)); } } } @@ -4996,9 +4756,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 { @@ -5017,34 +4777,30 @@ 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; - Val* v = op->Eval(f); + auto v = op->Eval(f); if ( ! v ) return 0; - Val* nv = cast_value_to_type(v, Type()); + IntrusivePtr nv{AdoptRef{}, cast_value_to_type(v.get(), Type())}; if ( nv ) - { - Unref(v); return nv; - } ODesc d; d.Add("invalid cast of value with type '"); @@ -5057,7 +4813,6 @@ Val* CastExpr::Eval(Frame* f) const ! v->AsRecordVal()->Lookup(0) ) d.Add(" (nil $data field)"); - Unref(v); RuntimeError(d.Description()); return 0; // not reached. } @@ -5069,28 +4824,20 @@ 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; - if ( can_cast_value_to_type(v, t) ) - return val_mgr->GetBool(1); + if ( can_cast_value_to_type(v, t.get()) ) + return {AdoptRef{}, val_mgr->GetBool(1)}; else - return val_mgr->GetBool(0); + return {AdoptRef{}, val_mgr->GetBool(0)}; } void IsExpr::ExprDescribe(ODesc* d) const @@ -5100,15 +4847,15 @@ 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) @@ -5138,7 +4885,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; } @@ -5163,7 +4910,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; } @@ -5177,14 +4924,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; } @@ -5300,13 +5047,13 @@ val_list* eval_list(Frame* f, const ListExpr* l) 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 ) diff --git a/src/Expr.h b/src/Expr.h index 771f4782e5..c2bcebae79 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -5,6 +5,7 @@ // BRO expressions. #include "BroList.h" +#include "IntrusivePtr.h" #include "Timer.h" #include "Type.h" #include "EventHandler.h" @@ -58,6 +59,7 @@ typedef enum { extern const char* expr_name(BroExprTag t); +template class IntrusivePtr; class Stmt; class Frame; class ListExpr; @@ -72,16 +74,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 +91,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 +108,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 int IsPure() const; @@ -145,7 +144,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 +213,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 +224,20 @@ protected: void RuntimeErrorWithCallStack(const std::string& msg) const; BroExprTag tag; - BroType* type; + IntrusivePtr type; int 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; int IsPure() const override; TraversalCode Traverse(TraversalCallback* cb) const override; @@ -247,91 +245,88 @@ 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; int 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(); } int 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 +342,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; int 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; int IsPure() const override; TraversalCode Traverse(TraversalCallback* cb) const override; @@ -497,31 +491,30 @@ 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; int IsRecordElement(TypeDecl* td) const override; - Val* InitVal(const BroType* t, Val* aggr) const override; + IntrusivePtr InitVal(const BroType* t, IntrusivePtr aggr) const override; int IsPure() const override; protected: @@ -529,18 +522,18 @@ 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); int CanAdd() const override; int CanDel() const override; @@ -548,19 +541,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 +562,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 +570,13 @@ public: int 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 +589,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 +605,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 +635,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 +653,19 @@ 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 +680,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 +704,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 +748,51 @@ protected: class ScheduleExpr : public Expr { public: - ScheduleExpr(Expr* when, EventExpr* event); - ~ScheduleExpr() override; + ScheduleExpr(IntrusivePtr when, IntrusivePtr event); int 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(); } int 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 +806,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 +821,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 +836,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 +856,17 @@ public: // True if the entire list represents constant values. int 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 +876,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 +908,7 @@ 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 47993ba03b..5583032f79 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -815,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(0); if ( fmt_str_val ) { @@ -829,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; } @@ -841,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; } @@ -868,7 +865,7 @@ static int get_func_priority(const attr_list& attrs) continue; } - Val* v = a->AttrExpr()->Eval(0); + auto v = a->AttrExpr()->Eval(0); if ( ! v ) { a->Error("cannot evaluate attribute expression"); @@ -877,13 +874,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..2eea08acfa 100644 --- a/src/ID.cc +++ b/src/ID.cc @@ -278,15 +278,14 @@ void ID::SetOption() void ID::EvalFunc(Expr* ef, Expr* ev) { - Expr* arg1 = new ConstExpr(val->Ref()); - ListExpr* args = new ListExpr(); - args->Append(arg1); - args->Append(ev->Ref()); + auto arg1 = make_intrusive(IntrusivePtr{NewRef{}, val}); + auto args = make_intrusive(); + args->Append(std::move(arg1)); + args->Append({NewRef{}, ev}); - CallExpr* ce = new CallExpr(ef->Ref(), args); + auto ce = make_intrusive(IntrusivePtr{NewRef{}, ef}, std::move(args)); - SetVal(ce->Eval(0)); - Unref(ce); + SetVal(ce->Eval(0).release()); } #if 0 diff --git a/src/Stmt.cc b/src/Stmt.cc index e9a54917f9..495a3ed432 100644 --- a/src/Stmt.cc +++ b/src/Stmt.cc @@ -321,14 +321,10 @@ Val* 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; } @@ -670,10 +666,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; @@ -1068,15 +1064,12 @@ Val* WhileStmt::Exec(Frame* f, stmt_flow_type& flow) const 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; @@ -1481,7 +1474,7 @@ Val* ReturnStmt::Exec(Frame* f, stmt_flow_type& flow) const flow = FLOW_RETURN; if ( e ) - return e->Eval(f); + return e->Eval(f).release(); else return 0; } diff --git a/src/Trigger.cc b/src/Trigger.cc index 5a600074a6..9d71ce5700 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,13 +298,12 @@ 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 { - v = body->Exec(f, flow); + v = {AdoptRef{}, body->Exec(f, flow)}; } catch ( InterpreterException& e ) { /* Already reported. */ } @@ -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 ) diff --git a/src/Type.cc b/src/Type.cc index 31ee469b64..8ab11ce312 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -705,7 +705,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(0).release() : 0; } int RecordType::FieldOffset(const char* field) const @@ -2065,7 +2065,7 @@ BroType* init_type(Expr* init) { if ( init->Tag() != EXPR_LIST ) { - BroType* t = init->InitType(); + auto t = init->InitType(); if ( ! t ) return 0; @@ -2073,11 +2073,10 @@ BroType* init_type(Expr* init) t->AsTypeList()->Types()->length() != 1 ) { init->Error("list used in scalar initialization"); - Unref(t); return 0; } - return t; + return t.release(); } ListExpr* init_list = init->AsListExpr(); @@ -2094,47 +2093,25 @@ BroType* init_type(Expr* init) if ( e0->IsRecordElement(0) ) // ListExpr's know how to build a record from their // components. - return init_list->InitType(); + return init_list->InitType().release(); - BroType* t = e0->InitType(); + auto 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; 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; - } - 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 ) @@ -2145,18 +2122,18 @@ BroType* init_type(Expr* init) 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/Val.cc b/src/Val.cc index 5bfa228e4b..72cca0017f 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); + Expr* coerce = new RecordCoerceExpr({NewRef{}, def_attr->AttrExpr()}, + {NewRef{}, ytype->AsRecordType()}); + def_val = coerce->Eval(0).release(); Unref(coerce); } 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(0); 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(0); 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 ) @@ -2575,7 +2571,7 @@ RecordVal::RecordVal(RecordType* t, bool init_fields) : Val(t) { 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; + auto def = def_attr ? def_attr->AttrExpr()->Eval(0) : 0; 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()); } } @@ -2710,9 +2703,9 @@ RecordVal* RecordVal::CoerceTo(const RecordType* t, Val* aggr, bool allow_orphan 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(0).release()); continue; } diff --git a/src/Var.cc b/src/Var.cc index 05bdfbfc7e..0399af05cb 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -16,11 +16,11 @@ #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 ) { @@ -159,26 +159,23 @@ static void make_var(ID* id, IntrusivePtr t, init_class c, IntrusivePtr 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 = make_intrusive(init.release(), 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; - - Val* v = 0; + IntrusivePtr v; if ( init ) { v = init_val(init.get(), t.get(), aggr); @@ -187,9 +184,9 @@ static void make_var(ID* id, IntrusivePtr t, init_class c, IntrusivePtr } if ( aggr ) - id->SetVal(aggr, c); + id->SetVal(aggr.release(), c); else if ( v ) - id->SetVal(v, c); + id->SetVal(v.release(), c); } } @@ -244,9 +241,9 @@ IntrusivePtr add_local(IntrusivePtr id, IntrusivePtr t, init_ // may free "init" const Location location = init->GetLocationInfo() != nullptr ? *init->GetLocationInfo() : no_location; - Expr* name_expr = new NameExpr(IntrusivePtr{id}.release(), dt == VAR_CONST); + auto name_expr = make_intrusive(id, dt == VAR_CONST); auto stmt = - make_intrusive(new AssignExpr(name_expr, init.release(), 0, 0, + make_intrusive(new AssignExpr(std::move(name_expr), std::move(init), 0, 0, id->Attrs() ? id->Attrs()->Attrs() : 0 )); stmt->SetLocationInfo(&location); @@ -262,8 +259,8 @@ IntrusivePtr add_local(IntrusivePtr id, IntrusivePtr t, init_ extern IntrusivePtr add_and_assign_local(IntrusivePtr id, IntrusivePtr init, IntrusivePtr val) { - make_var(id.get(), 0, INIT_FULL, IntrusivePtr{init}, 0, VAR_REGULAR, 0); - return make_intrusive(new NameExpr(id.release()), init.release(), 0, val.release()); + make_var(id.get(), 0, INIT_FULL, init, 0, VAR_REGULAR, 0); + return make_intrusive(make_intrusive(std::move(id)), std::move(init), 0, std::move(val)); } void add_type(ID* id, IntrusivePtr t, attr_list* attr) diff --git a/src/input/Manager.cc b/src/input/Manager.cc index fcd574647f..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); } } diff --git a/src/parse.y b/src/parse.y index a7c5b1e980..3f9c51e973 100644 --- a/src/parse.y +++ b/src/parse.y @@ -312,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 @@ -474,7 +474,7 @@ 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 @@ -486,7 +486,7 @@ expr: | expr '[' expr_list ']' { set_location(@1, @4); - $$ = new IndexExpr($1, $3); + $$ = new IndexExpr({AdoptRef{}, $1}, {AdoptRef{}, $3}); } | index_slice @@ -494,13 +494,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 '=' @@ -516,20 +516,20 @@ expr: } 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 ']' @@ -552,7 +552,7 @@ expr: } if ( is_record_ctor ) - $$ = new RecordConstructorExpr($2); + $$ = new RecordConstructorExpr({AdoptRef{}, $2}); else $$ = $2; } @@ -560,33 +560,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 '(' @@ -612,20 +612,20 @@ expr: { switch ( ctor_type->Tag() ) { case TYPE_RECORD: - $$ = new RecordCoerceExpr(new RecordConstructorExpr($4), - ctor_type->AsRecordType()); + $$ = new RecordCoerceExpr(make_intrusive(IntrusivePtr{AdoptRef{}, $4}), + {NewRef{}, ctor_type->AsRecordType()}); 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: @@ -635,7 +635,7 @@ expr: } else - $$ = new CallExpr($1, $4, in_hook > 0); + $$ = new CallExpr({AdoptRef{}, $1}, {AdoptRef{}, $4}, in_hook > 0); } | TOK_HOOK { ++in_hook; } expr @@ -650,7 +650,7 @@ expr: | expr TOK_HAS_FIELD TOK_ID { set_location(@1, @3); - $$ = new HasFieldExpr($1, $3); + $$ = new HasFieldExpr({AdoptRef{}, $1}, $3); } | anonymous_function @@ -659,7 +659,7 @@ expr: | TOK_SCHEDULE expr '{' event '}' { set_location(@1, @5); - $$ = new ScheduleExpr($2, $4); + $$ = new ScheduleExpr({AdoptRef{}, $2}, {AdoptRef{}, $4}); } | TOK_ID @@ -694,7 +694,7 @@ expr: { id->Error("undeclared variable"); id->SetType(error_type()); - $$ = new NameExpr(id.release()); + $$ = new NameExpr(std::move(id)); } else if ( id->IsEnumConst() ) @@ -704,11 +704,11 @@ 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 { - $$ = new NameExpr(id.release()); + $$ = new NameExpr(std::move(id)); } } } @@ -716,7 +716,7 @@ expr: | TOK_CONSTANT { set_location(@1); - $$ = new ConstExpr($1); + $$ = new ConstExpr({AdoptRef{}, $1}); } | '/' { begin_RE(); } TOK_PATTERN_TEXT TOK_PATTERN_END @@ -730,30 +730,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}); } ; @@ -761,13 +761,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}); } ; @@ -1301,15 +1301,15 @@ 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: @@ -1364,7 +1364,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; @@ -1534,7 +1534,7 @@ 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).release()); if ( ! $5 ) brofiler.AddStmt($$); @@ -1586,7 +1586,7 @@ event: reporter->Warning("%s", id->GetDeprecationWarning().c_str()); } - $$ = new EventExpr($1, $3); + $$ = new EventExpr($1, {AdoptRef{}, $3}); } ; @@ -1839,19 +1839,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/scan.l b/src/scan.l index ca197501d6..641a0d6fb3 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,7 +747,7 @@ void do_atif(Expr* expr) LocalNameFinder cb; expr->Traverse(&cb); - Val* val = 0; + IntrusivePtr val; if ( cb.local_names.empty() ) val = expr->Eval(0); @@ -767,8 +768,6 @@ void do_atif(Expr* expr) if_stack.push_back(current_depth); BEGIN(IGNORE); } - - Unref(val); } void do_atifdef(const char* id) From edde591748609f8fec1f5ef84ba215497cc988ea Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 26 Feb 2020 19:21:22 +0100 Subject: [PATCH 15/22] ID: use class IntrusivePtr --- src/Expr.cc | 8 ++--- src/Func.cc | 2 +- src/ID.cc | 66 +++++++++++++++--------------------- src/ID.h | 29 ++++++++-------- src/Net.cc | 2 +- src/Type.cc | 2 +- src/Var.cc | 34 ++++++++----------- src/broker/Manager.cc | 2 +- src/main.cc | 2 +- src/option.bif | 5 ++- src/parse.y | 4 +-- src/supervisor/Supervisor.cc | 2 +- 12 files changed, 71 insertions(+), 87 deletions(-) diff --git a/src/Expr.cc b/src/Expr.cc index 7b33a141d8..4912c1c1c0 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -272,7 +272,7 @@ IntrusivePtr NameExpr::MakeLvalue() void NameExpr::Assign(Frame* f, IntrusivePtr v) { if ( id->IsGlobal() ) - id->SetVal(v.release()); + id->SetVal(std::move(v)); else f->SetElement(id.get(), v.release()); } @@ -4241,10 +4241,10 @@ LambdaExpr::LambdaExpr(std::unique_ptr arg_ing, // 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(); } diff --git a/src/Func.cc b/src/Func.cc index 5583032f79..58652c8217 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -613,7 +613,7 @@ BuiltinFunc::BuiltinFunc(built_in_func arg_func, const char* arg_name, reporter->InternalError("built-in function %s multiply defined", Name()); type = id->Type()->Ref(); - id->SetVal(new Val(this)); + id->SetVal(make_intrusive(this)); } BuiltinFunc::~BuiltinFunc() diff --git a/src/ID.cc b/src/ID.cc index 2eea08acfa..2355962fb6 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,20 +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) { auto arg1 = make_intrusive(IntrusivePtr{NewRef{}, val}); auto args = make_intrusive(); args->Append(std::move(arg1)); - args->Append({NewRef{}, ev}); + args->Append(std::move(ev)); - auto ce = make_intrusive(IntrusivePtr{NewRef{}, ef}, std::move(args)); + auto ce = make_intrusive(std::move(ef), std::move(args)); - SetVal(ce->Eval(0).release()); + SetVal(ce->Eval(0)); } #if 0 @@ -358,7 +348,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 @@ -581,9 +571,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 @@ -593,6 +583,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..7394bcd450 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; @@ -109,11 +110,11 @@ public: { 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 +123,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/Type.cc b/src/Type.cc index 8ab11ce312..cb9bd60bb0 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -1177,7 +1177,7 @@ void EnumType::CheckAndAddName(const string& module_name, const char* name, 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 ) diff --git a/src/Var.cc b/src/Var.cc index 0399af05cb..80af567595 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -104,15 +104,15 @@ static void make_var(ID* id, IntrusivePtr t, init_class c, IntrusivePtr t = {AdoptRef{}, init_type(init.get())}; if ( ! t ) { - id->SetType(error_type()); + id->SetType({AdoptRef{}, error_type()}); return; } } - id->SetType(t->Ref()); + id->SetType(t); if ( attr ) - id->AddAttrs(new Attributes(attr, t.get(), false, id->IsGlobal())); + id->AddAttrs(make_intrusive(attr, t.get(), false, id->IsGlobal())); if ( init ) { @@ -121,10 +121,7 @@ static void make_var(ID* id, IntrusivePtr t, init_class c, IntrusivePtr { TableConstructorExpr* ctor = (TableConstructorExpr*) init.get(); if ( ctor->Attrs() ) - { - ::Ref(ctor->Attrs()); - id->AddAttrs(ctor->Attrs()); - } + id->AddAttrs({NewRef{}, ctor->Attrs()}); } break; @@ -132,10 +129,7 @@ static void make_var(ID* id, IntrusivePtr t, init_class c, IntrusivePtr { SetConstructorExpr* ctor = (SetConstructorExpr*) init.get(); if ( ctor->Attrs() ) - { - ::Ref(ctor->Attrs()); - id->AddAttrs(ctor->Attrs()); - } + id->AddAttrs({NewRef{}, ctor->Attrs()}); } break; @@ -155,7 +149,7 @@ static void make_var(ID* id, IntrusivePtr t, init_class c, IntrusivePtr if ( init && ((c == INIT_EXTRA && id->FindAttr(ATTR_ADD_FUNC)) || (c == INIT_REMOVE && id->FindAttr(ATTR_DEL_FUNC)) )) // Just apply the function. - id->SetVal(init->Ref(), c); + id->SetVal(init, c); else if ( dt != VAR_REDEF || init || ! attr ) { @@ -184,9 +178,9 @@ static void make_var(ID* id, IntrusivePtr t, init_class c, IntrusivePtr } if ( aggr ) - id->SetVal(aggr.release(), c); + id->SetVal(std::move(aggr), c); else if ( v ) - id->SetVal(v.release(), c); + id->SetVal(std::move(v), c); } } @@ -216,7 +210,7 @@ static void make_var(ID* id, IntrusivePtr t, init_class c, IntrusivePtr // 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)); } } @@ -284,11 +278,11 @@ void add_type(ID* id, IntrusivePtr t, attr_list* attr) tnew->SetName(id->Name()); - id->SetType(IntrusivePtr{tnew}.release()); + id->SetType(tnew); id->MakeType(); if ( attr ) - id->SetAttrs(new Attributes(attr, tnew.get(), false, false)); + id->SetAttrs(make_intrusive(attr, tnew.get(), false, false)); } static void transfer_arg_defaults(RecordType* args, RecordType* recv) @@ -386,7 +380,7 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor, } } else - id->SetType(IntrusivePtr{t}.release()); + id->SetType(t); push_scope(id, attrs); @@ -402,7 +396,7 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor, arg_id->Error("argument name used twice"); 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) ) @@ -494,7 +488,7 @@ void end_func(IntrusivePtr body) ingredients->frame_size, ingredients->priority); - ingredients->id->SetVal(new Val(f)); + ingredients->id->SetVal(make_intrusive(f)); ingredients->id->SetConst(); } 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/main.cc b/src/main.cc index b47d2fcf59..30334c5b3e 100644 --- a/src/main.cc +++ b/src/main.cc @@ -717,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 3f9c51e973..c11242e7ec 100644 --- a/src/parse.y +++ b/src/parse.y @@ -693,7 +693,7 @@ expr: if ( ! id->Type() ) { id->Error("undeclared variable"); - id->SetType(error_type()); + id->SetType({AdoptRef{}, error_type()}); $$ = new NameExpr(std::move(id)); } @@ -1623,7 +1623,7 @@ case_type: TOK_TYPE type { $$ = new ID(0, SCOPE_FUNCTION, 0); - $$->SetType($2); + $$->SetType({AdoptRef{}, $2}); } | TOK_TYPE type TOK_AS TOK_ID 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; } From 95e2d66fb028921215709a45da16a54875e9539d Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 26 Feb 2020 20:21:49 +0100 Subject: [PATCH 16/22] zeekygen: use class IntrusivePtr --- src/Type.cc | 2 +- src/parse.y | 32 +++++++++++++++++++------------- src/plugin/ComponentManager.h | 2 +- src/zeekygen/IdentifierInfo.cc | 11 +++-------- src/zeekygen/IdentifierInfo.h | 11 ++++++----- src/zeekygen/Manager.cc | 10 +++++----- src/zeekygen/Manager.h | 6 +++--- src/zeekygen/ScriptInfo.cc | 4 ++-- 8 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/Type.cc b/src/Type.cc index cb9bd60bb0..ab422f2ba0 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -1183,7 +1183,7 @@ void EnumType::CheckAndAddName(const string& module_name, const char* name, if ( deprecation ) id->MakeDeprecated(deprecation); - zeekygen_mgr->Identifier(id.get()); + zeekygen_mgr->Identifier(std::move(id)); } else { diff --git a/src/parse.y b/src/parse.y index c11242e7ec..4daa1562ff 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1086,27 +1086,31 @@ decl: | TOK_GLOBAL def_global_id opt_type init_class opt_init opt_attr ';' { - add_global($2, {AdoptRef{}, $3}, $4, {AdoptRef{}, $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, {AdoptRef{}, $3}, $4, {AdoptRef{}, $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, {AdoptRef{}, $3}, $4, {AdoptRef{}, $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 id{AdoptRef{}, $2}; IntrusivePtr init{AdoptRef{}, $5}; - add_global($2, {AdoptRef{}, $3}, $4, init, $6, VAR_REDEF); - zeekygen_mgr->Redef($2, ::filename, $4, init.release()); + 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 '{' @@ -1133,12 +1137,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, {AdoptRef{}, $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 @@ -1168,10 +1173,11 @@ conditional: func_hdr: TOK_FUNCTION def_global_id func_params opt_attr { - begin_func($2, current_module.c_str(), + 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 { diff --git a/src/plugin/ComponentManager.h b/src/plugin/ComponentManager.h index 8740e376b3..87d22fc189 100644 --- a/src/plugin/ComponentManager.h +++ b/src/plugin/ComponentManager.h @@ -135,7 +135,7 @@ ComponentManager::ComponentManager(const string& arg_module, const string& { auto id = install_ID(local_id.c_str(), module.c_str(), true, true); add_type(id.get(), tag_enum_type, 0); - zeekygen_mgr->Identifier(id.get()); + zeekygen_mgr->Identifier(std::move(id)); } template diff --git a/src/zeekygen/IdentifierInfo.cc b/src/zeekygen/IdentifierInfo.cc index c94dd7fb99..291e39981f 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; 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)); } } From 3d999b53fef5a395ea0597d00b68daaf04041aa5 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 26 Feb 2020 20:30:26 +0100 Subject: [PATCH 17/22] Val: use nullptr instead of 0 --- src/Val.cc | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Val.cc b/src/Val.cc index 72cca0017f..23a9cdab5d 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -3037,7 +3037,7 @@ void VectorVal::ValDescribe(ODesc* d) const Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* expr_location) { if ( ! v ) - return 0; + return nullptr; BroType* vt = v->Type(); @@ -3060,7 +3060,7 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* ex t->Error("type clash", v, 0, expr_location); Unref(v); - return 0; + return nullptr; } if ( ! BothArithmetic(t_tag, v_tag) && @@ -3071,7 +3071,7 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* ex else t->Error("arithmetic mixed with non-arithmetic", v, 0, expr_location); Unref(v); - return 0; + return nullptr; } if ( v_tag == t_tag ) @@ -3084,7 +3084,7 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* ex { t->Error("over-promotion of arithmetic value", v, 0, expr_location); Unref(v); - return 0; + return nullptr; } } @@ -3103,7 +3103,7 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* ex { t->Error("overflow promoting from unsigned/double to signed arithmetic value", v, 0, expr_location); Unref(v); - return 0; + return nullptr; } else if ( t_tag == TYPE_INT ) promoted_v = val_mgr->GetInt(v->CoerceToInt()); @@ -3111,7 +3111,7 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* ex { reporter->InternalError("bad internal type in check_and_promote()"); Unref(v); - return 0; + return nullptr; } break; @@ -3121,7 +3121,7 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* ex { t->Error("overflow promoting from signed/double to unsigned arithmetic value", v, 0, expr_location); Unref(v); - return 0; + return nullptr; } else if ( t_tag == TYPE_COUNT || t_tag == TYPE_COUNTER ) promoted_v = val_mgr->GetCount(v->CoerceToUnsigned()); @@ -3129,7 +3129,7 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* ex { reporter->InternalError("bad internal type in check_and_promote()"); Unref(v); - return 0; + return nullptr; } break; @@ -3141,7 +3141,7 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* ex default: reporter->InternalError("bad internal type in check_and_promote()"); Unref(v); - return 0; + return nullptr; } Unref(v); @@ -3221,7 +3221,7 @@ Val* cast_value_to_type(Val* v, BroType* t) // 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. @@ -3233,12 +3233,12 @@ Val* cast_value_to_type(Val* v, BroType* t) auto dv = v->AsRecordVal()->Lookup(0); if ( ! dv ) - return 0; + return nullptr; return static_cast(dv)->castTo(t).release(); } - return 0; + return nullptr; } bool can_cast_value_to_type(const Val* v, BroType* t) From 96951c1300bf40916578d76d07944f311f04abe8 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 26 Feb 2020 20:29:53 +0100 Subject: [PATCH 18/22] Val: use IntrusivePtr in check_and_promote() --- src/Expr.cc | 16 ++++++++-------- src/Val.cc | 35 +++++++++++++---------------------- src/Val.h | 3 ++- 3 files changed, 23 insertions(+), 31 deletions(-) diff --git a/src/Expr.cc b/src/Expr.cc index 4912c1c1c0..c338ef13e2 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -127,7 +127,7 @@ IntrusivePtr Expr::InitVal(const BroType* t, IntrusivePtr aggr) const if ( IsError() ) return 0; - return {AdoptRef{}, check_and_promote(Eval(0).release(), t, 1)}; + return check_and_promote(Eval(0), t, 1); } int Expr::IsError() const @@ -2279,7 +2279,7 @@ void AssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) const TableVal* tv = aggr->AsTableVal(); auto index = op1->Eval(f); - IntrusivePtr v{AdoptRef{}, check_and_promote(op2->Eval(f).release(), t->YieldType(), 1)}; + auto v = check_and_promote(op2->Eval(f), t->YieldType(), 1); if ( ! index || ! v ) return; @@ -3220,7 +3220,7 @@ IntrusivePtr SetConstructorExpr::InitVal(const BroType* t, IntrusivePtr element = {AdoptRef{}, check_and_promote(e->Eval(0).release(), index_type, 1)}; + auto element = check_and_promote(e->Eval(0), index_type, 1); if ( ! element || ! tval->Assign(element.get(), 0) ) { @@ -3321,7 +3321,7 @@ IntrusivePtr VectorConstructorExpr::InitVal(const BroType* t, IntrusivePtr< loop_over_list(exprs, i) { Expr* e = exprs[i]; - IntrusivePtr v{AdoptRef{}, check_and_promote(e->Eval(0).release(), t->YieldType(), 1)}; + auto v = check_and_promote(e->Eval(0), t->YieldType(), 1); if ( ! v || ! vec->Assign(i, v.release()) ) { @@ -3640,9 +3640,9 @@ IntrusivePtr RecordCoerceExpr::Fold(Val* v) const else if ( BothArithmetic(rhs_type->Tag(), field_type->Tag()) && ! same_type(rhs_type, field_type) ) { - if ( Val* new_val = check_and_promote(rhs.release(), field_type, false, op->GetLocationInfo()) ) + if ( auto new_val = check_and_promote(rhs, field_type, false, op->GetLocationInfo()) ) { - rhs = {AdoptRef{}, new_val}; + rhs = std::move(new_val); } else { @@ -4653,9 +4653,9 @@ IntrusivePtr ListExpr::AddSetInit(const BroType* t, IntrusivePtr aggr) } if ( expr->Type()->Tag() == TYPE_LIST ) - element = {AdoptRef{}, check_and_promote(element.release(), it, 1)}; + element = check_and_promote(std::move(element), it, 1); else - element = {AdoptRef{}, check_and_promote(element.release(), (*it->Types())[0], 1)}; + element = check_and_promote(std::move(element), (*it->Types())[0], 1); if ( ! element ) return 0; diff --git a/src/Val.cc b/src/Val.cc index 23a9cdab5d..86ee5ff38e 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -3034,7 +3034,7 @@ 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 nullptr; @@ -3058,8 +3058,7 @@ 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); + t->Error("type clash", v.get(), 0, expr_location); return nullptr; } @@ -3067,10 +3066,9 @@ Val* check_and_promote(Val* v, const BroType* t, int is_init, const Location* ex (! 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); + t->Error("arithmetic mixed with non-arithmetic", v.get(), 0, expr_location); return nullptr; } @@ -3082,8 +3080,7 @@ 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); + t->Error("over-promotion of arithmetic value", v.get(), 0, expr_location); return nullptr; } } @@ -3096,55 +3093,49 @@ 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); + 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 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); + 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 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 nullptr; } - Unref(v); return promoted_v; } diff --git a/src/Val.h b/src/Val.h index 0777d79779..5f32b65935 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,7 +1019,7 @@ 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); +extern IntrusivePtr check_and_promote(IntrusivePtr 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 From 3331abb4f277b80743099bd26cdc661a7869dfec Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 27 Feb 2020 10:15:03 +0100 Subject: [PATCH 19/22] Val: cast_value_to_type() returns IntrusivePtr --- src/Expr.cc | 3 +-- src/Stmt.cc | 2 +- src/Val.cc | 6 +++--- src/Val.h | 3 +-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Expr.cc b/src/Expr.cc index c338ef13e2..d5764ad8ee 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -4797,8 +4797,7 @@ IntrusivePtr CastExpr::Eval(Frame* f) const if ( ! v ) return 0; - IntrusivePtr nv{AdoptRef{}, cast_value_to_type(v.get(), Type())}; - + auto nv = cast_value_to_type(v.get(), Type()); if ( nv ) return nv; diff --git a/src/Stmt.cc b/src/Stmt.cc index 495a3ed432..0b5a78511f 100644 --- a/src/Stmt.cc +++ b/src/Stmt.cc @@ -834,7 +834,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; diff --git a/src/Val.cc b/src/Val.cc index 86ee5ff38e..41dfc3b6b8 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -3206,7 +3206,7 @@ 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(). @@ -3217,7 +3217,7 @@ Val* cast_value_to_type(Val* v, BroType* t) // 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()) ) { @@ -3226,7 +3226,7 @@ Val* cast_value_to_type(Val* v, BroType* t) if ( ! dv ) return nullptr; - return static_cast(dv)->castTo(t).release(); + return static_cast(dv)->castTo(t); } return nullptr; diff --git a/src/Val.h b/src/Val.h index 5f32b65935..9e4289a546 100644 --- a/src/Val.h +++ b/src/Val.h @@ -1037,10 +1037,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. From 837c8f759bd9c2bb74c227e3473f3da7867f76b8 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 27 Feb 2020 10:17:18 +0100 Subject: [PATCH 20/22] Val: remove unimplemented prototype recover_val() In the initial commit 10 years ago (61757ac78bbff8364c24e9aabdc612a35ae76911), the implementation was gone already. --- src/Val.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Val.h b/src/Val.h index 9e4289a546..1722a3a01a 100644 --- a/src/Val.h +++ b/src/Val.h @@ -1021,12 +1021,6 @@ protected: // the checking is done in the context of an initialization. extern IntrusivePtr check_and_promote(IntrusivePtr 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 int same_val(const Val* v1, const Val* v2); extern int same_atomic_val(const Val* v1, const Val* v2); extern bool is_atomic_val(const Val* v); From 50ae129c573d12b8767b766696635aa9092a14de Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 27 Feb 2020 10:34:54 +0100 Subject: [PATCH 21/22] Stmt: remove unused default constructors and `friend` declarations --- src/Stmt.h | 43 ------------------------------------------- 1 file changed, 43 deletions(-) diff --git a/src/Stmt.h b/src/Stmt.h index a65af2ee88..8822c96daa 100644 --- a/src/Stmt.h +++ b/src/Stmt.h @@ -90,7 +90,6 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; protected: - ExprListStmt() { l = 0; } ExprListStmt(BroStmtTag t, ListExpr* arg_l); ~ExprListStmt() override; @@ -109,9 +108,6 @@ public: explicit PrintStmt(ListExpr* l) : ExprListStmt(STMT_PRINT, l) { } protected: - friend class Stmt; - PrintStmt() {} - Val* DoExec(val_list* vals, stmt_flow_type& flow) const override; }; @@ -129,8 +125,6 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; protected: - friend class Stmt; - ExprStmt() { e = 0; } ExprStmt(BroStmtTag t, Expr* e); virtual Val* DoExec(Frame* f, Val* v, stmt_flow_type& flow) const; @@ -153,9 +147,6 @@ public: 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; int IsPure() const override; @@ -182,9 +173,6 @@ public: TraversalCode Traverse(TraversalCallback* cb) const; protected: - friend class Stmt; - Case() { expr_cases = 0; type_cases = 0; s = 0; } - ListExpr* expr_cases; id_list* type_cases; Stmt* s; @@ -204,9 +192,6 @@ 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; int IsPure() const override; @@ -244,10 +229,6 @@ public: Val* Exec(Frame* f, stmt_flow_type& flow) const override; TraversalCode Traverse(TraversalCallback* cb) const override; - -protected: - friend class Stmt; - AddStmt() {} }; class DelStmt : public ExprStmt { @@ -258,10 +239,6 @@ public: Val* Exec(Frame* f, stmt_flow_type& flow) const override; TraversalCode Traverse(TraversalCallback* cb) const override; - -protected: - friend class Stmt; - DelStmt() {} }; class EventStmt : public ExprStmt { @@ -273,9 +250,6 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; protected: - friend class Stmt; - EventStmt() { event_expr = 0; } - EventExpr* event_expr; }; @@ -292,11 +266,6 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; protected: - friend class Stmt; - - WhileStmt() - { loop_condition = 0; body = 0; } - Val* Exec(Frame* f, stmt_flow_type& flow) const override; Expr* loop_condition; @@ -323,9 +292,6 @@ 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; id_list* loop_vars; @@ -384,10 +350,6 @@ public: Val* Exec(Frame* f, stmt_flow_type& flow) const override; void Describe(ODesc* d) const override; - -protected: - friend class Stmt; - ReturnStmt() {} }; class StmtList : public Stmt { @@ -442,9 +404,6 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; protected: - friend class Stmt; - InitStmt() { inits = 0; } - id_list* inits; }; @@ -479,8 +438,6 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; protected: - WhenStmt() { cond = 0; s1 = s2 = 0; timeout = 0; is_return = 0; } - Expr* cond; Stmt* s1; Stmt* s2; From 46397de5c0fcc2485419286c4c2e41917b5fffee Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 27 Feb 2020 10:19:15 +0100 Subject: [PATCH 22/22] Stmt: use class IntrusivePtr --- src/Func.cc | 2 +- src/Stmt.cc | 196 ++++++++++++++++++++----------------------------- src/Stmt.h | 135 +++++++++++++++++----------------- src/Trigger.cc | 13 ++-- src/Var.cc | 2 +- src/parse.y | 46 ++++++------ 6 files changed, 176 insertions(+), 218 deletions(-) diff --git a/src/Func.cc b/src/Func.cc index 58652c8217..01a5d0b470 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 ) diff --git a/src/Stmt.cc b/src/Stmt.cc index 0b5a78511f..c69976201b 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,23 +141,20 @@ 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; } @@ -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 IntrusivePtr print_log(val_list* vals) { auto plval = lookup_enum_val("Log", "PRINTLOG"); auto record = make_intrusive(internal_type("Log::PrintLogInfo")->AsRecordType()); @@ -231,7 +226,7 @@ static Val* print_log(val_list* vals) 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(); @@ -294,29 +289,23 @@ Val* PrintStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */) const return 0; } -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; @@ -329,7 +318,7 @@ Val* ExprStmt::Exec(Frame* f, stmt_flow_type& flow) const return 0; } -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; } @@ -375,29 +364,23 @@ 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); @@ -405,9 +388,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 } @@ -479,8 +462,8 @@ 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()); @@ -490,9 +473,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); @@ -605,8 +585,8 @@ 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(); @@ -628,7 +608,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; } @@ -816,9 +796,9 @@ 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; @@ -901,7 +881,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"); @@ -912,7 +892,7 @@ 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; @@ -934,7 +914,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; @@ -948,7 +928,7 @@ 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; @@ -969,12 +949,11 @@ 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()); @@ -1003,19 +982,15 @@ 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 { @@ -1056,11 +1031,11 @@ 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 ( ; ; ) { @@ -1085,8 +1060,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; @@ -1163,10 +1138,10 @@ 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() ) { @@ -1180,7 +1155,7 @@ ForStmt::ForStmt(id_list* arg_loop_vars, Expr* loop_expr, ID* val_var) } else { - add_local({NewRef{}, value_var}, {NewRef{}, yield_type}, INIT_NONE, + add_local(value_var, {NewRef{}, yield_type}, INIT_NONE, 0, 0, VAR_REGULAR); } } @@ -1193,14 +1168,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 ) { @@ -1219,7 +1191,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()); @@ -1349,7 +1321,7 @@ 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; @@ -1376,7 +1348,7 @@ 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; @@ -1403,7 +1375,7 @@ 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; @@ -1430,7 +1402,7 @@ 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(); @@ -1465,16 +1437,20 @@ 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; if ( e ) - return e->Eval(f).release(); + return e->Eval(f); else return 0; } @@ -1507,7 +1483,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; @@ -1520,9 +1496,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 } @@ -1586,7 +1562,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; @@ -1603,9 +1579,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 } } @@ -1659,7 +1635,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; @@ -1723,7 +1699,7 @@ 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; @@ -1752,17 +1728,13 @@ 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)) { - assert(arg_cond); - assert(arg_s1); + assert(cond); + assert(s1); - cond = arg_cond; - s1 = arg_s1; - s2 = arg_s2; - timeout = arg_timeout; is_return = arg_is_return; if ( ! cond->IsError() && ! IsBool(cond->Type()->Tag()) ) @@ -1779,27 +1751,15 @@ 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); + new trigger::Trigger(IntrusivePtr{cond}.release(), IntrusivePtr{s1}.release(), IntrusivePtr{s2}.release(), IntrusivePtr{timeout}.release(), f, is_return, location); return 0; } diff --git a/src/Stmt.h b/src/Stmt.h index 8822c96daa..c6225e7438 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,104 +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(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: - 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: - 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: - 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: - 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; } @@ -192,7 +193,7 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; protected: - 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. @@ -223,40 +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; }; 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; }; 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: - 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; @@ -266,24 +267,24 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; protected: - Val* Exec(Frame* f, stmt_flow_type& flow) const override; + IntrusivePtr 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; @@ -292,20 +293,20 @@ public: TraversalCode Traverse(TraversalCallback* cb) const override; protected: - 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; @@ -319,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; @@ -333,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; @@ -345,9 +346,9 @@ 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; }; @@ -357,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; } @@ -377,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; @@ -395,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; } @@ -411,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; @@ -422,25 +423,25 @@ 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: - 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 9d71ce5700..15d912fb2d 100644 --- a/src/Trigger.cc +++ b/src/Trigger.cc @@ -303,7 +303,7 @@ bool Trigger::Eval() try { - v = {AdoptRef{}, body->Exec(f, flow)}; + v = body->Exec(f, flow); } catch ( InterpreterException& e ) { /* Already reported. */ } @@ -346,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. */ } @@ -368,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/Var.cc b/src/Var.cc index 80af567595..d0b5d87e2a 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -237,7 +237,7 @@ IntrusivePtr add_local(IntrusivePtr id, IntrusivePtr t, init_ auto name_expr = make_intrusive(id, dt == VAR_CONST); auto stmt = - make_intrusive(new AssignExpr(std::move(name_expr), std::move(init), 0, 0, + make_intrusive(make_intrusive(std::move(name_expr), std::move(init), 0, nullptr, id->Attrs() ? id->Attrs()->Attrs() : 0 )); stmt->SetLocationInfo(&location); diff --git a/src/parse.y b/src/parse.y index 4daa1562ff..b888eddbb3 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1395,7 +1395,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($$); } @@ -1403,7 +1403,7 @@ stmt: | TOK_EVENT event ';' opt_no_test { set_location(@1, @3); - $$ = new EventStmt($2); + $$ = new EventStmt({AdoptRef{}, $2}); if ( ! $4 ) brofiler.AddStmt($$); } @@ -1411,29 +1411,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 @@ -1471,7 +1471,7 @@ stmt: | TOK_RETURN expr ';' opt_no_test { set_location(@1, @2); - $$ = new ReturnStmt($2); + $$ = new ReturnStmt({AdoptRef{}, $2}); if ( ! $4 ) brofiler.AddStmt($$); } @@ -1479,7 +1479,7 @@ stmt: | TOK_ADD expr ';' opt_no_test { set_location(@1, @3); - $$ = new AddStmt($2); + $$ = new AddStmt({AdoptRef{}, $2}); if ( ! $4 ) brofiler.AddStmt($$); } @@ -1487,7 +1487,7 @@ stmt: | TOK_DELETE expr ';' opt_no_test { set_location(@1, @3); - $$ = new DelStmt($2); + $$ = new DelStmt({AdoptRef{}, $2}); if ( ! $4 ) brofiler.AddStmt($$); } @@ -1511,13 +1511,13 @@ 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(); } @@ -1526,13 +1526,13 @@ 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(); } @@ -1540,7 +1540,7 @@ stmt: | index_slice '=' expr ';' opt_no_test { set_location(@1, @4); - $$ = new ExprStmt(get_assign_expr({AdoptRef{}, $1}, {AdoptRef{}, $3}, in_init).release()); + $$ = new ExprStmt(get_assign_expr({AdoptRef{}, $1}, {AdoptRef{}, $3}, in_init)); if ( ! $5 ) brofiler.AddStmt($$); @@ -1549,7 +1549,7 @@ stmt: | expr ';' opt_no_test { set_location(@1, @2); - $$ = new ExprStmt($1); + $$ = new ExprStmt({AdoptRef{}, $1}); if ( ! $3 ) brofiler.AddStmt($$); } @@ -1605,13 +1605,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: @@ -1675,12 +1675,12 @@ for_head: id_list* loop_vars = new id_list; 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 ')' @@ -1713,7 +1713,7 @@ for_head: id_list* loop_vars = new id_list; loop_vars->push_back(key_var.release()); - $$ = new ForStmt(loop_vars, $7, val_var.release()); + $$ = new ForStmt(loop_vars, {AdoptRef{}, $7}, std::move(val_var)); } | TOK_FOR '(' '[' local_id_list ']' ',' TOK_ID TOK_IN expr ')' @@ -1732,7 +1732,7 @@ for_head: else val_var = install_ID($7, module, false, false); - $$ = new ForStmt($4, $9, val_var.release()); + $$ = new ForStmt($4, {AdoptRef{}, $9}, std::move(val_var)); } ;