Stop assuming no-debug-info variables have type int
authorPedro Alves <palves@redhat.com>
Mon, 4 Sep 2017 19:21:15 +0000 (20:21 +0100)
committerPedro Alves <palves@redhat.com>
Mon, 4 Sep 2017 19:21:15 +0000 (20:21 +0100)
An earlier commit made GDB no longer assume no-debug-info functions
return int.  This commit gives the same treatment to variables.

Currently, you can end misled by GDB over output like this:

  (gdb) p var
  $1 = -1
  (gdb) p /x var
  $2 = 0xffffffff

until you realize that GDB is assuming that the variable is an "int",
because:

  (gdb) ptype var
  type = <data variable, no debug info>

You may try to fix it by casting, but that doesn't really help:

  (gdb) p /x (unsigned long long) var
  $3 = 0xffffffffffffffff            # incorrect
         ^^

That's incorrect output, because the variable was defined like this:

  uint64_t var = 0x7fffffffffffffff;
                   ^^

What happened is that with the cast, GDB did an int -> 'unsigned long
long' conversion instead of reinterpreting the variable as the cast-to
type.  To get at the variable properly you have to reinterpret the
variable's address manually instead, with either:

  (gdb) p /x *(unsigned long long *) &var
  $4 = 0x7fffffffffffffff
  (gdb) p /x {unsigned long long} &var
  $5 = 0x7fffffffffffffff

After this commit GDB does it for you.  This is what you'll get
instead:

  (gdb) p var
  'var' has unknown type; cast it to its declared type
  (gdb) p /x (unsigned long long) var
  $1 = 0x7fffffffffffffff

As in the functions patch, the "compile" machinery doesn't currently
have the cast-to type handy, so it continues assuming no-debug
variables have int type, though now at least it warns.

The change to gdb.cp/m-static.exp deserves an explanation:

 - gdb_test "print 'gnu_obj_1::method()::sintvar'" "\\$\[0-9\]+ = 4" \
 + gdb_test "print (int) 'gnu_obj_1::method()::sintvar'" "\\$\[0-9\]+ = 4" \

That's printing the "sintvar" function local static of the
"gnu_obj_1::method()" method.

The problem with that test is that that "'S::method()::static_var'"
syntax doesn't really work in C++ as you'd expect.  The way to make it
work correctly currently is to quote the method part, not the whole
expression, like:

  (gdb) print 'gnu_obj_1::method()'::sintvar

If you wrap the whole expression in quotes, like in m-static.exp, what
really happens is that the parser considers the whole string as a
symbol name, but there's no debug symbol with that name.  However,
local statics have linkage and are given a mangled name that demangles
to the same string as the full expression, so that's what GDB prints.
After this commit, and without the cast, the print in m-static.exp
would error out saying that the variable has unknown type:

  (gdb) p 'gnu_obj_1::method()::sintvar'
  'gnu_obj_1::method()::sintvar' has unknown type; cast it to its declared type

TBC, if currently (even before this series) you try to print any
function local static variable of type other than int, you'll get
bogus results.  You can see that with m-static.cc as is, even.
Printing the "svar" local, which is a boolean (1 byte) still prints as
"int" (4 bytes):

  (gdb) p 'gnu_obj_1::method()::svar'
  $1 = 1
  (gdb) ptype 'gnu_obj_1::method()::svar'
  type = <data variable, no debug info>

This probably prints some random bogus value on big endian machines.

If 'svar' was of some aggregate type (etc.) we'd still print it as
int, so the problem would have been more obvious...  After this
commit, you'll get instead:

  (gdb) p 'gnu_obj_1::method()::svar'
  'gnu_obj_1::method()::svar' has unknown type; cast it to its declared type

... so at least GDB is no longer misleading.  Making GDB find the real
local static debug symbol is the subject of the following patches.  In
the end, it'll all "Just Work".

gdb/ChangeLog:
2017-09-04  Pedro Alves  <palves@redhat.com>

* ax-gdb.c: Include "typeprint.h".
(gen_expr_for_cast): New function.
(gen_expr) <OP_CAST, OP_CAST_TYPE>: Use it.
<OP_VAR_VALUE, OP_MSYM_VAR_VALUE>: Error out if the variable's
type is unknown.
* dwarf2read.c (new_symbol_full): Fallback to int instead of
nodebug_data_symbol.
* eval.c: Include "typeprint.h".
(evaluate_subexp_standard) <OP_VAR_VALUE, OP_VAR_MSYM_VALUE>:
Error out if symbol has unknown type.
<UNOP_CAST, UNOP_CAST_TYPE>: Common bits factored out to
evaluate_subexp_for_cast.
(evaluate_subexp_for_address, evaluate_subexp_for_sizeof): Handle
OP_VAR_MSYM_VALUE.
(evaluate_subexp_for_cast): New function.
* gdbtypes.c (init_nodebug_var_type): New function.
(objfile_type): Use it to initialize types of variables with no
debug info.
* typeprint.c (error_unknown_type): New.
* typeprint.h (error_unknown_type): New declaration.
* compile/compile-c-types.c (convert_type_basic): Handle
TYPE_CODE_ERROR; warn and fallback to int for variables with
unknown type.

gdb/testsuite/ChangeLog:
2017-09-04  Pedro Alves  <palves@redhat.com>

* gdb.asm/asm-source.exp: Add casts to int.
* gdb.base/nodebug.c (dataglobal8, dataglobal32_1, dataglobal32_2)
(dataglobal64_1, dataglobal64_2): New globals.
* gdb.base/nodebug.exp: Test different expressions involving the
new globals, with print, whatis and ptype.  Add casts to int.
* gdb.base/solib-display.exp: Add casts to int.
* gdb.compile/compile-ifunc.exp: Expect warning.  Add cast to int.
* gdb.cp/m-static.exp: Add cast to int.
* gdb.dwarf2/dw2-skip-prologue.exp: Add cast to int.
* gdb.threads/tls-nodebug.exp: Check that gdb errors out printing
tls variable with no debug info without a cast.  Test with a cast
to int too.
* gdb.trace/entry-values.exp: Add casts.

18 files changed:
gdb/ChangeLog
gdb/ax-gdb.c
gdb/compile/compile-c-types.c
gdb/dwarf2read.c
gdb/eval.c
gdb/gdbtypes.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.asm/asm-source.exp
gdb/testsuite/gdb.base/nodebug.c
gdb/testsuite/gdb.base/nodebug.exp
gdb/testsuite/gdb.base/solib-display.exp
gdb/testsuite/gdb.compile/compile-ifunc.exp
gdb/testsuite/gdb.cp/m-static.exp
gdb/testsuite/gdb.dwarf2/dw2-skip-prologue.exp
gdb/testsuite/gdb.threads/tls-nodebug.exp
gdb/testsuite/gdb.trace/entry-values.exp
gdb/typeprint.c
gdb/typeprint.h

index 7859c64731603e8c14f1e722c130898d01212345..4e08489c49dbf2f0f392d5b03d1de2e9102d2f0f 100644 (file)
@@ -1,3 +1,29 @@
+2017-09-04  Pedro Alves  <palves@redhat.com>
+
+       * ax-gdb.c: Include "typeprint.h".
+       (gen_expr_for_cast): New function.
+       (gen_expr) <OP_CAST, OP_CAST_TYPE>: Use it.
+       <OP_VAR_VALUE, OP_MSYM_VAR_VALUE>: Error out if the variable's
+       type is unknown.
+       * dwarf2read.c (new_symbol_full): Fallback to int instead of
+       nodebug_data_symbol.
+       * eval.c: Include "typeprint.h".
+       (evaluate_subexp_standard) <OP_VAR_VALUE, OP_VAR_MSYM_VALUE>:
+       Error out if symbol has unknown type.
+       <UNOP_CAST, UNOP_CAST_TYPE>: Common bits factored out to
+       evaluate_subexp_for_cast.
+       (evaluate_subexp_for_address, evaluate_subexp_for_sizeof): Handle
+       OP_VAR_MSYM_VALUE.
+       (evaluate_subexp_for_cast): New function.
+       * gdbtypes.c (init_nodebug_var_type): New function.
+       (objfile_type): Use it to initialize types of variables with no
+       debug info.
+       * typeprint.c (error_unknown_type): New.
+       * typeprint.h (error_unknown_type): New declaration.
+       * compile/compile-c-types.c (convert_type_basic): Handle
+       TYPE_CODE_ERROR; warn and fallback to int for variables with
+       unknown type.
+
 2017-09-04  Pedro Alves  <palves@redhat.com>
 
        * eval.c (evaluate_var_value): New function, factored out from ...
index 3fdf81afee587f6bd2f1e06d38650025c23701e6..2b5e481dc0141561cb425f44a659746b5cd701b9 100644 (file)
@@ -42,7 +42,7 @@
 #include "linespec.h"
 #include "location.h"
 #include "objfiles.h"
-
+#include "typeprint.h"
 #include "valprint.h"
 #include "c-lang.h"
 
@@ -1765,6 +1765,40 @@ gen_sizeof (struct expression *exp, union exp_element **pc,
 }
 \f
 
+/* Generate bytecode for a cast to TO_TYPE.  Advance *PC over the
+   subexpression.  */
+
+static void
+gen_expr_for_cast (struct expression *exp, union exp_element **pc,
+                  struct agent_expr *ax, struct axs_value *value,
+                  struct type *to_type)
+{
+  enum exp_opcode op = (*pc)[0].opcode;
+
+  /* Don't let symbols be handled with gen_expr because that throws an
+     "unknown type" error for no-debug data symbols.  Instead, we want
+     the cast to reinterpret such symbols.  */
+  if (op == OP_VAR_MSYM_VALUE || op == OP_VAR_VALUE)
+    {
+      if (op == OP_VAR_VALUE)
+       {
+         gen_var_ref (ax, value, (*pc)[2].symbol);
+
+         if (value->optimized_out)
+           error (_("`%s' has been optimized out, cannot use"),
+                  SYMBOL_PRINT_NAME ((*pc)[2].symbol));
+       }
+      else
+       gen_msym_var_ref (ax, value, (*pc)[2].msymbol, (*pc)[1].objfile);
+      if (TYPE_CODE (value->type) == TYPE_CODE_ERROR)
+       value->type = to_type;
+      (*pc) += 4;
+    }
+  else
+    gen_expr (exp, pc, ax, value);
+  gen_cast (ax, value, to_type);
+}
+
 /* Generating bytecode from GDB expressions: general recursive thingy  */
 
 /* XXX: i18n */
@@ -1978,11 +2012,18 @@ gen_expr (struct expression *exp, union exp_element **pc,
        error (_("`%s' has been optimized out, cannot use"),
               SYMBOL_PRINT_NAME ((*pc)[2].symbol));
 
+      if (TYPE_CODE (value->type) == TYPE_CODE_ERROR)
+       error_unknown_type (SYMBOL_PRINT_NAME ((*pc)[2].symbol));
+
       (*pc) += 4;
       break;
 
     case OP_VAR_MSYM_VALUE:
       gen_msym_var_ref (ax, value, (*pc)[2].msymbol, (*pc)[1].objfile);
+
+      if (TYPE_CODE (value->type) == TYPE_CODE_ERROR)
+       error_unknown_type (MSYMBOL_PRINT_NAME ((*pc)[2].msymbol));
+
       (*pc) += 4;
       break;
 
@@ -2043,8 +2084,7 @@ gen_expr (struct expression *exp, union exp_element **pc,
        struct type *type = (*pc)[1].type;
 
        (*pc) += 3;
-       gen_expr (exp, pc, ax, value);
-       gen_cast (ax, value, type);
+       gen_expr_for_cast (exp, pc, ax, value, type);
       }
       break;
 
@@ -2059,9 +2099,7 @@ gen_expr (struct expression *exp, union exp_element **pc,
        val = evaluate_subexp (NULL, exp, &offset, EVAL_AVOID_SIDE_EFFECTS);
        type = value_type (val);
        *pc = &exp->elts[offset];
-
-       gen_expr (exp, pc, ax, value);
-       gen_cast (ax, value, type);
+       gen_expr_for_cast (exp, pc, ax, value, type);
       }
       break;
 
index 2bfa72d2b8cdb1a742b6f2b84bc60799c18eb24c..b53a3c45dcf3cbff80c34f70db0e16fdf6dc6cee 100644 (file)
@@ -383,6 +383,21 @@ convert_type_basic (struct compile_c_instance *context, struct type *type)
 
     case TYPE_CODE_COMPLEX:
       return convert_complex (context, type);
+
+    case TYPE_CODE_ERROR:
+      {
+       /* Ideally, if we get here due to a cast expression, we'd use
+          the cast-to type as the variable's type, like GDB's
+          built-in parser does.  For now, assume "int" like GDB's
+          built-in parser used to do, but at least warn.  */
+       struct type *fallback;
+       if (TYPE_OBJFILE_OWNED (type))
+         fallback = objfile_type (TYPE_OWNER (type).objfile)->builtin_int;
+       else
+         fallback = builtin_type (TYPE_OWNER (type).gdbarch)->builtin_int;
+       warning (_("variable has unknown type; assuming int"));
+       return convert_int (context, fallback);
+      }
     }
 
   return C_CTX (context)->c_ops->error (C_CTX (context),
index ead4f3ca350a113675b0ecf9f428ae6e0e526773..893e04d83f5849fc090ae09b23cac75ebe07cb5c 100644 (file)
@@ -19139,8 +19139,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
             variables with missing type entries.  Change the
             misleading `void' type to something sensible.  */
          if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_VOID)
-           SYMBOL_TYPE (sym)
-             = objfile_type (objfile)->nodebug_data_symbol;
+           SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_int;
 
          attr = dwarf2_attr (die, DW_AT_const_value, cu);
          /* In the case of DW_TAG_member, we should only be called for
index a97f4a999e6624ac2709a4dfb93d77a7753f6755..75d3c86f123a0b4f3f2b19dfa215bc8dc60940e5 100644 (file)
@@ -39,6 +39,7 @@
 #include "valprint.h"
 #include "gdb_obstack.h"
 #include "objfiles.h"
+#include "typeprint.h"
 #include <ctype.h>
 
 /* This is defined in valops.c */
@@ -52,6 +53,10 @@ static struct value *evaluate_subexp_for_sizeof (struct expression *, int *,
 static struct value *evaluate_subexp_for_address (struct expression *,
                                                  int *, enum noside);
 
+static value *evaluate_subexp_for_cast (expression *exp, int *pos,
+                                       enum noside noside,
+                                       struct type *type);
+
 static struct value *evaluate_struct_tuple (struct value *,
                                            struct expression *, int *,
                                            enum noside, int);
@@ -796,14 +801,30 @@ evaluate_subexp_standard (struct type *expect_type,
       (*pos) += 3;
       if (noside == EVAL_SKIP)
        return eval_skip_value (exp);
-      return evaluate_var_value (noside,
-                                exp->elts[pc + 1].block,
-                                exp->elts[pc + 2].symbol);
+
+      {
+       symbol *var = exp->elts[pc + 2].symbol;
+       if (TYPE_CODE (SYMBOL_TYPE (var)) == TYPE_CODE_ERROR)
+         error_unknown_type (SYMBOL_PRINT_NAME (var));
+
+       return evaluate_var_value (noside, exp->elts[pc + 1].block, var);
+      }
+
     case OP_VAR_MSYM_VALUE:
-      (*pos) += 3;
-      return evaluate_var_msym_value (noside,
-                                     exp->elts[pc + 1].objfile,
-                                     exp->elts[pc + 2].msymbol);
+      {
+       (*pos) += 3;
+
+       minimal_symbol *msymbol = exp->elts[pc + 2].msymbol;
+       value *val = evaluate_var_msym_value (noside,
+                                             exp->elts[pc + 1].objfile,
+                                             msymbol);
+
+       type = value_type (val);
+       if (TYPE_CODE (type) == TYPE_CODE_ERROR
+           && (noside != EVAL_AVOID_SIDE_EFFECTS || pc != 0))
+         error_unknown_type (MSYMBOL_PRINT_NAME (msymbol));
+       return val;
+      }
 
     case OP_VAR_ENTRY_VALUE:
       (*pos) += 2;
@@ -2589,22 +2610,12 @@ evaluate_subexp_standard (struct type *expect_type,
     case UNOP_CAST:
       (*pos) += 2;
       type = exp->elts[pc + 1].type;
-      arg1 = evaluate_subexp (type, exp, pos, noside);
-      if (noside == EVAL_SKIP)
-       return eval_skip_value (exp);
-      if (type != value_type (arg1))
-       arg1 = value_cast (type, arg1);
-      return arg1;
+      return evaluate_subexp_for_cast (exp, pos, noside, type);
 
     case UNOP_CAST_TYPE:
       arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
       type = value_type (arg1);
-      arg1 = evaluate_subexp (type, exp, pos, noside);
-      if (noside == EVAL_SKIP)
-       return eval_skip_value (exp);
-      if (type != value_type (arg1))
-       arg1 = value_cast (type, arg1);
-      return arg1;
+      return evaluate_subexp_for_cast (exp, pos, noside, type);
 
     case UNOP_DYNAMIC_CAST:
       arg1 = evaluate_subexp (NULL, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
@@ -2927,6 +2938,22 @@ evaluate_subexp_for_address (struct expression *exp, int *pos,
       else
        return address_of_variable (var, exp->elts[pc + 1].block);
 
+    case OP_VAR_MSYM_VALUE:
+      {
+       (*pos) += 4;
+
+       value *val = evaluate_var_msym_value (noside,
+                                             exp->elts[pc + 1].objfile,
+                                             exp->elts[pc + 2].msymbol);
+       if (noside == EVAL_AVOID_SIDE_EFFECTS)
+         {
+           struct type *type = lookup_pointer_type (value_type (val));
+           return value_zero (type, not_lval);
+         }
+       else
+         return value_addr (val);
+      }
+
     case OP_SCOPE:
       tem = longest_to_int (exp->elts[pc + 2].longconst);
       (*pos) += 5 + BYTES_TO_EXP_ELEM (tem + 1);
@@ -3065,6 +3092,23 @@ evaluate_subexp_for_sizeof (struct expression *exp, int *pos,
        (*pos) += 4;
       break;
 
+    case OP_VAR_MSYM_VALUE:
+      {
+       (*pos) += 4;
+
+       minimal_symbol *msymbol = exp->elts[pc + 2].msymbol;
+       value *val = evaluate_var_msym_value (noside,
+                                             exp->elts[pc + 1].objfile,
+                                             msymbol);
+
+       type = value_type (val);
+       if (TYPE_CODE (type) == TYPE_CODE_ERROR)
+         error_unknown_type (MSYMBOL_PRINT_NAME (msymbol));
+
+       return value_from_longest (size_type, TYPE_LENGTH (type));
+      }
+      break;
+
       /* Deal with the special case if NOSIDE is EVAL_NORMAL and the resulting
         type of the subscript is a variable length array type. In this case we
         must re-evaluate the right hand side of the subcription to allow
@@ -3112,6 +3156,61 @@ evaluate_subexp_for_sizeof (struct expression *exp, int *pos,
   return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
 }
 
+/* Evaluate a subexpression of EXP, at index *POS, and return a value
+   for that subexpression cast to TO_TYPE.  Advance *POS over the
+   subexpression.  */
+
+static value *
+evaluate_subexp_for_cast (expression *exp, int *pos,
+                         enum noside noside,
+                         struct type *to_type)
+{
+  int pc = *pos;
+
+  /* Don't let symbols be evaluated with evaluate_subexp because that
+     throws an "unknown type" error for no-debug data symbols.
+     Instead, we want the cast to reinterpret the symbol.  */
+  if (exp->elts[pc].opcode == OP_VAR_MSYM_VALUE
+      || exp->elts[pc].opcode == OP_VAR_VALUE)
+    {
+      (*pos) += 4;
+
+      value *val;
+      if (exp->elts[pc].opcode == OP_VAR_MSYM_VALUE)
+       {
+         if (noside == EVAL_AVOID_SIDE_EFFECTS)
+           return value_zero (to_type, not_lval);
+
+         val = evaluate_var_msym_value (noside,
+                                        exp->elts[pc + 1].objfile,
+                                        exp->elts[pc + 2].msymbol);
+       }
+      else
+       val = evaluate_var_value (noside,
+                                 exp->elts[pc + 1].block,
+                                 exp->elts[pc + 2].symbol);
+
+      if (noside == EVAL_SKIP)
+       return eval_skip_value (exp);
+
+      val = value_cast (to_type, val);
+
+      /* Don't allow e.g. '&(int)var_with_no_debug_info'.  */
+      if (VALUE_LVAL (val) == lval_memory)
+       {
+         if (value_lazy (val))
+           value_fetch_lazy (val);
+         VALUE_LVAL (val) = not_lval;
+       }
+      return val;
+    }
+
+  value *val = evaluate_subexp (to_type, exp, pos, noside);
+  if (noside == EVAL_SKIP)
+    return eval_skip_value (exp);
+  return value_cast (to_type, val);
+}
+
 /* Parse a type expression in the string [P..P+LENGTH).  */
 
 struct type *
index a22f0ca21e8e2f4e8e4c3c3794c5e09ca7d540f7..fc86225bf673ffbf9f1210cba2d2d1f0081afda6 100644 (file)
@@ -2770,6 +2770,16 @@ init_type (struct objfile *objfile, enum type_code code, int length,
   return type;
 }
 
+/* Allocate a TYPE_CODE_ERROR type structure associated with OBJFILE,
+   to use with variables that have no debug info.  NAME is the type
+   name.  */
+
+static struct type *
+init_nodebug_var_type (struct objfile *objfile, const char *name)
+{
+  return init_type (objfile, TYPE_CODE_ERROR, 0, name);
+}
+
 /* Allocate a TYPE_CODE_INT type structure associated with OBJFILE.
    BIT is the type size in bits.  If UNSIGNED_P is non-zero, set
    the type's TYPE_UNSIGNED flag.  NAME is the type name.  */
@@ -5325,14 +5335,11 @@ objfile_type (struct objfile *objfile)
                         "<text from jump slot in .got.plt, no debug info>",
                         objfile_type->nodebug_text_symbol);
   objfile_type->nodebug_data_symbol
-    = init_integer_type (objfile, gdbarch_int_bit (gdbarch), 0,
-                        "<data variable, no debug info>");
+    = init_nodebug_var_type (objfile, "<data variable, no debug info>");
   objfile_type->nodebug_unknown_symbol
-    = init_integer_type (objfile, TARGET_CHAR_BIT, 0,
-                        "<variable (not text or data), no debug info>");
+    = init_nodebug_var_type (objfile, "<variable (not text or data), no debug info>");
   objfile_type->nodebug_tls_symbol
-    = init_integer_type (objfile, gdbarch_int_bit (gdbarch), 0,
-                        "<thread local variable, no debug info>");
+    = init_nodebug_var_type (objfile, "<thread local variable, no debug info>");
 
   /* NOTE: on some targets, addresses and pointers are not necessarily
      the same.
index 5457aa12f59094f902461844731f4b812ab4efdb..072423deb79d4a6e503bbde2e5e6026f17eef3b8 100644 (file)
@@ -1,3 +1,19 @@
+2017-09-04  Pedro Alves  <palves@redhat.com>
+
+       * gdb.asm/asm-source.exp: Add casts to int.
+       * gdb.base/nodebug.c (dataglobal8, dataglobal32_1, dataglobal32_2)
+       (dataglobal64_1, dataglobal64_2): New globals.
+       * gdb.base/nodebug.exp: Test different expressions involving the
+       new globals, with print, whatis and ptype.  Add casts to int.
+       * gdb.base/solib-display.exp: Add casts to int.
+       * gdb.compile/compile-ifunc.exp: Expect warning.  Add cast to int.
+       * gdb.cp/m-static.exp: Add cast to int.
+       * gdb.dwarf2/dw2-skip-prologue.exp: Add cast to int.
+       * gdb.threads/tls-nodebug.exp: Check that gdb errors out printing
+       tls variable with no debug info without a cast.  Test with a cast
+       to int too.
+       * gdb.trace/entry-values.exp: Add casts.
+
 2017-09-04  Pedro Alves  <palves@redhat.com>
 
        * gdb.base/nodebug.exp: Test that ptype's error about functions
index e07e5543f2077244f675a7e832b37525975400b5..138609a3c80b7ddb62a9906ebeb68f58d8f97c1e 100644 (file)
@@ -465,14 +465,14 @@ proc test_dis { command var } {
 }
 
 # See if we can look at a global variable, three ways
-gdb_test "print globalvar" ".* = 11" "look at global variable"
+gdb_test "print (int) globalvar" ".* = 11" "look at global variable"
 test_dis "x/i &globalvar" "globalvar"
-test_dis "disassem &globalvar, &globalvar+1" "globalvar"
+test_dis "disassem &globalvar, (int *) &globalvar+1" "globalvar"
 
 # See if we can look at a static variable, three ways
-gdb_test "print staticvar" ".* = 5" "look at static variable"
+gdb_test "print (int) staticvar" ".* = 5" "look at static variable"
 test_dis "x/i &staticvar" "staticvar"
-test_dis "disassem &staticvar, &staticvar+1" "staticvar"
+test_dis "disassem &staticvar, (int *) &staticvar+1" "staticvar"
 
 # See if we can look at a static function
 gdb_test "disassem foostatic" ".*<\\+0>:.*End of assembler dump." \
index 99641e801217c990c5eefe9d8105c985a1f00a1e..c7bc93991b846c1854dbef3f0a2a64af47722c79 100644 (file)
@@ -8,6 +8,13 @@ static int datalocal = 4;              /* Should go in local data */
 int bssglobal;                         /* Should go in global bss */
 static int bsslocal;                   /* Should go in local bss */
 
+/* Non-int-sized global data variables.  */
+uint8_t dataglobal8 = 0xff;
+uint32_t dataglobal32_1 = 0x7fffffff;
+uint32_t dataglobal32_2 = 0x000000ff;
+uint64_t dataglobal64_1 = 0x7fffffffffffffff;
+uint64_t dataglobal64_2 = 0x00000000000000ff;
+
 int
 inner (int x)
 {
index da704f10370120d25b753fc5801da88dc80d74e2..2099456dde0c57dfafd3736b7bb77795c97e2c78 100644 (file)
@@ -152,11 +152,57 @@ if [runto inner] then {
     # we may or may not have debug info for those (depending on
     # whether we have debug info for the C runtime, for example).
     gdb_test_no_output "macro define uint8 unsigned char"
-
-    gdb_test "p dataglobal" "= 3"
-    gdb_test "whatis dataglobal" \
-       "<(data variable|variable), no debug info>|int"
-    gdb_test "ptype dataglobal" "<(data variable|variable), no debug info>|int"
+    gdb_test_no_output "macro define uint32 unsigned int"
+    gdb_test_no_output "macro define uint64 unsigned long long"
+
+    set data_var_type "<data variable, no debug info>"
+    set unk_type_re "has unknown type.*to its declared type"
+    set ptr_math_re "Cannot perform pointer math on incomplete type \"$data_var_type\", try casting to a known type, or void \\*\\."
+    set not_mem_re "Attempt to take address of value not located in memory\\."
+
+    set dataglobal_unk_re "dataglobal.*$unk_type_re"
+
+        #exp                           #fmt #print                                             #ptype/whatis
+    foreach line {
+       {"dataglobal"                   ""   $dataglobal_unk_re                                 " = $data_var_type"}
+       {"(int) dataglobal"             ""   "= 3"                                              " = int"}
+       {"sizeof(dataglobal)"           ""   $dataglobal_unk_re                                 $dataglobal_unk_re}
+       {"sizeof(dataglobal + 1)"       ""   $dataglobal_unk_re                                 $dataglobal_unk_re}
+       {"sizeof((int) dataglobal)"     ""   " = $decimal"                                      " = int"}
+       {"dataglobal + 1"               ""   $dataglobal_unk_re                                 $dataglobal_unk_re}
+       {"&dataglobal"                  ""   "\\($data_var_type \\*\\) $hex <dataglobal>"       " = $data_var_type \\*"}
+       {"&dataglobal + 1"              ""   $ptr_math_re                                       $ptr_math_re}
+       {"(int *) &dataglobal + 1"      ""   " = \\(int \\*\\) $hex <datalocal>"                "int \\*"}
+       {"&(int) dataglobal + 1"        ""   $not_mem_re                                        $not_mem_re}
+       {"&dataglobal, &dataglobal"     ""   "\\($data_var_type \\*\\) $hex <dataglobal>"       " = $data_var_type \\*"}
+       {"*dataglobal"                  ""   $dataglobal_unk_re                                 $dataglobal_unk_re}
+
+       {"dataglobal8"                  "/x" $dataglobal_unk_re                                 " = $data_var_type"}
+       {"(uint8) dataglobal8"          "/x" " = 0xff"                                          "unsigned char"}
+
+       {"dataglobal32_1"               "/x" $dataglobal_unk_re                                 " = $data_var_type"}
+       {"(uint32) dataglobal32_1"      "/x" " = 0x7fffffff"                                    "unsigned int"}
+       {"dataglobal32_2"               "/x" $dataglobal_unk_re                                 " = $data_var_type"}
+       {"(uint32) dataglobal32_2"      "/x" " = 0xff"                                          "unsigned int"}
+
+       {"dataglobal64_1"               "/x" $dataglobal_unk_re                                 " = $data_var_type"}
+       {"(uint64) dataglobal64_1"      "/x" " = 0x7fffffffffffffff"                            "unsigned long long"}
+       {"dataglobal64_2"               "/x" $dataglobal_unk_re                                 " = $data_var_type"}
+       {"(uint64) dataglobal64_2"      "/x" " = 0xff"                                          "unsigned long long"}
+    } {
+       set exp [lindex $line 0]
+       # Expand variables.
+       set fmt [subst -nobackslashes [lindex $line 1]]
+       set print [subst  -nobackslashes [lindex $line 2]]
+       set whatis [subst -nobackslashes [lindex $line 3]]
+       if {$fmt == ""} {
+           gdb_test "p $exp" $print
+       } else {
+           gdb_test "p $fmt $exp" $print
+       }
+       gdb_test "whatis $exp" $whatis
+       gdb_test "ptype $exp" $whatis
+    }
     
     # The only symbol xcoff puts out for statics is for the TOC entry.
     # Possible, but hairy, for gdb to deal.  Right now it doesn't, it
@@ -164,35 +210,39 @@ if [runto inner] then {
     setup_xfail "rs6000*-*-aix*"
     setup_xfail "powerpc*-*-aix*"
 
-    gdb_test "p datalocal" "= 4"
+    gdb_test "p datalocal" "datalocal.*$unk_type_re"
+    gdb_test "p (int) datalocal" "= 4"
 
     setup_xfail "rs6000*-*-aix*"
     setup_xfail "powerpc*-*-aix*"
 
-    gdb_test "whatis datalocal" "<(data variable|variable), no debug info>"
+    gdb_test "whatis datalocal" "datalocal.*$data_var_type"
 
     setup_xfail "rs6000*-*-aix*"
     setup_xfail "powerpc*-*-aix*"
 
-    gdb_test "ptype datalocal" "<(data variable|variable), no debug info>"
-    gdb_test "p bssglobal" "= 0"
-    gdb_test "whatis bssglobal" "<(data variable|variable), no debug info>|int"
-    gdb_test "ptype bssglobal" "<(data variable|variable), no debug info>|int"
+    gdb_test "ptype datalocal" "datalocal.*$data_var_type"
+
+    gdb_test "p bssglobal" "bssglobal.*$unk_type_re"
+    gdb_test "p (int) bssglobal" "= 0"
+    gdb_test "whatis bssglobal" $data_var_type
+    gdb_test "ptype bssglobal" $data_var_type
 
     setup_xfail "rs6000*-*-aix*"
     setup_xfail "powerpc*-*-aix*"
 
-    gdb_test "p bsslocal" "= 0"
+    gdb_test "p bsslocal" "bsslocal.*$unk_type_re"
+    gdb_test "p (int) bsslocal" "= 0"
 
     setup_xfail "rs6000*-*-aix*"
     setup_xfail "powerpc*-*-aix*"
 
-    gdb_test "whatis bsslocal" "<(data variable|variable), no debug info>"
+    gdb_test "whatis bsslocal" $data_var_type
 
     setup_xfail "rs6000*-*-aix*"
     setup_xfail "powerpc*-*-aix*"
 
-    gdb_test "ptype bsslocal" "<(data variable|variable), no debug info>"
+    gdb_test "ptype bsslocal" $data_var_type
 
     gdb_test "backtrace 10" "#0.*inner.*#1.*middle.*#2.*top.*#3.*main.*" \
        "backtrace from inner in nodebug.exp"
index 1e2685315b5b832441f7fc018de1db9e38dd1610..6df9f260215a2165c426ef38f7d21065c4c5ce17 100644 (file)
@@ -94,9 +94,9 @@ foreach libsepdebug {NO IN SEP} { with_test_prefix "$libsepdebug" {
       return 0
     }
 
-    gdb_test "display a_global" "1: a_global = 41"
-    gdb_test "display b_global" "2: b_global = 42"
-    gdb_test "display c_global" "3: c_global = 43"
+    gdb_test "display (int) a_global" "1: \\(int\\) a_global = 41"
+    gdb_test "display (int) b_global" "2: \\(int\\) b_global = 42"
+    gdb_test "display (int) c_global" "3: \\(int\\) c_global = 43"
 
     if { [gdb_start_cmd] < 0 } {
        fail "can't run to main (2)"
@@ -104,9 +104,9 @@ foreach libsepdebug {NO IN SEP} { with_test_prefix "$libsepdebug" {
     }
 
     gdb_test "" [multi_line \
-                    "1: a_global = 41" \
-                    "2: b_global = 42"  \
-                    "3: c_global = 43" \
+                    "1: \\(int\\) a_global = 41" \
+                    "2: \\(int\\) b_global = 42"  \
+                    "3: \\(int\\) c_global = 43" \
                    ] "after rerun"
 
     # Now rebuild the library without b_global
@@ -132,9 +132,9 @@ foreach libsepdebug {NO IN SEP} { with_test_prefix "$libsepdebug" {
 
 
     gdb_test "" [multi_line \
-                    "1: a_global = 41" \
+                    "1: \\(int\\) a_global = 41" \
                     "warning: .*b_global.*"  \
-                    "3: c_global = 43" \
+                    "3: \\(int\\) c_global = 43" \
                    ] "after rerun (2)"
 
     # Now verify that displays which are not in the shared library
index dc442ffc8acc0afb78a1817e1c6960e8e771a629..b591939d89ba1c2854d070b6559ac01b733f0f56 100644 (file)
@@ -36,9 +36,10 @@ with_test_prefix "nodebug" {
        return -1
     }
 
-    gdb_test_no_output "compile code resultvar = gnu_ifunc (10);"
+    gdb_test "compile code resultvar = gnu_ifunc (10);" \
+       "warning: variable has unknown type; assuming int"
 
-    gdb_test "p resultvar" " = 11"
+    gdb_test "p (int) resultvar" " = 11"
 
 }
 
index 52eea1ad80e6231b4c2c1bff4e123100ec8cf23a..eeb88e978fbd6673342d7859eda3dd540615d534 100644 (file)
@@ -54,8 +54,8 @@ gdb_continue_to_breakpoint "end of constructors"
 
 # simple object, static const int, accessing via 'class::method::variable'
 # Regression test for PR c++/15203 and PR c++/15210
-gdb_test "print 'gnu_obj_1::method()::sintvar'" "\\$\[0-9\]+ = 4" \
-    "simple object, static const int, accessing via 'class::method::variable"
+gdb_test "print (int) 'gnu_obj_1::method()::sintvar'" "\\$\[0-9\]+ = 4" \
+    "simple object, static int, accessing via 'class::method::variable'"
 
 # simple object, static const bool
 gdb_test "print test1.test" "\\$\[0-9\]* = true" "simple object, static const bool"
index 458809b4b178a4d0cba7dd99512396fc5ac0ad86..6338e6db523ce8dda739f485548f135dbdc94163 100644 (file)
@@ -79,4 +79,4 @@ gdb_continue_to_breakpoint "func"
 # Sanity check GDB has really found 2 locations
 gdb_test {info break $bpnum} "\r\n2\\.1\[ \t\]\[^\n\]*\r\n2\\.2\[ \t\]\[^\n\]*" "2 locations found"
 
-gdb_test "p v" " = 0" "no statement got executed"
+gdb_test "p (int) v" " = 0" "no statement got executed"
index 8dc9444c4ad9b1eacd15d3528053b58b2cf733ef..e7187365567b3c548d47d29cf5f6397b291bb7b7 100644 (file)
@@ -33,7 +33,10 @@ if ![runto_main] then {
 }
 
 # Formerly: Cannot access memory at address 0x0
-gdb_test "p thread_local" "= 42" "thread local storage"
+gdb_test "p thread_local" "'thread_local' has unknown type; cast it to its declared type" \
+    "thread local storage, unknown type"
+gdb_test "p (int) thread_local" "= 42" \
+    "thread local storage, cast"
 
 # Done!
 #
index b2650c6d2e5bab60d24c13108db04e5ab0b14da7..baf93714ee725522af48a17224b109c684c54aae 100644 (file)
@@ -194,8 +194,8 @@ gdb_test_sequence "bt" "bt (1)" {
 # Update global variables 'global1' and 'global2' and test that the
 # entry values are updated too.
 
-gdb_test_no_output "set var global1=10"
-gdb_test_no_output "set var global2=11"
+gdb_test_no_output "set var *(int *) &global1=10"
+gdb_test_no_output "set var *(int *) &global2=11"
 
 gdb_test_sequence "bt" "bt (2)" {
     "\[\r\n\]#0 .* foo \\(i=[-]?[0-9]+, i@entry=10, j=[-]?[0-9]+, j@entry=11\\)"
@@ -226,7 +226,7 @@ gdb_test "trace foo" "Tracepoint $decimal at .*"
 # argument j.
 
 gdb_trace_setactions "set action for tracepoint 1" "" \
-    "collect i, j, global1, \(\*\(void \*\*\) \(\$$spreg\)\) @ 128" "^$"
+    "collect i, j, (int) global1, \(\*\(void \*\*\) \(\$$spreg\)\) @ 128" "^$"
 
 gdb_test_no_output "tstart"
 
index 8e58bf9b5f80def8901ee8b2f9a1202708c90604..0cc6821cf5a4a7f32e62d8033b67960170b68287 100644 (file)
@@ -394,6 +394,15 @@ type_print_unknown_return_type (struct ui_file *stream)
   fprintf_filtered (stream, _("<unknown return type>"));
 }
 
+/* See typeprint.h.  */
+
+void
+error_unknown_type (const char *sym_print_name)
+{
+  error (_("'%s' has unknown type; cast it to its declared type"),
+        sym_print_name);
+}
+
 /* Print type of EXP, or last thing in value history if EXP == NULL.
    show is passed to type_print.  */
 
index d4e19e5b881dd0d37d6f69d5d66fb96e4560b78f..a458aa4e2f343d2bc76241b0a3c7d5ee98354639 100644 (file)
@@ -78,6 +78,11 @@ void c_type_print_args (struct type *, struct ui_file *, int, enum language,
 
 void type_print_unknown_return_type (struct ui_file *stream);
 
+/* Throw an error indicating that the user tried to use a symbol that
+   has unknown type.  SYM_PRINT_NAME is the name of the symbol, to be
+   included in the error message.  */
+extern void error_unknown_type (const char *sym_print_name);
+
 extern void val_print_not_allocated (struct ui_file *stream);
 
 extern void val_print_not_associated (struct ui_file *stream);