gdb/
[binutils-gdb.git] / gdb / valops.c
index ca3408345b61f681a2e37ec970862eb1f7445932..4a7a3349adb2a4af75167f3978bfb050dc488a10 100644 (file)
@@ -53,12 +53,12 @@ extern int overload_debug;
 static int typecmp (int staticp, int varargs, int nargs,
                    struct field t1[], struct value *t2[]);
 
-static struct value *search_struct_field (char *, struct value *, 
+static struct value *search_struct_field (const char *, struct value *, 
                                          int, struct type *, int);
 
-static struct value *search_struct_method (char *, struct value **,
-                                      struct value **,
-                                      int, int *, struct type *);
+static struct value *search_struct_method (const char *, struct value **,
+                                          struct value **,
+                                          int, int *, struct type *);
 
 static int find_oload_champ_namespace (struct type **, int,
                                       const char *, const char *,
@@ -100,7 +100,7 @@ static CORE_ADDR allocate_space_in_inferior (int);
 
 static struct value *cast_into_complex (struct type *, struct value *);
 
-static struct fn_field *find_method_list (struct value **, char *,
+static struct fn_field *find_method_list (struct value **, const char *,
                                          int, struct type *, int *,
                                          struct type **, int *);
 
@@ -250,10 +250,33 @@ value_cast_structs (struct type *type, struct value *v2)
 
   /* Downcasting: look in the type of the target to see if it contains the
      type of the source as a superclass.  If so, we'll need to
-     offset the pointer rather than just change its type.
-     FIXME: This fails silently with virtual inheritance.  */
+     offset the pointer rather than just change its type.  */
   if (TYPE_NAME (t2) != NULL)
     {
+      /* Try downcasting using the run-time type of the value.  */
+      int full, top, using_enc;
+      struct type *real_type;
+
+      real_type = value_rtti_type (v2, &full, &top, &using_enc);
+      if (real_type)
+       {
+         v = value_full_object (v2, real_type, full, top, using_enc);
+         v = value_at_lazy (real_type, value_address (v));
+
+         /* We might be trying to cast to the outermost enclosing
+            type, in which case search_struct_field won't work.  */
+         if (TYPE_NAME (real_type) != NULL
+             && !strcmp (TYPE_NAME (real_type), TYPE_NAME (t1)))
+           return v;
+
+         v = search_struct_field (type_name_no_tag (t2), v, 0, real_type, 1);
+         if (v)
+           return v;
+       }
+
+      /* Try downcasting using information from the destination type
+        T2.  This wouldn't work properly for classes with virtual
+        bases, but those were handled above.  */
       v = search_struct_field (type_name_no_tag (t2),
                               value_zero (t1, not_lval), 0, t1, 1);
       if (v)
@@ -1783,13 +1806,14 @@ typecmp (int staticp, int varargs, int nargs,
    fields, look for a baseclass named NAME.  */
 
 static struct value *
-search_struct_field (char *name, struct value *arg1, int offset,
+search_struct_field (const char *name, struct value *arg1, int offset,
                     struct type *type, int looking_for_baseclass)
 {
   int i;
-  int nbases = TYPE_N_BASECLASSES (type);
+  int nbases;
 
   CHECK_TYPEDEF (type);
+  nbases = TYPE_N_BASECLASSES (type);
 
   if (!looking_for_baseclass)
     for (i = TYPE_NFIELDS (type) - 1; i >= nbases; i--)
@@ -1879,7 +1903,9 @@ search_struct_field (char *name, struct value *arg1, int offset,
 
          boffset = baseclass_offset (type, i,
                                      value_contents (arg1) + offset,
-                                     value_address (arg1) + offset);
+                                     value_address (arg1)
+                                     + value_embedded_offset (arg1)
+                                     + offset);
          if (boffset == -1)
            error (_("virtual baseclass botch"));
 
@@ -1887,8 +1913,9 @@ search_struct_field (char *name, struct value *arg1, int offset,
             by the user program. Make sure that it still points to a
             valid memory location.  */
 
-         boffset += offset;
-         if (boffset < 0 || boffset >= TYPE_LENGTH (type))
+         boffset += value_embedded_offset (arg1) + offset;
+         if (boffset < 0
+             || boffset >= TYPE_LENGTH (value_enclosing_type (arg1)))
            {
              CORE_ADDR base_addr;
 
@@ -1903,18 +1930,9 @@ search_struct_field (char *name, struct value *arg1, int offset,
            }
          else
            {
-             if (VALUE_LVAL (arg1) == lval_memory && value_lazy (arg1))
-               v2  = allocate_value_lazy (basetype);
-             else
-               {
-                 v2  = allocate_value (basetype);
-                 memcpy (value_contents_raw (v2),
-                         value_contents_raw (arg1) + boffset,
-                         TYPE_LENGTH (basetype));
-               }
-             set_value_component_location (v2, arg1);
-             VALUE_FRAME_ID (v2) = VALUE_FRAME_ID (arg1);
-             set_value_offset (v2, value_offset (arg1) + boffset);
+             v2 = value_copy (arg1);
+             deprecated_set_value_type (v2, basetype);
+             set_value_embedded_offset (v2, boffset);
            }
 
          if (found_baseclass)
@@ -1945,7 +1963,7 @@ search_struct_field (char *name, struct value *arg1, int offset,
    (value) -1, else return NULL.  */
 
 static struct value *
-search_struct_method (char *name, struct value **arg1p,
+search_struct_method (const char *name, struct value **arg1p,
                      struct value **args, int offset,
                      int *static_memfuncp, struct type *type)
 {
@@ -2075,7 +2093,7 @@ search_struct_method (char *name, struct value **arg1p,
 
 struct value *
 value_struct_elt (struct value **argp, struct value **args,
-                 char *name, int *static_memfuncp, char *err)
+                 const char *name, int *static_memfuncp, const char *err)
 {
   struct type *t;
   struct value *v;
@@ -2170,7 +2188,7 @@ value_struct_elt (struct value **argp, struct value **args,
 */
 
 static struct fn_field *
-find_method_list (struct value **argp, char *method,
+find_method_list (struct value **argp, const char *method,
                  int offset, struct type *type, int *num_fns,
                  struct type **basetype, int *boffset)
 {
@@ -2240,7 +2258,7 @@ find_method_list (struct value **argp, char *method,
 */
 
 struct fn_field *
-value_find_oload_method_list (struct value **argp, char *method, 
+value_find_oload_method_list (struct value **argp, const char *method,
                              int offset, int *num_fns, 
                              struct type **basetype, int *boffset)
 {
@@ -2297,7 +2315,7 @@ value_find_oload_method_list (struct value **argp, char *method,
 
 int
 find_overload_match (struct type **arg_types, int nargs, 
-                    char *name, int method, int lax, 
+                    const char *name, int method, int lax, 
                     struct value **objp, struct symbol *fsym,
                     struct value **valp, struct symbol **symp, 
                     int *staticp)
@@ -2328,12 +2346,25 @@ find_overload_match (struct type **arg_types, int nargs,
   if (method)
     {
       gdb_assert (obj);
+
+      /* OBJ may be a pointer value rather than the object itself.  */
+      obj = coerce_ref (obj);
+      while (TYPE_CODE (check_typedef (value_type (obj))) == TYPE_CODE_PTR)
+       obj = coerce_ref (value_ind (obj));
       obj_type_name = TYPE_NAME (value_type (obj));
-      /* Hack: evaluate_subexp_standard often passes in a pointer
-         value rather than the object itself, so try again.  */
-      if ((!obj_type_name || !*obj_type_name) 
-         && (TYPE_CODE (value_type (obj)) == TYPE_CODE_PTR))
-       obj_type_name = TYPE_NAME (TYPE_TARGET_TYPE (value_type (obj)));
+
+      /* First check whether this is a data member, e.g. a pointer to
+        a function.  */
+      if (TYPE_CODE (check_typedef (value_type (obj))) == TYPE_CODE_STRUCT)
+       {
+         *valp = search_struct_field (name, obj, 0,
+                                      check_typedef (value_type (obj)), 0);
+         if (*valp)
+           {
+             *staticp = 1;
+             return 0;
+           }
+       }
 
       fns_ptr = value_find_oload_method_list (&temp, name, 
                                              0, &num_fns, 
@@ -2353,16 +2384,29 @@ find_overload_match (struct type **arg_types, int nargs,
     }
   else
     {
-      const char *qualified_name = SYMBOL_CPLUS_DEMANGLED_NAME (fsym);
+      const char *qualified_name = SYMBOL_NATURAL_NAME (fsym);
+
+      /* If we have a function with a C++ name, try to extract just
+        the function part.  Do not try this for non-functions (e.g.
+        function pointers).  */
+      if (qualified_name
+         && TYPE_CODE (check_typedef (SYMBOL_TYPE (fsym))) == TYPE_CODE_FUNC)
+       {
+         func_name = cp_func_name (qualified_name);
 
-      /* If we have a C++ name, try to extract just the function
-        part.  */
-      if (qualified_name)
-       func_name = cp_func_name (qualified_name);
+         /* If cp_func_name did not remove anything, the name of the
+            symbol did not include scope or argument types - it was
+            probably a C-style function.  */
+         if (func_name && strcmp (func_name, qualified_name) == 0)
+           {
+             xfree (func_name);
+             func_name = NULL;
+           }
+       }
 
-      /* If there was no C++ name, this must be a C-style function.
-        Just return the same symbol.  Do the same if cp_func_name
-        fails for some reason.  */
+      /* If there was no C++ name, this must be a C-style function or
+        not a function at all.  Just return the same symbol.  Do the
+        same if cp_func_name fails for some reason.  */
       if (func_name == NULL)
         {
          *symp = fsym;
@@ -2763,6 +2807,9 @@ check_field (struct type *type, const char *name)
 {
   int i;
 
+  /* The type may be a stub.  */
+  CHECK_TYPEDEF (type);
+
   for (i = TYPE_NFIELDS (type) - 1; i >= TYPE_N_BASECLASSES (type); i--)
     {
       char *t_field_name = TYPE_FIELD_NAME (type, i);
@@ -3096,9 +3143,9 @@ value_maybe_namespace_elt (const struct type *curtype,
   struct symbol *sym;
   struct value *result;
 
-  sym = cp_lookup_symbol_namespace (namespace_name, name, NULL,
+  sym = cp_lookup_symbol_namespace(namespace_name, name,
                                    get_selected_block (0), 
-                                   VAR_DOMAIN);
+                                   VAR_DOMAIN, 1);
 
   if (sym == NULL)
     return NULL;
@@ -3240,7 +3287,7 @@ value_of_local (const char *name, int complain)
 
   /* Calling lookup_block_symbol is necessary to get the LOC_REGISTER
      symbol instead of the LOC_ARG one (if both exist).  */
-  sym = lookup_block_symbol (b, name, NULL, VAR_DOMAIN);
+  sym = lookup_block_symbol (b, name, VAR_DOMAIN);
   if (sym == NULL)
     {
       if (complain)