Fetch the NT_ARM_TLS register set for native FreeBSD/arm processes.
[binutils-gdb.git] / gdb / eval.c
index b7b8915fa89cd618f5980a034a22b1634c881454..ce1d883aa86bc5071e36a5cd08015e582076a36b 100644 (file)
@@ -967,6 +967,93 @@ structop_base_operation::evaluate_funcall
                                  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 = value_type (lhs);
+  for (;;)
+    {
+      type = check_typedef (type);
+      if (!type->is_pointer_or_reference ())
+       break;
+      type = TYPE_TARGET_TYPE (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 */
 
@@ -1106,18 +1193,6 @@ eval_op_objc_selector (struct type *expect_type, struct expression *exp,
                             lookup_child_selector (exp->gdbarch, sel));
 }
 
-/* Helper function that implements the body of BINOP_CONCAT.  */
-
-struct value *
-eval_op_concat (struct type *expect_type, struct expression *exp,
-               enum noside noside, struct value *arg1, struct value *arg2)
-{
-  if (binop_user_defined_p (BINOP_CONCAT, arg1, arg2))
-    return value_x_binop (arg1, arg2, BINOP_CONCAT, OP_NULL, noside);
-  else
-    return value_concat (arg1, arg2);
-}
-
 /* A helper function for TERNOP_SLICE.  */
 
 struct value *
@@ -2472,6 +2547,22 @@ array_operation::evaluate (struct type *expect_type,
   return value_array (tem2, tem3, 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 (type) > TYPE_LENGTH (value_type (old_value)))
+    error (_("length type is larger than the value type"));
+
+  struct value *result = allocate_value (type);
+  value_contents_copy (result, 0, old_value, 0, TYPE_LENGTH (type));
+  return result;
+}
+
 }
 
 \f