2010-03-15 Stan Shebs <stan@codesourcery.com>
authorStan Shebs <shebs@codesourcery.com>
Mon, 15 Mar 2010 23:53:21 +0000 (23:53 +0000)
committerStan Shebs <shebs@codesourcery.com>
Mon, 15 Mar 2010 23:53:21 +0000 (23:53 +0000)
* ax-gdb.c: Include cp-support.h.
(find_field): Remove.
(gen_primitive_field): New function.
(gen_struct_ref_recursive): New function.
(gen_struct_ref): Rewrite to call gen_struct_ref_recursive instead
of find_field.
(gen_static_field): New function.
(gen_struct_elt_for_reference): New.
(gen_namespace_elt): New.
(gen_maybe_namespace_elt): New.
(gen_aggregate_elt_ref): New.
(gen_expr): Add OP_SCOPE, display opcode name in error message.

gdb/ChangeLog
gdb/ax-gdb.c

index 31745c6db78e2f364b87714c5636e83051aeb054..e77c2ba32ca1d22430ea43f21870d6e3e0004798 100644 (file)
@@ -1,3 +1,18 @@
+2010-03-15 Stan Shebs  <stan@codesourcery.com>
+
+       * ax-gdb.c: Include cp-support.h.
+       (find_field): Remove.
+       (gen_primitive_field): New function.
+       (gen_struct_ref_recursive): New function.
+       (gen_struct_ref): Rewrite to call gen_struct_ref_recursive instead
+       of find_field.
+       (gen_static_field): New function.
+       (gen_struct_elt_for_reference): New.
+       (gen_namespace_elt): New.
+       (gen_maybe_namespace_elt): New.
+       (gen_aggregate_elt_ref): New.
+       (gen_expr): Add OP_SCOPE, display opcode name in error message.
+
 2010-03-15  Tom Tromey  <tromey@redhat.com>
 
        * dwarf2read.c (die_needs_namespace): Also return 0 for
index 4c273468686b26f1db213d8f3c849a77116e3df6..5e22422a7b7ada9daaafc60e8d1e4629a7c1a536 100644 (file)
@@ -39,6 +39,7 @@
 #include "dictionary.h"
 #include "breakpoint.h"
 #include "tracepoint.h"
+#include "cp-support.h"
 
 /* To make sense of this file, you should read doc/agentexpr.texi.
    Then look at the types and enums in ax-gdb.h.  For the code itself,
@@ -127,14 +128,25 @@ static void gen_logical_not (struct agent_expr *ax, struct axs_value *value,
 static void gen_complement (struct agent_expr *ax, struct axs_value *value);
 static void gen_deref (struct agent_expr *, struct axs_value *);
 static void gen_address_of (struct agent_expr *, struct axs_value *);
-static int find_field (struct type *type, char *name);
 static void gen_bitfield_ref (struct expression *exp, struct agent_expr *ax,
                              struct axs_value *value,
                              struct type *type, int start, int end);
+static void gen_primitive_field (struct expression *exp,
+                                struct agent_expr *ax,
+                                struct axs_value *value,
+                                int offset, int fieldno, struct type *type);
+static int gen_struct_ref_recursive (struct expression *exp,
+                                    struct agent_expr *ax,
+                                    struct axs_value *value,
+                                    char *field, int offset,
+                                    struct type *type);
 static void gen_struct_ref (struct expression *exp, struct agent_expr *ax,
                            struct axs_value *value,
                            char *field,
                            char *operator_name, char *operand_name);
+static void gen_static_field (struct expression *exp,
+                             struct agent_expr *ax, struct axs_value *value,
+                             struct type *type, int fieldno);
 static void gen_repeat (struct expression *exp, union exp_element **pc,
                        struct agent_expr *ax, struct axs_value *value);
 static void gen_sizeof (struct expression *exp, union exp_element **pc,
@@ -1116,46 +1128,6 @@ gen_address_of (struct agent_expr *ax, struct axs_value *value)
       }
 }
 
-
-/* A lot of this stuff will have to change to support C++.  But we're
-   not going to deal with that at the moment.  */
-
-/* Find the field in the structure type TYPE named NAME, and return
-   its index in TYPE's field array.  */
-static int
-find_field (struct type *type, char *name)
-{
-  int i;
-
-  CHECK_TYPEDEF (type);
-
-  /* Make sure this isn't C++.  */
-  if (TYPE_N_BASECLASSES (type) != 0)
-    internal_error (__FILE__, __LINE__,
-                   _("find_field: derived classes supported"));
-
-  for (i = 0; i < TYPE_NFIELDS (type); i++)
-    {
-      char *this_name = TYPE_FIELD_NAME (type, i);
-
-      if (this_name)
-       {
-         if (strcmp (name, this_name) == 0)
-           return i;
-
-         if (this_name[0] == '\0')
-           internal_error (__FILE__, __LINE__,
-                           _("find_field: anonymous unions not supported"));
-       }
-    }
-
-  error (_("Couldn't find member named `%s' in struct/union `%s'"),
-        name, TYPE_TAG_NAME (type));
-
-  return 0;
-}
-
-
 /* Generate code to push the value of a bitfield of a structure whose
    address is on the top of the stack.  START and END give the
    starting and one-past-ending *bit* numbers of the field within the
@@ -1316,6 +1288,90 @@ gen_bitfield_ref (struct expression *exp, struct agent_expr *ax,
   value->type = type;
 }
 
+/* Generate bytecodes for field number FIELDNO of type TYPE.  OFFSET
+   is an accumulated offset (in bytes), will be nonzero for objects
+   embedded in other objects, like C++ base classes.  Behavior should
+   generally follow value_primitive_field.  */
+
+static void
+gen_primitive_field (struct expression *exp,
+                    struct agent_expr *ax, struct axs_value *value,
+                    int offset, int fieldno, struct type *type)
+{
+  /* Is this a bitfield?  */
+  if (TYPE_FIELD_PACKED (type, fieldno))
+    gen_bitfield_ref (exp, ax, value, TYPE_FIELD_TYPE (type, fieldno),
+                     (offset * TARGET_CHAR_BIT
+                      + TYPE_FIELD_BITPOS (type, fieldno)),
+                     (offset * TARGET_CHAR_BIT
+                      + TYPE_FIELD_BITPOS (type, fieldno)
+                      + TYPE_FIELD_BITSIZE (type, fieldno)));
+  else
+    {
+      gen_offset (ax, offset
+                 + TYPE_FIELD_BITPOS (type, fieldno) / TARGET_CHAR_BIT);
+      value->kind = axs_lvalue_memory;
+      value->type = TYPE_FIELD_TYPE (type, fieldno);
+    }
+}
+
+/* Search for the given field in either the given type or one of its
+   base classes.  Return 1 if found, 0 if not.  */
+
+static int
+gen_struct_ref_recursive (struct expression *exp, struct agent_expr *ax,
+                         struct axs_value *value,
+                         char *field, int offset, struct type *type)
+{
+  int i, rslt;
+  int nbases = TYPE_N_BASECLASSES (type);
+
+  CHECK_TYPEDEF (type);
+
+  for (i = TYPE_NFIELDS (type) - 1; i >= nbases; i--)
+    {
+      char *this_name = TYPE_FIELD_NAME (type, i);
+
+      if (this_name)
+       {
+         if (strcmp (field, this_name) == 0)
+           {
+             /* Note that bytecodes for the struct's base (aka
+                "this") will have been generated already, which will
+                be unnecessary but not harmful if the static field is
+                being handled as a global.  */
+             if (field_is_static (&TYPE_FIELD (type, i)))
+               {
+                 gen_static_field (exp, ax, value, type, i);
+                 return 1;
+               }
+
+             gen_primitive_field (exp, ax, value, offset, i, type);
+             return 1;
+           }
+#if 0 /* is this right? */
+         if (this_name[0] == '\0')
+           internal_error (__FILE__, __LINE__,
+                           _("find_field: anonymous unions not supported"));
+#endif
+       }
+    }
+
+  /* Now scan through base classes recursively.  */
+  for (i = 0; i < nbases; i++)
+    {
+      struct type *basetype = check_typedef (TYPE_BASECLASS (type, i));
+
+      rslt = gen_struct_ref_recursive (exp, ax, value, field,
+                                      offset + TYPE_BASECLASS_BITPOS (type, i) / TARGET_CHAR_BIT,
+                                      basetype);
+      if (rslt)
+       return 1;
+    }
+
+  /* Not found anywhere, flag so caller can complain.  */
+  return 0;
+}
 
 /* Generate code to reference the member named FIELD of a structure or
    union.  The top of the stack, as described by VALUE, should have
@@ -1328,7 +1384,7 @@ gen_struct_ref (struct expression *exp, struct agent_expr *ax,
                char *operator_name, char *operand_name)
 {
   struct type *type;
-  int i;
+  int found;
 
   /* Follow pointers until we reach a non-pointer.  These aren't the C
      semantics, but they're what the normal GDB evaluator does, so we
@@ -1351,22 +1407,151 @@ gen_struct_ref (struct expression *exp, struct agent_expr *ax,
   if (value->kind != axs_lvalue_memory)
     error (_("Structure does not live in memory."));
 
-  i = find_field (type, field);
+  /* Search through fields and base classes recursively.  */
+  found = gen_struct_ref_recursive (exp, ax, value, field, 0, type);
+  
+  if (!found)
+    error (_("Couldn't find member named `%s' in struct/union/class `%s'"),
+          field, TYPE_TAG_NAME (type));
+}
 
-  /* Is this a bitfield?  */
-  if (TYPE_FIELD_PACKED (type, i))
-    gen_bitfield_ref (exp, ax, value, TYPE_FIELD_TYPE (type, i),
-                     TYPE_FIELD_BITPOS (type, i),
-                     (TYPE_FIELD_BITPOS (type, i)
-                      + TYPE_FIELD_BITSIZE (type, i)));
-  else
+static int
+gen_namespace_elt (struct expression *exp,
+                  struct agent_expr *ax, struct axs_value *value,
+                  const struct type *curtype, char *name);
+static int
+gen_maybe_namespace_elt (struct expression *exp,
+                        struct agent_expr *ax, struct axs_value *value,
+                        const struct type *curtype, char *name);
+
+static void
+gen_static_field (struct expression *exp,
+                 struct agent_expr *ax, struct axs_value *value,
+                 struct type *type, int fieldno)
+{
+  if (TYPE_FIELD_LOC_KIND (type, fieldno) == FIELD_LOC_KIND_PHYSADDR)
     {
-      gen_offset (ax, TYPE_FIELD_BITPOS (type, i) / TARGET_CHAR_BIT);
+      ax_const_l (ax, TYPE_FIELD_STATIC_PHYSADDR (type, fieldno));
       value->kind = axs_lvalue_memory;
-      value->type = TYPE_FIELD_TYPE (type, i);
+      value->type = TYPE_FIELD_TYPE (type, fieldno);
+    }
+  else
+    {
+      char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno);
+      struct symbol *sym = lookup_symbol (phys_name, 0, VAR_DOMAIN, 0);
+      if (sym == NULL)
+       error (_("symbol not found"));
+
+      gen_var_ref (exp->gdbarch, ax, value, sym);
+    }
+}
+
+static int
+gen_struct_elt_for_reference (struct expression *exp,
+                             struct agent_expr *ax, struct axs_value *value,
+                             struct type *type, char *fieldname)
+{
+  struct type *t = type;
+  int i;
+  struct value *v, *result;
+
+  if (TYPE_CODE (t) != TYPE_CODE_STRUCT
+      && TYPE_CODE (t) != TYPE_CODE_UNION)
+    internal_error (__FILE__, __LINE__,
+                   _("non-aggregate type to gen_struct_elt_for_reference"));
+
+  for (i = TYPE_NFIELDS (t) - 1; i >= TYPE_N_BASECLASSES (t); i--)
+    {
+      char *t_field_name = TYPE_FIELD_NAME (t, i);
+
+      if (t_field_name && strcmp (t_field_name, fieldname) == 0)
+       {
+         if (field_is_static (&TYPE_FIELD (t, i)))
+           {
+             gen_static_field (exp, ax, value, t, i);
+             return 1;
+           }
+         if (TYPE_FIELD_PACKED (t, i))
+           error (_("pointers to bitfield members not allowed"));
+
+         /* FIXME we need a way to do "want_address" equivalent */       
+
+         error (_("Cannot reference non-static field \"%s\""), fieldname);
+       }
     }
+
+  /* FIXME add other scoped-reference cases here */
+
+  /* Do a last-ditch lookup.  */
+  return gen_maybe_namespace_elt (exp, ax, value, type, fieldname);
 }
 
+/* C++: Return the member NAME of the namespace given by the type
+   CURTYPE.  */
+
+static int
+gen_namespace_elt (struct expression *exp,
+                  struct agent_expr *ax, struct axs_value *value,
+                  const struct type *curtype, char *name)
+{
+  int found = gen_maybe_namespace_elt (exp, ax, value, curtype, name);
+
+  if (!found)
+    error (_("No symbol \"%s\" in namespace \"%s\"."), 
+          name, TYPE_TAG_NAME (curtype));
+
+  return found;
+}
+
+/* A helper function used by value_namespace_elt and
+   value_struct_elt_for_reference.  It looks up NAME inside the
+   context CURTYPE; this works if CURTYPE is a namespace or if CURTYPE
+   is a class and NAME refers to a type in CURTYPE itself (as opposed
+   to, say, some base class of CURTYPE).  */
+
+static int
+gen_maybe_namespace_elt (struct expression *exp,
+                        struct agent_expr *ax, struct axs_value *value,
+                        const struct type *curtype, char *name)
+{
+  const char *namespace_name = TYPE_TAG_NAME (curtype);
+  struct symbol *sym;
+
+  sym = cp_lookup_symbol_namespace (namespace_name, name,
+                                   block_for_pc (ax->scope),
+                                   VAR_DOMAIN, 0);
+
+  if (sym == NULL)
+    return 0;
+
+  gen_var_ref (exp->gdbarch, ax, value, sym);
+
+  return 1;
+}
+
+
+static int
+gen_aggregate_elt_ref (struct expression *exp,
+                      struct agent_expr *ax, struct axs_value *value,
+                      struct type *type, char *field,
+                      char *operator_name, char *operand_name)
+{
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_STRUCT:
+    case TYPE_CODE_UNION:
+      return gen_struct_elt_for_reference (exp, ax, value, type, field);
+      break;
+    case TYPE_CODE_NAMESPACE:
+      return gen_namespace_elt (exp, ax, value, type, field);
+      break;
+    default:
+      internal_error (__FILE__, __LINE__,
+                     _("non-aggregate type in gen_aggregate_elt_ref"));
+    }
+
+  return 0;
+}
 
 /* Generate code for GDB's magical `repeat' operator.  
    LVALUE @ INT creates an array INT elements long, and whose elements
@@ -1823,11 +2008,27 @@ gen_expr (struct expression *exp, union exp_element **pc,
       }
       break;
 
+    case OP_SCOPE:
+      {
+       struct type *type = (*pc)[1].type;
+       int length = longest_to_int ((*pc)[2].longconst);
+       char *name = &(*pc)[3].string;
+       int found;
+
+       found = gen_aggregate_elt_ref (exp, ax, value, type, name,
+                                      "?", "??");
+       if (!found)
+         error (_("There is no field named %s"), name);
+       (*pc) += 5 + BYTES_TO_EXP_ELEM (length + 1);
+      }
+      break;
+
     case OP_TYPE:
       error (_("Attempt to use a type name as an expression."));
 
     default:
-      error (_("Unsupported operator in expression."));
+      error (_("Unsupported operator %s (%d) in expression."),
+            op_string (op), op);
     }
 }