This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 1/2] introduce UNOP_CAST_TYPE and UNOP_MEMVAL_TYPE


This patch introduces UNOP_CAST_TYPE and UNOP_MEMVAL_TYPE.  These are
like UNOP_CAST and UNOP_MEMVAL, but take the type argument as an
expression.

This patch is just preparation for the next patch, which uses this new
functionality to (mostly) implement typeof.  typeof needs to take an
expression as an argument; and because expression type resolution is
generally deferred to evaluation time in gdb, typeof must also be
implemented this way.

This patch also changes the representation of UNOP_REINTERPRET_CAST
and UNOP_DYNAMIC_CAST to follow.  These are only ever generated by the
C++ parser and it seemed simplest to just have a single representation
for them.

Finally, this fixes a latent bug in watchpoint_exp_is_const that I
noticed while writing this patch.

	* ax-gdb.c (gen_expr): Handle UNOP_CAST_TYPE, UNOP_MEMVAL_TYPE.
	* breakpoint.c (watchpoint_exp_is_const): Handle UNOP_CAST_TYPE,
	UNOP_REINTERPRET_CAST, UNOP_DYNAMIC_CAST.
	* c-exp.y (exp): Emit UNOP_MEMVAL_TYPE, UNOP_CAST_TYPE.  Update
	for changes to UNOP_REINTERPRET_CAST, UNOP_DYNAMIC_CAST.  Use
	type_exp production where appropriate.
	* eval.c (evaluate_subexp_standard) <UNOP_CAST_TYPE>: New case.
	<UNOP_DYNAMIC_CAST, UNOP_REINTERPRET_CAST>: Update.
	<UNOP_MEMVAL_TYPE>: New case.
	(evaluate_subexp_for_address) <UNOP_MEMVAL_TYPE>: New case.
	(evaluate_subexp_for_sizeof) <UNOP_MEMVAL_TYPE>: New case.
	* expprint.c (print_subexp_standard) <UNOP_CAST_TYPE>: New case.
	<UNOP_MEMVAL_TYPE>: New case.
	(dump_subexp_body_standard) <UNOP_DYNAMIC_CAST,
	UNOP_REINTERPRET_CAST>: Update.
	<UNOP_CAST_TYPE, UNOP_MEMVAL_TYPE>: New cases.
	* parse.c (operator_length_standard) <UNOP_DYNAMIC_CAST,
	UNOP_REINTERPRET_CAST>: Update.
	<UNOP_CAST_TYPE, UNOP_MEMVAL_TYPE>: New cases.
	* stack.c (return_command): Also check for UNOP_CAST_TYPE.
	* std-operator.def (UNOP_CAST_TYPE, UNOP_MEMVAL_TYPE): New
	constants.
---
 gdb/ax-gdb.c         |   42 ++++++++++++++++++++++++++++++++++++++++++
 gdb/breakpoint.c     |    4 ++++
 gdb/c-exp.y          |   36 ++++++++++++------------------------
 gdb/eval.c           |   47 +++++++++++++++++++++++++++++++++++++++++++----
 gdb/expprint.c       |   40 ++++++++++++++++++++++++++++++++++++----
 gdb/parse.c          |   12 ++++++++----
 gdb/stack.c          |    3 ++-
 gdb/std-operator.def |    6 ++++++
 8 files changed, 153 insertions(+), 37 deletions(-)

diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
index 1bf03df..8f14a94 100644
--- a/gdb/ax-gdb.c
+++ b/gdb/ax-gdb.c
@@ -2072,6 +2072,23 @@ gen_expr (struct expression *exp, union exp_element **pc,
       }
       break;
 
+    case UNOP_CAST_TYPE:
+      {
+	int offset;
+	struct value *val;
+	struct type *type;
+
+	++*pc;
+	offset = *pc - exp->elts;
+	val = evaluate_subexp (NULL, exp, &offset, EVAL_AVOID_SIDE_EFFECTS);
+	type = value_type (val);
+	*pc = &exp->elts[offset];
+
+	gen_expr (exp, pc, ax, value);
+	gen_cast (ax, value, type);
+      }
+      break;
+
     case UNOP_MEMVAL:
       {
 	struct type *type = check_typedef ((*pc)[1].type);
@@ -2090,6 +2107,31 @@ gen_expr (struct expression *exp, union exp_element **pc,
       }
       break;
 
+    case UNOP_MEMVAL_TYPE:
+      {
+	int offset;
+	struct value *val;
+	struct type *type;
+
+	++*pc;
+	offset = *pc - exp->elts;
+	val = evaluate_subexp (NULL, exp, &offset, EVAL_AVOID_SIDE_EFFECTS);
+	type = value_type (val);
+	*pc = &exp->elts[offset];
+
+	gen_expr (exp, pc, ax, value);
+
+	/* If we have an axs_rvalue or an axs_lvalue_memory, then we
+	   already have the right value on the stack.  For
+	   axs_lvalue_register, we must convert.  */
+	if (value->kind == axs_lvalue_register)
+	  require_rvalue (ax, value);
+
+	value->type = type;
+	value->kind = axs_lvalue_memory;
+      }
+      break;
+
     case UNOP_PLUS:
       (*pc)++;
       /* + FOO is equivalent to 0 + FOO, which can be optimized.  */
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 71a5e19..df6b598 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -9941,6 +9941,10 @@ watchpoint_exp_is_const (const struct expression *exp)
 	case UNOP_ADDR:
 	case UNOP_HIGH:
 	case UNOP_CAST:
+
+	case UNOP_CAST_TYPE:
+	case UNOP_REINTERPRET_CAST:
+	case UNOP_DYNAMIC_CAST:
 	  /* Unary, binary and ternary operators: We have to check
 	     their operands.  If they are constant, then so is the
 	     result of that operation.  For instance, if A and B are
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 7afce77..c4a050d 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -459,16 +459,12 @@ exp	:	lcurly arglist rcurly	%prec ARROW
 			  write_exp_elt_opcode (OP_ARRAY); }
 	;
 
-exp	:	lcurly type rcurly exp  %prec UNARY
-			{ write_exp_elt_opcode (UNOP_MEMVAL);
-			  write_exp_elt_type ($2);
-			  write_exp_elt_opcode (UNOP_MEMVAL); }
+exp	:	lcurly type_exp rcurly exp  %prec UNARY
+			{ write_exp_elt_opcode (UNOP_MEMVAL_TYPE); }
 	;
 
-exp	:	'(' type ')' exp  %prec UNARY
-			{ write_exp_elt_opcode (UNOP_CAST);
-			  write_exp_elt_type ($2);
-			  write_exp_elt_opcode (UNOP_CAST); }
+exp	:	'(' type_exp ')' exp  %prec UNARY
+			{ write_exp_elt_opcode (UNOP_CAST_TYPE); }
 	;
 
 exp	:	'(' exp1 ')'
@@ -627,30 +623,22 @@ exp	:	SIZEOF '(' type ')'	%prec UNARY
 			  write_exp_elt_opcode (OP_LONG); }
 	;
 
-exp	:	REINTERPRET_CAST '<' type '>' '(' exp ')' %prec UNARY
-			{ write_exp_elt_opcode (UNOP_REINTERPRET_CAST);
-			  write_exp_elt_type ($3);
-			  write_exp_elt_opcode (UNOP_REINTERPRET_CAST); }
+exp	:	REINTERPRET_CAST '<' type_exp '>' '(' exp ')' %prec UNARY
+			{ write_exp_elt_opcode (UNOP_REINTERPRET_CAST); }
 	;
 
-exp	:	STATIC_CAST '<' type '>' '(' exp ')' %prec UNARY
-			{ write_exp_elt_opcode (UNOP_CAST);
-			  write_exp_elt_type ($3);
-			  write_exp_elt_opcode (UNOP_CAST); }
+exp	:	STATIC_CAST '<' type_exp '>' '(' exp ')' %prec UNARY
+			{ write_exp_elt_opcode (UNOP_CAST_TYPE); }
 	;
 
-exp	:	DYNAMIC_CAST '<' type '>' '(' exp ')' %prec UNARY
-			{ write_exp_elt_opcode (UNOP_DYNAMIC_CAST);
-			  write_exp_elt_type ($3);
-			  write_exp_elt_opcode (UNOP_DYNAMIC_CAST); }
+exp	:	DYNAMIC_CAST '<' type_exp '>' '(' exp ')' %prec UNARY
+			{ write_exp_elt_opcode (UNOP_DYNAMIC_CAST); }
 	;
 
-exp	:	CONST_CAST '<' type '>' '(' exp ')' %prec UNARY
+exp	:	CONST_CAST '<' type_exp '>' '(' exp ')' %prec UNARY
 			{ /* We could do more error checking here, but
 			     it doesn't seem worthwhile.  */
-			  write_exp_elt_opcode (UNOP_CAST);
-			  write_exp_elt_type ($3);
-			  write_exp_elt_opcode (UNOP_CAST); }
+			  write_exp_elt_opcode (UNOP_CAST_TYPE); }
 	;
 
 string_exp:
diff --git a/gdb/eval.c b/gdb/eval.c
index 3d43406..11c5290 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -2690,17 +2690,27 @@ evaluate_subexp_standard (struct type *expect_type,
 	arg1 = value_cast (type, arg1);
       return arg1;
 
+    case UNOP_CAST_TYPE:
+      arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+      type = value_type (arg1);
+      arg1 = evaluate_subexp (type, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+	goto nosideret;
+      if (type != value_type (arg1))
+	arg1 = value_cast (type, arg1);
+      return arg1;
+
     case UNOP_DYNAMIC_CAST:
-      (*pos) += 2;
-      type = exp->elts[pc + 1].type;
+      arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+      type = value_type (arg1);
       arg1 = evaluate_subexp (type, exp, pos, noside);
       if (noside == EVAL_SKIP)
 	goto nosideret;
       return value_dynamic_cast (type, arg1);
 
     case UNOP_REINTERPRET_CAST:
-      (*pos) += 2;
-      type = exp->elts[pc + 1].type;
+      arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+      type = value_type (arg1);
       arg1 = evaluate_subexp (type, exp, pos, noside);
       if (noside == EVAL_SKIP)
 	goto nosideret;
@@ -2717,6 +2727,18 @@ evaluate_subexp_standard (struct type *expect_type,
 	return value_at_lazy (exp->elts[pc + 1].type,
 			      value_as_address (arg1));
 
+    case UNOP_MEMVAL_TYPE:
+      arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+      type = value_type (arg1);
+      arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+      if (noside == EVAL_SKIP)
+	goto nosideret;
+      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+	return value_zero (exp->elts[pc + 1].type, lval_memory);
+      else
+	return value_at_lazy (exp->elts[pc + 1].type,
+			      value_as_address (arg1));
+
     case UNOP_MEMVAL_TLS:
       (*pos) += 3;
       arg1 = evaluate_subexp (expect_type, exp, pos, noside);
@@ -2919,6 +2941,17 @@ evaluate_subexp_for_address (struct expression *exp, int *pos,
       return value_cast (lookup_pointer_type (exp->elts[pc + 1].type),
 			 evaluate_subexp (NULL_TYPE, exp, pos, noside));
 
+    case UNOP_MEMVAL_TYPE:
+      {
+	struct type *type;
+
+	(*pos) += 1;
+	x = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+	type = value_type (x);
+	return value_cast (lookup_pointer_type (type),
+			   evaluate_subexp (NULL_TYPE, exp, pos, noside));
+      }
+
     case OP_VAR_VALUE:
       var = exp->elts[pc + 2].symbol;
 
@@ -3061,6 +3094,12 @@ evaluate_subexp_for_sizeof (struct expression *exp, int *pos)
       type = check_typedef (exp->elts[pc + 1].type);
       return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
 
+    case UNOP_MEMVAL_TYPE:
+      (*pos) += 1;
+      val = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+      type = check_typedef (value_type (val));
+      return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
+
     case OP_VAR_VALUE:
       (*pos) += 4;
       type = check_typedef (SYMBOL_TYPE (exp->elts[pc + 2].symbol));
diff --git a/gdb/expprint.c b/gdb/expprint.c
index 6915d43..c3f6697 100644
--- a/gdb/expprint.c
+++ b/gdb/expprint.c
@@ -429,13 +429,25 @@ print_subexp_standard (struct expression *exp, int *pos,
 	fputs_filtered (")", stream);
       return;
 
+    case UNOP_CAST_TYPE:
+      (*pos) += 1;
+      if ((int) prec > (int) PREC_PREFIX)
+	fputs_filtered ("(", stream);
+      fputs_filtered ("(", stream);
+      print_subexp (exp, pos, stream, PREC_PREFIX);
+      fputs_filtered (") ", stream);
+      print_subexp (exp, pos, stream, PREC_PREFIX);
+      if ((int) prec > (int) PREC_PREFIX)
+	fputs_filtered (")", stream);
+      return;
+
     case UNOP_DYNAMIC_CAST:
     case UNOP_REINTERPRET_CAST:
       fputs_filtered (opcode == UNOP_DYNAMIC_CAST ? "dynamic_cast"
 		      : "reinterpret_cast", stream);
       fputs_filtered ("<", stream);
-      (*pos) += 2;
-      type_print (exp->elts[pc + 1].type, "", stream, 0);
+      (*pos) += 1;
+      print_subexp (exp, pos, stream, PREC_PREFIX);
       fputs_filtered ("> (", stream);
       print_subexp (exp, pos, stream, PREC_PREFIX);
       fputs_filtered (")", stream);
@@ -471,6 +483,18 @@ print_subexp_standard (struct expression *exp, int *pos,
 	fputs_filtered (")", stream);
       return;
 
+    case UNOP_MEMVAL_TYPE:
+      (*pos) += 1;
+      if ((int) prec > (int) PREC_PREFIX)
+	fputs_filtered ("(", stream);
+      fputs_filtered ("{", stream);
+      print_subexp (exp, pos, stream, PREC_PREFIX);
+      fputs_filtered ("} ", stream);
+      print_subexp (exp, pos, stream, PREC_PREFIX);
+      if ((int) prec > (int) PREC_PREFIX)
+	fputs_filtered (")", stream);
+      return;
+
     case UNOP_MEMVAL_TLS:
       (*pos) += 3;
       if ((int) prec > (int) PREC_PREFIX)
@@ -910,10 +934,18 @@ dump_subexp_body_standard (struct expression *exp,
 	  elt = dump_subexp (exp, stream, elt);
       }
       break;
-    case UNOP_MEMVAL:
-    case UNOP_CAST:
     case UNOP_DYNAMIC_CAST:
     case UNOP_REINTERPRET_CAST:
+    case UNOP_CAST_TYPE:
+    case UNOP_MEMVAL_TYPE:
+      ++elt;
+      fprintf_filtered (stream, " (");
+      elt = dump_subexp (exp, stream, elt);
+      fprintf_filtered (stream, ")");
+      elt = dump_subexp (exp, stream, elt);
+      break;
+    case UNOP_MEMVAL:
+    case UNOP_CAST:
       fprintf_filtered (stream, "Type @");
       gdb_print_host_address (exp->elts[elt].type, stream);
       fprintf_filtered (stream, " (");
diff --git a/gdb/parse.c b/gdb/parse.c
index c372f40..a600994 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -911,10 +911,16 @@ operator_length_standard (const struct expression *expr, int endpos,
       oplen = 3;
       break;
 
-    case BINOP_VAL:
-    case UNOP_CAST:
+    case UNOP_CAST_TYPE:
     case UNOP_DYNAMIC_CAST:
     case UNOP_REINTERPRET_CAST:
+    case UNOP_MEMVAL_TYPE:
+      oplen = 1;
+      args = 2;
+      break;
+
+    case BINOP_VAL:
+    case UNOP_CAST:
     case UNOP_MEMVAL:
       oplen = 3;
       args = 1;
@@ -1608,8 +1614,6 @@ operator_check_standard (struct expression *exp, int pos,
     case OP_SCOPE:
     case OP_TYPE:
     case UNOP_CAST:
-    case UNOP_DYNAMIC_CAST:
-    case UNOP_REINTERPRET_CAST:
     case UNOP_MAX:
     case UNOP_MEMVAL:
     case UNOP_MIN:
diff --git a/gdb/stack.c b/gdb/stack.c
index 02e36ca..e1b7ecd 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -2268,7 +2268,8 @@ return_command (char *retval_exp, int from_tty)
 	return_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (thisfun));
       if (return_type == NULL)
       	{
-	  if (retval_expr->elts[0].opcode != UNOP_CAST)
+	  if (retval_expr->elts[0].opcode != UNOP_CAST
+	      && retval_expr->elts[0].opcode != UNOP_CAST_TYPE)
 	    error (_("Return value type not available for selected "
 		     "stack frame.\n"
 		     "Please use an explicit cast of the value to return."));
diff --git a/gdb/std-operator.def b/gdb/std-operator.def
index f2f650b..9c6a01b 100644
--- a/gdb/std-operator.def
+++ b/gdb/std-operator.def
@@ -216,6 +216,9 @@ OP (OP_ARRAY)
    It casts the value of the following subexpression.  */
 OP (UNOP_CAST)
 
+/* Like UNOP_CAST, but the type is a subexpression.  */
+OP (UNOP_CAST_TYPE)
+
 /* The C++ dynamic_cast operator.  */
 OP (UNOP_DYNAMIC_CAST)
 
@@ -235,6 +238,9 @@ OP (UNOP_MEMVAL)
    following subexpression from the TLS specified by `struct objfile'.  */
 OP (UNOP_MEMVAL_TLS)
 
+/* Like UNOP_MEMVAL, but the type is supplied as a subexpression.  */
+OP (UNOP_MEMVAL_TYPE)
+
 /* UNOP_... operate on one value from a following subexpression
    and replace it with a result.  They take no immediate arguments.  */
 
-- 
1.7.7.6


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]