Attr: use class IntrusivePtr

This commit is contained in:
Max Kellermann 2020-03-05 19:41:59 +01:00
parent 097a362c80
commit 36a26a7b43
8 changed files with 62 additions and 61 deletions

View file

@ -23,18 +23,20 @@ const char* attr_name(attr_tag t)
return attr_names[int(t)]; return attr_names[int(t)];
} }
Attr::Attr(attr_tag t, Expr* e) Attr::Attr(attr_tag t, IntrusivePtr<Expr> e)
:expr(std::move(e))
{ {
tag = t; tag = t;
expr = e;
SetLocationInfo(&start_location, &end_location); SetLocationInfo(&start_location, &end_location);
} }
Attr::~Attr() Attr::Attr(attr_tag t)
:Attr(t, nullptr)
{ {
Unref(expr);
} }
Attr::~Attr() = default;
void Attr::Describe(ODesc* d) const void Attr::Describe(ODesc* d) const
{ {
AddTag(d); AddTag(d);
@ -131,10 +133,10 @@ void Attr::AddTag(ODesc* d) const
d->Add(attr_name(Tag())); d->Add(attr_name(Tag()));
} }
Attributes::Attributes(attr_list* a, BroType* t, bool arg_in_record, bool is_global) Attributes::Attributes(attr_list* a, IntrusivePtr<BroType> t, bool arg_in_record, bool is_global)
:type(std::move(t))
{ {
attrs = new attr_list(a->length()); attrs = new attr_list(a->length());
type = t->Ref();
in_record = arg_in_record; in_record = arg_in_record;
global_var = is_global; global_var = is_global;
@ -145,7 +147,7 @@ Attributes::Attributes(attr_list* a, BroType* t, bool arg_in_record, bool is_glo
// the necessary checking gets done. // the necessary checking gets done.
for ( const auto& attr : *a ) for ( const auto& attr : *a )
AddAttr(attr); AddAttr({NewRef{}, attr});
delete a; delete a;
} }
@ -156,23 +158,20 @@ Attributes::~Attributes()
Unref(attr); Unref(attr);
delete attrs; delete attrs;
Unref(type);
} }
void Attributes::AddAttr(Attr* attr) void Attributes::AddAttr(IntrusivePtr<Attr> attr)
{ {
if ( ! attrs ) if ( ! attrs )
attrs = new attr_list(1); attrs = new attr_list(1);
// We overwrite old attributes by deleting them first. // We overwrite old attributes by deleting them first.
RemoveAttr(attr->Tag()); RemoveAttr(attr->Tag());
attrs->push_back(attr); attrs->push_back(IntrusivePtr{attr}.release());
Ref(attr);
// We only check the attribute after we've added it, to facilitate // We only check the attribute after we've added it, to facilitate
// generating error messages via Attributes::Describe. // generating error messages via Attributes::Describe.
CheckAttr(attr); CheckAttr(attr.get());
// For ADD_FUNC or DEL_FUNC, add in an implicit REDEF, since // For ADD_FUNC or DEL_FUNC, add in an implicit REDEF, since
// those attributes only have meaning for a redefinable value. // those attributes only have meaning for a redefinable value.
@ -190,7 +189,7 @@ void Attributes::AddAttrs(Attributes* a)
{ {
attr_list* as = a->Attrs(); attr_list* as = a->Attrs();
for ( const auto& attr : *as ) for ( const auto& attr : *as )
AddAttr(attr); AddAttr({NewRef{}, attr});
Unref(a); Unref(a);
} }
@ -274,7 +273,7 @@ void Attributes::CheckAttr(Attr* a)
} }
FuncType* aft = at->AsFuncType(); FuncType* aft = at->AsFuncType();
if ( ! same_type(aft->YieldType(), type) ) if ( ! same_type(aft->YieldType(), type.get()) )
{ {
a->AttrExpr()->Error( a->AttrExpr()->Error(
is_add ? is_add ?
@ -299,7 +298,7 @@ void Attributes::CheckAttr(Attr* a)
if ( type->Tag() != TYPE_TABLE || (type->IsSet() && ! in_record) ) if ( type->Tag() != TYPE_TABLE || (type->IsSet() && ! in_record) )
{ {
if ( same_type(atype, type) ) if ( same_type(atype, type.get()) )
// Ok. // Ok.
break; break;
@ -315,15 +314,15 @@ void Attributes::CheckAttr(Attr* a)
// Ok. // Ok.
break; break;
auto e = check_and_promote_expr(a->AttrExpr(), type); auto e = check_and_promote_expr(a->AttrExpr(), type.get());
if ( e ) if ( e )
{ {
a->SetAttrExpr(e.release()); a->SetAttrExpr(std::move(e));
// Ok. // Ok.
break; break;
} }
a->AttrExpr()->Error("&default value has inconsistent type", type); a->AttrExpr()->Error("&default value has inconsistent type", type.get());
return; return;
} }
@ -357,7 +356,7 @@ void Attributes::CheckAttr(Attr* a)
auto e = check_and_promote_expr(a->AttrExpr(), ytype); auto e = check_and_promote_expr(a->AttrExpr(), ytype);
if ( e ) if ( e )
{ {
a->SetAttrExpr(e.release()); a->SetAttrExpr(std::move(e));
// Ok. // Ok.
break; break;
} }
@ -373,16 +372,16 @@ void Attributes::CheckAttr(Attr* a)
{ {
// &default applies to record field. // &default applies to record field.
if ( same_type(atype, type) ) if ( same_type(atype, type.get()) )
// Ok. // Ok.
break; break;
if ( (atype->Tag() == TYPE_TABLE && atype->AsTableType()->IsUnspecifiedTable()) ) if ( (atype->Tag() == TYPE_TABLE && atype->AsTableType()->IsUnspecifiedTable()) )
{ {
auto e = check_and_promote_expr(a->AttrExpr(), type); auto e = check_and_promote_expr(a->AttrExpr(), type.get());
if ( e ) if ( e )
{ {
a->SetAttrExpr(e.release()); a->SetAttrExpr(std::move(e));
break; break;
} }
} }
@ -573,7 +572,7 @@ void Attributes::CheckAttr(Attr* a)
break; break;
case ATTR_LOG: case ATTR_LOG:
if ( ! threading::Value::IsCompatibleType(type) ) if ( ! threading::Value::IsCompatibleType(type.get()) )
Error("&log applied to a type that cannot be logged"); Error("&log applied to a type that cannot be logged");
break; break;

View file

@ -4,6 +4,7 @@
#include "Obj.h" #include "Obj.h"
#include "BroList.h" #include "BroList.h"
#include "IntrusivePtr.h"
class Expr; class Expr;
@ -35,18 +36,20 @@ typedef enum {
class Attr : public BroObj { class Attr : public BroObj {
public: public:
explicit Attr(attr_tag t, Expr* e = 0); Attr(attr_tag t, IntrusivePtr<Expr> e);
explicit Attr(attr_tag t);
~Attr() override; ~Attr() override;
attr_tag Tag() const { return tag; } attr_tag Tag() const { return tag; }
Expr* AttrExpr() const { return expr; } Expr* AttrExpr() const { return expr.get(); }
// Up to the caller to decide if previous expr can be unref'd since it may // Up to the caller to decide if previous expr can be unref'd since it may
// not always be safe; e.g. expressions (at time of writing) don't always // not always be safe; e.g. expressions (at time of writing) don't always
// keep careful track of referencing their operands, so doing something // keep careful track of referencing their operands, so doing something
// like SetAttrExpr(coerce(AttrExpr())) must not completely unref the // like SetAttrExpr(coerce(AttrExpr())) must not completely unref the
// previous expr as the new expr depends on it. // previous expr as the new expr depends on it.
void SetAttrExpr(Expr* e) { expr = e; } template<typename E>
void SetAttrExpr(E &&e) { expr = std::forward<E>(e); }
void Describe(ODesc* d) const override; void Describe(ODesc* d) const override;
void DescribeReST(ODesc* d, bool shorten = false) const; void DescribeReST(ODesc* d, bool shorten = false) const;
@ -69,16 +72,16 @@ protected:
void AddTag(ODesc* d) const; void AddTag(ODesc* d) const;
attr_tag tag; attr_tag tag;
Expr* expr; IntrusivePtr<Expr> expr;
}; };
// Manages a collection of attributes. // Manages a collection of attributes.
class Attributes : public BroObj { class Attributes : public BroObj {
public: public:
Attributes(attr_list* a, BroType* t, bool in_record, bool is_global); Attributes(attr_list* a, IntrusivePtr<BroType> t, bool in_record, bool is_global);
~Attributes() override; ~Attributes() override;
void AddAttr(Attr* a); void AddAttr(IntrusivePtr<Attr> a);
void AddAttrs(Attributes* a); // Unref's 'a' when done void AddAttrs(Attributes* a); // Unref's 'a' when done
Attr* FindAttr(attr_tag t) const; Attr* FindAttr(attr_tag t) const;
@ -93,10 +96,9 @@ public:
bool operator==(const Attributes& other) const; bool operator==(const Attributes& other) const;
protected: protected:
Attributes() : type(), attrs(), in_record() { }
void CheckAttr(Attr* attr); void CheckAttr(Attr* attr);
BroType* type; IntrusivePtr<BroType> type;
attr_list* attrs; attr_list* attrs;
bool in_record; bool in_record;
bool global_var; bool global_var;

View file

@ -3123,7 +3123,7 @@ TableConstructorExpr::TableConstructorExpr(IntrusivePtr<ListExpr> constructor_li
} }
} }
attrs = arg_attrs ? new Attributes(arg_attrs, type.get(), false, false) : 0; attrs = arg_attrs ? new Attributes(arg_attrs, type, false, false) : 0;
type_list* indices = type->AsTableType()->Indices()->Types(); type_list* indices = type->AsTableType()->Indices()->Types();
const expr_list& cle = op->AsListExpr()->Exprs(); const expr_list& cle = op->AsListExpr()->Exprs();
@ -3238,7 +3238,7 @@ SetConstructorExpr::SetConstructorExpr(IntrusivePtr<ListExpr> constructor_list,
else if ( type->Tag() != TYPE_TABLE || ! type->AsTableType()->IsSet() ) else if ( type->Tag() != TYPE_TABLE || ! type->AsTableType()->IsSet() )
SetError("values in set(...) constructor do not specify a set"); SetError("values in set(...) constructor do not specify a set");
attrs = arg_attrs ? new Attributes(arg_attrs, type.get(), false, false) : 0; attrs = arg_attrs ? new Attributes(arg_attrs, type, false, false) : 0;
type_list* indices = type->AsTableType()->Indices()->Types(); type_list* indices = type->AsTableType()->Indices()->Types();
expr_list& cle = op->AsListExpr()->Exprs(); expr_list& cle = op->AsListExpr()->Exprs();

View file

@ -188,9 +188,9 @@ void ID::UpdateValAttrs()
TypeDecl* fd = rt->FieldDecl(i); TypeDecl* fd = rt->FieldDecl(i);
if ( ! fd->attrs ) if ( ! fd->attrs )
fd->attrs = make_intrusive<Attributes>(new attr_list, rt->FieldType(i), true, IsGlobal()); fd->attrs = make_intrusive<Attributes>(new attr_list, IntrusivePtr{NewRef{}, rt->FieldType(i)}, true, IsGlobal());
fd->attrs->AddAttr(new Attr(ATTR_LOG)); fd->attrs->AddAttr(make_intrusive<Attr>(ATTR_LOG));
} }
} }
} }
@ -206,13 +206,13 @@ bool ID::IsDeprecated() const
return FindAttr(ATTR_DEPRECATED) != 0; return FindAttr(ATTR_DEPRECATED) != 0;
} }
void ID::MakeDeprecated(Expr* deprecation) void ID::MakeDeprecated(IntrusivePtr<Expr> deprecation)
{ {
if ( IsDeprecated() ) if ( IsDeprecated() )
return; return;
attr_list* attr = new attr_list{new Attr(ATTR_DEPRECATED, deprecation)}; attr_list* attr = new attr_list{new Attr(ATTR_DEPRECATED, std::move(deprecation))};
AddAttrs(make_intrusive<Attributes>(attr, Type(), false, IsGlobal())); AddAttrs(make_intrusive<Attributes>(attr, IntrusivePtr{NewRef{}, Type()}, false, IsGlobal()));
} }
string ID::GetDeprecationWarning() const string ID::GetDeprecationWarning() const
@ -262,7 +262,7 @@ void ID::SetOption()
if ( ! IsRedefinable() ) if ( ! IsRedefinable() )
{ {
attr_list* attr = new attr_list{new Attr(ATTR_REDEF)}; attr_list* attr = new attr_list{new Attr(ATTR_REDEF)};
AddAttrs(make_intrusive<Attributes>(attr, Type(), false, IsGlobal())); AddAttrs(make_intrusive<Attributes>(attr, IntrusivePtr{NewRef{}, Type()}, false, IsGlobal()));
} }
} }

View file

@ -86,7 +86,7 @@ public:
bool IsDeprecated() const; bool IsDeprecated() const;
void MakeDeprecated(Expr* deprecation); void MakeDeprecated(IntrusivePtr<Expr> deprecation);
std::string GetDeprecationWarning() const; std::string GetDeprecationWarning() const;

View file

@ -571,7 +571,7 @@ void FuncType::DescribeReST(ODesc* d, bool roles_only) const
TypeDecl::TypeDecl(IntrusivePtr<BroType> t, const char* i, attr_list* arg_attrs, bool in_record) TypeDecl::TypeDecl(IntrusivePtr<BroType> t, const char* i, attr_list* arg_attrs, bool in_record)
:type(std::move(t)), :type(std::move(t)),
attrs(arg_attrs ? make_intrusive<Attributes>(arg_attrs, type.get(), in_record, false) : nullptr), attrs(arg_attrs ? make_intrusive<Attributes>(arg_attrs, type, in_record, false) : nullptr),
id(i) id(i)
{ {
} }
@ -821,9 +821,9 @@ const char* RecordType::AddFields(type_decl_list* others, attr_list* attr)
if ( log ) if ( log )
{ {
if ( ! td->attrs ) if ( ! td->attrs )
td->attrs = make_intrusive<Attributes>(new attr_list, td->type.get(), true, false); td->attrs = make_intrusive<Attributes>(new attr_list, td->type, true, false);
td->attrs->AddAttr(new Attr(ATTR_LOG)); td->attrs->AddAttr(make_intrusive<Attr>(ATTR_LOG));
} }
types->push_back(td); types->push_back(td);
@ -1122,7 +1122,7 @@ void EnumType::CheckAndAddName(const string& module_name, const char* name,
id->SetEnumConst(); id->SetEnumConst();
if ( deprecation ) if ( deprecation )
id->MakeDeprecated(deprecation); id->MakeDeprecated({NewRef{}, deprecation});
zeekygen_mgr->Identifier(std::move(id)); zeekygen_mgr->Identifier(std::move(id));
} }

View file

@ -114,7 +114,7 @@ static void make_var(ID* id, IntrusivePtr<BroType> t, init_class c,
id->SetType(t); id->SetType(t);
if ( attr ) if ( attr )
id->AddAttrs(make_intrusive<Attributes>(attr, t.get(), false, id->IsGlobal())); id->AddAttrs(make_intrusive<Attributes>(attr, t, false, id->IsGlobal()));
if ( init ) if ( init )
{ {
@ -294,7 +294,7 @@ void add_type(ID* id, IntrusivePtr<BroType> t, attr_list* attr)
id->MakeType(); id->MakeType();
if ( attr ) if ( attr )
id->SetAttrs(make_intrusive<Attributes>(attr, tnew.get(), false, false)); id->SetAttrs(make_intrusive<Attributes>(attr, tnew, false, false));
} }
static void transfer_arg_defaults(RecordType* args, RecordType* recv) static void transfer_arg_defaults(RecordType* args, RecordType* recv)
@ -312,11 +312,11 @@ static void transfer_arg_defaults(RecordType* args, RecordType* recv)
if ( ! recv_i->attrs ) if ( ! recv_i->attrs )
{ {
attr_list* a = new attr_list{def}; attr_list* a = new attr_list{def};
recv_i->attrs = make_intrusive<Attributes>(a, recv_i->type.get(), true, false); recv_i->attrs = make_intrusive<Attributes>(a, recv_i->type, true, false);
} }
else if ( ! recv_i->attrs->FindAttr(ATTR_DEFAULT) ) else if ( ! recv_i->attrs->FindAttr(ATTR_DEFAULT) )
recv_i->attrs->AddAttr(def); recv_i->attrs->AddAttr({NewRef{}, def});
} }
} }
@ -412,7 +412,7 @@ void begin_func(ID* id, const char* module_name, function_flavor flavor,
} }
if ( Attr* depr_attr = find_attr(attrs, ATTR_DEPRECATED) ) if ( Attr* depr_attr = find_attr(attrs, ATTR_DEPRECATED) )
id->MakeDeprecated(depr_attr->AttrExpr()); id->MakeDeprecated({NewRef{}, depr_attr->AttrExpr()});
} }
class OuterIDBindingFinder : public TraversalCallback { class OuterIDBindingFinder : public TraversalCallback {

View file

@ -1351,31 +1351,31 @@ attr_list:
attr: attr:
TOK_ATTR_DEFAULT '=' expr TOK_ATTR_DEFAULT '=' expr
{ $$ = new Attr(ATTR_DEFAULT, $3); } { $$ = new Attr(ATTR_DEFAULT, {AdoptRef{}, $3}); }
| TOK_ATTR_OPTIONAL | TOK_ATTR_OPTIONAL
{ $$ = new Attr(ATTR_OPTIONAL); } { $$ = new Attr(ATTR_OPTIONAL); }
| TOK_ATTR_REDEF | TOK_ATTR_REDEF
{ $$ = new Attr(ATTR_REDEF); } { $$ = new Attr(ATTR_REDEF); }
| TOK_ATTR_ADD_FUNC '=' expr | TOK_ATTR_ADD_FUNC '=' expr
{ $$ = new Attr(ATTR_ADD_FUNC, $3); } { $$ = new Attr(ATTR_ADD_FUNC, {AdoptRef{}, $3}); }
| TOK_ATTR_DEL_FUNC '=' expr | TOK_ATTR_DEL_FUNC '=' expr
{ $$ = new Attr(ATTR_DEL_FUNC, $3); } { $$ = new Attr(ATTR_DEL_FUNC, {AdoptRef{}, $3}); }
| TOK_ATTR_ON_CHANGE '=' expr | TOK_ATTR_ON_CHANGE '=' expr
{ $$ = new Attr(ATTR_ON_CHANGE, $3); } { $$ = new Attr(ATTR_ON_CHANGE, {AdoptRef{}, $3}); }
| TOK_ATTR_EXPIRE_FUNC '=' expr | TOK_ATTR_EXPIRE_FUNC '=' expr
{ $$ = new Attr(ATTR_EXPIRE_FUNC, $3); } { $$ = new Attr(ATTR_EXPIRE_FUNC, {AdoptRef{}, $3}); }
| TOK_ATTR_EXPIRE_CREATE '=' expr | TOK_ATTR_EXPIRE_CREATE '=' expr
{ $$ = new Attr(ATTR_EXPIRE_CREATE, $3); } { $$ = new Attr(ATTR_EXPIRE_CREATE, {AdoptRef{}, $3}); }
| TOK_ATTR_EXPIRE_READ '=' expr | TOK_ATTR_EXPIRE_READ '=' expr
{ $$ = new Attr(ATTR_EXPIRE_READ, $3); } { $$ = new Attr(ATTR_EXPIRE_READ, {AdoptRef{}, $3}); }
| TOK_ATTR_EXPIRE_WRITE '=' expr | TOK_ATTR_EXPIRE_WRITE '=' expr
{ $$ = new Attr(ATTR_EXPIRE_WRITE, $3); } { $$ = new Attr(ATTR_EXPIRE_WRITE, {AdoptRef{}, $3}); }
| TOK_ATTR_RAW_OUTPUT | TOK_ATTR_RAW_OUTPUT
{ $$ = new Attr(ATTR_RAW_OUTPUT); } { $$ = new Attr(ATTR_RAW_OUTPUT); }
| TOK_ATTR_PRIORITY '=' expr | TOK_ATTR_PRIORITY '=' expr
{ $$ = new Attr(ATTR_PRIORITY, $3); } { $$ = new Attr(ATTR_PRIORITY, {AdoptRef{}, $3}); }
| TOK_ATTR_TYPE_COLUMN '=' expr | TOK_ATTR_TYPE_COLUMN '=' expr
{ $$ = new Attr(ATTR_TYPE_COLUMN, $3); } { $$ = new Attr(ATTR_TYPE_COLUMN, {AdoptRef{}, $3}); }
| TOK_ATTR_LOG | TOK_ATTR_LOG
{ $$ = new Attr(ATTR_LOG); } { $$ = new Attr(ATTR_LOG); }
| TOK_ATTR_ERROR_HANDLER | TOK_ATTR_ERROR_HANDLER
@ -1385,7 +1385,7 @@ attr:
| TOK_ATTR_DEPRECATED '=' TOK_CONSTANT | TOK_ATTR_DEPRECATED '=' TOK_CONSTANT
{ {
if ( IsString($3->Type()->Tag()) ) if ( IsString($3->Type()->Tag()) )
$$ = new Attr(ATTR_DEPRECATED, new ConstExpr({AdoptRef{}, $3})); $$ = new Attr(ATTR_DEPRECATED, make_intrusive<ConstExpr>(IntrusivePtr{AdoptRef{}, $3}));
else else
{ {
ODesc d; ODesc d;