summaryrefslogtreecommitdiffstats
path: root/parse.cxx
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2009-02-11 14:34:32 -0800
committerJosh Stone <jistone@redhat.com>2009-02-18 12:47:25 -0800
commit9b5af2958a35174a67076c0f27cff0ed5950736d (patch)
treeedd1da26e8e47d033c6ad29fc2e797243b7ba1d0 /parse.cxx
parentbbc46bf643491173b9086907cf0820b3fd2c1fe3 (diff)
downloadsystemtap-steved-9b5af2958a35174a67076c0f27cff0ed5950736d.tar.gz
systemtap-steved-9b5af2958a35174a67076c0f27cff0ed5950736d.tar.xz
systemtap-steved-9b5af2958a35174a67076c0f27cff0ed5950736d.zip
Add high-level support for @cast()ing
This handles all of the parsing, traversal, and optimization. It doesn't actually resolve the cast yet though. * staptree.h (struct cast_op, visitor::visit_cast_op): New. * staptree.cxx (cast_op::print/visit, various visitor::visit_cast_op's): Incorporate cast_op into the basic tree operations. * parse.cxx (parser::parse_symbol): Parse @cast operator with an expression operand, type string, and optional module string. * translate.cxx (c_unparser::visit_cast_op): Error out if a @cast survives to translation. * elaborate.cxx (typeresolution_info::visit_cast_op): Error out if a @cast survives to type resolution. (symbol_fetcher::visit_cast_op): treat @casts as a symbol target (void_statement_reducer::visit_cast_op): unused @casts can be discarded, but the operand should still be evaluated.
Diffstat (limited to 'parse.cxx')
-rw-r--r--parse.cxx49
1 files changed, 48 insertions, 1 deletions
diff --git a/parse.cxx b/parse.cxx
index 0419dcb9..aeb11998 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -2331,7 +2331,54 @@ parser::parse_symbol ()
bool pf_stream, pf_format, pf_delim, pf_newline, pf_char;
- if (name.size() > 0 && name[0] == '@')
+ if (name == "@cast")
+ {
+ // type-punning time
+ cast_op *cop = new cast_op;
+ cop->tok = t;
+ cop->base_name = name;
+ expect_op("(");
+ cop->operand = parse_expression ();
+ expect_op(",");
+ expect_unknown(tok_string, cop->type);
+ if (peek_op (","))
+ {
+ next();
+ expect_unknown(tok_string, cop->module);
+ }
+ expect_op(")");
+ while (true)
+ {
+ string c;
+ if (peek_op ("->"))
+ {
+ next();
+ expect_ident_or_keyword (c);
+ cop->components.push_back
+ (make_pair (target_symbol::comp_struct_member, c));
+ }
+ else if (peek_op ("["))
+ {
+ next();
+ expect_unknown (tok_number, c);
+ expect_op ("]");
+ cop->components.push_back
+ (make_pair (target_symbol::comp_literal_array_index, c));
+ }
+ else
+ break;
+ }
+ // if there aren't any dereferences, then the cast is pointless
+ if (cop->components.empty())
+ {
+ expression *op = cop->operand;
+ delete cop;
+ return op;
+ }
+ return cop;
+ }
+
+ else if (name.size() > 0 && name[0] == '@')
{
stat_op *sop = new stat_op;
if (name == "@avg")