+2020-04-24  Tom Tromey  <tromey@adacore.com>
+
+       PR python/23662:
+       * python/py-type.c (convert_field): Handle
+       FIELD_LOC_KIND_DWARF_BLOCK.
+       (typy_get_sizeof): Handle TYPE_HAS_DYNAMIC_LENGTH.
+       (typy_get_dynamic): Nw function.
+       (type_object_getset): Add "dynamic".
+       * NEWS: Add entry.
+
 2020-04-24  Tom Tromey  <tromey@adacore.com>
 
        * ada-typeprint.c (print_choices, print_variant_part)
 
   ** gdb.register_window_type can be used to implement new TUI windows
      in Python.
 
+  ** Dynamic types can now be queried.  gdb.Type has a new attribute,
+     "dynamic", and gdb.Type.sizeof can be None for a dynamic type.  A
+     field of a dynamic type may have None for its "bitpos" attribute
+     as well.
+
 *** Changes in GDB 9
 
 * 'thread-exited' event is now available in the annotations interface.
 
+2020-04-24  Tom Tromey  <tromey@adacore.com>
+
+       PR python/23662:
+       * python.texi (Types In Python): Document new features.
+
 2020-04-15  Artur Shepilko  <nomadbyte@gmail.com>
 
        * gdb.texinfo: Transform @var{[host]} to [@var{host}]; this
 
 @code{TYPE_CODE_} constants defined below.
 @end defvar
 
+@defvar Type.dynamic
+A boolean indicating whether this type is dynamic.  In some
+situations, such as Rust @code{enum} types or Ada variant records, the
+concrete type of a value may vary depending on its contents.
+@end defvar
+
 @defvar Type.name
 The name of this type.  If this type has no name, then @code{None}
 is returned.
 @defvar Type.sizeof
 The size of this type, in target @code{char} units.  Usually, a
 target's @code{char} type will be an 8-bit byte.  However, on some
-unusual platforms, this type may have a different size.
+unusual platforms, this type may have a different size.  A dynamic
+type may not have a fixed size; in this case, this attribute's value
+will be @code{None}.
 @end defvar
 
 @defvar Type.tag
 @item bitpos
 This attribute is not available for @code{enum} or @code{static}
 (as in C@t{++}) fields.  The value is the position, counting
-in bits, from the start of the containing type.
+in bits, from the start of the containing type.  Note that, in a
+dynamic type, the position of a field may not be constant.  In this
+case, the value will be @code{None}.
 
 @item enumval
 This attribute is only available for @code{enum} fields, and its value
 
        }
       else
        {
-         arg.reset (gdb_py_long_from_longest (TYPE_FIELD_BITPOS (type,
-                                                                 field)));
+         if (TYPE_FIELD_LOC_KIND (type, field) == FIELD_LOC_KIND_DWARF_BLOCK)
+           arg = gdbpy_ref<>::new_reference (Py_None);
+         else
+           arg.reset (gdb_py_long_from_longest (TYPE_FIELD_BITPOS (type,
+                                                                   field)));
          attrstring = "bitpos";
        }
 
 {
   struct type *type = ((type_object *) self)->type;
 
+  bool size_varies = false;
   try
     {
       check_typedef (type);
+
+      size_varies = TYPE_HAS_DYNAMIC_LENGTH (type);
     }
   catch (const gdb_exception &except)
     {
 
   /* Ignore exceptions.  */
 
+  if (size_varies)
+    Py_RETURN_NONE;
   return gdb_py_long_from_longest (TYPE_LENGTH (type));
 }
 
   return gdb_py_object_from_ulongest (align).release ();
 }
 
+/* Return whether or not the type is dynamic.  */
+static PyObject *
+typy_get_dynamic (PyObject *self, void *closure)
+{
+  struct type *type = ((type_object *) self)->type;
+
+  bool result = false;
+  try
+    {
+      result = is_dynamic_type (type);
+    }
+  catch (const gdb_exception &except)
+    {
+      /* Ignore exceptions.  */
+    }
+
+  if (result)
+    Py_RETURN_TRUE;
+  Py_RETURN_FALSE;
+}
+
 static struct type *
 typy_lookup_typename (const char *type_name, const struct block *block)
 {
     "The alignment of this type, in bytes.", NULL },
   { "code", typy_get_code, NULL,
     "The code for this type.", NULL },
+  { "dynamic", typy_get_dynamic, NULL,
+    "Whether this type is dynamic.", NULL },
   { "name", typy_get_name, NULL,
     "The name for this type, or None.", NULL },
   { "sizeof", typy_get_sizeof, NULL,
 
+2020-04-24  Tom Tromey  <tromey@adacore.com>
+
+       PR python/23662:
+       * gdb.ada/variant.exp: Add Python checks.
+       * gdb.rust/simple.exp: Add dynamic type checks.
+
 2020-04-24  Tom Tromey  <tromey@adacore.com>
 
        * gdb.ada/mi_var_array.exp: Try all -fgnat-encodings settings.
 
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 load_lib "ada.exp"
+load_lib "gdb-python.exp"
 
 standard_ada_testfile pkg
 
        " = \\(one => 3, two => 0, str => \"zzz\", onevalue => 33, str2 => \"\"\\)"
     gdb_test "print nav3" \
        " = \\(one => 3, two => 7, str => \"zzz\", onevalue => 33, str2 => \"qqqqqqq\", twovalue => 88\\)"
+
+    # This is only supported for the DWARF encoding.
+    if {$scenario == "minimal" && ![skip_python_tests]} {
+       gdb_test_no_output \
+           "python t = gdb.lookup_type('nested_and_variable')" \
+           "fetch type for python"
+       gdb_test "python print(t.dynamic)" "True"
+       gdb_test "python print(t\['onevalue'\].bitpos)" "None"
+    }
 }
 
 }
 
 gdb_test "python print(gdb.lookup_type('simple::HiBob'))" "simple::HiBob"
+
+gdb_test_no_output "python e = gdb.parse_and_eval('e')" \
+    "get value of e for python"
+gdb_test "python print(len(e.type.fields()))" "2"
+gdb_test "python print(e.type.fields()\[0\].artificial)" "True"
+gdb_test "python print(e.type.fields()\[1\].name)" "Two"
+
+gdb_test "python print(e.type.dynamic)" "False"
+gdb_test "python print(gdb.lookup_type('simple::MoreComplicated').dynamic)" \
+    "True"