diff options
author | graydon <graydon> | 2005-08-09 18:17:24 +0000 |
---|---|---|
committer | graydon <graydon> | 2005-08-09 18:17:24 +0000 |
commit | d98d459c440fb476869b34a84bb8a75d28fbb188 (patch) | |
tree | 592d6ab998b1bab7c3d67ea23272884f78fc8860 | |
parent | debd8982950caa54b27944775910dd282b82b338 (diff) | |
download | systemtap-steved-d98d459c440fb476869b34a84bb8a75d28fbb188.tar.gz systemtap-steved-d98d459c440fb476869b34a84bb8a75d28fbb188.tar.xz systemtap-steved-d98d459c440fb476869b34a84bb8a75d28fbb188.zip |
2005-08-09 Graydon Hoare <graydon@redhat.com>
* elaborate.cxx:
(delete_statement_symresolution_info): New struct.
(symresolution_info::visit_delete_statement): Use it.
(delete_statement_typeresolution_info): New struct.
(typeresolution_info::visit_delete_statement): Use it.
(symresolution_info::find_var): Accept -1 as 'unknown' arity.
* elaborate.h: Update to reflect changes in .cxx.
* translate.cxx (mapvar::del): New method.
(c_unparser::getmap): Check arity >= 1;
(delete_statement_operand_visitor): New struct.
(c_unparser::visit_delete_statement): Use it.
* staptree.cxx (vardecl::set_arity): Accept and ignore -1.
(vardecl::compatible_arity): Likewise.
* testsuite/buildok/eight.stp: New test for 'delete' operator.
-rw-r--r-- | ChangeLog | 17 | ||||
-rw-r--r-- | elaborate.cxx | 75 | ||||
-rw-r--r-- | elaborate.h | 5 | ||||
-rw-r--r-- | staptree.cxx | 5 | ||||
-rwxr-xr-x | testsuite/buildok/eight.stp | 10 | ||||
-rw-r--r-- | translate.cxx | 48 |
6 files changed, 147 insertions, 13 deletions
@@ -1,3 +1,20 @@ +2005-08-09 Graydon Hoare <graydon@redhat.com> + + * elaborate.cxx: + (delete_statement_symresolution_info): New struct. + (symresolution_info::visit_delete_statement): Use it. + (delete_statement_typeresolution_info): New struct. + (typeresolution_info::visit_delete_statement): Use it. + (symresolution_info::find_var): Accept -1 as 'unknown' arity. + * elaborate.h: Update to reflect changes in .cxx. + * translate.cxx (mapvar::del): New method. + (c_unparser::getmap): Check arity >= 1; + (delete_statement_operand_visitor): New struct. + (c_unparser::visit_delete_statement): Use it. + * staptree.cxx (vardecl::set_arity): Accept and ignore -1. + (vardecl::compatible_arity): Likewise. + * testsuite/buildok/eight.stp: New test for 'delete' operator. + 2005-08-08 Roland McGrath <roland@redhat.com> * loc2c-test.c: New file. diff --git a/elaborate.cxx b/elaborate.cxx index 8adcc2a7..c9f1fcd1 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -730,6 +730,45 @@ symresolution_info::visit_foreach_loop (foreach_loop* e) e->block->visit (this); } +struct +delete_statement_symresolution_info: + public traversing_visitor +{ + symresolution_info *parent; + + delete_statement_symresolution_info (symresolution_info *p): + parent(p) + {} + + void visit_arrayindex (arrayindex* e) + { + parent->visit_arrayindex (e); + } + void visit_functioncall (functioncall* e) + { + parent->visit_functioncall (e); + } + + void visit_symbol (symbol* e) + { + if (e->referent) + return; + + vardecl* d = parent->find_var (e->name, -1); + if (d) + e->referent = d; + else + throw semantic_error ("unresolved array in delete statement", e->tok); + } +}; + +void +symresolution_info::visit_delete_statement (delete_statement* s) +{ + delete_statement_symresolution_info di (this); + s->value->visit (&di); +} + void symresolution_info::visit_symbol (symbol* e) @@ -807,7 +846,7 @@ symresolution_info::visit_functioncall (functioncall* e) vardecl* -symresolution_info::find_var (const string& name, unsigned arity) +symresolution_info::find_var (const string& name, int arity) { // search locals @@ -837,12 +876,12 @@ symresolution_info::find_var (const string& name, unsigned arity) // search processed globals for (unsigned i=0; i<session.globals.size(); i++) if (session.globals[i]->name == name - && session.globals[i]->compatible_arity(arity)) + && session.globals[i]->compatible_arity(arity)) { session.globals[i]->set_arity (arity); return session.globals[i]; } - + // search library globals for (unsigned i=0; i<session.library_files.size(); i++) { @@ -852,7 +891,7 @@ symresolution_info::find_var (const string& name, unsigned arity) vardecl* g = f->globals[j]; if (g->name == name && g->compatible_arity (arity)) { - g->set_arity (arity); + g->set_arity (arity); // put library into the queue if not already there if (find (session.files.begin(), session.files.end(), f) @@ -1510,11 +1549,35 @@ typeresolution_info::visit_expr_statement (expr_statement* e) } +struct delete_statement_typeresolution_info: + public throwing_visitor +{ + typeresolution_info *parent; + delete_statement_typeresolution_info (typeresolution_info *p): + throwing_visitor ("invalid operand of delete expression"), + parent (p) + {} + + void visit_arrayindex (arrayindex* e) + { + parent->visit_arrayindex (e); + } + + void visit_symbol (symbol* e) + { + exp_type ignored = pe_unknown; + assert (e->referent != 0); + resolve_2types (e, e->referent, parent, ignored); + } +}; + + void typeresolution_info::visit_delete_statement (delete_statement* e) { - // XXX: not yet supported - unresolved (e->tok); + delete_statement_typeresolution_info di (this); + t = pe_unknown; + e->value->visit (&di); } diff --git a/elaborate.h b/elaborate.h index 4b42e0be..86da8b51 100644 --- a/elaborate.h +++ b/elaborate.h @@ -35,10 +35,8 @@ public: // XXX: instead in systemtap_session? void derive_probes (match_node * root, probe *p, std::vector<derived_probe*>& dps); - -protected: - vardecl* find_var (const std::string& name, unsigned arity); + vardecl* find_var (const std::string& name, int arity); functiondecl* find_function (const std::string& name, unsigned arity); void visit_block (block *s); @@ -46,6 +44,7 @@ protected: void visit_foreach_loop (foreach_loop* e); void visit_arrayindex (arrayindex* e); void visit_functioncall (functioncall* e); + void visit_delete_statement (delete_statement* s); }; diff --git a/staptree.cxx b/staptree.cxx index b5a7ae49..31330017 100644 --- a/staptree.cxx +++ b/staptree.cxx @@ -106,7 +106,8 @@ vardecl::vardecl (): void vardecl::set_arity (int a) { - assert (a >= 0); + if (a < 0) + return; if (arity != a && arity >= 0) throw semantic_error ("inconsistent arity", tok); @@ -123,7 +124,7 @@ vardecl::set_arity (int a) bool vardecl::compatible_arity (int a) { - if (arity == -1) + if (arity == -1 || a == -1) return true; return arity == a; } diff --git a/testsuite/buildok/eight.stp b/testsuite/buildok/eight.stp new file mode 100755 index 00000000..84390270 --- /dev/null +++ b/testsuite/buildok/eight.stp @@ -0,0 +1,10 @@ +#! stap -p4 + +global foo + +probe begin { + foo[1] = 1 + delete foo[1] + delete foo[foo[foo[foo[1]]]] + delete foo +} diff --git a/translate.cxx b/translate.cxx index 0bb56815..b013fc29 100644 --- a/translate.cxx +++ b/translate.cxx @@ -327,6 +327,11 @@ struct mapvar static string key_typename(exp_type e); static string value_typename(exp_type e); + string del () const + { + return "_stp_map_key_del (" + qname() + ")"; + } + string seek (vector<tmpvar> const & indices) const { string result = "_stp_map_key" + mangled_indices() + " ("; @@ -1203,7 +1208,9 @@ c_unparser::getvar(vardecl *v, token const *tok) mapvar c_unparser::getmap(vardecl *v, token const *tok) -{ +{ + if (v->arity < 1) + throw new semantic_error("attempt to use scalar where map expected", tok); return mapvar (is_local (v, tok), v->type, v->name, v->index_types); } @@ -1380,10 +1387,47 @@ c_unparser::visit_next_statement (next_statement* s) } +struct delete_statement_operand_visitor: + public throwing_visitor +{ + c_unparser *parent; + delete_statement_operand_visitor (c_unparser *p): + throwing_visitor ("invalid operand of delete expression"), + parent (p) + {} + void visit_symbol (symbol* e); + void visit_arrayindex (arrayindex* e); +}; + +void +delete_statement_operand_visitor::visit_symbol (symbol* e) +{ + mapvar mvar = parent->getmap(e->referent, e->tok); + varlock guard (*parent, mvar); + parent->o->newline() << mvar.fini (); + parent->o->newline() << mvar.init (); +} + +void +delete_statement_operand_visitor::visit_arrayindex (arrayindex* e) +{ + vector<tmpvar> idx; + parent->load_map_indices (e, idx); + parent->o->newline() << "if (unlikely (c->errorcount)) goto out;"; + { + mapvar mvar = parent->getmap (e->referent, e->tok); + varlock guard (*parent, mvar); + parent->o->newline() << mvar.seek (idx) << ";"; + parent->o->newline() << mvar.del () << ";"; + } +} + + void c_unparser::visit_delete_statement (delete_statement* s) { - throw semantic_error ("delete statement not yet implemented", s->tok); + delete_statement_operand_visitor dv (this); + s->value->visit (&dv); } |