+2020-12-24  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       PR gdb/27059
+       * eval.c (evaluate_subexp_for_sizeof): Handle not allocated and
+       not associated arrays.
+       * f-lang.c (fortran_adjust_dynamic_array_base_address_hack): Don't
+       adjust arrays that are not allocated/associated.
+       * gdbtypes.c (resolve_dynamic_range): Update header comment.  Add
+       new parameter which is used to sometimes set dynamic properties to
+       undefined.
+       (resolve_dynamic_array_or_string): Update header comment.  Add new
+       parameter which is used to guard evaluating dynamic properties.
+       Resolve allocated/associated properties first.
+
 2020-12-24  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * gdbtypes (recursive_dump_type): Include allocated and associated
 
        {
          val = evaluate_subexp (nullptr, exp, pos, EVAL_NORMAL);
          type = value_type (val);
-         if (type->code () == TYPE_CODE_ARRAY
-             && is_dynamic_type (type->index_type ())
-             && type->bounds ()->high.kind () == PROP_UNDEFINED)
-           return allocate_optimized_out_value (size_type);
+         if (type->code () == TYPE_CODE_ARRAY)
+           {
+             if (type_not_allocated (type) || type_not_associated (type))
+               return value_zero (size_type, not_lval);
+             else if (is_dynamic_type (type->index_type ())
+                      && type->bounds ()->high.kind () == PROP_UNDEFINED)
+               return allocate_optimized_out_value (size_type);
+           }
        }
       else
        (*pos) += 4;
 
 {
   gdb_assert (type->code () == TYPE_CODE_ARRAY);
 
+  /* We can't adjust the base address for arrays that have no content.  */
+  if (type_not_allocated (type) || type_not_associated (type))
+    return address;
+
   int ndimensions = calc_f77_array_dims (type);
   LONGEST total_offset = 0;
 
 
 
 /* Given a dynamic range type (dyn_range_type) and a stack of
    struct property_addr_info elements, return a static version
-   of that type.  */
+   of that type.
+
+   When RESOLVE_P is true then the returned static range is created by
+   actually evaluating any dynamic properties within the range type, while
+   when RESOLVE_P is false the returned static range has all of the bounds
+   and stride information set to undefined.  The RESOLVE_P set to false
+   case will be used when evaluating a dynamic array that is not
+   allocated, or not associated, i.e. the bounds information might not be
+   initialized yet.  */
 
 static struct type *
 resolve_dynamic_range (struct type *dyn_range_type,
-                      struct property_addr_info *addr_stack)
+                      struct property_addr_info *addr_stack,
+                      bool resolve_p = true)
 {
   CORE_ADDR value;
   struct type *static_range_type, *static_target_type;
   gdb_assert (dyn_range_type->code () == TYPE_CODE_RANGE);
 
   const struct dynamic_prop *prop = &dyn_range_type->bounds ()->low;
-  if (dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
+  if (resolve_p && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
     low_bound.set_const_val (value);
   else
     low_bound.set_undefined ();
 
   prop = &dyn_range_type->bounds ()->high;
-  if (dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
+  if (resolve_p && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
     {
       high_bound.set_const_val (value);
 
 
   bool byte_stride_p = dyn_range_type->bounds ()->flag_is_byte_stride;
   prop = &dyn_range_type->bounds ()->stride;
-  if (dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
+  if (resolve_p && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
     {
       stride.set_const_val (value);
 
 
 /* Resolves dynamic bound values of an array or string type TYPE to static
    ones.  ADDR_STACK is a stack of struct property_addr_info to be used if
-   needed during the dynamic resolution.  */
+   needed during the dynamic resolution.
+
+   When RESOLVE_P is true then the dynamic properties of TYPE are
+   evaluated, otherwise the dynamic properties of TYPE are not evaluated,
+   instead we assume the array is not allocated/associated yet.  */
 
 static struct type *
 resolve_dynamic_array_or_string (struct type *type,
-                                struct property_addr_info *addr_stack)
+                                struct property_addr_info *addr_stack,
+                                bool resolve_p = true)
 {
   CORE_ADDR value;
   struct type *elt_type;
 
   type = copy_type (type);
 
-  elt_type = type;
-  range_type = check_typedef (elt_type->index_type ());
-  range_type = resolve_dynamic_range (range_type, addr_stack);
-
-  /* Resolve allocated/associated here before creating a new array type, which
-     will update the length of the array accordingly.  */
+  /* Resolve the allocated and associated properties before doing anything
+     else.  If an array is not allocated or not associated then (at least
+     for Fortran) there is no guarantee that the data to define the upper
+     bound, lower bound, or stride will be correct.  If RESOLVE_P is
+     already false at this point then this is not the first dimension of
+     the array and a more outer dimension has already marked this array as
+     not allocated/associated, as such we just ignore this property.  This
+     is fine as GDB only checks the allocated/associated on the outer most
+     dimension of the array.  */
   prop = TYPE_ALLOCATED_PROP (type);
-  if (prop != NULL && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
-    prop->set_const_val (value);
+  if (prop != NULL && resolve_p
+      && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
+    {
+      prop->set_const_val (value);
+      if (value == 0)
+       resolve_p = false;
+    }
 
   prop = TYPE_ASSOCIATED_PROP (type);
-  if (prop != NULL && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
-    prop->set_const_val (value);
+  if (prop != NULL && resolve_p
+      && dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
+    {
+      prop->set_const_val (value);
+      if (value == 0)
+       resolve_p = false;
+    }
 
-  ary_dim = check_typedef (TYPE_TARGET_TYPE (elt_type));
+  range_type = check_typedef (type->index_type ());
+  range_type = resolve_dynamic_range (range_type, addr_stack, resolve_p);
 
+  ary_dim = check_typedef (TYPE_TARGET_TYPE (type));
   if (ary_dim != NULL && ary_dim->code () == TYPE_CODE_ARRAY)
-    elt_type = resolve_dynamic_array_or_string (ary_dim, addr_stack);
+    elt_type = resolve_dynamic_array_or_string (ary_dim, addr_stack, resolve_p);
   else
     elt_type = TYPE_TARGET_TYPE (type);
 
   prop = type->dyn_prop (DYN_PROP_BYTE_STRIDE);
-  if (prop != NULL)
+  if (prop != NULL && resolve_p)
     {
       if (dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
        {
 
+2020-12-24  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       PR gdb/27059
+       * gdb.dwarf2/dyn-type-unallocated.c: New file.
+       * gdb.dwarf2/dyn-type-unallocated.exp: New file.
+
 2020-12-21  Peter Waller  <p@pwaller.net>
 
        * gdb.base/style-interp-exec-mi.exp: New.
 
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2020 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 "../lib/attributes.h"
+
+/* Our fake dynamic object.  */
+void *dyn_object;
+
+void __attribute__((noinline)) ATTRIBUTE_NOCLONE
+marker ()
+{ /* Nothing.  */ }
+
+int
+main ()
+{
+  asm ("main_label: .globl main_label");
+
+  /* Initialise the dynamic object.  */
+  dyn_object = 0;
+
+  asm ("marker_label: .globl marker_label");
+  marker ();   /* Break here.  */
+
+  return 0;
+}
+
 
--- /dev/null
+# Copyright 2020 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/>.
+
+# Test for issue PR gdb/27059.  The problem was that when resolving a
+# dynamic type that was not-allocated GDB would still try to execute
+# the DWARF expressions for the upper, lower, and byte-stride values.
+#
+# The problem is that, at least in some gfortran compiled programs,
+# these values are undefined until the array is allocated.
+#
+# As a result, executing the dwarf expressions was triggering integer
+# overflow in some cases.
+#
+# This test aims to make the sometimes occurring integer overflow a
+# more noticeable error by creating an array that is always marked as
+# not-allocated.
+#
+# The dwarf expressions for the various attributes then contains an
+# infinite loop.  If GDB ever tries to execute these expressions we
+# will get a test timeout.  With this issue fixed the expressions are
+# never executed and the test completes as we'd expect.
+
+load_lib dwarf.exp
+
+if {![dwarf2_support]} {
+    return 0
+}
+
+standard_testfile .c -dw.S
+
+if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } {
+    return -1
+}
+
+set asm_file [standard_output_file $srcfile2]
+Dwarf::assemble $asm_file {
+    cu {} {
+       global srcfile
+
+       compile_unit {
+           {producer "gcc" }
+            {language @DW_LANG_Fortran90}
+            {name ${srcfile}}
+            {low_pc 0 addr}
+        } {
+           declare_labels array_type_label integer_type_label
+
+           set int_size [get_sizeof "int" "UNKNOWN"]
+           set voidp_size [get_sizeof "void *" "UNKNOWN"]
+
+            integer_type_label: DW_TAG_base_type {
+                {DW_AT_byte_size $int_size DW_FORM_sdata}
+                {DW_AT_encoding  @DW_ATE_signed}
+                {DW_AT_name      integer}
+            }
+
+           array_type_label: DW_TAG_array_type {
+               {DW_AT_type :$integer_type_label}
+               {DW_AT_data_location {
+                   DW_OP_push_object_address
+                   DW_OP_deref
+               } SPECIAL_expr}
+               {DW_AT_allocated {
+                   DW_OP_lit0
+               } SPECIAL_expr}
+           } {
+               DW_TAG_subrange_type {
+                   {DW_AT_type        :$integer_type_label}
+                   {DW_AT_lower_bound {
+                       DW_OP_skip -3
+                   } SPECIAL_expr}
+                   {DW_AT_upper_bound {
+                       DW_OP_skip -3
+                   } SPECIAL_expr}
+                   {DW_AT_byte_stride {
+                       DW_OP_skip -3
+                   } SPECIAL_expr}
+               }
+           }
+
+           DW_TAG_variable {
+                {DW_AT_location {
+                    DW_OP_addr [gdb_target_symbol dyn_object]
+                } SPECIAL_expr}
+               {name "dyn_object"}
+               {type :$array_type_label}
+           }
+            subprogram {
+                {external 1 flag}
+                {MACRO_AT_func {main}}
+            }
+        }
+    }
+}
+
+if { [prepare_for_testing "failed to prepare" "${testfile}" \
+         [list $srcfile $asm_file] {nodebug}] } {
+    return -1
+}
+
+if ![runto_main] {
+    return -1
+}
+
+gdb_breakpoint "marker_label"
+gdb_continue_to_breakpoint "stop at marker_label"
+gdb_test "ptype dyn_object" "type = integer, allocatable \\(:\\)"