| /* Evaluate expressions for GDB. | 
 |  | 
 |    Copyright (C) 1986-2024 Free Software Foundation, Inc. | 
 |  | 
 |    This file is part of GDB. | 
 |  | 
 |    This program is free software; you can redistribute it and/or modify | 
 |    it under the terms of the GNU General Public License as published by | 
 |    the Free Software Foundation; either version 3 of the License, or | 
 |    (at your option) any later version. | 
 |  | 
 |    This program is distributed in the hope that it will be useful, | 
 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |    GNU General Public License for more details. | 
 |  | 
 |    You should have received a copy of the GNU General Public License | 
 |    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ | 
 |  | 
 | #include "symtab.h" | 
 | #include "gdbtypes.h" | 
 | #include "value.h" | 
 | #include "expression.h" | 
 | #include "target.h" | 
 | #include "frame.h" | 
 | #include "gdbthread.h" | 
 | #include "language.h" | 
 | #include "cp-abi.h" | 
 | #include "infcall.h" | 
 | #include "objc-lang.h" | 
 | #include "block.h" | 
 | #include "parser-defs.h" | 
 | #include "cp-support.h" | 
 | #include "ui-out.h" | 
 | #include "regcache.h" | 
 | #include "user-regs.h" | 
 | #include "valprint.h" | 
 | #include "gdbsupport/gdb_obstack.h" | 
 | #include "objfiles.h" | 
 | #include "typeprint.h" | 
 | #include <ctype.h> | 
 | #include "expop.h" | 
 | #include "c-exp.h" | 
 | #include "inferior.h" | 
 |  | 
 |  | 
 | /* Parse the string EXP as a C expression, evaluate it, | 
 |    and return the result as a number.  */ | 
 |  | 
 | CORE_ADDR | 
 | parse_and_eval_address (const char *exp) | 
 | { | 
 |   expression_up expr = parse_expression (exp); | 
 |  | 
 |   return value_as_address (expr->evaluate ()); | 
 | } | 
 |  | 
 | /* Like parse_and_eval_address, but treats the value of the expression | 
 |    as an integer, not an address, returns a LONGEST, not a CORE_ADDR.  */ | 
 | LONGEST | 
 | parse_and_eval_long (const char *exp) | 
 | { | 
 |   expression_up expr = parse_expression (exp); | 
 |  | 
 |   return value_as_long (expr->evaluate ()); | 
 | } | 
 |  | 
 | struct value * | 
 | parse_and_eval (const char *exp, parser_flags flags) | 
 | { | 
 |   expression_up expr = parse_expression (exp, nullptr, flags); | 
 |  | 
 |   return expr->evaluate (); | 
 | } | 
 |  | 
 | /* Parse up to a comma (or to a closeparen) | 
 |    in the string EXPP as an expression, evaluate it, and return the value. | 
 |    EXPP is advanced to point to the comma.  */ | 
 |  | 
 | struct value * | 
 | parse_to_comma_and_eval (const char **expp) | 
 | { | 
 |   expression_up expr = parse_exp_1 (expp, 0, nullptr, | 
 | 				    PARSER_COMMA_TERMINATES); | 
 |  | 
 |   return expr->evaluate (); | 
 | } | 
 |  | 
 |  | 
 | /* See expression.h.  */ | 
 |  | 
 | bool | 
 | expression::uses_objfile (struct objfile *objfile) const | 
 | { | 
 |   gdb_assert (objfile->separate_debug_objfile_backlink == nullptr); | 
 |   return op->uses_objfile (objfile); | 
 | } | 
 |  | 
 | /* See expression.h.  */ | 
 |  | 
 | struct value * | 
 | expression::evaluate (struct type *expect_type, enum noside noside) | 
 | { | 
 |   std::optional<enable_thread_stack_temporaries> stack_temporaries; | 
 |   if (target_has_execution () && inferior_ptid != null_ptid | 
 |       && language_defn->la_language == language_cplus | 
 |       && !thread_stack_temporaries_enabled_p (inferior_thread ())) | 
 |     stack_temporaries.emplace (inferior_thread ()); | 
 |  | 
 |   struct value *retval = op->evaluate (expect_type, this, noside); | 
 |  | 
 |   if (stack_temporaries.has_value () | 
 |       && value_in_thread_stack_temporaries (retval, inferior_thread ())) | 
 |     retval = retval->non_lval (); | 
 |  | 
 |   return retval; | 
 | } | 
 |  | 
 | /* Find the current value of a watchpoint on EXP.  Return the value in | 
 |    *VALP and *RESULTP and the chain of intermediate and final values | 
 |    in *VAL_CHAIN.  RESULTP and VAL_CHAIN may be NULL if the caller does | 
 |    not need them. | 
 |  | 
 |    If PRESERVE_ERRORS is true, then exceptions are passed through. | 
 |    Otherwise, if PRESERVE_ERRORS is false, then if a memory error | 
 |    occurs while evaluating the expression, *RESULTP will be set to | 
 |    NULL.  *RESULTP may be a lazy value, if the result could not be | 
 |    read from memory.  It is used to determine whether a value is | 
 |    user-specified (we should watch the whole value) or intermediate | 
 |    (we should watch only the bit used to locate the final value). | 
 |  | 
 |    If the final value, or any intermediate value, could not be read | 
 |    from memory, *VALP will be set to NULL.  *VAL_CHAIN will still be | 
 |    set to any referenced values.  *VALP will never be a lazy value. | 
 |    This is the value which we store in struct breakpoint. | 
 |  | 
 |    If VAL_CHAIN is non-NULL, the values put into *VAL_CHAIN will be | 
 |    released from the value chain.  If VAL_CHAIN is NULL, all generated | 
 |    values will be left on the value chain.  */ | 
 |  | 
 | void | 
 | fetch_subexp_value (struct expression *exp, | 
 | 		    expr::operation *op, | 
 | 		    struct value **valp, struct value **resultp, | 
 | 		    std::vector<value_ref_ptr> *val_chain, | 
 | 		    bool preserve_errors) | 
 | { | 
 |   struct value *mark, *new_mark, *result; | 
 |  | 
 |   *valp = NULL; | 
 |   if (resultp) | 
 |     *resultp = NULL; | 
 |   if (val_chain) | 
 |     val_chain->clear (); | 
 |  | 
 |   /* Evaluate the expression.  */ | 
 |   mark = value_mark (); | 
 |   result = NULL; | 
 |  | 
 |   try | 
 |     { | 
 |       result = op->evaluate (nullptr, exp, EVAL_NORMAL); | 
 |     } | 
 |   catch (const gdb_exception &ex) | 
 |     { | 
 |       /* Ignore memory errors if we want watchpoints pointing at | 
 | 	 inaccessible memory to still be created; otherwise, throw the | 
 | 	 error to some higher catcher.  */ | 
 |       switch (ex.error) | 
 | 	{ | 
 | 	case MEMORY_ERROR: | 
 | 	  if (!preserve_errors) | 
 | 	    break; | 
 | 	  [[fallthrough]]; | 
 | 	default: | 
 | 	  throw; | 
 | 	  break; | 
 | 	} | 
 |     } | 
 |  | 
 |   new_mark = value_mark (); | 
 |   if (mark == new_mark) | 
 |     return; | 
 |   if (resultp) | 
 |     *resultp = result; | 
 |  | 
 |   /* Make sure it's not lazy, so that after the target stops again we | 
 |      have a non-lazy previous value to compare with.  */ | 
 |   if (result != NULL) | 
 |     { | 
 |       if (!result->lazy ()) | 
 | 	*valp = result; | 
 |       else | 
 | 	{ | 
 |  | 
 | 	  try | 
 | 	    { | 
 | 	      result->fetch_lazy (); | 
 | 	      *valp = result; | 
 | 	    } | 
 | 	  catch (const gdb_exception_error &except) | 
 | 	    { | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |   if (val_chain) | 
 |     { | 
 |       /* Return the chain of intermediate values.  We use this to | 
 | 	 decide which addresses to watch.  */ | 
 |       *val_chain = value_release_to_mark (mark); | 
 |     } | 
 | } | 
 |  | 
 | /* Promote value ARG1 as appropriate before performing a unary operation | 
 |    on this argument. | 
 |    If the result is not appropriate for any particular language then it | 
 |    needs to patch this function.  */ | 
 |  | 
 | void | 
 | unop_promote (const struct language_defn *language, struct gdbarch *gdbarch, | 
 | 	      struct value **arg1) | 
 | { | 
 |   struct type *type1; | 
 |  | 
 |   *arg1 = coerce_ref (*arg1); | 
 |   type1 = check_typedef ((*arg1)->type ()); | 
 |  | 
 |   if (is_integral_type (type1)) | 
 |     { | 
 |       switch (language->la_language) | 
 | 	{ | 
 | 	default: | 
 | 	  /* Perform integral promotion for ANSI C/C++. | 
 | 	     If not appropriate for any particular language | 
 | 	     it needs to modify this function.  */ | 
 | 	  { | 
 | 	    struct type *builtin_int = builtin_type (gdbarch)->builtin_int; | 
 |  | 
 | 	    if (type1->length () < builtin_int->length ()) | 
 | 	      *arg1 = value_cast (builtin_int, *arg1); | 
 | 	  } | 
 | 	  break; | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | /* Promote values ARG1 and ARG2 as appropriate before performing a binary | 
 |    operation on those two operands. | 
 |    If the result is not appropriate for any particular language then it | 
 |    needs to patch this function.  */ | 
 |  | 
 | void | 
 | binop_promote (const struct language_defn *language, struct gdbarch *gdbarch, | 
 | 	       struct value **arg1, struct value **arg2) | 
 | { | 
 |   struct type *promoted_type = NULL; | 
 |   struct type *type1; | 
 |   struct type *type2; | 
 |  | 
 |   *arg1 = coerce_ref (*arg1); | 
 |   *arg2 = coerce_ref (*arg2); | 
 |  | 
 |   type1 = check_typedef ((*arg1)->type ()); | 
 |   type2 = check_typedef ((*arg2)->type ()); | 
 |  | 
 |   if ((type1->code () != TYPE_CODE_FLT | 
 |        && type1->code () != TYPE_CODE_DECFLOAT | 
 |        && !is_integral_type (type1)) | 
 |       || (type2->code () != TYPE_CODE_FLT | 
 | 	  && type2->code () != TYPE_CODE_DECFLOAT | 
 | 	  && !is_integral_type (type2))) | 
 |     return; | 
 |  | 
 |   if (is_fixed_point_type (type1) || is_fixed_point_type (type2)) | 
 |     return; | 
 |  | 
 |   if (type1->code () == TYPE_CODE_DECFLOAT | 
 |       || type2->code () == TYPE_CODE_DECFLOAT) | 
 |     { | 
 |       /* No promotion required.  */ | 
 |     } | 
 |   else if (type1->code () == TYPE_CODE_FLT | 
 | 	   || type2->code () == TYPE_CODE_FLT) | 
 |     { | 
 |       switch (language->la_language) | 
 | 	{ | 
 | 	case language_c: | 
 | 	case language_cplus: | 
 | 	case language_asm: | 
 | 	case language_objc: | 
 | 	case language_opencl: | 
 | 	  /* No promotion required.  */ | 
 | 	  break; | 
 |  | 
 | 	default: | 
 | 	  /* For other languages the result type is unchanged from gdb | 
 | 	     version 6.7 for backward compatibility. | 
 | 	     If either arg was long double, make sure that value is also long | 
 | 	     double.  Otherwise use double.  */ | 
 | 	  if (type1->length () * 8 > gdbarch_double_bit (gdbarch) | 
 | 	      || type2->length () * 8 > gdbarch_double_bit (gdbarch)) | 
 | 	    promoted_type = builtin_type (gdbarch)->builtin_long_double; | 
 | 	  else | 
 | 	    promoted_type = builtin_type (gdbarch)->builtin_double; | 
 | 	  break; | 
 | 	} | 
 |     } | 
 |   else if (type1->code () == TYPE_CODE_BOOL | 
 | 	   && type2->code () == TYPE_CODE_BOOL) | 
 |     { | 
 |       /* No promotion required.  */ | 
 |     } | 
 |   else | 
 |     /* Integral operations here.  */ | 
 |     /* FIXME: Also mixed integral/booleans, with result an integer.  */ | 
 |     { | 
 |       const struct builtin_type *builtin = builtin_type (gdbarch); | 
 |       unsigned int promoted_len1 = type1->length (); | 
 |       unsigned int promoted_len2 = type2->length (); | 
 |       int is_unsigned1 = type1->is_unsigned (); | 
 |       int is_unsigned2 = type2->is_unsigned (); | 
 |       unsigned int result_len; | 
 |       int unsigned_operation; | 
 |  | 
 |       /* Determine type length and signedness after promotion for | 
 | 	 both operands.  */ | 
 |       if (promoted_len1 < builtin->builtin_int->length ()) | 
 | 	{ | 
 | 	  is_unsigned1 = 0; | 
 | 	  promoted_len1 = builtin->builtin_int->length (); | 
 | 	} | 
 |       if (promoted_len2 < builtin->builtin_int->length ()) | 
 | 	{ | 
 | 	  is_unsigned2 = 0; | 
 | 	  promoted_len2 = builtin->builtin_int->length (); | 
 | 	} | 
 |  | 
 |       if (promoted_len1 > promoted_len2) | 
 | 	{ | 
 | 	  unsigned_operation = is_unsigned1; | 
 | 	  result_len = promoted_len1; | 
 | 	} | 
 |       else if (promoted_len2 > promoted_len1) | 
 | 	{ | 
 | 	  unsigned_operation = is_unsigned2; | 
 | 	  result_len = promoted_len2; | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  unsigned_operation = is_unsigned1 || is_unsigned2; | 
 | 	  result_len = promoted_len1; | 
 | 	} | 
 |  | 
 |       switch (language->la_language) | 
 | 	{ | 
 | 	case language_opencl: | 
 | 	  if (result_len | 
 | 	      <= lookup_signed_typename (language, "int")->length()) | 
 | 	    { | 
 | 	      promoted_type = | 
 | 		(unsigned_operation | 
 | 		 ? lookup_unsigned_typename (language, "int") | 
 | 		 : lookup_signed_typename (language, "int")); | 
 | 	    } | 
 | 	  else if (result_len | 
 | 		   <= lookup_signed_typename (language, "long")->length()) | 
 | 	    { | 
 | 	      promoted_type = | 
 | 		(unsigned_operation | 
 | 		 ? lookup_unsigned_typename (language, "long") | 
 | 		 : lookup_signed_typename (language,"long")); | 
 | 	    } | 
 | 	  break; | 
 | 	default: | 
 | 	  if (result_len <= builtin->builtin_int->length ()) | 
 | 	    { | 
 | 	      promoted_type = (unsigned_operation | 
 | 			       ? builtin->builtin_unsigned_int | 
 | 			       : builtin->builtin_int); | 
 | 	    } | 
 | 	  else if (result_len <= builtin->builtin_long->length ()) | 
 | 	    { | 
 | 	      promoted_type = (unsigned_operation | 
 | 			       ? builtin->builtin_unsigned_long | 
 | 			       : builtin->builtin_long); | 
 | 	    } | 
 | 	  else if (result_len <= builtin->builtin_long_long->length ()) | 
 | 	    { | 
 | 	      promoted_type = (unsigned_operation | 
 | 			       ? builtin->builtin_unsigned_long_long | 
 | 			       : builtin->builtin_long_long); | 
 | 	    } | 
 | 	  else | 
 | 	    { | 
 | 	      promoted_type = (unsigned_operation | 
 | 			       ? builtin->builtin_uint128 | 
 | 			       : builtin->builtin_int128); | 
 | 	    } | 
 | 	  break; | 
 | 	} | 
 |     } | 
 |  | 
 |   if (promoted_type) | 
 |     { | 
 |       /* Promote both operands to common type.  */ | 
 |       *arg1 = value_cast (promoted_type, *arg1); | 
 |       *arg2 = value_cast (promoted_type, *arg2); | 
 |     } | 
 | } | 
 |  | 
 | static int | 
 | ptrmath_type_p (const struct language_defn *lang, struct type *type) | 
 | { | 
 |   type = check_typedef (type); | 
 |   if (TYPE_IS_REFERENCE (type)) | 
 |     type = type->target_type (); | 
 |  | 
 |   switch (type->code ()) | 
 |     { | 
 |     case TYPE_CODE_PTR: | 
 |     case TYPE_CODE_FUNC: | 
 |       return 1; | 
 |  | 
 |     case TYPE_CODE_ARRAY: | 
 |       return type->is_vector () ? 0 : lang->c_style_arrays_p (); | 
 |  | 
 |     default: | 
 |       return 0; | 
 |     } | 
 | } | 
 |  | 
 | /* Represents a fake method with the given parameter types.  This is | 
 |    used by the parser to construct a temporary "expected" type for | 
 |    method overload resolution.  FLAGS is used as instance flags of the | 
 |    new type, in order to be able to make the new type represent a | 
 |    const/volatile overload.  */ | 
 |  | 
 | class fake_method | 
 | { | 
 | public: | 
 |   fake_method (type_instance_flags flags, | 
 | 	       int num_types, struct type **param_types); | 
 |   ~fake_method (); | 
 |  | 
 |   /* The constructed type.  */ | 
 |   struct type *type () { return &m_type; } | 
 |  | 
 | private: | 
 |   struct type m_type {}; | 
 |   main_type m_main_type {}; | 
 | }; | 
 |  | 
 | fake_method::fake_method (type_instance_flags flags, | 
 | 			  int num_types, struct type **param_types) | 
 | { | 
 |   struct type *type = &m_type; | 
 |  | 
 |   TYPE_MAIN_TYPE (type) = &m_main_type; | 
 |   type->set_length (1); | 
 |   type->set_code (TYPE_CODE_METHOD); | 
 |   TYPE_CHAIN (type) = type; | 
 |   type->set_instance_flags (flags); | 
 |   if (num_types > 0) | 
 |     { | 
 |       if (param_types[num_types - 1] == NULL) | 
 | 	{ | 
 | 	  --num_types; | 
 | 	  type->set_has_varargs (true); | 
 | 	} | 
 |       else if (check_typedef (param_types[num_types - 1])->code () | 
 | 	       == TYPE_CODE_VOID) | 
 | 	{ | 
 | 	  --num_types; | 
 | 	  /* Caller should have ensured this.  */ | 
 | 	  gdb_assert (num_types == 0); | 
 | 	  type->set_is_prototyped (true); | 
 | 	} | 
 |     } | 
 |  | 
 |   /* We don't use TYPE_ZALLOC here to allocate space as TYPE is owned by | 
 |      neither an objfile nor a gdbarch.  As a result we must manually | 
 |      allocate memory for auxiliary fields, and free the memory ourselves | 
 |      when we are done with it.  */ | 
 |   type->set_num_fields (num_types); | 
 |   type->set_fields | 
 |     ((struct field *) xzalloc (sizeof (struct field) * num_types)); | 
 |  | 
 |   while (num_types-- > 0) | 
 |     type->field (num_types).set_type (param_types[num_types]); | 
 | } | 
 |  | 
 | fake_method::~fake_method () | 
 | { | 
 |   xfree (m_type.fields ()); | 
 | } | 
 |  | 
 | namespace expr | 
 | { | 
 |  | 
 | value * | 
 | type_instance_operation::evaluate (struct type *expect_type, | 
 | 				   struct expression *exp, | 
 | 				   enum noside noside) | 
 | { | 
 |   type_instance_flags flags = std::get<0> (m_storage); | 
 |   std::vector<type *> &types = std::get<1> (m_storage); | 
 |  | 
 |   fake_method fake_expect_type (flags, types.size (), types.data ()); | 
 |   return std::get<2> (m_storage)->evaluate (fake_expect_type.type (), | 
 | 					    exp, noside); | 
 | } | 
 |  | 
 | } | 
 |  | 
 | /* Helper for evaluating an OP_VAR_VALUE.  */ | 
 |  | 
 | value * | 
 | evaluate_var_value (enum noside noside, const block *blk, symbol *var) | 
 | { | 
 |   /* JYG: We used to just return value::zero of the symbol type if | 
 |      we're asked to avoid side effects.  Otherwise we return | 
 |      value_of_variable (...).  However I'm not sure if | 
 |      value_of_variable () has any side effect.  We need a full value | 
 |      object returned here for whatis_exp () to call evaluate_type () | 
 |      and then pass the full value to value_rtti_target_type () if we | 
 |      are dealing with a pointer or reference to a base class and print | 
 |      object is on.  */ | 
 |  | 
 |   struct value *ret = NULL; | 
 |  | 
 |   try | 
 |     { | 
 |       ret = value_of_variable (var, blk); | 
 |     } | 
 |  | 
 |   catch (const gdb_exception_error &except) | 
 |     { | 
 |       if (noside != EVAL_AVOID_SIDE_EFFECTS) | 
 | 	throw; | 
 |  | 
 |       ret = value::zero (var->type (), not_lval); | 
 |     } | 
 |  | 
 |   return ret; | 
 | } | 
 |  | 
 | namespace expr | 
 |  | 
 | { | 
 |  | 
 | value * | 
 | var_value_operation::evaluate (struct type *expect_type, | 
 | 			       struct expression *exp, | 
 | 			       enum noside noside) | 
 | { | 
 |   symbol *var = std::get<0> (m_storage).symbol; | 
 |   if (var->type ()->code () == TYPE_CODE_ERROR) | 
 |     error_unknown_type (var->print_name ()); | 
 |   return evaluate_var_value (noside, std::get<0> (m_storage).block, var); | 
 | } | 
 |  | 
 | } /* namespace expr */ | 
 |  | 
 | /* Helper for evaluating an OP_VAR_MSYM_VALUE.  */ | 
 |  | 
 | value * | 
 | evaluate_var_msym_value (enum noside noside, | 
 | 			 struct objfile *objfile, minimal_symbol *msymbol) | 
 | { | 
 |   CORE_ADDR address; | 
 |   type *the_type = find_minsym_type_and_address (msymbol, objfile, &address); | 
 |  | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS && !the_type->is_gnu_ifunc ()) | 
 |     return value::zero (the_type, not_lval); | 
 |   else | 
 |     return value_at_lazy (the_type, address); | 
 | } | 
 |  | 
 | /* See expression.h.  */ | 
 |  | 
 | value * | 
 | evaluate_subexp_do_call (expression *exp, enum noside noside, | 
 | 			 value *callee, | 
 | 			 gdb::array_view<value *> argvec, | 
 | 			 const char *function_name, | 
 | 			 type *default_return_type) | 
 | { | 
 |   if (callee == NULL) | 
 |     error (_("Cannot evaluate function -- may be inlined")); | 
 |  | 
 |   type *ftype = callee->type (); | 
 |  | 
 |   /* If the callee is a struct, there might be a user-defined function call | 
 |      operator that should be used instead.  */ | 
 |   std::vector<value *> vals; | 
 |   if (overload_resolution | 
 |       && exp->language_defn->la_language == language_cplus | 
 |       && check_typedef (ftype)->code () == TYPE_CODE_STRUCT) | 
 |     { | 
 |       /* Include space for the `this' pointer at the start.  */ | 
 |       vals.resize (argvec.size () + 1); | 
 |  | 
 |       vals[0] = value_addr (callee); | 
 |       for (int i = 0; i < argvec.size (); ++i) | 
 | 	vals[i + 1] = argvec[i]; | 
 |  | 
 |       int static_memfuncp; | 
 |       find_overload_match (vals, "operator()", METHOD, &vals[0], nullptr, | 
 | 			   &callee, nullptr, &static_memfuncp, 0, noside); | 
 |       if (!static_memfuncp) | 
 | 	argvec = vals; | 
 |  | 
 |       ftype = callee->type (); | 
 |     } | 
 |  | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     { | 
 |       /* If the return type doesn't look like a function type, | 
 | 	 call an error.  This can happen if somebody tries to turn | 
 | 	 a variable into a function call.  */ | 
 |  | 
 |       if (ftype->code () == TYPE_CODE_INTERNAL_FUNCTION) | 
 | 	{ | 
 | 	  /* The call to call_internal_function below handles noside.  */ | 
 | 	} | 
 |       else if (ftype->code () == TYPE_CODE_XMETHOD) | 
 | 	{ | 
 | 	  type *return_type = callee->result_type_of_xmethod (argvec); | 
 |  | 
 | 	  if (return_type == NULL) | 
 | 	    error (_("Xmethod is missing return type.")); | 
 | 	  return value::zero (return_type, not_lval); | 
 | 	} | 
 |       else if (ftype->code () == TYPE_CODE_FUNC | 
 | 	       || ftype->code () == TYPE_CODE_METHOD) | 
 | 	{ | 
 | 	  if (ftype->is_gnu_ifunc ()) | 
 | 	    { | 
 | 	      CORE_ADDR address = callee->address (); | 
 | 	      type *resolved_type = find_gnu_ifunc_target_type (address); | 
 |  | 
 | 	      if (resolved_type != NULL) | 
 | 		ftype = resolved_type; | 
 | 	    } | 
 |  | 
 | 	  type *return_type = ftype->target_type (); | 
 |  | 
 | 	  if (return_type == NULL) | 
 | 	    return_type = default_return_type; | 
 |  | 
 | 	  if (return_type == NULL) | 
 | 	    error_call_unknown_return_type (function_name); | 
 |  | 
 | 	  return value::allocate (return_type); | 
 | 	} | 
 |       else | 
 | 	error (_("Expression of type other than " | 
 | 		 "\"Function returning ...\" used as function")); | 
 |     } | 
 |   switch (callee->type ()->code ()) | 
 |     { | 
 |     case TYPE_CODE_INTERNAL_FUNCTION: | 
 |       return call_internal_function (exp->gdbarch, exp->language_defn, | 
 | 				     callee, argvec.size (), argvec.data (), | 
 | 				     noside); | 
 |     case TYPE_CODE_XMETHOD: | 
 |       return callee->call_xmethod (argvec); | 
 |     default: | 
 |       return call_function_by_hand (callee, default_return_type, argvec); | 
 |     } | 
 | } | 
 |  | 
 | namespace expr | 
 | { | 
 |  | 
 | value * | 
 | operation::evaluate_funcall (struct type *expect_type, | 
 | 			     struct expression *exp, | 
 | 			     enum noside noside, | 
 | 			     const char *function_name, | 
 | 			     const std::vector<operation_up> &args) | 
 | { | 
 |   std::vector<value *> vals (args.size ()); | 
 |  | 
 |   value *callee = evaluate_with_coercion (exp, noside); | 
 |   struct type *type = callee->type (); | 
 |   if (type->code () == TYPE_CODE_PTR) | 
 |     type = type->target_type (); | 
 |   /* If type is a struct, num_fields would refer to the number of | 
 |      members in the type, not the number of arguments.  */ | 
 |   bool type_has_arguments | 
 |     = type->code () == TYPE_CODE_FUNC || type->code () == TYPE_CODE_METHOD; | 
 |   for (int i = 0; i < args.size (); ++i) | 
 |     { | 
 |       if (type_has_arguments && i < type->num_fields ()) | 
 | 	vals[i] = args[i]->evaluate (type->field (i).type (), exp, noside); | 
 |       else | 
 | 	vals[i] = args[i]->evaluate_with_coercion (exp, noside); | 
 |     } | 
 |  | 
 |   return evaluate_subexp_do_call (exp, noside, callee, vals, | 
 | 				  function_name, expect_type); | 
 | } | 
 |  | 
 | value * | 
 | var_value_operation::evaluate_funcall (struct type *expect_type, | 
 | 				       struct expression *exp, | 
 | 				       enum noside noside, | 
 | 				       const std::vector<operation_up> &args) | 
 | { | 
 |   if (!overload_resolution | 
 |       || exp->language_defn->la_language != language_cplus) | 
 |     return operation::evaluate_funcall (expect_type, exp, noside, args); | 
 |  | 
 |   std::vector<value *> argvec (args.size ()); | 
 |   for (int i = 0; i < args.size (); ++i) | 
 |     argvec[i] = args[i]->evaluate_with_coercion (exp, noside); | 
 |  | 
 |   struct symbol *symp; | 
 |   find_overload_match (argvec, NULL, NON_METHOD, | 
 | 		       NULL, std::get<0> (m_storage).symbol, | 
 | 		       NULL, &symp, NULL, 0, noside); | 
 |  | 
 |   if (symp->type ()->code () == TYPE_CODE_ERROR) | 
 |     error_unknown_type (symp->print_name ()); | 
 |   value *callee = evaluate_var_value (noside, std::get<0> (m_storage).block, | 
 | 				      symp); | 
 |  | 
 |   return evaluate_subexp_do_call (exp, noside, callee, argvec, | 
 | 				  nullptr, expect_type); | 
 | } | 
 |  | 
 | value * | 
 | scope_operation::evaluate_funcall (struct type *expect_type, | 
 | 				   struct expression *exp, | 
 | 				   enum noside noside, | 
 | 				   const std::vector<operation_up> &args) | 
 | { | 
 |   if (!overload_resolution | 
 |       || exp->language_defn->la_language != language_cplus) | 
 |     return operation::evaluate_funcall (expect_type, exp, noside, args); | 
 |  | 
 |   /* Unpack it locally so we can properly handle overload | 
 |      resolution.  */ | 
 |   const std::string &name = std::get<1> (m_storage); | 
 |   struct type *type = std::get<0> (m_storage); | 
 |  | 
 |   symbol *function = NULL; | 
 |   const char *function_name = NULL; | 
 |   std::vector<value *> argvec (1 + args.size ()); | 
 |   if (type->code () == TYPE_CODE_NAMESPACE) | 
 |     { | 
 |       function = cp_lookup_symbol_namespace (type->name (), | 
 | 					     name.c_str (), | 
 | 					     get_selected_block (0), | 
 | 					     SEARCH_FUNCTION_DOMAIN).symbol; | 
 |       if (function == NULL) | 
 | 	error (_("No symbol \"%s\" in namespace \"%s\"."), | 
 | 	       name.c_str (), type->name ()); | 
 |     } | 
 |   else | 
 |     { | 
 |       gdb_assert (type->code () == TYPE_CODE_STRUCT | 
 | 		  || type->code () == TYPE_CODE_UNION); | 
 |       function_name = name.c_str (); | 
 |  | 
 |       /* We need a properly typed value for method lookup.  */ | 
 |       argvec[0] = value::zero (type, lval_memory); | 
 |     } | 
 |  | 
 |   for (int i = 0; i < args.size (); ++i) | 
 |     argvec[i + 1] = args[i]->evaluate_with_coercion (exp, noside); | 
 |   gdb::array_view<value *> arg_view = argvec; | 
 |  | 
 |   value *callee = nullptr; | 
 |   if (function_name != nullptr) | 
 |     { | 
 |       int static_memfuncp; | 
 |  | 
 |       find_overload_match (arg_view, function_name, METHOD, | 
 | 			   &argvec[0], nullptr, &callee, nullptr, | 
 | 			   &static_memfuncp, 0, noside); | 
 |       if (!static_memfuncp) | 
 | 	{ | 
 | 	  /* For the time being, we don't handle this.  */ | 
 | 	  error (_("Call to overloaded function %s requires " | 
 | 		   "`this' pointer"), | 
 | 		 function_name); | 
 | 	} | 
 |  | 
 |       arg_view = arg_view.slice (1); | 
 |     } | 
 |   else | 
 |     { | 
 |       symbol *symp; | 
 |       arg_view = arg_view.slice (1); | 
 |       find_overload_match (arg_view, nullptr, | 
 | 			   NON_METHOD, nullptr, function, | 
 | 			   nullptr, &symp, nullptr, 1, noside); | 
 |       callee = value_of_variable (symp, get_selected_block (0)); | 
 |     } | 
 |  | 
 |   return evaluate_subexp_do_call (exp, noside, callee, arg_view, | 
 | 				  nullptr, expect_type); | 
 | } | 
 |  | 
 | value * | 
 | structop_member_base::evaluate_funcall (struct type *expect_type, | 
 | 					struct expression *exp, | 
 | 					enum noside noside, | 
 | 					const std::vector<operation_up> &args) | 
 | { | 
 |   /* First, evaluate the structure into lhs.  */ | 
 |   value *lhs; | 
 |   if (opcode () == STRUCTOP_MEMBER) | 
 |     lhs = std::get<0> (m_storage)->evaluate_for_address (exp, noside); | 
 |   else | 
 |     lhs = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | 
 |  | 
 |   std::vector<value *> vals (args.size () + 1); | 
 |   gdb::array_view<value *> val_view = vals; | 
 |   /* If the function is a virtual function, then the aggregate | 
 |      value (providing the structure) plays its part by providing | 
 |      the vtable.  Otherwise, it is just along for the ride: call | 
 |      the function directly.  */ | 
 |   value *rhs = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | 
 |   value *callee; | 
 |  | 
 |   type *a1_type = check_typedef (rhs->type ()); | 
 |   if (a1_type->code () == TYPE_CODE_METHODPTR) | 
 |     { | 
 |       if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 | 	callee = value::zero (a1_type->target_type (), not_lval); | 
 |       else | 
 | 	callee = cplus_method_ptr_to_value (&lhs, rhs); | 
 |  | 
 |       vals[0] = lhs; | 
 |     } | 
 |   else if (a1_type->code () == TYPE_CODE_MEMBERPTR) | 
 |     { | 
 |       struct type *type_ptr | 
 | 	= lookup_pointer_type (TYPE_SELF_TYPE (a1_type)); | 
 |       struct type *target_type_ptr | 
 | 	= lookup_pointer_type (a1_type->target_type ()); | 
 |  | 
 |       /* Now, convert this value to an address.  */ | 
 |       lhs = value_cast (type_ptr, lhs); | 
 |  | 
 |       long mem_offset = value_as_long (rhs); | 
 |  | 
 |       callee = value_from_pointer (target_type_ptr, | 
 | 				   value_as_long (lhs) + mem_offset); | 
 |       callee = value_ind (callee); | 
 |  | 
 |       val_view = val_view.slice (1); | 
 |     } | 
 |   else | 
 |     error (_("Non-pointer-to-member value used in pointer-to-member " | 
 | 	     "construct")); | 
 |  | 
 |   for (int i = 0; i < args.size (); ++i) | 
 |     vals[i + 1] = args[i]->evaluate_with_coercion (exp, noside); | 
 |  | 
 |   return evaluate_subexp_do_call (exp, noside, callee, val_view, | 
 | 				  nullptr, expect_type); | 
 |  | 
 | } | 
 |  | 
 | value * | 
 | structop_base_operation::evaluate_funcall | 
 |      (struct type *expect_type, struct expression *exp, enum noside noside, | 
 |       const std::vector<operation_up> &args) | 
 | { | 
 |   /* Allocate space for the function call arguments, Including space for a | 
 |      `this' pointer at the start.  */ | 
 |   std::vector<value *> vals (args.size () + 1); | 
 |   /* First, evaluate the structure into vals[0].  */ | 
 |   enum exp_opcode op = opcode (); | 
 |   if (op == STRUCTOP_STRUCT) | 
 |     { | 
 |       /* If v is a variable in a register, and the user types | 
 | 	 v.method (), this will produce an error, because v has no | 
 | 	 address. | 
 |  | 
 | 	 A possible way around this would be to allocate a copy of | 
 | 	 the variable on the stack, copy in the contents, call the | 
 | 	 function, and copy out the contents.  I.e. convert this | 
 | 	 from call by reference to call by copy-return (or | 
 | 	 whatever it's called).  However, this does not work | 
 | 	 because it is not the same: the method being called could | 
 | 	 stash a copy of the address, and then future uses through | 
 | 	 that address (after the method returns) would be expected | 
 | 	 to use the variable itself, not some copy of it.  */ | 
 |       vals[0] = std::get<0> (m_storage)->evaluate_for_address (exp, noside); | 
 |     } | 
 |   else | 
 |     { | 
 |       vals[0] = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | 
 |       /* Check to see if the operator '->' has been overloaded. | 
 | 	 If the operator has been overloaded replace vals[0] with the | 
 | 	 value returned by the custom operator and continue | 
 | 	 evaluation.  */ | 
 |       while (unop_user_defined_p (op, vals[0])) | 
 | 	{ | 
 | 	  struct value *value = nullptr; | 
 | 	  try | 
 | 	    { | 
 | 	      value = value_x_unop (vals[0], op, noside); | 
 | 	    } | 
 | 	  catch (const gdb_exception_error &except) | 
 | 	    { | 
 | 	      if (except.error == NOT_FOUND_ERROR) | 
 | 		break; | 
 | 	      else | 
 | 		throw; | 
 | 	    } | 
 |  | 
 | 	  vals[0] = value; | 
 | 	} | 
 |     } | 
 |  | 
 |   /* Evaluate the arguments.  The '+ 1' here is to allow for the `this' | 
 |      pointer we placed into vals[0].  */ | 
 |   for (int i = 0; i < args.size (); ++i) | 
 |     vals[i + 1] = args[i]->evaluate_with_coercion (exp, noside); | 
 |  | 
 |   /* The array view includes the `this' pointer.  */ | 
 |   gdb::array_view<value *> arg_view (vals); | 
 |  | 
 |   int static_memfuncp; | 
 |   value *callee; | 
 |   const char *tstr = std::get<1> (m_storage).c_str (); | 
 |   if (overload_resolution | 
 |       && exp->language_defn->la_language == language_cplus) | 
 |     { | 
 |       /* Language is C++, do some overload resolution before | 
 | 	 evaluation.  */ | 
 |       value *val0 = vals[0]; | 
 |       find_overload_match (arg_view, tstr, METHOD, | 
 | 			   &val0, nullptr, &callee, nullptr, | 
 | 			   &static_memfuncp, 0, noside); | 
 |       vals[0] = val0; | 
 |     } | 
 |   else | 
 |     /* Non-C++ case -- or no overload resolution.  */ | 
 |     { | 
 |       struct value *temp = vals[0]; | 
 |  | 
 |       callee = value_struct_elt (&temp, arg_view, tstr, | 
 | 				 &static_memfuncp, | 
 | 				 op == STRUCTOP_STRUCT | 
 | 				 ? "structure" : "structure pointer"); | 
 |       /* value_struct_elt updates temp with the correct value of the | 
 | 	 ``this'' pointer if necessary, so modify it to reflect any | 
 | 	 ``this'' changes.  */ | 
 |       vals[0] = value_from_longest (lookup_pointer_type (temp->type ()), | 
 | 				    temp->address () | 
 | 				    + temp->embedded_offset ()); | 
 |     } | 
 |  | 
 |   /* Take out `this' if needed.  */ | 
 |   if (static_memfuncp) | 
 |     arg_view = arg_view.slice (1); | 
 |  | 
 |   return evaluate_subexp_do_call (exp, noside, callee, arg_view, | 
 | 				  nullptr, expect_type); | 
 | } | 
 |  | 
 | /* Helper for structop_base_operation::complete which recursively adds | 
 |    field and method names from TYPE, a struct or union type, to the | 
 |    OUTPUT list.  PREFIX is prepended to each result.  */ | 
 |  | 
 | static void | 
 | add_struct_fields (struct type *type, completion_list &output, | 
 | 		   const char *fieldname, int namelen, const char *prefix) | 
 | { | 
 |   int i; | 
 |   int computed_type_name = 0; | 
 |   const char *type_name = NULL; | 
 |  | 
 |   type = check_typedef (type); | 
 |   for (i = 0; i < type->num_fields (); ++i) | 
 |     { | 
 |       if (i < TYPE_N_BASECLASSES (type)) | 
 | 	add_struct_fields (TYPE_BASECLASS (type, i), | 
 | 			   output, fieldname, namelen, prefix); | 
 |       else if (type->field (i).name ()) | 
 | 	{ | 
 | 	  if (type->field (i).name ()[0] != '\0') | 
 | 	    { | 
 | 	      if (! strncmp (type->field (i).name (), | 
 | 			     fieldname, namelen)) | 
 | 		output.emplace_back (concat (prefix, type->field (i).name (), | 
 | 					     nullptr)); | 
 | 	    } | 
 | 	  else if (type->field (i).type ()->code () == TYPE_CODE_UNION) | 
 | 	    { | 
 | 	      /* Recurse into anonymous unions.  */ | 
 | 	      add_struct_fields (type->field (i).type (), | 
 | 				 output, fieldname, namelen, prefix); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |   for (i = TYPE_NFN_FIELDS (type) - 1; i >= 0; --i) | 
 |     { | 
 |       const char *name = TYPE_FN_FIELDLIST_NAME (type, i); | 
 |  | 
 |       if (name && ! strncmp (name, fieldname, namelen)) | 
 | 	{ | 
 | 	  if (!computed_type_name) | 
 | 	    { | 
 | 	      type_name = type->name (); | 
 | 	      computed_type_name = 1; | 
 | 	    } | 
 | 	  /* Omit constructors from the completion list.  */ | 
 | 	  if (!type_name || strcmp (type_name, name)) | 
 | 	    output.emplace_back (concat (prefix, name, nullptr)); | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | /* See expop.h.  */ | 
 |  | 
 | bool | 
 | structop_base_operation::complete (struct expression *exp, | 
 | 				   completion_tracker &tracker, | 
 | 				   const char *prefix) | 
 | { | 
 |   const std::string &fieldname = std::get<1> (m_storage); | 
 |  | 
 |   value *lhs = std::get<0> (m_storage)->evaluate (nullptr, exp, | 
 | 						  EVAL_AVOID_SIDE_EFFECTS); | 
 |   struct type *type = lhs->type (); | 
 |   for (;;) | 
 |     { | 
 |       type = check_typedef (type); | 
 |       if (!type->is_pointer_or_reference ()) | 
 | 	break; | 
 |       type = type->target_type (); | 
 |     } | 
 |  | 
 |   if (type->code () == TYPE_CODE_UNION | 
 |       || type->code () == TYPE_CODE_STRUCT) | 
 |     { | 
 |       completion_list result; | 
 |  | 
 |       add_struct_fields (type, result, fieldname.c_str (), | 
 | 			 fieldname.length (), prefix); | 
 |       tracker.add_completions (std::move (result)); | 
 |       return true; | 
 |     } | 
 |  | 
 |   return false; | 
 | } | 
 |  | 
 | } /* namespace expr */ | 
 |  | 
 | /* Return true if type is integral or reference to integral */ | 
 |  | 
 | static bool | 
 | is_integral_or_integral_reference (struct type *type) | 
 | { | 
 |   if (is_integral_type (type)) | 
 |     return true; | 
 |  | 
 |   type = check_typedef (type); | 
 |   return (type != nullptr | 
 | 	  && TYPE_IS_REFERENCE (type) | 
 | 	  && is_integral_type (type->target_type ())); | 
 | } | 
 |  | 
 | /* Helper function that implements the body of OP_SCOPE.  */ | 
 |  | 
 | struct value * | 
 | eval_op_scope (struct type *expect_type, struct expression *exp, | 
 | 	       enum noside noside, | 
 | 	       struct type *type, const char *string) | 
 | { | 
 |   struct value *arg1 = value_aggregate_elt (type, string, expect_type, | 
 | 					    0, noside); | 
 |   if (arg1 == NULL) | 
 |     error (_("There is no field named %s"), string); | 
 |   return arg1; | 
 | } | 
 |  | 
 | /* Helper function that implements the body of OP_VAR_ENTRY_VALUE.  */ | 
 |  | 
 | struct value * | 
 | eval_op_var_entry_value (struct type *expect_type, struct expression *exp, | 
 | 			 enum noside noside, symbol *sym) | 
 | { | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     return value::zero (sym->type (), not_lval); | 
 |  | 
 |   const symbol_computed_ops *computed_ops = sym->computed_ops (); | 
 |   if (computed_ops == nullptr | 
 |       || computed_ops->read_variable_at_entry == nullptr) | 
 |     error (_("Symbol \"%s\" does not have any specific entry value"), | 
 | 	   sym->print_name ()); | 
 |  | 
 |   frame_info_ptr frame = get_selected_frame (NULL); | 
 |   return computed_ops->read_variable_at_entry (sym, frame); | 
 | } | 
 |  | 
 | /* Helper function that implements the body of OP_VAR_MSYM_VALUE.  */ | 
 |  | 
 | struct value * | 
 | eval_op_var_msym_value (struct type *expect_type, struct expression *exp, | 
 | 			enum noside noside, bool outermost_p, | 
 | 			bound_minimal_symbol msymbol) | 
 | { | 
 |   value *val = evaluate_var_msym_value (noside, msymbol.objfile, | 
 | 					msymbol.minsym); | 
 |  | 
 |   struct type *type = val->type (); | 
 |   if (type->code () == TYPE_CODE_ERROR | 
 |       && (noside != EVAL_AVOID_SIDE_EFFECTS || !outermost_p)) | 
 |     error_unknown_type (msymbol.minsym->print_name ()); | 
 |   return val; | 
 | } | 
 |  | 
 | /* Helper function that implements the body of OP_FUNC_STATIC_VAR.  */ | 
 |  | 
 | struct value * | 
 | eval_op_func_static_var (struct type *expect_type, struct expression *exp, | 
 | 			 enum noside noside, | 
 | 			 value *func, const char *var) | 
 | { | 
 |   CORE_ADDR addr = func->address (); | 
 |   const block *blk = block_for_pc (addr); | 
 |   struct block_symbol sym = lookup_symbol (var, blk, SEARCH_VAR_DOMAIN, | 
 | 					   nullptr); | 
 |   if (sym.symbol == NULL) | 
 |     error (_("No symbol \"%s\" in specified context."), var); | 
 |   return evaluate_var_value (noside, sym.block, sym.symbol); | 
 | } | 
 |  | 
 | /* Helper function that implements the body of OP_REGISTER.  */ | 
 |  | 
 | struct value * | 
 | eval_op_register (struct type *expect_type, struct expression *exp, | 
 | 		  enum noside noside, const char *name) | 
 | { | 
 |   int regno; | 
 |   struct value *val; | 
 |  | 
 |   regno = user_reg_map_name_to_regnum (exp->gdbarch, | 
 | 				       name, strlen (name)); | 
 |   if (regno == -1) | 
 |     error (_("Register $%s not available."), name); | 
 |  | 
 |   /* In EVAL_AVOID_SIDE_EFFECTS mode, we only need to return | 
 |      a value with the appropriate register type.  Unfortunately, | 
 |      we don't have easy access to the type of user registers. | 
 |      So for these registers, we fetch the register value regardless | 
 |      of the evaluation mode.  */ | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS | 
 |       && regno < gdbarch_num_cooked_regs (exp->gdbarch)) | 
 |     val = value::zero (register_type (exp->gdbarch, regno), not_lval); | 
 |   else | 
 |     val = value_of_register | 
 |       (regno, get_next_frame_sentinel_okay (get_selected_frame ())); | 
 |   if (val == NULL) | 
 |     error (_("Value of register %s not available."), name); | 
 |   else | 
 |     return val; | 
 | } | 
 |  | 
 | namespace expr | 
 | { | 
 |  | 
 | value * | 
 | string_operation::evaluate (struct type *expect_type, | 
 | 			    struct expression *exp, | 
 | 			    enum noside noside) | 
 | { | 
 |   const std::string &str = std::get<0> (m_storage); | 
 |   struct type *type = language_string_char_type (exp->language_defn, | 
 | 						 exp->gdbarch); | 
 |   return value_string (str.c_str (), str.size (), type); | 
 | } | 
 |  | 
 | struct value * | 
 | ternop_slice_operation::evaluate (struct type *expect_type, | 
 | 				  struct expression *exp, | 
 | 				  enum noside noside) | 
 | { | 
 |   struct value *array | 
 |     = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | 
 |   struct value *low | 
 |     = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | 
 |   struct value *upper | 
 |     = std::get<2> (m_storage)->evaluate (nullptr, exp, noside); | 
 |  | 
 |   int lowbound = value_as_long (low); | 
 |   int upperbound = value_as_long (upper); | 
 |   return value_slice (array, lowbound, upperbound - lowbound + 1); | 
 | } | 
 |  | 
 | } /* namespace expr */ | 
 |  | 
 | /* Helper function that implements the body of OP_OBJC_SELECTOR.  */ | 
 |  | 
 | struct value * | 
 | eval_op_objc_selector (struct type *expect_type, struct expression *exp, | 
 | 		       enum noside noside, | 
 | 		       const char *sel) | 
 | { | 
 |   struct type *selector_type = builtin_type (exp->gdbarch)->builtin_data_ptr; | 
 |   return value_from_longest (selector_type, | 
 | 			     lookup_child_selector (exp->gdbarch, sel)); | 
 | } | 
 |  | 
 | /* A helper function for STRUCTOP_STRUCT.  */ | 
 |  | 
 | struct value * | 
 | eval_op_structop_struct (struct type *expect_type, struct expression *exp, | 
 | 			 enum noside noside, | 
 | 			 struct value *arg1, const char *string) | 
 | { | 
 |   struct value *arg3 = value_struct_elt (&arg1, {}, string, | 
 | 					 NULL, "structure"); | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     arg3 = value::zero (arg3->type (), arg3->lval ()); | 
 |   return arg3; | 
 | } | 
 |  | 
 | /* A helper function for STRUCTOP_PTR.  */ | 
 |  | 
 | struct value * | 
 | eval_op_structop_ptr (struct type *expect_type, struct expression *exp, | 
 | 		      enum noside noside, | 
 | 		      struct value *arg1, const char *string) | 
 | { | 
 |   /* Check to see if operator '->' has been overloaded.  If so replace | 
 |      arg1 with the value returned by evaluating operator->().  */ | 
 |   while (unop_user_defined_p (STRUCTOP_PTR, arg1)) | 
 |     { | 
 |       struct value *value = NULL; | 
 |       try | 
 | 	{ | 
 | 	  value = value_x_unop (arg1, STRUCTOP_PTR, noside); | 
 | 	} | 
 |  | 
 |       catch (const gdb_exception_error &except) | 
 | 	{ | 
 | 	  if (except.error == NOT_FOUND_ERROR) | 
 | 	    break; | 
 | 	  else | 
 | 	    throw; | 
 | 	} | 
 |  | 
 |       arg1 = value; | 
 |     } | 
 |  | 
 |   /* JYG: if print object is on we need to replace the base type | 
 |      with rtti type in order to continue on with successful | 
 |      lookup of member / method only available in the rtti type.  */ | 
 |   { | 
 |     struct type *arg_type = arg1->type (); | 
 |     struct type *real_type; | 
 |     int full, using_enc; | 
 |     LONGEST top; | 
 |     struct value_print_options opts; | 
 |  | 
 |     get_user_print_options (&opts); | 
 |     if (opts.objectprint && arg_type->target_type () | 
 | 	&& (arg_type->target_type ()->code () == TYPE_CODE_STRUCT)) | 
 |       { | 
 | 	real_type = value_rtti_indirect_type (arg1, &full, &top, | 
 | 					      &using_enc); | 
 | 	if (real_type) | 
 | 	  arg1 = value_cast (real_type, arg1); | 
 |       } | 
 |   } | 
 |  | 
 |   struct value *arg3 = value_struct_elt (&arg1, {}, string, | 
 | 					 NULL, "structure pointer"); | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     arg3 = value::zero (arg3->type (), arg3->lval ()); | 
 |   return arg3; | 
 | } | 
 |  | 
 | /* A helper function for STRUCTOP_MEMBER.  */ | 
 |  | 
 | struct value * | 
 | eval_op_member (struct type *expect_type, struct expression *exp, | 
 | 		enum noside noside, | 
 | 		struct value *arg1, struct value *arg2) | 
 | { | 
 |   long mem_offset; | 
 |  | 
 |   struct value *arg3; | 
 |   struct type *type = check_typedef (arg2->type ()); | 
 |   switch (type->code ()) | 
 |     { | 
 |     case TYPE_CODE_METHODPTR: | 
 |       if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 | 	return value::zero (type->target_type (), not_lval); | 
 |       else | 
 | 	{ | 
 | 	  arg2 = cplus_method_ptr_to_value (&arg1, arg2); | 
 | 	  gdb_assert (arg2->type ()->code () == TYPE_CODE_PTR); | 
 | 	  return value_ind (arg2); | 
 | 	} | 
 |  | 
 |     case TYPE_CODE_MEMBERPTR: | 
 |       /* Now, convert these values to an address.  */ | 
 |       if (check_typedef (arg1->type ())->code () != TYPE_CODE_PTR) | 
 | 	arg1 = value_addr (arg1); | 
 |       arg1 = value_cast_pointers (lookup_pointer_type (TYPE_SELF_TYPE (type)), | 
 | 				  arg1, 1); | 
 |  | 
 |       mem_offset = value_as_long (arg2); | 
 |  | 
 |       arg3 = value_from_pointer (lookup_pointer_type (type->target_type ()), | 
 | 				 value_as_long (arg1) + mem_offset); | 
 |       return value_ind (arg3); | 
 |  | 
 |     default: | 
 |       error (_("non-pointer-to-member value used " | 
 | 	       "in pointer-to-member construct")); | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for BINOP_ADD.  */ | 
 |  | 
 | struct value * | 
 | eval_op_add (struct type *expect_type, struct expression *exp, | 
 | 	     enum noside noside, | 
 | 	     struct value *arg1, struct value *arg2) | 
 | { | 
 |   if (binop_user_defined_p (BINOP_ADD, arg1, arg2)) | 
 |     return value_x_binop (arg1, arg2, BINOP_ADD, OP_NULL, noside); | 
 |   else if (ptrmath_type_p (exp->language_defn, arg1->type ()) | 
 | 	   && is_integral_or_integral_reference (arg2->type ())) | 
 |     return value_ptradd (arg1, value_as_long (arg2)); | 
 |   else if (ptrmath_type_p (exp->language_defn, arg2->type ()) | 
 | 	   && is_integral_or_integral_reference (arg1->type ())) | 
 |     return value_ptradd (arg2, value_as_long (arg1)); | 
 |   else | 
 |     { | 
 |       binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
 |       return value_binop (arg1, arg2, BINOP_ADD); | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for BINOP_SUB.  */ | 
 |  | 
 | struct value * | 
 | eval_op_sub (struct type *expect_type, struct expression *exp, | 
 | 	     enum noside noside, | 
 | 	     struct value *arg1, struct value *arg2) | 
 | { | 
 |   if (binop_user_defined_p (BINOP_SUB, arg1, arg2)) | 
 |     return value_x_binop (arg1, arg2, BINOP_SUB, OP_NULL, noside); | 
 |   else if (ptrmath_type_p (exp->language_defn, arg1->type ()) | 
 | 	   && ptrmath_type_p (exp->language_defn, arg2->type ())) | 
 |     { | 
 |       /* FIXME -- should be ptrdiff_t */ | 
 |       struct type *type = builtin_type (exp->gdbarch)->builtin_long; | 
 |       return value_from_longest (type, value_ptrdiff (arg1, arg2)); | 
 |     } | 
 |   else if (ptrmath_type_p (exp->language_defn, arg1->type ()) | 
 | 	   && is_integral_or_integral_reference (arg2->type ())) | 
 |     return value_ptradd (arg1, - value_as_long (arg2)); | 
 |   else | 
 |     { | 
 |       binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
 |       return value_binop (arg1, arg2, BINOP_SUB); | 
 |     } | 
 | } | 
 |  | 
 | /* Helper function for several different binary operations.  */ | 
 |  | 
 | struct value * | 
 | eval_op_binary (struct type *expect_type, struct expression *exp, | 
 | 		enum noside noside, enum exp_opcode op, | 
 | 		struct value *arg1, struct value *arg2) | 
 | { | 
 |   if (binop_user_defined_p (op, arg1, arg2)) | 
 |     return value_x_binop (arg1, arg2, op, OP_NULL, noside); | 
 |   else | 
 |     { | 
 |       /* If EVAL_AVOID_SIDE_EFFECTS and we're dividing by zero, | 
 | 	 fudge arg2 to avoid division-by-zero, the caller is | 
 | 	 (theoretically) only looking for the type of the result.  */ | 
 |       if (noside == EVAL_AVOID_SIDE_EFFECTS | 
 | 	  /* ??? Do we really want to test for BINOP_MOD here? | 
 | 	     The implementation of value_binop gives it a well-defined | 
 | 	     value.  */ | 
 | 	  && (op == BINOP_DIV | 
 | 	      || op == BINOP_INTDIV | 
 | 	      || op == BINOP_REM | 
 | 	      || op == BINOP_MOD) | 
 | 	  && value_logical_not (arg2)) | 
 | 	{ | 
 | 	  struct value *v_one; | 
 |  | 
 | 	  v_one = value_one (arg2->type ()); | 
 | 	  binop_promote (exp->language_defn, exp->gdbarch, &arg1, &v_one); | 
 | 	  return value_binop (arg1, v_one, op); | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  /* For shift and integer exponentiation operations, | 
 | 	     only promote the first argument.  */ | 
 | 	  if ((op == BINOP_LSH || op == BINOP_RSH || op == BINOP_EXP) | 
 | 	      && is_integral_type (arg2->type ())) | 
 | 	    unop_promote (exp->language_defn, exp->gdbarch, &arg1); | 
 | 	  else | 
 | 	    binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
 |  | 
 | 	  return value_binop (arg1, arg2, op); | 
 | 	} | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for BINOP_SUBSCRIPT.  */ | 
 |  | 
 | struct value * | 
 | eval_op_subscript (struct type *expect_type, struct expression *exp, | 
 | 		   enum noside noside, enum exp_opcode op, | 
 | 		   struct value *arg1, struct value *arg2) | 
 | { | 
 |   if (binop_user_defined_p (op, arg1, arg2)) | 
 |     return value_x_binop (arg1, arg2, op, OP_NULL, noside); | 
 |   else | 
 |     { | 
 |       /* If the user attempts to subscript something that is not an | 
 | 	 array or pointer type (like a plain int variable for example), | 
 | 	 then report this as an error.  */ | 
 |  | 
 |       arg1 = coerce_ref (arg1); | 
 |       struct type *type = check_typedef (arg1->type ()); | 
 |       if (type->code () != TYPE_CODE_ARRAY | 
 | 	  && type->code () != TYPE_CODE_PTR) | 
 | 	{ | 
 | 	  if (type->name ()) | 
 | 	    error (_("cannot subscript something of type `%s'"), | 
 | 		   type->name ()); | 
 | 	  else | 
 | 	    error (_("cannot subscript requested type")); | 
 | 	} | 
 |  | 
 |       if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 | 	return value::zero (type->target_type (), arg1->lval ()); | 
 |       else | 
 | 	return value_subscript (arg1, value_as_long (arg2)); | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for BINOP_EQUAL.  */ | 
 |  | 
 | struct value * | 
 | eval_op_equal (struct type *expect_type, struct expression *exp, | 
 | 	       enum noside noside, enum exp_opcode op, | 
 | 	       struct value *arg1, struct value *arg2) | 
 | { | 
 |   if (binop_user_defined_p (op, arg1, arg2)) | 
 |     { | 
 |       return value_x_binop (arg1, arg2, op, OP_NULL, noside); | 
 |     } | 
 |   else | 
 |     { | 
 |       binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
 |       int tem = value_equal (arg1, arg2); | 
 |       struct type *type = language_bool_type (exp->language_defn, | 
 | 					      exp->gdbarch); | 
 |       return value_from_longest (type, (LONGEST) tem); | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for BINOP_NOTEQUAL.  */ | 
 |  | 
 | struct value * | 
 | eval_op_notequal (struct type *expect_type, struct expression *exp, | 
 | 		  enum noside noside, enum exp_opcode op, | 
 | 		  struct value *arg1, struct value *arg2) | 
 | { | 
 |   if (binop_user_defined_p (op, arg1, arg2)) | 
 |     { | 
 |       return value_x_binop (arg1, arg2, op, OP_NULL, noside); | 
 |     } | 
 |   else | 
 |     { | 
 |       binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
 |       int tem = value_equal (arg1, arg2); | 
 |       struct type *type = language_bool_type (exp->language_defn, | 
 | 					      exp->gdbarch); | 
 |       return value_from_longest (type, (LONGEST) ! tem); | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for BINOP_LESS.  */ | 
 |  | 
 | struct value * | 
 | eval_op_less (struct type *expect_type, struct expression *exp, | 
 | 	      enum noside noside, enum exp_opcode op, | 
 | 	      struct value *arg1, struct value *arg2) | 
 | { | 
 |   if (binop_user_defined_p (op, arg1, arg2)) | 
 |     { | 
 |       return value_x_binop (arg1, arg2, op, OP_NULL, noside); | 
 |     } | 
 |   else | 
 |     { | 
 |       binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
 |       int tem = value_less (arg1, arg2); | 
 |       struct type *type = language_bool_type (exp->language_defn, | 
 | 					      exp->gdbarch); | 
 |       return value_from_longest (type, (LONGEST) tem); | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for BINOP_GTR.  */ | 
 |  | 
 | struct value * | 
 | eval_op_gtr (struct type *expect_type, struct expression *exp, | 
 | 	     enum noside noside, enum exp_opcode op, | 
 | 	     struct value *arg1, struct value *arg2) | 
 | { | 
 |   if (binop_user_defined_p (op, arg1, arg2)) | 
 |     { | 
 |       return value_x_binop (arg1, arg2, op, OP_NULL, noside); | 
 |     } | 
 |   else | 
 |     { | 
 |       binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
 |       int tem = value_less (arg2, arg1); | 
 |       struct type *type = language_bool_type (exp->language_defn, | 
 | 					      exp->gdbarch); | 
 |       return value_from_longest (type, (LONGEST) tem); | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for BINOP_GEQ.  */ | 
 |  | 
 | struct value * | 
 | eval_op_geq (struct type *expect_type, struct expression *exp, | 
 | 	     enum noside noside, enum exp_opcode op, | 
 | 	     struct value *arg1, struct value *arg2) | 
 | { | 
 |   if (binop_user_defined_p (op, arg1, arg2)) | 
 |     { | 
 |       return value_x_binop (arg1, arg2, op, OP_NULL, noside); | 
 |     } | 
 |   else | 
 |     { | 
 |       binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
 |       int tem = value_less (arg2, arg1) || value_equal (arg1, arg2); | 
 |       struct type *type = language_bool_type (exp->language_defn, | 
 | 					      exp->gdbarch); | 
 |       return value_from_longest (type, (LONGEST) tem); | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for BINOP_LEQ.  */ | 
 |  | 
 | struct value * | 
 | eval_op_leq (struct type *expect_type, struct expression *exp, | 
 | 	     enum noside noside, enum exp_opcode op, | 
 | 	     struct value *arg1, struct value *arg2) | 
 | { | 
 |   if (binop_user_defined_p (op, arg1, arg2)) | 
 |     { | 
 |       return value_x_binop (arg1, arg2, op, OP_NULL, noside); | 
 |     } | 
 |   else | 
 |     { | 
 |       binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2); | 
 |       int tem = value_less (arg1, arg2) || value_equal (arg1, arg2); | 
 |       struct type *type = language_bool_type (exp->language_defn, | 
 | 					      exp->gdbarch); | 
 |       return value_from_longest (type, (LONGEST) tem); | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for BINOP_REPEAT.  */ | 
 |  | 
 | struct value * | 
 | eval_op_repeat (struct type *expect_type, struct expression *exp, | 
 | 		enum noside noside, enum exp_opcode op, | 
 | 		struct value *arg1, struct value *arg2) | 
 | { | 
 |   struct type *type = check_typedef (arg2->type ()); | 
 |   if (type->code () != TYPE_CODE_INT | 
 |       && type->code () != TYPE_CODE_ENUM) | 
 |     error (_("Non-integral right operand for \"@\" operator.")); | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     { | 
 |       return allocate_repeat_value (arg1->type (), | 
 | 				    longest_to_int (value_as_long (arg2))); | 
 |     } | 
 |   else | 
 |     return value_repeat (arg1, longest_to_int (value_as_long (arg2))); | 
 | } | 
 |  | 
 | /* A helper function for UNOP_PLUS.  */ | 
 |  | 
 | struct value * | 
 | eval_op_plus (struct type *expect_type, struct expression *exp, | 
 | 	      enum noside noside, enum exp_opcode op, | 
 | 	      struct value *arg1) | 
 | { | 
 |   if (unop_user_defined_p (op, arg1)) | 
 |     return value_x_unop (arg1, op, noside); | 
 |   else | 
 |     { | 
 |       unop_promote (exp->language_defn, exp->gdbarch, &arg1); | 
 |       return value_pos (arg1); | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for UNOP_NEG.  */ | 
 |  | 
 | struct value * | 
 | eval_op_neg (struct type *expect_type, struct expression *exp, | 
 | 	     enum noside noside, enum exp_opcode op, | 
 | 	     struct value *arg1) | 
 | { | 
 |   if (unop_user_defined_p (op, arg1)) | 
 |     return value_x_unop (arg1, op, noside); | 
 |   else | 
 |     { | 
 |       unop_promote (exp->language_defn, exp->gdbarch, &arg1); | 
 |       return value_neg (arg1); | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for UNOP_COMPLEMENT.  */ | 
 |  | 
 | struct value * | 
 | eval_op_complement (struct type *expect_type, struct expression *exp, | 
 | 		    enum noside noside, enum exp_opcode op, | 
 | 		    struct value *arg1) | 
 | { | 
 |   if (unop_user_defined_p (UNOP_COMPLEMENT, arg1)) | 
 |     return value_x_unop (arg1, UNOP_COMPLEMENT, noside); | 
 |   else | 
 |     { | 
 |       unop_promote (exp->language_defn, exp->gdbarch, &arg1); | 
 |       return value_complement (arg1); | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for UNOP_LOGICAL_NOT.  */ | 
 |  | 
 | struct value * | 
 | eval_op_lognot (struct type *expect_type, struct expression *exp, | 
 | 		enum noside noside, enum exp_opcode op, | 
 | 		struct value *arg1) | 
 | { | 
 |   if (unop_user_defined_p (op, arg1)) | 
 |     return value_x_unop (arg1, op, noside); | 
 |   else | 
 |     { | 
 |       struct type *type = language_bool_type (exp->language_defn, | 
 | 					      exp->gdbarch); | 
 |       return value_from_longest (type, (LONGEST) value_logical_not (arg1)); | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for UNOP_IND.  */ | 
 |  | 
 | struct value * | 
 | eval_op_ind (struct type *expect_type, struct expression *exp, | 
 | 	     enum noside noside, | 
 | 	     struct value *arg1) | 
 | { | 
 |   struct type *type = check_typedef (arg1->type ()); | 
 |   if (type->code () == TYPE_CODE_METHODPTR | 
 |       || type->code () == TYPE_CODE_MEMBERPTR) | 
 |     error (_("Attempt to dereference pointer " | 
 | 	     "to member without an object")); | 
 |   if (unop_user_defined_p (UNOP_IND, arg1)) | 
 |     return value_x_unop (arg1, UNOP_IND, noside); | 
 |   else if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     { | 
 |       type = check_typedef (arg1->type ()); | 
 |  | 
 |       /* If the type pointed to is dynamic then in order to resolve the | 
 | 	 dynamic properties we must actually dereference the pointer. | 
 | 	 There is a risk that this dereference will have side-effects | 
 | 	 in the inferior, but being able to print accurate type | 
 | 	 information seems worth the risk. */ | 
 |       if (!type->is_pointer_or_reference () | 
 | 	  || !is_dynamic_type (type->target_type ())) | 
 | 	{ | 
 | 	  if (type->is_pointer_or_reference () | 
 | 	      /* In C you can dereference an array to get the 1st elt.  */ | 
 | 	      || type->code () == TYPE_CODE_ARRAY) | 
 | 	    return value::zero (type->target_type (), | 
 | 			       lval_memory); | 
 | 	  else if (type->code () == TYPE_CODE_INT) | 
 | 	    /* GDB allows dereferencing an int.  */ | 
 | 	    return value::zero (builtin_type (exp->gdbarch)->builtin_int, | 
 | 			       lval_memory); | 
 | 	  else | 
 | 	    error (_("Attempt to take contents of a non-pointer value.")); | 
 | 	} | 
 |     } | 
 |  | 
 |   /* Allow * on an integer so we can cast it to whatever we want. | 
 |      This returns an int, which seems like the most C-like thing to | 
 |      do.  "long long" variables are rare enough that | 
 |      BUILTIN_TYPE_LONGEST would seem to be a mistake.  */ | 
 |   if (type->code () == TYPE_CODE_INT) | 
 |     return value_at_lazy (builtin_type (exp->gdbarch)->builtin_int, | 
 | 			  value_as_address (arg1)); | 
 |   return value_ind (arg1); | 
 | } | 
 |  | 
 | /* A helper function for UNOP_ALIGNOF.  */ | 
 |  | 
 | struct value * | 
 | eval_op_alignof (struct type *expect_type, struct expression *exp, | 
 | 		 enum noside noside, | 
 | 		 struct value *arg1) | 
 | { | 
 |   struct type *type = arg1->type (); | 
 |   /* FIXME: This should be size_t.  */ | 
 |   struct type *size_type = builtin_type (exp->gdbarch)->builtin_int; | 
 |   ULONGEST align = type_align (type); | 
 |   if (align == 0) | 
 |     error (_("could not determine alignment of type")); | 
 |   return value_from_longest (size_type, align); | 
 | } | 
 |  | 
 | /* A helper function for UNOP_MEMVAL.  */ | 
 |  | 
 | struct value * | 
 | eval_op_memval (struct type *expect_type, struct expression *exp, | 
 | 		enum noside noside, | 
 | 		struct value *arg1, struct type *type) | 
 | { | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     return value::zero (type, lval_memory); | 
 |   else | 
 |     return value_at_lazy (type, value_as_address (arg1)); | 
 | } | 
 |  | 
 | /* A helper function for UNOP_PREINCREMENT.  */ | 
 |  | 
 | struct value * | 
 | eval_op_preinc (struct type *expect_type, struct expression *exp, | 
 | 		enum noside noside, enum exp_opcode op, | 
 | 		struct value *arg1) | 
 | { | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     return arg1; | 
 |   else if (unop_user_defined_p (op, arg1)) | 
 |     { | 
 |       return value_x_unop (arg1, op, noside); | 
 |     } | 
 |   else | 
 |     { | 
 |       struct value *arg2; | 
 |       if (ptrmath_type_p (exp->language_defn, arg1->type ())) | 
 | 	arg2 = value_ptradd (arg1, 1); | 
 |       else | 
 | 	{ | 
 | 	  struct value *tmp = arg1; | 
 |  | 
 | 	  arg2 = value_one (arg1->type ()); | 
 | 	  binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); | 
 | 	  arg2 = value_binop (tmp, arg2, BINOP_ADD); | 
 | 	} | 
 |  | 
 |       return value_assign (arg1, arg2); | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for UNOP_PREDECREMENT.  */ | 
 |  | 
 | struct value * | 
 | eval_op_predec (struct type *expect_type, struct expression *exp, | 
 | 		enum noside noside, enum exp_opcode op, | 
 | 		struct value *arg1) | 
 | { | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     return arg1; | 
 |   else if (unop_user_defined_p (op, arg1)) | 
 |     { | 
 |       return value_x_unop (arg1, op, noside); | 
 |     } | 
 |   else | 
 |     { | 
 |       struct value *arg2; | 
 |       if (ptrmath_type_p (exp->language_defn, arg1->type ())) | 
 | 	arg2 = value_ptradd (arg1, -1); | 
 |       else | 
 | 	{ | 
 | 	  struct value *tmp = arg1; | 
 |  | 
 | 	  arg2 = value_one (arg1->type ()); | 
 | 	  binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); | 
 | 	  arg2 = value_binop (tmp, arg2, BINOP_SUB); | 
 | 	} | 
 |  | 
 |       return value_assign (arg1, arg2); | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for UNOP_POSTINCREMENT.  */ | 
 |  | 
 | struct value * | 
 | eval_op_postinc (struct type *expect_type, struct expression *exp, | 
 | 		 enum noside noside, enum exp_opcode op, | 
 | 		 struct value *arg1) | 
 | { | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     return arg1; | 
 |   else if (unop_user_defined_p (op, arg1)) | 
 |     { | 
 |       return value_x_unop (arg1, op, noside); | 
 |     } | 
 |   else | 
 |     { | 
 |       struct value *arg3 = arg1->non_lval (); | 
 |       struct value *arg2; | 
 |  | 
 |       if (ptrmath_type_p (exp->language_defn, arg1->type ())) | 
 | 	arg2 = value_ptradd (arg1, 1); | 
 |       else | 
 | 	{ | 
 | 	  struct value *tmp = arg1; | 
 |  | 
 | 	  arg2 = value_one (arg1->type ()); | 
 | 	  binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); | 
 | 	  arg2 = value_binop (tmp, arg2, BINOP_ADD); | 
 | 	} | 
 |  | 
 |       value_assign (arg1, arg2); | 
 |       return arg3; | 
 |     } | 
 | } | 
 |  | 
 | /* A helper function for UNOP_POSTDECREMENT.  */ | 
 |  | 
 | struct value * | 
 | eval_op_postdec (struct type *expect_type, struct expression *exp, | 
 | 		 enum noside noside, enum exp_opcode op, | 
 | 		 struct value *arg1) | 
 | { | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     return arg1; | 
 |   else if (unop_user_defined_p (op, arg1)) | 
 |     { | 
 |       return value_x_unop (arg1, op, noside); | 
 |     } | 
 |   else | 
 |     { | 
 |       struct value *arg3 = arg1->non_lval (); | 
 |       struct value *arg2; | 
 |  | 
 |       if (ptrmath_type_p (exp->language_defn, arg1->type ())) | 
 | 	arg2 = value_ptradd (arg1, -1); | 
 |       else | 
 | 	{ | 
 | 	  struct value *tmp = arg1; | 
 |  | 
 | 	  arg2 = value_one (arg1->type ()); | 
 | 	  binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); | 
 | 	  arg2 = value_binop (tmp, arg2, BINOP_SUB); | 
 | 	} | 
 |  | 
 |       value_assign (arg1, arg2); | 
 |       return arg3; | 
 |     } | 
 | } | 
 |  | 
 | namespace expr | 
 | { | 
 |  | 
 | struct value * | 
 | type_operation::evaluate (struct type *expect_type, struct expression *exp, | 
 | 			  enum noside noside) | 
 | { | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     return value::allocate (std::get<0> (m_storage)); | 
 |   else | 
 |     error (_("Attempt to use a type name as an expression")); | 
 | } | 
 |  | 
 | } | 
 |  | 
 | /* A helper function for BINOP_ASSIGN_MODIFY.  */ | 
 |  | 
 | struct value * | 
 | eval_binop_assign_modify (struct type *expect_type, struct expression *exp, | 
 | 			  enum noside noside, enum exp_opcode op, | 
 | 			  struct value *arg1, struct value *arg2) | 
 | { | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     return arg1; | 
 |   if (binop_user_defined_p (op, arg1, arg2)) | 
 |     return value_x_binop (arg1, arg2, BINOP_ASSIGN_MODIFY, op, noside); | 
 |   else if (op == BINOP_ADD && ptrmath_type_p (exp->language_defn, | 
 | 					      arg1->type ()) | 
 | 	   && is_integral_type (arg2->type ())) | 
 |     arg2 = value_ptradd (arg1, value_as_long (arg2)); | 
 |   else if (op == BINOP_SUB && ptrmath_type_p (exp->language_defn, | 
 | 					      arg1->type ()) | 
 | 	   && is_integral_type (arg2->type ())) | 
 |     arg2 = value_ptradd (arg1, - value_as_long (arg2)); | 
 |   else | 
 |     { | 
 |       struct value *tmp = arg1; | 
 |  | 
 |       /* For shift and integer exponentiation operations, | 
 | 	 only promote the first argument.  */ | 
 |       if ((op == BINOP_LSH || op == BINOP_RSH || op == BINOP_EXP) | 
 | 	  && is_integral_type (arg2->type ())) | 
 | 	unop_promote (exp->language_defn, exp->gdbarch, &tmp); | 
 |       else | 
 | 	binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); | 
 |  | 
 |       arg2 = value_binop (tmp, arg2, op); | 
 |     } | 
 |   return value_assign (arg1, arg2); | 
 | } | 
 |  | 
 | /* Note that ARGS needs 2 empty slots up front and must end with a | 
 |    null pointer.  */ | 
 | static struct value * | 
 | eval_op_objc_msgcall (struct type *expect_type, struct expression *exp, | 
 | 		      enum noside noside, CORE_ADDR selector, | 
 | 		      value *target, gdb::array_view<value *> args) | 
 | { | 
 |   CORE_ADDR responds_selector = 0; | 
 |   CORE_ADDR method_selector = 0; | 
 |  | 
 |   int struct_return = 0; | 
 |  | 
 |   struct value *msg_send = NULL; | 
 |   struct value *msg_send_stret = NULL; | 
 |   int gnu_runtime = 0; | 
 |  | 
 |   struct value *method = NULL; | 
 |   struct value *called_method = NULL; | 
 |  | 
 |   struct type *selector_type = NULL; | 
 |   struct type *long_type; | 
 |   struct type *type; | 
 |  | 
 |   struct value *ret = NULL; | 
 |   CORE_ADDR addr = 0; | 
 |  | 
 |   value *argvec[5]; | 
 |  | 
 |   long_type = builtin_type (exp->gdbarch)->builtin_long; | 
 |   selector_type = builtin_type (exp->gdbarch)->builtin_data_ptr; | 
 |  | 
 |   if (value_as_long (target) == 0) | 
 |     return value_from_longest (long_type, 0); | 
 |  | 
 |   if (lookup_minimal_symbol (current_program_space, "objc_msg_lookup").minsym | 
 |       != nullptr) | 
 |     gnu_runtime = 1; | 
 |  | 
 |   /* Find the method dispatch (Apple runtime) or method lookup | 
 |      (GNU runtime) function for Objective-C.  These will be used | 
 |      to lookup the symbol information for the method.  If we | 
 |      can't find any symbol information, then we'll use these to | 
 |      call the method, otherwise we can call the method | 
 |      directly.  The msg_send_stret function is used in the special | 
 |      case of a method that returns a structure (Apple runtime | 
 |      only).  */ | 
 |   if (gnu_runtime) | 
 |     { | 
 |       type = selector_type; | 
 |  | 
 |       type = lookup_function_type (type); | 
 |       type = lookup_pointer_type (type); | 
 |       type = lookup_function_type (type); | 
 |       type = lookup_pointer_type (type); | 
 |  | 
 |       msg_send = find_function_in_inferior ("objc_msg_lookup", NULL); | 
 |       msg_send_stret | 
 | 	= find_function_in_inferior ("objc_msg_lookup", NULL); | 
 |  | 
 |       msg_send = value_from_pointer (type, value_as_address (msg_send)); | 
 |       msg_send_stret = value_from_pointer (type, | 
 | 					   value_as_address (msg_send_stret)); | 
 |     } | 
 |   else | 
 |     { | 
 |       msg_send = find_function_in_inferior ("objc_msgSend", NULL); | 
 |       /* Special dispatcher for methods returning structs.  */ | 
 |       msg_send_stret | 
 | 	= find_function_in_inferior ("objc_msgSend_stret", NULL); | 
 |     } | 
 |  | 
 |   /* Verify the target object responds to this method.  The | 
 |      standard top-level 'Object' class uses a different name for | 
 |      the verification method than the non-standard, but more | 
 |      often used, 'NSObject' class.  Make sure we check for both.  */ | 
 |  | 
 |   responds_selector | 
 |     = lookup_child_selector (exp->gdbarch, "respondsToSelector:"); | 
 |   if (responds_selector == 0) | 
 |     responds_selector | 
 |       = lookup_child_selector (exp->gdbarch, "respondsTo:"); | 
 |  | 
 |   if (responds_selector == 0) | 
 |     error (_("no 'respondsTo:' or 'respondsToSelector:' method")); | 
 |  | 
 |   method_selector | 
 |     = lookup_child_selector (exp->gdbarch, "methodForSelector:"); | 
 |   if (method_selector == 0) | 
 |     method_selector | 
 |       = lookup_child_selector (exp->gdbarch, "methodFor:"); | 
 |  | 
 |   if (method_selector == 0) | 
 |     error (_("no 'methodFor:' or 'methodForSelector:' method")); | 
 |  | 
 |   /* Call the verification method, to make sure that the target | 
 |      class implements the desired method.  */ | 
 |  | 
 |   argvec[0] = msg_send; | 
 |   argvec[1] = target; | 
 |   argvec[2] = value_from_longest (long_type, responds_selector); | 
 |   argvec[3] = value_from_longest (long_type, selector); | 
 |   argvec[4] = 0; | 
 |  | 
 |   ret = call_function_by_hand (argvec[0], NULL, {argvec + 1, 3}); | 
 |   if (gnu_runtime) | 
 |     { | 
 |       /* Function objc_msg_lookup returns a pointer.  */ | 
 |       argvec[0] = ret; | 
 |       ret = call_function_by_hand (argvec[0], NULL, {argvec + 1, 3}); | 
 |     } | 
 |   if (value_as_long (ret) == 0) | 
 |     error (_("Target does not respond to this message selector.")); | 
 |  | 
 |   /* Call "methodForSelector:" method, to get the address of a | 
 |      function method that implements this selector for this | 
 |      class.  If we can find a symbol at that address, then we | 
 |      know the return type, parameter types etc.  (that's a good | 
 |      thing).  */ | 
 |  | 
 |   argvec[0] = msg_send; | 
 |   argvec[1] = target; | 
 |   argvec[2] = value_from_longest (long_type, method_selector); | 
 |   argvec[3] = value_from_longest (long_type, selector); | 
 |   argvec[4] = 0; | 
 |  | 
 |   ret = call_function_by_hand (argvec[0], NULL, {argvec + 1, 3}); | 
 |   if (gnu_runtime) | 
 |     { | 
 |       argvec[0] = ret; | 
 |       ret = call_function_by_hand (argvec[0], NULL, {argvec + 1, 3}); | 
 |     } | 
 |  | 
 |   /* ret should now be the selector.  */ | 
 |  | 
 |   addr = value_as_long (ret); | 
 |   if (addr) | 
 |     { | 
 |       struct symbol *sym = NULL; | 
 |  | 
 |       /* The address might point to a function descriptor; | 
 | 	 resolve it to the actual code address instead.  */ | 
 |       addr = gdbarch_convert_from_func_ptr_addr | 
 | 	(exp->gdbarch, addr, current_inferior ()->top_target ()); | 
 |  | 
 |       /* Is it a high_level symbol?  */ | 
 |       sym = find_pc_function (addr); | 
 |       if (sym != NULL) | 
 | 	method = value_of_variable (sym, 0); | 
 |     } | 
 |  | 
 |   /* If we found a method with symbol information, check to see | 
 |      if it returns a struct.  Otherwise assume it doesn't.  */ | 
 |  | 
 |   if (method) | 
 |     { | 
 |       CORE_ADDR funaddr; | 
 |       struct type *val_type; | 
 |  | 
 |       funaddr = find_function_addr (method, &val_type); | 
 |  | 
 |       block_for_pc (funaddr); | 
 |  | 
 |       val_type = check_typedef (val_type); | 
 |  | 
 |       if ((val_type == NULL) | 
 | 	  || (val_type->code () == TYPE_CODE_ERROR)) | 
 | 	{ | 
 | 	  if (expect_type != NULL) | 
 | 	    val_type = expect_type; | 
 | 	} | 
 |  | 
 |       struct_return = using_struct_return (exp->gdbarch, method, | 
 | 					   val_type); | 
 |     } | 
 |   else if (expect_type != NULL) | 
 |     { | 
 |       struct_return = using_struct_return (exp->gdbarch, NULL, | 
 | 					   check_typedef (expect_type)); | 
 |     } | 
 |  | 
 |   /* Found a function symbol.  Now we will substitute its | 
 |      value in place of the message dispatcher (obj_msgSend), | 
 |      so that we call the method directly instead of through | 
 |      the dispatcher.  The main reason for doing this is that | 
 |      we can now evaluate the return value and parameter values | 
 |      according to their known data types, in case we need to | 
 |      do things like promotion, dereferencing, special handling | 
 |      of structs and doubles, etc. | 
 |  | 
 |      We want to use the type signature of 'method', but still | 
 |      jump to objc_msgSend() or objc_msgSend_stret() to better | 
 |      mimic the behavior of the runtime.  */ | 
 |  | 
 |   if (method) | 
 |     { | 
 |       if (method->type ()->code () != TYPE_CODE_FUNC) | 
 | 	error (_("method address has symbol information " | 
 | 		 "with non-function type; skipping")); | 
 |  | 
 |       /* Create a function pointer of the appropriate type, and | 
 | 	 replace its value with the value of msg_send or | 
 | 	 msg_send_stret.  We must use a pointer here, as | 
 | 	 msg_send and msg_send_stret are of pointer type, and | 
 | 	 the representation may be different on systems that use | 
 | 	 function descriptors.  */ | 
 |       if (struct_return) | 
 | 	called_method | 
 | 	  = value_from_pointer (lookup_pointer_type (method->type ()), | 
 | 				value_as_address (msg_send_stret)); | 
 |       else | 
 | 	called_method | 
 | 	  = value_from_pointer (lookup_pointer_type (method->type ()), | 
 | 				value_as_address (msg_send)); | 
 |     } | 
 |   else | 
 |     { | 
 |       if (struct_return) | 
 | 	called_method = msg_send_stret; | 
 |       else | 
 | 	called_method = msg_send; | 
 |     } | 
 |  | 
 |  | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     { | 
 |       /* If the return type doesn't look like a function type, | 
 | 	 call an error.  This can happen if somebody tries to | 
 | 	 turn a variable into a function call.  This is here | 
 | 	 because people often want to call, eg, strcmp, which | 
 | 	 gdb doesn't know is a function.  If gdb isn't asked for | 
 | 	 it's opinion (ie. through "whatis"), it won't offer | 
 | 	 it.  */ | 
 |  | 
 |       struct type *callee_type = called_method->type (); | 
 |  | 
 |       if (callee_type && callee_type->code () == TYPE_CODE_PTR) | 
 | 	callee_type = callee_type->target_type (); | 
 |       callee_type = callee_type->target_type (); | 
 |  | 
 |       if (callee_type) | 
 | 	{ | 
 | 	  if ((callee_type->code () == TYPE_CODE_ERROR) && expect_type) | 
 | 	    return value::allocate (expect_type); | 
 | 	  else | 
 | 	    return value::allocate (callee_type); | 
 | 	} | 
 |       else | 
 | 	error (_("Expression of type other than " | 
 | 		 "\"method returning ...\" used as a method")); | 
 |     } | 
 |  | 
 |   /* Now depending on whether we found a symbol for the method, | 
 |      we will either call the runtime dispatcher or the method | 
 |      directly.  */ | 
 |  | 
 |   args[0] = target; | 
 |   args[1] = value_from_longest (long_type, selector); | 
 |  | 
 |   if (gnu_runtime && (method != NULL)) | 
 |     { | 
 |       /* Function objc_msg_lookup returns a pointer.  */ | 
 |       struct type *tem_type = called_method->type (); | 
 |       tem_type = lookup_pointer_type (lookup_function_type (tem_type)); | 
 |       called_method->deprecated_set_type (tem_type); | 
 |       called_method = call_function_by_hand (called_method, NULL, args); | 
 |     } | 
 |  | 
 |   return call_function_by_hand (called_method, NULL, args); | 
 | } | 
 |  | 
 | /* Helper function for MULTI_SUBSCRIPT.  */ | 
 |  | 
 | static struct value * | 
 | eval_multi_subscript (struct type *expect_type, struct expression *exp, | 
 | 		      enum noside noside, value *arg1, | 
 | 		      gdb::array_view<value *> args) | 
 | { | 
 |   for (value *arg2 : args) | 
 |     { | 
 |       if (binop_user_defined_p (MULTI_SUBSCRIPT, arg1, arg2)) | 
 | 	{ | 
 | 	  arg1 = value_x_binop (arg1, arg2, MULTI_SUBSCRIPT, OP_NULL, noside); | 
 | 	} | 
 |       else | 
 | 	{ | 
 | 	  arg1 = coerce_ref (arg1); | 
 | 	  struct type *type = check_typedef (arg1->type ()); | 
 |  | 
 | 	  switch (type->code ()) | 
 | 	    { | 
 | 	    case TYPE_CODE_PTR: | 
 | 	    case TYPE_CODE_ARRAY: | 
 | 	    case TYPE_CODE_STRING: | 
 | 	      arg1 = value_subscript (arg1, value_as_long (arg2)); | 
 | 	      break; | 
 |  | 
 | 	    default: | 
 | 	      if (type->name ()) | 
 | 		error (_("cannot subscript something of type `%s'"), | 
 | 		       type->name ()); | 
 | 	      else | 
 | 		error (_("cannot subscript requested type")); | 
 | 	    } | 
 | 	} | 
 |     } | 
 |   return (arg1); | 
 | } | 
 |  | 
 | namespace expr | 
 | { | 
 |  | 
 | value * | 
 | objc_msgcall_operation::evaluate (struct type *expect_type, | 
 | 				  struct expression *exp, | 
 | 				  enum noside noside) | 
 | { | 
 |   enum noside sub_no_side = EVAL_NORMAL; | 
 |   struct type *selector_type = builtin_type (exp->gdbarch)->builtin_data_ptr; | 
 |  | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     sub_no_side = EVAL_NORMAL; | 
 |   else | 
 |     sub_no_side = noside; | 
 |   value *target | 
 |     = std::get<1> (m_storage)->evaluate (selector_type, exp, sub_no_side); | 
 |  | 
 |   if (value_as_long (target) == 0) | 
 |     sub_no_side = EVAL_AVOID_SIDE_EFFECTS; | 
 |   else | 
 |     sub_no_side = noside; | 
 |   std::vector<operation_up> &args = std::get<2> (m_storage); | 
 |   value **argvec = XALLOCAVEC (struct value *, args.size () + 3); | 
 |   argvec[0] = nullptr; | 
 |   argvec[1] = nullptr; | 
 |   for (int i = 0; i < args.size (); ++i) | 
 |     argvec[i + 2] = args[i]->evaluate_with_coercion (exp, sub_no_side); | 
 |   argvec[args.size () + 2] = nullptr; | 
 |  | 
 |   return eval_op_objc_msgcall (expect_type, exp, noside, std:: | 
 | 			       get<0> (m_storage), target, | 
 | 			       gdb::make_array_view (argvec, | 
 | 						     args.size () + 3)); | 
 | } | 
 |  | 
 | value * | 
 | multi_subscript_operation::evaluate (struct type *expect_type, | 
 | 				     struct expression *exp, | 
 | 				     enum noside noside) | 
 | { | 
 |   value *arg1 = std::get<0> (m_storage)->evaluate_with_coercion (exp, noside); | 
 |   std::vector<operation_up> &values = std::get<1> (m_storage); | 
 |   value **argvec = XALLOCAVEC (struct value *, values.size ()); | 
 |   for (int ix = 0; ix < values.size (); ++ix) | 
 |     argvec[ix] = values[ix]->evaluate_with_coercion (exp, noside); | 
 |   return eval_multi_subscript (expect_type, exp, noside, arg1, | 
 | 			       gdb::make_array_view (argvec, values.size ())); | 
 | } | 
 |  | 
 | value * | 
 | logical_and_operation::evaluate (struct type *expect_type, | 
 | 				 struct expression *exp, | 
 | 				 enum noside noside) | 
 | { | 
 |   value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | 
 |  | 
 |   value *arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, | 
 | 						   EVAL_AVOID_SIDE_EFFECTS); | 
 |  | 
 |   if (binop_user_defined_p (BINOP_LOGICAL_AND, arg1, arg2)) | 
 |     { | 
 |       arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | 
 |       return value_x_binop (arg1, arg2, BINOP_LOGICAL_AND, OP_NULL, noside); | 
 |     } | 
 |   else | 
 |     { | 
 |       bool tem = value_logical_not (arg1); | 
 |       if (!tem) | 
 | 	{ | 
 | 	  arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | 
 | 	  tem = value_logical_not (arg2); | 
 | 	} | 
 |       struct type *type = language_bool_type (exp->language_defn, | 
 | 					      exp->gdbarch); | 
 |       return value_from_longest (type, !tem); | 
 |     } | 
 | } | 
 |  | 
 | value * | 
 | logical_or_operation::evaluate (struct type *expect_type, | 
 | 				struct expression *exp, | 
 | 				enum noside noside) | 
 | { | 
 |   value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | 
 |  | 
 |   value *arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, | 
 | 						   EVAL_AVOID_SIDE_EFFECTS); | 
 |  | 
 |   if (binop_user_defined_p (BINOP_LOGICAL_OR, arg1, arg2)) | 
 |     { | 
 |       arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | 
 |       return value_x_binop (arg1, arg2, BINOP_LOGICAL_OR, OP_NULL, noside); | 
 |     } | 
 |   else | 
 |     { | 
 |       bool tem = value_logical_not (arg1); | 
 |       if (tem) | 
 | 	{ | 
 | 	  arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside); | 
 | 	  tem = value_logical_not (arg2); | 
 | 	} | 
 |  | 
 |       struct type *type = language_bool_type (exp->language_defn, | 
 | 					      exp->gdbarch); | 
 |       return value_from_longest (type, !tem); | 
 |     } | 
 | } | 
 |  | 
 | value * | 
 | adl_func_operation::evaluate (struct type *expect_type, | 
 | 			      struct expression *exp, | 
 | 			      enum noside noside) | 
 | { | 
 |   std::vector<operation_up> &arg_ops = std::get<2> (m_storage); | 
 |   std::vector<value *> args (arg_ops.size ()); | 
 |   for (int i = 0; i < arg_ops.size (); ++i) | 
 |     args[i] = arg_ops[i]->evaluate_with_coercion (exp, noside); | 
 |  | 
 |   struct symbol *symp; | 
 |   find_overload_match (args, std::get<0> (m_storage).c_str (), | 
 | 		       NON_METHOD, | 
 | 		       nullptr, nullptr, | 
 | 		       nullptr, &symp, nullptr, 0, noside); | 
 |   if (symp->type ()->code () == TYPE_CODE_ERROR) | 
 |     error_unknown_type (symp->print_name ()); | 
 |   value *callee = evaluate_var_value (noside, std::get<1> (m_storage), symp); | 
 |   return evaluate_subexp_do_call (exp, noside, callee, args, | 
 | 				  nullptr, expect_type); | 
 |  | 
 | } | 
 |  | 
 | /* This function evaluates brace-initializers (in C/C++) for | 
 |    structure types.  */ | 
 |  | 
 | struct value * | 
 | array_operation::evaluate_struct_tuple (struct value *struct_val, | 
 | 					struct expression *exp, | 
 | 					enum noside noside, int nargs) | 
 | { | 
 |   const std::vector<operation_up> &in_args = std::get<2> (m_storage); | 
 |   struct type *struct_type = check_typedef (struct_val->type ()); | 
 |   struct type *field_type; | 
 |   int fieldno = -1; | 
 |  | 
 |   int idx = 0; | 
 |   while (--nargs >= 0) | 
 |     { | 
 |       struct value *val = NULL; | 
 |       int bitpos, bitsize; | 
 |       bfd_byte *addr; | 
 |  | 
 |       fieldno++; | 
 |       /* Skip static fields.  */ | 
 |       while (fieldno < struct_type->num_fields () | 
 | 	     && struct_type->field (fieldno).is_static ()) | 
 | 	fieldno++; | 
 |       if (fieldno >= struct_type->num_fields ()) | 
 | 	error (_("too many initializers")); | 
 |       field_type = struct_type->field (fieldno).type (); | 
 |       if (field_type->code () == TYPE_CODE_UNION | 
 | 	  && struct_type->field (fieldno).name ()[0] == '0') | 
 | 	error (_("don't know which variant you want to set")); | 
 |  | 
 |       /* Here, struct_type is the type of the inner struct, | 
 | 	 while substruct_type is the type of the inner struct. | 
 | 	 These are the same for normal structures, but a variant struct | 
 | 	 contains anonymous union fields that contain substruct fields. | 
 | 	 The value fieldno is the index of the top-level (normal or | 
 | 	 anonymous union) field in struct_field, while the value | 
 | 	 subfieldno is the index of the actual real (named inner) field | 
 | 	 in substruct_type.  */ | 
 |  | 
 |       field_type = struct_type->field (fieldno).type (); | 
 |       if (val == 0) | 
 | 	val = in_args[idx++]->evaluate (field_type, exp, noside); | 
 |  | 
 |       /* Now actually set the field in struct_val.  */ | 
 |  | 
 |       /* Assign val to field fieldno.  */ | 
 |       if (val->type () != field_type) | 
 | 	val = value_cast (field_type, val); | 
 |  | 
 |       bitsize = struct_type->field (fieldno).bitsize (); | 
 |       bitpos = struct_type->field (fieldno).loc_bitpos (); | 
 |       addr = struct_val->contents_writeable ().data () + bitpos / 8; | 
 |       if (bitsize) | 
 | 	modify_field (struct_type, addr, | 
 | 		      value_as_long (val), bitpos % 8, bitsize); | 
 |       else | 
 | 	memcpy (addr, val->contents ().data (), | 
 | 		val->type ()->length ()); | 
 |  | 
 |     } | 
 |   return struct_val; | 
 | } | 
 |  | 
 | value * | 
 | array_operation::evaluate (struct type *expect_type, | 
 | 			   struct expression *exp, | 
 | 			   enum noside noside) | 
 | { | 
 |   const int provided_low_bound = std::get<0> (m_storage); | 
 |   const std::vector<operation_up> &in_args = std::get<2> (m_storage); | 
 |   const int nargs = std::get<1> (m_storage) - provided_low_bound + 1; | 
 |   struct type *type = expect_type ? check_typedef (expect_type) : nullptr; | 
 |  | 
 |   if (expect_type != nullptr | 
 |       && type->code () == TYPE_CODE_STRUCT) | 
 |     { | 
 |       struct value *rec = value::allocate (expect_type); | 
 |  | 
 |       memset (rec->contents_raw ().data (), '\0', type->length ()); | 
 |       return evaluate_struct_tuple (rec, exp, noside, nargs); | 
 |     } | 
 |  | 
 |   if (expect_type != nullptr | 
 |       && type->code () == TYPE_CODE_ARRAY) | 
 |     { | 
 |       struct type *range_type = type->index_type (); | 
 |       struct type *element_type = type->target_type (); | 
 |       struct value *array = value::allocate (expect_type); | 
 |       int element_size = check_typedef (element_type)->length (); | 
 |       LONGEST low_bound, high_bound; | 
 |  | 
 |       if (!get_discrete_bounds (range_type, &low_bound, &high_bound)) | 
 | 	{ | 
 | 	  low_bound = 0; | 
 | 	  high_bound = (type->length () / element_size) - 1; | 
 | 	} | 
 |       if (low_bound + nargs - 1 > high_bound) | 
 | 	error (_("Too many array elements")); | 
 |       memset (array->contents_raw ().data (), 0, expect_type->length ()); | 
 |       for (int idx = 0; idx < nargs; ++idx) | 
 | 	{ | 
 | 	  struct value *element; | 
 |  | 
 | 	  element = in_args[idx]->evaluate (element_type, exp, noside); | 
 | 	  if (element->type () != element_type) | 
 | 	    element = value_cast (element_type, element); | 
 | 	  memcpy (array->contents_raw ().data () + idx * element_size, | 
 | 		  element->contents ().data (), | 
 | 		  element_size); | 
 | 	} | 
 |       return array; | 
 |     } | 
 |  | 
 |   if (expect_type != nullptr | 
 |       && type->code () == TYPE_CODE_SET) | 
 |     { | 
 |       struct value *set = value::allocate (expect_type); | 
 |       gdb_byte *valaddr = set->contents_raw ().data (); | 
 |       struct type *element_type = type->index_type (); | 
 |       struct type *check_type = element_type; | 
 |       LONGEST low_bound, high_bound; | 
 |  | 
 |       /* Get targettype of elementtype.  */ | 
 |       while (check_type->code () == TYPE_CODE_RANGE | 
 | 	     || check_type->code () == TYPE_CODE_TYPEDEF) | 
 | 	check_type = check_type->target_type (); | 
 |  | 
 |       if (!get_discrete_bounds (element_type, &low_bound, &high_bound)) | 
 | 	error (_("(power)set type with unknown size")); | 
 |       memset (valaddr, '\0', type->length ()); | 
 |       for (int idx = 0; idx < nargs; idx++) | 
 | 	{ | 
 | 	  LONGEST range_low, range_high; | 
 | 	  struct type *range_low_type, *range_high_type; | 
 | 	  struct value *elem_val; | 
 |  | 
 | 	  elem_val = in_args[idx]->evaluate (element_type, exp, noside); | 
 | 	  range_low_type = range_high_type = elem_val->type (); | 
 | 	  range_low = range_high = value_as_long (elem_val); | 
 |  | 
 | 	  /* Check types of elements to avoid mixture of elements from | 
 | 	     different types. Also check if type of element is "compatible" | 
 | 	     with element type of powerset.  */ | 
 | 	  if (range_low_type->code () == TYPE_CODE_RANGE) | 
 | 	    range_low_type = range_low_type->target_type (); | 
 | 	  if (range_high_type->code () == TYPE_CODE_RANGE) | 
 | 	    range_high_type = range_high_type->target_type (); | 
 | 	  if ((range_low_type->code () != range_high_type->code ()) | 
 | 	      || (range_low_type->code () == TYPE_CODE_ENUM | 
 | 		  && (range_low_type != range_high_type))) | 
 | 	    /* different element modes.  */ | 
 | 	    error (_("POWERSET tuple elements of different mode")); | 
 | 	  if ((check_type->code () != range_low_type->code ()) | 
 | 	      || (check_type->code () == TYPE_CODE_ENUM | 
 | 		  && range_low_type != check_type)) | 
 | 	    error (_("incompatible POWERSET tuple elements")); | 
 | 	  if (range_low > range_high) | 
 | 	    { | 
 | 	      warning (_("empty POWERSET tuple range")); | 
 | 	      continue; | 
 | 	    } | 
 | 	  if (range_low < low_bound || range_high > high_bound) | 
 | 	    error (_("POWERSET tuple element out of range")); | 
 | 	  range_low -= low_bound; | 
 | 	  range_high -= low_bound; | 
 | 	  for (; range_low <= range_high; range_low++) | 
 | 	    { | 
 | 	      int bit_index = (unsigned) range_low % TARGET_CHAR_BIT; | 
 |  | 
 | 	      if (gdbarch_byte_order (exp->gdbarch) == BFD_ENDIAN_BIG) | 
 | 		bit_index = TARGET_CHAR_BIT - 1 - bit_index; | 
 | 	      valaddr[(unsigned) range_low / TARGET_CHAR_BIT] | 
 | 		|= 1 << bit_index; | 
 | 	    } | 
 | 	} | 
 |       return set; | 
 |     } | 
 |  | 
 |   std::vector<value *> argvec (nargs); | 
 |   for (int tem = 0; tem < nargs; tem++) | 
 |     { | 
 |       /* Ensure that array expressions are coerced into pointer | 
 | 	 objects.  */ | 
 |       argvec[tem] = in_args[tem]->evaluate_with_coercion (exp, noside); | 
 |     } | 
 |   return value_array (provided_low_bound, argvec); | 
 | } | 
 |  | 
 | value * | 
 | unop_extract_operation::evaluate (struct type *expect_type, | 
 | 				  struct expression *exp, | 
 | 				  enum noside noside) | 
 | { | 
 |   value *old_value = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | 
 |   struct type *type = get_type (); | 
 |  | 
 |   if (type->length () > old_value->type ()->length ()) | 
 |     error (_("length type is larger than the value type")); | 
 |  | 
 |   struct value *result = value::allocate (type); | 
 |   old_value->contents_copy (result, 0, 0, type->length ()); | 
 |   return result; | 
 | } | 
 |  | 
 | } | 
 |  | 
 |  | 
 | /* Helper for evaluate_subexp_for_address.  */ | 
 |  | 
 | static value * | 
 | evaluate_subexp_for_address_base (struct expression *exp, enum noside noside, | 
 | 				  value *x) | 
 | { | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     { | 
 |       struct type *type = check_typedef (x->type ()); | 
 |  | 
 |       if (TYPE_IS_REFERENCE (type)) | 
 | 	return value::zero (lookup_pointer_type (type->target_type ()), | 
 | 			   not_lval); | 
 |       else if (x->lval () == lval_memory || value_must_coerce_to_target (x)) | 
 | 	return value::zero (lookup_pointer_type (x->type ()), | 
 | 			   not_lval); | 
 |       else | 
 | 	error (_("Attempt to take address of " | 
 | 		 "value not located in memory.")); | 
 |     } | 
 |   return value_addr (x); | 
 | } | 
 |  | 
 | namespace expr | 
 | { | 
 |  | 
 | value * | 
 | operation::evaluate_for_cast (struct type *expect_type, | 
 | 			      struct expression *exp, | 
 | 			      enum noside noside) | 
 | { | 
 |   value *val = evaluate (expect_type, exp, noside); | 
 |   return value_cast (expect_type, val); | 
 | } | 
 |  | 
 | value * | 
 | operation::evaluate_for_address (struct expression *exp, enum noside noside) | 
 | { | 
 |   value *val = evaluate (nullptr, exp, noside); | 
 |   return evaluate_subexp_for_address_base (exp, noside, val); | 
 | } | 
 |  | 
 | value * | 
 | scope_operation::evaluate_for_address (struct expression *exp, | 
 | 				       enum noside noside) | 
 | { | 
 |   value *x = value_aggregate_elt (std::get<0> (m_storage), | 
 | 				  std::get<1> (m_storage).c_str (), | 
 | 				  NULL, 1, noside); | 
 |   if (x == NULL) | 
 |     error (_("There is no field named %s"), std::get<1> (m_storage).c_str ()); | 
 |   return x; | 
 | } | 
 |  | 
 | value * | 
 | unop_ind_base_operation::evaluate_for_address (struct expression *exp, | 
 | 					       enum noside noside) | 
 | { | 
 |   value *x = std::get<0> (m_storage)->evaluate (nullptr, exp, noside); | 
 |  | 
 |   /* We can't optimize out "&*" if there's a user-defined operator*.  */ | 
 |   if (unop_user_defined_p (UNOP_IND, x)) | 
 |     { | 
 |       x = value_x_unop (x, UNOP_IND, noside); | 
 |       return evaluate_subexp_for_address_base (exp, noside, x); | 
 |     } | 
 |  | 
 |   return coerce_array (x); | 
 | } | 
 |  | 
 | value * | 
 | var_msym_value_operation::evaluate_for_address (struct expression *exp, | 
 | 						enum noside noside) | 
 | { | 
 |   const bound_minimal_symbol &b = std::get<0> (m_storage); | 
 |   value *val = evaluate_var_msym_value (noside, b.objfile, b.minsym); | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     { | 
 |       struct type *type = lookup_pointer_type (val->type ()); | 
 |       return value::zero (type, not_lval); | 
 |     } | 
 |   else | 
 |     return value_addr (val); | 
 | } | 
 |  | 
 | value * | 
 | unop_memval_operation::evaluate_for_address (struct expression *exp, | 
 | 					     enum noside noside) | 
 | { | 
 |   return value_cast (lookup_pointer_type (std::get<1> (m_storage)), | 
 | 		     std::get<0> (m_storage)->evaluate (nullptr, exp, noside)); | 
 | } | 
 |  | 
 | value * | 
 | unop_memval_type_operation::evaluate_for_address (struct expression *exp, | 
 | 						  enum noside noside) | 
 | { | 
 |   value *typeval = std::get<0> (m_storage)->evaluate (nullptr, exp, | 
 | 						      EVAL_AVOID_SIDE_EFFECTS); | 
 |   struct type *type = typeval->type (); | 
 |   return value_cast (lookup_pointer_type (type), | 
 | 		     std::get<1> (m_storage)->evaluate (nullptr, exp, noside)); | 
 | } | 
 |  | 
 | value * | 
 | var_value_operation::evaluate_for_address (struct expression *exp, | 
 | 					   enum noside noside) | 
 | { | 
 |   symbol *var = std::get<0> (m_storage).symbol; | 
 |  | 
 |   /* C++: The "address" of a reference should yield the address | 
 |    * of the object pointed to.  Let value_addr() deal with it.  */ | 
 |   if (TYPE_IS_REFERENCE (var->type ())) | 
 |     return operation::evaluate_for_address (exp, noside); | 
 |  | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     { | 
 |       struct type *type = lookup_pointer_type (var->type ()); | 
 |       enum address_class sym_class = var->aclass (); | 
 |  | 
 |       if (sym_class == LOC_CONST | 
 | 	  || sym_class == LOC_CONST_BYTES | 
 | 	  || sym_class == LOC_REGISTER) | 
 | 	error (_("Attempt to take address of register or constant.")); | 
 |  | 
 |       return value::zero (type, not_lval); | 
 |     } | 
 |   else | 
 |     return address_of_variable (var, std::get<0> (m_storage).block); | 
 | } | 
 |  | 
 | value * | 
 | var_value_operation::evaluate_with_coercion (struct expression *exp, | 
 | 					     enum noside noside) | 
 | { | 
 |   struct symbol *var = std::get<0> (m_storage).symbol; | 
 |   struct type *type = check_typedef (var->type ()); | 
 |   if (type->code () == TYPE_CODE_ARRAY | 
 |       && !type->is_vector () | 
 |       && CAST_IS_CONVERSION (exp->language_defn)) | 
 |     { | 
 |       struct value *val = address_of_variable (var, | 
 | 					       std::get<0> (m_storage).block); | 
 |       return value_cast (lookup_pointer_type (type->target_type ()), val); | 
 |     } | 
 |   return evaluate (nullptr, exp, noside); | 
 | } | 
 |  | 
 | } | 
 |  | 
 | /* Helper function for evaluating the size of a type.  */ | 
 |  | 
 | static value * | 
 | evaluate_subexp_for_sizeof_base (struct expression *exp, struct type *type) | 
 | { | 
 |   /* FIXME: This should be size_t.  */ | 
 |   struct type *size_type = builtin_type (exp->gdbarch)->builtin_int; | 
 |   /* $5.3.3/2 of the C++ Standard (n3290 draft) says of sizeof: | 
 |      "When applied to a reference or a reference type, the result is | 
 |      the size of the referenced type."  */ | 
 |   type = check_typedef (type); | 
 |   if (exp->language_defn->la_language == language_cplus | 
 |       && (TYPE_IS_REFERENCE (type))) | 
 |     type = check_typedef (type->target_type ()); | 
 |   else if (exp->language_defn->la_language == language_fortran | 
 | 	   && type->code () == TYPE_CODE_PTR) | 
 |     { | 
 |       /* Dereference Fortran pointer types to allow them for the Fortran | 
 | 	 sizeof intrinsic.  */ | 
 |       type = check_typedef (type->target_type ()); | 
 |     } | 
 |   return value_from_longest (size_type, (LONGEST) type->length ()); | 
 | } | 
 |  | 
 | namespace expr | 
 | { | 
 |  | 
 | value * | 
 | operation::evaluate_for_sizeof (struct expression *exp, enum noside noside) | 
 | { | 
 |   value *val = evaluate (nullptr, exp, EVAL_AVOID_SIDE_EFFECTS); | 
 |   return evaluate_subexp_for_sizeof_base (exp, val->type ()); | 
 | } | 
 |  | 
 | value * | 
 | var_msym_value_operation::evaluate_for_sizeof (struct expression *exp, | 
 | 					       enum noside noside) | 
 |  | 
 | { | 
 |   const bound_minimal_symbol &b = std::get<0> (m_storage); | 
 |   value *mval = evaluate_var_msym_value (noside, b.objfile, b.minsym); | 
 |  | 
 |   struct type *type = mval->type (); | 
 |   if (type->code () == TYPE_CODE_ERROR) | 
 |     error_unknown_type (b.minsym->print_name ()); | 
 |  | 
 |   /* FIXME: This should be size_t.  */ | 
 |   struct type *size_type = builtin_type (exp->gdbarch)->builtin_int; | 
 |   return value_from_longest (size_type, type->length ()); | 
 | } | 
 |  | 
 | value * | 
 | subscript_operation::evaluate_for_sizeof (struct expression *exp, | 
 | 					  enum noside noside) | 
 | { | 
 |   if (noside == EVAL_NORMAL) | 
 |     { | 
 |       value *val = std::get<0> (m_storage)->evaluate (nullptr, exp, | 
 | 						      EVAL_AVOID_SIDE_EFFECTS); | 
 |       struct type *type = check_typedef (val->type ()); | 
 |       if (type->code () == TYPE_CODE_ARRAY) | 
 | 	{ | 
 | 	  type = check_typedef (type->target_type ()); | 
 | 	  if (type->code () == TYPE_CODE_ARRAY) | 
 | 	    { | 
 | 	      type = type->index_type (); | 
 | 	      /* Only re-evaluate the right hand side if the resulting type | 
 | 		 is a variable length type.  */ | 
 | 	      if (type->bounds ()->flag_bound_evaluated) | 
 | 		{ | 
 | 		  val = evaluate (nullptr, exp, EVAL_NORMAL); | 
 | 		  /* FIXME: This should be size_t.  */ | 
 | 		  struct type *size_type | 
 | 		    = builtin_type (exp->gdbarch)->builtin_int; | 
 | 		  return value_from_longest | 
 | 		    (size_type, (LONGEST) val->type ()->length ()); | 
 | 		} | 
 | 	    } | 
 | 	} | 
 |     } | 
 |  | 
 |   return operation::evaluate_for_sizeof (exp, noside); | 
 | } | 
 |  | 
 | value * | 
 | unop_ind_base_operation::evaluate_for_sizeof (struct expression *exp, | 
 | 					      enum noside noside) | 
 | { | 
 |   value *val = std::get<0> (m_storage)->evaluate (nullptr, exp, | 
 | 						  EVAL_AVOID_SIDE_EFFECTS); | 
 |   struct type *type = check_typedef (val->type ()); | 
 |   if (!type->is_pointer_or_reference () | 
 |       && type->code () != TYPE_CODE_ARRAY) | 
 |     error (_("Attempt to take contents of a non-pointer value.")); | 
 |   type = type->target_type (); | 
 |   if (is_dynamic_type (type)) | 
 |     type = value_ind (val)->type (); | 
 |   /* FIXME: This should be size_t.  */ | 
 |   struct type *size_type = builtin_type (exp->gdbarch)->builtin_int; | 
 |   return value_from_longest (size_type, (LONGEST) type->length ()); | 
 | } | 
 |  | 
 | value * | 
 | unop_memval_operation::evaluate_for_sizeof (struct expression *exp, | 
 | 					    enum noside noside) | 
 | { | 
 |   return evaluate_subexp_for_sizeof_base (exp, std::get<1> (m_storage)); | 
 | } | 
 |  | 
 | value * | 
 | unop_memval_type_operation::evaluate_for_sizeof (struct expression *exp, | 
 | 						 enum noside noside) | 
 | { | 
 |   value *typeval = std::get<0> (m_storage)->evaluate (nullptr, exp, | 
 | 						      EVAL_AVOID_SIDE_EFFECTS); | 
 |   return evaluate_subexp_for_sizeof_base (exp, typeval->type ()); | 
 | } | 
 |  | 
 | value * | 
 | var_value_operation::evaluate_for_sizeof (struct expression *exp, | 
 | 					  enum noside noside) | 
 | { | 
 |   struct type *type = std::get<0> (m_storage).symbol->type (); | 
 |   if (is_dynamic_type (type)) | 
 |     { | 
 |       value *val = evaluate (nullptr, exp, EVAL_NORMAL); | 
 |       type = val->type (); | 
 |       if (type->code () == TYPE_CODE_ARRAY) | 
 | 	{ | 
 | 	  /* FIXME: This should be size_t.  */ | 
 | 	  struct type *size_type = builtin_type (exp->gdbarch)->builtin_int; | 
 | 	  if (type_not_allocated (type) || type_not_associated (type)) | 
 | 	    return value::zero (size_type, not_lval); | 
 | 	  else if (is_dynamic_type (type->index_type ()) | 
 | 		   && !type->bounds ()->high.is_available ()) | 
 | 	    return value::allocate_optimized_out (size_type); | 
 | 	} | 
 |     } | 
 |   return evaluate_subexp_for_sizeof_base (exp, type); | 
 | } | 
 |  | 
 | value * | 
 | var_msym_value_operation::evaluate_for_cast (struct type *to_type, | 
 | 					     struct expression *exp, | 
 | 					     enum noside noside) | 
 | { | 
 |   if (noside == EVAL_AVOID_SIDE_EFFECTS) | 
 |     return value::zero (to_type, not_lval); | 
 |  | 
 |   const bound_minimal_symbol &b = std::get<0> (m_storage); | 
 |   value *val = evaluate_var_msym_value (noside, b.objfile, b.minsym); | 
 |  | 
 |   val = value_cast (to_type, val); | 
 |  | 
 |   /* Don't allow e.g. '&(int)var_with_no_debug_info'.  */ | 
 |   if (val->lval () == lval_memory) | 
 |     { | 
 |       if (val->lazy ()) | 
 | 	val->fetch_lazy (); | 
 |       val->set_lval (not_lval); | 
 |     } | 
 |   return val; | 
 | } | 
 |  | 
 | value * | 
 | var_value_operation::evaluate_for_cast (struct type *to_type, | 
 | 					struct expression *exp, | 
 | 					enum noside noside) | 
 | { | 
 |   value *val = evaluate_var_value (noside, | 
 | 				   std::get<0> (m_storage).block, | 
 | 				   std::get<0> (m_storage).symbol); | 
 |  | 
 |   val = value_cast (to_type, val); | 
 |  | 
 |   /* Don't allow e.g. '&(int)var_with_no_debug_info'.  */ | 
 |   if (val->lval () == lval_memory) | 
 |     { | 
 |       if (val->lazy ()) | 
 | 	val->fetch_lazy (); | 
 |       val->set_lval (not_lval); | 
 |     } | 
 |   return val; | 
 | } | 
 |  | 
 | } | 
 |  | 
 | /* Parse a type expression in the string [P..P+LENGTH).  */ | 
 |  | 
 | struct type * | 
 | parse_and_eval_type (const char *p, int length) | 
 | { | 
 |   char *tmp = (char *) alloca (length + 4); | 
 |  | 
 |   tmp[0] = '('; | 
 |   memcpy (tmp + 1, p, length); | 
 |   tmp[length + 1] = ')'; | 
 |   tmp[length + 2] = '0'; | 
 |   tmp[length + 3] = '\0'; | 
 |   expression_up expr = parse_expression (tmp); | 
 |   expr::unop_cast_operation *op | 
 |     = dynamic_cast<expr::unop_cast_operation *> (expr->op.get ()); | 
 |   if (op == nullptr) | 
 |     error (_("Internal error in eval_type.")); | 
 |   return op->get_type (); | 
 | } |