Merge remote-tracking branch 'origin/topic/jsiwek/const'

* origin/topic/jsiwek/const:
  Make const variables actually constant.  Addresses #922.

Closes #922.
This commit is contained in:
Robin Sommer 2012-12-14 14:51:35 -08:00
commit ea6b62f586
11 changed files with 128 additions and 11 deletions

View file

@ -1,4 +1,11 @@
2.1-231 | 2012-12-14 14:51:35 -0800
* Make const variables actually constant. Both local and global
variables declared with "const" could be modified, but now
expressions that would modify them generate an error message at
parse-time. Addresses #922. (Jon Siwek)
2.1-229 | 2012-12-14 14:46:12 -0800
* Fix memory leak in ASCII reader when encoutering errors in input.

View file

@ -1 +1 @@
2.1-229
2.1-231

View file

@ -21,12 +21,10 @@ redef Cluster::manager2worker_events += /Notice::begin_suppression/;
redef Cluster::worker2manager_events += /Notice::cluster_notice/;
@if ( Cluster::local_node_type() != Cluster::MANAGER )
# The notice policy is completely handled by the manager and shouldn't be
# done by workers or proxies to save time for packet processing.
event bro_init() &priority=11
{
Notice::policy = table();
}
redef Notice::policy = table();
event Notice::begin_suppression(n: Notice::Info)
{

View file

@ -229,9 +229,10 @@ bool Expr::DoUnserialize(UnserialInfo* info)
}
NameExpr::NameExpr(ID* arg_id) : Expr(EXPR_NAME)
NameExpr::NameExpr(ID* arg_id, bool const_init) : Expr(EXPR_NAME)
{
id = arg_id;
in_const_init = const_init;
SetType(id->Type()->Ref());
EventHandler* h = event_registry->Lookup(id->Name());
@ -287,6 +288,9 @@ Expr* NameExpr::MakeLvalue()
if ( id->AsType() )
ExprError("Type name is not an lvalue");
if ( id->IsConst() && ! in_const_init )
ExprError("const is not a modifiable lvalue");
return new RefExpr(this);
}
@ -337,9 +341,11 @@ bool NameExpr::DoSerialize(SerialInfo* info) const
// Write out just the name of the function if requested.
if ( info->globals_as_names && id->IsGlobal() )
return SERIALIZE('n') && SERIALIZE(id->Name());
return SERIALIZE('n') && SERIALIZE(id->Name()) &&
SERIALIZE(in_const_init);
else
return SERIALIZE('f') && id->Serialize(info);
return SERIALIZE('f') && id->Serialize(info) &&
SERIALIZE(in_const_init);
}
bool NameExpr::DoUnserialize(UnserialInfo* info)
@ -370,6 +376,9 @@ bool NameExpr::DoUnserialize(UnserialInfo* info)
if ( ! id )
return false;
if ( ! UNSERIALIZE(&in_const_init) )
return false;
return true;
}

View file

@ -198,7 +198,7 @@ protected:
class NameExpr : public Expr {
public:
NameExpr(ID* id);
NameExpr(ID* id, bool const_init = false);
~NameExpr();
ID* Id() const { return id; }
@ -220,6 +220,7 @@ protected:
DECLARE_SERIAL(NameExpr);
ID* id;
bool in_const_init;
};
class ConstExpr : public Expr {

View file

@ -210,7 +210,6 @@ static void make_var(ID* id, BroType* t, init_class c, Expr* init,
// defined.
Func* f = new BroFunc(id, 0, 0, 0, 0);
id->SetVal(new Val(f));
id->SetConst();
}
}
@ -233,8 +232,9 @@ Stmt* add_local(ID* id, BroType* t, init_class c, Expr* init,
Ref(id);
Expr* name_expr = new NameExpr(id, dt == VAR_CONST);
Stmt* stmt =
new ExprStmt(new AssignExpr(new NameExpr(id), init, 0, 0,
new ExprStmt(new AssignExpr(name_expr, init, 0, 0,
id->Attrs() ? id->Attrs()->Attrs() : 0 ));
stmt->SetLocationInfo(init->GetLocationInfo());

View file

@ -0,0 +1,13 @@
error in ./invalid.bro, line 15: const is not a modifiable lvalue (foo)
error in ./invalid.bro, line 16: const is not a modifiable lvalue (foo)
error in ./invalid.bro, line 17: const is not a modifiable lvalue (bar)
error in ./invalid.bro, line 17: const is not a modifiable lvalue (foo)
error in ./invalid.bro, line 18: const is not a modifiable lvalue (foo)
error in ./invalid.bro, line 19: const is not a modifiable lvalue (foo)
error in ./invalid.bro, line 20: const is not a modifiable lvalue (foo)
error in ./invalid.bro, line 22: const is not a modifiable lvalue (foo)
error in ./invalid.bro, line 25: const is not a modifiable lvalue (bar)
error in ./invalid.bro, line 26: const is not a modifiable lvalue (baz)
error in ./invalid.bro, line 27: const is not a modifiable lvalue (bar)
error in ./invalid.bro, line 28: const is not a modifiable lvalue (baz)
error in ./invalid.bro, line 33: const is not a modifiable lvalue (foo)

View file

@ -0,0 +1,10 @@
40
enter f, 10
exit f, 110
enter f, 9
exit f, 109
enter f, 7
exit f, 107
foo, 10
bar, 9
baz, 7

View file

@ -0,0 +1,79 @@
# @TEST-EXEC: bro -b valid.bro 2>valid.stderr 1>valid.stdout
# @TEST-EXEC: btest-diff valid.stderr
# @TEST-EXEC: btest-diff valid.stdout
# @TEST-EXEC-FAIL: bro -b invalid.bro 2>invalid.stderr 1>invalid.stdout
# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff invalid.stderr
# @TEST-EXEC: btest-diff invalid.stdout
@TEST-START-FILE valid.bro
# First some simple code that should be valid and error-free.
function f(c: count)
{
print "enter f", c;
c = c + 100;
print "exit f", c;
}
const foo = 0 &redef;
redef foo = 10;
const bar = 9;
event bro_init()
{
const baz = 7;
local i = foo;
i = i + bar + 2;
i = i + baz + 11;
++i;
print i;
--i;
f(foo);
f(bar);
f(baz);
print "foo", foo;
print "bar", bar;
print "baz", baz;
}
@TEST-END-FILE
@TEST-START-FILE invalid.bro
# Now some const assignments that should generate errors at parse-time.
const foo = 0 &redef;
redef foo = 10;
const bar = 9;
event bro_init()
{
const baz = 7;
local s = 0;
print "nope";
foo = 100;
foo = bar;
foo = bar = baz;
foo = s;
++foo;
s = foo = bar;
if ( foo = 0 )
print "nope";
bar = 1 + 1;
baz = s;
++bar;
--baz;
print "foo", foo;
print "bar", bar;
print "baz", baz;
print "foo=foo", foo = foo;
}
@TEST-END-FILE