Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH v5 08/15] vla: support for DW_AT_count
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
  2014-02-06 16:27 ` [PATCH v5 11/15] test: cover subranges with present DW_AT_count attribute Sanimir Agovic
  2014-02-06 16:27 ` [PATCH v5 04/15] vla: enable sizeof operator to work with variable length arrays Sanimir Agovic
@ 2014-02-06 16:27 ` Sanimir Agovic
  2014-02-28 16:53   ` Joel Brobecker
  2014-02-06 16:28 ` [PATCH v5 14/15] test: basic c99 vla tests for C primitives Sanimir Agovic
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 45+ messages in thread
From: Sanimir Agovic @ 2014-02-06 16:27 UTC (permalink / raw)
  To: tromey, brobecker; +Cc: keven.boell, gdb-patches

This patch adds support for DW_AT_count as requested in the code review:

  https://sourceware.org/ml/gdb-patches/2013-11/msg00200.html

2013-11-19  Sanimir Agovic  <sanimir.agovic@intel.com>
            Keven Boell <keven.boell@intel.com>

	* dwarf2read.c (read_subrange_type): Convert DW_AT_count to a dynamic
	property and store it as the high bound and flag the range accordingly.
	* gdbtypes.c (resolve_dynamic_bounds): If range is flagged as
	RANGE_UPPER_BOUND_IS_COUNT assign low + high - 1 as the new high bound.
	* gdbtypes.h (enum range_flags): New enum.
	(struct range_bounds): Add flags member.


Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
---
 gdb/dwarf2read.c | 18 ++++++++++--------
 gdb/gdbtypes.c   |  5 +++++
 gdb/gdbtypes.h   |  9 +++++++++
 3 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 1d5fa3d..1e4de21 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -14334,6 +14334,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
   struct attribute *attr;
   struct dynamic_prop low, high;
   int low_default_is_valid;
+  int high_bound_is_count = 0;
   const char *name;
   LONGEST negative_mask;
 
@@ -14400,15 +14401,13 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
   if (!attr_to_dynamic_prop (attr, die, cu, &high))
     {
       attr = dwarf2_attr (die, DW_AT_count, cu);
-      if (attr)
-	{
-	  int count = dwarf2_get_attr_constant_value (attr, 1);
-	  high.data.const_val = low.data.const_val + count - 1;
-	}
-      else
+      if (attr_to_dynamic_prop (attr, die, cu, &high))
 	{
-	  /* Unspecified array length.  */
-	  high.data.const_val = low.data.const_val - 1;
+	  /* If bounds are constant do the final calculation here.  */
+	  if (low.kind == PROP_CONST && high.kind == PROP_CONST)
+	    high.data.const_val = low.data.const_val + high.data.const_val - 1;
+	  else
+	    high_bound_is_count = 1;
 	}
     }
 
@@ -14461,6 +14460,9 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
 
   range_type = create_range_type (NULL, orig_base_type, &low, &high);
 
+  if (high_bound_is_count)
+    TYPE_RANGE_DATA (range_type)->flags = RANGE_UPPER_BOUND_IS_COUNT;
+
   /* Ada expects an empty array on no boundary attributes.  */
   if (attr == NULL && cu->language != language_ada)
     TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED;
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index f5bd236..83a2c75 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -1674,6 +1674,11 @@ resolve_dynamic_bounds (struct type *type, CORE_ADDR addr)
     {
       high_bound.kind = PROP_CONST;
       high_bound.data.const_val = value;
+
+      if ((TYPE_RANGE_DATA (range_type)->flags & RANGE_UPPER_BOUND_IS_COUNT)
+	  == RANGE_UPPER_BOUND_IS_COUNT)
+	high_bound.data.const_val
+	  = low_bound.data.const_val + high_bound.data.const_val - 1;
     }
   else
     {
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 38cd240..100e3f4 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -392,6 +392,12 @@ struct dynamic_prop
   } data;
 };
 
+/* Flags used in main_type.range_bounds for bounds evaluation.  */
+
+enum range_flags
+{
+  RANGE_UPPER_BOUND_IS_COUNT = 1 /* High bound contains number of elements.  */
+};
 
 /* Determine which field of the union main_type.fields[x].loc is used.  */
 
@@ -622,6 +628,9 @@ struct main_type
       /* High bound of range.  */
 
       struct dynamic_prop high;
+
+      /* Flags about this range.  */
+      unsigned int flags;
     } *bounds;
 
   } flds_bnds;
-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v5 04/15] vla: enable sizeof operator to work with variable length arrays
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
  2014-02-06 16:27 ` [PATCH v5 11/15] test: cover subranges with present DW_AT_count attribute Sanimir Agovic
@ 2014-02-06 16:27 ` Sanimir Agovic
  2014-02-06 16:27 ` [PATCH v5 08/15] vla: support for DW_AT_count Sanimir Agovic
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 45+ messages in thread
From: Sanimir Agovic @ 2014-02-06 16:27 UTC (permalink / raw)
  To: tromey, brobecker; +Cc: keven.boell, gdb-patches

In C99 the sizeof operator computes the size of a variable length array
at runtime (6.5.3.4 The sizeof operator). This patch reflects the semantic
change in the debugger.

We now are able to get the size of a vla:

1| void foo (size_t n) {
2|   int vla[n];
3| }

(gdb) p sizeof(vla)

yields N * sizeof(int).

2013-10-18  Sanimir Agovic  <sanimir.agovic@intel.com>
            Keven Boell  <keven.boell@intel.com>

	* eval.c (evaluate_subexp_for_sizeof) <OP_VAR_VALUE>: If the type
	passed to sizeof is dynamic evaluate the argument to compute the length.


Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
---
 gdb/eval.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/gdb/eval.c b/gdb/eval.c
index 9d81a92..a81e789 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -3041,8 +3041,14 @@ evaluate_subexp_for_sizeof (struct expression *exp, int *pos)
       return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
 
     case OP_VAR_VALUE:
-      (*pos) += 4;
       type = check_typedef (SYMBOL_TYPE (exp->elts[pc + 2].symbol));
+      if (is_dynamic_type (type))
+	{
+	  val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_NORMAL);
+	  type = value_type (val);
+	}
+      else
+	(*pos) += 4;
       return
 	value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
 
-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v5 00/15] C99 variable length array support
@ 2014-02-06 16:27 Sanimir Agovic
  2014-02-06 16:27 ` [PATCH v5 11/15] test: cover subranges with present DW_AT_count attribute Sanimir Agovic
                   ` (16 more replies)
  0 siblings, 17 replies; 45+ messages in thread
From: Sanimir Agovic @ 2014-02-06 16:27 UTC (permalink / raw)
  To: tromey, brobecker; +Cc: keven.boell, gdb-patches

Hello,

this patch series (v5) add C99 variable length support to gdb.

It allows the user to evaluate a vla like an ordinary static array e.g. print
its elements instead of printing the pointer to the array. In addition the size
of a vla can be retrieved with gdbs builtin sizeof operator.


    1| void foo (size_t n) {
    2|   int ary[n];
    3|   memset(ary, 0, sizeof(ary));
    4| }

    (gdb) print ary
    $1 = {0 <repeats 42 times>}

    (gdb) print sizeof ary
    $2 = 168

Changes in v5
=============
All patches are reviewed by Tom Tromey and Joel Brobecker except for:

 - New #1, renamed create_range_type to create_static_range_type as requested
   in https://sourceware.org/ml/gdb-patches/2013-12/msg00682.html
 - Modified #3, handle ref/expr/const attribute in a better way, removing
   the need to alter the dwarf expression by pushing a dw_op_deref to the ops.
   This addresses https://sourceware.org/ml/gdb-patches/2013-11/msg00785.html
 - Modified #8, the semantic of dw_at_count attribute is now handled in
   resolve_dynamic_bound instead during dwarf parsing. A change triggered
   by patch #3
 - New #10, handles sizeof sideffect as requested in
   https://sourceware.org/ml/gdb-patches/2014-01/msg00732.html

Changes in v4
=============
 - Documented side effect of value_at, value_at_lazy, value_from_pointer,
 value_from_contents_and_address
 - Removed usage of copy_type_recursive and instead use copy_type selective

Changes in v3
=============
 - Add line breaks to long test expressions.
 - Add side effect check for sizeof/ptype/whatis to vla-datatypes.exp.
 - Add test file for subranges with present DW_AT_count attribute.
 - Add introduction comments to all new functions.
 - Add patch which deals with value contents with constant byte-sequence.
   It will be squashed once the series is approved.
 - Deal with location lists in case we reference a die in DW_AT_location.
   This fixes the crash Pedro was mentioning in:
   https://sourceware.org/ml/gdb-patches/2013-11/msg00646.html
 - Renamed struct dwarf2_bound to dynamic_prop and remove all references
   to dwarf2 entities in gdbtypes.[c,h] introduced by this patch series.
 - Addressed various coding style issues.
 - Fixed typo in commit log.

Changes in v2
=============
 - Removed patch 05/10: allow side effects for sizeof argument
 - New patch: support for DW_AT_count
 - Replaced undefined_low, high with DWARF_UNDEFINED
 - Add varobj testcase to mi test
 - Fixed commit log
 - Various small issues mentioned in patches 01/10 and 02/10

Some technical background
=========================

Dwarf allows certain attributes e.g upper/lower bound to be computed
dynamically. To support this feature with the current gdb type-system types
are "normalized". This means types with dynamic properties are converted
to types with static properties.

To convert a type with dynamic properties into one with static properties
access to inferior memory is needed. Therefore we hooked into the following
value constructors value_at/value_at_lazy/value_from_contents_and_address
as they require an inferior address in addition to a type to instantiate
a value. If the passed type has dynamic properties we resolve the bounds
and thus the type is modified, not in place but rather by a new copy.

Given the following code snippet:

  struct value *val = value_at (my_vla_type, at_address);

Before this was always true:
  TYPE_LENGTH (value_type (val)) == TYPE_LENGTH (my_vla_type)

This is not the case after applying this patch series. Type normalization
is done in the mentioned value constructors and might change the value type.

Some documentation, examples as well as a github branch with support for c99
and Fortran variable length arrays is availabel at http://intel-gdb.github.io/

 -Sanimir & Keven

Sanimir Agovic (15):
  refactoring: rename create_range_type to create_static_range_type
  vla: introduce new bound type abstraction adapt uses
  type: add c99 variable length array support
  vla: enable sizeof operator to work with variable length arrays
  vla: enable sizeof operator for indirection
  vla: update type from newly created value
  vla: print "variable length" for unresolved dynamic bounds
  vla: support for DW_AT_count
  vla: resolve dynamic bounds if value contents is a constant
    byte-sequence
  vla: evaluate operand of sizeof if its type is a vla
  test: cover subranges with present DW_AT_count attribute
  test: multi-dimensional c99 vla.
  test: evaluate pointers to C99 vla correctly.
  test: basic c99 vla tests for C primitives
  test: add mi vla test

 gdb/ada-lang.c                            |  35 ++--
 gdb/c-typeprint.c                         |   6 +-
 gdb/coffread.c                            |   4 +-
 gdb/cp-valprint.c                         |   2 +
 gdb/d-valprint.c                          |   1 +
 gdb/dwarf2loc.c                           | 116 +++++++++++
 gdb/dwarf2loc.h                           |  24 +++
 gdb/dwarf2read.c                          | 153 +++++++++-----
 gdb/eval.c                                |  50 ++++-
 gdb/f-exp.y                               |   9 +-
 gdb/findvar.c                             |   3 +
 gdb/gdbtypes.c                            | 320 ++++++++++++++++++++++++------
 gdb/gdbtypes.h                            |  79 ++++++--
 gdb/jv-valprint.c                         |   1 +
 gdb/m2-valprint.c                         |   2 +-
 gdb/mdebugread.c                          |   4 +-
 gdb/parse.c                               |   3 +-
 gdb/stabsread.c                           |  11 +-
 gdb/testsuite/gdb.base/vla-datatypes.c    |  86 ++++++++
 gdb/testsuite/gdb.base/vla-datatypes.exp  | 138 +++++++++++++
 gdb/testsuite/gdb.base/vla-multi.c        |  55 +++++
 gdb/testsuite/gdb.base/vla-multi.exp      |  48 +++++
 gdb/testsuite/gdb.base/vla-ptr.c          |  63 ++++++
 gdb/testsuite/gdb.base/vla-ptr.exp        |  52 +++++
 gdb/testsuite/gdb.base/vla-sideeffect.c   |  42 ++++
 gdb/testsuite/gdb.base/vla-sideeffect.exp |  88 ++++++++
 gdb/testsuite/gdb.dwarf2/count.exp        | 106 ++++++++++
 gdb/testsuite/gdb.mi/mi-vla-c99.exp       |  82 ++++++++
 gdb/testsuite/gdb.mi/vla.c                |  35 ++++
 gdb/valops.c                              |  31 ++-
 gdb/valprint.c                            |   2 +-
 gdb/value.c                               |  18 +-
 32 files changed, 1489 insertions(+), 180 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/vla-datatypes.c
 create mode 100644 gdb/testsuite/gdb.base/vla-datatypes.exp
 create mode 100644 gdb/testsuite/gdb.base/vla-multi.c
 create mode 100644 gdb/testsuite/gdb.base/vla-multi.exp
 create mode 100644 gdb/testsuite/gdb.base/vla-ptr.c
 create mode 100644 gdb/testsuite/gdb.base/vla-ptr.exp
 create mode 100644 gdb/testsuite/gdb.base/vla-sideeffect.c
 create mode 100644 gdb/testsuite/gdb.base/vla-sideeffect.exp
 create mode 100644 gdb/testsuite/gdb.dwarf2/count.exp
 create mode 100644 gdb/testsuite/gdb.mi/mi-vla-c99.exp
 create mode 100644 gdb/testsuite/gdb.mi/vla.c

-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v5 11/15] test: cover subranges with present DW_AT_count attribute
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
@ 2014-02-06 16:27 ` Sanimir Agovic
  2014-02-28 17:52   ` Joel Brobecker
  2014-02-06 16:27 ` [PATCH v5 04/15] vla: enable sizeof operator to work with variable length arrays Sanimir Agovic
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 45+ messages in thread
From: Sanimir Agovic @ 2014-02-06 16:27 UTC (permalink / raw)
  To: tromey, brobecker; +Cc: keven.boell, gdb-patches

The dwarf attribute DW_AT_count specifies the elements of a subrange.
This test covers subranges with present count but absent upper bound
attribute, both with static and dynamic attribute values.

2013-11-26  Sanimir Agovic  <sanimir.agovic@intel.com>
            Keven Boell  <keven.boell@intel.com>

testsuite:
	* gdb.dwarf2/count.exp: New test.


Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
---
 gdb/testsuite/gdb.dwarf2/count.exp | 106 +++++++++++++++++++++++++++++++++++++
 1 file changed, 106 insertions(+)
 create mode 100644 gdb/testsuite/gdb.dwarf2/count.exp

diff --git a/gdb/testsuite/gdb.dwarf2/count.exp b/gdb/testsuite/gdb.dwarf2/count.exp
new file mode 100644
index 0000000..80744b1
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/count.exp
@@ -0,0 +1,106 @@
+# Copyright 2013 Free Software Foundation, Inc.
+
+# 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/>.
+
+# Tests to cover DW_AT_count attribute in subranges.
+
+load_lib dwarf.exp
+
+# Only run on targets which support dwarf and gas.
+if { ![dwarf2_support] } {
+    return 0
+}
+
+standard_testfile main.c count.S
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+    cu {} {
+	compile_unit {{language @DW_LANG_C99}} {
+	    declare_labels char_label array_label static_array_label
+	    declare_labels var_label
+
+	    char_label: base_type {
+		{name char}
+		{encoding @DW_ATE_signed}
+		{byte_size 1 DW_FORM_sdata}
+	    }
+
+	    array_label: array_type {
+		{type :$char_label}
+	    } {
+		subrange_type {
+		    {count {DW_OP_lit5} SPECIAL_expr}
+		    {type :$char_label}
+		}
+	    }
+
+	    static_array_label: array_type {
+		{type :$char_label}
+	    } {
+		subrange_type {
+		    {count 5 DW_FORM_sdata}
+		    {type :$char_label}
+		}
+	    }
+
+	    DW_TAG_variable {
+		{name array}
+		{type :$array_label}
+		{const_value hello DW_FORM_block1}
+	    }
+
+	    DW_TAG_variable {
+		{name static_array}
+		{type :$static_array_label}
+		{const_value world DW_FORM_block1}
+	    }
+	}
+    }
+}
+
+if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile}1.o \
+	  object {nodebug}] != "" } {
+    return -1
+}
+
+if { [gdb_compile $asm_file ${binfile}2.o object {nodebug}] != "" } {
+    return -1
+}
+
+if { [gdb_compile [list ${binfile}1.o ${binfile}2.o] \
+	  "${binfile}" executable {}] != "" } {
+    return -1
+}
+
+global GDBFLAGS
+set saved_gdbflags $GDBFLAGS
+set GDBFLAGS [concat $GDBFLAGS " -readnow"]
+clean_restart ${testfile}
+set GDBFLAGS $saved_gdbflags
+
+if ![runto_main] {
+    perror "couldn't run to main"
+    return -1
+}
+
+gdb_test "ptype array" "type = char \\\[5\\\]" "ptype array"
+gdb_test "whatis array" "type = char \\\[5\\\]" "whatis array"
+gdb_test "print array" "\"hello\"" "print array"
+gdb_test "print sizeof array" "5" "print sizeof array"
+
+gdb_test "ptype static_array" "type = char \\\[5\\\]" "ptype static_array"
+gdb_test "whatis static_array" "type = char \\\[5\\\]" "whatis static_array"
+gdb_test "print static_array" "\"world\"" "print static_array"
+gdb_test "print sizeof static_array" "5" "print sizeof static_array"
-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v5 14/15] test: basic c99 vla tests for C primitives
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
                   ` (2 preceding siblings ...)
  2014-02-06 16:27 ` [PATCH v5 08/15] vla: support for DW_AT_count Sanimir Agovic
@ 2014-02-06 16:28 ` Sanimir Agovic
  2014-02-28 18:04   ` Joel Brobecker
  2014-02-06 16:28 ` [PATCH v5 07/15] vla: print "variable length" for unresolved dynamic bounds Sanimir Agovic
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 45+ messages in thread
From: Sanimir Agovic @ 2014-02-06 16:28 UTC (permalink / raw)
  To: tromey, brobecker; +Cc: keven.boell, gdb-patches

2013-10-18  Keven Boell  <keven.boell@intel.com>
            Sanimir Agovic  <sanimir.agovic@intel.com>

gdb/testsuite:
	* gdb.base/vla-datatypes.c: New. Test source file
	for VLA datatype checks.
	* gdb.base/vla-datatypes.exp: New. Tests ensure that
	a VLA in C can be evaluated correctly with standard
	C types.


Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
---
 gdb/testsuite/gdb.base/vla-datatypes.c   |  86 +++++++++++++++++++
 gdb/testsuite/gdb.base/vla-datatypes.exp | 138 +++++++++++++++++++++++++++++++
 2 files changed, 224 insertions(+)
 create mode 100644 gdb/testsuite/gdb.base/vla-datatypes.c
 create mode 100644 gdb/testsuite/gdb.base/vla-datatypes.exp

diff --git a/gdb/testsuite/gdb.base/vla-datatypes.c b/gdb/testsuite/gdb.base/vla-datatypes.c
new file mode 100644
index 0000000..267d239
--- /dev/null
+++ b/gdb/testsuite/gdb.base/vla-datatypes.c
@@ -0,0 +1,86 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2013 Free Software Foundation, Inc.
+
+   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 <stddef.h>
+#define SIZE 5
+
+struct foo
+{
+  int a;
+};
+
+typedef struct bar
+{
+  int x;
+  struct foo y;
+} BAR;
+
+void
+vla_factory (int n)
+{
+  int             int_vla[n];
+  unsigned int    unsigned_int_vla[n];
+  double          double_vla[n];
+  float           float_vla[n];
+  long            long_vla[n];
+  unsigned long   unsigned_long_vla[n];
+  char            char_vla[n];
+  short           short_vla[n];
+  unsigned short  unsigned_short_vla[n];
+  unsigned char   unsigned_char_vla[n];
+  struct foo      foo_vla[n];
+  BAR             bar_vla[n];
+  int i;
+
+  for (i = 0; i < n; i++)
+    {
+      int_vla[i] = i*2;
+      unsigned_int_vla[i] = i*2;
+      double_vla[i] = i/2.0;
+      float_vla[i] = i/2.0f;
+      long_vla[i] = i*2;
+      unsigned_long_vla[i] = i*2;
+      char_vla[i] = 'A';
+      short_vla[i] = i*2;
+      unsigned_short_vla[i] = i*2;
+      unsigned_char_vla[i] = 'A';
+      foo_vla[i].a = i*2;
+      bar_vla[i].x = i*2;
+      bar_vla[i].y.a = i*2;
+    }
+
+  size_t int_size        = sizeof(int_vla);     /* vlas_filled */
+  size_t uint_size       = sizeof(unsigned_int_vla);
+  size_t double_size     = sizeof(double_vla);
+  size_t float_size      = sizeof(float_vla);
+  size_t long_size       = sizeof(long_vla);
+  size_t char_size       = sizeof(char_vla);
+  size_t short_size      = sizeof(short_vla);
+  size_t ushort_size     = sizeof(unsigned_short_vla);
+  size_t uchar_size      = sizeof(unsigned_char_vla);
+  size_t foo_size        = sizeof(foo_vla);
+  size_t bar_size        = sizeof(bar_vla);
+
+  return;                                 /* break_end_of_vla_factory */
+}
+
+int
+main ()
+{
+  vla_factory(SIZE);
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/vla-datatypes.exp b/gdb/testsuite/gdb.base/vla-datatypes.exp
new file mode 100644
index 0000000..c251709
--- /dev/null
+++ b/gdb/testsuite/gdb.base/vla-datatypes.exp
@@ -0,0 +1,138 @@
+# Copyright 2013 Free Software Foundation, Inc.
+
+# 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/>.
+
+standard_testfile ".c"
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_breakpoint [gdb_get_line_number "vlas_filled"]
+gdb_continue_to_breakpoint "vlas_filled"
+
+# Check the values of VLA's.
+gdb_test "print int_vla" "\\$\\d+ = \\\{0, 2, 4, 6, 8\\\}" \
+         "print int_vla"
+gdb_test "print unsigned_int_vla" "\\$\\d+ = \\\{0, 2, 4, 6, 8\\\}" \
+         "print unsigned_int_vla"
+gdb_test "print double_vla" "\\$\\d+ = \\\{0, 0.5, 1, 1.5, 2\\\}" \
+         "print double_vla"
+gdb_test "print float_vla" "\\$\\d+ = \\\{0, 0.5, 1, 1.5, 2\\\}" \
+         "print float_vla"
+gdb_test "print long_vla" "\\$\\d+ = \\\{0, 2, 4, 6, 8\\\}" \
+         "print long_vla"
+gdb_test "print unsigned_long_vla" "\\$\\d+ = \\\{0, 2, 4, 6, 8\\\}" \
+         "print unsigned_long_vla"
+gdb_test "print char_vla" "\\$\\d+ = \"AAAAA\"" \
+         "print char_vla"
+gdb_test "print short_vla" "\\$\\d+ = \\\{0, 2, 4, 6, 8\\\}" \
+         "print short_vla"
+gdb_test "print unsigned_short_vla" "\\$\\d+ = \\\{0, 2, 4, 6, 8\\\}" \
+         "print unsigned_short_vla"
+gdb_test "print unsigned_char_vla" "\\$\\d+ = \"AAAAA\"" \
+         "print unsigned_char_vla"
+gdb_test "print foo_vla" \
+         "\\\{\\\{a = 0\\\}, \\\{a = 2\\\}, \\\{a = 4\\\}, \\\{a = 6\\\}, \\\{a = 8\\\}\\\}" \
+         "print foo_vla"
+gdb_test "print bar_vla" \
+         "\\\{\\\{x = 0, y = \\\{a = 0\\\}\\\}, \\\{x = 2, y = \\\{a = 2\\\}\\\}, \\\{x = 4, y = \\\{a = 4\\\}\\\}, \\\{x = 6, y = \\\{a = 6\\\}\\\}, \\\{x = 8, y = \\\{a = 8\\\}\\\}\\\}" \
+         "print bar_vla"
+
+# Check whatis of VLA's.
+gdb_test "whatis int_vla" "type = int \\\[5\\\]" "whatis int_vla"
+gdb_test "whatis unsigned_int_vla" "type = unsigned int \\\[5\\\]" \
+         "whatis unsigned_int_vla"
+gdb_test "whatis double_vla" "type = double \\\[5\\\]" "whatis double_vla"
+gdb_test "whatis float_vla" "type = float \\\[5\\\]" "whatis float_vla"
+gdb_test "whatis long_vla" "type = long( int)? \\\[5\\\]" "whatis long_vla"
+gdb_test "whatis unsigned_long_vla" \
+         "type = (long unsigned int|unsigned long) \\\[5\\\]" \
+         "whatis unsigned_long_vla"
+gdb_test "whatis char_vla" "type = char \\\[5\\\]" "whatis char_vla"
+gdb_test "whatis short_vla" "type = short( int)? \\\[5\\\]" \
+         "whatis short_vla"
+gdb_test "whatis unsigned_short_vla" \
+         "type = (short unsigned int|unsigned short) \\\[5\\\]" \
+         "whatis unsigned_short_vla"
+gdb_test "whatis unsigned_char_vla" "type = unsigned char \\\[5\\\]" \
+         "whatis unsigned_char_vla"
+gdb_test "whatis foo_vla" "type = struct foo \\\[5\\\]" "whatis foo_vla"
+gdb_test "whatis bar_vla" "type = BAR \\\[5\\\]" "whatis bar_vla"
+
+# Check ptype of VLA's.
+gdb_test "ptype int_vla" "type = int \\\[5\\\]" "ptype int_vla"
+gdb_test "ptype unsigned_int_vla" "type = unsigned int \\\[5\\\]" \
+         "ptype unsigned_int_vla"
+gdb_test "ptype double_vla" "type = double \\\[5\\\]" "ptype double_vla"
+gdb_test "ptype float_vla" "type = float \\\[5\\\]" "ptype float_vla"
+gdb_test "ptype long_vla" "type = long( int)? \\\[5\\\]" "ptype long_vla"
+gdb_test "ptype unsigned_long_vla" "type = unsigned long \\\[5\\\]" \
+         "ptype unsigned_long_vla"
+gdb_test "ptype char_vla" "type = char \\\[5\\\]" "ptype char_vla"
+gdb_test "ptype short_vla" "type = short( int)? \\\[5\\\]" \
+         "ptype short_vla"
+gdb_test "ptype unsigned_short_vla" "type = unsigned short \\\[5\\\]" \
+         "ptype unsigned_short_vla"
+gdb_test "ptype unsigned_char_vla" "type = unsigned char \\\[5\\\]" \
+         "ptype unsigned_char_vla"
+gdb_test "ptype foo_vla" "type = struct foo {\r\n\\s+int a;\r\n} \\\[5\\\]" \
+         "ptype foo_vla"
+gdb_test "ptype bar_vla" \
+         "type = struct bar {\r\n\\s+int x;\r\n\\s+struct foo y;\r\n} \\\[5\\\]" \
+         "ptype bar_vla"
+
+# Check the size of the VLA's.
+gdb_breakpoint [gdb_get_line_number "break_end_of_vla_factory"]
+gdb_continue_to_breakpoint "break_end_of_vla_factory"
+gdb_test "print int_size == sizeof(int_vla)" "\\$\\d+ = 1" "size of int_vla"
+gdb_test "print uint_size == sizeof(unsigned_int_vla)" "\\$\\d+ = 1" \
+         "size of unsigned_int_vla"
+gdb_test "print double_size == sizeof(double_vla)" "\\$\\d+ = 1" \
+         "size of double_vla"
+gdb_test "print float_size == sizeof(float_vla)" "\\$\\d+ = 1" \
+         "size of float_vla"
+gdb_test "print long_size == sizeof(long_vla)" "\\$\\d+ = 1" \
+         "size of long_vla"
+gdb_test "print char_size == sizeof(char_vla)" "\\$\\d+ = 1" \
+         "size of char_vla"
+gdb_test "print short_size == sizeof(short_vla)" "\\$\\d+ = 1" \
+         "size of short_vla"
+gdb_test "print ushort_size == sizeof(unsigned_short_vla)" "\\$\\d+ = 1" \
+         "size of unsigned_short_vla"
+gdb_test "print uchar_size == sizeof(unsigned_char_vla)" "\\$\\d+ = 1" \
+         "size of unsigned_char_vla"
+gdb_test "print foo_size == sizeof(foo_vla)" "\\$\\d+ = 1" "size of foo_vla"
+gdb_test "print bar_size == sizeof(bar_vla)" "\\$\\d+ = 1" "size of bar_vla"
+
+# Check side effects for sizeof argument.
+set sizeof_int [get_sizeof "int" 4]
+gdb_test_no_output  "set variable int_vla\[0\] = 42" \
+                    "set variable int_vla\[0\] = 42"
+
+gdb_test "print sizeof (++int_vla\[0\])" "\\$\\d+ = ${sizeof_int}" \
+         "print sizeof (++int_vla\[0\])"
+gdb_test "print int_vla\[0\]" "\\$\\d+ = 42" \
+         "print int_vla\[0\] - sizeof no side effects"
+
+gdb_test "ptype ++int_vla\[0\]" "type = int" "ptype ++int_vla\[0\]"
+gdb_test "print int_vla\[0\]" "\\$\\d+ = 42" \
+         "print int_vla\[0\] - ptype no side effects"
+
+gdb_test "whatis ++int_vla\[0\]" "type = int" "whatis ++int_vla\[0\]"
+gdb_test "print int_vla\[0\]" "\\$\\d+ = 42" \
+         "print int_vla\[0\] - whatis no side effects"
-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v5 06/15] vla: update type from newly created value
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
                   ` (7 preceding siblings ...)
  2014-02-06 16:28 ` [PATCH v5 02/15] vla: introduce new bound type abstraction adapt uses Sanimir Agovic
@ 2014-02-06 16:28 ` Sanimir Agovic
  2014-02-06 16:28 ` [PATCH v5 05/15] vla: enable sizeof operator for indirection Sanimir Agovic
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 45+ messages in thread
From: Sanimir Agovic @ 2014-02-06 16:28 UTC (permalink / raw)
  To: tromey, brobecker; +Cc: keven.boell, gdb-patches

Constructing a value based on a type and address might change the type
of the newly constructed value. Thus re-fetch type via value_type to ensure
we have the correct type at hand.

2013-10-18  Sanimir Agovic  <sanimir.agovic@intel.com>
            Keven Boell  <keven.boell@intel.com>

	* ada-lang.c (ada_value_primitive_packed_val): Re-fetch type from value.
	(ada_template_to_fixed_record_type_1): Likewise.
	(ada_to_fixed_type_1): Likewise.
	* cp-valprint.c (cp_print_value_fields_rtti): Likewise.
	(cp_print_value): Likewise.
	* d-valprint.c (dynamic_array_type): Likewise.
	* jv-valprint.c (java_value_print): Likewise.
	* valops.c (value_ind): Likewise.
	* value.c (coerce_ref): Likewise.


Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
---
 gdb/ada-lang.c    | 13 +++++++++++--
 gdb/cp-valprint.c |  2 ++
 gdb/d-valprint.c  |  1 +
 gdb/jv-valprint.c |  1 +
 gdb/valops.c      |  3 +++
 gdb/value.c       |  1 +
 6 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 0d93267..14cdeb2 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -2300,6 +2300,7 @@ ada_value_primitive_packed_val (struct value *obj, const gdb_byte *valaddr,
   else if (VALUE_LVAL (obj) == lval_memory && value_lazy (obj))
     {
       v = value_at (type, value_address (obj));
+      type = value_type (v);
       bytes = (unsigned char *) alloca (len);
       read_memory (value_address (v) + offset, bytes, len);
     }
@@ -7657,6 +7658,7 @@ ada_template_to_fixed_record_type_1 (struct type *type,
 		 size first before creating the value.  */
 	      check_size (rtype);
 	      dval = value_from_contents_and_address (rtype, valaddr, address);
+	      rtype = value_type (dval);
 	    }
           else
             dval = dval0;
@@ -7759,7 +7761,10 @@ ada_template_to_fixed_record_type_1 (struct type *type,
       off = TYPE_FIELD_BITPOS (rtype, variant_field);
 
       if (dval0 == NULL)
-        dval = value_from_contents_and_address (rtype, valaddr, address);
+	{
+	  dval = value_from_contents_and_address (rtype, valaddr, address);
+	  rtype = value_type (dval);
+	}
       else
         dval = dval0;
 
@@ -7900,7 +7905,10 @@ to_record_with_fixed_variant_part (struct type *type, const gdb_byte *valaddr,
     return type;
 
   if (dval0 == NULL)
-    dval = value_from_contents_and_address (type, valaddr, address);
+    {
+      dval = value_from_contents_and_address (type, valaddr, address);
+      type = value_type (dval);
+    }
   else
     dval = dval0;
 
@@ -8198,6 +8206,7 @@ ada_to_fixed_type_1 (struct type *type, const gdb_byte *valaddr,
 	      value_from_contents_and_address (fixed_record_type,
 					       valaddr,
 					       address);
+            fixed_record_type = value_type (obj);
             if (real_type != NULL)
               return to_fixed_record_type
 		(real_type, NULL,
diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c
index bcf54ff..b868d37 100644
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -443,6 +443,7 @@ cp_print_value_fields_rtti (struct type *type,
       /* Ugh, we have to convert back to a value here.  */
       value = value_from_contents_and_address (type, valaddr + offset,
 					       address + offset);
+      type = value_type (value);
       /* We don't actually care about most of the result here -- just
 	 the type.  We already have the correct offset, due to how
 	 val_print was initially called.  */
@@ -545,6 +546,7 @@ cp_print_value (struct type *type, struct type *real_type,
 		  base_val = value_from_contents_and_address (baseclass,
 							      buf,
 							      address + boffset);
+		  baseclass = value_type (base_val);
 		  thisoffset = 0;
 		  boffset = 0;
 		  thistype = baseclass;
diff --git a/gdb/d-valprint.c b/gdb/d-valprint.c
index 6e9c28d..cca629a 100644
--- a/gdb/d-valprint.c
+++ b/gdb/d-valprint.c
@@ -59,6 +59,7 @@ dynamic_array_type (struct type *type, const gdb_byte *valaddr,
 
       true_type = lookup_array_range_type (true_type, 0, length - 1);
       ival = value_at (true_type, addr);
+      true_type = value_type (ival);
 
       d_val_print (true_type,
 		   value_contents_for_printing (ival),
diff --git a/gdb/jv-valprint.c b/gdb/jv-valprint.c
index f465ca0..808e01b 100644
--- a/gdb/jv-valprint.c
+++ b/gdb/jv-valprint.c
@@ -65,6 +65,7 @@ java_value_print (struct value *val, struct ui_file *stream,
 	  type = lookup_pointer_type (type);
 
 	  val = value_at (type, address);
+	  type = value_type (val);
 	}
     }
 
diff --git a/gdb/valops.c b/gdb/valops.c
index a7260b9..270cbef 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -268,6 +268,7 @@ value_cast_structs (struct type *type, struct value *v2)
 	{
 	  v = value_full_object (v2, real_type, full, top, using_enc);
 	  v = value_at_lazy (real_type, value_address (v));
+	  real_type = value_type (v);
 
 	  /* We might be trying to cast to the outermost enclosing
 	     type, in which case search_struct_field won't work.  */
@@ -803,6 +804,7 @@ value_dynamic_cast (struct type *type, struct value *arg)
     return value_at_lazy (type, addr);
 
   tem = value_at (type, addr);
+  type = value_type (tem);
 
   /* The first dynamic check specified in 5.2.7.  */
   if (is_public_ancestor (arg_type, TYPE_TARGET_TYPE (resolved_type)))
@@ -1617,6 +1619,7 @@ value_ind (struct value *arg1)
 			      (value_as_address (arg1)
 			       - value_pointed_to_offset (arg1)));
 
+      enc_type = value_type (arg2);
       return readjust_indirect_value_type (arg2, enc_type, base_type, arg1);
     }
 
diff --git a/gdb/value.c b/gdb/value.c
index 12726a1..7e6e0e7 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -3362,6 +3362,7 @@ coerce_ref (struct value *arg)
   retval = value_at_lazy (enc_type,
                           unpack_pointer (value_type (arg),
                                           value_contents (arg)));
+  enc_type = value_type (retval);
   return readjust_indirect_value_type (retval, enc_type,
                                        value_type_arg_tmp, arg);
 }
-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v5 09/15] vla: resolve dynamic bounds if value contents is a constant byte-sequence
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
                   ` (11 preceding siblings ...)
  2014-02-06 16:28 ` [PATCH v5 10/15] vla: evaluate operand of sizeof if its type is a vla Sanimir Agovic
@ 2014-02-06 16:28 ` Sanimir Agovic
  2014-02-07 10:27   ` Joel Brobecker
  2014-02-28 17:09   ` Joel Brobecker
  2014-02-06 16:28 ` [PATCH v5 12/15] test: multi-dimensional c99 vla Sanimir Agovic
                   ` (3 subsequent siblings)
  16 siblings, 2 replies; 45+ messages in thread
From: Sanimir Agovic @ 2014-02-06 16:28 UTC (permalink / raw)
  To: tromey, brobecker; +Cc: keven.boell, gdb-patches

A variable location might be a constant value and therefore no inferior memory
access is needed to read the content. In this case try to resolve the type
bounds.

2013-11-26  Sanimir Agovic  <sanimir.agovic@intel.com>
            Keven Boell  <keven.boell@intel.com>

	* findvar.c (default_read_var_value): Resolve dynamic bounds if location
	points to a constant blob.


Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
---
 gdb/findvar.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/gdb/findvar.c b/gdb/findvar.c
index ec6afd6..a543dc4 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -468,6 +468,9 @@ default_read_var_value (struct symbol *var, struct frame_info *frame)
       return v;
 
     case LOC_CONST_BYTES:
+      if (is_dynamic_type (type))
+	/* Value is a constant byte-sequence and needs no memory access.  */
+	type = resolve_dynamic_type (type, /* Unused address.  */ 0);
       v = allocate_value (type);
       memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var),
 	      TYPE_LENGTH (type));
-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v5 15/15] test: add mi vla test
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
                   ` (4 preceding siblings ...)
  2014-02-06 16:28 ` [PATCH v5 07/15] vla: print "variable length" for unresolved dynamic bounds Sanimir Agovic
@ 2014-02-06 16:28 ` Sanimir Agovic
  2014-02-28 18:07   ` Joel Brobecker
  2014-02-06 16:28 ` [PATCH v5 01/15] refactoring: rename create_range_type to create_static_range_type Sanimir Agovic
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 45+ messages in thread
From: Sanimir Agovic @ 2014-02-06 16:28 UTC (permalink / raw)
  To: tromey, brobecker; +Cc: keven.boell, gdb-patches

2013-10-18  Keven Boell  <keven.boell@intel.com>
            Sanimir Agovic  <sanimir.agovic@intel.com>

testsuite/gdb.mi/

	* mi-vla-c99.exp: New file.
	* vla.c: New file.


Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
---
 gdb/testsuite/gdb.mi/mi-vla-c99.exp | 82 +++++++++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.mi/vla.c          | 35 ++++++++++++++++
 2 files changed, 117 insertions(+)
 create mode 100644 gdb/testsuite/gdb.mi/mi-vla-c99.exp
 create mode 100644 gdb/testsuite/gdb.mi/vla.c

diff --git a/gdb/testsuite/gdb.mi/mi-vla-c99.exp b/gdb/testsuite/gdb.mi/mi-vla-c99.exp
new file mode 100644
index 0000000..9d0c6cc
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/mi-vla-c99.exp
@@ -0,0 +1,82 @@
+# Copyright 1999-2013 Free Software Foundation, Inc.
+
+# Contributed by Intel Corp. <keven.boell@intel.com>
+#
+# 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/>.
+
+# Verify that, using the MI, we can evaluate a simple C Variable Length
+# Array (VLA).
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+    continue
+}
+
+standard_testfile vla.c
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" \
+                  "${binfile}" executable {debug}] != "" } {
+     untested mi-vla-basics.exp
+     return -1
+}
+
+mi_delete_breakpoints
+mi_gdb_reinitialize_dir $srcdir/$subdir
+mi_gdb_load ${binfile}
+
+set bp_lineno [gdb_get_line_number "vla-filled"]
+
+mi_create_breakpoint "-t vla.c:$bp_lineno" 1 "del" "func" \
+             ".*vla.c" $bp_lineno $hex \
+             "insert breakpoint at line $bp_lineno after vla is filled"
+mi_run_cmd
+mi_expect_stop "breakpoint-hit" "func" "\{name=\"n\",value=\"5\"\}" \
+               ".*vla.c" "$bp_lineno" { "" "disp=\"del\"" } \
+               "run to breakpoint at line $bp_lineno"
+
+mi_gdb_test "500-data-evaluate-expression vla" \
+    "500\\^done,value=\"\\{0, 1, 2, 3, 4\\}\"" "evaluate complete vla"
+
+mi_gdb_test "501-data-evaluate-expression vla\[0\]" \
+    "501\\^done,value=\"0\"" "evaluate vla\[0\]"
+
+mi_gdb_test "502-data-evaluate-expression vla\[2\]" \
+    "502\\^done,value=\"2\"" "evaluate vla\[2\]"
+
+mi_gdb_test "503-data-evaluate-expression vla\[4\]" \
+    "503\\^done,value=\"4\"" "evaluate vla\[4\]"
+
+mi_create_varobj_checked vla vla "int \\\[5\\\]" \
+                                 "create local variable vla"
+
+mi_gdb_test "504-var-info-type vla" \
+    "504\\^done,type=\"int \\\[5\\\]\"" \
+    "info type variable vla"
+
+mi_gdb_test "505-var-show-format vla" \
+    "505\\^done,format=\"natural\"" \
+    "show format variable vla"
+
+mi_gdb_test "506-var-evaluate-expression vla" \
+    "506\\^done,value=\"\\\[5\\\]\"" \
+    "eval variable vla"
+
+mi_list_array_varobj_children "vla" "5" "int" \
+    "get children of vla"
+
+mi_gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.mi/vla.c b/gdb/testsuite/gdb.mi/vla.c
new file mode 100644
index 0000000..9b33fc8
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/vla.c
@@ -0,0 +1,35 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Contributed by Intel Corp. <keven.boell@intel.com>
+
+   Copyright 2013 Free Software Foundation, Inc.
+
+   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/>.  */
+
+int func (int n)
+{
+  int vla[n], i;
+
+  for (i = 0; i < n; i++)
+    vla[i] = i;
+
+  return n;                 /* vla-filled */
+}
+
+int main ()
+{
+  func (5);
+
+  return 0;
+}
-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v5 10/15] vla: evaluate operand of sizeof if its type is a vla
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
                   ` (10 preceding siblings ...)
  2014-02-06 16:28 ` [PATCH v5 13/15] test: evaluate pointers to C99 vla correctly Sanimir Agovic
@ 2014-02-06 16:28 ` Sanimir Agovic
  2014-02-28 17:37   ` Joel Brobecker
  2014-02-06 16:28 ` [PATCH v5 09/15] vla: resolve dynamic bounds if value contents is a constant byte-sequence Sanimir Agovic
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 45+ messages in thread
From: Sanimir Agovic @ 2014-02-06 16:28 UTC (permalink / raw)
  To: tromey, brobecker; +Cc: keven.boell, gdb-patches

The c99 standard in "6.5.3.4 The sizeof operator" states:

 If the type of the operand is a variable length array type, the operand
 is evaluated;[...]

This patch mirrors the following c99 semantic in gdb:

 1| int vla[n][m];
 2| int i = 1;
 3| sizeof(vla[i++][0]); // No sideffect
 4| assert (i == 1);
 5| sizeof(vla[i++]);    // With sideffect
 6| assert (i == 2);

Note: ptype/whatsis still do not allow any sideeffects.

This patch was motivated by:

  https://sourceware.org/ml/gdb-patches/2014-01/msg00732.html

2014-02-05  Sanimir Agovic  <sanimir.agovic@intel.com>
            Keven Boell <keven.boell@intel.com>

	* eval.c (evaluate_subexp_for_sizeof): Add enum noside argument.
	(evaluate_subexp_standard): Pass noside argument.
	(evaluate_subexp_for_sizeof) <BINOP_SUBSCRIPT>: Handle subscript case
	if noside equals EVAL_NORMAL. If the subscript yields a vla type
	re-evaluate subscript operation with EVAL_NORMAL to enable sideffects.
	* gdbtypes.c (resolve_dynamic_bounds): Mark bound as evaluated.
	* gdbtypes.h (enum range_flags): Add RANGE_EVALUATED case.

testsuite/gdb.base/

	* vla-sideeffect.c: New file.
	* vla-sideeffect.exp: New file.


Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
---
 gdb/eval.c                                | 40 ++++++++++++--
 gdb/gdbtypes.c                            |  1 +
 gdb/gdbtypes.h                            |  3 +-
 gdb/testsuite/gdb.base/vla-sideeffect.c   | 42 +++++++++++++++
 gdb/testsuite/gdb.base/vla-sideeffect.exp | 88 +++++++++++++++++++++++++++++++
 5 files changed, 170 insertions(+), 4 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/vla-sideeffect.c
 create mode 100644 gdb/testsuite/gdb.base/vla-sideeffect.exp

diff --git a/gdb/eval.c b/gdb/eval.c
index b3e45ca..7a34b95 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -51,7 +51,8 @@ extern int overload_resolution;
 
 /* Prototypes for local functions.  */
 
-static struct value *evaluate_subexp_for_sizeof (struct expression *, int *);
+static struct value *evaluate_subexp_for_sizeof (struct expression *, int *,
+						 enum noside);
 
 static struct value *evaluate_subexp_for_address (struct expression *,
 						  int *, enum noside);
@@ -2563,7 +2564,7 @@ evaluate_subexp_standard (struct type *expect_type,
 	  evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
 	  goto nosideret;
 	}
-      return evaluate_subexp_for_sizeof (exp, pos);
+      return evaluate_subexp_for_sizeof (exp, pos, noside);
 
     case UNOP_CAST:
       (*pos) += 2;
@@ -3000,7 +3001,8 @@ evaluate_subexp_with_coercion (struct expression *exp,
    Advance *POS over the subexpression.  */
 
 static struct value *
-evaluate_subexp_for_sizeof (struct expression *exp, int *pos)
+evaluate_subexp_for_sizeof (struct expression *exp, int *pos,
+			    enum noside noside)
 {
   /* FIXME: This should be size_t.  */
   struct type *size_type = builtin_type (exp->gdbarch)->builtin_int;
@@ -3054,6 +3056,38 @@ evaluate_subexp_for_sizeof (struct expression *exp, int *pos)
       return
 	value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
 
+    case BINOP_SUBSCRIPT:
+      if (noside == EVAL_NORMAL)
+	{
+	  int oldpos = *pos;
+
+	  (*pos) += 1;
+	  val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+	  *pos = oldpos;
+	  noside = EVAL_AVOID_SIDE_EFFECTS;
+
+	  type = check_typedef (value_type (val));
+	  if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
+	    {
+	      type = check_typedef (TYPE_TARGET_TYPE (type));
+	      if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
+		{
+		  type = TYPE_INDEX_TYPE (type);
+		  if ((TYPE_RANGE_DATA (type)->flags & RANGE_EVALUATED)
+		      == RANGE_EVALUATED)
+		    {
+		      val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_NORMAL);
+		      return value_from_longest
+			(size_type, (LONGEST)TYPE_LENGTH (value_type (val)));
+		    }
+		}
+	    }
+	}
+
+      val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
+      return value_from_longest (size_type,
+				 (LONGEST)TYPE_LENGTH (value_type (val)));
+
     default:
       val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
       return value_from_longest (size_type,
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 83a2c75..67aa439 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -1697,6 +1697,7 @@ resolve_dynamic_bounds (struct type *type, CORE_ADDR addr)
     = create_range_type (NULL,
 			 TYPE_TARGET_TYPE (range_type),
 			 &low_bound, &high_bound);
+  TYPE_RANGE_DATA (range_type)->flags |= RANGE_EVALUATED;
   array_type = create_array_type (copy_type (type),
 				  array_type,
 				  range_type);
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 100e3f4..4e92d4a 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -396,7 +396,8 @@ struct dynamic_prop
 
 enum range_flags
 {
-  RANGE_UPPER_BOUND_IS_COUNT = 1 /* High bound contains number of elements.  */
+  RANGE_UPPER_BOUND_IS_COUNT = 1, /* High bound contains number of elements.  */
+  RANGE_EVALUATED                 /* Bound was dynamic.  */
 };
 
 /* Determine which field of the union main_type.fields[x].loc is used.  */
diff --git a/gdb/testsuite/gdb.base/vla-sideeffect.c b/gdb/testsuite/gdb.base/vla-sideeffect.c
new file mode 100644
index 0000000..29ee99b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/vla-sideeffect.c
@@ -0,0 +1,42 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2014 Free Software Foundation, Inc.
+
+   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 <stddef.h>
+#define SIZE 10
+
+int
+main ()
+{
+  int n = SIZE;
+  int i = 0;
+  int j = 0;
+  int vla2[SIZE][n];
+  int vla1[n];
+
+  for (i = 0; i < n; i++)
+    vla1[i] = (i * 2) + n;
+
+  for (i = 0; i < SIZE; i++)
+    for (j = 0; j < n; j++)
+      vla2[i][j] = (i + j) + n;
+
+
+  i = 0;
+  j = 0;
+
+  return 0;           /* vla-filled */
+}
diff --git a/gdb/testsuite/gdb.base/vla-sideeffect.exp b/gdb/testsuite/gdb.base/vla-sideeffect.exp
new file mode 100644
index 0000000..0ea9bc2
--- /dev/null
+++ b/gdb/testsuite/gdb.base/vla-sideeffect.exp
@@ -0,0 +1,88 @@
+# Copyright 2014 Free Software Foundation, Inc.
+
+# 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/>.
+
+# Tests sideffect of sizeof evaluation.
+# Based on gcc/testsuite/gcc.dg/vla-4.c; vla-15.c
+
+standard_testfile ".c"
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_breakpoint [gdb_get_line_number "vla-filled"]
+gdb_continue_to_breakpoint "vla-filled"
+
+# Check side effects for sizeof argument.
+set sizeof_int [get_sizeof "int" 4]
+set sizeof_vla [ expr "10" * "$sizeof_int" ]
+
+gdb_test "print sizeof (vla1\[i++\])" "\\$\\d+ = ${sizeof_int}" \
+         "print sizeof (vla1\[i++\])"
+gdb_test "print i" "\\$\\d+ = 0" \
+         "print i - sizeof no side effects"
+
+gdb_test "print sizeof (++vla1\[0\])" "\\$\\d+ = ${sizeof_int}" \
+         "print sizeof (++vla1\[0\])"
+gdb_test "print vla1\[0\]" "\\$\\d+ = 10" \
+         "print vla1\[0\] - sizeof no side effects"
+
+gdb_test "ptype ++vla1\[0\]" "type = int" "ptype ++vla1\[0\]"
+gdb_test "print vla1\[0\]" "\\$\\d+ = 10" \
+         "print vla1\[0\] - ptype no side effects"
+
+gdb_test "whatis ++vla1\[0\]" "type = int" "whatis ++vla1\[0\]"
+gdb_test "print vla1\[0\]" "\\$\\d+ = 10" \
+         "print vla1\[0\] - whatis no side effects"
+
+
+gdb_test "print sizeof (vla2\[i++\])" "\\$\\d+ = ${sizeof_vla}" \
+         "print sizeof (vla2\[i++\])"
+gdb_test "print i" "\\$\\d+ = 1" \
+         "print i - sizeof with side effects (1)"
+
+gdb_test "print sizeof (vla2\[i++ + sizeof(j++)\])" "\\$\\d+ = ${sizeof_vla}" \
+         "print sizeof (vla2\[i++ + sizeof(j++)\])"
+gdb_test "print i" "\\$\\d+ = 2" \
+         "print i - sizeof with side effects (2)"
+gdb_test "print j" "\\$\\d+ = 0" \
+         "print j - sizeof with no side effects"
+
+gdb_test "ptype vla2\[i++\]" "type = int \\\[10\\\]" \
+         "ptype vla2\[i++\]"
+gdb_test "print i" "\\$\\d+ = 2" \
+         "print i - ptype with side effects (1)"
+
+gdb_test "ptype vla2\[i++ + sizeof(j++)\]" "type = int \\\[10\\\]" \
+         "ptype vla2\[i++ + sizeof(j++)\]"
+gdb_test "print i" "\\$\\d+ = 2" \
+         "print i - ptype with side effects (2)"
+gdb_test "print j" "\\$\\d+ = 0" \
+         "print j - ptype with no side effects"
+
+gdb_test "whatis vla2\[i++\]" "type = int \\\[10\\\]" \
+         "whatis vla2\[i++\]"
+gdb_test "print i" "\\$\\d+ = 2" \
+         "print i - whatis with side effects (1)"
+
+gdb_test "whatis vla2\[i++ + sizeof(j++)\]" "type = int \\\[10\\\]" \
+         "whatis vla2\[i++ + sizeof(j++)\]"
+gdb_test "print i" "\\$\\d+ = 2" \
+         "print i - whatis with side effects (2)"
+gdb_test "print j" "\\$\\d+ = 0" \
+         "print j - whatis with no side effects"
-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v5 01/15] refactoring: rename create_range_type to create_static_range_type
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
                   ` (5 preceding siblings ...)
  2014-02-06 16:28 ` [PATCH v5 15/15] test: add mi vla test Sanimir Agovic
@ 2014-02-06 16:28 ` Sanimir Agovic
  2014-02-27 22:03   ` Joel Brobecker
  2014-02-06 16:28 ` [PATCH v5 02/15] vla: introduce new bound type abstraction adapt uses Sanimir Agovic
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 45+ messages in thread
From: Sanimir Agovic @ 2014-02-06 16:28 UTC (permalink / raw)
  To: tromey, brobecker; +Cc: keven.boell, gdb-patches

2013-12-19  Sanimir Agovic  <sanimir.agovic@intel.com>
            Keven Boell <keven.boell@intel.com>

	* gdbtypes.c (create_static_range_type): Renamed from create_range_type.
	* gdbtypes.h (create_static_range_type): Renamed from create_range_type.
	* ada-lang.c (*): All uses of create_range_type updated.
	* coffread.c (*): All uses of create_range_type updated.
	* dwarf2read.c (*): All uses of create_range_type updated.
	* f-exp.y (*): All uses of create_range_type updated.
	* m2-valprint.c (*): All uses of create_range_type updated.
	* mdebugread.c (*): All uses of create_range_type updated.
	* stabsread.c (*): All uses of create_range_type updated.
	* valops.c (*): All uses of create_range_type updated.
	* valprint.c (*): All uses of create_range_type updated.


Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
---
 gdb/ada-lang.c    | 22 +++++++++++-----------
 gdb/coffread.c    |  4 ++--
 gdb/dwarf2read.c  |  6 +++---
 gdb/f-exp.y       |  9 ++++++---
 gdb/gdbtypes.c    |  6 +++---
 gdb/gdbtypes.h    |  4 ++--
 gdb/m2-valprint.c |  2 +-
 gdb/mdebugread.c  |  4 ++--
 gdb/stabsread.c   | 11 ++++++-----
 gdb/valops.c      | 16 ++++++++--------
 gdb/valprint.c    |  2 +-
 11 files changed, 45 insertions(+), 41 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 786ca7a..0d93267 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -1875,8 +1875,8 @@ ada_type_of_array (struct value *arr, int bounds)
           struct value *high = desc_one_bound (descriptor, arity, 1);
 
           arity -= 1;
-          create_range_type (range_type, value_type (low),
-                             longest_to_int (value_as_long (low)),
+          create_static_range_type (range_type, value_type (low),
+				    longest_to_int (value_as_long (low)),
                              longest_to_int (value_as_long (high)));
           elt_type = create_array_type (array_type, elt_type, range_type);
 
@@ -2649,8 +2649,8 @@ ada_value_slice_from_ptr (struct value *array_ptr, struct type *type,
     + ((low - ada_discrete_type_low_bound (TYPE_INDEX_TYPE (type0)))
        * TYPE_LENGTH (TYPE_TARGET_TYPE (type0)));
   struct type *index_type =
-    create_range_type (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type0)),
-                       low, high);
+    create_static_range_type (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type0)),
+			      low, high);
   struct type *slice_type =
     create_array_type (NULL, TYPE_TARGET_TYPE (type0), index_type);
 
@@ -2663,7 +2663,7 @@ ada_value_slice (struct value *array, int low, int high)
 {
   struct type *type = ada_check_typedef (value_type (array));
   struct type *index_type =
-    create_range_type (NULL, TYPE_INDEX_TYPE (type), low, high);
+    create_static_range_type (NULL, TYPE_INDEX_TYPE (type), low, high);
   struct type *slice_type =
     create_array_type (NULL, TYPE_TARGET_TYPE (type), index_type);
 
@@ -2872,8 +2872,8 @@ empty_array (struct type *arr_type, int low)
 {
   struct type *arr_type0 = ada_check_typedef (arr_type);
   struct type *index_type =
-    create_range_type (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (arr_type0)),
-                       low, low - 1);
+    create_static_range_type
+    (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (arr_type0)), low, low - 1);
   struct type *elt_type = ada_array_element_type (arr_type0, 1);
 
   return allocate_value (create_array_type (NULL, elt_type, index_type));
@@ -10853,9 +10853,8 @@ to_fixed_range_type (struct type *raw_type, struct value *dval)
       if (L < INT_MIN || U > INT_MAX)
 	return raw_type;
       else
-	return create_range_type (alloc_type_copy (raw_type), raw_type,
-				  ada_discrete_type_low_bound (raw_type),
-				  ada_discrete_type_high_bound (raw_type));
+	return create_static_range_type (alloc_type_copy (raw_type), raw_type,
+					 L, U);
     }
   else
     {
@@ -10918,7 +10917,8 @@ to_fixed_range_type (struct type *raw_type, struct value *dval)
             }
         }
 
-      type = create_range_type (alloc_type_copy (raw_type), base_type, L, U);
+      type = create_static_range_type (alloc_type_copy (raw_type),
+				       base_type, L, U);
       TYPE_NAME (type) = name;
       return type;
     }
diff --git a/gdb/coffread.c b/gdb/coffread.c
index b49e30c..0e6cd88 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -1842,8 +1842,8 @@ decode_type (struct coff_symbol *cs, unsigned int c_type,
 	  base_type = decode_type (cs, new_c_type, aux, objfile);
 	  index_type = objfile_type (objfile)->builtin_int;
 	  range_type =
-	    create_range_type ((struct type *) NULL, 
-			       index_type, 0, n - 1);
+	    create_static_range_type ((struct type *) NULL,
+				      index_type, 0, n - 1);
 	  type =
 	    create_array_type ((struct type *) NULL, 
 			       base_type, range_type);
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 1c7dfc5..4ba25ff 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -13231,7 +13231,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
   if (die->child == NULL)
     {
       index_type = objfile_type (objfile)->builtin_int;
-      range_type = create_range_type (NULL, index_type, 0, -1);
+      range_type = create_static_range_type (NULL, index_type, 0, -1);
       type = create_array_type (NULL, element_type, range_type);
       return set_die_type (die, type, cu);
     }
@@ -13935,7 +13935,7 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
     }
 
   index_type = objfile_type (objfile)->builtin_int;
-  range_type = create_range_type (NULL, index_type, 1, length);
+  range_type = create_static_range_type (NULL, index_type, 1, length);
   char_type = language_string_char_type (cu->language_defn, gdbarch);
   type = create_string_type (NULL, char_type, range_type);
 
@@ -14400,7 +14400,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
   if (!TYPE_UNSIGNED (base_type) && (high & negative_mask))
     high |= negative_mask;
 
-  range_type = create_range_type (NULL, orig_base_type, low, high);
+  range_type = create_static_range_type (NULL, orig_base_type, low, high);
 
   /* Mark arrays with dynamic length at least as an array of unspecified
      length.  GDB could check the boundary but before it gets implemented at
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
index 567cd00..af8de68 100644
--- a/gdb/f-exp.y
+++ b/gdb/f-exp.y
@@ -558,10 +558,13 @@ ptype	:	typebase
 			array_size = pop_type_int ();
 			if (array_size != -1)
 			  {
+			    struct type *index_type;
+
+			    index_type = parse_f_type->builtin_integer;
 			    range_type =
-			      create_range_type ((struct type *) NULL,
-						 parse_f_type->builtin_integer,
-						 0, array_size - 1);
+			      create_static_range_type((struct type *) NULL,
+						       index_type,
+						       0, array_size - 1);
 			    follow_type =
 			      create_array_type ((struct type *) NULL,
 						 follow_type, range_type);
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 2470304..807e18e 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -809,8 +809,8 @@ allocate_stub_method (struct type *type)
    sure it is TYPE_CODE_UNDEF before we bash it into a range type?  */
 
 struct type *
-create_range_type (struct type *result_type, struct type *index_type,
-		   LONGEST low_bound, LONGEST high_bound)
+create_static_range_type (struct type *result_type, struct type *index_type,
+			  LONGEST low_bound, LONGEST high_bound)
 {
   if (result_type == NULL)
     result_type = alloc_type_copy (index_type);
@@ -998,7 +998,7 @@ lookup_array_range_type (struct type *element_type,
   struct gdbarch *gdbarch = get_type_arch (element_type);
   struct type *index_type = builtin_type (gdbarch)->builtin_int;
   struct type *range_type
-    = create_range_type (NULL, index_type, low_bound, high_bound);
+    = create_static_range_type (NULL, index_type, low_bound, high_bound);
 
   return create_array_type (NULL, element_type, range_type);
 }
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index c7bef5f..0396078 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1526,8 +1526,8 @@ extern struct type *lookup_function_type_with_arguments (struct type *,
 							 int,
 							 struct type **);
 
-extern struct type *create_range_type (struct type *, struct type *, LONGEST,
-				       LONGEST);
+extern struct type *create_static_range_type (struct type *, struct type *,
+					      LONGEST, LONGEST);
 
 extern struct type *create_array_type (struct type *, struct type *,
 				       struct type *);
diff --git a/gdb/m2-valprint.c b/gdb/m2-valprint.c
index f8a8f75..12c38a5 100644
--- a/gdb/m2-valprint.c
+++ b/gdb/m2-valprint.c
@@ -475,7 +475,7 @@ m2_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
 			address, stream, recurse, original_value, options);
 	  break;
 	}
-      /* FIXME: create_range_type does not set the unsigned bit in a
+      /* FIXME: create_static_range_type does not set the unsigned bit in a
          range type (I think it probably should copy it from the target
          type), so we won't print values which are too large to
          fit in a signed integer correctly.  */
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index bbeea12..b0ba3ee 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -1869,8 +1869,8 @@ upgrade_type (int fd, struct type **tpp, int tq, union aux_ext *ax, int bigend,
       ax++;
       rf = AUX_GET_WIDTH (bigend, ax);	/* bit size of array element */
 
-      range = create_range_type ((struct type *) NULL, indx,
-				 lower, upper);
+      range = create_static_range_type ((struct type *) NULL, indx,
+					lower, upper);
 
       t = create_array_type ((struct type *) NULL, *tpp, range);
 
diff --git a/gdb/stabsread.c b/gdb/stabsread.c
index 0046772..b8e36d4 100644
--- a/gdb/stabsread.c
+++ b/gdb/stabsread.c
@@ -863,9 +863,9 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type,
 	    /* NULL terminate the string.  */
 	    string_local[ind] = 0;
 	    range_type
-	      = create_range_type (NULL,
-				   objfile_type (objfile)->builtin_int,
-				   0, ind);
+	      = create_static_range_type (NULL,
+					  objfile_type (objfile)->builtin_int,
+					  0, ind);
 	    SYMBOL_TYPE (sym) = create_array_type (NULL,
 				  objfile_type (objfile)->builtin_char,
 				  range_type);
@@ -3615,7 +3615,7 @@ read_array_type (char **pp, struct type *type,
     }
 
   range_type =
-    create_range_type ((struct type *) NULL, index_type, lower, upper);
+    create_static_range_type ((struct type *) NULL, index_type, lower, upper);
   type = create_array_type (type, element_type, range_type);
 
   return type;
@@ -4245,7 +4245,8 @@ handle_true_range:
       index_type = objfile_type (objfile)->builtin_int;
     }
 
-  result_type = create_range_type ((struct type *) NULL, index_type, n2, n3);
+  result_type
+    = create_static_range_type ((struct type *) NULL, index_type, n2, n3);
   return (result_type);
 }
 
diff --git a/gdb/valops.c b/gdb/valops.c
index d43c758..5c7bb89 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -415,10 +415,10 @@ value_cast (struct type *type, struct value *arg2)
 		       "divide object size in cast"));
 	  /* FIXME-type-allocation: need a way to free this type when
 	     we are done with it.  */
-	  range_type = create_range_type ((struct type *) NULL,
-					  TYPE_TARGET_TYPE (range_type),
-					  low_bound,
-					  new_length + low_bound - 1);
+	  range_type = create_static_range_type ((struct type *) NULL,
+						 TYPE_TARGET_TYPE (range_type),
+						 low_bound,
+						 new_length + low_bound - 1);
 	  deprecated_set_value_type (arg2, 
 				     create_array_type ((struct type *) NULL,
 							element_type, 
@@ -3569,10 +3569,10 @@ value_slice (struct value *array, int lowbound, int length)
 
   /* FIXME-type-allocation: need a way to free this type when we are
      done with it.  */
-  slice_range_type = create_range_type ((struct type *) NULL,
-					TYPE_TARGET_TYPE (range_type),
-					lowbound, 
-					lowbound + length - 1);
+  slice_range_type = create_static_range_type ((struct type *) NULL,
+					       TYPE_TARGET_TYPE (range_type),
+					       lowbound,
+					       lowbound + length - 1);
 
     {
       struct type *element_type = TYPE_TARGET_TYPE (array_type);
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 7ebcdfd..b178109 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -597,7 +597,7 @@ generic_val_print (struct type *type, const gdb_byte *valaddr,
       break;
 
     case TYPE_CODE_RANGE:
-      /* FIXME: create_range_type does not set the unsigned bit in a
+      /* FIXME: create_static_range_type does not set the unsigned bit in a
          range type (I think it probably should copy it from the
          target type), so we won't print values which are too large to
          fit in a signed integer correctly.  */
-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v5 03/15] type: add c99 variable length array support
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
                   ` (13 preceding siblings ...)
  2014-02-06 16:28 ` [PATCH v5 12/15] test: multi-dimensional c99 vla Sanimir Agovic
@ 2014-02-06 16:28 ` Sanimir Agovic
  2014-02-28 16:27   ` Joel Brobecker
  2014-02-09  3:49 ` [PATCH v5 00/15] C99 " Joel Brobecker
  2014-02-28 18:13 ` status update: " Joel Brobecker
  16 siblings, 1 reply; 45+ messages in thread
From: Sanimir Agovic @ 2014-02-06 16:28 UTC (permalink / raw)
  To: tromey, brobecker; +Cc: keven.boell, gdb-patches

The dwarf standard allow certain attributes to be expressed as dwarf
expressions rather than constants. For instance upper-/lowerbound attributes.
In case of a c99 variable length array the upperbound is a dynamic attribute.

With this change c99 vla behave the same as with static arrays.

1| void foo (size_t n) {
2|   int ary[n];
3|   memset(ary, 0, sizeof(ary));
4| }

(gdb) print ary
$1 = {0 <repeats 42 times>}

2013-10-18  Sanimir Agovic  <sanimir.agovic@intel.com>
            Keven Boell  <keven.boell@intel.com>

	* dwarf2loc.c (dwarf2_locexpr_baton_eval): New function.
	(dwarf2_evaluate_property): New function.
	* dwarf2loc.h (dwarf2_evaluate_property): New function prototype.
	* dwarf2read.c (attr_to_dynamic_prop): New function.
	(read_subrange_type): Use attr_to_dynamic_prop to read high bound
	attribute.
	* gdbtypes.c: Include dwarf2loc.h.
	(is_dynamic_type): New function.
	(resolve_dynamic_type): New function.
	(resolve_dynamic_bounds): New function.
	(get_type_length): New function.
	(check_typedef): Use get_type_length to compute type length.
	* gdbtypes.h (TYPE_HIGH_BOUND_KIND): New macro.
	(TYPE_LOW_BOUND_KIND): New macro.
	(is_dynamic_type): New function prototype.
	* value.c (value_from_contents_and_address): Call resolve_dynamic_type
	to resolve dynamic properties of the type. Update comment.
	* valops.c (get_value_at, value_at, value_at_lazy): Update comment.


Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
---
 gdb/dwarf2loc.c  | 120 +++++++++++++++++++++++++
 gdb/dwarf2loc.h  |  24 +++++
 gdb/dwarf2read.c | 100 +++++++++++++++------
 gdb/gdbtypes.c   | 264 ++++++++++++++++++++++++++++++++++++++++++++-----------
 gdb/gdbtypes.h   |  10 +++
 gdb/valops.c     |  12 ++-
 gdb/value.c      |  17 ++--
 7 files changed, 459 insertions(+), 88 deletions(-)

diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 2b1f323..72bc727 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -2431,6 +2431,126 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame,
   return dwarf2_evaluate_loc_desc_full (type, frame, data, size, per_cu, 0);
 }
 
+/* Evaluates a dwarf expression and stores the result in VAL, expecting
+   that the dwarf expression only produces a single CORE_ADDR.  ADDR is a
+   context (location of a variable) and might be needed to evaluate the
+   location expression.
+   Returns 1 on success, 0 otherwise.   */
+
+static int
+dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
+			   CORE_ADDR addr, CORE_ADDR *valp)
+{
+  struct dwarf_expr_context *ctx;
+  struct dwarf_expr_baton baton;
+  struct objfile *objfile;
+  struct cleanup *cleanup;
+
+  if (dlbaton == NULL || dlbaton->size == 0)
+    return 0;
+
+  ctx = new_dwarf_expr_context ();
+  cleanup = make_cleanup_free_dwarf_expr_context (ctx);
+
+  baton.frame = get_selected_frame (NULL);
+  baton.per_cu = dlbaton->per_cu;
+
+  objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
+
+  ctx->gdbarch = get_objfile_arch (objfile);
+  ctx->addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
+  ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (dlbaton->per_cu);
+  ctx->offset = dwarf2_per_cu_text_offset (dlbaton->per_cu);
+  ctx->funcs = &dwarf_expr_ctx_funcs;
+  ctx->baton = &baton;
+
+  dwarf_expr_eval (ctx, dlbaton->data, dlbaton->size);
+
+  switch (ctx->location)
+    {
+    case DWARF_VALUE_REGISTER:
+    case DWARF_VALUE_MEMORY:
+    case DWARF_VALUE_STACK:
+      *valp = dwarf_expr_fetch_address (ctx, 0);
+      if (ctx->location == DWARF_VALUE_REGISTER)
+	*valp = dwarf_expr_read_addr_from_reg (&baton, *valp);
+      do_cleanups (cleanup);
+      return 1;
+    case DWARF_VALUE_LITERAL:
+      *valp = extract_signed_integer (ctx->data, ctx->len,
+				      gdbarch_byte_order (ctx->gdbarch));
+      do_cleanups (cleanup);
+      return 1;
+      /* Not supported dwarf values.  */
+    case DWARF_VALUE_OPTIMIZED_OUT:
+    case DWARF_VALUE_IMPLICIT_POINTER:
+      break;
+    }
+
+  do_cleanups (cleanup);
+
+  return 0;
+}
+
+/* See dwarf2loc.h.  */
+
+int
+dwarf2_evaluate_property (const struct dynamic_prop *prop, CORE_ADDR address,
+			  CORE_ADDR *value)
+{
+  if (prop == NULL)
+    return 0;
+
+  switch (prop->kind)
+    {
+    case PROP_LOCEXPR:
+      {
+	const struct dwarf2_property_baton *baton = prop->data.baton;
+
+	if (dwarf2_locexpr_baton_eval (&baton->locexpr, address, value))
+	  {
+	    if (baton->referenced_type)
+	      {
+		struct value *val = value_at (baton->referenced_type, *value);
+
+		*value = value_as_address (val);
+	      }
+	    return 1;
+	  }
+      }
+      break;
+
+    case PROP_LOCLIST:
+      {
+	struct dwarf2_property_baton *baton = prop->data.baton;
+	struct frame_info *frame = get_selected_frame (NULL);
+	CORE_ADDR pc = get_frame_address_in_block (frame);
+	const gdb_byte *data;
+	struct value *val;
+	size_t size;
+
+	data = dwarf2_find_location_expression (&baton->loclist, &size, pc);
+	if (data != NULL)
+	  {
+	    val = dwarf2_evaluate_loc_desc (baton->referenced_type, frame, data,
+					    size, baton->loclist.per_cu);
+	    if (!value_optimized_out (val))
+	      {
+		*value = value_as_address (val);
+		return 1;
+	      }
+	  }
+      }
+      break;
+
+    case PROP_CONST:
+      *value = prop->data.const_val;
+      return 1;
+    }
+
+  return 0;
+}
+
 \f
 /* Helper functions and baton for dwarf2_loc_desc_needs_frame.  */
 
diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h
index 9bc8ca5..9be3e24 100644
--- a/gdb/dwarf2loc.h
+++ b/gdb/dwarf2loc.h
@@ -90,6 +90,13 @@ struct value *dwarf2_evaluate_loc_desc (struct type *type,
 					size_t size,
 					struct dwarf2_per_cu_data *per_cu);
 
+/* Converts a dynamic property into a static one.  ADDR is the address of
+   the object currently being evaluated and might be nedded.
+   Returns 1 if PROP could be converted and the static value is passed back
+   into VALUE, otherwise returns 0.  */
+int dwarf2_evaluate_property (const struct dynamic_prop *prop,
+			      CORE_ADDR addr, CORE_ADDR *value);
+
 CORE_ADDR dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
 				  unsigned int addr_index);
 
@@ -135,6 +142,23 @@ struct dwarf2_loclist_baton
   unsigned char from_dwo;
 };
 
+/* A dynamic property is either expressed as a single location expression
+   or a location list in the context of TYPE.  */
+
+struct dwarf2_property_baton
+{
+  /* Keep track of referenced type.  */
+  struct type *referenced_type;
+  union
+  {
+    /* Location expression.  */
+    struct dwarf2_locexpr_baton locexpr;
+
+    /* Location list to be evaluated in the context of TYPE.  */
+    struct dwarf2_loclist_baton loclist;
+  };
+};
+
 extern const struct symbol_computed_ops dwarf2_locexpr_funcs;
 extern const struct symbol_computed_ops dwarf2_loclist_funcs;
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 101065b..1d5fa3d 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -14252,6 +14252,78 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
   return set_die_type (die, type, cu);
 }
 
+/* Parse dwarf attribute if it's a block, reference or constant and put the
+   resulting value of the attribute into struct bound_prop.
+   Returns 1 if ATTR could be resolved into PROP, 0 otherwise.  */
+
+static int
+attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
+		      struct dwarf2_cu *cu, struct dynamic_prop *prop)
+{
+  struct dwarf2_property_baton *baton;
+  struct obstack *obstack = &cu->objfile->objfile_obstack;
+
+  if (attr == NULL || prop == NULL)
+    return 0;
+
+  if (attr_form_is_block (attr))
+    {
+      baton = obstack_alloc (obstack, sizeof (*baton));
+      baton->referenced_type = NULL;
+      baton->locexpr.per_cu = cu->per_cu;
+      baton->locexpr.size = DW_BLOCK (attr)->size;
+      baton->locexpr.data = DW_BLOCK (attr)->data;
+      prop->data.baton = baton;
+      prop->kind = PROP_LOCEXPR;
+      gdb_assert (prop->data.baton != NULL);
+    }
+  else if (attr_form_is_ref (attr))
+    {
+      struct dwarf2_cu *target_cu = cu;
+      struct die_info *target_die;
+      struct attribute *target_attr;
+
+      target_die = follow_die_ref (die, attr, &target_cu);
+      target_attr = dwarf2_attr (target_die, DW_AT_location, target_cu);
+      if (target_attr == NULL)
+	return 0;
+
+      if (attr_form_is_section_offset (target_attr))
+	{
+	  baton = obstack_alloc (obstack, sizeof (*baton));
+	  baton->referenced_type = die_type (target_die, target_cu);
+	  fill_in_loclist_baton (cu, &baton->loclist, target_attr);
+	  prop->data.baton = baton;
+	  prop->kind = PROP_LOCLIST;
+	  gdb_assert (prop->data.baton != NULL);
+	}
+      else if (attr_form_is_block (target_attr))
+	{
+	  baton = obstack_alloc (obstack, sizeof (*baton));
+	  baton->referenced_type = die_type (target_die, target_cu);
+	  baton->locexpr.per_cu = cu->per_cu;
+	  baton->locexpr.size = DW_BLOCK (target_attr)->size;
+	  baton->locexpr.data = DW_BLOCK (target_attr)->data;
+	  prop->data.baton = baton;
+	  prop->kind = PROP_LOCEXPR;
+	  gdb_assert (prop->data.baton != NULL);
+	}
+    }
+  else if (attr_form_is_constant (attr))
+    {
+      prop->data.const_val = dwarf2_get_attr_constant_value (attr, 0);
+      prop->kind = PROP_CONST;
+    }
+  else
+    {
+      dwarf2_invalid_attrib_class_complaint (dwarf_form_name (attr->form),
+					     dwarf2_name (die, cu));
+      return 0;
+    }
+
+  return 1;
+}
+
 /* Read the given DW_AT_subrange DIE.  */
 
 static struct type *
@@ -14325,27 +14397,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
 	       die->offset.sect_off, objfile_name (cu->objfile));
 
   attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
-  if (attr)
-    {
-      if (attr_form_is_block (attr) || attr_form_is_ref (attr))
-        {
-          /* GCC encodes arrays with unspecified or dynamic length
-             with a DW_FORM_block1 attribute or a reference attribute.
-             FIXME: GDB does not yet know how to handle dynamic
-             arrays properly, treat them as arrays with unspecified
-             length for now.
-
-             FIXME: jimb/2003-09-22: GDB does not really know
-             how to handle arrays of unspecified length
-             either; we just represent them as zero-length
-             arrays.  Choose an appropriate upper bound given
-             the lower bound we've computed above.  */
-          high.data.const_val = low.data.const_val - 1;
-        }
-      else
-        high.data.const_val = dwarf2_get_attr_constant_value (attr, 1);
-    }
-  else
+  if (!attr_to_dynamic_prop (attr, die, cu, &high))
     {
       attr = dwarf2_attr (die, DW_AT_count, cu);
       if (attr)
@@ -14409,12 +14461,6 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
 
   range_type = create_range_type (NULL, orig_base_type, &low, &high);
 
-  /* Mark arrays with dynamic length at least as an array of unspecified
-     length.  GDB could check the boundary but before it gets implemented at
-     least allow accessing the array elements.  */
-  if (attr && attr_form_is_block (attr))
-    TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED;
-
   /* Ada expects an empty array on no boundary attributes.  */
   if (attr == NULL && cu->language != language_ada)
     TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED;
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 7f0269c..f5bd236 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -853,6 +853,17 @@ create_static_range_type (struct type *result_type, struct type *index_type,
   return result_type;
 }
 
+/* Predicate tests whether BOUNDS are static.  Returns 1 if all bounds values
+   are static, otherwise returns 0.  */
+
+static int
+has_static_range (const struct range_bounds *bounds)
+{
+  return (bounds->low.kind == PROP_CONST
+	  && bounds->high.kind == PROP_CONST);
+}
+
+
 /* Set *LOWP and *HIGHP to the lower and upper bounds of discrete type
    TYPE.  Return 1 if type is a range type, 0 if it is discrete (and
    bounds will fit in LONGEST), or -1 otherwise.  */
@@ -982,24 +993,28 @@ create_array_type (struct type *result_type,
 		   struct type *element_type,
 		   struct type *range_type)
 {
-  LONGEST low_bound, high_bound;
-
   if (result_type == NULL)
     result_type = alloc_type_copy (range_type);
 
   TYPE_CODE (result_type) = TYPE_CODE_ARRAY;
   TYPE_TARGET_TYPE (result_type) = element_type;
-  if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
-    low_bound = high_bound = 0;
-  CHECK_TYPEDEF (element_type);
-  /* Be careful when setting the array length.  Ada arrays can be
-     empty arrays with the high_bound being smaller than the low_bound.
-     In such cases, the array length should be zero.  */
-  if (high_bound < low_bound)
-    TYPE_LENGTH (result_type) = 0;
-  else
-    TYPE_LENGTH (result_type) =
-      TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
+
+  if (has_static_range (TYPE_RANGE_DATA (range_type)))
+    {
+      LONGEST low_bound, high_bound;
+
+      if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
+	low_bound = high_bound = 0;
+      CHECK_TYPEDEF (element_type);
+      /* Be careful when setting the array length.  Ada arrays can be
+	 empty arrays with the high_bound being smaller than the low_bound.
+	 In such cases, the array length should be zero.  */
+      if (high_bound < low_bound)
+	TYPE_LENGTH (result_type) = 0;
+      else
+	TYPE_LENGTH (result_type) =
+	  TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
+    }
   TYPE_NFIELDS (result_type) = 1;
   TYPE_FIELDS (result_type) =
     (struct field *) TYPE_ZALLOC (result_type, sizeof (struct field));
@@ -1530,7 +1545,181 @@ stub_noname_complaint (void)
   complaint (&symfile_complaints, _("stub type has NULL name"));
 }
 
-/* Find the real type of TYPE.  This function returns the real type,
+/* Calculates the size of a type.  If TYPE has static bound values takes upper
+   and lower bound into account, otherwise only the TYPE length is returned.
+   TYPE is expected not to be a typedef.  */
+
+static ULONGEST
+get_type_length (const struct type *type)
+{
+  const struct type *range_type, *target_type;
+  ULONGEST len = TYPE_LENGTH (type);
+  LONGEST low_bound, high_bound;
+
+  gdb_assert (TYPE_CODE (type) != TYPE_CODE_TYPEDEF);
+
+  if (TYPE_CODE (type) != TYPE_CODE_ARRAY
+      && TYPE_CODE (type) != TYPE_CODE_STRING)
+    return len;
+
+  range_type = check_typedef (TYPE_INDEX_TYPE (type));
+
+  if (!has_static_range (TYPE_RANGE_DATA (range_type)))
+    return len;
+
+  target_type = check_typedef (TYPE_TARGET_TYPE (type));
+
+  /* Now recompute the length of the array type, based on its
+     number of elements and the target type's length.
+     Watch out for Ada null Ada arrays where the high bound
+     is smaller than the low bound.  */
+  low_bound = TYPE_LOW_BOUND (range_type);
+  high_bound = TYPE_HIGH_BOUND (range_type);
+
+  if (high_bound < low_bound)
+    len = 0;
+  else
+    {
+      /* For now, we conservatively take the array length to be 0
+         if its length exceeds UINT_MAX.  The code below assumes
+         that for x < 0, (ULONGEST) x == -x + ULONGEST_MAX + 1,
+         which is technically not guaranteed by C, but is usually true
+         (because it would be true if x were unsigned with its
+         high-order bit on).  It uses the fact that
+         high_bound-low_bound is always representable in
+         ULONGEST and that if high_bound-low_bound+1 overflows,
+         it overflows to 0.  We must change these tests if we
+         decide to increase the representation of TYPE_LENGTH
+         from unsigned int to ULONGEST.  */
+      ULONGEST ulow = low_bound, uhigh = high_bound;
+      ULONGEST tlen = get_type_length (target_type);
+
+      len = tlen * (uhigh - ulow + 1);
+      if (tlen == 0 || (len / tlen - 1 + ulow) != uhigh || len > UINT_MAX)
+        len = 0;
+    }
+
+  return len;
+}
+
+/* See gdbtypes.h.  */
+
+int
+is_dynamic_type (const struct type *type)
+{
+  if (TYPE_CODE (type) == TYPE_CODE_ARRAY
+      && TYPE_NFIELDS (type) == 1)
+    {
+      const struct type *range_type = TYPE_INDEX_TYPE (type);
+
+      if (!has_static_range (TYPE_RANGE_DATA (range_type)))
+	return 1;
+    }
+
+  if (TYPE_CODE (type) == TYPE_CODE_ARRAY
+      || TYPE_CODE (type) == TYPE_CODE_PTR
+      || TYPE_CODE (type) == TYPE_CODE_REF
+      || TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+    return is_dynamic_type (check_typedef (TYPE_TARGET_TYPE (type)));
+
+  return 0;
+}
+
+/* Resolves dynamic bound values of an array type to static ones.
+   TYPE is modified in place and is expected not to be a typedef.
+   ADDRESS might be needed to resolve the subrange bounds, it is the location
+   of the associated array.  */
+
+static struct type *
+resolve_dynamic_bounds (struct type *type, CORE_ADDR addr)
+{
+  CORE_ADDR value;
+  struct type *array_type;
+  struct type *range_type;
+  struct type *ary_dim;
+  const struct dynamic_prop *prop;
+  const struct dwarf2_locexpr_baton *baton;
+  struct dynamic_prop low_bound, high_bound;
+
+  if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF
+      || TYPE_CODE (type) == TYPE_CODE_PTR)
+    {
+      struct type *copy = copy_type (type);
+
+      TYPE_TARGET_TYPE (copy)
+	= resolve_dynamic_bounds (TYPE_TARGET_TYPE (type), addr);
+
+      return copy;
+    }
+
+  gdb_assert (TYPE_CODE (type) == TYPE_CODE_ARRAY);
+
+  array_type = check_typedef (type);
+  range_type = check_typedef (TYPE_INDEX_TYPE (array_type));
+
+  prop = &TYPE_RANGE_DATA (range_type)->low;
+  if (dwarf2_evaluate_property (prop, addr, &value))
+    {
+      low_bound.kind = PROP_CONST;
+      low_bound.data.const_val = value;
+    }
+  else
+    {
+      low_bound.kind = PROP_UNDEFINED;
+      low_bound.data.const_val = 0;
+    }
+
+  prop = &TYPE_RANGE_DATA (range_type)->high;
+  if (dwarf2_evaluate_property (prop, addr, &value))
+    {
+      high_bound.kind = PROP_CONST;
+      high_bound.data.const_val = value;
+    }
+  else
+    {
+      high_bound.kind = PROP_UNDEFINED;
+      high_bound.data.const_val = 0;
+    }
+
+  ary_dim = check_typedef (TYPE_TARGET_TYPE (array_type));
+
+  if (ary_dim != NULL && TYPE_CODE (ary_dim) == TYPE_CODE_ARRAY)
+    array_type = resolve_dynamic_bounds (TYPE_TARGET_TYPE (type), addr);
+  else
+    array_type = TYPE_TARGET_TYPE (type);
+
+  range_type
+    = create_range_type (NULL,
+			 TYPE_TARGET_TYPE (range_type),
+			 &low_bound, &high_bound);
+  array_type = create_array_type (copy_type (type),
+				  array_type,
+				  range_type);
+
+  return array_type;
+}
+
+/* See gdbtypes.h  */
+
+struct type *
+resolve_dynamic_type (struct type *type, CORE_ADDR addr)
+{
+  struct type *real_type = check_typedef (type);
+  struct type *resolved_type;
+
+  if (!TYPE_OBJFILE_OWNED (real_type))
+    return type;
+
+  if (!is_dynamic_type (real_type))
+    return type;
+
+  resolved_type = resolve_dynamic_bounds (type, addr);
+  resolved_type->length = get_type_length (check_typedef (resolved_type));
+
+  return resolved_type;
+}
+
+/* find the real type of TYPE.  This function returns the real type,
    after removing all layers of typedefs, and completing opaque or stub
    types.  Completion changes the TYPE argument, but stripping of
    typedefs does not.
@@ -1706,44 +1895,15 @@ check_typedef (struct type *type)
 	  /* Nothing we can do.  */
 	}
       else if (TYPE_CODE (type) == TYPE_CODE_ARRAY
-	       && TYPE_NFIELDS (type) == 1
-	       && (TYPE_CODE (range_type = TYPE_INDEX_TYPE (type))
-		   == TYPE_CODE_RANGE))
-	{
-	  /* Now recompute the length of the array type, based on its
-	     number of elements and the target type's length.
-	     Watch out for Ada null Ada arrays where the high bound
-	     is smaller than the low bound.  */
-	  const LONGEST low_bound = TYPE_LOW_BOUND (range_type);
-	  const LONGEST high_bound = TYPE_HIGH_BOUND (range_type);
-	  ULONGEST len;
-
-	  if (high_bound < low_bound)
-	    len = 0;
-	  else
-	    {
-	      /* For now, we conservatively take the array length to be 0
-		 if its length exceeds UINT_MAX.  The code below assumes
-		 that for x < 0, (ULONGEST) x == -x + ULONGEST_MAX + 1,
-		 which is technically not guaranteed by C, but is usually true
-		 (because it would be true if x were unsigned with its
-		 high-order bit on).  It uses the fact that
-		 high_bound-low_bound is always representable in
-		 ULONGEST and that if high_bound-low_bound+1 overflows,
-		 it overflows to 0.  We must change these tests if we 
-		 decide to increase the representation of TYPE_LENGTH
-		 from unsigned int to ULONGEST.  */
-	      ULONGEST ulow = low_bound, uhigh = high_bound;
-	      ULONGEST tlen = TYPE_LENGTH (target_type);
-
-	      len = tlen * (uhigh - ulow + 1);
-	      if (tlen == 0 || (len / tlen - 1 + ulow) != uhigh 
-		  || len > UINT_MAX)
-		len = 0;
-	    }
-	  TYPE_LENGTH (type) = len;
-	  TYPE_TARGET_STUB (type) = 0;
-	}
+	       || TYPE_CODE (type) == TYPE_CODE_STRING)
+        {
+          range_type = TYPE_INDEX_TYPE (type);
+          if (has_static_range (TYPE_RANGE_DATA (range_type)))
+            {
+              TYPE_LENGTH (type) = get_type_length (type);
+              TYPE_TARGET_STUB (type) = 0;
+            }
+        }
       else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
 	{
 	  TYPE_LENGTH (type) = TYPE_LENGTH (target_type);
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index f6e68c5..38cd240 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -1,3 +1,4 @@
+
 /* Internal type definitions for GDB.
 
    Copyright (C) 1992-2013 Free Software Foundation, Inc.
@@ -1574,6 +1575,15 @@ extern struct type *lookup_unsigned_typename (const struct language_defn *,
 extern struct type *lookup_signed_typename (const struct language_defn *,
 					    struct gdbarch *, const char *);
 
+/* Resolves all dynamic values of a type e.g. array bounds to static values.
+   ADDR specifies the location of the variable the type is bound to.
+   If TYPE has no dynamic values returns TYPE otherwise a new type with static
+   values is returned.  */
+extern struct type *resolve_dynamic_type (struct type *type, CORE_ADDR addr);
+
+/* Predicates if the type has dynamic values, which are not resolved yet.  */
+extern int is_dynamic_type (const struct type *type);
+
 extern struct type *check_typedef (struct type *);
 
 #define CHECK_TYPEDEF(TYPE)			\
diff --git a/gdb/valops.c b/gdb/valops.c
index 5c7bb89..a7260b9 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -902,7 +902,9 @@ value_one (struct type *type)
   return val;
 }
 
-/* Helper function for value_at, value_at_lazy, and value_at_lazy_stack.  */
+/* Helper function for value_at, value_at_lazy, and value_at_lazy_stack.
+   The type of the created value may differ from the passed type TYPE.
+   Make sure to retrieve values new type after this call.  */
 
 static struct value *
 get_value_at (struct type *type, CORE_ADDR addr, int lazy)
@@ -927,7 +929,9 @@ get_value_at (struct type *type, CORE_ADDR addr, int lazy)
    value_at_lazy instead.  value_at_lazy simply records the address of
    the data and sets the lazy-evaluation-required flag.  The lazy flag
    is tested in the value_contents macro, which is used if and when
-   the contents are actually required.
+   the contents are actually required.  The type of the created value
+   may differ from the passed type TYPE.  Make sure to retrieve values
+   new type after this call.
 
    Note: value_at does *NOT* handle embedded offsets; perform such
    adjustments before or after calling it.  */
@@ -938,7 +942,9 @@ value_at (struct type *type, CORE_ADDR addr)
   return get_value_at (type, addr, 0);
 }
 
-/* Return a lazy value with type TYPE located at ADDR (cf. value_at).  */
+/* Return a lazy value with type TYPE located at ADDR (cf. value_at).
+   The type of the created value may differ from the passed type TYPE.
+   Make sure to retrieve values new type after this call.  */
 
 struct value *
 value_at_lazy (struct type *type, CORE_ADDR addr)
diff --git a/gdb/value.c b/gdb/value.c
index a64e7e1..12726a1 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -3178,32 +3178,37 @@ value_from_ulongest (struct type *type, ULONGEST num)
 
 
 /* Create a value representing a pointer of type TYPE to the address
-   ADDR.  */
+   ADDR.  The type of the created value may differ from the passed
+   type TYPE.  Make sure to retrieve values new type after this call.  */
 struct value *
 value_from_pointer (struct type *type, CORE_ADDR addr)
 {
-  struct value *val = allocate_value (type);
+  struct type *resolved_type = resolve_dynamic_type (type, addr);
+  struct value *val = allocate_value (resolved_type);
 
-  store_typed_address (value_contents_raw (val), check_typedef (type), addr);
+  store_typed_address (value_contents_raw (val),
+		       check_typedef (resolved_type), addr);
   return val;
 }
 
 
 /* Create a value of type TYPE whose contents come from VALADDR, if it
    is non-null, and whose memory address (in the inferior) is
-   ADDRESS.  */
+   ADDRESS.  The type of the created value may differ from the passed
+   type TYPE.  Make sure to retrieve values new type after this call.  */
 
 struct value *
 value_from_contents_and_address (struct type *type,
 				 const gdb_byte *valaddr,
 				 CORE_ADDR address)
 {
+  struct type *resolved_type = resolve_dynamic_type (type, address);
   struct value *v;
 
   if (valaddr == NULL)
-    v = allocate_value_lazy (type);
+    v = allocate_value_lazy (resolved_type);
   else
-    v = value_from_contents (type, valaddr);
+    v = value_from_contents (resolved_type, valaddr);
   set_value_address (v, address);
   VALUE_LVAL (v) = lval_memory;
   return v;
-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v5 12/15] test: multi-dimensional c99 vla.
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
                   ` (12 preceding siblings ...)
  2014-02-06 16:28 ` [PATCH v5 09/15] vla: resolve dynamic bounds if value contents is a constant byte-sequence Sanimir Agovic
@ 2014-02-06 16:28 ` Sanimir Agovic
  2014-02-28 17:58   ` Joel Brobecker
  2014-02-06 16:28 ` [PATCH v5 03/15] type: add c99 variable length array support Sanimir Agovic
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 45+ messages in thread
From: Sanimir Agovic @ 2014-02-06 16:28 UTC (permalink / raw)
  To: tromey, brobecker; +Cc: keven.boell, gdb-patches

2013-10-18  Keven Boell  <keven.boell@intel.com>
            Sanimir Agovic  <sanimir.agovic@intel.com>

gdb/testsuite:
	* gdb.base/vla-multi.c: New. Test source file
	for testing multi-dimensional VLA's in C.
	* gdb.base/vla-multi.exp: New. Tests ensure
	that multi-dimensional VLA's can be evaluated
	correctly in C.


Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
---
 gdb/testsuite/gdb.base/vla-multi.c   | 55 ++++++++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/vla-multi.exp | 48 +++++++++++++++++++++++++++++++
 2 files changed, 103 insertions(+)
 create mode 100644 gdb/testsuite/gdb.base/vla-multi.c
 create mode 100644 gdb/testsuite/gdb.base/vla-multi.exp

diff --git a/gdb/testsuite/gdb.base/vla-multi.c b/gdb/testsuite/gdb.base/vla-multi.c
new file mode 100644
index 0000000..47c753e
--- /dev/null
+++ b/gdb/testsuite/gdb.base/vla-multi.c
@@ -0,0 +1,55 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2013 Free Software Foundation, Inc.
+
+   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/>.  */
+
+void
+f1 (int n, int m, int vla_ptr[n][m])
+{
+  return;                                 /* f1_breakpoint */
+}
+
+void
+f2 (int m, int vla_ptr[][m])
+{
+  return;                                 /* f2_breakpoint */
+}
+
+void
+vla_mult (int n, int m)
+{
+  int vla[n][m];
+  int i, j;
+
+  for (i = 0; i < n; i++)
+    {
+      for (j = 0; j < m; j++)
+        {
+          vla[i][j] = i + j;
+        }
+    }
+
+  f1(n, m, vla);                          /* vla_filled */
+  f2(m, vla);
+
+  return;
+}
+
+int
+main()
+{
+  vla_mult(2, 2);
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/vla-multi.exp b/gdb/testsuite/gdb.base/vla-multi.exp
new file mode 100644
index 0000000..53f626f
--- /dev/null
+++ b/gdb/testsuite/gdb.base/vla-multi.exp
@@ -0,0 +1,48 @@
+# Copyright 2013 Free Software Foundation, Inc.
+
+# 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/>.
+
+standard_testfile ".c"
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+set sizeof_int [get_sizeof "int" 4]
+
+gdb_breakpoint [gdb_get_line_number "vla_filled"]
+gdb_continue_to_breakpoint "vla_filled"
+gdb_test "print vla" "\\$\\d+ = \\\{\\\{0, 1\\\}, \\\{1, 2\\\}\\\}" \
+         "print vla"
+gdb_test "print vla\[0\]\[1\]" "\\$\\d+ = 1" "print vla\[0\]\[1\]"
+
+gdb_breakpoint [gdb_get_line_number "f1_breakpoint"]
+gdb_continue_to_breakpoint "f1_breakpoint"
+gdb_test "print *vla_ptr" "\\$\\d+ = \\\{0, 1\\\}" "print *vla_ptr (f1)"
+
+# Calculate the overall size of the vla.
+set sizeof_vla [ expr "2" * "$sizeof_int" ]
+gdb_test "print sizeof vla_ptr\[0\]" "\\$\\d+ = ${sizeof_vla}" \
+         "print sizeof vla_ptr\[0\]"
+gdb_test "ptype &vla_ptr" \
+    "type = int \\\(\\\*\\\*\\\)\\\[variable length\\\]" \
+    "ptype &vla_ptr"
+
+gdb_breakpoint [gdb_get_line_number "f2_breakpoint"]
+gdb_continue_to_breakpoint "f2_breakpoint"
+gdb_test "print *vla_ptr" "\\$\\d+ = \\\{0, 1\\\}" "print *vla_ptr (f2)"
-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v5 05/15] vla: enable sizeof operator for indirection
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
                   ` (8 preceding siblings ...)
  2014-02-06 16:28 ` [PATCH v5 06/15] vla: update type from newly created value Sanimir Agovic
@ 2014-02-06 16:28 ` Sanimir Agovic
  2014-02-06 16:28 ` [PATCH v5 13/15] test: evaluate pointers to C99 vla correctly Sanimir Agovic
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 45+ messages in thread
From: Sanimir Agovic @ 2014-02-06 16:28 UTC (permalink / raw)
  To: tromey, brobecker; +Cc: keven.boell, gdb-patches

This patch enables the sizeof operator for indirections:

1| void foo (size_t n) {
2|   int vla[n];
3|   int *vla_ptr = &vla;
4| }

(gdb) p sizeof(*vla_ptr)

yields sizeof (size_t) * n.

2013-10-18  Sanimir Agovic  <sanimir.agovic@intel.com>
            Keven Boell  <keven.boell@intel.com>

	* eval.c (evaluate_subexp_for_sizeof) <UNOP_IND>: Create an indirect
	value and retrieve the dynamic type size.


Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
---
 gdb/eval.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/gdb/eval.c b/gdb/eval.c
index a81e789..b3e45ca 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -3027,6 +3027,8 @@ evaluate_subexp_for_sizeof (struct expression *exp, int *pos)
 	  && TYPE_CODE (type) != TYPE_CODE_ARRAY)
 	error (_("Attempt to take contents of a non-pointer value."));
       type = check_typedef (TYPE_TARGET_TYPE (type));
+      if (is_dynamic_type (type))
+	type = value_type (value_ind (val));
       return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
 
     case UNOP_MEMVAL:
-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v5 13/15] test: evaluate pointers to C99 vla correctly.
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
                   ` (9 preceding siblings ...)
  2014-02-06 16:28 ` [PATCH v5 05/15] vla: enable sizeof operator for indirection Sanimir Agovic
@ 2014-02-06 16:28 ` Sanimir Agovic
  2014-02-28 18:01   ` Joel Brobecker
  2014-02-06 16:28 ` [PATCH v5 10/15] vla: evaluate operand of sizeof if its type is a vla Sanimir Agovic
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 45+ messages in thread
From: Sanimir Agovic @ 2014-02-06 16:28 UTC (permalink / raw)
  To: tromey, brobecker; +Cc: keven.boell, gdb-patches

2013-10-18  Keven Boell  <keven.boell@intel.com>
            Sanimir Agovic  <sanimir.agovic@intel.com>

gdb/testsuite:
	* gdb.base/vla-ptr.c: New. Test source file
	for testing pointers to VLA's in C.
	* gdb.base/vla-ptr.exp: New. Tests ensure that
	the evaluation of pointers to VLA's work
	correctly in C.


Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
---
 gdb/testsuite/gdb.base/vla-ptr.c   | 63 ++++++++++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/vla-ptr.exp | 52 +++++++++++++++++++++++++++++++
 2 files changed, 115 insertions(+)
 create mode 100644 gdb/testsuite/gdb.base/vla-ptr.c
 create mode 100644 gdb/testsuite/gdb.base/vla-ptr.exp

diff --git a/gdb/testsuite/gdb.base/vla-ptr.c b/gdb/testsuite/gdb.base/vla-ptr.c
new file mode 100644
index 0000000..85c41e0
--- /dev/null
+++ b/gdb/testsuite/gdb.base/vla-ptr.c
@@ -0,0 +1,63 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2013 Free Software Foundation, Inc.
+
+   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/>.  */
+
+#define SIZE 5
+
+void
+foo (int n, int vla_ptr[n])
+{
+  return;         /* foo_bp */
+}
+
+void
+bar (int *vla_ptr)
+{
+  return;         /* bar_bp */
+}
+
+void
+vla_func (int n)
+{
+  int vla[n];
+  int (*vla_ptr)[n];
+  typedef int typedef_vla[n];
+  typedef_vla td_vla;
+  int i;
+
+  for (i = 0; i < n; i++)
+    {
+      vla[i] = 2+i;
+      td_vla[i] = 4+i;
+    }
+
+  foo(n, vla);
+  bar(vla);
+
+  vla_ptr = &vla;
+
+  typedef_vla *td_ptr = &td_vla;  /* vla_ptr_assigned */
+
+  return;         /* typedef_ptr_assigned */
+}
+
+int
+main ()
+{
+  vla_func(SIZE);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/vla-ptr.exp b/gdb/testsuite/gdb.base/vla-ptr.exp
new file mode 100644
index 0000000..a7785b0
--- /dev/null
+++ b/gdb/testsuite/gdb.base/vla-ptr.exp
@@ -0,0 +1,52 @@
+# Copyright 2013 Free Software Foundation, Inc.
+
+# 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/>.
+
+standard_testfile ".c"
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+set sizeof_int [get_sizeof "int" 4]
+
+# Check that VLA passed to function (pointer) points to the first element.
+gdb_breakpoint [gdb_get_line_number "foo_bp"]
+gdb_continue_to_breakpoint "foo_bp"
+gdb_test "print vla_ptr" "\\\(int \\\*\\\) $hex" "print vla_ptr (foo)"
+gdb_test "print *vla_ptr" "\\$\\d+ = 2" "print *vla_ptr (foo)"
+
+gdb_breakpoint [gdb_get_line_number "bar_bp"]
+gdb_continue_to_breakpoint "bar_bp"
+gdb_test "print vla_ptr" "\\\(int \\\*\\\) $hex" "print vla_ptr (bar)"
+gdb_test "print *vla_ptr" "\\$\\d+ = 2" "print *vla_ptr (bar)"
+
+gdb_breakpoint [gdb_get_line_number "vla_ptr_assigned"]
+gdb_continue_to_breakpoint "vla_ptr_assigned"
+gdb_test "print *vla_ptr" "\\$\\d+ = \\\{2, 3, 4, 5, 6\\\}" \
+         "print *vla_ptr (vla_func)"
+
+# Calculate the overall size of the vla.
+set sizeof_vla [ expr "5" * "$sizeof_int" ]
+gdb_test "print sizeof(*vla_ptr)" "\\$\\d+ = ${sizeof_vla}" \
+         "print sizeof(*vla_ptr) (vla_func)"
+
+gdb_breakpoint [gdb_get_line_number "typedef_ptr_assigned"]
+gdb_continue_to_breakpoint "typedef_ptr_assigned"
+gdb_test "print td_vla" "\\$\\d+ = \\\{4, 5, 6, 7, 8\\\}" "print td_vla"
+gdb_test "print *td_ptr" "\\$\\d+ = \\\{4, 5, 6, 7, 8\\\}" "print *td_ptr"
-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v5 02/15] vla: introduce new bound type abstraction adapt uses
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
                   ` (6 preceding siblings ...)
  2014-02-06 16:28 ` [PATCH v5 01/15] refactoring: rename create_range_type to create_static_range_type Sanimir Agovic
@ 2014-02-06 16:28 ` Sanimir Agovic
  2014-02-06 16:28 ` [PATCH v5 06/15] vla: update type from newly created value Sanimir Agovic
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 45+ messages in thread
From: Sanimir Agovic @ 2014-02-06 16:28 UTC (permalink / raw)
  To: tromey, brobecker; +Cc: keven.boell, gdb-patches

The rational behind this patch is to get started to implement the feature
described in dwarf4 standard (2.19) Static and Dynamic Values of Attributes.
It adds new BOUND_PROP to store either a constant, exprloc, or reference to
describe an upper-/lower bound of a subrange. Other than that no new features
are introduced.

2013-10-18  Sanimir Agovic  <sanimir.agovic@intel.com>
            Keven Boell  <keven.boell@intel.com>

	* dwarf2read.c (read_subrange_type): Use struct bound_prop for
	declaring high/low bounds and change uses accordingly. Call
	create_range_type instead of create_static_range_type.
	* gdbtypes.c (create_range_type): New function.
	(create_range_type): Convert bounds into struct bound_prop and pass
	them to create_range_type.
	* gdbtypes.h (struct bound_prop): New struct.
	(create_range_type): New function prototype.
	(struct range_bounds): Use struct bound_prop instead of LONGEST for
	high/low bounds. Remove low_undefined/high_undefined and adapt all uses.
	(TYPE_LOW_BOUND,TYPE_HIGH_BOUND): Adapt macros to refer to the static
	part of the bound.
	* parse.c (follow_types): Set high bound kind to BOUND_UNDEFINED.


Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
---
 gdb/dwarf2read.c | 43 ++++++++++++++++++++++++------------------
 gdb/gdbtypes.c   | 50 +++++++++++++++++++++++++++++++++++--------------
 gdb/gdbtypes.h   | 57 ++++++++++++++++++++++++++++++++++++++++++--------------
 gdb/parse.c      |  3 ++-
 4 files changed, 106 insertions(+), 47 deletions(-)

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 4ba25ff..101065b 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -14260,7 +14260,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
   struct type *base_type, *orig_base_type;
   struct type *range_type;
   struct attribute *attr;
-  LONGEST low, high;
+  struct dynamic_prop low, high;
   int low_default_is_valid;
   const char *name;
   LONGEST negative_mask;
@@ -14277,33 +14277,37 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
   if (range_type)
     return range_type;
 
+  low.kind = PROP_CONST;
+  high.kind = PROP_CONST;
+  high.data.const_val = 0;
+
   /* Set LOW_DEFAULT_IS_VALID if current language and DWARF version allow
      omitting DW_AT_lower_bound.  */
   switch (cu->language)
     {
     case language_c:
     case language_cplus:
-      low = 0;
+      low.data.const_val = 0;
       low_default_is_valid = 1;
       break;
     case language_fortran:
-      low = 1;
+      low.data.const_val = 1;
       low_default_is_valid = 1;
       break;
     case language_d:
     case language_java:
     case language_objc:
-      low = 0;
+      low.data.const_val = 0;
       low_default_is_valid = (cu->header.version >= 4);
       break;
     case language_ada:
     case language_m2:
     case language_pascal:
-      low = 1;
+      low.data.const_val = 1;
       low_default_is_valid = (cu->header.version >= 4);
       break;
     default:
-      low = 0;
+      low.data.const_val = 0;
       low_default_is_valid = 0;
       break;
     }
@@ -14313,7 +14317,8 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
      but we don't know how to handle it.  */
   attr = dwarf2_attr (die, DW_AT_lower_bound, cu);
   if (attr)
-    low = dwarf2_get_attr_constant_value (attr, low);
+    low.data.const_val
+      = dwarf2_get_attr_constant_value (attr, low.data.const_val);
   else if (!low_default_is_valid)
     complaint (&symfile_complaints, _("Missing DW_AT_lower_bound "
 				      "- DIE at 0x%x [in module %s]"),
@@ -14335,10 +14340,10 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
              either; we just represent them as zero-length
              arrays.  Choose an appropriate upper bound given
              the lower bound we've computed above.  */
-          high = low - 1;
+          high.data.const_val = low.data.const_val - 1;
         }
       else
-        high = dwarf2_get_attr_constant_value (attr, 1);
+        high.data.const_val = dwarf2_get_attr_constant_value (attr, 1);
     }
   else
     {
@@ -14346,12 +14351,12 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
       if (attr)
 	{
 	  int count = dwarf2_get_attr_constant_value (attr, 1);
-	  high = low + count - 1;
+	  high.data.const_val = low.data.const_val + count - 1;
 	}
       else
 	{
 	  /* Unspecified array length.  */
-	  high = low - 1;
+	  high.data.const_val = low.data.const_val - 1;
 	}
     }
 
@@ -14395,22 +14400,24 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
 
   negative_mask =
     (LONGEST) -1 << (TYPE_LENGTH (base_type) * TARGET_CHAR_BIT - 1);
-  if (!TYPE_UNSIGNED (base_type) && (low & negative_mask))
-    low |= negative_mask;
-  if (!TYPE_UNSIGNED (base_type) && (high & negative_mask))
-    high |= negative_mask;
+  if (low.kind == PROP_CONST
+      && !TYPE_UNSIGNED (base_type) && (low.data.const_val & negative_mask))
+    low.data.const_val |= negative_mask;
+  if (high.kind == PROP_CONST
+      && !TYPE_UNSIGNED (base_type) && (high.data.const_val & negative_mask))
+    high.data.const_val |= negative_mask;
 
-  range_type = create_static_range_type (NULL, orig_base_type, low, high);
+  range_type = create_range_type (NULL, orig_base_type, &low, &high);
 
   /* Mark arrays with dynamic length at least as an array of unspecified
      length.  GDB could check the boundary but before it gets implemented at
      least allow accessing the array elements.  */
   if (attr && attr_form_is_block (attr))
-    TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1;
+    TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED;
 
   /* Ada expects an empty array on no boundary attributes.  */
   if (attr == NULL && cu->language != language_ada)
-    TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1;
+    TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED;
 
   name = dwarf2_name (die, cu);
   if (name)
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 807e18e..7f0269c 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -798,19 +798,13 @@ allocate_stub_method (struct type *type)
   return mtype;
 }
 
-/* Create a range type using either a blank type supplied in
-   RESULT_TYPE, or creating a new type, inheriting the objfile from
-   INDEX_TYPE.
-
-   Indices will be of type INDEX_TYPE, and will range from LOW_BOUND
-   to HIGH_BOUND, inclusive.
-
-   FIXME: Maybe we should check the TYPE_CODE of RESULT_TYPE to make
-   sure it is TYPE_CODE_UNDEF before we bash it into a range type?  */
+/* Create a range type with a dynamic range from LOW_BOUND to
+   HIGH_BOUND, inclusive.  See create_range_type for further details. */
 
 struct type *
-create_static_range_type (struct type *result_type, struct type *index_type,
-			  LONGEST low_bound, LONGEST high_bound)
+create_range_type (struct type *result_type, struct type *index_type,
+		   const struct dynamic_prop *low_bound,
+		   const struct dynamic_prop *high_bound)
 {
   if (result_type == NULL)
     result_type = alloc_type_copy (index_type);
@@ -820,17 +814,45 @@ create_static_range_type (struct type *result_type, struct type *index_type,
     TYPE_TARGET_STUB (result_type) = 1;
   else
     TYPE_LENGTH (result_type) = TYPE_LENGTH (check_typedef (index_type));
+
   TYPE_RANGE_DATA (result_type) = (struct range_bounds *)
     TYPE_ZALLOC (result_type, sizeof (struct range_bounds));
-  TYPE_LOW_BOUND (result_type) = low_bound;
-  TYPE_HIGH_BOUND (result_type) = high_bound;
+  TYPE_RANGE_DATA (result_type)->low = *low_bound;
+  TYPE_RANGE_DATA (result_type)->high = *high_bound;
 
-  if (low_bound >= 0)
+  if (low_bound->kind == PROP_CONST && low_bound->data.const_val >= 0)
     TYPE_UNSIGNED (result_type) = 1;
 
   return result_type;
 }
 
+/* Create a range type using either a blank type supplied in
+   RESULT_TYPE, or creating a new type, inheriting the objfile from
+   INDEX_TYPE.
+
+   Indices will be of type INDEX_TYPE, and will range from LOW_BOUND
+   to HIGH_BOUND, inclusive.
+
+   FIXME: Maybe we should check the TYPE_CODE of RESULT_TYPE to make
+   sure it is TYPE_CODE_UNDEF before we bash it into a range type?  */
+
+struct type *
+create_static_range_type (struct type *result_type, struct type *index_type,
+			  LONGEST low_bound, LONGEST high_bound)
+{
+  struct dynamic_prop low, high;
+
+  low.kind = PROP_CONST;
+  low.data.const_val = low_bound;
+
+  high.kind = PROP_CONST;
+  high.data.const_val = high_bound;
+
+  result_type = create_range_type (result_type, index_type, &low, &high);
+
+  return result_type;
+}
+
 /* Set *LOWP and *HIGHP to the lower and upper bounds of discrete type
    TYPE.  Return 1 if type is a range type, 0 if it is discrete (and
    bounds will fit in LONGEST), or -1 otherwise.  */
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 0396078..f6e68c5 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -365,6 +365,33 @@ enum type_instance_flag_value
 #define TYPE_ADDRESS_CLASS_ALL(t) (TYPE_INSTANCE_FLAGS(t) \
 				   & TYPE_INSTANCE_FLAG_ADDRESS_CLASS_ALL)
 
+/* Used to store a dynamic property.  */
+
+struct dynamic_prop
+{
+  /* Determine which field of the union dynamic_prop.data is used.  */
+  enum
+  {
+    PROP_UNDEFINED, /* Not defined.  */
+    PROP_CONST,     /* Constant.  */
+    PROP_LOCEXPR,   /* Location expression.  */
+    PROP_LOCLIST    /* Location list.  */
+  } kind;
+
+  /* Storage for dynamic or static value.  */
+  union data
+  {
+    /* Storage for constant property.  */
+
+    LONGEST const_val;
+
+    /* Storage for dynamic property.  */
+
+    void *baton;
+  } data;
+};
+
+
 /* Determine which field of the union main_type.fields[x].loc is used.  */
 
 enum field_loc_kind
@@ -589,19 +616,11 @@ struct main_type
     {
       /* Low bound of range.  */
 
-      LONGEST low;
+      struct dynamic_prop low;
 
       /* High bound of range.  */
 
-      LONGEST high;
-
-      /* Flags indicating whether the values of low and high are
-         valid.  When true, the respective range value is
-         undefined.  Currently used only for FORTRAN arrays.  */
-           
-      char low_undefined;
-      char high_undefined;
-
+      struct dynamic_prop high;
     } *bounds;
 
   } flds_bnds;
@@ -1066,12 +1085,18 @@ extern void allocate_gnat_aux_type (struct type *);
 
 #define TYPE_INDEX_TYPE(type) TYPE_FIELD_TYPE (type, 0)
 #define TYPE_RANGE_DATA(thistype) TYPE_MAIN_TYPE(thistype)->flds_bnds.bounds
-#define TYPE_LOW_BOUND(range_type) TYPE_RANGE_DATA(range_type)->low
-#define TYPE_HIGH_BOUND(range_type) TYPE_RANGE_DATA(range_type)->high
+#define TYPE_LOW_BOUND(range_type) \
+  TYPE_RANGE_DATA(range_type)->low.data.const_val
+#define TYPE_HIGH_BOUND(range_type) \
+  TYPE_RANGE_DATA(range_type)->high.data.const_val
 #define TYPE_LOW_BOUND_UNDEFINED(range_type) \
-   TYPE_RANGE_DATA(range_type)->low_undefined
+  (TYPE_RANGE_DATA(range_type)->low.kind == PROP_UNDEFINED)
 #define TYPE_HIGH_BOUND_UNDEFINED(range_type) \
-   TYPE_RANGE_DATA(range_type)->high_undefined
+  (TYPE_RANGE_DATA(range_type)->high.kind == PROP_UNDEFINED)
+#define TYPE_HIGH_BOUND_KIND(range_type) \
+  TYPE_RANGE_DATA(range_type)->high.kind
+#define TYPE_LOW_BOUND_KIND(range_type) \
+  TYPE_RANGE_DATA(range_type)->low.kind
 
 /* Moto-specific stuff for FORTRAN arrays.  */
 
@@ -1529,6 +1554,10 @@ extern struct type *lookup_function_type_with_arguments (struct type *,
 extern struct type *create_static_range_type (struct type *, struct type *,
 					      LONGEST, LONGEST);
 
+extern struct type *create_range_type (struct type *, struct type *,
+				       const struct dynamic_prop *,
+				       const struct dynamic_prop *);
+
 extern struct type *create_array_type (struct type *, struct type *,
 				       struct type *);
 extern struct type *lookup_array_range_type (struct type *, LONGEST, LONGEST);
diff --git a/gdb/parse.c b/gdb/parse.c
index 4b9ca5d..b1671f3 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -1710,7 +1710,8 @@ follow_types (struct type *follow_type)
 	  lookup_array_range_type (follow_type,
 				   0, array_size >= 0 ? array_size - 1 : 0);
 	if (array_size < 0)
-	  TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (follow_type) = 1;
+	  TYPE_HIGH_BOUND_KIND (TYPE_INDEX_TYPE (follow_type))
+	    = PROP_UNDEFINED;
 	break;
       case tp_function:
 	/* FIXME-type-allocation: need a way to free this type when we are
-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH v5 07/15] vla: print "variable length" for unresolved dynamic bounds
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
                   ` (3 preceding siblings ...)
  2014-02-06 16:28 ` [PATCH v5 14/15] test: basic c99 vla tests for C primitives Sanimir Agovic
@ 2014-02-06 16:28 ` Sanimir Agovic
  2014-02-06 16:28 ` [PATCH v5 15/15] test: add mi vla test Sanimir Agovic
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 45+ messages in thread
From: Sanimir Agovic @ 2014-02-06 16:28 UTC (permalink / raw)
  To: tromey, brobecker; +Cc: keven.boell, gdb-patches

1| void foo (size_t n) {
2|   int vla[n];
3| }

Given the following expression

  (gdb) ptype &vla

Gdb evaluates the expression with EVAL_AVOID_SIDE_EFFECTS and thus
does not resolve the bounds information and misinterprets the high
bound as a constant. The current output is:

  type = int (*)[1289346]

this patch deals with this case and prints:

  type = int (*)[variable length]

instead.

2013-08-30  Keven Boell  <keven.boell@intel.com>
            Sanimir Agovic  <sanimir.agovic@intel.com>

	* c-typeprint.c (c_type_print_varspec_suffix): Added
	check for not yet resolved high bound. If unresolved, print
	"variable length" string to the console instead of random
	length.


Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
---
 gdb/c-typeprint.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c
index 2757337..739d770 100644
--- a/gdb/c-typeprint.c
+++ b/gdb/c-typeprint.c
@@ -689,7 +689,11 @@ c_type_print_varspec_suffix (struct type *type,
 
 	fprintf_filtered (stream, (is_vector ?
 				   " __attribute__ ((vector_size(" : "["));
-	if (get_array_bounds (type, &low_bound, &high_bound))
+	/* Bounds are not yet resolved, print a bounds placeholder instead.  */
+	if (TYPE_HIGH_BOUND_KIND (TYPE_INDEX_TYPE (type)) == PROP_LOCEXPR
+	    || TYPE_HIGH_BOUND_KIND (TYPE_INDEX_TYPE (type)) == PROP_LOCLIST)
+	  fprintf_filtered (stream, "variable length");
+	else if (get_array_bounds (type, &low_bound, &high_bound))
 	  fprintf_filtered (stream, "%s", 
 			    plongest (high_bound - low_bound + 1));
 	fprintf_filtered (stream, (is_vector ? ")))" : "]"));
-- 
1.8.4.2


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 09/15] vla: resolve dynamic bounds if value contents is a constant byte-sequence
  2014-02-06 16:28 ` [PATCH v5 09/15] vla: resolve dynamic bounds if value contents is a constant byte-sequence Sanimir Agovic
@ 2014-02-07 10:27   ` Joel Brobecker
  2014-02-07 12:27     ` Agovic, Sanimir
  2014-02-28 17:09   ` Joel Brobecker
  1 sibling, 1 reply; 45+ messages in thread
From: Joel Brobecker @ 2014-02-07 10:27 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

Hello!

> 2013-11-26  Sanimir Agovic  <sanimir.agovic@intel.com>
>             Keven Boell  <keven.boell@intel.com>
> 
> 	* findvar.c (default_read_var_value): Resolve dynamic bounds if location
> 	points to a constant blob.

Small trivial comment....

>      case LOC_CONST_BYTES:
> +      if (is_dynamic_type (type))
> +	/* Value is a constant byte-sequence and needs no memory access.  */
> +	type = resolve_dynamic_type (type, /* Unused address.  */ 0);

Although not required by C, we prefer in the GDB project to still
use curly braces around the if block. The reason is that the comment
visually looks like a statement, so it looks like the if block as
more than one statement, hence the use of curly braces...

Thank you!

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* RE: [PATCH v5 09/15] vla: resolve dynamic bounds if value contents is a constant byte-sequence
  2014-02-07 10:27   ` Joel Brobecker
@ 2014-02-07 12:27     ` Agovic, Sanimir
  0 siblings, 0 replies; 45+ messages in thread
From: Agovic, Sanimir @ 2014-02-07 12:27 UTC (permalink / raw)
  To: 'Joel Brobecker'; +Cc: tromey, Boell, Keven, gdb-patches

Thanks for your review.

The inlined diff below wraps the single statement + comment within curly braces.

diff --git a/gdb/findvar.c b/gdb/findvar.c
index a543dc4..11ce3c6 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -469,8 +469,10 @@ default_read_var_value (struct symbol *var, struct frame_info *frame)

     case LOC_CONST_BYTES:
       if (is_dynamic_type (type))
-       /* Value is a constant byte-sequence and needs no memory access.  */
-       type = resolve_dynamic_type (type, /* Unused address.  */ 0);
+       {
+         /* Value is a constant byte-sequence and needs no memory access.  */
+         type = resolve_dynamic_type (type, /* Unused address.  */ 0);
+       }
       v = allocate_value (type);
       memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var),
              TYPE_LENGTH (type));

 -Sanimir

> -----Original Message-----
> From: Joel Brobecker [mailto:brobecker@adacore.com]
> Sent: Friday, February 07, 2014 11:27 AM
> To: Agovic, Sanimir
> Cc: tromey@redhat.com; Boell, Keven; gdb-patches@sourceware.org
> Subject: Re: [PATCH v5 09/15] vla: resolve dynamic bounds if value contents is a constant
> byte-sequence
> 
> Hello!
> 
> > 2013-11-26  Sanimir Agovic  <sanimir.agovic@intel.com>
> >             Keven Boell  <keven.boell@intel.com>
> >
> > 	* findvar.c (default_read_var_value): Resolve dynamic bounds if location
> > 	points to a constant blob.
> 
> Small trivial comment....
> 
> >      case LOC_CONST_BYTES:
> > +      if (is_dynamic_type (type))
> > +	/* Value is a constant byte-sequence and needs no memory access.  */
> > +	type = resolve_dynamic_type (type, /* Unused address.  */ 0);
> 
> Although not required by C, we prefer in the GDB project to still
> use curly braces around the if block. The reason is that the comment
> visually looks like a statement, so it looks like the if block as
> more than one statement, hence the use of curly braces...
> 
> Thank you!
> 
> --
> Joel
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 00/15] C99 variable length array support
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
                   ` (14 preceding siblings ...)
  2014-02-06 16:28 ` [PATCH v5 03/15] type: add c99 variable length array support Sanimir Agovic
@ 2014-02-09  3:49 ` Joel Brobecker
  2014-02-10  4:33   ` Joel Brobecker
  2014-02-28 18:13 ` status update: " Joel Brobecker
  16 siblings, 1 reply; 45+ messages in thread
From: Joel Brobecker @ 2014-02-09  3:49 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

> this patch series (v5) add C99 variable length support to gdb.

Thanks for sending the latest version of the patch series.
The log of the changes between each series is also very helpful.

I scanned through each patch, and have no real new comment.
FOAD, this is unfortunately not an approval, since I don't feel
comfortable enough with dwarf2read to review them well.

The next step for me is to test those changes against the AdaCore
testsuite. I will try to schedule that early next week.

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 00/15] C99 variable length array support
  2014-02-09  3:49 ` [PATCH v5 00/15] C99 " Joel Brobecker
@ 2014-02-10  4:33   ` Joel Brobecker
  2014-02-17 20:22     ` Joel Brobecker
  2014-02-26 14:05     ` Joel Brobecker
  0 siblings, 2 replies; 45+ messages in thread
From: Joel Brobecker @ 2014-02-10  4:33 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

Hello Sanimir,

> The next step for me is to test those changes against the AdaCore
> testsuite. I will try to schedule that early next week.

Good news! No regression detected with our testsuite on x86_64-linux.
No improvement either, but that is to be expected, since we already
handle the dynamicity via other means (hopefully to be deprecated
soon).

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 00/15] C99 variable length array support
  2014-02-10  4:33   ` Joel Brobecker
@ 2014-02-17 20:22     ` Joel Brobecker
  2014-02-26 14:05     ` Joel Brobecker
  1 sibling, 0 replies; 45+ messages in thread
From: Joel Brobecker @ 2014-02-17 20:22 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

Hello,

> > The next step for me is to test those changes against the AdaCore
> > testsuite. I will try to schedule that early next week.
> 
> Good news! No regression detected with our testsuite on x86_64-linux.
> No improvement either, but that is to be expected, since we already
> handle the dynamicity via other means (hopefully to be deprecated
> soon).

Pinging this patch series on behalf of its author...
Starting at:
https://www.sourceware.org/ml/gdb-patches/2014-02/msg00097.html

Thank you!
-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 00/15] C99 variable length array support
  2014-02-10  4:33   ` Joel Brobecker
  2014-02-17 20:22     ` Joel Brobecker
@ 2014-02-26 14:05     ` Joel Brobecker
  2014-03-03 16:51       ` Agovic, Sanimir
  1 sibling, 1 reply; 45+ messages in thread
From: Joel Brobecker @ 2014-02-26 14:05 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

> > The next step for me is to test those changes against the AdaCore
> > testsuite. I will try to schedule that early next week.
> 
> Good news! No regression detected with our testsuite on x86_64-linux.
> No improvement either, but that is to be expected, since we already
> handle the dynamicity via other means (hopefully to be deprecated
> soon).

Fair warning: ISTM that this patch series is very close to approval,
and I would really like to see this patch series go in. So I will
start reviewing past discussion an comparing the latest version
against past comments. If all comments have been addressed, my plan
is to approve the patch. Please let me know if there are any objections.

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 01/15] refactoring: rename create_range_type to create_static_range_type
  2014-02-06 16:28 ` [PATCH v5 01/15] refactoring: rename create_range_type to create_static_range_type Sanimir Agovic
@ 2014-02-27 22:03   ` Joel Brobecker
  2014-02-28 11:02     ` Agovic, Sanimir
  0 siblings, 1 reply; 45+ messages in thread
From: Joel Brobecker @ 2014-02-27 22:03 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

On Thu, Feb 06, 2014 at 05:27:22PM +0100, Sanimir Agovic wrote:
> 2013-12-19  Sanimir Agovic  <sanimir.agovic@intel.com>
>             Keven Boell <keven.boell@intel.com>
> 
> 	* gdbtypes.c (create_static_range_type): Renamed from create_range_type.
> 	* gdbtypes.h (create_static_range_type): Renamed from create_range_type.
> 	* ada-lang.c (*): All uses of create_range_type updated.
> 	* coffread.c (*): All uses of create_range_type updated.
> 	* dwarf2read.c (*): All uses of create_range_type updated.
> 	* f-exp.y (*): All uses of create_range_type updated.
> 	* m2-valprint.c (*): All uses of create_range_type updated.
> 	* mdebugread.c (*): All uses of create_range_type updated.
> 	* stabsread.c (*): All uses of create_range_type updated.
> 	* valops.c (*): All uses of create_range_type updated.
> 	* valprint.c (*): All uses of create_range_type updated.

Can you remove the " (*)" from the ChangeLog entries? These are not
needed. Thus, for instance:

        * ada-lang.c: All uses of create_range_type updated.

I have a few minor formatting nits highighted below, but this patch
is pre-approved with those changes.

Thank you!

> diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
> index 786ca7a..0d93267 100644
> --- a/gdb/ada-lang.c
> +++ b/gdb/ada-lang.c
> @@ -1875,8 +1875,8 @@ ada_type_of_array (struct value *arr, int bounds)
>            struct value *high = desc_one_bound (descriptor, arity, 1);
>  
>            arity -= 1;
> -          create_range_type (range_type, value_type (low),
> -                             longest_to_int (value_as_long (low)),
> +          create_static_range_type (range_type, value_type (low),
> +				    longest_to_int (value_as_long (low)),
>                               longest_to_int (value_as_long (high)));

The indentation of the 3 line (longest_to_int) needs to be adjusted.

>    struct type *index_type =
> -    create_range_type (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type0)),
> -                       low, high);
> +    create_static_range_type (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type0)),
> +			      low, high);

I know that you've been following the style in this file, but
the assignment operator should be at the start of the next line.
We don't need or even want to fix all incorrect forms in this patch,
but can we fix the ones we touch?

>    struct type *index_type =
> -    create_range_type (NULL, TYPE_INDEX_TYPE (type), low, high);
> +    create_static_range_type (NULL, TYPE_INDEX_TYPE (type), low, high);

Same here, please.

>    struct type *index_type =
> -    create_range_type (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (arr_type0)),
> -                       low, low - 1);
> +    create_static_range_type
> +    (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (arr_type0)), low, low - 1);

Same as above. Also, can you indent the '(' for the start of the
function parameters 2 characters past the funtion's indentation?
Something like the following:

  struct type *index_type
    = create_static_range_type
        (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (arr_type0)), low, low - 1);

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* RE: [PATCH v5 01/15] refactoring: rename create_range_type to create_static_range_type
  2014-02-27 22:03   ` Joel Brobecker
@ 2014-02-28 11:02     ` Agovic, Sanimir
  0 siblings, 0 replies; 45+ messages in thread
From: Agovic, Sanimir @ 2014-02-28 11:02 UTC (permalink / raw)
  To: 'Joel Brobecker'; +Cc: tromey, Boell, Keven, gdb-patches

Thanks for your review.

> I have a few minor formatting nits highighted below, but this patch
> is pre-approved with those changes.
Addressed mentioned ChangeLog and coding style issues below. Thanks again.

 -Sanimir

> -----Original Message-----
> From: Joel Brobecker [mailto:brobecker@adacore.com]
> Sent: Thursday, February 27, 2014 11:03 PM
> To: Agovic, Sanimir
> Cc: tromey@redhat.com; Boell, Keven; gdb-patches@sourceware.org
> Subject: Re: [PATCH v5 01/15] refactoring: rename create_range_type to
> create_static_range_type
> 
> On Thu, Feb 06, 2014 at 05:27:22PM +0100, Sanimir Agovic wrote:
> > 2013-12-19  Sanimir Agovic  <sanimir.agovic@intel.com>
> >             Keven Boell <keven.boell@intel.com>
> >
> > 	* gdbtypes.c (create_static_range_type): Renamed from create_range_type.
> > 	* gdbtypes.h (create_static_range_type): Renamed from create_range_type.
> > 	* ada-lang.c (*): All uses of create_range_type updated.
> > 	* coffread.c (*): All uses of create_range_type updated.
> > 	* dwarf2read.c (*): All uses of create_range_type updated.
> > 	* f-exp.y (*): All uses of create_range_type updated.
> > 	* m2-valprint.c (*): All uses of create_range_type updated.
> > 	* mdebugread.c (*): All uses of create_range_type updated.
> > 	* stabsread.c (*): All uses of create_range_type updated.
> > 	* valops.c (*): All uses of create_range_type updated.
> > 	* valprint.c (*): All uses of create_range_type updated.
> 
> Can you remove the " (*)" from the ChangeLog entries? These are not
> needed. Thus, for instance:
> 
>         * ada-lang.c: All uses of create_range_type updated.
> 
> I have a few minor formatting nits highighted below, but this patch
> is pre-approved with those changes.
> 
> Thank you!
> 
> > diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
> > index 786ca7a..0d93267 100644
> > --- a/gdb/ada-lang.c
> > +++ b/gdb/ada-lang.c
> > @@ -1875,8 +1875,8 @@ ada_type_of_array (struct value *arr, int bounds)
> >            struct value *high = desc_one_bound (descriptor, arity, 1);
> >
> >            arity -= 1;
> > -          create_range_type (range_type, value_type (low),
> > -                             longest_to_int (value_as_long (low)),
> > +          create_static_range_type (range_type, value_type (low),
> > +				    longest_to_int (value_as_long (low)),
> >                               longest_to_int (value_as_long (high)));
> 
> The indentation of the 3 line (longest_to_int) needs to be adjusted.
> 
> >    struct type *index_type =
> > -    create_range_type (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type0)),
> > -                       low, high);
> > +    create_static_range_type (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (type0)),
> > +			      low, high);
> 
> I know that you've been following the style in this file, but
> the assignment operator should be at the start of the next line.
> We don't need or even want to fix all incorrect forms in this patch,
> but can we fix the ones we touch?
> 
> >    struct type *index_type =
> > -    create_range_type (NULL, TYPE_INDEX_TYPE (type), low, high);
> > +    create_static_range_type (NULL, TYPE_INDEX_TYPE (type), low, high);
> 
> Same here, please.
> 
> >    struct type *index_type =
> > -    create_range_type (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (arr_type0)),
> > -                       low, low - 1);
> > +    create_static_range_type
> > +    (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (arr_type0)), low, low - 1);
> 
> Same as above. Also, can you indent the '(' for the start of the
> function parameters 2 characters past the funtion's indentation?
> Something like the following:
> 
>   struct type *index_type
>     = create_static_range_type
>         (NULL, TYPE_TARGET_TYPE (TYPE_INDEX_TYPE (arr_type0)), low, low - 1);
> 
> --
> Joel
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 03/15] type: add c99 variable length array support
  2014-02-06 16:28 ` [PATCH v5 03/15] type: add c99 variable length array support Sanimir Agovic
@ 2014-02-28 16:27   ` Joel Brobecker
  2014-04-08  6:41     ` Agovic, Sanimir
  0 siblings, 1 reply; 45+ messages in thread
From: Joel Brobecker @ 2014-02-28 16:27 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

Hi Sanimir,

> 2013-10-18  Sanimir Agovic  <sanimir.agovic@intel.com>
>             Keven Boell  <keven.boell@intel.com>
> 
> 	* dwarf2loc.c (dwarf2_locexpr_baton_eval): New function.
> 	(dwarf2_evaluate_property): New function.
> 	* dwarf2loc.h (dwarf2_evaluate_property): New function prototype.
> 	* dwarf2read.c (attr_to_dynamic_prop): New function.
> 	(read_subrange_type): Use attr_to_dynamic_prop to read high bound
> 	attribute.
> 	* gdbtypes.c: Include dwarf2loc.h.
> 	(is_dynamic_type): New function.
> 	(resolve_dynamic_type): New function.
> 	(resolve_dynamic_bounds): New function.
> 	(get_type_length): New function.
> 	(check_typedef): Use get_type_length to compute type length.
> 	* gdbtypes.h (TYPE_HIGH_BOUND_KIND): New macro.
> 	(TYPE_LOW_BOUND_KIND): New macro.
> 	(is_dynamic_type): New function prototype.
> 	* value.c (value_from_contents_and_address): Call resolve_dynamic_type
> 	to resolve dynamic properties of the type. Update comment.
> 	* valops.c (get_value_at, value_at, value_at_lazy): Update comment.

Tough review (took a while). Some questions and comments, but nothing
too serious. See below.

I apologize in advance if I appear to nit-pick - I only allow myself to
do so when touching the patch for other reasons too.  Thank you!

> Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
> ---
>  gdb/dwarf2loc.c  | 120 +++++++++++++++++++++++++
>  gdb/dwarf2loc.h  |  24 +++++
>  gdb/dwarf2read.c | 100 +++++++++++++++------
>  gdb/gdbtypes.c   | 264 ++++++++++++++++++++++++++++++++++++++++++++-----------
>  gdb/gdbtypes.h   |  10 +++
>  gdb/valops.c     |  12 ++-
>  gdb/value.c      |  17 ++--
>  7 files changed, 459 insertions(+), 88 deletions(-)
> 
> diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
> index 2b1f323..72bc727 100644
> --- a/gdb/dwarf2loc.c
> +++ b/gdb/dwarf2loc.c
> @@ -2431,6 +2431,126 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame,
>    return dwarf2_evaluate_loc_desc_full (type, frame, data, size, per_cu, 0);
>  }
>  
> +/* Evaluates a dwarf expression and stores the result in VAL, expecting
> +   that the dwarf expression only produces a single CORE_ADDR.  ADDR is a
> +   context (location of a variable) and might be needed to evaluate the
> +   location expression.
> +   Returns 1 on success, 0 otherwise.   */
> +
> +static int
> +dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
> +			   CORE_ADDR addr, CORE_ADDR *valp)
> +{
> +  struct dwarf_expr_context *ctx;
> +  struct dwarf_expr_baton baton;
> +  struct objfile *objfile;
> +  struct cleanup *cleanup;
> +
> +  if (dlbaton == NULL || dlbaton->size == 0)
> +    return 0;
> +
> +  ctx = new_dwarf_expr_context ();
> +  cleanup = make_cleanup_free_dwarf_expr_context (ctx);
> +
> +  baton.frame = get_selected_frame (NULL);
> +  baton.per_cu = dlbaton->per_cu;
> +
> +  objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
> +
> +  ctx->gdbarch = get_objfile_arch (objfile);
> +  ctx->addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
> +  ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (dlbaton->per_cu);
> +  ctx->offset = dwarf2_per_cu_text_offset (dlbaton->per_cu);
> +  ctx->funcs = &dwarf_expr_ctx_funcs;
> +  ctx->baton = &baton;
> +
> +  dwarf_expr_eval (ctx, dlbaton->data, dlbaton->size);
> +
> +  switch (ctx->location)
> +    {
> +    case DWARF_VALUE_REGISTER:
> +    case DWARF_VALUE_MEMORY:
> +    case DWARF_VALUE_STACK:
> +      *valp = dwarf_expr_fetch_address (ctx, 0);
> +      if (ctx->location == DWARF_VALUE_REGISTER)
> +	*valp = dwarf_expr_read_addr_from_reg (&baton, *valp);
> +      do_cleanups (cleanup);
> +      return 1;
> +    case DWARF_VALUE_LITERAL:
> +      *valp = extract_signed_integer (ctx->data, ctx->len,
> +				      gdbarch_byte_order (ctx->gdbarch));
> +      do_cleanups (cleanup);
> +      return 1;
> +      /* Not supported dwarf values.  */
> +    case DWARF_VALUE_OPTIMIZED_OUT:
> +    case DWARF_VALUE_IMPLICIT_POINTER:

Would "Unsupported" be more idiomatic? I'm not a native English
speaker, so I am not sure. But "unsupported" somehow sounds better.
Feel free to choose either option.

> +      break;
> +    }
> +
> +  do_cleanups (cleanup);
> +
> +  return 0;

Can you remove the empty line betwee do_cleanups and return?
It's not very important, but compresses a bit the code, I think.

> +}
> +
> +/* See dwarf2loc.h.  */
> +
> +int
> +dwarf2_evaluate_property (const struct dynamic_prop *prop, CORE_ADDR address,
> +			  CORE_ADDR *value)
> +{
> +  if (prop == NULL)
> +    return 0;
> +
> +  switch (prop->kind)
> +    {
> +    case PROP_LOCEXPR:
> +      {
> +	const struct dwarf2_property_baton *baton = prop->data.baton;
> +
> +	if (dwarf2_locexpr_baton_eval (&baton->locexpr, address, value))
> +	  {
> +	    if (baton->referenced_type)
> +	      {
> +		struct value *val = value_at (baton->referenced_type, *value);
> +
> +		*value = value_as_address (val);
> +	      }
> +	    return 1;
> +	  }
> +      }
> +      break;
> +
> +    case PROP_LOCLIST:
> +      {
> +	struct dwarf2_property_baton *baton = prop->data.baton;
> +	struct frame_info *frame = get_selected_frame (NULL);
> +	CORE_ADDR pc = get_frame_address_in_block (frame);
> +	const gdb_byte *data;
> +	struct value *val;
> +	size_t size;
> +
> +	data = dwarf2_find_location_expression (&baton->loclist, &size, pc);
> +	if (data != NULL)
> +	  {
> +	    val = dwarf2_evaluate_loc_desc (baton->referenced_type, frame, data,
> +					    size, baton->loclist.per_cu);
> +	    if (!value_optimized_out (val))
> +	      {
> +		*value = value_as_address (val);
> +		return 1;
> +	      }
> +	  }
> +      }
> +      break;
> +
> +    case PROP_CONST:
> +      *value = prop->data.const_val;
> +      return 1;
> +    }
> +
> +  return 0;
> +}
> +
>  \f
>  /* Helper functions and baton for dwarf2_loc_desc_needs_frame.  */
>  
> diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h
> index 9bc8ca5..9be3e24 100644
> --- a/gdb/dwarf2loc.h
> +++ b/gdb/dwarf2loc.h
> @@ -90,6 +90,13 @@ struct value *dwarf2_evaluate_loc_desc (struct type *type,
>  					size_t size,
>  					struct dwarf2_per_cu_data *per_cu);
>  
> +/* Converts a dynamic property into a static one.  ADDR is the address of
> +   the object currently being evaluated and might be nedded.
> +   Returns 1 if PROP could be converted and the static value is passed back
> +   into VALUE, otherwise returns 0.  */
> +int dwarf2_evaluate_property (const struct dynamic_prop *prop,
> +			      CORE_ADDR addr, CORE_ADDR *value);
> +

Would you mind adding an empty line betwee documentation and
declaration? It's a bit of a nit-pick, but since we're adjusting
this patch, we might as well.

>  CORE_ADDR dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
>  				  unsigned int addr_index);
>  
> @@ -135,6 +142,23 @@ struct dwarf2_loclist_baton
>    unsigned char from_dwo;
>  };
>  
> +/* A dynamic property is either expressed as a single location expression
> +   or a location list in the context of TYPE.  */
> +
> +struct dwarf2_property_baton
> +{
> +  /* Keep track of referenced type.  */
> +  struct type *referenced_type;

Can you explain in this comment what the referenced type is?
If it helps, giving an example could be used.

> +  union
> +  {
> +    /* Location expression.  */
> +    struct dwarf2_locexpr_baton locexpr;
> +
> +    /* Location list to be evaluated in the context of TYPE.  */
> +    struct dwarf2_loclist_baton loclist;
> +  };
> +};
> +
>  extern const struct symbol_computed_ops dwarf2_locexpr_funcs;
>  extern const struct symbol_computed_ops dwarf2_loclist_funcs;
>  
> diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
> index 101065b..1d5fa3d 100644
> --- a/gdb/dwarf2read.c
> +++ b/gdb/dwarf2read.c
> @@ -14252,6 +14252,78 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
>    return set_die_type (die, type, cu);
>  }
>  
> +/* Parse dwarf attribute if it's a block, reference or constant and put the
> +   resulting value of the attribute into struct bound_prop.
> +   Returns 1 if ATTR could be resolved into PROP, 0 otherwise.  */
> +
> +static int
> +attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
> +		      struct dwarf2_cu *cu, struct dynamic_prop *prop)
> +{
> +  struct dwarf2_property_baton *baton;
> +  struct obstack *obstack = &cu->objfile->objfile_obstack;
> +
> +  if (attr == NULL || prop == NULL)
> +    return 0;
> +
> +  if (attr_form_is_block (attr))
> +    {
> +      baton = obstack_alloc (obstack, sizeof (*baton));
> +      baton->referenced_type = NULL;
> +      baton->locexpr.per_cu = cu->per_cu;
> +      baton->locexpr.size = DW_BLOCK (attr)->size;
> +      baton->locexpr.data = DW_BLOCK (attr)->data;
> +      prop->data.baton = baton;
> +      prop->kind = PROP_LOCEXPR;
> +      gdb_assert (prop->data.baton != NULL);
> +    }
> +  else if (attr_form_is_ref (attr))
> +    {
> +      struct dwarf2_cu *target_cu = cu;
> +      struct die_info *target_die;
> +      struct attribute *target_attr;
> +
> +      target_die = follow_die_ref (die, attr, &target_cu);
> +      target_attr = dwarf2_attr (target_die, DW_AT_location, target_cu);
> +      if (target_attr == NULL)
> +	return 0;
> +
> +      if (attr_form_is_section_offset (target_attr))
> +	{
> +	  baton = obstack_alloc (obstack, sizeof (*baton));
> +	  baton->referenced_type = die_type (target_die, target_cu);
> +	  fill_in_loclist_baton (cu, &baton->loclist, target_attr);
> +	  prop->data.baton = baton;
> +	  prop->kind = PROP_LOCLIST;
> +	  gdb_assert (prop->data.baton != NULL);
> +	}
> +      else if (attr_form_is_block (target_attr))
> +	{
> +	  baton = obstack_alloc (obstack, sizeof (*baton));
> +	  baton->referenced_type = die_type (target_die, target_cu);
> +	  baton->locexpr.per_cu = cu->per_cu;
> +	  baton->locexpr.size = DW_BLOCK (target_attr)->size;
> +	  baton->locexpr.data = DW_BLOCK (target_attr)->data;
> +	  prop->data.baton = baton;
> +	  prop->kind = PROP_LOCEXPR;
> +	  gdb_assert (prop->data.baton != NULL);
> +	}

It looks like, if TARGET_ATTR is neither a section offset
nor a block, you're getting through to the "return 1" at the end
of the function even though you've haven't set PROP. From my
reading of the DWARF v4 standard, DW_AT_location attributes
should not have any other forms, but let's protect ourselves
against it. I would add a complaint and then return 0.

> +    }
> +  else if (attr_form_is_constant (attr))
> +    {
> +      prop->data.const_val = dwarf2_get_attr_constant_value (attr, 0);
> +      prop->kind = PROP_CONST;
> +    }
> +  else
> +    {
> +      dwarf2_invalid_attrib_class_complaint (dwarf_form_name (attr->form),
> +					     dwarf2_name (die, cu));
> +      return 0;
> +    }
> +
> +  return 1;
> +}
> +
>  /* Read the given DW_AT_subrange DIE.  */
>  
>  static struct type *
> @@ -14325,27 +14397,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
>  	       die->offset.sect_off, objfile_name (cu->objfile));
>  
>    attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
> -  if (attr)
> -    {
> -      if (attr_form_is_block (attr) || attr_form_is_ref (attr))
> -        {
> -          /* GCC encodes arrays with unspecified or dynamic length
> -             with a DW_FORM_block1 attribute or a reference attribute.
> -             FIXME: GDB does not yet know how to handle dynamic
> -             arrays properly, treat them as arrays with unspecified
> -             length for now.
> -
> -             FIXME: jimb/2003-09-22: GDB does not really know
> -             how to handle arrays of unspecified length
> -             either; we just represent them as zero-length
> -             arrays.  Choose an appropriate upper bound given
> -             the lower bound we've computed above.  */
> -          high.data.const_val = low.data.const_val - 1;
> -        }
> -      else
> -        high.data.const_val = dwarf2_get_attr_constant_value (attr, 1);
> -    }
> -  else
> +  if (!attr_to_dynamic_prop (attr, die, cu, &high))
>      {
>        attr = dwarf2_attr (die, DW_AT_count, cu);
>        if (attr)

I know that in the testcase you are trying to support, the bounds
are necessarily starting at zero and therefore constant/non-dynamic.
But can you modify the function to also handle the DW_AT_lower_bound
the same way? Other languages such as Ada will need that also, and
that seems like the logical time to be doing it.

> @@ -14409,12 +14461,6 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
>  
>    range_type = create_range_type (NULL, orig_base_type, &low, &high);
>  
> -  /* Mark arrays with dynamic length at least as an array of unspecified
> -     length.  GDB could check the boundary but before it gets implemented at
> -     least allow accessing the array elements.  */
> -  if (attr && attr_form_is_block (attr))
> -    TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED;
> -
>    /* Ada expects an empty array on no boundary attributes.  */
>    if (attr == NULL && cu->language != language_ada)
>      TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED;
> diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
> index 7f0269c..f5bd236 100644
> --- a/gdb/gdbtypes.c
> +++ b/gdb/gdbtypes.c
> @@ -853,6 +853,17 @@ create_static_range_type (struct type *result_type, struct type *index_type,
>    return result_type;
>  }
>  
> +/* Predicate tests whether BOUNDS are static.  Returns 1 if all bounds values
> +   are static, otherwise returns 0.  */
> +
> +static int
> +has_static_range (const struct range_bounds *bounds)
> +{
> +  return (bounds->low.kind == PROP_CONST
> +	  && bounds->high.kind == PROP_CONST);
> +}
> +
> +
>  /* Set *LOWP and *HIGHP to the lower and upper bounds of discrete type
>     TYPE.  Return 1 if type is a range type, 0 if it is discrete (and
>     bounds will fit in LONGEST), or -1 otherwise.  */
> @@ -982,24 +993,28 @@ create_array_type (struct type *result_type,
>  		   struct type *element_type,
>  		   struct type *range_type)
>  {
> -  LONGEST low_bound, high_bound;
> -
>    if (result_type == NULL)
>      result_type = alloc_type_copy (range_type);
>  
>    TYPE_CODE (result_type) = TYPE_CODE_ARRAY;
>    TYPE_TARGET_TYPE (result_type) = element_type;
> -  if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
> -    low_bound = high_bound = 0;
> -  CHECK_TYPEDEF (element_type);
> -  /* Be careful when setting the array length.  Ada arrays can be
> -     empty arrays with the high_bound being smaller than the low_bound.
> -     In such cases, the array length should be zero.  */
> -  if (high_bound < low_bound)
> -    TYPE_LENGTH (result_type) = 0;
> -  else
> -    TYPE_LENGTH (result_type) =
> -      TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
> +
> +  if (has_static_range (TYPE_RANGE_DATA (range_type)))
> +    {
> +      LONGEST low_bound, high_bound;
> +
> +      if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
> +	low_bound = high_bound = 0;
> +      CHECK_TYPEDEF (element_type);
> +      /* Be careful when setting the array length.  Ada arrays can be
> +	 empty arrays with the high_bound being smaller than the low_bound.
> +	 In such cases, the array length should be zero.  */
> +      if (high_bound < low_bound)
> +	TYPE_LENGTH (result_type) = 0;
> +      else
> +	TYPE_LENGTH (result_type) =
> +	  TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
> +    }
>    TYPE_NFIELDS (result_type) = 1;
>    TYPE_FIELDS (result_type) =
>      (struct field *) TYPE_ZALLOC (result_type, sizeof (struct field));

Does it look like you might be leaving the TYPE_LENGTH undefined
for the case of the non-static array index? (Eg when result_type
is not passed as NULL).

It may not matter in practice, as we are probably supposed to ignore
that field for those arrays anyway. But in the case we're not, leaving
the length undefined could cause all sorts of nastiness. For instance,
a struct value fetching its contents could allocate a buffer using
that size, which potentially means randomly large memory regions,
leading to a memory error, always very scary for the typical user.

Any objection to setting the length to 0 in this case?

> @@ -1530,7 +1545,181 @@ stub_noname_complaint (void)
>    complaint (&symfile_complaints, _("stub type has NULL name"));
>  }
>  
> -/* Find the real type of TYPE.  This function returns the real type,
> +/* Calculates the size of a type.  If TYPE has static bound values takes upper
> +   and lower bound into account, otherwise only the TYPE length is returned.
> +   TYPE is expected not to be a typedef.  */

Would you mind explaining this part to me?

Intuitively, if it is an array with static bounds, then haven't we
already set the correct array length during the call to "create_array_type"?
And if the type is indeed dynamic, is the TYPE's TYPE_LENGTH correct?

> +
> +static ULONGEST
> +get_type_length (const struct type *type)
> +{
> +  const struct type *range_type, *target_type;
> +  ULONGEST len = TYPE_LENGTH (type);
> +  LONGEST low_bound, high_bound;
> +
> +  gdb_assert (TYPE_CODE (type) != TYPE_CODE_TYPEDEF);
> +
> +  if (TYPE_CODE (type) != TYPE_CODE_ARRAY
> +      && TYPE_CODE (type) != TYPE_CODE_STRING)
> +    return len;
> +
> +  range_type = check_typedef (TYPE_INDEX_TYPE (type));
> +
> +  if (!has_static_range (TYPE_RANGE_DATA (range_type)))
> +    return len;
> +
> +  target_type = check_typedef (TYPE_TARGET_TYPE (type));
> +
> +  /* Now recompute the length of the array type, based on its
> +     number of elements and the target type's length.
> +     Watch out for Ada null Ada arrays where the high bound
> +     is smaller than the low bound.  */
> +  low_bound = TYPE_LOW_BOUND (range_type);
> +  high_bound = TYPE_HIGH_BOUND (range_type);
> +
> +  if (high_bound < low_bound)
> +    len = 0;
> +  else
> +    {
> +      /* For now, we conservatively take the array length to be 0
> +         if its length exceeds UINT_MAX.  The code below assumes
> +         that for x < 0, (ULONGEST) x == -x + ULONGEST_MAX + 1,
> +         which is technically not guaranteed by C, but is usually true
> +         (because it would be true if x were unsigned with its
> +         high-order bit on).  It uses the fact that
> +         high_bound-low_bound is always representable in
> +         ULONGEST and that if high_bound-low_bound+1 overflows,
> +         it overflows to 0.  We must change these tests if we
> +         decide to increase the representation of TYPE_LENGTH
> +         from unsigned int to ULONGEST.  */
> +      ULONGEST ulow = low_bound, uhigh = high_bound;
> +      ULONGEST tlen = get_type_length (target_type);
> +
> +      len = tlen * (uhigh - ulow + 1);
> +      if (tlen == 0 || (len / tlen - 1 + ulow) != uhigh || len > UINT_MAX)
> +        len = 0;
> +    }
> +
> +  return len;
> +}
> +
> +/* See gdbtypes.h.  */
> +
> +int
> +is_dynamic_type (const struct type *type)
> +{
> +  if (TYPE_CODE (type) == TYPE_CODE_ARRAY
> +      && TYPE_NFIELDS (type) == 1)
> +    {
> +      const struct type *range_type = TYPE_INDEX_TYPE (type);
> +
> +      if (!has_static_range (TYPE_RANGE_DATA (range_type)))
> +	return 1;
> +    }
> +
> +  if (TYPE_CODE (type) == TYPE_CODE_ARRAY
> +      || TYPE_CODE (type) == TYPE_CODE_PTR
> +      || TYPE_CODE (type) == TYPE_CODE_REF
> +      || TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
> +    return is_dynamic_type (check_typedef (TYPE_TARGET_TYPE (type)));

As discussed on IRC, I think that TYPE_NFIELDS should always
be 1 for TYPE_CODE_ARRAY. So let's transform that into an assert,
if you don't mind, and see what happens?

Can you explain why you included TYPE_CODE_PTR in the list?
This is not clear to me based on the function's description.
The risk I see with this is trying to print the value of a pointer
to a dynamic array - the printing really only needs to display
the address, and not resolve the underlying array. Also, from
a logical standpoint, pointers are not dynamic types.

In the case of TYPE_CODE_TYPEDEF, I think it would be better to do
the unwrapping at the end, as it would be more consistent with what
we do, and also avoid an additional level of recursion. In fact,
the only recursion that's only really needed, I think, is for arrays,
no? Thus...

   type = check_typedef (type);

   if (TYPE_CODE (type) == TYPE_CODE_REF)
     type = check_typedef (TYPE_TARGET_TYPE (type));

   switch (TYPE_CODE (type))
     {
       case TYPE_CODE_ARRAY:
         gdb_assert (TYPE_NFIELDS (type) == 1);
         range_type = TYPE_INDEX_TYPE (type);
         if (!has_static_range (TYPE_INDEX_TYPE (type)))
           return 1;
         else
           return is_dynamic_type (TYPE_TARGET_TYPE (type));
         break;

       default:
         return 0;
         break;
     }

... for instance.

> +
> +  return 0;
> +}
> +
> +/* Resolves dynamic bound values of an array type to static ones.
> +   TYPE is modified in place and is expected not to be a typedef.
> +   ADDRESS might be needed to resolve the subrange bounds, it is the location
> +   of the associated array.  */

In this description, you mention that TYPE is expected NOT to be
a typedef, and yet the code tests for it...

> +
> +static struct type *
> +resolve_dynamic_bounds (struct type *type, CORE_ADDR addr)
> +{
> +  CORE_ADDR value;
> +  struct type *array_type;
> +  struct type *range_type;
> +  struct type *ary_dim;
> +  const struct dynamic_prop *prop;
> +  const struct dwarf2_locexpr_baton *baton;
> +  struct dynamic_prop low_bound, high_bound;
> +
> +  if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF
> +      || TYPE_CODE (type) == TYPE_CODE_PTR)
> +    {
> +      struct type *copy = copy_type (type);
> +
> +      TYPE_TARGET_TYPE (copy)
> +	= resolve_dynamic_bounds (TYPE_TARGET_TYPE (type), addr);
> +
> +      return copy;
> +    }

Same remark as above for the handling of typedefs. I think this will
help avoid an unnecessary type copy.

Also, same question about handling pointers. Why do it here?


> +
> +  gdb_assert (TYPE_CODE (type) == TYPE_CODE_ARRAY);
> +
> +  array_type = check_typedef (type);
> +  range_type = check_typedef (TYPE_INDEX_TYPE (array_type));

If the assert above passed, you should not need the check_typedef
on TYPE to get ARRAY_TYPE.


> +
> +  prop = &TYPE_RANGE_DATA (range_type)->low;
> +  if (dwarf2_evaluate_property (prop, addr, &value))
> +    {
> +      low_bound.kind = PROP_CONST;
> +      low_bound.data.const_val = value;
> +    }
> +  else
> +    {
> +      low_bound.kind = PROP_UNDEFINED;
> +      low_bound.data.const_val = 0;
> +    }
> +
> +  prop = &TYPE_RANGE_DATA (range_type)->high;
> +  if (dwarf2_evaluate_property (prop, addr, &value))
> +    {
> +      high_bound.kind = PROP_CONST;
> +      high_bound.data.const_val = value;
> +    }
> +  else
> +    {
> +      high_bound.kind = PROP_UNDEFINED;
> +      high_bound.data.const_val = 0;
> +    }
> +
> +  ary_dim = check_typedef (TYPE_TARGET_TYPE (array_type));
> +
> +  if (ary_dim != NULL && TYPE_CODE (ary_dim) == TYPE_CODE_ARRAY)
> +    array_type = resolve_dynamic_bounds (TYPE_TARGET_TYPE (type), addr);
> +  else
> +    array_type = TYPE_TARGET_TYPE (type);

I know this is going to sound a little silly, but would you mind
calling "array_type" something like "elt_type" instead. The else
block where you have "array_type = TYPE_TARGET_TYPE" really threw me
at first, thinking you had a bug in your code.

> +
> +  range_type
> +    = create_range_type (NULL,
> +			 TYPE_TARGET_TYPE (range_type),
> +			 &low_bound, &high_bound);

Small formatting nit-pick (while we're touching this code):

  range_type = create_range_type (NULL,
                                  TYPE_TARGET_TYPE (range_type),
                                  &low_bound, &high_bound);

> +  array_type = create_array_type (copy_type (type),
> +				  array_type,
> +				  range_type);
> +
> +  return array_type;
> +}
> +
> +/* See gdbtypes.h  */
> +
> +struct type *
> +resolve_dynamic_type (struct type *type, CORE_ADDR addr)
> +{
> +  struct type *real_type = check_typedef (type);
> +  struct type *resolved_type;
> +
> +  if (!TYPE_OBJFILE_OWNED (real_type))
> +    return type;

Can you explain this? This definitely deserves a comment.

> +  if (!is_dynamic_type (real_type))
> +    return type;
> +
> +  resolved_type = resolve_dynamic_bounds (type, addr);
> +  resolved_type->length = get_type_length (check_typedef (resolved_type));

Same as above regarding get_type_length. It seems to me that the length
should have already been correctly computed by create_array_type,
called from resolve_dynamic_bounds.

> +
> +  return resolved_type;
> +}
> +
> +/* find the real type of TYPE.  This function returns the real type,
      ^^^^

I think you unintentionally modified the first line of this comment...
This line should not be part of the diff.



>     after removing all layers of typedefs, and completing opaque or stub
>     types.  Completion changes the TYPE argument, but stripping of
>     typedefs does not.
> @@ -1706,44 +1895,15 @@ check_typedef (struct type *type)
>  	  /* Nothing we can do.  */
>  	}
>        else if (TYPE_CODE (type) == TYPE_CODE_ARRAY
> -	       && TYPE_NFIELDS (type) == 1
> -	       && (TYPE_CODE (range_type = TYPE_INDEX_TYPE (type))
> -		   == TYPE_CODE_RANGE))
> -	{
> -	  /* Now recompute the length of the array type, based on its
> -	     number of elements and the target type's length.
> -	     Watch out for Ada null Ada arrays where the high bound
> -	     is smaller than the low bound.  */
> -	  const LONGEST low_bound = TYPE_LOW_BOUND (range_type);
> -	  const LONGEST high_bound = TYPE_HIGH_BOUND (range_type);
> -	  ULONGEST len;
> -
> -	  if (high_bound < low_bound)
> -	    len = 0;
> -	  else
> -	    {
> -	      /* For now, we conservatively take the array length to be 0
> -		 if its length exceeds UINT_MAX.  The code below assumes
> -		 that for x < 0, (ULONGEST) x == -x + ULONGEST_MAX + 1,
> -		 which is technically not guaranteed by C, but is usually true
> -		 (because it would be true if x were unsigned with its
> -		 high-order bit on).  It uses the fact that
> -		 high_bound-low_bound is always representable in
> -		 ULONGEST and that if high_bound-low_bound+1 overflows,
> -		 it overflows to 0.  We must change these tests if we 
> -		 decide to increase the representation of TYPE_LENGTH
> -		 from unsigned int to ULONGEST.  */
> -	      ULONGEST ulow = low_bound, uhigh = high_bound;
> -	      ULONGEST tlen = TYPE_LENGTH (target_type);
> -
> -	      len = tlen * (uhigh - ulow + 1);
> -	      if (tlen == 0 || (len / tlen - 1 + ulow) != uhigh 
> -		  || len > UINT_MAX)
> -		len = 0;
> -	    }
> -	  TYPE_LENGTH (type) = len;
> -	  TYPE_TARGET_STUB (type) = 0;
> -	}
> +	       || TYPE_CODE (type) == TYPE_CODE_STRING)
> +        {
> +          range_type = TYPE_INDEX_TYPE (type);
> +          if (has_static_range (TYPE_RANGE_DATA (range_type)))
> +            {
> +              TYPE_LENGTH (type) = get_type_length (type);
> +              TYPE_TARGET_STUB (type) = 0;
> +            }
> +        }
>        else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
>  	{
>  	  TYPE_LENGTH (type) = TYPE_LENGTH (target_type);
> diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
> index f6e68c5..38cd240 100644
> --- a/gdb/gdbtypes.h
> +++ b/gdb/gdbtypes.h
> @@ -1,3 +1,4 @@
> +
>  /* Internal type definitions for GDB.
>  
>     Copyright (C) 1992-2013 Free Software Foundation, Inc.
> @@ -1574,6 +1575,15 @@ extern struct type *lookup_unsigned_typename (const struct language_defn *,
>  extern struct type *lookup_signed_typename (const struct language_defn *,
>  					    struct gdbarch *, const char *);
>  
> +/* Resolves all dynamic values of a type e.g. array bounds to static values.
> +   ADDR specifies the location of the variable the type is bound to.
> +   If TYPE has no dynamic values returns TYPE otherwise a new type with static
> +   values is returned.  */
> +extern struct type *resolve_dynamic_type (struct type *type, CORE_ADDR addr);
> +
> +/* Predicates if the type has dynamic values, which are not resolved yet.  */
> +extern int is_dynamic_type (const struct type *type);
> +

While making adjustments to this patch, would you mind adjusting
the style of the function descriptions, please. We use the imperative
style when describing the actions of the function. For instance:

/* Resolve (no s) all dynamic values of a type.

"ADDR specifies" should still be with an 's'...


>  extern struct type *check_typedef (struct type *);
>  
>  #define CHECK_TYPEDEF(TYPE)			\
> diff --git a/gdb/valops.c b/gdb/valops.c
> index 5c7bb89..a7260b9 100644
> --- a/gdb/valops.c
> +++ b/gdb/valops.c
> @@ -902,7 +902,9 @@ value_one (struct type *type)
>    return val;
>  }
>  
> -/* Helper function for value_at, value_at_lazy, and value_at_lazy_stack.  */
> +/* Helper function for value_at, value_at_lazy, and value_at_lazy_stack.
> +   The type of the created value may differ from the passed type TYPE.
> +   Make sure to retrieve values new type after this call.  */
                           ^^^^^^^^

Suggest: Make sure to retrieve the returned value's new type after
this call.

I'd suggest also an example of when the value's type might be
different...

>  static struct value *
>  get_value_at (struct type *type, CORE_ADDR addr, int lazy)
> @@ -927,7 +929,9 @@ get_value_at (struct type *type, CORE_ADDR addr, int lazy)
>     value_at_lazy instead.  value_at_lazy simply records the address of
>     the data and sets the lazy-evaluation-required flag.  The lazy flag
>     is tested in the value_contents macro, which is used if and when
> -   the contents are actually required.
> +   the contents are actually required.  The type of the created value
> +   may differ from the passed type TYPE.  Make sure to retrieve values
> +   new type after this call.
>  
>     Note: value_at does *NOT* handle embedded offsets; perform such
>     adjustments before or after calling it.  */
> @@ -938,7 +942,9 @@ value_at (struct type *type, CORE_ADDR addr)
>    return get_value_at (type, addr, 0);
>  }
>  
> -/* Return a lazy value with type TYPE located at ADDR (cf. value_at).  */
> +/* Return a lazy value with type TYPE located at ADDR (cf. value_at).
> +   The type of the created value may differ from the passed type TYPE.
> +   Make sure to retrieve values new type after this call.  */

Same remark as above. And in value.c below as well.

>  
>  struct value *
>  value_at_lazy (struct type *type, CORE_ADDR addr)
> diff --git a/gdb/value.c b/gdb/value.c
> index a64e7e1..12726a1 100644
> --- a/gdb/value.c
> +++ b/gdb/value.c
> @@ -3178,32 +3178,37 @@ value_from_ulongest (struct type *type, ULONGEST num)
>  
>  
>  /* Create a value representing a pointer of type TYPE to the address
> -   ADDR.  */
> +   ADDR.  The type of the created value may differ from the passed
> +   type TYPE.  Make sure to retrieve values new type after this call.  */
>  struct value *
>  value_from_pointer (struct type *type, CORE_ADDR addr)
>  {
> -  struct value *val = allocate_value (type);
> +  struct type *resolved_type = resolve_dynamic_type (type, addr);
> +  struct value *val = allocate_value (resolved_type);
>  
> -  store_typed_address (value_contents_raw (val), check_typedef (type), addr);
> +  store_typed_address (value_contents_raw (val),
> +		       check_typedef (resolved_type), addr);
>    return val;
>  }
>  
>  
>  /* Create a value of type TYPE whose contents come from VALADDR, if it
>     is non-null, and whose memory address (in the inferior) is
> -   ADDRESS.  */
> +   ADDRESS.  The type of the created value may differ from the passed
> +   type TYPE.  Make sure to retrieve values new type after this call.  */
>  
>  struct value *
>  value_from_contents_and_address (struct type *type,
>  				 const gdb_byte *valaddr,
>  				 CORE_ADDR address)
>  {
> +  struct type *resolved_type = resolve_dynamic_type (type, address);
>    struct value *v;
>  
>    if (valaddr == NULL)
> -    v = allocate_value_lazy (type);
> +    v = allocate_value_lazy (resolved_type);
>    else
> -    v = value_from_contents (type, valaddr);
> +    v = value_from_contents (resolved_type, valaddr);
>    set_value_address (v, address);
>    VALUE_LVAL (v) = lval_memory;
>    return v;
> -- 
> 1.8.4.2

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 08/15] vla: support for DW_AT_count
  2014-02-06 16:27 ` [PATCH v5 08/15] vla: support for DW_AT_count Sanimir Agovic
@ 2014-02-28 16:53   ` Joel Brobecker
  2014-03-12 13:51     ` Agovic, Sanimir
  0 siblings, 1 reply; 45+ messages in thread
From: Joel Brobecker @ 2014-02-28 16:53 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

> 2013-11-19  Sanimir Agovic  <sanimir.agovic@intel.com>
>             Keven Boell <keven.boell@intel.com>
> 
> 	* dwarf2read.c (read_subrange_type): Convert DW_AT_count to a dynamic
> 	property and store it as the high bound and flag the range accordingly.
> 	* gdbtypes.c (resolve_dynamic_bounds): If range is flagged as
> 	RANGE_UPPER_BOUND_IS_COUNT assign low + high - 1 as the new high bound.
> 	* gdbtypes.h (enum range_flags): New enum.
> 	(struct range_bounds): Add flags member.

Overall, the patch looks OK to me, but I'd rather we be consistent
with what we've been doing with other type flags, and use a bitfield
instead. I think that'll simplify your patch a bit.

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 09/15] vla: resolve dynamic bounds if value contents is a constant byte-sequence
  2014-02-06 16:28 ` [PATCH v5 09/15] vla: resolve dynamic bounds if value contents is a constant byte-sequence Sanimir Agovic
  2014-02-07 10:27   ` Joel Brobecker
@ 2014-02-28 17:09   ` Joel Brobecker
  2014-03-12 13:40     ` Agovic, Sanimir
  2014-03-13 16:00     ` Joel Brobecker
  1 sibling, 2 replies; 45+ messages in thread
From: Joel Brobecker @ 2014-02-28 17:09 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

> A variable location might be a constant value and therefore no inferior memory
> access is needed to read the content. In this case try to resolve the type
> bounds.
> 
> 2013-11-26  Sanimir Agovic  <sanimir.agovic@intel.com>
>             Keven Boell  <keven.boell@intel.com>
> 
> 	* findvar.c (default_read_var_value): Resolve dynamic bounds if location
> 	points to a constant blob.

Would you mind explaining this change a little more; perhaps using
some example code would help me understand why we want to resolve
dynamic types in this case (and also only in this case)?

Thank you,

> Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
> ---
>  gdb/findvar.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/gdb/findvar.c b/gdb/findvar.c
> index ec6afd6..a543dc4 100644
> --- a/gdb/findvar.c
> +++ b/gdb/findvar.c
> @@ -468,6 +468,9 @@ default_read_var_value (struct symbol *var, struct frame_info *frame)
>        return v;
>  
>      case LOC_CONST_BYTES:
> +      if (is_dynamic_type (type))
> +	/* Value is a constant byte-sequence and needs no memory access.  */
> +	type = resolve_dynamic_type (type, /* Unused address.  */ 0);
>        v = allocate_value (type);
>        memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var),
>  	      TYPE_LENGTH (type));
> -- 
> 1.8.4.2

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 10/15] vla: evaluate operand of sizeof if its type is a vla
  2014-02-06 16:28 ` [PATCH v5 10/15] vla: evaluate operand of sizeof if its type is a vla Sanimir Agovic
@ 2014-02-28 17:37   ` Joel Brobecker
  2014-03-19 12:55     ` Agovic, Sanimir
  0 siblings, 1 reply; 45+ messages in thread
From: Joel Brobecker @ 2014-02-28 17:37 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

On Thu, Feb 06, 2014 at 05:27:31PM +0100, Sanimir Agovic wrote:
> The c99 standard in "6.5.3.4 The sizeof operator" states:
> 
>  If the type of the operand is a variable length array type, the operand
>  is evaluated;[...]
> 
> This patch mirrors the following c99 semantic in gdb:
> 
>  1| int vla[n][m];
>  2| int i = 1;
>  3| sizeof(vla[i++][0]); // No sideffect
>  4| assert (i == 1);
>  5| sizeof(vla[i++]);    // With sideffect
>  6| assert (i == 2);

Not knowing C that well, I don't understand why the first one
does not have any side effect, while the second does. Can you
explain?  This will also help explain the implementation, as
I don't understand the logic yet.

> 2014-02-05  Sanimir Agovic  <sanimir.agovic@intel.com>
>             Keven Boell <keven.boell@intel.com>
> 
> 	* eval.c (evaluate_subexp_for_sizeof): Add enum noside argument.
> 	(evaluate_subexp_standard): Pass noside argument.
> 	(evaluate_subexp_for_sizeof) <BINOP_SUBSCRIPT>: Handle subscript case
> 	if noside equals EVAL_NORMAL. If the subscript yields a vla type
> 	re-evaluate subscript operation with EVAL_NORMAL to enable sideffects.
> 	* gdbtypes.c (resolve_dynamic_bounds): Mark bound as evaluated.
> 	* gdbtypes.h (enum range_flags): Add RANGE_EVALUATED case.
> 
> testsuite/gdb.base/
> 
> 	* vla-sideeffect.c: New file.
> 	* vla-sideeffect.exp: New file.

My comments below.

> 
> 
> Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
> ---
>  gdb/eval.c                                | 40 ++++++++++++--
>  gdb/gdbtypes.c                            |  1 +
>  gdb/gdbtypes.h                            |  3 +-
>  gdb/testsuite/gdb.base/vla-sideeffect.c   | 42 +++++++++++++++
>  gdb/testsuite/gdb.base/vla-sideeffect.exp | 88 +++++++++++++++++++++++++++++++
>  5 files changed, 170 insertions(+), 4 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.base/vla-sideeffect.c
>  create mode 100644 gdb/testsuite/gdb.base/vla-sideeffect.exp
> 
> diff --git a/gdb/eval.c b/gdb/eval.c
> index b3e45ca..7a34b95 100644
> --- a/gdb/eval.c
> +++ b/gdb/eval.c
> @@ -51,7 +51,8 @@ extern int overload_resolution;
>  
>  /* Prototypes for local functions.  */
>  
> -static struct value *evaluate_subexp_for_sizeof (struct expression *, int *);
> +static struct value *evaluate_subexp_for_sizeof (struct expression *, int *,
> +						 enum noside);
>  
>  static struct value *evaluate_subexp_for_address (struct expression *,
>  						  int *, enum noside);
> @@ -2563,7 +2564,7 @@ evaluate_subexp_standard (struct type *expect_type,
>  	  evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
>  	  goto nosideret;
>  	}
> -      return evaluate_subexp_for_sizeof (exp, pos);
> +      return evaluate_subexp_for_sizeof (exp, pos, noside);
>  
>      case UNOP_CAST:
>        (*pos) += 2;
> @@ -3000,7 +3001,8 @@ evaluate_subexp_with_coercion (struct expression *exp,
>     Advance *POS over the subexpression.  */
>  
>  static struct value *
> -evaluate_subexp_for_sizeof (struct expression *exp, int *pos)
> +evaluate_subexp_for_sizeof (struct expression *exp, int *pos,
> +			    enum noside noside)

Can you also update the function's introductory comment to document
the new parameter?

>  {
>    /* FIXME: This should be size_t.  */
>    struct type *size_type = builtin_type (exp->gdbarch)->builtin_int;
> @@ -3054,6 +3056,38 @@ evaluate_subexp_for_sizeof (struct expression *exp, int *pos)
>        return
>  	value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
>  
> +    case BINOP_SUBSCRIPT:
> +      if (noside == EVAL_NORMAL)
> +	{

This deserves a comment explaining why you do what you in EVAL_NORMAL
mode.  Probably something along the lines of the answer to the question
I asked above. Especially the bits I marked as [1] below...


> +	  int oldpos = *pos;
> +
> +	  (*pos) += 1;
> +	  val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
> +	  *pos = oldpos;
> +	  noside = EVAL_AVOID_SIDE_EFFECTS;

It would be easier, I think, to have a temporary like you do, and pass
that temporary as the position to evaluate_subexp.  You'd then not
have to restore POS afterwards.

Also, I don't think you need to set noside to EVAL_AVOID_SIDE_EFFECTS
since you're not using it other than in your initial mode check.

> +
> +	  type = check_typedef (value_type (val));
> +	  if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
> +	    {
> +	      type = check_typedef (TYPE_TARGET_TYPE (type));
> +	      if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
> +		{
> +		  type = TYPE_INDEX_TYPE (type);
> +		  if ((TYPE_RANGE_DATA (type)->flags & RANGE_EVALUATED)
> +		      == RANGE_EVALUATED)
> +		    {

[1] (see reference to this above).

> +		      val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_NORMAL);
> +		      return value_from_longest
> +			(size_type, (LONGEST)TYPE_LENGTH (value_type (val)));
> +		    }
> +		}
> +	    }
> +	}
> +
> +      val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
> +      return value_from_longest (size_type,
> +				 (LONGEST)TYPE_LENGTH (value_type (val)));

Formatting: Space after "(LONGEST)". But I suggest intead falling
through to the default: case below. Just add a command mentioning
that you are doing it intentionally. Eg:

        /* Fall through.  */


> +
>      default:
>        val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
>        return value_from_longest (size_type,
> diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
> index 83a2c75..67aa439 100644
> --- a/gdb/gdbtypes.c
> +++ b/gdb/gdbtypes.c
> @@ -1697,6 +1697,7 @@ resolve_dynamic_bounds (struct type *type, CORE_ADDR addr)
>      = create_range_type (NULL,
>  			 TYPE_TARGET_TYPE (range_type),
>  			 &low_bound, &high_bound);
> +  TYPE_RANGE_DATA (range_type)->flags |= RANGE_EVALUATED;
>    array_type = create_array_type (copy_type (type),
>  				  array_type,
>  				  range_type);
> diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
> index 100e3f4..4e92d4a 100644
> --- a/gdb/gdbtypes.h
> +++ b/gdb/gdbtypes.h
> @@ -396,7 +396,8 @@ struct dynamic_prop
>  
>  enum range_flags
>  {
> -  RANGE_UPPER_BOUND_IS_COUNT = 1 /* High bound contains number of elements.  */
> +  RANGE_UPPER_BOUND_IS_COUNT = 1, /* High bound contains number of elements.  */
> +  RANGE_EVALUATED                 /* Bound was dynamic.  */

Same as in one of the previous patches. I think a bit component would
be better.. I also would like the comment to be a little more
elaborated: What does it mean when the flag is set vs unset?

>  };
>  
>  /* Determine which field of the union main_type.fields[x].loc is used.  */
> diff --git a/gdb/testsuite/gdb.base/vla-sideeffect.c b/gdb/testsuite/gdb.base/vla-sideeffect.c
> new file mode 100644
> index 0000000..29ee99b
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/vla-sideeffect.c
> @@ -0,0 +1,42 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2014 Free Software Foundation, Inc.
> +
> +   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 <stddef.h>
> +#define SIZE 10
> +
> +int
> +main ()

Add "void" as param here, please.

> +{
> +  int n = SIZE;
> +  int i = 0;
> +  int j = 0;
> +  int vla2[SIZE][n];
> +  int vla1[n];
> +
> +  for (i = 0; i < n; i++)
> +    vla1[i] = (i * 2) + n;
> +
> +  for (i = 0; i < SIZE; i++)
> +    for (j = 0; j < n; j++)
> +      vla2[i][j] = (i + j) + n;
> +
> +
> +  i = 0;
> +  j = 0;
> +
> +  return 0;           /* vla-filled */
> +}
> diff --git a/gdb/testsuite/gdb.base/vla-sideeffect.exp b/gdb/testsuite/gdb.base/vla-sideeffect.exp
> new file mode 100644
> index 0000000..0ea9bc2
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/vla-sideeffect.exp
> @@ -0,0 +1,88 @@
> +# Copyright 2014 Free Software Foundation, Inc.
> +
> +# 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/>.
> +
> +# Tests sideffect of sizeof evaluation.
           ^^^^^^^^^
side-effects

> +# Based on gcc/testsuite/gcc.dg/vla-4.c; vla-15.c
> +
> +standard_testfile ".c"

The ".c" shouldn't be necessary. Can you remove it?

> +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
> +    return -1
> +}
> +
> +if ![runto_main] {
> +    return -1
> +}
> +
> +gdb_breakpoint [gdb_get_line_number "vla-filled"]
> +gdb_continue_to_breakpoint "vla-filled"
> +
> +# Check side effects for sizeof argument.
> +set sizeof_int [get_sizeof "int" 4]
> +set sizeof_vla [ expr "10" * "$sizeof_int" ]
> +
> +gdb_test "print sizeof (vla1\[i++\])" "\\$\\d+ = ${sizeof_int}" \

You don't need to match the $N part of the output, we've traditionally
saved us the trouble, but simply using: " = ${sizeof_int}"

Can you adjust the testcase throughout?

> +         "print sizeof (vla1\[i++\])"
> +gdb_test "print i" "\\$\\d+ = 0" \
> +         "print i - sizeof no side effects"
> +
> +gdb_test "print sizeof (++vla1\[0\])" "\\$\\d+ = ${sizeof_int}" \
> +         "print sizeof (++vla1\[0\])"
> +gdb_test "print vla1\[0\]" "\\$\\d+ = 10" \
> +         "print vla1\[0\] - sizeof no side effects"
> +
> +gdb_test "ptype ++vla1\[0\]" "type = int" "ptype ++vla1\[0\]"
> +gdb_test "print vla1\[0\]" "\\$\\d+ = 10" \
> +         "print vla1\[0\] - ptype no side effects"
> +
> +gdb_test "whatis ++vla1\[0\]" "type = int" "whatis ++vla1\[0\]"
> +gdb_test "print vla1\[0\]" "\\$\\d+ = 10" \
> +         "print vla1\[0\] - whatis no side effects"
> +
> +
> +gdb_test "print sizeof (vla2\[i++\])" "\\$\\d+ = ${sizeof_vla}" \
> +         "print sizeof (vla2\[i++\])"
> +gdb_test "print i" "\\$\\d+ = 1" \
> +         "print i - sizeof with side effects (1)"
> +
> +gdb_test "print sizeof (vla2\[i++ + sizeof(j++)\])" "\\$\\d+ = ${sizeof_vla}" \
> +         "print sizeof (vla2\[i++ + sizeof(j++)\])"
> +gdb_test "print i" "\\$\\d+ = 2" \
> +         "print i - sizeof with side effects (2)"
> +gdb_test "print j" "\\$\\d+ = 0" \
> +         "print j - sizeof with no side effects"
> +
> +gdb_test "ptype vla2\[i++\]" "type = int \\\[10\\\]" \
> +         "ptype vla2\[i++\]"
> +gdb_test "print i" "\\$\\d+ = 2" \
> +         "print i - ptype with side effects (1)"
> +
> +gdb_test "ptype vla2\[i++ + sizeof(j++)\]" "type = int \\\[10\\\]" \
> +         "ptype vla2\[i++ + sizeof(j++)\]"
> +gdb_test "print i" "\\$\\d+ = 2" \
> +         "print i - ptype with side effects (2)"
> +gdb_test "print j" "\\$\\d+ = 0" \
> +         "print j - ptype with no side effects"
> +
> +gdb_test "whatis vla2\[i++\]" "type = int \\\[10\\\]" \
> +         "whatis vla2\[i++\]"
> +gdb_test "print i" "\\$\\d+ = 2" \
> +         "print i - whatis with side effects (1)"
> +
> +gdb_test "whatis vla2\[i++ + sizeof(j++)\]" "type = int \\\[10\\\]" \
> +         "whatis vla2\[i++ + sizeof(j++)\]"
> +gdb_test "print i" "\\$\\d+ = 2" \
> +         "print i - whatis with side effects (2)"
> +gdb_test "print j" "\\$\\d+ = 0" \
> +         "print j - whatis with no side effects"
> -- 
> 1.8.4.2

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 11/15] test: cover subranges with present DW_AT_count attribute
  2014-02-06 16:27 ` [PATCH v5 11/15] test: cover subranges with present DW_AT_count attribute Sanimir Agovic
@ 2014-02-28 17:52   ` Joel Brobecker
  0 siblings, 0 replies; 45+ messages in thread
From: Joel Brobecker @ 2014-02-28 17:52 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

On Thu, Feb 06, 2014 at 05:27:32PM +0100, Sanimir Agovic wrote:
> The dwarf attribute DW_AT_count specifies the elements of a subrange.
> This test covers subranges with present count but absent upper bound
> attribute, both with static and dynamic attribute values.
> 
> 2013-11-26  Sanimir Agovic  <sanimir.agovic@intel.com>
>             Keven Boell  <keven.boell@intel.com>
> 
> testsuite:
> 	* gdb.dwarf2/count.exp: New test.

One small comment.  Pre-approved with those changes made.

> +gdb_test "ptype array" "type = char \\\[5\\\]" "ptype array"
> +gdb_test "whatis array" "type = char \\\[5\\\]" "whatis array"
> +gdb_test "print array" "\"hello\"" "print array"
> +gdb_test "print sizeof array" "5" "print sizeof array"
> +
> +gdb_test "ptype static_array" "type = char \\\[5\\\]" "ptype static_array"
> +gdb_test "whatis static_array" "type = char \\\[5\\\]" "whatis static_array"
> +gdb_test "print static_array" "\"world\"" "print static_array"
> +gdb_test "print sizeof static_array" "5" "print sizeof static_array"

In the 4 "print" tests, can you start the expected output by
" = "? In particular for the sizeof tests, it'll make sure that
you don't match a bogus return value that happens to contain
a 5 in it.

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 12/15] test: multi-dimensional c99 vla.
  2014-02-06 16:28 ` [PATCH v5 12/15] test: multi-dimensional c99 vla Sanimir Agovic
@ 2014-02-28 17:58   ` Joel Brobecker
  0 siblings, 0 replies; 45+ messages in thread
From: Joel Brobecker @ 2014-02-28 17:58 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

> gdb/testsuite:
> 	* gdb.base/vla-multi.c: New. Test source file
> 	for testing multi-dimensional VLA's in C.
> 	* gdb.base/vla-multi.exp: New. Tests ensure
> 	that multi-dimensional VLA's can be evaluated
> 	correctly in C.

A small formatting nit: You normally need a second space after
periods. But in this case, you don't need to explain the purpose
of the files. If you feel that the comment is needed somewhere,
it should be in the files themselves.

I have some minor comments below, but the patch is pre-approved
with those changes made.

> 
> 
> Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
> ---
>  gdb/testsuite/gdb.base/vla-multi.c   | 55 ++++++++++++++++++++++++++++++++++++
>  gdb/testsuite/gdb.base/vla-multi.exp | 48 +++++++++++++++++++++++++++++++
>  2 files changed, 103 insertions(+)
>  create mode 100644 gdb/testsuite/gdb.base/vla-multi.c
>  create mode 100644 gdb/testsuite/gdb.base/vla-multi.exp
> 
> diff --git a/gdb/testsuite/gdb.base/vla-multi.c b/gdb/testsuite/gdb.base/vla-multi.c
> new file mode 100644
> index 0000000..47c753e
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/vla-multi.c
> @@ -0,0 +1,55 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2013 Free Software Foundation, Inc.

The copyright year range needs to include 2014 (use "2013-2014").

> +
> +   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/>.  */
> +
> +void
> +f1 (int n, int m, int vla_ptr[n][m])
> +{
> +  return;                                 /* f1_breakpoint */
> +}
> +
> +void
> +f2 (int m, int vla_ptr[][m])
> +{
> +  return;                                 /* f2_breakpoint */
> +}
> +
> +void
> +vla_mult (int n, int m)
> +{
> +  int vla[n][m];
> +  int i, j;
> +
> +  for (i = 0; i < n; i++)
> +    {
> +      for (j = 0; j < m; j++)
> +        {
> +          vla[i][j] = i + j;
> +        }
> +    }
> +
> +  f1(n, m, vla);                          /* vla_filled */
> +  f2(m, vla);
> +
> +  return;
> +}
> +
> +int
> +main()

Please add a "void" here as param.

> +{
> +  vla_mult(2, 2);
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.base/vla-multi.exp b/gdb/testsuite/gdb.base/vla-multi.exp
> new file mode 100644
> index 0000000..53f626f
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/vla-multi.exp
> @@ -0,0 +1,48 @@
> +# Copyright 2013 Free Software Foundation, Inc.

Copyright year...

> +
> +# 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/>.
> +
> +standard_testfile ".c"

Can you remove the ".c"?

> +
> +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
> +    return -1
> +}
> +
> +if ![runto_main] {
> +    return -1
> +}
> +
> +set sizeof_int [get_sizeof "int" 4]
> +
> +gdb_breakpoint [gdb_get_line_number "vla_filled"]
> +gdb_continue_to_breakpoint "vla_filled"
> +gdb_test "print vla" "\\$\\d+ = \\\{\\\{0, 1\\\}, \\\{1, 2\\\}\\\}" \
> +         "print vla"
> +gdb_test "print vla\[0\]\[1\]" "\\$\\d+ = 1" "print vla\[0\]\[1\]"
> +
> +gdb_breakpoint [gdb_get_line_number "f1_breakpoint"]
> +gdb_continue_to_breakpoint "f1_breakpoint"
> +gdb_test "print *vla_ptr" "\\$\\d+ = \\\{0, 1\\\}" "print *vla_ptr (f1)"
> +
> +# Calculate the overall size of the vla.
> +set sizeof_vla [ expr "2" * "$sizeof_int" ]
> +gdb_test "print sizeof vla_ptr\[0\]" "\\$\\d+ = ${sizeof_vla}" \
> +         "print sizeof vla_ptr\[0\]"
> +gdb_test "ptype &vla_ptr" \
> +    "type = int \\\(\\\*\\\*\\\)\\\[variable length\\\]" \
> +    "ptype &vla_ptr"
> +
> +gdb_breakpoint [gdb_get_line_number "f2_breakpoint"]
> +gdb_continue_to_breakpoint "f2_breakpoint"
> +gdb_test "print *vla_ptr" "\\$\\d+ = \\\{0, 1\\\}" "print *vla_ptr (f2)"

Can you remove the $N matching for the "print" tests?

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 13/15] test: evaluate pointers to C99 vla correctly.
  2014-02-06 16:28 ` [PATCH v5 13/15] test: evaluate pointers to C99 vla correctly Sanimir Agovic
@ 2014-02-28 18:01   ` Joel Brobecker
  0 siblings, 0 replies; 45+ messages in thread
From: Joel Brobecker @ 2014-02-28 18:01 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

On Thu, Feb 06, 2014 at 05:27:34PM +0100, Sanimir Agovic wrote:
> 2013-10-18  Keven Boell  <keven.boell@intel.com>
>             Sanimir Agovic  <sanimir.agovic@intel.com>
> 
> gdb/testsuite:
> 	* gdb.base/vla-ptr.c: New. Test source file
> 	for testing pointers to VLA's in C.
> 	* gdb.base/vla-ptr.exp: New. Tests ensure that
> 	the evaluation of pointers to VLA's work
> 	correctly in C.

Same as the previous test: You don't need to say in the ChangeLog
file what the purpose of files are.

And I have the same kind of minor comments I made in another test
patch. Also pre-approved with those comments addressed.

> 
> 
> Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
> ---
>  gdb/testsuite/gdb.base/vla-ptr.c   | 63 ++++++++++++++++++++++++++++++++++++++
>  gdb/testsuite/gdb.base/vla-ptr.exp | 52 +++++++++++++++++++++++++++++++
>  2 files changed, 115 insertions(+)
>  create mode 100644 gdb/testsuite/gdb.base/vla-ptr.c
>  create mode 100644 gdb/testsuite/gdb.base/vla-ptr.exp
> 
> diff --git a/gdb/testsuite/gdb.base/vla-ptr.c b/gdb/testsuite/gdb.base/vla-ptr.c
> new file mode 100644
> index 0000000..85c41e0
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/vla-ptr.c
> @@ -0,0 +1,63 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2013 Free Software Foundation, Inc.

Please update the copyright year range...

> +
> +   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/>.  */
> +
> +#define SIZE 5
> +
> +void
> +foo (int n, int vla_ptr[n])
> +{
> +  return;         /* foo_bp */
> +}
> +
> +void
> +bar (int *vla_ptr)
> +{
> +  return;         /* bar_bp */
> +}
> +
> +void
> +vla_func (int n)
> +{
> +  int vla[n];
> +  int (*vla_ptr)[n];
> +  typedef int typedef_vla[n];
> +  typedef_vla td_vla;
> +  int i;
> +
> +  for (i = 0; i < n; i++)
> +    {
> +      vla[i] = 2+i;
> +      td_vla[i] = 4+i;
> +    }
> +
> +  foo(n, vla);
> +  bar(vla);
> +
> +  vla_ptr = &vla;
> +
> +  typedef_vla *td_ptr = &td_vla;  /* vla_ptr_assigned */
> +
> +  return;         /* typedef_ptr_assigned */
> +}
> +
> +int
> +main ()

Missing "void" as arg.

> -- 
> 1.8.4.2

> +{
> +  vla_func(SIZE);
> +
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.base/vla-ptr.exp b/gdb/testsuite/gdb.base/vla-ptr.exp
> new file mode 100644
> index 0000000..a7785b0
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/vla-ptr.exp
> @@ -0,0 +1,52 @@
> +# Copyright 2013 Free Software Foundation, Inc.

Copyright year range...

> +
> +# 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/>.
> +
> +standard_testfile ".c"

No ".c"...

> +
> +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
> +    return -1
> +}
> +
> +if ![runto_main] {
> +    return -1
> +}
> +
> +set sizeof_int [get_sizeof "int" 4]
> +
> +# Check that VLA passed to function (pointer) points to the first element.
> +gdb_breakpoint [gdb_get_line_number "foo_bp"]
> +gdb_continue_to_breakpoint "foo_bp"
> +gdb_test "print vla_ptr" "\\\(int \\\*\\\) $hex" "print vla_ptr (foo)"
> +gdb_test "print *vla_ptr" "\\$\\d+ = 2" "print *vla_ptr (foo)"
> +
> +gdb_breakpoint [gdb_get_line_number "bar_bp"]
> +gdb_continue_to_breakpoint "bar_bp"
> +gdb_test "print vla_ptr" "\\\(int \\\*\\\) $hex" "print vla_ptr (bar)"
> +gdb_test "print *vla_ptr" "\\$\\d+ = 2" "print *vla_ptr (bar)"
> +
> +gdb_breakpoint [gdb_get_line_number "vla_ptr_assigned"]
> +gdb_continue_to_breakpoint "vla_ptr_assigned"
> +gdb_test "print *vla_ptr" "\\$\\d+ = \\\{2, 3, 4, 5, 6\\\}" \
> +         "print *vla_ptr (vla_func)"
> +
> +# Calculate the overall size of the vla.
> +set sizeof_vla [ expr "5" * "$sizeof_int" ]
> +gdb_test "print sizeof(*vla_ptr)" "\\$\\d+ = ${sizeof_vla}" \
> +         "print sizeof(*vla_ptr) (vla_func)"
> +
> +gdb_breakpoint [gdb_get_line_number "typedef_ptr_assigned"]
> +gdb_continue_to_breakpoint "typedef_ptr_assigned"
> +gdb_test "print td_vla" "\\$\\d+ = \\\{4, 5, 6, 7, 8\\\}" "print td_vla"
> +gdb_test "print *td_ptr" "\\$\\d+ = \\\{4, 5, 6, 7, 8\\\}" "print *td_ptr"

Please remove the $N checking in the expected output of "print" tests.

> -- 
> 1.8.4.2

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 14/15] test: basic c99 vla tests for C primitives
  2014-02-06 16:28 ` [PATCH v5 14/15] test: basic c99 vla tests for C primitives Sanimir Agovic
@ 2014-02-28 18:04   ` Joel Brobecker
  0 siblings, 0 replies; 45+ messages in thread
From: Joel Brobecker @ 2014-02-28 18:04 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

On Thu, Feb 06, 2014 at 05:27:35PM +0100, Sanimir Agovic wrote:
> 2013-10-18  Keven Boell  <keven.boell@intel.com>
>             Sanimir Agovic  <sanimir.agovic@intel.com>
> 
> gdb/testsuite:
> 	* gdb.base/vla-datatypes.c: New. Test source file
> 	for VLA datatype checks.
> 	* gdb.base/vla-datatypes.exp: New. Tests ensure that
> 	a VLA in C can be evaluated correctly with standard
> 	C types.

Same comments as the other tests patches. Just to make sure, I marked
them using "Here", to save myself a bit of typing...

Pre-approved with those changes.

> 
> 
> Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
> ---
>  gdb/testsuite/gdb.base/vla-datatypes.c   |  86 +++++++++++++++++++
>  gdb/testsuite/gdb.base/vla-datatypes.exp | 138 +++++++++++++++++++++++++++++++
>  2 files changed, 224 insertions(+)
>  create mode 100644 gdb/testsuite/gdb.base/vla-datatypes.c
>  create mode 100644 gdb/testsuite/gdb.base/vla-datatypes.exp
> 
> diff --git a/gdb/testsuite/gdb.base/vla-datatypes.c b/gdb/testsuite/gdb.base/vla-datatypes.c
> new file mode 100644
> index 0000000..267d239
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/vla-datatypes.c
> @@ -0,0 +1,86 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2013 Free Software Foundation, Inc.

Here.

> +
> +   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 <stddef.h>
> +#define SIZE 5
> +
> +struct foo
> +{
> +  int a;
> +};
> +
> +typedef struct bar
> +{
> +  int x;
> +  struct foo y;
> +} BAR;
> +
> +void
> +vla_factory (int n)
> +{
> +  int             int_vla[n];
> +  unsigned int    unsigned_int_vla[n];
> +  double          double_vla[n];
> +  float           float_vla[n];
> +  long            long_vla[n];
> +  unsigned long   unsigned_long_vla[n];
> +  char            char_vla[n];
> +  short           short_vla[n];
> +  unsigned short  unsigned_short_vla[n];
> +  unsigned char   unsigned_char_vla[n];
> +  struct foo      foo_vla[n];
> +  BAR             bar_vla[n];
> +  int i;
> +
> +  for (i = 0; i < n; i++)
> +    {
> +      int_vla[i] = i*2;
> +      unsigned_int_vla[i] = i*2;
> +      double_vla[i] = i/2.0;
> +      float_vla[i] = i/2.0f;
> +      long_vla[i] = i*2;
> +      unsigned_long_vla[i] = i*2;
> +      char_vla[i] = 'A';
> +      short_vla[i] = i*2;
> +      unsigned_short_vla[i] = i*2;
> +      unsigned_char_vla[i] = 'A';
> +      foo_vla[i].a = i*2;
> +      bar_vla[i].x = i*2;
> +      bar_vla[i].y.a = i*2;
> +    }
> +
> +  size_t int_size        = sizeof(int_vla);     /* vlas_filled */
> +  size_t uint_size       = sizeof(unsigned_int_vla);
> +  size_t double_size     = sizeof(double_vla);
> +  size_t float_size      = sizeof(float_vla);
> +  size_t long_size       = sizeof(long_vla);
> +  size_t char_size       = sizeof(char_vla);
> +  size_t short_size      = sizeof(short_vla);
> +  size_t ushort_size     = sizeof(unsigned_short_vla);
> +  size_t uchar_size      = sizeof(unsigned_char_vla);
> +  size_t foo_size        = sizeof(foo_vla);
> +  size_t bar_size        = sizeof(bar_vla);
> +
> +  return;                                 /* break_end_of_vla_factory */
> +}
> +
> +int
> +main ()

Here...

> +{
> +  vla_factory(SIZE);
> +  return 0;
> +}
> diff --git a/gdb/testsuite/gdb.base/vla-datatypes.exp b/gdb/testsuite/gdb.base/vla-datatypes.exp
> new file mode 100644
> index 0000000..c251709
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/vla-datatypes.exp
> @@ -0,0 +1,138 @@
> +# Copyright 2013 Free Software Foundation, Inc.

Here.

> +# 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/>.
> +
> +standard_testfile ".c"

Here.

> +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
> +    return -1
> +}
> +
> +if ![runto_main] {
> +    return -1
> +}
> +
> +gdb_breakpoint [gdb_get_line_number "vlas_filled"]
> +gdb_continue_to_breakpoint "vlas_filled"
> +

All "print" tests below...

> +# Check the values of VLA's.
> +gdb_test "print int_vla" "\\$\\d+ = \\\{0, 2, 4, 6, 8\\\}" \
> +         "print int_vla"
> +gdb_test "print unsigned_int_vla" "\\$\\d+ = \\\{0, 2, 4, 6, 8\\\}" \
> +         "print unsigned_int_vla"
> +gdb_test "print double_vla" "\\$\\d+ = \\\{0, 0.5, 1, 1.5, 2\\\}" \
> +         "print double_vla"
> +gdb_test "print float_vla" "\\$\\d+ = \\\{0, 0.5, 1, 1.5, 2\\\}" \
> +         "print float_vla"
> +gdb_test "print long_vla" "\\$\\d+ = \\\{0, 2, 4, 6, 8\\\}" \
> +         "print long_vla"
> +gdb_test "print unsigned_long_vla" "\\$\\d+ = \\\{0, 2, 4, 6, 8\\\}" \
> +         "print unsigned_long_vla"
> +gdb_test "print char_vla" "\\$\\d+ = \"AAAAA\"" \
> +         "print char_vla"
> +gdb_test "print short_vla" "\\$\\d+ = \\\{0, 2, 4, 6, 8\\\}" \
> +         "print short_vla"
> +gdb_test "print unsigned_short_vla" "\\$\\d+ = \\\{0, 2, 4, 6, 8\\\}" \
> +         "print unsigned_short_vla"
> +gdb_test "print unsigned_char_vla" "\\$\\d+ = \"AAAAA\"" \
> +         "print unsigned_char_vla"
> +gdb_test "print foo_vla" \
> +         "\\\{\\\{a = 0\\\}, \\\{a = 2\\\}, \\\{a = 4\\\}, \\\{a = 6\\\}, \\\{a = 8\\\}\\\}" \
> +         "print foo_vla"
> +gdb_test "print bar_vla" \
> +         "\\\{\\\{x = 0, y = \\\{a = 0\\\}\\\}, \\\{x = 2, y = \\\{a = 2\\\}\\\}, \\\{x = 4, y = \\\{a = 4\\\}\\\}, \\\{x = 6, y = \\\{a = 6\\\}\\\}, \\\{x = 8, y = \\\{a = 8\\\}\\\}\\\}" \
> +         "print bar_vla"
> +
> +# Check whatis of VLA's.
> +gdb_test "whatis int_vla" "type = int \\\[5\\\]" "whatis int_vla"
> +gdb_test "whatis unsigned_int_vla" "type = unsigned int \\\[5\\\]" \
> +         "whatis unsigned_int_vla"
> +gdb_test "whatis double_vla" "type = double \\\[5\\\]" "whatis double_vla"
> +gdb_test "whatis float_vla" "type = float \\\[5\\\]" "whatis float_vla"
> +gdb_test "whatis long_vla" "type = long( int)? \\\[5\\\]" "whatis long_vla"
> +gdb_test "whatis unsigned_long_vla" \
> +         "type = (long unsigned int|unsigned long) \\\[5\\\]" \
> +         "whatis unsigned_long_vla"
> +gdb_test "whatis char_vla" "type = char \\\[5\\\]" "whatis char_vla"
> +gdb_test "whatis short_vla" "type = short( int)? \\\[5\\\]" \
> +         "whatis short_vla"
> +gdb_test "whatis unsigned_short_vla" \
> +         "type = (short unsigned int|unsigned short) \\\[5\\\]" \
> +         "whatis unsigned_short_vla"
> +gdb_test "whatis unsigned_char_vla" "type = unsigned char \\\[5\\\]" \
> +         "whatis unsigned_char_vla"
> +gdb_test "whatis foo_vla" "type = struct foo \\\[5\\\]" "whatis foo_vla"
> +gdb_test "whatis bar_vla" "type = BAR \\\[5\\\]" "whatis bar_vla"
> +
> +# Check ptype of VLA's.
> +gdb_test "ptype int_vla" "type = int \\\[5\\\]" "ptype int_vla"
> +gdb_test "ptype unsigned_int_vla" "type = unsigned int \\\[5\\\]" \
> +         "ptype unsigned_int_vla"
> +gdb_test "ptype double_vla" "type = double \\\[5\\\]" "ptype double_vla"
> +gdb_test "ptype float_vla" "type = float \\\[5\\\]" "ptype float_vla"
> +gdb_test "ptype long_vla" "type = long( int)? \\\[5\\\]" "ptype long_vla"
> +gdb_test "ptype unsigned_long_vla" "type = unsigned long \\\[5\\\]" \
> +         "ptype unsigned_long_vla"
> +gdb_test "ptype char_vla" "type = char \\\[5\\\]" "ptype char_vla"
> +gdb_test "ptype short_vla" "type = short( int)? \\\[5\\\]" \
> +         "ptype short_vla"
> +gdb_test "ptype unsigned_short_vla" "type = unsigned short \\\[5\\\]" \
> +         "ptype unsigned_short_vla"
> +gdb_test "ptype unsigned_char_vla" "type = unsigned char \\\[5\\\]" \
> +         "ptype unsigned_char_vla"
> +gdb_test "ptype foo_vla" "type = struct foo {\r\n\\s+int a;\r\n} \\\[5\\\]" \
> +         "ptype foo_vla"
> +gdb_test "ptype bar_vla" \
> +         "type = struct bar {\r\n\\s+int x;\r\n\\s+struct foo y;\r\n} \\\[5\\\]" \
> +         "ptype bar_vla"
> +
> +# Check the size of the VLA's.
> +gdb_breakpoint [gdb_get_line_number "break_end_of_vla_factory"]
> +gdb_continue_to_breakpoint "break_end_of_vla_factory"
> +gdb_test "print int_size == sizeof(int_vla)" "\\$\\d+ = 1" "size of int_vla"
> +gdb_test "print uint_size == sizeof(unsigned_int_vla)" "\\$\\d+ = 1" \
> +         "size of unsigned_int_vla"
> +gdb_test "print double_size == sizeof(double_vla)" "\\$\\d+ = 1" \
> +         "size of double_vla"
> +gdb_test "print float_size == sizeof(float_vla)" "\\$\\d+ = 1" \
> +         "size of float_vla"
> +gdb_test "print long_size == sizeof(long_vla)" "\\$\\d+ = 1" \
> +         "size of long_vla"
> +gdb_test "print char_size == sizeof(char_vla)" "\\$\\d+ = 1" \
> +         "size of char_vla"
> +gdb_test "print short_size == sizeof(short_vla)" "\\$\\d+ = 1" \
> +         "size of short_vla"
> +gdb_test "print ushort_size == sizeof(unsigned_short_vla)" "\\$\\d+ = 1" \
> +         "size of unsigned_short_vla"
> +gdb_test "print uchar_size == sizeof(unsigned_char_vla)" "\\$\\d+ = 1" \
> +         "size of unsigned_char_vla"
> +gdb_test "print foo_size == sizeof(foo_vla)" "\\$\\d+ = 1" "size of foo_vla"
> +gdb_test "print bar_size == sizeof(bar_vla)" "\\$\\d+ = 1" "size of bar_vla"
> +
> +# Check side effects for sizeof argument.
> +set sizeof_int [get_sizeof "int" 4]
> +gdb_test_no_output  "set variable int_vla\[0\] = 42" \
> +                    "set variable int_vla\[0\] = 42"
> +
> +gdb_test "print sizeof (++int_vla\[0\])" "\\$\\d+ = ${sizeof_int}" \
> +         "print sizeof (++int_vla\[0\])"
> +gdb_test "print int_vla\[0\]" "\\$\\d+ = 42" \
> +         "print int_vla\[0\] - sizeof no side effects"
> +
> +gdb_test "ptype ++int_vla\[0\]" "type = int" "ptype ++int_vla\[0\]"
> +gdb_test "print int_vla\[0\]" "\\$\\d+ = 42" \
> +         "print int_vla\[0\] - ptype no side effects"
> +
> +gdb_test "whatis ++int_vla\[0\]" "type = int" "whatis ++int_vla\[0\]"
> +gdb_test "print int_vla\[0\]" "\\$\\d+ = 42" \
> +         "print int_vla\[0\] - whatis no side effects"
> -- 
> 1.8.4.2

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 15/15] test: add mi vla test
  2014-02-06 16:28 ` [PATCH v5 15/15] test: add mi vla test Sanimir Agovic
@ 2014-02-28 18:07   ` Joel Brobecker
  2014-03-12 12:53     ` Agovic, Sanimir
  0 siblings, 1 reply; 45+ messages in thread
From: Joel Brobecker @ 2014-02-28 18:07 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

On Thu, Feb 06, 2014 at 05:27:36PM +0100, Sanimir Agovic wrote:
> 2013-10-18  Keven Boell  <keven.boell@intel.com>
>             Sanimir Agovic  <sanimir.agovic@intel.com>
> 
> testsuite/gdb.mi/
> 
> 	* mi-vla-c99.exp: New file.
> 	* vla.c: New file.

Some minor comments as before - pre-approved with those changes.

> Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
> ---
>  gdb/testsuite/gdb.mi/mi-vla-c99.exp | 82 +++++++++++++++++++++++++++++++++++++
>  gdb/testsuite/gdb.mi/vla.c          | 35 ++++++++++++++++
>  2 files changed, 117 insertions(+)
>  create mode 100644 gdb/testsuite/gdb.mi/mi-vla-c99.exp
>  create mode 100644 gdb/testsuite/gdb.mi/vla.c
> 
> diff --git a/gdb/testsuite/gdb.mi/mi-vla-c99.exp b/gdb/testsuite/gdb.mi/mi-vla-c99.exp
> new file mode 100644
> index 0000000..9d0c6cc
> --- /dev/null
> +++ b/gdb/testsuite/gdb.mi/mi-vla-c99.exp
> @@ -0,0 +1,82 @@
> +# Copyright 1999-2013 Free Software Foundation, Inc.

Copyright year range.

> +
> +# Contributed by Intel Corp. <keven.boell@intel.com>
> +#
> +# 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/>.
> +
> +# Verify that, using the MI, we can evaluate a simple C Variable Length
> +# Array (VLA).
> +
> +load_lib mi-support.exp
> +set MIFLAGS "-i=mi"
> +
> +gdb_exit
> +if [mi_gdb_start] {
> +    continue
> +}
> +
> +standard_testfile vla.c
> +
> +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" \
> +                  "${binfile}" executable {debug}] != "" } {
> +     untested mi-vla-basics.exp
> +     return -1
> +}
> +
> +mi_delete_breakpoints
> +mi_gdb_reinitialize_dir $srcdir/$subdir
> +mi_gdb_load ${binfile}
> +
> +set bp_lineno [gdb_get_line_number "vla-filled"]
> +
> +mi_create_breakpoint "-t vla.c:$bp_lineno" 1 "del" "func" \
> +             ".*vla.c" $bp_lineno $hex \
> +             "insert breakpoint at line $bp_lineno after vla is filled"
> +mi_run_cmd
> +mi_expect_stop "breakpoint-hit" "func" "\{name=\"n\",value=\"5\"\}" \
> +               ".*vla.c" "$bp_lineno" { "" "disp=\"del\"" } \
> +               "run to breakpoint at line $bp_lineno"
> +
> +mi_gdb_test "500-data-evaluate-expression vla" \
> +    "500\\^done,value=\"\\{0, 1, 2, 3, 4\\}\"" "evaluate complete vla"
> +
> +mi_gdb_test "501-data-evaluate-expression vla\[0\]" \
> +    "501\\^done,value=\"0\"" "evaluate vla\[0\]"
> +
> +mi_gdb_test "502-data-evaluate-expression vla\[2\]" \
> +    "502\\^done,value=\"2\"" "evaluate vla\[2\]"
> +
> +mi_gdb_test "503-data-evaluate-expression vla\[4\]" \
> +    "503\\^done,value=\"4\"" "evaluate vla\[4\]"
> +
> +mi_create_varobj_checked vla vla "int \\\[5\\\]" \
> +                                 "create local variable vla"
> +
> +mi_gdb_test "504-var-info-type vla" \
> +    "504\\^done,type=\"int \\\[5\\\]\"" \
> +    "info type variable vla"
> +
> +mi_gdb_test "505-var-show-format vla" \
> +    "505\\^done,format=\"natural\"" \
> +    "show format variable vla"
> +
> +mi_gdb_test "506-var-evaluate-expression vla" \
> +    "506\\^done,value=\"\\\[5\\\]\"" \
> +    "eval variable vla"
> +
> +mi_list_array_varobj_children "vla" "5" "int" \
> +    "get children of vla"
> +
> +mi_gdb_exit
> +return 0
> diff --git a/gdb/testsuite/gdb.mi/vla.c b/gdb/testsuite/gdb.mi/vla.c
> new file mode 100644
> index 0000000..9b33fc8
> --- /dev/null
> +++ b/gdb/testsuite/gdb.mi/vla.c
> @@ -0,0 +1,35 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Contributed by Intel Corp. <keven.boell@intel.com>
> +
> +   Copyright 2013 Free Software Foundation, Inc.

Copyright year range...

> +
> +   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/>.  */
> +
> +int func (int n)

Formatting:

int
func (int n)

> +{
> +  int vla[n], i;
> +
> +  for (i = 0; i < n; i++)
> +    vla[i] = i;
> +
> +  return n;                 /* vla-filled */
> +}
> +
> +int main ()

Rewrite:

int
main (void)

> +{
> +  func (5);
> +
> +  return 0;
> +}
> -- 
> 1.8.4.2

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* status update: [PATCH v5 00/15] C99 variable length array support
  2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
                   ` (15 preceding siblings ...)
  2014-02-09  3:49 ` [PATCH v5 00/15] C99 " Joel Brobecker
@ 2014-02-28 18:13 ` Joel Brobecker
  16 siblings, 0 replies; 45+ messages in thread
From: Joel Brobecker @ 2014-02-28 18:13 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

OK, quick recap on this patch series as of today:

The patches that have been OK'ed so far, by either Tom or myself, and
possibly with some requests for minor adjustments, are:

   #01 | refactoring: rename create_range_type to create_static_range_type
   #02 | vla: introduce new bound type abstraction adapt uses
   #04 | vla: enable sizeof operator to work with variable length arrays
   #05 | vla: enable sizeof operator for indirection
   #06 | vla: update type from newly created value
   #07 | vla: print "variable length" for unresolved dynamic bounds
   #11 | test: cover subranges with present DW_AT_count attribute
   #12 | test: multi-dimensional c99 vla
   #13 | test: evaluate pointers to C99 vla correctly
   #14 | test: basic c99 vla tests for C primitives
   #15 | test: add mi vla test

The following patches are still under review and awaiting for answers
and/or updated patches:

   #03 | type: add c99 variable length array support
   #08 | vla: support for DW_AT_count
   #09 | vla: resolve dynamic bounds if value contents is a constant byte-seq
   #10 | vla: evaluate operand of sizeof if its type is a vla

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* RE: [PATCH v5 00/15] C99 variable length array support
  2014-02-26 14:05     ` Joel Brobecker
@ 2014-03-03 16:51       ` Agovic, Sanimir
  0 siblings, 0 replies; 45+ messages in thread
From: Agovic, Sanimir @ 2014-03-03 16:51 UTC (permalink / raw)
  To: 'Joel Brobecker'; +Cc: tromey, Boell, Keven, gdb-patches

Thanks Joel for taking care. I`m going to address your issues for the VLA patch series this week.

 -Sanimir

> -----Original Message-----
> From: gdb-patches-owner@sourceware.org [mailto:gdb-patches-owner@sourceware.org] On Behalf
> Of Joel Brobecker
> Sent: Wednesday, February 26, 2014 03:06 PM
> To: Agovic, Sanimir
> Cc: tromey@redhat.com; Boell, Keven; gdb-patches@sourceware.org
> Subject: Re: [PATCH v5 00/15] C99 variable length array support
> 
> > > The next step for me is to test those changes against the AdaCore
> > > testsuite. I will try to schedule that early next week.
> >
> > Good news! No regression detected with our testsuite on x86_64-linux.
> > No improvement either, but that is to be expected, since we already
> > handle the dynamicity via other means (hopefully to be deprecated
> > soon).
> 
> Fair warning: ISTM that this patch series is very close to approval,
> and I would really like to see this patch series go in. So I will
> start reviewing past discussion an comparing the latest version
> against past comments. If all comments have been addressed, my plan
> is to approve the patch. Please let me know if there are any objections.
> 
> --
> Joel
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052


^ permalink raw reply	[flat|nested] 45+ messages in thread

* RE: [PATCH v5 15/15] test: add mi vla test
  2014-02-28 18:07   ` Joel Brobecker
@ 2014-03-12 12:53     ` Agovic, Sanimir
  0 siblings, 0 replies; 45+ messages in thread
From: Agovic, Sanimir @ 2014-03-12 12:53 UTC (permalink / raw)
  To: 'Joel Brobecker'; +Cc: tromey, Boell, Keven, gdb-patches

Thanks for your review.

I addressed all issues in the series dealing with tests.

	https://sourceware.org/ml/gdb-patches/2014-02/msg00874.html
	https://sourceware.org/ml/gdb-patches/2014-02/msg00873.html
	https://sourceware.org/ml/gdb-patches/2014-02/msg00872.html
	https://sourceware.org/ml/gdb-patches/2014-02/msg00871.html

 -Sanimir

> -----Original Message-----
> From: Joel Brobecker [mailto:brobecker@adacore.com]
> Sent: Friday, February 28, 2014 07:07 PM
> To: Agovic, Sanimir
> Cc: tromey@redhat.com; Boell, Keven; gdb-patches@sourceware.org
> Subject: Re: [PATCH v5 15/15] test: add mi vla test
> 
> On Thu, Feb 06, 2014 at 05:27:36PM +0100, Sanimir Agovic wrote:
> > 2013-10-18  Keven Boell  <keven.boell@intel.com>
> >             Sanimir Agovic  <sanimir.agovic@intel.com>
> >
> > testsuite/gdb.mi/
> >
> > 	* mi-vla-c99.exp: New file.
> > 	* vla.c: New file.
> 
> Some minor comments as before - pre-approved with those changes.
> 
> > Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
> > ---
> >  gdb/testsuite/gdb.mi/mi-vla-c99.exp | 82 +++++++++++++++++++++++++++++++++++++
> >  gdb/testsuite/gdb.mi/vla.c          | 35 ++++++++++++++++
> >  2 files changed, 117 insertions(+)
> >  create mode 100644 gdb/testsuite/gdb.mi/mi-vla-c99.exp
> >  create mode 100644 gdb/testsuite/gdb.mi/vla.c
> >
> > diff --git a/gdb/testsuite/gdb.mi/mi-vla-c99.exp b/gdb/testsuite/gdb.mi/mi-vla-c99.exp
> > new file mode 100644
> > index 0000000..9d0c6cc
> > --- /dev/null
> > +++ b/gdb/testsuite/gdb.mi/mi-vla-c99.exp
> > @@ -0,0 +1,82 @@
> > +# Copyright 1999-2013 Free Software Foundation, Inc.
> 
> Copyright year range.
> 
> > +
> > +# Contributed by Intel Corp. <keven.boell@intel.com>
> > +#
> > +# 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/>.
> > +
> > +# Verify that, using the MI, we can evaluate a simple C Variable Length
> > +# Array (VLA).
> > +
> > +load_lib mi-support.exp
> > +set MIFLAGS "-i=mi"
> > +
> > +gdb_exit
> > +if [mi_gdb_start] {
> > +    continue
> > +}
> > +
> > +standard_testfile vla.c
> > +
> > +if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" \
> > +                  "${binfile}" executable {debug}] != "" } {
> > +     untested mi-vla-basics.exp
> > +     return -1
> > +}
> > +
> > +mi_delete_breakpoints
> > +mi_gdb_reinitialize_dir $srcdir/$subdir
> > +mi_gdb_load ${binfile}
> > +
> > +set bp_lineno [gdb_get_line_number "vla-filled"]
> > +
> > +mi_create_breakpoint "-t vla.c:$bp_lineno" 1 "del" "func" \
> > +             ".*vla.c" $bp_lineno $hex \
> > +             "insert breakpoint at line $bp_lineno after vla is filled"
> > +mi_run_cmd
> > +mi_expect_stop "breakpoint-hit" "func" "\{name=\"n\",value=\"5\"\}" \
> > +               ".*vla.c" "$bp_lineno" { "" "disp=\"del\"" } \
> > +               "run to breakpoint at line $bp_lineno"
> > +
> > +mi_gdb_test "500-data-evaluate-expression vla" \
> > +    "500\\^done,value=\"\\{0, 1, 2, 3, 4\\}\"" "evaluate complete vla"
> > +
> > +mi_gdb_test "501-data-evaluate-expression vla\[0\]" \
> > +    "501\\^done,value=\"0\"" "evaluate vla\[0\]"
> > +
> > +mi_gdb_test "502-data-evaluate-expression vla\[2\]" \
> > +    "502\\^done,value=\"2\"" "evaluate vla\[2\]"
> > +
> > +mi_gdb_test "503-data-evaluate-expression vla\[4\]" \
> > +    "503\\^done,value=\"4\"" "evaluate vla\[4\]"
> > +
> > +mi_create_varobj_checked vla vla "int \\\[5\\\]" \
> > +                                 "create local variable vla"
> > +
> > +mi_gdb_test "504-var-info-type vla" \
> > +    "504\\^done,type=\"int \\\[5\\\]\"" \
> > +    "info type variable vla"
> > +
> > +mi_gdb_test "505-var-show-format vla" \
> > +    "505\\^done,format=\"natural\"" \
> > +    "show format variable vla"
> > +
> > +mi_gdb_test "506-var-evaluate-expression vla" \
> > +    "506\\^done,value=\"\\\[5\\\]\"" \
> > +    "eval variable vla"
> > +
> > +mi_list_array_varobj_children "vla" "5" "int" \
> > +    "get children of vla"
> > +
> > +mi_gdb_exit
> > +return 0
> > diff --git a/gdb/testsuite/gdb.mi/vla.c b/gdb/testsuite/gdb.mi/vla.c
> > new file mode 100644
> > index 0000000..9b33fc8
> > --- /dev/null
> > +++ b/gdb/testsuite/gdb.mi/vla.c
> > @@ -0,0 +1,35 @@
> > +/* This testcase is part of GDB, the GNU debugger.
> > +
> > +   Contributed by Intel Corp. <keven.boell@intel.com>
> > +
> > +   Copyright 2013 Free Software Foundation, Inc.
> 
> Copyright year range...
> 
> > +
> > +   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/>.  */
> > +
> > +int func (int n)
> 
> Formatting:
> 
> int
> func (int n)
> 
> > +{
> > +  int vla[n], i;
> > +
> > +  for (i = 0; i < n; i++)
> > +    vla[i] = i;
> > +
> > +  return n;                 /* vla-filled */
> > +}
> > +
> > +int main ()
> 
> Rewrite:
> 
> int
> main (void)
> 
> > +{
> > +  func (5);
> > +
> > +  return 0;
> > +}
> > --
> > 1.8.4.2
> 
> --
> Joel
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052


^ permalink raw reply	[flat|nested] 45+ messages in thread

* RE: [PATCH v5 09/15] vla: resolve dynamic bounds if value contents is a constant byte-sequence
  2014-02-28 17:09   ` Joel Brobecker
@ 2014-03-12 13:40     ` Agovic, Sanimir
  2014-03-13 16:00     ` Joel Brobecker
  1 sibling, 0 replies; 45+ messages in thread
From: Agovic, Sanimir @ 2014-03-12 13:40 UTC (permalink / raw)
  To: 'Joel Brobecker'; +Cc: tromey, Boell, Keven, gdb-patches

Thanks for your review.

 -Sanimir

> Would you mind explaining this change a little more; perhaps using
> some example code would help me understand why we want to resolve
> dynamic types in this case (and also only in this case)?
> 
I added a test[1] for DW_AT_count attribute with the help of the 
dwarf assembler. I used const_value to embed the actual array data
into the debug information itself rather than having a location
in the inferior.

+           DW_TAG_variable {
+               {name array}
+               {type :$array_label}
+               {const_value hello DW_FORM_block1}
+           }

The test[1] initially failed because we ended up handling the
case LOC_CONST_BYTES which does not use value_at & friends and simply
copies the raw data into the value and thus the bounds never get
resolved.

     case LOC_CONST_BYTES:
+      if (is_dynamic_type (type))
+	/* Value is a constant byte-sequence and needs no memory access.  */
+	type = resolve_dynamic_type (type, /* Unused address.  */ 0);
       v = allocate_value (type);

In all other cases so far we call value_at (...) to construct a value
and therefore get the correct type/bounds.

[1] https://sourceware.org/ml/gdb-patches/2014-02/msg00100.html

 -Sanimir
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052


^ permalink raw reply	[flat|nested] 45+ messages in thread

* RE: [PATCH v5 08/15] vla: support for DW_AT_count
  2014-02-28 16:53   ` Joel Brobecker
@ 2014-03-12 13:51     ` Agovic, Sanimir
  2014-03-13 15:36       ` Joel Brobecker
  0 siblings, 1 reply; 45+ messages in thread
From: Agovic, Sanimir @ 2014-03-12 13:51 UTC (permalink / raw)
  To: 'Joel Brobecker'; +Cc: tromey, Boell, Keven, gdb-patches

Thanks for your review.

> Overall, the patch looks OK to me, but I'd rather we be consistent
> with what we've been doing with other type flags, and use a bitfield
> instead. I think that'll simplify your patch a bit.
> 
I`m using bitfields now but they are still part of the struct range_bounds
and not struct main_type as they are specific to arrays and not types in
general.

 -Sanimir
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 08/15] vla: support for DW_AT_count
  2014-03-12 13:51     ` Agovic, Sanimir
@ 2014-03-13 15:36       ` Joel Brobecker
  0 siblings, 0 replies; 45+ messages in thread
From: Joel Brobecker @ 2014-03-13 15:36 UTC (permalink / raw)
  To: Agovic, Sanimir; +Cc: tromey, Boell, Keven, gdb-patches

> I`m using bitfields now but they are still part of the struct range_bounds
> and not struct main_type as they are specific to arrays and not types in
> general.

Thanks, Sanimir. That sounds good to me.

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 09/15] vla: resolve dynamic bounds if value contents is a constant byte-sequence
  2014-02-28 17:09   ` Joel Brobecker
  2014-03-12 13:40     ` Agovic, Sanimir
@ 2014-03-13 16:00     ` Joel Brobecker
  2014-03-19 15:35       ` Agovic, Sanimir
  1 sibling, 1 reply; 45+ messages in thread
From: Joel Brobecker @ 2014-03-13 16:00 UTC (permalink / raw)
  To: Sanimir Agovic; +Cc: tromey, keven.boell, gdb-patches

> > 2013-11-26  Sanimir Agovic  <sanimir.agovic@intel.com>
> >             Keven Boell  <keven.boell@intel.com>
> > 
> > 	* findvar.c (default_read_var_value): Resolve dynamic bounds if location
> > 	points to a constant blob.
> 
> Would you mind explaining this change a little more; perhaps using
> some example code would help me understand why we want to resolve
> dynamic types in this case (and also only in this case)?

I see. It took me a while to understand what you are saying, but
I do, now. It's one of these situations where it's almost a shame
that some case branches return, while others don't, and fallback
on something that happens to take care of dynamicity. Oh well, I have
no better proposal at the moment, so the current approach is fine
with me.

Question for you:  Shouldn't we be doing the same for LOC_CONST?

Thank you,

> >  gdb/findvar.c | 3 +++
> >  1 file changed, 3 insertions(+)
> > 
> > diff --git a/gdb/findvar.c b/gdb/findvar.c
> > index ec6afd6..a543dc4 100644
> > --- a/gdb/findvar.c
> > +++ b/gdb/findvar.c
> > @@ -468,6 +468,9 @@ default_read_var_value (struct symbol *var, struct frame_info *frame)
> >        return v;
> >  
> >      case LOC_CONST_BYTES:
> > +      if (is_dynamic_type (type))
> > +	/* Value is a constant byte-sequence and needs no memory access.  */
> > +	type = resolve_dynamic_type (type, /* Unused address.  */ 0);
> >        v = allocate_value (type);
> >        memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var),
> >  	      TYPE_LENGTH (type));
> > -- 
> > 1.8.4.2
> 
> -- 
> Joel

-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* RE: [PATCH v5 10/15] vla: evaluate operand of sizeof if its type is a vla
  2014-02-28 17:37   ` Joel Brobecker
@ 2014-03-19 12:55     ` Agovic, Sanimir
  2014-03-19 15:12       ` Joel Brobecker
  0 siblings, 1 reply; 45+ messages in thread
From: Agovic, Sanimir @ 2014-03-19 12:55 UTC (permalink / raw)
  To: 'Joel Brobecker'; +Cc: tromey, Boell, Keven, gdb-patches

Thanks for your review.

> >  1| int vla[n][m];
> >  2| int i = 1;
> >  3| sizeof(vla[i++][0]); // No sideffect
> >  4| assert (i == 1);
> >  5| sizeof(vla[i++]);    // With sideffect
> >  6| assert (i == 2);
> 
> Not knowing C that well, I don't understand why the first one
> does not have any side effect, while the second does. Can you
> explain?  This will also help explain the implementation, as
> I don't understand the logic yet.
> 
If the operand passed to sizeof evaluates to a variable length array type then C99
requires that the size of the operand is evaluated at runtime (otherwise at compile
time).

1| int vla[n][m];

sizeof(vla[0])      // Operand type is a variable length type, size is evaluated at runtime
sizeof(vla[0][0])   // Operand type is an int, size is evaluated at compile time 

If the expression contains a side effects it is evaluated too

sizeof(vla[i++])    // i gets modified as the operand is evaluated at runtime
sizeof(vla[i++][0]) // no modifications, operand type evaluates to int

The C99 chapter about sizeof is "6.5.3.4 The sizeof operator".

I addressed all of your issues below.

 -Sanimir

> > 2014-02-05  Sanimir Agovic  <sanimir.agovic@intel.com>
> >             Keven Boell <keven.boell@intel.com>
> >
> > 	* eval.c (evaluate_subexp_for_sizeof): Add enum noside argument.
> > 	(evaluate_subexp_standard): Pass noside argument.
> > 	(evaluate_subexp_for_sizeof) <BINOP_SUBSCRIPT>: Handle subscript case
> > 	if noside equals EVAL_NORMAL. If the subscript yields a vla type
> > 	re-evaluate subscript operation with EVAL_NORMAL to enable sideffects.
> > 	* gdbtypes.c (resolve_dynamic_bounds): Mark bound as evaluated.
> > 	* gdbtypes.h (enum range_flags): Add RANGE_EVALUATED case.
> >
> > testsuite/gdb.base/
> >
> > 	* vla-sideeffect.c: New file.
> > 	* vla-sideeffect.exp: New file.
> 
> My comments below.
> 
> >
> >
> > Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
> > ---
> >  gdb/eval.c                                | 40 ++++++++++++--
> >  gdb/gdbtypes.c                            |  1 +
> >  gdb/gdbtypes.h                            |  3 +-
> >  gdb/testsuite/gdb.base/vla-sideeffect.c   | 42 +++++++++++++++
> >  gdb/testsuite/gdb.base/vla-sideeffect.exp | 88 +++++++++++++++++++++++++++++++
> >  5 files changed, 170 insertions(+), 4 deletions(-)
> >  create mode 100644 gdb/testsuite/gdb.base/vla-sideeffect.c
> >  create mode 100644 gdb/testsuite/gdb.base/vla-sideeffect.exp
> >
> > diff --git a/gdb/eval.c b/gdb/eval.c
> > index b3e45ca..7a34b95 100644
> > --- a/gdb/eval.c
> > +++ b/gdb/eval.c
> > @@ -51,7 +51,8 @@ extern int overload_resolution;
> >
> >  /* Prototypes for local functions.  */
> >
> > -static struct value *evaluate_subexp_for_sizeof (struct expression *, int *);
> > +static struct value *evaluate_subexp_for_sizeof (struct expression *, int *,
> > +						 enum noside);
> >
> >  static struct value *evaluate_subexp_for_address (struct expression *,
> >  						  int *, enum noside);
> > @@ -2563,7 +2564,7 @@ evaluate_subexp_standard (struct type *expect_type,
> >  	  evaluate_subexp (NULL_TYPE, exp, pos, EVAL_SKIP);
> >  	  goto nosideret;
> >  	}
> > -      return evaluate_subexp_for_sizeof (exp, pos);
> > +      return evaluate_subexp_for_sizeof (exp, pos, noside);
> >
> >      case UNOP_CAST:
> >        (*pos) += 2;
> > @@ -3000,7 +3001,8 @@ evaluate_subexp_with_coercion (struct expression *exp,
> >     Advance *POS over the subexpression.  */
> >
> >  static struct value *
> > -evaluate_subexp_for_sizeof (struct expression *exp, int *pos)
> > +evaluate_subexp_for_sizeof (struct expression *exp, int *pos,
> > +			    enum noside noside)
> 
> Can you also update the function's introductory comment to document
> the new parameter?
> 
Done

> >  {
> >    /* FIXME: This should be size_t.  */
> >    struct type *size_type = builtin_type (exp->gdbarch)->builtin_int;
> > @@ -3054,6 +3056,38 @@ evaluate_subexp_for_sizeof (struct expression *exp, int *pos)
> >        return
> >  	value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
> >
> > +    case BINOP_SUBSCRIPT:
> > +      if (noside == EVAL_NORMAL)
> > +	{
> 
> This deserves a comment explaining why you do what you in EVAL_NORMAL
> mode.  Probably something along the lines of the answer to the question
> I asked above. Especially the bits I marked as [1] below...
> 
> 
I will try, please have a look at the upcoming v6.

> > +	  int oldpos = *pos;
> > +
> > +	  (*pos) += 1;
> > +	  val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
> > +	  *pos = oldpos;
> > +	  noside = EVAL_AVOID_SIDE_EFFECTS;
> 
> It would be easier, I think, to have a temporary like you do, and pass
> that temporary as the position to evaluate_subexp.  You'd then not
> have to restore POS afterwards.
> 
> Also, I don't think you need to set noside to EVAL_AVOID_SIDE_EFFECTS
> since you're not using it other than in your initial mode check.
> 
Both done.

> > +
> > +	  type = check_typedef (value_type (val));
> > +	  if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
> > +	    {
> > +	      type = check_typedef (TYPE_TARGET_TYPE (type));
> > +	      if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
> > +		{
> > +		  type = TYPE_INDEX_TYPE (type);
> > +		  if ((TYPE_RANGE_DATA (type)->flags & RANGE_EVALUATED)
> > +		      == RANGE_EVALUATED)
> > +		    {
> 
> [1] (see reference to this above).
> 
> > +		      val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_NORMAL);
> > +		      return value_from_longest
> > +			(size_type, (LONGEST)TYPE_LENGTH (value_type (val)));
> > +		    }
> > +		}
> > +	    }
> > +	}
> > +
> > +      val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
> > +      return value_from_longest (size_type,
> > +				 (LONGEST)TYPE_LENGTH (value_type (val)));
> 
> Formatting: Space after "(LONGEST)". But I suggest intead falling
> through to the default: case below. Just add a command mentioning
> that you are doing it intentionally. Eg:
> 
>         /* Fall through.  */
> 
Done.

> 
> > +
> >      default:
> >        val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
> >        return value_from_longest (size_type,
> > diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
> > index 83a2c75..67aa439 100644
> > --- a/gdb/gdbtypes.c
> > +++ b/gdb/gdbtypes.c
> > @@ -1697,6 +1697,7 @@ resolve_dynamic_bounds (struct type *type, CORE_ADDR addr)
> >      = create_range_type (NULL,
> >  			 TYPE_TARGET_TYPE (range_type),
> >  			 &low_bound, &high_bound);
> > +  TYPE_RANGE_DATA (range_type)->flags |= RANGE_EVALUATED;
> >    array_type = create_array_type (copy_type (type),
> >  				  array_type,
> >  				  range_type);
> > diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
> > index 100e3f4..4e92d4a 100644
> > --- a/gdb/gdbtypes.h
> > +++ b/gdb/gdbtypes.h
> > @@ -396,7 +396,8 @@ struct dynamic_prop
> >
> >  enum range_flags
> >  {
> > -  RANGE_UPPER_BOUND_IS_COUNT = 1 /* High bound contains number of elements.  */
> > +  RANGE_UPPER_BOUND_IS_COUNT = 1, /* High bound contains number of elements.  */
> > +  RANGE_EVALUATED                 /* Bound was dynamic.  */
> 
> Same as in one of the previous patches. I think a bit component would
> be better.. I also would like the comment to be a little more
> elaborated: What does it mean when the flag is set vs unset?
> 
Done.

> >  };
> >
> >  /* Determine which field of the union main_type.fields[x].loc is used.  */
> > diff --git a/gdb/testsuite/gdb.base/vla-sideeffect.c b/gdb/testsuite/gdb.base/vla-
> sideeffect.c
> > new file mode 100644
> > index 0000000..29ee99b
> > --- /dev/null
> > +++ b/gdb/testsuite/gdb.base/vla-sideeffect.c
> > @@ -0,0 +1,42 @@
> > +/* This testcase is part of GDB, the GNU debugger.
> > +
> > +   Copyright 2014 Free Software Foundation, Inc.
> > +
> > +   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 <stddef.h>
> > +#define SIZE 10
> > +
> > +int
> > +main ()
> 
> Add "void" as param here, please.
> 
Done.
> > +{
> > +  int n = SIZE;
> > +  int i = 0;
> > +  int j = 0;
> > +  int vla2[SIZE][n];
> > +  int vla1[n];
> > +
> > +  for (i = 0; i < n; i++)
> > +    vla1[i] = (i * 2) + n;
> > +
> > +  for (i = 0; i < SIZE; i++)
> > +    for (j = 0; j < n; j++)
> > +      vla2[i][j] = (i + j) + n;
> > +
> > +
> > +  i = 0;
> > +  j = 0;
> > +
> > +  return 0;           /* vla-filled */
> > +}
> > diff --git a/gdb/testsuite/gdb.base/vla-sideeffect.exp b/gdb/testsuite/gdb.base/vla-
> sideeffect.exp
> > new file mode 100644
> > index 0000000..0ea9bc2
> > --- /dev/null
> > +++ b/gdb/testsuite/gdb.base/vla-sideeffect.exp
> > @@ -0,0 +1,88 @@
> > +# Copyright 2014 Free Software Foundation, Inc.
> > +
> > +# 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/>.
> > +
> > +# Tests sideffect of sizeof evaluation.
>            ^^^^^^^^^
> side-effects
> 
Done.

> > +# Based on gcc/testsuite/gcc.dg/vla-4.c; vla-15.c
> > +
> > +standard_testfile ".c"
> 
> The ".c" shouldn't be necessary. Can you remove it?
> 
Done.

> > +if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
> > +    return -1
> > +}
> > +
> > +if ![runto_main] {
> > +    return -1
> > +}
> > +
> > +gdb_breakpoint [gdb_get_line_number "vla-filled"]
> > +gdb_continue_to_breakpoint "vla-filled"
> > +
> > +# Check side effects for sizeof argument.
> > +set sizeof_int [get_sizeof "int" 4]
> > +set sizeof_vla [ expr "10" * "$sizeof_int" ]
> > +
> > +gdb_test "print sizeof (vla1\[i++\])" "\\$\\d+ = ${sizeof_int}" \
> 
> You don't need to match the $N part of the output, we've traditionally
> saved us the trouble, but simply using: " = ${sizeof_int}"
> 
> Can you adjust the testcase throughout?
> 
Done.

> > +         "print sizeof (vla1\[i++\])"
> > +gdb_test "print i" "\\$\\d+ = 0" \
> > +         "print i - sizeof no side effects"
> > +
> > +gdb_test "print sizeof (++vla1\[0\])" "\\$\\d+ = ${sizeof_int}" \
> > +         "print sizeof (++vla1\[0\])"
> > +gdb_test "print vla1\[0\]" "\\$\\d+ = 10" \
> > +         "print vla1\[0\] - sizeof no side effects"
> > +
> > +gdb_test "ptype ++vla1\[0\]" "type = int" "ptype ++vla1\[0\]"
> > +gdb_test "print vla1\[0\]" "\\$\\d+ = 10" \
> > +         "print vla1\[0\] - ptype no side effects"
> > +
> > +gdb_test "whatis ++vla1\[0\]" "type = int" "whatis ++vla1\[0\]"
> > +gdb_test "print vla1\[0\]" "\\$\\d+ = 10" \
> > +         "print vla1\[0\] - whatis no side effects"
> > +
> > +
> > +gdb_test "print sizeof (vla2\[i++\])" "\\$\\d+ = ${sizeof_vla}" \
> > +         "print sizeof (vla2\[i++\])"
> > +gdb_test "print i" "\\$\\d+ = 1" \
> > +         "print i - sizeof with side effects (1)"
> > +
> > +gdb_test "print sizeof (vla2\[i++ + sizeof(j++)\])" "\\$\\d+ = ${sizeof_vla}" \
> > +         "print sizeof (vla2\[i++ + sizeof(j++)\])"
> > +gdb_test "print i" "\\$\\d+ = 2" \
> > +         "print i - sizeof with side effects (2)"
> > +gdb_test "print j" "\\$\\d+ = 0" \
> > +         "print j - sizeof with no side effects"
> > +
> > +gdb_test "ptype vla2\[i++\]" "type = int \\\[10\\\]" \
> > +         "ptype vla2\[i++\]"
> > +gdb_test "print i" "\\$\\d+ = 2" \
> > +         "print i - ptype with side effects (1)"
> > +
> > +gdb_test "ptype vla2\[i++ + sizeof(j++)\]" "type = int \\\[10\\\]" \
> > +         "ptype vla2\[i++ + sizeof(j++)\]"
> > +gdb_test "print i" "\\$\\d+ = 2" \
> > +         "print i - ptype with side effects (2)"
> > +gdb_test "print j" "\\$\\d+ = 0" \
> > +         "print j - ptype with no side effects"
> > +
> > +gdb_test "whatis vla2\[i++\]" "type = int \\\[10\\\]" \
> > +         "whatis vla2\[i++\]"
> > +gdb_test "print i" "\\$\\d+ = 2" \
> > +         "print i - whatis with side effects (1)"
> > +
> > +gdb_test "whatis vla2\[i++ + sizeof(j++)\]" "type = int \\\[10\\\]" \
> > +         "whatis vla2\[i++ + sizeof(j++)\]"
> > +gdb_test "print i" "\\$\\d+ = 2" \
> > +         "print i - whatis with side effects (2)"
> > +gdb_test "print j" "\\$\\d+ = 0" \
> > +         "print j - whatis with no side effects"
> > --
> > 1.8.4.2
> 
> --
> Joel
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 10/15] vla: evaluate operand of sizeof if its type is a vla
  2014-03-19 12:55     ` Agovic, Sanimir
@ 2014-03-19 15:12       ` Joel Brobecker
  0 siblings, 0 replies; 45+ messages in thread
From: Joel Brobecker @ 2014-03-19 15:12 UTC (permalink / raw)
  To: Agovic, Sanimir; +Cc: tromey, Boell, Keven, gdb-patches

> If the operand passed to sizeof evaluates to a variable length array
> type then C99 requires that the size of the operand is evaluated at
> runtime (otherwise at compile time).
> 
> 1| int vla[n][m];
> 
> sizeof(vla[0])      // Operand type is a variable length type, size is evaluated at runtime
> sizeof(vla[0][0])   // Operand type is an int, size is evaluated at compile time 
> 
> If the expression contains a side effects it is evaluated too
> 
> sizeof(vla[i++])    // i gets modified as the operand is evaluated at runtime
> sizeof(vla[i++][0]) // no modifications, operand type evaluates to int

Very interesting! I guess whoever is writing ...

    sizeof(vla[i++][0])

... instead of ...

    sizeof(vla[i + 1][0])

... is trying to shoot himself in the foot!

Thanks for the explanation. I confess that the C RM is often somewhat
obscure to me.

> I addressed all of your issues below.

Thanks! I look forward to v6 :). Hopefully that'll be the final
iteration. FYI: I have one patch already that's dependent on your patch
series, and it has to do with handling of "ptype dynamic_sized_array"
in Ada.

Thanks!
-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

* RE: [PATCH v5 09/15] vla: resolve dynamic bounds if value contents is a constant byte-sequence
  2014-03-13 16:00     ` Joel Brobecker
@ 2014-03-19 15:35       ` Agovic, Sanimir
  0 siblings, 0 replies; 45+ messages in thread
From: Agovic, Sanimir @ 2014-03-19 15:35 UTC (permalink / raw)
  To: 'Joel Brobecker'; +Cc: tromey, Boell, Keven, gdb-patches

Thanks for your review.

> I see. It took me a while to understand what you are saying, but
> I do, now. It's one of these situations where it's almost a shame
> that some case branches return, while others don't, and fallback
> on something that happens to take care of dynamicity. Oh well, I have
> no better proposal at the moment, so the current approach is fine
> with me.
> 
> Question for you:  Shouldn't we be doing the same for LOC_CONST?
> 
Good catch, indeed we should. I have updated the patch to cover
LOC_CONST and added a test-case as well. Thanks again.

 -Sanimir

Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052


^ permalink raw reply	[flat|nested] 45+ messages in thread

* RE: [PATCH v5 03/15] type: add c99 variable length array support
  2014-02-28 16:27   ` Joel Brobecker
@ 2014-04-08  6:41     ` Agovic, Sanimir
  2014-04-08 12:49       ` Joel Brobecker
  0 siblings, 1 reply; 45+ messages in thread
From: Agovic, Sanimir @ 2014-04-08  6:41 UTC (permalink / raw)
  To: 'Joel Brobecker'; +Cc: gdb-patches

Thanks for your review.

Seems like some code and comments were not adjusted after the migrating
from deep copying type to only array/range/typdef copies. I removed not
needed code and adjusted the comments to reflect the actual code.
Thanks a lot for pointing out.

I addressed all issues (see below) except for these two:

> > +  if (!attr_to_dynamic_prop (attr, die, cu, &high))
> >      {
> >        attr = dwarf2_attr (die, DW_AT_count, cu);
> >        if (attr)
> 
> I know that in the testcase you are trying to support, the bounds
> are necessarily starting at zero and therefore constant/non-dynamic.
> But can you modify the function to also handle the DW_AT_lower_bound
> the same way? Other languages such as Ada will need that also, and
> that seems like the logical time to be doing it.
>
The motivation behind the c99 patch series is to introduce the core concept
of dynamic properties and thus we like to keep it small. Based on that work
the Fortran patch series will fill the gap.

> > +int
> > +is_dynamic_type (const struct type *type)
> > +{
> > +  if (TYPE_CODE (type) == TYPE_CODE_ARRAY
> > +      && TYPE_NFIELDS (type) == 1)
> > +    {
> > +      const struct type *range_type = TYPE_INDEX_TYPE (type);
> > +
> > +      if (!has_static_range (TYPE_RANGE_DATA (range_type)))
> > +	return 1;
> > +    }
> > +
> > +  if (TYPE_CODE (type) == TYPE_CODE_ARRAY
> > +      || TYPE_CODE (type) == TYPE_CODE_PTR
> > +      || TYPE_CODE (type) == TYPE_CODE_REF
> > +      || TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
> > +    return is_dynamic_type (check_typedef (TYPE_TARGET_TYPE (type)));
> As discussed on IRC, I think that TYPE_NFIELDS should always
> be 1 for TYPE_CODE_ARRAY. So let's transform that into an assert,
> if you don't mind, and see what happens?
> Can you explain why you included TYPE_CODE_PTR in the list?
>
> This is not clear to me based on the function's description.
> The risk I see with this is trying to print the value of a pointer
> to a dynamic array - the printing really only needs to display
> the address, and not resolve the underlying array. Also, from
> a logical standpoint, pointers are not dynamic types.
>
I may remove the pointer chasing from the patch series, but this means
we won't support the following feature:

  1| int foo(int vla[n][m])

  (gdb) ptype vla
  type = int (*)[] 
  (gdb) print vla[0]
  Cannot perform pointer math on incomplete types, try casting to a known type, or void *.

So we included TYPE_CODE_PTR to support such use case. 

> > +
> > +static struct type *
> > +resolve_dynamic_bounds (struct type *type, CORE_ADDR addr)
> > +{
> > +  CORE_ADDR value;
> > +  struct type *array_type;
> > +  struct type *range_type;
> > +  struct type *ary_dim;
> > +  const struct dynamic_prop *prop;
> > +  const struct dwarf2_locexpr_baton *baton;
> > +  struct dynamic_prop low_bound, high_bound;
> > +
> > +  if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF
> > +      || TYPE_CODE (type) == TYPE_CODE_PTR)
> > +    {
> > +      struct type *copy = copy_type (type);
> > +
> > +      TYPE_TARGET_TYPE (copy)
> > +	= resolve_dynamic_bounds (TYPE_TARGET_TYPE (type), addr);
> > +
> > +      return copy;
> > +    }
> 
> Same remark as above for the handling of typedefs. I think this will
> help avoid an unnecessary type copy.
> 
> Also, same question about handling pointers. Why do it here?
> 
We need to copy typedef to preserve the correct typename otherwise we
end up with the real type. The reasoning behind TYPE_CODE_PTR is pretty
much the same as for the above case.

 -Sanimir

> -----Original Message-----
> From: Joel Brobecker [mailto:brobecker@adacore.com]
> Sent: Friday, February 28, 2014 05:27 PM
> To: Agovic, Sanimir
> Cc: tromey@redhat.com; Boell, Keven; gdb-patches@sourceware.org
> Subject: Re: [PATCH v5 03/15] type: add c99 variable length array support
> 
> Hi Sanimir,
> 
> > 2013-10-18  Sanimir Agovic  <sanimir.agovic@intel.com>
> >             Keven Boell  <keven.boell@intel.com>
> >
> > 	* dwarf2loc.c (dwarf2_locexpr_baton_eval): New function.
> > 	(dwarf2_evaluate_property): New function.
> > 	* dwarf2loc.h (dwarf2_evaluate_property): New function prototype.
> > 	* dwarf2read.c (attr_to_dynamic_prop): New function.
> > 	(read_subrange_type): Use attr_to_dynamic_prop to read high bound
> > 	attribute.
> > 	* gdbtypes.c: Include dwarf2loc.h.
> > 	(is_dynamic_type): New function.
> > 	(resolve_dynamic_type): New function.
> > 	(resolve_dynamic_bounds): New function.
> > 	(get_type_length): New function.
> > 	(check_typedef): Use get_type_length to compute type length.
> > 	* gdbtypes.h (TYPE_HIGH_BOUND_KIND): New macro.
> > 	(TYPE_LOW_BOUND_KIND): New macro.
> > 	(is_dynamic_type): New function prototype.
> > 	* value.c (value_from_contents_and_address): Call resolve_dynamic_type
> > 	to resolve dynamic properties of the type. Update comment.
> > 	* valops.c (get_value_at, value_at, value_at_lazy): Update comment.
> 
> Tough review (took a while). Some questions and comments, but nothing
> too serious. See below.
> 
> I apologize in advance if I appear to nit-pick - I only allow myself to
> do so when touching the patch for other reasons too.  Thank you!
> 
> > Signed-off-by: Sanimir Agovic <sanimir.agovic@intel.com>
> > ---
> >  gdb/dwarf2loc.c  | 120 +++++++++++++++++++++++++
> >  gdb/dwarf2loc.h  |  24 +++++
> >  gdb/dwarf2read.c | 100 +++++++++++++++------
> >  gdb/gdbtypes.c   | 264 ++++++++++++++++++++++++++++++++++++++++++++-----------
> >  gdb/gdbtypes.h   |  10 +++
> >  gdb/valops.c     |  12 ++-
> >  gdb/value.c      |  17 ++--
> >  7 files changed, 459 insertions(+), 88 deletions(-)
> >
> > diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
> > index 2b1f323..72bc727 100644
> > --- a/gdb/dwarf2loc.c
> > +++ b/gdb/dwarf2loc.c
> > @@ -2431,6 +2431,126 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info
> *frame,
> >    return dwarf2_evaluate_loc_desc_full (type, frame, data, size, per_cu, 0);
> >  }
> >
> > +/* Evaluates a dwarf expression and stores the result in VAL, expecting
> > +   that the dwarf expression only produces a single CORE_ADDR.  ADDR is a
> > +   context (location of a variable) and might be needed to evaluate the
> > +   location expression.
> > +   Returns 1 on success, 0 otherwise.   */
> > +
> > +static int
> > +dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
> > +			   CORE_ADDR addr, CORE_ADDR *valp)
> > +{
> > +  struct dwarf_expr_context *ctx;
> > +  struct dwarf_expr_baton baton;
> > +  struct objfile *objfile;
> > +  struct cleanup *cleanup;
> > +
> > +  if (dlbaton == NULL || dlbaton->size == 0)
> > +    return 0;
> > +
> > +  ctx = new_dwarf_expr_context ();
> > +  cleanup = make_cleanup_free_dwarf_expr_context (ctx);
> > +
> > +  baton.frame = get_selected_frame (NULL);
> > +  baton.per_cu = dlbaton->per_cu;
> > +
> > +  objfile = dwarf2_per_cu_objfile (dlbaton->per_cu);
> > +
> > +  ctx->gdbarch = get_objfile_arch (objfile);
> > +  ctx->addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu);
> > +  ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (dlbaton->per_cu);
> > +  ctx->offset = dwarf2_per_cu_text_offset (dlbaton->per_cu);
> > +  ctx->funcs = &dwarf_expr_ctx_funcs;
> > +  ctx->baton = &baton;
> > +
> > +  dwarf_expr_eval (ctx, dlbaton->data, dlbaton->size);
> > +
> > +  switch (ctx->location)
> > +    {
> > +    case DWARF_VALUE_REGISTER:
> > +    case DWARF_VALUE_MEMORY:
> > +    case DWARF_VALUE_STACK:
> > +      *valp = dwarf_expr_fetch_address (ctx, 0);
> > +      if (ctx->location == DWARF_VALUE_REGISTER)
> > +	*valp = dwarf_expr_read_addr_from_reg (&baton, *valp);
> > +      do_cleanups (cleanup);
> > +      return 1;
> > +    case DWARF_VALUE_LITERAL:
> > +      *valp = extract_signed_integer (ctx->data, ctx->len,
> > +				      gdbarch_byte_order (ctx->gdbarch));
> > +      do_cleanups (cleanup);
> > +      return 1;
> > +      /* Not supported dwarf values.  */
> > +    case DWARF_VALUE_OPTIMIZED_OUT:
> > +    case DWARF_VALUE_IMPLICIT_POINTER:
> 
> Would "Unsupported" be more idiomatic? I'm not a native English
> speaker, so I am not sure. But "unsupported" somehow sounds better.
> Feel free to choose either option.
> 
Chose "unsupported".

> > +      break;
> > +    }
> > +
> > +  do_cleanups (cleanup);
> > +
> > +  return 0;
> 
> Can you remove the empty line betwee do_cleanups and return?
> It's not very important, but compresses a bit the code, I think.
> 
Done.

> > +}
> > +
> > +/* See dwarf2loc.h.  */
> > +
> > +int
> > +dwarf2_evaluate_property (const struct dynamic_prop *prop, CORE_ADDR address,
> > +			  CORE_ADDR *value)
> > +{
> > +  if (prop == NULL)
> > +    return 0;
> > +
> > +  switch (prop->kind)
> > +    {
> > +    case PROP_LOCEXPR:
> > +      {
> > +	const struct dwarf2_property_baton *baton = prop->data.baton;
> > +
> > +	if (dwarf2_locexpr_baton_eval (&baton->locexpr, address, value))
> > +	  {
> > +	    if (baton->referenced_type)
> > +	      {
> > +		struct value *val = value_at (baton->referenced_type, *value);
> > +
> > +		*value = value_as_address (val);
> > +	      }
> > +	    return 1;
> > +	  }
> > +      }
> > +      break;
> > +
> > +    case PROP_LOCLIST:
> > +      {
> > +	struct dwarf2_property_baton *baton = prop->data.baton;
> > +	struct frame_info *frame = get_selected_frame (NULL);
> > +	CORE_ADDR pc = get_frame_address_in_block (frame);
> > +	const gdb_byte *data;
> > +	struct value *val;
> > +	size_t size;
> > +
> > +	data = dwarf2_find_location_expression (&baton->loclist, &size, pc);
> > +	if (data != NULL)
> > +	  {
> > +	    val = dwarf2_evaluate_loc_desc (baton->referenced_type, frame, data,
> > +					    size, baton->loclist.per_cu);
> > +	    if (!value_optimized_out (val))
> > +	      {
> > +		*value = value_as_address (val);
> > +		return 1;
> > +	      }
> > +	  }
> > +      }
> > +      break;
> > +
> > +    case PROP_CONST:
> > +      *value = prop->data.const_val;
> > +      return 1;
> > +    }
> > +
> > +  return 0;
> > +}
> > +
> >  

> >  /* Helper functions and baton for dwarf2_loc_desc_needs_frame.  */
> >
> > diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h
> > index 9bc8ca5..9be3e24 100644
> > --- a/gdb/dwarf2loc.h
> > +++ b/gdb/dwarf2loc.h
> > @@ -90,6 +90,13 @@ struct value *dwarf2_evaluate_loc_desc (struct type *type,
> >  					size_t size,
> >  					struct dwarf2_per_cu_data *per_cu);
> >
> > +/* Converts a dynamic property into a static one.  ADDR is the address of
> > +   the object currently being evaluated and might be nedded.
> > +   Returns 1 if PROP could be converted and the static value is passed back
> > +   into VALUE, otherwise returns 0.  */
> > +int dwarf2_evaluate_property (const struct dynamic_prop *prop,
> > +			      CORE_ADDR addr, CORE_ADDR *value);
> > +
> 
> Would you mind adding an empty line betwee documentation and
> declaration? It's a bit of a nit-pick, but since we're adjusting
> this patch, we might as well.
> 
Done.

> >  CORE_ADDR dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
> >  				  unsigned int addr_index);
> >
> > @@ -135,6 +142,23 @@ struct dwarf2_loclist_baton
> >    unsigned char from_dwo;
> >  };
> >
> > +/* A dynamic property is either expressed as a single location expression
> > +   or a location list in the context of TYPE.  */
> > +
> > +struct dwarf2_property_baton
> > +{
> > +  /* Keep track of referenced type.  */
> > +  struct type *referenced_type;
> 
> Can you explain in this comment what the referenced type is?
> If it helps, giving an example could be used.
> 
Done, see my inlined my changes:
-- >8 --
diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h
index 644c546..bcc02694 100644
--- a/gdb/dwarf2loc.h
+++ b/gdb/dwarf2loc.h
@@ -144,13 +144,14 @@ struct dwarf2_loclist_baton
 };

 /* A dynamic property is either expressed as a single location expression
-   or a location list. If the property is a reference store its targeted
-   type in TYPE.  */
+   or a location list. If the property is an indirection, pointing to
+   another die, keep track of the targeted type in REFERENCED_TYPE.  */

 struct dwarf2_property_baton
 {
-  /* A property might reference another die. In this case we need to create
-     a value of type REFERENCED_TYPE; otherwise NULL.  */
+  /* If the property is an indirection, we need to evaluate the location
+     LOCEXPR or LOCLIST in the context of the type REFERENCED_TYPE.
+     If NULL, the location is the actual value of the property.  */
   struct type *referenced_type;
   union
   {


> > +  union
> > +  {
> > +    /* Location expression.  */
> > +    struct dwarf2_locexpr_baton locexpr;
> > +
> > +    /* Location list to be evaluated in the context of TYPE.  */
> > +    struct dwarf2_loclist_baton loclist;
> > +  };
> > +};
> > +
> >  extern const struct symbol_computed_ops dwarf2_locexpr_funcs;
> >  extern const struct symbol_computed_ops dwarf2_loclist_funcs;
> >
> > diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
> > index 101065b..1d5fa3d 100644
> > --- a/gdb/dwarf2read.c
> > +++ b/gdb/dwarf2read.c
> > @@ -14252,6 +14252,78 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
> >    return set_die_type (die, type, cu);
> >  }
> >
> > +/* Parse dwarf attribute if it's a block, reference or constant and put the
> > +   resulting value of the attribute into struct bound_prop.
> > +   Returns 1 if ATTR could be resolved into PROP, 0 otherwise.  */
> > +
> > +static int
> > +attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die,
> > +		      struct dwarf2_cu *cu, struct dynamic_prop *prop)
> > +{
> > +  struct dwarf2_property_baton *baton;
> > +  struct obstack *obstack = &cu->objfile->objfile_obstack;
> > +
> > +  if (attr == NULL || prop == NULL)
> > +    return 0;
> > +
> > +  if (attr_form_is_block (attr))
> > +    {
> > +      baton = obstack_alloc (obstack, sizeof (*baton));
> > +      baton->referenced_type = NULL;
> > +      baton->locexpr.per_cu = cu->per_cu;
> > +      baton->locexpr.size = DW_BLOCK (attr)->size;
> > +      baton->locexpr.data = DW_BLOCK (attr)->data;
> > +      prop->data.baton = baton;
> > +      prop->kind = PROP_LOCEXPR;
> > +      gdb_assert (prop->data.baton != NULL);
> > +    }
> > +  else if (attr_form_is_ref (attr))
> > +    {
> > +      struct dwarf2_cu *target_cu = cu;
> > +      struct die_info *target_die;
> > +      struct attribute *target_attr;
> > +
> > +      target_die = follow_die_ref (die, attr, &target_cu);
> > +      target_attr = dwarf2_attr (target_die, DW_AT_location, target_cu);
> > +      if (target_attr == NULL)
> > +	return 0;
> > +
> > +      if (attr_form_is_section_offset (target_attr))
> > +	{
> > +	  baton = obstack_alloc (obstack, sizeof (*baton));
> > +	  baton->referenced_type = die_type (target_die, target_cu);
> > +	  fill_in_loclist_baton (cu, &baton->loclist, target_attr);
> > +	  prop->data.baton = baton;
> > +	  prop->kind = PROP_LOCLIST;
> > +	  gdb_assert (prop->data.baton != NULL);
> > +	}
> > +      else if (attr_form_is_block (target_attr))
> > +	{
> > +	  baton = obstack_alloc (obstack, sizeof (*baton));
> > +	  baton->referenced_type = die_type (target_die, target_cu);
> > +	  baton->locexpr.per_cu = cu->per_cu;
> > +	  baton->locexpr.size = DW_BLOCK (target_attr)->size;
> > +	  baton->locexpr.data = DW_BLOCK (target_attr)->data;
> > +	  prop->data.baton = baton;
> > +	  prop->kind = PROP_LOCEXPR;
> > +	  gdb_assert (prop->data.baton != NULL);
> > +	}
> 
> It looks like, if TARGET_ATTR is neither a section offset
> nor a block, you're getting through to the "return 1" at the end
> of the function even though you've haven't set PROP. From my
> reading of the DWARF v4 standard, DW_AT_location attributes
> should not have any other forms, but let's protect ourselves
> against it. 
>
> I would add a complaint and then return 0.
> 
Done.

> > +    }
> > +  else if (attr_form_is_constant (attr))
> > +    {
> > +      prop->data.const_val = dwarf2_get_attr_constant_value (attr, 0);
> > +      prop->kind = PROP_CONST;
> > +    }
> > +  else
> > +    {
> > +      dwarf2_invalid_attrib_class_complaint (dwarf_form_name (attr->form),
> > +					     dwarf2_name (die, cu));
> > +      return 0;
> > +    }
> > +
> > +  return 1;
> > +}
> > +
> >  /* Read the given DW_AT_subrange DIE.  */
> >
> > @@ -14409,12 +14461,6 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
> >
> >    range_type = create_range_type (NULL, orig_base_type, &low, &high);
> >
> > -  /* Mark arrays with dynamic length at least as an array of unspecified
> > -     length.  GDB could check the boundary but before it gets implemented at
> > -     least allow accessing the array elements.  */
> > -  if (attr && attr_form_is_block (attr))
> > -    TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED;
> > -
> >    /* Ada expects an empty array on no boundary attributes.  */
> >    if (attr == NULL && cu->language != language_ada)
> >      TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED;
> > diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
> > index 7f0269c..f5bd236 100644
> > --- a/gdb/gdbtypes.c
> > +++ b/gdb/gdbtypes.c
> > @@ -853,6 +853,17 @@ create_static_range_type (struct type *result_type, struct type
> *index_type,
> >    return result_type;
> >  }
> >
> > +/* Predicate tests whether BOUNDS are static.  Returns 1 if all bounds values
> > +   are static, otherwise returns 0.  */
> > +
> > +static int
> > +has_static_range (const struct range_bounds *bounds)
> > +{
> > +  return (bounds->low.kind == PROP_CONST
> > +	  && bounds->high.kind == PROP_CONST);
> > +}
> > +
> > +
> >  /* Set *LOWP and *HIGHP to the lower and upper bounds of discrete type
> >     TYPE.  Return 1 if type is a range type, 0 if it is discrete (and
> >     bounds will fit in LONGEST), or -1 otherwise.  */
> > @@ -982,24 +993,28 @@ create_array_type (struct type *result_type,
> >  		   struct type *element_type,
> >  		   struct type *range_type)
> >  {
> > -  LONGEST low_bound, high_bound;
> > -
> >    if (result_type == NULL)
> >      result_type = alloc_type_copy (range_type);
> >
> >    TYPE_CODE (result_type) = TYPE_CODE_ARRAY;
> >    TYPE_TARGET_TYPE (result_type) = element_type;
> > -  if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
> > -    low_bound = high_bound = 0;
> > -  CHECK_TYPEDEF (element_type);
> > -  /* Be careful when setting the array length.  Ada arrays can be
> > -     empty arrays with the high_bound being smaller than the low_bound.
> > -     In such cases, the array length should be zero.  */
> > -  if (high_bound < low_bound)
> > -    TYPE_LENGTH (result_type) = 0;
> > -  else
> > -    TYPE_LENGTH (result_type) =
> > -      TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
> > +
> > +  if (has_static_range (TYPE_RANGE_DATA (range_type)))
> > +    {
> > +      LONGEST low_bound, high_bound;
> > +
> > +      if (get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
> > +	low_bound = high_bound = 0;
> > +      CHECK_TYPEDEF (element_type);
> > +      /* Be careful when setting the array length.  Ada arrays can be
> > +	 empty arrays with the high_bound being smaller than the low_bound.
> > +	 In such cases, the array length should be zero.  */
> > +      if (high_bound < low_bound)
> > +	TYPE_LENGTH (result_type) = 0;
> > +      else
> > +	TYPE_LENGTH (result_type) =
> > +	  TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
> > +    }
> >    TYPE_NFIELDS (result_type) = 1;
> >    TYPE_FIELDS (result_type) =
> >      (struct field *) TYPE_ZALLOC (result_type, sizeof (struct field));
> 
> Does it look like you might be leaving the TYPE_LENGTH undefined
> for the case of the non-static array index? (Eg when result_type
> is not passed as NULL).
> 
> It may not matter in practice, as we are probably supposed to ignore
> that field for those arrays anyway. But in the case we're not, leaving
> the length undefined could cause all sorts of nastiness. For instance,
> a struct value fetching its contents could allocate a buffer using
> that size, which potentially means randomly large memory regions,
> leading to a memory error, always very scary for the typical user.
> 
> Any objection to setting the length to 0 in this case?
> 
Set length to 0 as proposed.


> > @@ -1530,7 +1545,181 @@ stub_noname_complaint (void)
> >    complaint (&symfile_complaints, _("stub type has NULL name"));
> >  }
> >
> > -/* Find the real type of TYPE.  This function returns the real type,
> > +/* Calculates the size of a type.  If TYPE has static bound values takes upper
> > +   and lower bound into account, otherwise only the TYPE length is returned.
> > +   TYPE is expected not to be a typedef.  */
> 
> Would you mind explaining this part to me?
> 
> Intuitively, if it is an array with static bounds, then haven't we
> already set the correct array length during the call to "create_array_type"?
> And if the type is indeed dynamic, is the TYPE's TYPE_LENGTH correct?
> 
We moved from deep copying types to only copy the range/array types and forgot to
remove the get_type_length function which was needed in the former case. Removed
the code.

> > +
> > +static ULONGEST
> > +get_type_length (const struct type *type)
> > +{
> > +  const struct type *range_type, *target_type;
> > +  ULONGEST len = TYPE_LENGTH (type);
> > +  LONGEST low_bound, high_bound;
> > +
> > +  gdb_assert (TYPE_CODE (type) != TYPE_CODE_TYPEDEF);
> > +
> > +  if (TYPE_CODE (type) != TYPE_CODE_ARRAY
> > +      && TYPE_CODE (type) != TYPE_CODE_STRING)
> > +    return len;
> > +
> > +  range_type = check_typedef (TYPE_INDEX_TYPE (type));
> > +
> > +  if (!has_static_range (TYPE_RANGE_DATA (range_type)))
> > +    return len;
> > +
> > +  target_type = check_typedef (TYPE_TARGET_TYPE (type));
> > +
> > +  /* Now recompute the length of the array type, based on its
> > +     number of elements and the target type's length.
> > +     Watch out for Ada null Ada arrays where the high bound
> > +     is smaller than the low bound.  */
> > +  low_bound = TYPE_LOW_BOUND (range_type);
> > +  high_bound = TYPE_HIGH_BOUND (range_type);
> > +
> > +  if (high_bound < low_bound)
> > +    len = 0;
> > +  else
> > +    {
> > +      /* For now, we conservatively take the array length to be 0
> > +         if its length exceeds UINT_MAX.  The code below assumes
> > +         that for x < 0, (ULONGEST) x == -x + ULONGEST_MAX + 1,
> > +         which is technically not guaranteed by C, but is usually true
> > +         (because it would be true if x were unsigned with its
> > +         high-order bit on).  It uses the fact that
> > +         high_bound-low_bound is always representable in
> > +         ULONGEST and that if high_bound-low_bound+1 overflows,
> > +         it overflows to 0.  We must change these tests if we
> > +         decide to increase the representation of TYPE_LENGTH
> > +         from unsigned int to ULONGEST.  */
> > +      ULONGEST ulow = low_bound, uhigh = high_bound;
> > +      ULONGEST tlen = get_type_length (target_type);
> > +
> > +      len = tlen * (uhigh - ulow + 1);
> > +      if (tlen == 0 || (len / tlen - 1 + ulow) != uhigh || len > UINT_MAX)
> > +        len = 0;
> > +    }
> > +
> > +  return len;
> > +}
> > +
> > +/* See gdbtypes.h.  */
> > +
> > +int
> > +is_dynamic_type (const struct type *type)
> > +{
> > +  if (TYPE_CODE (type) == TYPE_CODE_ARRAY
> > +      && TYPE_NFIELDS (type) == 1)
> > +    {
> > +      const struct type *range_type = TYPE_INDEX_TYPE (type);
> > +
> > +      if (!has_static_range (TYPE_RANGE_DATA (range_type)))
> > +	return 1;
> > +    }
> > +
> > +  if (TYPE_CODE (type) == TYPE_CODE_ARRAY
> > +      || TYPE_CODE (type) == TYPE_CODE_PTR
> > +      || TYPE_CODE (type) == TYPE_CODE_REF
> > +      || TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
> > +    return is_dynamic_type (check_typedef (TYPE_TARGET_TYPE (type)));
> 
> As discussed on IRC, I think that TYPE_NFIELDS should always
> be 1 for TYPE_CODE_ARRAY. So let's transform that into an assert,
> if you don't mind, and see what happens?
> 
Added assert on nfields == 1.

> > +
> > +  return 0;
> > +}
> > +
> > +/* Resolves dynamic bound values of an array type to static ones.
> > +   TYPE is modified in place and is expected not to be a typedef.
> > +   ADDRESS might be needed to resolve the subrange bounds, it is the location
> > +   of the associated array.  */
> 
> In this description, you mention that TYPE is expected NOT to be
> a typedef, and yet the code tests for it...
> 
Modified the comment to reflect the actual code.

> 
> > +
> > +  gdb_assert (TYPE_CODE (type) == TYPE_CODE_ARRAY);
> > +
> > +  array_type = check_typedef (type);
> > +  range_type = check_typedef (TYPE_INDEX_TYPE (array_type));
> 
> If the assert above passed, you should not need the check_typedef
> on TYPE to get ARRAY_TYPE.
> 
Removed.

> 
> > +
> > +  prop = &TYPE_RANGE_DATA (range_type)->low;
> > +  if (dwarf2_evaluate_property (prop, addr, &value))
> > +    {
> > +      low_bound.kind = PROP_CONST;
> > +      low_bound.data.const_val = value;
> > +    }
> > +  else
> > +    {
> > +      low_bound.kind = PROP_UNDEFINED;
> > +      low_bound.data.const_val = 0;
> > +    }
> > +
> > +  prop = &TYPE_RANGE_DATA (range_type)->high;
> > +  if (dwarf2_evaluate_property (prop, addr, &value))
> > +    {
> > +      high_bound.kind = PROP_CONST;
> > +      high_bound.data.const_val = value;
> > +    }
> > +  else
> > +    {
> > +      high_bound.kind = PROP_UNDEFINED;
> > +      high_bound.data.const_val = 0;
> > +    }
> > +
> > +  ary_dim = check_typedef (TYPE_TARGET_TYPE (array_type));
> > +
> > +  if (ary_dim != NULL && TYPE_CODE (ary_dim) == TYPE_CODE_ARRAY)
> > +    array_type = resolve_dynamic_bounds (TYPE_TARGET_TYPE (type), addr);
> > +  else
> > +    array_type = TYPE_TARGET_TYPE (type);
> 
> I know this is going to sound a little silly, but would you mind
> calling "array_type" something like "elt_type" instead. The else
> block where you have "array_type = TYPE_TARGET_TYPE" really threw me
> at first, thinking you had a bug in your code.
> 
Done.

> > +
> > +  range_type
> > +    = create_range_type (NULL,
> > +			 TYPE_TARGET_TYPE (range_type),
> > +			 &low_bound, &high_bound);
> 
> Small formatting nit-pick (while we're touching this code):
> 
Done.

>   range_type = create_range_type (NULL,
>                                   TYPE_TARGET_TYPE (range_type),
>                                   &low_bound, &high_bound);
> 
> > +  array_type = create_array_type (copy_type (type),
> > +				  array_type,
> > +				  range_type);
> > +
> > +  return array_type;
> > +}
> > +
> > +/* See gdbtypes.h  */
> > +
> > +struct type *
> > +resolve_dynamic_type (struct type *type, CORE_ADDR addr)
> > +{
> > +  struct type *real_type = check_typedef (type);
> > +  struct type *resolved_type;
> > +
> > +  if (!TYPE_OBJFILE_OWNED (real_type))
> > +    return type;
> 
> Can you explain this? This definitely deserves a comment.
> 
This is a left over from the deep-type-copy patch series. Removed.

> > +  if (!is_dynamic_type (real_type))
> > +    return type;
> > +
> > +  resolved_type = resolve_dynamic_bounds (type, addr);
> > +  resolved_type->length = get_type_length (check_typedef (resolved_type));
> 
> Same as above regarding get_type_length. It seems to me that the length
> should have already been correctly computed by create_array_type,
> called from resolve_dynamic_bounds.
> 
Indeed. Removed old deep-type-copy code.
> > +
> > +  return resolved_type;
> > +}
> > +
> > +/* find the real type of TYPE.  This function returns the real type,
>       ^^^^
> 
> I think you unintentionally modified the first line of this comment...
> This line should not be part of the diff.
> 
Done.

> 
> 
> >     after removing all layers of typedefs, and completing opaque or stub
> >     types.  Completion changes the TYPE argument, but stripping of
> >     typedefs does not.
> > @@ -1706,44 +1895,15 @@ check_typedef (struct type *type)
> >  	  /* Nothing we can do.  */
> >  	}
> >        else if (TYPE_CODE (type) == TYPE_CODE_ARRAY
> > -	       && TYPE_NFIELDS (type) == 1
> > -	       && (TYPE_CODE (range_type = TYPE_INDEX_TYPE (type))
> > -		   == TYPE_CODE_RANGE))
> > -	{
> > -	  /* Now recompute the length of the array type, based on its
> > -	     number of elements and the target type's length.
> > -	     Watch out for Ada null Ada arrays where the high bound
> > -	     is smaller than the low bound.  */
> > -	  const LONGEST low_bound = TYPE_LOW_BOUND (range_type);
> > -	  const LONGEST high_bound = TYPE_HIGH_BOUND (range_type);
> > -	  ULONGEST len;
> > -
> > -	  if (high_bound < low_bound)
> > -	    len = 0;
> > -	  else
> > -	    {
> > -	      /* For now, we conservatively take the array length to be 0
> > -		 if its length exceeds UINT_MAX.  The code below assumes
> > -		 that for x < 0, (ULONGEST) x == -x + ULONGEST_MAX + 1,
> > -		 which is technically not guaranteed by C, but is usually true
> > -		 (because it would be true if x were unsigned with its
> > -		 high-order bit on).  It uses the fact that
> > -		 high_bound-low_bound is always representable in
> > -		 ULONGEST and that if high_bound-low_bound+1 overflows,
> > -		 it overflows to 0.  We must change these tests if we
> > -		 decide to increase the representation of TYPE_LENGTH
> > -		 from unsigned int to ULONGEST.  */
> > -	      ULONGEST ulow = low_bound, uhigh = high_bound;
> > -	      ULONGEST tlen = TYPE_LENGTH (target_type);
> > -
> > -	      len = tlen * (uhigh - ulow + 1);
> > -	      if (tlen == 0 || (len / tlen - 1 + ulow) != uhigh
> > -		  || len > UINT_MAX)
> > -		len = 0;
> > -	    }
> > -	  TYPE_LENGTH (type) = len;
> > -	  TYPE_TARGET_STUB (type) = 0;
> > -	}
> > +	       || TYPE_CODE (type) == TYPE_CODE_STRING)
> > +        {
> > +          range_type = TYPE_INDEX_TYPE (type);
> > +          if (has_static_range (TYPE_RANGE_DATA (range_type)))
> > +            {
> > +              TYPE_LENGTH (type) = get_type_length (type);
> > +              TYPE_TARGET_STUB (type) = 0;
> > +            }
> > +        }
> >        else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
> >  	{
> >  	  TYPE_LENGTH (type) = TYPE_LENGTH (target_type);
> > diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
> > index f6e68c5..38cd240 100644
> > --- a/gdb/gdbtypes.h
> > +++ b/gdb/gdbtypes.h
> > @@ -1,3 +1,4 @@
> > +
> >  /* Internal type definitions for GDB.
> >
> >     Copyright (C) 1992-2013 Free Software Foundation, Inc.
> > @@ -1574,6 +1575,15 @@ extern struct type *lookup_unsigned_typename (const struct
> language_defn *,
> >  extern struct type *lookup_signed_typename (const struct language_defn *,
> >  					    struct gdbarch *, const char *);
> >
> > +/* Resolves all dynamic values of a type e.g. array bounds to static values.
> > +   ADDR specifies the location of the variable the type is bound to.
> > +   If TYPE has no dynamic values returns TYPE otherwise a new type with static
> > +   values is returned.  */
> > +extern struct type *resolve_dynamic_type (struct type *type, CORE_ADDR addr);
> > +
> > +/* Predicates if the type has dynamic values, which are not resolved yet.  */
> > +extern int is_dynamic_type (const struct type *type);
> > +
> 
> While making adjustments to this patch, would you mind adjusting
> the style of the function descriptions, please. We use the imperative
> style when describing the actions of the function. For instance:
> 
Done.

> /* Resolve (no s) all dynamic values of a type.
> 
> "ADDR specifies" should still be with an 's'...
> 
> 
> >  extern struct type *check_typedef (struct type *);
> >
> >  #define CHECK_TYPEDEF(TYPE)			\
> > diff --git a/gdb/valops.c b/gdb/valops.c
> > index 5c7bb89..a7260b9 100644
> > --- a/gdb/valops.c
> > +++ b/gdb/valops.c
> > @@ -902,7 +902,9 @@ value_one (struct type *type)
> >    return val;
> >  }
> >
> > -/* Helper function for value_at, value_at_lazy, and value_at_lazy_stack.  */
> > +/* Helper function for value_at, value_at_lazy, and value_at_lazy_stack.
> > +   The type of the created value may differ from the passed type TYPE.
> > +   Make sure to retrieve values new type after this call.  */
>                            ^^^^^^^^
> 
> Suggest: Make sure to retrieve the returned value's new type after
> this call.
> 
> I'd suggest also an example of when the value's type might be
> different...
> 
> [...]
> 
> Same remark as above. And in value.c below as well.
> 
Done.

> >
> >  struct value *
> >  value_at_lazy (struct type *type, CORE_ADDR addr)
> > diff --git a/gdb/value.c b/gdb/value.c
> > index a64e7e1..12726a1 100644
> > --- a/gdb/value.c
> > +++ b/gdb/value.c
> > @@ -3178,32 +3178,37 @@ value_from_ulongest (struct type *type, ULONGEST num)
> >
> >
> >  /* Create a value representing a pointer of type TYPE to the address
> > -   ADDR.  */
> > +   ADDR.  The type of the created value may differ from the passed
> > +   type TYPE.  Make sure to retrieve values new type after this call.  */
> >  struct value *
> >  value_from_pointer (struct type *type, CORE_ADDR addr)
> >  {
> > -  struct value *val = allocate_value (type);
> > +  struct type *resolved_type = resolve_dynamic_type (type, addr);
> > +  struct value *val = allocate_value (resolved_type);
> >
> > -  store_typed_address (value_contents_raw (val), check_typedef (type), addr);
> > +  store_typed_address (value_contents_raw (val),
> > +		       check_typedef (resolved_type), addr);
> >    return val;
> >  }
> >
> >
> >  /* Create a value of type TYPE whose contents come from VALADDR, if it
> >     is non-null, and whose memory address (in the inferior) is
> > -   ADDRESS.  */
> > +   ADDRESS.  The type of the created value may differ from the passed
> > +   type TYPE.  Make sure to retrieve values new type after this call.  */
> >
> >  struct value *
> >  value_from_contents_and_address (struct type *type,
> >  				 const gdb_byte *valaddr,
> >  				 CORE_ADDR address)
> >  {
> > +  struct type *resolved_type = resolve_dynamic_type (type, address);
> >    struct value *v;
> >
> >    if (valaddr == NULL)
> > -    v = allocate_value_lazy (type);
> > +    v = allocate_value_lazy (resolved_type);
> >    else
> > -    v = value_from_contents (type, valaddr);
> > +    v = value_from_contents (resolved_type, valaddr);
> >    set_value_address (v, address);
> >    VALUE_LVAL (v) = lval_memory;
> >    return v;
> > --
> > 1.8.4.2
> 
> --
> Joel
Intel GmbH
Dornacher Strasse 1
85622 Feldkirchen/Muenchen, Deutschland
Sitz der Gesellschaft: Feldkirchen bei Muenchen
Geschaeftsfuehrer: Christian Lamprechter, Hannes Schwaderer, Douglas Lusk
Registergericht: Muenchen HRB 47456
Ust.-IdNr./VAT Registration No.: DE129385895
Citibank Frankfurt a.M. (BLZ 502 109 00) 600119052


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH v5 03/15] type: add c99 variable length array support
  2014-04-08  6:41     ` Agovic, Sanimir
@ 2014-04-08 12:49       ` Joel Brobecker
  0 siblings, 0 replies; 45+ messages in thread
From: Joel Brobecker @ 2014-04-08 12:49 UTC (permalink / raw)
  To: Agovic, Sanimir; +Cc: gdb-patches

> I addressed all issues (see below) except for these two:
> 
> > > +  if (!attr_to_dynamic_prop (attr, die, cu, &high))
> > >      {
> > >        attr = dwarf2_attr (die, DW_AT_count, cu);
> > >        if (attr)
> > 
> > I know that in the testcase you are trying to support, the bounds
> > are necessarily starting at zero and therefore constant/non-dynamic.
> > But can you modify the function to also handle the DW_AT_lower_bound
> > the same way? Other languages such as Ada will need that also, and
> > that seems like the logical time to be doing it.
> >
> The motivation behind the c99 patch series is to introduce the core concept
> of dynamic properties and thus we like to keep it small. Based on that work
> the Fortran patch series will fill the gap.

OK with me if you prefer to handle this case as a follow up patch.

> > > +int
> > > +is_dynamic_type (const struct type *type)
> > > +{
> > > +  if (TYPE_CODE (type) == TYPE_CODE_ARRAY
> > > +      && TYPE_NFIELDS (type) == 1)
> > > +    {
> > > +      const struct type *range_type = TYPE_INDEX_TYPE (type);
> > > +
> > > +      if (!has_static_range (TYPE_RANGE_DATA (range_type)))
> > > +	return 1;
> > > +    }
> > > +
> > > +  if (TYPE_CODE (type) == TYPE_CODE_ARRAY
> > > +      || TYPE_CODE (type) == TYPE_CODE_PTR
> > > +      || TYPE_CODE (type) == TYPE_CODE_REF
> > > +      || TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
> > > +    return is_dynamic_type (check_typedef (TYPE_TARGET_TYPE (type)));
> > As discussed on IRC, I think that TYPE_NFIELDS should always
> > be 1 for TYPE_CODE_ARRAY. So let's transform that into an assert,
> > if you don't mind, and see what happens?
> > Can you explain why you included TYPE_CODE_PTR in the list?
> >
> > This is not clear to me based on the function's description.
> > The risk I see with this is trying to print the value of a pointer
> > to a dynamic array - the printing really only needs to display
> > the address, and not resolve the underlying array. Also, from
> > a logical standpoint, pointers are not dynamic types.
> >
> I may remove the pointer chasing from the patch series, but this means
> we won't support the following feature:
> 
>   1| int foo(int vla[n][m])
> 
>   (gdb) ptype vla
>   type = int (*)[] 
>   (gdb) print vla[0]
>   Cannot perform pointer math on incomplete types, try casting to a known type, or void *.
> 
> So we included TYPE_CODE_PTR to support such use case. 

OK. Do we have a test for this in the patches you propose?
I think it's important to have one. That way, if anyone like me
just tries to remove it, it'll show up in the testsuite.

> > Can you explain in this comment what the referenced type is?
> > If it helps, giving an example could be used.
> > 
> Done, see my inlined my changes:

Thank you. Small comment (see below):

> -- >8 --
> diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h
> index 644c546..bcc02694 100644
> --- a/gdb/dwarf2loc.h
> +++ b/gdb/dwarf2loc.h
> @@ -144,13 +144,14 @@ struct dwarf2_loclist_baton
>  };
> 
>  /* A dynamic property is either expressed as a single location expression
> -   or a location list. If the property is a reference store its targeted
> -   type in TYPE.  */
> +   or a location list. If the property is an indirection, pointing to

                        ^^ missing second space after period.

Ok - I think we're ready for v6 of the patch series. Let's hope that'll
be it! :)

Thanks,
-- 
Joel


^ permalink raw reply	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2014-04-08 12:49 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-06 16:27 [PATCH v5 00/15] C99 variable length array support Sanimir Agovic
2014-02-06 16:27 ` [PATCH v5 11/15] test: cover subranges with present DW_AT_count attribute Sanimir Agovic
2014-02-28 17:52   ` Joel Brobecker
2014-02-06 16:27 ` [PATCH v5 04/15] vla: enable sizeof operator to work with variable length arrays Sanimir Agovic
2014-02-06 16:27 ` [PATCH v5 08/15] vla: support for DW_AT_count Sanimir Agovic
2014-02-28 16:53   ` Joel Brobecker
2014-03-12 13:51     ` Agovic, Sanimir
2014-03-13 15:36       ` Joel Brobecker
2014-02-06 16:28 ` [PATCH v5 14/15] test: basic c99 vla tests for C primitives Sanimir Agovic
2014-02-28 18:04   ` Joel Brobecker
2014-02-06 16:28 ` [PATCH v5 07/15] vla: print "variable length" for unresolved dynamic bounds Sanimir Agovic
2014-02-06 16:28 ` [PATCH v5 15/15] test: add mi vla test Sanimir Agovic
2014-02-28 18:07   ` Joel Brobecker
2014-03-12 12:53     ` Agovic, Sanimir
2014-02-06 16:28 ` [PATCH v5 01/15] refactoring: rename create_range_type to create_static_range_type Sanimir Agovic
2014-02-27 22:03   ` Joel Brobecker
2014-02-28 11:02     ` Agovic, Sanimir
2014-02-06 16:28 ` [PATCH v5 02/15] vla: introduce new bound type abstraction adapt uses Sanimir Agovic
2014-02-06 16:28 ` [PATCH v5 06/15] vla: update type from newly created value Sanimir Agovic
2014-02-06 16:28 ` [PATCH v5 05/15] vla: enable sizeof operator for indirection Sanimir Agovic
2014-02-06 16:28 ` [PATCH v5 13/15] test: evaluate pointers to C99 vla correctly Sanimir Agovic
2014-02-28 18:01   ` Joel Brobecker
2014-02-06 16:28 ` [PATCH v5 10/15] vla: evaluate operand of sizeof if its type is a vla Sanimir Agovic
2014-02-28 17:37   ` Joel Brobecker
2014-03-19 12:55     ` Agovic, Sanimir
2014-03-19 15:12       ` Joel Brobecker
2014-02-06 16:28 ` [PATCH v5 09/15] vla: resolve dynamic bounds if value contents is a constant byte-sequence Sanimir Agovic
2014-02-07 10:27   ` Joel Brobecker
2014-02-07 12:27     ` Agovic, Sanimir
2014-02-28 17:09   ` Joel Brobecker
2014-03-12 13:40     ` Agovic, Sanimir
2014-03-13 16:00     ` Joel Brobecker
2014-03-19 15:35       ` Agovic, Sanimir
2014-02-06 16:28 ` [PATCH v5 12/15] test: multi-dimensional c99 vla Sanimir Agovic
2014-02-28 17:58   ` Joel Brobecker
2014-02-06 16:28 ` [PATCH v5 03/15] type: add c99 variable length array support Sanimir Agovic
2014-02-28 16:27   ` Joel Brobecker
2014-04-08  6:41     ` Agovic, Sanimir
2014-04-08 12:49       ` Joel Brobecker
2014-02-09  3:49 ` [PATCH v5 00/15] C99 " Joel Brobecker
2014-02-10  4:33   ` Joel Brobecker
2014-02-17 20:22     ` Joel Brobecker
2014-02-26 14:05     ` Joel Brobecker
2014-03-03 16:51       ` Agovic, Sanimir
2014-02-28 18:13 ` status update: " Joel Brobecker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox