summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgraydon <graydon>2005-07-23 02:50:14 +0000
committergraydon <graydon>2005-07-23 02:50:14 +0000
commit67c0a57949358f8e708361ce93ef3ccc0ea8ef93 (patch)
tree1268285cc9ef661824c565aee3503b30667bd4b5
parentbeb816a08698ceaf39910ab40f08beba6c8edb6e (diff)
downloadsystemtap-steved-67c0a57949358f8e708361ce93ef3ccc0ea8ef93.tar.gz
systemtap-steved-67c0a57949358f8e708361ce93ef3ccc0ea8ef93.tar.xz
systemtap-steved-67c0a57949358f8e708361ce93ef3ccc0ea8ef93.zip
2005-07-22 Graydon Hoare <graydon@redhat.com>
* translate.cxx (itervar): New class. (*::visit_foreach_loop): Implement. Various bug fixes. * staptree.cxx (deep_copy_visitor::*): Copy tok fields. * elaborate.cxx (lvalue_aware_traversing_visitor): (mutated_map_collector): (no_map_mutation_during_iteration_check): New classes. (semantic_pass_maps): New function to check map usage. (semantic_pass): Call it. * testsuite/transok/eight.stp: Test 'foreach' loop translation. * testsuite/semko/{thirteen,fourteen,fifteen}.stp: Test prohibited forms of foreach loops.
-rw-r--r--ChangeLog15
-rw-r--r--elaborate.cxx171
-rw-r--r--staptree.cxx45
-rwxr-xr-xtestsuite/semko/fifteen.stp14
-rwxr-xr-xtestsuite/semko/fourteen.stp20
-rwxr-xr-xtestsuite/semko/thirteen.stp20
-rwxr-xr-xtestsuite/transok/eight.stp30
-rw-r--r--translate.cxx142
8 files changed, 438 insertions, 19 deletions
diff --git a/ChangeLog b/ChangeLog
index 02e030a2..081bafc0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2005-07-22 Graydon Hoare <graydon@redhat.com>
+
+ * translate.cxx (itervar): New class.
+ (*::visit_foreach_loop): Implement.
+ Various bug fixes.
+ * staptree.cxx (deep_copy_visitor::*): Copy tok fields.
+ * elaborate.cxx (lvalue_aware_traversing_visitor):
+ (mutated_map_collector):
+ (no_map_mutation_during_iteration_check): New classes.
+ (semantic_pass_maps): New function to check map usage.
+ (semantic_pass): Call it.
+ * testsuite/transok/eight.stp: Test 'foreach' loop translation.
+ * testsuite/semko/{thirteen,fourteen,fifteen}.stp:
+ Test prohibited forms of foreach loops.
+
2005-07-21 Martin Hunt <hunt@redhat.com>
* Makefile.am (EXTRA_DIST): Add systemtap.spec.
diff --git a/elaborate.cxx b/elaborate.cxx
index 8adf9f96..8980895f 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -15,8 +15,11 @@ extern "C" {
#include <sys/utsname.h>
}
-#include <fstream>
#include <algorithm>
+#include <fstream>
+#include <map>
+#include <set>
+#include <vector>
#if 0
#ifdef HAVE_ELFUTILS_LIBDW_H
@@ -378,11 +381,176 @@ symresolution_info::derive_probes (match_node * root,
}
// ------------------------------------------------------------------------
+//
+// Map usage checks
+//
+
+class lvalue_aware_traversing_visitor
+ : public traversing_visitor
+{
+ unsigned lval_depth;
+public:
+
+ lvalue_aware_traversing_visitor() : lval_depth(0) {}
+
+ bool is_in_lvalue()
+ {
+ return lval_depth > 0;
+ }
+
+ virtual void visit_pre_crement (pre_crement* e)
+ {
+ ++lval_depth;
+ e->operand->visit (this);
+ --lval_depth;
+ }
+
+ virtual void visit_post_crement (post_crement* e)
+ {
+ ++lval_depth;
+ e->operand->visit (this);
+ --lval_depth;
+ }
+
+ virtual void visit_assignment (assignment* e)
+ {
+ ++lval_depth;
+ e->left->visit (this);
+ --lval_depth;
+ e->right->visit (this);
+ }
+
+ virtual void visit_delete_statement (delete_statement* s)
+ {
+ ++lval_depth;
+ s->value->visit (this);
+ --lval_depth;
+ }
+
+};
+
+
+struct mutated_map_collector
+ : public lvalue_aware_traversing_visitor
+{
+ set<vardecl *> * mutated_maps;
+
+ mutated_map_collector(set<vardecl *> * mm)
+ : mutated_maps (mm)
+ {}
+
+ void visit_arrayindex (arrayindex *e)
+ {
+ if (is_in_lvalue())
+ mutated_maps->insert(e->referent);
+ }
+};
+
+
+struct no_map_mutation_during_iteration_check
+ : public lvalue_aware_traversing_visitor
+{
+ systemtap_session & session;
+ map<functiondecl *,set<vardecl *> *> & function_mutates_maps;
+ vector<vardecl *> maps_being_iterated;
+
+ no_map_mutation_during_iteration_check
+ (systemtap_session & sess,
+ map<functiondecl *,set<vardecl *> *> & fmm)
+ : session(sess), function_mutates_maps (fmm)
+ {}
+
+ void visit_arrayindex (arrayindex *e)
+ {
+ if (is_in_lvalue())
+ {
+ for (unsigned i = 0; i < maps_being_iterated.size(); ++i)
+ {
+ vardecl *m = maps_being_iterated[i];
+ if (m == e->referent)
+ {
+ string err = ("map '" + m->name +
+ "' modified during 'foreach' iteration");
+ session.print_error (semantic_error (err, e->tok));
+ }
+ }
+ }
+ }
+
+ void visit_functioncall (functioncall* e)
+ {
+ map<functiondecl *,set<vardecl *> *>::const_iterator i
+ = function_mutates_maps.find (e->referent);
+
+ if (i != function_mutates_maps.end())
+ {
+ for (unsigned j = 0; j < maps_being_iterated.size(); ++j)
+ {
+ vardecl *m = maps_being_iterated[j];
+ if (i->second->find (m) != i->second->end())
+ {
+ string err = ("function call modifies map '" + m->name +
+ "' during 'foreach' iteration");
+ session.print_error (semantic_error (err, e->tok));
+ }
+ }
+ }
+
+ for (unsigned i=0; i<e->args.size(); i++)
+ e->args[i]->visit (this);
+ }
+
+ void visit_foreach_loop(foreach_loop* s)
+ {
+ maps_being_iterated.push_back (s->base_referent);
+ for (unsigned i=0; i<s->indexes.size(); i++)
+ s->indexes[i]->visit (this);
+ s->block->visit (this);
+ maps_being_iterated.pop_back();
+ }
+};
+static int
+semantic_pass_maps (systemtap_session & sess)
+{
+
+ map<functiondecl *, set<vardecl *> *> fmm;
+ no_map_mutation_during_iteration_check chk(sess, fmm);
+
+ for (unsigned i = 0; i < sess.functions.size(); ++i)
+ {
+ functiondecl * fn = sess.functions[i];
+ if (fn->body)
+ {
+ set<vardecl *> * m = new set<vardecl *>();
+ mutated_map_collector mc (m);
+ fn->body->visit (&mc);
+ fmm[fn] = m;
+ }
+ }
+
+ for (unsigned i = 0; i < sess.functions.size(); ++i)
+ {
+ if (sess.functions[i]->body)
+ sess.functions[i]->body->visit (&chk);
+ }
+
+ for (unsigned i = 0; i < sess.probes.size(); ++i)
+ {
+ if (sess.probes[i]->body)
+ sess.probes[i]->body->visit (&chk);
+ }
+
+ return sess.num_errors;
+}
+
+// ------------------------------------------------------------------------
+
static int semantic_pass_symbols (systemtap_session&);
static int semantic_pass_types (systemtap_session&);
+static int semantic_pass_maps (systemtap_session&);
@@ -485,6 +653,7 @@ semantic_pass (systemtap_session& s)
int rc = semantic_pass_symbols (s);
if (rc == 0) rc = semantic_pass_types (s);
+ if (rc == 0) rc = semantic_pass_maps (s);
return rc;
}
diff --git a/staptree.cxx b/staptree.cxx
index 8183cffb..9a6d72bd 100644
--- a/staptree.cxx
+++ b/staptree.cxx
@@ -1015,6 +1015,7 @@ void
deep_copy_visitor::visit_block (block *s)
{
block *n = new block;
+ n->tok = s->tok;
for (unsigned i = 0; i < s->statements.size(); ++i)
{
statement *ns;
@@ -1027,13 +1028,16 @@ deep_copy_visitor::visit_block (block *s)
void
deep_copy_visitor::visit_null_statement (null_statement *s)
{
- provide <null_statement*> (this, new null_statement);
+ null_statement *n = new null_statement;
+ n->tok = s->tok;
+ provide <null_statement*> (this, n);
}
void
deep_copy_visitor::visit_expr_statement (expr_statement *s)
{
expr_statement *n = new expr_statement;
+ n->tok = s->tok;
require <expression*> (this, &(n->value), s->value);
provide <expr_statement*> (this, n);
}
@@ -1042,6 +1046,7 @@ void
deep_copy_visitor::visit_if_statement (if_statement* s)
{
if_statement *n = new if_statement;
+ n->tok = s->tok;
require <expression*> (this, &(n->condition), s->condition);
require <statement*> (this, &(n->thenblock), s->thenblock);
require <statement*> (this, &(n->elseblock), s->elseblock);
@@ -1052,6 +1057,7 @@ void
deep_copy_visitor::visit_for_loop (for_loop* s)
{
for_loop *n = new for_loop;
+ n->tok = s->tok;
require <expr_statement*> (this, &(n->init), s->init);
require <expression*> (this, &(n->cond), s->cond);
require <expr_statement*> (this, &(n->incr), s->incr);
@@ -1063,6 +1069,7 @@ void
deep_copy_visitor::visit_foreach_loop (foreach_loop* s)
{
foreach_loop *n = new foreach_loop;
+ n->tok = s->tok;
for (unsigned i = 0; i < s->indexes.size(); ++i)
{
symbol *sym;
@@ -1079,6 +1086,7 @@ void
deep_copy_visitor::visit_return_statement (return_statement* s)
{
return_statement *n = new return_statement;
+ n->tok = s->tok;
require <expression*> (this, &(n->value), s->value);
provide <return_statement*> (this, n);
}
@@ -1087,6 +1095,7 @@ void
deep_copy_visitor::visit_delete_statement (delete_statement* s)
{
delete_statement *n = new delete_statement;
+ n->tok = s->tok;
require <expression*> (this, &(n->value), s->value);
provide <delete_statement*> (this, n);
}
@@ -1094,31 +1103,41 @@ deep_copy_visitor::visit_delete_statement (delete_statement* s)
void
deep_copy_visitor::visit_next_statement (next_statement* s)
{
- provide <next_statement*> (this, new next_statement);
+ next_statement *n = new next_statement;
+ n->tok = s->tok;
+ provide <next_statement*> (this, n);
}
void
deep_copy_visitor::visit_break_statement (break_statement* s)
{
- provide <break_statement*> (this, new break_statement);
+ break_statement *n = new break_statement;
+ n->tok = s->tok;
+ provide <break_statement*> (this, n);
}
void
deep_copy_visitor::visit_continue_statement (continue_statement* s)
{
- provide <continue_statement*> (this, new continue_statement);
+ continue_statement *n = new continue_statement;
+ n->tok = s->tok;
+ provide <continue_statement*> (this, n);
}
void
deep_copy_visitor::visit_literal_string (literal_string* e)
{
- provide <literal_string*> (this, new literal_string(e->value));
+ literal_string *n = new literal_string(e->value);
+ n->tok = e->tok;
+ provide <literal_string*> (this, n);
}
void
deep_copy_visitor::visit_literal_number (literal_number* e)
{
- provide <literal_number*> (this, new literal_number(e->value));
+ literal_number *n = new literal_number(e->value);
+ n->tok = e->tok;
+ provide <literal_number*> (this, n);
}
void
@@ -1126,6 +1145,7 @@ deep_copy_visitor::visit_binary_expression (binary_expression* e)
{
binary_expression *n = new binary_expression;
n->op = e->op;
+ n->tok = e->tok;
require <expression*> (this, &(n->left), e->left);
require <expression*> (this, &(n->right), e->right);
provide <binary_expression*> (this, n);
@@ -1136,6 +1156,7 @@ deep_copy_visitor::visit_unary_expression (unary_expression* e)
{
unary_expression *n = new unary_expression;
n->op = e->op;
+ n->tok = e->tok;
require <expression*> (this, &(n->operand), e->operand);
provide <unary_expression*> (this, n);
}
@@ -1145,6 +1166,7 @@ deep_copy_visitor::visit_pre_crement (pre_crement* e)
{
pre_crement *n = new pre_crement;
n->op = e->op;
+ n->tok = e->tok;
require <expression*> (this, &(n->operand), e->operand);
provide <pre_crement*> (this, n);
}
@@ -1154,6 +1176,7 @@ deep_copy_visitor::visit_post_crement (post_crement* e)
{
post_crement *n = new post_crement;
n->op = e->op;
+ n->tok = e->tok;
require <expression*> (this, &(n->operand), e->operand);
provide <post_crement*> (this, n);
}
@@ -1164,6 +1187,7 @@ deep_copy_visitor::visit_logical_or_expr (logical_or_expr* e)
{
logical_or_expr *n = new logical_or_expr;
n->op = e->op;
+ n->tok = e->tok;
require <expression*> (this, &(n->left), e->left);
require <expression*> (this, &(n->right), e->right);
provide <logical_or_expr*> (this, n);
@@ -1174,6 +1198,7 @@ deep_copy_visitor::visit_logical_and_expr (logical_and_expr* e)
{
logical_and_expr *n = new logical_and_expr;
n->op = e->op;
+ n->tok = e->tok;
require <expression*> (this, &(n->left), e->left);
require <expression*> (this, &(n->right), e->right);
provide <logical_and_expr*> (this, n);
@@ -1183,6 +1208,7 @@ void
deep_copy_visitor::visit_array_in (array_in* e)
{
array_in *n = new array_in;
+ n->tok = e->tok;
require <arrayindex*> (this, &(n->operand), e->operand);
provide <array_in*> (this, n);
}
@@ -1192,6 +1218,7 @@ deep_copy_visitor::visit_comparison (comparison* e)
{
comparison *n = new comparison;
n->op = e->op;
+ n->tok = e->tok;
require <expression*> (this, &(n->left), e->left);
require <expression*> (this, &(n->right), e->right);
provide <comparison*> (this, n);
@@ -1202,6 +1229,7 @@ deep_copy_visitor::visit_concatenation (concatenation* e)
{
concatenation *n = new concatenation;
n->op = e->op;
+ n->tok = e->tok;
require <expression*> (this, &(n->left), e->left);
require <expression*> (this, &(n->right), e->right);
provide <concatenation*> (this, n);
@@ -1211,6 +1239,7 @@ void
deep_copy_visitor::visit_ternary_expression (ternary_expression* e)
{
ternary_expression *n = new ternary_expression;
+ n->tok = e->tok;
require <expression*> (this, &(n->cond), e->cond);
require <expression*> (this, &(n->truevalue), e->truevalue);
require <expression*> (this, &(n->falsevalue), e->falsevalue);
@@ -1222,6 +1251,7 @@ deep_copy_visitor::visit_assignment (assignment* e)
{
assignment *n = new assignment;
n->op = e->op;
+ n->tok = e->tok;
require <expression*> (this, &(n->left), e->left);
require <expression*> (this, &(n->right), e->right);
provide <assignment*> (this, n);
@@ -1231,6 +1261,7 @@ void
deep_copy_visitor::visit_symbol (symbol* e)
{
symbol *n = new symbol;
+ n->tok = e->tok;
n->name = e->name;
n->referent = NULL;
provide <symbol*> (this, n);
@@ -1240,6 +1271,7 @@ void
deep_copy_visitor::visit_arrayindex (arrayindex* e)
{
arrayindex *n = new arrayindex;
+ n->tok = e->tok;
n->base = e->base;
n->referent = NULL;
for (unsigned i = 0; i < e->indexes.size(); ++i)
@@ -1255,6 +1287,7 @@ void
deep_copy_visitor::visit_functioncall (functioncall* e)
{
functioncall *n = new functioncall;
+ n->tok = e->tok;
n->function = e->function;
n->referent = NULL;
for (unsigned i = 0; i < e->args.size(); ++i)
diff --git a/testsuite/semko/fifteen.stp b/testsuite/semko/fifteen.stp
new file mode 100755
index 00000000..612271db
--- /dev/null
+++ b/testsuite/semko/fifteen.stp
@@ -0,0 +1,14 @@
+#! stap -p2
+
+global tangle
+
+probe begin
+{
+ foreach (state in tangle)
+ {
+ state = tangle[state]++
+ }
+ printk("hello from systemtap")
+}
+
+
diff --git a/testsuite/semko/fourteen.stp b/testsuite/semko/fourteen.stp
new file mode 100755
index 00000000..16bd784b
--- /dev/null
+++ b/testsuite/semko/fourteen.stp
@@ -0,0 +1,20 @@
+#! stap -p2
+
+global foo
+
+function bar()
+{
+ a = foo["hello"]++
+ return 10
+}
+
+probe begin
+{
+ foreach (a in foo)
+ {
+ bar()
+ }
+ printk("hello from systemtap")
+}
+
+
diff --git a/testsuite/semko/thirteen.stp b/testsuite/semko/thirteen.stp
new file mode 100755
index 00000000..88761ded
--- /dev/null
+++ b/testsuite/semko/thirteen.stp
@@ -0,0 +1,20 @@
+#! stap -p2
+
+global foo
+
+function bar()
+{
+ foo["hello"] = 10
+ return 10
+}
+
+probe begin
+{
+ foreach (a in foo)
+ {
+ bar()
+ }
+ printk("hello from systemtap")
+}
+
+
diff --git a/testsuite/transok/eight.stp b/testsuite/transok/eight.stp
new file mode 100755
index 00000000..e703a5ae
--- /dev/null
+++ b/testsuite/transok/eight.stp
@@ -0,0 +1,30 @@
+#! stap -p3
+
+global foo
+global baz
+
+function bar()
+{
+ return foo["hello"]
+}
+
+probe begin
+{
+ foo["hello"] = 10
+ foreach (a in foo)
+ {
+ bar()
+ }
+
+ baz[1,"hello",a] = "chicken"
+ baz[1,"goodbye",a] = "supreme"
+
+ foreach ([x,y,z] in baz)
+ {
+ printk(baz[x,y,z] . y)
+ }
+
+ printk("hello from systemtap")
+}
+
+
diff --git a/translate.cxx b/translate.cxx
index 3c26fade..d794c6be 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -33,6 +33,7 @@ stringify(T t)
struct var;
struct tmpvar;
struct mapvar;
+struct itervar;
struct c_unparser: public unparser, public visitor
{
@@ -67,6 +68,7 @@ struct c_unparser: public unparser, public visitor
string c_typename (exp_type e);
string c_varname (const string& e);
+ void c_assign (var& lvalue, const string& rvalue, const token *tok);
void c_assign (const string& lvalue, expression* rvalue, const string& msg);
void c_assign (const string& lvalue, const string& rvalue, exp_type type,
const string& msg, const token* tok);
@@ -84,6 +86,7 @@ struct c_unparser: public unparser, public visitor
tmpvar gensym(exp_type ty);
var getvar(vardecl *v, token const *tok = NULL);
+ itervar getiter(foreach_loop *f);
mapvar getmap(vardecl *v, token const *tok = NULL);
void load_map_indices(arrayindex *e,
@@ -131,10 +134,13 @@ struct c_tmpcounter:
{
c_unparser* parent;
c_tmpcounter (c_unparser* p):
- parent (p) {}
+ parent (p)
+ {
+ parent->tmpvar_counter = 0;
+ }
// void visit_for_loop (for_loop* s);
- // void visit_foreach_loop (foreach_loop* s);
+ void visit_foreach_loop (foreach_loop* s);
// void visit_return_statement (return_statement* s);
// void visit_delete_statement (delete_statement* s);
void visit_binary_expression (binary_expression* e);
@@ -170,7 +176,7 @@ struct c_unparser_assignment:
tmpvar const & rval,
token const * tok);
- void c_assignop(tmpvar const & dst,
+ void c_assignop(tmpvar & res,
var const & lvar,
tmpvar const & tmp,
token const * tok);
@@ -240,13 +246,13 @@ public:
if (ty == pe_long)
{
c.o->newline() << "if (" << qname() << " == 0) {";
- c.o->newline(1) << "errorcount++;";
+ c.o->newline(1) << "c->errorcount++;";
c.o->newline() << qname() << " = 1;";
c.o->newline(-1) << "}";
}
}
- string init()
+ string init() const
{
switch (type())
{
@@ -377,6 +383,65 @@ struct mapvar
};
+class itervar
+{
+ exp_type referent_ty;
+ string name;
+
+public:
+
+ itervar (foreach_loop *e, unsigned & counter)
+ : referent_ty(e->base_referent->type),
+ name("__tmp" + stringify(counter++))
+ {
+ if (referent_ty != pe_long && referent_ty != pe_string)
+ throw semantic_error("iterating over illegal reference type", e->tok);
+ }
+
+ string declare () const
+ {
+ return "struct map_node *" + name + ";";
+ }
+
+ string start (mapvar const & mv) const
+ {
+ if (mv.type() != referent_ty)
+ throw semantic_error("inconsistent iterator type in itervar::start()");
+
+ return "_stp_map_start (" + mv.qname() + ")";
+ }
+
+ string next (mapvar const & mv) const
+ {
+ if (mv.type() != referent_ty)
+ throw semantic_error("inconsistent iterator type in itervar::next()");
+
+ return "_stp_map_iter (" + mv.qname() + ", " + qname() + ")";
+ }
+
+ string qname () const
+ {
+ return "l->" + name;
+ }
+
+ string get_key (exp_type ty, unsigned i) const
+ {
+ switch (ty)
+ {
+ case pe_long:
+ return "_stp_key_get_int64 ("+ qname() + ", " + stringify(i) + ")";
+ case pe_string:
+ return "_stp_key_get_str ("+ qname() + ", " + stringify(i) + ")";
+ default:
+ throw semantic_error("illegal key type");
+ }
+ }
+};
+
+ostream & operator<<(ostream & o, itervar const & v)
+{
+ return o << v.qname();
+}
// ------------------------------------------------------------------------
@@ -915,6 +980,21 @@ c_unparser::c_varname (const string& e)
return e;
}
+void
+c_unparser::c_assign (var& lvalue, const string& rvalue, const token *tok)
+{
+ switch (lvalue.type())
+ {
+ case pe_string:
+ c_strcpy(lvalue.qname(), rvalue);
+ break;
+ case pe_long:
+ o->newline() << lvalue << " = " << rvalue << ";";
+ break;
+ default:
+ throw semantic_error ("unknown rvalue type in assignment", tok);
+ }
+}
void
c_unparser::c_assign (const string& lvalue, expression* rvalue,
@@ -959,7 +1039,7 @@ c_unparser::c_assign (const string& lvalue, const string& rvalue,
void
-c_unparser_assignment::c_assignop(tmpvar const & _res,
+c_unparser_assignment::c_assignop(tmpvar & res,
var const & lval,
tmpvar const & rval,
token const * tok)
@@ -975,7 +1055,7 @@ c_unparser_assignment::c_assignop(tmpvar const & _res,
// we'd like to work with a local tmpvar so we can overwrite it in
// some optimized cases
- tmpvar res = _res;
+
translator_output* o = parent->o;
if (res.type() == pe_string)
@@ -1152,6 +1232,13 @@ c_unparser::getmap(vardecl *v, token const *tok)
}
+itervar
+c_unparser::getiter(foreach_loop *f)
+{
+ return itervar (f, tmpvar_counter);
+}
+
+
void
c_unparser::visit_block (block *s)
{
@@ -1248,9 +1335,40 @@ c_unparser::visit_for_loop (for_loop *s)
void
+c_tmpcounter::visit_foreach_loop (foreach_loop *s)
+{
+ itervar iv = parent->getiter (s);
+ parent->o->newline() << iv.declare();
+ s->block->visit (this);
+}
+
+void
c_unparser::visit_foreach_loop (foreach_loop *s)
{
- throw semantic_error ("foreach loop not yet implemented", s->tok);
+ mapvar mv = getmap (s->base_referent, s->tok);
+ itervar iv = getiter (s);
+ vector<var> keys;
+
+ varlock guard (*this, mv);
+
+ o->newline() << "for ("
+ << iv << " = " << iv.start (mv) << "; ";
+ o->newline() << " " << iv << "; ";
+ o->newline() << " " << iv << " = " << iv.next (mv) << ")";
+ o->newline() << "{";
+ o->indent (1);
+
+ for (unsigned i = 0; i < s->indexes.size(); ++i)
+ {
+ // copy the iter values into the specified locals
+ var v = getvar (s->indexes[i]->referent);
+ c_assign (v, iv.get_key (v.type(), i), s->tok);
+ }
+
+ s->block->visit (this);
+
+ o->indent (-1);
+ o->newline() << "}";
}
@@ -1760,13 +1878,13 @@ c_unparser::visit_arrayindex (arrayindex* e)
// reentrancy issues that pop up with nested expressions:
// e.g. a[a[c]=5] could deadlock
- o->newline() << "if (errorcount) goto out;";
+ o->newline() << "if (c->errorcount) goto out;";
{
mapvar mvar = getmap (e->referent, e->tok);
varlock guard (*this, mvar);
o->newline() << mvar.seek (idx) << ";";
- o->newline() << res << " = " << mvar.get() << ";";
+ c_assign (res, mvar.get(), e->tok);
}
o->newline() << res << ";";
@@ -1836,7 +1954,7 @@ c_unparser_assignment::visit_arrayindex (arrayindex *e)
// reentrancy issues that pop up with nested expressions:
// e.g. ++a[a[c]=5] could deadlock
- o->newline() << "if (errorcount) goto out;";
+ o->newline() << "if (c->errorcount) goto out;";
prepare_rvalue (op, rvar, e->tok);
@@ -1844,7 +1962,7 @@ c_unparser_assignment::visit_arrayindex (arrayindex *e)
mapvar mvar = parent->getmap (e->referent, e->tok);
varlock guard (*parent, mvar);
o->newline() << mvar.seek (idx) << ";";
- o->newline() << lvar << " = " << mvar.get() << ";";
+ parent->c_assign (lvar, mvar.get(), e->tok);
c_assignop (res, lvar, rvar, e->tok);
o->newline() << mvar.set (lvar) << ";";
}