Blob Blame History Raw
http://sourceware.org/gdb/wiki/ProjectArcher
http://sourceware.org/gdb/wiki/ArcherBranchManagement

GIT snapshot:
commit 39998c496988faaa1509cc6ab76b5c4777659bf4

branch `archer' - the merge of branches:
archer-tromey-delayed-symfile2
archer-tromey-python
archer-pmuldoon-next-over-throw2
archer-jankratochvil-fortran-module2
archer-jankratochvil-watchpoint2
archer-jankratochvil-vla
archer-keiths-expr-cumulative
# plus older archer-jankratochvil-ifunc


diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 98f42b9..dbf8273 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -167,6 +167,12 @@ TARGET_SYSTEM_ROOT = @TARGET_SYSTEM_ROOT@
 TARGET_SYSTEM_ROOT_DEFINE = @TARGET_SYSTEM_ROOT_DEFINE@
 
 # Did the user give us a --with-gdb-datadir option?
+GDB_DATADIR_PATH = @GDB_DATADIR_PATH@
+
+# The argument to --with-pythondir.  If not given, this is
+# GDB_DATADIR_PATH/python.
+pythondir = @pythondir@
+
 GDB_DATADIR = @GDB_DATADIR@
 
 # Helper code from gnulib.
@@ -267,23 +273,39 @@ SUBDIR_TUI_CFLAGS= \
 #
 SUBDIR_PYTHON_OBS = \
 	python.o \
+	py-block.o \
+	py-breakpoint.o \
 	py-cmd.o \
 	py-frame.o \
 	py-function.o \
+	py-hooks.o \
+	py-inferior.o \
+	py-infthread.o \
 	py-lazy-string.o \
 	py-objfile.o \
+	py-param.o \
 	py-prettyprint.o \
+	py-symbol.o \
+	py-symtab.o \
 	py-type.o \
 	py-utils.o \
 	py-value.o
 SUBDIR_PYTHON_SRCS = \
 	python/python.c \
+	python/py-block.c \
+	python/py-breakpoint.c \
 	python/py-cmd.c \
 	python/py-frame.c \
 	python/py-function.c \
+	python/py-hooks.c \
+	python/py-inferior.c \
+	python/py-infthread.c \
 	python/py-lazy-string.c \
 	python/py-objfile.c \
+	python/py-param.c \
 	python/py-prettyprint.c \
+	python/py-symbol.c \
+	python/py-symtab.c \
 	python/py-type.c \
 	python/py-utils.c \
 	python/py-value.c
@@ -756,7 +778,8 @@ config/rs6000/nm-rs6000.h top.h bsd-kvm.h gdb-stabs.h reggroups.h \
 annotate.h sim-regno.h dictionary.h dfp.h main.h frame-unwind.h	\
 remote-fileio.h i386-linux-tdep.h vax-tdep.h objc-lang.h \
 sentinel-frame.h bcache.h symfile.h windows-tdep.h linux-tdep.h \
-gdb_usleep.h jit.h xml-syscall.h ada-operator.inc microblaze-tdep.h
+gdb_usleep.h jit.h python/python.h python/python-internal.h \
+xml-syscall.h ada-operator.inc microblaze-tdep.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -1270,6 +1293,12 @@ stamp-h: $(srcdir)/config.in config.status
 	  CONFIG_LINKS= \
 	  $(SHELL) config.status
 
+.gdbinit: $(srcdir)/gdbinit.in config.status
+	CONFIG_FILES=".gdbinit:gdbinit.in" \
+	  CONFIG_COMMANDS= \
+	  CONFIG_HEADERS= \
+	  $(SHELL) config.status
+
 config.status: $(srcdir)/configure configure.tgt configure.host
 	$(SHELL) config.status --recheck
 
@@ -1970,6 +1999,14 @@ python.o: $(srcdir)/python/python.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/python.c
 	$(POSTCOMPILE)
 
+py-block.o: $(srcdir)/python/py-block.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-block.c
+	$(POSTCOMPILE)
+
+py-breakpoint.o: $(srcdir)/python/py-breakpoint.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-breakpoint.c
+	$(POSTCOMPILE)
+
 py-cmd.o: $(srcdir)/python/py-cmd.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-cmd.c
 	$(POSTCOMPILE)
@@ -1982,6 +2019,18 @@ py-function.o: $(srcdir)/python/py-function.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-function.c
 	$(POSTCOMPILE)
 
+py-hooks.o: $(srcdir)/python/py-hooks.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-hooks.c
+	$(POSTCOMPILE)
+
+py-inferior.o: $(srcdir)/python/py-inferior.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-inferior.c
+	$(POSTCOMPILE)
+
+py-infthread.o: $(srcdir)/python/py-infthread.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-infthread.c
+	$(POSTCOMPILE)
+
 py-lazy-string.o: $(srcdir)/python/py-lazy-string.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-lazy-string.c
 	$(POSTCOMPILE)
@@ -1990,10 +2039,22 @@ py-objfile.o: $(srcdir)/python/py-objfile.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-objfile.c
 	$(POSTCOMPILE)
 
+py-param.o: $(srcdir)/python/py-param.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-param.c
+	$(POSTCOMPILE)
+
 py-prettyprint.o: $(srcdir)/python/py-prettyprint.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-prettyprint.c
 	$(POSTCOMPILE)
 
+py-symbol.o: $(srcdir)/python/py-symbol.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-symbol.c
+	$(POSTCOMPILE)
+
+py-symtab.o: $(srcdir)/python/py-symtab.c
+	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-symtab.c
+	$(POSTCOMPILE)
+
 py-type.o: $(srcdir)/python/py-type.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-type.c
 	$(POSTCOMPILE)
@@ -2006,6 +2067,36 @@ py-value.o: $(srcdir)/python/py-value.c
 	$(COMPILE) $(PYTHON_CFLAGS) $(srcdir)/python/py-value.c
 	$(POSTCOMPILE)
 
+# All python library files, with the "python/lib" stripped off.
+# Note that we should only install files in the "gdb" module.
+PY_FILES = gdb/FrameIterator.py gdb/FrameWrapper.py gdb/command/alias.py \
+    gdb/command/backtrace.py gdb/command/require.py \
+    gdb/command/pahole.py gdb/command/upto.py gdb/command/__init__.py \
+    gdb/command/ignore_errors.py gdb/command/save_breakpoints.py \
+    gdb/function/caller_is.py gdb/function/in_scope.py \
+    gdb/function/__init__.py gdb/backtrace.py gdb/__init__.py
+
+# Install the Python library.  Python library files go under
+# $(pythondir).
+install-python:
+	files='$(PY_FILES)'; for file in $$files; do \
+	  dir=`echo "$$file" | sed 's,/[^/]*$$,,'`; \
+	  $(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(pythondir)/$$dir; \
+	  $(INSTALL_DATA) $(srcdir)/python/lib/$$file $(DESTDIR)$(pythondir)/$$file; \
+	done
+
+# Other packages may have their files installed in $(pythondir).
+uninstall-python:
+	files='$(PY_FILES)'; for file in $$files; do \
+	  slashdir=`echo "/$$file" | sed 's,/[^/]*$$,,'`; \
+	  rm -f $(DESTDIR)$(pythondir)/$$file; \
+	  while test "x$$file" != "x$$slashdir"; do \
+	    rmdir 2>/dev/null "$(DESTDIR)$(pythondir)$$slashdir"; \
+	    file="$$slashdir"; \
+	    slashdir=`echo "$$file" | sed 's,/[^/]*$$,,'`; \
+	  done \
+	done
+
 #
 # Dependency tracking.  Most of this is conditional on GNU Make being
 # found by configure; if GNU Make is not found, we fall back to a
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 7a2d2ca..4bf4e31 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -4781,14 +4781,10 @@ ada_lookup_symbol (const char *name, const struct block *block0,
 
 static struct symbol *
 ada_lookup_symbol_nonlocal (const char *name,
-                            const char *linkage_name,
                             const struct block *block,
                             const domain_enum domain)
 {
-  if (linkage_name == NULL)
-    linkage_name = name;
-  return ada_lookup_symbol (linkage_name, block_static_block (block), domain,
-                            NULL);
+  return ada_lookup_symbol (name, block_static_block (block), domain, NULL);
 }
 
 
@@ -10938,6 +10934,40 @@ ada_operator_length (struct expression *exp, int pc, int *oplenp, int *argsp)
     }
 }
 
+/* Implementation of the exp_descriptor method operator_check.  */
+
+static int
+ada_operator_check (struct expression *exp, int pos,
+		    int (*type_func) (struct type *type, void *data),
+		    int (*objfile_func) (struct objfile *objfile, void *data),
+		    void *data)
+{
+  const union exp_element *const elts = exp->elts;
+  struct type *type = NULL;
+
+  switch (elts[pos].opcode)
+    {
+      case UNOP_IN_RANGE:
+      case UNOP_QUAL:
+	type = elts[pos + 1].type;
+	break;
+
+      default:
+	return operator_check_standard (exp, pos, type_func, objfile_func,
+					data);
+    }
+
+  /* Invoke callbacks for TYPE and OBJFILE if they were set as non-NULL.  */
+
+  if (type && type_func && (*type_func) (type, data))
+    return 1;
+  if (type && TYPE_OBJFILE (type) && objfile_func
+      && (*objfile_func) (TYPE_OBJFILE (type), data))
+    return 1;
+
+  return 0;
+}
+
 static char *
 ada_op_name (enum exp_opcode opcode)
 {
@@ -11326,6 +11356,7 @@ parse (void)
 static const struct exp_descriptor ada_exp_descriptor = {
   ada_print_subexp,
   ada_operator_length,
+  ada_operator_check,
   ada_op_name,
   ada_dump_subexp_body,
   ada_evaluate_subexp
diff --git a/gdb/alpha-linux-tdep.c b/gdb/alpha-linux-tdep.c
index 3c71f2f..bbfe5a1 100644
--- a/gdb/alpha-linux-tdep.c
+++ b/gdb/alpha-linux-tdep.c
@@ -26,6 +26,7 @@
 #include "symtab.h"
 #include "regset.h"
 #include "regcache.h"
+#include "linux-tdep.h"
 
 #include "alpha-tdep.h"
 
@@ -236,6 +237,9 @@ alpha_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 
   set_gdbarch_regset_from_core_section
     (gdbarch, alpha_linux_regset_from_core_section);
+
+  set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+					  linux_convert_from_func_ptr_addr);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
index 5c9e558..55a1873 100644
--- a/gdb/amd64-linux-nat.c
+++ b/gdb/amd64-linux-nat.c
@@ -350,6 +350,20 @@ amd64_linux_dr_unset_status (unsigned long mask)
     }
 }
 
+/* See i386_dr_low_type.detach.  Do not use wrappers amd64_linux_dr_set_control
+   or amd64_linux_dr_reset_addr as they would modify the register cache
+   (amd64_linux_dr).  */
+
+static void
+amd64_linux_dr_detach (void)
+{
+  int regnum;
+
+  amd64_linux_dr_set (inferior_ptid, DR_CONTROL, 0);
+  amd64_linux_dr_unset_status (~0UL);
+  for (regnum = DR_FIRSTADDR; regnum <= DR_LASTADDR; regnum++)
+    amd64_linux_dr_set (inferior_ptid, regnum, 0);
+}
 
 static void
 amd64_linux_new_thread (ptid_t ptid)
@@ -702,6 +716,7 @@ _initialize_amd64_linux_nat (void)
   i386_dr_low.reset_addr = amd64_linux_dr_reset_addr;
   i386_dr_low.get_status = amd64_linux_dr_get_status;
   i386_dr_low.unset_status = amd64_linux_dr_unset_status;
+  i386_dr_low.detach = amd64_linux_dr_detach;
   i386_set_debug_register_length (8);
 
   /* Override the GNU/Linux inferior startup hook.  */
diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c
index c28eef7..02c11e1 100644
--- a/gdb/amd64-linux-tdep.c
+++ b/gdb/amd64-linux-tdep.c
@@ -1481,6 +1481,9 @@ amd64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   amd64_linux_record_tdep.arg6 = AMD64_R9_REGNUM;
 
   tdep->i386_syscall_record = amd64_linux_syscall_record;
+
+  set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+					  linux_convert_from_func_ptr_addr);
 }
 
 
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index af409f6..406c066 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -918,6 +918,9 @@ arm_linux_init_abi (struct gdbarch_info info,
   set_gdbarch_displaced_step_free_closure (gdbarch,
 					   simple_displaced_step_free_closure);
   set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
+
+  set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+					  linux_convert_from_func_ptr_addr);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
index 3e151de..ddbcb6e 100644
--- a/gdb/ax-gdb.c
+++ b/gdb/ax-gdb.c
@@ -1812,7 +1812,7 @@ gen_expr (struct expression *exp, union exp_element **pc,
 
 	/* Calling lookup_block_symbol is necessary to get the LOC_REGISTER
 	   symbol instead of the LOC_ARG one (if both exist).  */
-	sym = lookup_block_symbol (b, this_name, NULL, VAR_DOMAIN);
+	sym = lookup_block_symbol (b, this_name, VAR_DOMAIN);
 	if (!sym)
 	  error (_("no `%s' found"), this_name);
 
diff --git a/gdb/block.c b/gdb/block.c
index 48ac21b..0eccecb 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -227,8 +227,9 @@ block_set_scope (struct block *block, const char *scope,
   BLOCK_NAMESPACE (block)->scope = scope;
 }
 
-/* This returns the using directives list associated with BLOCK, if
-   any.  */
+/* This returns the first using directives associated with BLOCK, if
+   any.  Each BLOCK_NAMESPACE()->USING already contains all the namespaces
+   imported at that code point - even those from its parent blocks.  */
 
 struct using_direct *
 block_using (const struct block *block)
@@ -318,6 +319,25 @@ allocate_block (struct obstack *obstack)
   BLOCK_SUPERBLOCK (bl) = NULL;
   BLOCK_DICT (bl) = NULL;
   BLOCK_NAMESPACE (bl) = NULL;
+  BLOCK_FORTRAN_USE (bl) = NULL;
 
   return bl;
 }
+
+/* Return OBJFILE in which BLOCK is located or NULL if we cannot find it for
+   whatever reason.  */
+
+struct objfile *
+block_objfile (const struct block *block)
+{
+  struct symbol *func;
+
+  if (block == NULL)
+    return NULL;
+
+  func = block_linkage_function (block);
+  if (func == NULL)
+    return NULL;
+
+  return SYMBOL_SYMTAB (func)->objfile;
+}
diff --git a/gdb/block.h b/gdb/block.h
index 7eedb6c..b147826 100644
--- a/gdb/block.h
+++ b/gdb/block.h
@@ -96,6 +96,15 @@ struct block
     cplus_specific;
   }
   language_specific;
+
+  /* FIXME: It should be in the LANGUAGE_SPECIFIC region but the
+     BLOCK_NAMESPACE accessor is not protected by the C language check.  */
+
+  struct
+    {
+      struct fortran_using *use;
+    }
+  fortran_specific;
 };
 
 #define BLOCK_START(bl)		(bl)->startaddr
@@ -104,6 +113,7 @@ struct block
 #define BLOCK_SUPERBLOCK(bl)	(bl)->superblock
 #define BLOCK_DICT(bl)		(bl)->dict
 #define BLOCK_NAMESPACE(bl)   (bl)->language_specific.cplus_specific.namespace
+#define BLOCK_FORTRAN_USE(bl)	(bl)->fortran_specific.use
 
 /* Macro to loop through all symbols in a block BL, in no particular
    order.  ITER helps keep track of the iteration, and should be a
@@ -166,4 +176,6 @@ extern const struct block *block_global_block (const struct block *block);
 
 extern struct block *allocate_block (struct obstack *obstack);
 
+extern struct objfile *block_objfile (const struct block *block);
+
 #endif /* BLOCK_H */
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 8c97949..0b66740 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -61,6 +61,7 @@
 #include "valprint.h"
 #include "jit.h"
 #include "xml-syscall.h"
+#include "parser-defs.h"
 
 /* readline include files */
 #include "readline/readline.h"
@@ -614,6 +615,53 @@ get_breakpoint (int num)
 }
 
 
+/* Set break condition of breakpoint B to EXP.  */
+
+void
+set_breakpoint_condition (struct breakpoint *b, char *exp, int from_tty)
+{
+  struct bp_location *loc = b->loc;
+
+  for (; loc; loc = loc->next)
+    {
+      if (loc->cond)
+	{
+	  xfree (loc->cond);
+	  loc->cond = 0;
+	}
+    }
+
+  if (b->cond_string != NULL)
+    xfree (b->cond_string);
+
+  if (*exp == 0)
+    {
+      b->cond_string = NULL;
+      if (from_tty)
+	printf_filtered (_("Breakpoint %d now unconditional.\n"), b->number);
+    }
+  else
+    {
+      char *arg = exp;
+
+      /* I don't know if it matters whether this is the string the user
+	 typed in or the decompiled expression.  */
+      b->cond_string = xstrdup (arg);
+      b->condition_not_parsed = 0;
+      for (loc = b->loc; loc; loc = loc->next)
+	{
+	  arg = exp;
+	  loc->cond =
+	    parse_exp_1 (&arg, block_for_pc (loc->address), 0);
+	  if (*arg)
+	    error (_("Junk at end of expression"));
+	}
+    }
+
+  breakpoints_changed ();
+  observer_notify_breakpoint_modified (b->number);
+}
+
 /* condition N EXP -- set break condition of breakpoint N to EXP.  */
 
 static void
@@ -634,42 +682,7 @@ condition_command (char *arg, int from_tty)
   ALL_BREAKPOINTS (b)
     if (b->number == bnum)
       {
-	struct bp_location *loc = b->loc;
-	for (; loc; loc = loc->next)
-	  {
-	    if (loc->cond)
-	      {
-		xfree (loc->cond);
-		loc->cond = 0;
-	      }
-	  }
-	if (b->cond_string != NULL)
-	  xfree (b->cond_string);
-
-	if (*p == 0)
-	  {
-	    b->cond_string = NULL;
-	    if (from_tty)
-	      printf_filtered (_("Breakpoint %d now unconditional.\n"), bnum);
-	  }
-	else
-	  {
-	    arg = p;
-	    /* I don't know if it matters whether this is the string the user
-	       typed in or the decompiled expression.  */
-	    b->cond_string = xstrdup (arg);
-	    b->condition_not_parsed = 0;
-	    for (loc = b->loc; loc; loc = loc->next)
-	      {
-		arg = p;
-		loc->cond =
-		  parse_exp_1 (&arg, block_for_pc (loc->address), 0);
-		if (*arg)
-		  error (_("Junk at end of expression"));
-	      }
-	  }
-	breakpoints_changed ();
-	observer_notify_breakpoint_modified (b->number);
+	set_breakpoint_condition (b, p, from_tty);
 	return;
       }
 
@@ -1868,6 +1881,36 @@ create_longjmp_master_breakpoint (char *func_name)
   do_cleanups (old_chain);
 }
 
+/* Install a master breakpoint on the unwinder's debug hook.  */
+
+void
+create_exception_master_breakpoint (void)
+{
+  struct objfile *objfile;
+
+  ALL_OBJFILES (objfile)
+    {
+      struct minimal_symbol *debug_hook;
+
+      debug_hook = lookup_minimal_symbol_text ("_Unwind_DebugHook", objfile);
+      if (debug_hook != NULL)
+	{
+	  CORE_ADDR pc;
+	  struct breakpoint *b;
+
+	  pc = find_function_start_pc (get_objfile_arch (objfile),
+				       SYMBOL_VALUE_ADDRESS (debug_hook),
+				       SYMBOL_OBJ_SECTION (debug_hook));
+	  b = create_internal_breakpoint (get_objfile_arch (objfile),
+					  pc, bp_exception_master);
+	  b->addr_string = xstrdup ("_Unwind_DebugHook");
+	  b->enable_state = bp_disabled;
+	}
+    }
+
+  update_global_location_list (1);
+}
+
 void
 update_breakpoints_after_exec (void)
 {
@@ -1909,7 +1952,7 @@ update_breakpoints_after_exec (void)
     /* Thread event breakpoints must be set anew after an exec(),
        as must overlay event and longjmp master breakpoints.  */
     if (b->type == bp_thread_event || b->type == bp_overlay_event
-	|| b->type == bp_longjmp_master)
+	|| b->type == bp_longjmp_master || b->type == bp_exception_master)
       {
 	delete_breakpoint (b);
 	continue;
@@ -1924,7 +1967,8 @@ update_breakpoints_after_exec (void)
 
     /* Longjmp and longjmp-resume breakpoints are also meaningless
        after an exec.  */
-    if (b->type == bp_longjmp || b->type == bp_longjmp_resume)
+    if (b->type == bp_longjmp || b->type == bp_longjmp_resume
+	|| b->type == bp_exception || b->type == bp_exception_resume)
       {
 	delete_breakpoint (b);
 	continue;
@@ -1985,6 +2029,7 @@ update_breakpoints_after_exec (void)
   create_longjmp_master_breakpoint ("_longjmp");
   create_longjmp_master_breakpoint ("siglongjmp");
   create_longjmp_master_breakpoint ("_siglongjmp");
+  create_exception_master_breakpoint ();
 }
 
 int
@@ -2008,6 +2053,7 @@ detach_breakpoints (int pid)
     if (b->inserted)
       val |= remove_breakpoint_1 (b, mark_inserted);
   }
+  val |= target_detach_watchpoints ();
   do_cleanups (old_chain);
   return val;
 }
@@ -2107,12 +2153,14 @@ remove_breakpoint_1 (struct bp_location *b, insertion_state_t is)
 	return val;
       b->inserted = (is == mark_inserted);
     }
-  else if (b->loc_type == bp_loc_hardware_watchpoint)
+  /* bp_loc_hardware_watchpoint with mark_inserted is being handled by
+     target_detach_watchpoints.  */
+  else if (b->loc_type == bp_loc_hardware_watchpoint && is == mark_uninserted)
     {
       struct value *v;
       struct value *n;
 
-      b->inserted = (is == mark_inserted);
+      b->inserted = 0;
       val = target_remove_watchpoint (b->address, b->length, 
 				      b->watchpoint_type);
 
@@ -2892,6 +2940,12 @@ print_it_typical (bpstat bs)
       result = PRINT_NOTHING;
       break;
 
+    case bp_exception_master:
+      /* These should never be enabled.  */
+      printf_filtered (_("Exception Master Breakpoint: gdb should not stop!\n"));
+      result = PRINT_NOTHING;
+      break;
+
     case bp_watchpoint:
     case bp_hardware_watchpoint:
       annotate_watchpoint (b->number);
@@ -2979,6 +3033,8 @@ print_it_typical (bpstat bs)
     case bp_none:
     case bp_longjmp:
     case bp_longjmp_resume:
+    case bp_exception:
+    case bp_exception_resume:
     case bp_step_resume:
     case bp_watchpoint_scope:
     case bp_call_dummy:
@@ -3383,8 +3439,12 @@ bpstat_check_location (const struct bp_location *bl,
 
 /* If BS refers to a watchpoint, determine if the watched values
    has actually changed, and we should stop.  If not, set BS->stop
-   to 0.  */
-static void
+   to 0.
+   Return 0 for watchpoints which could not be the cause of this trap.
+   In such case PRINT_IT will be print_it_noop and STOP will be 0.
+   Otherwise return 1 but in such case it is not guaranteed whether this
+   breakpoint did or did not trigger this trap.  */
+static int
 bpstat_check_watchpoint (bpstat bs)
 {
   const struct bp_location *bl = bs->breakpoint_at;
@@ -3473,8 +3533,10 @@ bpstat_check_watchpoint (bpstat bs)
 	     anything for this watchpoint.  */
 	  bs->print_it = print_it_noop;
 	  bs->stop = 0;
+	  return 0;
 	}
     }
+  return 1;
 }
 
 
@@ -3588,6 +3650,8 @@ bpstat_stop_status (struct address_space *aspace,
 
       for (bl = b->loc; bl != NULL; bl = bl->next)
 	{
+	  bpstat bs_prev = bs;
+
 	  /* For hardware watchpoints, we look only at the first location.
 	     The watchpoint_check function will work on entire expression,
 	     not the individual locations.  For read watchopints, the
@@ -3605,6 +3669,7 @@ bpstat_stop_status (struct address_space *aspace,
 	  /* Come here if it's a watchpoint, or if the break address matches */
 
 	  bs = bpstat_alloc (bl, bs);	/* Alloc a bpstat to explain stop */
+	  gdb_assert (bs_prev->next == bs);
 
 	  /* Assume we stop.  Should we find watchpoint that is not actually
 	     triggered, or if condition of breakpoint is false, we'll reset
@@ -3612,12 +3677,22 @@ bpstat_stop_status (struct address_space *aspace,
 	  bs->stop = 1;
 	  bs->print = 1;
 
-	  bpstat_check_watchpoint (bs);
-	  if (!bs->stop)
-	    continue;
+	  if (!bpstat_check_watchpoint (bs))
+	    {
+	      /* Ensure bpstat_explains_signal stays false if this BL could not be
+		 the cause of this trap.  */
+
+	      gdb_assert (bs->print_it == print_it_noop);
+	      gdb_assert (!bs->stop);
+	      xfree (bs);
+	      bs = bs_prev;
+	      bs->next = NULL;
+	      continue;
+	    }
 
 	  if (b->type == bp_thread_event || b->type == bp_overlay_event
-	      || b->type == bp_longjmp_master)
+	      || b->type == bp_longjmp_master
+	      || b->type == bp_exception_master)
 	    /* We do not stop for these.  */
 	    bs->stop = 0;
 	  else
@@ -3826,6 +3901,7 @@ bpstat_what (bpstat bs)
   struct bpstat_what retval;
 
   retval.call_dummy = 0;
+  retval.is_longjmp = 0;
   for (; bs != NULL; bs = bs->next)
     {
       enum class bs_class = no_effect;
@@ -3872,10 +3948,15 @@ bpstat_what (bpstat bs)
 	    bs_class = no_effect;
 	  break;
 	case bp_longjmp:
+	case bp_exception:
 	  bs_class = long_jump;
+	  retval.is_longjmp = bs->breakpoint_at->owner->type == bp_longjmp;
 	  break;
 	case bp_longjmp_resume:
+	case bp_exception_resume:
 	  bs_class = long_resume;
+	  retval.is_longjmp
+	    = bs->breakpoint_at->owner->type == bp_longjmp_resume;
 	  break;
 	case bp_step_resume:
 	  if (bs->stop)
@@ -3898,6 +3979,7 @@ bpstat_what (bpstat bs)
 	case bp_thread_event:
 	case bp_overlay_event:
 	case bp_longjmp_master:
+	case bp_exception_master:
 	  bs_class = bp_nostop;
 	  break;
 	case bp_catchpoint:
@@ -4042,6 +4124,8 @@ print_one_breakpoint_location (struct breakpoint *b,
     {bp_access_watchpoint, "acc watchpoint"},
     {bp_longjmp, "longjmp"},
     {bp_longjmp_resume, "longjmp resume"},
+    {bp_exception, "exception"},
+    {bp_exception_resume, "exception resume"},
     {bp_step_resume, "step resume"},
     {bp_watchpoint_scope, "watchpoint scope"},
     {bp_call_dummy, "call dummy"},
@@ -4049,6 +4133,7 @@ print_one_breakpoint_location (struct breakpoint *b,
     {bp_thread_event, "thread events"},
     {bp_overlay_event, "overlay events"},
     {bp_longjmp_master, "longjmp master"},
+    {bp_exception_master, "exception master"},
     {bp_catchpoint, "catchpoint"},
     {bp_tracepoint, "tracepoint"},
     {bp_fast_tracepoint, "fast tracepoint"},
@@ -4173,6 +4258,8 @@ print_one_breakpoint_location (struct breakpoint *b,
       case bp_finish:
       case bp_longjmp:
       case bp_longjmp_resume:
+      case bp_exception:
+      case bp_exception_resume:
       case bp_step_resume:
       case bp_watchpoint_scope:
       case bp_call_dummy:
@@ -4180,6 +4267,7 @@ print_one_breakpoint_location (struct breakpoint *b,
       case bp_thread_event:
       case bp_overlay_event:
       case bp_longjmp_master:
+      case bp_exception_master:
       case bp_tracepoint:
       case bp_fast_tracepoint:
       case bp_jit_event:
@@ -4816,6 +4904,8 @@ allocate_bp_location (struct breakpoint *bpt)
     case bp_finish:
     case bp_longjmp:
     case bp_longjmp_resume:
+    case bp_exception:
+    case bp_exception_resume:
     case bp_step_resume:
     case bp_watchpoint_scope:
     case bp_call_dummy:
@@ -4824,6 +4914,7 @@ allocate_bp_location (struct breakpoint *bpt)
     case bp_overlay_event:
     case bp_jit_event:
     case bp_longjmp_master:
+    case bp_exception_master:
       loc->loc_type = bp_loc_software_breakpoint;
       break;
     case bp_hardware_breakpoint:
@@ -5012,8 +5103,7 @@ make_breakpoint_permanent (struct breakpoint *b)
 }
 
 /* Call this routine when stepping and nexting to enable a breakpoint
-   if we do a longjmp() in THREAD.  When we hit that breakpoint, call
-   set_longjmp_resume_breakpoint() to figure out where we are going. */
+   if we do a longjmp() or 'throw' in THREAD.  */
 
 void
 set_longjmp_breakpoint (int thread)
@@ -5026,10 +5116,11 @@ set_longjmp_breakpoint (int thread)
      clones of those and enable them for the requested thread.  */
   ALL_BREAKPOINTS_SAFE (b, temp)
     if (b->pspace == current_program_space
-	&& b->type == bp_longjmp_master)
+	&& (b->type == bp_longjmp_master
+	    || b->type == bp_exception_master))
       {
 	struct breakpoint *clone = clone_momentary_breakpoint (b);
-	clone->type = bp_longjmp;
+	clone->type = b->type == bp_longjmp_master ? bp_longjmp : bp_exception;
 	clone->thread = thread;
       }
 }
@@ -5041,7 +5132,7 @@ delete_longjmp_breakpoint (int thread)
   struct breakpoint *b, *temp;
 
   ALL_BREAKPOINTS_SAFE (b, temp)
-    if (b->type == bp_longjmp)
+    if (b->type == bp_longjmp || b->type == bp_exception)
       {
 	if (b->thread == thread)
 	  delete_breakpoint (b);
@@ -6116,6 +6207,8 @@ mention (struct breakpoint *b)
       case bp_finish:
       case bp_longjmp:
       case bp_longjmp_resume:
+      case bp_exception:
+      case bp_exception_resume:
       case bp_step_resume:
       case bp_call_dummy:
       case bp_watchpoint_scope:
@@ -6124,6 +6217,7 @@ mention (struct breakpoint *b)
       case bp_overlay_event:
       case bp_jit_event:
       case bp_longjmp_master:
+      case bp_exception_master:
 	break;
       }
 
@@ -7509,6 +7603,7 @@ struct until_break_command_continuation_args
 {
   struct breakpoint *breakpoint;
   struct breakpoint *breakpoint2;
+  int thread_num;
 };
 
 /* This function is called by fetch_inferior_event via the
@@ -7523,6 +7618,7 @@ until_break_command_continuation (void *arg)
   delete_breakpoint (a->breakpoint);
   if (a->breakpoint2)
     delete_breakpoint (a->breakpoint2);
+  delete_longjmp_breakpoint (a->thread_num);
 }
 
 void
@@ -7534,6 +7630,8 @@ until_break_command (char *arg, int from_tty, int anywhere)
   struct breakpoint *breakpoint;
   struct breakpoint *breakpoint2 = NULL;
   struct cleanup *old_chain;
+  int thread;
+  struct thread_info *tp;
 
   clear_proceed_status ();
 
@@ -7572,6 +7670,9 @@ until_break_command (char *arg, int from_tty, int anywhere)
 
   old_chain = make_cleanup_delete_breakpoint (breakpoint);
 
+  tp = inferior_thread ();
+  thread = tp->num;
+
   /* Keep within the current frame, or in frames called by the current
      one.  */
 
@@ -7584,6 +7685,10 @@ until_break_command (char *arg, int from_tty, int anywhere)
 					      frame_unwind_caller_id (frame),
 					      bp_until);
       make_cleanup_delete_breakpoint (breakpoint2);
+
+      set_longjmp_breakpoint (thread);
+      tp->initiating_frame = frame_unwind_caller_id (frame);
+      make_cleanup (delete_longjmp_breakpoint_cleanup, &thread);
     }
 
   proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
@@ -7600,6 +7705,7 @@ until_break_command (char *arg, int from_tty, int anywhere)
 
       args->breakpoint = breakpoint;
       args->breakpoint2 = breakpoint2;
+      args->thread_num = thread;
 
       discard_cleanups (old_chain);
       add_continuation (inferior_thread (),
@@ -8796,6 +8902,7 @@ delete_command (char *arg, int from_tty)
 	    && b->type != bp_thread_event
 	    && b->type != bp_overlay_event
 	    && b->type != bp_longjmp_master
+	    && b->type != bp_exception_master
 	    && b->number >= 0)
 	  {
 	    breaks_to_delete = 1;
@@ -8815,6 +8922,7 @@ delete_command (char *arg, int from_tty)
 		&& b->type != bp_jit_event
 		&& b->type != bp_overlay_event
 		&& b->type != bp_longjmp_master
+		&& b->type != bp_exception_master
 		&& b->number >= 0)
 	      delete_breakpoint (b);
 	  }
@@ -9125,6 +9233,7 @@ breakpoint_re_set_one (void *bint)
 	 reset later by breakpoint_re_set.  */
     case bp_overlay_event:
     case bp_longjmp_master:
+    case bp_exception_master:
       delete_breakpoint (b);
       break;
 
@@ -9147,6 +9256,8 @@ breakpoint_re_set_one (void *bint)
     case bp_step_resume:
     case bp_longjmp:
     case bp_longjmp_resume:
+    case bp_exception:
+    case bp_exception_resume:
     case bp_jit_event:
       break;
     }
@@ -9189,6 +9300,7 @@ breakpoint_re_set (void)
   create_longjmp_master_breakpoint ("_longjmp");
   create_longjmp_master_breakpoint ("siglongjmp");
   create_longjmp_master_breakpoint ("_siglongjmp");
+  create_exception_master_breakpoint ();
 }
 
 /* Reset the thread number of this breakpoint:
@@ -10187,6 +10299,22 @@ all_tracepoints ()
   return tp_vec;
 }
 
+/* Call type_mark_used for any TYPEs referenced from this GDB source file.  */
+
+static void
+breakpoint_types_mark_used (void)
+{
+  struct breakpoint *b;
+
+  ALL_BREAKPOINTS (b)
+    {
+      if (b->exp)
+	exp_types_mark_used (b->exp);
+      if (b->val)
+	type_mark_used (value_type (b->val));
+    }
+}
+
 
 /* This help string is used for the break, hbreak, tbreak and thbreak commands.
    It is defined as a macro to prevent duplication.
@@ -10731,4 +10859,5 @@ inferior in all-stop mode, gdb behaves as if always-inserted mode is off."),
   automatic_hardware_breakpoints = 1;
 
   observer_attach_about_to_proceed (breakpoint_about_to_proceed);
+  observer_attach_mark_used (breakpoint_types_mark_used);
 }
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 6b373a3..59aa412 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -56,6 +56,13 @@ enum bptype
     bp_longjmp,			/* secret breakpoint to find longjmp() */
     bp_longjmp_resume,		/* secret breakpoint to escape longjmp() */
 
+    /* An internal breakpoint that is installed on the unwinder's
+       debug hook.  */
+    bp_exception,
+    /* An internal breakpoint that is set at the point where an
+       exception will land.  */
+    bp_exception_resume,
+
     /* Used by wait_for_inferior for stepping over subroutine calls, for
        stepping over signal handlers, and for skipping prologues.  */
     bp_step_resume,
@@ -118,6 +125,9 @@ enum bptype
 
     bp_longjmp_master,
 
+    /* Like bp_longjmp_master, but for exceptions.  */
+    bp_exception_master,
+
     bp_catchpoint,
 
     bp_tracepoint,
@@ -603,6 +613,10 @@ struct bpstat_what
        continuing from a call dummy without popping the frame is not a
        useful one).  */
     int call_dummy;
+
+    /* Used for BPSTAT_WHAT_SET_LONGJMP_RESUME.  True if we are
+       handling a longjmp, false if we are handling an exception.  */
+    int is_longjmp;
   };
 
 /* The possible return values for print_bpstat, print_it_normal,
@@ -985,6 +999,9 @@ extern int catching_syscall_number (int syscall_number);
 /* Tell a breakpoint to be quiet.  */
 extern void make_breakpoint_silent (struct breakpoint *);
 
+/* Set break condition of breakpoint B to EXP.  */
+extern void set_breakpoint_condition (struct breakpoint *b, char *exp, int from_tty);
+
 /* Return a tracepoint with the given number if found.  */
 extern struct breakpoint *get_tracepoint (int num);
 
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 845771c..7a74d7e 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -186,6 +186,7 @@ static struct stoken operator_stoken (const char *);
 %token <tsval> STRING
 %token <tsval> CHAR
 %token <ssym> NAME /* BLOCKNAME defined below to give it higher precedence. */
+%token <ssym> UNKNOWN_CPP_NAME
 %token <voidval> COMPLETE
 %token <tsym> TYPENAME
 %type <sval> name
@@ -391,6 +392,30 @@ exp	:	exp '('
 			  write_exp_elt_opcode (OP_FUNCALL); }
 	;
 
+exp	:	UNKNOWN_CPP_NAME '('
+			{
+
+			 /* This could potentially be a an argument defined
+			    lookup function (Koenig).  */
+			  write_exp_elt_opcode (OP_ADL_FUNC);
+			  write_exp_elt_block (expression_context_block);
+			  write_exp_elt_sym (NULL); /* Place holder */
+			  write_exp_string ($1.stoken);
+			  write_exp_elt_opcode (OP_ADL_FUNC);
+
+			/* This is to save the value of arglist_len
+			   being accumulated by an outer function call.  */
+
+			  start_arglist ();
+			}
+		arglist ')'	%prec ARROW
+			{
+			  write_exp_elt_opcode (OP_FUNCALL);
+			  write_exp_elt_longcst ((LONGEST) end_arglist ());
+			  write_exp_elt_opcode (OP_FUNCALL);
+			}
+	;
+
 lcurly	:	'{'
 			{ start_arglist (); }
 	;
@@ -418,6 +443,24 @@ exp     :       exp '(' nonempty_typelist ')' const_or_volatile
 			}
 	;
 
+/*
+exp     :       BLOCKNAME '(' nonempty_typelist ')'
+			{ int i;
+			  write_exp_elt_opcode (TYPE_INSTANCE_LOOKUP);
+			  write_exp_elt_sym ($1.sym);
+			  write_exp_elt_opcode (TYPE_INSTANCE_LOOKUP);
+
+			  write_exp_elt_opcode (TYPE_INSTANCE);
+			  write_exp_elt_longcst ((LONGEST) $<ivec>3[0]);
+			  for (i = 0; i < $<ivec>3[0]; ++i)
+			    write_exp_elt_type ($<tvec>3[i + 1]);
+			  write_exp_elt_longcst((LONGEST) $<ivec>3[0]);
+			  write_exp_elt_opcode (TYPE_INSTANCE);
+			  do_cleanups (typelist_cleanup);
+			}
+	;
+*/
+
 rcurly	:	'}'
 			{ $$ = end_arglist () - 1; }
 	;
@@ -785,12 +828,13 @@ qualified_name:	typebase COLONCOLON name
 	;
 
 variable:	qualified_name
+	|	COLONCOLON qualified_name
 	|	COLONCOLON name
 			{
 			  char *name = copy_name ($2);
 			  struct symbol *sym;
 			  struct minimal_symbol *msymbol;
-
+			  
 			  sym =
 			    lookup_symbol (name, (const struct block *) NULL,
 					   VAR_DOMAIN, (int *) NULL);
@@ -1286,6 +1330,7 @@ name	:	NAME { $$ = $1.stoken; }
 	|	BLOCKNAME { $$ = $1.stoken; }
 	|	TYPENAME { $$ = $1.stoken; }
 	|	NAME_OR_INT  { $$ = $1.stoken; }
+	|	UNKNOWN_CPP_NAME  { $$ = $1.stoken; }	
 	|	operator { $$ = $1; }
 	;
 
@@ -1298,6 +1343,15 @@ name_not_typename :	NAME
    context where only a name could occur, this might be useful.
   	|	NAME_OR_INT
  */
+  	|	UNKNOWN_CPP_NAME 
+	|	operator
+			{
+			  $$.stoken = $1;
+			  $$.sym = lookup_symbol ($1.ptr,
+						  expression_context_block,
+						  VAR_DOMAIN,
+						  &$$.is_a_field_of_this);
+			}
 	;
 
 %%
@@ -2033,6 +2087,13 @@ static int last_was_structop;
 static int
 yylex (void)
 {
+  /* name_prefix stores the full qualification of a variable that is
+     specified in the expression. It is used to eleminate confusion 
+     during lookup.*/
+  static char *name_prefix = NULL;
+  static int name_prefix_len = 0;
+  static int terminate_prefix = 0;
+  
   int c;
   int namelen;
   unsigned int i;
@@ -2041,9 +2102,19 @@ yylex (void)
   char *copy;
 
   last_was_structop = 0;
-
+  
  retry:
-
+  
+  if (terminate_prefix
+      || lexptr != name_prefix + name_prefix_len)
+    {
+      /* Some token was skipped, so clear name_prefix. */
+      name_prefix = NULL;
+      name_prefix_len = 0;
+    }
+    
+  terminate_prefix = 1;
+  	  	  
   /* Check if this is a macro invocation that we need to expand.  */
   if (! scanning_macro_expansion ())
     {
@@ -2079,10 +2150,19 @@ yylex (void)
 	    && parse_language->la_language != language_cplus)
 	  break;
 
+	if (tokentab2[i].token == COLONCOLON)
+	  {
+	    name_prefix_len += 2;
+	    terminate_prefix = 0;
+	    if (name_prefix == NULL)
+	      name_prefix = lexptr;
+	  }
+
 	lexptr += 2;
 	yylval.opcode = tokentab2[i].opcode;
 	if (in_parse_field && tokentab2[i].token == ARROW)
 	  last_was_structop = 1;
+	
 	return tokentab2[i].token;
       }
 
@@ -2111,6 +2191,8 @@ yylex (void)
         return 0;
 
     case ' ':
+      name_prefix_len++;
+      terminate_prefix = 0;
     case '\t':
     case '\n':
       lexptr++;
@@ -2268,11 +2350,13 @@ yylex (void)
     error ("Invalid character '%c' in expression.", c);
 
   /* It's a name.  See how long it is.  */
+  
   namelen = 0;
   for (c = tokstart[namelen];
        (c == '_' || c == '$' || (c >= '0' && c <= '9')
 	|| (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '<');)
     {
+    
       /* Template parameter lists are part of the name.
 	 FIXME: This mishandles `print $a<4&&$a>3'.  */
 
@@ -2357,14 +2441,33 @@ yylex (void)
      currently as names of types; NAME for other symbols.
      The caller is not constrained to care about the distinction.  */
   {
+    char *tmp = copy;
     struct symbol *sym;
     int is_a_field_of_this = 0;
     int hextype;
 
-    sym = lookup_symbol (copy, expression_context_block,
+    if (name_prefix != NULL)
+      {
+	tmp = alloca (name_prefix_len + namelen + 1);
+	memcpy (tmp, name_prefix, name_prefix_len + namelen);
+	tmp[name_prefix_len + namelen] = '\0';
+      }
+
+    sym = lookup_symbol (tmp, expression_context_block,
 			 VAR_DOMAIN,
 			 parse_language->la_language == language_cplus
 			 ? &is_a_field_of_this : (int *) NULL);
+			 
+    /* Keep this name as the prefix for the next name. */
+    if (sym)
+      {
+	if (name_prefix == NULL)
+	  name_prefix = tokstart;
+
+	name_prefix_len += namelen;
+	terminate_prefix = 0;
+      }
+
     /* Call lookup_symtab, not lookup_partial_symtab, in case there are
        no psymtabs (coff, xcoff, or some future change to blow away the
        psymtabs once once symbols are read).  */
@@ -2423,6 +2526,12 @@ yylex (void)
     yylval.ssym.is_a_field_of_this = is_a_field_of_this;
     if (in_parse_field && *lexptr == '\0')
       saw_name_at_eof = 1;
+        
+    if (sym == NULL 
+        && parse_language->la_language == language_cplus
+        && !lookup_minimal_symbol (tmp, NULL, NULL))
+      return UNKNOWN_CPP_NAME;
+
     return NAME;
   }
 }
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index d620881..34cb34a 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -1140,6 +1140,7 @@ static const struct exp_descriptor exp_descriptor_c =
 {
   print_subexp_standard,
   operator_length_standard,
+  operator_check_standard,
   op_name_standard,
   dump_subexp_body_standard,
   evaluate_subexp_c
diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c
index ed98381..3061ab7 100644
--- a/gdb/c-typeprint.c
+++ b/gdb/c-typeprint.c
@@ -32,6 +32,7 @@
 #include "c-lang.h"
 #include "typeprint.h"
 #include "cp-abi.h"
+#include "jv-lang.h"
 
 #include "gdb_string.h"
 #include <errno.h>
@@ -40,8 +41,6 @@ static void cp_type_print_method_args (struct type *mtype, char *prefix,
 				       char *varstring, int staticp,
 				       struct ui_file *stream);
 
-static void c_type_print_args (struct type *, struct ui_file *);
-
 static void cp_type_print_derivation_info (struct ui_file *, struct type *);
 
 static void c_type_print_varspec_prefix (struct type *, struct ui_file *, int,
@@ -197,6 +196,23 @@ cp_type_print_method_args (struct type *mtype, char *prefix, char *varstring,
     fprintf_filtered (stream, "void");
 
   fprintf_filtered (stream, ")");
+
+  /* For non-static methods, read qualifiers from the type of
+     THIS.  */
+  if (!staticp)
+    {
+      struct type *domain;
+
+      gdb_assert (nargs > 0);
+      gdb_assert (TYPE_CODE (args[0].type) == TYPE_CODE_PTR);
+      domain = TYPE_TARGET_TYPE (args[0].type);
+
+      if (TYPE_CONST (domain))
+	fprintf_filtered (stream, " const");
+
+      if (TYPE_VOLATILE (domain))
+	fprintf_filtered (stream, " volatile");
+    }
 }
 
 
@@ -353,10 +369,14 @@ c_type_print_modifier (struct type *type, struct ui_file *stream,
 
 /* Print out the arguments of TYPE, which should have TYPE_CODE_METHOD
    or TYPE_CODE_FUNC, to STREAM.  Artificial arguments, such as "this"
-   in non-static methods, are displayed.  */
+   in non-static methods, are displayed if SHOW_ARTIFICIAL is
+   non-zero. LANGUAGE is the language in which TYPE was defined.  This is
+   a necessary evil since this code is used by the C, C++, and Java
+   backends. */
 
-static void
-c_type_print_args (struct type *type, struct ui_file *stream)
+void
+c_type_print_args (struct type *type, struct ui_file *stream,
+		   int show_artificial, enum language language)
 {
   int i, len;
   struct field *args;
@@ -368,13 +388,19 @@ c_type_print_args (struct type *type, struct ui_file *stream)
 
   for (i = 0; i < TYPE_NFIELDS (type); i++)
     {
+      if (TYPE_FIELD_ARTIFICIAL (type, i) && !show_artificial)
+	continue;
+
       if (printed_any)
 	{
 	  fprintf_filtered (stream, ", ");
 	  wrap_here ("    ");
 	}
 
-      c_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0);
+      if (language == language_java)
+	java_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0);
+      else
+	c_print_type (TYPE_FIELD_TYPE (type, i), "", stream, -1, 0);
       printed_any = 1;
     }
 
@@ -558,7 +584,13 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
 	fprintf_filtered (stream, ")");
 
       fprintf_filtered (stream, "[");
-      if (TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0
+      if (TYPE_RANGE_DATA (TYPE_INDEX_TYPE (type))->high.kind
+	  != RANGE_BOUND_KIND_CONSTANT)
+	{
+	  /* No _() - printed sources should not be locale dependent.  */
+	  fprintf_filtered (stream, "variable");
+	}
+      else if (TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0
 	&& !TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type))
 	fprintf_filtered (stream, "%d",
 			  (TYPE_LENGTH (type)
@@ -591,7 +623,7 @@ c_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
       if (passed_a_ptr)
 	fprintf_filtered (stream, ")");
       if (!demangled_args)
-	c_type_print_args (type, stream);
+	c_type_print_args (type, stream, 1, language_c);
       c_type_print_varspec_suffix (TYPE_TARGET_TYPE (type), stream, show,
 				   passed_a_ptr, 0);
       break;
diff --git a/gdb/coffread.c b/gdb/coffread.c
index ba413ad..44676a8 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -2123,6 +2123,7 @@ static struct sym_fns coff_sym_fns =
   coff_new_init,		/* sym_new_init: init anything gbl to entire symtab */
   coff_symfile_init,		/* sym_init: read initial info, setup for sym_read() */
   coff_symfile_read,		/* sym_read: read a symbol file into symtab */
+  NULL,				/* sym_read_psymbols */
   coff_symfile_finish,		/* sym_finish: finished with file, cleanup */
   default_symfile_offsets,	/* sym_offsets:  xlate external to internal form */
   default_symfile_segments,	/* sym_segments: Get segment information from
diff --git a/gdb/config.in b/gdb/config.in
index ebde876..907b275 100644
--- a/gdb/config.in
+++ b/gdb/config.in
@@ -46,11 +46,10 @@
    language is requested. */
 #undef ENABLE_NLS
 
-/* look for global separate data files in this path [DATADIR/gdb] */
+/* Global directory for GDB data files. */
 #undef GDB_DATADIR
 
-/* Define if the gdb-datadir directory should be relocated when GDB is moved.
-   */
+/* Define if GDB datadir should be relocated when GDB is moved. */
 #undef GDB_DATADIR_RELOCATABLE
 
 /* Define to be a string naming the default host character set. */
@@ -653,6 +652,9 @@
    'ptrdiff_t'. */
 #undef PTRDIFF_T_SUFFIX
 
+/* Define to install path for Python sources */
+#undef PYTHONDIR
+
 /* Relocated directory for source files. */
 #undef RELOC_SRCDIR
 
diff --git a/gdb/configure b/gdb/configure
index 1983d04..8dca37e 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -676,6 +676,8 @@ REPORT_BUGS_TO
 PKGVERSION
 TARGET_OBS
 subdirs
+pythondir
+GDB_DATADIR_PATH
 GDB_DATADIR
 DEBUGDIR
 am__fastdepCC_FALSE
@@ -885,6 +887,7 @@ enable_dependency_tracking
 with_separate_debug_dir
 with_gdb_datadir
 with_relocated_sources
+with_pythondir
 enable_targets
 enable_64_bit_bfd
 enable_gdbcli
@@ -1586,6 +1589,10 @@ Optional Packages:
                           [DATADIR/gdb]
   --with-relocated-sources=PATH
                           automatically relocate this path for source files
+  --with-gdb-datadir      look for global separate data files in this path
+                          [DATADIR/gdb]
+  --with-pythondir        install Python data files in this path
+                          [DATADIR/gdb/python]
   --with-libunwind        use libunwind frame unwinding support
   --with-curses           use the curses library instead of the termcap
                           library
@@ -6866,6 +6873,73 @@ _ACEOF
 fi
 
 
+# GDB's datadir relocation
+
+gdbdatadir=${datadir}/gdb
+
+
+# Check whether --with-gdb-datadir was given.
+if test "${with_gdb_datadir+set}" = set; then :
+  withval=$with_gdb_datadir; gdbdatadir="${withval}"
+fi
+
+
+
+  test "x$prefix" = xNONE && prefix="$ac_default_prefix"
+  test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+  ac_define_dir=`eval echo $gdbdatadir`
+  ac_define_dir=`eval echo $ac_define_dir`
+
+cat >>confdefs.h <<_ACEOF
+#define GDB_DATADIR "$ac_define_dir"
+_ACEOF
+
+
+
+if test "x$exec_prefix" = xNONE || test "x$exec_prefix" = 'x${prefix}'; then
+  if test "x$prefix" = xNONE; then
+    test_prefix=/usr/local
+  else
+    test_prefix=$prefix
+  fi
+else
+  test_prefix=$exec_prefix
+fi
+
+case ${gdbdatadir} in
+  "${test_prefix}"|"${test_prefix}/"*|\
+  '${exec_prefix}'|'${exec_prefix}/'*)
+
+$as_echo "#define GDB_DATADIR_RELOCATABLE 1" >>confdefs.h
+
+  ;;
+esac
+GDB_DATADIR_PATH=${gdbdatadir}
+
+
+
+# Check whether --with-pythondir was given.
+if test "${with_pythondir+set}" = set; then :
+  withval=$with_pythondir; pythondir="${withval}"
+else
+  pythondir=no
+fi
+
+
+# If the user passed in a path, define it.  Otherwise, compute it at
+# runtime based on the possibly-relocatable datadir.
+if test "$pythondir" = "no"; then
+  pythondir='$(GDB_DATADIR_PATH)/python'
+else
+
+cat >>confdefs.h <<_ACEOF
+#define PYTHONDIR "$pythondir"
+_ACEOF
+
+fi
+
+
+
 
 
 subdirs="$subdirs doc testsuite"
@@ -9604,6 +9678,8 @@ $as_echo "#define HAVE_PYTHON 1" >>confdefs.h
   CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)"
   CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)"
   CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)"
+  CONFIG_INSTALL="$CONFIG_INSTALL install-python"
+  CONFIG_UNINSTALL="$CONFIG_UNINSTALL uninstall-python"
   ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
 
   # Flags needed to compile Python code (taken from python-config --cflags).
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 6f873b5..77985c8 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -108,6 +108,51 @@ AS_HELP_STRING([--with-relocated-sources=PATH], [automatically relocate this pat
               [Relocated directory for source files. ])
 ])
 
+# GDB's datadir relocation
+
+gdbdatadir=${datadir}/gdb
+
+AC_ARG_WITH([gdb-datadir],
+  [AS_HELP_STRING([--with-gdb-datadir],
+                  [look for global separate data files in this path [DATADIR/gdb]])], [gdbdatadir="${withval}"])
+
+AC_DEFINE_DIR(GDB_DATADIR, gdbdatadir,
+              [Global directory for GDB data files. ])
+
+if test "x$exec_prefix" = xNONE || test "x$exec_prefix" = 'x${prefix}'; then
+  if test "x$prefix" = xNONE; then
+    test_prefix=/usr/local
+  else
+    test_prefix=$prefix
+  fi
+else
+  test_prefix=$exec_prefix
+fi
+
+case ${gdbdatadir} in
+  "${test_prefix}"|"${test_prefix}/"*|\
+  '${exec_prefix}'|'${exec_prefix}/'*)
+    AC_DEFINE(GDB_DATADIR_RELOCATABLE, 1, [Define if GDB datadir should be relocated when GDB is moved.])
+  ;;
+esac
+GDB_DATADIR_PATH=${gdbdatadir}
+AC_SUBST(GDB_DATADIR_PATH)
+
+AC_ARG_WITH([pythondir],
+  [AS_HELP_STRING([--with-pythondir],
+                  [install Python data files in this path [DATADIR/gdb/python]])], [pythondir="${withval}"], [pythondir=no])
+
+# If the user passed in a path, define it.  Otherwise, compute it at
+# runtime based on the possibly-relocatable datadir.
+if test "$pythondir" = "no"; then
+  pythondir='$(GDB_DATADIR_PATH)/python'
+else
+  AC_DEFINE_UNQUOTED(PYTHONDIR, "$pythondir",
+      [Define to install path for Python sources])
+fi
+AC_SUBST(pythondir)
+
+
 AC_CONFIG_SUBDIRS(doc testsuite)
 
 # Check whether to support alternative target configurations
@@ -674,6 +719,8 @@ if test "${have_libpython}" = yes; then
   CONFIG_OBS="$CONFIG_OBS \$(SUBDIR_PYTHON_OBS)"
   CONFIG_DEPS="$CONFIG_DEPS \$(SUBDIR_PYTHON_DEPS)"
   CONFIG_SRCS="$CONFIG_SRCS \$(SUBDIR_PYTHON_SRCS)"
+  CONFIG_INSTALL="$CONFIG_INSTALL install-python"
+  CONFIG_UNINSTALL="$CONFIG_UNINSTALL uninstall-python"
   ENABLE_CFLAGS="$ENABLE_CFLAGS \$(SUBDIR_PYTHON_CFLAGS)"
 
   # Flags needed to compile Python code (taken from python-config --cflags).
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 62e6683..2b9bb2f 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -40,7 +40,7 @@ alpha*-*-osf*)
 alpha*-*-linux*)
 	# Target: Little-endian Alpha running Linux
 	gdb_target_obs="alpha-tdep.o alpha-mdebug-tdep.o alpha-linux-tdep.o \
-			solib.o solib-svr4.o"
+			solib.o solib-svr4.o linux-tdep.o"
 	;;
 alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu)
 	# Target: FreeBSD/alpha
@@ -67,7 +67,7 @@ alpha*-*-*)
 am33_2.0*-*-linux*)
 	# Target: Matsushita mn10300 (AM33) running Linux
 	gdb_target_obs="mn10300-tdep.o mn10300-linux-tdep.o corelow.o \
-			solib.o solib-svr4.o"
+			solib.o solib-svr4.o linux-tdep.o"
 	;;
 
 arm*-wince-pe | arm*-*-mingw32ce*)
@@ -233,7 +233,7 @@ i[34567]86-*-*)
 
 ia64-*-linux*)
 	# Target: Intel IA-64 running GNU/Linux
-	gdb_target_obs="ia64-tdep.o ia64-linux-tdep.o \
+	gdb_target_obs="ia64-tdep.o ia64-linux-tdep.o linux-tdep.o \
 			solib.o solib-svr4.o symfile-mem.o"
 	build_gdbserver=yes
 	;;
@@ -263,7 +263,8 @@ m32c-*-*)
 m32r*-*-linux*)
 	# Target: Renesas M32R running GNU/Linux
 	gdb_target_obs="m32r-tdep.o m32r-linux-tdep.o remote-m32r-sdi.o \
-			glibc-tdep.o solib.o solib-svr4.o symfile-mem.o"
+			glibc-tdep.o solib.o solib-svr4.o symfile-mem.o \
+			linux-tdep.o"
 	gdb_sim=../sim/m32r/libsim.a
 	build_gdbserver=yes
 	;;
@@ -317,7 +318,7 @@ microblaze*-linux-*)
 	# Target: Xilinx MicroBlaze running Linux
 	gdb_target_obs="microblaze-tdep.o microblaze-linux-tdep.o microblaze-rom.o \
 			monitor.o dsrec.o solib.o solib-svr4.o corelow.o \
-			symfile-mem.o"
+			symfile-mem.o linux-tdep.o"
 	gdb_sim=../sim/microblaze/libsim.a
 	;;
 microblaze*-xilinx-*)
@@ -337,7 +338,8 @@ mips*-sgi-irix6*)
 mips*-*-linux*)
 	# Target: Linux/MIPS
 	gdb_target_obs="mips-tdep.o mips-linux-tdep.o glibc-tdep.o \
-			corelow.o solib.o solib-svr4.o symfile-mem.o"
+			corelow.o solib.o solib-svr4.o symfile-mem.o \
+			linux-tdep.o"
 	gdb_sim=../sim/mips/libsim.a
 	build_gdbserver=yes
 	;;
@@ -427,7 +429,7 @@ sh*-*-linux*)
 	# Target: GNU/Linux Super-H
 	gdb_target_obs="sh-tdep.o sh64-tdep.o sh-linux-tdep.o monitor.o \
 			dsrec.o solib.o solib-svr4.o symfile-mem.o \
-			glibc-tdep.o corelow.o"
+			glibc-tdep.o corelow.o linux-tdep.o"
 	gdb_sim=../sim/sh/libsim.a
 	build_gdbserver=yes
 	;;
@@ -455,7 +457,8 @@ sh*)
 sparc-*-linux*)
 	# Target: GNU/Linux SPARC
 	gdb_target_obs="sparc-tdep.o sparc-sol2-tdep.o sol2-tdep.o \
-			sparc-linux-tdep.o solib.o solib-svr4.o symfile-mem.o"
+			sparc-linux-tdep.o solib.o solib-svr4.o symfile-mem.o \
+			linux-tdep.o"
 	if test "x$enable_64_bit_bfd" = "xyes"; then
 	    # Target: GNU/Linux UltraSPARC
 	    gdb_target_obs="sparc64-tdep.o sparc64-sol2-tdep.o \
@@ -466,7 +469,7 @@ sparc64-*-linux*)
 	# Target: GNU/Linux UltraSPARC
 	gdb_target_obs="sparc64-tdep.o sparc64-sol2-tdep.o sol2-tdep.o \
 			sparc64-linux-tdep.o sparc-tdep.o sparc-sol2-tdep.o \
-			sparc-linux-tdep.o solib.o solib-svr4.o"
+			sparc-linux-tdep.o solib.o solib-svr4.o linux-tdep.o"
 	build_gdbserver=yes
 	;;
 sparc*-*-freebsd* | sparc*-*-kfreebsd*-gnu)
@@ -601,7 +604,8 @@ x86_64-*-openbsd*)
 xtensa*-*-linux*)	gdb_target=linux
 	# Target: GNU/Linux Xtensa
 	gdb_target_obs="xtensa-tdep.o xtensa-config.o xtensa-linux-tdep.o \
-			solib.o solib-svr4.o corelow.o symfile-mem.o"
+			solib.o solib-svr4.o corelow.o symfile-mem.o \
+			linux-tdep.o"
 	build_gdbserver=yes
 	;;
 xtensa*)
diff --git a/gdb/cp-name-parser.y b/gdb/cp-name-parser.y
index 81f6a5d..097db65 100644
--- a/gdb/cp-name-parser.y
+++ b/gdb/cp-name-parser.y
@@ -389,7 +389,7 @@ function
 		|	colon_ext_only function_arglist start_opt
 			{ $$ = fill_comp (DEMANGLE_COMPONENT_TYPED_NAME, $1, $2.comp);
 			  if ($3) $$ = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $3); }
-
+		|	colon_ext_only
 		|	conversion_op_name start_opt
 			{ $$ = $1.comp;
 			  if ($2) $$ = fill_comp (DEMANGLE_COMPONENT_LOCAL_NAME, $$, $2); }
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index 5e894d4..6325ead 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -34,14 +34,17 @@
 #include "buildsym.h"
 
 static struct symbol *lookup_namespace_scope (const char *name,
-					      const char *linkage_name,
 					      const struct block *block,
 					      const domain_enum domain,
 					      const char *scope,
 					      int scope_len);
 
+static struct symbol *cp_lookup_symbol_in_namespace (const char *namespace,
+                                                     const char *name,
+                                                     const struct block *block,
+                                                     const domain_enum domain);
+
 static struct symbol *lookup_symbol_file (const char *name,
-					  const char *linkage_name,
 					  const struct block *block,
 					  const domain_enum domain,
 					  int anonymous_namespace);
@@ -117,7 +120,7 @@ cp_scan_for_anonymous_namespaces (const struct symbol *symbol)
 		 anonymous namespace.  So add symbols in it to the
 		 namespace given by the previous component if there is
 		 one, or to the global namespace if there isn't.  */
-	      cp_add_using_directive (dest, src, NULL);
+	      cp_add_using_directive (dest, src, NULL, "", 0);
 	    }
 	  /* The "+ 2" is for the "::".  */
 	  previous_component = next_component + 2;
@@ -132,7 +135,8 @@ cp_scan_for_anonymous_namespaces (const struct symbol *symbol)
    has already been added, don't add it twice.  */
 
 void
-cp_add_using_directive (const char *dest, const char *src, const char *alias)
+cp_add_using_directive (const char *dest, const char *src, const char *alias,
+			const char *declaration, const int line_number)
 {
   struct using_direct *current;
   struct using_direct *new;
@@ -146,7 +150,8 @@ cp_add_using_directive (const char *dest, const char *src, const char *alias)
 	return;
     }
 
-  using_directives = cp_add_using (dest, src, alias, using_directives);
+  using_directives = cp_add_using (dest, src, alias, declaration,
+				   line_number, using_directives);
 
 }
 
@@ -198,9 +203,11 @@ cp_is_anonymous (const char *namespace)
 	  != NULL);
 }
 
-/* Create a new struct using direct which imports the namespace SRC into the
-   scope DEST.  ALIAS is the name of the imported namespace in the current
-   scope.  If ALIAS is NULL then the namespace is known by its original name.
+/* Create a new struct using direct which imports the namespace SRC
+   into the scope DEST.  ALIAS is the name of the imported namespace
+   in the current scope.  If ALIAS is NULL then the
+   namespace is known by its original name.
+
    Set its next member in the linked list to NEXT; allocate all memory
    using xmalloc.  It copies the strings, so NAME can be a temporary
    string.  */
@@ -209,19 +216,23 @@ struct using_direct *
 cp_add_using (const char *dest,
               const char *src,
               const char *alias,
+              const char *declaration,
+              const int line_number,
 	      struct using_direct *next)
 {
   struct using_direct *retval;
 
   retval = xmalloc (sizeof (struct using_direct));
-  retval->import_src = savestring (src, strlen(src));
-  retval->import_dest = savestring (dest, strlen(dest));
+  retval->import_src = savestring (src, strlen (src));
+  retval->import_dest = savestring (dest, strlen (dest));
 
   if (alias != NULL)
     retval->alias = savestring (alias, strlen (alias));
   else
     retval->alias = NULL;
 
+  retval->declaration = savestring (declaration, strlen (declaration));
+  retval->line_number = line_number;
   retval->next = next;
   retval->searched = 0;
 
@@ -238,19 +249,100 @@ cp_add_using (const char *dest,
 
 struct symbol *
 cp_lookup_symbol_nonlocal (const char *name,
-			   const char *linkage_name,
 			   const struct block *block,
 			   const domain_enum domain)
 {
-  struct symbol *sym;
+  struct symbol *sym; 
   const char *scope = block_scope (block);
 
-  sym = lookup_namespace_scope (name, linkage_name, block, domain, scope, 0);
+  sym = lookup_namespace_scope (name, block, domain, scope, 0);
   if (sym != NULL)
     return sym;
 
-  return cp_lookup_symbol_namespace (scope, name, linkage_name, block, domain,
-                                     1);
+  return cp_lookup_symbol_namespace(scope, name, block, domain);
+}
+
+/* Searches for NAME in the current namespace, and by applying relevant import
+   statements belonging to BLOCK and its parents.  SCOPE is the namespace
+   scope of the context in which the search is being evaluated.  */
+
+struct symbol*
+cp_lookup_symbol_namespace (const char *scope,
+                            const char *name,
+                            const struct block *block,
+                            const domain_enum domain)
+{
+  struct symbol *sym;
+
+  /* First, try to find the symbol in the given namespace.  */
+  sym = cp_lookup_symbol_in_namespace (scope, name, block, domain);
+  if ( sym != NULL)
+    return sym;
+    
+  /* Search for name in namespaces imported to this and parent blocks.  */
+  while (block != NULL)
+    {
+      sym = cp_lookup_symbol_imports(scope,name, block, domain,0,1);
+
+      if (sym)
+        return sym;
+
+      block = BLOCK_SUPERBLOCK(block);
+    }
+
+  return NULL;
+}
+
+/* Lookup NAME at namespace scope (or, in C terms, in static and
+   global variables).  SCOPE is the namespace that the current
+   function is defined within; only consider namespaces whose length
+   is at least SCOPE_LEN.  Other arguments are as in
+   cp_lookup_symbol_nonlocal.
+
+   For example, if we're within a function A::B::f and looking for a
+   symbol x, this will get called with NAME = "x", SCOPE = "A::B", and
+   SCOPE_LEN = 0.  It then calls itself with NAME and SCOPE the same,
+   but with SCOPE_LEN = 1.  And then it calls itself with NAME and
+   SCOPE the same, but with SCOPE_LEN = 4.  This third call looks for
+   "A::B::x"; if it doesn't find it, then the second call looks for
+   "A::x", and if that call fails, then the first call looks for
+   "x".  */
+
+struct symbol *
+lookup_namespace_scope (const char *name,
+			const struct block *block,
+			const domain_enum domain,
+			const char *scope,
+			int scope_len)
+{
+  char *namespace;
+
+  if (scope[scope_len] != '\0')
+    {
+      /* Recursively search for names in child namespaces first.  */
+
+      struct symbol *sym;
+      int new_scope_len = scope_len;
+
+      /* If the current scope is followed by "::", skip past that.  */
+      if (new_scope_len != 0)
+	{
+	  gdb_assert (scope[new_scope_len] == ':');
+	  new_scope_len += 2;
+	}
+      new_scope_len += cp_find_first_component (scope + new_scope_len);
+      sym = lookup_namespace_scope (name, block, domain, scope, new_scope_len);
+      if (sym != NULL)
+	return sym;
+    }
+
+  /* Okay, we didn't find a match in our children, so look for the
+     name in the current namespace.  */
+
+  namespace = alloca (scope_len + 1);
+  strncpy (namespace, scope, scope_len);
+  namespace[scope_len] = '\0';
+  return cp_lookup_symbol_in_namespace (namespace, name,block, domain);
 }
 
 /* Look up NAME in the C++ namespace NAMESPACE. Other arguments are as in
@@ -258,25 +350,24 @@ cp_lookup_symbol_nonlocal (const char *name,
 
 static struct symbol *
 cp_lookup_symbol_in_namespace (const char *namespace,
-                               const char *name,
-                               const char *linkage_name,
-                               const struct block *block,
-                               const domain_enum domain)
+			       const char *name,
+			       const struct block *block,
+			       const domain_enum domain)
 {
+
   if (namespace[0] == '\0')
     {
-      return lookup_symbol_file (name, linkage_name, block,
-                                 domain, 0);
+      return lookup_symbol_file (name, block,domain, 0);
     }
   else
     {
-      char *concatenated_name = alloca (strlen (namespace) + 2 +
-                                        strlen (name+ 1));
+      char *concatenated_name
+	= alloca (strlen (namespace) + 2 + strlen (name) + 1);
       strcpy (concatenated_name, namespace);
       strcat (concatenated_name, "::");
       strcat (concatenated_name, name);
-      return lookup_symbol_file (concatenated_name, linkage_name,
-                                 block, domain,cp_is_anonymous (namespace));
+      return lookup_symbol_file (concatenated_name, block, domain,
+				cp_is_anonymous (namespace));
     }
 }
 
@@ -291,9 +382,17 @@ reset_directive_searched (void *data)
 }
 
 /* Search for NAME by applying all import statements belonging
-   to BLOCK which are applicable in SCOPE.
+   to BLOCK which are applicable in SCOPE. If DECLARATION_ONLY the search
+   is restricted to using declarations.
+   Example:
+
+     namespace A{
+       int x;
+     }
+     using A::x;
+
    If SEARCH_PARENTS the search will include imports which are applicable in
-   parents of SCOPE.
+   parents of scopes.
    Example:
 
      namespace A{
@@ -307,26 +406,33 @@ reset_directive_searched (void *data)
    and Y will be considered. If SEARCH_PARENTS is false only the import of Y
    is considered.  */
 
-static struct symbol *
+struct symbol *
 cp_lookup_symbol_imports (const char *scope,
                           const char *name,
-                          const char *linkage_name,
                           const struct block *block,
                           const domain_enum domain,
-                          const int search_parents)
+                          int declaration_only,
+                          int search_parents)
 {
   struct using_direct *current;
-  struct symbol *sym;
-  int len;
+  struct symbol *sym = NULL;
   int directive_match;
+  int current_line;
   struct cleanup *searched_cleanup;
 
-  /* First, try to find the symbol in the given namespace.  */
-  sym = cp_lookup_symbol_in_namespace (scope, name, linkage_name, block,
-                                       domain);
-  if (sym != NULL)
+  if(!declaration_only)
+    /* First, try to find the symbol in the given namespace.  */
+    sym = cp_lookup_symbol_in_namespace (scope, name, block, domain);
+
+  if ( sym != NULL)
     return sym;
 
+  if (has_stack_frames ())
+    current_line = find_pc_line (get_frame_pc (get_selected_frame (NULL)),
+                                              0).line;
+  else
+    current_line = 0;
+
   /* Go through the using directives.  If any of them add new
      names to the namespace we're searching in, see if we can find a
      match by applying them.  */
@@ -335,7 +441,10 @@ cp_lookup_symbol_imports (const char *scope,
        current != NULL;
        current = current->next)
     {
-      len = strlen (current->import_dest);
+  
+      /* If the import destination is the current scope or one of its ancestors then
+         it is applicable.  */
+      int len = strlen (current->import_dest);
       directive_match = (search_parents
                          ? (strncmp (scope, current->import_dest,
                                      strlen (current->import_dest)) == 0
@@ -343,130 +452,70 @@ cp_lookup_symbol_imports (const char *scope,
                                 || scope[len] == ':' || scope[len] == '\0'))
                          : strcmp (scope, current->import_dest) == 0);
 
-      /* If the import destination is the current scope or one of its ancestors then
-         it is applicable.  */
-      if (directive_match && !current->searched)
+      if (directive_match &&
+          current->line_number < current_line &&
+          !current->searched)
 	{
-	/* Mark this import as searched so that the recursive call does not
-           search it again.  */
-	current->searched = 1;
-	searched_cleanup = make_cleanup (reset_directive_searched, current);
-
-	if (current->alias != NULL && strcmp (name, current->alias) == 0)
-	  /* If the import is creating an alias and the alias matches the
-	     sought name.  Pass current->import_src as the NAME to direct the
-	     search towards the aliased namespace.  */
-	  {
+	  current->searched = 1;
+	  searched_cleanup = make_cleanup (reset_directive_searched, current);
+
+	  /* If there is an import of a single declaration, compare the imported
+	     declaration with the sought out name. If there is a match pass
+	     current->import_src as NAMESPACE to direct the search towards the
+	     imported namespace.  */
+	  if (strcmp ("", current->declaration) != 0)
+	    {
+	    if (strcmp (name, current->declaration) == 0)
+	      {
+	      sym = cp_lookup_symbol_in_namespace (current->import_src,
+	                                           name,
+	                                           block,
+	                                           domain);
+	      }
+
+	    current->searched = 0;
+	    if (sym)
+	      return sym;
+
+	    continue;
+	    }
+	   
+	  if (declaration_only)
+	    {
+	    current->searched = 0;
+	    discard_cleanups (searched_cleanup);
+	    continue;
+	    }
+
+	  if (current->alias != NULL && strcmp (name, current->alias) == 0)
+	    /* If the import is creating an alias and the alias matches the
+	       sought name. Pass current->inner as the NAME to direct the
+	       search towards the aliased namespace */
+	    {
 	    sym = cp_lookup_symbol_in_namespace (scope,
 	                                         current->import_src,
-	                                         linkage_name,
 	                                         block,
 	                                         domain);
-	  }
-	else if (current->alias == NULL)
-	  {
+	    } else if (current->alias == NULL){
 	    /* If this import statement creates no alias, pass current->inner as
-               NAMESPACE to direct the search towards the imported namespace.  */
-	    sym = cp_lookup_symbol_imports (current->import_src,
-	                                    name,
-	                                    linkage_name,
-	                                    block,
-	                                    domain,
-	                                    0);
-	  }
-	current->searched = 0;
-	discard_cleanups (searched_cleanup);
-
-	if (sym != NULL)
-	  return sym;
-	}
-    }
-
-  return NULL;
-}
-
- /* Searches for NAME in the current namespace, and by applying relevant import
-    statements belonging to BLOCK and its parents. SCOPE is the namespace scope
-    of the context in which the search is being evaluated.  */
-
-struct symbol*
-cp_lookup_symbol_namespace (const char *scope,
-                            const char *name,
-                            const char *linkage_name,
-                            const struct block *block,
-                            const domain_enum domain,
-                            const int search_parents)
-{
-  struct symbol *sym;
-
-  /* Search for name in namespaces imported to this and parent blocks.  */
-  while (block != NULL)
-    {
-      sym = cp_lookup_symbol_imports (scope, name, linkage_name, block, domain,
-                                      search_parents);
-
-      if (sym)
-	return sym;
-
-      block = BLOCK_SUPERBLOCK (block);
-    }
-
-  return NULL;
-}
-
-/* Lookup NAME at namespace scope (or, in C terms, in static and
-   global variables).  SCOPE is the namespace that the current
-   function is defined within; only consider namespaces whose length
-   is at least SCOPE_LEN.  Other arguments are as in
-   cp_lookup_symbol_nonlocal.
-
-   For example, if we're within a function A::B::f and looking for a
-   symbol x, this will get called with NAME = "x", SCOPE = "A::B", and
-   SCOPE_LEN = 0.  It then calls itself with NAME and SCOPE the same,
-   but with SCOPE_LEN = 1.  And then it calls itself with NAME and
-   SCOPE the same, but with SCOPE_LEN = 4.  This third call looks for
-   "A::B::x"; if it doesn't find it, then the second call looks for
-   "A::x", and if that call fails, then the first call looks for
-   "x".  */
-
-static struct symbol *
-lookup_namespace_scope (const char *name,
-			const char *linkage_name,
-			const struct block *block,
-			const domain_enum domain,
-			const char *scope,
-			int scope_len)
-{
-  char *namespace;
-
-  if (scope[scope_len] != '\0')
-    {
-      /* Recursively search for names in child namespaces first.  */
+	       NAMESPACE to direct the search towards the imported namespace. */
+	      sym = cp_lookup_symbol_imports (current->import_src,
+	                                      name,
+	                                      block,
+	                                      domain,
+	                                      0,
+	                                      0);
+	    }
 
-      struct symbol *sym;
-      int new_scope_len = scope_len;
+	  current->searched = 0;
+	  discard_cleanups (searched_cleanup);
 
-      /* If the current scope is followed by "::", skip past that.  */
-      if (new_scope_len != 0)
-	{
-	  gdb_assert (scope[new_scope_len] == ':');
-	  new_scope_len += 2;
+	  if (sym != NULL)
+	    return sym;
 	}
-      new_scope_len += cp_find_first_component (scope + new_scope_len);
-      sym = lookup_namespace_scope (name, linkage_name, block,
-				    domain, scope, new_scope_len);
-      if (sym != NULL)
-	return sym;
     }
 
-  /* Okay, we didn't find a match in our children, so look for the
-     name in the current namespace.  */
-
-  namespace = alloca (scope_len + 1);
-  strncpy (namespace, scope, scope_len);
-  namespace[scope_len] = '\0';
-  return cp_lookup_symbol_in_namespace (namespace, name, linkage_name,
-                                        block, domain);
+  return NULL;
 }
 
 /* Look up NAME in BLOCK's static block and in global blocks.  If
@@ -476,17 +525,15 @@ lookup_namespace_scope (const char *name,
 
 static struct symbol *
 lookup_symbol_file (const char *name,
-		    const char *linkage_name,
 		    const struct block *block,
 		    const domain_enum domain,
 		    int anonymous_namespace)
 {
   struct symbol *sym = NULL;
 
-  sym = lookup_symbol_static (name, linkage_name, block, domain);
+  sym = lookup_symbol_static (name, block, domain);
   if (sym != NULL)
     return sym;
-
   if (anonymous_namespace)
     {
       /* Symbols defined in anonymous namespaces have external linkage
@@ -496,12 +543,11 @@ lookup_symbol_file (const char *name,
       const struct block *global_block = block_global_block (block);
       
       if (global_block != NULL)
-	sym = lookup_symbol_aux_block (name, linkage_name, global_block,
-				       domain);
+	sym = lookup_symbol_aux_block (name, global_block, domain);
     }
   else
     {
-      sym = lookup_symbol_global (name, linkage_name, block, domain);
+      sym = lookup_symbol_global (name, block, domain);
     }
 
   if (sym != NULL)
@@ -522,6 +568,7 @@ lookup_symbol_file (const char *name,
       sym = lookup_possible_namespace_symbol (name);
       if (sym != NULL)
 	return sym;
+
     }
 
   return NULL;
@@ -550,10 +597,9 @@ cp_lookup_nested_type (struct type *parent_type,
 
 	const char *parent_name = TYPE_TAG_NAME (parent_type);
 	struct symbol *sym = cp_lookup_symbol_in_namespace (parent_name,
-	                                                    nested_name,
-	                                                    NULL,
-	                                                    block,
-	                                                    VAR_DOMAIN);
+							 nested_name,
+							 block,
+							 VAR_DOMAIN);
 	if (sym == NULL || SYMBOL_CLASS (sym) != LOC_TYPEDEF)
 	  return NULL;
 	else
@@ -797,7 +843,7 @@ check_one_possible_namespace_symbol (const char *name, int len,
 
   memcpy (name_copy, name, len);
   name_copy[len] = '\0';
-  sym = lookup_block_symbol (block, name_copy, NULL, VAR_DOMAIN);
+  sym = lookup_block_symbol (block, name_copy, VAR_DOMAIN);
 
   if (sym == NULL)
     {
@@ -838,7 +884,7 @@ lookup_possible_namespace_symbol (const char *name)
       struct symbol *sym;
 
       sym = lookup_block_symbol (get_possible_namespace_block (objfile),
-				 name, NULL, VAR_DOMAIN);
+				 name, VAR_DOMAIN);
 
       if (sym != NULL)
 	return sym;
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index c31fcff..8c5d56f 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -50,7 +50,7 @@ static void demangled_name_complaint (const char *name);
 
 /* Functions/variables related to overload resolution.  */
 
-static int sym_return_val_size;
+static int sym_return_val_size = -1;
 static int sym_return_val_index;
 static struct symbol **sym_return_val;
 
@@ -190,7 +190,8 @@ mangled_name_to_comp (const char *mangled_name, int options,
   return ret;
 }
 
-/* Return the name of the class containing method PHYSNAME.  */
+/* Return the name of the class or namespace containing
+   function, method, or variable PHYSNAME.  */
 
 char *
 cp_class_name_from_physname (const char *physname)
@@ -711,6 +712,82 @@ make_symbol_overload_list (const char *func_name,
 
   return sym_return_val;
 }
+/* Adds the function FUNC_NAME from NAMESPACE to the overload set.  */
+
+static void
+make_symbol_overload_list_namespace (const char *func_name,
+                                     const char *namespace)
+{
+
+  if (namespace[0] == '\0')
+    {
+      make_symbol_overload_list_qualified (func_name);
+    }
+  else
+    {
+      char *concatenated_name
+	= alloca (strlen (namespace) + 2 + strlen (func_name) + 1);
+      strcpy (concatenated_name, namespace);
+      strcat (concatenated_name, "::");
+      strcat (concatenated_name, func_name);
+      make_symbol_overload_list_qualified (concatenated_name);
+    }
+}
+
+/* Search the namespace of the given type and namespace of and public base
+ types.  */
+static void make_symbol_overload_list_adl_namespace (struct type *type,
+						     const char *func_name)
+{
+  char *namespace;
+  char *type_name;
+  int i, prefix_len;
+
+  if (TYPE_CODE (type) == TYPE_CODE_PTR || TYPE_CODE (type) == TYPE_CODE_REF
+      || TYPE_CODE (type) == TYPE_CODE_ARRAY)
+    return make_symbol_overload_list_adl_namespace (TYPE_TARGET_TYPE (type),
+                                                    func_name);
+
+  type_name = TYPE_NAME (type);
+
+  prefix_len = cp_entire_prefix_len (type_name);
+
+  if (prefix_len != 0)
+    {
+      namespace = alloca (prefix_len + 1);
+      strncpy (namespace, type_name, prefix_len);
+      namespace[prefix_len] = '\0';
+
+      make_symbol_overload_list_namespace (func_name, namespace);
+    }
+
+  /* Check public base type */
+  if (TYPE_CODE(type) == TYPE_CODE_CLASS)
+    for (i = 0; i < TYPE_N_BASECLASSES (type); i++)
+      {
+	if (BASETYPE_VIA_PUBLIC (type, i))
+	  make_symbol_overload_list_adl_namespace (TYPE_BASECLASS (type, i),
+						   func_name);
+      }
+
+}
+
+/* Adds the the overload list overload candidates for FUNC_NAME found through
+   argument dependent lookup.  */
+
+struct symbol **
+make_symbol_overload_list_adl (struct type **arg_types, int nargs,
+                               const char *func_name)
+{
+  int i;
+
+  gdb_assert (sym_return_val_size != -1);
+
+  for (i = 1; i <= nargs; i++)
+    make_symbol_overload_list_adl_namespace (arg_types[i - 1], func_name);
+
+  return sym_return_val;
+}
 
 /* This applies the using directives to add namespaces to search in,
    and then searches for overloads in all of those namespaces.  It
@@ -739,20 +816,7 @@ make_symbol_overload_list_using (const char *func_name,
     }
 
   /* Now, add names for this namespace.  */
-  
-  if (namespace[0] == '\0')
-    {
-      make_symbol_overload_list_qualified (func_name);
-    }
-  else
-    {
-      char *concatenated_name
-	= alloca (strlen (namespace) + 2 + strlen (func_name) + 1);
-      strcpy (concatenated_name, namespace);
-      strcat (concatenated_name, "::");
-      strcat (concatenated_name, func_name);
-      make_symbol_overload_list_qualified (concatenated_name);
-    }
+  make_symbol_overload_list_namespace (func_name, namespace);
 }
 
 /* This does the bulk of the work of finding overloaded symbols.
@@ -840,9 +904,9 @@ read_in_psymtabs (const char *func_name)
     if (ps->readin)
       continue;
 
-    if ((lookup_partial_symbol (ps, func_name, NULL, 1, VAR_DOMAIN)
+    if ((lookup_partial_symbol (ps, func_name, 1, VAR_DOMAIN)
 	 != NULL)
-	|| (lookup_partial_symbol (ps, func_name, NULL, 0, VAR_DOMAIN)
+	|| (lookup_partial_symbol (ps, func_name, 0, VAR_DOMAIN)
 	    != NULL))
       psymtab_to_symtab (ps);
   }
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index a6a9af1..57aa5e5 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -38,20 +38,24 @@ struct demangle_component;
 
 /* This struct is designed to store data from using directives.  It
    says that names from namespace IMPORT_SRC should be visible within
-   namespace IMPORT_DEST.  These form a linked list; NEXT is the next element
-   of the list.  If the imported namespace has been aliased, ALIAS is set to a
-   string representing the alias.  Otherwise, ALIAS is NULL.
-   Eg:
-       namespace C = A::B;
+   namespace IMPORT_DEST.  These form a linked list; NEXT is the next
+   element of the list.  ALIAS is set to a non empty string if the imported
+   namespace has been aliased.Eg:
+       namespace C=A::B;
    ALIAS = "C"
+   DECLARATION is the name of the imported declaration, if this import 
+   statement represents one. Eg:
+       using A::x;
+   Where x is variable in namespace A. declaration is set to x.  
 */
 
 struct using_direct
 {
   char *import_src;
   char *import_dest;
-
   char *alias;
+  char *declaration;
+  int line_number;
 
   struct using_direct *next;
 
@@ -64,6 +68,7 @@ struct using_direct
 
 extern char *cp_canonicalize_string (const char *string);
 
+
 extern char *cp_class_name_from_physname (const char *physname);
 
 extern char *method_name_from_physname (const char *physname);
@@ -79,6 +84,10 @@ extern char *cp_remove_params (const char *demangled_name);
 extern struct symbol **make_symbol_overload_list (const char *,
 						  const char *);
 
+extern struct symbol **make_symbol_overload_list_adl (struct type **arg_types,
+                                                      int nargs,
+                                                      const char *func_name);
+
 extern struct type *cp_lookup_rtti_type (const char *name,
 					 struct block *block);
 
@@ -90,11 +99,15 @@ extern int cp_is_anonymous (const char *namespace);
 
 extern void cp_add_using_directive (const char *dest,
                                     const char *src,
-                                    const char *alias);
+                                    const char *alias,
+                                    const char *declaration,
+                                    const int line_number);
 
 extern struct using_direct *cp_add_using (const char *dest,
                                           const char *src,
                                           const char *alias,
+                                          const char *declaration,
+                                          const int line_number,
 					  struct using_direct *next);
 
 extern void cp_initialize_namespace (void);
@@ -111,16 +124,20 @@ extern void cp_set_block_scope (const struct symbol *symbol,
 extern void cp_scan_for_anonymous_namespaces (const struct symbol *symbol);
 
 extern struct symbol *cp_lookup_symbol_nonlocal (const char *name,
-						 const char *linkage_name,
 						 const struct block *block,
 						 const domain_enum domain);
 
+struct symbol *cp_lookup_symbol_imports (const char *scope,
+                                         const char *name,
+                                         const struct block *block,
+                                         const domain_enum domain,
+                                         int declaration_only,
+                                         int search_parents);
+
 extern struct symbol *cp_lookup_symbol_namespace (const char *namespace,
-						  const char *name,
-						  const char *linkage_name,
-						  const struct block *block,
-						  const domain_enum domain,
-						  const int search_parents);
+                                                  const char *name,
+                                                  const struct block *block,
+                                                  const domain_enum domain);
 
 extern struct type *cp_lookup_nested_type (struct type *parent_type,
 					   const char *nested_name,
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index c9a5754..fc33da2 100644
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -3565,6 +3565,7 @@ static struct sym_fns aout_sym_fns =
   dbx_new_init,		/* sym_new_init: init anything gbl to entire symtab */
   dbx_symfile_init,	/* sym_init: read initial info, setup for sym_read() */
   dbx_symfile_read,		/* sym_read: read a symbol file into symtab */
+  NULL,				/* sym_read_psymbols */
   dbx_symfile_finish,		/* sym_finish: finished with file, cleanup */
   default_symfile_offsets, /* sym_offsets: parse user's offsets to
 			      internal form */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 0e3e093..661ba18 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -1157,6 +1157,16 @@ for remote debugging.
 Run using @var{device} for your program's standard input and output.
 @c FIXME: kingdon thinks there is more to -tty.  Investigate.
 
+@item -P
+@cindex @code{-P}
+@itemx --python
+@cindex @code{--python}
+Change interpretation of command line so that the argument immediately
+following this switch is taken to be the name of a Python script file.
+This option stops option processing; subsequent options are passed to
+Python as @code{sys.argv}.  This option is only available if Python
+scripting support was enabled when @value{GDBN} was configured.
+
 @c resolve the situation of these eventually
 @item -tui
 @cindex @code{--tui}
@@ -19215,7 +19225,7 @@ using the @code{script-extension} setting.
 @table @code
 @kindex source
 @cindex execute commands from a file
-@item source [@code{-v}] @var{filename}
+@item source [@code{-v}] [@code{-p}] @var{filename}
 Execute the command file @var{filename}.
 @end table
 
@@ -19493,8 +19503,6 @@ containing @code{end}.  For example:
 
 @smallexample
 (@value{GDBP}) python
-Type python script
-End with a line saying just "end".
 >print 23
 >end
 23
@@ -19507,6 +19515,14 @@ in a Python script.  This can be controlled using @code{maint set
 python print-stack}: if @code{on}, the default, then Python stack
 printing is enabled; if @code{off}, then Python stack printing is
 disabled.
+
+@kindex maint set python auto-load
+@item maint set python auto-load
+By default, @value{GDBN} will attempt to automatically load Python
+code when an object file is opened.  This can be controlled using
+@code{maint set python auto-load}: if @code{on}, the default, then
+Python auto-loading is enabled; if @code{off}, then Python
+auto-loading is disabled.
 @end table
 
 It is also possible to execute a Python script from the @value{GDBN}
@@ -19528,6 +19544,14 @@ and thus is always available.
 @cindex python api
 @cindex programming in python
 
+You can get quick online help for @value{GDBN}'s Python API by issuing
+the command @w{@kbd{python help (gdb)}}.
+
+Functions and methods which have two or more optional arguments allow
+them to be specified using keyword syntax.  This allows passing some
+optional arguments while skipping others.  Example:
+@w{@code{gdb.some_function ('foo', bar = 1, baz = 2)}}.
+
 @cindex python stdout
 @cindex python pagination
 At startup, @value{GDBN} overrides Python's @code{sys.stdout} and
@@ -19540,13 +19564,17 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown.
 * Basic Python::                Basic Python Functions.
 * Exception Handling::
 * Auto-loading::                Automatically loading Python code.
-* Values From Inferior::
+* Values From Inferior::	Python representation of values.
 * Types In Python::		Python representation of types.
 * Pretty Printing::		Pretty-printing values.
 * Selecting Pretty-Printers::   How GDB chooses a pretty-printer.
+* Inferiors In Python::		Python representation of inferiors (processes)
+* Threads In Python::           Accessing inferior threads from Python.
 * Commands In Python::          Implementing new commands in Python.
+* Parameters In Python::        Adding new @value{GDBN} parameters.
 * Functions In Python::         Writing new convenience functions.
 * Objfiles In Python::          Object files.
+* Breakpoints In Python::       Manipulating breakpoints using Python.
 * Frames In Python::            Acessing inferior stack frames from Python.
 * Lazy Strings In Python::      Python representation of lazy strings.
 @end menu
@@ -19574,6 +19602,12 @@ command as having originated from the user invoking it interactively.
 It must be a boolean value.  If omitted, it defaults to @code{False}.
 @end defun
 
+@findex gdb.breakpoints
+@defun breakpoints
+Return a sequence holding all of @value{GDBN}'s breakpoints.
+@xref{Breakpoints In Python}, for more information.
+@end defun
+
 @findex gdb.parameter
 @defun parameter parameter
 Return the value of a @value{GDBN} parameter.  @var{parameter} is a
@@ -19590,6 +19624,7 @@ a Python value of the appropriate type, and returned.
 @defun history number
 Return a value from @value{GDBN}'s value history (@pxref{Value
 History}).  @var{number} indicates which history element to return.
+
 If @var{number} is negative, then @value{GDBN} will take its absolute value
 and count backward from the last element (i.e., the most recent element) to
 find the value to return.  If @var{number} is zero, then @value{GDBN} will
@@ -19614,6 +19649,21 @@ compute values, for example, it is the only way to get the value of a
 convenience variable (@pxref{Convenience Vars}) as a @code{gdb.Value}.
 @end defun
 
+@findex gdb.post_event
+@defun post_event event
+Put @var{event}, a callable object taking no arguments, into
+@value{GDBN}'s internal event queue.  This callable will be invoked at
+some later point, during @value{GDBN}'s event processing.  Events
+posted using @code{post_event} will be run in the order in which they
+were posted; however, there is no way to know when they will be
+processed relative to other events inside @value{GDBN}.
+
+@value{GDBN} is not thread-safe.  If your Python program uses multiple
+threads, you must be careful to only call @value{GDBN}-specific
+functions in the main @value{GDBN} thread.  @code{post_event} ensures
+this.
+@end defun
+
 @findex gdb.write
 @defun write string
 Print a string to @value{GDBN}'s paginated standard output stream.
@@ -19628,6 +19678,11 @@ Flush @value{GDBN}'s paginated standard output stream.  Flushing
 function.
 @end defun
 
+@findex gdb.solib_address
+@defun solib_address @var{address}
+Return the name of the shared library holding the given address, or None.
+@end defun
+
 @node Exception Handling
 @subsubsection Exception Handling
 @cindex python exceptions
@@ -19866,6 +19921,9 @@ module:
 This function looks up a type by name.  @var{name} is the name of the
 type to look up.  It must be a string.
 
+If @var{block} is given, then @var{name} is looked up in that scope.
+Otherwise, it is searched for globally.
+
 Ordinarily, this function will return an instance of @code{gdb.Type}.
 If the named type cannot be found, it will throw an exception.
 @end defun
@@ -19988,7 +20046,7 @@ If the type does not have a target, this method will throw an
 exception.
 @end defmethod
 
-@defmethod Type template_argument n
+@defmethod Type template_argument n [block]
 If this @code{gdb.Type} is an instantiation of a template, this will
 return a new @code{gdb.Type} which represents the type of the
 @var{n}th template argument.
@@ -19996,7 +20054,8 @@ return a new @code{gdb.Type} which represents the type of the
 If this @code{gdb.Type} is not a template type, this will throw an
 exception.  Ordinarily, only C@t{++} code will have template types.
 
-@var{name} is searched for globally.
+If @var{block} is given, then @var{name} is looked up in that scope.
+Otherwise, it is searched for globally.
 @end defmethod
 @end table
 
@@ -20350,6 +20409,121 @@ import gdb.libstdcxx.v6
 gdb.libstdcxx.v6.register_printers (gdb.current_objfile ())
 @end smallexample
 
+@node Inferiors In Python
+@subsubsection Inferiors In Python
+
+Programs which are being run under @value{GDBN} are called inferiors
+(@pxref{Inferiors and Programs}).  Python scripts can access
+information about and manipulate inferiors controlled by @value{GDBN}
+via objects of the @code{gdb.Inferior} class.
+
+The following inferior-related functions are available in the @code{gdb}
+module:
+
+@defun inferiors
+Return a tuple containing all inferior objects.
+@end defun
+
+A @code{gdb.Inferior} object has the following attributes:
+
+@table @code
+@defivar Inferior num 
+ID of inferior, as assigned by GDB.
+@end defivar
+
+@defivar Inferior pid 
+Process ID of the inferior, assigned by the underlying OS.
+@end defivar
+
+@defivar Inferior was_attached
+Boolean signaling whether the inferior was created using `attach', or
+started by @value{GDBN} itself.
+@end defivar
+@end table
+
+A @code{gdb.Inferior} object has the following methods:
+
+@table @code
+@defmethod Inferior threads 
+This method returns a tuple holding all the threads which are valid
+when it is called.  If there are no valid threads, the method will
+return an empty list.
+@end defmethod
+
+@findex gdb.read_memory
+@defmethod Inferior read_memory @var{address} @var{length}
+Read @var{length} bytes of memory from the inferior, starting at
+@var{address}.  Returns a buffer object, which behaves much like an array
+or a string. It can be modified and given to the @code{gdb.write_memory}
+function.
+@end defmethod
+
+@findex gdb.write_memory
+@defmethod Inferior write_memory @var{address} @var{buffer} @r{[}@var{length}@r{]}
+Write the contents of @var{buffer} (a Python object which supports the
+buffer protocol, i.e., a string, an array or the object returned from
+@code{gdb.read_memory}) to the inferior, starting at @var{address}.
+If given, @var{length} determines the number of bytes from @var{buffer} to
+be written.
+@end defmethod
+
+@findex gdb.search_memory
+@defmethod Inferior search_memory @var{address} @var{length} @var{pattern} @r{[}@var{size}@r{]} @r{[}@var{max_count}@r{]}
+Search a region of the inferior memory starting at @var{address} with the
+given @var{length}.  @var{pattern} can be a string, a byte array, a buffer
+object, a number, a @code{gdb.Value} object (@pxref{Values From Inferior})
+or a list or tuple with elements in any combination of those types.  If
+@var{size} is given and is non-zero, it specifies the size in bytes of a
+Python scalar or @code{gdb.Value} in the search pattern.  If @var{size} is
+zero or not specified, it is taken from the value's type in the current
+language.  This is useful when one wants to specify the search pattern as
+a mixture of types.  Note that this means, for example, that in the case of
+C-like languages a search for an untyped 0x42 will search for
+@samp{(int) 0x42} which is typically four bytes.  @var{max_count} is the
+highest number of matches to search for.
+@end defmethod
+@end table
+
+@node Threads In Python
+@subsubsection Threads In Python
+
+Python scripts can access information about and manipulate inferior threads
+controlled by @value{GDBN} via objects of the @code{gdb.InferiorThread} class.
+
+The following inferior-related functions are available in the @code{gdb}
+module:
+
+@findex gdb.selected_thread
+@defun selected_thread
+This function returns the thread object for the selected thread.  If there
+is no selected thread, this will return @code{None}.
+@end defun
+
+A @code{gdb.InferiorThread} object has the following attributes:
+
+@table @code
+@defivar InferiorThread num 
+ID of the thread, as assigned by GDB.
+@end defivar
+@end table
+
+A @code{gdb.InferiorThread} object has the following methods:
+
+@table @code
+@defmethod InferiorThread frames
+Return a tuple containing all frames in the thread.
+@end defmethod
+
+@defmethod InferiorThread newest_frame
+Return the newest frame thread's stack.
+@end defmethod
+
+@defmethod InferiorThread switch_to_thread 
+This changes @value{GDBN}'s currently selected thread to the one represented
+by this object.
+@end defmethod
+@end table
+
 @node Commands In Python
 @subsubsection Commands In Python
 
@@ -20602,6 +20776,135 @@ registration of the command with @value{GDBN}.  Depending on how the
 Python code is read into @value{GDBN}, you may need to import the
 @code{gdb} module explicitly.
 
+@node Parameters In Python
+@subsubsection Parameters In Python
+
+@cindex parameters in python
+@cindex python parameters
+@tindex gdb.Parameter
+@tindex Parameter
+You can implement new @value{GDBN} parameters using Python.  A new
+parameter is implemented as an instance of the @code{gdb.Parameter}
+class.  Parameters are exposed to the user via the @code{set} and
+@code{show} commands.
+
+@defmethod Parameter __init__ name @var{command-class} @var{parameter-class} @r{[}@var{enum-sequence}@r{]}
+The object initializer for @code{Parameter} registers the new
+parameter with @value{GDBN}.  This initializer is normally invoked
+from the subclass' own @code{__init__} method.
+
+@var{name} is the name of the new parameter.  If @var{name} consists
+of multiple words, then the initial words are looked for as prefix
+commands.  In this case, if one of the prefix commands does not exist,
+an exception is raised.
+
+@var{command-class} should be one of the @samp{COMMAND_} constants
+(@pxref{Commands In Python}).  This argument tells @value{GDBN} how to
+categorize the new parameter in the help system.
+
+@var{parameter-class} should be one of the @samp{PARAM_} constants
+defined below.  This argument tells @value{GDBN} the type of the new
+parameter; this information is used for input validation and
+completion.
+
+If @var{parameter-class} is @code{PARAM_ENUM}, then
+@var{enum-sequence} must be a sequence of strings.  These strings
+represent the possible values for the parameter.
+
+If @var{parameter-class} is not @code{PARAM_ENUM}, then the presence
+of a fourth argument will cause an exception to be thrown.
+
+The help text for the new parameter is taken from the Python
+documentation string for the parameter's class, if there is one.  If
+there is no documentation string, a default value is used.
+@end defmethod
+
+@defivar Parameter set_doc
+If this attribute exists, and is a string, then its value is used as
+the help text for this parameter's @code{set} command.  The value is
+examined when @code{Parameter.__init__} is invoked; subsequent changes
+have no effect.
+@end defivar
+
+@defivar Parameter show_doc
+If this attribute exists, and is a string, then its value is used as
+the help text for this parameter's @code{show} command.  The value is
+examined when @code{Parameter.__init__} is invoked; subsequent changes
+have no effect.
+@end defivar
+
+@defivar Parameter value
+The @code{value} attribute holds the underlying value of the
+parameter.  It can be read and assigned to just as any other
+attribute.  @value{GDBN} does validation when assignments are made.
+@end defivar
+
+
+When a new parameter is defined, its type must be specified.  The
+available types are represented by constants defined in the @code{gdb}
+module:
+
+@table @code
+@findex PARAM_BOOLEAN
+@findex gdb.PARAM_BOOLEAN
+@item PARAM_BOOLEAN
+The value is a plain boolean.  The Python boolean values, @code{True}
+and @code{False} are the only valid values.
+
+@findex PARAM_AUTO_BOOLEAN
+@findex gdb.PARAM_AUTO_BOOLEAN
+@item PARAM_AUTO_BOOLEAN
+The value has three possible states: true, false, and @samp{auto}.  In
+Python, true and false are represented using boolean constants, and
+@samp{auto} is represented using @code{None}.
+
+@findex PARAM_UINTEGER
+@findex gdb.PARAM_UINTEGER
+@item PARAM_UINTEGER
+The value is an unsigned integer.  The value of 0 should be
+interpreted to mean ``unlimited''.
+
+@findex PARAM_INTEGER
+@findex gdb.PARAM_INTEGER
+@item PARAM_INTEGER
+The value is a signed integer.  The value of 0 should be interpreted
+to mean ``unlimited''.
+
+@findex PARAM_STRING
+@findex gdb.PARAM_STRING
+@item PARAM_STRING
+The value is a string.  When the user modifies the string, escapes are
+translated.
+
+@findex PARAM_STRING_NOESCAPE
+@findex gdb.PARAM_STRING_NOESCAPE
+@item PARAM_STRING_NOESCAPE
+The value is a string.  When the user modifies the string, escapes are
+passed through untranslated.
+
+@findex PARAM_OPTIONAL_FILENAME
+@findex gdb.PARAM_OPTIONAL_FILENAME
+@item PARAM_OPTIONAL_FILENAME
+The value is a either a filename (a string), or @code{None}.
+
+@findex PARAM_FILENAME
+@findex gdb.PARAM_FILENAME
+@item PARAM_FILENAME
+The value is a filename (a string).
+
+@findex PARAM_ZINTEGER
+@findex gdb.PARAM_ZINTEGER
+@item PARAM_ZINTEGER
+The value is an integer.  This is like @code{PARAM_INTEGER}, except 0
+is interpreted as itself.
+
+@findex PARAM_ENUM
+@findex gdb.PARAM_ENUM
+@item PARAM_ENUM
+The value is a string, which must be one of a collection string
+constants provided when the parameter is created.
+@end table
+
 @node Functions In Python
 @subsubsection Writing new convenience functions
 
@@ -20706,6 +21009,82 @@ which is used to format the value.  @xref{Pretty Printing}, for more
 information.
 @end defivar
 
+@node Breakpoints In Python
+@subsubsection Manipulating breakpoints using Python
+
+@cindex breakpoints in python
+@cindex python breakpoints
+@tindex gdb.Breakpoint
+@tindex Breakpoint
+Python code can manipulate breakpoints via the @code{gdb.Breakpoint}
+class.
+
+@defmethod Breakpoint __init__ location
+Create a new breakpoint.  @var{location} is a string naming the
+location of the breakpoint.  The contents can be any location
+recognized by the @code{break} command.
+@end defmethod
+
+@defmethod Breakpoint is_valid
+Return @code{True} if this @code{Breakpoint} object is valid,
+@code{False} otherwise.  A @code{Breakpoint} object can become invalid
+if the user deletes the breakpoint.  In this case, the object still
+exists, but the underlying breakpoint does not.
+@end defmethod
+
+@defivar Breakpoint enabled
+This attribute is @code{True} if the breakpoint is enabled, and
+@code{False} otherwise.  This attribute is writable.
+@end defivar
+
+@defivar Breakpoint silent
+This attribute is @code{True} if the breakpoint is silent, and
+@code{False} otherwise.  This attribute is writable.
+
+Note that a breakpoint can also be silent if it has commands and the
+first command is @code{silent}.  This is not reported by the
+@code{silent} attribute.
+@end defivar
+
+@defivar Breakpoint thread
+If the breakpoint is thread-specific, this attribute holds the thread
+id.  If the breakpoint is not thread-specific, this attribute is
+@code{None}.  This attribute is writable.
+@end defivar
+
+@defivar Breakpoint ignore_count
+This attribute holds the ignore count for the breakpoint, an integer.
+This attribute is writable.
+@end defivar
+
+@defivar Breakpoint number
+This attribute holds the breakpoint's number -- the identifier used by
+the user to manipulate the breakpoint.  This attribute is not writable.
+@end defivar
+
+@defivar Breakpoint hit_count
+This attribute holds the hit count for the breakpoint, an integer.
+This attribute is writable, but currently it can only be set to zero.
+@end defivar
+
+@defivar Breakpoint location
+This attribute holds the location of the breakpoint, as specified by
+the user.  It is a string.  This attribute is not writable.
+@end defivar
+
+@defivar Breakpoint condition
+This attribute holds the condition of the breakpoint, as specified by
+the user.  It is a string.  If there is no condition, this attribute's
+value is @code{None}.  This attribute is writable.
+@end defivar
+
+@defivar Breakpoint commands
+This attribute holds the commands attached to the breakpoint.  If
+there are commands, this returns a string holding all the commands,
+separated by newlines.  If there are no commands, this attribute is
+@code{None}.  This attribute is not writable.
+@end defivar
+
 @node Frames In Python
 @subsubsection Acessing inferior stack frames from Python.
 
@@ -20770,6 +21149,14 @@ function to a string.
 Returns the frame's resume address.
 @end defmethod
 
+@defmethod Frame block
+Returns the frame's code block. @c (@pxref{Block,,Code Blocks and Scopes}).
+@end defmethod
+
+@defmethod Frame function
+Returns the symbol for the function corresponding to this frame. @c (@pxref{Symbols In Python}).
+@end defmethod
+
 @defmethod Frame older
 Return the frame that called this frame.
 @end defmethod
@@ -20778,10 +21165,18 @@ Return the frame that called this frame.
 Return the frame called by this frame.
 @end defmethod
 
+@defmethod Frame find_sal
+Return the frame's symtab and line object. @c (@pxref{Symtab_and_line,, Symtab and line}).
+@end defmethod
+
 @defmethod Frame read_var variable
 Return the value of the given variable in this frame.  @var{variable} must
 be a string.
 @end defmethod
+
+@defmethod Frame select
+Set this frame to be the user's selected frame.
+@end defmethod
 @end table
 
 @node Lazy Strings In Python
diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo
index 7741855..df3fc87 100644
--- a/gdb/doc/gdbint.texinfo
+++ b/gdb/doc/gdbint.texinfo
@@ -2107,6 +2107,18 @@ time, and so we attempt to handle symbols incrementally.  For instance,
 we create @dfn{partial symbol tables} consisting of only selected
 symbols, and only expand them to full symbol tables when necessary.
 
+@menu
+* Symbol Reading::
+* Partial Symbol Tables::
+* Types::
+* Object File Formats::
+* Debugging File Formats::
+* Adding a New Symbol Reader to GDB::
+* Memory Management for Symbol Files::
+* Memory Management for Types::
+@end menu
+
+@node Symbol Reading
 @section Symbol Reading
 
 @cindex symbol reading
@@ -2199,6 +2211,7 @@ symtab.  Upon return, @code{pst->readin} should have been set to 1, and
 zero if there were no symbols in that part of the symbol file.
 @end table
 
+@node Partial Symbol Tables
 @section Partial Symbol Tables
 
 @value{GDBN} has three types of symbol tables:
@@ -2294,6 +2307,7 @@ and all the psymbols themselves are allocated in a pair of large arrays
 on an obstack, so there is little to be gained by trying to free them
 unless you want to do a lot more work.
 
+@node Types
 @section Types
 
 @unnumberedsubsec Fundamental Types (e.g., @code{FT_VOID}, @code{FT_BOOLEAN}).
@@ -2316,6 +2330,7 @@ types map to one @code{TYPE_CODE_*} type, and are distinguished by
 other members of the type struct, such as whether the type is signed
 or unsigned, and how many bits it uses.
 
+@anchor{Builtin Types}
 @unnumberedsubsec Builtin Types (e.g., @code{builtin_type_void}, @code{builtin_type_char}).
 
 These are instances of type structs that roughly correspond to
@@ -2330,6 +2345,7 @@ only one instance exists, while @file{c-lang.c} builds as many
 @code{TYPE_CODE_INT} types as needed, with each one associated with
 some particular objfile.
 
+@node Object File Formats
 @section Object File Formats
 @cindex object file formats
 
@@ -2415,6 +2431,7 @@ SOM, which is a cross-language ABI).
 
 The SOM reader is in @file{somread.c}.
 
+@node Debugging File Formats
 @section Debugging File Formats
 
 This section describes characteristics of debugging information that
@@ -2486,6 +2503,7 @@ DWARF 3 is an improved version of DWARF 2.
 @cindex SOM debugging info
 Like COFF, the SOM definition includes debugging information.
 
+@node Adding a New Symbol Reader to GDB
 @section Adding a New Symbol Reader to @value{GDBN}
 
 @cindex adding debugging info reader
@@ -2508,6 +2526,7 @@ will only ever be implemented by one object file format may be called
 directly.  This interface should be described in a file
 @file{bfd/lib@var{xyz}.h}, which is included by @value{GDBN}.
 
+@node Memory Management for Symbol Files
 @section Memory Management for Symbol Files
 
 Most memory associated with a loaded symbol file is stored on
@@ -2519,10 +2538,45 @@ released when the objfile is unloaded or reloaded.  Therefore one
 objfile must not reference symbol or type data from another objfile;
 they could be unloaded at different times.
 
-User convenience variables, et cetera, have associated types.  Normally
-these types live in the associated objfile.  However, when the objfile
-is unloaded, those types are deep copied to global memory, so that
-the values of the user variables and history items are not lost.
+@node Memory Management for Types
+@section Memory Management for Types
+@cindex memory management for types
+
+@findex TYPE_OBJFILE
+@code{TYPE_OBJFILE} macro indicates the current memory owner of the type.
+Non-@code{NULL} value indicates it is owned by an objfile (specifically by its
+obstack) and in such case the type remains valid till the objfile is unloaded
+or reloaded.  For such types with an associated objfile no reference counting
+is being made.
+
+User convenience variables, et cetera, have associated types.  Normally these
+types live in the associated objfile.  However, when the objfile is unloaded,
+those types are deep copied to global memory, so that the values of the user
+variables and history items are not lost.  During the copy they will get their
+@code{TYPE_OBJFILE} set to @code{NULL} and become so-called @dfn{reclaimable}
+types.
+
+Types with null @code{TYPE_OBJFILE} can be either permanent types
+(@pxref{Builtin Types}) or reclaimable types which will be deallocated at the
+first idle @value{GDBN} moment if the last object referencing them is removed.
+Permanent types are allocated by the function @code{alloc_type} (and its
+derivations like @code{init_type}) specifying objfile as @code{NULL}.  The
+reclaimable types are created the same way but moreover they need to have
+@code{type_init_group} called to start their tracking as being possibly
+deallocatable.
+
+@findex free_all_types
+When @value{GDBN} gets idle it always calls the @code{free_all_types} function
+which deallocates any unused types.  All types currently not owned by an
+objfile must be marked as used on each @code{free_all_types} call as they would
+get deallocated as unused otherwise.
+
+@code{free_all_types} automatically checks for any cross-type references such
+as through @code{TYPE_TARGET_TYPE}, @code{TYPE_POINTER_TYPE} etc.@: and
+prevents early deallocation for any such existing references.  Reclaimable
+types may reference any other reclaimable types or even permanent types.  But
+permanent types must not reference reclaimable types (nor an objfile associated
+type).
 
 
 @node Language Support
diff --git a/gdb/doc/observer.texi b/gdb/doc/observer.texi
index db3d114..759200f 100644
--- a/gdb/doc/observer.texi
+++ b/gdb/doc/observer.texi
@@ -213,6 +213,11 @@ Bytes from @var{data} to @var{data} + @var{len} have been written
 to the current inferior at @var{addr}.
 @end deftypefun
 
+@deftypefun void mark_used (void)
+Mark any possibly reclaimable objects as used during a mark-and-sweep garbage
+collector pass.  Currently only @code{type_mark_used} marker is supported.
+@end deftypefun
+
  @deftypefun void test_notification (int @var{somearg})
 This observer is used for internal testing.  Do not use.  
 See testsuite/gdb.gdb/observer.exp.
diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c
index 99100d7..5915249 100644
--- a/gdb/dwarf2-frame.c
+++ b/gdb/dwarf2-frame.c
@@ -38,6 +38,7 @@
 
 #include "complaints.h"
 #include "dwarf2-frame.h"
+#include "addrmap.h"
 
 struct comp_unit;
 
@@ -1582,6 +1583,14 @@ dwarf2_frame_find_fde (CORE_ADDR *pc)
       CORE_ADDR offset;
       CORE_ADDR seek_pc;
 
+      if (objfile->quick_addrmap)
+	{
+	  if (!addrmap_find (objfile->quick_addrmap, *pc))
+	    continue;
+	}
+      /* FIXME: Read-in only .debug_frame/.eh_frame without .debug_info?  */
+      require_partial_symbols (objfile);
+
       fde_table = objfile_data (objfile, dwarf2_frame_objfile_data);
       if (fde_table == NULL)
 	continue;
diff --git a/gdb/dwarf2expr.c b/gdb/dwarf2expr.c
index ed21edf..1b10cb7 100644
--- a/gdb/dwarf2expr.c
+++ b/gdb/dwarf2expr.c
@@ -868,6 +868,13 @@ execute_stack_op (struct dwarf_expr_context *ctx,
 	  ctx->initialized = 0;
 	  goto no_push;
 
+	case DW_OP_push_object_address:
+	  if (ctx->get_object_address == NULL)
+	    error (_("DWARF-2 expression error: DW_OP_push_object_address must "
+	           "have a value to push."));
+	  result = (ctx->get_object_address) (ctx->baton);
+	  break;
+
 	default:
 	  error (_("Unhandled dwarf expression opcode 0x%x"), op);
 	}
diff --git a/gdb/dwarf2expr.h b/gdb/dwarf2expr.h
index 437ca39..f7fce92 100644
--- a/gdb/dwarf2expr.h
+++ b/gdb/dwarf2expr.h
@@ -102,10 +102,10 @@ struct dwarf_expr_context
      The result must be live until the current expression evaluation
      is complete.  */
   unsigned char *(*get_subr) (void *baton, off_t offset, size_t *length);
+#endif
 
   /* Return the `object address' for DW_OP_push_object_address.  */
   CORE_ADDR (*get_object_address) (void *baton);
-#endif
 
   /* The current depth of dwarf expression recursion, via DW_OP_call*,
      DW_OP_fbreg, DW_OP_push_object_address, etc., and the maximum
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 1c4d057..20dcacd 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -46,6 +46,12 @@ static void
 dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc,
 			 gdb_byte **start, size_t *length);
 
+static struct value *dwarf2_evaluate_loc_desc (struct type *type,
+					       struct frame_info *frame,
+					       gdb_byte *data,
+					       unsigned short size,
+					     struct dwarf2_per_cu_data *per_cu);
+
 /* A helper function for dealing with location lists.  Given a
    symbol baton (BATON) and a pc value (PC), find the appropriate
    location expression, set *LOCEXPR_LENGTH, and return a pointer
@@ -121,6 +127,9 @@ struct dwarf_expr_baton
 {
   struct frame_info *frame;
   struct objfile *objfile;
+  /* From DW_TAG_variable's DW_AT_location (not DW_TAG_type's
+     DW_AT_data_location) for DW_OP_push_object_address.  */
+  CORE_ADDR object_address;
 };
 
 /* Helper functions for dwarf2_evaluate_loc_desc.  */
@@ -189,22 +198,33 @@ dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc,
       symbaton = SYMBOL_LOCATION_BATON (framefunc);
       *start = find_location_expression (symbaton, length, pc);
     }
-  else
+  else if (SYMBOL_COMPUTED_OPS (framefunc) == &dwarf2_locexpr_funcs)
     {
       struct dwarf2_locexpr_baton *symbaton;
+
       symbaton = SYMBOL_LOCATION_BATON (framefunc);
-      if (symbaton != NULL)
-	{
-	  *length = symbaton->size;
-	  *start = symbaton->data;
-	}
-      else
-	*start = NULL;
+      gdb_assert (symbaton != NULL);
+      *start = symbaton->data;
+      *length = symbaton->size;
     }
+  else if (SYMBOL_COMPUTED_OPS (framefunc) == &dwarf2_missing_funcs)
+    {
+      struct dwarf2_locexpr_baton *symbaton;
+
+      symbaton = SYMBOL_LOCATION_BATON (framefunc);
+      gdb_assert (symbaton == NULL);
+      *start = NULL;
+      *length = 0;	/* unused */
+    }
+  else
+    internal_error (__FILE__, __LINE__,
+		    _("Unsupported SYMBOL_COMPUTED_OPS %p for \"%s\""),
+		    SYMBOL_COMPUTED_OPS (framefunc),
+		    SYMBOL_PRINT_NAME (framefunc));
 
   if (*start == NULL)
     error (_("Could not find the frame base for \"%s\"."),
-	   SYMBOL_NATURAL_NAME (framefunc));
+	   SYMBOL_PRINT_NAME (framefunc));
 }
 
 /* Helper function for dwarf2_evaluate_loc_desc.  Computes the CFA for
@@ -227,6 +247,155 @@ dwarf_expr_tls_address (void *baton, CORE_ADDR offset)
   return target_translate_tls_address (debaton->objfile, offset);
 }
 
+static CORE_ADDR
+dwarf_expr_object_address (void *baton)
+{
+  struct dwarf_expr_baton *debaton = baton;
+
+  /* The message is suppressed in DWARF_BLOCK_EXEC.  */
+  if (debaton->object_address == 0)
+    error (_("Cannot resolve DW_OP_push_object_address for a missing object"));
+
+  return debaton->object_address;
+}
+
+/* Address of the variable we are currently referring to.  It is set from
+   DW_TAG_variable's DW_AT_location (not DW_TAG_type's DW_AT_data_location) for
+   DW_OP_push_object_address.  */
+
+static CORE_ADDR object_address;
+
+/* Callers use object_address_set while their callers use the result set so we
+   cannot run the cleanup at the local block of our direct caller.  Still we
+   should reset OBJECT_ADDRESS at least for the next GDB command.  */
+
+static void
+object_address_cleanup (void *prev_save_voidp)
+{
+  CORE_ADDR *prev_save = prev_save_voidp;
+
+  object_address = *prev_save;
+  xfree (prev_save);
+}
+
+/* Set the base address - DW_AT_location - of a variable.  It is being later
+   used to derive other object addresses by DW_OP_push_object_address.
+
+   It would be useful to sanity check ADDRESS - such as for some objects with
+   unset value_raw_address - but some valid addresses may be zero (such as first
+   objects in relocatable .o files).  */
+
+void
+object_address_set (CORE_ADDR address)
+{
+  CORE_ADDR *prev_save;
+
+  prev_save = xmalloc (sizeof *prev_save);
+  *prev_save = object_address;
+  make_cleanup (object_address_cleanup, prev_save);
+
+  object_address = address;
+}
+
+/* Evaluate DWARF expression at DATA ... DATA + SIZE with its result readable
+   by dwarf_expr_fetch (RETVAL, 0).  FRAME parameter can be NULL to call
+   get_selected_frame to find it.  Returned dwarf_expr_context freeing is
+   pushed on the cleanup chain.  */
+
+static struct dwarf_expr_context *
+dwarf_expr_prep_ctx (struct frame_info *frame, gdb_byte *data,
+		     unsigned short size, struct dwarf2_per_cu_data *per_cu)
+{
+  struct dwarf_expr_context *ctx;
+  struct dwarf_expr_baton baton;
+
+  if (!frame)
+    frame = get_selected_frame (NULL);
+
+  baton.frame = frame;
+  baton.objfile = dwarf2_per_cu_objfile (per_cu);
+  baton.object_address = object_address;
+
+  ctx = new_dwarf_expr_context ();
+  make_cleanup_free_dwarf_expr_context (ctx);
+
+  ctx->gdbarch = get_objfile_arch (baton.objfile);
+  ctx->addr_size = dwarf2_per_cu_addr_size (per_cu);
+  ctx->baton = &baton;
+  ctx->read_reg = dwarf_expr_read_reg;
+  ctx->read_mem = dwarf_expr_read_mem;
+  ctx->get_frame_base = dwarf_expr_frame_base;
+  ctx->get_frame_cfa = dwarf_expr_frame_cfa;
+  ctx->get_tls_address = dwarf_expr_tls_address;
+  ctx->get_object_address = dwarf_expr_object_address;
+
+  dwarf_expr_eval (ctx, data, size);
+
+  /* It was used only during dwarf_expr_eval.  */
+  ctx->baton = NULL;
+
+  return ctx;
+}
+
+/* Evaluate DWARF expression at DLBATON expecting it produces exactly one
+   CORE_ADDR result on the DWARF stack stack.  */
+
+CORE_ADDR
+dwarf_locexpr_baton_eval (struct dwarf2_locexpr_baton *dlbaton)
+{
+  struct dwarf_expr_context *ctx;
+  CORE_ADDR retval;
+  struct cleanup *back_to = make_cleanup (null_cleanup, 0);
+
+  ctx = dwarf_expr_prep_ctx (NULL, dlbaton->data, dlbaton->size,
+			     dlbaton->per_cu);
+  if (ctx->num_pieces > 0)
+    error (_("DW_OP_*piece is unsupported for DW_FORM_block"));
+
+  retval = dwarf_expr_fetch (ctx, 0);
+
+  if (ctx->location == DWARF_VALUE_REGISTER)
+    {
+      /* Inlined dwarf_expr_read_reg as we no longer have the baton. */
+
+      int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (ctx->gdbarch, retval);
+      struct type *type = builtin_type (ctx->gdbarch)->builtin_data_ptr;
+      struct frame_info *frame = get_selected_frame (NULL);
+
+      retval = address_from_register (type, gdb_regnum, frame);
+    }
+
+  do_cleanups (back_to);
+
+  return retval;
+}
+
+/* Evaluate DWARF location list at DLLBATON expecting it produces exactly one
+   CORE_ADDR result stored to *ADDRP on the DWARF stack stack.  If the result
+   could not be found return zero and keep *ADDRP unchanged.  */
+
+int
+dwarf_loclist_baton_eval (struct dwarf2_loclist_baton *dllbaton,
+			  struct type *type, CORE_ADDR *addrp)
+{
+  struct frame_info *frame = get_selected_frame (NULL);
+  gdb_byte *data;
+  size_t size;
+  struct value *val;
+
+  data = find_location_expression (dllbaton, &size,
+				   get_frame_address_in_block (frame));
+  if (data == NULL)
+    return 0;
+
+  val = dwarf2_evaluate_loc_desc (type, frame, data, size, dllbaton->per_cu);
+  if (value_optimized_out (val))
+    return 0;
+
+  *addrp = value_as_address (val);
+  return 1;
+}
+
 struct piece_closure
 {
   /* The number of pieces used to describe this variable.  */
@@ -401,48 +570,31 @@ static struct lval_funcs pieced_value_funcs = {
    SIZE, to find the current location of variable VAR in the context
    of FRAME.  */
 static struct value *
-dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
+dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame,
 			  gdb_byte *data, unsigned short size,
 			  struct dwarf2_per_cu_data *per_cu)
 {
   struct value *retval;
-  struct dwarf_expr_baton baton;
   struct dwarf_expr_context *ctx;
-  struct cleanup *old_chain;
+  struct cleanup *old_chain = make_cleanup (null_cleanup, 0);
 
   if (size == 0)
     {
-      retval = allocate_value (SYMBOL_TYPE (var));
+      retval = allocate_value (type);
       VALUE_LVAL (retval) = not_lval;
       set_value_optimized_out (retval, 1);
       return retval;
     }
 
-  baton.frame = frame;
-  baton.objfile = dwarf2_per_cu_objfile (per_cu);
-
-  ctx = new_dwarf_expr_context ();
-  old_chain = make_cleanup_free_dwarf_expr_context (ctx);
-
-  ctx->gdbarch = get_objfile_arch (baton.objfile);
-  ctx->addr_size = dwarf2_per_cu_addr_size (per_cu);
-  ctx->baton = &baton;
-  ctx->read_reg = dwarf_expr_read_reg;
-  ctx->read_mem = dwarf_expr_read_mem;
-  ctx->get_frame_base = dwarf_expr_frame_base;
-  ctx->get_frame_cfa = dwarf_expr_frame_cfa;
-  ctx->get_tls_address = dwarf_expr_tls_address;
+  ctx = dwarf_expr_prep_ctx (frame, data, size, per_cu);
 
-  dwarf_expr_eval (ctx, data, size);
   if (ctx->num_pieces > 0)
     {
       struct piece_closure *c;
       struct frame_id frame_id = get_frame_id (frame);
 
       c = allocate_piece_closure (ctx->num_pieces, ctx->pieces, ctx->gdbarch);
-      retval = allocate_computed_value (SYMBOL_TYPE (var),
-					&pieced_value_funcs,
-					c);
+      retval = allocate_computed_value (type, &pieced_value_funcs, c);
       VALUE_FRAME_ID (retval) = frame_id;
     }
   else
@@ -454,7 +606,7 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
 	    struct gdbarch *arch = get_frame_arch (frame);
 	    CORE_ADDR dwarf_regnum = dwarf_expr_fetch (ctx, 0);
 	    int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, dwarf_regnum);
-	    retval = value_from_register (SYMBOL_TYPE (var), gdb_regnum, frame);
+	    retval = value_from_register (type, gdb_regnum, frame);
 	  }
 	  break;
 
@@ -463,7 +615,12 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
 	    CORE_ADDR address = dwarf_expr_fetch (ctx, 0);
 	    int in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0);
 
-	    retval = allocate_value (SYMBOL_TYPE (var));
+	    /* object_address_set called here is required in ALLOCATE_VALUE's
+	       CHECK_TYPEDEF for the object's possible
+	       DW_OP_push_object_address.  */
+	    object_address_set (address);
+
+	    retval = allocate_value (type);
 	    VALUE_LVAL (retval) = lval_memory;
 	    set_value_lazy (retval, 1);
 	    if (in_stack_memory)
@@ -478,10 +635,10 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
 	    bfd_byte *contents;
 	    size_t n = ctx->addr_size;
 
-	    retval = allocate_value (SYMBOL_TYPE (var));
+	    retval = allocate_value (type);
 	    contents = value_contents_raw (retval);
-	    if (n > TYPE_LENGTH (SYMBOL_TYPE (var)))
-	      n = TYPE_LENGTH (SYMBOL_TYPE (var));
+	    if (n > TYPE_LENGTH (type))
+	      n = TYPE_LENGTH (type);
 	    store_unsigned_integer (contents, n,
 				    gdbarch_byte_order (ctx->gdbarch),
 				    value);
@@ -493,10 +650,10 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
 	    bfd_byte *contents;
 	    size_t n = ctx->len;
 
-	    retval = allocate_value (SYMBOL_TYPE (var));
+	    retval = allocate_value (type);
 	    contents = value_contents_raw (retval);
-	    if (n > TYPE_LENGTH (SYMBOL_TYPE (var)))
-	      n = TYPE_LENGTH (SYMBOL_TYPE (var));
+	    if (n > TYPE_LENGTH (type))
+	      n = TYPE_LENGTH (type);
 	    memcpy (contents, ctx->data, n);
 	  }
 	  break;
@@ -720,8 +877,8 @@ locexpr_read_variable (struct symbol *symbol, struct frame_info *frame)
 {
   struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
   struct value *val;
-  val = dwarf2_evaluate_loc_desc (symbol, frame, dlbaton->data, dlbaton->size,
-				  dlbaton->per_cu);
+  val = dwarf2_evaluate_loc_desc (SYMBOL_TYPE (symbol), frame, dlbaton->data,
+				  dlbaton->size, dlbaton->per_cu);
 
   return val;
 }
@@ -844,7 +1001,7 @@ loclist_read_variable (struct symbol *symbol, struct frame_info *frame)
       set_value_optimized_out (val, 1);
     }
   else
-    val = dwarf2_evaluate_loc_desc (symbol, frame, data, size,
+    val = dwarf2_evaluate_loc_desc (SYMBOL_TYPE (symbol), frame, data, size,
 				    dlbaton->per_cu);
 
   return val;
@@ -868,7 +1025,7 @@ static int
 loclist_describe_location (struct symbol *symbol, struct ui_file *stream)
 {
   /* FIXME: Could print the entire list of locations.  */
-  fprintf_filtered (stream, "a variable with multiple locations");
+  fprintf_filtered (stream, _("a variable with multiple locations"));
   return 1;
 }
 
@@ -884,16 +1041,56 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
 
   data = find_location_expression (dlbaton, &size, ax->scope);
   if (data == NULL)
-    error (_("Variable \"%s\" is not available."), SYMBOL_NATURAL_NAME (symbol));
+    error (_("Variable \"%s\" is not available."), SYMBOL_PRINT_NAME (symbol));
 
   dwarf2_tracepoint_var_ref (symbol, gdbarch, ax, value, data, size);
 }
 
-/* The set of location functions used with the DWARF-2 expression
-   evaluator and location lists.  */
+/* The set of location functions used with the DWARF-2 location lists.  */
 const struct symbol_computed_ops dwarf2_loclist_funcs = {
   loclist_read_variable,
   loclist_read_needs_frame,
   loclist_describe_location,
   loclist_tracepoint_var_ref
 };
+
+static struct value *
+missing_read_variable (struct symbol *symbol, struct frame_info *frame)
+{
+  struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
+
+  gdb_assert (dlbaton == NULL);
+  error (_("Unable to resolve variable \"%s\""), SYMBOL_PRINT_NAME (symbol));
+}
+
+static int
+missing_read_needs_frame (struct symbol *symbol)
+{
+  return 0;
+}
+
+static int
+missing_describe_location (struct symbol *symbol, struct ui_file *stream)
+{
+  fprintf_filtered (stream, _("a variable we are unable to resolve"));
+  return 1;
+}
+
+static void
+missing_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch,
+			    struct agent_expr *ax, struct axs_value *value)
+{
+  struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol);
+
+  gdb_assert (dlbaton == NULL);
+  error (_("Unable to resolve variable \"%s\""), SYMBOL_PRINT_NAME (symbol));
+}
+
+/* The set of location functions used with the DWARF-2 evaluator when we are
+   unable to resolve the symbols.  */
+const struct symbol_computed_ops dwarf2_missing_funcs = {
+  missing_read_variable,
+  missing_read_needs_frame,
+  missing_describe_location,
+  missing_tracepoint_var_ref
+};
diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h
index fa0bd11..3535c1f 100644
--- a/gdb/dwarf2loc.h
+++ b/gdb/dwarf2loc.h
@@ -72,5 +72,14 @@ struct dwarf2_loclist_baton
 
 extern const struct symbol_computed_ops dwarf2_locexpr_funcs;
 extern const struct symbol_computed_ops dwarf2_loclist_funcs;
+extern const struct symbol_computed_ops dwarf2_missing_funcs;
+
+extern void object_address_set (CORE_ADDR address);
+
+extern CORE_ADDR dwarf_locexpr_baton_eval
+  (struct dwarf2_locexpr_baton *dlbaton);
+
+extern int dwarf_loclist_baton_eval (struct dwarf2_loclist_baton *dllbaton,
+				     struct type *type, CORE_ADDR *addrp);
 
 #endif /* dwarf2loc.h */
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index a05c946..9452844 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -48,6 +48,10 @@
 #include "gdbcmd.h"
 #include "block.h"
 #include "addrmap.h"
+#include "block.h"
+#include "f-lang.h"
+#include "typeprint.h"
+#include "jv-lang.h"
 
 #include <fcntl.h>
 #include "gdb_string.h"
@@ -96,7 +100,7 @@ typedef struct pubnames_header
 _PUBNAMES_HEADER;
 #define _ACTUAL_PUBNAMES_HEADER_SIZE 13
 
-/* .debug_pubnames header
+/* .debug_aranges header
    Because of alignment constraints, this structure has padding and cannot
    be mapped directly onto the beginning of the .debug_info section.  */
 typedef struct aranges_header
@@ -153,7 +157,10 @@ struct dwarf2_section_info
   asection *asection;
   gdb_byte *buffer;
   bfd_size_type size;
-  int was_mmapped;
+  /* A function to call to deallocate BUFFER.  If NULL, no
+     deallocation is needed.  A pointer to this structure is passed as
+     the only argument.  */
+  void (*destructor) (struct dwarf2_section_info *);
 };
 
 struct dwarf2_per_objfile
@@ -333,6 +340,19 @@ struct dwarf2_cu
      DIEs for namespaces, we don't need to try to infer them
      from mangled names.  */
   unsigned int has_namespace_info : 1;
+
+  /* Fields are valid according to the LANGUAGE field.  */
+  union
+    {
+      /* language_fortran */
+      struct
+        {
+	  /* Module names imported to the block being currently read in.  */
+	  struct fortran_using *use;
+	}
+      fortran;
+    }
+  language_specific;
 };
 
 /* Persistent data held for a compilation unit, even when not
@@ -487,8 +507,7 @@ struct partial_die_info
     unsigned int has_byte_size : 1;
 
     /* The name of this DIE.  Normally the value of DW_AT_name, but
-       sometimes DW_TAG_MIPS_linkage_name or a string computed in some
-       other fashion.  */
+       sometimes a default name for unnamed DIEs.  */
     char *name;
 
     /* The scope to prepend to our children.  This is generally
@@ -788,7 +807,8 @@ static void scan_partial_symbols (struct partial_die_info *,
 static void add_partial_symbol (struct partial_die_info *,
 				struct dwarf2_cu *);
 
-static int pdi_needs_namespace (enum dwarf_tag tag);
+static gdb_byte *read_comp_unit_head (struct comp_unit_head *, gdb_byte *,
+				      bfd *);
 
 static void add_partial_namespace (struct partial_die_info *pdi,
 				   CORE_ADDR *lowpc, CORE_ADDR *highpc,
@@ -813,6 +833,10 @@ static void dwarf2_psymtab_to_symtab (struct partial_symtab *);
 
 static void psymtab_to_symtab_1 (struct partial_symtab *);
 
+static void dwarf2_read_section_1 (struct objfile *objfile,
+				   struct obstack *obstack,
+				   struct dwarf2_section_info *info);
+
 static void dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu);
 
 static void dwarf2_free_abbrev_table (void *);
@@ -984,17 +1008,25 @@ static void dwarf2_attach_fn_fields_to_type (struct field_info *,
 
 static void process_structure_scope (struct die_info *, struct dwarf2_cu *);
 
-static const char *determine_class_name (struct die_info *die,
-					 struct dwarf2_cu *cu);
-
 static void read_common_block (struct die_info *, struct dwarf2_cu *);
 
 static void read_namespace (struct die_info *die, struct dwarf2_cu *);
 
+static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
+
 static void read_module (struct die_info *die, struct dwarf2_cu *cu);
 
 static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
 
+static struct type *read_module_type (struct die_info *die,
+				      struct dwarf2_cu *cu);
+
+static void read_fortran_imported_module (struct die_info *die,
+					  struct dwarf2_cu *cu);
+
+static void read_fortran_imported_declaration (struct die_info *die,
+					       struct dwarf2_cu *cu);
+
 static const char *namespace_name (struct die_info *die,
 				   int *is_anonymous, struct dwarf2_cu *);
 
@@ -1028,7 +1060,8 @@ static gdb_byte *read_full_die (const struct die_reader_specs *reader,
 
 static void process_die (struct die_info *, struct dwarf2_cu *);
 
-static char *dwarf2_linkage_name (struct die_info *, struct dwarf2_cu *);
+static char *fortran_module_linkage_name (struct die_info *die,
+					  struct dwarf2_cu *cu);
 
 static char *dwarf2_canonicalize_name (char *, struct dwarf2_cu *,
 				       struct obstack *);
@@ -1114,6 +1147,9 @@ static int attr_form_is_section_offset (struct attribute *);
 
 static int attr_form_is_constant (struct attribute *);
 
+static struct dwarf2_loclist_baton *dwarf2_attr_to_loclist_baton
+  (struct attribute *attr, struct dwarf2_cu *cu);
+
 static void dwarf2_symbol_mark_computed (struct attribute *attr,
 					 struct symbol *sym,
 					 struct dwarf2_cu *cu);
@@ -1144,6 +1180,9 @@ static void age_cached_comp_units (void);
 
 static void free_one_cached_comp_unit (void *);
 
+static void fetch_die_type_attrs (struct die_info *die, struct type *type,
+				  struct dwarf2_cu *cu);
+
 static struct type *set_die_type (struct die_info *, struct type *,
 				  struct dwarf2_cu *);
 
@@ -1163,22 +1202,31 @@ static void dwarf2_clear_marks (struct dwarf2_per_cu_data *);
 
 static struct type *get_die_type (struct die_info *die, struct dwarf2_cu *cu);
 
+static void destroy_section (struct dwarf2_section_info *info);
+
+static struct dwarf2_locexpr_baton *dwarf2_attr_to_locexpr_baton
+  (struct attribute *attr, struct dwarf2_cu *cu);
+
 /* Try to locate the sections we need for DWARF 2 debugging
    information and return true if we have enough to do something.  */
 
 int
 dwarf2_has_info (struct objfile *objfile)
 {
-  struct dwarf2_per_objfile *data;
-
-  /* Initialize per-objfile state.  */
-  data = obstack_alloc (&objfile->objfile_obstack, sizeof (*data));
-  memset (data, 0, sizeof (*data));
-  set_objfile_data (objfile, dwarf2_objfile_data_key, data);
-  dwarf2_per_objfile = data;
+  dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key);
+  if (!dwarf2_per_objfile)
+    {
+      /* Initialize per-objfile state.  */
+      struct dwarf2_per_objfile *data
+	= obstack_alloc (&objfile->objfile_obstack, sizeof (*data));
+      memset (data, 0, sizeof (*data));
+      set_objfile_data (objfile, dwarf2_objfile_data_key, data);
+      dwarf2_per_objfile = data;
 
-  bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, NULL);
-  return (data->info.asection != NULL && data->abbrev.asection != NULL);
+      bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, NULL);
+    }
+  return (dwarf2_per_objfile->info.asection != NULL
+	  && dwarf2_per_objfile->abbrev.asection != NULL);
 }
 
 /* When loading sections, we can either look for ".<name>", or for
@@ -1271,10 +1319,13 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *ignore_ptr)
 }
 
 /* Decompress a section that was compressed using zlib.  Store the
-   decompressed buffer, and its size, in OUTBUF and OUTSIZE.  */
+   decompressed buffer, and its size, in OUTBUF and OUTSIZE.  The
+   result is allocated on OBSTACK; if OBSTACK is NULL, xmalloc is
+   used.  */
 
 static void
-zlib_decompress_section (struct objfile *objfile, asection *sectp,
+zlib_decompress_section (struct objfile *objfile, struct obstack *obstack,
+			 asection *sectp,
                          gdb_byte **outbuf, bfd_size_type *outsize)
 {
   bfd *abfd = objfile->obfd;
@@ -1291,6 +1342,7 @@ zlib_decompress_section (struct objfile *objfile, asection *sectp,
   z_stream strm;
   int rc;
   int header_size = 12;
+  struct cleanup *old = NULL;
 
   if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0
       || bfd_bread (compressed_buffer, compressed_size, abfd) != compressed_size)
@@ -1320,8 +1372,13 @@ zlib_decompress_section (struct objfile *objfile, asection *sectp,
   strm.avail_in = compressed_size - header_size;
   strm.next_in = (Bytef*) compressed_buffer + header_size;
   strm.avail_out = uncompressed_size;
-  uncompressed_buffer = obstack_alloc (&objfile->objfile_obstack,
-                                       uncompressed_size);
+  if (obstack)
+    uncompressed_buffer = obstack_alloc (obstack, uncompressed_size);
+  else
+    {
+      uncompressed_buffer = xmalloc (uncompressed_size);
+      old = make_cleanup (xfree, uncompressed_buffer);
+    }
   rc = inflateInit (&strm);
   while (strm.avail_in > 0)
     {
@@ -1342,26 +1399,176 @@ zlib_decompress_section (struct objfile *objfile, asection *sectp,
     error (_("Dwarf Error: concluding DWARF uncompression in '%s': %d"),
            bfd_get_filename (abfd), rc);
 
+  if (old)
+    discard_cleanups (old);
   do_cleanups (cleanup);
   *outbuf = uncompressed_buffer;
   *outsize = uncompressed_size;
 #endif
 }
 
-/* Read the contents of the section SECTP from object file specified by
-   OBJFILE, store info about the section into INFO.
-   If the section is compressed, uncompress it before returning.  */
+/* A cleanup that calls destroy_section.  */
 
 static void
-dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
+destroy_section_cleanup (void *arg)
+{
+  destroy_section (arg);
+}
+
+/* Read the .debug_aranges section and construct an address map.  */
+
+void
+dwarf2_create_quick_addrmap (struct objfile *objfile)
+{
+  char *aranges_buffer, *aranges_ptr;
+  bfd *abfd = objfile->obfd;
+  CORE_ADDR baseaddr;
+  struct cleanup *old;
+  struct obstack temp_obstack;
+  struct addrmap *mutable_map;
+
+  if (!dwarf2_per_objfile->aranges.asection)
+    return;
+
+  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+  dwarf2_read_section_1 (objfile, NULL, &dwarf2_per_objfile->aranges);
+  aranges_buffer = dwarf2_per_objfile->aranges.buffer;
+  aranges_ptr = aranges_buffer;
+  old = make_cleanup (destroy_section_cleanup, &dwarf2_per_objfile->aranges);
+
+  obstack_init (&temp_obstack);
+  make_cleanup_obstack_free (&temp_obstack);
+  mutable_map = addrmap_create_mutable (&temp_obstack);
+
+  while ((aranges_ptr - aranges_buffer) < dwarf2_per_objfile->aranges.size)
+    {
+      struct comp_unit_head cu_header;
+      unsigned int bytes_read, segment_size, delta;
+      LONGEST info_offset;
+      struct dwarf2_cu cu;
+      char *end_ptr;
+
+      cu_header.initial_length_size = 0;
+      end_ptr = aranges_ptr;
+      aranges_ptr = read_comp_unit_head (&cu_header, aranges_ptr, abfd);
+      end_ptr += cu_header.initial_length_size + cu_header.length;
+
+      /* Sanity check.  */
+      if (end_ptr - aranges_ptr >= dwarf2_per_objfile->aranges.size)
+	{
+	  do_cleanups (old);
+	  complaint (&symfile_complaints,
+		     _("aranges entry runs off end of `.debug_aranges' section, ignored"));
+	  return;
+	}
+      if (cu_header.addr_size == 0)
+	{
+	  do_cleanups (old);
+	  complaint (&symfile_complaints,
+		     _("aranges entry has zero addr_size, ignored"));
+	  return;
+	}
+
+      segment_size = read_1_byte (abfd, aranges_ptr);
+      aranges_ptr += 1;
+
+      /* Align the pointer to twice the pointer size.  I didn't see
+	 this in the spec but it appears to be required.  */
+      delta = (aranges_ptr - aranges_buffer) % (2 * cu_header.addr_size);
+      delta = (2 * cu_header.addr_size - delta) % (2 * cu_header.addr_size);
+      aranges_ptr += delta;
+
+      memset (&cu, 0, sizeof (cu));
+      cu.header.addr_size = cu_header.addr_size;
+
+      while (1)
+	{
+	  CORE_ADDR address, length;
+
+	  address = read_address (abfd, aranges_ptr, &cu, &bytes_read);
+	  aranges_ptr += bytes_read;
+
+	  length = read_address (abfd, aranges_ptr, &cu, &bytes_read);
+	  aranges_ptr += bytes_read;
+
+	  if (address == 0 && length == 0)
+	    break;
+
+	  if (length == 0)
+	    {
+	      do_cleanups (old);
+	      complaint (&symfile_complaints,
+			 _("aranges entry has zero length, ignored"));
+	      return;
+	    }
+
+	  address += baseaddr;
+
+	  addrmap_set_empty (mutable_map, address, address + length - 1,
+			     objfile);
+	}
+
+      /* Some older versions of GCC incorrectly started the arange
+	 with a (0,0) pair.  If we encounter any oddity while reading
+	 the section, just abandon the attempt; falling back to the
+	 slower code is always safe.  */
+      if (aranges_ptr != end_ptr)
+	{
+	  do_cleanups (old);
+	  complaint (&symfile_complaints,
+		     _("aranges entry ends early, ignored"));
+	  return;
+	}
+    }
+
+  objfile->quick_addrmap = addrmap_create_fixed (mutable_map,
+						 &objfile->objfile_obstack);
+  do_cleanups (old);
+}
+
+/* Free a section buffer allocated with xmalloc.  */
+
+static void
+xfree_section_buffer (struct dwarf2_section_info *info)
+{
+  xfree (info->buffer);
+}
+
+/* If section described by INFO was mmapped, munmap it now.  */
+
+static void
+munmap_section_buffer (struct dwarf2_section_info *info)
+{
+#ifdef HAVE_MMAP
+  intptr_t begin = (intptr_t) info->buffer;
+  intptr_t map_begin = begin & ~(pagesize - 1);
+  size_t map_length = info->size + begin - map_begin;
+  gdb_assert (munmap ((void *) map_begin, map_length) == 0);
+#else
+  /* Without HAVE_MMAP, we should never be here to begin with.  */
+  gdb_assert (0);
+#endif
+}
+
+/* Read the contents of the section at OFFSET and of size SIZE from
+   the object file specified by OBJFILE into OBSTACK and store it into
+   INFO.  If OBSTACK is NULL, xmalloc is used instead.  If the section
+   is compressed, uncompress it before returning.  */
+
+static void
+dwarf2_read_section_1 (struct objfile *objfile,
+		       struct obstack *obstack,
+		       struct dwarf2_section_info *info)
 {
   bfd *abfd = objfile->obfd;
   asection *sectp = info->asection;
   gdb_byte *buf, *retbuf;
   unsigned char header[4];
+  struct cleanup *old = NULL;
 
   info->buffer = NULL;
-  info->was_mmapped = 0;
+  info->destructor = 0;
 
   if (info->asection == NULL || info->size == 0)
     return;
@@ -1374,7 +1581,7 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
       /* Upon decompression, update the buffer and its size.  */
       if (strncmp (header, "ZLIB", sizeof (header)) == 0)
         {
-          zlib_decompress_section (objfile, sectp, &info->buffer,
+          zlib_decompress_section (objfile, obstack, sectp, &info->buffer,
 				   &info->size);
           return;
         }
@@ -1397,7 +1604,7 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
 
       if (retbuf != MAP_FAILED)
 	{
-	  info->was_mmapped = 1;
+	  info->destructor = munmap_section_buffer;
 	  info->buffer = retbuf + (sectp->filepos & (pagesize - 1)) ;
 	  return;
 	}
@@ -1405,8 +1612,15 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
 #endif
 
   /* If we get here, we are a normal, not-compressed section.  */
-  info->buffer = buf
-    = obstack_alloc (&objfile->objfile_obstack, info->size);
+  if (obstack)
+    buf = obstack_alloc (obstack, info->size);
+  else
+    {
+      buf = xmalloc (info->size);
+      old = make_cleanup (xfree, buf);
+      info->destructor = xfree_section_buffer;
+    }
+  info->buffer = buf;
 
   /* When debugging .o files, we may need to apply relocations; see
      http://sourceware.org/ml/gdb-patches/2002-04/msg00136.html .
@@ -1415,6 +1629,8 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
   retbuf = symfile_relocate_debug_section (objfile, sectp, buf);
   if (retbuf != NULL)
     {
+      if (old)
+	discard_cleanups (old);
       info->buffer = retbuf;
       return;
     }
@@ -1423,6 +1639,19 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
       || bfd_bread (buf, info->size, abfd) != info->size)
     error (_("Dwarf Error: Can't read DWARF data from '%s'"),
 	   bfd_get_filename (abfd));
+
+  if (old)
+    discard_cleanups (old);
+}
+
+/* Read the contents of the section SECTP from object file specified by
+   OBJFILE, store info about the section into INFO.
+   If the section is compressed, uncompress it before returning.  */
+
+static void
+dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
+{
+  dwarf2_read_section_1 (objfile, &objfile->objfile_obstack, info);
 }
 
 /* Fill in SECTP, BUFP and SIZEP with section info, given OBJFILE and
@@ -2070,6 +2299,29 @@ build_type_psymtabs (struct objfile *objfile)
 			  process_type_comp_unit, objfile);
 }
 
+/* A cleanup function that clears an objfile's psymtabs.  There are
+   two cases to consider.  If we are reading symbols directly, then on
+   a failure the objfile will be destroyed.  In this case, clearing
+   the psymtabs is fine -- a little wasted time, but nothing serious.
+   If we are reading symbols lazily, then it is too late to destroy
+   the objfile.  Instead we just make it look like the objfile has no
+   psymtabs.  */
+
+static void
+do_clear_psymtabs (void *arg)
+{
+  struct objfile *objfile = arg;
+
+  objfile->psymtabs_addrmap = NULL;
+  objfile->psymtabs = NULL;
+  bcache_xfree (objfile->psymbol_cache);
+  objfile->psymbol_cache = bcache_xmalloc ();
+  xfree (objfile->global_psymbols.list);
+  memset (&objfile->global_psymbols, 0, sizeof (objfile->global_psymbols));
+  xfree (objfile->static_psymbols.list);
+  memset (&objfile->static_psymbols, 0, sizeof (objfile->static_psymbols));
+}
+
 /* Build the partial symbol table by doing a quick pass through the
    .debug_info and .debug_abbrev sections.  */
 
@@ -2080,7 +2332,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile)
      mmap()  on architectures that support it. (FIXME) */
   bfd *abfd = objfile->obfd;
   gdb_byte *info_ptr;
-  struct cleanup *back_to;
+  struct cleanup *back_to, *clear_psymtabs;
 
   info_ptr = dwarf2_per_objfile->info.buffer;
 
@@ -2094,6 +2346,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile)
 
   objfile->psymtabs_addrmap =
     addrmap_create_mutable (&objfile->objfile_obstack);
+  clear_psymtabs = make_cleanup (do_clear_psymtabs, objfile);
 
   /* Since the objects we're extracting from .debug_info vary in
      length, only the individual functions to extract them (like
@@ -2123,6 +2376,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile)
 					    dwarf2_per_objfile->info.size);
     }
 
+  discard_cleanups (clear_psymtabs);
   objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap,
 						    &objfile->objfile_obstack);
 
@@ -2389,11 +2643,18 @@ partial_die_parent_scope (struct partial_die_info *pdi,
       || parent->tag == DW_TAG_union_type
       || parent->tag == DW_TAG_enumeration_type)
     {
+      char *parent_name = parent->name;
+
+      /* G++ 4.1 produced DW_TAG_namespace with DW_AT_name "::".  */
+      if (parent->tag == DW_TAG_namespace && parent_name != NULL
+          && strcmp (parent_name, "::") == 0)
+	parent_name = NULL;
+
       if (grandparent_scope == NULL)
-	parent->scope = parent->name;
+	parent->scope = parent_name;
       else
 	parent->scope = typename_concat (&cu->comp_unit_obstack, grandparent_scope,
-					 parent->name, cu);
+					 parent_name, cu);
     }
   else if (parent->tag == DW_TAG_enumerator)
     /* Enumerators should not get the name of the enumeration as a prefix.  */
@@ -2405,7 +2666,7 @@ partial_die_parent_scope (struct partial_die_info *pdi,
 	 ignoring them.  */
       complaint (&symfile_complaints,
 		 _("unhandled containing DIE tag %d for DIE at %d"),
-		 parent->tag, pdi->offset);
+		 parent->tag, real_pdi->offset);
       parent->scope = grandparent_scope;
     }
 
@@ -2420,12 +2681,22 @@ partial_die_full_name (struct partial_die_info *pdi,
 		       struct dwarf2_cu *cu)
 {
   char *parent_scope;
+  struct partial_die_info *real_pdi;
 
-  parent_scope = partial_die_parent_scope (pdi, cu);
-  if (parent_scope == NULL)
-    return NULL;
-  else
+  /* We need to look at our parent DIE; if we have a DW_AT_specification,
+     then this means the parent of the specification DIE.
+     partial_die_parent_scope does this loop also, but we do it here
+     since we need to examine real_pdi->parent ourselves.  */
+
+  real_pdi = pdi;
+  while (real_pdi->has_specification)
+    real_pdi = find_partial_die (real_pdi->spec_offset, cu);
+
+  parent_scope = partial_die_parent_scope (real_pdi, cu);
+  if (parent_scope != NULL)
     return typename_concat (NULL, parent_scope, pdi->name, cu);
+
+  return NULL;
 }
 
 static void
@@ -2441,12 +2712,9 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
-  if (pdi_needs_namespace (pdi->tag))
-    {
-      actual_name = partial_die_full_name (pdi, cu);
-      if (actual_name)
-	built_actual_name = 1;
-    }
+  actual_name = partial_die_full_name (pdi, cu);
+  if (actual_name)
+    built_actual_name = 1;
 
   if (actual_name == NULL)
     actual_name = pdi->name;
@@ -2543,6 +2811,13 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 			   &objfile->global_psymbols,
 			   0, (CORE_ADDR) 0, cu->language, objfile);
       break;
+    case DW_TAG_module:
+      add_psymbol_to_list (actual_name, strlen (actual_name),
+			   built_actual_name,
+			   MODULE_DOMAIN, LOC_STATIC,
+			   &objfile->global_psymbols,
+			   0, (CORE_ADDR) 0, cu->language, objfile);
+      break;
     case DW_TAG_class_type:
     case DW_TAG_interface_type:
     case DW_TAG_structure_type:
@@ -2586,49 +2861,10 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
       break;
     }
 
-  /* Check to see if we should scan the name for possible namespace
-     info.  Only do this if this is C++, if we don't have namespace
-     debugging info in the file, if the psym is of an appropriate type
-     (otherwise we'll have psym == NULL), and if we actually had a
-     mangled name to begin with.  */
-
-  /* FIXME drow/2004-02-22: Why don't we do this for classes, i.e. the
-     cases which do not set PSYM above?  */
-
-  if (cu->language == language_cplus
-      && cu->has_namespace_info == 0
-      && psym != NULL
-      && SYMBOL_CPLUS_DEMANGLED_NAME (psym) != NULL)
-    cp_check_possible_namespace_symbols (SYMBOL_CPLUS_DEMANGLED_NAME (psym),
-					 objfile);
-
   if (built_actual_name)
     xfree (actual_name);
 }
 
-/* Determine whether a die of type TAG living in a C++ class or
-   namespace needs to have the name of the scope prepended to the
-   name listed in the die.  */
-
-static int
-pdi_needs_namespace (enum dwarf_tag tag)
-{
-  switch (tag)
-    {
-    case DW_TAG_namespace:
-    case DW_TAG_typedef:
-    case DW_TAG_class_type:
-    case DW_TAG_interface_type:
-    case DW_TAG_structure_type:
-    case DW_TAG_union_type:
-    case DW_TAG_enumeration_type:
-    case DW_TAG_enumerator:
-      return 1;
-    default:
-      return 0;
-    }
-}
-
 /* Read a partial die corresponding to a namespace; also, add a symbol
    corresponding to that namespace to the symbol table.  NAMESPACE is
    the name of the enclosing namespace.  */
@@ -2656,12 +2892,12 @@ static void
 add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
 		    CORE_ADDR *highpc, int need_pc, struct dwarf2_cu *cu)
 {
-  /* Now scan partial symbols in that module.
+  /* Add a symbol for the module.  */
 
-     FIXME: Support the separate Fortran module namespaces.  */
+  add_partial_symbol (pdi, cu);
 
-  if (pdi->has_children)
-    scan_partial_symbols (pdi->die_child, lowpc, highpc, need_pc, cu);
+  /* Partial symbols in that module are not scanned as they are never globally
+     visible.  They get imported to the specific scopes on the full read.  */
 }
 
 /* Read a partial die corresponding to a subprogram and create a partial
@@ -2739,7 +2975,6 @@ guess_structure_name (struct partial_die_info *struct_pdi,
 	 could fix this by only using the demangled name to get the
 	 prefix (but see comment in read_structure_type).  */
 
-      struct partial_die_info *child_pdi = struct_pdi->die_child;
       struct partial_die_info *real_pdi;
 
       /* If this DIE (this DIE's specification, if any) has a parent, then
@@ -2752,27 +2987,6 @@ guess_structure_name (struct partial_die_info *struct_pdi,
 
       if (real_pdi->die_parent != NULL)
 	return;
-
-      while (child_pdi != NULL)
-	{
-	  if (child_pdi->tag == DW_TAG_subprogram)
-	    {
-	      char *actual_class_name
-		= language_class_name_from_physname (cu->language_defn,
-						     child_pdi->name);
-	      if (actual_class_name != NULL)
-		{
-		  struct_pdi->name
-		    = obsavestring (actual_class_name,
-				    strlen (actual_class_name),
-				    &cu->objfile->objfile_obstack);
-		  xfree (actual_class_name);
-		}
-	      break;
-	    }
-
-	  child_pdi = child_pdi->die_sibling;
-	}
     }
 }
 
@@ -3325,6 +3539,14 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
     case DW_TAG_imported_declaration:
     case DW_TAG_imported_module:
       processing_has_namespace_info = 1;
+      if (cu->language == language_fortran)
+	{
+	  if (die->tag == DW_TAG_imported_declaration)
+	    read_fortran_imported_declaration (die, cu);
+	  else
+	    read_fortran_imported_module (die, cu);
+	  break;
+	}
       if (die->child != NULL && (die->tag == DW_TAG_imported_declaration
 				 || cu->language != language_fortran))
 	complaint (&symfile_complaints, _("Tag '%s' has unexpected children"),
@@ -3337,42 +3559,183 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
     }
 }
 
+/* A helper function for dwarf2_compute_name which determines whether DIE
+   needs to have the name of the scope prepended to the name listed in the
+   die.  */
+
+static int
+die_needs_namespace (struct die_info *die, struct dwarf2_cu *cu)
+{
+  switch (die->tag)
+    {
+    case DW_TAG_namespace:
+    case DW_TAG_typedef:
+    case DW_TAG_class_type:
+    case DW_TAG_interface_type:
+    case DW_TAG_structure_type:
+    case DW_TAG_union_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_enumerator:
+    case DW_TAG_subprogram:
+    case DW_TAG_member:
+      return 1;
+
+    case DW_TAG_variable:
+      {
+	struct attribute *attr;
+
+	/* We only need to prefix "globally" visible variables.  These include
+	   any variable marked with DW_AT_external or any variable that
+	   lives in a namespace.  [Variables in anonymous namespaces
+	   require prefixing, but they are not DW_AT_external.]  */
+
+	if (dwarf2_attr (die, DW_AT_specification, cu))
+	  {
+	    struct dwarf2_cu *spec_cu = cu;
+	    return die_needs_namespace (die_specification (die, &spec_cu),
+					spec_cu);
+	  }
+
+	/* A variable in a lexical block of some kind does not need
+	   a namespace, even though in C++ such variables may be
+	   external and have a mangled name.  */
+	if (die->parent->tag == DW_TAG_lexical_block
+	    || die->parent->tag == DW_TAG_try_block
+	    || die->parent->tag == DW_TAG_catch_block)
+	  return 0;
+
+	attr = dwarf2_attr (die, DW_AT_external, cu);
+	if (attr || die->parent->tag == DW_TAG_namespace)
+	  return 1;
+
+	return 0;
+      }
+
+    default:
+      return 0;
+    }
+}
+
+/* Compute the fully qualified name of DIE in CU.  If PHYSNAME is nonzero,
+   compute the physname for the object, which include a method's
+   formal parameters (C++/Java) and return type (Java).
+
+   The result is allocated on the objfile_obstack and canonicalized.  */
+
+static const char *
+dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu,
+		     int physname)
+{
+  if (name == NULL)
+    name = dwarf2_name (die, cu);
+
+  /* These are the only languages we know how to qualify names in.  */
+  if (name != NULL
+      && (cu->language == language_cplus || cu->language == language_java))
+    {
+      if (die_needs_namespace (die, cu))
+	{
+	  long length;
+	  char *prefix;
+	  struct ui_file *buf;
+
+	  prefix = determine_prefix (die, cu);
+	  buf = mem_fileopen ();
+	  if (*prefix != '\0')
+	    {
+	      char *prefixed_name = typename_concat (NULL, prefix, name, cu);
+	      fputs_unfiltered (prefixed_name, buf);
+	      xfree (prefixed_name);
+	    }
+	  else
+	    fputs_unfiltered (name ? name : "", buf);
+
+	  /* For Java and C++ methods, append formal parameter type
+	     information, if PHYSNAME.  */
+
+	  if (physname && die->tag == DW_TAG_subprogram
+	      && (cu->language == language_cplus
+		  || cu->language == language_java))
+	    {
+	      struct type *type = read_type_die (die, cu);
+
+	      c_type_print_args (type, buf, 0, cu->language);
+
+	      if (cu->language == language_java)
+		{
+		  /* For java, we must append the return type to method
+		     names. */
+		  if (die->tag == DW_TAG_subprogram)
+		    java_print_type (TYPE_TARGET_TYPE (type), "", buf,
+				     0, 0);
+		}
+	      else if (cu->language == language_cplus)
+		{
+		  if (TYPE_NFIELDS (type) > 0
+		      && TYPE_FIELD_ARTIFICIAL (type, 0)
+		      && TYPE_CONST (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, 0))))
+		    fputs_unfiltered (" const", buf);
+		}
+	    }
+
+	  name = ui_file_obsavestring (buf, &cu->objfile->objfile_obstack,
+				       &length);
+	  ui_file_delete (buf);
+
+	  if (cu->language == language_cplus)
+	    {
+	      char *cname
+		= dwarf2_canonicalize_name (name, cu,
+					    &cu->objfile->objfile_obstack);
+	      if (cname != NULL)
+		name = cname;
+	    }
+	}
+    }
+
+  return name;
+}
+
 /* Return the fully qualified name of DIE, based on its DW_AT_name.
    If scope qualifiers are appropriate they will be added.  The result
    will be allocated on the objfile_obstack, or NULL if the DIE does
-   not have a name.  */
+   not have a name.  NAME may either be from a previous call to
+   dwarf2_name or NULL.
+
+   The output string will be canonicalized (if C++/Java). */
 
 static const char *
-dwarf2_full_name (struct die_info *die, struct dwarf2_cu *cu)
+dwarf2_full_name (char *name, struct die_info *die, struct dwarf2_cu *cu)
 {
-  struct attribute *attr;
-  char *prefix, *name;
-  struct ui_file *buf = NULL;
+  return dwarf2_compute_name (name, die, cu, 0);
+}
 
-  name = dwarf2_name (die, cu);
-  if (!name)
-    return NULL;
+/* Construct a physname for the given DIE in CU.  NAME may either be
+   from a previous call to dwarf2_name or NULL.  The result will be
+   allocated on teh objfile_objstack or NULL if the DIE does not have a
+   name.
 
-  /* These are the only languages we know how to qualify names in.  */
-  if (cu->language != language_cplus
-      && cu->language != language_java)
-    return name;
-
-  /* If no prefix is necessary for this type of DIE, return the
-     unqualified name.  The other three tags listed could be handled
-     in pdi_needs_namespace, but that requires broader changes.  */
-  if (!pdi_needs_namespace (die->tag)
-      && die->tag != DW_TAG_subprogram
-      && die->tag != DW_TAG_variable
-      && die->tag != DW_TAG_member)
-    return name;
-
-  prefix = determine_prefix (die, cu);
-  if (*prefix != '\0')
-    name = typename_concat (&cu->objfile->objfile_obstack, prefix,
-			    name, cu);
+   The output string will be canonicalized (if C++/Java).  */
 
-  return name;
+static const char *
+dwarf2_physname (char *name, struct die_info *die, struct dwarf2_cu *cu)
+{
+  return dwarf2_compute_name (name, die, cu, 1);
+}
+
+/* Read the given DIE's DW_AT_decl_line number.  Return -1 if in case of an
+   error.  */
+
+static int
+dwarf2_read_decl_line (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct attribute *line_attr;
+
+  line_attr = dwarf2_attr (die, DW_AT_decl_line, cu);
+  if (line_attr)
+    return DW_UNSND (line_attr);
+
+  return -1;
 }
 
 /* Read the import statement specified by the given die and record it.  */
@@ -3385,11 +3748,15 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
   struct dwarf2_cu *imported_cu;
   const char *imported_name;
   const char *imported_name_prefix;
-  char *import_alias;
-
-  const char *import_prefix;
   char *canonical_name;
-
+  const char *import_alias;
+  const char *imported_declaration = "";
+  const char *import_prefix;
+  
+  int line_number = -1;
+  
+  int is_anonymous = 0;
+  
   import_attr = dwarf2_attr (die, DW_AT_import, cu);
   if (import_attr == NULL)
     {
@@ -3439,19 +3806,25 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
     }
 
   /* Figure out the local name after import.  */
-  import_alias = dwarf2_name (die, cu);
+  import_alias = dwarf2_name(die, cu);
 
-  /* Figure out where the statement is being imported to.  */
+  
+  /* Determine the line number at which the import was made */
+  line_number = dwarf2_read_decl_line(die, cu);
+  
+  /* Figure out where the statement is being imported to */
   import_prefix = determine_prefix (die, cu);
 
   /* Figure out what the scope of the imported die is and prepend it
      to the name of the imported die.  */
   imported_name_prefix = determine_prefix (imported_die, imported_cu);
-
-  if (strlen (imported_name_prefix) > 0)
-    {
-      canonical_name = alloca (strlen (imported_name_prefix)
-                               + 2 + strlen (imported_name) + 1);
+  
+  if(imported_die->tag != DW_TAG_namespace){
+    imported_declaration = imported_name;
+    canonical_name = (char*)imported_name_prefix;
+  }else{
+    if(strlen (imported_name_prefix) > 0){
+      canonical_name = alloca (strlen (imported_name_prefix) + 2 + strlen (imported_name) + 1);
       strcpy (canonical_name, imported_name_prefix);
       strcat (canonical_name, "::");
       strcat (canonical_name, imported_name);
@@ -3461,10 +3834,13 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
       canonical_name = alloca (strlen (imported_name) + 1);
       strcpy (canonical_name, imported_name);
     }
-
+  }
+  
   using_directives = cp_add_using (import_prefix,
                                    canonical_name,
                                    import_alias,
+                                   imported_declaration,
+                                   line_number,
                                    using_directives);
 }
 
@@ -3734,6 +4110,14 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
   struct attribute *attr;
 
   attr = dwarf2_attr (die, DW_AT_abstract_origin, cu);
+  
+  /* GCC 4.3 incorrectly uses DW_AT_specification to indicate die inheritence
+     in the case of import statements. The following is to accommodate 
+     that.  */
+  if(!attr){
+    attr = dwarf2_attr (die, DW_AT_specification, cu);
+  }
+  
   if (!attr)
     return;
 
@@ -3832,6 +4216,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
   char *name;
   CORE_ADDR baseaddr;
   struct block *block;
+  unsigned die_children = 0;
   int inlined_func = (die->tag == DW_TAG_inlined_subroutine);
 
   if (inlined_func)
@@ -3850,13 +4235,23 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
-  name = dwarf2_linkage_name (die, cu);
+  name = dwarf2_name (die, cu);
 
   /* Ignore functions with missing or empty names and functions with
      missing or invalid low and high pc attributes.  */
-  if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL))
+  if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL)){
+    /* explore abstract origins if present. They might contain useful information
+     such as import statements. */
+    child_die = die->child;
+    while (child_die && child_die->tag)
+      {
+	child_die = sibling_die (child_die);
+	die_children++;
+      }
+    inherit_abstract_dies(die, cu);
     return;
-
+  }
+  
   lowpc += baseaddr;
   highpc += baseaddr;
 
@@ -3883,14 +4278,19 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
 
   cu->list_in_scope = &local_symbols;
 
-  if (die->child != NULL)
+  switch (cu->language)
     {
-      child_die = die->child;
-      while (child_die && child_die->tag)
-	{
-	  process_die (child_die, cu);
-	  child_die = sibling_die (child_die);
-	}
+    case language_fortran:
+      cu->language_specific.fortran.use = NULL;
+      break;
+    }
+
+  child_die = die->child;
+  while (child_die && child_die->tag)
+    {
+      process_die (child_die, cu);
+      child_die = sibling_die (child_die);
+      die_children++;
     }
 
   inherit_abstract_dies (die, cu);
@@ -3906,6 +4306,13 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
 			determine_prefix (die, cu),
 			processing_has_namespace_info);
 
+  switch (cu->language)
+    {
+    case language_fortran:
+      BLOCK_FORTRAN_USE (block) = cu->language_specific.fortran.use;
+      break;
+    }
+
   /* If we have address ranges, record them.  */
   dwarf2_record_block_ranges (die, block, baseaddr, cu);
   
@@ -4524,7 +4931,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
 	return;
 
       /* Get physical name.  */
-      physname = dwarf2_linkage_name (die, cu);
+      physname = (char *) dwarf2_physname (fieldname, die, cu);
 
       /* The name is already allocated along with this objfile, so we don't
 	 need to duplicate it for the type.  */
@@ -4686,7 +5093,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
     return;
 
   /* Get the mangled name.  */
-  physname = dwarf2_linkage_name (die, cu);
+  physname = (char *) dwarf2_physname (fieldname, die, cu);
 
   /* Look up member function name in fieldlist.  */
   for (i = 0; i < fip->nfnfields; i++)
@@ -4993,14 +5400,18 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
       if (cu->language == language_cplus
 	  || cu->language == language_java)
 	{
-	  const char *new_prefix = determine_class_name (die, cu);
-	  TYPE_TAG_NAME (type) = (char *) new_prefix;
+	  TYPE_TAG_NAME (type) = (char *) dwarf2_full_name (name, die, cu);
+	  if (die->tag == DW_TAG_structure_type
+	      || die->tag == DW_TAG_class_type)
+	    TYPE_NAME (type) = TYPE_TAG_NAME (type);
 	}
       else
 	{
 	  /* The name is already allocated along with this objfile, so
 	     we don't need to duplicate it for the type.  */
-	  TYPE_TAG_NAME (type) = name;
+	  TYPE_TAG_NAME (type) = (char *) name;
+	  if (die->tag == DW_TAG_class_type)
+	    TYPE_NAME (type) = TYPE_TAG_NAME (type);
 	}
     }
 
@@ -5219,7 +5630,7 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
   type = alloc_type (objfile);
 
   TYPE_CODE (type) = TYPE_CODE_ENUM;
-  name = dwarf2_full_name (die, cu);
+  name = dwarf2_full_name (NULL, die, cu);
   if (name != NULL)
     TYPE_TAG_NAME (type) = (char *) name;
 
@@ -5244,51 +5655,6 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
   return set_die_type (die, type, cu);
 }
 
-/* Determine the name of the type represented by DIE, which should be
-   a named C++ or Java compound type.  Return the name in question,
-   allocated on the objfile obstack.  */
-
-static const char *
-determine_class_name (struct die_info *die, struct dwarf2_cu *cu)
-{
-  const char *new_prefix = NULL;
-
-  /* If we don't have namespace debug info, guess the name by trying
-     to demangle the names of members, just like we did in
-     guess_structure_name.  */
-  if (!processing_has_namespace_info)
-    {
-      struct die_info *child;
-
-      for (child = die->child;
-	   child != NULL && child->tag != 0;
-	   child = sibling_die (child))
-	{
-	  if (child->tag == DW_TAG_subprogram)
-	    {
-	      char *phys_prefix
-		= language_class_name_from_physname (cu->language_defn,
-						     dwarf2_linkage_name
-						     (child, cu));
-
-	      if (phys_prefix != NULL)
-		{
-		  new_prefix
-		    = obsavestring (phys_prefix, strlen (phys_prefix),
-				    &cu->objfile->objfile_obstack);
-		  xfree (phys_prefix);
-		  break;
-		}
-	    }
-	}
-    }
-
-  if (new_prefix == NULL)
-    new_prefix = dwarf2_full_name (die, cu);
-
-  return new_prefix;
-}
-
 /* Given a pointer to a die which begins an enumeration, process all
    the dies that define the members of the enumeration, and create the
    symbol for the enumeration type.
@@ -5366,6 +5732,29 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
   new_symbol (die, this_type, cu);
 }
 
+/* Create a new array dimension referencing its target type TYPE.
+
+   Multidimensional arrays are internally represented as a stack of
+   singledimensional arrays being referenced by their TYPE_TARGET_TYPE.  */
+
+static struct type *
+create_single_array_dimension (struct type *type, struct type *range_type,
+			       struct die_info *die, struct dwarf2_cu *cu)
+{
+  type = create_array_type (NULL, type, range_type);
+
+  /* These generic type attributes need to be fetched by
+     evaluate_subexp_standard <multi_f77_subscript>'s call of
+     value_subscripted_rvalue only for the innermost array type.  */
+  fetch_die_type_attrs (die, type, cu);
+
+  /* These generic type attributes are checked for allocated/associated
+     validity while accessing FIELD_LOC_KIND_DWARF_BLOCK.  */
+  fetch_die_type_attrs (die, range_type, cu);
+
+  return type;
+}
+
 /* Extract all information from a DW_TAG_array_type DIE and put it in
    the DIE's type field.  For now, this only handles one dimensional
    arrays.  */
@@ -5379,7 +5768,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
   struct type *element_type, *range_type, *index_type;
   struct type **range_types = NULL;
   struct attribute *attr;
-  int ndim = 0;
+  int ndim = 0, i;
   struct cleanup *back_to;
   char *name;
 
@@ -5426,16 +5815,11 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
   type = element_type;
 
   if (read_array_order (die, cu) == DW_ORD_col_major)
-    {
-      int i = 0;
-      while (i < ndim)
-	type = create_array_type (NULL, type, range_types[i++]);
-    }
-  else
-    {
-      while (ndim-- > 0)
-	type = create_array_type (NULL, type, range_types[ndim]);
-    }
+    for (i = 0; i < ndim; i++)
+      type = create_single_array_dimension (type, range_types[i], die, cu);
+  else /* (read_array_order (die, cu) == DW_ORD_row_major) */
+    for (i = ndim - 1; i >= 0; i--)
+      type = create_single_array_dimension (type, range_types[i], die, cu);
 
   /* Understand Dwarf2 support for vector types (like they occur on
      the PowerPC w/ AltiVec).  Gcc just adds another attribute to the
@@ -5624,7 +6008,7 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu)
       if (is_anonymous)
 	{
 	  const char *previous_prefix = determine_prefix (die, cu);
-	  cp_add_using_directive (previous_prefix, TYPE_NAME (type), NULL);
+	  cp_add_using_directive (previous_prefix, TYPE_NAME (type), NULL, "", dwarf2_read_decl_line(die, cu));
 	}
     }
 
@@ -5640,20 +6024,155 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu)
     }
 }
 
-/* Read a Fortran module.  */
+/* Read a Fortran module as global symbol which can be later looked up by
+   f_lookup_symbol_nonlocal.  */
 
 static void
 read_module (struct die_info *die, struct dwarf2_cu *cu)
 {
-  struct die_info *child_die = die->child;
+  struct type *type;
+
+  type = read_module_type (die, cu);
+
+  if (type)
+    new_symbol (die, type, cu);
+}
+
+/* Read a Fortran module as type.
+
+   Modules present only as declarations - being used only for DW_AT_import of
+   DW_TAG_imported_module - are ignored here.  They are read in only in form of
+   the module name by read_fortran_imported_module.  */
+
+static struct type *
+read_module_type (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct objfile *objfile = cu->objfile;
+  struct die_info *child_die;
+  struct type *type;
+  char *module_name;
+  struct context_stack *new;
+  struct pending *save_file_symbols;
+  struct pending *save_global_symbols;
+  struct pending **save_list_in_scope;
+
+  if (die_is_declaration (die, cu))
+    return NULL;
+
+  module_name = dwarf2_name (die, cu);
+  if (!module_name)
+    complaint (&symfile_complaints, _("DW_TAG_module has no name, offset 0x%x"),
+               die->offset);
+  type = init_type (TYPE_CODE_MODULE, 0, 0, module_name, objfile);
+
+  /* Create a context for reading the module variables.  */
+
+  new = push_context (0, 0);
+
+  save_file_symbols = file_symbols;
+  file_symbols = NULL;
+  save_global_symbols = global_symbols;
+  global_symbols = NULL;
+  save_list_in_scope = cu->list_in_scope;
 
-  /* FIXME: Support the separate Fortran module namespaces.  */
+  /* Process the child DIEs.  */
 
+  child_die = die->child;
   while (child_die && child_die->tag)
     {
+      /* Any DW_TAG_subprogram will reset LIST_IN_SCOPE to LOCAL_SYMBOLS.  */
+      cu->list_in_scope = &global_symbols;
+
       process_die (child_die, cu);
       child_die = sibling_die (child_die);
     }
+
+  /* Finish this module and restore the context.  */
+
+  TYPE_MODULE_BLOCK (type) = finish_block (NULL, &global_symbols,
+                                           new->old_blocks, 0, 0, objfile);
+
+  if (file_symbols)
+    complaint (&symfile_complaints, _("DW_TAG_module contains static symbols"));
+  if (local_symbols)
+    complaint (&symfile_complaints, _("DW_TAG_module contains local symbols"));
+  if (param_symbols)
+    complaint (&symfile_complaints, _("DW_TAG_module contains function "
+				      "parameters"));
+
+  file_symbols = save_file_symbols;
+  global_symbols = save_global_symbols;
+  cu->list_in_scope = save_list_in_scope;
+
+  pop_context ();
+
+  set_die_type (die, type, cu);
+
+  return type;
+}
+
+/* Import a Fortran module.  Only store the module name for its later lookup by
+   f_lookup_symbol_nonlocal.  */
+
+static void
+read_fortran_imported_module (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct objfile *objfile = cu->objfile;
+  struct attribute *attr;
+  struct die_info *module_die;
+  char *module_name;
+  struct fortran_using *use;
+
+  attr = dwarf2_attr (die, DW_AT_import, cu);
+  if (attr == NULL)
+    return;
+
+  module_die = follow_die_ref (die, attr, &cu);
+  module_name = dwarf2_name (module_die, cu);
+  if (module_name == NULL)
+    {
+      complaint (&symfile_complaints,
+		 _("Imported DIE at offset 0x%x has no name"), die->offset);
+      return;
+    }
+
+  /* Fortran does not allow any duplicity between local and any of the imported
+     symbols.  Therefore the order of the USE statements is not portant.
+     gfortran prints:
+     Error: Name 'X' at (1) is an ambiguous reference to 'X' from module 'Y'  */
+
+  use = obstack_alloc (&objfile->objfile_obstack, sizeof (*use)
+						  + strlen (module_name));
+  strcpy (use->module_name, module_name);
+  gdb_assert (cu->language == language_fortran);
+  use->next = cu->language_specific.fortran.use;
+  cu->language_specific.fortran.use = use;
+}
+
+/* Import a single Fortran declaration and possibly rename it.  */
+
+static void
+read_fortran_imported_declaration (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct attribute *attr;
+  struct die_info *imported_die;
+  struct symbol *sym;
+  char *rename = dwarf2_name (die, cu);
+
+  attr = dwarf2_attr (die, DW_AT_import, cu);
+  if (attr == NULL)
+    {
+      complaint (&symfile_complaints,
+		 _("Fortran DW_TAG_imported_declaration is missing "
+		   "DW_AT_import at offset 0x%x"), die->offset);
+      return;
+    }
+  imported_die = follow_die_ref (die, attr, &cu);
+
+  sym = new_symbol (imported_die, NULL, cu);
+
+  if (sym && rename)
+    SYMBOL_CPLUS_DEMANGLED_NAME (sym) = rename;
 }
 
 /* Return the name of the namespace represented by DIE.  Set
@@ -5818,29 +6337,115 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct type *type, *range_type, *index_type, *char_type;
   struct attribute *attr;
-  unsigned int length;
+  int length;
+
+  index_type = objfile_type (objfile)->builtin_int;
+  /* RANGE_TYPE is allocated from OBJFILE, not as a permanent type.  */
+  range_type = alloc_type (objfile);
+  /* LOW_BOUND and HIGH_BOUND are set for real below.  */
+  range_type = create_range_type (range_type, index_type, 0, -1);
+
+  /* C/C++ should probably have the low bound 0 but C/C++ does not use
+     DW_TAG_string_type.  */
+  TYPE_LOW_BOUND (range_type) = 1;
 
   attr = dwarf2_attr (die, DW_AT_string_length, cu);
-  if (attr)
-    {
-      length = DW_UNSND (attr);
+  if (attr && attr_form_is_block (attr))
+    {
+      /* Security check for a size overflow.  */
+      if (DW_BLOCK (attr)->size + 2 < DW_BLOCK (attr)->size)
+	TYPE_HIGH_BOUND (range_type) = 1;
+      /* Extend the DWARF block by a new DW_OP_deref/DW_OP_deref_size
+	 instruction as DW_AT_string_length specifies the length location, not
+	 its value.  */
+      else
+	{
+	  struct dwarf2_locexpr_baton *length_baton = NULL;
+	  struct dwarf_block *blk = DW_BLOCK (attr);
+
+	  /* Turn any single DW_OP_reg* into DW_OP_breg*(0) but clearing
+	     DW_OP_deref* in such case.  */
+
+	  if (blk->size == 1 && blk->data[0] >= DW_OP_reg0
+	      && blk->data[0] <= DW_OP_reg31)
+	    length_baton = dwarf2_attr_to_locexpr_baton (attr, cu);
+	  else if (blk->size > 1 && blk->data[0] == DW_OP_regx)
+	    {
+	      ULONGEST ulongest;
+	      gdb_byte *end;
+
+	      end = read_uleb128 (&blk->data[1], &blk->data[blk->size],
+				  &ulongest);
+	      if (end == &blk->data[blk->size])
+		length_baton = dwarf2_attr_to_locexpr_baton (attr, cu);
+	    }
+
+	  if (length_baton == NULL)
+	    {
+	      struct attribute *size_attr;
+
+	      length_baton = obstack_alloc (&cu->comp_unit_obstack,
+					    sizeof (*length_baton));
+	      length_baton->per_cu = cu->per_cu;
+	      length_baton->size = DW_BLOCK (attr)->size + 2;
+	      length_baton->data = obstack_alloc (&cu->comp_unit_obstack,
+						  length_baton->size);
+	      memcpy (length_baton->data, DW_BLOCK (attr)->data,
+		      DW_BLOCK (attr)->size);
+
+	      /* DW_AT_BYTE_SIZE existing together with DW_AT_STRING_LENGTH
+		 specifies the size of an integer to fetch.  */
+	      size_attr = dwarf2_attr (die, DW_AT_byte_size, cu);
+	      if (size_attr)
+		{
+		  length_baton->data[DW_BLOCK (attr)->size] = DW_OP_deref_size;
+		  length_baton->data[DW_BLOCK (attr)->size + 1] =
+							   DW_UNSND (size_attr);
+		  if (length_baton->data[DW_BLOCK (attr)->size + 1]
+		      != DW_UNSND (size_attr))
+		    complaint (&symfile_complaints,
+			       _("DW_AT_string_length's DW_AT_byte_size "
+				 "integer exceeds the byte size storage"));
+		}
+	      else
+		{
+		  length_baton->data[DW_BLOCK (attr)->size] = DW_OP_deref;
+		  length_baton->data[DW_BLOCK (attr)->size + 1] = DW_OP_nop;
+		}
+	    }
+
+	  TYPE_RANGE_DATA (range_type)->high.kind
+	    = RANGE_BOUND_KIND_DWARF_BLOCK;
+	  TYPE_RANGE_DATA (range_type)->high.u.dwarf_block = length_baton;
+	  TYPE_DYNAMIC (range_type) = 1;
+	}
     }
   else
     {
-      /* check for the DW_AT_byte_size attribute */
+      if (attr && attr_form_is_constant (attr))
+	{
+	  /* We currently do not support a constant address where the location
+	     should be read from - attr_form_is_block is expected instead.  See
+	     DWARF for the DW_AT_STRING_LENGTH vs. DW_AT_BYTE_SIZE difference.
+	     */
+	  /* PASSTHRU */
+	}
+
       attr = dwarf2_attr (die, DW_AT_byte_size, cu);
-      if (attr)
-        {
-          length = DW_UNSND (attr);
-        }
+      if (attr && attr_form_is_block (attr))
+	{
+	  TYPE_RANGE_DATA (range_type)->high.kind
+	    = RANGE_BOUND_KIND_DWARF_BLOCK;
+	  TYPE_RANGE_DATA (range_type)->high.u.dwarf_block =
+					dwarf2_attr_to_locexpr_baton (attr, cu);
+	  TYPE_DYNAMIC (range_type) = 1;
+	}
+      else if (attr && attr_form_is_constant (attr))
+	TYPE_HIGH_BOUND (range_type) = dwarf2_get_attr_constant_value (attr, 0);
       else
-        {
-          length = 1;
-        }
+	TYPE_HIGH_BOUND (range_type) = 1;
     }
 
-  index_type = objfile_type (objfile)->builtin_int;
-  range_type = create_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);
 
@@ -5940,11 +6545,10 @@ static struct type *
 read_typedef (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct objfile *objfile = cu->objfile;
-  struct attribute *attr;
   const char *name = NULL;
   struct type *this_type;
 
-  name = dwarf2_full_name (die, cu);
+  name = dwarf2_full_name (NULL, die, cu);
   this_type = init_type (TYPE_CODE_TYPEDEF, 0,
 			 TYPE_FLAG_TARGET_STUB, NULL, objfile);
   TYPE_NAME (this_type) = (char *) name;
@@ -6048,8 +6652,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
   struct type *base_type;
   struct type *range_type;
   struct attribute *attr;
-  LONGEST low = 0;
-  LONGEST high = -1;
+  LONGEST low;
   char *name;
   LONGEST negative_mask;
   
@@ -6063,49 +6666,157 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
 		     0, NULL, cu->objfile);
     }
 
-  if (cu->language == language_fortran)
-    { 
-      /* FORTRAN implies a lower bound of 1, if not given.  */
-      low = 1;
-    }
+  /* LOW_BOUND and HIGH_BOUND are set for real below.  */
+  range_type = create_range_type (NULL, base_type, 0, -1);
+
+  negative_mask = 
+    (LONGEST) -1 << (TYPE_LENGTH (base_type) * TARGET_CHAR_BIT - 1);
 
-  /* FIXME: For variable sized arrays either of these could be
-     a variable rather than a constant value.  We'll allow it,
-     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, 0);
+  if (attr && attr_form_is_block (attr))
+    {
+      TYPE_RANGE_DATA (range_type)->low.kind = RANGE_BOUND_KIND_DWARF_BLOCK;
+      TYPE_RANGE_DATA (range_type)->low.u.dwarf_block =
+					dwarf2_attr_to_locexpr_baton (attr, cu);
+      TYPE_DYNAMIC (range_type) = 1;
+      /* For setting a default if DW_AT_UPPER_BOUND would be missing.  */
+      low = 0;
+    }
+  else if (attr && is_ref_attr (attr))
+    {
+      struct die_info *target_die;
+      struct dwarf2_cu *target_cu = cu;
+      struct attribute *target_loc_attr;
+
+      target_die = follow_die_ref_or_sig (die, attr, &target_cu);
+      gdb_assert (target_cu->objfile == cu->objfile);
+      target_loc_attr = dwarf2_attr (target_die, DW_AT_location, target_cu);
+
+      TYPE_RANGE_DATA (range_type)->low.kind = RANGE_BOUND_KIND_DWARF_LOCLIST;
+      TYPE_RANGE_DATA (range_type)->low.u.dwarf_loclist.loclist
+        = dwarf2_attr_to_loclist_baton (target_loc_attr, target_cu);
+      TYPE_RANGE_DATA (range_type)->low.u.dwarf_loclist.type
+        = die_type (target_die, target_cu);
+      TYPE_DYNAMIC (range_type) = 1;
+      /* For setting a default if DW_AT_UPPER_BOUND would be missing.  */
+      low = 0;
+    }
+  else
+    {
+      if (attr && attr_form_is_constant (attr))
+	low = dwarf2_get_attr_constant_value (attr, 0);
+      else
+	{
+	  if (cu->language == language_fortran)
+	    {
+	      /* FORTRAN implies a lower bound of 1, if not given.  */
+	      low = 1;
+	    }
+	  else
+	    {
+	      /* According to DWARF we should assume the value 0 only for
+		 LANGUAGE_C and LANGUAGE_CPLUS.  */
+	      low = 0;
+	    }
+	}
+      if (!TYPE_UNSIGNED (base_type) && (low & negative_mask))
+	low |= negative_mask;
+      TYPE_LOW_BOUND (range_type) = low;
+      if (low >= 0)
+	TYPE_UNSIGNED (range_type) = 1;
+    }
 
   attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
-  if (attr)
-    {       
-      if (attr->form == DW_FORM_block1)
-        {
-          /* GCC encodes arrays with unspecified or dynamic length
-             with a DW_FORM_block1 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 = low - 1;
-        }
+  if (!attr || (!attr_form_is_block (attr) && !attr_form_is_constant (attr)
+		&& !is_ref_attr (attr)))
+    {
+      attr = dwarf2_attr (die, DW_AT_count, cu);
+      /* It does not hurt but it is needlessly ineffective in check_typedef.  */
+      if (attr && (attr_form_is_block (attr) || attr_form_is_constant (attr)))
+      	{
+	  TYPE_RANGE_HIGH_BOUND_IS_COUNT (range_type) = 1;
+	  TYPE_DYNAMIC (range_type) = 1;
+	}
+      /* Pass it now as the regular DW_AT_upper_bound.  */
+    }
+
+  if (attr && attr_form_is_block (attr))
+    {
+      TYPE_RANGE_DATA (range_type)->high.kind = RANGE_BOUND_KIND_DWARF_BLOCK;
+      TYPE_RANGE_DATA (range_type)->high.u.dwarf_block =
+					dwarf2_attr_to_locexpr_baton (attr, cu);
+      TYPE_DYNAMIC (range_type) = 1;
+    }
+  else if (attr && is_ref_attr (attr))
+    {
+      struct die_info *target_die;
+      struct dwarf2_cu *target_cu = cu;
+      struct attribute *target_loc_attr;
+
+      target_die = follow_die_ref_or_sig (die, attr, &target_cu);
+      gdb_assert (target_cu->objfile == cu->objfile);
+      target_loc_attr = dwarf2_attr (target_die, DW_AT_location, target_cu);
+
+      TYPE_RANGE_DATA (range_type)->high.kind = RANGE_BOUND_KIND_DWARF_LOCLIST;
+      TYPE_RANGE_DATA (range_type)->high.u.dwarf_loclist.loclist
+        = dwarf2_attr_to_loclist_baton (target_loc_attr, target_cu);
+      TYPE_RANGE_DATA (range_type)->high.u.dwarf_loclist.type
+        = die_type (target_die, target_cu);
+      TYPE_DYNAMIC (range_type) = 1;
+    }
+  else
+    {
+      if (attr && attr_form_is_constant (attr))
+	{
+	  LONGEST high;
+
+	  high = dwarf2_get_attr_constant_value (attr, 0);
+	  if (!TYPE_UNSIGNED (base_type) && (high & negative_mask))
+	    high |= negative_mask;
+	  TYPE_HIGH_BOUND (range_type) = high;
+	}
       else
-        high = dwarf2_get_attr_constant_value (attr, 1);
+	{
+	  TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1;
+	  TYPE_HIGH_BOUND (range_type) = low - 1;
+	}
     }
 
-  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;
+  /* DW_AT_bit_stride is currently unsupported as we count in bytes.  */
+  attr = dwarf2_attr (die, DW_AT_byte_stride, cu);
+  if (attr && attr_form_is_block (attr))
+    {
+      TYPE_RANGE_DATA (range_type)->byte_stride.kind
+        = RANGE_BOUND_KIND_DWARF_BLOCK;
+      TYPE_RANGE_DATA (range_type)->byte_stride.u.dwarf_block =
+					dwarf2_attr_to_locexpr_baton (attr, cu);
+      TYPE_DYNAMIC (range_type) = 1;
+    }
+  else if (attr && is_ref_attr (attr))
+    {
+      struct die_info *target_die;
+      struct dwarf2_cu *target_cu = cu;
+      struct attribute *target_loc_attr;
 
-  range_type = create_range_type (NULL, base_type, low, high);
+      target_die = follow_die_ref_or_sig (die, attr, &target_cu);
+      gdb_assert (target_cu->objfile == cu->objfile);
+      target_loc_attr = dwarf2_attr (target_die, DW_AT_location, target_cu);
+
+      TYPE_RANGE_DATA (range_type)->byte_stride.kind
+        = RANGE_BOUND_KIND_DWARF_LOCLIST;
+      TYPE_RANGE_DATA (range_type)->byte_stride.u.dwarf_loclist.loclist
+        = dwarf2_attr_to_loclist_baton (target_loc_attr, target_cu);
+      TYPE_RANGE_DATA (range_type)->byte_stride.u.dwarf_loclist.type
+        = die_type (target_die, target_cu);
+      TYPE_DYNAMIC (range_type) = 1;
+    }
+  else if (attr && attr_form_is_constant (attr))
+    {
+      TYPE_BYTE_STRIDE (range_type) = dwarf2_get_attr_constant_value (attr, 0);
+      if (TYPE_BYTE_STRIDE (range_type) == 0)
+	complaint (&symfile_complaints,
+		   _("Found DW_AT_byte_stride with unsupported value 0"));
+    }
 
   name = dwarf2_name (die, cu);
   if (name)
@@ -6564,6 +7275,7 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
 	  && abbrev->tag != DW_TAG_lexical_block
 	  && abbrev->tag != DW_TAG_variable
 	  && abbrev->tag != DW_TAG_namespace
+	  && abbrev->tag != DW_TAG_module
 	  && abbrev->tag != DW_TAG_member)
 	{
 	  /* Otherwise we skip to the next sibling, if any.  */
@@ -6772,7 +7484,8 @@ read_partial_die (struct partial_die_info *part_die,
 	    }
 	  break;
 	case DW_AT_MIPS_linkage_name:
-	  part_die->name = DW_STRING (&attr);
+	  if (cu->language == language_ada)
+	    part_die->name = DW_STRING (&attr);
 	  break;
 	case DW_AT_low_pc:
 	  has_low_pc_attr = 1;
@@ -6970,7 +7683,8 @@ fixup_partial_die (struct partial_die_info *part_die,
   /* If we found a reference attribute and the DIE has no name, try
      to find a name in the referred to DIE.  */
 
-  if (part_die->name == NULL && part_die->has_specification)
+  if (part_die->has_specification
+      && (part_die->name == NULL || !part_die->is_external))
     {
       struct partial_die_info *spec_die;
 
@@ -8312,10 +9026,12 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
      (i.e. when the value of a register or memory location is
      referenced, or a thread-local block, etc.).  Then again, it might
      not be worthwhile.  I'm assuming that it isn't unless performance
-     or memory numbers show me otherwise.  */
+     or memory numbers show me otherwise.
+     
+     SYMBOL_CLASS may get overriden by dwarf2_symbol_mark_computed.  */
 
-  dwarf2_symbol_mark_computed (attr, sym, cu);
   SYMBOL_CLASS (sym) = LOC_COMPUTED;
+  dwarf2_symbol_mark_computed (attr, sym, cu);
 }
 
 /* Given a pointer to a DWARF information entry, figure out if we need
@@ -8337,21 +9053,27 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 
   baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
-  if (die->tag != DW_TAG_namespace)
-    name = dwarf2_linkage_name (die, cu);
-  else
-    name = TYPE_NAME (type);
-
+  name = dwarf2_name (die, cu);
   if (name)
     {
+      const char *linkagename;
+
       sym = (struct symbol *) obstack_alloc (&objfile->objfile_obstack,
 					     sizeof (struct symbol));
       OBJSTAT (objfile, n_syms++);
       memset (sym, 0, sizeof (struct symbol));
+      /* Some methods are called w/o checking SYMBOL_COMPUTED_OPS validity.  */
+      SYMBOL_COMPUTED_OPS (sym) = &dwarf2_missing_funcs;
 
       /* Cache this symbol's name and the name's demangled form (if any).  */
       SYMBOL_LANGUAGE (sym) = cu->language;
-      SYMBOL_SET_NAMES (sym, name, strlen (name), 0, objfile);
+      linkagename = dwarf2_physname (name, die, cu);
+      SYMBOL_SET_NAMES (sym, linkagename, strlen (linkagename), 0, objfile);
+      if (cu->language == language_fortran)
+	{
+	  SYMBOL_CPLUS_DEMANGLED_NAME (sym) = SYMBOL_LINKAGE_NAME (sym);
+	  SYMBOL_LINKAGE_NAME (sym) = fortran_module_linkage_name (die, cu);
+	}
 
       /* Default assumptions.
          Use the passed type or decode it from the die.  */
@@ -8451,7 +9173,24 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 	      var_decode_location (attr, sym, cu);
 	      attr2 = dwarf2_attr (die, DW_AT_external, cu);
 	      if (attr2 && (DW_UNSND (attr2) != 0))
-		add_symbol_to_list (sym, &global_symbols);
+		{
+		  struct pending **list_to_add;
+
+		  /* Workaround gfortran PR debug/40040 - it uses
+		     DW_AT_location for variables in -fPIC libraries which may
+		     get overriden by other libraries/executable and get
+		     a different address.  Resolve it by .dynsym instead.  */
+
+		  if (cu->language == language_fortran && die->parent
+		      && die->parent->tag == DW_TAG_module)
+		    SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
+
+		  /* A variable with DW_AT_external is never static, but it
+		     may be block-scoped.  */
+		  list_to_add = (cu->list_in_scope == &file_symbols
+				 ? &global_symbols : cu->list_in_scope);
+		  add_symbol_to_list (sym, list_to_add);
+		}
 	      else
 		add_symbol_to_list (sym, cu->list_in_scope);
 	    }
@@ -8576,7 +9315,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 	  }
 	  break;
 	case DW_TAG_typedef:
-	  SYMBOL_LINKAGE_NAME (sym) = (char *) dwarf2_full_name (die, cu);
+	  SYMBOL_LINKAGE_NAME (sym)
+	    = (char *) dwarf2_full_name (name, die, cu);
 	  SYMBOL_CLASS (sym) = LOC_TYPEDEF;
 	  SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
 	  add_symbol_to_list (sym, cu->list_in_scope);
@@ -8588,7 +9328,8 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 	  add_symbol_to_list (sym, cu->list_in_scope);
 	  break;
 	case DW_TAG_enumerator:
-	  SYMBOL_LINKAGE_NAME (sym) = (char *) dwarf2_full_name (die, cu);
+	  SYMBOL_LINKAGE_NAME (sym)
+	    = (char *) dwarf2_full_name (name, die, cu);
 	  attr = dwarf2_attr (die, DW_AT_const_value, cu);
 	  if (attr)
 	    {
@@ -8612,6 +9353,11 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 	  SYMBOL_CLASS (sym) = LOC_TYPEDEF;
 	  add_symbol_to_list (sym, &global_symbols);
 	  break;
+	case DW_TAG_module:
+	  SYMBOL_CLASS (sym) = LOC_STATIC;
+	  SYMBOL_DOMAIN (sym) = MODULE_DOMAIN;
+	  add_symbol_to_list (sym, &global_symbols);
+	  break;
 	default:
 	  /* Not a tag we recognize.  Hopefully we aren't processing
 	     trash data, but since we must specifically ignore things
@@ -8625,8 +9371,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
       /* For the benefit of old versions of GCC, check for anonymous
 	 namespaces based on the demangled name.  */
       if (!processing_has_namespace_info
-	  && cu->language == language_cplus
-	  && dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu) != NULL)
+	  && cu->language == language_cplus)
 	cp_scan_for_anonymous_namespaces (sym);
     }
   return (sym);
@@ -8938,12 +9683,18 @@ read_type_die (struct die_info *die, struct dwarf2_cu *cu)
     case DW_TAG_namespace:
       this_type = read_namespace_type (die, cu);
       break;
+    case DW_TAG_module:
+      this_type = read_module_type (die, cu);
+      break;
     default:
       complaint (&symfile_complaints, _("unexpected tag in read_type_die: '%s'"),
 		 dwarf_tag_name (die->tag));
       break;
     }
 
+  if (this_type)
+    finalize_type (this_type);
+
   return this_type;
 }
 
@@ -9011,6 +9762,10 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
       case DW_TAG_namespace:
 	parent_type = read_type_die (parent, cu);
 	/* We give a name to even anonymous namespaces.  */
+
+	/* G++ 4.1 produced DW_TAG_namespace with DW_AT_name "::".  */
+	if (strcmp (TYPE_TAG_NAME (parent_type), "::") == 0)
+	  return "";
 	return TYPE_TAG_NAME (parent_type);
       case DW_TAG_class_type:
       case DW_TAG_interface_type:
@@ -9025,7 +9780,7 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
 	     So it does not need a prefix.  */
 	  return "";
       default:
-	return determine_prefix (parent, cu);
+        return determine_prefix (parent, cu);
       }
 }
 
@@ -9078,17 +9833,37 @@ sibling_die (struct die_info *die)
   return die->sibling;
 }
 
-/* Get linkage name of a die, return NULL if not found.  */
+/* Return the fully qualified .symtab name for symbols contained in Fortran
+   modules.  Return DWARF2_NAME otherwise.  */
 
 static char *
-dwarf2_linkage_name (struct die_info *die, struct dwarf2_cu *cu)
+fortran_module_linkage_name (struct die_info *die, struct dwarf2_cu *cu)
 {
-  struct attribute *attr;
+  char *name;
+
+  gdb_assert (cu->language == language_fortran);
+
+  name = dwarf2_name (die, cu);
+
+  if (name && die->parent && die->parent->tag == DW_TAG_module)
+    {
+      char *module_name = dwarf2_name (die->parent, cu);
+
+      if (module_name)
+	{
+	  char *retval;
 
-  attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu);
-  if (attr && DW_STRING (attr))
-    return DW_STRING (attr);
-  return dwarf2_name (die, cu);
+	  /* `__modulename_MOD_variablename0'.  */
+	  retval = obstack_alloc (&cu->objfile->objfile_obstack,
+				  2 + strlen (module_name) + 5 + strlen (name)
+				  + 1);
+	  sprintf (retval, "__%s_MOD_%s", module_name, name);
+
+	  return retval;
+	}
+    }
+
+  return name;
 }
 
 /* Get name of a die, return NULL if not found.  */
@@ -11436,64 +12211,94 @@ attr_form_is_constant (struct attribute *attr)
     }
 }
 
+/* Convert DW_BLOCK into struct dwarf2_locexpr_baton.  ATTR must be a DW_BLOCK
+   attribute type.  */
+
+static struct dwarf2_locexpr_baton *
+dwarf2_attr_to_locexpr_baton (struct attribute *attr, struct dwarf2_cu *cu)
+{
+  struct dwarf2_locexpr_baton *baton;
+
+  gdb_assert (attr_form_is_block (attr));
+
+  baton = obstack_alloc (&cu->objfile->objfile_obstack, sizeof (*baton));
+  baton->per_cu = cu->per_cu;
+  gdb_assert (baton->per_cu);
+
+  /* Note that we're just copying the block's data pointer
+     here, not the actual data.  We're still pointing into the
+     info_buffer for SYM's objfile; right now we never release
+     that buffer, but when we do clean up properly this may
+     need to change.  */
+  baton->size = DW_BLOCK (attr)->size;
+  baton->data = DW_BLOCK (attr)->data;
+  gdb_assert (baton->size == 0 || baton->data != NULL);
+
+  return baton;
+}
+
+static struct dwarf2_loclist_baton *
+dwarf2_attr_to_loclist_baton (struct attribute *attr, struct dwarf2_cu *cu)
+{
+  struct dwarf2_loclist_baton *baton;
+
+  if (!(attr_form_is_section_offset (attr)
+	/* ".debug_loc" may not exist at all, or the offset may be outside
+	   the section.  If so, fall through to the complaint in the
+	   other branch.  */
+	&& DW_UNSND (attr) < dwarf2_per_objfile->loc.size))
+    return NULL;
+
+  baton = obstack_alloc (&cu->objfile->objfile_obstack,
+			 sizeof (struct dwarf2_loclist_baton));
+  baton->per_cu = cu->per_cu;
+  gdb_assert (baton->per_cu);
+
+  /* We don't know how long the location list is, but make sure we
+     don't run off the edge of the section.  */
+  baton->size = dwarf2_per_objfile->loc.size - DW_UNSND (attr);
+  baton->data = dwarf2_per_objfile->loc.buffer + DW_UNSND (attr);
+  baton->base_address = cu->base_address;
+  if (cu->base_known == 0)
+    complaint (&symfile_complaints,
+	       _("Location list used without specifying the CU base address."));
+
+  return baton;
+}
+
+/* SYM may get its SYMBOL_CLASS overriden on invalid ATTR content.  */
+
 static void
 dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
 			     struct dwarf2_cu *cu)
 {
-  if (attr_form_is_section_offset (attr)
-      /* ".debug_loc" may not exist at all, or the offset may be outside
-	 the section.  If so, fall through to the complaint in the
-	 other branch.  */
-      && DW_UNSND (attr) < dwarf2_per_objfile->loc.size)
-    {
-      struct dwarf2_loclist_baton *baton;
-
-      baton = obstack_alloc (&cu->objfile->objfile_obstack,
-			     sizeof (struct dwarf2_loclist_baton));
-      baton->per_cu = cu->per_cu;
-      gdb_assert (baton->per_cu);
-
-      /* We don't know how long the location list is, but make sure we
-	 don't run off the edge of the section.  */
-      baton->size = dwarf2_per_objfile->loc.size - DW_UNSND (attr);
-      baton->data = dwarf2_per_objfile->loc.buffer + DW_UNSND (attr);
-      baton->base_address = cu->base_address;
-      if (cu->base_known == 0)
-	complaint (&symfile_complaints,
-		   _("Location list used without specifying the CU base address."));
+  struct dwarf2_loclist_baton *loclist_baton;
 
+  loclist_baton = dwarf2_attr_to_loclist_baton (attr, cu);
+  if (loclist_baton)
+    {
       SYMBOL_COMPUTED_OPS (sym) = &dwarf2_loclist_funcs;
-      SYMBOL_LOCATION_BATON (sym) = baton;
+      SYMBOL_LOCATION_BATON (sym) = loclist_baton;
+    }
+  else if (attr_form_is_block (attr))
+    {
+      SYMBOL_COMPUTED_OPS (sym) = &dwarf2_locexpr_funcs;
+      SYMBOL_LOCATION_BATON (sym) = dwarf2_attr_to_locexpr_baton (attr, cu);
     }
   else
     {
-      struct dwarf2_locexpr_baton *baton;
+      dwarf2_invalid_attrib_class_complaint ("location description",
+					     SYMBOL_NATURAL_NAME (sym));
 
-      baton = obstack_alloc (&cu->objfile->objfile_obstack,
-			     sizeof (struct dwarf2_locexpr_baton));
-      baton->per_cu = cu->per_cu;
-      gdb_assert (baton->per_cu);
+      /* Some methods are called w/o checking SYMBOL_COMPUTED_OPS validity.  */
 
-      if (attr_form_is_block (attr))
-	{
-	  /* Note that we're just copying the block's data pointer
-	     here, not the actual data.  We're still pointing into the
-	     info_buffer for SYM's objfile; right now we never release
-	     that buffer, but when we do clean up properly this may
-	     need to change.  */
-	  baton->size = DW_BLOCK (attr)->size;
-	  baton->data = DW_BLOCK (attr)->data;
-	}
-      else
-	{
-	  dwarf2_invalid_attrib_class_complaint ("location description",
-						 SYMBOL_NATURAL_NAME (sym));
-	  baton->size = 0;
-	  baton->data = NULL;
-	}
-      
-      SYMBOL_COMPUTED_OPS (sym) = &dwarf2_locexpr_funcs;
-      SYMBOL_LOCATION_BATON (sym) = baton;
+      SYMBOL_COMPUTED_OPS (sym) = &dwarf2_missing_funcs;
+      SYMBOL_LOCATION_BATON (sym) = NULL;
+
+      /* For functions a missing DW_AT_frame_base does not optimize out the
+	 whole function definition, only its frame base resolving.  */
+      if (attr->name == DW_AT_location)
+	SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
     }
 }
 
@@ -11781,6 +12586,31 @@ offset_and_type_eq (const void *item_lhs, const void *item_rhs)
   return ofs_lhs->offset == ofs_rhs->offset;
 }
 
+/* Fill in generic attributes applicable for type DIEs.  */
+
+static void
+fetch_die_type_attrs (struct die_info *die, struct type *type,
+		      struct dwarf2_cu *cu)
+{
+  struct attribute *attr;
+
+  attr = dwarf2_attr (die, DW_AT_data_location, cu);
+  if (attr_form_is_block (attr))
+    TYPE_DATA_LOCATION_DWARF_BLOCK (type) = dwarf2_attr_to_locexpr_baton (attr,
+									  cu);
+  gdb_assert (!TYPE_DATA_LOCATION_IS_ADDR (type));
+
+  attr = dwarf2_attr (die, DW_AT_allocated, cu);
+  if (attr_form_is_block (attr))
+    TYPE_ALLOCATED (type) = dwarf2_attr_to_locexpr_baton (attr, cu);
+  gdb_assert (!TYPE_NOT_ALLOCATED (type));
+
+  attr = dwarf2_attr (die, DW_AT_associated, cu);
+  if (attr_form_is_block (attr))
+    TYPE_ASSOCIATED (type) = dwarf2_attr_to_locexpr_baton (attr, cu);
+  gdb_assert (!TYPE_NOT_ASSOCIATED (type));
+}
+
 /* Set the type associated with DIE to TYPE.  Save it in CU's hash
    table if necessary.  For convenience, return TYPE.  */
 
@@ -11789,6 +12619,8 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 {
   struct dwarf2_offset_and_type **slot, ofs;
 
+  fetch_die_type_attrs (die, type, cu);
+
   /* For Ada types, make sure that the gnat-specific data is always
      initialized (if not already set).  There are a few types where
      we should not be doing so, because the type-specific area is
@@ -11944,23 +12776,13 @@ show_dwarf2_cmd (char *args, int from_tty)
   cmd_show_list (show_dwarf2_cmdlist, from_tty, "");
 }
 
-/* If section described by INFO was mmapped, munmap it now.  */
+/* A helper function to destroy a debug section.  */
 
 static void
-munmap_section_buffer (struct dwarf2_section_info *info)
+destroy_section (struct dwarf2_section_info *info)
 {
-  if (info->was_mmapped)
-    {
-#ifdef HAVE_MMAP
-      intptr_t begin = (intptr_t) info->buffer;
-      intptr_t map_begin = begin & ~(pagesize - 1);
-      size_t map_length = info->size + begin - map_begin;
-      gdb_assert (munmap ((void *) map_begin, map_length) == 0);
-#else
-      /* Without HAVE_MMAP, we should never be here to begin with.  */
-      gdb_assert (0);
-#endif
-    }
+  if (info->destructor)
+    (*info->destructor) (info);
 }
 
 /* munmap debug sections for OBJFILE, if necessary.  */
@@ -11969,15 +12791,15 @@ static void
 dwarf2_per_objfile_free (struct objfile *objfile, void *d)
 {
   struct dwarf2_per_objfile *data = d;
-  munmap_section_buffer (&data->info);
-  munmap_section_buffer (&data->abbrev);
-  munmap_section_buffer (&data->line);
-  munmap_section_buffer (&data->str);
-  munmap_section_buffer (&data->macinfo);
-  munmap_section_buffer (&data->ranges);
-  munmap_section_buffer (&data->loc);
-  munmap_section_buffer (&data->frame);
-  munmap_section_buffer (&data->eh_frame);
+  destroy_section (&data->info);
+  destroy_section (&data->abbrev);
+  destroy_section (&data->line);
+  destroy_section (&data->str);
+  destroy_section (&data->macinfo);
+  destroy_section (&data->ranges);
+  destroy_section (&data->loc);
+  destroy_section (&data->frame);
+  destroy_section (&data->eh_frame);
 }
 
 void _initialize_dwarf2_read (void);
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 9a2a1e3..72b1d13 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -179,7 +179,8 @@ record_minimal_symbol (const char *name, int name_len, int copy_name,
 {
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
 
-  if (ms_type == mst_text || ms_type == mst_file_text)
+  if (ms_type == mst_text || ms_type == mst_file_text
+      || ms_type == mst_text_gnu_ifunc)
     address = gdbarch_smash_text_address (gdbarch, address);
 
   return prim_record_minimal_symbol_full (name, name_len, copy_name, address,
@@ -388,7 +389,10 @@ elf_symtab_read (struct objfile *objfile, int type,
 	    {
 	      if (sym->flags & (BSF_GLOBAL | BSF_WEAK))
 		{
-		  ms_type = mst_text;
+		  if (sym->flags & BSF_GNU_INDIRECT_FUNCTION)
+		    ms_type = mst_text_gnu_ifunc;
+		  else
+		    ms_type = mst_text;
 		}
 	      else if ((sym->name[0] == '.' && sym->name[1] == 'L')
 		       || ((sym->flags & BSF_LOCAL)
@@ -879,20 +883,13 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags)
 				str_sect->filepos,
 				bfd_section_size (abfd, str_sect));
     }
-  if (dwarf2_has_info (objfile))
-    {
-      /* DWARF 2 sections */
-      dwarf2_build_psymtabs (objfile);
-    }
-
-  /* FIXME: kettenis/20030504: This still needs to be integrated with
-     dwarf2read.c in a better way.  */
-  dwarf2_build_frame_info (objfile);
 
+  if (dwarf2_has_info (objfile))
+    dwarf2_create_quick_addrmap (objfile);
   /* If the file has its own symbol tables it has no separate debug info.
      `.dynsym'/`.symtab' go to MSYMBOLS, `.debug_info' goes to SYMTABS/PSYMTABS.
      `.gnu_debuglink' may no longer be present with `.note.gnu.build-id'.  */
-  if (!objfile_has_partial_symbols (objfile))
+  else
     {
       char *debugfile;
 
@@ -910,6 +907,20 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags)
     }
 }
 
+static void
+read_psyms (struct objfile *objfile)
+{
+  if (dwarf2_has_info (objfile))
+    {
+      /* DWARF 2 sections */
+      dwarf2_build_psymtabs (objfile);
+    }
+
+  /* FIXME: kettenis/20030504: This still needs to be integrated with
+     dwarf2read.c in a better way.  */
+  dwarf2_build_frame_info (objfile);
+}
+
 /* This cleans up the objfile's deprecated_sym_stab_info pointer, and
    the chain of stab_section_info's, that might be dangling from
    it.  */
@@ -1052,6 +1063,7 @@ static struct sym_fns elf_sym_fns =
   elf_new_init,			/* sym_new_init: init anything gbl to entire symtab */
   elf_symfile_init,		/* sym_init: read initial info, setup for sym_read() */
   elf_symfile_read,		/* sym_read: read a symbol file into symtab */
+  read_psyms,			/* sym_read_psymbols */
   elf_symfile_finish,		/* sym_finish: finished with file, cleanup */
   default_symfile_offsets,	/* sym_offsets:  Translate ext. to int. relocation */
   elf_symfile_segments,		/* sym_segments: Get segment information from
diff --git a/gdb/eval.c b/gdb/eval.c
index e2ceea7..1bcb4a7 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -43,6 +43,7 @@
 #include "gdb_obstack.h"
 #include "objfiles.h"
 #include "python/python.h"
+#include "dwarf2loc.h"
 
 #include "gdb_assert.h"
 
@@ -696,6 +697,7 @@ evaluate_subexp_standard (struct type *expect_type,
   long mem_offset;
   struct type **arg_types;
   int save_pos1;
+  struct cleanup *old_chain;
   struct symbol *function = NULL;
   char *function_name = NULL;
 
@@ -731,6 +733,7 @@ evaluate_subexp_standard (struct type *expect_type,
       return value_from_decfloat (exp->elts[pc + 1].type,
 				  exp->elts[pc + 2].decfloatconst);
 
+    case OP_ADL_FUNC:
     case OP_VAR_VALUE:
       (*pos) += 3;
       if (noside == EVAL_SKIP)
@@ -1334,7 +1337,6 @@ evaluate_subexp_standard (struct type *expect_type,
       argvec = (struct value **) alloca (sizeof (struct value *) * (nargs + 3));
       if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
 	{
-	  nargs++;
 	  /* First, evaluate the structure into arg2 */
 	  pc2 = (*pos)++;
 
@@ -1358,21 +1360,40 @@ evaluate_subexp_standard (struct type *expect_type,
 
 	  arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
 
-	  if (TYPE_CODE (check_typedef (value_type (arg1)))
-	      != TYPE_CODE_METHODPTR)
-	    error (_("Non-pointer-to-member value used in pointer-to-member "
-		     "construct"));
-
-	  if (noside == EVAL_AVOID_SIDE_EFFECTS)
+	  type = check_typedef (value_type (arg1));
+	  switch (TYPE_CODE (type))
 	    {
-	      struct type *method_type = check_typedef (value_type (arg1));
-	      arg1 = value_zero (method_type, not_lval);
+	    case TYPE_CODE_METHODPTR:
+	      if (noside == EVAL_AVOID_SIDE_EFFECTS)
+		arg1 = value_zero (TYPE_TARGET_TYPE (type), not_lval);
+	      else
+		arg1 = cplus_method_ptr_to_value (&arg2, arg1);
+
+	      /* Now, say which argument to start evaluating from */
+	      nargs++;
+	      tem = 2;
+	      argvec[1] = arg2;
+	      break;
+
+	    case TYPE_CODE_MEMBERPTR:
+	      /* Now, convert these values to an address.  */
+	      arg2 = value_cast (lookup_pointer_type (TYPE_DOMAIN_TYPE (type)),
+				 arg2);
+
+	      mem_offset = value_as_long (arg1);
+
+	      arg1 = value_from_pointer (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
+					 value_as_long (arg2) + mem_offset);
+	      arg1 = value_ind (arg1);
+	      tem = 1;
+	      break;
+
+	    default:
+	      error (_("Non-pointer-to-member value used in pointer-to-member "
+		       "construct"));
 	    }
-	  else
-	    arg1 = cplus_method_ptr_to_value (&arg2, arg1);
 
-	  /* Now, say which argument to start evaluating from */
-	  tem = 2;
+	  argvec[0] = arg1;
 	}
       else if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR)
 	{
@@ -1412,6 +1433,17 @@ evaluate_subexp_standard (struct type *expect_type,
 	  /* Now, say which argument to start evaluating from */
 	  tem = 2;
 	}
+      else if (op == OP_ADL_FUNC)
+        {
+          /* Save the function position and move pos so that the arguments
+             can be evaluated. */
+          int func_name_len;
+          save_pos1 = *pos;
+          tem = 1;
+
+          func_name_len = longest_to_int (exp->elts[save_pos1 + 3].longconst);
+          (*pos) += 6 + BYTES_TO_EXP_ELEM (func_name_len + 1);
+        }
       else if (op == OP_SCOPE
 	       && overload_resolution
 	       && (exp->language_defn->la_language == language_cplus))
@@ -1433,9 +1465,9 @@ evaluate_subexp_standard (struct type *expect_type,
 	  if (TYPE_CODE (type) == TYPE_CODE_NAMESPACE)
 	    {
 	      function = cp_lookup_symbol_namespace (TYPE_TAG_NAME (type),
-						     name, NULL,
+						     name,
 						     get_selected_block (0),
-						     VAR_DOMAIN, 1);
+						     VAR_DOMAIN);
 	      if (function == NULL)
 		error (_("No symbol \"%s\" in namespace \"%s\"."), 
 		       name, TYPE_TAG_NAME (type));
@@ -1484,6 +1516,33 @@ evaluate_subexp_standard (struct type *expect_type,
       /* signal end of arglist */
       argvec[tem] = 0;
 
+      if (op == OP_ADL_FUNC)
+        {
+          struct symbol *symp;
+          char *func_name;
+          int  name_len;
+          int string_pc = save_pos1 + 3;
+
+          /* Extract the function name.  */
+          name_len = longest_to_int (exp->elts[string_pc].longconst);
+          func_name = (char *) alloca (name_len + 1);
+          strcpy (func_name, &exp->elts[string_pc + 1].string);
+
+          /* Prepare list of argument types for overload resolution */
+          arg_types = (struct type **) alloca (nargs * (sizeof (struct type *)));
+          for (ix = 1; ix <= nargs; ix++)
+            arg_types[ix - 1] = value_type (argvec[ix]);
+
+          find_overload_match (arg_types, nargs, func_name,
+                               0 /* not method */ , 0 /* strict match */ ,
+                               NULL, NULL /* pass NULL symbol since symbol is unknown */ ,
+                               NULL, &symp, NULL);
+
+          /* Now fix the expression being evaluated */
+          exp->elts[save_pos1 + 2].symbol = symp;
+          argvec[0] = evaluate_subexp_with_coercion (exp, &save_pos1, noside);
+        }
+
       if (op == STRUCTOP_STRUCT || op == STRUCTOP_PTR
 	  || (op == OP_SCOPE && function_name != NULL))
 	{
@@ -1552,8 +1611,7 @@ evaluate_subexp_standard (struct type *expect_type,
 	}
       else if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR)
 	{
-	  argvec[1] = arg2;
-	  argvec[0] = arg1;
+	  /* Pointer to member.  argvec is already set up.  */
 	}
       else if (op == OP_VAR_VALUE || (op == OP_SCOPE && function != NULL))
 	{
@@ -1653,6 +1711,8 @@ evaluate_subexp_standard (struct type *expect_type,
 
       /* First determine the type code we are dealing with.  */
       arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
+      old_chain = make_cleanup (null_cleanup, 0);
+      object_address_set (value_raw_address (arg1));
       type = check_typedef (value_type (arg1));
       code = TYPE_CODE (type);
 
@@ -1673,6 +1733,7 @@ evaluate_subexp_standard (struct type *expect_type,
 	      code = TYPE_CODE (type);
 	    }
 	} 
+      do_cleanups (old_chain);
 
       switch (code)
 	{
@@ -1834,6 +1895,26 @@ evaluate_subexp_standard (struct type *expect_type,
       xfree (expect_type);
       return arg1;
 
+    case TYPE_INSTANCE_LOOKUP:
+      {
+	int i;
+	struct symbol *sym;
+	struct type **arg_types;
+	(*pos) += 3;
+	arg_types = (struct type **) alloca (TYPE_NFIELDS (expect_type)
+					     * sizeof (struct type *));
+	for (i = 0; i < TYPE_NFIELDS (expect_type); ++i)
+	  arg_types[i] = TYPE_FIELD_TYPE (expect_type, i);
+	(void) find_overload_match (arg_types, TYPE_NFIELDS (expect_type),
+				    NULL /* no need for name */,
+				    0 /* not method */,
+				    0 /* strict match */,
+				    NULL, exp->elts[pc + 1].symbol, NULL,
+				    &sym, NULL);
+	i = 0;
+      }
+      break;
+
     case BINOP_CONCAT:
       arg1 = evaluate_subexp_with_coercion (exp, pos, noside);
       arg2 = evaluate_subexp_with_coercion (exp, pos, noside);
@@ -2105,13 +2186,19 @@ evaluate_subexp_standard (struct type *expect_type,
       {
 	int subscript_array[MAX_FORTRAN_DIMS];
 	int array_size_array[MAX_FORTRAN_DIMS];
+	int byte_stride_array[MAX_FORTRAN_DIMS];
 	int ndimensions = 1, i;
 	struct type *tmp_type;
 	int offset_item;	/* The array offset where the item lives */
+	CORE_ADDR offset_byte;	/* byte_stride based offset  */
+	unsigned element_size;
 
 	if (nargs > MAX_FORTRAN_DIMS)
 	  error (_("Too many subscripts for F77 (%d Max)"), MAX_FORTRAN_DIMS);
 
+	old_chain = make_cleanup (null_cleanup, 0);
+	object_address_set (value_raw_address (arg1));
+
 	tmp_type = check_typedef (value_type (arg1));
 	ndimensions = calc_f77_array_dims (type);
 
@@ -2141,6 +2228,9 @@ evaluate_subexp_standard (struct type *expect_type,
 	    upper = f77_get_upperbound (tmp_type);
 	    lower = f77_get_lowerbound (tmp_type);
 
+	    byte_stride_array[nargs - i - 1] =
+					TYPE_ARRAY_BYTE_STRIDE_VALUE (tmp_type);
+
 	    array_size_array[nargs - i - 1] = upper - lower + 1;
 
 	    /* Zero-normalize subscripts so that offsetting will work. */
@@ -2159,13 +2249,25 @@ evaluate_subexp_standard (struct type *expect_type,
 	      tmp_type = check_typedef (TYPE_TARGET_TYPE (tmp_type));
 	  }
 
+	/* Kept for the f77_get_upperbound / f77_get_lowerbound calls above.  */
+	do_cleanups (old_chain);
+
 	/* Now let us calculate the offset for this item */
 
-	offset_item = subscript_array[ndimensions - 1];
+	offset_item = 0;
+	offset_byte = 0;
+
+	for (i = ndimensions - 1; i >= 0; --i)
+	  {
+	    offset_item *= array_size_array[i];
+	    if (byte_stride_array[i] == 0)
+	      offset_item += subscript_array[i];
+	    else
+	      offset_byte += subscript_array[i] * byte_stride_array[i];
+	  }
 
-	for (i = ndimensions - 1; i > 0; --i)
-	  offset_item =
-	    array_size_array[i - 1] * offset_item + subscript_array[i - 1];
+	element_size = TYPE_LENGTH (TYPE_TARGET_TYPE (tmp_type));
+	offset_byte += offset_item * element_size;
 
 	/* Let us now play a dirty trick: we will take arg1 
 	   which is a value node pointing to the topmost level
@@ -2175,7 +2277,7 @@ evaluate_subexp_standard (struct type *expect_type,
 	   returns the correct type value */
 
 	deprecated_set_value_type (arg1, tmp_type);
-	return value_subscripted_rvalue (arg1, offset_item, 0);
+	return value_subscripted_rvalue (arg1, offset_byte);
       }
 
     case BINOP_LOGICAL_AND:
@@ -2409,14 +2511,22 @@ evaluate_subexp_standard (struct type *expect_type,
       if (expect_type && TYPE_CODE (expect_type) == TYPE_CODE_PTR)
 	expect_type = TYPE_TARGET_TYPE (check_typedef (expect_type));
       arg1 = evaluate_subexp (expect_type, exp, pos, noside);
+      old_chain = make_cleanup (null_cleanup, 0);
+      object_address_set (value_raw_address (arg1));
       type = check_typedef (value_type (arg1));
       if (TYPE_CODE (type) == TYPE_CODE_METHODPTR
 	  || TYPE_CODE (type) == TYPE_CODE_MEMBERPTR)
 	error (_("Attempt to dereference pointer to member without an object"));
       if (noside == EVAL_SKIP)
-	goto nosideret;
+	{
+	  do_cleanups (old_chain);
+	  goto nosideret;
+	}
       if (unop_user_defined_p (op, arg1))
-	return value_x_unop (arg1, op, noside);
+	{
+	  do_cleanups (old_chain);
+	  return value_x_unop (arg1, op, noside);
+	}
       else if (noside == EVAL_AVOID_SIDE_EFFECTS)
 	{
 	  type = check_typedef (value_type (arg1));
@@ -2425,12 +2535,18 @@ evaluate_subexp_standard (struct type *expect_type,
 	  /* In C you can dereference an array to get the 1st elt.  */
 	      || TYPE_CODE (type) == TYPE_CODE_ARRAY
 	    )
-	    return value_zero (TYPE_TARGET_TYPE (type),
-			       lval_memory);
+	    {
+	      do_cleanups (old_chain);
+	      return value_zero (TYPE_TARGET_TYPE (type),
+				 lval_memory);
+	    }
 	  else if (TYPE_CODE (type) == TYPE_CODE_INT)
-	    /* GDB allows dereferencing an int.  */
-	    return value_zero (builtin_type (exp->gdbarch)->builtin_int,
-			       lval_memory);
+	    {
+	      do_cleanups (old_chain);
+	      /* GDB allows dereferencing an int.  */
+	      return value_zero (builtin_type (exp->gdbarch)->builtin_int,
+				 lval_memory);
+	    }
 	  else
 	    error (_("Attempt to take contents of a non-pointer value."));
 	}
@@ -2440,9 +2556,14 @@ evaluate_subexp_standard (struct type *expect_type,
 	 do.  "long long" variables are rare enough that
 	 BUILTIN_TYPE_LONGEST would seem to be a mistake.  */
       if (TYPE_CODE (type) == TYPE_CODE_INT)
-	return value_at_lazy (builtin_type (exp->gdbarch)->builtin_int,
-			      (CORE_ADDR) value_as_address (arg1));
-      return value_ind (arg1);
+	{
+	  do_cleanups (old_chain);
+	  return value_at_lazy (builtin_type (exp->gdbarch)->builtin_int,
+				(CORE_ADDR) value_as_address (arg1));
+	}
+      arg1 = value_ind (arg1);
+      do_cleanups (old_chain);
+      return arg1;
 
     case UNOP_ADDR:
       /* C++: check for and handle pointer to members.  */
@@ -2777,7 +2898,7 @@ evaluate_subexp_with_coercion (struct expression *exp,
 {
   enum exp_opcode op;
   int pc;
-  struct value *val;
+  struct value *val = NULL;
   struct symbol *var;
   struct type *type;
 
@@ -2788,12 +2909,17 @@ evaluate_subexp_with_coercion (struct expression *exp,
     {
     case OP_VAR_VALUE:
       var = exp->elts[pc + 2].symbol;
+      /* address_of_variable will call object_address_set for check_typedef.
+	 Call it only if required as it can error-out on VAR in register.  */
+      if (TYPE_DYNAMIC (SYMBOL_TYPE (var)))
+	val = address_of_variable (var, exp->elts[pc + 1].block);
       type = check_typedef (SYMBOL_TYPE (var));
       if (TYPE_CODE (type) == TYPE_CODE_ARRAY
 	  && CAST_IS_CONVERSION)
 	{
 	  (*pos) += 4;
-	  val = address_of_variable (var, exp->elts[pc + 1].block);
+	  if (!val)
+	    val = address_of_variable (var, exp->elts[pc + 1].block);
 	  return value_cast (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
 			     val);
 	}
@@ -2845,9 +2971,13 @@ evaluate_subexp_for_sizeof (struct expression *exp, int *pos)
 
     case OP_VAR_VALUE:
       (*pos) += 4;
-      type = check_typedef (SYMBOL_TYPE (exp->elts[pc + 2].symbol));
-      return
-	value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
+      /* We do not need to call read_var_value but the object evaluation may
+	 need to have executed object_address_set which needs valid
+	 SYMBOL_VALUE_ADDRESS of the symbol.  Still VALUE returned by
+	 read_var_value we left as lazy.  */
+      type = value_type (read_var_value (exp->elts[pc + 2].symbol,
+					deprecated_safe_get_selected_frame ()));
+      return value_from_longest (size_type, (LONGEST) TYPE_LENGTH (type));
 
     default:
       val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS);
diff --git a/gdb/expprint.c b/gdb/expprint.c
index e378831..45deffe 100644
--- a/gdb/expprint.c
+++ b/gdb/expprint.c
@@ -816,6 +816,8 @@ op_name_standard (enum exp_opcode opcode)
       return "OP_TYPE";
     case OP_LABELED:
       return "OP_LABELED";
+    case OP_ADL_FUNC:
+      return "OP_ADL_FUNC";
     }
 }
 
diff --git a/gdb/expression.h b/gdb/expression.h
index ca216cf..6be0b1e 100644
--- a/gdb/expression.h
+++ b/gdb/expression.h
@@ -95,6 +95,11 @@ enum exp_opcode
        TYPE_INSTANCE num_types type0 ... typeN num_types TYPE_INSTANCE  */
     TYPE_INSTANCE,
 
+    /* TYPE_INSTANCE_LOOKUP is used when the user specifies a specific
+       type instantiation of a function (not a method). In this case,
+       we must toss the results of the parser and manually do the lookup. */
+    TYPE_INSTANCE_LOOKUP,
+
     /* end of C++.  */
 
     /* For Modula-2 integer division DIV */
@@ -347,6 +352,10 @@ enum exp_opcode
        Then comes another OP_DECFLOAT.  */
     OP_DECFLOAT,
 
+    /* OP_ADL_FUNC specifies that the argument is to be looked up in an
+       Argument Dependent manner (Koenig lookup) */
+    OP_ADL_FUNC,
+
      /* First extension operator.  Individual language modules define
 	extra operators in *.inc include files below always starting with
 	numbering at OP_EXTENDED0:
@@ -451,4 +460,5 @@ extern char *op_string (enum exp_opcode);
 extern void dump_raw_expression (struct expression *, struct ui_file *, char *);
 extern void dump_prefix_expression (struct expression *, struct ui_file *);
 
+
 #endif /* !defined (EXPRESSION_H) */
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index b914b49..78aef2f 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -31,6 +31,8 @@
 #include "f-lang.h"
 #include "valprint.h"
 #include "value.h"
+#include "block.h"
+#include "gdb_assert.h"
 
 
 /* Following is dubious stuff that had been in the xcoff reader. */
@@ -306,6 +308,46 @@ f_language_arch_info (struct gdbarch *gdbarch,
   lai->bool_type_default = builtin->builtin_logical_s2;
 }
 
+/* Find if NAME is not contained in any of the Fortran modules imported by the
+   Fortran USE statement.
+
+   As Fortran has no nested blocks such lookup can be processed from
+   lookup_symbol_nonlocal - when no local blocks could satisfy the lookup.  */
+
+static struct symbol *
+f_lookup_symbol_nonlocal (const char *name,
+			  const struct block *block,
+			  const domain_enum domain)
+{
+  if (block)
+    {
+      struct fortran_using *use;
+
+      for (use = BLOCK_FORTRAN_USE (block); use; use = use->next)
+	{
+	  struct symbol *sym;
+	  struct type *type;
+	  struct symbol *retval;
+
+	  sym = lookup_symbol_global (use->module_name, block, MODULE_DOMAIN);
+
+	  /* Module name lookup should not fail with correct debug info.  */
+	  if (sym == NULL)
+	    continue;
+
+	  type = SYMBOL_TYPE (sym);
+	  gdb_assert (TYPE_CODE (type) == TYPE_CODE_MODULE);
+	  gdb_assert (TYPE_MODULE_BLOCK (type) != NULL);
+
+	  retval = lookup_block_symbol (TYPE_MODULE_BLOCK (type), name, domain);
+	  if (retval)
+	    return retval;
+	}
+    }
+
+  return basic_lookup_symbol_nonlocal (name, block, domain);
+}
+
 /* This is declared in c-lang.h but it is silly to import that file for what
    is already just a hack. */
 extern int c_value_print (struct value *, struct ui_file *,
@@ -333,7 +375,7 @@ const struct language_defn f_language_defn =
   c_value_print,		/* FIXME */
   NULL,				/* Language specific skip_trampoline */
   NULL,                    	/* name_of_this */
-  basic_lookup_symbol_nonlocal,	/* lookup_symbol_nonlocal */
+  f_lookup_symbol_nonlocal,	/* lookup_symbol_nonlocal */
   basic_lookup_transparent_type,/* lookup_transparent_type */
   NULL,				/* Language specific symbol demangler */
   NULL,				/* Language specific class_name_from_physname */
diff --git a/gdb/f-lang.h b/gdb/f-lang.h
index b98c556..c68379a 100644
--- a/gdb/f-lang.h
+++ b/gdb/f-lang.h
@@ -28,6 +28,10 @@ extern void f_error (char *);	/* Defined in f-exp.y */
 extern void f_print_type (struct type *, char *, struct ui_file *, int,
 			  int);
 
+extern const char *f_object_address_data_valid_print_to_stream
+  (struct type *type, struct ui_file *stream);
+extern void f_object_address_data_valid_or_error (struct type *type);
+
 extern int f_val_print (struct type *, const gdb_byte *, int, CORE_ADDR,
 			struct ui_file *, int,
 			const struct value_print_options *);
@@ -125,3 +129,10 @@ struct builtin_f_type
 /* Return the Fortran type table for the specified architecture.  */
 extern const struct builtin_f_type *builtin_f_type (struct gdbarch *gdbarch);
 
+/* List of module names being imported by a block though BLOCK_FORTRAN_USE.  */
+
+struct fortran_using
+  {
+    struct fortran_using *next;
+    char module_name[1];
+  };
diff --git a/gdb/f-typeprint.c b/gdb/f-typeprint.c
index 0332932..6e8668c 100644
--- a/gdb/f-typeprint.c
+++ b/gdb/f-typeprint.c
@@ -32,7 +32,7 @@
 #include "gdbcore.h"
 #include "target.h"
 #include "f-lang.h"
-
+#include "dwarf2loc.h"
 #include "gdb_string.h"
 #include <errno.h>
 
@@ -49,6 +49,34 @@ void f_type_print_varspec_prefix (struct type *, struct ui_file *,
 void f_type_print_base (struct type *, struct ui_file *, int, int);
 
 
+const char *
+f_object_address_data_valid_print_to_stream (struct type *type,
+					     struct ui_file *stream)
+{
+  const char *msg;
+
+  msg = object_address_data_not_valid (type);
+  if (msg != NULL)
+    {
+      /* Assuming the content printed to STREAM should not be localized.  */
+      fprintf_filtered (stream, "<%s>", msg);
+    }
+
+  return msg;
+}
+
+void
+f_object_address_data_valid_or_error (struct type *type)
+{
+  const char *msg;
+
+  msg = object_address_data_not_valid (type);
+  if (msg != NULL)
+    {
+      error (_("Cannot access it because the %s."), _(msg));
+    }
+}
+
 /* LEVEL is the depth to indent lines by.  */
 
 void
@@ -58,6 +86,9 @@ f_print_type (struct type *type, char *varstring, struct ui_file *stream,
   enum type_code code;
   int demangled_args;
 
+  if (f_object_address_data_valid_print_to_stream (type, stream) != NULL)
+    return;
+
   f_type_print_base (type, stream, show, level);
   code = TYPE_CODE (type);
   if ((varstring != NULL && *varstring != '\0')
@@ -165,6 +196,9 @@ f_type_print_varspec_suffix (struct type *type, struct ui_file *stream,
 
   QUIT;
 
+  if (TYPE_CODE (type) != TYPE_CODE_TYPEDEF)
+    CHECK_TYPEDEF (type);
+
   switch (TYPE_CODE (type))
     {
     case TYPE_CODE_ARRAY:
diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c
index 9bd3640..f52b858 100644
--- a/gdb/f-valprint.c
+++ b/gdb/f-valprint.c
@@ -54,15 +54,17 @@ int f77_array_offset_tbl[MAX_FORTRAN_DIMS + 1][2];
 /* The following macro gives us the size of the nth dimension, Where 
    n is 1 based. */
 
-#define F77_DIM_SIZE(n) (f77_array_offset_tbl[n][1])
+#define F77_DIM_COUNT(n) (f77_array_offset_tbl[n][1])
 
-/* The following gives us the offset for row n where n is 1-based. */
+/* The following gives us the element size for row n where n is 1-based. */
 
-#define F77_DIM_OFFSET(n) (f77_array_offset_tbl[n][0])
+#define F77_DIM_BYTE_STRIDE(n) (f77_array_offset_tbl[n][0])
 
 int
 f77_get_lowerbound (struct type *type)
 {
+  f_object_address_data_valid_or_error (type);
+
   if (TYPE_ARRAY_LOWER_BOUND_IS_UNDEFINED (type))
     error (_("Lower bound may not be '*' in F77"));
 
@@ -72,14 +74,17 @@ f77_get_lowerbound (struct type *type)
 int
 f77_get_upperbound (struct type *type)
 {
+  f_object_address_data_valid_or_error (type);
+
   if (TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type))
     {
-      /* We have an assumed size array on our hands.  Assume that
-	 upper_bound == lower_bound so that we show at least 1 element.
-	 If the user wants to see more elements, let him manually ask for 'em
-	 and we'll subscript the array and show him.  */
+      /* We have an assumed size array on our hands.  As type_length_get
+	 already assumes a length zero of arrays with underfined bounds VALADDR
+	 passed to the Fortran functions does not contained the real inferior
+	 memory content.  User should request printing of specific array
+	 elements instead.  */
 
-      return f77_get_lowerbound (type);
+      return f77_get_lowerbound (type) - 1;
     }
 
   return TYPE_ARRAY_UPPER_BOUND_VALUE (type);
@@ -135,24 +140,29 @@ f77_create_arrayprint_offset_tbl (struct type *type, struct ui_file *stream)
       upper = f77_get_upperbound (tmp_type);
       lower = f77_get_lowerbound (tmp_type);
 
-      F77_DIM_SIZE (ndimen) = upper - lower + 1;
+      F77_DIM_COUNT (ndimen) = upper - lower + 1;
+
+      F77_DIM_BYTE_STRIDE (ndimen) =
+        TYPE_ARRAY_BYTE_STRIDE_VALUE (tmp_type);
 
       tmp_type = TYPE_TARGET_TYPE (tmp_type);
       ndimen++;
     }
 
-  /* Now we multiply eltlen by all the offsets, so that later we 
+  /* Now we multiply eltlen by all the BYTE_STRIDEs, so that later we
      can print out array elements correctly.  Up till now we 
-     know an offset to apply to get the item but we also 
+     know an eltlen to apply to get the item but we also
      have to know how much to add to get to the next item */
 
   ndimen--;
   eltlen = TYPE_LENGTH (tmp_type);
-  F77_DIM_OFFSET (ndimen) = eltlen;
+  if (F77_DIM_BYTE_STRIDE (ndimen) == 0)
+    F77_DIM_BYTE_STRIDE (ndimen) = eltlen;
   while (--ndimen > 0)
     {
-      eltlen *= F77_DIM_SIZE (ndimen + 1);
-      F77_DIM_OFFSET (ndimen) = eltlen;
+      eltlen *= F77_DIM_COUNT (ndimen + 1);
+      if (F77_DIM_BYTE_STRIDE (ndimen) == 0)
+	F77_DIM_BYTE_STRIDE (ndimen) = eltlen;
     }
 }
 
@@ -172,34 +182,34 @@ f77_print_array_1 (int nss, int ndimensions, struct type *type,
 
   if (nss != ndimensions)
     {
-      for (i = 0; (i < F77_DIM_SIZE (nss) && (*elts) < options->print_max); i++)
+      for (i = 0; (i < F77_DIM_COUNT (nss) && (*elts) < options->print_max); i++)
 	{
 	  fprintf_filtered (stream, "( ");
 	  f77_print_array_1 (nss + 1, ndimensions, TYPE_TARGET_TYPE (type),
-			     valaddr + i * F77_DIM_OFFSET (nss),
-			     address + i * F77_DIM_OFFSET (nss),
+			     valaddr + i * F77_DIM_BYTE_STRIDE (nss),
+			     address + i * F77_DIM_BYTE_STRIDE (nss),
 			     stream, recurse, options, elts);
 	  fprintf_filtered (stream, ") ");
 	}
-      if (*elts >= options->print_max && i < F77_DIM_SIZE (nss)) 
+      if (*elts >= options->print_max && i < F77_DIM_COUNT (nss))
 	fprintf_filtered (stream, "...");
     }
   else
     {
-      for (i = 0; i < F77_DIM_SIZE (nss) && (*elts) < options->print_max;
+      for (i = 0; i < F77_DIM_COUNT (nss) && (*elts) < options->print_max;
 	   i++, (*elts)++)
 	{
 	  val_print (TYPE_TARGET_TYPE (type),
-		     valaddr + i * F77_DIM_OFFSET (ndimensions),
+		     valaddr + i * F77_DIM_BYTE_STRIDE (ndimensions),
 		     0,
-		     address + i * F77_DIM_OFFSET (ndimensions),
+		     address + i * F77_DIM_BYTE_STRIDE (ndimensions),
 		     stream, recurse, options, current_language);
 
-	  if (i != (F77_DIM_SIZE (nss) - 1))
+	  if (i != (F77_DIM_COUNT (nss) - 1))
 	    fprintf_filtered (stream, ", ");
 
 	  if ((*elts == options->print_max - 1)
-	      && (i != (F77_DIM_SIZE (nss) - 1)))
+	      && (i != (F77_DIM_COUNT (nss) - 1)))
 	    fprintf_filtered (stream, "...");
 	}
     }
@@ -253,6 +263,9 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
   CORE_ADDR addr;
   int index;
 
+  if (f_object_address_data_valid_print_to_stream (type, stream) != NULL)
+    return 0;
+
   CHECK_TYPEDEF (type);
   switch (TYPE_CODE (type))
     {
diff --git a/gdb/findcmd.c b/gdb/findcmd.c
index c752316..df2687c 100644
--- a/gdb/findcmd.c
+++ b/gdb/findcmd.c
@@ -27,7 +27,7 @@
 
 /* Copied from bfd_put_bits.  */
 
-static void
+void
 put_bits (bfd_uint64_t data, char *buf, int bits, bfd_boolean big_p)
 {
   int i;
@@ -45,6 +45,41 @@ put_bits (bfd_uint64_t data, char *buf, int bits, bfd_boolean big_p)
     }
 }
 
+/* Allocates a buffer in *PATTERN_BUF, with a hard-coded initial size which
+   will be returned in *PATTERN_BUF_SIZE. *PATTERN_BUF_END points to the same
+   place as *PATTERN_BUF, indicating that the buffer is initially empty.  */
+
+void
+allocate_pattern_buffer (char **pattern_buf, char **pattern_buf_end,
+			 ULONGEST *pattern_buf_size)
+{
+#define INITIAL_PATTERN_BUF_SIZE 100
+  *pattern_buf_size = INITIAL_PATTERN_BUF_SIZE;
+  *pattern_buf = xmalloc (*pattern_buf_size);
+  *pattern_buf_end = *pattern_buf;
+}
+
+/* Grows *PATTERN_BUF by a factor of two if it's not large enough to hold
+   VAL_BYTES more bytes  or a 64-bit value, whichever is larger.
+   *PATTERN_BUF_END is updated as necessary.  */
+
+void
+increase_pattern_buffer (char **pattern_buf, char **pattern_buf_end,
+			 ULONGEST *pattern_buf_size, int val_bytes)
+{
+    /* Keep it simple and assume size == 'g' when watching for when we
+       need to grow the pattern buf.  */
+    if ((*pattern_buf_end - *pattern_buf + max (val_bytes, sizeof (int64_t)))
+	> *pattern_buf_size)
+      {
+	size_t current_offset = *pattern_buf_end - *pattern_buf;
+
+	*pattern_buf_size *= 2;
+	*pattern_buf = xrealloc (*pattern_buf, *pattern_buf_size);
+	*pattern_buf_end = *pattern_buf + current_offset;
+      }
+}
+
 /* Subroutine of find_command to simplify it.
    Parse the arguments of the "find" command.  */
 
@@ -61,8 +96,7 @@ parse_find_args (char *args, ULONGEST *max_countp,
   char *pattern_buf;
   /* Current size of search pattern buffer.
      We realloc space as needed.  */
-#define INITIAL_PATTERN_BUF_SIZE 100
-  ULONGEST pattern_buf_size = INITIAL_PATTERN_BUF_SIZE;
+  ULONGEST pattern_buf_size;
   /* Pointer to one past the last in-use part of pattern_buf.  */
   char *pattern_buf_end;
   ULONGEST pattern_len;
@@ -75,8 +109,7 @@ parse_find_args (char *args, ULONGEST *max_countp,
   if (args == NULL)
     error (_("Missing search parameters."));
 
-  pattern_buf = xmalloc (pattern_buf_size);
-  pattern_buf_end = pattern_buf;
+  allocate_pattern_buffer (&pattern_buf, &pattern_buf_end, &pattern_buf_size);
   old_cleanups = make_cleanup (free_current_contents, &pattern_buf);
 
   /* Get search granularity and/or max count if specified.
@@ -173,16 +206,8 @@ parse_find_args (char *args, ULONGEST *max_countp,
       v = parse_to_comma_and_eval (&s);
       val_bytes = TYPE_LENGTH (value_type (v));
 
-      /* Keep it simple and assume size == 'g' when watching for when we
-	 need to grow the pattern buf.  */
-      if ((pattern_buf_end - pattern_buf + max (val_bytes, sizeof (int64_t)))
-	  > pattern_buf_size)
-	{
-	  size_t current_offset = pattern_buf_end - pattern_buf;
-	  pattern_buf_size *= 2;
-	  pattern_buf = xrealloc (pattern_buf, pattern_buf_size);
-	  pattern_buf_end = pattern_buf + current_offset;
-	}
+      increase_pattern_buffer (&pattern_buf, &pattern_buf_end,
+			       &pattern_buf_size, val_bytes);
 
       if (size != '\0')
 	{
@@ -237,6 +262,45 @@ parse_find_args (char *args, ULONGEST *max_countp,
   discard_cleanups (old_cleanups);
 }
 
+/* Drives target_search_memory to sweep through the specified search space,
+   possibly in several iterations (with one call to this function for each
+   iteration).  *START_ADDR is the address where the search starts, and is
+   updated to the next starting address to continue the search.
+   *SEARCH_SPACE_LEN is the amount of bytes which will be searched, and is
+   updated for the next iteration. PATTERN_BUF holds the pattern to be searched
+   for, PATTERN_LEN is the size of the pattern in bytes.  If a match is found,
+   it's address is put in *FOUND_ADDR.
+
+   Returns 1 if found, 0 if not found, and -1 if there was an error requiring
+   halting of the search (e.g. memory read error).  */
+
+int
+search_memory (CORE_ADDR *start_addr, ULONGEST *search_space_len,
+	       const char *pattern_buf, ULONGEST pattern_len,
+	       CORE_ADDR *found_addr)
+{
+  /* Offset from start of this iteration to the next iteration.  */
+  ULONGEST next_iter_incr;
+  int found;
+    
+  found = target_search_memory (*start_addr, *search_space_len,
+				pattern_buf, pattern_len, found_addr);
+  if (found <= 0)
+    return found;
+
+  /* Begin next iteration at one byte past this match.  */
+  next_iter_incr = (*found_addr - *start_addr) + 1;
+
+  /* For robustness, we don't let search_space_len go -ve here.  */
+  if (*search_space_len >= next_iter_incr)
+    *search_space_len -= next_iter_incr;
+  else
+    *search_space_len = 0;
+  *start_addr += next_iter_incr;
+
+  return found;
+}
+
 static void
 find_command (char *args, int from_tty)
 {
@@ -267,12 +331,11 @@ find_command (char *args, int from_tty)
   while (search_space_len >= pattern_len
 	 && found_count < max_count)
     {
-      /* Offset from start of this iteration to the next iteration.  */
-      ULONGEST next_iter_incr;
       CORE_ADDR found_addr;
-      int found = target_search_memory (start_addr, search_space_len,
-					pattern_buf, pattern_len, &found_addr);
+      int found;
 
+      found = search_memory (&start_addr, &search_space_len, pattern_buf,
+			     pattern_len, &found_addr);
       if (found <= 0)
 	break;
 
@@ -280,16 +343,6 @@ find_command (char *args, int from_tty)
       printf_filtered ("\n");
       ++found_count;
       last_found_addr = found_addr;
-
-      /* Begin next iteration at one byte past this match.  */
-      next_iter_incr = (found_addr - start_addr) + 1;
-
-      /* For robustness, we don't let search_space_len go -ve here.  */
-      if (search_space_len >= next_iter_incr)
-	search_space_len -= next_iter_incr;
-      else
-	search_space_len = 0;
-      start_addr += next_iter_incr;
     }
 
   /* Record and print the results.  */
diff --git a/gdb/findvar.c b/gdb/findvar.c
index e117a8e..6bd3724 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -35,6 +35,7 @@
 #include "user-regs.h"
 #include "block.h"
 #include "objfiles.h"
+#include "dwarf2loc.h"
 
 /* Basic byte-swapping routines.  All 'extract' functions return a
    host-format integer from a target-format integer at ADDR which is
@@ -397,27 +398,16 @@ symbol_read_needs_frame (struct symbol *sym)
 /* Given a struct symbol for a variable,
    and a stack frame id, read the value of the variable
    and return a (pointer to a) struct value containing the value. 
-   If the variable cannot be found, return a zero pointer.  */
+   If the variable cannot be found, return a zero pointer.
+   We have to first find the address of the variable before allocating struct
+   value to return as its size may depend on DW_OP_PUSH_OBJECT_ADDRESS possibly
+   used by its type.  */
 
 struct value *
 read_var_value (struct symbol *var, struct frame_info *frame)
 {
-  struct value *v;
   struct type *type = SYMBOL_TYPE (var);
   CORE_ADDR addr;
-  int len;
-
-  if (SYMBOL_CLASS (var) == LOC_COMPUTED
-      || SYMBOL_CLASS (var) == LOC_REGISTER)
-    /* These cases do not use V.  */
-    v = NULL;
-  else
-    {
-      v = allocate_value (type);
-      VALUE_LVAL (v) = lval_memory;	/* The most likely possibility.  */
-    }
-
-  len = TYPE_LENGTH (type);
 
   if (symbol_read_needs_frame (var))
     gdb_assert (frame);
@@ -425,32 +415,40 @@ read_var_value (struct symbol *var, struct frame_info *frame)
   switch (SYMBOL_CLASS (var))
     {
     case LOC_CONST:
-      /* Put the constant back in target format.  */
-      store_signed_integer (value_contents_raw (v), len,
-			    gdbarch_byte_order (get_type_arch (type)),
-			    (LONGEST) SYMBOL_VALUE (var));
-      VALUE_LVAL (v) = not_lval;
-      return v;
+      {
+	/* Put the constant back in target format.  */
+	struct value *v = allocate_value (type);
+	VALUE_LVAL (v) = not_lval;
+	store_signed_integer (value_contents_raw (v), TYPE_LENGTH (type),
+			      gdbarch_byte_order (get_type_arch (type)),
+			      (LONGEST) SYMBOL_VALUE (var));
+	return v;
+      }
 
     case LOC_LABEL:
-      /* Put the constant back in target format.  */
-      if (overlay_debugging)
-	{
-	  CORE_ADDR addr
-	    = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
-					SYMBOL_OBJ_SECTION (var));
-	  store_typed_address (value_contents_raw (v), type, addr);
-	}
-      else
-	store_typed_address (value_contents_raw (v), type,
-			      SYMBOL_VALUE_ADDRESS (var));
-      VALUE_LVAL (v) = not_lval;
-      return v;
+      {
+	/* Put the constant back in target format.  */
+	struct value *v = allocate_value (type);
+	VALUE_LVAL (v) = not_lval;
+	if (overlay_debugging)
+	  {
+	    CORE_ADDR addr
+	      = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
+					  SYMBOL_OBJ_SECTION (var));
+	    store_typed_address (value_contents_raw (v), type, addr);
+	  }
+	else
+	  store_typed_address (value_contents_raw (v), type,
+				SYMBOL_VALUE_ADDRESS (var));
+	return v;
+      }
 
     case LOC_CONST_BYTES:
       {
-	memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var), len);
+	struct value *v = allocate_value (type);
 	VALUE_LVAL (v) = not_lval;
+	memcpy (value_contents_raw (v), SYMBOL_VALUE_BYTES (var),
+		TYPE_LENGTH (type));
 	return v;
       }
 
@@ -492,12 +490,23 @@ read_var_value (struct symbol *var, struct frame_info *frame)
       break;
 
     case LOC_BLOCK:
-      if (overlay_debugging)
-	set_value_address (v, symbol_overlayed_address
-	  (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_OBJ_SECTION (var)));
-      else
-	set_value_address (v, BLOCK_START (SYMBOL_BLOCK_VALUE (var)));
-      return v;
+      {
+        CORE_ADDR addr;
+	struct value *v;
+
+	if (overlay_debugging)
+	  addr = symbol_overlayed_address
+	    (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_OBJ_SECTION (var));
+	else
+	  addr = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
+	/* ADDR is set here for ALLOCATE_VALUE's CHECK_TYPEDEF for
+	   DW_OP_push_object_address.  */
+	object_address_set (addr);
+	v = allocate_value (type);
+	VALUE_LVAL (v) = lval_memory;
+	set_value_address (v, addr);
+	return v;
+      }
 
     case LOC_REGISTER:
     case LOC_REGPARM_ADDR:
@@ -516,7 +525,6 @@ read_var_value (struct symbol *var, struct frame_info *frame)
 	      error (_("Value of register variable not available."));
 
 	    addr = value_as_address (regval);
-	    VALUE_LVAL (v) = lval_memory;
 	  }
 	else
 	  {
@@ -559,18 +567,33 @@ read_var_value (struct symbol *var, struct frame_info *frame)
       break;
 
     case LOC_OPTIMIZED_OUT:
-      VALUE_LVAL (v) = not_lval;
-      set_value_optimized_out (v, 1);
-      return v;
+      {
+        struct value *v = allocate_value (type);
+
+	VALUE_LVAL (v) = not_lval;
+	set_value_optimized_out (v, 1);
+	return v;
+      }
 
     default:
       error (_("Cannot look up value of a botched symbol."));
       break;
     }
 
-  set_value_address (v, addr);
-  set_value_lazy (v, 1);
-  return v;
+  {
+    struct value *v;
+
+    /* ADDR is set here for ALLOCATE_VALUE's CHECK_TYPEDEF for
+       DW_OP_PUSH_OBJECT_ADDRESS.  */
+    object_address_set (addr);
+    v = allocate_value (type);
+    VALUE_LVAL (v) = lval_memory;
+    set_value_address (v, addr);
+
+    set_value_lazy (v, 1);
+
+    return v;
+  }
 }
 
 /* Install default attributes for register values.  */
@@ -607,10 +630,11 @@ struct value *
 value_from_register (struct type *type, int regnum, struct frame_info *frame)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
-  struct type *type1 = check_typedef (type);
   struct value *v;
 
-  if (gdbarch_convert_register_p (gdbarch, regnum, type1))
+  type = check_typedef (type);
+
+  if (gdbarch_convert_register_p (gdbarch, regnum, type))
     {
       /* The ISA/ABI need to something weird when obtaining the
          specified value from this register.  It might need to
@@ -624,7 +648,7 @@ value_from_register (struct type *type, int regnum, struct frame_info *frame)
       VALUE_FRAME_ID (v) = get_frame_id (frame);
       VALUE_REGNUM (v) = regnum;
       gdbarch_register_to_value (gdbarch,
-				 frame, regnum, type1, value_contents_raw (v));
+				 frame, regnum, type, value_contents_raw (v));
     }
   else
     {
diff --git a/gdb/frv-linux-tdep.c b/gdb/frv-linux-tdep.c
index c051a4d..5b07063 100644
--- a/gdb/frv-linux-tdep.c
+++ b/gdb/frv-linux-tdep.c
@@ -32,6 +32,7 @@
 #include "frame-unwind.h"
 #include "regset.h"
 #include "gdb_string.h"
+#include "linux-tdep.h"
 
 /* Define the size (in bytes) of an FR-V instruction.  */
 static const int frv_instr_size = 4;
@@ -486,7 +487,21 @@ frv_linux_regset_from_core_section (struct gdbarch *gdbarch,
   return NULL;
 }
 
-
+static CORE_ADDR
+frv_linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
+				      CORE_ADDR addr,
+				      struct target_ops *targ)
+{
+  CORE_ADDR pc = frv_convert_from_func_ptr_addr (gdbarch, addr, targ);
+  CORE_ADDR resolved;
+
+  resolved = linux_convert_from_func_and_ptr (gdbarch, addr, pc);
+  if (resolved != pc)
+    pc = frv_convert_from_func_ptr_addr (gdbarch, resolved, targ);
+
+  return pc;
+}
+
 static void
 frv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
@@ -494,6 +509,10 @@ frv_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   frame_unwind_append_unwinder (gdbarch, &frv_linux_sigtramp_frame_unwind); 
   set_gdbarch_regset_from_core_section (gdbarch,
                                         frv_linux_regset_from_core_section);
+
+  if (frv_abi (gdbarch) == FRV_ABI_FDPIC)
+    set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+					  frv_linux_convert_from_func_ptr_addr);
 }
 
 static enum gdb_osabi
diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c
index a38ec8e..b8856a9 100644
--- a/gdb/frv-tdep.c
+++ b/gdb/frv-tdep.c
@@ -1169,7 +1169,7 @@ find_func_descr (struct gdbarch *gdbarch, CORE_ADDR entry_point)
   return descr;
 }
 
-static CORE_ADDR
+CORE_ADDR
 frv_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr,
                                 struct target_ops *targ)
 {
diff --git a/gdb/frv-tdep.h b/gdb/frv-tdep.h
index 25cc9c4..95d5fe5 100644
--- a/gdb/frv-tdep.h
+++ b/gdb/frv-tdep.h
@@ -118,3 +118,6 @@ CORE_ADDR frv_fetch_objfile_link_map (struct objfile *objfile);
 struct target_so_ops;
 extern struct target_so_ops frv_so_ops;
 
+CORE_ADDR frv_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
+					  CORE_ADDR addr,
+					  struct target_ops *targ);
diff --git a/gdb/gdbinit.in b/gdb/gdbinit.in
index ffb7f53..a2e7e94 100644
--- a/gdb/gdbinit.in
+++ b/gdb/gdbinit.in
@@ -1,5 +1,15 @@
 echo Setting up the environment for debugging gdb.\n
 
+# Set up the Python library and "require" command.
+python
+from os.path import abspath
+gdb.datadir = abspath ('@srcdir@/python/lib')
+gdb.pythonlibdir = gdb.datadir
+gdb.__path__ = [gdb.datadir + '/gdb']
+sys.path.insert(0, gdb.datadir)
+end
+source @srcdir@/python/lib/gdb/__init__.py
+
 set complaints 1
 
 b internal_error
diff --git a/gdb/gdbthread.h b/gdb/gdbthread.h
index cd24eaf..119af7d 100644
--- a/gdb/gdbthread.h
+++ b/gdb/gdbthread.h
@@ -185,6 +185,10 @@ struct thread_info
   /* True if this thread has been explicitly requested to stop.  */
   int stop_requested;
 
+  /* The initiating frame of a nexting operation, used for deciding
+     which exceptions to intercept.  */
+  struct frame_id initiating_frame;
+
   /* Private data used by the target vector implementation.  */
   struct private_thread_info *private;
 
@@ -257,6 +261,9 @@ extern struct thread_info *any_live_thread_of_process (int pid);
 /* Change the ptid of thread OLD_PTID to NEW_PTID.  */
 void thread_change_ptid (ptid_t old_ptid, ptid_t new_ptid);
 
+/* Prune dead threads from the list of threads.  */
+extern void prune_threads (void);
+
 /* Iterator function to call a user-provided callback function
    once for each known thread.  */
 typedef int (*thread_callback_func) (struct thread_info *, void *);
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 46846c4..95bcca4 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -39,6 +39,9 @@
 #include "cp-abi.h"
 #include "gdb_assert.h"
 #include "hashtab.h"
+#include "observer.h"
+#include "dwarf2expr.h"
+#include "dwarf2loc.h"
 
 
 /* Floatformat pairs.  */
@@ -119,6 +122,24 @@ static void print_arg_types (struct field *, int, int);
 static void dump_fn_fieldlists (struct type *, int);
 static void print_cplus_stuff (struct type *, int);
 
+/* A reference count structure for the type reference count map.  Each
+   type in a hierarchy of types is mapped to the same reference
+   count.  */
+struct type_refc_entry
+{
+  /* One type in the hierarchy.  Each type in the hierarchy gets its
+     own slot.  */
+  struct type *type;
+
+  /* A pointer to the shared reference count.  */
+  int *refc;
+};
+
+/* The hash table holding all discardable `struct type *' references.  */
+static htab_t type_discardable_table;
+
+/* Current type_discardable_check pass used for TYPE_DISCARDABLE_AGE.  */
+static int type_discardable_age_current;
 
 /* Allocate a new OBJFILE-associated type structure and fill it
    with some defaults.  Space for the type structure is allocated
@@ -149,6 +170,39 @@ alloc_type (struct objfile *objfile)
   return type;
 }
 
+/* Declare TYPE as discardable on next garbage collection by free_all_types.
+   You must call type_mark_used during each free_all_types to protect TYPE from
+   being deallocated.  */
+
+static void
+set_type_as_discardable (struct type *type)
+{
+  void **slot;
+
+  gdb_assert (!TYPE_DISCARDABLE (type));
+
+  TYPE_DISCARDABLE (type) = 1;
+  TYPE_DISCARDABLE_AGE (type) = type_discardable_age_current;
+
+  slot = htab_find_slot (type_discardable_table, type, INSERT);
+  gdb_assert (!*slot);
+  *slot = type;
+}
+
+/* Allocate a new type like alloc_type but preserve for it the discardability
+   state of PARENT_TYPE.  */
+
+static struct type *
+alloc_type_as_parent (struct type *parent_type)
+{
+  struct type *new_type = alloc_type_copy (parent_type);
+
+  if (TYPE_DISCARDABLE (parent_type))
+    set_type_as_discardable (new_type);
+
+  return new_type;
+}
+
 /* Allocate a new GDBARCH-associated type structure and fill it
    with some defaults.  Space for the type structure is allocated
    on the heap.  */
@@ -274,7 +328,7 @@ make_pointer_type (struct type *type, struct type **typeptr)
 
   if (typeptr == 0 || *typeptr == 0)	/* We'll need to allocate one.  */
     {
-      ntype = alloc_type_copy (type);
+      ntype = alloc_type_as_parent (type);
       if (typeptr)
 	*typeptr = ntype;
     }
@@ -351,7 +405,7 @@ make_reference_type (struct type *type, struct type **typeptr)
 
   if (typeptr == 0 || *typeptr == 0)	/* We'll need to allocate one.  */
     {
-      ntype = alloc_type_copy (type);
+      ntype = alloc_type_as_parent (type);
       if (typeptr)
 	*typeptr = ntype;
     }
@@ -723,6 +777,7 @@ create_range_type (struct type *result_type, struct type *index_type,
     TYPE_ZALLOC (result_type, sizeof (struct range_bounds));
   TYPE_LOW_BOUND (result_type) = low_bound;
   TYPE_HIGH_BOUND (result_type) = high_bound;
+  TYPE_BYTE_STRIDE (result_type) = 0;
 
   if (low_bound >= 0)
     TYPE_UNSIGNED (result_type) = 1;
@@ -822,26 +877,45 @@ create_array_type (struct type *result_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);
   TYPE_NFIELDS (result_type) = 1;
   TYPE_FIELDS (result_type) =
     (struct field *) TYPE_ZALLOC (result_type, sizeof (struct field));
   TYPE_INDEX_TYPE (result_type) = range_type;
   TYPE_VPTR_FIELDNO (result_type) = -1;
 
-  /* TYPE_FLAG_TARGET_STUB will take care of zero length arrays */
+  /* DWARF blocks may depend on runtime information like
+     DW_OP_PUSH_OBJECT_ADDRESS not being available during the
+     CREATE_ARRAY_TYPE time.  */
+  if (TYPE_RANGE_DATA (range_type)->low.kind != RANGE_BOUND_KIND_CONSTANT
+      || TYPE_RANGE_DATA (range_type)->high.kind != RANGE_BOUND_KIND_CONSTANT
+      || TYPE_LOW_BOUND_UNDEFINED (range_type) 
+      || TYPE_HIGH_BOUND_UNDEFINED (range_type) 
+      || get_discrete_bounds (range_type, &low_bound, &high_bound) < 0)
+    {
+      low_bound = 0;
+      high_bound = -1;
+    }
+
+  /* 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.  TYPE_TARGET_STUB needs to
+     be checked as it may have dependencies on DWARF blocks depending on
+     runtime information not available during the CREATE_ARRAY_TYPE time.  */
+  if (high_bound < low_bound || TYPE_TARGET_STUB (element_type))
+    TYPE_LENGTH (result_type) = 0;
+  else
+    {
+      CHECK_TYPEDEF (element_type);
+      TYPE_LENGTH (result_type) =
+	TYPE_LENGTH (element_type) * (high_bound - low_bound + 1);
+    }
+
   if (TYPE_LENGTH (result_type) == 0)
-    TYPE_TARGET_STUB (result_type) = 1;
+    {
+      /* The real size will be computed for specific instances by
+	 CHECK_TYPEDEF.  */
+      TYPE_TARGET_STUB (result_type) = 1;
+    }
 
   return result_type;
 }
@@ -1337,6 +1411,105 @@ stub_noname_complaint (void)
   complaint (&symfile_complaints, _("stub type has NULL name"));
 }
 
+/* Calculate the memory length of array TYPE.
+
+   TARGET_TYPE should be set to `check_typedef (TYPE_TARGET_TYPE (type))' as
+   a performance hint.  Feel free to pass NULL.  Set FULL_SPAN to return the
+   size incl. the possible padding of the last element - it may differ from the
+   cleared FULL_SPAN return value (the expected SIZEOF) for non-zero
+   TYPE_BYTE_STRIDE values.  */
+
+static LONGEST
+type_length_get (struct type *type, struct type *target_type, int full_span)
+{
+  struct type *range_type;
+  LONGEST byte_stride = 0;	/* `= 0' for a false GCC warning.  */
+  LONGEST count, element_size, retval;
+
+  if (TYPE_CODE (type) != TYPE_CODE_ARRAY
+      && TYPE_CODE (type) != TYPE_CODE_STRING)
+    return TYPE_LENGTH (type);
+
+  /* Avoid executing TYPE_HIGH_BOUND for invalid (unallocated/unassociated)
+     Fortran arrays.  The allocated data will never be used so they can be
+     zero-length.  */
+  if (object_address_data_not_valid (type))
+    return 0;
+
+  range_type = TYPE_INDEX_TYPE (type);
+  if (TYPE_LOW_BOUND_UNDEFINED (range_type)
+      || TYPE_HIGH_BOUND_UNDEFINED (range_type))
+    return 0;
+  count = TYPE_HIGH_BOUND (range_type) - TYPE_LOW_BOUND (range_type) + 1;
+  /* It may happen for wrong DWARF annotations returning garbage data.  */
+  if (count < 0)
+    warning (_("Range for type %s has invalid bounds %s..%s"),
+	     TYPE_NAME (type), plongest (TYPE_LOW_BOUND (range_type)),
+	     plongest (TYPE_HIGH_BOUND (range_type)));
+  /* The code below does not handle count == 0 right.  */
+  if (count <= 0)
+    return 0;
+  if (full_span || count > 1)
+    {
+      /* We do not use TYPE_ARRAY_BYTE_STRIDE_VALUE (type) here as we want to
+         force FULL_SPAN to 1.  */
+      byte_stride = TYPE_BYTE_STRIDE (range_type);
+      if (byte_stride == 0)
+        {
+	  if (target_type == NULL)
+	    target_type = check_typedef (TYPE_TARGET_TYPE (type));
+	  byte_stride = type_length_get (target_type, NULL, 1);
+	}
+    }
+
+  /* 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.
+     */
+
+  if (full_span)
+    {
+      retval = count * byte_stride;
+      if (count == 0 || retval / count != byte_stride || retval > UINT_MAX)
+	retval = 0;
+      return retval;
+    }
+  if (target_type == NULL)
+    target_type = check_typedef (TYPE_TARGET_TYPE (type));
+  element_size = type_length_get (target_type, NULL, 1);
+  retval = (count - 1) * byte_stride + element_size;
+  if (retval < element_size
+      || (byte_stride != 0
+          && (retval - element_size) / byte_stride != count - 1)
+      || retval > UINT_MAX)
+    retval = 0;
+  return retval;
+}
+
+/* Prepare TYPE after being read in by the backend.  Currently this function
+   only propagates the TYPE_DYNAMIC flag.  */
+
+void
+finalize_type (struct type *type)
+{
+  int i;
+
+  for (i = 0; i < TYPE_NFIELDS (type); ++i)
+    if (TYPE_FIELD_TYPE (type, i) && TYPE_DYNAMIC (TYPE_FIELD_TYPE (type, i)))
+      break;
+
+  /* FIXME: cplus_stuff is ignored here.  */
+  if (i < TYPE_NFIELDS (type)
+      || (TYPE_VPTR_BASETYPE (type) && TYPE_DYNAMIC (TYPE_VPTR_BASETYPE (type)))
+      || (TYPE_TARGET_TYPE (type) && TYPE_DYNAMIC (TYPE_TARGET_TYPE (type))))
+    TYPE_DYNAMIC (type) = 1;
+}
+
 /* Added by Bryan Boreham, Kewill, Sun Sep 17 18:07:17 1989.
 
    If this is a stubbed struct (i.e. declared as struct foo *), see if
@@ -1468,51 +1641,36 @@ check_typedef (struct type *type)
         }
     }
 
-  if (TYPE_TARGET_STUB (type))
+  /* copy_type_recursive automatically makes the resulting type containing only
+     constant values expected by the callers of this function.  */
+  if (TYPE_DYNAMIC (type))
+    {
+      htab_t copied_types;
+      struct type *type_old = type;
+
+      copied_types = create_copied_types_hash (NULL);
+      type = copy_type_recursive (type, copied_types);
+      htab_delete (copied_types);
+
+      gdb_assert (TYPE_DYNAMIC (type) == 0);
+    }
+
+  if (TYPE_TARGET_STUB (type) || TYPE_DYNAMIC (type))
     {
-      struct type *range_type;
       struct type *target_type = check_typedef (TYPE_TARGET_TYPE (type));
 
+      if (TYPE_DYNAMIC (type))
+	TYPE_TARGET_TYPE (type) = target_type;
       if (TYPE_STUB (target_type) || TYPE_TARGET_STUB (target_type))
 	{
 	  /* Empty.  */
 	}
       else if (TYPE_CODE (type) == TYPE_CODE_ARRAY
-	       && TYPE_NFIELDS (type) == 1
-	       && (TYPE_CODE (range_type = TYPE_INDEX_TYPE (type))
-		   == TYPE_CODE_RANGE))
+	       || TYPE_CODE (type) == TYPE_CODE_STRING)
 	{
 	  /* 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;
+	     number of elements and the target type's length.  */
+	  TYPE_LENGTH (type) = type_length_get (type, target_type, 0);
 	  TYPE_TARGET_STUB (type) = 0;
 	}
       else if (TYPE_CODE (type) == TYPE_CODE_RANGE)
@@ -1520,9 +1678,12 @@ check_typedef (struct type *type)
 	  TYPE_LENGTH (type) = TYPE_LENGTH (target_type);
 	  TYPE_TARGET_STUB (type) = 0;
 	}
+      TYPE_DYNAMIC (type) = 0;
     }
+
   /* Cache TYPE_LENGTH for future use.  */
   TYPE_LENGTH (orig_type) = TYPE_LENGTH (type);
+
   return type;
 }
 
@@ -1791,6 +1952,8 @@ init_type (enum type_code code, int length, int flags,
     TYPE_NOTTEXT (type) = 1;
   if (flags & TYPE_FLAG_FIXED_INSTANCE)
     TYPE_FIXED_INSTANCE (type) = 1;
+  if (flags & TYPE_FLAG_GNU_IFUNC)
+    TYPE_GNU_IFUNC (type) = 1;
 
   if (name)
     TYPE_NAME (type) = obsavestring (name, strlen (name),
@@ -1815,6 +1978,7 @@ init_type (enum type_code code, int length, int flags,
         TYPE_SPECIFIC_FIELD (type) = TYPE_SPECIFIC_CALLING_CONVENTION;
         break;
     }
+
   return type;
 }
 
@@ -2992,33 +3156,42 @@ type_pair_eq (const void *item_lhs, const void *item_rhs)
 }
 
 /* Allocate the hash table used by copy_type_recursive to walk
-   types without duplicates.  We use OBJFILE's obstack, because
-   OBJFILE is about to be deleted.  */
+   types without duplicates.   */
 
 htab_t
 create_copied_types_hash (struct objfile *objfile)
 {
-  return htab_create_alloc_ex (1, type_pair_hash, type_pair_eq,
-			       NULL, &objfile->objfile_obstack,
-			       hashtab_obstack_allocate,
-			       dummy_obstack_deallocate);
+  if (objfile == NULL)
+    {
+      /* NULL OBJFILE is for TYPE_DYNAMIC types already contained in
+	 OBJFILE_MALLOC memory, such as those from VALUE_HISTORY_CHAIN.  Table
+	 element entries get allocated by xmalloc - so use xfree.  */
+      return htab_create (1, type_pair_hash, type_pair_eq, xfree);
+    }
+  else
+    {
+      /* Use OBJFILE's obstack, because OBJFILE is about to be deleted.  Table
+	 element entries get allocated by xmalloc - so use xfree.  */
+      return htab_create_alloc_ex (1, type_pair_hash, type_pair_eq,
+				   xfree, &objfile->objfile_obstack,
+				   hashtab_obstack_allocate,
+				   dummy_obstack_deallocate);
+    }
 }
 
-/* Recursively copy (deep copy) TYPE, if it is associated with
-   OBJFILE.  Return a new type allocated using malloc, a saved type if
-   we have already visited TYPE (using COPIED_TYPES), or TYPE if it is
-   not associated with OBJFILE.  */
+/* A helper for copy_type_recursive.  This does all the work.  OBJFILE is used
+   only for an assertion checking.  */
 
-struct type *
-copy_type_recursive (struct objfile *objfile, 
-		     struct type *type,
-		     htab_t copied_types)
+static struct type *
+copy_type_recursive_1 (struct objfile *objfile, 
+		       struct type *type,
+		       htab_t copied_types)
 {
   struct type_pair *stored, pair;
   void **slot;
   struct type *new_type;
 
-  if (! TYPE_OBJFILE_OWNED (type))
+  if (! TYPE_OBJFILE_OWNED (type) && !TYPE_DYNAMIC (type))
     return type;
 
   /* This type shouldn't be pointing to any types in other objfiles;
@@ -3033,8 +3206,10 @@ copy_type_recursive (struct objfile *objfile,
   new_type = alloc_type_arch (get_type_arch (type));
 
   /* We must add the new type to the hash table immediately, in case
-     we encounter this type again during a recursive call below.  */
-  stored = obstack_alloc (&objfile->objfile_obstack, sizeof (struct type_pair));
+     we encounter this type again during a recursive call below.  Memory could
+     be allocated from OBJFILE in the case we will be removing OBJFILE, this
+     optimization is missed and xfree is called for it from COPIED_TYPES.  */
+  stored = xmalloc (sizeof (*stored));
   stored->old = type;
   stored->new = new_type;
   *slot = stored;
@@ -3045,6 +3220,19 @@ copy_type_recursive (struct objfile *objfile,
   TYPE_OBJFILE_OWNED (new_type) = 0;
   TYPE_OWNER (new_type).gdbarch = get_type_arch (type);
 
+  /* TYPE_MAIN_TYPE memory copy above rewrote the TYPE_DISCARDABLE flag so we
+     need to initialize it again.  And even if TYPE was already discardable
+     NEW_TYPE so far is not registered in TYPE_DISCARDABLE_TABLE.  */
+  TYPE_DISCARDABLE (new_type) = 0;
+  set_type_as_discardable (new_type);
+
+  /* Pre-clear the fields processed by delete_main_type.  If DWARF block
+     evaluations below call error we would leave an unfreeable TYPE.  */
+  TYPE_TARGET_TYPE (new_type) = NULL;
+  TYPE_VPTR_BASETYPE (new_type) = NULL;
+  TYPE_NFIELDS (new_type) = 0;
+  TYPE_FIELDS (new_type) = NULL;
+
   if (TYPE_NAME (type))
     TYPE_NAME (new_type) = xstrdup (TYPE_NAME (type));
   if (TYPE_TAG_NAME (type))
@@ -3053,12 +3241,48 @@ copy_type_recursive (struct objfile *objfile,
   TYPE_INSTANCE_FLAGS (new_type) = TYPE_INSTANCE_FLAGS (type);
   TYPE_LENGTH (new_type) = TYPE_LENGTH (type);
 
+  if (TYPE_ALLOCATED (new_type))
+    {
+      gdb_assert (!TYPE_NOT_ALLOCATED (new_type));
+
+      if (!dwarf_locexpr_baton_eval (TYPE_ALLOCATED (new_type)))
+        TYPE_NOT_ALLOCATED (new_type) = 1;
+      TYPE_ALLOCATED (new_type) = NULL;
+    }
+
+  if (TYPE_ASSOCIATED (new_type))
+    {
+      gdb_assert (!TYPE_NOT_ASSOCIATED (new_type));
+
+      if (!dwarf_locexpr_baton_eval (TYPE_ASSOCIATED (new_type)))
+        TYPE_NOT_ASSOCIATED (new_type) = 1;
+      TYPE_ASSOCIATED (new_type) = NULL;
+    }
+
+  if (!TYPE_DATA_LOCATION_IS_ADDR (new_type)
+      && TYPE_DATA_LOCATION_DWARF_BLOCK (new_type))
+    {
+      if (TYPE_NOT_ALLOCATED (new_type)
+          || TYPE_NOT_ASSOCIATED (new_type))
+	TYPE_DATA_LOCATION_DWARF_BLOCK (new_type) = NULL;
+      else
+	{
+	  TYPE_DATA_LOCATION_IS_ADDR (new_type) = 1;
+	  TYPE_DATA_LOCATION_ADDR (new_type) = dwarf_locexpr_baton_eval
+				    (TYPE_DATA_LOCATION_DWARF_BLOCK (new_type));
+	}
+    }
+
   /* Copy the fields.  */
   if (TYPE_NFIELDS (type))
     {
       int i, nfields;
 
+      /* TYPE_CODE_RANGE uses TYPE_RANGE_DATA of the union with TYPE_FIELDS.  */
+      gdb_assert (TYPE_CODE (type) != TYPE_CODE_RANGE);
+
       nfields = TYPE_NFIELDS (type);
+      TYPE_NFIELDS (new_type) = nfields;
       TYPE_FIELDS (new_type) = XCALLOC (nfields, struct field);
       for (i = 0; i < nfields; i++)
 	{
@@ -3067,8 +3291,8 @@ copy_type_recursive (struct objfile *objfile,
 	  TYPE_FIELD_BITSIZE (new_type, i) = TYPE_FIELD_BITSIZE (type, i);
 	  if (TYPE_FIELD_TYPE (type, i))
 	    TYPE_FIELD_TYPE (new_type, i)
-	      = copy_type_recursive (objfile, TYPE_FIELD_TYPE (type, i),
-				     copied_types);
+	      = copy_type_recursive_1 (objfile, TYPE_FIELD_TYPE (type, i),
+				       copied_types);
 	  if (TYPE_FIELD_NAME (type, i))
 	    TYPE_FIELD_NAME (new_type, i) = 
 	      xstrdup (TYPE_FIELD_NAME (type, i));
@@ -3095,24 +3319,166 @@ copy_type_recursive (struct objfile *objfile,
 	}
     }
 
+  /* Both FIELD_LOC_KIND_DWARF_BLOCK and TYPE_RANGE_HIGH_BOUND_IS_COUNT were
+     possibly converted.  */
+  TYPE_DYNAMIC (new_type) = 0;
+
   /* For range types, copy the bounds information. */
-  if (TYPE_CODE (type) == TYPE_CODE_RANGE)
+  if (TYPE_CODE (new_type) == TYPE_CODE_RANGE)
     {
       TYPE_RANGE_DATA (new_type) = xmalloc (sizeof (struct range_bounds));
       *TYPE_RANGE_DATA (new_type) = *TYPE_RANGE_DATA (type);
+
+      switch (TYPE_RANGE_DATA (new_type)->low.kind)
+	{
+	case RANGE_BOUND_KIND_CONSTANT:
+	  break;
+	case RANGE_BOUND_KIND_DWARF_BLOCK:
+	  /* `struct dwarf2_locexpr_baton' is too bound to its objfile so
+	     it is expected to be made constant by CHECK_TYPEDEF.
+	     TYPE_NOT_ALLOCATED and TYPE_NOT_ASSOCIATED are not valid for TYPE.
+	     */
+	  if (TYPE_NOT_ALLOCATED (new_type) || TYPE_NOT_ASSOCIATED (new_type)
+	      || ! has_stack_frames ())
+	    {
+	      /* We should set 1 for Fortran but how to find the language?  */
+	      TYPE_LOW_BOUND (new_type) = 0;
+	      TYPE_LOW_BOUND_UNDEFINED (new_type) = 1;
+	    }
+	  else
+	    TYPE_LOW_BOUND (new_type) = dwarf_locexpr_baton_eval
+				(TYPE_RANGE_DATA (new_type)->low.u.dwarf_block);
+	  TYPE_RANGE_DATA (new_type)->low.kind = RANGE_BOUND_KIND_CONSTANT;
+	  break;
+	case RANGE_BOUND_KIND_DWARF_LOCLIST:
+	  {
+	    CORE_ADDR addr;
+
+	    /* `struct dwarf2_loclist_baton' is too bound to its objfile so
+	       it is expected to be made constant by CHECK_TYPEDEF.
+	       TYPE_NOT_ALLOCATED and TYPE_NOT_ASSOCIATED are not valid for TYPE.
+	       */
+	    if (! TYPE_NOT_ALLOCATED (new_type)
+	        && ! TYPE_NOT_ASSOCIATED (new_type) && has_stack_frames ()
+	        && dwarf_loclist_baton_eval
+		  (TYPE_RANGE_DATA (new_type)->low.u.dwarf_loclist.loclist,
+		   TYPE_RANGE_DATA (new_type)->low.u.dwarf_loclist.type, &addr))
+	      TYPE_LOW_BOUND (new_type) = addr;
+	    else
+	      {
+		/* We should set 1 for Fortran but how to find the language?  */
+		TYPE_LOW_BOUND (new_type) = 0;
+		TYPE_LOW_BOUND_UNDEFINED (new_type) = 1;
+	      }
+	    TYPE_RANGE_DATA (new_type)->low.kind = RANGE_BOUND_KIND_CONSTANT;
+	  }
+	  break;
+	}
+
+      switch (TYPE_RANGE_DATA (new_type)->high.kind)
+	{
+	case RANGE_BOUND_KIND_CONSTANT:
+	  break;
+	case RANGE_BOUND_KIND_DWARF_BLOCK:
+	  /* `struct dwarf2_locexpr_baton' is too bound to its objfile so
+	     it is expected to be made constant by CHECK_TYPEDEF.
+	     TYPE_NOT_ALLOCATED and TYPE_NOT_ASSOCIATED are not valid for TYPE.
+	     */
+	  if (TYPE_NOT_ALLOCATED (new_type) || TYPE_NOT_ASSOCIATED (new_type)
+	      || ! has_stack_frames ())
+	    {
+	      TYPE_HIGH_BOUND (new_type) = TYPE_LOW_BOUND (new_type) - 1;
+	      TYPE_HIGH_BOUND_UNDEFINED (new_type) = 1;
+	    }
+	  else
+	    TYPE_HIGH_BOUND (new_type) = dwarf_locexpr_baton_eval
+			       (TYPE_RANGE_DATA (new_type)->high.u.dwarf_block);
+	  TYPE_RANGE_DATA (new_type)->high.kind = RANGE_BOUND_KIND_CONSTANT;
+	  break;
+	case RANGE_BOUND_KIND_DWARF_LOCLIST:
+	  {
+	    CORE_ADDR addr;
+
+	    /* `struct dwarf2_loclist_baton' is too bound to its objfile so
+	       it is expected to be made constant by CHECK_TYPEDEF.
+	       TYPE_NOT_ALLOCATED and TYPE_NOT_ASSOCIATED are not valid for TYPE.
+	       */
+	    if (! TYPE_NOT_ALLOCATED (new_type)
+	        && ! TYPE_NOT_ASSOCIATED (new_type) && has_stack_frames ()
+	        && dwarf_loclist_baton_eval
+		      (TYPE_RANGE_DATA (new_type)->high.u.dwarf_loclist.loclist,
+		       TYPE_RANGE_DATA (new_type)->high.u.dwarf_loclist.type,
+		       &addr))
+	      TYPE_HIGH_BOUND (new_type) = addr;
+	    else
+	      {
+		TYPE_HIGH_BOUND (new_type) = TYPE_LOW_BOUND (new_type) - 1;
+		TYPE_HIGH_BOUND_UNDEFINED (new_type) = 1;
+	      }
+	    TYPE_RANGE_DATA (new_type)->high.kind = RANGE_BOUND_KIND_CONSTANT;
+	  }
+	  break;
+	}
+
+      switch (TYPE_RANGE_DATA (new_type)->byte_stride.kind)
+	{
+	case RANGE_BOUND_KIND_CONSTANT:
+	  break;
+	case RANGE_BOUND_KIND_DWARF_BLOCK:
+	  /* `struct dwarf2_locexpr_baton' is too bound to its objfile so
+	     it is expected to be made constant by CHECK_TYPEDEF.
+	     TYPE_NOT_ALLOCATED and TYPE_NOT_ASSOCIATED are not valid for TYPE.
+	     */
+	  if (TYPE_NOT_ALLOCATED (new_type) || TYPE_NOT_ASSOCIATED (new_type)
+	      || ! has_stack_frames ())
+	    TYPE_BYTE_STRIDE (new_type) = 0;
+	  else
+	    TYPE_BYTE_STRIDE (new_type) = dwarf_locexpr_baton_eval
+			(TYPE_RANGE_DATA (new_type)->byte_stride.u.dwarf_block);
+	  TYPE_RANGE_DATA (new_type)->byte_stride.kind
+	    = RANGE_BOUND_KIND_CONSTANT;
+	  break;
+	case RANGE_BOUND_KIND_DWARF_LOCLIST:
+	  {
+	    CORE_ADDR addr = 0;
+
+	    /* `struct dwarf2_loclist_baton' is too bound to its objfile so
+	       it is expected to be made constant by CHECK_TYPEDEF.
+	       TYPE_NOT_ALLOCATED and TYPE_NOT_ASSOCIATED are not valid for TYPE.
+	       */
+	    if (! TYPE_NOT_ALLOCATED (new_type)
+		&& ! TYPE_NOT_ASSOCIATED (new_type) && has_stack_frames ())
+	      dwarf_loclist_baton_eval
+	       (TYPE_RANGE_DATA (new_type)->byte_stride.u.dwarf_loclist.loclist,
+		TYPE_RANGE_DATA (new_type)->byte_stride.u.dwarf_loclist.type,
+		&addr);
+	    TYPE_BYTE_STRIDE (new_type) = addr;
+	    TYPE_RANGE_DATA (new_type)->byte_stride.kind
+	      = RANGE_BOUND_KIND_CONSTANT;
+	  }
+	  break;
+	}
+
+      /* Convert TYPE_RANGE_HIGH_BOUND_IS_COUNT into a regular bound.  */
+      if (TYPE_RANGE_HIGH_BOUND_IS_COUNT (new_type))
+	{
+	  TYPE_HIGH_BOUND (new_type) = TYPE_LOW_BOUND (new_type)
+				       + TYPE_HIGH_BOUND (new_type) - 1;
+	  TYPE_RANGE_HIGH_BOUND_IS_COUNT (new_type) = 0;
+	}
     }
 
   /* Copy pointers to other types.  */
   if (TYPE_TARGET_TYPE (type))
     TYPE_TARGET_TYPE (new_type) = 
-      copy_type_recursive (objfile, 
-			   TYPE_TARGET_TYPE (type),
-			   copied_types);
+      copy_type_recursive_1 (objfile, 
+			     TYPE_TARGET_TYPE (type),
+			     copied_types);
   if (TYPE_VPTR_BASETYPE (type))
     TYPE_VPTR_BASETYPE (new_type) = 
-      copy_type_recursive (objfile,
-			   TYPE_VPTR_BASETYPE (type),
-			   copied_types);
+      copy_type_recursive_1 (objfile,
+			     TYPE_VPTR_BASETYPE (type),
+			     copied_types);
   /* Maybe copy the type_specific bits.
 
      NOTE drow/2005-12-09: We do not copy the C++-specific bits like
@@ -3130,6 +3496,17 @@ copy_type_recursive (struct objfile *objfile,
   return new_type;
 }
 
+/* Recursively copy (deep copy) TYPE.  Return a new type allocated using
+   malloc, a saved type if we have already visited TYPE (using COPIED_TYPES),
+   or TYPE if it is not associated with OBJFILE.  */
+
+struct type *
+copy_type_recursive (struct type *type,
+		     htab_t copied_types)
+{
+  return copy_type_recursive_1 (TYPE_OBJFILE (type), type, copied_types);
+}
+
 /* Make a copy of the given TYPE, except that the pointer & reference
    types are not preserved.
    
@@ -3152,6 +3529,211 @@ copy_type (const struct type *type)
   return new_type;
 }
 
+/* Callback type for main_type_crawl.  */
+typedef int (*main_type_crawl_iter) (struct type *type, void *data);
+
+#if 0
+
+/* Allocate a hash table which is used when freeing a struct type.  */
+
+static htab_t
+create_deleted_types_hash (void)
+{
+  return htab_create (1, htab_hash_pointer, htab_eq_pointer, NULL);
+}
+
+#endif
+
+/* Iterate all main_type structures reachable through any `struct type *' from
+   TYPE.  ITER will be called only for one type of each main_type, use
+   TYPE_CHAIN traversal to find all the type instances.  ITER is being called
+   for each main_type found.  ITER returns non-zero if main_type_crawl should
+   depth-first enter the specific type.  ITER must provide some detection for
+   reentering the same main_type as this function would otherwise endlessly
+   loop.  */
+
+static void
+main_type_crawl (struct type *type, main_type_crawl_iter iter, void *data)
+{
+  struct type *type_iter;
+  int i;
+
+  if (!type)
+    return;
+
+  gdb_assert (TYPE_OBJFILE (type) == NULL);
+
+  /* `struct cplus_struct_type' handling is unsupported by this function.  */
+  gdb_assert ((TYPE_CODE (type) != TYPE_CODE_STRUCT
+	       && TYPE_CODE (type) != TYPE_CODE_UNION)
+	      || !HAVE_CPLUS_STRUCT (type));
+
+  if (!(*iter) (type, data))
+    return;
+
+  /* Iterate all the type instances of this main_type.  */
+  type_iter = type;
+  do
+    {
+      gdb_assert (TYPE_MAIN_TYPE (type_iter) == TYPE_MAIN_TYPE (type));
+
+      main_type_crawl (TYPE_POINTER_TYPE (type), iter, data);
+      main_type_crawl (TYPE_REFERENCE_TYPE (type), iter, data);
+
+      type_iter = TYPE_CHAIN (type_iter);
+    }
+  while (type_iter != type);
+
+  for (i = 0; i < TYPE_NFIELDS (type); i++)
+    main_type_crawl (TYPE_FIELD_TYPE (type, i), iter, data);
+
+  main_type_crawl (TYPE_TARGET_TYPE (type), iter, data);
+  main_type_crawl (TYPE_VPTR_BASETYPE (type), iter, data);
+}
+
+/* A helper for delete_type which deletes a main_type and the things to which
+   it refers.  TYPE is a type whose main_type we wish to destroy.  */
+
+static void
+delete_main_type (struct type *type)
+{
+  int i;
+
+  gdb_assert (TYPE_DISCARDABLE (type));
+  gdb_assert (TYPE_OBJFILE (type) == NULL);
+
+  xfree (TYPE_NAME (type));
+  xfree (TYPE_TAG_NAME (type));
+
+  for (i = 0; i < TYPE_NFIELDS (type); ++i)
+    {
+      xfree (TYPE_FIELD_NAME (type, i));
+
+      if (TYPE_FIELD_LOC_KIND (type, i) == FIELD_LOC_KIND_PHYSNAME)
+	xfree (TYPE_FIELD_STATIC_PHYSNAME (type, i));
+    }
+  xfree (TYPE_FIELDS (type));
+
+  gdb_assert (!HAVE_CPLUS_STRUCT (type));
+
+  xfree (TYPE_MAIN_TYPE (type));
+}
+
+/* Delete all the instances on TYPE_CHAIN of TYPE, including their referenced
+   main_type.  TYPE must be a reclaimable type - neither permanent nor objfile
+   associated.  */
+
+static void
+delete_type_chain (struct type *type)
+{
+  struct type *type_iter, *type_iter_to_free;
+
+  gdb_assert (TYPE_DISCARDABLE (type));
+  gdb_assert (TYPE_OBJFILE (type) == NULL);
+
+  delete_main_type (type);
+
+  type_iter = type;
+  do
+    {
+      type_iter_to_free = type_iter;
+      type_iter = TYPE_CHAIN (type_iter);
+      xfree (type_iter_to_free);
+    }
+  while (type_iter != type);
+}
+
+/* Hash function for type_discardable_table.  */
+
+static hashval_t
+type_discardable_hash (const void *p)
+{
+  const struct type *type = p;
+
+  return htab_hash_pointer (TYPE_MAIN_TYPE (type));
+}
+
+/* Equality function for type_discardable_table.  */
+
+static int
+type_discardable_equal (const void *a, const void *b)
+{
+  const struct type *left = a;
+  const struct type *right = b;
+
+  return TYPE_MAIN_TYPE (left) == TYPE_MAIN_TYPE (right);
+}
+
+/* A helper for type_mark_used.  */
+
+static int
+type_mark_used_crawl (struct type *type, void *unused)
+{
+  if (!TYPE_DISCARDABLE (type))
+    return 0;
+
+  if (TYPE_DISCARDABLE_AGE (type) == type_discardable_age_current)
+    return 0;
+
+  TYPE_DISCARDABLE_AGE (type) = type_discardable_age_current;
+
+  /* Continue the traversal.  */
+  return 1;
+}
+
+/* Mark TYPE and its connected types as used in this free_all_types pass.  */
+
+void
+type_mark_used (struct type *type)
+{
+  if (type == NULL)
+    return;
+
+  if (!TYPE_DISCARDABLE (type))
+    return;
+
+  main_type_crawl (type, type_mark_used_crawl, NULL);
+}
+
+/* A traverse callback for type_discardable_table which removes any
+   type_discardable whose reference count is now zero (unused link).  */
+
+static int
+type_discardable_remove (void **slot, void *unused)
+{
+  struct type *type = *slot;
+
+  gdb_assert (TYPE_DISCARDABLE (type));
+
+  if (TYPE_DISCARDABLE_AGE (type) != type_discardable_age_current)
+    {
+      delete_type_chain (type);
+
+      htab_clear_slot (type_discardable_table, slot);
+    }
+
+  return 1;
+}
+
+/* Free all the reclaimable types that have been allocated and that have
+   currently zero reference counter.
+
+   This function is called after each command, successful or not.  Use this
+   cleanup only in the GDB idle state as GDB only marks those types used by
+   globally tracked objects (with no autovariable references tracking).  */
+
+void
+free_all_types (void)
+{
+  /* Mark a new pass.  As GDB checks all the entries were visited after each
+     pass there cannot be any stale entries already containing the changed
+     value.  */
+  type_discardable_age_current ^= 1;
+
+  observer_notify_mark_used ();
+
+  htab_traverse (type_discardable_table, type_discardable_remove, NULL);
+}
 
 /* Helper functions to initialize architecture-specific types.  */
 
@@ -3475,6 +4057,8 @@ gdbtypes_post_init (struct gdbarch *gdbarch)
     = lookup_pointer_type (builtin_type->builtin_void);
   builtin_type->builtin_func_ptr
     = lookup_pointer_type (lookup_function_type (builtin_type->builtin_void));
+  builtin_type->builtin_func_func
+    = lookup_function_type (builtin_type->builtin_func_ptr);
 
   /* This type represents a GDB internal function.  */
   builtin_type->internal_fn
@@ -3588,6 +4172,11 @@ objfile_type (struct objfile *objfile)
 		 "<text variable, no debug info>", objfile);
   TYPE_TARGET_TYPE (objfile_type->nodebug_text_symbol)
     = objfile_type->builtin_int;
+  objfile_type->nodebug_text_gnu_ifunc_symbol
+    = init_type (TYPE_CODE_FUNC, 1, TYPE_FLAG_GNU_IFUNC,
+		 "<text gnu-ifunc variable, no debug info>", objfile);
+  TYPE_TARGET_TYPE (objfile_type->nodebug_text_gnu_ifunc_symbol)
+    = objfile_type->nodebug_text_symbol;
   objfile_type->nodebug_data_symbol
     = init_type (TYPE_CODE_INT,
 		 gdbarch_int_bit (gdbarch) / HOST_CHAR_BIT, 0,
@@ -3642,6 +4231,11 @@ void
 _initialize_gdbtypes (void)
 {
   gdbtypes_data = gdbarch_data_register_post_init (gdbtypes_post_init);
+
+  type_discardable_table = htab_create_alloc (20, type_discardable_hash,
+					     type_discardable_equal, NULL,
+					     xcalloc, xfree);
+
   objfile_type_data = register_objfile_data ();
 
   add_setshow_zinteger_cmd ("overload", no_class, &overload_debug, _("\
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 643fa03..efe5512 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -138,6 +138,8 @@ enum type_code
 
     TYPE_CODE_DECFLOAT,		/* Decimal floating point.  */
 
+    TYPE_CODE_MODULE,		/* Fortran module.  */
+
     /* Internal function type.  */
     TYPE_CODE_INTERNAL_FUNCTION
   };
@@ -171,6 +173,7 @@ enum type_flag_value
   TYPE_FLAG_FIXED_INSTANCE = (1 << 15),
   TYPE_FLAG_STUB_SUPPORTED = (1 << 16),
   TYPE_FLAG_NOTTEXT = (1 << 17),
+  TYPE_FLAG_GNU_IFUNC = (1 << 18),
 
   /* Used for error-checking.  */
   TYPE_FLAG_MIN = TYPE_FLAG_UNSIGNED
@@ -214,6 +217,11 @@ enum type_instance_flag_value
 
 #define TYPE_TARGET_STUB(t)	(TYPE_MAIN_TYPE (t)->flag_target_stub)
 
+/* Type needs to be evaluated on each CHECK_TYPEDEF and its results must not be
+   sticky.  */
+
+#define TYPE_DYNAMIC(t)		(TYPE_MAIN_TYPE (t)->flag_dynamic)
+
 /* Static type.  If this is set, the corresponding type had 
  * a static modifier.
  * Note: This may be unnecessary, since static data members
@@ -271,6 +279,12 @@ enum type_instance_flag_value
 
 #define TYPE_NOTTEXT(t)		(TYPE_MAIN_TYPE (t)->flag_nottext)
 
+/* Currently used only for TYPE_CODE_FUNC where specifies the real function
+   address is returned by this function call.  TYPE_TARGET_TYPE determines the
+   final returned function type to be presented to user.  */
+
+#define TYPE_GNU_IFUNC(t)	(TYPE_MAIN_TYPE (t)->flag_gnu_ifunc)
+
 /* Type owner.  If TYPE_OBJFILE_OWNED is true, the type is owned by
    the objfile retrieved as TYPE_OBJFILE.  Otherweise, the type is
    owned by an architecture; TYPE_OBJFILE is NULL in this case.  */
@@ -285,6 +299,48 @@ enum type_instance_flag_value
 
 #define TYPE_DECLARED_CLASS(t) (TYPE_MAIN_TYPE (t)->flag_declared_class)
 
+/* Define this type as being reclaimable during free_all_types.  Type is
+   required to be have TYPE_OBJFILE set to NULL.  Setting this flag requires
+   initializing TYPE_DISCARDABLE_AGE, see alloc_type_discardable.  */
+
+#define TYPE_DISCARDABLE(t)	(TYPE_MAIN_TYPE (t)->flag_discardable)
+
+/* Marker this type has been visited by the type_mark_used by this
+   mark-and-sweep types garbage collecting pass.  Current pass is represented
+   by TYPE_DISCARDABLE_AGE_CURRENT.  */
+
+#define TYPE_DISCARDABLE_AGE(t)	(TYPE_MAIN_TYPE (t)->flag_discardable_age)
+
+/* Is HIGH_BOUND a low-bound relative count (1) or the high bound itself (0)?  */
+
+#define TYPE_RANGE_HIGH_BOUND_IS_COUNT(range_type) \
+  (TYPE_MAIN_TYPE (range_type)->flag_range_high_bound_is_count)
+
+/* Not allocated.  TYPE_ALLOCATED(t) must be NULL in such case.  If this flag
+   is unset and TYPE_ALLOCATED(t) is NULL then the type is allocated.  If this
+   flag is unset and TYPE_ALLOCATED(t) is not NULL then its DWARF block
+   determines the actual allocation state.  */
+
+#define TYPE_NOT_ALLOCATED(t)	(TYPE_MAIN_TYPE (t)->flag_not_allocated)
+
+/* Not associated.  TYPE_ASSOCIATED(t) must be NULL in such case.  If this flag
+   is unset and TYPE_ASSOCIATED(t) is NULL then the type is associated.  If
+   this flag is unset and TYPE_ASSOCIATED(t) is not NULL then its DWARF block
+   determines the actual association state.  */
+
+#define TYPE_NOT_ASSOCIATED(t)	(TYPE_MAIN_TYPE (t)->flag_not_associated)
+
+/* Address of the actual data as for DW_AT_data_location.  Its dwarf block must
+   not be evaluated unless both TYPE_NOT_ALLOCATED and TYPE_NOT_ASSOCIATED are
+   false.  If TYPE_DATA_LOCATION_IS_ADDR set then TYPE_DATA_LOCATION_ADDR value
+   is the actual data address value.  If unset and
+   TYPE_DATA_LOCATION_DWARF_BLOCK is NULL then the value is the normal
+   value_raw_address.  If unset and TYPE_DATA_LOCATION_DWARF_BLOCK is not NULL
+   then its DWARF block determines the actual data address.  */
+
+#define TYPE_DATA_LOCATION_IS_ADDR(t) \
+  (TYPE_MAIN_TYPE (t)->flag_data_location_is_addr)
+
 /* Constant type.  If this is set, the corresponding type has a
  * const modifier.
  */
@@ -342,8 +398,7 @@ enum field_loc_kind
   {
     FIELD_LOC_KIND_BITPOS,	/* bitpos */
     FIELD_LOC_KIND_PHYSADDR,	/* physaddr */
-    FIELD_LOC_KIND_PHYSNAME,	/* physname */
-    FIELD_LOC_KIND_DWARF_BLOCK	/* dwarf_block */
+    FIELD_LOC_KIND_PHYSNAME	/* physname */
   };
 
 /* A discriminant to determine which field in the main_type.type_specific
@@ -390,11 +445,19 @@ struct main_type
   unsigned int flag_vector : 1;
   unsigned int flag_stub_supported : 1;
   unsigned int flag_nottext : 1;
+  unsigned int flag_gnu_ifunc : 1;
   unsigned int flag_fixed_instance : 1;
   unsigned int flag_objfile_owned : 1;
   /* True if this type was declared with "class" rather than
      "struct".  */
   unsigned int flag_declared_class : 1;
+  unsigned int flag_discardable : 1;
+  unsigned int flag_discardable_age : 1;
+  unsigned int flag_dynamic : 1;
+  unsigned int flag_range_high_bound_is_count : 1;
+  unsigned int flag_not_allocated : 1;
+  unsigned int flag_not_associated : 1;
+  unsigned int flag_data_location_is_addr : 1;
 
   /* A discriminant telling us which field of the type_specific union
      is being used for this type, if any.  */
@@ -465,6 +528,20 @@ struct main_type
 
   struct type *target_type;
 
+  /* For DW_AT_data_location.  */
+  union
+    {
+      struct dwarf2_locexpr_baton *dwarf_block;
+      CORE_ADDR addr;
+    }
+  data_location;
+
+  /* For DW_AT_allocated.  */
+  struct dwarf2_locexpr_baton *allocated;
+
+  /* For DW_AT_associated.  */
+  struct dwarf2_locexpr_baton *associated;
+
   /* For structure and union types, a description of each field.
      For set and pascal array types, there is one "field",
      whose type is the domain type of the set or array.
@@ -501,12 +578,6 @@ struct main_type
 
 	CORE_ADDR physaddr;
 	char *physname;
-
-	/* The field location can be computed by evaluating the following DWARF
-	   block.  This can be used in Fortran variable-length arrays, for
-	   instance.  */
-
-	struct dwarf2_locexpr_baton *dwarf_block;
       }
       loc;
 
@@ -544,13 +615,34 @@ struct main_type
 
     struct range_bounds
     {
+      struct
+	{
+	  union
+	    {
+	      LONGEST constant;
+	      struct dwarf2_locexpr_baton *dwarf_block;
+	      struct
+		{
+		  struct dwarf2_loclist_baton *loclist;
+		  struct type *type;
+		}
+	      dwarf_loclist;
+	    }
+	  u;
+	  enum range_bound_kind
+	    {
+	      RANGE_BOUND_KIND_CONSTANT,
+	      RANGE_BOUND_KIND_DWARF_BLOCK,
+	      RANGE_BOUND_KIND_DWARF_LOCLIST
+	    }
+	  kind;
+	}
       /* Low bound of range. */
-
-      LONGEST low;
-
+      low,
       /* High bound of range. */
-
-      LONGEST high;
+      high,
+      /* Byte stride of range. */
+      byte_stride;
 
       /* Flags indicating whether the values of low and high are
          valid.  When true, the respective range value is
@@ -602,6 +694,9 @@ struct main_type
        supporting multiple ABIs.  Right now this is only fetched from
        the Dwarf-2 DW_AT_calling_convention attribute.  */
     unsigned calling_convention;
+
+    /* For TYPE_CODE_MODULE, the list of symbols contained in the module.  */
+    struct block *module_block;
   } type_specific;
 };
 
@@ -838,13 +933,6 @@ struct cplus_struct_type
     int is_dynamic : 2;
   };
 
-/* Struct used in computing virtual base list */
-struct vbase
-  {
-    struct type *vbasetype;	/* pointer to virtual base */
-    struct vbase *next;		/* next in chain */
-  };
-
 /* Struct used for ranking a function for overload resolution */
 struct badness_vector
   {
@@ -899,9 +987,9 @@ extern void allocate_gnat_aux_type (struct type *);
 #define TYPE_POINTER_TYPE(thistype) (thistype)->pointer_type
 #define TYPE_REFERENCE_TYPE(thistype) (thistype)->reference_type
 #define TYPE_CHAIN(thistype) (thistype)->chain
-/* Note that if thistype is a TYPEDEF type, you have to call check_typedef.
-   But check_typedef does set the TYPE_LENGTH of the TYPEDEF type,
-   so you only have to call check_typedef once.  Since allocate_value
+/* Note that if thistype is a TYPEDEF, ARRAY or STRING type, you have to call
+   check_typedef.  But check_typedef does set the TYPE_LENGTH of the TYPEDEF
+   type, so you only have to call check_typedef once.  Since allocate_value
    calls check_typedef, TYPE_LENGTH (VALUE_TYPE (X)) is safe.  */
 #define TYPE_LENGTH(thistype) (thistype)->length
 /* Note that TYPE_CODE can be TYPE_CODE_TYPEDEF, so if you want the real
@@ -910,11 +998,16 @@ extern void allocate_gnat_aux_type (struct type *);
 #define TYPE_NFIELDS(thistype) TYPE_MAIN_TYPE(thistype)->nfields
 #define TYPE_FIELDS(thistype) TYPE_MAIN_TYPE(thistype)->flds_bnds.fields
 #define TYPE_TEMPLATE_ARGS(thistype) TYPE_CPLUS_SPECIFIC(thistype)->template_args
+#define TYPE_DATA_LOCATION_DWARF_BLOCK(thistype) TYPE_MAIN_TYPE (thistype)->data_location.dwarf_block
+#define TYPE_DATA_LOCATION_ADDR(thistype) TYPE_MAIN_TYPE (thistype)->data_location.addr
+#define TYPE_ALLOCATED(thistype) TYPE_MAIN_TYPE (thistype)->allocated
+#define TYPE_ASSOCIATED(thistype) TYPE_MAIN_TYPE (thistype)->associated
 
 #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.u.constant
+#define TYPE_HIGH_BOUND(range_type) TYPE_RANGE_DATA(range_type)->high.u.constant
+#define TYPE_BYTE_STRIDE(range_type) TYPE_RANGE_DATA(range_type)->byte_stride.u.constant
 #define TYPE_LOW_BOUND_UNDEFINED(range_type) \
    TYPE_RANGE_DATA(range_type)->low_undefined
 #define TYPE_HIGH_BOUND_UNDEFINED(range_type) \
@@ -931,7 +1024,14 @@ extern void allocate_gnat_aux_type (struct type *);
    (TYPE_HIGH_BOUND(TYPE_INDEX_TYPE((arraytype))))
 
 #define TYPE_ARRAY_LOWER_BOUND_VALUE(arraytype) \
-   (TYPE_LOW_BOUND(TYPE_INDEX_TYPE((arraytype))))
+  TYPE_LOW_BOUND (TYPE_INDEX_TYPE (arraytype))
+
+/* TYPE_BYTE_STRIDE (TYPE_INDEX_TYPE (arraytype)) with a fallback to the
+   element size if no specific stride value is known.  */
+#define TYPE_ARRAY_BYTE_STRIDE_VALUE(arraytype)		\
+  (TYPE_BYTE_STRIDE (TYPE_INDEX_TYPE (arraytype)) == 0	\
+   ? TYPE_LENGTH (TYPE_TARGET_TYPE (arraytype))		\
+   : TYPE_BYTE_STRIDE (TYPE_INDEX_TYPE (arraytype)))
 
 /* C++ */
 
@@ -959,6 +1059,7 @@ extern void allocate_gnat_aux_type (struct type *);
 #define TYPE_GNAT_SPECIFIC(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.gnat_stuff
 #define TYPE_DESCRIPTIVE_TYPE(thistype) TYPE_GNAT_SPECIFIC(thistype)->descriptive_type
 #define TYPE_CALLING_CONVENTION(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.calling_convention
+#define TYPE_MODULE_BLOCK(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.module_block
 #define TYPE_BASECLASS(thistype,index) TYPE_FIELD_TYPE(thistype, index)
 #define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses
 #define TYPE_BASECLASS_NAME(thistype,index) TYPE_FIELD_NAME(thistype, index)
@@ -977,7 +1078,6 @@ extern void allocate_gnat_aux_type (struct type *);
 #define FIELD_BITPOS(thisfld) ((thisfld).loc.bitpos)
 #define FIELD_STATIC_PHYSNAME(thisfld) ((thisfld).loc.physname)
 #define FIELD_STATIC_PHYSADDR(thisfld) ((thisfld).loc.physaddr)
-#define FIELD_DWARF_BLOCK(thisfld) ((thisfld).loc.dwarf_block)
 #define SET_FIELD_BITPOS(thisfld, bitpos)			\
   (FIELD_LOC_KIND (thisfld) = FIELD_LOC_KIND_BITPOS,		\
    FIELD_BITPOS (thisfld) = (bitpos))
@@ -987,9 +1087,6 @@ extern void allocate_gnat_aux_type (struct type *);
 #define SET_FIELD_PHYSADDR(thisfld, addr)			\
   (FIELD_LOC_KIND (thisfld) = FIELD_LOC_KIND_PHYSADDR,		\
    FIELD_STATIC_PHYSADDR (thisfld) = (addr))
-#define SET_FIELD_DWARF_BLOCK(thisfld, addr)			\
-  (FIELD_LOC_KIND (thisfld) = FIELD_LOC_KIND_DWARF_BLOCK,	\
-   FIELD_DWARF_BLOCK (thisfld) = (addr))
 #define FIELD_ARTIFICIAL(thisfld) ((thisfld).artificial)
 #define FIELD_BITSIZE(thisfld) ((thisfld).bitsize)
 
@@ -1000,7 +1097,6 @@ extern void allocate_gnat_aux_type (struct type *);
 #define TYPE_FIELD_BITPOS(thistype, n) FIELD_BITPOS (TYPE_FIELD (thistype, n))
 #define TYPE_FIELD_STATIC_PHYSNAME(thistype, n) FIELD_STATIC_PHYSNAME (TYPE_FIELD (thistype, n))
 #define TYPE_FIELD_STATIC_PHYSADDR(thistype, n) FIELD_STATIC_PHYSADDR (TYPE_FIELD (thistype, n))
-#define TYPE_FIELD_DWARF_BLOCK(thistype, n) FIELD_DWARF_BLOCK (TYPE_FIELD (thistype, n))
 #define TYPE_FIELD_ARTIFICIAL(thistype, n) FIELD_ARTIFICIAL(TYPE_FIELD(thistype,n))
 #define TYPE_FIELD_BITSIZE(thistype, n) FIELD_BITSIZE(TYPE_FIELD(thistype,n))
 #define TYPE_FIELD_PACKED(thistype, n) (FIELD_BITSIZE(TYPE_FIELD(thistype,n))!=0)
@@ -1139,6 +1235,10 @@ struct builtin_type
      (*) () can server as a generic function pointer.  */
   struct type *builtin_func_ptr;
 
+  /* `function returning pointer to function (returning void)' type.
+     The final void return type is not significant for it.  */
+  struct type *builtin_func_func;
+
 
   /* Special-purpose types.  */
 
@@ -1179,6 +1279,7 @@ struct objfile_type
 
   /* Types used for symbols with no debug information.  */
   struct type *nodebug_text_symbol;
+  struct type *nodebug_text_gnu_ifunc_symbol;
   struct type *nodebug_data_symbol;
   struct type *nodebug_unknown_symbol;
   struct type *nodebug_tls_symbol;
@@ -1333,6 +1434,18 @@ extern struct type *create_array_type (struct type *, struct type *,
 				       struct type *);
 extern struct type *lookup_array_range_type (struct type *, int, int);
 
+extern CORE_ADDR type_range_any_field_internal (struct type *range_type,
+						int fieldno);
+
+extern int type_range_high_bound_internal (struct type *range_type);
+
+extern int type_range_count_bound_internal (struct type *range_type);
+
+extern CORE_ADDR type_range_byte_stride_internal (struct type *range_type,
+						  struct type *element_type);
+
+extern void finalize_type (struct type *type);
+
 extern struct type *create_string_type (struct type *, struct type *,
 					struct type *);
 extern struct type *lookup_string_range_type (struct type *, int, int);
@@ -1375,6 +1488,8 @@ extern int is_public_ancestor (struct type *, struct type *);
 
 extern int is_unique_ancestor (struct type *, struct value *);
 
+extern void type_mark_used (struct type *type);
+
 /* Overload resolution */
 
 #define LENGTH_MATCH(bv) ((bv)->rank[0])
@@ -1437,10 +1552,11 @@ extern void maintenance_print_type (char *, int);
 
 extern htab_t create_copied_types_hash (struct objfile *objfile);
 
-extern struct type *copy_type_recursive (struct objfile *objfile,
-					 struct type *type,
+extern struct type *copy_type_recursive (struct type *type,
 					 htab_t copied_types);
 
 extern struct type *copy_type (const struct type *type);
 
+extern void free_all_types (void);
+
 #endif /* GDBTYPES_H */
diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c
index 5321401..b1882a2 100644
--- a/gdb/gnu-v3-abi.c
+++ b/gdb/gnu-v3-abi.c
@@ -26,6 +26,7 @@
 #include "demangle.h"
 #include "objfiles.h"
 #include "valprint.h"
+#include "c-lang.h"
 
 #include "gdb_assert.h"
 #include "gdb_string.h"
@@ -456,10 +457,8 @@ gnuv3_find_method_in (struct type *domain, CORE_ADDR voffset,
 		      LONGEST adjustment)
 {
   int i;
-  const char *physname;
 
   /* Search this class first.  */
-  physname = NULL;
   if (adjustment == 0)
     {
       int len;
@@ -587,15 +586,24 @@ gnuv3_print_method_ptr (const gdb_byte *contents,
 	{
 	  char *demangled_name = cplus_demangle (physname,
 						 DMGL_ANSI | DMGL_PARAMS);
-	  if (demangled_name != NULL)
+	  fprintf_filtered (stream, "&virtual ");
+	  if (demangled_name == NULL)
+	    fputs_filtered (physname, stream);
+	  else
 	    {
-	      fprintf_filtered (stream, "&virtual ");
 	      fputs_filtered (demangled_name, stream);
 	      xfree (demangled_name);
-	      return;
 	    }
+	  return;
 	}
     }
+  else if (ptr_value != 0)
+    {
+      /* Found a non-virtual function: print out the type.  */
+      fputs_filtered ("(", stream);
+      c_print_type (type, "", stream, -1, 0);
+      fputs_filtered (") ", stream);
+    }
 
   /* We didn't find it; print the raw data.  */
   if (vbit)
diff --git a/gdb/hppa-linux-tdep.c b/gdb/hppa-linux-tdep.c
index ebfc2f5..e40105b 100644
--- a/gdb/hppa-linux-tdep.c
+++ b/gdb/hppa-linux-tdep.c
@@ -32,6 +32,7 @@
 #include "regset.h"
 #include "regcache.h"
 #include "hppa-tdep.h"
+#include "linux-tdep.h"
 
 #include "elf/common.h"
 
@@ -513,7 +514,21 @@ hppa_linux_regset_from_core_section (struct gdbarch *gdbarch,
 
   return NULL;
 }
-
+
+static CORE_ADDR
+hppa32_linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
+					 CORE_ADDR addr,
+					 struct target_ops *targ)
+{
+  CORE_ADDR pc = hppa32_convert_from_func_ptr_addr (gdbarch, addr, targ);
+  CORE_ADDR resolved;
+
+  resolved = linux_convert_from_func_and_ptr (gdbarch, addr, pc);
+  if (resolved != pc)
+    pc = hppa32_convert_from_func_ptr_addr (gdbarch, resolved, targ);
+
+  return pc;
+}
 
 /* Forward declarations.  */
 extern initialize_file_ftype _initialize_hppa_linux_tdep;
@@ -555,6 +570,10 @@ hppa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* Enable TLS support.  */
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
+
+  if (tdep->bytes_per_address == 4)
+    set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+				       hppa32_linux_convert_from_func_ptr_addr);
 }
 
 void
diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c
index a0665ef..347fbe4 100644
--- a/gdb/hppa-tdep.c
+++ b/gdb/hppa-tdep.c
@@ -1247,7 +1247,7 @@ hppa64_return_value (struct gdbarch *gdbarch, struct type *func_type,
 }
 
 
-static CORE_ADDR
+CORE_ADDR
 hppa32_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr,
 				   struct target_ops *targ)
 {
diff --git a/gdb/hppa-tdep.h b/gdb/hppa-tdep.h
index e2d8752..c626637 100644
--- a/gdb/hppa-tdep.h
+++ b/gdb/hppa-tdep.h
@@ -246,4 +246,8 @@ extern int hppa_in_solib_call_trampoline (struct gdbarch *gdbarch,
 					  CORE_ADDR pc, char *name);
 extern CORE_ADDR hppa_skip_trampoline_code (struct frame_info *, CORE_ADDR pc);
 
+extern CORE_ADDR hppa32_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
+						    CORE_ADDR addr,
+						    struct target_ops *targ);
+
 #endif  /* hppa-tdep.h */
diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c
index ff837f2..1710487 100644
--- a/gdb/i386-linux-nat.c
+++ b/gdb/i386-linux-nat.c
@@ -696,6 +696,21 @@ i386_linux_dr_unset_status (unsigned long mask)
     }
 }
 
+/* See i386_dr_low_type.detach.  Do not use wrappers i386_linux_dr_set_control
+   or i386_linux_dr_reset_addr as they would modify the register cache
+   (i386_linux_dr).  */
+
+static void
+i386_linux_dr_detach (void)
+{
+  int regnum;
+
+  i386_linux_dr_set (inferior_ptid, DR_CONTROL, 0);
+  i386_linux_dr_unset_status (~0UL);
+  for (regnum = DR_FIRSTADDR; regnum <= DR_LASTADDR; regnum++)
+    i386_linux_dr_set (inferior_ptid, regnum, 0);
+}
+
 static void
 i386_linux_new_thread (ptid_t ptid)
 {
@@ -868,6 +883,7 @@ _initialize_i386_linux_nat (void)
   i386_dr_low.reset_addr = i386_linux_dr_reset_addr;
   i386_dr_low.get_status = i386_linux_dr_get_status;
   i386_dr_low.unset_status = i386_linux_dr_unset_status;
+  i386_dr_low.detach = i386_linux_dr_detach;
   i386_set_debug_register_length (4);
 
   /* Override the default ptrace resume method.  */
diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c
index 5acd229..aec1736 100644
--- a/gdb/i386-linux-tdep.c
+++ b/gdb/i386-linux-tdep.c
@@ -798,6 +798,9 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
                                   i386_linux_get_syscall_number);
 
   set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
+
+  set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+					  linux_convert_from_func_ptr_addr);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff --git a/gdb/i386-nat.c b/gdb/i386-nat.c
index fa0cce6..42dfd1c 100644
--- a/gdb/i386-nat.c
+++ b/gdb/i386-nat.c
@@ -527,6 +527,17 @@ i386_remove_watchpoint (CORE_ADDR addr, int len, int type)
   return retval;
 }
 
+/* See target_detach_watchpoints.  */
+
+static int
+i386_detach_watchpoints (void)
+{
+  if (i386_dr_low.detach)
+    i386_dr_low.detach ();
+
+  return 0;
+}
+
 /* Return non-zero if we can watch a memory region that starts at
    address ADDR and whose length is LEN bytes.  */
 
@@ -679,6 +690,7 @@ i386_use_watchpoints (struct target_ops *t)
   t->to_stopped_data_address = i386_stopped_data_address;
   t->to_insert_watchpoint = i386_insert_watchpoint;
   t->to_remove_watchpoint = i386_remove_watchpoint;
+  t->to_detach_watchpoints = i386_detach_watchpoints;
   t->to_insert_hw_breakpoint = i386_insert_hw_breakpoint;
   t->to_remove_hw_breakpoint = i386_remove_hw_breakpoint;
 }
diff --git a/gdb/i386-nat.h b/gdb/i386-nat.h
index 7317e7d..ea914a5 100644
--- a/gdb/i386-nat.h
+++ b/gdb/i386-nat.h
@@ -62,6 +62,10 @@ extern void i386_use_watchpoints (struct target_ops *);
       unset_status             -- unset the specified bits of the debug
 				  status (DR6) register for all LWPs
 
+      detach                   -- clear all debug registers of only the
+				  INFERIOR_PTID task without affecting any
+				  register caches.
+
    Additionally, the native file should set the debug_register_length
    field to 4 or 8 depending on the number of bytes used for
    deubg registers.  */
@@ -73,6 +77,7 @@ struct i386_dr_low_type
     void (*reset_addr) (int);
     unsigned long (*get_status) (void);
     void (*unset_status) (unsigned long);
+    void (*detach) (void);
     int debug_register_length;
   };
 
diff --git a/gdb/ia64-linux-tdep.c b/gdb/ia64-linux-tdep.c
index b12f282..8ddb24a 100644
--- a/gdb/ia64-linux-tdep.c
+++ b/gdb/ia64-linux-tdep.c
@@ -26,6 +26,7 @@
 #include "osabi.h"
 #include "solib-svr4.h"
 #include "symtab.h"
+#include "linux-tdep.h"
 
 /* The sigtramp code is in a non-readable (executable-only) region
    of memory called the ``gate page''.  The addresses in question
@@ -139,6 +140,9 @@ ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* Enable TLS support.  */
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
+
+  set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+					  linux_convert_from_func_ptr_addr);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff --git a/gdb/infcall.c b/gdb/infcall.c
index e642894..6ac95cc 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -252,9 +252,17 @@ find_function_addr (struct value *function, struct type **retval_type)
       if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
 	  || TYPE_CODE (ftype) == TYPE_CODE_METHOD)
 	{
-	  funaddr = gdbarch_convert_from_func_ptr_addr (gdbarch, funaddr,
-							&current_target);
-	  value_type = TYPE_TARGET_TYPE (ftype);
+	  CORE_ADDR funaddr2;
+
+	  funaddr2 = gdbarch_convert_from_func_ptr_addr (gdbarch, funaddr,
+							 &current_target);
+
+	  /* If TYPE_GNU_IFUNC is currently not resolvable keep its type.  */
+	  if (funaddr2 != funaddr || !TYPE_GNU_IFUNC (ftype))
+	    {
+	      funaddr = funaddr2;
+	      value_type = TYPE_TARGET_TYPE (ftype);
+	    }
 	}
     }
   else if (code == TYPE_CODE_INT)
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 29cf427..0ec598e 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -808,7 +808,7 @@ nexti_command (char *count_string, int from_tty)
   step_1 (1, 1, count_string);
 }
 
-static void
+void
 delete_longjmp_breakpoint_cleanup (void *arg)
 {
   int thread = * (int *) arg;
@@ -848,10 +848,13 @@ step_1 (int skip_subroutines, int single_inst, char *count_string)
 
   if (!single_inst || skip_subroutines)		/* leave si command alone */
     {
+      struct thread_info *tp = inferior_thread ();
+
       if (in_thread_list (inferior_ptid))
  	thread = pid_to_thread_id (inferior_ptid);
 
       set_longjmp_breakpoint (thread);
+      tp->initiating_frame = get_frame_id (get_current_frame ());
 
       make_cleanup (delete_longjmp_breakpoint_cleanup, &thread);
     }
@@ -1200,6 +1203,15 @@ signal_command (char *signum_exp, int from_tty)
   proceed ((CORE_ADDR) -1, oursig, 0);
 }
 
+/* A continuation callback for until_next_command.  */
+
+static void
+until_next_continuation (void *arg)
+{
+  struct thread_info *tp = arg;
+  delete_longjmp_breakpoint (tp->num);
+}
+
 /* Proceed until we reach a different source line with pc greater than
    our current one or exit the function.  We skip calls in both cases.
 
@@ -1216,6 +1228,8 @@ until_next_command (int from_tty)
   struct symbol *func;
   struct symtab_and_line sal;
   struct thread_info *tp = inferior_thread ();
+  int thread = tp->num;
+  struct cleanup *old_chain;
 
   clear_proceed_status ();
   set_step_frame ();
@@ -1251,7 +1265,19 @@ until_next_command (int from_tty)
 
   tp->step_multi = 0;		/* Only one call to proceed */
 
+  set_longjmp_breakpoint (thread);
+  tp->initiating_frame = get_frame_id (frame);
+  old_chain = make_cleanup (delete_longjmp_breakpoint_cleanup, &thread);
+
   proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1);
+
+  if (target_can_async_p () && is_running (inferior_ptid))
+    {
+      discard_cleanups (old_chain);
+      add_continuation (tp, until_next_continuation, tp, NULL);
+    }
+  else
+    do_cleanups (old_chain);
 }
 
 static void
@@ -1428,6 +1454,7 @@ finish_command_continuation (void *arg)
   if (bs != NULL && tp->proceed_to_finish)
     observer_notify_normal_stop (bs, 1 /* print frame */);
   delete_breakpoint (a->breakpoint);
+  delete_longjmp_breakpoint (inferior_thread ()->num);
 }
 
 static void
@@ -1511,6 +1538,7 @@ finish_forward (struct symbol *function, struct frame_info *frame)
   struct breakpoint *breakpoint;
   struct cleanup *old_chain;
   struct finish_command_continuation_args *cargs;
+  int thread = tp->num;
 
   sal = find_pc_line (get_frame_pc (frame), 0);
   sal.pc = get_frame_pc (frame);
@@ -1521,6 +1549,10 @@ finish_forward (struct symbol *function, struct frame_info *frame)
 
   old_chain = make_cleanup_delete_breakpoint (breakpoint);
 
+  set_longjmp_breakpoint (thread);
+  tp->initiating_frame = get_frame_id (frame);
+  make_cleanup (delete_longjmp_breakpoint_cleanup, &thread);
+
   tp->proceed_to_finish = 1;    /* We want stop_registers, please...  */
   cargs = xmalloc (sizeof (*cargs));
 
diff --git a/gdb/inferior.h b/gdb/inferior.h
index e557d6c..d4ae1df 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -275,6 +275,8 @@ extern void interrupt_target_command (char *args, int from_tty);
 
 extern void interrupt_target_1 (int all_threads);
 
+extern void delete_longjmp_breakpoint_cleanup (void *arg);
+
 extern void detach_command (char *, int);
 
 extern void notice_new_inferior (ptid_t, int, int);
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 9a5c3a8..ed2f530 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -45,6 +45,8 @@
 #include "language.h"
 #include "solib.h"
 #include "main.h"
+#include "dictionary.h"
+#include "block.h"
 #include "gdb_assert.h"
 #include "mi/mi-common.h"
 #include "event-top.h"
@@ -2024,6 +2026,8 @@ static void insert_step_resume_breakpoint_at_sal (struct gdbarch *gdbarch,
 						  struct symtab_and_line sr_sal,
 						  struct frame_id sr_id);
 static void insert_longjmp_resume_breakpoint (struct gdbarch *, CORE_ADDR);
+static void check_exception_resume (struct execution_control_state *,
+				    struct frame_info *, struct symbol *);
 
 static void stop_stepping (struct execution_control_state *ecs);
 static void prepare_to_wait (struct execution_control_state *ecs);
@@ -2971,6 +2975,10 @@ handle_inferior_event (struct execution_control_state *ecs)
 
       stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
 
+      /* Clear WATCHPOINT_TRIGGERED values from previous stop which could
+	 confuse bpstat_stop_status and bpstat_explains_signal.  */
+      watchpoints_triggered (&ecs->ws);
+
       ecs->event_thread->stop_bpstat
 	= bpstat_stop_status (get_regcache_aspace (get_current_regcache ()),
 			      stop_pc, ecs->ptid);
@@ -3055,6 +3063,10 @@ handle_inferior_event (struct execution_control_state *ecs)
 
       stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
 
+      /* Clear WATCHPOINT_TRIGGERED values from previous stop which could
+	 confuse bpstat_stop_status and bpstat_explains_signal.  */
+      watchpoints_triggered (&ecs->ws);
+
       /* Do whatever is necessary to the parent branch of the vfork.  */
       handle_vfork_child_exec_or_exit (1);
 
@@ -3793,23 +3805,33 @@ process_event_stop_test:
 
 	ecs->event_thread->stepping_over_breakpoint = 1;
 
-	if (!gdbarch_get_longjmp_target_p (gdbarch)
-	    || !gdbarch_get_longjmp_target (gdbarch, frame, &jmp_buf_pc))
+	if (what.is_longjmp)
 	  {
-	    if (debug_infrun)
-	      fprintf_unfiltered (gdb_stdlog, "\
+	    if (!gdbarch_get_longjmp_target_p (gdbarch)
+		|| !gdbarch_get_longjmp_target (gdbarch,
+						frame, &jmp_buf_pc))
+	      {
+		if (debug_infrun)
+		  fprintf_unfiltered (gdb_stdlog, "\
 infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
-	    keep_going (ecs);
-	    return;
-	  }
+		keep_going (ecs);
+		return;
+	      }
 
-	/* We're going to replace the current step-resume breakpoint
-	   with a longjmp-resume breakpoint.  */
-	delete_step_resume_breakpoint (ecs->event_thread);
+	    /* We're going to replace the current step-resume breakpoint
+	       with a longjmp-resume breakpoint.  */
+	    delete_step_resume_breakpoint (ecs->event_thread);
 
-	/* Insert a breakpoint at resume address.  */
-	insert_longjmp_resume_breakpoint (gdbarch, jmp_buf_pc);
+	    /* Insert a breakpoint at resume address.  */
+	    insert_longjmp_resume_breakpoint (gdbarch, jmp_buf_pc);
+	  }
+	else
+	  {
+	    struct symbol *func = get_frame_function (frame);
 
+	    if (func)
+	      check_exception_resume (ecs, frame, func);
+	  }
 	keep_going (ecs);
 	return;
 
@@ -3821,6 +3843,53 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME (!gdbarch_get_longjmp_target)\n");
 	gdb_assert (ecs->event_thread->step_resume_breakpoint != NULL);
 	delete_step_resume_breakpoint (ecs->event_thread);
 
+	if (!what.is_longjmp)
+	  {
+	    /* There are several cases to consider.
+	       
+	       1. The initiating frame no longer exists.  In this case
+	       we must stop, because the exception has gone too far.
+	       
+	       2. The initiating frame exists, and is the same as the
+	       current frame.
+	       
+	       2.1. If we are stepping, defer to the stepping logic.
+	       
+	       2.2. Otherwise, we are not stepping, so we are doing a
+	       "finish" and we have reached the calling frame.  So,
+	       stop.
+	       
+	       3. The initiating frame exists and is different from
+	       the current frame.  This means the exception has been
+	       caught beneath the initiating frame, so keep going.  */
+	    struct frame_info *init_frame
+	      = frame_find_by_id (ecs->event_thread->initiating_frame);
+	    if (init_frame)
+	      {
+		struct frame_id current_id
+		  = get_frame_id (get_current_frame ());
+		if (frame_id_eq (current_id,
+				 ecs->event_thread->initiating_frame))
+		  {
+		    if (ecs->event_thread->step_range_start)
+		      {
+			/* Case 2.1.  */
+			break;
+		      }
+		    else
+		      {
+			/* Case 2.2: fall through.  */
+		      }
+		  }
+		else
+		  {
+		    /* Case 3.  */
+		    keep_going (ecs);
+		    return;
+		  }
+	      }
+	  }
+
 	ecs->event_thread->stop_step = 1;
 	print_stop_reason (END_STEPPING_RANGE, 0);
 	stop_stepping (ecs);
@@ -4840,6 +4909,96 @@ insert_longjmp_resume_breakpoint (struct gdbarch *gdbarch, CORE_ADDR pc)
     set_momentary_breakpoint_at_pc (gdbarch, pc, bp_longjmp_resume);
 }
 
+/* Insert an exception resume breakpoint.  TP is the thread throwing
+   the exception.  The block B is the block of the unwinder debug hook
+   function.  FRAME is the frame corresponding to the call to this
+   function.  SYM is the symbol of the function argument holding the
+   target PC of the exception.  */
+
+static void
+insert_exception_resume_breakpoint (struct thread_info *tp,
+				    struct block *b,
+				    struct frame_info *frame,
+				    struct symbol *sym)
+{
+  struct gdb_exception e;
+
+  /* We want to ignore errors here.  */
+  TRY_CATCH (e, RETURN_MASK_ALL)
+    {
+      struct symbol *vsym;
+      struct value *value;
+      CORE_ADDR handler;
+      struct breakpoint *bp;
+
+      vsym = lookup_symbol (SYMBOL_LINKAGE_NAME (sym), b, VAR_DOMAIN, NULL);
+      value = read_var_value (vsym, frame);
+      handler = value_as_address (value);
+
+      /* We're going to replace the current step-resume breakpoint
+	 with an exception-resume breakpoint.  */
+      delete_step_resume_breakpoint (tp);
+
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun: exception resume at %lx\n",
+			    (unsigned long) handler);
+
+      bp = set_momentary_breakpoint_at_pc (get_frame_arch (frame),
+					   handler, bp_exception_resume);
+      inferior_thread ()->step_resume_breakpoint = bp;
+    }
+}
+
+/* This is called when an exception has been intercepted.  Check to
+   see whether the exception's destination is of interest, and if so,
+   set an exception resume breakpoint there.  */
+
+static void
+check_exception_resume (struct execution_control_state *ecs,
+			struct frame_info *frame, struct symbol *func)
+{
+  struct gdb_exception e;
+
+  TRY_CATCH (e, RETURN_MASK_ALL)
+    {
+      struct block *b;
+      struct dict_iterator iter;
+      struct symbol *sym;
+      int argno = 0;
+
+      /* The exception breakpoint is a thread-specific breakpoint on
+	 the unwinder's debug hook, declared as:
+	 
+	 void _Unwind_DebugHook (void *cfa, void *handler);
+	 
+	 The CFA argument indicates the frame to which control is
+	 about to be transferred.  HANDLER is the destination PC.
+	 
+	 We ignore the CFA and set a temporary breakpoint at HANDLER.
+	 This is not extremely efficient but it avoids issues in gdb
+	 with computing the DWARF CFA, and it also works even in weird
+	 cases such as throwing an exception from inside a signal
+	 handler.  */
+
+      b = SYMBOL_BLOCK_VALUE (func);
+      ALL_BLOCK_SYMBOLS (b, iter, sym)
+	{
+	  if (!SYMBOL_IS_ARGUMENT (sym))
+	    continue;
+
+	  if (argno == 0)
+	    ++argno;
+	  else
+	    {
+	      insert_exception_resume_breakpoint (ecs->event_thread,
+						  b, frame, sym);
+	      break;
+	    }
+	}
+    }
+}
+
 static void
 stop_stepping (struct execution_control_state *ecs)
 {
diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c
index 24b6673..22ed960 100644
--- a/gdb/jv-lang.c
+++ b/gdb/jv-lang.c
@@ -1121,6 +1121,7 @@ const struct exp_descriptor exp_descriptor_java =
 {
   print_subexp_standard,
   operator_length_standard,
+  operator_check_standard,
   op_name_standard,
   dump_subexp_body_standard,
   evaluate_subexp_java
diff --git a/gdb/language.h b/gdb/language.h
index 4f78a28..e0096f5 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -258,7 +258,6 @@ struct language_defn
        variables.  */
 
     struct symbol *(*la_lookup_symbol_nonlocal) (const char *,
-						 const char *,
 						 const struct block *,
 						 const domain_enum);
 
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 75a74e2..ec4d569 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -40,6 +40,7 @@
 #include "interps.h"
 #include "mi/mi-cmds.h"
 #include "target.h"
+#include "arch-utils.h"
 
 /* We share this one with symtab.c, but it is not exported widely. */
 
@@ -50,8 +51,6 @@ extern char *operator_chars (char *, char **);
 static void initialize_defaults (struct symtab **default_symtab,
 				 int *default_line);
 
-static void set_flags (char *arg, int *is_quoted, char **paren_pointer);
-
 static struct symtabs_and_lines decode_indirect (char **argptr);
 
 static char *locate_first_half (char **argptr, int *is_quote_enclosed);
@@ -313,10 +312,7 @@ add_matching_methods (int method_counter, struct type *t,
 				   NULL, VAR_DOMAIN,
 				   language,
 				   (int *) NULL);
-      /* See PR10966.  Remove check on symbol domain and class when
-	 we stop using (bad) linkage names on constructors.  */
-      if (sym_arr[i1] && (SYMBOL_DOMAIN (sym_arr[i1]) == VAR_DOMAIN
-			  && SYMBOL_CLASS (sym_arr[i1]) == LOC_BLOCK))
+      if (sym_arr[i1])
 	i1++;
       else
 	{
@@ -631,6 +627,37 @@ See set/show multiple-symbol."));
   discard_cleanups (old_chain);
   return return_values;
 }
+
+/* A helper function for decode_line_1 and friends which skips P
+   past any method overload information at the beginning of P, e.g.,
+   "(const struct foo *)".
+
+   This function assumes that P has already been validated to contain
+   overload information, and it will assert if *P != '('.  */
+static char *
+find_method_overload_end (char *p)
+{
+  int depth = 0;
+
+  gdb_assert (*p == '(');
+
+  while (*p)
+    {
+      if (*p == '(')
+	++depth;
+      else if (*p == ')')
+	{
+	  if (--depth == 0)
+	    {
+	      ++p;
+	      break;
+	    }
+	}
+      ++p;
+    }
+
+  return p;
+}
 
 /* The parser of linespec itself. */
 
@@ -691,18 +718,17 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
   struct symtab *file_symtab = NULL;
 
   char *copy;
-  /* This is NULL if there are no parens in *ARGPTR, or a pointer to
-     the closing parenthesis if there are parens.  */
-  char *paren_pointer;
   /* This says whether or not something in *ARGPTR is quoted with
      completer_quotes (i.e. with single quotes).  */
   int is_quoted;
-  /* Is part of *ARGPTR is enclosed in double quotes?  */
+  /* Is *ARGPTR is enclosed in double quotes?  */
   int is_quote_enclosed;
   int is_objc_method = 0;
   char *saved_arg = *argptr;
   /* If IS_QUOTED, the end of the quoted bit.  */
   char *end_quote = NULL;
+  /* The "first half" of the linespec.  */
+  char *first_half;
 
   if (not_found_ptr)
     *not_found_ptr = 0;
@@ -716,12 +742,9 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
   if (**argptr == '*')
     return decode_indirect (argptr);
 
-  /* Set various flags.  'paren_pointer' is important for overload
-     checking, where we allow things like:
-        (gdb) break c::f(int)
-  */
-
-  set_flags (*argptr, &is_quoted, &paren_pointer);
+  is_quoted = (*argptr
+	       && strchr (get_gdb_completer_quote_characters (),
+			  **argptr) != NULL);
   if (is_quoted)
     end_quote = skip_quoted (*argptr);
 
@@ -734,15 +757,12 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
      will point to "". If this is a C++ name, like "A::B::foo", p will
      point to "::B::foo". Argptr is not changed by this call.  */
 
-  p = locate_first_half (argptr, &is_quote_enclosed);
+  first_half = p = locate_first_half (argptr, &is_quote_enclosed);
 
   /* Check if this is an Objective-C method (anything that starts with
      a '+' or '-' and a '[').  */
   if (is_objc_method_format (p))
-    {
-      is_objc_method = 1;
-      paren_pointer  = NULL; /* Just a category name.  Ignore it.  */
-    }
+    is_objc_method = 1;
 
   /* Check if the symbol could be an Objective-C selector.  */
 
@@ -754,9 +774,6 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
       return values;
   }
 
-  if (is_quoted)
-    *argptr = *argptr + 1;
-
   /* Does it look like there actually were two parts?  */
 
   if (p[0] == ':' || p[0] == '.')
@@ -770,67 +787,48 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
 	
       if (p[0] == '.' || p[1] == ':')
 	{
-	  if (paren_pointer == NULL)
-	    return decode_compound (argptr, funfirstline, canonical,
+	  struct symtabs_and_lines values;
+
+	  if (is_quote_enclosed)
+	    ++saved_arg;
+	  values = decode_compound (argptr, funfirstline, canonical,
 				    saved_arg, p, not_found_ptr);
-	  /* Otherwise, fall through to decode_variable below.  */
+	  if (is_quoted && **argptr == '\'')
+	    *argptr = *argptr + 1;
+	  return values;
 	}
-      else
-	{
-	  /* No, the first part is a filename; set file_symtab to be that file's
-	     symtab.  Also, move argptr past the filename.  */
 
-	  file_symtab = symtab_from_filename (argptr, p, is_quote_enclosed,
-					      not_found_ptr);
+      /* No, the first part is a filename; set file_symtab to be that file's
+	 symtab.  Also, move argptr past the filename.  */
 
-	  /* Check for single quotes on the non-filename part.  */
-	  if (!is_quoted)
-	    {
-	      is_quoted = (**argptr
-			   && strchr (get_gdb_completer_quote_characters (),
-				      **argptr) != NULL);
-	      if (is_quoted)
-		end_quote = skip_quoted (*argptr);
-	    }
-	}
-    }
-#if 0
-  /* No one really seems to know why this was added. It certainly
-     breaks the command line, though, whenever the passed
-     name is of the form ClassName::Method. This bit of code
-     singles out the class name, and if funfirstline is set (for
-     example, you are setting a breakpoint at this function),
-     you get an error. This did not occur with earlier
-     verions, so I am ifdef'ing this out. 3/29/99 */
-  else
-    {
-      /* Check if what we have till now is a symbol name */
+      file_symtab = symtab_from_filename (argptr, p, is_quote_enclosed,
+					  not_found_ptr);
 
-      /* We may be looking at a template instantiation such
-         as "foo<int>".  Check here whether we know about it,
-         instead of falling through to the code below which
-         handles ordinary function names, because that code
-         doesn't like seeing '<' and '>' in a name -- the
-         skip_quoted call doesn't go past them.  So see if we
-         can figure it out right now. */
-
-      copy = (char *) alloca (p - *argptr + 1);
-      memcpy (copy, *argptr, p - *argptr);
-      copy[p - *argptr] = '\000';
-      sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0);
-      if (sym)
+      /* Check for single quotes on the non-filename part.  */
+      if (!is_quoted)
 	{
-	  *argptr = (*p == '\'') ? p + 1 : p;
-	  return symbol_found (funfirstline, canonical, copy, sym, NULL);
+	  is_quoted = (**argptr
+		       && strchr (get_gdb_completer_quote_characters (),
+				  **argptr) != NULL);
+	  if (is_quoted)
+	    end_quote = skip_quoted (*argptr);
 	}
-      /* Otherwise fall out from here and go to file/line spec
-         processing, etc. */
     }
-#endif
 
   /* file_symtab is specified file's symtab, or 0 if no file specified.
      arg no longer contains the file name.  */
 
+  /* If the filename was quoted, we must re-check the quotation.  */
+
+  if (end_quote == first_half && *end_quote!= '\0')
+    {
+      is_quoted = (**argptr
+		   && strchr (get_gdb_completer_quote_characters (),
+			      **argptr) != NULL);
+      if (is_quoted)
+	end_quote = skip_quoted (*argptr);
+    }
+
   /* Check whether arg is all digits (and sign).  */
 
   q = *argptr;
@@ -861,10 +859,6 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
       /* allow word separators in method names for Obj-C */
       p = skip_quoted_chars (*argptr, NULL, "");
     }
-  else if (paren_pointer != NULL)
-    {
-      p = paren_pointer + 1;
-    }
   else
     {
       p = skip_quoted (*argptr);
@@ -874,6 +868,14 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
   if (*p == '<')
     p = find_template_name_end (p);
 
+  /* Keep method overload information.  */
+  if (*p == '(')
+    p = find_method_overload_end (p);
+
+  /* Make sure we keep important kewords like "const" */
+  if (strncmp (p, " const", 6) == 0)
+    p += 6;
+
   copy = (char *) alloca (p - *argptr + 1);
   memcpy (copy, *argptr, p - *argptr);
   copy[p - *argptr] = '\0';
@@ -921,10 +923,9 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
    function is passed ARGPTR as an argument, it modifies what ARGPTR
    points to; typically, it advances *ARGPTR past whatever substring
    it has just looked at.  (If it doesn't modify *ARGPTR, then the
-   function gets passed *ARGPTR instead, which is then called ARG: see
-   set_flags, for example.)  Also, functions that return a struct
-   symtabs_and_lines may modify CANONICAL, as in the description of
-   decode_line_1.
+   function gets passed *ARGPTR instead, which is then called ARG.)
+   Also, functions that return a struct symtabs_and_lines may modify
+   CANONICAL, as in the description of decode_line_1.
 
    If a function returns a struct symtabs_and_lines, then that struct
    will immediately make its way up the call chain to be returned by
@@ -951,44 +952,6 @@ initialize_defaults (struct symtab **default_symtab, int *default_line)
     }
 }
 
-static void
-set_flags (char *arg, int *is_quoted, char **paren_pointer)
-{
-  char *ii;
-  int has_if = 0;
-
-  /* 'has_if' is for the syntax:
-        (gdb) break foo if (a==b)
-  */
-  if ((ii = strstr (arg, " if ")) != NULL ||
-      (ii = strstr (arg, "\tif ")) != NULL ||
-      (ii = strstr (arg, " if\t")) != NULL ||
-      (ii = strstr (arg, "\tif\t")) != NULL ||
-      (ii = strstr (arg, " if(")) != NULL ||
-      (ii = strstr (arg, "\tif( ")) != NULL)
-    has_if = 1;
-  /* Temporarily zap out "if (condition)" to not confuse the
-     parenthesis-checking code below.  This is undone below. Do not
-     change ii!!  */
-  if (has_if)
-    {
-      *ii = '\0';
-    }
-
-  *is_quoted = (*arg
-		&& strchr (get_gdb_completer_quote_characters (),
-			   *arg) != NULL);
-
-  *paren_pointer = strchr (arg, '(');
-  if (*paren_pointer != NULL)
-    *paren_pointer = strrchr (*paren_pointer, ')');
-
-  /* Now that we're safely past the paren_pointer check, put back " if
-     (condition)" so outer layers can see it.  */
-  if (has_if)
-    *ii = ' ';
-}
-
 
 
 /* Decode arg of the form *PC.  */
@@ -1059,7 +1022,14 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
       p++;
     }
   else
-    *is_quote_enclosed = 0;
+    {
+      *is_quote_enclosed = 0;
+      if (strchr (get_gdb_completer_quote_characters (), *p))
+	{
+	  ++(*argptr);
+	  ++p;
+	}
+    }
   for (; *p; p++)
     {
       if (p[0] == '<')
@@ -1088,8 +1058,9 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
       if (p[0] == '.' && strchr (p, ':') == NULL)
 	{
 	  /* Java qualified method.  Find the *last* '.', since the
-	     others are package qualifiers.  */
-	  for (p1 = p; *p1; p1++)
+	     others are package qualifiers.  Stop at any open parenthesis
+	     which might provide overload information.  */
+	  for (p1 = p; *p1 && *p1 != '('; p1++)
 	    {
 	      if (*p1 == '.')
 		p = p1;
@@ -1241,6 +1212,7 @@ decode_compound (char **argptr, int funfirstline, char ***canonical,
   struct symbol *sym_class;
   struct symbol **sym_arr;
   struct type *t;
+  char *saved_java_argptr = NULL;
 
   /* First check for "global" namespace specification, of the form
      "::foo".  If found, skip over the colons and jump to normal
@@ -1289,7 +1261,8 @@ decode_compound (char **argptr, int funfirstline, char ***canonical,
       /* PASS2: p2->"::fun", p->":fun" */
 
       /* Move pointer ahead to next double-colon.  */
-      while (*p && (p[0] != ' ') && (p[0] != '\t') && (p[0] != '\''))
+      while (*p && (p[0] != ' ') && (p[0] != '\t') && (p[0] != '\'')
+	     && (*p != '('))
 	{
 	  if (current_language->la_language == language_cplus)
 	    p += cp_validate_operator (p);
@@ -1367,8 +1340,10 @@ decode_compound (char **argptr, int funfirstline, char ***canonical,
       else
 	{
 	  /* At this point argptr->"fun".  */
+	  char *a;
 	  p = *argptr;
-	  while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p != ':')
+	  while (*p && *p != ' ' && *p != '\t' && *p != ',' && *p != ':'
+		 && *p != '(')
 	    p++;
 	  /* At this point p->"".  String ended.  */
 	  /* Nope, C++ operators could have spaces in them
@@ -1380,6 +1355,42 @@ decode_compound (char **argptr, int funfirstline, char ***canonical,
 	      /* The above loop has already swallowed "operator".  */
 	      p += cp_validate_operator (p - 8) - 8;
 	    }
+
+	  /* Keep any template parameters */
+	  if (*p == '<')
+	    p = find_template_name_end (p);
+
+	  /* Keep method overload information.  */
+	  a = strchr (p, '(');
+	  if (a != NULL)
+	    p = find_method_overload_end (a);
+
+	  /* Make sure we keep important kewords like "const" */
+	  if (strncmp (p, " const", 6) == 0)
+	    p += 6;
+
+	  /* Java may append typenames,  so assume that if there is
+	     anything else left in *argptr, it must be a typename.  */
+	  if (*p && current_language->la_language == language_java)
+	    {
+	      struct type *type;
+	      p2 = p;
+	      while (*p2)
+		++p2;
+	      copy = (char *) alloca (p2 - p + 1);
+	      memcpy (copy, p, p2 - p);
+	      copy[p2 - p] = '\0';
+	      type = lookup_typename (current_language, get_current_arch (),
+				      copy, NULL, 1);
+	      if (type != NULL)
+		{
+		  /* Save the location of this just in case this
+		     method/type combination isn't actually defined.
+		     It will be checked later.  */
+		  saved_java_argptr = p;
+		  p = p2;
+		}
+	    }
 	}
 
       /* Allocate our own copy of the substring between argptr and
@@ -1408,9 +1419,26 @@ decode_compound (char **argptr, int funfirstline, char ***canonical,
 	 here, we return. If not, and we are at the and of the string,
 	 we'll lookup the whole string in the symbol tables.  */
 
-      return find_method (funfirstline, canonical, saved_arg,
-			  copy, t, sym_class, not_found_ptr);
-
+      values = find_method (funfirstline, canonical, saved_arg,
+			    copy, t, sym_class, not_found_ptr);
+      if (saved_java_argptr != NULL && values.nelts == 1)
+	{
+	  /* The user specified a specific return type for a java method.
+	     Double-check that it really is the one the user specified.
+	     [This is a necessary evil because strcmp_iw_ordered stops
+	     comparisons too prematurely.]  */
+	  sym = find_pc_sect_function (values.sals[0].pc,
+				       values.sals[0].section);
+	  /* We just found a SAL, we had better be able to go backwards!  */
+	  gdb_assert (sym != NULL);
+	  if (strcmp_iw (SYMBOL_LINKAGE_NAME (sym), saved_arg) != 0)
+	    {
+	      xfree (values.sals);
+	      error (_("the class `%s' does not have any method instance named %s\n"),
+		     SYMBOL_PRINT_NAME (sym_class), copy);
+	    }
+	}
+      return values;
     } /* End if symbol found */
 
 
@@ -1534,8 +1562,39 @@ find_method (int funfirstline, char ***canonical, char *saved_arg,
     }
   if (i1 > 0)
     {
-      /* There is more than one field with that name
-	 (overloaded).  Ask the user which one to use.  */
+      /* If we were given a specific overload instance, use that
+	 (or error if no matches were found).  Otherwise ask the user
+	 which one to use.  */
+      if (strchr (saved_arg, '(') != NULL)
+	{
+	  int i;
+	  for (i = 0; i < i1; ++i)
+	    {
+	      char *name = saved_arg;
+	      char *canon = cp_canonicalize_string (name);
+	      if (canon != NULL)
+		name = canon;
+
+	      if (strcmp_iw (name, SYMBOL_LINKAGE_NAME (sym_arr[i])) == 0)
+		{
+		  values.sals = (struct symtab_and_line *)
+		    xmalloc (sizeof (struct symtab_and_line));
+		  values.nelts = 1;
+		  values.sals[0] = find_function_start_sal (sym_arr[i],
+							    funfirstline);
+		  if (canon)
+		    xfree (canon);
+		  return values;
+		}
+
+	      if (canon)
+		xfree (canon);
+	    }
+
+	  error (_("the class `%s' does not have any method instance named %s\n"),
+		 SYMBOL_PRINT_NAME (sym_class), copy);
+	}
+
       return decode_line_2 (sym_arr, i1, funfirstline, canonical);
     }
   else
@@ -1577,7 +1636,8 @@ symtab_from_filename (char **argptr, char *p, int is_quote_enclosed,
   copy = (char *) alloca (p - *argptr + 1);
   memcpy (copy, *argptr, p - *argptr);
   /* It may have the ending quote right after the file name.  */
-  if (is_quote_enclosed && copy[p - *argptr - 1] == '"')
+  if ((is_quote_enclosed && copy[p - *argptr - 1] == '"')
+      || copy[p - *argptr - 1] == '\'')
     copy[p - *argptr - 1] = 0;
   else
     copy[p - *argptr] = 0;
@@ -1840,7 +1900,7 @@ symbol_found (int funfirstline, char ***canonical, char *copy,
 	{
 	  struct blockvector *bv = BLOCKVECTOR (SYMBOL_SYMTAB (sym));
 	  struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-	  if (lookup_block_symbol (b, copy, NULL, VAR_DOMAIN) != NULL)
+	  if (lookup_block_symbol (b, copy, VAR_DOMAIN) != NULL)
 	    build_canonical_line_spec (values.sals, copy, canonical);
 	}
       return values;
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index e55d958..e41ed74 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -2618,6 +2618,39 @@ linux_nat_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
   return lp->stopped_data_address_p;
 }
 
+/* In `set follow-fork-mode child' with multithreaded parent we need to detach
+   watchpoints from all the LWPs.  In such case INFERIOR_PTID will be the
+   non-threaded new child while LWP_LIST will still contain all the threads of
+   the parent being detached.  */
+
+static int
+linux_nat_detach_watchpoints (void)
+{
+  struct lwp_info *lp;
+  int found = 0, retval = 0;
+  ptid_t filter = pid_to_ptid (ptid_get_pid (inferior_ptid));
+  struct cleanup *old_chain = save_inferior_ptid ();
+
+  for (lp = lwp_list; lp; lp = lp->next)
+    if (ptid_match (lp->ptid, filter))
+      {
+	inferior_ptid = lp->ptid;
+	retval |= linux_ops->to_detach_watchpoints ();
+	found = 1;
+      }
+
+  do_cleanups (old_chain);
+
+  if (!found)
+    {
+      gdb_assert (!is_lwp (inferior_ptid));
+
+      retval |= linux_ops->to_detach_watchpoints ();
+    }
+
+  return retval;
+}
+
 /* Wait until LP is stopped.  */
 
 static int
@@ -5584,6 +5617,8 @@ linux_nat_add_target (struct target_ops *t)
   t->to_thread_address_space = linux_nat_thread_address_space;
   t->to_stopped_by_watchpoint = linux_nat_stopped_by_watchpoint;
   t->to_stopped_data_address = linux_nat_stopped_data_address;
+  if (linux_ops->to_detach_watchpoints)
+    t->to_detach_watchpoints = linux_nat_detach_watchpoints;
 
   t->to_can_async_p = linux_nat_can_async_p;
   t->to_is_async_p = linux_nat_is_async_p;
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 07fd67c..02b2342 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -23,6 +23,8 @@
 #include "auxv.h"
 #include "target.h"
 #include "elf/common.h"
+#include "value.h"
+#include "infcall.h"
 
 /* This function is suitable for architectures that don't
    extend/override the standard siginfo structure.  */
@@ -152,3 +154,43 @@ linux_has_shared_address_space (void)
 
   return target_is_uclinux;
 }
+
+/* Call gnu-ifunc to resolve breakpoint at its returned function.  */
+
+CORE_ADDR
+linux_convert_from_func_and_ptr (struct gdbarch *gdbarch, CORE_ADDR func_ptr,
+                                 CORE_ADDR pc)
+{
+  struct type *func_func_type = builtin_type (gdbarch)->builtin_func_func;
+  struct minimal_symbol *msymbol;
+  struct value *function, *address;
+
+  if (!target_has_execution)
+    return pc;
+
+  msymbol = lookup_minimal_symbol_by_pc (func_ptr);
+  if (msymbol == NULL)
+    return pc;
+  if (MSYMBOL_TYPE (msymbol) != mst_text_gnu_ifunc)
+    return pc;
+
+  /* Not at the gnu-ifunc entry point?  */
+  if (SYMBOL_VALUE_ADDRESS (msymbol) != func_ptr)
+    return pc;
+
+  function = allocate_value (func_func_type);
+  set_value_address (function, pc);
+
+  /* gnu-ifuncs have no arguments.  FUNCTION is the code instruction address
+     while ADDRESS is a function descriptor.  */
+  address = call_function_by_hand (function, 0, NULL);
+
+  return value_as_address (address);
+}
+
+CORE_ADDR
+linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr,
+				  struct target_ops *targ)
+{
+  return linux_convert_from_func_and_ptr (gdbarch, addr, addr);
+}
diff --git a/gdb/linux-tdep.h b/gdb/linux-tdep.h
index a8b522b..282190e 100644
--- a/gdb/linux-tdep.h
+++ b/gdb/linux-tdep.h
@@ -22,4 +22,11 @@
 
 struct type *linux_get_siginfo_type (struct gdbarch *);
 
+CORE_ADDR linux_convert_from_func_and_ptr (struct gdbarch *gdbarch,
+					   CORE_ADDR func_ptr, CORE_ADDR pc);
+
+CORE_ADDR linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
+					    CORE_ADDR addr,
+					    struct target_ops *targ);
+
 #endif /* linux-tdep.h */
diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
index 80e9bf9..3057774 100644
--- a/gdb/m2-lang.c
+++ b/gdb/m2-lang.c
@@ -356,6 +356,7 @@ const struct exp_descriptor exp_descriptor_modula2 =
 {
   print_subexp_standard,
   operator_length_standard,
+  operator_check_standard,
   op_name_standard,
   dump_subexp_body_standard,
   evaluate_subexp_modula2
diff --git a/gdb/m32r-linux-tdep.c b/gdb/m32r-linux-tdep.c
index 6804609..2cb1bf9 100644
--- a/gdb/m32r-linux-tdep.c
+++ b/gdb/m32r-linux-tdep.c
@@ -30,6 +30,7 @@
 #include "gdb_string.h"
 
 #include "glibc-tdep.h"
+#include "linux-tdep.h"
 #include "solib-svr4.h"
 #include "symtab.h"
 
@@ -422,6 +423,9 @@ m32r_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   /* Enable TLS support.  */
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
                                              svr4_fetch_objfile_link_map);
+
+  set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+					  linux_convert_from_func_ptr_addr);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff --git a/gdb/machoread.c b/gdb/machoread.c
index a810bb2..b416970 100644
--- a/gdb/machoread.c
+++ b/gdb/machoread.c
@@ -842,6 +842,7 @@ static struct sym_fns macho_sym_fns = {
   macho_new_init,               /* sym_new_init: init anything gbl to entire symtab */
   macho_symfile_init,           /* sym_init: read initial info, setup for sym_read() */
   macho_symfile_read,           /* sym_read: read a symbol file into symtab */
+  NULL,				/* sym_read_psymbols */
   macho_symfile_finish,         /* sym_finish: finished with file, cleanup */
   macho_symfile_offsets,        /* sym_offsets:  xlate external to internal form */
   default_symfile_segments,	/* sym_segments: Get segment information from
diff --git a/gdb/main.c b/gdb/main.c
index e261348..92c63a7 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -40,6 +40,7 @@
 #include "interps.h"
 #include "main.h"
 
+#include "python/python.h"
 #include "source.h"
 
 /* If nonzero, display time usage both at startup and for each command.  */
@@ -259,6 +260,8 @@ captured_main (void *data)
   char *cdarg = NULL;
   char *ttyarg = NULL;
 
+  int python_script = 0;
+
   /* These are static so that we can take their address in an initializer.  */
   static int print_help;
   static int print_version;
@@ -434,10 +437,14 @@ captured_main (void *data)
       {"args", no_argument, &set_args, 1},
       {"l", required_argument, 0, 'l'},
       {"return-child-result", no_argument, &return_child_result, 1},
+#if HAVE_PYTHON
+      {"python", no_argument, 0, 'P'},
+      {"P", no_argument, 0, 'P'},
+#endif
       {0, no_argument, 0, 0}
     };
 
-    while (1)
+    while (!python_script)
       {
 	int option_index;
 
@@ -455,6 +462,9 @@ captured_main (void *data)
 	  case 0:
 	    /* Long option that just sets a flag.  */
 	    break;
+	  case 'P':
+	    python_script = 1;
+	    break;
 	  case OPT_SE:
 	    symarg = optarg;
 	    execarg = optarg;
@@ -641,7 +651,31 @@ extern int gdbtk_test (char *);
 
   /* Now that gdb_init has created the initial inferior, we're in position
      to set args for that inferior.  */
-  if (set_args)
+  if (python_script)
+    {
+      /* The first argument is a python script to evaluate, and
+	 subsequent arguments are passed to the script for
+	 processing there.  */
+      if (optind >= argc)
+	{
+	  fprintf_unfiltered (gdb_stderr,
+			      _("%s: Python script file name required\n"),
+			      argv[0]);
+	  exit (1);
+	}
+
+      /* FIXME: should handle inferior I/O intelligently here.
+	 E.g., should be possible to run gdb in pipeline and have
+	 Python (and gdb) output go to stderr or file; and if a
+	 prompt is needed, open the tty.  */
+      quiet = 1;
+      /* FIXME: should read .gdbinit if, and only if, a prompt is
+	 requested by the script.  Though... maybe this is not
+	 ideal?  */
+      /* FIXME: likewise, reading in history.  */
+      inhibit_gdbinit = 1;
+    }
+  else if (set_args)
     {
       /* The remaining options are the command-line options for the
 	 inferior.  The first one is the sym/exec file, and the rest
@@ -867,7 +901,8 @@ Can't attach to process and specify a core file at the same time."));
   xfree (cmdarg);
 
   /* Read in the old history after all the command files have been read. */
-  init_history ();
+  if (!python_script)
+    init_history ();
 
   if (batch)
     {
@@ -896,13 +931,25 @@ Can't attach to process and specify a core file at the same time."));
 #endif
     }
 
-  /* NOTE: cagney/1999-11-07: There is probably no reason for not
-     moving this loop and the code found in captured_command_loop()
-     into the command_loop() proper.  The main thing holding back that
-     change - SET_TOP_LEVEL() - has been eliminated. */
-  while (1)
+#if HAVE_PYTHON
+  if (python_script)
     {
-      catch_errors (captured_command_loop, 0, "", RETURN_MASK_ALL);
+      extern int pagination_enabled;
+      pagination_enabled = 0;
+      run_python_script (argc - optind, &argv[optind]);
+      return 1;
+    }
+  else
+#endif
+    {
+      /* NOTE: cagney/1999-11-07: There is probably no reason for not
+	 moving this loop and the code found in captured_command_loop()
+	 into the command_loop() proper.  The main thing holding back that
+	 change - SET_TOP_LEVEL() - has been eliminated. */
+      while (1)
+	{
+	  catch_errors (captured_command_loop, 0, "", RETURN_MASK_ALL);
+	}
     }
   /* No exit -- exit is through quit_command.  */
 }
@@ -934,7 +981,12 @@ print_gdb_help (struct ui_file *stream)
   fputs_unfiltered (_("\
 This is the GNU debugger.  Usage:\n\n\
     gdb [options] [executable-file [core-file or process-id]]\n\
-    gdb [options] --args executable-file [inferior-arguments ...]\n\n\
+    gdb [options] --args executable-file [inferior-arguments ...]\n"), stream);
+#if HAVE_PYTHON
+  fputs_unfiltered (_("\
+    gdb [options] [--python|-P] script-file [script-arguments ...]\n"), stream);
+#endif
+  fputs_unfiltered (_("\n\
 Options:\n\n\
 "), stream);
   fputs_unfiltered (_("\
@@ -972,7 +1024,13 @@ Options:\n\n\
   --nw		     Do not use a window interface.\n\
   --nx               Do not read "), stream);
   fputs_unfiltered (gdbinit, stream);
-  fputs_unfiltered (_(" file.\n\
+  fputs_unfiltered (_(" file.\n"), stream);
+#if HAVE_PYTHON
+  fputs_unfiltered (_("\
+  --python, -P       Following argument is Python script file; remaining\n\
+                     arguments are passed to script.\n"), stream);
+#endif
+  fputs_unfiltered (_("\
   --quiet            Do not print version number on startup.\n\
   --readnow          Fully read symbol files on first access.\n\
 "), stream);
diff --git a/gdb/maint.c b/gdb/maint.c
index 4316d66..fe8a069 100644
--- a/gdb/maint.c
+++ b/gdb/maint.c
@@ -914,4 +914,12 @@ When enabled GDB is profiled."),
 			   show_maintenance_profile_p,
 			   &maintenance_set_cmdlist,
 			   &maintenance_show_cmdlist);
+  add_setshow_filename_cmd ("gdb_datadir", class_maintenance,
+                           &gdb_datadir, _("Set GDB's datadir path."),
+                           _("Show GDB's datadir path."),
+                           _("\
+When set, GDB uses the specified path to search for data files."),
+                           NULL, NULL,
+                           &maintenance_set_cmdlist,
+                           &maintenance_show_cmdlist);
 }
diff --git a/gdb/mi/mi-cmd-var.c b/gdb/mi/mi-cmd-var.c
index b227411..3b932f0 100644
--- a/gdb/mi/mi-cmd-var.c
+++ b/gdb/mi/mi-cmd-var.c
@@ -697,7 +697,6 @@ mi_cmd_var_update (char *command, char **argv, int argc)
     }
   else
     {
-      /* Get varobj handle, if a valid var obj name was specified */
       struct varobj *var = varobj_get_handle (name);
 
       varobj_update_one (var, print_values, 1 /* explicit */);
diff --git a/gdb/microblaze-linux-tdep.c b/gdb/microblaze-linux-tdep.c
index a691b62..d679516 100644
--- a/gdb/microblaze-linux-tdep.c
+++ b/gdb/microblaze-linux-tdep.c
@@ -35,6 +35,7 @@
 #include "trad-frame.h"
 #include "frame-unwind.h"
 #include "tramp-frame.h"
+#include "linux-tdep.h"
 
 
 static int
@@ -133,6 +134,9 @@ microblaze_linux_init_abi (struct gdbarch_info info,
   /* Trampolines.  */
   tramp_frame_prepend_unwinder (gdbarch,
 				&microblaze_linux_sighandler_tramp_frame);
+
+  set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+					  linux_convert_from_func_ptr_addr);
 }
 
 void
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index 287f9de..1fe0fbe 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -331,8 +331,9 @@ lookup_minimal_symbol_text (const char *name, struct objfile *objf)
 	       msymbol = msymbol->hash_next)
 	    {
 	      if (strcmp (SYMBOL_LINKAGE_NAME (msymbol), name) == 0 &&
-		  (MSYMBOL_TYPE (msymbol) == mst_text ||
-		   MSYMBOL_TYPE (msymbol) == mst_file_text))
+		  (MSYMBOL_TYPE (msymbol) == mst_text
+		   || MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc
+		   || MSYMBOL_TYPE (msymbol) == mst_file_text))
 		{
 		  switch (MSYMBOL_TYPE (msymbol))
 		    {
@@ -694,6 +695,16 @@ lookup_minimal_symbol_by_pc (CORE_ADDR pc)
   return lookup_minimal_symbol_by_pc_section (pc, NULL);
 }
 
+/* Return non-zero iff PC is in function implementing gnu-ifunc selection.  */
+
+int
+in_gnu_ifunc_stub (CORE_ADDR pc)
+{
+  struct minimal_symbol *msymbol = lookup_minimal_symbol_by_pc (pc);
+
+  return msymbol && MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc;
+}
+
 /* Find the minimal symbol named NAME, and return both the minsym
    struct and its objfile.  This only checks the linkage name.  Sets
    *OBJFILE_P and returns the minimal symbol, if it is found.  If it
@@ -763,6 +774,7 @@ prim_record_minimal_symbol (const char *name, CORE_ADDR address,
   switch (ms_type)
     {
     case mst_text:
+    case mst_text_gnu_ifunc:
     case mst_file_text:
     case mst_solib_trampoline:
       section = SECT_OFF_TEXT (objfile);
@@ -1228,7 +1240,8 @@ find_solib_trampoline_target (struct frame_info *frame, CORE_ADDR pc)
     {
       ALL_MSYMBOLS (objfile, msymbol)
       {
-	if (MSYMBOL_TYPE (msymbol) == mst_text
+	if ((MSYMBOL_TYPE (msymbol) == mst_text
+	    || MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc)
 	    && strcmp (SYMBOL_LINKAGE_NAME (msymbol),
 		       SYMBOL_LINKAGE_NAME (tsymbol)) == 0)
 	  return SYMBOL_VALUE_ADDRESS (msymbol);
diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c
index 5924b30..2957024 100644
--- a/gdb/mips-linux-tdep.c
+++ b/gdb/mips-linux-tdep.c
@@ -38,6 +38,7 @@
 #include "target-descriptions.h"
 #include "mips-linux-tdep.h"
 #include "glibc-tdep.h"
+#include "linux-tdep.h"
 
 static struct target_so_ops mips_svr4_so_ops;
 
@@ -1222,6 +1223,9 @@ mips_linux_init_abi (struct gdbarch_info info,
 	tdesc_numbered_register (feature, tdesc_data, MIPS_RESTART_REGNUM,
 				 "restart");
     }
+
+  set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+					  linux_convert_from_func_ptr_addr);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff --git a/gdb/mipsread.c b/gdb/mipsread.c
index 093313e..9144d00 100644
--- a/gdb/mipsread.c
+++ b/gdb/mipsread.c
@@ -394,6 +394,7 @@ static struct sym_fns ecoff_sym_fns =
   mipscoff_new_init,		/* sym_new_init: init anything gbl to entire symtab */
   mipscoff_symfile_init,	/* sym_init: read initial info, setup for sym_read() */
   mipscoff_symfile_read,	/* sym_read: read a symbol file into symtab */
+  NULL,				/* sym_read_psymbols */
   mipscoff_symfile_finish,	/* sym_finish: finished with file, cleanup */
   default_symfile_offsets,	/* sym_offsets: dummy FIXME til implem sym reloc */
   default_symfile_segments,	/* sym_segments: Get segment information from
diff --git a/gdb/mn10300-linux-tdep.c b/gdb/mn10300-linux-tdep.c
index d4602a4..7bba707 100644
--- a/gdb/mn10300-linux-tdep.c
+++ b/gdb/mn10300-linux-tdep.c
@@ -32,6 +32,7 @@
 #include "frame.h"
 #include "trad-frame.h"
 #include "tramp-frame.h"
+#include "linux-tdep.h"
 
 #include <stdlib.h>
 
@@ -718,6 +719,9 @@ am33_linux_init_osabi (struct gdbarch_info gdbinfo, struct gdbarch *gdbarch)
 
   tramp_frame_prepend_unwinder (gdbarch, &am33_linux_sigframe);
   tramp_frame_prepend_unwinder (gdbarch, &am33_linux_rt_sigframe);
+
+  set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+					  linux_convert_from_func_ptr_addr);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index a050f15..04d1f1c 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -1178,16 +1178,6 @@ find_methods (struct symtab *symtab, char type,
 
 	  QUIT;
 
-	  /* The minimal symbol might point to a function descriptor;
-	     resolve it to the actual code address instead.  */
-	  pc = gdbarch_convert_from_func_ptr_addr (gdbarch, pc,
-						   &current_target);
-
-	  if (symtab)
-	    if (pc < BLOCK_START (block) || pc >= BLOCK_END (block))
-	      /* Not in the specified symtab.  */
-	      continue;
-
 	  symname = SYMBOL_NATURAL_NAME (msymbol);
 	  if (symname == NULL)
 	    continue;
@@ -1223,6 +1213,17 @@ find_methods (struct symtab *symtab, char type,
 	      ((nselector == NULL) || (strcmp (selector, nselector) != 0)))
 	    continue;
 
+	  /* The minimal symbol might point to a function descriptor;
+	     resolve it to the actual code address instead.  Delay the call as
+	     its resolution may be expensive.  */
+	  pc = gdbarch_convert_from_func_ptr_addr (gdbarch, pc,
+						   &current_target);
+
+	  if (symtab)
+	    if (pc < BLOCK_START (block) || pc >= BLOCK_END (block))
+	      /* Not in the specified symtab.  */
+	      continue;
+
 	  sym = find_pc_function (pc);
 	  if (sym != NULL)
 	    {
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index c2763c2..5d62020 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -792,6 +792,10 @@ objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets)
     }
   }
 
+  if (objfile->quick_addrmap)
+    addrmap_relocate (objfile->quick_addrmap,
+		      ANOFFSET (delta, SECT_OFF_TEXT (objfile)));
+
   {
     struct partial_symbol **psym;
 
@@ -917,7 +921,7 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
 int
 objfile_has_partial_symbols (struct objfile *objfile)
 {
-  return objfile->psymtabs != NULL;
+  return objfile->psymtabs != NULL || objfile->quick_addrmap;
 }
 
 /* Return non-zero if OBJFILE has full symbols.  */
@@ -957,6 +961,20 @@ have_partial_symbols (void)
     if (objfile_has_partial_symbols (ofp))
       return 1;
   }
+
+  /* Try again, after reading partial symbols.  We do this in two
+     passes because objfiles are always added to the head of the list,
+     and there might be a later objfile for which we've already read
+     partial symbols.  */
+  ALL_OBJFILES (ofp)
+  {
+    require_partial_symbols (ofp);
+    if (ofp->psymtabs != NULL)
+      {
+	return 1;
+      }
+  }
+
   return 0;
 }
 
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
index c689622..eb3ae10 100644
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -213,6 +213,11 @@ struct objfile
 
     struct partial_symtab *psymtabs;
 
+    /* An address map that can be used to quickly determine if an
+       address comes from this objfile.  This can be NULL.  */
+
+    struct addrmap *quick_addrmap;
+
     /* Map addresses to the entries of PSYMTABS.  It would be more efficient to
        have a map per the whole process but ADDRMAP cannot selectively remove
        its items during FREE_OBJFILE.  This mapping is already present even for
@@ -426,6 +431,15 @@ struct objfile
 
 #define OBJF_USERLOADED	(1 << 3)	/* User loaded */
 
+/* Set if we have tried to read partial symtabs for this objfile.
+   This is used to allow lazy reading of partial symtabs.  */
+
+#define OBJF_SYMTABS_READ (1 << 6)
+
+/* This flag is set for the main objfile.  */
+
+#define OBJF_MAIN (1 << 7)
+
 /* The object file that contains the runtime common minimal symbols
    for SunOS4. Note that this objfile has no associated BFD.  */
 
@@ -606,6 +620,13 @@ extern void gdb_bfd_unref (struct bfd *abfd);
   ALL_OBJFILES (objfile)	 \
     ALL_OBJFILE_PSYMTABS (objfile, p)
 
+/* Like ALL_PSYMTABS, but ensure that partial symbols have been read
+   before examining the objfile.  */
+
+#define ALL_PSYMTABS_REQUIRED(objfile, p)			\
+  ALL_OBJFILES (objfile)					\
+    ALL_OBJFILE_PSYMTABS (require_partial_symbols (objfile), p)
+
 #define ALL_PSPACE_PSYMTABS(ss, objfile, p)		\
   ALL_PSPACE_OBJFILES (ss, objfile)			\
     ALL_OBJFILE_PSYMTABS (objfile, p)
diff --git a/gdb/parse.c b/gdb/parse.c
index aabc461..e2ab8d9 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -62,6 +62,7 @@ const struct exp_descriptor exp_descriptor_standard =
   {
     print_subexp_standard,
     operator_length_standard,
+    operator_check_standard,
     op_name_standard,
     dump_subexp_body_standard,
     evaluate_subexp_standard
@@ -523,6 +524,11 @@ write_exp_msymbol (struct minimal_symbol *msymbol)
       write_exp_elt_type (objfile_type (objfile)->nodebug_text_symbol);
       break;
 
+    case mst_text_gnu_ifunc:
+      write_exp_elt_type (objfile_type (objfile)
+					       ->nodebug_text_gnu_ifunc_symbol);
+      break;
+
     case mst_data:
     case mst_file_data:
     case mst_bss:
@@ -853,6 +859,10 @@ operator_length_standard (struct expression *expr, int endpos,
       args = 1;
       break;
 
+    case TYPE_INSTANCE_LOOKUP:
+      oplen = 3;
+      break;
+
     case OP_OBJC_MSGCALL:	/* Objective C message (method) call */
       oplen = 4;
       args = 1 + longest_to_int (expr->elts[endpos - 2].longconst);
@@ -889,6 +899,13 @@ operator_length_standard (struct expression *expr, int endpos,
       args = 1;
       break;
 
+    case OP_ADL_FUNC:
+      oplen = longest_to_int (expr->elts[endpos - 2].longconst);
+      oplen = 4 + BYTES_TO_EXP_ELEM (oplen + 1);
+      oplen++;
+      oplen++;
+      break;
+
     case OP_LABELED:
     case STRUCTOP_STRUCT:
     case STRUCTOP_PTR:
@@ -1373,6 +1390,151 @@ parser_fprintf (FILE *x, const char *y, ...)
   va_end (args);
 }
 
+/* Implementation of the exp_descriptor method operator_check.  */
+
+int
+operator_check_standard (struct expression *exp, int pos,
+			 int (*type_func) (struct type *type, void *data),
+			 int (*objfile_func) (struct objfile *objfile,
+					      void *data),
+			 void *data)
+{
+  const union exp_element *const elts = exp->elts;
+  struct type *type = NULL;
+  struct objfile *objfile = NULL;
+
+  /* Extended operators should have been already handled by exp_descriptor
+     iterate method of its specific language.  */
+  gdb_assert (elts[pos].opcode < OP_EXTENDED0);
+
+  /* Track the callers of write_exp_elt_type for this table.  */
+
+  switch (elts[pos].opcode)
+    {
+    case BINOP_VAL:
+    case OP_COMPLEX:
+    case OP_DECFLOAT:
+    case OP_DOUBLE:
+    case OP_LONG:
+    case OP_SCOPE:
+    case OP_TYPE:
+    case UNOP_CAST:
+    case UNOP_MAX:
+    case UNOP_MEMVAL:
+    case UNOP_MIN:
+      type = elts[pos + 1].type;
+      break;
+
+    case UNOP_MEMVAL_TLS:
+      objfile = elts[pos + 1].objfile;
+      type = elts[pos + 2].type;
+      break;
+
+    case OP_VAR_VALUE:
+      {
+	const struct block *const block = elts[pos + 1].block;
+	const struct symbol *const symbol = elts[pos + 2].symbol;
+	const struct obj_section *const section = SYMBOL_OBJ_SECTION (symbol);
+
+	/* Check objfile where the variable itself is placed.
+	   SYMBOL_OBJ_SECTION (symbol) may be NULL.  */
+	if (objfile_func && (*objfile_func) (SYMBOL_SYMTAB (symbol)->objfile, data))
+	  return 1;
+
+	/* Check objfile where is placed the code touching the variable.  */
+	objfile = block_objfile (block);
+
+	type = SYMBOL_TYPE (symbol);
+      }
+      break;
+    }
+
+  /* Invoke callbacks for TYPE and OBJFILE if they were set as non-NULL.  */
+
+  if (type && type_func && (*type_func) (type, data))
+    return 1;
+  if (type && TYPE_OBJFILE (type) && objfile_func
+      && (*objfile_func) (TYPE_OBJFILE (type), data))
+    return 1;
+  if (objfile && objfile_func && (*objfile_func) (objfile, data))
+    return 1;
+
+  return 0;
+}
+
+/* Call TYPE_FUNC and OBJFILE_FUNC for any TYPE and OBJFILE found being
+   referenced by EXP.  The functions are never called with NULL TYPE or NULL
+   OBJFILE.  Functions get passed an arbitrary caller supplied DATA pointer.
+   If any of the functions returns non-zero value then (any other) non-zero
+   value is immediately returned to the caller.  Otherwise zero is returned
+   after iterating through whole EXP.  */
+
+static int
+exp_iterate (struct expression *exp,
+	     int (*type_func) (struct type *type, void *data),
+	     int (*objfile_func) (struct objfile *objfile, void *data),
+	     void *data)
+{
+  int endpos;
+  const union exp_element *const elts = exp->elts;
+
+  for (endpos = exp->nelts; endpos > 0; )
+    {
+      int pos, args, oplen = 0;
+
+      exp->language_defn->la_exp_desc->operator_length (exp, endpos,
+							&oplen, &args);
+      gdb_assert (oplen > 0);
+
+      pos = endpos - oplen;
+      if (exp->language_defn->la_exp_desc->operator_check (exp, pos, type_func,
+							   objfile_func, data))
+	return 1;
+
+      endpos = pos;
+    }
+
+  return 0;
+}
+
+/* Helper for exp_uses_objfile.  */
+
+static int
+exp_uses_objfile_iter (struct objfile *exp_objfile, void *objfile_voidp)
+{
+  struct objfile *objfile = objfile_voidp;
+
+  return exp_objfile == objfile;
+}
+
+/* Return 1 if EXP uses OBJFILE (and will become dangling when OBJFILE
+   is unloaded), otherwise return 0.  */
+
+int
+exp_uses_objfile (struct expression *exp, struct objfile *objfile)
+{
+  return exp_iterate (exp, NULL, exp_uses_objfile_iter, objfile);
+}
+
+/* Helper for exp_types_mark_used.  */
+
+static int
+exp_types_mark_used_iter (struct type *type, void *unused)
+{
+  type_mark_used (type);
+
+  /* Continue the traversal.  */
+  return 0;
+}
+
+/* Call type_mark_used for any TYPE contained in EXP.  */
+
+void
+exp_types_mark_used (struct expression *exp)
+{
+  exp_iterate (exp, exp_types_mark_used_iter, NULL, NULL);
+}
+
 void
 _initialize_parse (void)
 {
diff --git a/gdb/parser-defs.h b/gdb/parser-defs.h
index c4eb1a0..2a43fe3 100644
--- a/gdb/parser-defs.h
+++ b/gdb/parser-defs.h
@@ -192,6 +192,13 @@ extern void operator_length (struct expression *, int, int *, int *);
 
 extern void operator_length_standard (struct expression *, int, int *, int *);
 
+extern int operator_check_standard (struct expression *exp, int pos,
+				    int (*type_func) (struct type *type,
+						      void *data),
+				    int (*objfile_func)
+				      (struct objfile *objfile, void *data),
+				    void *data);
+
 extern char *op_name_standard (enum exp_opcode);
 
 extern struct type *follow_types (struct type *);
@@ -270,6 +277,20 @@ struct exp_descriptor
        the number of subexpressions it takes.  */
     void (*operator_length) (struct expression*, int, int*, int *);
 
+    /* Call TYPE_FUNC and OBJFILE_FUNC for any TYPE and OBJFILE found being
+       referenced by the single operator of EXP at position POS.  Operator
+       parameters are located at positive (POS + number) offsets in EXP.
+       The functions should never be called with NULL TYPE or NULL OBJFILE.
+       Functions should get passed an arbitrary caller supplied DATA pointer.
+       If any of the functions returns non-zero value then (any other) non-zero
+       value should be immediately returned to the caller.  Otherwise zero
+       should be returned.  */
+    int (*operator_check) (struct expression *exp, int pos,
+			   int (*type_func) (struct type *type, void *data),
+			   int (*objfile_func) (struct objfile *objfile,
+						void *data),
+			   void *data);
+
     /* Name of this operator for dumping purposes.  */
     char *(*op_name) (enum exp_opcode);
 
@@ -302,4 +323,8 @@ extern void print_subexp_standard (struct expression *, int *,
 
 extern void parser_fprintf (FILE *, const char *, ...) ATTR_FORMAT (printf, 2 ,3);
 
+extern int exp_uses_objfile (struct expression *exp, struct objfile *objfile);
+
+extern void exp_types_mark_used (struct expression *exp);
+
 #endif /* PARSER_DEFS_H */
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index 10ff73d..5b68f56 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -1391,6 +1391,24 @@ ppc_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw)
   return 0;
 }
 
+/* See target_detach_watchpoints.  Do not use wrapper
+   ppc_linux_remove_watchpoint as it would modify the register cache
+   (saved_dabr_value).  */
+
+static int
+ppc_linux_detach_watchpoints (void)
+{
+  pid_t tid;
+
+  tid = TIDGET (inferior_ptid);
+  if (tid == 0)
+    tid = PIDGET (inferior_ptid);
+
+  if (ptrace (PTRACE_SET_DEBUGREG, tid, NULL, NULL) < 0)
+    return -1;
+  return 0;
+}
+
 static void
 ppc_linux_new_thread (ptid_t ptid)
 {
@@ -1648,6 +1666,7 @@ _initialize_ppc_linux_nat (void)
   t->to_region_ok_for_hw_watchpoint = ppc_linux_region_ok_for_hw_watchpoint;
   t->to_insert_watchpoint = ppc_linux_insert_watchpoint;
   t->to_remove_watchpoint = ppc_linux_remove_watchpoint;
+  t->to_detach_watchpoints = ppc_linux_detach_watchpoints;
   t->to_stopped_by_watchpoint = ppc_linux_stopped_by_watchpoint;
   t->to_stopped_data_address = ppc_linux_stopped_data_address;
   t->to_watchpoint_addr_within_range = ppc_linux_watchpoint_addr_within_range;
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index fae5ab2..94f993e 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -48,6 +48,7 @@
 #include "arch-utils.h"
 #include "spu-tdep.h"
 #include "xml-syscall.h"
+#include "linux-tdep.h"
 
 #include "features/rs6000/powerpc-32l.c"
 #include "features/rs6000/powerpc-altivec32l.c"
@@ -672,8 +673,19 @@ ppc64_linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
       res = bfd_get_section_contents (s->bfd, s->the_bfd_section,
 				      &buf, addr - s->addr, 8);
       if (res != 0)
-	return extract_unsigned_integer (buf, 8, byte_order)
-		- bfd_section_vma (s->bfd, s->the_bfd_section) + s->addr;
+	{
+	  CORE_ADDR pc, resolved;
+	  
+	  pc = extract_unsigned_integer (buf, 8, byte_order)
+	       - bfd_section_vma (s->bfd, s->the_bfd_section) + s->addr;
+
+	  resolved = linux_convert_from_func_and_ptr (gdbarch, addr, pc);
+	  if (resolved != pc)
+	    pc = ppc64_linux_convert_from_func_ptr_addr (gdbarch, resolved,
+							 targ);
+
+	  return pc;
+	}
    }
 
   return addr;
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index c8cb35c..18dae9e 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -46,7 +46,6 @@
 #include "exceptions.h"
 #include "observer.h"
 #include "solist.h"
-#include "solib.h"
 #include "parser-defs.h"
 #include "charset.h"
 #include "arch-utils.h"
@@ -941,6 +940,11 @@ print_command_1 (char *exp, int inspect, int voidprint)
   else
     val = access_value_history (0);
 
+  /* Do not try to OBJECT_ADDRESS_SET here anything.  We are interested in the
+     source variable base addresses as found by READ_VAR_VALUE.  The value here
+     can be already a calculated expression address inappropriate for
+     DW_OP_push_object_address.  */
+
   if (voidprint || (val && value_type (val) &&
 		    TYPE_CODE (value_type (val)) != TYPE_CODE_VOID))
     {
@@ -1437,6 +1441,22 @@ x_command (char *exp, int from_tty)
 	set_internalvar (lookup_internalvar ("__"), last_examine_value);
     }
 }
+
+/* Call type_mark_used for any TYPEs referenced from this GDB source file.  */
+
+static void
+print_types_mark_used (void)
+{
+  struct display *d;
+
+  if (last_examine_value)
+    type_mark_used (value_type (last_examine_value));
+
+  for (d = display_chain; d; d = d->next)
+    if (d->exp)
+      exp_types_mark_used (d->exp);
+}
+
 
 
 /* Add an expression to the auto-display chain.
@@ -1859,51 +1879,6 @@ disable_display_command (char *args, int from_tty)
       }
 }
 
-/* Return 1 if D uses SOLIB (and will become dangling when SOLIB
-   is unloaded), otherwise return 0.  */
-
-static int
-display_uses_solib_p (const struct display *d,
-		      const struct so_list *solib)
-{
-  int endpos;
-  struct expression *const exp = d->exp;
-  const union exp_element *const elts = exp->elts;
-
-  if (d->block != NULL
-      && d->pspace == solib->pspace
-      && solib_contains_address_p (solib, d->block->startaddr))
-    return 1;
-
-  for (endpos = exp->nelts; endpos > 0; )
-    {
-      int i, args, oplen = 0;
-
-      exp->language_defn->la_exp_desc->operator_length (exp, endpos,
-							&oplen, &args);
-      gdb_assert (oplen > 0);
-
-      i = endpos - oplen;
-      if (elts[i].opcode == OP_VAR_VALUE)
-	{
-	  const struct block *const block = elts[i + 1].block;
-	  const struct symbol *const symbol = elts[i + 2].symbol;
-
-	  if (block != NULL
-	      && solib_contains_address_p (solib,
-					   block->startaddr))
-	    return 1;
-
-	  /* SYMBOL_OBJ_SECTION (symbol) may be NULL.  */
-	  if (SYMBOL_SYMTAB (symbol)->objfile == solib->objfile)
-	    return 1;
-	}
-      endpos -= oplen;
-    }
-
-  return 0;
-}
-
 /* display_chain items point to blocks and expressions.  Some expressions in
    turn may point to symbols.
    Both symbols and blocks are obstack_alloc'd on objfile_stack, and are
@@ -1915,18 +1890,20 @@ display_uses_solib_p (const struct display *d,
 static void
 clear_dangling_display_expressions (struct so_list *solib)
 {
+  struct objfile *objfile = solib->objfile;
   struct display *d;
-  struct objfile *objfile = NULL;
 
-  for (d = display_chain; d; d = d->next)
-    {
-      if (d->exp && display_uses_solib_p (d, solib))
-	{
-	  xfree (d->exp);
-	  d->exp = NULL;
-	  d->block = NULL;
-	}
-    }
+  if (objfile == NULL)
+    return;
+
+  for (d = display_chain; d != NULL; d = d->next)
+    if (block_objfile (d->block) == objfile
+	|| (d->exp && exp_uses_objfile (d->exp, objfile)))
+      {
+	xfree (d->exp);
+	d->exp = NULL;
+	d->block = NULL;
+      }
 }
 
 
@@ -2811,4 +2788,6 @@ Show printing of source filename and line number with <symbol>."), NULL,
 			   NULL,
 			   show_print_symbol_filename,
 			   &setprintlist, &showprintlist);
+
+  observer_attach_mark_used (print_types_mark_used);
 }
diff --git a/gdb/python/lib/gdb/FrameIterator.py b/gdb/python/lib/gdb/FrameIterator.py
new file mode 100644
index 0000000..5654546
--- /dev/null
+++ b/gdb/python/lib/gdb/FrameIterator.py
@@ -0,0 +1,33 @@
+# Iterator over frames.
+
+# Copyright (C) 2008, 2009 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/>.
+
+class FrameIterator:
+    """An iterator that iterates over frames."""
+
+    def __init__ (self, frame):
+        "Initialize a FrameIterator.  FRAME is the starting frame."
+        self.frame = frame
+
+    def __iter__ (self):
+        return self
+
+    def next (self):
+        result = self.frame
+        if result is None:
+            raise StopIteration
+        self.frame = result.older ()
+        return result
diff --git a/gdb/python/lib/gdb/FrameWrapper.py b/gdb/python/lib/gdb/FrameWrapper.py
new file mode 100644
index 0000000..b790a54
--- /dev/null
+++ b/gdb/python/lib/gdb/FrameWrapper.py
@@ -0,0 +1,112 @@
+# Wrapper API for frames.
+
+# Copyright (C) 2008, 2009 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/>.
+
+import gdb
+
+# FIXME: arguably all this should be on Frame somehow.
+class FrameWrapper:
+    def __init__ (self, frame):
+        self.frame = frame;
+
+    def write_symbol (self, stream, sym, block):
+        if len (sym.linkage_name):
+            nsym, is_field_of_this = gdb.lookup_symbol (sym.linkage_name, block)
+            if nsym.addr_class != gdb.SYMBOL_LOC_REGISTER:
+                sym = nsym
+
+        stream.write (sym.print_name + "=")
+        try:
+            val = self.read_var (sym)
+            if val != None:
+                val = str (val)
+        # FIXME: would be nice to have a more precise exception here.
+        except RuntimeError, text:
+            val = text
+        if val == None:
+            stream.write ("???")
+        else:
+            stream.write (str (val))
+
+    def print_frame_locals (self, stream, func):
+        if not func:
+            return
+
+        first = True
+        block = func.value
+
+        for sym in block:
+            if sym.is_argument:
+                continue;
+
+            self.write_symbol (stream, sym, block)
+            stream.write ('\n')
+
+    def print_frame_args (self, stream, func):
+        if not func:
+            return
+
+        first = True
+        block = func.value
+
+        for sym in block:
+            if not sym.is_argument:
+                continue;
+
+            if not first:
+                stream.write (", ")
+
+            self.write_symbol (stream, sym, block)
+            first = False
+
+    # FIXME: this should probably just be a method on gdb.Frame.
+    # But then we need stream wrappers.
+    def describe (self, stream, full):
+        if self.type () == gdb.DUMMY_FRAME:
+            stream.write (" <function called from gdb>\n")
+        elif self.type () == gdb.SIGTRAMP_FRAME:
+            stream.write (" <signal handler called>\n")
+        else:
+            sal = self.find_sal ()
+            pc = self.pc ()
+            name = self.name ()
+            if not name:
+                name = "??"
+            if pc != sal.pc or not sal.symtab:
+                stream.write (" 0x%08x in" % pc)
+            stream.write (" " + name + " (")
+
+            func = self.function ()
+            self.print_frame_args (stream, func)
+
+            stream.write (")")
+
+            if sal.symtab and sal.symtab.filename:
+                stream.write (" at " + sal.symtab.filename)
+                stream.write (":" + str (sal.line))
+
+            if not self.name () or (not sal.symtab or not sal.symtab.filename):
+                lib = gdb.solib_address (pc)
+                if lib:
+                    stream.write (" from " + lib)
+
+            stream.write ("\n")
+
+            if full:
+                self.print_frame_locals (stream, func)
+
+    def __getattr__ (self, name):
+        return getattr (self.frame, name)
diff --git a/gdb/python/lib/gdb/__init__.py b/gdb/python/lib/gdb/__init__.py
new file mode 100644
index 0000000..b375c68
--- /dev/null
+++ b/gdb/python/lib/gdb/__init__.py
@@ -0,0 +1,19 @@
+# Startup code.
+
+# Copyright (C) 2008 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/>.
+
+# Load the require command by default.
+import gdb.command.require
diff --git a/gdb/python/lib/gdb/backtrace.py b/gdb/python/lib/gdb/backtrace.py
new file mode 100644
index 0000000..2baab5f
--- /dev/null
+++ b/gdb/python/lib/gdb/backtrace.py
@@ -0,0 +1,42 @@
+# Filtering backtrace.
+
+# Copyright (C) 2008 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/>.
+
+import gdb
+import itertools
+
+# Our only exports.
+__all__ = ['push_frame_filter', 'create_frame_filter']
+
+frame_filter = None
+
+def push_frame_filter (constructor):
+    """Register a new backtrace filter class with the 'backtrace' command.
+The filter will be passed an iterator as an argument.  The iterator
+will return gdb.Frame-like objects.  The filter should in turn act as
+an iterator returning such objects."""
+    global frame_filter
+    if frame_filter == None:
+        frame_filter = constructor
+    else:
+        frame_filter = lambda iterator: constructor (frame_filter (iterator))
+
+def create_frame_filter (iter):
+    global frame_filter
+    if frame_filter is None:
+        return iter
+    return frame_filter (iter)
+
diff --git a/gdb/python/lib/gdb/command/__init__.py b/gdb/python/lib/gdb/command/__init__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/gdb/python/lib/gdb/command/__init__.py
@@ -0,0 +1 @@
+
diff --git a/gdb/python/lib/gdb/command/alias.py b/gdb/python/lib/gdb/command/alias.py
new file mode 100644
index 0000000..96b6618
--- /dev/null
+++ b/gdb/python/lib/gdb/command/alias.py
@@ -0,0 +1,59 @@
+# Alias command.
+
+# Copyright (C) 2008 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/>.
+
+import gdb
+
+class AliasImplementation (gdb.Command):
+    def __init__ (self, name, real, doc):
+        # Have to set __doc__ before the super init call.
+        # It would be nice if gdb's help looked up __doc__ dynamically.
+        self.__doc__ = doc
+        # Note: no good way to complete :(
+        super (AliasImplementation, self).__init__ (name, gdb.COMMAND_NONE)
+        self.real = real
+
+    def invoke(self, arg, from_tty):
+        gdb.execute (self.real + ' ' + arg, from_tty)
+
+class AliasCommand (gdb.Command):
+    """Alias one command to another.
+In the simplest form, the first word is the name of the alias, and
+the remaining words are the the expansion.
+An '=' by itself can be used to define a multi-word alias; words
+before the '=' are the name of the new command."""
+
+    def __init__ (self):
+        # Completion is not quite right here.
+        super (AliasCommand, self).__init__ ("alias", gdb.COMMAND_NONE,
+                                             gdb.COMPLETE_COMMAND)
+
+    def invoke (self, arg, from_tty):
+        self.dont_repeat ()
+        # Without some form of quoting we can't alias a multi-word
+        # command to another command.
+        args = arg.split()
+        try:
+            start = args.index ('=')
+            end = start + 1
+        except ValueError:
+            start = 1
+            end = 1
+        target = " ".join(args[end:])
+        AliasImplementation (" ".join (args[0:start]), target,
+                             "This command is an alias for '%s'." % target)
+
+AliasCommand()
diff --git a/gdb/python/lib/gdb/command/backtrace.py b/gdb/python/lib/gdb/command/backtrace.py
new file mode 100644
index 0000000..ec9a527
--- /dev/null
+++ b/gdb/python/lib/gdb/command/backtrace.py
@@ -0,0 +1,106 @@
+# New backtrace command.
+
+# Copyright (C) 2008, 2009 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/>.
+
+import gdb
+import gdb.backtrace
+import itertools
+from gdb.FrameIterator import FrameIterator
+from gdb.FrameWrapper import FrameWrapper
+import sys
+
+class ReverseBacktraceParameter (gdb.Parameter):
+    """The new-backtrace command can show backtraces in 'reverse' order.
+This means that the innermost frame will be printed last.
+Note that reverse backtraces are more expensive to compute."""
+
+    set_doc = "Enable or disable reverse backtraces."
+    show_doc = "Show whether backtraces will be printed in reverse order."
+
+    def __init__(self):
+        gdb.Parameter.__init__ (self, "reverse-backtrace",
+                                gdb.COMMAND_STACK, gdb.PARAM_BOOLEAN)
+        # Default to compatibility with gdb.
+        self.value = False
+
+class FilteringBacktrace (gdb.Command):
+    """Print backtrace of all stack frames, or innermost COUNT frames.
+With a negative argument, print outermost -COUNT frames.
+Use of the 'full' qualifier also prints the values of the local variables.
+Use of the 'raw' qualifier avoids any filtering by loadable modules.
+"""
+
+    def __init__ (self):
+        # FIXME: this is not working quite well enough to replace
+        # "backtrace" yet.
+        gdb.Command.__init__ (self, "new-backtrace", gdb.COMMAND_STACK)
+        self.reverse = ReverseBacktraceParameter()
+
+    def reverse_iter (self, iter):
+        result = []
+        for item in iter:
+            result.append (item)
+        result.reverse()
+        return result
+
+    def final_n (self, iter, x):
+        result = []
+        for item in iter:
+            result.append (item)
+        return result[x:]
+
+    def invoke (self, arg, from_tty):
+        i = 0
+        count = 0
+        filter = True
+        full = False
+
+        for word in arg.split (" "):
+            if word == '':
+                continue
+            elif word == 'raw':
+                filter = False
+            elif word == 'full':
+                full = True
+            else:
+                count = int (word)
+
+        # FIXME: provide option to start at selected frame
+        # However, should still number as if starting from newest
+	newest_frame = gdb.selected_thread ().newest_frame ()
+        iter = itertools.imap (FrameWrapper,
+                               FrameIterator (newest_frame))
+        if filter:
+            iter = gdb.backtrace.create_frame_filter (iter)
+
+        # Now wrap in an iterator that numbers the frames.
+        iter = itertools.izip (itertools.count (0), iter)
+
+        # Reverse if the user wanted that.
+        if self.reverse.value:
+            iter = self.reverse_iter (iter)
+
+        # Extract sub-range user wants.
+        if count < 0:
+            iter = self.final_n (iter, count)
+        elif count > 0:
+            iter = itertools.islice (iter, 0, count)
+
+        for pair in iter:
+            sys.stdout.write ("#%-2d" % pair[0])
+            pair[1].describe (sys.stdout, full)
+
+FilteringBacktrace()
diff --git a/gdb/python/lib/gdb/command/ignore_errors.py b/gdb/python/lib/gdb/command/ignore_errors.py
new file mode 100644
index 0000000..6fa48ff
--- /dev/null
+++ b/gdb/python/lib/gdb/command/ignore_errors.py
@@ -0,0 +1,37 @@
+# Ignore errors in user commands.
+
+# Copyright (C) 2008 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/>.
+
+import gdb
+
+class IgnoreErrorsCommand (gdb.Command):
+    """Execute a single command, ignoring all errors.
+Only one-line commands are supported.
+This is primarily useful in scripts."""
+
+    def __init__ (self):
+        super (IgnoreErrorsCommand, self).__init__ ("ignore-errors",
+                                                    gdb.COMMAND_OBSCURE,
+                                                    # FIXME...
+                                                    gdb.COMPLETE_COMMAND)
+
+    def invoke (self, arg, from_tty):
+        try:
+            gdb.execute (arg, from_tty)
+        except:
+            pass
+
+IgnoreErrorsCommand ()
diff --git a/gdb/python/lib/gdb/command/pahole.py b/gdb/python/lib/gdb/command/pahole.py
new file mode 100644
index 0000000..21a0bf0
--- /dev/null
+++ b/gdb/python/lib/gdb/command/pahole.py
@@ -0,0 +1,75 @@
+# pahole command for gdb
+
+# Copyright (C) 2008, 2009 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/>.
+
+import gdb
+
+class Pahole (gdb.Command):
+    """Show the holes in a structure.
+This command takes a single argument, a type name.
+It prints the type and displays comments showing where holes are."""
+
+    def __init__ (self):
+        super (Pahole, self).__init__ ("pahole", gdb.COMMAND_NONE,
+                                       gdb.COMPLETE_SYMBOL)
+
+    def pahole (self, type, level, name):
+        if name is None:
+            name = ''
+        tag = type.tag
+        if tag is None:
+            tag = ''
+        print '%sstruct %s {' % (' ' * (2 * level), tag)
+        bitpos = 0
+        for field in type.fields ():
+            # Skip static fields.
+            if not hasattr (field, ('bitpos')):
+                continue
+
+            ftype = field.type.strip_typedefs()
+
+            if bitpos != field.bitpos:
+                hole = field.bitpos - bitpos
+                print '  /* XXX %d bit hole, try to pack */' % hole
+                bitpos = field.bitpos
+            if field.bitsize > 0:
+                fieldsize = field.bitsize
+            else:
+                # TARGET_CHAR_BIT here...
+                fieldsize = 8 * ftype.sizeof
+
+            # TARGET_CHAR_BIT
+            print ' /* %3d %3d */' % (int (bitpos / 8), int (fieldsize / 8)),
+            bitpos = bitpos + fieldsize
+
+            if ftype.code == gdb.TYPE_CODE_STRUCT:
+                self.pahole (ftype, level + 1, field.name)
+            else:
+                print ' ' * (2 + 2 * level),
+                print '%s %s' % (str (ftype), field.name)
+
+        print ' ' * (14 + 2 * level),
+        print '} %s' % name
+
+    def invoke (self, arg, from_tty):
+        type = gdb.lookup_type (arg)
+        type = type.strip_typedefs ()
+        if type.code != gdb.TYPE_CODE_STRUCT:
+            raise TypeError, '%s is not a struct type' % arg
+        print ' ' * 14,
+        self.pahole (type, 0, '')
+
+Pahole()
diff --git a/gdb/python/lib/gdb/command/require.py b/gdb/python/lib/gdb/command/require.py
new file mode 100644
index 0000000..1fbc1e8
--- /dev/null
+++ b/gdb/python/lib/gdb/command/require.py
@@ -0,0 +1,57 @@
+# Demand-loading commands.
+
+# Copyright (C) 2008, 2009 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/>.
+
+import gdb
+import os
+
+class RequireCommand (gdb.Command):
+    """Prefix command for requiring features."""
+
+    def __init__ (self):
+        super (RequireCommand, self).__init__ ("require",
+                                               gdb.COMMAND_SUPPORT,
+                                               gdb.COMPLETE_NONE,
+                                               True)
+
+class RequireSubcommand (gdb.Command):
+    """Demand-load a command by name."""
+
+    def __init__ (self, name):
+        self.__doc__ = "Demand-load a %s by name." % name
+        super (RequireSubcommand, self).__init__ ("require %s" % name,
+                                                  gdb.COMMAND_SUPPORT)
+        self.name = name
+
+    def invoke (self, arg, from_tty):
+        for cmd in arg.split():
+            exec ('import gdb.' + self.name + '.' + cmd, globals ())
+
+    def complete (self, text, word):
+        dir = gdb.pythondir + '/gdb/' + self.name
+        result = []
+        for file in os.listdir(dir):
+            if not file.startswith (word) or not file.endswith ('.py'):
+                continue
+            feature = file[0:-3]
+            if feature == 'require' or feature == '__init__':
+                continue
+            result.append (feature)
+        return result
+
+RequireCommand()
+RequireSubcommand("command")
+RequireSubcommand("function")
diff --git a/gdb/python/lib/gdb/command/save_breakpoints.py b/gdb/python/lib/gdb/command/save_breakpoints.py
new file mode 100644
index 0000000..6143187
--- /dev/null
+++ b/gdb/python/lib/gdb/command/save_breakpoints.py
@@ -0,0 +1,65 @@
+# Save breakpoints.
+
+# Copyright (C) 2008, 2009 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/>.
+
+from __future__ import with_statement
+import gdb
+
+class SavePrefixCommand (gdb.Command):
+  "Prefix command for saving things."
+
+  def __init__ (self):
+    super (SavePrefixCommand, self).__init__ ("save",
+                                              gdb.COMMAND_SUPPORT,
+                                              gdb.COMPLETE_NONE, True)
+
+class SaveBreakpointsCommand (gdb.Command):
+    """Save the current breakpoints to a file.
+This command takes a single argument, a file name.
+The breakpoints can be restored using the 'source' command."""
+
+    def __init__ (self):
+        super (SaveBreakpointsCommand, self).__init__ ("save breakpoints",
+                                                       gdb.COMMAND_SUPPORT,
+                                                       gdb.COMPLETE_FILENAME)
+
+    def invoke (self, arg, from_tty):
+        self.dont_repeat ()
+        bps = gdb.breakpoints ()
+        if bps is None:
+            raise RuntimeError, 'No breakpoints to save'
+        with open (arg.strip (), 'w') as f:
+            for bp in bps:
+                print >> f, "break", bp.location,
+                if bp.thread is not None:
+                    print >> f, " thread", bp.thread,
+                if bp.condition is not None:
+                    print >> f, " if", bp.condition,
+                print >> f
+                if not bp.enabled:
+                    print >> f, "disable $bpnum"
+                # Note: we don't save the ignore count; there doesn't
+                # seem to be much point.
+                commands = bp.commands
+                if commands is not None:
+                    print >> f, "commands"
+                    # Note that COMMANDS has a trailing newline.
+                    print >> f, commands,
+                    print >> f, "end"
+                print >> f
+
+SavePrefixCommand ()
+SaveBreakpointsCommand ()
diff --git a/gdb/python/lib/gdb/command/upto.py b/gdb/python/lib/gdb/command/upto.py
new file mode 100644
index 0000000..faf54ed
--- /dev/null
+++ b/gdb/python/lib/gdb/command/upto.py
@@ -0,0 +1,129 @@
+# upto command.
+
+# Copyright (C) 2009 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/>.
+
+import gdb
+import re
+from gdb.FrameIterator import FrameIterator
+from gdb.FrameWrapper import FrameWrapper
+
+class UptoPrefix (gdb.Command):
+    def __init__ (self):
+        super (UptoPrefix, self).__init__ ("upto", gdb.COMMAND_STACK,
+                                           prefix = True)
+
+class UptoImplementation (gdb.Command):
+    def __init__ (self, subcommand):
+        super (UptoImplementation, self).__init__ ("upto " + subcommand,
+                                                   gdb.COMMAND_STACK)
+
+    def search (self):
+        saved = gdb.selected_frame ()
+        iter = FrameIterator (saved)
+        found = False
+        try:
+            for frame in iter:
+                frame.select ()
+                try:
+                    if self.filter (frame):
+                        wrapper = FrameWrapper (frame)
+                        wrapper.describe (sys.stdout, False)
+                        return
+                except:
+                    pass
+        except:
+            pass
+        saved.select ()
+        raise RuntimeError, 'Could not find a matching frame'
+
+    def invoke (self, arg, from_tty):
+        self.rx = re.compile (arg)
+        self.search ()
+
+class UptoSymbolCommand (UptoImplementation):
+    """Select and print some calling stack frame, based on symbol.
+The argument is a regular expression.  This command moves up the
+stack, stopping at the first frame whose symbol matches the regular
+expression."""
+
+    def __init__ (self):
+        super (UptoSymbolCommand, self).__init__ ("symbol")
+
+    def filter (self, frame):
+        name = frame.name ()
+        if name is not None:
+            if self.rx.search (name) is not None:
+                return True
+        return False
+
+class UptoSourceCommand (UptoImplementation):
+    """Select and print some calling stack frame, based on source file.
+The argument is a regular expression.  This command moves up the
+stack, stopping at the first frame whose source file name matches the
+regular expression."""
+
+    def __init__ (self):
+        super (UptoSourceCommand, self).__init__ ("source")
+
+    def filter (self, frame):
+        name = frame.find_sal ().symtab.filename
+        if name is not None:
+            if self.rx.search (name) is not None:
+                return True
+        return False
+
+class UptoObjectCommand (UptoImplementation):
+    """Select and print some calling stack frame, based on object file.
+The argument is a regular expression.  This command moves up the
+stack, stopping at the first frame whose object file name matches the
+regular expression."""
+
+    def __init__ (self):
+        super (UptoObjectCommand, self).__init__ ("object")
+
+    def filter (self, frame):
+        name = frame.find_sal ().symtab.objfile.filename
+        if name is not None:
+            if self.rx.search (name) is not None:
+                return True
+        return False
+
+class UptoWhereCommand (UptoImplementation):
+    """Select and print some calling stack frame, based on expression.
+The argument is an expression.  This command moves up the stack,
+parsing and evaluating the expression in each frame.  This stops when
+the expression evaluates to a non-zero (true) value."""
+
+    def __init__ (self):
+        super (UptoWhereCommand, self).__init__ ("where")
+
+    def filter (self, frame):
+        try:
+            if gdb.parse_and_eval (self.expression):
+                return True
+        except:
+            pass
+        return False
+
+    def invoke (self, arg, from_tty):
+        self.expression = arg
+        self.search ()
+
+UptoPrefix ()
+UptoSymbolCommand ()
+UptoSourceCommand ()
+UptoObjectCommand ()
+UptoWhereCommand ()
diff --git a/gdb/python/lib/gdb/function/__init__.py b/gdb/python/lib/gdb/function/__init__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/gdb/python/lib/gdb/function/__init__.py
@@ -0,0 +1 @@
+
diff --git a/gdb/python/lib/gdb/function/caller_is.py b/gdb/python/lib/gdb/function/caller_is.py
new file mode 100644
index 0000000..2b9c5c7
--- /dev/null
+++ b/gdb/python/lib/gdb/function/caller_is.py
@@ -0,0 +1,58 @@
+# Caller-is functions.
+
+# Copyright (C) 2008 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/>.
+
+import gdb
+import re
+
+class CallerIs (gdb.Function):
+    """Return True if the calling function's name is equal to a string.
+This function takes one or two arguments.
+The first argument is the name of a function; if the calling function's
+name is equal to this argument, this function returns True.
+The optional second argument tells this function how many stack frames
+to traverse to find the calling function.  The default is 1."""
+
+    def __init__ (self):
+        super (CallerIs, self).__init__ ("caller_is")
+
+    def invoke (self, name, nframes = 1):
+        frame = gdb.selected_frame ()
+        while nframes > 0:
+            frame = frame.older ()
+            nframes = nframes - 1
+        return frame.name () == name.string ()
+
+class CallerMatches (gdb.Function):
+    """Return True if the calling function's name matches a string.
+This function takes one or two arguments.
+The first argument is a regular expression; if the calling function's
+name is matched by this argument, this function returns True.
+The optional second argument tells this function how many stack frames
+to traverse to find the calling function.  The default is 1."""
+
+    def __init__ (self):
+        super (CallerMatches, self).__init__ ("caller_matches")
+
+    def invoke (self, name, nframes = 1):
+        frame = gdb.selected_frame ()
+        while nframes > 0:
+            frame = frame.older ()
+            nframes = nframes - 1
+        return re.match (name.string (), frame.name ()) is not None
+
+CallerIs()
+CallerMatches()
diff --git a/gdb/python/lib/gdb/function/in_scope.py b/gdb/python/lib/gdb/function/in_scope.py
new file mode 100644
index 0000000..debb3bb
--- /dev/null
+++ b/gdb/python/lib/gdb/function/in_scope.py
@@ -0,0 +1,47 @@
+# In-scope function.
+
+# Copyright (C) 2008 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/>.
+
+import gdb
+
+class InScope (gdb.Function):
+    """Return True if all the given variables or macros are in scope.
+Takes one argument for each variable name to be checked."""
+
+    def __init__ (self):
+	super (InScope, self).__init__ ("in_scope")
+
+    def invoke (self, *vars):
+        if len (vars) == 0:
+	    raise TypeError, "in_scope takes at least one argument"
+
+        # gdb.Value isn't hashable so it can't be put in a map.
+	# Convert to string first.
+	wanted = set (map (lambda x: x.string (), vars))
+	found = set ()
+	block = gdb.selected_frame ().block ()
+	while block:
+	    for sym in block:
+		if (sym.is_argument or sym.is_constant
+		      or sym.is_function or sym.is_variable):
+		    if sym.name in wanted:
+			found.add (sym.name)
+
+	    block = block.superblock
+
+	return wanted == found
+
+InScope ()
diff --git a/gdb/python/py-block.c b/gdb/python/py-block.c
new file mode 100644
index 0000000..8019e9d
--- /dev/null
+++ b/gdb/python/py-block.c
@@ -0,0 +1,265 @@
+/* Python interface to blocks.
+
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 "defs.h"
+#include "block.h"
+#include "dictionary.h"
+#include "symtab.h"
+#include "python-internal.h"
+
+typedef struct {
+  PyObject_HEAD
+  struct block *block;
+} block_object;
+
+typedef struct {
+  PyObject_HEAD
+  struct dictionary *dict;
+  struct dict_iterator iter;
+  int initialized_p;
+} block_syms_iterator_object;
+
+static PyTypeObject block_syms_iterator_object_type;
+
+static PyObject *
+blpy_iter (PyObject *self)
+{
+  block_syms_iterator_object *block_iter_obj;
+
+  block_iter_obj = PyObject_New (block_syms_iterator_object,
+			    &block_syms_iterator_object_type);
+  if (block_iter_obj == NULL)
+    {
+      PyErr_SetString (PyExc_MemoryError,
+		       "Could not allocate iterator object.");
+      return NULL;
+    }
+
+  block_iter_obj->dict = BLOCK_DICT (((block_object *) self)->block);
+  block_iter_obj->initialized_p = 0;
+
+  return (PyObject *) block_iter_obj;
+}
+
+static PyObject *
+blpy_get_start (PyObject *self, void *closure)
+{
+  block_object *self_block = (block_object *) self;
+
+  return PyLong_FromUnsignedLongLong (BLOCK_START (self_block->block));
+}
+
+static PyObject *
+blpy_get_end (PyObject *self, void *closure)
+{
+  block_object *self_block = (block_object *) self;
+
+  return PyLong_FromUnsignedLongLong (BLOCK_END (self_block->block));
+}
+
+static PyObject *
+blpy_get_function (PyObject *self, void *closure)
+{
+  block_object *self_block = (block_object *) self;
+  struct symbol *sym;
+
+  sym = BLOCK_FUNCTION (self_block->block);
+  if (sym)
+    return symbol_to_symbol_object (sym);
+
+  Py_RETURN_NONE;
+}
+
+static PyObject *
+blpy_get_superblock (PyObject *self, void *closure)
+{
+  block_object *self_block = (block_object *) self;
+  struct block *block;
+
+  block = BLOCK_SUPERBLOCK (self_block->block);
+  if (block)
+    return block_to_block_object (block);
+
+  Py_RETURN_NONE;
+}
+
+PyObject *
+block_to_block_object (struct block *block)
+{
+  block_object *block_obj;
+
+  block_obj = PyObject_New (block_object, &block_object_type);
+  if (block_obj == NULL)
+    {
+      PyErr_SetString (PyExc_MemoryError, "Could not allocate block object.");
+      return NULL;
+    }
+
+  block_obj->block = block;
+
+  return (PyObject *) block_obj;
+}
+
+struct block *
+block_object_to_block (PyObject *obj)
+{
+  if (! PyObject_TypeCheck (obj, &block_object_type))
+    return NULL;
+  return ((block_object *) obj)->block;
+}
+
+static PyObject *
+blpy_block_syms_iter (PyObject *self)
+{
+  return self;
+}
+
+static PyObject *
+blpy_block_syms_iternext (PyObject *self)
+{
+  block_syms_iterator_object *iter_obj = (block_syms_iterator_object *) self;
+  struct symbol *sym;
+
+  if (!iter_obj->initialized_p)
+    {
+      sym = dict_iterator_first (iter_obj->dict,  &(iter_obj->iter));
+      iter_obj->initialized_p = 1;
+    }
+  else
+    sym = dict_iterator_next (&(iter_obj->iter));
+
+  return (sym == NULL)? NULL : symbol_to_symbol_object (sym);
+}
+
+/* Return the innermost lexical block containing the specified pc value,
+   or 0 if there is none.  */
+
+PyObject *
+gdbpy_block_for_pc (PyObject *self, PyObject *args)
+{
+  unsigned PY_LONG_LONG pc;
+  struct block *block;
+  PyObject *sym_obj;
+
+  if (!PyArg_ParseTuple (args, "K", &pc))
+    return NULL;
+
+  block = block_for_pc (pc);
+  if (block)
+    return block_to_block_object (block);
+
+  Py_RETURN_NONE;
+}
+
+void
+gdbpy_initialize_blocks (void)
+{
+  block_object_type.tp_new = PyType_GenericNew;
+  if (PyType_Ready (&block_object_type) < 0)
+    return;
+
+  block_syms_iterator_object_type.tp_new = PyType_GenericNew;
+  if (PyType_Ready (&block_syms_iterator_object_type) < 0)
+    return;
+
+  Py_INCREF (&block_object_type);
+  PyModule_AddObject (gdb_module, "Block", (PyObject *) &block_object_type);
+
+  Py_INCREF (&block_syms_iterator_object_type);
+  PyModule_AddObject (gdb_module, "BlockIterator",
+		      (PyObject *) &block_syms_iterator_object_type);
+}
+
+
+
+static PyGetSetDef block_object_getset[] = {
+  { "start", blpy_get_start, NULL, "Start address of the block.", NULL },
+  { "end", blpy_get_end, NULL, "End address of the block.", NULL },
+  { "function", blpy_get_function, NULL,
+    "Symbol that names the block, or None.", NULL },
+  { "superblock", blpy_get_superblock, NULL,
+    "Block containing the block, or None.", NULL },
+  { NULL }  /* Sentinel */
+};
+
+PyTypeObject block_object_type = {
+  PyObject_HEAD_INIT (NULL)
+  0,				  /*ob_size*/
+  "gdb.Block",			  /*tp_name*/
+  sizeof (block_object),	  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  0,				  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  0,				  /*tp_compare*/
+  0,				  /*tp_repr*/
+  0,				  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  0,				  /*tp_as_mapping*/
+  0,				  /*tp_hash */
+  0,				  /*tp_call*/
+  0,				  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  0,				  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,  /*tp_flags*/
+  "GDB block object",		  /* tp_doc */
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  blpy_iter,			  /* tp_iter */
+  0,				  /* tp_iternext */
+  0,				  /* tp_methods */
+  0,				  /* tp_members */
+  block_object_getset		  /* tp_getset */
+};
+
+static PyTypeObject block_syms_iterator_object_type = {
+  PyObject_HEAD_INIT (NULL)
+  0,				  /*ob_size*/
+  "gdb.BlockIterator",		  /*tp_name*/
+  sizeof (block_syms_iterator_object),	      /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  0,				  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  0,				  /*tp_compare*/
+  0,				  /*tp_repr*/
+  0,				  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  0,				  /*tp_as_mapping*/
+  0,				  /*tp_hash */
+  0,				  /*tp_call*/
+  0,				  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  0,				  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,  /*tp_flags*/
+  "GDB block syms iterator object",	      /* tp_doc */
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  blpy_block_syms_iter,		  /* tp_iter */
+  blpy_block_syms_iternext,	  /* tp_iternext */
+  0				  /* tp_methods */
+};
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
new file mode 100644
index 0000000..783385e
--- /dev/null
+++ b/gdb/python/py-breakpoint.c
@@ -0,0 +1,666 @@
+/* Python interface to breakpoints
+
+   Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 "defs.h"
+#include "value.h"
+#include "exceptions.h"
+#include "python-internal.h"
+#include "charset.h"
+#include "breakpoint.h"
+#include "gdbcmd.h"
+#include "gdbthread.h"
+#include "observer.h"
+#include "arch-utils.h"
+#include "language.h"
+
+/* From breakpoint.c.  */
+extern struct breakpoint *breakpoint_chain;
+
+
+typedef struct breakpoint_object breakpoint_object;
+
+static PyTypeObject breakpoint_object_type;
+
+/* A dynamically allocated vector of breakpoint objects.  Each
+   breakpoint has a number.  A breakpoint is valid if its slot in this
+   vector is non-null.  When a breakpoint is deleted, we drop our
+   reference to it and zero its slot; this is how we let the Python
+   object have a lifetime which is independent from that of the gdb
+   breakpoint.  */
+static breakpoint_object **bppy_breakpoints;
+
+/* Number of slots in bppy_breakpoints.  */
+static int bppy_slots;
+
+/* Number of live breakpoints.  */
+static int bppy_live;
+
+/* Variables used to pass information between the Breakpoint
+   constructor and the breakpoint-created hook function.  */
+static breakpoint_object *bppy_pending_object;
+
+struct breakpoint_object
+{
+  PyObject_HEAD
+
+  /* The breakpoint number according to gdb.  */
+  int number;
+
+  /* The gdb breakpoint object, or NULL if the breakpoint has been
+     deleted.  */
+  struct breakpoint *bp;
+};
+
+/* Evaluate to true if the breakpoint NUM is valid, false otherwise.  */
+#define BPPY_VALID_P(Num)			\
+    ((Num) >= 0					\
+     && (Num) < bppy_slots			\
+     && bppy_breakpoints[Num] != NULL)
+
+/* Require that BREAKPOINT be a valid breakpoint ID; throw a Python
+   exception if it is invalid.  */
+#define BPPY_REQUIRE_VALID(Breakpoint)					\
+    do {								\
+      if (! BPPY_VALID_P ((Breakpoint)->number))			\
+	return PyErr_Format (PyExc_RuntimeError, "breakpoint %d is invalid", \
+			     (Breakpoint)->number);			\
+    } while (0)
+
+/* Require that BREAKPOINT be a valid breakpoint ID; throw a Python
+   exception if it is invalid.  This macro is for use in setter functions.  */
+#define BPPY_SET_REQUIRE_VALID(Breakpoint)				\
+    do {								\
+      if (! BPPY_VALID_P ((Breakpoint)->number))			\
+        {								\
+	  PyErr_Format (PyExc_RuntimeError, "breakpoint %d is invalid", \
+			(Breakpoint)->number);				\
+	  return -1;							\
+	}								\
+    } while (0)
+
+/* Python function which checks the validity of a breakpoint object.  */
+static PyObject *
+bppy_is_valid (PyObject *self, PyObject *args)
+{
+  if (((breakpoint_object *) self)->bp)
+    Py_RETURN_TRUE;
+  Py_RETURN_FALSE;
+}
+
+/* Python function to test whether or not the breakpoint is enabled.  */
+static PyObject *
+bppy_get_enabled (PyObject *self, void *closure)
+{
+  if (! ((breakpoint_object *) self)->bp)
+    Py_RETURN_FALSE;
+  /* Not clear what we really want here.  */
+  if (((breakpoint_object *) self)->bp->enable_state == bp_enabled)
+    Py_RETURN_TRUE;
+  Py_RETURN_FALSE;
+}
+
+/* Python function to test whether or not the breakpoint is silent.  */
+static PyObject *
+bppy_get_silent (PyObject *self, void *closure)
+{
+  BPPY_REQUIRE_VALID ((breakpoint_object *) self);
+  if (((breakpoint_object *) self)->bp->silent)
+    Py_RETURN_TRUE;
+  Py_RETURN_FALSE;
+}
+
+/* Python function to set the enabled state of a breakpoint.  */
+static int
+bppy_set_enabled (PyObject *self, PyObject *newvalue, void *closure)
+{
+  breakpoint_object *self_bp = (breakpoint_object *) self;
+  int cmp;
+
+  BPPY_SET_REQUIRE_VALID (self_bp);
+
+  if (newvalue == NULL)
+    {
+      PyErr_SetString (PyExc_TypeError, "cannot delete `enabled' attribute");
+      return -1;
+    }
+  else if (! PyBool_Check (newvalue))
+    {
+      PyErr_SetString (PyExc_TypeError,
+		       "the value of `enabled' must be a boolean");
+      return -1;
+    }
+
+  cmp = PyObject_IsTrue (newvalue);
+  if (cmp < 0)
+    return -1;
+  else if (cmp == 1)
+    enable_breakpoint (self_bp->bp);
+  else 
+    disable_breakpoint (self_bp->bp);
+  return 0;
+}
+
+/* Python function to set the 'silent' state of a breakpoint.  */
+static int
+bppy_set_silent (PyObject *self, PyObject *newvalue, void *closure)
+{
+  breakpoint_object *self_bp = (breakpoint_object *) self;
+  int cmp;
+
+  BPPY_SET_REQUIRE_VALID (self_bp);
+
+  if (newvalue == NULL)
+    {
+      PyErr_SetString (PyExc_TypeError, "cannot delete `silent' attribute");
+      return -1;
+    }
+  else if (! PyBool_Check (newvalue))
+    {
+      PyErr_SetString (PyExc_TypeError,
+		       "the value of `silent' must be a boolean");
+      return -1;
+    }
+
+  cmp = PyObject_IsTrue (newvalue);
+  if (cmp < 0)
+    return -1;
+  else
+    self_bp->bp->silent = cmp;
+
+  return 0;
+}
+
+/* Python function to set the thread of a breakpoint.  */
+static int
+bppy_set_thread (PyObject *self, PyObject *newvalue, void *closure)
+{
+  breakpoint_object *self_bp = (breakpoint_object *) self;
+  int id;
+
+  BPPY_SET_REQUIRE_VALID (self_bp);
+
+  if (newvalue == NULL)
+    {
+      PyErr_SetString (PyExc_TypeError, "cannot delete `thread' attribute");
+      return -1;
+    }
+  else if (PyInt_Check (newvalue))
+    {
+      id = (int) PyInt_AsLong (newvalue);
+      if (! valid_thread_id (id))
+	{
+	  PyErr_SetString (PyExc_RuntimeError, "invalid thread id");
+	  return -1;
+	}
+    }
+  else if (newvalue == Py_None)
+    id = -1;
+  else
+    {
+      PyErr_SetString (PyExc_TypeError,
+		       "the value of `thread' must be an integer or None");
+      return -1;
+    }
+
+  self_bp->bp->thread = id;
+
+  return 0;
+}
+
+/* Python function to set the ignore count of a breakpoint.  */
+static int
+bppy_set_ignore_count (PyObject *self, PyObject *newvalue, void *closure)
+{
+  breakpoint_object *self_bp = (breakpoint_object *) self;
+  long value;
+
+  BPPY_SET_REQUIRE_VALID (self_bp);
+
+  if (newvalue == NULL)
+    {
+      PyErr_SetString (PyExc_TypeError,
+		       "cannot delete `ignore_count' attribute");
+      return -1;
+    }
+  else if (! PyInt_Check (newvalue))
+    {
+      PyErr_SetString (PyExc_TypeError,
+		       "the value of `ignore_count' must be an integer");
+      return -1;
+    }
+
+  value = PyInt_AsLong (newvalue);
+  if (value < 0)
+    value = 0;
+  set_ignore_count (self_bp->number, (int) value, 0);
+
+  return 0;
+}
+
+/* Python function to set the hit count of a breakpoint.  */
+static int
+bppy_set_hit_count (PyObject *self, PyObject *newvalue, void *closure)
+{
+  breakpoint_object *self_bp = (breakpoint_object *) self;
+
+  BPPY_SET_REQUIRE_VALID (self_bp);
+
+  if (newvalue == NULL)
+    {
+      PyErr_SetString (PyExc_TypeError, "cannot delete `hit_count' attribute");
+      return -1;
+    }
+  else if (! PyInt_Check (newvalue) || PyInt_AsLong (newvalue) != 0)
+    {
+      PyErr_SetString (PyExc_AttributeError,
+		       "the value of `hit_count' must be zero");
+      return -1;
+    }
+
+  self_bp->bp->hit_count = 0;
+
+  return 0;
+}
+
+/* Python function to get the location of a breakpoint.  */
+static PyObject *
+bppy_get_location (PyObject *self, void *closure)
+{
+  char *str;
+
+  BPPY_REQUIRE_VALID ((breakpoint_object *) self);
+  str = ((breakpoint_object *) self)->bp->addr_string;
+  /* FIXME: watchpoints?  tracepoints?  */
+  if (! str)
+    str = "";
+  return PyString_Decode (str, strlen (str), host_charset (), NULL);
+}
+
+/* Python function to get the condition expression of a breakpoint.  */
+static PyObject *
+bppy_get_condition (PyObject *self, void *closure)
+{
+  char *str;
+  BPPY_REQUIRE_VALID ((breakpoint_object *) self);
+
+  str = ((breakpoint_object *) self)->bp->cond_string;
+  if (! str)
+    Py_RETURN_NONE;
+  return PyString_Decode (str, strlen (str), host_charset (), NULL);
+}
+
+static int
+bppy_set_condition (PyObject *self, PyObject *newvalue, void *closure)
+{
+  char *exp;
+  breakpoint_object *self_bp = (breakpoint_object *) self;
+  volatile struct gdb_exception except;
+
+  BPPY_SET_REQUIRE_VALID (self_bp);
+
+  if (newvalue == NULL)
+    {
+      PyErr_SetString (PyExc_TypeError, "cannot delete `condition' attribute");
+      return -1;
+    }
+  else if (newvalue == Py_None)
+    exp = "";
+  else
+    {
+      exp = python_string_to_host_string (newvalue);
+      if (exp == NULL)
+	return -1;
+    }
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      set_breakpoint_condition (self_bp->bp, exp, 0);
+    }
+  GDB_PY_SET_HANDLE_EXCEPTION (except);
+
+  return 0;
+}
+
+/* Python function to get the commands attached to a breakpoint.  */
+static PyObject *
+bppy_get_commands (PyObject *self, void *closure)
+{
+  breakpoint_object *self_bp = (breakpoint_object *) self;
+  long length;
+  volatile struct gdb_exception except;
+  struct ui_file *string_file;
+  struct cleanup *chain;
+  PyObject *result;
+  char *cmdstr;
+
+  BPPY_REQUIRE_VALID (self_bp);
+
+  if (! self_bp->bp->commands)
+    Py_RETURN_NONE;
+
+  string_file = mem_fileopen ();
+  chain = make_cleanup_ui_file_delete (string_file);
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      /* FIXME: this can fail.  Maybe we need to be making a new
+	 ui_out object here?  */
+      ui_out_redirect (uiout, string_file);
+      print_command_lines (uiout, self_bp->bp->commands, 0);
+      ui_out_redirect (uiout, NULL);
+    }
+  cmdstr = ui_file_xstrdup (string_file, &length);
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  result = PyString_Decode (cmdstr, strlen (cmdstr), host_charset (), NULL);
+  do_cleanups (chain);
+  xfree (cmdstr);
+  return result;
+}
+
+/* Python function to get the breakpoint's number.  */
+static PyObject *
+bppy_get_number (PyObject *self, void *closure)
+{
+  breakpoint_object *self_bp = (breakpoint_object *) self;
+
+  BPPY_REQUIRE_VALID (self_bp);
+
+  return PyInt_FromLong (self_bp->number);
+}
+
+/* Python function to get the breakpoint's thread ID.  */
+static PyObject *
+bppy_get_thread (PyObject *self, void *closure)
+{
+  breakpoint_object *self_bp = (breakpoint_object *) self;
+
+  BPPY_REQUIRE_VALID (self_bp);
+
+  if (self_bp->bp->thread == -1)
+    Py_RETURN_NONE;
+
+  return PyInt_FromLong (self_bp->bp->thread);
+}
+
+/* Python function to get the breakpoint's hit count.  */
+static PyObject *
+bppy_get_hit_count (PyObject *self, void *closure)
+{
+  breakpoint_object *self_bp = (breakpoint_object *) self;
+
+  BPPY_REQUIRE_VALID (self_bp);
+
+  return PyInt_FromLong (self_bp->bp->hit_count);
+}
+
+/* Python function to get the breakpoint's ignore count.  */
+static PyObject *
+bppy_get_ignore_count (PyObject *self, void *closure)
+{
+  breakpoint_object *self_bp = (breakpoint_object *) self;
+
+  BPPY_REQUIRE_VALID (self_bp);
+
+  return PyInt_FromLong (self_bp->bp->ignore_count);
+}
+
+/* Python function to create a new breakpoint.  */
+static PyObject *
+bppy_new (PyTypeObject *subtype, PyObject *args, PyObject *kwargs)
+{
+  PyObject *result;
+  char *spec;
+  volatile struct gdb_exception except;
+
+  /* FIXME: allow condition, thread, temporary, ... ? */
+  if (! PyArg_ParseTuple (args, "s", &spec))
+    return NULL;
+  result = subtype->tp_alloc (subtype, 0);
+  if (! result)
+    return NULL;
+  bppy_pending_object = (breakpoint_object *) result;
+  bppy_pending_object->number = -1;
+  bppy_pending_object->bp = NULL;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      set_breakpoint (python_gdbarch, spec, NULL, 0, 0, -1, 0,
+		      AUTO_BOOLEAN_TRUE, 1);
+    }
+  if (except.reason < 0)
+    {
+      subtype->tp_free (result);
+      return PyErr_Format (except.reason == RETURN_QUIT
+			     ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
+			     "%s", except.message);
+    }
+
+  BPPY_REQUIRE_VALID ((breakpoint_object *) result);
+  return result;
+}
+
+
+
+/* Static function to return a tuple holding all breakpoints.  */
+
+PyObject *
+gdbpy_breakpoints (PyObject *self, PyObject *args)
+{
+  PyObject *result;
+
+  if (bppy_live == 0)
+    Py_RETURN_NONE;
+
+  result = PyTuple_New (bppy_live);
+  if (result)
+    {
+      int i, out = 0;
+      for (i = 0; out < bppy_live; ++i)
+	{
+	  if (! bppy_breakpoints[i])
+	    continue;
+	  Py_INCREF (bppy_breakpoints[i]);
+	  PyTuple_SetItem (result, out, (PyObject *) bppy_breakpoints[i]);
+	  ++out;
+	}
+    }
+  return result;
+}
+
+
+
+/* Event callback functions.  */
+
+/* Callback that is used when a breakpoint is created.  This function
+   will create a new Python breakpoint object.  */
+static void
+gdbpy_breakpoint_created (int num)
+{
+  breakpoint_object *newbp;
+  struct breakpoint *bp;
+  struct cleanup *cleanup;
+
+  if (num < 0)
+    return;
+
+  for (bp = breakpoint_chain; bp; bp = bp->next)
+    if (bp->number == num)
+      break;
+  if (! bp)
+    return;
+
+  if (num >= bppy_slots)
+    {
+      int old = bppy_slots;
+      bppy_slots = bppy_slots * 2 + 10;
+      bppy_breakpoints
+	= (breakpoint_object **) xrealloc (bppy_breakpoints,
+					   (bppy_slots
+					    * sizeof (breakpoint_object *)));
+      memset (&bppy_breakpoints[old], 0,
+	      (bppy_slots - old) * sizeof (PyObject *));
+    }
+
+  ++bppy_live;
+
+  cleanup = ensure_python_env (get_current_arch (), current_language);
+
+  if (bppy_pending_object)
+    {
+      newbp = bppy_pending_object;
+      bppy_pending_object = NULL;
+    }
+  else
+    newbp = PyObject_New (breakpoint_object, &breakpoint_object_type);
+  if (newbp)
+    {
+      PyObject *hookfn;
+
+      newbp->number = num;
+      newbp->bp = bp;
+      bppy_breakpoints[num] = newbp;
+
+      hookfn = gdbpy_get_hook_function ("new_breakpoint");
+      if (hookfn)
+	{
+	  PyObject *result;
+	  result = PyObject_CallFunctionObjArgs (hookfn, newbp, NULL);
+	  if (result)
+	    {
+	      Py_DECREF (result);
+	    }
+	  Py_DECREF (hookfn);
+	}
+    }
+
+  /* Just ignore errors here.  */
+  PyErr_Clear ();
+
+  do_cleanups (cleanup);
+}
+
+/* Callback that is used when a breakpoint is deleted.  This will
+   invalidate the corresponding Python object.  */
+static void
+gdbpy_breakpoint_deleted (int num)
+{
+  struct cleanup *cleanup;
+
+  cleanup = ensure_python_env (get_current_arch (), current_language);
+  if (BPPY_VALID_P (num))
+    {
+      bppy_breakpoints[num]->bp = NULL;
+      Py_DECREF (bppy_breakpoints[num]);
+      bppy_breakpoints[num] = NULL;
+      --bppy_live;
+    }
+  do_cleanups (cleanup);
+}
+
+
+
+/* Initialize the Python breakpoint code.  */
+void
+gdbpy_initialize_breakpoints (void)
+{
+  breakpoint_object_type.tp_new = bppy_new;
+  if (PyType_Ready (&breakpoint_object_type) < 0)
+    return;
+
+  Py_INCREF (&breakpoint_object_type);
+  PyModule_AddObject (gdb_module, "Breakpoint",
+		      (PyObject *) &breakpoint_object_type);
+
+  observer_attach_breakpoint_created (gdbpy_breakpoint_created);
+  observer_attach_breakpoint_deleted (gdbpy_breakpoint_deleted);
+}
+
+
+
+static PyGetSetDef breakpoint_object_getset[] = {
+  { "enabled", bppy_get_enabled, bppy_set_enabled,
+    "Boolean telling whether the breakpoint is enabled.", NULL },
+  { "silent", bppy_get_silent, bppy_set_silent,
+    "Boolean telling whether the breakpoint is silent.", NULL },
+  { "thread", bppy_get_thread, bppy_set_thread,
+    "Thread ID for the breakpoint.\n\
+If the value is a thread ID (integer), then this is a thread-specific breakpoint.\n\
+If the value is None, then this breakpoint not thread-specific.\n\
+No other type of value can be used.", NULL },
+  { "ignore_count", bppy_get_ignore_count, bppy_set_ignore_count,
+    "Number of times this breakpoint should be automatically continued.",
+    NULL },
+  { "number", bppy_get_number, NULL,
+    "Breakpoint's number assigned by GDB.", NULL },
+  { "hit_count", bppy_get_hit_count, bppy_set_hit_count,
+    "Number of times the breakpoint has been hit.\n\
+Can be set to zero to clear the count. No other value is valid\n\
+when setting this property.", NULL },
+  { "location", bppy_get_location, NULL,
+    "Location of the breakpoint, as specified by the user.", NULL},
+  { "condition", bppy_get_condition, bppy_set_condition,
+    "Condition of the breakpoint, as specified by the user,\
+or None if no condition set."},
+  { "commands", bppy_get_commands, NULL,
+    "Commands of the breakpoint, as specified by the user."},
+  { NULL }  /* Sentinel.  */
+};
+
+static PyMethodDef breakpoint_object_methods[] =
+{
+  { "is_valid", bppy_is_valid, METH_NOARGS,
+    "Return true if this breakpoint is valid, false if not." },
+  { NULL } /* Sentinel.  */
+};
+
+static PyTypeObject breakpoint_object_type =
+{
+  PyObject_HEAD_INIT (NULL)
+  0,				  /*ob_size*/
+  "gdb.Breakpoint",		  /*tp_name*/
+  sizeof (breakpoint_object),	  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  0,				  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  0,				  /*tp_compare*/
+  0,				  /*tp_repr*/
+  0,				  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  0,				  /*tp_as_mapping*/
+  0,				  /*tp_hash */
+  0,				  /*tp_call*/
+  0,				  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  0,				  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
+  "GDB breakpoint object",	  /* tp_doc */
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  0,				  /* tp_iter */
+  0,				  /* tp_iternext */
+  breakpoint_object_methods,	  /* tp_methods */
+  0,				  /* tp_members */
+  breakpoint_object_getset	  /* tp_getset */
+};
diff --git a/gdb/python/py-cmd.c b/gdb/python/py-cmd.c
index ae462d9..dd364df 100644
--- a/gdb/python/py-cmd.c
+++ b/gdb/python/py-cmd.c
@@ -49,8 +49,7 @@ static struct cmdpy_completer completers[] =
 
 #define N_COMPLETERS (sizeof (completers) / sizeof (completers[0]))
 
-/* A gdb command.  For the time being only ordinary commands (not
-   set/show commands) are allowed.  */
+/* A gdb command.  */
 struct cmdpy_object
 {
   PyObject_HEAD
@@ -263,10 +262,13 @@ cmdpy_completer (struct cmd_list_element *command, char *text, char *word)
    *BASE_LIST is set to the final prefix command's list of
    *sub-commands.
    
+   START_LIST is the list in which the search starts.
+   
    This function returns the xmalloc()d name of the new command.  On
    error sets the Python error and returns NULL.  */
-static char *
-parse_command_name (char *text, struct cmd_list_element ***base_list)
+char *
+gdbpy_parse_command_name (char *text, struct cmd_list_element ***base_list,
+			  struct cmd_list_element **start_list)
 {
   struct cmd_list_element *elt;
   int len = strlen (text);
@@ -299,7 +301,7 @@ parse_command_name (char *text, struct cmd_list_element ***base_list)
     ;
   if (i < 0)
     {
-      *base_list = &cmdlist;
+      *base_list = start_list;
       return result;
     }
 
@@ -308,7 +310,7 @@ parse_command_name (char *text, struct cmd_list_element ***base_list)
   prefix_text[i + 1] = '\0';
 
   text = prefix_text;
-  elt = lookup_cmd_1 (&text, cmdlist, NULL, 1);
+  elt = lookup_cmd_1 (&text, *start_list, NULL, 1);
   if (!elt || elt == (struct cmd_list_element *) -1)
     {
       PyErr_Format (PyExc_RuntimeError, _("could not find command prefix %s"),
@@ -399,7 +401,7 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw)
       return -1;
     }
 
-  cmd_name = parse_command_name (name, &cmd_list);
+  cmd_name = gdbpy_parse_command_name (name, &cmd_list, &cmdlist);
   if (! cmd_name)
     return -1;
 
diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index 334bad9..524353d 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -202,10 +202,59 @@ frapy_pc (PyObject *self, PyObject *args)
   return PyLong_FromUnsignedLongLong (pc);
 }
 
+/* Implementation of gdb.Frame.block (self) -> gdb.Block.
+   Returns the frame's code block.  */
+
+static PyObject *
+frapy_block (PyObject *self, PyObject *args)
+{
+  struct frame_info *frame;
+  struct block *block = NULL;
+  volatile struct gdb_exception except;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+
+      block = block_for_pc (get_frame_address_in_block (frame));
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  if (block)
+    return block_to_block_object (block);
+
+  Py_RETURN_NONE;
+}
+
+
+/* Implementation of gdb.Frame.function (self) -> gdb.Symbol.
+   Returns the symbol for the function corresponding to this frame.  */
+
+static PyObject *
+frapy_function (PyObject *self, PyObject *args)
+{
+  struct symbol *sym = NULL;
+  struct frame_info *frame;
+  volatile struct gdb_exception except;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+
+      sym = find_pc_function (get_frame_address_in_block (frame));
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  if (sym)
+    return symbol_to_symbol_object (sym);
+
+  Py_RETURN_NONE;
+}
+
 /* Convert a frame_info struct to a Python Frame object.
    Sets a Python exception and returns NULL on error.  */
 
-static frame_object *
+PyObject *
 frame_info_to_frame_object (struct frame_info *frame)
 {
   frame_object *frame_obj;
@@ -235,7 +284,7 @@ frame_info_to_frame_object (struct frame_info *frame)
 
   frame_obj->gdbarch = get_frame_arch (frame);
 
-  return frame_obj;
+  return (PyObject *) frame_obj;
 }
 
 /* Implementation of gdb.Frame.older (self) -> gdb.Frame.
@@ -296,7 +345,30 @@ frapy_newer (PyObject *self, PyObject *args)
   return next_obj;
 }
 
-/* Implementation of gdb.Frame.read_var_value (self, variable) -> gdb.Value.
+/* Implementation of gdb.Frame.find_sal (self) -> gdb.Symtab_and_line.
+   Returns the frame's symtab and line.  */
+
+static PyObject *
+frapy_find_sal (PyObject *self, PyObject *args)
+{
+  struct frame_info *frame;
+  struct symtab_and_line sal;
+  volatile struct gdb_exception except;
+  PyObject *sal_obj = NULL;   /* Initialize to appease gcc warning.  */
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      FRAPY_REQUIRE_VALID ((frame_object *) self, frame);
+
+      find_frame_sal (frame, &sal);
+      sal_obj = symtab_and_line_to_sal_object (sal);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  return sal_obj;
+}
+
+/* Implementation of gdb.Frame.read_var (self, variable) -> gdb.Value.
    Returns the value of the given variable in this frame.  The argument must be
    a string.  Returns None if GDB can't find the specified variable.  */
 
@@ -312,7 +384,9 @@ frapy_read_var (PyObject *self, PyObject *args)
   if (!PyArg_ParseTuple (args, "O", &sym_obj))
     return NULL;
 
-  if (gdbpy_is_string (sym_obj))
+  if (PyObject_TypeCheck (sym_obj, &symbol_object_type))
+    var = symbol_object_to_symbol (sym_obj);
+  else if (gdbpy_is_string (sym_obj))
     {
       char *var_name;
       struct block *block = NULL;
@@ -365,6 +439,25 @@ frapy_read_var (PyObject *self, PyObject *args)
   Py_RETURN_NONE;
 }
 
+/* Select this frame.  */
+
+static PyObject *
+frapy_select (PyObject *self, PyObject *args)
+{
+  struct frame_info *fi;
+  frame_object *frame = (frame_object *) self;
+  volatile struct gdb_exception except;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      FRAPY_REQUIRE_VALID (frame, fi);
+      select_frame (fi);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  Py_RETURN_NONE;
+}
+
 /* Implementation of gdb.selected_frame () -> gdb.Frame.
    Returns the selected frame object.  */
 
@@ -372,7 +465,7 @@ PyObject *
 gdbpy_selected_frame (PyObject *self, PyObject *args)
 {
   struct frame_info *frame;
-  frame_object *frame_obj = NULL;   /* Initialize to appease gcc warning.  */
+  PyObject *frame_obj = NULL;   /* Initialize to appease gcc warning.  */
   volatile struct gdb_exception except;
 
   TRY_CATCH (except, RETURN_MASK_ALL)
@@ -382,7 +475,7 @@ gdbpy_selected_frame (PyObject *self, PyObject *args)
     }
   GDB_PY_HANDLE_EXCEPTION (except);
 
-  return (PyObject *) frame_obj;
+  return frame_obj;
 }
 
 /* Implementation of gdb.stop_reason_string (Integer) -> String.
@@ -484,15 +577,26 @@ Return the reason why it's not possible to find frames older than this." },
   { "pc", frapy_pc, METH_NOARGS,
     "pc () -> Long.\n\
 Return the frame's resume address." },
+  { "block", frapy_block, METH_NOARGS,
+    "block () -> gdb.Block.\n\
+Return the frame's code block." },
+  { "function", frapy_function, METH_NOARGS,
+    "function () -> gdb.Symbol.\n\
+Returns the symbol for the function corresponding to this frame." },
   { "older", frapy_older, METH_NOARGS,
     "older () -> gdb.Frame.\n\
 Return the frame that called this frame." },
   { "newer", frapy_newer, METH_NOARGS,
     "newer () -> gdb.Frame.\n\
 Return the frame called by this frame." },
+  { "find_sal", frapy_find_sal, METH_NOARGS,
+    "find_sal () -> gdb.Symtab_and_line.\n\
+Return the frame's symtab and line." },
   { "read_var", frapy_read_var, METH_VARARGS,
     "read_var (variable) -> gdb.Value.\n\
 Return the value of the variable in this frame." },
+  { "select", frapy_select, METH_NOARGS,
+    "Select this frame as the user's current frame." },
   {NULL}  /* Sentinel */
 };
 
diff --git a/gdb/python/py-hooks.c b/gdb/python/py-hooks.c
new file mode 100644
index 0000000..a3140bc
--- /dev/null
+++ b/gdb/python/py-hooks.c
@@ -0,0 +1,50 @@
+/* Notifications from gdb to Python
+
+   Copyright (C) 2008 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 "defs.h"
+#include "cli/cli-decode.h"
+#include "charset.h"
+#include "python.h"
+#include "python-internal.h"
+#include "observer.h"
+
+PyObject *
+gdbpy_get_hook_function (const char *name)
+{
+  PyObject *hooks;
+  PyObject *result;
+
+  if (! PyObject_HasAttrString (gdb_module, "hooks"))
+    return NULL;
+  hooks = PyObject_GetAttrString (gdb_module, "hooks");
+  if (! hooks)
+    return NULL;
+  /* The cast is because the Python function doesn't declare const argument.
+     This is a problem in Python version 2.4, but not in 2.5.  */
+  if (! PyObject_HasAttrString (hooks, (char *) name))
+    {
+      Py_DECREF (hooks);
+      return NULL;
+    }
+  /* The cast is because the Python function doesn't declare const argument.
+     This is a problem in Python version 2.4, but not in 2.5.  */
+  result = PyObject_GetAttrString (hooks, (char *) name);
+  Py_DECREF (hooks);
+  return result;
+}
diff --git a/gdb/python/py-inferior.c b/gdb/python/py-inferior.c
new file mode 100644
index 0000000..b259ab5
--- /dev/null
+++ b/gdb/python/py-inferior.c
@@ -0,0 +1,934 @@
+/* Python interface to inferiors.
+
+   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 "defs.h"
+#include "exceptions.h"
+#include "gdbcore.h"
+#include "gdbthread.h"
+#include "inferior.h"
+#include "observer.h"
+#include "python-internal.h"
+#include "arch-utils.h"
+#include "language.h"
+
+struct threadlist_entry {
+  thread_object *thread_obj;
+  struct threadlist_entry *next;
+};
+
+typedef struct
+{
+  PyObject_HEAD
+
+  /* The inferior we represent.  */
+  struct inferior *inferior;
+
+  /* thread_object instances under this inferior.  This list owns a reference
+     to each object it contains. */
+  struct threadlist_entry *threads;
+
+  /* Number of threads in the list.  */
+  int nthreads;
+} inferior_object;
+
+static PyTypeObject inferior_object_type;
+
+typedef struct {
+  PyObject_HEAD
+  void *buffer;
+
+  /* These are kept just for mbpy_str.  */
+  CORE_ADDR addr;
+  CORE_ADDR length;
+} membuf_object;
+
+static PyTypeObject membuf_object_type;
+
+/* Require that INFERIOR be a valid inferior ID.  */
+#define INFPY_REQUIRE_VALID(Inferior)				\
+  do {								\
+    if (!Inferior->inferior)					\
+      {								\
+	PyErr_SetString (PyExc_RuntimeError,			\
+			 "inferior no longer exists");	        \
+	return NULL;						\
+      }								\
+  } while (0)
+
+struct inflist_entry {
+  inferior_object *inf_obj;
+  struct inflist_entry *next;
+};
+
+
+
+/* Inferior objects list.  */
+
+/* List containing inferior_objects.  This list owns a reference to each
+   object it contains.  */
+static struct inflist_entry *gdbpy_inferior_list;
+
+static int ninferiors;
+
+
+/* An observer callback function that is called when an inferior has
+   been created.  Creates a corresponding Python object for the inferior
+   and adds it to the list.  */
+static void
+add_inferior_object (int pid)
+{
+  struct inferior *inf = find_inferior_pid (pid);
+  inferior_object *inf_obj;
+  struct inflist_entry *entry;
+  struct cleanup *cleanup;
+
+  if (!inf)
+    {
+      warning (_("Can't create Python Inferior object."));
+      return;
+    }
+
+  /* While creating new inferior no inferior thread is available.  Therefore
+     get_current_arch has no valid current frame (and it would crash).  */
+
+  cleanup = ensure_python_env (target_gdbarch, current_language);
+
+  inf_obj = PyObject_New (inferior_object, &inferior_object_type);
+  if (!inf_obj)
+    {
+      warning (_("Can't create Python Inferior object."));
+      gdbpy_print_stack ();
+      do_cleanups (cleanup);
+      return;
+    }
+
+  inf_obj->inferior = inf;
+  inf_obj->threads = NULL;
+  inf_obj->nthreads = 0;
+
+  entry = xmalloc (sizeof (struct inflist_entry));
+  entry->inf_obj = inf_obj;
+  entry->next = gdbpy_inferior_list;
+
+  gdbpy_inferior_list = entry;
+
+  ninferiors++;
+
+  do_cleanups (cleanup);
+}
+
+/* An observer callback function that is called when an inferior has
+   been deleted.  Removes the corresponding Python object from the
+   inferior list, and removes the list's reference to the object.  */
+static void
+delete_inferior_object (int pid)
+{
+  struct cleanup *cleanup;
+  struct inflist_entry **inf_entry, *inf_tmp;
+  struct threadlist_entry *th_entry, *th_tmp;
+
+  /* Find inferior_object for the given PID.  */
+  for (inf_entry = &gdbpy_inferior_list; *inf_entry != NULL;
+       inf_entry = &(*inf_entry)->next)
+    if ((*inf_entry)->inf_obj->inferior->pid == pid)
+      break;
+
+  if (!*inf_entry)
+    return;
+
+  cleanup = ensure_python_env (get_current_arch (), current_language);
+
+  inf_tmp = *inf_entry;
+  inf_tmp->inf_obj->inferior = NULL;
+
+  /* Deallocate threads list.  */
+  for (th_entry = inf_tmp->inf_obj->threads; th_entry != NULL;)
+    {
+      Py_DECREF (th_entry->thread_obj);
+
+      th_tmp = th_entry;
+      th_entry = th_entry->next;
+      xfree (th_tmp);
+    }
+
+  inf_tmp->inf_obj->nthreads = 0;
+
+  *inf_entry = (*inf_entry)->next;
+  Py_DECREF (inf_tmp->inf_obj);
+  xfree (inf_tmp);
+
+  ninferiors--;
+
+  do_cleanups (cleanup);
+}
+
+/* Finds the Python Inferior object for the given pid.  Returns a borrowed
+   reference.  */
+PyObject *
+find_inferior_object (int pid)
+{
+  struct inflist_entry *p;
+
+  for (p = gdbpy_inferior_list; p != NULL; p = p->next)
+    if (p->inf_obj->inferior->pid == pid)
+      return (PyObject *) p->inf_obj;
+
+  return NULL;
+}
+
+/* Finds the Python InferiorThread object for the given ptid.  Returns a
+   borrowed reference.  */
+thread_object *
+find_thread_object (ptid_t ptid)
+{
+  int pid;
+  struct inflist_entry *p;
+  struct threadlist_entry *q;
+
+  pid = PIDGET (ptid);
+  for (p = gdbpy_inferior_list; p != NULL; p = p->next)
+    if (p->inf_obj->inferior->pid == pid)
+      for (q = p->inf_obj->threads; q != NULL; q = q->next)
+	if (ptid_equal (q->thread_obj->thread->ptid, ptid))
+	  return q->thread_obj;
+
+  return NULL;
+}
+
+
+
+/* Inferior object.  */
+
+static void
+add_thread_object (struct thread_info *tp)
+{
+  struct cleanup *cleanup;
+  thread_object *thread_obj;
+  inferior_object *inf_obj;
+  struct threadlist_entry *entry;
+
+  /* Note that the arch does not matter here, because we can't run
+     arbitrary Python code.  Calling get_current_arch here will
+     crash.  */
+  cleanup = ensure_python_env (target_gdbarch, current_language);
+
+  thread_obj = create_thread_object (tp);
+  if (!thread_obj)
+    {
+      warning (_("Can't create Python InferiorThread object."));
+      gdbpy_print_stack ();
+      do_cleanups (cleanup);
+      return;
+    }
+
+  inf_obj = (inferior_object *) thread_obj->inf_obj;
+
+  entry = xmalloc (sizeof (struct threadlist_entry));
+  entry->thread_obj = thread_obj;
+  entry->next = inf_obj->threads;
+
+  inf_obj->threads = entry;
+  inf_obj->nthreads++;
+
+  do_cleanups (cleanup);
+}
+
+static void
+delete_thread_object (struct thread_info *tp, int ignore)
+{
+  struct cleanup *cleanup;
+  inferior_object *inf_obj;
+  thread_object *thread_obj;
+  struct threadlist_entry **entry, *tmp;
+
+  inf_obj = (inferior_object *) find_inferior_object (PIDGET(tp->ptid));
+  if (!inf_obj)
+    return;
+
+  /* Find thread entry in its inferior's thread_list.  */
+  for (entry = &inf_obj->threads; *entry != NULL; entry = &(*entry)->next)
+    if ((*entry)->thread_obj->thread == tp)
+      break;
+
+  if (!*entry)
+    return;
+
+  cleanup = ensure_python_env (get_current_arch (), current_language);
+
+  tmp = *entry;
+  tmp->thread_obj->thread = NULL;
+
+  *entry = (*entry)->next;
+  inf_obj->nthreads--;
+
+  Py_DECREF (tmp->thread_obj);
+  xfree (tmp);
+
+
+  do_cleanups (cleanup);
+}
+
+static PyObject *
+infpy_threads (PyObject *self, PyObject *args)
+{
+  int i;
+  struct threadlist_entry *entry;
+  inferior_object *inf_obj = (inferior_object *) self;
+  PyObject *tuple;
+
+  INFPY_REQUIRE_VALID (inf_obj);
+
+
+  tuple = PyTuple_New (inf_obj->nthreads);
+  if (!tuple)
+    return NULL;
+
+  /* The list is in reverse order of thread age (i.e., newest comes first),
+     is this a problem?  */
+  for (i = 0, entry = inf_obj->threads; i < inf_obj->nthreads;
+       i++, entry = entry->next)
+    {
+      Py_INCREF (entry->thread_obj);
+      PyTuple_SET_ITEM (tuple, i, (PyObject *) entry->thread_obj);
+    }
+
+  return tuple;
+}
+
+static PyObject *
+infpy_get_num (PyObject *self, void *closure)
+{
+  inferior_object *inf = (inferior_object *) self;
+
+  INFPY_REQUIRE_VALID (inf);
+
+  return PyLong_FromLong (inf->inferior->num);
+}
+
+static PyObject *
+infpy_get_pid (PyObject *self, void *closure)
+{
+  inferior_object *inf = (inferior_object *) self;
+
+  INFPY_REQUIRE_VALID (inf);
+
+  return PyLong_FromLong (inf->inferior->pid);
+}
+
+static PyObject *
+infpy_get_was_attached (PyObject *self, void *closure)
+{
+  inferior_object *inf = (inferior_object *) self;
+  INFPY_REQUIRE_VALID (inf);
+  if (inf->inferior->attach_flag)
+    Py_RETURN_TRUE;
+  Py_RETURN_FALSE;
+}
+
+
+
+/* Implementation of gdb.inferiors () -> (gdb.Inferior, ...).
+   Returns a list of all inferiors.  */
+
+PyObject *
+gdbpy_inferiors (PyObject *unused, PyObject *unused2)
+{
+  int i;
+  struct inflist_entry *entry;
+  PyObject *tuple;
+
+  tuple = PyTuple_New (ninferiors);
+  if (!tuple)
+    return NULL;
+
+  /* The list is in reverse order of inferior age (i.e., newest comes first),
+     is this a problem?  */
+  for (i = 0, entry = gdbpy_inferior_list;
+       i < ninferiors;
+       i++, entry = entry->next)
+    {
+      Py_INCREF (entry->inf_obj);
+      PyTuple_SET_ITEM (tuple, i, (PyObject *) entry->inf_obj);
+    }
+
+  return tuple;
+}
+
+
+
+/* Membuf and memory manipulation.  */
+
+/* Implementation of gdb.read_memory (address, length).
+   Returns a Python buffer object with LENGTH bytes of the inferior's memory
+   at ADDRESS. Both arguments are integers.  */
+
+static PyObject *
+infpy_read_memory (PyObject *self, PyObject *args)
+{
+  int error = 0;
+  CORE_ADDR addr, length;
+  void *buffer = NULL;
+  membuf_object *membuf_obj;
+  PyObject *addr_obj, *length_obj;
+  struct cleanup *cleanups;
+  volatile struct gdb_exception except;
+
+  if (! PyArg_ParseTuple (args, "OO", &addr_obj, &length_obj))
+    return NULL;
+
+  cleanups = make_cleanup (null_cleanup, NULL);
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (!get_addr_from_python (addr_obj, &addr)
+	  || !get_addr_from_python (length_obj, &length))
+	{
+	  error = 1;
+	  break;
+	}
+
+      buffer = xmalloc (length);
+      make_cleanup (xfree, buffer);
+
+      read_memory (addr, buffer, length);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  if (error)
+    {
+      do_cleanups (cleanups);
+      return NULL;
+    }
+
+  membuf_obj = PyObject_New (membuf_object, &membuf_object_type);
+  if (membuf_obj == NULL)
+    {
+      PyErr_SetString (PyExc_MemoryError,
+		       "Could not allocate memory buffer object.");
+      do_cleanups (cleanups);
+      return NULL;
+    }
+
+  discard_cleanups (cleanups);
+
+  membuf_obj->buffer = buffer;
+  membuf_obj->addr = addr;
+  membuf_obj->length = length;
+
+  return PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj, 0,
+				       Py_END_OF_BUFFER);
+}
+
+/* Implementation of gdb.write_memory (address, buffer [, length]).
+   Writes the contents of BUFFER (a Python object supporting the read buffer
+   protocol) at ADDRESS in the inferior's memory.  Write LENGTH bytes from
+   BUFFER, or its entire contents if the argument is not provided.  The
+   function returns nothing.  */
+
+static PyObject *
+infpy_write_memory (PyObject *self, PyObject *args)
+{
+  int buf_len, error = 0;
+  const char *buffer;
+  CORE_ADDR addr, length;
+  PyObject *addr_obj, *length_obj = NULL;
+  volatile struct gdb_exception except;
+
+  if (! PyArg_ParseTuple (args, "Os#|O", &addr_obj, &buffer, &buf_len,
+			  &length_obj))
+    return NULL;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (!get_addr_from_python (addr_obj, &addr))
+	{
+	  error = 1;
+	  break;
+	}
+      
+      if (!length_obj)
+	length = buf_len;
+      else if (!get_addr_from_python (length_obj, &length))
+	{
+	  error = 1;
+	  break;
+	}
+
+      write_memory (addr, buffer, length);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  if (error)
+    return NULL;
+
+  Py_RETURN_NONE;
+}
+
+/* Destructor of Membuf objects.  */
+
+static void
+mbpy_dealloc (PyObject *self)
+{
+  xfree (((membuf_object *) self)->buffer);
+  self->ob_type->tp_free (self);
+}
+
+/* Return a description of the Membuf object.  */
+
+static PyObject *
+mbpy_str (PyObject *self)
+{
+  membuf_object *membuf_obj = (membuf_object *) self;
+
+  return PyString_FromFormat ("memory buffer for address %s, %s bytes long",
+			      paddress (python_gdbarch, membuf_obj->addr),
+			      pulongest (membuf_obj->length));
+}
+
+static Py_ssize_t
+get_read_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr)
+{
+  membuf_object *membuf_obj = (membuf_object *) self;
+
+  if (segment)
+    {
+      PyErr_SetString (PyExc_SystemError,
+		       "The memory buffer supports only one segment.");
+      return -1;
+    }
+
+  *ptrptr = membuf_obj->buffer;
+
+  return membuf_obj->length;
+}
+
+static Py_ssize_t
+get_write_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr)
+{
+  return get_read_buffer (self, segment, ptrptr);
+}
+
+static Py_ssize_t
+get_seg_count (PyObject *self, Py_ssize_t *lenp)
+{
+  if (lenp)
+    *lenp = ((membuf_object *) self)->length;
+
+  return 1;
+}
+
+static Py_ssize_t
+get_char_buffer (PyObject *self, Py_ssize_t segment, char **ptrptr)
+{
+  void *ptr = NULL;
+  Py_ssize_t ret;
+
+  ret = get_read_buffer (self, segment, &ptr);
+  *ptrptr = (char *) ptr;
+
+  return ret;
+}
+
+/* Adds GDB value V to the pattern buffer in *PATTERN_BUF.  If SIZE is not zero,
+   it specifies the number of bytes from V to copy to *PATTERN_BUF.  The
+   function increases the size of *PATTERN_BUF as necessary, adjusting
+   *PATTERN_BUF_END and *PATTERN_BUF_SIZE in the process.  */
+
+static void
+add_value_pattern (struct value *v, int size, char **pattern_buf,
+		   char **pattern_buf_end, ULONGEST *pattern_buf_size)
+{
+  int val_bytes;
+
+  if (size)
+    {
+      LONGEST x = value_as_long (v);
+
+      if (size == 1)
+	*(*pattern_buf_end)++ = x;
+      else
+	{
+	  put_bits (x, *pattern_buf_end, size * 8,
+		    gdbarch_byte_order (python_gdbarch) == BFD_ENDIAN_BIG);
+	  *pattern_buf_end += size;
+	}
+    }
+  else
+   {
+     val_bytes = TYPE_LENGTH (value_type (v));
+
+     increase_pattern_buffer (pattern_buf, pattern_buf_end,
+			      pattern_buf_size, val_bytes);
+
+     memcpy (*pattern_buf_end, value_contents_raw (v), val_bytes);
+     *pattern_buf_end += val_bytes;
+   }
+}
+
+/* This function does the actual work of constructing the pattern buffer from
+   OBJ.  If OBJ is an object which implements the read buffer protocol (such
+   as a string, a byte array or gdb.Membuf), then its contents are directly
+   copied to *PATTERN_BUF.  If it is a list, then this function is recursively
+   called for each of its elements.  If OBJ is an object which can be converted
+   to a GDB value, then the contents of the value are copied to PATTERN_BUF.
+   If SIZE is different than zero, then it limits the number of bytes which
+   are copied to the buffer in case OBJ is converted to a GDB value.  That
+   means that SIZE influences only Python scalars and gdb.Value objects.
+   The function increases the size of *PATTERN_BUF as necessary, adjusting
+   *PATTERN_BUF_END and *PATTERN_BUF_SIZE in the process.
+
+   Returns 1 on success or 0 on failure, with a Python exception set.  This
+   function can also throw GDB exceptions.  */
+
+static int
+add_pattern_element (PyObject *obj, int size, char **pattern_buf,
+		     char **pattern_buf_end, ULONGEST *pattern_buf_size)
+{
+  if (PyObject_CheckReadBuffer (obj))
+    {
+      /* Handle string, Unicode string, byte array, gdb.Membuf and any other
+         object implementing the buffer protocol.  The SIZE parameter is
+	 ignored in this case.  */
+
+      Py_ssize_t val_bytes;
+      const void *buffer;
+
+      if (PyObject_AsReadBuffer (obj, &buffer, &val_bytes) == -1)
+	return 0;
+
+      increase_pattern_buffer (pattern_buf, pattern_buf_end,
+			       pattern_buf_size, val_bytes);
+
+      memcpy (*pattern_buf_end, buffer, val_bytes);
+      *pattern_buf_end += val_bytes;
+    }
+  else if (gdbpy_is_value_object (obj))
+    add_value_pattern (value_object_to_value (obj), size, pattern_buf,
+		       pattern_buf_end, pattern_buf_size);
+  else if (PySequence_Check (obj))
+    {
+      /* Handle lists and tuples.  */
+
+      Py_ssize_t i, num_objs;
+
+      num_objs = PySequence_Size (obj);
+      for (i = 0; i < num_objs; i++)
+	if (!add_pattern_element (PySequence_GetItem (obj, i), size,
+				  pattern_buf, pattern_buf_end,
+				  pattern_buf_size))
+	  return 0;
+    }
+  else
+    {
+      /* See if we can convert from a Python object to a GDB value.  */
+
+      struct value *v = convert_value_from_python (obj);
+
+      if (v)
+	add_value_pattern (v, size, pattern_buf, pattern_buf_end,
+			   pattern_buf_size);
+      else
+	return 0;
+    }
+
+  return 1;
+}
+
+/* Constructs the search pattern from OBJ, putting it in *PATTERN_BUFP, and its
+   size in *PATTERN_LENP.  See the function add_pattern_element to learn how
+   the search pattern is obtained from OBJ.
+
+   Returns 1 on success or 0 on failure, with a Python exception set.  This
+   function can also throw GDB exceptions.  */
+
+static int
+get_search_pattern (PyObject *obj, int size, char **pattern_bufp,
+		    ULONGEST *pattern_lenp)
+{
+  /* Buffer to hold the search pattern.  */
+  char *pattern_buf;
+  /* Current size of search pattern buffer.
+     We realloc space as needed.  */
+  ULONGEST pattern_buf_size;
+  /* Pointer to one past the last in-use part of pattern_buf.  */
+  char *pattern_buf_end;
+  struct cleanup *old_cleanups;
+
+  allocate_pattern_buffer (&pattern_buf, &pattern_buf_end, &pattern_buf_size);
+  old_cleanups = make_cleanup (free_current_contents, &pattern_buf);
+
+  if (!add_pattern_element (obj, size, &pattern_buf, &pattern_buf_end,
+			    &pattern_buf_size))
+    {
+      do_cleanups (old_cleanups);
+
+      return 0;
+    }
+
+  *pattern_bufp = pattern_buf;
+  *pattern_lenp = pattern_buf_end - pattern_buf;
+
+  discard_cleanups (old_cleanups);
+
+  return 1;
+}
+
+/* Implementation of
+   gdb.search_memory (address, length, pattern [, size] [, max_count]).
+   The third argument may be either a pattern, or a list or tupple of patterns
+   to be searched.  Size is the size in bytes of each search query value, either
+   1, 2, 4 or 8.  Returns a list of the addresses where matches were found.  */
+
+static PyObject *
+infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
+{
+  int size = 0;
+  unsigned int found_count = 0;
+  long max_count = 0;
+  CORE_ADDR start_addr, length;
+  char *pattern_buf;
+  static char *keywords[] = { "address", "length", "pattern", "size",
+			      "max_count", NULL };
+  ULONGEST pattern_len, search_space_len;
+  PyObject *pattern, *list = NULL, *start_addr_obj, *length_obj;
+  volatile struct gdb_exception except;
+
+  if (! PyArg_ParseTupleAndKeywords (args, kw, "OOO|il", keywords,
+				     &start_addr_obj, &length_obj, &pattern,
+				     &size, &max_count))
+    return NULL;
+
+  if (!max_count)
+    max_count = LONG_MAX;
+
+  if (size != 0 && size != 1 && size != 2 && size != 4 && size != 8)
+    {
+      PyErr_SetString (PyExc_ValueError, "invalid pattern size");
+      return NULL;
+    }
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (get_addr_from_python (start_addr_obj, &start_addr)
+	  && get_addr_from_python (length_obj, &length))
+	{
+	  if (!length)
+	    {
+	      PyErr_SetString (PyExc_ValueError, "empty search range");
+	      break;
+	    }
+	  /* Watch for overflows.  */
+	  else if (length > CORE_ADDR_MAX
+		   || (start_addr + length - 1) < start_addr)
+	    {
+	      PyErr_SetString (PyExc_ValueError, "search range too large");
+	      break;
+	    }
+
+	  search_space_len = length;
+
+	  if (get_search_pattern (pattern, size, &pattern_buf, &pattern_len))
+	    {
+	      /* Any cleanups get automatically executed on an exception.  */
+	      struct cleanup *cleanups = make_cleanup (xfree, pattern_buf);
+
+	      list = PyList_New (0);
+
+	      while (search_space_len >= pattern_len && found_count < max_count)
+		{
+		  CORE_ADDR found_addr;
+		  int found;
+
+		  found = search_memory (&start_addr, &search_space_len,
+					 pattern_buf, pattern_len, &found_addr);
+		  if (found <= 0)
+		    break;
+
+		  PyList_Append (list, PyLong_FromUnsignedLong (found_addr));
+		  ++found_count;
+		}
+
+	      do_cleanups (cleanups);
+	    }
+	}
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  return list;
+}
+
+
+
+void
+gdbpy_initialize_inferior (void)
+{
+  if (PyType_Ready (&inferior_object_type) < 0)
+    return;
+
+  Py_INCREF (&inferior_object_type);
+  PyModule_AddObject (gdb_module, "Inferior",
+		      (PyObject *) &inferior_object_type);
+
+  gdbpy_inferior_list = NULL;
+  ninferiors = 0;
+
+  observer_attach_inferior_appeared (add_inferior_object);
+  observer_attach_inferior_exit (delete_inferior_object);
+  observer_attach_new_thread (add_thread_object);
+  observer_attach_thread_exit (delete_thread_object);
+
+  if (PyType_Ready (&membuf_object_type) < 0)
+    return;
+
+  Py_INCREF (&membuf_object_type);
+  PyModule_AddObject (gdb_module, "Membuf", (PyObject *) &membuf_object_type);
+}
+
+
+
+static PyGetSetDef inferior_object_getset[] =
+{
+  { "num", infpy_get_num, NULL, "ID of inferior, as assigned by GDB.", NULL },
+  { "pid", infpy_get_pid, NULL, "PID of inferior, as assigned by the OS.",
+    NULL },
+  { "was_attached", infpy_get_was_attached, NULL,
+    "True if the inferior was created using 'attach'.", NULL },
+
+  { NULL }
+};
+
+static PyMethodDef inferior_object_methods[] =
+{
+  { "threads", infpy_threads, METH_NOARGS,
+    "Return all the threads of this inferior." },
+
+  { "read_memory", infpy_read_memory, METH_VARARGS,
+    "read_memory (address, length) -> buffer\n\
+Return a buffer object for reading from the inferior's memory." },
+  { "write_memory", infpy_write_memory, METH_VARARGS,
+    "write_memory (address, buffer [, length])\n\
+Write the given buffer object to the inferior's memory." },
+  { "search_memory", (PyCFunction) infpy_search_memory, METH_VARARGS | METH_KEYWORDS,
+    "search_memory (address, length, pattern [, size] [, max_count]) -> list\n\
+Return a list with the addresses where matches were found." },
+
+  { NULL }
+};
+
+static PyTypeObject inferior_object_type =
+{
+  PyObject_HEAD_INIT (NULL)
+  0,				  /* ob_size */
+  "gdb.Inferior",		  /* tp_name */
+  sizeof (inferior_object),	  /* tp_basicsize */
+  0,				  /* tp_itemsize */
+  0,				  /* tp_dealloc */
+  0,				  /* tp_print */
+  0,				  /* tp_getattr */
+  0,				  /* tp_setattr */
+  0,				  /* tp_compare */
+  0,				  /* tp_repr */
+  0,				  /* tp_as_number */
+  0,				  /* tp_as_sequence */
+  0,				  /* tp_as_mapping */
+  0,				  /* tp_hash  */
+  0,				  /* tp_call */
+  0,				  /* tp_str */
+  0,				  /* tp_getattro */
+  0,				  /* tp_setattro */
+  0,				  /* tp_as_buffer */
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,  /* tp_flags */
+  "GDB inferior object",	  /* tp_doc */
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  0,				  /* tp_iter */
+  0,				  /* tp_iternext */
+  inferior_object_methods,	  /* tp_methods */
+  0,				  /* tp_members */
+  inferior_object_getset,	  /* tp_getset */
+  0,				  /* tp_base */
+  0,				  /* tp_dict */
+  0,				  /* tp_descr_get */
+  0,				  /* tp_descr_set */
+  0,				  /* tp_dictoffset */
+  0,				  /* tp_init */
+  0				  /* tp_alloc */
+};
+
+
+
+/* Python doesn't provide a decent way to get compatibility here.  */
+#if HAVE_LIBPYTHON2_4
+#define CHARBUFFERPROC_NAME getcharbufferproc
+#else
+#define CHARBUFFERPROC_NAME charbufferproc
+#endif
+
+static PyBufferProcs buffer_procs = {
+  get_read_buffer,
+  get_write_buffer,
+  get_seg_count,
+  /* The cast here works around a difference between Python 2.4 and
+     Python 2.5.  */
+  (CHARBUFFERPROC_NAME) get_char_buffer
+};
+
+static PyTypeObject membuf_object_type = {
+  PyObject_HEAD_INIT (NULL)
+  0,				  /*ob_size*/
+  "gdb.Membuf",			  /*tp_name*/
+  sizeof (membuf_object),	  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  mbpy_dealloc,			  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  0,				  /*tp_compare*/
+  0,				  /*tp_repr*/
+  0,				  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  0,				  /*tp_as_mapping*/
+  0,				  /*tp_hash */
+  0,				  /*tp_call*/
+  mbpy_str,			  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  &buffer_procs,		  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
+  "GDB memory buffer object", 	  /*tp_doc*/
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  0,				  /* tp_iter */
+  0,				  /* tp_iternext */
+  0,				  /* tp_methods */
+  0,				  /* tp_members */
+  0,				  /* tp_getset */
+  0,				  /* tp_base */
+  0,				  /* tp_dict */
+  0,				  /* tp_descr_get */
+  0,				  /* tp_descr_set */
+  0,				  /* tp_dictoffset */
+  0,				  /* tp_init */
+  0,				  /* tp_alloc */
+  PyType_GenericNew		  /* tp_new */
+};
diff --git a/gdb/python/py-infthread.c b/gdb/python/py-infthread.c
new file mode 100644
index 0000000..21e4eab
--- /dev/null
+++ b/gdb/python/py-infthread.c
@@ -0,0 +1,285 @@
+/* Python interface to inferior threads.
+
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 "defs.h"
+#include "exceptions.h"
+#include "gdbthread.h"
+#include "inferior.h"
+#include "python-internal.h"
+
+static PyTypeObject thread_object_type;
+
+/* Require that INFERIOR be a valid inferior ID.  */
+#define THPY_REQUIRE_VALID(Thread)				\
+  do {								\
+    if (!Thread->thread)					\
+      {								\
+	PyErr_SetString (PyExc_RuntimeError,			\
+			 "thread no longer exists");	        \
+	return NULL;						\
+      }								\
+  } while (0)
+
+
+
+thread_object *
+create_thread_object (struct thread_info *tp)
+{
+  thread_object *thread_obj;
+  
+  thread_obj = PyObject_New (thread_object, &thread_object_type);
+  if (!thread_obj)
+    return NULL;
+
+  thread_obj->thread = tp;
+  thread_obj->inf_obj = find_inferior_object (PIDGET (tp->ptid));
+  Py_INCREF (thread_obj->inf_obj);
+
+  return thread_obj;
+}
+
+
+
+static void
+thpy_dealloc (PyObject *self)
+{
+  Py_DECREF (((thread_object *) self)->inf_obj);
+  self->ob_type->tp_free (self);
+}
+
+static PyObject *
+thpy_get_num (PyObject *self, void *closure)
+{
+  thread_object *thread_obj = (thread_object *) self;
+
+  THPY_REQUIRE_VALID (thread_obj);
+
+  return PyLong_FromLong (thread_obj->thread->num);
+}
+
+
+
+/* Implementation of Inferior.frames () -> (gdb.Frame, ...).
+   Returns a tuple of all frame objects.  */
+PyObject *
+thpy_frames (PyObject *self, PyObject *args)
+{
+  int result = 0;
+  struct frame_info *frame;
+  PyObject *frame_obj;
+  PyObject *list, *tuple;
+  thread_object *thread_obj = (thread_object *) self;
+  struct cleanup *cleanup;
+  volatile struct gdb_exception except;
+
+  THPY_REQUIRE_VALID (thread_obj);
+
+  list = PyList_New (0);
+  if (list == NULL)
+    {
+      PyErr_SetString (PyExc_MemoryError, "Could not allocate frames list.");
+      return NULL;
+    }
+
+  cleanup = make_cleanup_restore_current_thread ();
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      switch_to_thread (thread_obj->thread->ptid);
+
+      for (frame = get_current_frame (); frame; frame = get_prev_frame (frame))
+	{
+	  frame_obj = frame_info_to_frame_object (frame);
+	  if (frame_obj == NULL)
+	    {
+	      Py_DECREF (list);
+	      list = NULL;
+	      break;
+	    }
+
+	  PyList_Append (list, frame_obj);
+	}
+    }
+  if (except.reason < 0)
+    {
+      Py_DECREF (list);
+      return PyErr_Format (except.reason == RETURN_QUIT
+			   ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
+			   "%s", except.message);
+    }
+
+  do_cleanups (cleanup);
+
+  if (list)
+    {
+      tuple = PyList_AsTuple (list);
+      Py_DECREF (list);
+    }
+  else
+    tuple = NULL;
+
+  return tuple;
+}
+
+/* Implementation of InferiorThread.newest_frame () -> gdb.Frame.
+   Returns the newest frame object.  */
+PyObject *
+thpy_newest_frame (PyObject *self, PyObject *args)
+{
+  struct frame_info *frame;
+  PyObject *frame_obj = NULL;   /* Initialize to appease gcc warning.  */
+  thread_object *thread_obj = (thread_object *) self;
+  struct cleanup *cleanup;
+  volatile struct gdb_exception except;
+
+  THPY_REQUIRE_VALID (thread_obj);
+
+  cleanup = make_cleanup_restore_current_thread ();
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      switch_to_thread (thread_obj->thread->ptid);
+
+      frame = get_current_frame ();
+      frame_obj = frame_info_to_frame_object (frame);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  do_cleanups (cleanup);
+
+  return frame_obj;
+}
+
+/* Implementation of InferiorThread.switch ().
+   Makes this the GDB selected thread.  */
+static PyObject *
+thpy_switch (PyObject *self, PyObject *args)
+{
+  thread_object *thread_obj = (thread_object *) self;
+  struct cleanup *cleanup;
+  volatile struct gdb_exception except;
+
+  THPY_REQUIRE_VALID (thread_obj);
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      switch_to_thread (thread_obj->thread->ptid);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  Py_RETURN_NONE;
+}
+
+
+
+/* Implementation of gdb.selected_thread () -> gdb.InferiorThread.
+   Returns the selected thread object.  */
+PyObject *
+gdbpy_selected_thread (PyObject *self, PyObject *args)
+{
+  PyObject *thread_obj;
+  
+  thread_obj = (PyObject *) find_thread_object (inferior_ptid);
+  if (thread_obj)
+    {
+      Py_INCREF (thread_obj);
+      return thread_obj;
+    }
+
+  Py_RETURN_NONE;
+}
+
+
+
+void
+gdbpy_initialize_thread (void)
+{
+  if (PyType_Ready (&thread_object_type) < 0)
+    return;
+
+  Py_INCREF (&thread_object_type);
+  PyModule_AddObject (gdb_module, "InferiorThread",
+		      (PyObject *) &thread_object_type);
+}
+
+
+
+static PyGetSetDef thread_object_getset[] =
+{
+  { "num", thpy_get_num, NULL, "ID of the thread, as assigned by GDB.", NULL },
+
+  { NULL }
+};
+
+static PyMethodDef thread_object_methods[] =
+{
+  { "frames", thpy_frames, METH_NOARGS,
+    "frames () -> (gdb.Frame, ...)\n\
+Return a tuple containing all frames in the thread." },
+  { "newest_frame", thpy_newest_frame, METH_NOARGS,
+    "newest_frame () -> gdb.Frame\n\
+Return the newest frame in the thread." },
+  { "switch", thpy_switch, METH_NOARGS,
+    "switch ()\n\
+Makes this the GDB selected thread." },
+
+  { NULL }
+};
+
+static PyTypeObject thread_object_type =
+{
+  PyObject_HEAD_INIT (NULL)
+  0,				  /*ob_size*/
+  "gdb.InferiorThread",		  /*tp_name*/
+  sizeof (thread_object),	  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  thpy_dealloc,			  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  0,				  /*tp_compare*/
+  0,				  /*tp_repr*/
+  0,				  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  0,				  /*tp_as_mapping*/
+  0,				  /*tp_hash */
+  0,				  /*tp_call*/
+  0,				  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  0,				  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,  /*tp_flags*/
+  "GDB thread object",		  /* tp_doc */
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  0,				  /* tp_iter */
+  0,				  /* tp_iternext */
+  thread_object_methods,	  /* tp_methods */
+  0,				  /* tp_members */
+  thread_object_getset,		  /* tp_getset */
+  0,				  /* tp_base */
+  0,				  /* tp_dict */
+  0,				  /* tp_descr_get */
+  0,				  /* tp_descr_set */
+  0,				  /* tp_dictoffset */
+  0,				  /* tp_init */
+  0				  /* tp_alloc */
+};
diff --git a/gdb/python/py-membuf.c b/gdb/python/py-membuf.c
new file mode 100644
index 0000000..7bc294c
--- /dev/null
+++ b/gdb/python/py-membuf.c
@@ -0,0 +1,268 @@
+/* Python interface to the inferior memory.
+
+   Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 "defs.h"
+#include "exceptions.h"
+#include "gdbcore.h"
+#include "python-internal.h"
+
+typedef struct {
+  PyObject_HEAD
+  void *buffer;
+
+  /* These are kept just for mbpy_str.  */
+  CORE_ADDR addr;
+  CORE_ADDR length;
+} membuf_object;
+
+static PyTypeObject membuf_object_type;
+
+/* Implementation of gdb.read_memory (address, length).
+   Returns a Python buffer object with LENGTH bytes of the inferior's memory
+   at ADDRESS. Both arguments are integers.  */
+
+PyObject *
+gdbpy_read_memory (PyObject *self, PyObject *args)
+{
+  int error = 0;
+  CORE_ADDR addr, length;
+  void *buffer = NULL;
+  membuf_object *membuf_obj;
+  PyObject *addr_obj, *length_obj;
+  struct cleanup *cleanups = NULL;
+  volatile struct gdb_exception except;
+
+  if (! PyArg_ParseTuple (args, "OO", &addr_obj, &length_obj))
+    return NULL;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (!get_addr_from_python (addr_obj, &addr)
+	  || !get_addr_from_python (length_obj, &length))
+	{
+	  error = 1;
+	  break;
+	}
+
+      buffer = xmalloc (length);
+      cleanups = make_cleanup (xfree, buffer);
+
+      read_memory (addr, buffer, length);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  if (error)
+    return NULL;
+
+  discard_cleanups (cleanups);
+
+  membuf_obj = PyObject_New (membuf_object, &membuf_object_type);
+  if (membuf_obj == NULL)
+    {
+      xfree (buffer);
+      PyErr_SetString (PyExc_MemoryError,
+		       "Could not allocate memory buffer object.");
+      return NULL;
+    }
+
+  membuf_obj->buffer = buffer;
+  membuf_obj->addr = addr;
+  membuf_obj->length = length;
+
+  return PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj, 0,
+				       Py_END_OF_BUFFER);
+}
+
+/* Implementation of gdb.write_memory (address, buffer [, length]).
+   Writes the contents of BUFFER (a Python object supporting the read buffer
+   protocol) at ADDRESS in the inferior's memory.  Write LENGTH bytes from
+   BUFFER, or its entire contents if the argument is not provided.  The
+   function returns nothing.  */
+
+PyObject *
+gdbpy_write_memory (PyObject *self, PyObject *args)
+{
+  int buf_len, error = 0;
+  const char *buffer;
+  CORE_ADDR addr, length;
+  PyObject *addr_obj, *length_obj = NULL;
+  volatile struct gdb_exception except;
+
+  if (! PyArg_ParseTuple (args, "Os#|O", &addr_obj, &buffer, &buf_len,
+			  &length_obj))
+    return NULL;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (!get_addr_from_python (addr_obj, &addr))
+	{
+	  error = 1;
+	  break;
+	}
+      
+      if (!length_obj)
+	length = buf_len;
+      else if (!get_addr_from_python (length_obj, &length))
+	{
+	  error = 1;
+	  break;
+	}
+
+      write_memory (addr, buffer, length);
+    }
+  GDB_PY_HANDLE_EXCEPTION (except);
+
+  if (error)
+    return NULL;
+
+  Py_RETURN_NONE;
+}
+
+/* Destructor of Membuf objects.  */
+
+static void
+mbpy_dealloc (PyObject *self)
+{
+  xfree (((membuf_object *) self)->buffer);
+  self->ob_type->tp_free (self);
+}
+
+/* Return a description of the Membuf object.  */
+
+static PyObject *
+mbpy_str (PyObject *self)
+{
+  membuf_object *membuf_obj = (membuf_object *) self;
+
+  return PyString_FromFormat ("memory buffer for address %s, %s bytes long",
+			      paddress (membuf_obj->addr),
+			      pulongest (membuf_obj->length));
+}
+
+static Py_ssize_t
+get_read_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr)
+{
+  membuf_object *membuf_obj = (membuf_object *) self;
+
+  if (segment)
+    {
+      PyErr_SetString (PyExc_SystemError,
+		       "The memory buffer supports only one segment.");
+      return -1;
+    }
+
+  *ptrptr = membuf_obj->buffer;
+
+  return membuf_obj->length;
+}
+
+static Py_ssize_t
+get_write_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr)
+{
+  return get_read_buffer (self, segment, ptrptr);
+}
+
+static Py_ssize_t
+get_seg_count (PyObject *self, Py_ssize_t *lenp)
+{
+  if (lenp)
+    *lenp = ((membuf_object *) self)->length;
+
+  return 1;
+}
+
+static Py_ssize_t
+get_char_buffer (PyObject *self, Py_ssize_t segment, char **ptrptr)
+{
+  void *ptr = NULL;
+  Py_ssize_t ret;
+
+  ret = get_read_buffer (self, segment, &ptr);
+  *ptrptr = (char *) ptr;
+
+  return ret;
+}
+
+/* Python doesn't provide a decent way to get compatibility here.  */
+#if HAVE_LIBPYTHON2_4
+#define CHARBUFFERPROC_NAME getcharbufferproc
+#else
+#define CHARBUFFERPROC_NAME charbufferproc
+#endif
+
+static PyBufferProcs buffer_procs = {
+  get_read_buffer,
+  get_write_buffer,
+  get_seg_count,
+  /* The cast here works around a difference between Python 2.4 and
+     Python 2.5.  */
+  (CHARBUFFERPROC_NAME) get_char_buffer
+};
+
+static PyTypeObject membuf_object_type = {
+  PyObject_HEAD_INIT (NULL)
+  0,				  /*ob_size*/
+  "gdb.Membuf",			  /*tp_name*/
+  sizeof (membuf_object),	  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  mbpy_dealloc,			  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  0,				  /*tp_compare*/
+  0,				  /*tp_repr*/
+  0,				  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  0,				  /*tp_as_mapping*/
+  0,				  /*tp_hash */
+  0,				  /*tp_call*/
+  mbpy_str,			  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  &buffer_procs,		  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
+  "GDB memory buffer object", 	  /*tp_doc*/
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  0,				  /* tp_iter */
+  0,				  /* tp_iternext */
+  0,				  /* tp_methods */
+  0,				  /* tp_members */
+  0,				  /* tp_getset */
+  0,				  /* tp_base */
+  0,				  /* tp_dict */
+  0,				  /* tp_descr_get */
+  0,				  /* tp_descr_set */
+  0,				  /* tp_dictoffset */
+  0,				  /* tp_init */
+  0,				  /* tp_alloc */
+  PyType_GenericNew		  /* tp_new */
+};
+
+void
+gdbpy_initialize_membuf (void)
+{
+  if (PyType_Ready (&membuf_object_type) < 0)
+    return;
+
+  Py_INCREF (&membuf_object_type);
+  PyModule_AddObject (gdb_module, "Membuf", (PyObject *) &membuf_object_type);
+}
diff --git a/gdb/python/py-param.c b/gdb/python/py-param.c
new file mode 100644
index 0000000..1f591a8
--- /dev/null
+++ b/gdb/python/py-param.c
@@ -0,0 +1,606 @@
+/* gdb parameters implemented in Python
+
+   Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 "defs.h"
+#include "value.h"
+#include "exceptions.h"
+#include "python-internal.h"
+#include "charset.h"
+#include "gdbcmd.h"
+#include "cli/cli-decode.h"
+#include "completer.h"
+
+/* Parameter constants and their values.  */
+struct parm_constant
+{
+  char *name;
+  int value;
+};
+
+struct parm_constant parm_constants[] =
+{
+  { "PARAM_BOOLEAN", var_boolean },
+  { "PARAM_AUTO_BOOLEAN", var_auto_boolean },
+  { "PARAM_UINTEGER", var_uinteger },
+  { "PARAM_INTEGER", var_integer },
+  { "PARAM_STRING", var_string },
+  { "PARAM_STRING_NOESCAPE", var_string_noescape },
+  { "PARAM_OPTIONAL_FILENAME", var_optional_filename },
+  { "PARAM_FILENAME", var_filename },
+  { "PARAM_ZINTEGER", var_zinteger },
+  { "PARAM_ENUM", var_enum },
+  { NULL, 0 }
+};
+
+/* A union that can hold anything described by enum var_types.  */
+union parmpy_variable
+{
+  /* Hold an integer value, for boolean and integer types.  */
+  int intval;
+
+  /* Hold an auto_boolean.  */
+  enum auto_boolean autoboolval;
+
+  /* Hold an unsigned integer value, for uinteger.  */
+  unsigned int uintval;
+
+  /* Hold a string, for the various string types.  */
+  char *stringval;
+
+  /* Hold a string, for enums.  */
+  const char *cstringval;
+};
+
+/* A gdb parameter.  */
+struct parmpy_object
+{
+  PyObject_HEAD
+
+  /* The type of the parameter.  */
+  enum var_types type;
+
+  /* The value of the parameter.  */
+  union parmpy_variable value;
+
+  /* For an enum command, the possible values.  The vector is
+     allocated with xmalloc, as is each element.  It is
+     NULL-terminated.  */
+  const char **enumeration;
+};
+
+typedef struct parmpy_object parmpy_object;
+
+static PyTypeObject parmpy_object_type;
+
+/* Some handy string constants.  */
+static PyObject *set_doc_cst;
+static PyObject *show_doc_cst;
+
+
+
+/* Get an attribute.  */
+static PyObject *
+get_attr (PyObject *obj, PyObject *attr_name)
+{
+  if (PyString_Check (attr_name)
+      && ! strcmp (PyString_AsString (attr_name), "value"))
+    {
+      parmpy_object *self = (parmpy_object *) obj;
+      return gdbpy_parameter_value (self->type, &self->value);
+    }
+
+  return PyObject_GenericGetAttr (obj, attr_name);
+}
+
+/* Set a parameter value from a Python value.  Return 0 on success, -1
+   on failure.  */
+static int
+set_parameter_value (parmpy_object *self, PyObject *value)
+{
+  int cmp;
+
+  switch (self->type)
+    {
+    case var_string:
+    case var_string_noescape:
+    case var_optional_filename:
+    case var_filename:
+      if (! gdbpy_is_string (value)
+	  && (self->type == var_filename
+	      || value != Py_None))
+	{
+	  PyErr_SetString (PyExc_RuntimeError, "string required");
+	  return -1;
+	}
+      if (self->value.stringval)
+	xfree (self->value.stringval);
+      if (value == Py_None)
+	{
+	  if (self->type == var_optional_filename)
+	    self->value.stringval = xstrdup ("");
+	  else
+	    self->value.stringval = NULL;
+	}
+      else
+	self->value.stringval = python_string_to_host_string (value);
+      break;
+
+    case var_enum:
+      {
+	int i;
+	char *str;
+
+	if (! gdbpy_is_string (value))
+	  {
+	    PyErr_SetString (PyExc_RuntimeError, "string required");
+	    return -1;
+	  }
+
+	str = python_string_to_host_string (value);
+	for (i = 0; self->enumeration[i]; ++i)
+	  if (! strcmp (self->enumeration[i], str))
+	    break;
+	xfree (str);
+	if (! self->enumeration[i])
+	  {
+	    PyErr_SetString (PyExc_RuntimeError,
+			     "value must be member of enumeration");
+	    return -1;
+	  }
+	self->value.cstringval = self->enumeration[i];
+	break;
+      }
+
+    case var_boolean:
+      if (! PyBool_Check (value))
+	{
+	  PyErr_SetString (PyExc_RuntimeError, "boolean required");
+	  return -1;
+	}
+      cmp = PyObject_IsTrue (value);
+      if (cmp < 0) 
+	  return -1;
+      self->value.intval = cmp;
+      break;
+
+    case var_auto_boolean:
+      if (! PyBool_Check (value) && value != Py_None)
+	{
+	  PyErr_SetString (PyExc_RuntimeError,
+			   "boolean or None required");
+	  return -1;
+	}
+
+      if (value == Py_None)
+	self->value.autoboolval = AUTO_BOOLEAN_AUTO;
+      else
+	{
+	  cmp = PyObject_IsTrue (value);
+	  if (cmp < 0 )
+	    return -1;	  
+	  if (cmp == 1)
+	    self->value.autoboolval = AUTO_BOOLEAN_TRUE;
+	  else 
+	    self->value.autoboolval = AUTO_BOOLEAN_FALSE;
+
+	  break;
+	}
+
+    case var_integer:
+    case var_zinteger:
+    case var_uinteger:
+      {
+	long l;
+	int ok;
+
+	if (! PyInt_Check (value))
+	  {
+	    PyErr_SetString (PyExc_RuntimeError, "value must be integer");
+	    return -1;
+	  }
+
+	l = PyInt_AsLong (value);
+	if (self->type == var_uinteger)
+	  {
+	    ok = (l >= 0 && l <= UINT_MAX);
+	    if (l == 0)
+	      l = UINT_MAX;
+	  }
+	else if (self->type == var_integer)
+	  {
+	    ok = (l >= INT_MIN && l <= INT_MAX);
+	    if (l == 0)
+	      l = INT_MAX;
+	  }
+	else
+	  ok = (l >= INT_MIN && l <= INT_MAX);
+
+	if (! ok)
+	  {
+	    PyErr_SetString (PyExc_RuntimeError, "range exceeded");
+	    return -1;
+	  }
+
+	self->value.intval = (int) l;
+	break;
+      }
+
+    default:
+      PyErr_SetString (PyExc_RuntimeError, "programmer error: unhandled type");
+      return -1;
+    }
+
+  return 0;
+}
+
+/* Set an attribute.  */
+static int
+set_attr (PyObject *obj, PyObject *attr_name, PyObject *val)
+{
+  if (PyString_Check (attr_name)
+      && ! strcmp (PyString_AsString (attr_name), "value"))
+    {
+      if (!val)
+	{
+	  PyErr_SetString (PyExc_RuntimeError,
+			   "cannot delete a parameter's value");
+	  return -1;
+	}
+      return set_parameter_value ((parmpy_object *) obj, val);
+    }
+
+  return PyObject_GenericSetAttr (obj, attr_name, val);
+}
+
+
+
+/* A helper function that dispatches to the appropriate add_setshow
+   function.  */
+static void
+add_setshow_generic (int parmclass, enum command_class cmdclass,
+		     char *cmd_name, parmpy_object *self,
+		     char *set_doc, char *show_doc, char *help_doc,
+		     struct cmd_list_element **set_list,
+		     struct cmd_list_element **show_list)
+{
+  switch (parmclass)
+    {
+    case var_boolean:
+      add_setshow_boolean_cmd (cmd_name, cmdclass, &self->value.intval,
+			       set_doc, show_doc, help_doc,
+			       NULL, NULL, set_list, show_list);
+      break;
+
+    case var_auto_boolean:
+      add_setshow_auto_boolean_cmd (cmd_name, cmdclass,
+				    &self->value.autoboolval,
+				    set_doc, show_doc, help_doc,
+				    NULL, NULL, set_list, show_list);
+      break;
+
+    case var_uinteger:
+      add_setshow_uinteger_cmd (cmd_name, cmdclass, &self->value.uintval,
+				set_doc, show_doc, help_doc,
+				NULL, NULL, set_list, show_list);
+      break;
+
+    case var_integer:
+      add_setshow_integer_cmd (cmd_name, cmdclass, &self->value.intval,
+			       set_doc, show_doc, help_doc,
+			       NULL, NULL, set_list, show_list);
+      break;
+
+    case var_string:
+      add_setshow_string_cmd (cmd_name, cmdclass, &self->value.stringval,
+			      set_doc, show_doc, help_doc,
+			      NULL, NULL, set_list, show_list);
+      break;
+
+    case var_string_noescape:
+      add_setshow_string_noescape_cmd (cmd_name, cmdclass,
+				       &self->value.stringval,
+				       set_doc, show_doc, help_doc,
+				       NULL, NULL, set_list, show_list);
+      break;
+
+    case var_optional_filename:
+      add_setshow_optional_filename_cmd (cmd_name, cmdclass,
+					 &self->value.stringval,
+					 set_doc, show_doc, help_doc,
+					 NULL, NULL, set_list, show_list);
+      break;
+
+    case var_filename:
+      add_setshow_filename_cmd (cmd_name, cmdclass, &self->value.stringval,
+				set_doc, show_doc, help_doc,
+				NULL, NULL, set_list, show_list);
+      break;
+
+    case var_zinteger:
+      add_setshow_zinteger_cmd (cmd_name, cmdclass, &self->value.intval,
+				set_doc, show_doc, help_doc,
+				NULL, NULL, set_list, show_list);
+      break;
+
+    case var_enum:
+      add_setshow_enum_cmd (cmd_name, cmdclass, self->enumeration,
+			    &self->value.cstringval,
+			    set_doc, show_doc, help_doc,
+			    NULL, NULL, set_list, show_list);
+      /* Initialize the value, just in case.  */
+      self->value.cstringval = self->enumeration[0];
+      break;
+    }
+}
+
+/* A helper which computes enum values.  Returns 1 on success, 0 on
+   error.  */
+static int
+compute_enum_values (parmpy_object *self, PyObject *enum_values)
+{
+  Py_ssize_t size, i;
+
+  if (! enum_values)
+    {
+      PyErr_SetString (PyExc_RuntimeError,
+		       "enumeration required for PARAM_ENUM");
+      return 0;
+    }
+
+  if (! PySequence_Check (enum_values))
+    {
+      PyErr_SetString (PyExc_RuntimeError, "enumeration is not a sequence");
+      return 0;
+    }
+
+  size = PySequence_Size (enum_values);
+  if (size < 0)
+    return 0;
+  if (size == 0)
+    {
+      PyErr_SetString (PyExc_RuntimeError, "empty enumeration");
+      return 0;
+    }
+
+  self->enumeration = xmalloc ((size + 1) * sizeof (char *));
+  memset (self->enumeration, 0, (size + 1) * sizeof (char *));
+
+  for (i = 0; i < size; ++i)
+    {
+      PyObject *item = PySequence_GetItem (enum_values, i);
+      if (! item)
+	return 0;
+      if (! gdbpy_is_string (item))
+	{
+	  PyErr_SetString (PyExc_RuntimeError, "enumeration item not a string");
+	  return 0;
+	}
+      self->enumeration[i] = python_string_to_host_string (item);
+    }
+
+  return 1;
+}
+
+/* A helper function which returns a documentation string for an
+   object.  */
+static char *
+get_doc_string (PyObject *object, PyObject *attr)
+{
+  char *result = NULL;
+  if (PyObject_HasAttr (object, attr))
+    {
+      PyObject *ds_obj = PyObject_GetAttr (object, attr);
+      if (ds_obj && gdbpy_is_string (ds_obj))
+	result = python_string_to_host_string (ds_obj);
+    }
+  if (! result)
+    result = xstrdup ("This command is not documented.");
+  return result;
+}
+
+/* Object initializer; sets up gdb-side structures for command.
+
+   Use: __init__(NAME, CMDCLASS, PARMCLASS, [ENUM])
+
+   NAME is the name of the parameter.  It may consist of multiple
+   words, in which case the final word is the name of the new command,
+   and earlier words must be prefix commands.
+
+   CMDCLASS is the kind of command.  It should be one of the COMMAND_*
+   constants defined in the gdb module.
+
+   PARMCLASS is the type of the parameter.  It should be one of the
+   PARAM_* constants defined in the gdb module.
+
+   If PARMCLASS is PARAM_ENUM, then the final argument should be a
+   collection of strings.  These strings are the valid values for this
+   parameter.
+
+   The documentation for the parameter is taken from the doc string
+   for the python class.
+   
+*/
+static int
+parmpy_init (PyObject *self, PyObject *args, PyObject *kwds)
+{
+  parmpy_object *obj = (parmpy_object *) self;
+  char *name;
+  char *set_doc, *show_doc, *doc;
+  char *cmd_name;
+  int parmclass, cmdtype;
+  PyObject *enum_values = NULL;
+  struct cmd_list_element *cmd_list;
+  struct cmd_list_element **set_list, **show_list;
+  volatile struct gdb_exception except;
+
+  if (! PyArg_ParseTuple (args, "sii|O", &name, &cmdtype, &parmclass,
+			  &enum_values))
+    return -1;
+
+  if (cmdtype != no_class && cmdtype != class_run
+      && cmdtype != class_vars && cmdtype != class_stack
+      && cmdtype != class_files && cmdtype != class_support
+      && cmdtype != class_info && cmdtype != class_breakpoint
+      && cmdtype != class_trace && cmdtype != class_obscure
+      && cmdtype != class_maintenance)
+    {
+      PyErr_Format (PyExc_RuntimeError, "invalid command class argument");
+      return -1;
+    }
+
+  if (parmclass != var_boolean && parmclass != var_auto_boolean
+      && parmclass != var_uinteger && parmclass != var_integer
+      && parmclass != var_string && parmclass != var_string_noescape
+      && parmclass != var_optional_filename && parmclass != var_filename
+      && parmclass != var_zinteger && parmclass != var_enum)
+    {
+      PyErr_SetString (PyExc_RuntimeError, "invalid parameter class argument");
+      return -1;
+    }
+
+  if (enum_values && parmclass != var_enum)
+    {
+      PyErr_SetString (PyExc_RuntimeError,
+		       "only PARAM_ENUM accepts a fourth argument");
+      return -1;
+    }
+  if (parmclass == var_enum)
+    {
+      if (! compute_enum_values (obj, enum_values))
+	return -1;
+    }
+
+  obj->type = (enum var_types) parmclass;
+  memset (&obj->value, 0, sizeof (obj->value));
+  obj->enumeration = NULL;
+
+  cmd_name = gdbpy_parse_command_name (name, &set_list, &setlist);
+  if (! cmd_name)
+    return -1;
+  xfree (cmd_name);
+  cmd_name = gdbpy_parse_command_name (name, &show_list, &showlist);
+  if (! cmd_name)
+    return -1;
+
+  /* FIXME: there is no way to register a destructor function for
+     set/show commands.  So, these are leaked.  */
+  set_doc = get_doc_string (self, set_doc_cst);
+  show_doc = get_doc_string (self, show_doc_cst);
+  doc = get_doc_string (self, gdbpy_doc_cst);
+
+  Py_INCREF (self);
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      add_setshow_generic (parmclass, (enum command_class) cmdtype,
+			   cmd_name, obj,
+			   set_doc, show_doc,
+			   doc, set_list, show_list);
+    }
+  if (except.reason < 0)
+    {
+      xfree (cmd_name);
+      xfree (set_doc);
+      xfree (show_doc);
+      xfree (doc);
+      Py_DECREF (self);
+      PyErr_Format (except.reason == RETURN_QUIT
+		    ? PyExc_KeyboardInterrupt : PyExc_RuntimeError,
+		    "%s", except.message);
+      return -1;
+    }
+  return 0;
+}
+
+
+
+/* Initialize the 'parameters' module.  */
+void
+gdbpy_initialize_parameters (void)
+{
+  int i;
+
+  if (PyType_Ready (&parmpy_object_type) < 0)
+    return;
+
+  set_doc_cst = PyString_FromString ("set_doc");
+  if (! set_doc_cst)
+    return;
+  show_doc_cst = PyString_FromString ("show_doc");
+  if (! show_doc_cst)
+    return;
+
+  for (i = 0; parm_constants[i].name; ++i)
+    {
+      if (PyModule_AddIntConstant (gdb_module,
+				   parm_constants[i].name,
+				   parm_constants[i].value) < 0)
+	return;
+    }
+
+  Py_INCREF (&parmpy_object_type);
+  PyModule_AddObject (gdb_module, "Parameter",
+		      (PyObject *) &parmpy_object_type);
+}
+
+
+
+static PyTypeObject parmpy_object_type =
+{
+  PyObject_HEAD_INIT (NULL)
+  0,				  /*ob_size*/
+  "gdb.Parameter",		  /*tp_name*/
+  sizeof (parmpy_object),	  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  0,				  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  0,				  /*tp_compare*/
+  0,				  /*tp_repr*/
+  0,				  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  0,				  /*tp_as_mapping*/
+  0,				  /*tp_hash */
+  0,				  /*tp_call*/
+  0,				  /*tp_str*/
+  get_attr,			  /*tp_getattro*/
+  set_attr,			  /*tp_setattro*/
+  0,				  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+  "GDB parameter object",	  /* tp_doc */
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  0,				  /* tp_iter */
+  0,				  /* tp_iternext */
+  0,				  /* tp_methods */
+  0,				  /* tp_members */
+  0,				  /* tp_getset */
+  0,				  /* tp_base */
+  0,				  /* tp_dict */
+  0,				  /* tp_descr_get */
+  0,				  /* tp_descr_set */
+  0,				  /* tp_dictoffset */
+  parmpy_init,			  /* tp_init */
+  0,				  /* tp_alloc */
+  PyType_GenericNew		  /* tp_new */
+};
diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c
index 454aa5a..9991f13 100644
--- a/gdb/python/py-prettyprint.c
+++ b/gdb/python/py-prettyprint.c
@@ -143,10 +143,15 @@ pretty_print_one_value (PyObject *printer, struct value **out_value)
 	  if (! gdbpy_is_string (result) && ! gdbpy_is_lazy_string (result))
 	    {
 	      *out_value = convert_value_from_python (result);
-	      if (PyErr_Occurred ())
-		*out_value = NULL;
-	      Py_DECREF (result);
-	      result = NULL;
+ 	      if (PyErr_Occurred ())
+ 		*out_value = NULL;
+	      else
+		/* We must increment the value's refcount, because we
+		   are about to decref RESULT, and this may result in
+		   the value being destroyed.  */
+		value_incref (*out_value);
+ 	      Py_DECREF (result);
+ 	      result = NULL;
 	    }
 	}
     }
@@ -605,14 +610,7 @@ gdbpy_get_varobj_pretty_printer (struct value *value)
 {
   PyObject *val_obj;
   PyObject *pretty_printer = NULL;
-  volatile struct gdb_exception except;
 
-  TRY_CATCH (except, RETURN_MASK_ALL)
-    {
-      value = value_copy (value);
-    }
-  GDB_PY_HANDLE_EXCEPTION (except);
-  
   val_obj = value_to_value_object (value);
   if (! val_obj)
     return NULL;
diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c
new file mode 100644
index 0000000..03d43c1
--- /dev/null
+++ b/gdb/python/py-symbol.c
@@ -0,0 +1,336 @@
+/* Python interface to symbols.
+
+   Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 "defs.h"
+#include "block.h"
+#include "exceptions.h"
+#include "frame.h"
+#include "symtab.h"
+#include "python-internal.h"
+
+typedef struct {
+  PyObject_HEAD
+  struct symbol *symbol;
+} symbol_object;
+
+
+static PyObject *
+sympy_str (PyObject *self)
+{
+  int ret;
+  char *s;
+  PyObject *result;
+
+  ret = asprintf (&s, "symbol for %s",
+		  SYMBOL_PRINT_NAME (((symbol_object *) self)->symbol));
+  if (ret < 0)
+    Py_RETURN_NONE;
+
+  result = PyString_FromString (s);
+  xfree (s);
+
+  return result;
+}
+
+static PyObject *
+sympy_get_value (PyObject *self, void *closure)
+{
+  symbol_object *self_sym = (symbol_object *) self;
+
+  switch (SYMBOL_CLASS (self_sym->symbol))
+    {
+    case LOC_BLOCK:
+      return block_to_block_object (SYMBOL_BLOCK_VALUE (self_sym->symbol));
+    }
+
+  PyErr_SetString (PyExc_NotImplementedError,
+		   "Symbol type not yet supported in Python scripts.");
+  return NULL;
+}
+
+static PyObject *
+sympy_get_symtab (PyObject *self, void *closure)
+{
+  symbol_object *self_sym = (symbol_object *) self;
+
+  return symtab_to_symtab_object (SYMBOL_SYMTAB (self_sym->symbol));
+}
+
+static PyObject *
+sympy_get_name (PyObject *self, void *closure)
+{
+  symbol_object *self_sym = (symbol_object *) self;
+
+  return PyString_FromString (SYMBOL_NATURAL_NAME (self_sym->symbol));
+}
+
+static PyObject *
+sympy_get_linkage_name (PyObject *self, void *closure)
+{
+  symbol_object *self_sym = (symbol_object *) self;
+
+  return PyString_FromString (SYMBOL_LINKAGE_NAME (self_sym->symbol));
+}
+
+static PyObject *
+sympy_get_print_name (PyObject *self, void *closure)
+{
+  symbol_object *self_sym = (symbol_object *) self;
+
+  return PyString_FromString (SYMBOL_PRINT_NAME (self_sym->symbol));
+}
+
+static PyObject *
+sympy_get_addr_class (PyObject *self, void *closure)
+{
+  symbol_object *self_sym = (symbol_object *) self;
+
+  return PyInt_FromLong (SYMBOL_CLASS (self_sym->symbol));
+}
+
+static PyObject *
+sympy_is_argument (PyObject *self, void *closure)
+{
+  symbol_object *self_sym = (symbol_object *) self;
+
+  return PyBool_FromLong (SYMBOL_IS_ARGUMENT (self_sym->symbol));
+}
+
+static PyObject *
+sympy_is_constant (PyObject *self, void *closure)
+{
+  symbol_object *self_sym = (symbol_object *) self;
+  enum address_class class = SYMBOL_CLASS (self_sym->symbol);
+
+  return PyBool_FromLong (class == LOC_CONST || class == LOC_CONST_BYTES);
+}
+
+static PyObject *
+sympy_is_function (PyObject *self, void *closure)
+{
+  symbol_object *self_sym = (symbol_object *) self;
+  enum address_class class = SYMBOL_CLASS (self_sym->symbol);
+
+  return PyBool_FromLong (class == LOC_BLOCK);
+}
+
+static PyObject *
+sympy_is_variable (PyObject *self, void *closure)
+{
+  symbol_object *self_sym = (symbol_object *) self;
+  enum address_class class = SYMBOL_CLASS (self_sym->symbol);
+
+  return PyBool_FromLong (!SYMBOL_IS_ARGUMENT (self_sym->symbol)
+      && (class == LOC_LOCAL || class == LOC_REGISTER || class == LOC_STATIC
+	  || class == LOC_COMPUTED || class == LOC_OPTIMIZED_OUT));
+}
+
+PyObject *
+symbol_to_symbol_object (struct symbol *sym)
+{
+  symbol_object *sym_obj;
+
+  sym_obj = PyObject_New (symbol_object, &symbol_object_type);
+  if (sym_obj == NULL)
+    {
+      PyErr_SetString (PyExc_MemoryError, "Could not allocate symbol object.");
+      return NULL;
+    }
+
+  sym_obj->symbol = sym;
+
+  return (PyObject *) sym_obj;
+}
+
+struct symbol *
+symbol_object_to_symbol (PyObject *obj)
+{
+  if (! PyObject_TypeCheck (obj, &symbol_object_type))
+    return NULL;
+  return ((symbol_object *) obj)->symbol;
+}
+
+/* Implementation of
+   gdb.lookup_symbol (name [, block] [, domain]) -> (symbol, is_field_of_this)
+   A tuple with 2 elements is always returned.  The first is the symbol
+   object or None, the second is a boolean with the value of
+   is_a_field_of_this (see comment in lookup_symbol_in_language).  */
+
+PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw)
+{
+  int domain = VAR_DOMAIN, is_a_field_of_this = 0;
+  const char *name;
+  static char *keywords[] = { "name", "block", "domain", NULL };
+  struct symbol *symbol;
+  PyObject *block_obj = NULL, *ret_tuple, *sym_obj, *bool_obj;
+  struct block *block = NULL;
+
+  if (! PyArg_ParseTupleAndKeywords (args, kw, "s|O!i", keywords, &name,
+				     &block_object_type, &block_obj, &domain))
+    return NULL;
+
+  if (block_obj)
+    block = block_object_to_block (block_obj);
+  else
+    {
+      struct frame_info *selected_frame;
+      volatile struct gdb_exception except;
+
+      TRY_CATCH (except, RETURN_MASK_ALL)
+	{
+	  selected_frame  = get_selected_frame (_("No frame selected."));
+	  block = block_for_pc (get_frame_address_in_block (selected_frame));
+	}
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+
+  symbol = lookup_symbol (name, block, domain, &is_a_field_of_this);
+
+  ret_tuple = PyTuple_New (2);
+  if (!ret_tuple)
+    {
+      PyErr_SetString (PyExc_MemoryError, "Could not allocate tuple object.");
+      return NULL;
+    }
+
+  if (symbol)
+    {
+      sym_obj = symbol_to_symbol_object (symbol);
+      if (!sym_obj)
+	{
+	  Py_DECREF (ret_tuple);
+	  return NULL;
+	}
+    }
+  else
+    {
+      sym_obj = Py_None;
+      Py_INCREF (Py_None);
+    }
+  PyTuple_SET_ITEM (ret_tuple, 0, sym_obj);
+
+  bool_obj = is_a_field_of_this? Py_True : Py_False;
+  Py_INCREF (bool_obj);
+  PyTuple_SET_ITEM (ret_tuple, 1, bool_obj);
+
+  return ret_tuple;
+}
+
+void
+gdbpy_initialize_symbols (void)
+{
+  if (PyType_Ready (&symbol_object_type) < 0)
+    return;
+
+  /* FIXME: These would probably be best exposed as class attributes of Symbol,
+     but I don't know how to do it except by messing with the type's dictionary.
+     That seems too messy.  */
+  /* FIXME 2: Some of these were removed from GDB since I first wrote this code,
+     so it's probably a good idea not to expose them to Python.  */
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_UNDEF", LOC_UNDEF);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_CONST", LOC_CONST);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_STATIC", LOC_STATIC);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_REGISTER", LOC_REGISTER);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_ARG", LOC_ARG);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_REF_ARG", LOC_REF_ARG);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_LOCAL", LOC_LOCAL);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_TYPEDEF", LOC_TYPEDEF);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_LABEL", LOC_LABEL);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_BLOCK", LOC_BLOCK);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_CONST_BYTES",
+			   LOC_CONST_BYTES);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_UNRESOLVED", LOC_UNRESOLVED);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_OPTIMIZED_OUT",
+			   LOC_OPTIMIZED_OUT);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_COMPUTED", LOC_COMPUTED);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_LOC_REGPARM_ADDR",
+			   LOC_REGPARM_ADDR);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_UNDEF_DOMAIN", UNDEF_DOMAIN);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_VAR_DOMAIN", VAR_DOMAIN);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_STRUCT_DOMAIN", STRUCT_DOMAIN);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_LABEL_DOMAIN", LABEL_DOMAIN);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_VARIABLES_DOMAIN",
+			   VARIABLES_DOMAIN);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_FUNCTIONS_DOMAIN",
+			   FUNCTIONS_DOMAIN);
+  PyModule_AddIntConstant (gdb_module, "SYMBOL_TYPES_DOMAIN", TYPES_DOMAIN);
+
+  Py_INCREF (&symbol_object_type);
+  PyModule_AddObject (gdb_module, "Symbol", (PyObject *) &symbol_object_type);
+}
+
+
+
+static PyGetSetDef symbol_object_getset[] = {
+  { "value", sympy_get_value, NULL, "Value of the symbol.", NULL },
+  { "symtab", sympy_get_symtab, NULL,
+    "Symbol table in which the symbol appears.", NULL },
+  { "name", sympy_get_name, NULL,
+    "Name of the symbol, as it appears in the source code.", NULL },
+  { "linkage_name", sympy_get_linkage_name, NULL,
+    "Name of the symbol, as used by the linker (i.e., may be mangled).", NULL },
+  { "print_name", sympy_get_print_name, NULL,
+    "Name of the symbol in a form suitable for output.\n\
+This is either name or linkage_name, depending on whether the user asked GDB\n\
+to display demangled or mangled names.", NULL },
+  { "addr_class", sympy_get_addr_class, NULL, "Address class of the symbol." },
+  { "is_argument", sympy_is_argument, NULL,
+    "True if the symbol is an argument of a function." },
+  { "is_constant", sympy_is_constant, NULL,
+    "True if the symbol is a constant." },
+  { "is_function", sympy_is_function, NULL,
+    "True if the symbol is a function or method." },
+  { "is_variable", sympy_is_variable, NULL,
+    "True if the symbol is a variable." },
+  { NULL }  /* Sentinel */
+};
+
+PyTypeObject symbol_object_type = {
+  PyObject_HEAD_INIT (NULL)
+  0,				  /*ob_size*/
+  "gdb.Symbol",			  /*tp_name*/
+  sizeof (symbol_object),	  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  0,				  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  0,				  /*tp_compare*/
+  0,				  /*tp_repr*/
+  0,				  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  0,				  /*tp_as_mapping*/
+  0,				  /*tp_hash */
+  0,				  /*tp_call*/
+  sympy_str,			  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  0,				  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
+  "GDB symbol object",		  /* tp_doc */
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  0,				  /* tp_iter */
+  0,				  /* tp_iternext */
+  0,				  /* tp_methods */
+  0,				  /* tp_members */
+  symbol_object_getset		  /* tp_getset */
+};
diff --git a/gdb/python/py-symtab.c b/gdb/python/py-symtab.c
new file mode 100644
index 0000000..830e586
--- /dev/null
+++ b/gdb/python/py-symtab.c
@@ -0,0 +1,322 @@
+/* Python interface to symbol tables.
+
+   Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 "defs.h"
+#include "charset.h"
+#include "symtab.h"
+#include "source.h"
+#include "python-internal.h"
+
+typedef struct {
+  PyObject_HEAD
+  struct symtab *symtab;
+} symtab_object;
+
+static PyTypeObject symtab_object_type;
+
+typedef struct {
+  PyObject_HEAD
+  symtab_object *symtab;
+  struct symtab_and_line *sal;
+} sal_object;
+
+static PyTypeObject sal_object_type;
+
+
+static PyObject *
+stpy_str (PyObject *self)
+{
+  int ret;
+  char *s;
+  PyObject *result;
+
+  ret = asprintf (&s, "symbol table for %s",
+		  ((symtab_object *) self)->symtab->filename);
+  if (ret < 0)
+    Py_RETURN_NONE;
+
+  result = PyString_FromString (s);
+  xfree (s);
+
+  return result;
+}
+
+static PyObject *
+stpy_get_filename (PyObject *self, void *closure)
+{
+  symtab_object *self_symtab = (symtab_object *) self;
+  PyObject *str_obj;
+
+  /* FIXME: Can symtab->filename really be NULL?  */
+  if (self_symtab->symtab->filename)
+    str_obj = PyString_Decode (self_symtab->symtab->filename,
+			       strlen (self_symtab->symtab->filename),
+			       host_charset (), NULL);
+  else
+    {
+      str_obj = Py_None;
+      Py_INCREF (Py_None);
+    }
+
+  return str_obj;
+}
+
+static PyObject *
+stpy_get_objfile (PyObject *self, void *closure)
+{
+  symtab_object *self_symtab = (symtab_object *) self;
+  PyObject *result = objfile_to_objfile_object (self_symtab->symtab->objfile);
+  Py_INCREF (result);
+  return result;
+}
+
+static PyObject *
+stpy_fullname (PyObject *self, PyObject *args)
+{
+  char *fullname;
+
+  fullname = symtab_to_fullname (((symtab_object *) self)->symtab);
+  if (fullname)
+    return PyString_Decode (fullname, strlen (fullname), host_charset (), NULL);
+
+  Py_RETURN_NONE;
+}
+
+static PyObject *
+salpy_str (PyObject *self)
+{
+  int ret;
+  char *s, *filename;
+  sal_object *sal_obj;
+  PyObject *result;
+
+  sal_obj = (sal_object *) self;
+  filename = (sal_obj->symtab == (symtab_object *) Py_None)? "<unknown>" :
+					   sal_obj->symtab->symtab->filename;
+  ret = asprintf (&s, "symbol and line for %s, line %d", filename,
+		  sal_obj->sal->line);
+  if (ret < 0)
+    Py_RETURN_NONE;
+
+  result = PyString_FromString (s);
+  xfree (s);
+
+  return result;
+}
+
+static PyObject *
+salpy_get_pc (PyObject *self, void *closure)
+{
+  return PyLong_FromUnsignedLongLong (((sal_object *) self)->sal->pc);
+}
+
+static PyObject *
+salpy_get_line (PyObject *self, void *closure)
+{
+  return PyLong_FromUnsignedLongLong (((sal_object *) self)->sal->line);
+}
+
+static PyObject *
+salpy_get_symtab (PyObject *self, void *closure)
+{
+  sal_object *self_sal = (sal_object *) self;
+
+  Py_INCREF (self_sal->symtab);
+
+  return (PyObject *) self_sal->symtab;
+}
+
+static void 
+salpy_dealloc (PyObject *self)
+{
+  sal_object *self_sal = (sal_object *) self;
+
+  Py_DECREF (self_sal->symtab);
+  xfree (self_sal->sal);
+  self_sal->ob_type->tp_free (self);
+}
+
+PyObject *
+symtab_and_line_to_sal_object (struct symtab_and_line sal)
+{
+  sal_object *sal_obj;
+  symtab_object *symtab_obj;
+
+  sal_obj = PyObject_New (sal_object, &sal_object_type);
+  if (sal_obj == NULL)
+    {
+      PyErr_SetString (PyExc_MemoryError,
+		       "Could not allocate Symtab_and_line object.");
+      return NULL;
+    }
+
+  if (sal.symtab)
+    {
+      symtab_obj = (symtab_object *) symtab_to_symtab_object (sal.symtab);
+      if (symtab_obj == NULL)
+	{
+	  Py_DECREF (sal_obj);
+	  return NULL;
+	}
+
+      symtab_obj->symtab = sal.symtab;
+    }
+  else
+    {
+      symtab_obj = (symtab_object *) Py_None;
+      Py_INCREF (Py_None);
+    }
+
+  sal_obj->sal = (struct symtab_and_line *)
+				    xmalloc (sizeof (struct symtab_and_line));
+  *(sal_obj->sal) = sal;
+  sal_obj->symtab = symtab_obj;
+
+  return (PyObject *) sal_obj;
+}
+
+PyObject *
+symtab_to_symtab_object (struct symtab *symtab)
+{
+  symtab_object *symtab_obj;
+  
+  symtab_obj = PyObject_New (symtab_object, &symtab_object_type);
+  if (symtab_obj == NULL)
+    {
+      PyErr_SetString (PyExc_MemoryError,
+	  "Could not allocate Symtab object.");
+
+      return NULL;
+    }
+
+  symtab_obj->symtab = symtab;
+
+  return (PyObject *) symtab_obj;
+}
+
+void
+gdbpy_initialize_symtabs (void)
+{
+  symtab_object_type.tp_new = PyType_GenericNew;
+  if (PyType_Ready (&symtab_object_type) < 0)
+    return;
+
+  sal_object_type.tp_new = PyType_GenericNew;
+  if (PyType_Ready (&sal_object_type) < 0)
+    return;
+
+  Py_INCREF (&symtab_object_type);
+  PyModule_AddObject (gdb_module, "Symtab", (PyObject *) &symtab_object_type);
+
+  Py_INCREF (&sal_object_type);
+  PyModule_AddObject (gdb_module, "Symtab_and_line",
+		      (PyObject *) &sal_object_type);
+}
+
+
+
+static PyGetSetDef symtab_object_getset[] = {
+  { "filename", stpy_get_filename, NULL,
+    "The symbol table's source filename.", NULL },
+  { "objfile", stpy_get_objfile, NULL, "The symtab's objfile.",
+    NULL },
+  {NULL}  /* Sentinel */
+};
+
+static PyMethodDef symtab_object_methods[] = {
+  { "fullname", stpy_fullname, METH_NOARGS,
+    "Return the symtab's full source filename." },
+  {NULL}  /* Sentinel */
+};
+
+static PyTypeObject symtab_object_type = {
+  PyObject_HEAD_INIT (NULL)
+  0,				  /*ob_size*/
+  "gdb.Symtab",			  /*tp_name*/
+  sizeof (symtab_object),	  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  0,				  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  0,				  /*tp_compare*/
+  0,				  /*tp_repr*/
+  0,				  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  0,				  /*tp_as_mapping*/
+  0,				  /*tp_hash */
+  0,				  /*tp_call*/
+  stpy_str,			  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  0,				  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
+  "GDB symtab object",		  /* tp_doc */
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  0,				  /* tp_iter */
+  0,				  /* tp_iternext */
+  symtab_object_methods,	  /* tp_methods */
+  0,				  /* tp_members */
+  symtab_object_getset		  /* tp_getset */
+};
+
+static PyGetSetDef sal_object_getset[] = {
+  { "symtab", salpy_get_symtab, NULL, "Symtab object.", NULL },
+  { "pc", salpy_get_pc, NULL, "Return the symtab_and_line's pc.", NULL },
+  { "line", salpy_get_line, NULL,
+    "Return the symtab_and_line's line.", NULL },
+  {NULL}  /* Sentinel */
+};
+
+static PyTypeObject sal_object_type = {
+  PyObject_HEAD_INIT (NULL)
+  0,				  /*ob_size*/
+  "gdb.Symtab_and_line",	  /*tp_name*/
+  sizeof (sal_object),		  /*tp_basicsize*/
+  0,				  /*tp_itemsize*/
+  salpy_dealloc,		  /*tp_dealloc*/
+  0,				  /*tp_print*/
+  0,				  /*tp_getattr*/
+  0,				  /*tp_setattr*/
+  0,				  /*tp_compare*/
+  0,				  /*tp_repr*/
+  0,				  /*tp_as_number*/
+  0,				  /*tp_as_sequence*/
+  0,				  /*tp_as_mapping*/
+  0,				  /*tp_hash */
+  0,				  /*tp_call*/
+  salpy_str,			  /*tp_str*/
+  0,				  /*tp_getattro*/
+  0,				  /*tp_setattro*/
+  0,				  /*tp_as_buffer*/
+  Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
+  "GDB symtab_and_line object",	  /* tp_doc */
+  0,				  /* tp_traverse */
+  0,				  /* tp_clear */
+  0,				  /* tp_richcompare */
+  0,				  /* tp_weaklistoffset */
+  0,				  /* tp_iter */
+  0,				  /* tp_iternext */
+  0,				  /* tp_methods */
+  0,				  /* tp_members */
+  sal_object_getset		  /* tp_getset */
+};
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index a97c125..ac366bb 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -27,6 +27,8 @@
 #include "demangle.h"
 #include "objfiles.h"
 #include "language.h"
+#include "observer.h"
+#include "gdb_assert.h"
 
 typedef struct pyty_type_object
 {
@@ -35,11 +37,17 @@ typedef struct pyty_type_object
 
   /* If a Type object is associated with an objfile, it is kept on a
      doubly-linked list, rooted in the objfile.  This lets us copy the
-     underlying struct type when the objfile is deleted.  */
+     underlying struct type when the objfile is deleted.
+
+     With NULL objfile Type still can be doubly-linked in the list
+     PYTY_OBJECTS_DISCARDABLE.  */
   struct pyty_type_object *prev;
   struct pyty_type_object *next;
 } type_object;
 
+/* First element of a doubly-linked list of TYPE_DISCARDABLE Types.  */
+static type_object *pyty_objects_discardable;
+
 static PyTypeObject type_object_type;
 
 /* A Field object.  */
@@ -434,7 +442,7 @@ typy_get_sizeof (PyObject *self, void *closure)
 }
 
 static struct type *
-typy_lookup_typename (char *type_name)
+typy_lookup_typename (char *type_name, struct block *block)
 {
   struct type *type = NULL;
   volatile struct gdb_exception except;
@@ -448,7 +456,7 @@ typy_lookup_typename (char *type_name)
 	type = lookup_enum (type_name + 5, NULL);
       else
 	type = lookup_typename (python_language, python_gdbarch,
-				type_name, NULL, 0);
+				type_name, block, 0);
     }
   if (except.reason < 0)
     {
@@ -462,7 +470,8 @@ typy_lookup_typename (char *type_name)
 }
 
 static struct type *
-typy_lookup_type (struct demangle_component *demangled)
+typy_lookup_type (struct demangle_component *demangled,
+		  struct block *block)
 {
   struct type *type;
   char *type_name;
@@ -477,7 +486,7 @@ typy_lookup_type (struct demangle_component *demangled)
       || demangled_type == DEMANGLE_COMPONENT_CONST
       || demangled_type == DEMANGLE_COMPONENT_VOLATILE)
     {
-      type = typy_lookup_type (demangled->u.s_binary.left);
+      type = typy_lookup_type (demangled->u.s_binary.left, block);
       if (! type)
 	return NULL;
 
@@ -495,7 +504,7 @@ typy_lookup_type (struct demangle_component *demangled)
     }
 
   type_name = cp_comp_to_string (demangled, 10);
-  type = typy_lookup_typename (type_name);
+  type = typy_lookup_typename (type_name, block);
   xfree (type_name);
 
   return type;
@@ -509,10 +518,23 @@ typy_template_argument (PyObject *self, PyObject *args)
   struct demangle_component *demangled;
   const char *err;
   struct type *argtype;
+  struct block *block = NULL;
+  PyObject *block_obj = NULL;
 
-  if (! PyArg_ParseTuple (args, "i", &argno))
+  if (! PyArg_ParseTuple (args, "i|O", &argno, &block_obj))
     return NULL;
 
+  if (block_obj)
+    {
+      block = block_object_to_block (block_obj);
+      if (! block)
+	{
+	  PyErr_SetString (PyExc_RuntimeError,
+			   "second argument must be block");
+	  return NULL;
+	}
+    }
+
   type = check_typedef (type);
   if (TYPE_CODE (type) == TYPE_CODE_REF)
     type = check_typedef (TYPE_TARGET_TYPE (type));
@@ -555,7 +577,7 @@ typy_template_argument (PyObject *self, PyObject *args)
       return NULL;
     }
 
-  argtype = typy_lookup_type (demangled->u.s_binary.left);
+  argtype = typy_lookup_type (demangled->u.s_binary.left, block);
   if (! argtype)
     return NULL;
 
@@ -597,8 +619,59 @@ typy_str (PyObject *self)
 
 
 
+/* Key associated with each objfile pointing to the first element of
+   a doubly-linked list of Types associated with this objfile.  */
 static const struct objfile_data *typy_objfile_data_key;
 
+/* Link TYPE_OBJ to its appropriate list.  Either to its objfile associated one
+   or at least to the global list for TYPE_DISCARDABLE Types.  Permanent types
+   do not get linked anywhere.  */
+static void
+typy_link (type_object *type_obj)
+{
+  type_obj->prev = NULL;
+
+  if (type_obj->type && TYPE_OBJFILE (type_obj->type))
+    {
+      struct objfile *objfile = TYPE_OBJFILE (type_obj->type);
+
+      type_obj->next = objfile_data (objfile, typy_objfile_data_key);
+      if (type_obj->next)
+	type_obj->next->prev = type_obj;
+      set_objfile_data (objfile, typy_objfile_data_key, type_obj);
+    }
+  else if (type_obj->type && TYPE_DISCARDABLE (type_obj->type))
+    {
+      type_obj->next = pyty_objects_discardable;
+      if (type_obj->next)
+	type_obj->next->prev = type_obj;
+      pyty_objects_discardable = type_obj;
+    }
+  else
+    type_obj->next = NULL;
+}
+
+/* Unlink TYPE_OBJ from its current list.  Permanent types are not linked
+   anywhere and this function has no effect on them.  */
+static void
+typy_unlink (type_object *type_obj)
+{
+  if (type_obj->prev)
+    type_obj->prev->next = type_obj->next;
+  else if (type_obj->type && TYPE_OBJFILE (type_obj->type))
+    {
+      /* Must reset head of list.  */
+      struct objfile *objfile = TYPE_OBJFILE (type_obj->type);
+
+      set_objfile_data (objfile, typy_objfile_data_key, type_obj->next);
+    }
+  else if (pyty_objects_discardable == type_obj)
+    pyty_objects_discardable = type_obj->next;
+
+  if (type_obj->next)
+    type_obj->next->prev = type_obj->prev;
+}
+
 static void
 save_objfile_types (struct objfile *objfile, void *datum)
 {
@@ -616,12 +689,13 @@ save_objfile_types (struct objfile *objfile, void *datum)
     {
       type_object *next = obj->next;
 
-      htab_empty (copied_types);
+      gdb_assert (TYPE_OBJFILE (obj->type) == objfile);
+      typy_unlink (obj);
 
-      obj->type = copy_type_recursive (objfile, obj->type, copied_types);
+      obj->type = copy_type_recursive (obj->type, copied_types);
 
-      obj->next = NULL;
-      obj->prev = NULL;
+      gdb_assert (TYPE_OBJFILE (obj->type) == NULL);
+      typy_link (obj);
 
       obj = next;
     }
@@ -632,41 +706,25 @@ save_objfile_types (struct objfile *objfile, void *datum)
 }
 
 static void
-set_type (type_object *obj, struct type *type)
+typy_dealloc (PyObject *obj)
 {
-  obj->type = type;
-  obj->prev = NULL;
-  if (type && TYPE_OBJFILE (type))
-    {
-      struct objfile *objfile = TYPE_OBJFILE (type);
+  type_object *type_obj = (type_object *) obj;
 
-      obj->next = objfile_data (objfile, typy_objfile_data_key);
-      if (obj->next)
-	obj->next->prev = obj;
-      set_objfile_data (objfile, typy_objfile_data_key, obj);
-    }
-  else
-    obj->next = NULL;
+  typy_unlink (type_obj);
+
+  type_obj->ob_type->tp_free (obj);
 }
 
+/* Call type_mark_used for any TYPEs referenced from this GDB source file.  */
 static void
-typy_dealloc (PyObject *obj)
+typy_types_mark_used (void)
 {
-  type_object *type = (type_object *) obj;
-
-  if (type->prev)
-    type->prev->next = type->next;
-  else if (type->type && TYPE_OBJFILE (type->type))
-    {
-      /* Must reset head of list.  */
-      struct objfile *objfile = TYPE_OBJFILE (type->type);
-      if (objfile)
-	set_objfile_data (objfile, typy_objfile_data_key, type->next);
-    }
-  if (type->next)
-    type->next->prev = type->prev;
+  type_object *type_obj;
 
-  type->ob_type->tp_free (type);
+  for (type_obj = pyty_objects_discardable;
+       type_obj != NULL;
+       type_obj = type_obj->next)
+    type_mark_used (type_obj->type);
 }
 
 /* Create a new Type referring to TYPE.  */
@@ -677,7 +735,10 @@ type_to_type_object (struct type *type)
 
   type_obj = PyObject_New (type_object, &type_object_type);
   if (type_obj)
-    set_type (type_obj, type);
+    {
+      type_obj->type = type;
+      typy_link (type_obj);
+    }
 
   return (PyObject *) type_obj;
 }
@@ -696,14 +757,28 @@ type_object_to_type (PyObject *obj)
 PyObject *
 gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw)
 {
-  static char *keywords[] = { "name", NULL };
+  static char *keywords[] = { "name", "block", NULL };
   char *type_name = NULL;
   struct type *type = NULL;
+  PyObject *block_obj = NULL;
+  struct block *block = NULL;
 
-  if (! PyArg_ParseTupleAndKeywords (args, kw, "s", keywords, &type_name))
+  if (! PyArg_ParseTupleAndKeywords (args, kw, "s|O", keywords,
+				     &type_name, &block_obj))
     return NULL;
 
-  type = typy_lookup_typename (type_name);
+  if (block_obj)
+    {
+      block = block_object_to_block (block_obj);
+      if (! block)
+	{
+	  PyErr_SetString (PyExc_RuntimeError,
+			   "'block' argument must be a Block");
+	  return NULL;
+	}
+    }
+
+  type = typy_lookup_typename (type_name, block);
   if (! type)
     return NULL;
 
@@ -737,6 +812,8 @@ gdbpy_initialize_types (void)
 
   Py_INCREF (&field_object_type);
   PyModule_AddObject (gdb_module, "Field", (PyObject *) &field_object_type);
+
+  observer_attach_mark_used (typy_types_mark_used);
 }
 
 
diff --git a/gdb/python/py-utils.c b/gdb/python/py-utils.c
index 4ccf97f..87cde73 100644
--- a/gdb/python/py-utils.c
+++ b/gdb/python/py-utils.c
@@ -19,6 +19,7 @@
 
 #include "defs.h"
 #include "charset.h"
+#include "value.h"
 #include "python-internal.h"
 
 
@@ -219,3 +220,48 @@ gdbpy_is_string (PyObject *obj)
 {
   return PyString_Check (obj) || PyUnicode_Check (obj);
 }
+
+/* Converts OBJ to a CORE_ADDR value.
+
+   Returns 1 on success or 0 on failure, with a Python exception set.  This
+   function can also throw GDB exceptions.  */
+
+int
+get_addr_from_python (PyObject *obj, CORE_ADDR *addr)
+{
+  if (gdbpy_is_value_object (obj))
+    *addr = value_as_address (value_object_to_value (obj));
+  else if (PyLong_Check (obj))
+    {
+      /* Assume CORE_ADDR corresponds to unsigned long.  */
+      *addr = PyLong_AsUnsignedLong (obj);
+      if (PyErr_Occurred () != NULL)
+	return 0;
+    }
+  else if (PyInt_Check (obj))
+    {
+      long val;
+
+      /* Assume CORE_ADDR corresponds to unsigned long.  */
+      val = PyInt_AsLong (obj);
+
+      if (val >= 0)
+	*addr = val;
+      else
+      {
+	/* If no error ocurred, VAL is indeed negative.  */
+	if (PyErr_Occurred () != NULL)
+	  return 0;
+
+	PyErr_SetString (PyExc_ValueError, "negative address");
+	return 0;
+      }
+    }
+  else
+    {
+      PyErr_SetString (PyExc_TypeError, "invalid type for address");
+      return 0;
+    }
+
+  return 1;
+}
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index a792819..bdac80e 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -25,6 +25,7 @@
 #include "language.h"
 #include "dfp.h"
 #include "valprint.h"
+#include "observer.h"
 
 #ifdef HAVE_PYTHON
 
@@ -43,6 +44,10 @@
 /* Python's long type corresponds to C's long long type.  */
 #define builtin_type_pylong builtin_type (python_gdbarch)->builtin_long_long
 
+/* Python's long type corresponds to C's long long type.  Unsigned version.  */
+#define builtin_type_upylong builtin_type \
+  (python_gdbarch)->builtin_unsigned_long_long
+
 #define builtin_type_pybool \
   language_bool_type (python_language, python_gdbarch)
 
@@ -945,7 +950,34 @@ convert_value_from_python (PyObject *obj)
 	{
 	  LONGEST l = PyLong_AsLongLong (obj);
 
-	  if (! PyErr_Occurred ())
+	  if (PyErr_Occurred ())
+	    {
+	      /* If the error was an overflow, we can try converting to
+	         ULONGEST instead.  */
+	      if (PyErr_ExceptionMatches (PyExc_OverflowError))
+		{
+		  PyObject *etype, *evalue, *etraceback, *zero;
+
+		  PyErr_Fetch (&etype, &evalue, &etraceback);
+		  zero = PyInt_FromLong (0);
+
+		  /* Check whether obj is positive.  */
+		  if (PyObject_RichCompareBool (obj, zero, Py_GT) > 0)
+		    {
+		      ULONGEST ul;
+
+		      ul = PyLong_AsUnsignedLongLong (obj);
+		      if (! PyErr_Occurred ())
+			value = value_from_ulongest (builtin_type_upylong, ul);
+		    }
+		  else
+		    /* There's nothing we can do.  */
+		    PyErr_Restore (etype, evalue, etraceback);
+
+		  Py_DECREF (zero);
+		}
+	    }
+	  else
 	    value = value_from_longest (builtin_type_pylong, l);
 	}
       else if (PyFloat_Check (obj))
@@ -1011,6 +1043,25 @@ gdbpy_history (PyObject *self, PyObject *args)
   return value_to_value_object (res_val);
 }
 
+/* Call type_mark_used for any TYPEs referenced from this GDB source file.  */
+
+static void
+python_types_mark_used (void)
+{
+  value_object *iter;
+
+  for (iter = values_in_python; iter; iter = iter->next)
+    type_mark_used (value_type (iter->value));
+}
+
+/* Returns 1 in OBJ is a gdb.Value object, 0 otherwise.  */
+
+int
+gdbpy_is_value_object (PyObject *obj)
+{
+  return PyObject_TypeCheck (obj, &value_object_type);
+}
+
 void
 gdbpy_initialize_values (void)
 {
@@ -1021,6 +1072,8 @@ gdbpy_initialize_values (void)
   PyModule_AddObject (gdb_module, "Value", (PyObject *) &value_object_type);
 
   values_in_python = NULL;
+
+  observer_attach_mark_used (python_types_mark_used);
 }
 
 
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 1bfa700..52f9b39 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -61,36 +61,79 @@ typedef int Py_ssize_t;
 #define PyEval_ReleaseLock() 0
 #endif
 
+#include "command.h"
+
+struct block;
+struct symbol;
+struct symtab_and_line;
 struct value;
 struct language_defn;
 
 extern PyObject *gdb_module;
+extern PyTypeObject block_object_type;
 extern PyTypeObject value_object_type;
+extern PyTypeObject symbol_object_type;
+
+/* Used in python-inferior.c.  */
+typedef struct
+{
+  PyObject_HEAD
+
+  /* The thread we represent.  */
+  struct thread_info *thread;
+
+  /* The Inferior object to which this thread belongs.  */
+  PyObject *inf_obj;
+} thread_object;
 
 PyObject *gdbpy_history (PyObject *self, PyObject *args);
+PyObject *gdbpy_breakpoints (PyObject *, PyObject *);
 PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
+PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw);
 PyObject *gdbpy_selected_frame (PyObject *self, PyObject *args);
+PyObject *gdbpy_block_for_pc (PyObject *self, PyObject *args);
 PyObject *gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw);
 PyObject *gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
 					   const char *encoding, struct type *type);
+PyObject *gdbpy_inferiors (PyObject *unused, PyObject *unused2);
+PyObject *gdbpy_selected_thread (PyObject *self, PyObject *args);
 
+PyObject *symtab_and_line_to_sal_object (struct symtab_and_line sal);
+PyObject *symtab_to_symtab_object (struct symtab *symtab);
+PyObject *symbol_to_symbol_object (struct symbol *sym);
+PyObject *block_to_block_object (struct block *block);
 PyObject *value_to_value_object (struct value *v);
 PyObject *type_to_type_object (struct type *);
 PyObject *objfile_to_objfile_object (struct objfile *);
+PyObject *frame_info_to_frame_object (struct frame_info *frame);
+thread_object *create_thread_object (struct thread_info *tp);
+thread_object *find_thread_object (ptid_t ptid);
+PyObject *find_inferior_object (int pid);
 
 PyObject *objfpy_get_printers (PyObject *, void *);
 
+struct block *block_object_to_block (PyObject *obj);
+struct symbol *symbol_object_to_symbol (PyObject *obj);
 struct value *value_object_to_value (PyObject *self);
 struct value *convert_value_from_python (PyObject *obj);
 struct type *type_object_to_type (PyObject *obj);
 
+PyObject *gdbpy_get_hook_function (const char *);
+
 void gdbpy_initialize_values (void);
+void gdbpy_initialize_breakpoints (void);
 void gdbpy_initialize_frames (void);
+void gdbpy_initialize_symtabs (void);
 void gdbpy_initialize_commands (void);
+void gdbpy_initialize_symbols (void);
 void gdbpy_initialize_types (void);
+void gdbpy_initialize_blocks (void);
 void gdbpy_initialize_functions (void);
 void gdbpy_initialize_objfile (void);
 void gdbpy_initialize_lazy_string (void);
+void gdbpy_initialize_parameters (void);
+void gdbpy_initialize_thread (void);
+void gdbpy_initialize_inferior (void);
 
 struct cleanup *make_cleanup_py_decref (PyObject *py);
 
@@ -100,6 +143,12 @@ struct cleanup *ensure_python_env (struct gdbarch *gdbarch,
 extern struct gdbarch *python_gdbarch;
 extern const struct language_defn *python_language;
 
+char *gdbpy_parse_command_name (char *text,
+				struct cmd_list_element ***base_list,
+				struct cmd_list_element **start_list);
+
+PyObject *gdbpy_parameter_value (enum var_types, void *);
+
 /* Use this after a TRY_EXCEPT to throw the appropriate Python
    exception.  */
 #define GDB_PY_HANDLE_EXCEPTION(Exception)				\
@@ -110,6 +159,19 @@ extern const struct language_defn *python_language;
 			     "%s", Exception.message);			\
     } while (0)
 
+/* Use this after a TRY_EXCEPT to throw the appropriate Python
+   exception.  This macro is for use inside setter functions.  */
+#define GDB_PY_SET_HANDLE_EXCEPTION(Exception)				\
+    do {								\
+      if (Exception.reason < 0)						\
+        {								\
+	  PyErr_Format (Exception.reason == RETURN_QUIT			\
+			? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
+			"%s", Exception.message);			\
+	  return -1;							\
+	}								\
+    } while (0)
+
 
 void gdbpy_print_stack (void);
 
@@ -125,17 +187,22 @@ gdb_byte *gdbpy_extract_lazy_string (PyObject *string,
 				     struct type **str_type, 
 				     long *length, char **encoding);
 
+int gdbpy_is_value_object (PyObject *obj);
+
 /* Note that these are declared here, and not in python.h with the
    other pretty-printer functions, because they refer to PyObject.  */
 PyObject *apply_varobj_pretty_printer (PyObject *print_obj,
 				       struct value **replacement);
 PyObject *gdbpy_get_varobj_pretty_printer (struct value *value);
+PyObject *gdbpy_instantiate_printer (PyObject *cons, PyObject *value);
 char *gdbpy_get_display_hint (PyObject *printer);
 PyObject *gdbpy_default_visualizer (PyObject *self, PyObject *args);
 
-extern PyObject *gdbpy_doc_cst;
 extern PyObject *gdbpy_children_cst;
 extern PyObject *gdbpy_to_string_cst;
 extern PyObject *gdbpy_display_hint_cst;
+extern PyObject *gdbpy_doc_cst;
+
+int get_addr_from_python (PyObject *obj, CORE_ADDR *addr);
 
 #endif /* GDB_PYTHON_INTERNAL_H */
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 29386c9..195dace 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -28,6 +28,7 @@
 #include "value.h"
 #include "language.h"
 #include "exceptions.h"
+#include "event-loop.h"
 
 #include <ctype.h>
 
@@ -46,10 +47,17 @@ static int gdbpy_auto_load = 1;
 #include "cli/cli-decode.h"
 #include "charset.h"
 #include "top.h"
+#include "solib.h"
 #include "python-internal.h"
+#include "linespec.h"
+#include "symtab.h"
+#include "source.h"
 #include "version.h"
+#include "inferior.h"
+#include "gdbthread.h"
 #include "target.h"
 #include "gdbthread.h"
+#include "event-top.h"
 
 static PyMethodDef GdbMethods[];
 
@@ -197,10 +205,10 @@ python_command (char *arg, int from_tty)
    NULL (and set a Python exception) on error.  Helper function for
    get_parameter.  */
 
-static PyObject *
-parameter_to_python (struct cmd_list_element *cmd)
+PyObject *
+gdbpy_parameter_value (enum var_types type, void *var)
 {
-  switch (cmd->var_type)
+  switch (type)
     {
     case var_string:
     case var_string_noescape:
@@ -208,7 +216,7 @@ parameter_to_python (struct cmd_list_element *cmd)
     case var_filename:
     case var_enum:
       {
-	char *str = * (char **) cmd->var;
+	char *str = * (char **) var;
 	if (! str)
 	  str = "";
 	return PyString_Decode (str, strlen (str), host_charset (), NULL);
@@ -216,7 +224,7 @@ parameter_to_python (struct cmd_list_element *cmd)
 
     case var_boolean:
       {
-	if (* (int *) cmd->var)
+	if (* (int *) var)
 	  Py_RETURN_TRUE;
 	else
 	  Py_RETURN_FALSE;
@@ -224,7 +232,7 @@ parameter_to_python (struct cmd_list_element *cmd)
 
     case var_auto_boolean:
       {
-	enum auto_boolean ab = * (enum auto_boolean *) cmd->var;
+	enum auto_boolean ab = * (enum auto_boolean *) var;
 	if (ab == AUTO_BOOLEAN_TRUE)
 	  Py_RETURN_TRUE;
 	else if (ab == AUTO_BOOLEAN_FALSE)
@@ -234,15 +242,15 @@ parameter_to_python (struct cmd_list_element *cmd)
       }
 
     case var_integer:
-      if ((* (int *) cmd->var) == INT_MAX)
+      if ((* (int *) var) == INT_MAX)
 	Py_RETURN_NONE;
       /* Fall through.  */
     case var_zinteger:
-      return PyLong_FromLong (* (int *) cmd->var);
+      return PyLong_FromLong (* (int *) var);
 
     case var_uinteger:
       {
-	unsigned int val = * (unsigned int *) cmd->var;
+	unsigned int val = * (unsigned int *) var;
 	if (val == UINT_MAX)
 	  Py_RETURN_NONE;
 	return PyLong_FromUnsignedLong (val);
@@ -280,7 +288,7 @@ gdbpy_parameter (PyObject *self, PyObject *args)
 
   if (! cmd->var)
     return PyErr_Format (PyExc_RuntimeError, "`%s' is not a parameter", arg);
-  return parameter_to_python (cmd);
+  return gdbpy_parameter_value (cmd->var_type, cmd->var);
 }
 
 /* A Python function which evaluates a string using the gdb CLI.  */
@@ -323,6 +331,105 @@ execute_gdb_command (PyObject *self, PyObject *args)
   Py_RETURN_NONE;
 }
 
+/* Implementation of gdb.solib_address (Long) -> String.
+   Returns the name of the shared library holding a given address, or None.  */
+
+static PyObject *
+gdbpy_solib_address (PyObject *self, PyObject *args)
+{
+  unsigned long long pc;
+  char *soname;
+  PyObject *str_obj;
+
+  if (!PyArg_ParseTuple (args, "K", &pc))
+    return NULL;
+
+  soname = solib_name_from_address (current_program_space, pc);
+  if (soname)
+    str_obj = PyString_Decode (soname, strlen (soname), host_charset (), NULL);
+  else
+    {
+      str_obj = Py_None;
+      Py_INCREF (Py_None);
+    }
+
+  return str_obj;
+}
+
+/* A Python function which is a wrapper for decode_line_1.  */
+
+static PyObject *
+gdbpy_decode_line (PyObject *self, PyObject *args)
+{
+  struct symtabs_and_lines sals = { NULL, 0 }; /* Initialize to appease gcc.  */
+  struct symtab_and_line sal;
+  char *arg = NULL;
+  int free_sals = 0, i;
+  PyObject *result = NULL;
+  volatile struct gdb_exception except;
+
+  if (! PyArg_ParseTuple (args, "|s", &arg))
+    return NULL;
+
+  TRY_CATCH (except, RETURN_MASK_ALL)
+    {
+      if (arg)
+	{
+	  char *copy;
+
+	  arg = strdup (arg);
+	  copy = arg;
+
+	  sals = decode_line_1 (&copy, 0, 0, 0, 0, 0);
+	  free_sals = 1;
+	}
+      else
+	{
+	  set_default_source_symtab_and_line ();
+	  sal = get_current_source_symtab_and_line ();
+	  sals.sals = &sal;
+	  sals.nelts = 1;
+	}
+    }
+  if (arg)
+    xfree (arg);
+
+  if (except.reason < 0)
+    {
+      if (free_sals)
+	xfree (sals.sals);
+      /* We know this will always throw.  */
+      GDB_PY_HANDLE_EXCEPTION (except);
+    }
+
+  if (sals.nelts)
+    {
+      result = PyTuple_New (sals.nelts);
+      for (i = 0; i < sals.nelts; ++i)
+	{
+	  PyObject *obj;
+	  char *str;
+
+	  obj = symtab_and_line_to_sal_object (sals.sals[i]);
+	  if (! obj)
+	    {
+	      Py_DECREF (result);
+	      result = NULL;
+	      break;
+	    }
+
+	  PyTuple_SetItem (result, i, obj);
+	}
+    }
+
+  if (free_sals)
+    xfree (sals.sals);
+
+  if (result)
+    return result;
+  Py_RETURN_NONE;
+}
+
 /* Parse a string and evaluate it as an expression.  */
 static PyObject *
 gdbpy_parse_and_eval (PyObject *self, PyObject *args)
@@ -361,6 +468,114 @@ source_python_script (FILE *stream, char *file)
 
 
 
+/* Posting and handling events.  */
+
+/* A single event.  */
+struct gdbpy_event
+{
+  /* The Python event.  This is just a callable object.  */
+  PyObject *event;
+  /* The next event.  */
+  struct gdbpy_event *next;
+};
+
+/* All pending events.  */
+static struct gdbpy_event *gdbpy_event_list;
+/* The final link of the event list.  */
+static struct gdbpy_event **gdbpy_event_list_end;
+
+/* We use a file handler, and not an async handler, so that we can
+   wake up the main thread even when it is blocked in poll().  */
+static int gdbpy_event_fds[2];
+
+/* The file handler callback.  This reads from the internal pipe, and
+   then processes the Python event queue.  This will always be run in
+   the main gdb thread.  */
+static void
+gdbpy_run_events (int err, gdb_client_data ignore)
+{
+  struct cleanup *cleanup;
+  char buffer[100];
+  int r;
+
+  cleanup = ensure_python_env (get_current_arch (), current_language);
+
+  /* Just read whatever is available on the fd.  It is relatively
+     harmless if there are any bytes left over.  */
+  r = read (gdbpy_event_fds[0], buffer, sizeof (buffer));
+
+  while (gdbpy_event_list)
+    {
+      /* Dispatching the event might push a new element onto the event
+	 loop, so we update here "atomically enough".  */
+      struct gdbpy_event *item = gdbpy_event_list;
+      gdbpy_event_list = gdbpy_event_list->next;
+      if (gdbpy_event_list == NULL)
+	gdbpy_event_list_end = &gdbpy_event_list;
+
+      /* Ignore errors.  */
+      PyObject_CallObject (item->event, NULL);
+
+      Py_DECREF (item->event);
+      xfree (item);
+    }
+
+  do_cleanups (cleanup);
+}
+
+/* Submit an event to the gdb thread.  */
+static PyObject *
+gdbpy_post_event (PyObject *self, PyObject *args)
+{
+  struct gdbpy_event *event;
+  PyObject *func;
+  int wakeup;
+
+  if (!PyArg_ParseTuple (args, "O", &func))
+    return NULL;
+
+  if (!PyCallable_Check (func))
+    {
+      PyErr_SetString (PyExc_RuntimeError, "Posted event is not callable");
+      return NULL;
+    }
+
+  Py_INCREF (func);
+
+  /* From here until the end of the function, we have the GIL, so we
+     can operate on our global data structures without worrying.  */
+  wakeup = gdbpy_event_list == NULL;
+
+  event = XNEW (struct gdbpy_event);
+  event->event = func;
+  event->next = NULL;
+  *gdbpy_event_list_end = event;
+  gdbpy_event_list_end = &event->next;
+
+  /* Wake up gdb when needed.  */
+  if (wakeup)
+    {
+      char c = 'q';		/* Anything. */
+      if (write (gdbpy_event_fds[1], &c, 1) != 1)
+        return PyErr_SetFromErrno (PyExc_IOError);
+    }
+
+  Py_RETURN_NONE;
+}
+
+/* Initialize the Python event handler.  */
+static void
+gdbpy_initialize_events (void)
+{
+  if (!pipe (gdbpy_event_fds))
+    {
+      gdbpy_event_list_end = &gdbpy_event_list;
+      add_file_handler (gdbpy_event_fds[0], gdbpy_run_events, NULL);
+    }
+}
+
+
+
 /* Printing.  */
 
 /* A python function to write a single string using gdb's filtered
@@ -397,6 +612,55 @@ gdbpy_print_stack (void)
 
 
 
+/* Script interface.  */
+
+/* True if 'gdb -P' was used, false otherwise.  */
+static int running_python_script;
+
+/* True if we are currently in a call to 'gdb.cli', false otherwise.  */
+static int in_cli;
+
+/* Enter the command loop.  */
+
+static PyObject *
+gdbpy_cli (PyObject *unused1, PyObject *unused2)
+{
+  if (! running_python_script || in_cli)
+    return PyErr_Format (PyExc_RuntimeError, "cannot invoke CLI recursively");
+
+  in_cli = 1;
+  cli_command_loop ();
+  in_cli = 0;
+
+  Py_RETURN_NONE;
+}
+
+/* Set up the Python argument vector and evaluate a script.  This is
+   used to implement 'gdb -P'.  */
+
+void
+run_python_script (int argc, char **argv)
+{
+  FILE *input;
+
+  /* We never free this, since we plan to exit at the end.  */
+  ensure_python_env (get_current_arch (), current_language);
+
+  running_python_script = 1;
+  PySys_SetArgv (argc - 1, argv + 1);
+  input = fopen (argv[0], "r");
+  if (! input)
+    {
+      fprintf (stderr, "could not open %s: %s\n", argv[0], strerror (errno));
+      exit (1);
+    }
+  PyRun_SimpleFile (input, argv[0]);
+  fclose (input);
+  exit (0);
+}
+
+
+
 /* The "current" objfile.  This is set when gdb detects that a new
    objfile has been loaded.  It is only set for the duration of a call
    to gdbpy_new_objfile; it is NULL at other times.  */
@@ -640,14 +904,28 @@ Enables or disables auto-loading of Python code when an object is opened."),
   PyModule_AddStringConstant (gdb_module, "VERSION", (char*) version);
   PyModule_AddStringConstant (gdb_module, "HOST_CONFIG", (char*) host_name);
   PyModule_AddStringConstant (gdb_module, "TARGET_CONFIG", (char*) target_name);
+#ifdef PYTHONDIR
+  PyModule_AddStringConstant (gdb_module, "pythondir", PYTHONDIR);
+#else
+  if (gdb_datadir)
+    PyModule_AddStringConstant (gdb_module, "datadir", gdb_datadir);
+#endif
 
   gdbpy_initialize_values ();
+  gdbpy_initialize_breakpoints ();
   gdbpy_initialize_frames ();
+  gdbpy_initialize_symtabs ();
   gdbpy_initialize_commands ();
+  gdbpy_initialize_symbols ();
+  gdbpy_initialize_blocks ();
   gdbpy_initialize_functions ();
   gdbpy_initialize_types ();
+  gdbpy_initialize_parameters ();
   gdbpy_initialize_objfile ();
   gdbpy_initialize_lazy_string ();
+  gdbpy_initialize_thread ();
+  gdbpy_initialize_inferior ();
+  gdbpy_initialize_events ();
 
   PyRun_SimpleString ("import gdb");
   PyRun_SimpleString ("gdb.pretty_printers = []");
@@ -683,6 +961,15 @@ class GdbOutputFile:\n\
 \n\
 sys.stderr = GdbOutputFile()\n\
 sys.stdout = GdbOutputFile()\n\
+if hasattr (gdb, 'datadir'):\n\
+  gdb.pythondir = gdb.datadir + '/python'\n\
+if hasattr (gdb, 'pythondir'):\n\
+  sys.path.insert(0, gdb.pythondir)\n\
+  gdb.__path__ = [gdb.pythondir + '/gdb']\n\
+  from os.path import exists\n\
+  ipy = gdb.pythondir + '/gdb/__init__.py'\n\
+  if exists (ipy):\n\
+    execfile (ipy)\n\
 ");
 
   /* Release the GIL while gdb runs.  */
@@ -702,9 +989,14 @@ static PyMethodDef GdbMethods[] =
     "Get a value from history" },
   { "execute", execute_gdb_command, METH_VARARGS,
     "Execute a gdb command" },
+  { "cli", gdbpy_cli, METH_NOARGS,
+    "Enter the gdb CLI" },
   { "parameter", gdbpy_parameter, METH_VARARGS,
     "Return a gdb parameter's value" },
 
+  { "breakpoints", gdbpy_breakpoints, METH_NOARGS,
+    "Return a tuple of all breakpoint objects" },
+
   { "default_visualizer", gdbpy_default_visualizer, METH_VARARGS,
     "Find the default visualizer for a Value." },
 
@@ -725,11 +1017,39 @@ Return a string explaining unwind stop reason." },
     "lookup_type (name [, block]) -> type\n\
 Return a Type corresponding to the given name." },
 
+  { "lookup_symbol", (PyCFunction) gdbpy_lookup_symbol,
+    METH_VARARGS | METH_KEYWORDS,
+    "lookup_symbol (name [, block] [, domain]) -> (symbol, is_field_of_this)\n\
+Return a tuple with the symbol corresponding to the given name (or None) and\n\
+a boolean indicating if name is a field of the current implied argument\n\
+`this' (when the current language is object-oriented)." },
+  { "solib_address", gdbpy_solib_address, METH_VARARGS,
+    "solib_address (Long) -> String.\n\
+Return the name of the shared library holding a given address, or None." },
+
+  { "block_for_pc", gdbpy_block_for_pc, METH_VARARGS,
+    "Return the block containing the given pc value, or None." },
+
+  { "decode_line", gdbpy_decode_line, METH_VARARGS,
+    "Decode a string argument the way that 'break' or 'edit' does.\n\
+Return a tuple holding the file name (or None) and line number (or None).\n\
+Note: may later change to return an object." },
+
+  { "selected_thread", gdbpy_selected_thread, METH_NOARGS,
+    "selected_thread () -> gdb.InferiorThread.\n\
+Return the selected thread object." },
+  { "inferiors", gdbpy_inferiors, METH_NOARGS,
+    "inferiors () -> (gdb.Inferior, ...).\n\
+Return a tuple containing all inferiors." },
+
   { "parse_and_eval", gdbpy_parse_and_eval, METH_VARARGS,
     "parse_and_eval (String) -> Value.\n\
 Parse String as an expression, evaluate it, and return the result as a Value."
   },
 
+  { "post_event", gdbpy_post_event, METH_VARARGS,
+    "Post an event into gdb's event loop." },
+
   { "write", gdbpy_write, METH_VARARGS,
     "Write a string using gdb's filtered stream." },
   { "flush", gdbpy_flush, METH_NOARGS,
diff --git a/gdb/python/python.h b/gdb/python/python.h
index 5d93f67..1a5b9a8 100644
--- a/gdb/python/python.h
+++ b/gdb/python/python.h
@@ -26,6 +26,8 @@ void eval_python_from_control_command (struct command_line *);
 
 void source_python_script (FILE *stream, char *file);
 
+void run_python_script (int argc, char **argv);
+
 int apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr,
 			      int embedded_offset, CORE_ADDR address,
 			      struct ui_file *stream, int recurse,
diff --git a/gdb/scm-lang.c b/gdb/scm-lang.c
index 5898aad..23e5f22 100644
--- a/gdb/scm-lang.c
+++ b/gdb/scm-lang.c
@@ -231,6 +231,7 @@ const struct exp_descriptor exp_descriptor_scm =
 {
   print_subexp_standard,
   operator_length_standard,
+  operator_check_standard,
   op_name_standard,
   dump_subexp_body_standard,
   evaluate_exp
diff --git a/gdb/scm-valprint.c b/gdb/scm-valprint.c
index 1e8d48e..95185d4 100644
--- a/gdb/scm-valprint.c
+++ b/gdb/scm-valprint.c
@@ -62,9 +62,9 @@ scm_inferior_print (struct type *type, LONGEST value, struct ui_file *stream,
     {
       /* XXX: Should we cache these symbols?  */
       gdb_output_sym =
-	lookup_symbol_global ("gdb_output", NULL, NULL, VAR_DOMAIN);
+	lookup_symbol_global ("gdb_output", NULL, VAR_DOMAIN);
       gdb_output_len_sym =
-	lookup_symbol_global ("gdb_output_length", NULL, NULL, VAR_DOMAIN);
+	lookup_symbol_global ("gdb_output_length", NULL, VAR_DOMAIN);
 
       if ((gdb_output_sym == NULL) || (gdb_output_len_sym == NULL))
 	ret = -1;
diff --git a/gdb/sh-linux-tdep.c b/gdb/sh-linux-tdep.c
index da4137b..e3fcb1a 100644
--- a/gdb/sh-linux-tdep.c
+++ b/gdb/sh-linux-tdep.c
@@ -25,6 +25,7 @@
 
 #include "glibc-tdep.h"
 #include "sh-tdep.h"
+#include "linux-tdep.h"
 
 #define REGSx16(base) \
   {(base),      0}, \
@@ -89,6 +90,9 @@ sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
       tdep->core_gregmap = (struct sh_corefile_regmap *)gregs_table;
       tdep->core_fpregmap = (struct sh_corefile_regmap *)fpregs_table;
     }
+
+  set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+					  linux_convert_from_func_ptr_addr);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
index 3c70089..0ee7d85 100644
--- a/gdb/solib-darwin.c
+++ b/gdb/solib-darwin.c
@@ -408,7 +408,6 @@ darwin_relocate_section_addresses (struct so_list *so,
 static struct symbol *
 darwin_lookup_lib_symbol (const struct objfile *objfile,
 			  const char *name,
-			  const char *linkage_name,
 			  const domain_enum domain)
 {
   return NULL;
diff --git a/gdb/solib-spu.c b/gdb/solib-spu.c
index 94a77fb..7ea68d2 100644
--- a/gdb/solib-spu.c
+++ b/gdb/solib-spu.c
@@ -326,16 +326,13 @@ spu_bfd_open (char *pathname)
 static struct symbol *
 spu_lookup_lib_symbol (const struct objfile *objfile,
 		       const char *name,
-		       const char *linkage_name,
 		       const domain_enum domain)
 {
   if (bfd_get_arch (objfile->obfd) == bfd_arch_spu)
-    return lookup_global_symbol_from_objfile (objfile, name, linkage_name,
-					      domain);
+    return lookup_global_symbol_from_objfile (objfile, name, domain);
 
   if (svr4_so_ops.lookup_lib_global_symbol != NULL)
-    return svr4_so_ops.lookup_lib_global_symbol (objfile, name, linkage_name,
-						 domain);
+    return svr4_so_ops.lookup_lib_global_symbol (objfile, name, domain);
   return NULL;
 }
 
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 8edc889..5ea1779 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -1241,7 +1241,8 @@ svr4_in_dynsym_resolve_code (CORE_ADDR pc)
 	   && pc < info->interp_text_sect_high)
 	  || (pc >= info->interp_plt_sect_low
 	      && pc < info->interp_plt_sect_high)
-	  || in_plt_section (pc, NULL));
+	  || in_plt_section (pc, NULL)
+	  || in_gnu_ifunc_stub (pc));
 }
 
 /* Given an executable's ABFD and target, compute the entry-point
@@ -2038,7 +2039,6 @@ struct target_so_ops svr4_so_ops;
 static struct symbol *
 elf_lookup_lib_symbol (const struct objfile *objfile,
 		       const char *name,
-		       const char *linkage_name,
 		       const domain_enum domain)
 {
   bfd *abfd;
@@ -2056,8 +2056,7 @@ elf_lookup_lib_symbol (const struct objfile *objfile,
   if (abfd == NULL || scan_dyntag (DT_SYMBOLIC, abfd, NULL) != 1)
     return NULL;
 
-  return lookup_global_symbol_from_objfile
-		(objfile, name, linkage_name, domain);
+  return lookup_global_symbol_from_objfile (objfile, name, domain);
 }
 
 extern initialize_file_ftype _initialize_svr4_solib; /* -Wmissing-prototypes */
diff --git a/gdb/solib.c b/gdb/solib.c
index 842b27c..ac1c407 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -1154,13 +1154,12 @@ show_auto_solib_add (struct ui_file *file, int from_tty,
 struct symbol *
 solib_global_lookup (const struct objfile *objfile,
 		     const char *name,
-		     const char *linkage_name,
 		     const domain_enum domain)
 {
   struct target_so_ops *ops = solib_ops (target_gdbarch);
 
   if (ops->lookup_lib_global_symbol != NULL)
-    return ops->lookup_lib_global_symbol (objfile, name, linkage_name, domain);
+    return ops->lookup_lib_global_symbol (objfile, name, domain);
   return NULL;
 }
 
diff --git a/gdb/solist.h b/gdb/solist.h
index 573f736..51bfce9 100644
--- a/gdb/solist.h
+++ b/gdb/solist.h
@@ -117,7 +117,6 @@ struct target_so_ops
     /* Hook for looking up global symbols in a library-specific way.  */
     struct symbol * (*lookup_lib_global_symbol) (const struct objfile *objfile,
 						 const char *name,
-						 const char *linkage_name,
 						 const domain_enum domain);
 
     /* Given two so_list objects, one from the GDB thread list
@@ -157,7 +156,6 @@ extern struct target_so_ops *current_target_so_ops;
 /* Handler for library-specific global symbol lookup in solib.c.  */
 struct symbol *solib_global_lookup (const struct objfile *objfile,
 				    const char *name,
-				    const char *linkage_name,
 				    const domain_enum domain);
 
 #endif
diff --git a/gdb/somread.c b/gdb/somread.c
index 3d93c5e..a943806 100644
--- a/gdb/somread.c
+++ b/gdb/somread.c
@@ -432,6 +432,7 @@ static struct sym_fns som_sym_fns =
   som_new_init,			/* sym_new_init: init anything gbl to entire symtab */
   som_symfile_init,		/* sym_init: read initial info, setup for sym_read() */
   som_symfile_read,		/* sym_read: read a symbol file into symtab */
+  NULL,				/* sym_read_psymbols */
   som_symfile_finish,		/* sym_finish: finished with file, cleanup */
   som_symfile_offsets,		/* sym_offsets:  Translate ext. to int. relocation */
   default_symfile_segments,	/* sym_segments: Get segment information from
diff --git a/gdb/sparc-linux-tdep.c b/gdb/sparc-linux-tdep.c
index d65db6c..e91c0bf 100644
--- a/gdb/sparc-linux-tdep.c
+++ b/gdb/sparc-linux-tdep.c
@@ -32,6 +32,7 @@
 #include "symtab.h"
 #include "trad-frame.h"
 #include "tramp-frame.h"
+#include "linux-tdep.h"
 
 #include "sparc-tdep.h"
 
@@ -279,6 +280,9 @@ sparc32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   dwarf2_append_unwinders (gdbarch);
 
   set_gdbarch_write_pc (gdbarch, sparc_linux_write_pc);
+
+  set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+					  linux_convert_from_func_ptr_addr);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */
diff --git a/gdb/sparc64-linux-tdep.c b/gdb/sparc64-linux-tdep.c
index 8b7e908..4de6d9c 100644
--- a/gdb/sparc64-linux-tdep.c
+++ b/gdb/sparc64-linux-tdep.c
@@ -31,6 +31,7 @@
 #include "symtab.h"
 #include "trad-frame.h"
 #include "tramp-frame.h"
+#include "linux-tdep.h"
 
 #include "sparc64-tdep.h"
 
@@ -244,6 +245,9 @@ sparc64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->step_trap = sparc64_linux_step_trap;
 
   set_gdbarch_write_pc (gdbarch, sparc64_linux_write_pc);
+
+  set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+					  linux_convert_from_func_ptr_addr);
 }
 
 
diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c
index c6db8dc..7359b50 100644
--- a/gdb/spu-tdep.c
+++ b/gdb/spu-tdep.c
@@ -1841,7 +1841,7 @@ spu_catch_start (struct objfile *objfile)
       struct symbol *sym;
       struct symtab_and_line sal;
 
-      sym = lookup_block_symbol (block, "main", NULL, VAR_DOMAIN);
+      sym = lookup_block_symbol (block, "main", VAR_DOMAIN);
       if (sym)
 	{
 	  fixup_symbol_section (sym, objfile);
diff --git a/gdb/stack.c b/gdb/stack.c
index 2caf9d2..7adc399 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -1309,24 +1309,24 @@ backtrace_command_1 (char *count_exp, int show_locals, int from_tty)
   else
     count = -1;
 
-  if (info_verbose)
-    {
-      struct partial_symtab *ps;
-
-      /* Read in symbols for all of the frames.  Need to do this in a
-         separate pass so that "Reading in symbols for xxx" messages
-         don't screw up the appearance of the backtrace.  Also if
-         people have strong opinions against reading symbols for
-         backtrace this may have to be an option.  */
-      i = count;
-      for (fi = trailing; fi != NULL && i--; fi = get_prev_frame (fi))
-	{
-	  QUIT;
-	  ps = find_pc_psymtab (get_frame_address_in_block (fi));
-	  if (ps)
-	    PSYMTAB_TO_SYMTAB (ps); /* Force syms to come in.  */
-	}
-    }
+  {
+    struct partial_symtab *ps;
+
+    /* Read in symbols for all of the frames.  Need to do this
+       unconditionally to ensure that psymbols are read.  Also need to
+       do this in a separate pass so that "Reading in symbols for xxx"
+       messages don't screw up the appearance of the backtrace.  Also
+       if people have strong opinions against reading symbols for
+       backtrace this may have to be an option.  */
+    i = count;
+    for (fi = trailing; fi != NULL && i--; fi = get_prev_frame (fi))
+      {
+	QUIT;
+	ps = find_pc_psymtab (get_frame_address_in_block (fi));
+	if (info_verbose && ps)
+	  PSYMTAB_TO_SYMTAB (ps); /* Force syms to come in.  */
+      }
+  }
 
   for (i = 0, fi = trailing; fi && count--; i++, fi = get_prev_frame (fi))
     {
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 8705420..16f96a1 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -968,13 +968,16 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
   /* Give user a chance to burp if we'd be
      interactively wiping out any existing symbols.  */
 
-  if ((have_full_symbols () || have_partial_symbols ())
-      && (add_flags & SYMFILE_MAINLINE)
+  if ((add_flags & SYMFILE_MAINLINE)
+      && (have_full_symbols () || have_partial_symbols ())
       && from_tty
+      && (have_full_symbols () || have_partial_symbols ())
       && !query (_("Load new symbol table from \"%s\"? "), name))
     error (_("Not confirmed."));
 
   objfile = allocate_objfile (abfd, flags);
+  if (add_flags & SYMFILE_MAINLINE)
+    objfile->flags |= OBJF_MAIN;
   discard_cleanups (my_cleanups);
 
   /* We either created a new mapped symbol table, mapped an existing
@@ -1001,6 +1004,8 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
 
   if ((flags & OBJF_READNOW) || readnow_symbol_files)
     {
+      require_partial_symbols (objfile);
+
       if (from_tty || info_verbose)
 	{
 	  printf_unfiltered (_("expanding to full symbols..."));
@@ -2323,6 +2328,7 @@ reread_symbols (void)
 	  objfile->symtabs = NULL;
 	  objfile->psymtabs = NULL;
 	  objfile->psymtabs_addrmap = NULL;
+	  objfile->quick_addrmap = NULL;
 	  objfile->free_psymtabs = NULL;
 	  objfile->cp_namespace_symtab = NULL;
 	  objfile->msymbols = NULL;
@@ -2333,6 +2339,8 @@ reread_symbols (void)
 	  memset (&objfile->msymbol_demangled_hash, 0,
 		  sizeof (objfile->msymbol_demangled_hash));
 
+	  objfile->flags &= ~OBJF_SYMTABS_READ;
+
 	  objfile->psymbol_cache = bcache_xmalloc ();
 	  objfile->macro_cache = bcache_xmalloc ();
 	  objfile->filename_cache = bcache_xmalloc ();
diff --git a/gdb/symfile.h b/gdb/symfile.h
index fe95255..075610b 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -141,6 +141,12 @@ struct sym_fns
 
   void (*sym_read) (struct objfile *, int);
 
+  /* Read the partial symbols for an objfile.  This may be NULL, in
+     which case gdb assumes that sym_read already read the partial
+     symbols.  */
+
+  void (*sym_read_psymbols) (struct objfile *);
+
   /* Called when we are finished with an objfile.  Should do all
      cleanup that is specific to the object file format for the
      particular objfile.  */
@@ -330,8 +336,7 @@ extern int auto_solib_limit;
 
 extern void set_initial_language (void);
 
-extern struct partial_symtab *allocate_psymtab (const char *,
-						struct objfile *);
+extern struct partial_symtab *allocate_psymtab (const char *, struct objfile *);
 
 extern void discard_psymtab (struct partial_symtab *);
 
@@ -402,7 +407,7 @@ void free_symfile_segment_data (struct symfile_segment_data *data);
 /* From dwarf2read.c */
 
 extern int dwarf2_has_info (struct objfile *);
-
+extern void dwarf2_create_quick_addrmap (struct objfile *);
 extern void dwarf2_build_psymtabs (struct objfile *);
 extern void dwarf2_build_frame_info (struct objfile *);
 
diff --git a/gdb/symmisc.c b/gdb/symmisc.c
index 1f3eb9e..3ff239a 100644
--- a/gdb/symmisc.c
+++ b/gdb/symmisc.c
@@ -294,6 +294,9 @@ dump_msymbols (struct objfile *objfile, struct ui_file *outfile)
 	case mst_text:
 	  ms_type = 'T';
 	  break;
+	case mst_text_gnu_ifunc:
+	  ms_type = 'i';
+	  break;
 	case mst_solib_trampoline:
 	  ms_type = 'S';
 	  break;
@@ -1143,7 +1146,7 @@ maintenance_check_symtabs (char *ignore, int from_tty)
     while (length--)
       {
 	sym = lookup_block_symbol (b, SYMBOL_LINKAGE_NAME (*psym),
-				   NULL, SYMBOL_DOMAIN (*psym));
+				   SYMBOL_DOMAIN (*psym));
 	if (!sym)
 	  {
 	    printf_filtered ("Static symbol `");
@@ -1160,7 +1163,7 @@ maintenance_check_symtabs (char *ignore, int from_tty)
     while (length--)
       {
 	sym = lookup_block_symbol (b, SYMBOL_LINKAGE_NAME (*psym),
-				   NULL, SYMBOL_DOMAIN (*psym));
+				   SYMBOL_DOMAIN (*psym));
 	if (!sym)
 	  {
 	    printf_filtered ("Global symbol `");
diff --git a/gdb/symtab.c b/gdb/symtab.c
index af4e501..9537dae 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -42,6 +42,7 @@
 #include "ada-lang.h"
 #include "p-lang.h"
 #include "addrmap.h"
+#include "cp-support.h"
 
 #include "hashtab.h"
 
@@ -85,7 +86,6 @@ static int find_line_common (struct linetable *, int, int *);
 char *operator_chars (char *p, char **end);
 
 static struct symbol *lookup_symbol_aux (const char *name,
-					 const char *linkage_name,
 					 const struct block *block,
 					 const domain_enum domain,
 					 enum language language,
@@ -93,20 +93,19 @@ static struct symbol *lookup_symbol_aux (const char *name,
 
 static
 struct symbol *lookup_symbol_aux_local (const char *name,
-					const char *linkage_name,
 					const struct block *block,
-					const domain_enum domain);
+					const domain_enum domain,
+					enum language language,
+					int *is_a_field_of_this);
 
 static
 struct symbol *lookup_symbol_aux_symtabs (int block_index,
 					  const char *name,
-					  const char *linkage_name,
 					  const domain_enum domain);
 
 static
 struct symbol *lookup_symbol_aux_psymtabs (int block_index,
 					   const char *name,
-					   const char *linkage_name,
 					   const domain_enum domain);
 
 static int file_matches (char *, char **, int);
@@ -271,7 +270,7 @@ lookup_partial_symtab (const char *name)
       make_cleanup (xfree, real_path);
     }
 
-  ALL_PSYMTABS (objfile, pst)
+  ALL_PSYMTABS_REQUIRED (objfile, pst)
   {
     if (FILENAME_CMP (name, pst->filename) == 0)
       {
@@ -414,7 +413,8 @@ symbol_init_language_specific (struct general_symbol_info *gsymbol,
   gsymbol->language = language;
   if (gsymbol->language == language_cplus
       || gsymbol->language == language_java
-      || gsymbol->language == language_objc)
+      || gsymbol->language == language_objc
+      || gsymbol->language == language_fortran)
     {
       gsymbol->language_specific.cplus_specific.demangled_name = NULL;
     }
@@ -498,7 +498,7 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
       || gsymbol->language == language_auto)
     {
       demangled =
-        cplus_demangle (mangled, DMGL_PARAMS | DMGL_ANSI);
+        cplus_demangle (mangled, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE);
       if (demangled != NULL)
 	{
 	  gsymbol->language = language_cplus;
@@ -695,6 +695,7 @@ symbol_natural_name (const struct general_symbol_info *gsymbol)
     case language_cplus:
     case language_java:
     case language_objc:
+    case language_fortran:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
 	return gsymbol->language_specific.cplus_specific.demangled_name;
       break;
@@ -720,6 +721,7 @@ symbol_demangled_name (const struct general_symbol_info *gsymbol)
     case language_cplus:
     case language_java:
     case language_objc:
+    case language_fortran:
       if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
 	return gsymbol->language_specific.cplus_specific.demangled_name;
       break;
@@ -931,7 +933,13 @@ find_pc_sect_psymtab (CORE_ADDR pc, struct obj_section *section)
      than the later used TEXTLOW/TEXTHIGH one.  */
 
   ALL_OBJFILES (objfile)
-    if (objfile->psymtabs_addrmap != NULL)
+  {
+    if (objfile->quick_addrmap)
+      {
+	if (!addrmap_find (objfile->quick_addrmap, pc))
+	  continue;
+      }
+    if (require_partial_symbols (objfile)->psymtabs_addrmap != NULL)
       {
 	struct partial_symtab *pst;
 
@@ -964,6 +972,7 @@ find_pc_sect_psymtab (CORE_ADDR pc, struct obj_section *section)
 	    return pst;
 	  }
       }
+  }
 
   /* Existing PSYMTABS_ADDRMAP mapping is present even for PARTIAL_SYMTABs
      which still have no corresponding full SYMTABs read.  But it is not
@@ -1231,6 +1240,22 @@ fixup_psymbol_section (struct partial_symbol *psym, struct objfile *objfile)
   return psym;
 }
 
+/* Ensure that the partial symbols for OBJFILE have been loaded.  This
+   function always returns its argument, as a convenience.  */
+
+struct objfile *
+require_partial_symbols (struct objfile *objfile)
+{
+  if ((objfile->flags & OBJF_SYMTABS_READ) == 0)
+    {
+      objfile->flags |= OBJF_SYMTABS_READ;
+
+      if (objfile->sf->sym_read_psymbols)
+	(*objfile->sf->sym_read_psymbols) (objfile);
+    }
+  return objfile;
+}
+
 /* Find the definition for a specified symbol name NAME
    in domain DOMAIN, visible from lexical block BLOCK.
    Returns the struct symbol pointer, or zero if no symbol is found.
@@ -1257,10 +1282,14 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 {
   char *demangled_name = NULL;
   const char *modified_name = NULL;
-  const char *mangled_name = NULL;
   struct symbol *returnval;
   struct cleanup *cleanup = make_cleanup (null_cleanup, 0);
 
+  if(strncmp(name, "::", 2) == 0){/* this must be a global name */
+    name = name+2;
+    block = NULL;
+  }
+  
   modified_name = name;
 
   /* If we are using C++ or Java, demangle the name before doing a lookup, so
@@ -1270,7 +1299,6 @@ lookup_symbol_in_language (const char *name, const struct block *block,
       demangled_name = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS);
       if (demangled_name)
 	{
-	  mangled_name = name;
 	  modified_name = demangled_name;
 	  make_cleanup (xfree, demangled_name);
 	}
@@ -1292,7 +1320,6 @@ lookup_symbol_in_language (const char *name, const struct block *block,
 		      		       DMGL_ANSI | DMGL_PARAMS | DMGL_JAVA);
       if (demangled_name)
 	{
-	  mangled_name = name;
 	  modified_name = demangled_name;
 	  make_cleanup (xfree, demangled_name);
 	}
@@ -1311,8 +1338,8 @@ lookup_symbol_in_language (const char *name, const struct block *block,
       modified_name = copy;
     }
 
-  returnval = lookup_symbol_aux (modified_name, mangled_name, block,
-				 domain, lang, is_a_field_of_this);
+  returnval = lookup_symbol_aux (modified_name, block, domain, lang,
+				 is_a_field_of_this);
   do_cleanups (cleanup);
 
   return returnval;
@@ -1336,9 +1363,9 @@ lookup_symbol (const char *name, const struct block *block,
    well.  */
 
 static struct symbol *
-lookup_symbol_aux (const char *name, const char *linkage_name,
-		   const struct block *block, const domain_enum domain,
-		   enum language language, int *is_a_field_of_this)
+lookup_symbol_aux (const char *name, const struct block *block,
+		   const domain_enum domain, enum language language,
+		   int *is_a_field_of_this)
 {
   struct symbol *sym;
   const struct language_defn *langdef;
@@ -1354,56 +1381,19 @@ lookup_symbol_aux (const char *name, const char *linkage_name,
   /* Search specified block and its superiors.  Don't search
      STATIC_BLOCK or GLOBAL_BLOCK.  */
 
-  sym = lookup_symbol_aux_local (name, linkage_name, block, domain);
+  sym = lookup_symbol_aux_local (name, block, domain, language, is_a_field_of_this);
   if (sym != NULL)
     return sym;
 
-  /* If requested to do so by the caller and if appropriate for LANGUAGE,
-     check to see if NAME is a field of `this'. */
-
-  langdef = language_def (language);
-
-  if (langdef->la_name_of_this != NULL && is_a_field_of_this != NULL
-      && block != NULL)
-    {
-      struct symbol *sym = NULL;
-      const struct block *function_block = block;
-      /* 'this' is only defined in the function's block, so find the
-	 enclosing function block.  */
-      for (; function_block && !BLOCK_FUNCTION (function_block);
-	   function_block = BLOCK_SUPERBLOCK (function_block));
-
-      if (function_block && !dict_empty (BLOCK_DICT (function_block)))
-	sym = lookup_block_symbol (function_block, langdef->la_name_of_this,
-				   NULL, VAR_DOMAIN);
-      if (sym)
-	{
-	  struct type *t = sym->type;
-
-	  /* I'm not really sure that type of this can ever
-	     be typedefed; just be safe.  */
-	  CHECK_TYPEDEF (t);
-	  if (TYPE_CODE (t) == TYPE_CODE_PTR
-	      || TYPE_CODE (t) == TYPE_CODE_REF)
-	    t = TYPE_TARGET_TYPE (t);
-
-	  if (TYPE_CODE (t) != TYPE_CODE_STRUCT
-	      && TYPE_CODE (t) != TYPE_CODE_UNION)
-	    error (_("Internal error: `%s' is not an aggregate"),
-		   langdef->la_name_of_this);
-
-	  if (check_field (t, name))
-	    {
-	      *is_a_field_of_this = 1;
-	      return NULL;
-	    }
-	}
-    }
+  /* this symbol was found to be a member variable
+     do not perform the global search. */
+  if (is_a_field_of_this && *is_a_field_of_this)
+    return NULL;
 
   /* Now do whatever is appropriate for LANGUAGE to look
      up static and global variables.  */
-
-  sym = langdef->la_lookup_symbol_nonlocal (name, linkage_name, block, domain);
+  langdef = language_def (language);
+  sym = langdef->la_lookup_symbol_nonlocal (name, block, domain);
   if (sym != NULL)
     return sym;
 
@@ -1413,11 +1403,11 @@ lookup_symbol_aux (const char *name, const char *linkage_name,
      desired name as a file-level static, then do psymtab-to-symtab
      conversion on the fly and return the found symbol. */
 
-  sym = lookup_symbol_aux_symtabs (STATIC_BLOCK, name, linkage_name, domain);
+  sym = lookup_symbol_aux_symtabs (STATIC_BLOCK, name, domain);
   if (sym != NULL)
     return sym;
 
-  sym = lookup_symbol_aux_psymtabs (STATIC_BLOCK, name, linkage_name, domain);
+  sym = lookup_symbol_aux_psymtabs (STATIC_BLOCK, name, domain);
   if (sym != NULL)
     return sym;
 
@@ -1428,30 +1418,81 @@ lookup_symbol_aux (const char *name, const char *linkage_name,
    Don't search STATIC_BLOCK or GLOBAL_BLOCK.  */
 
 static struct symbol *
-lookup_symbol_aux_local (const char *name, const char *linkage_name,
-			 const struct block *block,
-			 const domain_enum domain)
+lookup_symbol_aux_local (const char *name, const struct block *block,
+			 const domain_enum domain, enum language language,
+			 int *is_a_field_of_this)
 {
   struct symbol *sym;
-  const struct block *static_block = block_static_block (block);
+  const struct block *global_block = block_global_block (block);
+  const struct block *block_iterator = block;
+  const struct language_defn *langdef;
+
+  langdef = language_def (language);
 
   /* Check if either no block is specified or it's a global block.  */
 
-  if (static_block == NULL)
+  if (global_block == NULL)
     return NULL;
 
-  while (block != static_block)
+  while (block_iterator != global_block)
     {
-      sym = lookup_symbol_aux_block (name, linkage_name, block, domain);
+
+      sym = lookup_symbol_aux_block (name, block_iterator, domain);
+
       if (sym != NULL)
 	return sym;
+    
+      if (language == language_cplus )
+        {
+          sym = cp_lookup_symbol_imports (block_scope (block_iterator), name,
+                                          block_iterator, domain, 1, 1);
 
-      if (BLOCK_FUNCTION (block) != NULL && block_inlined_p (block))
-	break;
-      block = BLOCK_SUPERBLOCK (block);
+          if (sym != NULL)
+            return sym;
+        }
+
+      if (langdef->la_name_of_this != NULL && is_a_field_of_this != NULL
+	  && BLOCK_FUNCTION (block_iterator))
+        {
+          if (!dict_empty (BLOCK_DICT (block_iterator)))
+            {
+              sym = lookup_block_symbol (block_iterator,
+					 langdef->la_name_of_this,
+					 VAR_DOMAIN);
+
+
+              if (sym)
+                {
+                  struct type *t = sym->type;
+
+                  /* I'm not really sure that type of this can ever
+                     be typedefed; just be safe.  */
+                  CHECK_TYPEDEF (t);
+                  if (TYPE_CODE (t) == TYPE_CODE_PTR
+                      || TYPE_CODE (t) == TYPE_CODE_REF)
+                      t = TYPE_TARGET_TYPE (t);
+
+                  if (TYPE_CODE (t) != TYPE_CODE_STRUCT
+                      && TYPE_CODE (t) != TYPE_CODE_UNION)
+                    error (_("Internal error: `%s' is not an aggregate"),
+                        langdef->la_name_of_this);
+
+                  if (check_field (t, name))
+                    {
+                      *is_a_field_of_this = 1;
+                      return NULL;
+                    }
+                }
+            }
+        }
+
+      if (BLOCK_FUNCTION (block_iterator) != NULL && block_inlined_p (block_iterator))
+        break;
+
+      block_iterator = BLOCK_SUPERBLOCK (block_iterator);
     }
 
-  /* We've reached the edge of the function without finding a result.  */
+  /* We've reached the global block without finding a result.  */
 
   return NULL;
 }
@@ -1485,13 +1526,12 @@ lookup_objfile_from_block (const struct block *block)
    block_found appropriately.  */
 
 struct symbol *
-lookup_symbol_aux_block (const char *name, const char *linkage_name,
-			 const struct block *block,
+lookup_symbol_aux_block (const char *name, const struct block *block,
 			 const domain_enum domain)
 {
   struct symbol *sym;
 
-  sym = lookup_block_symbol (block, name, linkage_name, domain);
+  sym = lookup_block_symbol (block, name, domain);
   if (sym)
     {
       block_found = block;
@@ -1507,7 +1547,6 @@ lookup_symbol_aux_block (const char *name, const char *linkage_name,
 struct symbol *
 lookup_global_symbol_from_objfile (const struct objfile *main_objfile,
 				   const char *name,
-				   const char *linkage_name,
 				   const domain_enum domain)
 {
   const struct objfile *objfile;
@@ -1526,7 +1565,7 @@ lookup_global_symbol_from_objfile (const struct objfile *main_objfile,
         {
           bv = BLOCKVECTOR (s);
           block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-          sym = lookup_block_symbol (block, name, linkage_name, domain);
+          sym = lookup_block_symbol (block, name, domain);
           if (sym)
             {
               block_found = block;
@@ -1535,16 +1574,16 @@ lookup_global_symbol_from_objfile (const struct objfile *main_objfile,
         }
 
       /* Now go through psymtabs.  */
+      require_partial_symbols ((struct objfile *) objfile);
       ALL_OBJFILE_PSYMTABS (objfile, ps)
         {
           if (!ps->readin
-              && lookup_partial_symbol (ps, name, linkage_name,
-                                        1, domain))
+              && lookup_partial_symbol (ps, name, 1, domain))
             {
               s = PSYMTAB_TO_SYMTAB (ps);
               bv = BLOCKVECTOR (s);
               block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-              sym = lookup_block_symbol (block, name, linkage_name, domain);
+              sym = lookup_block_symbol (block, name, domain);
               return fixup_symbol_section (sym, (struct objfile *)objfile);
             }
         }
@@ -1559,8 +1598,7 @@ lookup_global_symbol_from_objfile (const struct objfile *main_objfile,
    static symbols.  */
 
 static struct symbol *
-lookup_symbol_aux_symtabs (int block_index,
-			   const char *name, const char *linkage_name,
+lookup_symbol_aux_symtabs (int block_index, const char *name,
 			   const domain_enum domain)
 {
   struct symbol *sym;
@@ -1573,7 +1611,7 @@ lookup_symbol_aux_symtabs (int block_index,
   {
     bv = BLOCKVECTOR (s);
     block = BLOCKVECTOR_BLOCK (bv, block_index);
-    sym = lookup_block_symbol (block, name, linkage_name, domain);
+    sym = lookup_block_symbol (block, name, domain);
     if (sym)
       {
 	block_found = block;
@@ -1591,7 +1629,6 @@ lookup_symbol_aux_symtabs (int block_index,
 
 static struct symbol *
 lookup_symbol_aux_psymtabs (int block_index, const char *name,
-			    const char *linkage_name,
 			    const domain_enum domain)
 {
   struct symbol *sym;
@@ -1602,16 +1639,15 @@ lookup_symbol_aux_psymtabs (int block_index, const char *name,
   struct symtab *s;
   const int psymtab_index = (block_index == GLOBAL_BLOCK ? 1 : 0);
 
-  ALL_PSYMTABS (objfile, ps)
+  ALL_PSYMTABS_REQUIRED (objfile, ps)
   {
     if (!ps->readin
-	&& lookup_partial_symbol (ps, name, linkage_name,
-				  psymtab_index, domain))
+	&& lookup_partial_symbol (ps, name, psymtab_index, domain))
       {
 	s = PSYMTAB_TO_SYMTAB (ps);
 	bv = BLOCKVECTOR (s);
 	block = BLOCKVECTOR_BLOCK (bv, block_index);
-	sym = lookup_block_symbol (block, name, linkage_name, domain);
+	sym = lookup_block_symbol (block, name, domain);
 	if (!sym)
 	  {
 	    /* This shouldn't be necessary, but as a last resort try
@@ -1628,7 +1664,7 @@ lookup_symbol_aux_psymtabs (int block_index, const char *name,
 	    block = BLOCKVECTOR_BLOCK (bv,
 				       block_index == GLOBAL_BLOCK ?
 				       STATIC_BLOCK : GLOBAL_BLOCK);
-	    sym = lookup_block_symbol (block, name, linkage_name, domain);
+	    sym = lookup_block_symbol (block, name, domain);
 	    if (!sym)
 	      error (_("Internal: %s symbol `%s' found in %s psymtab but not in symtab.\n%s may be an inlined function, or may be a template function\n(if a template, try specifying an instantiation: %s<type>)."),
 		     block_index == GLOBAL_BLOCK ? "global" : "static",
@@ -1647,7 +1683,6 @@ lookup_symbol_aux_psymtabs (int block_index, const char *name,
 
 struct symbol *
 basic_lookup_symbol_nonlocal (const char *name,
-			      const char *linkage_name,
 			      const struct block *block,
 			      const domain_enum domain)
 {
@@ -1681,11 +1716,11 @@ basic_lookup_symbol_nonlocal (const char *name,
      than that one, so I don't think we should worry about that for
      now.  */
 
-  sym = lookup_symbol_static (name, linkage_name, block, domain);
+  sym = lookup_symbol_static (name, block, domain);
   if (sym != NULL)
     return sym;
 
-  return lookup_symbol_global (name, linkage_name, block, domain);
+  return lookup_symbol_global (name, block, domain);
 }
 
 /* Lookup a symbol in the static block associated to BLOCK, if there
@@ -1693,14 +1728,13 @@ basic_lookup_symbol_nonlocal (const char *name,
 
 struct symbol *
 lookup_symbol_static (const char *name,
-		      const char *linkage_name,
 		      const struct block *block,
 		      const domain_enum domain)
 {
   const struct block *static_block = block_static_block (block);
 
   if (static_block != NULL)
-    return lookup_symbol_aux_block (name, linkage_name, static_block, domain);
+    return lookup_symbol_aux_block (name, static_block, domain);
   else
     return NULL;
 }
@@ -1710,7 +1744,6 @@ lookup_symbol_static (const char *name,
 
 struct symbol *
 lookup_symbol_global (const char *name,
-		      const char *linkage_name,
 		      const struct block *block,
 		      const domain_enum domain)
 {
@@ -1720,15 +1753,15 @@ lookup_symbol_global (const char *name,
   /* Call library-specific lookup procedure.  */
   objfile = lookup_objfile_from_block (block);
   if (objfile != NULL)
-    sym = solib_global_lookup (objfile, name, linkage_name, domain);
+    sym = solib_global_lookup (objfile, name, domain);
   if (sym != NULL)
     return sym;
 
-  sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, linkage_name, domain);
+  sym = lookup_symbol_aux_symtabs (GLOBAL_BLOCK, name, domain);
   if (sym != NULL)
     return sym;
 
-  return lookup_symbol_aux_psymtabs (GLOBAL_BLOCK, name, linkage_name, domain);
+  return lookup_symbol_aux_psymtabs (GLOBAL_BLOCK, name, domain);
 }
 
 int
@@ -1752,14 +1785,11 @@ symbol_matches_domain (enum language symbol_language,
 }
 
 /* Look, in partial_symtab PST, for symbol whose natural name is NAME.
-   If LINKAGE_NAME is non-NULL, check in addition that the symbol's
-   linkage name matches it.  Check the global symbols if GLOBAL, the
-   static symbols if not */
+   Check the global symbols if GLOBAL, the static symbols if not. */
 
 struct partial_symbol *
 lookup_partial_symbol (struct partial_symtab *pst, const char *name,
-		       const char *linkage_name, int global,
-		       domain_enum domain)
+		       int global, domain_enum domain)
 {
   struct partial_symbol *temp;
   struct partial_symbol **start, **psym;
@@ -1811,9 +1841,7 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name,
 	internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
 
       while (top <= real_top
-	     && (linkage_name != NULL
-		 ? strcmp (SYMBOL_LINKAGE_NAME (*top), linkage_name) == 0
-		 : SYMBOL_MATCHES_SEARCH_NAME (*top,name)))
+	     && SYMBOL_MATCHES_SEARCH_NAME (*top, name))
 	{
 	  if (symbol_matches_domain (SYMBOL_LANGUAGE (*top),
 				     SYMBOL_DOMAIN (*top), domain))
@@ -1830,15 +1858,9 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name,
       for (psym = start; psym < start + length; psym++)
 	{
 	  if (symbol_matches_domain (SYMBOL_LANGUAGE (*psym),
-				     SYMBOL_DOMAIN (*psym), domain))
-	    {
-	      if (linkage_name != NULL
-		  ? strcmp (SYMBOL_LINKAGE_NAME (*psym), linkage_name) == 0
-		  : SYMBOL_MATCHES_SEARCH_NAME (*psym, name))
-		{
-		  return (*psym);
-		}
-	    }
+				     SYMBOL_DOMAIN (*psym), domain)
+	      && SYMBOL_MATCHES_SEARCH_NAME (*psym, name))
+	    return (*psym);
 	}
     }
 
@@ -1880,22 +1902,25 @@ basic_lookup_transparent_type (const char *name)
   {
     bv = BLOCKVECTOR (s);
     block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-    sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
+    sym = lookup_block_symbol (block, name, STRUCT_DOMAIN);
     if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
       {
 	return SYMBOL_TYPE (sym);
       }
   }
 
-  ALL_PSYMTABS (objfile, ps)
+  /* FIXME: .debug_pubnames should be read in.
+     
+     One may also try to the first pass without the require_partial_symbols
+     call but that would behave nondeterministically.  */
+  ALL_PSYMTABS_REQUIRED (objfile, ps)
   {
-    if (!ps->readin && lookup_partial_symbol (ps, name, NULL,
-					      1, STRUCT_DOMAIN))
+    if (!ps->readin && lookup_partial_symbol (ps, name, 1, STRUCT_DOMAIN))
       {
 	s = PSYMTAB_TO_SYMTAB (ps);
 	bv = BLOCKVECTOR (s);
 	block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-	sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
+	sym = lookup_block_symbol (block, name, STRUCT_DOMAIN);
 	if (!sym)
 	  {
 	    /* This shouldn't be necessary, but as a last resort
@@ -1904,7 +1929,7 @@ basic_lookup_transparent_type (const char *name)
 	     * the psymtab gets it wrong in some cases.
 	     */
 	    block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-	    sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
+	    sym = lookup_block_symbol (block, name, STRUCT_DOMAIN);
 	    if (!sym)
 	      error (_("Internal: global symbol `%s' found in %s psymtab but not in symtab.\n\
 %s may be an inlined function, or may be a template function\n\
@@ -1928,21 +1953,26 @@ basic_lookup_transparent_type (const char *name)
   {
     bv = BLOCKVECTOR (s);
     block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-    sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
+    sym = lookup_block_symbol (block, name, STRUCT_DOMAIN);
     if (sym && !TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
       {
 	return SYMBOL_TYPE (sym);
       }
   }
 
-  ALL_PSYMTABS (objfile, ps)
+  /* FIXME: Something like .debug_pubnames containing also static symbols
+     should be read in.  Compiler needs to be taught to generate it first.
+     
+     One may also try to the first pass without the require_partial_symbols
+     call but that would behave nondeterministically.  */
+  ALL_PSYMTABS_REQUIRED (objfile, ps)
   {
-    if (!ps->readin && lookup_partial_symbol (ps, name, NULL, 0, STRUCT_DOMAIN))
+    if (!ps->readin && lookup_partial_symbol (ps, name, 0, STRUCT_DOMAIN))
       {
 	s = PSYMTAB_TO_SYMTAB (ps);
 	bv = BLOCKVECTOR (s);
 	block = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-	sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
+	sym = lookup_block_symbol (block, name, STRUCT_DOMAIN);
 	if (!sym)
 	  {
 	    /* This shouldn't be necessary, but as a last resort
@@ -1951,7 +1981,7 @@ basic_lookup_transparent_type (const char *name)
 	     * the psymtab gets it wrong in some cases.
 	     */
 	    block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
-	    sym = lookup_block_symbol (block, name, NULL, STRUCT_DOMAIN);
+	    sym = lookup_block_symbol (block, name, STRUCT_DOMAIN);
 	    if (!sym)
 	      error (_("Internal: static symbol `%s' found in %s psymtab but not in symtab.\n\
 %s may be an inlined function, or may be a template function\n\
@@ -1976,9 +2006,23 @@ find_main_psymtab (void)
   struct partial_symtab *pst;
   struct objfile *objfile;
 
-  ALL_PSYMTABS (objfile, pst)
+  ALL_OBJFILES (objfile)
+  {
+    if ((objfile->flags & OBJF_MAIN) == 0)
+      continue;
+    require_partial_symbols (objfile);
+    ALL_OBJFILE_PSYMTABS (objfile, pst)
+    {
+      if (lookup_partial_symbol (pst, main_name (), 1, VAR_DOMAIN))
+	{
+	  return pst;
+	}
+    }
+  }
+
+  ALL_PSYMTABS_REQUIRED (objfile, pst)
   {
-    if (lookup_partial_symbol (pst, main_name (), NULL, 1, VAR_DOMAIN))
+    if (lookup_partial_symbol (pst, main_name (), 1, VAR_DOMAIN))
       {
 	return (pst);
       }
@@ -1996,14 +2040,10 @@ find_main_psymtab (void)
    search on the symbols.  Each symbol which is marked as being a ObjC/C++
    symbol (language_cplus or language_objc set) has both the encoded and
    non-encoded names tested for a match.
-
-   If LINKAGE_NAME is non-NULL, verify that any symbol we find has this
-   particular mangled name.
 */
 
 struct symbol *
 lookup_block_symbol (const struct block *block, const char *name,
-		     const char *linkage_name,
 		     const domain_enum domain)
 {
   struct dict_iterator iter;
@@ -2016,9 +2056,7 @@ lookup_block_symbol (const struct block *block, const char *name,
 	   sym = dict_iter_name_next (name, &iter))
 	{
 	  if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
-				     SYMBOL_DOMAIN (sym), domain)
-	      && (linkage_name != NULL
-		  ? strcmp (SYMBOL_LINKAGE_NAME (sym), linkage_name) == 0 : 1))
+				     SYMBOL_DOMAIN (sym), domain))
 	    return sym;
 	}
       return NULL;
@@ -2038,9 +2076,7 @@ lookup_block_symbol (const struct block *block, const char *name,
 	   sym = dict_iter_name_next (name, &iter))
 	{
 	  if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
-				     SYMBOL_DOMAIN (sym), domain)
-	      && (linkage_name != NULL
-		  ? strcmp (SYMBOL_LINKAGE_NAME (sym), linkage_name) == 0 : 1))
+				     SYMBOL_DOMAIN (sym), domain))
 	    {
 	      sym_found = sym;
 	      if (!SYMBOL_IS_ARGUMENT (sym))
@@ -3201,7 +3237,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[],
   {mst_file_data, mst_solib_trampoline, mst_abs, mst_unknown};
   static enum minimal_symbol_type types4[]
   =
-  {mst_file_bss, mst_text, mst_abs, mst_unknown};
+  {mst_file_bss, mst_text_gnu_ifunc, mst_abs, mst_unknown};
   enum minimal_symbol_type ourtype;
   enum minimal_symbol_type ourtype2;
   enum minimal_symbol_type ourtype3;
@@ -3262,7 +3298,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[],
      matching the regexp.  That way we don't have to reproduce all of
      the machinery below. */
 
-  ALL_PSYMTABS (objfile, ps)
+  ALL_PSYMTABS_REQUIRED (objfile, ps)
   {
     struct partial_symbol **bound, **gbound, **sbound;
     int keep_going = 1;
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 167dfe8..2f88e93 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -280,6 +280,8 @@ enum minimal_symbol_type
 {
   mst_unknown = 0,		/* Unknown type, the default */
   mst_text,			/* Generally executable instructions */
+  mst_text_gnu_ifunc,		/* Executable code returning address
+				   of executable code */
   mst_data,			/* Generally initialized data */
   mst_bss,			/* Generally uninitialized data */
   mst_abs,			/* Generally absolute (nonrelocatable) */
@@ -396,7 +398,10 @@ typedef enum domain_enum_tag
   FUNCTIONS_DOMAIN,
 
   /* All defined types */
-  TYPES_DOMAIN
+  TYPES_DOMAIN,
+
+  /* Fortran module.  Their naming must be separate.  */
+  MODULE_DOMAIN
 }
 domain_enum;
 
@@ -994,7 +999,6 @@ extern struct symbol *lookup_symbol (const char *, const struct block *,
    that can't think of anything better to do.  */
 
 extern struct symbol *basic_lookup_symbol_nonlocal (const char *,
-						    const char *,
 						    const struct block *,
 						    const domain_enum);
 
@@ -1005,7 +1009,6 @@ extern struct symbol *basic_lookup_symbol_nonlocal (const char *,
    is one; do nothing if BLOCK is NULL or a global block.  */
 
 extern struct symbol *lookup_symbol_static (const char *name,
-					    const char *linkage_name,
 					    const struct block *block,
 					    const domain_enum domain);
 
@@ -1013,7 +1016,6 @@ extern struct symbol *lookup_symbol_static (const char *name,
    necessary).  */
 
 extern struct symbol *lookup_symbol_global (const char *name,
-					    const char *linkage_name,
 					    const struct block *block,
 					    const domain_enum domain);
 
@@ -1022,21 +1024,18 @@ extern struct symbol *lookup_symbol_global (const char *name,
    will fix up the symbol if necessary.  */
 
 extern struct symbol *lookup_symbol_aux_block (const char *name,
-					       const char *linkage_name,
 					       const struct block *block,
 					       const domain_enum domain);
 
 /* Lookup a partial symbol.  */
 
 extern struct partial_symbol *lookup_partial_symbol (struct partial_symtab *,
-						     const char *,
 						     const char *, int,
 						     domain_enum);
 
 /* lookup a symbol by name, within a specified block */
 
 extern struct symbol *lookup_block_symbol (const struct block *, const char *,
-					   const char *,
 					   const domain_enum);
 
 /* lookup a [struct, union, enum] by name, within a specified block */
@@ -1066,6 +1065,8 @@ extern void clear_pc_function_cache (void);
 
 /* from symtab.c: */
 
+struct objfile *require_partial_symbols (struct objfile *);
+
 /* lookup partial symbol table by filename */
 
 extern struct partial_symtab *lookup_partial_symtab (const char *);
@@ -1159,6 +1160,8 @@ extern struct minimal_symbol *lookup_minimal_symbol_by_pc_name
 
 extern struct minimal_symbol *lookup_minimal_symbol_by_pc (CORE_ADDR);
 
+extern int in_gnu_ifunc_stub (CORE_ADDR pc);
+
 extern struct minimal_symbol *
     lookup_minimal_symbol_and_objfile (const char *,
 				       struct objfile **);
@@ -1372,7 +1375,6 @@ extern /*const */ char *main_name (void);
 /* Check global symbols in objfile.  */
 struct symbol *lookup_global_symbol_from_objfile (const struct objfile *objfile,
 						  const char *name,
-						  const char *linkage_name,
 						  const domain_enum domain);
 
 extern struct symtabs_and_lines
diff --git a/gdb/target.c b/gdb/target.c
index e6659c9..eabd9fc 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -120,6 +120,8 @@ static int debug_to_insert_watchpoint (CORE_ADDR, int, int);
 
 static int debug_to_remove_watchpoint (CORE_ADDR, int, int);
 
+static int debug_to_detach_watchpoints (void);
+
 static int debug_to_stopped_by_watchpoint (void);
 
 static int debug_to_stopped_data_address (struct target_ops *, CORE_ADDR *);
@@ -583,6 +585,7 @@ update_current_target (void)
       INHERIT (to_remove_hw_breakpoint, t);
       INHERIT (to_insert_watchpoint, t);
       INHERIT (to_remove_watchpoint, t);
+      INHERIT (to_detach_watchpoints, t);
       INHERIT (to_stopped_data_address, t);
       INHERIT (to_have_steppable_watchpoint, t);
       INHERIT (to_have_continuable_watchpoint, t);
@@ -710,6 +713,9 @@ update_current_target (void)
   de_fault (to_remove_watchpoint,
 	    (int (*) (CORE_ADDR, int, int))
 	    return_minus_one);
+  de_fault (to_detach_watchpoints,
+	    (int (*) (void))
+	    return_zero);
   de_fault (to_stopped_by_watchpoint,
 	    (int (*) (void))
 	    return_zero);
@@ -3277,6 +3283,19 @@ debug_to_remove_watchpoint (CORE_ADDR addr, int len, int type)
   return retval;
 }
 
+static int
+debug_to_detach_watchpoints (void)
+{
+  int retval;
+
+  retval = debug_target.to_detach_watchpoints ();
+
+  fprintf_unfiltered (gdb_stdlog,
+		      "target_detach_watchpoints () = %ld\n",
+		      (unsigned long) retval);
+  return retval;
+}
+
 static void
 debug_to_terminal_init (void)
 {
@@ -3524,6 +3543,7 @@ setup_target_debug (void)
   current_target.to_remove_hw_breakpoint = debug_to_remove_hw_breakpoint;
   current_target.to_insert_watchpoint = debug_to_insert_watchpoint;
   current_target.to_remove_watchpoint = debug_to_remove_watchpoint;
+  current_target.to_detach_watchpoints = debug_to_detach_watchpoints;
   current_target.to_stopped_by_watchpoint = debug_to_stopped_by_watchpoint;
   current_target.to_stopped_data_address = debug_to_stopped_data_address;
   current_target.to_watchpoint_addr_within_range = debug_to_watchpoint_addr_within_range;
diff --git a/gdb/target.h b/gdb/target.h
index 7103ab2..741b2e5 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -422,6 +422,7 @@ struct target_ops
     int (*to_remove_hw_breakpoint) (struct gdbarch *, struct bp_target_info *);
     int (*to_remove_watchpoint) (CORE_ADDR, int, int);
     int (*to_insert_watchpoint) (CORE_ADDR, int, int);
+    int (*to_detach_watchpoints) (void);
     int (*to_stopped_by_watchpoint) (void);
     int to_have_steppable_watchpoint;
     int to_have_continuable_watchpoint;
@@ -1274,6 +1275,15 @@ extern char *normal_pid_to_str (ptid_t ptid);
 #define	target_remove_watchpoint(addr, len, type)	\
      (*current_target.to_remove_watchpoint) (addr, len, type)
 
+/* Clear all debug registers without affecting any register caches.  Function
+   acts on INFERIOR_PTID which should be the forked-off process, either the
+   non-threaded child one or the threaded parent one, depending on `set
+   follow-fork-mode'.  Both watchpoints and hardware breakpoints get removed.
+   Return 0 on success, -1 on failure.  */
+
+#define	target_detach_watchpoints()	\
+     (*current_target.to_detach_watchpoints) ()
+
 #define target_insert_hw_breakpoint(gdbarch, bp_tgt) \
      (*current_target.to_insert_hw_breakpoint) (gdbarch, bp_tgt)
 
@@ -1314,6 +1324,20 @@ extern int target_search_memory (CORE_ADDR start_addr,
                                  ULONGEST pattern_len,
                                  CORE_ADDR *found_addrp);
 
+/* Utility functions which can be used by search_memory implementations.  */
+
+void allocate_pattern_buffer (char **pattern_bufp, char **pattern_buf_end,
+			      ULONGEST *pattern_buf_size);
+
+void increase_pattern_buffer (char **pattern_bufp, char **pattern_buf_end,
+			      ULONGEST *pattern_buf_size, int val_bytes);
+
+int search_memory (CORE_ADDR *start_addr, ULONGEST *search_space_len,
+		   const char *pattern_buf, ULONGEST pattern_len,
+		   CORE_ADDR *found_addr);
+
+void put_bits (bfd_uint64_t data, char *buf, int bits, bfd_boolean big_p);
+
 /* Tracepoint-related operations.  */
 
 #define target_trace_init() \
diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-pointer-foo.S b/gdb/testsuite/gdb.arch/x86_64-vla-pointer-foo.S
new file mode 100644
index 0000000..83faaf6
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/x86_64-vla-pointer-foo.S
@@ -0,0 +1,457 @@
+	.file	"x86_64-vla-pointer.c"
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.text
+.Ltext0:
+.globl foo
+	.type	foo, @function
+foo:
+.LFB2:
+	.file 1 "x86_64-vla-pointer.c"
+	.loc 1 22 0
+	pushq	%rbp
+.LCFI0:
+	movq	%rsp, %rbp
+.LCFI1:
+	subq	$64, %rsp
+.LCFI2:
+	movl	%edi, -36(%rbp)
+	.loc 1 22 0
+	movq	%rsp, %rax
+	movq	%rax, -48(%rbp)
+	.loc 1 23 0
+	movl	-36(%rbp), %edx
+	movslq	%edx,%rax
+	subq	$1, %rax
+	movq	%rax, -24(%rbp)
+	.loc 1 24 0
+	movslq	%edx,%rax
+	addq	$15, %rax
+	addq	$15, %rax
+	shrq	$4, %rax
+	salq	$4, %rax
+	subq	%rax, %rsp
+	movq	%rsp, -56(%rbp)
+	movq	-56(%rbp), %rax
+	addq	$15, %rax
+	shrq	$4, %rax
+	salq	$4, %rax
+	movq	%rax, -56(%rbp)
+	movq	-56(%rbp), %rax
+	movq	%rax, -16(%rbp)
+	.loc 1 27 0
+	movl	$0, -4(%rbp)
+	jmp	.L2
+.L3:
+	.loc 1 28 0
+	movl	-4(%rbp), %esi
+	movl	-4(%rbp), %eax
+	movl	%eax, %ecx
+	movq	-16(%rbp), %rdx
+	movslq	%esi,%rax
+	movb	%cl, (%rdx,%rax)
+	.loc 1 27 0
+	addl	$1, -4(%rbp)
+.L2:
+	movl	-4(%rbp), %eax
+	cmpl	-36(%rbp), %eax
+	jl	.L3
+	.loc 1 30 0
+	.globl	break_here
+break_here:
+	movq	-16(%rbp), %rax
+	movb	$0, (%rax)
+	movq	-48(%rbp), %rsp
+	.loc 1 31 0
+	leave
+	ret
+.LFE2:
+	.size	foo, .-foo
+	.section	.debug_frame,"",@progbits
+.Lframe0:
+	.long	.LECIE0-.LSCIE0
+.LSCIE0:
+	.long	0xffffffff
+	.byte	0x1
+	.string	""
+	.uleb128 0x1
+	.sleb128 -8
+	.byte	0x10
+	.byte	0xc
+	.uleb128 0x7
+	.uleb128 0x8
+	.byte	0x90
+	.uleb128 0x1
+	.align 8
+.LECIE0:
+.LSFDE0:
+	.long	.LEFDE0-.LASFDE0
+.LASFDE0:
+	.long	.Lframe0
+	.quad	.LFB2
+	.quad	.LFE2-.LFB2
+	.byte	0x4
+	.long	.LCFI0-.LFB2
+	.byte	0xe
+	.uleb128 0x10
+	.byte	0x86
+	.uleb128 0x2
+	.byte	0x4
+	.long	.LCFI1-.LCFI0
+	.byte	0xd
+	.uleb128 0x6
+	.align 8
+.LEFDE0:
+	.section	.eh_frame,"a",@progbits
+.Lframe1:
+	.long	.LECIE1-.LSCIE1
+.LSCIE1:
+	.long	0x0
+	.byte	0x1
+	.string	"zR"
+	.uleb128 0x1
+	.sleb128 -8
+	.byte	0x10
+	.uleb128 0x1
+	.byte	0x3
+	.byte	0xc
+	.uleb128 0x7
+	.uleb128 0x8
+	.byte	0x90
+	.uleb128 0x1
+	.align 8
+.LECIE1:
+.LSFDE1:
+	.long	.LEFDE1-.LASFDE1
+.LASFDE1:
+	.long	.LASFDE1-.Lframe1
+	.long	.LFB2
+	.long	.LFE2-.LFB2
+	.uleb128 0x0
+	.byte	0x4
+	.long	.LCFI0-.LFB2
+	.byte	0xe
+	.uleb128 0x10
+	.byte	0x86
+	.uleb128 0x2
+	.byte	0x4
+	.long	.LCFI1-.LCFI0
+	.byte	0xd
+	.uleb128 0x6
+	.align 8
+.LEFDE1:
+	.text
+.Letext0:
+	.section	.debug_loc,"",@progbits
+.Ldebug_loc0:
+.LLST0:
+	.quad	.LFB2-.Ltext0
+	.quad	.LCFI0-.Ltext0
+	.value	0x2
+	.byte	0x77
+	.sleb128 8
+	.quad	.LCFI0-.Ltext0
+	.quad	.LCFI1-.Ltext0
+	.value	0x2
+	.byte	0x77
+	.sleb128 16
+	.quad	.LCFI1-.Ltext0
+	.quad	.LFE2-.Ltext0
+	.value	0x2
+	.byte	0x76
+	.sleb128 16
+	.quad	0x0
+	.quad	0x0
+	.section	.debug_info
+.Ldebug_relative:
+	.long	.Ldebug_end - .Ldebug_start
+.Ldebug_start:
+	.value	0x2
+	.long	.Ldebug_abbrev0
+	.byte	0x8
+	.uleb128 0x1
+	.long	.LASF2
+	.byte	0x1
+	.long	.LASF3
+	.long	.LASF4
+	.quad	.Ltext0
+	.quad	.Letext0
+	.long	.Ldebug_line0
+	.uleb128 0x2
+	.byte	0x1
+	.string	"foo"
+	.byte	0x1
+	.byte	0x16
+	.byte	0x1
+	.quad	.LFB2
+	.quad	.LFE2
+	.long	.LLST0
+	.long	.Ltype_int - .Ldebug_relative
+	.uleb128 0x3
+	.long	.LASF5
+	.byte	0x1
+	.byte	0x15
+	.long	.Ltype_int - .Ldebug_relative
+	.byte	0x2
+	.byte	0x91
+	.sleb128 -52
+.Ltag_pointer:
+	.uleb128 0x4
+	.byte	0x8	/* DW_AT_byte_size */
+	.long	.Ltag_array_type - .debug_info	/* DW_AT_type */
+	.uleb128 0x5	/* Abbrev Number: 5 (DW_TAG_variable) */
+	.long	.LASF0
+	.byte	0x1
+	.byte	0x18
+#if 1
+	.long	.Ltag_pointer - .debug_info
+#else
+	/* Debugging only: Skip the typedef indirection.  */
+	.long	.Ltag_array_type - .debug_info
+#endif
+	/* DW_AT_location: DW_FORM_block1: start */
+	.byte	0x3
+	.byte	0x91
+	.sleb128 -32
+#if 0
+	.byte	0x6	/* DW_OP_deref */
+#else
+	.byte	0x96	/* DW_OP_nop */
+#endif
+	/* DW_AT_location: DW_FORM_block1: end */
+	.uleb128 0x6
+	.string	"i"
+	.byte	0x1
+	.byte	0x19
+	.long	.Ltype_int - .Ldebug_relative
+	.byte	0x2
+	.byte	0x91
+	.sleb128 -20
+	.byte	0x0
+.Ltype_int:
+	.uleb128 0x7
+	.byte	0x4
+	.byte	0x5
+	.string	"int"
+.Ltag_array_type:
+	.uleb128 0x8	/* Abbrev Number: 8 (DW_TAG_array_type) */
+	.long	.Ltype_char - .Ldebug_relative
+	.long	.Ltype_ulong - .Ldebug_relative	/* DW_AT_sibling: DW_FORM_ref4 */
+1:	/* DW_AT_data_location: DW_FORM_block1: start */
+	.byte	2f - 3f	/* length */
+3:
+	.byte	0x97	/* DW_OP_push_object_address */
+#if 1
+	.byte	0x6	/* DW_OP_deref */
+#else
+	.byte	0x96	/* DW_OP_nop */
+#endif
+2:	/* DW_AT_data_location: DW_FORM_block1: end */
+	.uleb128 0x9
+	.long	.Ltype_char - .Ldebug_relative	/* DW_AT_type: DW_FORM_ref4 */
+	.byte	0x3
+	.byte	0x91
+	.sleb128 -40
+	.byte	0x6
+	.byte	0x0
+.Ltype_ulong:
+	.uleb128 0xa
+	.byte	0x8
+	.byte	0x7
+.Ltype_char:
+	.uleb128 0xb
+	.byte	0x1
+	.byte	0x6
+	.long	.LASF1
+	.byte	0x0
+.Ldebug_end:
+	.section	.debug_abbrev
+	.uleb128 0x1
+	.uleb128 0x11
+	.byte	0x1
+	.uleb128 0x25
+	.uleb128 0xe
+	.uleb128 0x13
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x1b
+	.uleb128 0xe
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x1
+	.uleb128 0x10
+	.uleb128 0x6
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0x2
+	.uleb128 0x2e
+	.byte	0x1
+	.uleb128 0x3f
+	.uleb128 0xc
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x27
+	.uleb128 0xc
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x1
+	.uleb128 0x40
+	.uleb128 0x6
+	.uleb128 0x1
+	.uleb128 0x13
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0x3
+	.uleb128 0x5
+	.byte	0x0
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x2
+	.uleb128 0xa
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0x4	/* .Ltag_pointer abbrev */
+	.uleb128 0x0f	/* DW_TAG_pointer_type */
+	.byte	0x0
+	.uleb128 0x0b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0x5
+	.uleb128 0x34
+	.byte	0x0
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x2
+	.uleb128 0xa
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0x6
+	.uleb128 0x34
+	.byte	0x0
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x2
+	.uleb128 0xa
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0x7
+	.uleb128 0x24
+	.byte	0x0
+	.uleb128 0xb
+	.uleb128 0xb
+	.uleb128 0x3e
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0x8
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0x8	/* Abbrev Number: 8 (DW_TAG_array_type) */
+	.uleb128 0x1
+	.byte	0x1
+	.uleb128 0x49	/* DW_AT_type */
+	.uleb128 0x13	/* DW_FORM_ref4 */
+	.uleb128 0x1	/* DW_AT_sibling */
+	.uleb128 0x13	/* DW_FORM_ref4 */
+	.uleb128 0x50	/* DW_AT_data_location */
+	.uleb128 0xa	/* DW_FORM_block1 */
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0x9
+	.uleb128 0x21
+	.byte	0x0
+	.uleb128 0x49	/* DW_AT_type */
+	.uleb128 0x13	/* DW_FORM_ref4 */
+	.uleb128 0x2f
+	.uleb128 0xa
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0xa
+	.uleb128 0x24
+	.byte	0x0
+	.uleb128 0xb
+	.uleb128 0xb
+	.uleb128 0x3e
+	.uleb128 0xb
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0xb
+	.uleb128 0x24
+	.byte	0x0
+	.uleb128 0xb
+	.uleb128 0xb
+	.uleb128 0x3e
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0xe
+	.byte	0x0
+	.byte	0x0
+	.byte	0x0
+	.section	.debug_pubnames,"",@progbits
+	.long	0x16
+	.value	0x2
+	.long	.Ldebug_info0
+	.long	0xa8
+	.long	0x2d
+	.string	"foo"
+	.long	0x0
+	.section	.debug_aranges,"",@progbits
+	.long	0x2c
+	.value	0x2
+	.long	.Ldebug_info0
+	.byte	0x8
+	.byte	0x0
+	.value	0x0
+	.value	0x0
+	.quad	.Ltext0
+	.quad	.Letext0-.Ltext0
+	.quad	0x0
+	.quad	0x0
+	.section	.debug_str,"MS",@progbits,1
+.LASF0:
+	.string	"array"
+.LASF5:
+	.string	"size"
+.LASF3:
+	.string	"x86_64-vla-pointer.c"
+.LASF6:
+	.string	"array_t"
+.LASF1:
+	.string	"char"
+.LASF4:
+	.string	"gdb.arch"
+.LASF2:
+	.string	"GNU C 4.3.2 20081105 (Red Hat 4.3.2-7)"
+	.ident	"GCC: (GNU) 4.3.2 20081105 (Red Hat 4.3.2-7)"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-pointer.c b/gdb/testsuite/gdb.arch/x86_64-vla-pointer.c
new file mode 100644
index 0000000..fe2c8f7
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/x86_64-vla-pointer.c
@@ -0,0 +1,43 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2009 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/>.  */
+
+#if 0
+
+void
+foo (int size)
+{
+  typedef char array_t[size];
+  array_t array;
+  int i;
+
+  for (i = 0; i < size; i++)
+    array[i] = i;
+
+  array[0] = 0;	/* break-here */
+}
+
+#else
+
+int
+main (void)
+{
+  foo (26);
+  foo (78);
+  return 0;
+}
+
+#endif
diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-pointer.exp b/gdb/testsuite/gdb.arch/x86_64-vla-pointer.exp
new file mode 100644
index 0000000..d243cf1
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/x86_64-vla-pointer.exp
@@ -0,0 +1,66 @@
+# Copyright 2009 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/>.
+
+if ![istarget "x86_64-*-*"] then {
+    verbose "Skipping over gdb.arch/x86_64-vla-pointer.exp test made only for x86_64."
+    return
+}
+
+set testfile x86_64-vla-pointer
+set srcasmfile ${testfile}-foo.S
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+set binobjfile ${objdir}/${subdir}/${testfile}-foo.o
+if  { [gdb_compile "${srcdir}/${subdir}/${srcasmfile}" "${binobjfile}" object {}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile} ${binobjfile}" "${binfile}" executable {debug}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] {
+    untested x86_64-vla-pointer
+    return -1
+}
+
+gdb_breakpoint "break_here"
+
+gdb_continue_to_breakpoint "break_here"
+
+gdb_test "whatis array" "type = char \\(\\*\\)\\\[variable\\\]" "first: whatis array"
+gdb_test "ptype array" "type = char \\(\\*\\)\\\[26\\\]" "first: ptype array"
+
+gdb_test "whatis *array" "type = char \\\[26\\\]" "first: whatis *array"
+gdb_test "ptype *array" "type = char \\\[26\\\]" "first: ptype *array"
+
+gdb_test "p (*array)\[1\]" "\\$\[0-9\] = 1 '\\\\001'"
+gdb_test "p (*array)\[2\]" "\\$\[0-9\] = 2 '\\\\002'"
+gdb_test "p (*array)\[3\]" "\\$\[0-9\] = 3 '\\\\003'"
+gdb_test "p (*array)\[4\]" "\\$\[0-9\] = 4 '\\\\004'"
+
+gdb_continue_to_breakpoint "break_here"
+
+gdb_test "whatis array" "type = char \\(\\*\\)\\\[variable\\\]" "second: whatis array"
+gdb_test "ptype array" "type = char \\(\\*\\)\\\[78\\\]" "second: ptype array"
+
+gdb_test "whatis *array" "type = char \\\[78\\\]" "second: whatis *array"
+gdb_test "ptype *array" "type = char \\\[78\\\]" "second: ptype *array"
diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-typedef-foo.S b/gdb/testsuite/gdb.arch/x86_64-vla-typedef-foo.S
new file mode 100644
index 0000000..66f7a39
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/x86_64-vla-typedef-foo.S
@@ -0,0 +1,455 @@
+	.file	"x86_64-vla-typedef.c"
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.text
+.Ltext0:
+.globl foo
+	.type	foo, @function
+foo:
+.LFB2:
+	.file 1 "x86_64-vla-typedef.c"
+	.loc 1 22 0
+	pushq	%rbp
+.LCFI0:
+	movq	%rsp, %rbp
+.LCFI1:
+	subq	$64, %rsp
+.LCFI2:
+	movl	%edi, -36(%rbp)
+	.loc 1 22 0
+	movq	%rsp, %rax
+	movq	%rax, -48(%rbp)
+	.loc 1 23 0
+	movl	-36(%rbp), %edx
+	movslq	%edx,%rax
+	subq	$1, %rax
+	movq	%rax, -24(%rbp)
+	.loc 1 24 0
+	movslq	%edx,%rax
+	addq	$15, %rax
+	addq	$15, %rax
+	shrq	$4, %rax
+	salq	$4, %rax
+	subq	%rax, %rsp
+	movq	%rsp, -56(%rbp)
+	movq	-56(%rbp), %rax
+	addq	$15, %rax
+	shrq	$4, %rax
+	salq	$4, %rax
+	movq	%rax, -56(%rbp)
+	movq	-56(%rbp), %rax
+	movq	%rax, -16(%rbp)
+	.loc 1 27 0
+	movl	$0, -4(%rbp)
+	jmp	.L2
+.L3:
+	.loc 1 28 0
+	movl	-4(%rbp), %esi
+	movl	-4(%rbp), %eax
+	movl	%eax, %ecx
+	movq	-16(%rbp), %rdx
+	movslq	%esi,%rax
+	movb	%cl, (%rdx,%rax)
+	.loc 1 27 0
+	addl	$1, -4(%rbp)
+.L2:
+	movl	-4(%rbp), %eax
+	cmpl	-36(%rbp), %eax
+	jl	.L3
+	.loc 1 30 0
+	.globl	break_here
+break_here:
+	movq	-16(%rbp), %rax
+	movb	$0, (%rax)
+	movq	-48(%rbp), %rsp
+	.loc 1 31 0
+	leave
+	ret
+.LFE2:
+	.size	foo, .-foo
+	.section	.debug_frame,"",@progbits
+.Lframe0:
+	.long	.LECIE0-.LSCIE0
+.LSCIE0:
+	.long	0xffffffff
+	.byte	0x1
+	.string	""
+	.uleb128 0x1
+	.sleb128 -8
+	.byte	0x10
+	.byte	0xc
+	.uleb128 0x7
+	.uleb128 0x8
+	.byte	0x90
+	.uleb128 0x1
+	.align 8
+.LECIE0:
+.LSFDE0:
+	.long	.LEFDE0-.LASFDE0
+.LASFDE0:
+	.long	.Lframe0
+	.quad	.LFB2
+	.quad	.LFE2-.LFB2
+	.byte	0x4
+	.long	.LCFI0-.LFB2
+	.byte	0xe
+	.uleb128 0x10
+	.byte	0x86
+	.uleb128 0x2
+	.byte	0x4
+	.long	.LCFI1-.LCFI0
+	.byte	0xd
+	.uleb128 0x6
+	.align 8
+.LEFDE0:
+	.section	.eh_frame,"a",@progbits
+.Lframe1:
+	.long	.LECIE1-.LSCIE1
+.LSCIE1:
+	.long	0x0
+	.byte	0x1
+	.string	"zR"
+	.uleb128 0x1
+	.sleb128 -8
+	.byte	0x10
+	.uleb128 0x1
+	.byte	0x3
+	.byte	0xc
+	.uleb128 0x7
+	.uleb128 0x8
+	.byte	0x90
+	.uleb128 0x1
+	.align 8
+.LECIE1:
+.LSFDE1:
+	.long	.LEFDE1-.LASFDE1
+.LASFDE1:
+	.long	.LASFDE1-.Lframe1
+	.long	.LFB2
+	.long	.LFE2-.LFB2
+	.uleb128 0x0
+	.byte	0x4
+	.long	.LCFI0-.LFB2
+	.byte	0xe
+	.uleb128 0x10
+	.byte	0x86
+	.uleb128 0x2
+	.byte	0x4
+	.long	.LCFI1-.LCFI0
+	.byte	0xd
+	.uleb128 0x6
+	.align 8
+.LEFDE1:
+	.text
+.Letext0:
+	.section	.debug_loc,"",@progbits
+.Ldebug_loc0:
+.LLST0:
+	.quad	.LFB2-.Ltext0
+	.quad	.LCFI0-.Ltext0
+	.value	0x2
+	.byte	0x77
+	.sleb128 8
+	.quad	.LCFI0-.Ltext0
+	.quad	.LCFI1-.Ltext0
+	.value	0x2
+	.byte	0x77
+	.sleb128 16
+	.quad	.LCFI1-.Ltext0
+	.quad	.LFE2-.Ltext0
+	.value	0x2
+	.byte	0x76
+	.sleb128 16
+	.quad	0x0
+	.quad	0x0
+	.section	.debug_info
+	.long	.Ldebug_end - .Ldebug_start
+.Ldebug_start:
+	.value	0x2
+	.long	.Ldebug_abbrev0
+	.byte	0x8
+	.uleb128 0x1
+	.long	.LASF2
+	.byte	0x1
+	.long	.LASF3
+	.long	.LASF4
+	.quad	.Ltext0
+	.quad	.Letext0
+	.long	.Ldebug_line0
+	.uleb128 0x2
+	.byte	0x1
+	.string	"foo"
+	.byte	0x1
+	.byte	0x16
+	.byte	0x1
+	.quad	.LFB2
+	.quad	.LFE2
+	.long	.LLST0
+	.long	0x83
+	.uleb128 0x3
+	.long	.LASF5
+	.byte	0x1
+	.byte	0x15
+	.long	0x83
+	.byte	0x2
+	.byte	0x91
+	.sleb128 -52
+.Ltag_typedef:
+	.uleb128 0x4
+	.long	.LASF6
+	.byte	0x1
+	.byte	0x17
+	.long	.Ltag_array_type - .debug_info
+	.uleb128 0x5	/* Abbrev Number: 5 (DW_TAG_variable) */
+	.long	.LASF0
+	.byte	0x1
+	.byte	0x18
+#if 1
+	.long	.Ltag_typedef - .debug_info
+#else
+	/* Debugging only: Skip the typedef indirection.  */
+	.long	.Ltag_array_type - .debug_info
+#endif
+	/* DW_AT_location: DW_FORM_block1: start */
+	.byte	0x3
+	.byte	0x91
+	.sleb128 -32
+#if 0
+	.byte	0x6	/* DW_OP_deref */
+#else
+	.byte	0x96	/* DW_OP_nop */
+#endif
+	/* DW_AT_location: DW_FORM_block1: end */
+	.uleb128 0x6
+	.string	"i"
+	.byte	0x1
+	.byte	0x19
+	.long	0x83
+	.byte	0x2
+	.byte	0x91
+	.sleb128 -20
+	.byte	0x0
+	.uleb128 0x7
+	.byte	0x4
+	.byte	0x5
+	.string	"int"
+.Ltag_array_type:
+	.uleb128 0x8	/* Abbrev Number: 8 (DW_TAG_array_type) */
+	.long	0xa0 + (2f - 1f)	/* DW_AT_type: DW_FORM_ref4 */
+	.long	0x9d + (2f - 1f)	/* DW_AT_sibling: DW_FORM_ref4 */
+1:	/* DW_AT_data_location: DW_FORM_block1: start */
+	.byte	2f - 3f	/* length */
+3:
+	.byte	0x97	/* DW_OP_push_object_address */
+	.byte	0x6	/* DW_OP_deref */
+2:	/* DW_AT_data_location: DW_FORM_block1: end */
+	.uleb128 0x9
+	.long	0x9d + (2b - 1b)	/* DW_AT_type: DW_FORM_ref4 */
+	.byte	0x3
+	.byte	0x91
+	.sleb128 -40
+	.byte	0x6
+	.byte	0x0
+	.uleb128 0xa
+	.byte	0x8
+	.byte	0x7
+	.uleb128 0xb
+	.byte	0x1
+	.byte	0x6
+	.long	.LASF1
+	.byte	0x0
+.Ldebug_end:
+	.section	.debug_abbrev
+	.uleb128 0x1
+	.uleb128 0x11
+	.byte	0x1
+	.uleb128 0x25
+	.uleb128 0xe
+	.uleb128 0x13
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x1b
+	.uleb128 0xe
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x1
+	.uleb128 0x10
+	.uleb128 0x6
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0x2
+	.uleb128 0x2e
+	.byte	0x1
+	.uleb128 0x3f
+	.uleb128 0xc
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x27
+	.uleb128 0xc
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x1
+	.uleb128 0x40
+	.uleb128 0x6
+	.uleb128 0x1
+	.uleb128 0x13
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0x3
+	.uleb128 0x5
+	.byte	0x0
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x2
+	.uleb128 0xa
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0x4
+	.uleb128 0x16
+	.byte	0x0
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0x5
+	.uleb128 0x34
+	.byte	0x0
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x2
+	.uleb128 0xa
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0x6
+	.uleb128 0x34
+	.byte	0x0
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x2
+	.uleb128 0xa
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0x7
+	.uleb128 0x24
+	.byte	0x0
+	.uleb128 0xb
+	.uleb128 0xb
+	.uleb128 0x3e
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0x8
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0x8	/* Abbrev Number: 8 (DW_TAG_array_type) */
+	.uleb128 0x1
+	.byte	0x1
+	.uleb128 0x49	/* DW_AT_type */
+	.uleb128 0x13	/* DW_FORM_ref4 */
+	.uleb128 0x1	/* DW_AT_sibling */
+	.uleb128 0x13	/* DW_FORM_ref4 */
+	.uleb128 0x50	/* DW_AT_data_location */
+	.uleb128 0xa	/* DW_FORM_block1 */
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0x9
+	.uleb128 0x21
+	.byte	0x0
+	.uleb128 0x49	/* DW_AT_type */
+	.uleb128 0x13	/* DW_FORM_ref4 */
+	.uleb128 0x2f
+	.uleb128 0xa
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0xa
+	.uleb128 0x24
+	.byte	0x0
+	.uleb128 0xb
+	.uleb128 0xb
+	.uleb128 0x3e
+	.uleb128 0xb
+	.byte	0x0
+	.byte	0x0
+	.uleb128 0xb
+	.uleb128 0x24
+	.byte	0x0
+	.uleb128 0xb
+	.uleb128 0xb
+	.uleb128 0x3e
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0xe
+	.byte	0x0
+	.byte	0x0
+	.byte	0x0
+	.section	.debug_pubnames,"",@progbits
+	.long	0x16
+	.value	0x2
+	.long	.Ldebug_info0
+	.long	0xa8
+	.long	0x2d
+	.string	"foo"
+	.long	0x0
+	.section	.debug_aranges,"",@progbits
+	.long	0x2c
+	.value	0x2
+	.long	.Ldebug_info0
+	.byte	0x8
+	.byte	0x0
+	.value	0x0
+	.value	0x0
+	.quad	.Ltext0
+	.quad	.Letext0-.Ltext0
+	.quad	0x0
+	.quad	0x0
+	.section	.debug_str,"MS",@progbits,1
+.LASF0:
+	.string	"array"
+.LASF5:
+	.string	"size"
+.LASF3:
+	.string	"x86_64-vla-typedef.c"
+.LASF6:
+	.string	"array_t"
+.LASF1:
+	.string	"char"
+.LASF4:
+	.string	"gdb.arch"
+.LASF2:
+	.string	"GNU C 4.3.2 20081105 (Red Hat 4.3.2-7)"
+	.ident	"GCC: (GNU) 4.3.2 20081105 (Red Hat 4.3.2-7)"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-typedef.c b/gdb/testsuite/gdb.arch/x86_64-vla-typedef.c
new file mode 100644
index 0000000..b809c4e
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/x86_64-vla-typedef.c
@@ -0,0 +1,43 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2008 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/>.  */
+
+#if 0
+
+void
+foo (int size)
+{
+  typedef char array_t[size];
+  array_t array;
+  int i;
+
+  for (i = 0; i < size; i++)
+    array[i] = i;
+
+  array[0] = 0;	/* break-here */
+}
+
+#else
+
+int
+main (void)
+{
+  foo (26);
+  foo (78);
+  return 0;
+}
+
+#endif
diff --git a/gdb/testsuite/gdb.arch/x86_64-vla-typedef.exp b/gdb/testsuite/gdb.arch/x86_64-vla-typedef.exp
new file mode 100644
index 0000000..b05411e
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/x86_64-vla-typedef.exp
@@ -0,0 +1,64 @@
+# Copyright 2009 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 DW_AT_data_location accessed through DW_TAG_typedef intermediate.
+
+if ![istarget "x86_64-*-*"] then {
+    verbose "Skipping over gdb.arch/x86_64-vla-typedef.exp test made only for x86_64."
+    return
+}
+
+set testfile x86_64-vla-typedef
+set srcasmfile ${testfile}-foo.S
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+set binobjfile ${objdir}/${subdir}/${testfile}-foo.o
+if  { [gdb_compile "${srcdir}/${subdir}/${srcasmfile}" "${binobjfile}" object {}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile} ${binobjfile}" "${binfile}" executable {debug}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] {
+    untested x86_64-vla-typedef
+    return -1
+}
+
+gdb_breakpoint "break_here"
+
+gdb_continue_to_breakpoint "break_here"
+
+gdb_test "whatis array" "type = array_t" "first: whatis array"
+
+gdb_test "ptype array" "type = char \\\[26\\\]" "first: ptype array"
+
+gdb_test "p array\[1\]" "\\$\[0-9\] = 1 '\\\\001'"
+gdb_test "p array\[2\]" "\\$\[0-9\] = 2 '\\\\002'"
+gdb_test "p array\[3\]" "\\$\[0-9\] = 3 '\\\\003'"
+gdb_test "p array\[4\]" "\\$\[0-9\] = 4 '\\\\004'"
+
+gdb_continue_to_breakpoint "break_here"
+
+gdb_test "whatis array" "type = array_t" "second: whatis array"
+
+gdb_test "ptype array" "type = char \\\[78\\\]" "second: ptype array"
diff --git a/gdb/testsuite/gdb.base/arrayidx.c b/gdb/testsuite/gdb.base/arrayidx.c
index ecc3289..f79ad40 100644
--- a/gdb/testsuite/gdb.base/arrayidx.c
+++ b/gdb/testsuite/gdb.base/arrayidx.c
@@ -17,6 +17,13 @@
 
 int array[] = {1, 2, 3, 4};
 
+#ifdef __GNUC__
+struct
+  {
+    int a[0];
+  } unbound;
+#endif
+
 int
 main (void)
 {
diff --git a/gdb/testsuite/gdb.base/arrayidx.exp b/gdb/testsuite/gdb.base/arrayidx.exp
index 0ef6c4b..330ed87 100644
--- a/gdb/testsuite/gdb.base/arrayidx.exp
+++ b/gdb/testsuite/gdb.base/arrayidx.exp
@@ -59,4 +59,12 @@ gdb_test "print array" \
          "\\{\\\[0\\\] = 1, \\\[1\\\] = 2, \\\[2\\\] = 3, \\\[3\\\] = 4\\}" \
          "Print array with array-indexes on"
 
-
+set test "p unbound.a == &unbound.a\[0\]"
+gdb_test_multiple $test $test {
+    -re " = 1\r\n$gdb_prompt $" {
+	pass $test
+    }
+    -re "No symbol \"unbound\" in current context.\r\n$gdb_prompt $" {
+	unsupported "$test (no GCC)"
+    }
+}
diff --git a/gdb/testsuite/gdb.base/gnu-ifunc-lib.c b/gdb/testsuite/gdb.base/gnu-ifunc-lib.c
new file mode 100644
index 0000000..204ce99
--- /dev/null
+++ b/gdb/testsuite/gdb.base/gnu-ifunc-lib.c
@@ -0,0 +1,54 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2009 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 <assert.h>
+
+typedef int (*final_t) (int arg);
+
+static int
+init_stub (int arg)
+{
+  return 0;
+}
+
+static int
+final (int arg)
+{
+  return arg + 1;
+}
+
+static volatile int gnu_ifunc_initialized;
+
+void
+gnu_ifunc_pre (void)
+{
+  assert (!gnu_ifunc_initialized);
+
+  gnu_ifunc_initialized = 1;
+}
+
+final_t gnu_ifuncX (void) asm ("gnu_ifunc");
+asm (".type gnu_ifunc, @gnu_indirect_function");
+
+final_t
+gnu_ifuncX (void)
+{
+  if (!gnu_ifunc_initialized)
+    return init_stub;
+  else
+    return final;
+}
diff --git a/gdb/testsuite/gdb.base/gnu-ifunc.c b/gdb/testsuite/gdb.base/gnu-ifunc.c
new file mode 100644
index 0000000..e4a823d
--- /dev/null
+++ b/gdb/testsuite/gdb.base/gnu-ifunc.c
@@ -0,0 +1,36 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2009 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 <assert.h>
+
+extern int gnu_ifunc (int arg);
+extern void gnu_ifunc_pre (void);
+
+int
+main (void)
+{
+  int i;
+
+  gnu_ifunc_pre ();
+  
+  i = gnu_ifunc (1);	/* break-at-call */
+  assert (i == 2);
+
+  gnu_ifunc (2);	/* break-at-nextcall */
+
+  return 0;	/* break-at-exit */
+}
diff --git a/gdb/testsuite/gdb.base/gnu-ifunc.exp b/gdb/testsuite/gdb.base/gnu-ifunc.exp
new file mode 100644
index 0000000..4b3ac41
--- /dev/null
+++ b/gdb/testsuite/gdb.base/gnu-ifunc.exp
@@ -0,0 +1,115 @@
+# Copyright (C) 2009 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/>.
+
+if {[skip_shlib_tests]} {
+    return 0
+}
+
+set testfile "gnu-ifunc"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+set libfile "${testfile}-lib"
+set libsrc ${libfile}.c
+set lib_so ${objdir}/${subdir}/${libfile}.so
+
+set lib_nodebug_so_base ${libfile}-nodebug.so
+set lib_nodebug_so ${objdir}/${subdir}/${lib_nodebug_so_base}
+
+# {debug} provides DWARF symbol gnu_ifuncX confusing the ELF symbol
+# gnu_ifunc during address->symbol resolution for printing the symbol.
+# Still we need it here for "step"ping into the function.
+set lib_opts [list debug]
+set lib_nodebug_opts [list]
+set exec_opts [list debug shlib=$lib_so]
+
+if [get_compiler_info ${binfile}] {
+    return -1
+}
+
+if { [gdb_compile_shlib ${srcdir}/${subdir}/$libsrc $lib_so $lib_opts] != ""
+     || [gdb_compile ${srcdir}/${subdir}/$srcfile $binfile executable $exec_opts] != ""} {
+    untested "Could not compile either $libsrc or $srcfile."
+    return -1
+}
+
+# Start with a fresh gdb.
+
+clean_restart $testfile
+gdb_load_shlibs ${lib_so}
+
+if ![runto_main] then {
+    fail "Can't run to main"
+    return 1;
+}
+
+# The "if" condition is artifical to test regression of a format patch.
+gdb_breakpoint "[gdb_get_line_number "break-at-nextcall"] if i && gnu_ifunc (i) != 42"
+
+gdb_breakpoint [gdb_get_line_number "break-at-call"]
+gdb_continue_to_breakpoint "break-at-call" ".*break-at-call.*"
+
+# Test GDB will automatically indirect the call.
+
+gdb_test "p gnu_ifunc (3)" " = 4"
+
+# Test GDB will skip the gnu_ifunc resolver on first call.
+
+gdb_test "step" "\r\nfinal .*"
+
+# Test GDB will not break before the final chosen implementation.
+
+# Also test a format patch regression:
+# Continuing.
+# Error in testing breakpoint condition:
+# Attempt to take address of value not located in memory.
+# 
+# Breakpoint 2, main () at ./gdb.base/gnu-ifunc.c:33
+
+gdb_test "continue" "Continuing.\r\n\r\nBreakpoint .* (at|in) .*break-at-nextcall.*" \
+	 "continue to break-at-nextcall"
+
+gdb_breakpoint "gnu_ifunc"
+
+gdb_continue_to_breakpoint "nextcall gnu_ifunc"
+
+gdb_test "frame" "#0 +(0x\[0-9a-f\]+ in +)?final \\(.*" "nextcall gnu_ifunc skipped"
+
+
+# Compare the two different addresses:
+
+gdb_test "p gnu_ifunc" " = {<text variable, no debug info>} 0x\[0-9a-f\]+ <final>" "p gnu_ifunc executing"
+gdb_test "info sym gnu_ifunc" "final in section .*" "info sym gnu_ifunc executing"
+
+set test "info addr gnu_ifunc"
+gdb_test_multiple $test $test {
+    -re "Symbol \"gnu_ifunc\" is at (0x\[0-9a-f\]+) in .*$gdb_prompt $" {
+	pass $test
+    }
+}
+gdb_test "info sym $expect_out(1,string)" "gnu_ifunc in section .*" "info sym <gnu_ifunc-address>"
+
+# <*gnu_ifunc> would be an incorrect resolution from DW_AT_MIPS_linkage_name.
+# We do not use {debug} build option for this purpose.
+
+if { [gdb_compile_shlib ${srcdir}/${subdir}/$libsrc $lib_nodebug_so $lib_nodebug_opts] != ""} {
+    untested "Could not compile either $libsrc."
+    return -1
+}
+
+clean_restart $lib_nodebug_so_base
+
+gdb_test "p gnu_ifunc" " = {<text gnu-ifunc variable, no debug info>} 0x\[0-9a-f\]+ <gnu_ifunc>" "p gnu_ifunc not executing without debug"
+gdb_test "info sym gnu_ifunc" "gnu_ifunc in section .*" "info sym gnu_ifunc not executing without debug"
diff --git a/gdb/testsuite/gdb.base/internal-var-field-address.c b/gdb/testsuite/gdb.base/internal-var-field-address.c
new file mode 100644
index 0000000..eeb7b85
--- /dev/null
+++ b/gdb/testsuite/gdb.base/internal-var-field-address.c
@@ -0,0 +1,20 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2009 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/>.  */
+
+struct {
+  int field;
+} staticstruct = { 1 };
diff --git a/gdb/testsuite/gdb.base/internal-var-field-address.exp b/gdb/testsuite/gdb.base/internal-var-field-address.exp
new file mode 100644
index 0000000..6d82e73
--- /dev/null
+++ b/gdb/testsuite/gdb.base/internal-var-field-address.exp
@@ -0,0 +1,26 @@
+# Copyright 2009 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/>.
+
+set test internal-var-field-address
+set binfile ${test}.x
+if  { [gdb_compile "${srcdir}/${subdir}/${test}.c" "${objdir}/${subdir}/${binfile}" object {debug}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+clean_restart $binfile
+
+gdb_test {set $varstruct = staticstruct}
+gdb_test {p $varstruct.field} " = 1"
diff --git a/gdb/testsuite/gdb.base/vla-overflow.c b/gdb/testsuite/gdb.base/vla-overflow.c
new file mode 100644
index 0000000..c5d5ee0
--- /dev/null
+++ b/gdb/testsuite/gdb.base/vla-overflow.c
@@ -0,0 +1,30 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2008 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 <stdlib.h>
+
+int
+main (int argc, char **argv)
+{
+  int array[argc];
+
+  array[0] = array[0];
+
+  abort ();
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/vla-overflow.exp b/gdb/testsuite/gdb.base/vla-overflow.exp
new file mode 100644
index 0000000..7203a48
--- /dev/null
+++ b/gdb/testsuite/gdb.base/vla-overflow.exp
@@ -0,0 +1,108 @@
+# Copyright 2008 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/>.
+
+# We could crash in:
+# #0  block_linkage_function (bl=0x0) at ../../gdb/block.c:69
+# #1  in dwarf_block_get_frame_base (...) at ../../gdb/dwarf2block.c:97
+#   97	  framefunc = block_linkage_function (get_frame_block (frame, NULL));
+# #2  in execute_stack_op (...) at ../../gdb/dwarf2expr.c:496
+# #3  in dwarf_block_exec_core () at ../../gdb/dwarf2block.c:156
+# #4  dwarf_block_exec (...) at ../../gdb/dwarf2block.c:206
+# #5  in range_type_count_bound_internal (...) at ../../gdb/gdbtypes.c:1430
+# #6  in create_array_type (...) at ../../gdb/gdbtypes.c:840
+# ...
+# #21 in psymtab_to_symtab (...) at ../../gdb/symfile.c:292
+# ...
+# #29 in backtrace_command_1 () at ../../gdb/stack.c:1273
+
+set testfile vla-overflow
+set shfile ${objdir}/${subdir}/${testfile}-gdb.sh
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+set f [open "|getconf PAGESIZE" "r"]
+gets $f pagesize
+close $f
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+set pid_of_gdb [exp_pid -i [board_info host fileid]]
+
+if { [runto_main] < 0 } {
+    untested vla-overflow
+    return -1
+}
+
+# Get the GDB memory size when we stay at main.
+
+proc memory_v_pages_get {} {
+    global pid_of_gdb pagesize
+    set fd [open "/proc/$pid_of_gdb/statm"]
+    gets $fd line
+    close $fd
+    # number of pages of virtual memory
+    scan $line "%d" drs
+    return $drs
+}
+
+set pages_found [memory_v_pages_get]
+
+set mb_reserve 10
+verbose -log "pages_found = $pages_found, mb_reserve = $mb_reserve"
+set kb_found [expr $pages_found * $pagesize / 1024]
+set kb_permit [expr $kb_found + 1 * 1024 + $mb_reserve * 1024]
+verbose -log "kb_found = $kb_found, kb_permit = $kb_permit"
+
+# Create the ulimit wrapper.
+set f [open $shfile "w"]
+puts $f "#! /bin/sh"
+puts $f "ulimit -v $kb_permit"
+puts $f "exec $GDB \"\$@\""
+close $f
+remote_exec host "chmod +x $shfile"
+
+gdb_exit
+set GDBold $GDB
+set GDB "$shfile"
+gdb_start
+set GDB $GDBold
+
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+set pid_of_gdb [exp_pid -i [board_info host fileid]]
+
+# Check the size again after the second run.
+# We must not stop in main as it would cache `array' and never crash later.
+
+gdb_run_cmd
+
+verbose -log "kb_found before abort() = [expr [memory_v_pages_get] * $pagesize / 1024]"
+
+gdb_test "" "Program received signal SIGABRT, Aborted..*" "Enter abort()"
+
+verbose -log "kb_found in abort() = [expr [memory_v_pages_get] * $pagesize / 1024]"
+
+# `abort' can get expressed as `*__GI_abort'.
+gdb_test "bt" "in \[^ \]*abort \\(.* in main \\(.*" "Backtrace after abort()"
+
+verbose -log "kb_found in bt after abort() = [expr [memory_v_pages_get] * $pagesize / 1024]"
diff --git a/gdb/testsuite/gdb.base/vla.c b/gdb/testsuite/gdb.base/vla.c
new file mode 100644
index 0000000..e1f3ed1
--- /dev/null
+++ b/gdb/testsuite/gdb.base/vla.c
@@ -0,0 +1,55 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2008 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 <string.h>
+
+void
+marker (void)
+{
+}
+
+void
+bar (char *a, char *b, char *c, int size)
+{
+  memset (a, '1', size);
+  memset (b, '2', size);
+  memset (c, '3', 48);
+}
+
+void
+foo (int size)
+{
+  char temp1[size];
+  char temp3[48];
+
+  temp1[size - 1] = '\0';
+  {
+    char temp2[size];
+
+    bar (temp1, temp2, temp3, size);
+
+    marker ();	/* break-here */
+  }
+}
+
+int
+main (void)
+{
+  foo (26);
+  foo (78);
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/vla.exp b/gdb/testsuite/gdb.base/vla.exp
new file mode 100644
index 0000000..5da7378
--- /dev/null
+++ b/gdb/testsuite/gdb.base/vla.exp
@@ -0,0 +1,62 @@
+# Copyright 2008 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/>.
+
+set testfile vla
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] {
+    untested vla
+    return -1
+}
+
+gdb_breakpoint [gdb_get_line_number "break-here"]
+
+gdb_continue_to_breakpoint "break-here"
+
+gdb_test "whatis temp1" "type = char \\\[variable\\\]" "first: whatis temp1"
+gdb_test "whatis temp2" "type = char \\\[variable\\\]" "first: whatis temp2"
+gdb_test "whatis temp3" "type = char \\\[48\\\]" "first: whatis temp3"
+
+gdb_test "ptype temp1" "type = char \\\[26\\\]" "first: ptype temp1"
+gdb_test "ptype temp2" "type = char \\\[26\\\]" "first: ptype temp2"
+gdb_test "ptype temp3" "type = char \\\[48\\\]" "first: ptype temp3"
+
+gdb_test "p temp1" " = '1' <repeats 26 times>" "first: print temp1"
+gdb_test "p temp2" " = '2' <repeats 26 times>" "first: print temp2"
+gdb_test "p temp3" " = '3' <repeats 48 times>" "first: print temp3"
+
+gdb_continue_to_breakpoint "break-here"
+
+gdb_test "whatis temp1" "type = char \\\[variable\\\]" "second: whatis temp1"
+gdb_test "whatis temp2" "type = char \\\[variable\\\]" "second: whatis temp2"
+gdb_test "whatis temp3" "type = char \\\[48\\\]" "second: whatis temp3"
+
+gdb_test "ptype temp1" "type = char \\\[78\\\]" "second: ptype temp1"
+gdb_test "ptype temp2" "type = char \\\[78\\\]" "second: ptype temp2"
+gdb_test "ptype temp3" "type = char \\\[48\\\]" "second: ptype temp3"
+
+gdb_test "p temp1" " = '1' <repeats 78 times>" "second: print temp1"
+gdb_test "p temp2" " = '2' <repeats 78 times>" "second: print temp2"
+gdb_test "p temp3" " = '3' <repeats 48 times>" "second: print temp3"
diff --git a/gdb/testsuite/gdb.cp/Makefile.in b/gdb/testsuite/gdb.cp/Makefile.in
index d78258e..1774244 100644
--- a/gdb/testsuite/gdb.cp/Makefile.in
+++ b/gdb/testsuite/gdb.cp/Makefile.in
@@ -4,7 +4,7 @@ srcdir = @srcdir@
 EXECUTABLES = ambiguous annota2 anon-union cplusfuncs cttiadd \
 	derivation inherit local member-ptr method misc \
         overload ovldbreak ref-typ ref-typ2 templates userdef virtfunc namespace \
-	ref-types ref-params method2 pr9594 gdb2495 virtfunc2 pr9067 \
+	ref-types ref-params method2 pr9594 gdb2495 gdb9593 virtfunc2 pr9067 \
 	pr1072
 
 all info install-info dvi install uninstall installcheck check:
diff --git a/gdb/testsuite/gdb.cp/cp-relocate.exp b/gdb/testsuite/gdb.cp/cp-relocate.exp
index f81a212..30d362a 100644
--- a/gdb/testsuite/gdb.cp/cp-relocate.exp
+++ b/gdb/testsuite/gdb.cp/cp-relocate.exp
@@ -30,7 +30,7 @@ proc get_func_address { func } {
     global gdb_prompt hex
 
     set rfunc [string_to_regexp $func]
-    gdb_test_multiple "print '${func}'" "get address of ${func}" {
+    gdb_test_multiple "print ${func}" "get address of ${func}" {
 	-re "\\\$\[0-9\]+ = \\{.*\\} (0|($hex) <${rfunc}>)\[\r\n\]+${gdb_prompt} $" {
 	    # $1 = {int ()} 0x24 <function_bar>
 	    # But if the function is at zero, the name may be omitted.
@@ -130,7 +130,7 @@ gdb_test "add-symbol-file ${binfile} 0 -s ${func1_sec} 0x10000 -s ${func2_sec} 0
 	"y"
 
 # Make sure the function addresses were updated.
-gdb_test "break *'$func1_name'" \
+gdb_test "break *$func1_name" \
     "Breakpoint $decimal at 0x1....: file .*"
-gdb_test "break *'$func2_name'" \
+gdb_test "break *$func2_name" \
     "Breakpoint $decimal at 0x2....: file .*"
diff --git a/gdb/testsuite/gdb.cp/cpexprs.cc b/gdb/testsuite/gdb.cp/cpexprs.cc
new file mode 100644
index 0000000..2bca4cd
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/cpexprs.cc
@@ -0,0 +1,431 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
+
+   Contributed by Red Hat, originally written by Keith Seitz.
+
+   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/>.
+
+   Please email any bugs, comments, and/or additions to this file to:
+   bug-gdb@gnu.org  */
+
+#include <stdlib.h>
+#include <iostream>
+
+// Forward decls
+class base;
+class derived;
+
+// A simple template with specializations
+template <typename T>
+class tclass
+{
+public:
+  void do_something () { } // tclass<T>::do_something
+};
+
+template <>
+void tclass<char>::do_something () { } // tclass<char>::do_something
+
+template <>
+void tclass<int>::do_something () { } // tclass<int>::do_something
+
+template<>
+void tclass<long>::do_something () { } // tclass<long>::do_something
+
+template<>
+void tclass<short>::do_something () { } // tclass<short>::do_something
+
+// A simple template with multiple template parameters
+template <class A, class B, class C, class D, class E>
+void flubber (void) // flubber
+{
+  A a;
+  B b;
+  C c;
+  D d;
+  E e;
+
+  ++a;
+  ++b;
+  ++c;
+  ++d;
+  ++e;
+}
+
+// Some contrived policies
+template <class T>
+struct operation_1
+{
+  static void function (void) { } // operation_1<T>::function
+};
+
+template <class T>
+struct operation_2
+{
+  static void function (void) { } // operation_2<T>::function
+};
+
+template <class T>
+struct operation_3
+{
+  static void function (void) { } // operation_3<T>::function
+};
+
+template <class T>
+struct operation_4
+{
+  static void function (void) { } // operation_4<T>::function
+};
+
+// A policy-based class w/ and w/o default policy
+template <class T, class Policy>
+class policy : public Policy
+{
+public:
+  policy (T obj) : obj_ (obj) { } // policy<T, Policy>::policy
+
+private:
+  T obj_;
+};
+
+template <class T, class Policy = operation_1<T> >
+class policyd : public Policy
+{
+public:
+  policyd (T obj) : obj_ (obj) { } // policyd<T, Policy>::policyd
+  ~policyd (void) { } // policyd<T, Policy>::~policyd
+
+private:
+  T obj_;
+};
+
+typedef policy<int, operation_1<void*> > policy1;
+typedef policy<int, operation_2<void*> > policy2;
+typedef policy<int, operation_3<void*> > policy3;
+typedef policy<int, operation_4<void*> > policy4;
+
+typedef policyd<int> policyd1;
+typedef policyd<long> policyd2;
+typedef policyd<char> policyd3;
+typedef policyd<base> policyd4;
+typedef policyd<tclass<int> > policyd5;
+
+class fluff { };
+static fluff *g_fluff = new fluff ();
+
+class base
+{
+protected:
+  int foo_;
+
+public:
+  base (void) : foo_ (42) { } // base::base(void)
+  base (int foo) : foo_ (foo) { } // base::base(int)
+  ~base (void) { } // base::~base
+
+  // Some overloaded methods
+  int overload (void) const { return 0; } // base::overload(void) const
+  int overload (int i) const { return 1; } // base::overload(int) const
+  int overload (short s) const { return 2; } // base::overload(short) const
+  int overload (long l) const { return 3; } // base::overload(long) const
+  int overload (char* a) const { return 4; } // base::overload(char*) const
+  int overload (base& b) const { return 5; } // base::overload(base&) const
+
+  // Operators
+  int operator+ (base const& o) const // base::operator+
+  { return foo_ + o.foo_; }
+
+  base operator++ (void) // base::operator++
+  { ++foo_; return *this; }
+
+  base operator+=(base const& o) // base::operator+=
+  { foo_ += o.foo_; return *this; }
+
+  int operator- (base const& o) const // base::operator-
+  { return foo_ - o.foo_; }
+
+  base operator-- (void) // base::operator--
+  { --foo_; return *this; }
+
+  base operator-= (base const& o) // base::operator-=
+  { foo_ -= o.foo_; return *this; }
+
+  int operator* (base const& o) const // base::operator*
+  { return foo_ * o.foo_; }
+
+  base operator*= (base const& o) // base::operator*=
+  { foo_ *= o.foo_; return *this; }
+
+  int operator/ (base const& o) const // base::operator/
+  { return foo_ / o.foo_; }
+
+  base operator/= (base const& o) // base::operator/=
+  { foo_ /= o.foo_; return *this; }
+
+  int operator% (base const& o) const // base::operator%
+  { return foo_ % o.foo_; }
+  
+  base operator%= (base const& o) // base::operator%=
+  { foo_ %= o.foo_; return *this; }
+
+  bool operator< (base const& o) const // base::operator<
+  { return foo_ < o.foo_; }
+
+  bool operator<= (base const& o) const // base::operator<=
+  { return foo_ <= o.foo_; }
+
+  bool operator> (base const& o) const // base::operator>
+  { return foo_ > o.foo_; }
+
+  bool operator>= (base const& o) const // base::operator>=
+  { return foo_ >= o.foo_; }
+
+  bool operator!= (base const& o) const // base::operator!=
+  { return foo_ != o.foo_; }
+
+  bool operator== (base const& o) const // base::operator==
+  { return foo_ == o.foo_; }
+
+  bool operator! (void) const // base::operator!
+  { return !foo_; }
+
+  bool operator&& (base const& o) const // base::operator&&
+  { return foo_ && o.foo_; }
+
+  bool operator|| (base const& o) const // base::operator||
+  { return foo_ || o.foo_; }
+
+  int operator<< (int value) const // base::operator<<
+  { return foo_  << value; }
+
+  base operator<<= (int value) // base::operator<<=
+  { foo_ <<= value; return *this; }
+
+  int operator>> (int value) const // base::operator>>
+  { return foo_  >> value; }
+
+  base operator>>= (int value) // base::operator>>=
+  { foo_ >>= value; return *this; }
+
+  int operator~ (void) const // base::operator~
+  { return ~foo_; }
+
+  int operator& (base const& o) const // base::operator&
+  { return foo_ & o.foo_; }
+
+  base operator&= (base const& o) // base::operator&=
+  { foo_ &= o.foo_; return *this; }
+
+  int operator| (base const& o) const // base::operator|
+  { return foo_ | o.foo_; }
+
+  base operator|= (base const& o) // base::operator|=
+  { foo_ |= o.foo_; return *this; }
+  
+  int operator^ (base const& o) const // base::operator^
+  { return foo_ ^ o.foo_; }
+
+  base operator^= (base const& o) // base::operator^=
+  { foo_ ^= o.foo_; return *this; }
+
+  base operator= (base const& o) // base::operator=
+  { foo_ = o.foo_; return *this; }
+
+  void operator() (void) const // base::operator()
+  { return; }
+
+  int operator[] (int idx) const // base::operator[]
+  { return idx; }
+
+  void* operator new (size_t size) throw () // base::operator new
+  { return malloc (size); }
+
+  void operator delete (void* ptr) // base::operator delete
+  { free (ptr); }
+
+  void* operator new[] (size_t size) throw () // base::operator new[]
+  { return malloc (size); }
+
+  void operator delete[] (void* ptr) // base::operator delete[]
+  { free (ptr); }
+
+  base const* operator-> (void) const // base::opeartor->
+  { return this; }
+
+  int operator->* (base const& b) const // base::operator->*
+  {  return foo_ * b.foo_; }
+
+  operator char* () const { return const_cast<char*> ("hello"); } // base::operator char*
+  operator int () const { return 21; } // base::operator int
+  operator fluff* () const { return new fluff (); } // base::operator fluff*
+  operator fluff** () const { return &g_fluff; } // base::operator fluff**
+};
+
+class base1 : public virtual base
+{
+public:
+  base1 (void) : foo_ (21) { } // base1::base1(void)
+  base1 (int a) : foo_(a) { } // base1::base1(int)
+  void a_function (void) const { } // base1::a_function
+
+protected:
+  int foo_;
+};
+
+class base2 : public virtual base
+{
+public:
+  base2 () : foo_ (3) { } // base2::base2
+
+protected:
+  void a_function (void) const { } // base2::a_function
+  int foo_;
+};
+
+class derived : public base1, public base2
+{
+  public:
+  derived(void) : foo_ (4) { } // derived::derived
+  void a_function (void) const // derived::a_function
+  { 
+    this->base1::a_function ();
+    this->base2::a_function ();
+  }
+
+  protected:
+  int foo_;
+};
+
+int
+main (int argc, char* argv[]) // main
+{ // main
+  derived d;
+  void (derived::*pfunc) (void) const = &derived::a_function;
+  (d.*pfunc) ();
+
+  base a (1), b (3), c (8);
+  (void) a.overload ();
+  (void) a.overload (static_cast<int> (0));
+  (void) a.overload (static_cast<short> (0));
+  (void) a.overload (static_cast<long> (0));
+  (void) a.overload (static_cast<char*> (0));
+  (void) a.overload (a);
+
+  int r;
+  r = b + c;
+  ++a;
+  a += b;
+  r = b - c;
+  --a;
+  a -= b;
+  r = b * c;
+  a *= b;
+  r = b / c;
+  a /= b;
+  r = b % c;
+  a %= b;
+  bool x = (b < c);
+  x = (b <= c);
+  x = (b > c);
+  x = (b >= c);
+  x = (b != c);
+  x = (b == c);
+  x = (!b);
+  x = (b && c);
+  x = (b || c);
+  r = b << 2;
+  a <<= 1;
+  r = b >> 2;
+  a >>= 1;
+  r = ~b;
+  r = b & c;
+  a &= c;
+  r = b | c;
+  a |= c;
+  r = b ^ c;
+  a ^= c;
+  a = c;
+  a ();
+  int i = a[3];
+  derived* f = new derived ();
+  derived* g = new derived[3];
+  delete f;
+  delete[] g;
+  a->overload ();
+  r = a->*b;
+
+  tclass<char> char_tclass;
+  tclass<int> int_tclass;
+  tclass<short> short_tclass;
+  tclass<long> long_tclass;
+  tclass<base> base_tclass;
+  char_tclass.do_something ();
+  int_tclass.do_something ();
+  short_tclass.do_something ();
+  long_tclass.do_something ();
+  base_tclass.do_something ();
+
+  flubber<int, int, int, int, int> ();
+  flubber<int, int, int, int, short> ();
+  flubber<int, int, int, int, long> ();
+  flubber<int, int, int, int, char> ();
+  flubber<int, int, int, short, int> ();
+  flubber<int, int, int, short, short> ();
+  flubber<int, int, int, short, long> ();
+  flubber<int, int, int, short, char> ();
+  flubber<int, int, int, long, int> ();
+  flubber<int, int, int, long, short> ();
+  flubber<int, int, int, long, long> ();
+  flubber<int, int, int, long, char> ();
+  flubber<int, int, int, char, int> ();
+  flubber<int, int, int, char, short> ();
+  flubber<int, int, int, char, long> ();
+  flubber<int, int, int, char, char> ();
+  flubber<int, int, short, int, int> ();
+  flubber<int, int, short, int, short> ();
+  flubber<int, int, short, int, long> ();
+  flubber<int, int, short, int, char> ();
+  flubber<int, int, short, short, int> ();
+  flubber<short, int, short, int, short> ();
+  flubber<long, short, long, short, long> ();
+
+  policy1 p1 (1);
+  p1.function ();
+  policy2 p2 (2);
+  p2.function ();
+  policy3 p3 (3);
+  p3.function ();
+  policy4 p4 (4);
+  p4.function ();
+
+  policyd1 pd1 (5);
+  pd1.function ();
+  policyd2 pd2 (6);
+  pd2.function ();
+  policyd3 pd3 (7);
+  pd3.function ();
+  policyd4 pd4 (d);
+  pd4.function ();
+  policyd5 pd5 (int_tclass);
+  pd5.function ();
+
+  base1 b1 (3);
+
+  r = a;
+  char* str = a;
+  fluff* flp = a;
+  fluff** flpp = a;
+}
+
diff --git a/gdb/testsuite/gdb.cp/cpexprs.exp b/gdb/testsuite/gdb.cp/cpexprs.exp
new file mode 100644
index 0000000..6074763
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/cpexprs.exp
@@ -0,0 +1,724 @@
+# cpexprs.exp - C++ expressions tests
+#
+# Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
+#
+# Contributed by Red Hat, originally written by Keith Seitz.
+#
+# 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/>.
+
+# This file is part of the gdb testsuite.
+
+# A helper proc which sets a breakpoint at FUNC and attempts to
+# run to the breakpoint.
+proc test_breakpoint {func} {
+    global DEC
+
+    # Restart every time
+    if {![runto_main]} {
+	perror "could not run to main when attempting to break at $func"
+    } else {
+	gdb_breakpoint "$func"
+	set i [expr {[string last : $func] + 1}]
+	set efunc [string_to_regexp [string range $func $i end]]
+	gdb_test "continue" \
+	    "Continuing.\r\n\r\nBreakpoint $DEC+,.*$efunc.*" \
+	    "continue to $func"
+    }
+}
+
+# Add a function to the list of tested functions
+# FUNC is the name of the function (which will be passed to gdb commands)
+# TYPE is the type of the function, as expected from the "print" command
+# PRINT is the name of the function, as expected result of the print command
+#  *OR* "-", indicating that FUNC should be used (needed for virtual/inherited
+#   funcs)
+# LST is either the expected result of the list command (the comment from
+#  the source code) *OR* "-", in which case FUNC will be used
+#
+# Usage:
+# add NAME TYPE PRINT LST
+# add NAME TYPE PRINT -
+proc add {func type print lst} {
+    global all_functions CONVAR ADDR
+
+    set all_functions($func,type) $type
+    if {$print == "-"} {
+	set print $func
+    }
+
+    # An exception: since gdb canonicalizes C++ output,
+    # "(void)" must be mutated to "()".
+    regsub {\(void\)} $print {()} print
+
+    set all_functions($func,print) \
+	"$CONVAR = {[string_to_regexp $type]} $ADDR <[string_to_regexp $print].*>"
+    if {$lst == "-"} {
+	set lst "$func"
+    }
+    set all_functions($func,list) ".*// [string_to_regexp $lst]"
+}
+
+proc get {func cmd} {
+    global all_functions
+    return $all_functions($func,$cmd)
+}
+
+# Returns a list of function names for a given command
+proc get_functions {cmd} {
+    global all_functions
+    set result {}
+    foreach i [array names all_functions *,$cmd] {
+	if {$all_functions($i) != ""} {
+	    set idx [string last , $i]
+	    if {$idx != -1} {
+		lappend result [string range $i 0 [expr {$idx - 1}]]
+	    }
+	}
+    }
+
+    return [lsort $result]
+}
+
+# Some convenience variables for this test
+set DEC {[0-9]}; # a decimal number
+set HEX {[0-9a-fA-F]}; # a hexidecimal number
+set CONVAR "\\\$$DEC+"; # convenience variable regexp
+set ADDR "0x$HEX+"; # address
+
+# An array of functions/methods that we are testing...
+# Each element consists is indexed by NAME,COMMAND, where
+# NAME is the function name and COMMAND is the gdb command that
+# we are testing. The value of the array for any index pair is
+# the expected result of running COMMAND with the NAME as argument.
+
+# The array holding all functions/methods to test. Valid subindexes
+# are (none need character escaping -- "add" will take care of that):
+
+# add name type print_name list
+# NAME,type: value is type of function 
+# NAME,print: value is print name of function (careful w/inherited/virtual!)
+# NAME,list: value is comment in source code on first line of function
+#   (without the leading "//")
+array set all_functions {}
+
+# "Normal" functions/methods
+add {main} \
+    {int (int, char **)} \
+    - \
+    -
+add {derived::a_function} \
+    {void (const derived * const)} \
+    - \
+    -
+add {base1::a_function} \
+    {void (const base1 * const)} \
+    - \
+    -
+add {base2::a_function} \
+    {void (const base2 * const)} \
+    - \
+    -
+
+# Constructors
+
+# On targets using the ARM EABI, the constructor is expected to return
+# "this".
+proc ctor { type arglist } {
+    if { [istarget arm*-*eabi*] } {
+	set ret "$type *"
+    } else {
+	set ret "void "
+    }
+    if { $arglist != "" } {
+	set arglist ", $arglist"
+    }
+    return "${ret}($type * const$arglist)"
+}
+
+add {derived::derived} \
+    [ctor derived ""] \
+    - \
+    -
+add {base1::base1(void)} \
+    [ctor base1 "const void ** const"] \
+    - \
+    -
+add {base1::base1(int)} \
+    [ctor base1 "int"] \
+    - \
+    -
+add {base2::base2} \
+    [ctor base2 "const void ** const"] \
+    - \
+    -
+add {base::base(void)} \
+    [ctor base ""] \
+    - \
+    -
+add {base::base(int)} \
+    [ctor base "int"] \
+    - \
+    -
+
+# Destructors
+
+# On targets using the ARM EABI, some destructors are expected
+# to return "this".  Others are void.  For internal reasons,
+# GCC returns void * instead of $type *; RealView appears to do
+# the same.
+proc dtor { type } {
+    if { [istarget arm*-*eabi*] } {
+	set ret "void *"
+    } else {
+	set ret "void "
+    }
+    return "${ret}($type * const)"
+}
+
+add {base::~base} \
+    [dtor base] \
+    - \
+    -
+
+# Overloaded methods (all are const -- we try to use the void
+# method with and without specifying "const")
+add {base::overload(void)} \
+    {int (const base * const)} \
+    - \
+    {base::overload(void) const}
+add {base::overload(void) const} \
+    {int (const base * const)} \
+    - \
+    {base::overload(void) const}
+add {base::overload(int) const} \
+    {int (const base * const, int)} \
+    - \
+    -
+add {base::overload(short) const} \
+    {int (const base * const, short)} \
+    - \
+    -
+add {base::overload(long) const} \
+    {int (const base * const, long)} \
+    - \
+    -
+add {base::overload(char*) const} \
+    {int (const base * const, char *)} \
+    - \
+    -
+add {base::overload(base&) const} \
+    {int (const base * const, base &)} \
+    - \
+    -
+
+# Operators
+add {base::operator+} \
+    {int (const base * const, const base &)} \
+    - \
+    -
+add {base::operator++} \
+    {base (base * const)} \
+    - \
+    -
+add {base::operator+=} \
+    {base (base * const, const base &)} \
+    - \
+    -
+add {base::operator-} \
+    {int (const base * const, const base &)} \
+    - \
+    -
+add {base::operator--} \
+    {base (base * const)} \
+    - \
+    -
+add {base::operator-=} \
+    {base (base * const, const base &)} \
+    - \
+    -
+add {base::operator*} \
+    {int (const base * const, const base &)} \
+    - \
+    -
+add {base::operator*=} \
+    {base (base * const, const base &)} \
+    - \
+    -
+add {base::operator/} \
+    {int (const base * const, const base &)} \
+    - \
+    -
+add {base::operator/=} \
+    {base (base * const, const base &)} \
+    - \
+    -
+add {base::operator%} \
+    {int (const base * const, const base &)} \
+    - \
+    -
+add {base::operator%=} \
+    {base (base * const, const base &)} \
+    - \
+    -
+add {base::operator<} \
+    {bool (const base * const, const base &)} \
+    - \
+    -
+add {base::operator<=} \
+    {bool (const base * const, const base &)} \
+    - \
+    -
+add {base::operator>} \
+    {bool (const base * const, const base &)} \
+    - \
+    -
+add {base::operator>=} \
+    {bool (const base * const, const base &)} \
+    - \
+    -
+add {base::operator!=} \
+    {bool (const base * const, const base &)} \
+    - \
+    -
+add {base::operator==} \
+    {bool (const base * const, const base &)} \
+    - \
+    -
+add {base::operator!} \
+    {bool (const base * const)} \
+    - \
+    -
+add {base::operator&&} \
+    {bool (const base * const, const base &)} \
+    - \
+    -
+add {base::operator||} \
+    {bool (const base * const, const base &)} \
+    - \
+    -
+add {base::operator<<} \
+    {int (const base * const, int)} \
+    - \
+    -
+add {base::operator<<=} \
+    {base (base * const, int)} \
+    - \
+    -
+add {base::operator>>} \
+    {int (const base * const, int)} \
+    - \
+    -
+add {base::operator>>=} \
+    {base (base * const, int)} \
+    - \
+    -
+add {base::operator~} \
+    {int (const base * const)} \
+    - \
+    -
+add {base::operator&} \
+    {int (const base * const, const base &)} \
+    - \
+    -
+add {base::operator&=} \
+    {base (base * const, const base &)} \
+    - \
+    -
+add {base::operator|} \
+    {int (const base * const, const base &)} \
+    - \
+    -
+add {base::operator|=} \
+    {base (base * const, const base &)} \
+    - \
+    -
+add {base::operator^} \
+    {int (const base * const, const base &)} \
+    - \
+    -
+add {base::operator^=} \
+    {base (base * const, const base &)} \
+    - \
+    -
+add {base::operator=} \
+    {base (base * const, const base &)} \
+    - \
+    -
+add {base::operator()} \
+    {void (const base * const)} \
+    - \
+    -
+add {base::operator[]} \
+    {int (const base * const, int)} \
+    - \
+    -
+add {base::operator new} \
+    {void *(size_t)} \
+    - \
+    -
+add {base::operator delete} \
+    {void (void *)} \
+    - \
+    -
+add {base::operator new[]} \
+    {void *(size_t)} \
+    - \
+    -
+add {base::operator delete[]} \
+    {void (void *)} \
+    - \
+    -
+add {base::operator char*} \
+    {char *(const base * const)} \
+    - \
+    -
+add {base::operator fluff*} \
+    {fluff *(const base * const)} \
+    - \
+    -
+add {base::operator fluff**} \
+    {fluff **(const base * const)} \
+    - \
+    -
+add {base::operator int} \
+    {int (const base * const)} \
+    - \
+    -
+
+# Templates
+add {tclass<char>::do_something} \
+    {void (tclass<char> * const)} \
+    - \
+    -
+add {tclass<int>::do_something} \
+    {void (tclass<int> * const)} \
+    - \
+    -
+add {tclass<long>::do_something} \
+    {void (tclass<long> * const)} \
+    - \
+    -
+add {tclass<short>::do_something} \
+    {void (tclass<short> * const)} \
+    - \
+    -
+add {tclass<base>::do_something} \
+    {void (tclass<base> * const)} \
+    - \
+    -
+add {flubber<int, int, int, int, int>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, int, int, short>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, int, int, long>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, int, int, char>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, int, short, int>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, int, short, short>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, int, short, long>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, int, short, char>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, int, long, int>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, int, long, short>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, int, long, long>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, int, long, char>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, int, char, int>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, int, char, short>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, int, char, long>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, int, char, char>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, short, int, int>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, short, int, short>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, short, int, long>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, short, int, char>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<int, int, short, short, int>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<short, int, short, int, short>} \
+    {void (void)} \
+    - \
+    flubber
+add {flubber<long, short, long, short, long>} \
+    {void (void)} \
+    - \
+    flubber
+add {tclass<base>::do_something} \
+    {void (tclass<base> * const)} \
+    - \
+    {tclass<T>::do_something}
+add {policy1::policy} \
+    [ctor "policy<int, operation_1<void*> >" "int"] \
+    {policy<int, operation_1<void*> >::policy} \
+    {policy<T, Policy>::policy}
+add {policy2::policy} \
+    [ctor "policy<int, operation_2<void*> >" int] \
+    {policy<int, operation_2<void*> >::policy} \
+    {policy<T, Policy>::policy}
+add {policy3::policy} \
+    [ctor "policy<int, operation_3<void*> >" "int"] \
+    {policy<int, operation_3<void*> >::policy} \
+    {policy<T, Policy>::policy}
+add {policy4::policy} \
+    [ctor "policy<int, operation_4<void*> >" "int"] \
+    {policy<int, operation_4<void*> >::policy} \
+    {policy<T, Policy>::policy}
+add {policy1::function} \
+    {void (void)} \
+    {operation_1<void*>::function} \
+    {operation_1<T>::function}
+add {policy2::function} \
+    {void (void)} \
+    {operation_2<void*>::function} \
+    {operation_2<T>::function}
+add {policy3::function} \
+    {void (void)} \
+    {operation_3<void*>::function} \
+    {operation_3<T>::function}
+add {policy4::function} \
+    {void (void)} \
+    {operation_4<void*>::function} \
+    {operation_4<T>::function}
+add {policyd<int, operation_1<int> >::policyd} \
+    [ctor "policyd<int, operation_1<int> >" "int"] \
+    - \
+    {policyd<T, Policy>::policyd}
+add {policyd1::policyd} \
+    [ctor "policyd<int, operation_1<int> >" "int"] \
+    {policyd<int, operation_1<int> >::policyd} \
+    {policyd<T, Policy>::policyd}
+add {policyd<int, operation_1<int> >::~policyd} \
+    [dtor "policyd<int, operation_1<int> >"] \
+    - \
+    {policyd<T, Policy>::~policyd}
+add {policyd1::~policyd} \
+    [dtor "policyd<int, operation_1<int> >"] \
+    {policyd<int, operation_1<int> >::~policyd} \
+    {policyd<T, Policy>::~policyd}
+add {policyd<long, operation_1<long> >::policyd} \
+    [ctor "policyd<long, operation_1<long> >" "long"] \
+    - \
+    {policyd<T, Policy>::policyd}
+add {policyd2::policyd} \
+    [ctor "policyd<long, operation_1<long> >" "long"] \
+    {policyd<long, operation_1<long> >::policyd} \
+    {policyd<T, Policy>::policyd}
+add {policyd<long, operation_1<long> >::~policyd} \
+    [dtor "policyd<long, operation_1<long> >"] \
+    - \
+    {policyd<T, Policy>::~policyd}
+add {policyd2::~policyd} \
+    [dtor "policyd<long, operation_1<long> >"] \
+    {policyd<long, operation_1<long> >::~policyd} \
+    {policyd<T, Policy>::~policyd}
+add {policyd<char, operation_1<char> >::policyd} \
+    [ctor "policyd<char, operation_1<char> >" "char"] \
+    - \
+    {policyd<T, Policy>::policyd}
+add {policyd3::policyd} \
+    [ctor "policyd<char, operation_1<char> >" "char"] \
+    {policyd<char, operation_1<char> >::policyd} \
+    {policyd<T, Policy>::policyd}
+add {policyd<char, operation_1<char> >::~policyd} \
+    [dtor "policyd<char, operation_1<char> >"] \
+    - \
+    {policyd<T, Policy>::~policyd}
+add {policyd3::~policyd} \
+    [dtor "policyd<char, operation_1<char> >"] \
+    {policyd<char, operation_1<char> >::~policyd} \
+    {policyd<T, Policy>::~policyd}
+add {policyd<base, operation_1<base> >::policyd} \
+    [ctor "policyd<base, operation_1<base> >" "base"] \
+    - \
+    {policyd<T, Policy>::policyd}
+add {policyd4::policyd} \
+    [ctor "policyd<base, operation_1<base> >" "base"] \
+    {policyd<base, operation_1<base> >::policyd} \
+    {policyd<T, Policy>::policyd}
+add {policyd<base, operation_1<base> >::~policyd} \
+    [dtor "policyd<base, operation_1<base> >"] \
+    - \
+    {policyd<T, Policy>::~policyd}
+add {policyd4::~policyd} \
+    [dtor "policyd<base, operation_1<base> >"] \
+    {policyd<base, operation_1<base> >::~policyd} \
+    {policyd<T, Policy>::~policyd}
+add {policyd<tclass<int>, operation_1<tclass<int> > >::policyd} \
+    [ctor "policyd<tclass<int>, operation_1<tclass<int> > >" "tclass<int>"] \
+    - \
+    {policyd<T, Policy>::policyd}
+add {policyd5::policyd} \
+    [ctor "policyd<tclass<int>, operation_1<tclass<int> > >" "tclass<int>"] \
+    {policyd<tclass<int>, operation_1<tclass<int> > >::policyd} \
+    {policyd<T, Policy>::policyd}
+add {policyd<tclass<int>, operation_1<tclass<int> > >::~policyd} \
+    [dtor "policyd<tclass<int>, operation_1<tclass<int> > >"] \
+    - \
+    {policyd<T, Policy>::~policyd}
+add {policyd5::~policyd} \
+    [dtor "policyd<tclass<int>, operation_1<tclass<int> > >"] \
+    {policyd<tclass<int>, operation_1<tclass<int> > >::~policyd} \
+    {policyd<T, Policy>::~policyd}
+add {policyd<int, operation_1<int> >::function} \
+    {void (void)} \
+    {operation_1<int>::function}\
+    {operation_1<T>::function}
+add {policyd1::function} \
+    {void (void)} \
+    {operation_1<int>::function} \
+    {operation_1<T>::function}
+add {policyd2::function} \
+    {void (void)} \
+    {operation_1<long>::function} \
+    {operation_1<T>::function}
+add {policyd<char, operation_1<char> >::function} \
+    {void (void)} \
+    {operation_1<char>::function} \
+    {operation_1<T>::function}
+add {policyd3::function} \
+    {void (void)} \
+    {operation_1<char>::function} \
+    {operation_1<T>::function}
+add {policyd<base, operation_1<base> >::function} \
+    {void (void)} \
+    {operation_1<base>::function} \
+    {operation_1<T>::function}
+add {policyd4::function} \
+    {void (void)} \
+    {operation_1<base>::function} \
+    {operation_1<T>::function}
+add {policyd<tclass<int>, operation_1<tclass<int> > >::function} \
+    {void (void)} \
+    {operation_1<tclass<int> >::function} \
+    {operation_1<T>::function}
+add {policyd5::function} \
+    {void (void)} \
+    {operation_1<tclass<int> >::function} \
+    {operation_1<T>::function}
+
+# Start the test
+if {$tracelevel} {
+    strace $tracelevel
+}
+
+if {[skip_cplus_tests]} { continue }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "cpexprs"
+set srcfile "${testfile}.cc"
+set binfile [file join $objdir $subdir $testfile]
+
+if  {[gdb_compile [file join $srcdir $subdir $srcfile] $binfile \
+	  executable {debug c++}] != "" } {
+    untested "$testfile.exp"
+    return -1
+}
+
+if {[get_compiler_info $binfile "c++"]} {
+    return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir [file join $srcdir $subdir]
+gdb_load $binfile
+
+if {![runto_main]} {
+    perror "couldn't run to breakpoint"
+    continue
+}
+
+# Set the listsize to one. This will help with testing "list".
+gdb_test "set listsize 1"
+
+# "print METHOD"
+foreach name [get_functions print] {
+    gdb_test "print $name" [get $name print] "print $name"
+}
+
+# "list METHOD"
+foreach name [get_functions list] {
+    gdb_test "list $name" [get $name list] "list $name"
+}
+
+# Running to breakpoint -- use any function we can "list"
+foreach name [get_functions list] {
+    # Skip "main", since test_breakpoint uses it
+    if {[string compare $name "main"] != 0} {
+	test_breakpoint $name
+    }
+}
+
+gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.cp/cplusfuncs.cc b/gdb/testsuite/gdb.cp/cplusfuncs.cc
index f4f78a6..11dba06 100644
--- a/gdb/testsuite/gdb.cp/cplusfuncs.cc
+++ b/gdb/testsuite/gdb.cp/cplusfuncs.cc
@@ -195,6 +195,12 @@ char *	dm_type_char_star (char * p)		{ return p; }
 int	dm_type_foo_ref (foo & foo)		{ return foo.ifoo; }
 int *	dm_type_int_star (int * p)		{ return p; }
 long *	dm_type_long_star (long * p)		{ return p; }
+int	dm_type_short (short i)			{ return i; }
+int	dm_type_long (long i)			{ return i; }
 int	dm_type_unsigned_int (unsigned int i)	{ return i; }
+int	dm_type_unsigned_short (unsigned short i)	{ return i; }
+int	dm_type_unsigned_long (unsigned long i)	{ return i; }
 int	dm_type_void (void)			{ return 0; }
 void *	dm_type_void_star (void * p)		{ return p; }
+typedef int myint;
+int	dm_type_typedef (myint i)		{ return i; }
diff --git a/gdb/testsuite/gdb.cp/cplusfuncs.exp b/gdb/testsuite/gdb.cp/cplusfuncs.exp
index f322586..443af7a 100644
--- a/gdb/testsuite/gdb.cp/cplusfuncs.exp
+++ b/gdb/testsuite/gdb.cp/cplusfuncs.exp
@@ -66,9 +66,25 @@ set dm_type_unsigned_int	"unsigned"
 set dm_type_void		"void"
 set dm_type_void_star		"void*"
 
+# Some other vagaries of GDB's type printing machinery.  The integer types
+# may have unsigned before or after their length, and may have "int"
+# appended.  The char* conversion operator may have name "char*" even if
+# the type is "char *", because the name comes from the debug information
+# and the type from GDB.  Function types may not see through typedefs.
+
+set dm_type_short		"short"
+set dm_type_long		"long"
+set dm_type_unsigned_short	"unsigned short"
+set dm_type_unsigned_long	"unsigned long"
+set dm_operator_char_star	"char*"
+set dm_operator_char_star_quoted	"char\\*"
+set dm_type_typedef		0
+
 proc probe_demangler { } {
     global gdb_prompt
     global dm_operator_comma
+    global dm_operator_char_star
+    global dm_operator_char_star_quoted
     global dm_type_char_star
     global dm_type_char_star_quoted
     global dm_type_foo_ref
@@ -77,6 +93,11 @@ proc probe_demangler { } {
     global dm_type_unsigned_int
     global dm_type_void
     global dm_type_void_star
+    global dm_type_short
+    global dm_type_unsigned_short
+    global dm_type_long
+    global dm_type_unsigned_long
+    global dm_type_typedef
 
     send_gdb "print &foo::operator,(foo&)\n"
     gdb_expect {
@@ -97,6 +118,26 @@ proc probe_demangler { } {
 	}
     }
 
+    send_gdb "print &foo::operator char*($dm_type_void)\n"
+    gdb_expect {
+	-re ".*foo::operator char \\*\\(void\\).*\r\n$gdb_prompt $" {
+	    # v2 demangler or GDB type printer
+	    set dm_operator_char_star "char *"
+	    set dm_operator_char_star_quoted "char \\*"
+	    pass "detect dm_operator_char_star"
+	}
+	-re ".*foo::operator char\\*\\(\\).*\r\n$gdb_prompt $" {
+	    # v3 demangler
+	    pass "detect dm_operator_char_star"
+	}
+	-re ".*$gdb_prompt $" {
+	    fail "detect dm_operator_char_star"
+	}
+	timeout {
+	    fail "detect dm_operator_char_star"
+	}
+    }
+
     send_gdb "print &dm_type_char_star\n"
     gdb_expect {
 	-re ".*dm_type_char_star\\(char \\*\\).*\r\n$gdb_prompt $" {
@@ -166,6 +207,11 @@ proc probe_demangler { } {
 	    # v3 demangler
 	    pass "detect dm_type_long_star"
 	}
+	-re ".*dm_type_long_star\\(long int \\*\\).*\r\n$gdb_prompt $" {
+	    # GCC v3 and GDB's type printer
+	    set dm_type_long_star "long int *"
+	    pass "detect dm_type_long_star"
+	}
 	-re ".*$gdb_prompt $" {
 	    fail "detect dm_type_long_star"
 	}
@@ -230,6 +276,101 @@ proc probe_demangler { } {
 	    fail "detect dm_type_void_star (timeout)"
 	}
     }
+
+    send_gdb "print &dm_type_short\n"
+    gdb_expect {
+	-re ".*dm_type_short\\(short\\).*\r\n$gdb_prompt $" {
+	    # v2 and v3 demanglers
+	    pass "detect dm_type_short"
+	}
+	-re ".*dm_type_short\\(short int\\).*\r\n$gdb_prompt $" {
+	    # GDB type printer
+	    set dm_type_short "short int"
+	    pass "detect dm_type_short"
+	}
+	-re ".*$gdb_prompt $" {
+	    fail "detect dm_type_short"
+	}
+	timeout {
+	    fail "detect dm_type_short (timeout)"
+	}
+    }
+
+    send_gdb "print &dm_type_unsigned_short\n"
+    gdb_expect {
+	-re ".*dm_type_unsigned_short\\(unsigned short\\).*\r\n$gdb_prompt $" {
+	    # v2 and v3 demanglers
+	    pass "detect dm_type_unsigned_short"
+	}
+	-re ".*dm_type_unsigned_short\\(short unsigned int\\).*\r\n$gdb_prompt $" {
+	    # GDB type printer
+	    set dm_type_unsigned_short "short unsigned int"
+	    pass "detect dm_type_unsigned_short"
+	}
+	-re ".*$gdb_prompt $" {
+	    fail "detect dm_type_unsigned_short"
+	}
+	timeout {
+	    fail "detect dm_type_unsigned_short (timeout)"
+	}
+    }
+
+    send_gdb "print &dm_type_long\n"
+    gdb_expect {
+	-re ".*dm_type_long\\(long\\).*\r\n$gdb_prompt $" {
+	    # v2 and v3 demanglers
+	    pass "detect dm_type_long"
+	}
+	-re ".*dm_type_long\\(long int\\).*\r\n$gdb_prompt $" {
+	    # GDB type printer
+	    set dm_type_long "long int"
+	    pass "detect dm_type_long"
+	}
+	-re ".*$gdb_prompt $" {
+	    fail "detect dm_type_long"
+	}
+	timeout {
+	    fail "detect dm_type_long (timeout)"
+	}
+    }
+
+    send_gdb "print &dm_type_unsigned_long\n"
+    gdb_expect {
+	-re ".*dm_type_unsigned_long\\(unsigned long\\).*\r\n$gdb_prompt $" {
+	    # v2 and v3 demanglers
+	    pass "detect dm_type_unsigned_long"
+	}
+	-re ".*dm_type_unsigned_long\\(long unsigned int\\).*\r\n$gdb_prompt $" {
+	    # GDB type printer
+	    set dm_type_unsigned_long "long unsigned int"
+	    pass "detect dm_type_unsigned_long"
+	}
+	-re ".*$gdb_prompt $" {
+	    fail "detect dm_type_unsigned_long"
+	}
+	timeout {
+	    fail "detect dm_type_unsigned_long (timeout)"
+	}
+    }
+
+    send_gdb "print &dm_type_typedef\n"
+    gdb_expect {
+	-re ".*dm_type_typedef\\(int\\).*\r\n$gdb_prompt $" {
+	    # v2 and v3 demanglers
+	    pass "detect dm_type_typedef"
+	}
+	-re ".*dm_type_typedef\\(myint\\).*\r\n$gdb_prompt $" {
+	    # GDB type printer
+	    set dm_type_typedef 1
+	    pass "detect dm_type_typedef"
+	}
+	-re ".*$gdb_prompt $" {
+	    fail "detect dm_type_typedef"
+	}
+	timeout {
+	    fail "detect dm_type_typedef (timeout)"
+	}
+    }
 }
 
 #
@@ -351,8 +492,9 @@ proc print_addr { name } {
 
 proc test_lookup_operator_functions {} {
     global dm_operator_comma
+    global dm_operator_char_star
     global dm_type_char_star
-    global dm_type_char_star_quoted
+    global dm_operator_char_star_quoted
     global dm_type_foo_ref
     global dm_type_void
     global dm_type_void_star
@@ -410,8 +552,8 @@ proc test_lookup_operator_functions {} {
 
     info_func "operator int("	"int foo::operator int($dm_type_void);"
     info_func "operator()("	"void foo::operator()($dm_type_foo_ref);"
-    info_func "operator $dm_type_char_star_quoted\(" \
-				"char *foo::operator $dm_type_char_star\($dm_type_void);"
+    info_func "operator $dm_operator_char_star_quoted\(" \
+				"char *foo::operator $dm_operator_char_star\($dm_type_void);"
 
 }
 
@@ -426,6 +568,7 @@ proc test_paddr_operator_functions {} {
     global dm_type_unsigned_int
     global dm_type_void
     global dm_type_void_star
+    global dm_operator_char_star
 
     print_addr "foo::operator*($dm_type_foo_ref)"
     print_addr "foo::operator%($dm_type_foo_ref)"
@@ -479,7 +622,7 @@ proc test_paddr_operator_functions {} {
     }
 
     print_addr "foo::operator int($dm_type_void)"
-    print_addr "foo::operator $dm_type_char_star\($dm_type_void)"
+    print_addr "foo::operator $dm_operator_char_star\($dm_type_void)"
 }
 
 #
@@ -489,17 +632,21 @@ proc test_paddr_operator_functions {} {
 proc test_paddr_overloaded_functions {} {
     global dm_type_unsigned_int
     global dm_type_void
+    global dm_type_short
+    global dm_type_unsigned_short
+    global dm_type_long
+    global dm_type_unsigned_long
 
     print_addr "overload1arg($dm_type_void)"
     print_addr "overload1arg(char)"
     print_addr "overload1arg(signed char)"
     print_addr "overload1arg(unsigned char)"
-    print_addr "overload1arg(short)"
-    print_addr "overload1arg(unsigned short)"
+    print_addr "overload1arg($dm_type_short)"
+    print_addr "overload1arg($dm_type_unsigned_short)"
     print_addr "overload1arg(int)"
     print_addr "overload1arg($dm_type_unsigned_int)"
-    print_addr "overload1arg(long)"
-    print_addr "overload1arg(unsigned long)"
+    print_addr "overload1arg($dm_type_long)"
+    print_addr "overload1arg($dm_type_unsigned_long)"
     print_addr "overload1arg(float)"
     print_addr "overload1arg(double)"
 
@@ -522,17 +669,31 @@ proc test_paddr_hairy_functions {} {
     global dm_type_char_star
     global dm_type_int_star
     global dm_type_long_star
+    global dm_type_typedef
 
     print_addr_2 "hairyfunc1" "hairyfunc1(int)"
-    print_addr_2 "hairyfunc2" "hairyfunc2(int (*)($dm_type_char_star))"
-    print_addr_2 "hairyfunc3" "hairyfunc3(int (*)(short (*)($dm_type_long_star)))"
-    print_addr_2 "hairyfunc4" "hairyfunc4(int (*)(short (*)($dm_type_char_star)))"
-
-    # gdb-gnats bug gdb/19:
-    # "gdb v3 demangler fails on hairyfunc5 hairyfunc6 hairyfunc7"
-    print_addr_2_kfail "hairyfunc5" "hairyfunc5(int (*(*)($dm_type_char_star))(long))" "hairyfunc5(int (*)(long) (*)(char*))" "gdb/19"
-    print_addr_2_kfail "hairyfunc6" "hairyfunc6(int (*(*)($dm_type_int_star))(long))" "hairyfunc6(int (*)(long) (*)(int*))" "gdb/19"
-    print_addr_2_kfail "hairyfunc7" "hairyfunc7(int (*(*)(int (*)($dm_type_char_star)))(long))" "hairyfunc7(int (*)(long) (*)(int (*)(char*)))" "gdb/19"
+
+    if {$dm_type_typedef == 0} {
+	print_addr_2 "hairyfunc2" "hairyfunc2(int (*)($dm_type_char_star))"
+	print_addr_2 "hairyfunc3" "hairyfunc3(int (*)(short (*)($dm_type_long_star)))"
+	print_addr_2 "hairyfunc4" "hairyfunc4(int (*)(short (*)($dm_type_char_star)))"
+
+	# gdb-gnats bug gdb/19:
+	# "gdb v3 demangler fails on hairyfunc5 hairyfunc6 hairyfunc7"
+	print_addr_2_kfail "hairyfunc5" "hairyfunc5(int (*(*)($dm_type_char_star))(long))" "hairyfunc5(int (*)(long) (*)(char*))" "gdb/19"
+	print_addr_2_kfail "hairyfunc6" "hairyfunc6(int (*(*)($dm_type_int_star))(long))" "hairyfunc6(int (*)(long) (*)(int*))" "gdb/19"
+	print_addr_2_kfail "hairyfunc7" "hairyfunc7(int (*(*)(int (*)($dm_type_char_star)))(long))" "hairyfunc7(int (*)(long) (*)(int (*)(char*)))" "gdb/19"
+    } else {
+	print_addr_2 "hairyfunc2" "hairyfunc2(PFPc_i)"
+	print_addr_2 "hairyfunc3" "hairyfunc3(PFPFPl_s_i)"
+	print_addr_2 "hairyfunc4" "hairyfunc4(PFPFPc_s_i)"
+
+	# gdb-gnats bug gdb/19:
+	# "gdb v3 demangler fails on hairyfunc5 hairyfunc6 hairyfunc7"
+	print_addr_2 "hairyfunc5" "hairyfunc5(PFPc_PFl_i)"
+	print_addr_2 "hairyfunc6" "hairyfunc6(PFPi_PFl_i)"
+	print_addr_2 "hairyfunc7" "hairyfunc7(PFPFPc_i_PFl_i)"
+    }
 }
 
 proc do_tests {} {
diff --git a/gdb/testsuite/gdb.cp/ctti.exp b/gdb/testsuite/gdb.cp/ctti.exp
index 454c6f4..8f88ad7 100644
--- a/gdb/testsuite/gdb.cp/ctti.exp
+++ b/gdb/testsuite/gdb.cp/ctti.exp
@@ -85,11 +85,6 @@ gdb_test "print c" "\\$\[0-9\]+ = 194 .*"
 gdb_test "print f" "\\$\[0-9\]+ = 9"
 gdb_test "print i" "\\$\[0-9\]+ = 4"
 
-# TODO: this needs more work before actually deploying it.
-# So bail out here.
-
-if { [ test_compiler_info gcc-*] } then { continue }
-
 gdb_test_multiple "print add<int>(2,2)" "print add<int>(2,2)" {
     -re "\\$\[0-9\]+ = 4\r\n$gdb_prompt $" {
 	pass "print add<int>(2,2)"
diff --git a/gdb/testsuite/gdb.cp/exception.exp b/gdb/testsuite/gdb.cp/exception.exp
index 47890f1..03c8847 100644
--- a/gdb/testsuite/gdb.cp/exception.exp
+++ b/gdb/testsuite/gdb.cp/exception.exp
@@ -146,7 +146,9 @@ gdb_test_multiple "continue" $name {
 
 set name "backtrace after first throw"
 gdb_test_multiple "backtrace" $name {
-    -re ".*#\[0-9\]+${ws}($hex in |)__cxa_throw.*#\[0-9\]+${ws}$hex in foo \\(i=20\\) at .*${srcfile}:\[0-9\]+\r\n#\[0-9\]+${ws}$hex in main \\(.*\\) at .*${srcfile}:\[0-9\]+\r\n$gdb_prompt $" {
+    -re ".*#\[0-9\]+.*\[\[:<:\]\]__cxa_throw\[\[:>:\]\].*#\[0-9\]+${ws}$hex in foo \\(i=20\\) at .*${srcfile}:\[0-9\]+\r\n#\[0-9\]+${ws}$hex in main \\(.*\\) at .*${srcfile}:\[0-9\]+\r\n$gdb_prompt $" {
+	# Either __cxxabiv1::__cxa_throw or __cxa_throw can be printed
+	# depending on debug info presence.
 	pass $name
     }
 }
@@ -168,7 +170,7 @@ gdb_test_multiple "continue" $name {
 
 set name "backtrace after first catch"
 gdb_test_multiple "backtrace" $name {
-    -re ".*#\[0-9\]+${ws}($hex in |)__cxa_begin_catch.*#\[0-9\]+${ws}$hex in main \\(.*\\) at .*$srcfile:\[0-9\]+\r\n$gdb_prompt $" {
+    -re ".*#\[0-9\]+.*\[\[:<:\]\]__cxa_begin_catch\[\[:>:\]\].*#\[0-9\]+${ws}$hex in main \\(.*\\) at .*$srcfile:\[0-9\]+\r\n$gdb_prompt $" {
 	pass $name
     }
 }
@@ -190,7 +192,7 @@ gdb_test_multiple "continue" $name {
 
 set name "backtrace after second throw"
 gdb_test_multiple "backtrace" $name {
-    -re ".*#\[0-9\]+${ws}($hex in |)__cxa_throw.*#\[0-9\]+${ws}$hex in foo \\(i=20\\) at .*${srcfile}:\[0-9\]+\r\n#\[0-9\]+${ws}$hex in main \\(.*\\) at .*${srcfile}:\[0-9\]+\r\n$gdb_prompt $" {
+    -re ".*#\[0-9\]+.*\[\[:<:\]\]__cxa_throw\[\[:>:\]\].*#\[0-9\]+${ws}$hex in foo \\(i=20\\) at .*${srcfile}:\[0-9\]+\r\n#\[0-9\]+${ws}$hex in main \\(.*\\) at .*${srcfile}:\[0-9\]+\r\n$gdb_prompt $" {
 	pass $name
     }
 }
@@ -212,7 +214,7 @@ gdb_test_multiple "continue" $name {
 
 set name "backtrace after second catch"
 gdb_test_multiple "backtrace" $name {
-    -re ".*#\[0-9\]+${ws}($hex in |)__cxa_begin_catch.*#\[0-9\]+${ws}$hex in main \\(.*\\) at .*$srcfile:\[0-9\]+\r\n$gdb_prompt $" {
+    -re ".*#\[0-9\]+.*\[\[:<:\]\]__cxa_begin_catch\[\[:>:\]\].*#\[0-9\]+${ws}$hex in main \\(.*\\) at .*$srcfile:\[0-9\]+\r\n$gdb_prompt $" {
 	pass $name
     }
 }
diff --git a/gdb/testsuite/gdb.cp/expand-sals.exp b/gdb/testsuite/gdb.cp/expand-sals.exp
index 25ec4a9..e4fd59b 100644
--- a/gdb/testsuite/gdb.cp/expand-sals.exp
+++ b/gdb/testsuite/gdb.cp/expand-sals.exp
@@ -46,7 +46,7 @@ gdb_continue_to_breakpoint "caller" ".*caller-line.*"
 
 # Test GDB caught this return call and not the next one through B::B()
 gdb_test "bt" \
-	 "#0 \[^\r\n\]* A \[^\r\n\]*\r\n#1 \[^\r\n\]* main \[^\r\n\]*" \
+	 "#0 \[^\r\n\]* (A::)?A \[^\r\n\]*\r\n#1 \[^\r\n\]* main \[^\r\n\]*" \
 	 "bt from A"
 
 gdb_continue_to_breakpoint "next caller func" ".*func-line.*"
diff --git a/gdb/testsuite/gdb.cp/gdb9593.cc b/gdb/testsuite/gdb.cp/gdb9593.cc
new file mode 100644
index 0000000..783c962
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/gdb9593.cc
@@ -0,0 +1,180 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2008, 2009 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 <iostream>
+
+using namespace std;
+
+class NextOverThrowDerivates
+{
+
+public:
+
+
+  // Single throw an exception in this function.
+  void function1() 
+  {
+    throw 20;
+  }
+
+  // Throw an exception in another function.
+  void function2() 
+  {
+    function1();
+  }
+
+  // Throw an exception in another function, but handle it
+  // locally.
+  void function3 () 
+  {
+    {
+      try
+	{
+	  function1 ();
+	}
+      catch (...) 
+	{
+	  cout << "Caught and handled function1 exception" << endl;
+	}
+    }
+  }
+
+  void rethrow ()
+  {
+    try
+      {
+	function1 ();
+      }
+    catch (...)
+      {
+	throw;
+      }
+  }
+
+  void finish ()
+  {
+    // We use this to test that a "finish" here does not end up in
+    // this frame, but in the one above.
+    try
+      {
+	function1 ();
+      }
+    catch (int x)
+      {
+      }
+    function1 ();		// marker for until
+  }
+
+  void until ()
+  {
+    function1 ();
+    function1 ();		// until here
+  }
+
+};
+NextOverThrowDerivates next_cases;
+
+
+int main () 
+{ 
+  try
+    {
+      next_cases.function1 ();
+    }
+  catch (...)
+    {
+      // Discard
+    }
+
+  try
+    {
+      next_cases.function2 ();
+    }
+  catch (...)
+    {
+      // Discard
+    }
+
+  try
+    {
+      // This is duplicated so we can next over one but step into
+      // another.
+      next_cases.function2 ();
+    }
+  catch (...)
+    {
+      // Discard
+    }
+
+  next_cases.function3 ();
+
+  try
+    {
+      next_cases.rethrow ();
+    }
+  catch (...)
+    {
+      // Discard
+    }
+
+  try
+    {
+      // Another duplicate so we can test "finish".
+      next_cases.function2 ();
+    }
+  catch (...)
+    {
+      // Discard
+    }
+
+  // Another test for "finish".
+  try
+    {
+      next_cases.finish ();
+    }
+  catch (...)
+    {
+    }
+
+  // Test of "until".
+  try
+    {
+      next_cases.finish ();
+    }
+  catch (...)
+    {
+    }
+
+  // Test of "until" with an argument.
+  try
+    {
+      next_cases.until ();
+    }
+  catch (...)
+    {
+    }
+
+  // Test of "advance".
+  try
+    {
+      next_cases.until ();
+    }
+  catch (...)
+    {
+    }
+}
+
diff --git a/gdb/testsuite/gdb.cp/gdb9593.exp b/gdb/testsuite/gdb.cp/gdb9593.exp
new file mode 100644
index 0000000..ee9aeff
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/gdb9593.exp
@@ -0,0 +1,185 @@
+# Copyright 2008, 2009 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/>.
+
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+if { [skip_cplus_tests] } { continue }
+
+set prms_id 9593
+set bug_id 0
+
+set testfile "gdb9593"
+set srcfile ${testfile}.cc
+set binfile $objdir/$subdir/$testfile
+
+# Create and source the file that provides information about the compiler
+# used to compile the test case.
+if [get_compiler_info ${binfile} "c++"] {
+    untested gdb9593.exp
+    return -1
+}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested gdb9593.exp
+    return -1
+}
+
+# Some targets can't do function calls, so don't even bother with this
+# test.
+if [target_info exists gdb,cannot_call_functions] {
+    setup_xfail "*-*-*" 9593
+    fail "This target can not call functions"
+    continue
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+    perror "couldn't run to main"
+    continue
+} 
+
+# See whether we have the needed unwinder hooks.
+set ok 1
+gdb_test_multiple "print _Unwind_DebugHook" "check for unwinder hook" {
+    -re "= .*_Unwind_DebugHook.*\r\n$gdb_prompt $" {
+	pass "check for unwinder hook"
+    }
+    -re "No symbol .* in current context.\r\n$gdb_prompt $" {
+	# Pass the test so we don't get bogus fails in the results.
+	pass "check for unwinder hook"
+	set ok 0
+    }
+}
+if {!$ok} {
+    untested gdb9593.exp
+    return -1
+}
+
+# See http://sourceware.org/bugzilla/show_bug.cgi?id=9593
+
+gdb_test "next" \
+    ".*catch (...).*" \
+    "next over a throw 1"
+
+gdb_test "next" \
+  ".*next_cases.function2.*" \
+  "next past catch 1"
+
+gdb_test "next" \
+    ".*catch (...).*" \
+    "next over a throw 2"
+
+gdb_test "next" \
+  ".*next_cases.function2.*" \
+  "next past catch 2"
+
+gdb_test "step" \
+  ".*function1().*" \
+  "step into function2 1"
+
+gdb_test "next" \
+    ".*catch (...).*" \
+    "next over a throw 3"
+
+gdb_test "next" \
+  ".*next_cases.function3.*" \
+  "next past catch 3"
+
+gdb_test "next" \
+  ".*next_cases.rethrow.*" \
+    "next over a throw 4"
+
+gdb_test "next" \
+  ".*catch (...).*" \
+  "next over a rethrow"
+
+gdb_test "next" \
+  ".*next_cases.function2.*" \
+  "next after a rethrow"
+
+gdb_test "step" \
+  ".*function1().*" \
+  "step into function2 2"
+
+gdb_test "finish" \
+  ".*catch (...).*" \
+  "finish 1"
+
+gdb_test "next" \
+  ".*next_cases.finish ().*" \
+  "next past catch 4"
+
+gdb_test "step" \
+  ".*function1 ().*" \
+  "step into finish method"
+
+gdb_test "finish" \
+  ".*catch (...).*" \
+  "finish 2"
+
+gdb_test "next" \
+  ".*next_cases.finish ().*" \
+  "next past catch 5"
+
+gdb_test "step" \
+  ".*function1 ().*" \
+  "step into finish, for until"
+
+gdb_test "until" \
+  ".*catch .int x.*" \
+  "until with no argument 1"
+
+set line [gdb_get_line_number "marker for until" $testfile.cc]
+
+gdb_test "until $line" \
+  ".*function1 ().*" \
+  "next past catch 6"
+
+gdb_test "until" \
+  ".*catch (...).*" \
+  "until with no argument 2"
+
+set line [gdb_get_line_number "until here" $testfile.cc]
+
+gdb_test "next" \
+  ".*next_cases.until ().*" \
+  "next past catch 6"
+
+gdb_test "step" \
+  ".*function1 ().*" \
+  "step into until"
+
+gdb_test "until $line" \
+  ".*catch (...).*" \
+  "until-over-throw"
+
+gdb_test "next" \
+  ".*next_cases.until ().*" \
+  "next past catch 7"
+
+gdb_test "step" \
+  ".*function1 ().*" \
+  "step into until, for advance"
+
+gdb_test "advance $line" \
+  ".*catch (...).*" \
+  "advance-over-throw"
diff --git a/gdb/testsuite/gdb.cp/m-static.cc b/gdb/testsuite/gdb.cp/m-static.cc
index 2a0b61c..7f997ef 100644
--- a/gdb/testsuite/gdb.cp/m-static.cc
+++ b/gdb/testsuite/gdb.cp/m-static.cc
@@ -15,6 +15,12 @@ protected:
 
 public:
   gnu_obj_1(antiquities a, long l) {}
+
+  long method ()
+  {
+    static bool svar = true;
+    return key2;
+  }
 };
 
 const bool gnu_obj_1::test;
@@ -70,5 +76,8 @@ int main()
 
   test4.dummy = test4.elsewhere;
   test4.dummy = 0;
-  return test4.dummy;	// breakpoint: constructs-done
+
+  test1.method (); // breakpoint: constructs-done
+
+  return test4.dummy;
 }
diff --git a/gdb/testsuite/gdb.cp/m-static.exp b/gdb/testsuite/gdb.cp/m-static.exp
index f207462..7b4e0ca 100644
--- a/gdb/testsuite/gdb.cp/m-static.exp
+++ b/gdb/testsuite/gdb.cp/m-static.exp
@@ -132,5 +132,10 @@ gdb_test "print test4.nowhere" "field nowhere is nonexistent or has been optimis
 # that GDB's current behavior in such situations is either consistent
 # across platforms or optimal, so I'm not including one now.
 
+# Step into test1.method and examine the method-scoped static.
+# This is a regression test for PR 9708.
+gdb_test "step" "gnu_obj_1::method.*"
+gdb_test "print svar" " = true"
+
 gdb_exit
 return 0
diff --git a/gdb/testsuite/gdb.cp/member-ptr.cc b/gdb/testsuite/gdb.cp/member-ptr.cc
index ffffb4c..b406a59 100644
--- a/gdb/testsuite/gdb.cp/member-ptr.cc
+++ b/gdb/testsuite/gdb.cp/member-ptr.cc
@@ -138,6 +138,7 @@ class Diamond : public Padding, public Left, public Right
 {
 public:
   virtual int vget_base ();
+  int (*func_ptr) (int);
 };
 
 int Diamond::vget_base ()
@@ -145,6 +146,12 @@ int Diamond::vget_base ()
   return this->Left::x + 2000;
 }
 
+int
+func (int x)
+{
+  return 19 + x;
+}
+
 int main ()
 {
   A a;
@@ -162,6 +169,7 @@ int main ()
   int (Diamond::*right_vpmf) ();
   int (Base::*base_vpmf) ();
   int Diamond::*diamond_pmi;
+  int (* Diamond::*diamond_pfunc_ptr) (int);
 
   PMI null_pmi;
   PMF null_pmf;
@@ -179,6 +187,7 @@ int main ()
 
   diamond.Left::x = 77;
   diamond.Right::x = 88;
+  diamond.func_ptr = func;
 
   /* Some valid pointer to members from a base class.  */
   left_pmf = (int (Diamond::*) ()) (int (Left::*) ()) (&Base::get_x);
@@ -193,11 +202,19 @@ int main ()
   /* A pointer to data member from a base class.  */
   diamond_pmi = (int Diamond::*) (int Left::*) &Base::x;
 
+  /* A pointer to data member, where the member is itself a pointer to
+     a function.  */
+  diamond_pfunc_ptr = (int (* Diamond::*) (int)) &Diamond::func_ptr;
+
   null_pmi = NULL;
   null_pmf = NULL;
 
   pmi = NULL; /* Breakpoint 1 here.  */
 
+  // Invalid (uses diamond_pfunc_ptr as a function):
+  // diamond.*diamond_pfunc_ptr (20);
+  (diamond.*diamond_pfunc_ptr) (20);
+
   k = (a.*pmf)(3);
 
   pmi = &A::jj;
diff --git a/gdb/testsuite/gdb.cp/member-ptr.exp b/gdb/testsuite/gdb.cp/member-ptr.exp
index 6832f3b..baf08d7 100644
--- a/gdb/testsuite/gdb.cp/member-ptr.exp
+++ b/gdb/testsuite/gdb.cp/member-ptr.exp
@@ -390,6 +390,33 @@ gdb_test_multiple "print ((int) pmi) == ((char *) &a.j - (char *) & a)" $name {
     }
 }
 
+# Check pointers to data members, which are themselves pointers to
+# functions.  These behave like data members, not like pointers to
+# member functions.
+
+gdb_test "ptype diamond_pfunc_ptr" \
+    "type = int \\(\\*Diamond::\\*\\)\\(int\\)"
+
+gdb_test "ptype diamond.*diamond_pfunc_ptr" \
+    "type = int \\(\\*\\)\\(int\\)"
+
+# This one is invalid; () binds more tightly than .*, so it tries to
+# call the member pointer as a normal pointer-to-function.
+
+gdb_test "print diamond.*diamond_pfunc_ptr (20)" \
+    "Invalid data type for function to be called."
+
+# With parentheses, it is valid.
+
+gdb_test "print (diamond.*diamond_pfunc_ptr) (20)" \
+    "$vhn = 39"
+
+# Make sure that we do not interpret this as either a member pointer
+# call or a member function call.
+
+gdb_test "print diamond.func_ptr (20)" \
+    "$vhn = 39"
+
 # ==========================
 # pointer to member function
 # ==========================
@@ -420,7 +447,7 @@ gdb_test_multiple "ptype pmf" $name {
 
 set name "print pmf"
 gdb_test_multiple "print pmf" $name {
-    -re "$vhn = $hex <A::bar\\(int\\)>\r\n$gdb_prompt $" {
+    -re "$vhn = \\(int \\(A::\\*\\)\\(A \\*, int\\)\\) $hex <A::bar\\(int\\)>\r\n$gdb_prompt $" {
 	pass $name
     }
     -re "$vhn = .*not supported with HP aCC.*\r\n$gdb_prompt $" {
@@ -608,6 +635,9 @@ gdb_test_multiple "print (a.*pmf)(3)" $name {
     }
 }
 
+gdb_test "ptype a.*pmf" "type = int \\(A \\*, int\\)"
+gdb_test "ptype (a.*pmf)(3)" "type = int"
+
 # Print out a pointer to data member which requires looking into
 # a base class.
 gdb_test "print diamond_pmi" "$vhn = &Base::x"
@@ -658,5 +688,5 @@ gdb_test "print null_pmi = &A::j" "$vhn = &A::j"
 gdb_test "print null_pmi = 0" "$vhn = NULL"
 
 gdb_test "print null_pmf" "$vhn = NULL"
-gdb_test "print null_pmf = &A::foo" "$vhn = $hex <A::foo ?\\(int\\)>"
+gdb_test "print null_pmf = &A::foo" "$vhn = \\(int \\(A::\\*\\)\\(A \\*, int\\)\\) $hex <A::foo ?\\(int\\)>"
 gdb_test "print null_pmf = 0" "$vhn = NULL"
diff --git a/gdb/testsuite/gdb.cp/namespace-koenig.cc b/gdb/testsuite/gdb.cp/namespace-koenig.cc
new file mode 100644
index 0000000..3c30cb2
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-koenig.cc
@@ -0,0 +1,232 @@
+namespace A
+{
+  class C
+  {
+  public:
+    static const int x = 11;
+  };
+
+  int
+  first (C c)
+  {
+    return 11;
+  }
+
+  int
+  first (int a, C c)
+  {
+    return 22;
+  }
+
+  int
+  second (int a, int b, C cc, int c, int d)
+  {
+    return 33;
+  }
+
+}
+
+struct B
+{
+  A::C c;
+};
+
+//------------
+
+namespace E
+{
+  class O{};
+  int foo (O o){return 1; }
+  int foo (O o, O o2){return 2; }
+  int foo (O o, O o2, int i){return 3; }
+}
+
+namespace F
+{
+  class O{};
+  int foo (       O fo, ::E::O eo){ return 4;}
+  int foo (int i, O fo, ::E::O eo){ return 5;}
+}
+
+namespace G
+{
+  class O{};
+  int foo (O go, ::F::O fo, ::E::O eo){ return 6; }
+}
+
+//------------
+
+namespace H
+{
+  class O{};
+  int foo (O){ return 7;}
+}
+
+namespace I
+{
+  class O: public H::O {};
+  class X: H::O{};
+}
+
+//------------
+
+namespace J
+{
+  union U{};
+  struct S{};
+  enum E{};
+
+  class A{
+  public:
+    class B{};
+  };
+
+  class C{};
+
+  int foo (U){ return 8;}
+  int foo (S){ return 9;}
+  int foo (E){ return 10;}
+  int foo (A::B){ return 11;}
+  int foo (A*){ return 12;}
+  int foo (A**){ return 13;}
+  int foo (C[]){ return 14;}
+
+}
+//------------
+
+namespace K{
+  class O{};
+
+  int foo(O, int){
+    return 15;
+  }
+
+  int bar(O, int){
+    return 15;
+  }
+}
+
+int foo(K::O, float){
+  return 16;
+}
+
+int bar(K::O, int){
+  return 16;
+}
+//------------
+
+namespace L {
+  namespace A{
+    namespace B{
+    class O {};
+
+    int foo (O){
+      return 17;
+    }
+
+    }
+  }
+}
+
+//------------
+
+namespace M {
+  class O{
+  public:
+    int operator== (int){
+      return 18;
+    }
+
+    int operator== (float){
+      return 19;
+    }
+
+    int operator+ (float){
+      return 22;
+    }
+
+  };
+
+  int operator!= (O, int){
+    return 20;
+  }
+
+  int operator!= (O, double){
+    return 21;
+  }
+
+  int operator+ (O, int){
+    return 23;
+  }
+
+  int operator++ (O){
+    return 24;
+  }
+
+}
+//------------
+int
+main ()
+{
+  A::C c;
+  B b;
+
+  A::first (c);
+  first (0, c);
+  second (0, 0, c, 0, 0);
+  A::first (b.c);
+
+  E::O eo;
+  F::O fo;
+  G::O go;
+
+  foo (eo);
+  foo (eo, eo);
+  foo (eo, eo, 1);
+  foo (fo, eo);
+  foo (1  ,fo, eo);
+  foo (go, fo, eo);
+
+  I::O io;
+  I::X ix;
+
+  foo (io);
+//foo (ix);
+
+  J::U ju;
+  J::S js;
+  J::E je;
+  J::A::B jab;
+  J::A *jap;
+  J::A **japp;
+  J::C jca[3];
+
+  foo (ju);
+  foo (js);
+  foo (je);
+  foo (jab);
+  foo (jap);
+  foo (japp);
+  foo (jca);
+
+  K::O ko;
+  foo (ko, 1);
+  foo (ko, 1.0f);
+  //bar(ko,1);
+
+  L::A::B::O labo;
+  foo (labo);
+
+  M::O o;
+  o == 5;
+  o == 5.0f;
+  o != 5;
+  o != 5.0f;
+  o + 5;
+  o + 5.0f;
+
+  return first (0, c) + foo (eo) +
+         foo (eo, eo) + foo (eo, eo, 1)  +
+         foo (fo, eo) + foo (1  ,fo, eo) +
+         foo (go, fo, eo);
+}
diff --git a/gdb/testsuite/gdb.cp/namespace-koenig.exp b/gdb/testsuite/gdb.cp/namespace-koenig.exp
new file mode 100644
index 0000000..c73e239
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-koenig.exp
@@ -0,0 +1,112 @@
+# Copyright 2008 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/>.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile namespace-koenig
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+# Get things started.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+############################################
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint main"
+    continue
+}
+
+# Test that koenig lookup finds correct function
+gdb_test "p first(c)" "= 11"
+
+# Change the number of parameters and position of
+# the qualifying parameter
+gdb_test "p second(0,0,c,0,0)" "= 33"
+
+# Test that koenig lookup finds correct function
+# even if it is overloaded
+gdb_test "p first(0,c)" "= 22"
+
+# Test that koenig lookup finds correct function
+# when the argument is an expression
+gdb_test "p first(b.c)" "= 11"
+
+# test that resolutions can be made across namespaces
+gdb_test "p foo(eo)"         "= 1"
+gdb_test "p foo(eo, eo)"     "= 2"
+gdb_test "p foo(eo, eo, 1)"  "= 3"
+gdb_test "p foo(fo, eo)"     "= 4"
+gdb_test "p foo(1 ,fo, eo)"  "= 5"
+gdb_test "p foo(go, fo, eo)" "= 6"
+
+#test that gdb fails gracefully
+gdb_test "p fake(eo)" "No symbol \"fake\" in current context."
+
+#test that namespaces of base classes are searched
+gdb_test "p foo(io)" "= 7"
+gdb_test "p foo(ix)" "Cannot resolve function foo to any overloaded instance"
+
+#test for other types
+gdb_test "p foo(ju)" "= 8"
+gdb_test "p foo(js)" "= 9"
+gdb_test "p foo(je)" "= 10"
+
+#test for class members
+setup_xfail "*-*-*"
+gdb_test "p foo(jab)" "= 11"
+
+gdb_test "p foo(jap)" "= 12"
+gdb_test "p foo(japp)" "= 13"
+gdb_test "p foo(jca)" "= 14"
+
+#test overload resolution
+gdb_test "p foo(ko,1)" "= 15"
+gdb_test "p foo(ko,1.0f)" "= 16"
+setup_xfail "*-*-*"
+gdb_test "p bar(ko,1)" "= -1"
+
+#test lookup of objects belonging to nested namespaces
+gdb_test "p foo(labo)" "= 17"
+
+# test lookup of namespace user-defined operators
+# and overload resolution:
+
+# within class
+gdb_test "p o == 5" "= 18"
+gdb_test "p o == 5.0f" "= 19"
+
+# within namespace
+gdb_test "p o != 5" "= 20"
+gdb_test "p o != 5.0f" "= 21"
+
+# across namespace and class
+gdb_test "p o + 5.0f" "= 22"
+gdb_test "p o + 5" "= 23"
+
+gdb_test "p o++" "= 24"
diff --git a/gdb/testsuite/gdb.cp/namespace-multiple-imports.cc b/gdb/testsuite/gdb.cp/namespace-multiple-imports.cc
new file mode 100644
index 0000000..6b180d6
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-multiple-imports.cc
@@ -0,0 +1,20 @@
+namespace A {
+  int x = 11;
+  namespace{
+    int xx = 22;
+  }
+}
+
+using namespace A;
+
+namespace{
+  int xxx = 33;
+};
+
+int main()
+{
+  x;
+  xx;
+  xxx;
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.cp/namespace-multiple-imports.exp b/gdb/testsuite/gdb.cp/namespace-multiple-imports.exp
new file mode 100644
index 0000000..e4bb9f8
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-multiple-imports.exp
@@ -0,0 +1,49 @@
+# Copyright 2008 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/>.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile namespace-multiple-imports
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+# Get things started.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+############################################
+# test printing of namespace imported within
+# the function.
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint main"
+    continue
+}
+
+gdb_test "print x" "\\$\[0-9\].* = 11"
+gdb_test "print xx" "\\$\[0-9\].* = 22"
+gdb_test "print xxx" "\\$\[0-9\].* = 33"
diff --git a/gdb/testsuite/gdb.cp/namespace-nested-imports.cc b/gdb/testsuite/gdb.cp/namespace-nested-imports.cc
new file mode 100644
index 0000000..9723f87
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-nested-imports.cc
@@ -0,0 +1,36 @@
+namespace A
+{
+  namespace B
+  {
+    int ab = 11;
+  }
+}
+
+namespace C
+{
+  namespace D
+  {
+    using namespace A::B;
+
+    int
+    second()
+    {
+      ab;
+      return 0;
+    }
+  }
+
+  int
+  first()
+  {
+    //ab;
+    return D::second();
+  }
+}
+
+int
+main()
+{
+  //ab;
+  return C::first();
+}
diff --git a/gdb/testsuite/gdb.cp/namespace-nested-imports.exp b/gdb/testsuite/gdb.cp/namespace-nested-imports.exp
new file mode 100644
index 0000000..d279fb5
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-nested-imports.exp
@@ -0,0 +1,57 @@
+# Copyright 2008 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/>.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile namespace-nested-imports
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+# Get things started.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+############################################
+if ![runto_main] then {
+    perror "couldn't run to breakpoint main"
+    continue
+}
+
+gdb_test "print ab" "No symbol .* in current context."
+
+############################################
+gdb_breakpoint C::first
+gdb_continue_to_breakpoint "C::first"
+
+gdb_test "print ab" "No symbol .* in current context."
+gdb_test "print C::D::ab" "= 11"
+
+############################################
+gdb_breakpoint C::D::second
+gdb_continue_to_breakpoint "C::D::second"
+
+gdb_test "print ab" "= 11"
diff --git a/gdb/testsuite/gdb.cp/namespace-no-imports.cc b/gdb/testsuite/gdb.cp/namespace-no-imports.cc
new file mode 100644
index 0000000..d1c68ab
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-no-imports.cc
@@ -0,0 +1,37 @@
+
+namespace A
+{
+  int _a = 11;
+
+  namespace B{
+
+    int ab = 22;
+
+    namespace C{
+
+      int abc = 33;
+
+      int second(){
+        return 0;
+      }
+
+    }
+
+    int first(){
+      _a;
+      ab;
+      C::abc;
+      return C::second();
+    }
+  }
+}
+
+
+int
+main()
+{
+  A::_a;
+  A::B::ab;
+  A::B::C::abc;
+  return A::B::first();
+}
diff --git a/gdb/testsuite/gdb.cp/namespace-no-imports.exp b/gdb/testsuite/gdb.cp/namespace-no-imports.exp
new file mode 100644
index 0000000..e508103
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-no-imports.exp
@@ -0,0 +1,76 @@
+# Copyright 2008 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/>.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile namespace-no-imports
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+# Get things started.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+############################################
+if ![runto_main] then {
+    perror "couldn't run to breakpoint main"
+    continue
+}
+
+gdb_test "print A::_a" "= 11"
+gdb_test "print A::B::ab" "= 22"
+gdb_test "print A::B::C::abc" "= 33"
+
+gdb_test "print _a" "No symbol .* in current context."
+gdb_test "print ab" "No symbol .* in current context."
+gdb_test "print abc" "No symbol .* in current context."
+
+############################################
+gdb_breakpoint A::B::first
+gdb_continue_to_breakpoint "A::B::first"
+
+gdb_test "print A::_a" "= 11"
+gdb_test "print A::B::ab" "= 22"
+gdb_test "print A::B::C::abc" "= 33"
+
+gdb_test "print _a" "= 11"
+gdb_test "print ab" "= 22"
+gdb_test "print C::abc" "= 33"
+
+gdb_test "print abc" "No symbol .* in current context."
+
+############################################
+gdb_breakpoint A::B::C::second
+gdb_continue_to_breakpoint "A::B::C::second"
+
+gdb_test "print A::_a" "= 11"
+gdb_test "print A::B::ab" "= 22"
+gdb_test "print A::B::C::abc" "= 33"
+
+gdb_test "print _a" "= 11"
+gdb_test "print ab" "= 22"
+gdb_test "print abc" "= 33"
diff --git a/gdb/testsuite/gdb.cp/namespace-recursive.cc b/gdb/testsuite/gdb.cp/namespace-recursive.cc
new file mode 100644
index 0000000..46d4c18
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-recursive.cc
@@ -0,0 +1,47 @@
+namespace A{
+  int ax = 9;
+}
+
+namespace B{
+  using namespace A;
+}
+
+namespace C{
+  using namespace B;
+}
+
+using namespace C;
+
+//---------------
+namespace D{
+  using namespace D;
+  int dx = 99;
+}
+using namespace D;
+
+//---------------
+namespace{
+  namespace{
+    int xx = 999;
+  }
+}
+
+//---------------
+namespace E{
+  int ex = 9999;
+}
+
+namespace F{
+  namespace FE = E;
+}
+
+namespace G{
+  namespace GF = F;
+}
+
+//----------------
+int main(){
+  using namespace D;
+  namespace GX = G;
+  return ax + dx + xx + G::GF::FE::ex;
+}
diff --git a/gdb/testsuite/gdb.cp/namespace-recursive.exp b/gdb/testsuite/gdb.cp/namespace-recursive.exp
new file mode 100644
index 0000000..5543757
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-recursive.exp
@@ -0,0 +1,75 @@
+# Copyright 2008 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/>.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile namespace-recursive
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+if [get_compiler_info ${binfile}] {
+    return -1;
+}
+
+
+# Get things started.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint main"
+    continue
+}
+
+############################################
+# test printing from namespace imported into
+# imported namespace
+
+gdb_test "print ax" "= 9"
+
+############################################
+# test that gdb can print without falling 
+# into search loop
+
+gdb_test "print dx" "= 99"
+
+############################################
+# test printing from namespace imported into
+# imported namespace where imports are implicit
+# anonymous namespace imports.
+
+gdb_test "print xx" "= 999"
+
+############################################
+# Test printing using recursive namespace
+# aliases.
+
+setup_kfail "gdb/10541" "*-*-*"
+gdb_test "ptype G::GF" "= namespace F"
+
+setup_kfail "gdb/10541" "*-*-*"
+gdb_test "print G::GF::FE::ex" "= 9999"
diff --git a/gdb/testsuite/gdb.cp/namespace-stress-declarations.cc b/gdb/testsuite/gdb.cp/namespace-stress-declarations.cc
new file mode 100644
index 0000000..173e49b
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-stress-declarations.cc
@@ -0,0 +1,93 @@
+int a;
+int b;
+int c;
+int d;
+int e;
+int f;
+int g;
+int h;
+int i;
+int j;
+int k;
+int l;
+int m;
+int n;
+int o;
+int p;
+int q;
+int r;
+int s;
+int t;
+int u;
+int v;
+int w;
+int x;
+int y;
+int z;
+
+namespace A
+{
+  int xyz;
+
+  using ::a;
+  using ::b;
+  using ::c;
+  using ::d;
+  using ::e;
+  using ::f;
+  using ::g;
+  using ::h;
+  using ::i;
+  using ::j;
+  using ::k;
+  using ::l;
+  using ::m;
+  using ::n;
+  using ::o;
+  using ::p;
+  using ::q;
+  using ::r;
+  using ::s;
+  using ::t;
+  using ::u;
+  using ::v;
+  using ::w;
+  using ::x;
+  using ::y;
+  using ::z;
+
+}
+
+using A::a;
+using A::b;
+using A::c;
+using A::d;
+using A::e;
+using A::f;
+using A::g;
+using A::h;
+using A::i;
+using A::j;
+using A::k;
+using A::l;
+using A::m;
+using A::n;
+using A::o;
+using A::p;
+using A::q;
+using A::r;
+using A::s;
+using A::t;
+using A::u;
+using A::v;
+using A::w;
+using A::x;
+using A::y;
+using A::z;
+
+using namespace A;
+
+int main ()
+{
+  return 0;
+}
\ No newline at end of file
diff --git a/gdb/testsuite/gdb.cp/namespace-stress-declarations.exp b/gdb/testsuite/gdb.cp/namespace-stress-declarations.exp
new file mode 100644
index 0000000..f22a14e
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-stress-declarations.exp
@@ -0,0 +1,50 @@
+# Copyright 2008 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/>.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile namespace-stress-declarations
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+if [get_compiler_info ${binfile}] {
+    return -1;
+}
+
+# Get things started.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint main"
+    continue
+}
+
+############################################
+# Test that the search can fail efficiently 
+
+gdb_test "print fakex" "No symbol \"fakex\" in current context."
diff --git a/gdb/testsuite/gdb.cp/namespace-stress.cc b/gdb/testsuite/gdb.cp/namespace-stress.cc
new file mode 100644
index 0000000..f34083e
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-stress.cc
@@ -0,0 +1,60 @@
+
+namespace A{ int x; }
+namespace B{ int x; }
+namespace C{ int x; }
+namespace D{ int x; }
+namespace E{ int x; }
+namespace F{ int x; }
+namespace G{ int x; }
+namespace H{ int x; }
+namespace I{ int x; }
+namespace J{ int x; }
+namespace K{ int x; }
+namespace L{ int x; }
+namespace M{ int x; }
+namespace N{ int x; }
+namespace O{ int x; }
+namespace P{ int x; }
+namespace Q{ int x; }
+namespace R{ int x; }
+namespace S{ int x; }
+namespace T{ int x; }
+namespace U{ int x; }
+namespace V{ int x; }
+namespace W{ int x; }
+namespace X{ int x; }
+namespace Y{ int x; }
+namespace Z{ int x; }
+
+
+int main(){
+
+  using namespace A;
+  using namespace B;
+  using namespace C;
+  using namespace D;
+  using namespace E;
+  using namespace F;
+  using namespace G;
+  using namespace H;
+  using namespace I;
+  using namespace J;
+  using namespace K;
+  using namespace L;
+  using namespace M;
+  using namespace N;
+  using namespace O;
+  using namespace P;
+  using namespace Q;
+  using namespace R;
+  using namespace S;
+  using namespace T;
+  using namespace U;
+  using namespace V;
+  using namespace W;
+  using namespace X;
+  using namespace Y;
+  using namespace Z;
+
+  return 0;
+}
\ No newline at end of file
diff --git a/gdb/testsuite/gdb.cp/namespace-stress.exp b/gdb/testsuite/gdb.cp/namespace-stress.exp
new file mode 100644
index 0000000..1806523
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/namespace-stress.exp
@@ -0,0 +1,50 @@
+# Copyright 2008 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/>.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile namespace-stress
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+if [get_compiler_info ${binfile}] {
+    return -1;
+}
+
+# Get things started.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint main"
+    continue
+}
+
+############################################
+# Test that the search can fail efficiently 
+
+gdb_test "print y" "No symbol \"y\" in current context."
diff --git a/gdb/testsuite/gdb.cp/namespace.exp b/gdb/testsuite/gdb.cp/namespace.exp
index 4362fd8..f7cfd57 100644
--- a/gdb/testsuite/gdb.cp/namespace.exp
+++ b/gdb/testsuite/gdb.cp/namespace.exp
@@ -24,6 +24,7 @@
 # for namespaces.
 # Note: As of 2000-06-03, they passed under g++ - djb
 
+load_lib "cp-support.exp"
 
 if $tracelevel then {
         strace $tracelevel
@@ -241,11 +242,16 @@ gdb_test "ptype E" "type = namespace C::D::E"
 gdb_test "ptype CClass" "type = (class C::CClass \{\r\n  public:|struct C::CClass \{)\r\n    int x;\r\n\}"
 gdb_test "ptype CClass::NestedClass" "type = (class C::CClass::NestedClass \{\r\n  public:|struct C::CClass::NestedClass \{)\r\n    int y;\r\n\}"
 gdb_test "ptype NestedClass" "No symbol \"NestedClass\" in current context."
-setup_kfail "gdb/1448" "*-*-*"
-gdb_test "ptype ::C::CClass" "type = class C::CClass \{\r\n  public:\r\n    int x;\r\n\}"
-setup_kfail "gdb/1448" "*-*-*"
-gdb_test "ptype ::C::CClass::NestedClass" "type = class C::CClass::NestedClass \{\r\n  public:\r\n    int y;\r\n\}"
-setup_kfail "gdb/1448" "*-*-*"
+cp_test_ptype_class \
+	"ptype ::C::CClass" "" "class" "C::CClass" \
+	{
+	    { field public "int x;" }
+	}
+cp_test_ptype_class \
+	"ptype ::C::CClass::NestedClass" "" "class" "C::CClass::NestedClass" \
+	{
+	    { field public "int y;" }
+	}
 gdb_test "ptype ::C::NestedClass" "No symbol \"NestedClass\" in namespace \"C\"."
 gdb_test "ptype C::CClass" "No symbol \"CClass\" in namespace \"C::C\"."
 gdb_test "ptype C::CClass::NestedClass" "No type \"CClass\" within class or namespace \"C::C\"."
@@ -255,8 +261,11 @@ gdb_test "ptype C::NestedClass" "No symbol \"NestedClass\" in namespace \"C::C\"
 
 gdb_test "print cOtherFile" "\\$\[0-9\].* = 316"
 gdb_test "ptype OtherFileClass" "type = (class C::OtherFileClass \{\r\n  public:|struct C::OtherFileClass \{)\r\n    int z;\r\n\}"
-setup_kfail "gdb/1448" "*-*-*"
-gdb_test "ptype ::C::OtherFileClass" "type = class C::OtherFileClass \{\r\n  public:\r\n    int z;\r\n\}"
+cp_test_ptype_class \
+	"ptype ::C::OtherFileClass" "" "class" "C::OtherFileClass" \
+	{
+	    { field public "int z;" }
+	}
 gdb_test "ptype C::OtherFileClass" "No symbol \"OtherFileClass\" in namespace \"C::C\"."
 
 # Some anonymous namespace tests.
diff --git a/gdb/testsuite/gdb.cp/nsusing.exp b/gdb/testsuite/gdb.cp/nsusing.exp
index 72a616e..fd99f87 100644
--- a/gdb/testsuite/gdb.cp/nsusing.exp
+++ b/gdb/testsuite/gdb.cp/nsusing.exp
@@ -30,7 +30,7 @@ if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
 }
 
 if [get_compiler_info ${binfile}] {
-    return -1
+    return -1;
 }
 
 
diff --git a/gdb/testsuite/gdb.cp/overload.exp b/gdb/testsuite/gdb.cp/overload.exp
index ae8fd26..8291022 100644
--- a/gdb/testsuite/gdb.cp/overload.exp
+++ b/gdb/testsuite/gdb.cp/overload.exp
@@ -74,12 +74,12 @@ set re_methods	"${re_methods}${ws}int overload1arg\\((void|)\\);"
 set re_methods	"${re_methods}${ws}int overload1arg\\(char\\);"
 set re_methods	"${re_methods}${ws}int overload1arg\\(signed char\\);"
 set re_methods	"${re_methods}${ws}int overload1arg\\(unsigned char\\);"
-set re_methods	"${re_methods}${ws}int overload1arg\\(short\\);"
-set re_methods	"${re_methods}${ws}int overload1arg\\(unsigned short\\);"
+set re_methods	"${re_methods}${ws}int overload1arg\\(short( int)?\\);"
+set re_methods	"${re_methods}${ws}int overload1arg\\((unsigned short|short unsigned)( int)?\\);"
 set re_methods	"${re_methods}${ws}int overload1arg\\(int\\);"
 set re_methods	"${re_methods}${ws}int overload1arg\\(unsigned int\\);"
-set re_methods	"${re_methods}${ws}int overload1arg\\(long\\);"
-set re_methods	"${re_methods}${ws}int overload1arg\\(unsigned long\\);"
+set re_methods	"${re_methods}${ws}int overload1arg\\(long( int)?\\);"
+set re_methods	"${re_methods}${ws}int overload1arg\\((unsigned long|long unsigned)( int)?\\);"
 set re_methods	"${re_methods}${ws}int overload1arg\\(float\\);"
 set re_methods	"${re_methods}${ws}int overload1arg\\(double\\);"
 set re_methods	"${re_methods}${ws}int overloadfnarg\\((void|)\\);"
diff --git a/gdb/testsuite/gdb.cp/ovldbreak.exp b/gdb/testsuite/gdb.cp/ovldbreak.exp
index 5b06b31..3e47c77 100644
--- a/gdb/testsuite/gdb.cp/ovldbreak.exp
+++ b/gdb/testsuite/gdb.cp/ovldbreak.exp
@@ -127,10 +127,24 @@ proc set_bp_overloaded {name expectedmenu mychoice bpnumber linenumber} {
 }
 
 # This is the expected menu for overload1arg.
-# Note the arg type variations on lines 6 and 13.
+# Note the arg type variations for void and integer types.
 # This accommodates different versions of g++.
 
-set menu_overload1arg "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n\\\[4\\\] foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r\n\\\[5\\\] foo::overload1arg\\(long\\) at.*$srcfile:118\r\n\\\[6\\\] foo::overload1arg\\((unsigned int|unsigned)\\) at.*$srcfile:117\r\n\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n\\\[8\\\] foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r\n\\\[9\\\] foo::overload1arg\\(short\\) at.*$srcfile:114\r\n\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n\\\[13\\\] foo::overload1arg\\((void|)\\) at.*$srcfile:110\r\n> $"
+set    menu_overload1arg "\\\[0\\\] cancel\r\n"
+append menu_overload1arg "\\\[1\\\] all\r\n"
+append menu_overload1arg "\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n"
+append menu_overload1arg "\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n"
+append menu_overload1arg "\\\[4\\\] foo::overload1arg\\((unsigned long|long unsigned)( int)?\\) at.*$srcfile:119\r\n"
+append menu_overload1arg "\\\[5\\\] foo::overload1arg\\(long( int)?\\) at.*$srcfile:118\r\n"
+append menu_overload1arg "\\\[6\\\] foo::overload1arg\\((unsigned int|unsigned)\\) at.*$srcfile:117\r\n"
+append menu_overload1arg "\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n"
+append menu_overload1arg "\\\[8\\\] foo::overload1arg\\((unsigned short|short unsigned)( int)?\\) at.*$srcfile:115\r\n"
+append menu_overload1arg "\\\[9\\\] foo::overload1arg\\(short( int)?\\) at.*$srcfile:114\r\n"
+append menu_overload1arg "\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n"
+append menu_overload1arg "\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n"
+append menu_overload1arg "\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n"
+append menu_overload1arg "\\\[13\\\] foo::overload1arg\\((void|)\\) at.*$srcfile:110\r\n"
+append menu_overload1arg "> $"
 
 # Set multiple-symbols to "ask", to allow us to test the use
 # of the multiple-choice menu when breaking on an overloaded method.
@@ -157,17 +171,17 @@ set_bp_overloaded "foo::overload1arg" "$menu_overload1arg" 13   13 110
 
 gdb_test "info break" \
     "Num     Type\[\t \]+Disp Enb Address\[\t \]+What.*
-\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in main at.*$srcfile:49\r
+\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in main(\\((|void)\\))? at.*$srcfile:49\r
 \[\t \]+breakpoint already hit 1 time\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
-\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(short\\) at.*$srcfile:114\r
-\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r
+\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(short( int)?\\) at.*$srcfile:114\r
+\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned short|short unsigned)( int)?\\) at.*$srcfile:115\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(int\\) at.*$srcfile:116\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned|unsigned int)\\) at.*$srcfile:117\r
-\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(long\\) at.*$srcfile:118\r
-\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r
+\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(long( int)?\\) at.*$srcfile:118\r
+\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned long|long unsigned)( int)?\\) at.*$srcfile:119\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(float\\) at.*$srcfile:120\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(double\\) at.*$srcfile:121\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((void|)\\) at.*$srcfile:110" \
@@ -215,17 +229,17 @@ gdb_expect {
 
 gdb_test "info break" \
     "Num     Type\[\t \]+Disp Enb Address\[\t \]+What.*
-\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in main at.*$srcfile:49\r
+\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in main(\\((|void)\\))? at.*$srcfile:49\r
 \[\t \]+breakpoint already hit 1 time\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
-\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(short\\) at.*$srcfile:114\r
-\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r
+\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(short( int)?\\) at.*$srcfile:114\r
+\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned short|short unsigned)( int)?\\) at.*$srcfile:115\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(int\\) at.*$srcfile:116\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned|unsigned int)\\) at.*$srcfile:117\r
-\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(long\\) at.*$srcfile:118\r
-\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r
+\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(long( int)?\\) at.*$srcfile:118\r
+\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned long|long unsigned)( int)?\\) at.*$srcfile:119\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(float\\) at.*$srcfile:120\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(double\\) at.*$srcfile:121\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((void|)\\) at.*$srcfile:110" \
@@ -296,12 +310,12 @@ gdb_test "info break" \
     "Num     Type\[\t \]+Disp Enb Address\[\t \]+What.*
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(double\\) at.*$srcfile:121\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(float\\) at.*$srcfile:120\r
-\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned long\\) at.*$srcfile:119\r
-\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(long\\) at.*$srcfile:118\r
+\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned long|long unsigned)( int)?\\) at.*$srcfile:119\r
+\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(long( int)?\\) at.*$srcfile:118\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned|unsigned int)\\) at.*$srcfile:117\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(int\\) at.*$srcfile:116\r
-\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned short\\) at.*$srcfile:115\r
-\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(short\\) at.*$srcfile:114\r
+\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned short|short unsigned)( int)?\\) at.*$srcfile:115\r
+\[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(short( int)?\\) at.*$srcfile:114\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
 \[0-9\]+\[\t \]+breakpoint     keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r
diff --git a/gdb/testsuite/gdb.cp/realcpp.cc b/gdb/testsuite/gdb.cp/realcpp.cc
new file mode 100644
index 0000000..8e4f72a
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/realcpp.cc
@@ -0,0 +1,409 @@
+#include <stdlib.h>
+#include <iostream>
+
+// Forward decls
+class base;
+class derived;
+
+// A simple template with specializations
+template <typename T>
+class tclass
+{
+public:
+  void do_something () { } // tclass<T>::do_something
+};
+
+template <>
+void tclass<char>::do_something () { } // tclass<char>::do_something
+
+template <>
+void tclass<int>::do_something () { } // tclass<int>::do_something
+
+template<>
+void tclass<long>::do_something () { } // tclass<long>::do_something
+
+template<>
+void tclass<short>::do_something () { } // tclass<short>::do_something
+
+// A simple template with multiple template parameters
+template <class A, class B, class C, class D, class E>
+void flubber (void) // flubber
+{
+  A a;
+  B b;
+  C c;
+  D d;
+  E e;
+
+  ++a;
+  ++b;
+  ++c;
+  ++d;
+  ++e;
+}
+
+// Some contrived policies
+template <class T>
+struct operation_1
+{
+  static void function (void) { } // operation_1<T>::function
+};
+
+template <class T>
+struct operation_2
+{
+  static void function (void) { } // operation_2<T>::function
+};
+
+template <class T>
+struct operation_3
+{
+  static void function (void) { } // operation_3<T>::function
+};
+
+template <class T>
+struct operation_4
+{
+  static void function (void) { } // operation_4<T>::function
+};
+
+// A policy-based class w/ and w/o default policy
+template <class T, class Policy>
+class policy : public Policy
+{
+public:
+  policy (T obj) : obj_ (obj) { } // policy<T, Policy>::policy
+
+private:
+  T obj_;
+};
+
+template <class T, class Policy = operation_1<T> >
+class policyd : public Policy
+{
+public:
+  policyd (T obj) : obj_ (obj) { } // policyd<T, Policy>::policyd
+  ~policyd (void) { } // policyd<T, Policy>::~policyd
+
+private:
+  T obj_;
+};
+
+typedef policy<int, operation_1<void*> > policy1;
+typedef policy<int, operation_2<void*> > policy2;
+typedef policy<int, operation_3<void*> > policy3;
+typedef policy<int, operation_4<void*> > policy4;
+
+typedef policyd<int> policyd1;
+typedef policyd<long> policyd2;
+typedef policyd<char> policyd3;
+typedef policyd<base> policyd4;
+typedef policyd<tclass<int> > policyd5;
+
+class fluff { };
+static fluff *g_fluff = new fluff ();
+
+class base
+{
+protected:
+  int foo_;
+
+public:
+  base (void) : foo_ (42) { } // base::base(void)
+  base (int foo) : foo_ (foo) { } // base::base(int)
+  ~base (void) { } // base::~base
+
+  // Some overloaded methods
+  int overload (void) const { return 0; } // base::overload(void) const
+  int overload (int i) const { return 1; } // base::overload(int) const
+  int overload (short s) const { return 2; } // base::overload(short) const
+  int overload (long l) const { return 3; } // base::overload(long) const
+  int overload (char* a) const { return 4; } // base::overload(char*) const
+  int overload (base& b) const { return 5; } // base::overload(base&) const
+
+  // Operators
+  int operator+ (base const& o) const // base::operator+
+  { return foo_ + o.foo_; }
+
+  base operator++ (void) // base::operator++
+  { ++foo_; return *this; }
+
+  base operator+=(base const& o) // base::operator+=
+  { foo_ += o.foo_; return *this; }
+
+  int operator- (base const& o) const // base::operator-
+  { return foo_ - o.foo_; }
+
+  base operator-- (void) // base::operator--
+  { --foo_; return *this; }
+
+  base operator-= (base const& o) // base::operator-=
+  { foo_ -= o.foo_; return *this; }
+
+  int operator* (base const& o) const // base::operator*
+  { return foo_ * o.foo_; }
+
+  base operator*= (base const& o) // base::operator*=
+  { foo_ *= o.foo_; return *this; }
+
+  int operator/ (base const& o) const // base::operator/
+  { return foo_ / o.foo_; }
+
+  base operator/= (base const& o) // base::operator/=
+  { foo_ /= o.foo_; return *this; }
+
+  int operator% (base const& o) const // base::operator%
+  { return foo_ % o.foo_; }
+  
+  base operator%= (base const& o) // base::operator%=
+  { foo_ %= o.foo_; return *this; }
+
+  bool operator< (base const& o) const // base::operator<
+  { return foo_ < o.foo_; }
+
+  bool operator<= (base const& o) const // base::operator<=
+  { return foo_ <= o.foo_; }
+
+  bool operator> (base const& o) const // base::operator>
+  { return foo_ > o.foo_; }
+
+  bool operator>= (base const& o) const // base::operator>=
+  { return foo_ >= o.foo_; }
+
+  bool operator!= (base const& o) const // base::operator!=
+  { return foo_ != o.foo_; }
+
+  bool operator== (base const& o) const // base::operator==
+  { return foo_ == o.foo_; }
+
+  bool operator! (void) const // base::operator!
+  { return !foo_; }
+
+  bool operator&& (base const& o) const // base::operator&&
+  { return foo_ && o.foo_; }
+
+  bool operator|| (base const& o) const // base::operator||
+  { return foo_ || o.foo_; }
+
+  int operator<< (int value) const // base::operator<<
+  { return foo_  << value; }
+
+  base operator<<= (int value) // base::operator<<=
+  { foo_ <<= value; return *this; }
+
+  int operator>> (int value) const // base::operator>>
+  { return foo_  >> value; }
+
+  base operator>>= (int value) // base::operator>>=
+  { foo_ >>= value; return *this; }
+
+  int operator~ (void) const // base::operator~
+  { return ~foo_; }
+
+  int operator& (base const& o) const // base::operator&
+  { return foo_ & o.foo_; }
+
+  base operator&= (base const& o) // base::operator&=
+  { foo_ &= o.foo_; return *this; }
+
+  int operator| (base const& o) const // base::operator|
+  { return foo_ | o.foo_; }
+
+  base operator|= (base const& o) // base::operator|=
+  { foo_ |= o.foo_; return *this; }
+  
+  int operator^ (base const& o) const // base::operator^
+  { return foo_ ^ o.foo_; }
+
+  base operator^= (base const& o) // base::operator^=
+  { foo_ ^= o.foo_; return *this; }
+
+  base operator= (base const& o) // base::operator=
+  { foo_ = o.foo_; return *this; }
+
+  void operator() (void) const // base::operator()
+  { return; }
+
+  int operator[] (int idx) const // base::operator[]
+  { return idx; }
+
+  void* operator new (size_t size) throw () // base::operator new
+  { return malloc (size); }
+
+  void operator delete (void* ptr) // base::operator delete
+  { free (ptr); }
+
+  void* operator new[] (size_t size) throw () // base::operator new[]
+  { return malloc (size); }
+
+  void operator delete[] (void* ptr) // base::operator delete[]
+  { free (ptr); }
+
+  base const* operator-> (void) const // base::opeartor->
+  { return this; }
+
+  int operator->* (base const& b) const // base::operator->*
+  {  return foo_ * b.foo_; }
+
+  operator char* () const { return const_cast<char*> ("hello"); } // base::operator char*
+  operator int () const { return 21; } // base::operator int
+  operator fluff* () const { return new fluff (); } // base::operator fluff*
+  operator fluff** () const { return &g_fluff; } // base::operator fluff**
+};
+
+class base1 : public virtual base
+{
+public:
+  base1 (void) : foo_ (21) { } // base1::base1(void)
+  base1 (int a) : foo_(a) { } // base1::base1(int)
+  void a_function (void) const { } // base1::a_function
+
+protected:
+  int foo_;
+};
+
+class base2 : public virtual base
+{
+public:
+  base2 () : foo_ (3) { } // base2::base2
+
+protected:
+  void a_function (void) const { } // base2::a_function
+  int foo_;
+};
+
+class derived : public base1, public base2
+{
+  public:
+  derived(void) : foo_ (4) { } // derived::derived
+  void a_function (void) const // derived::a_function
+  { 
+    this->base1::a_function ();
+    this->base2::a_function ();
+  }
+
+  protected:
+  int foo_;
+};
+
+int
+main (int argc, char* argv[]) // main
+{ // main
+  derived d;
+  void (derived::*pfunc) (void) const = &derived::a_function;
+  (d.*pfunc) ();
+
+  base a (1), b (3), c (8);
+  (void) a.overload ();
+  (void) a.overload (static_cast<int> (0));
+  (void) a.overload (static_cast<short> (0));
+  (void) a.overload (static_cast<long> (0));
+  (void) a.overload (static_cast<char*> (0));
+  (void) a.overload (a);
+
+  int r;
+  r = b + c;
+  ++a;
+  a += b;
+  r = b - c;
+  --a;
+  a -= b;
+  r = b * c;
+  a *= b;
+  r = b / c;
+  a /= b;
+  r = b % c;
+  a %= b;
+  bool x = (b < c);
+  x = (b <= c);
+  x = (b > c);
+  x = (b >= c);
+  x = (b != c);
+  x = (b == c);
+  x = (!b);
+  x = (b && c);
+  x = (b || c);
+  r = b << 2;
+  a <<= 1;
+  r = b >> 2;
+  a >>= 1;
+  r = ~b;
+  r = b & c;
+  a &= c;
+  r = b | c;
+  a |= c;
+  r = b ^ c;
+  a ^= c;
+  a = c;
+  a ();
+  int i = a[3];
+  derived* f = new derived ();
+  derived* g = new derived[3];
+  delete f;
+  delete[] g;
+  a->overload ();
+  r = a->*b;
+
+  tclass<char> char_tclass;
+  tclass<int> int_tclass;
+  tclass<short> short_tclass;
+  tclass<long> long_tclass;
+  tclass<base> base_tclass;
+  char_tclass.do_something ();
+  int_tclass.do_something ();
+  short_tclass.do_something ();
+  long_tclass.do_something ();
+  base_tclass.do_something ();
+
+  flubber<int, int, int, int, int> ();
+  flubber<int, int, int, int, short> ();
+  flubber<int, int, int, int, long> ();
+  flubber<int, int, int, int, char> ();
+  flubber<int, int, int, short, int> ();
+  flubber<int, int, int, short, short> ();
+  flubber<int, int, int, short, long> ();
+  flubber<int, int, int, short, char> ();
+  flubber<int, int, int, long, int> ();
+  flubber<int, int, int, long, short> ();
+  flubber<int, int, int, long, long> ();
+  flubber<int, int, int, long, char> ();
+  flubber<int, int, int, char, int> ();
+  flubber<int, int, int, char, short> ();
+  flubber<int, int, int, char, long> ();
+  flubber<int, int, int, char, char> ();
+  flubber<int, int, short, int, int> ();
+  flubber<int, int, short, int, short> ();
+  flubber<int, int, short, int, long> ();
+  flubber<int, int, short, int, char> ();
+  flubber<int, int, short, short, int> ();
+  flubber<short, int, short, int, short> ();
+  flubber<long, short, long, short, long> ();
+
+  policy1 p1 (1);
+  p1.function ();
+  policy2 p2 (2);
+  p2.function ();
+  policy3 p3 (3);
+  p3.function ();
+  policy4 p4 (4);
+  p4.function ();
+
+  policyd1 pd1 (5);
+  pd1.function ();
+  policyd2 pd2 (6);
+  pd2.function ();
+  policyd3 pd3 (7);
+  pd3.function ();
+  policyd4 pd4 (d);
+  pd4.function ();
+  policyd5 pd5 (int_tclass);
+  pd5.function ();
+
+  base1 b1 (3);
+
+  r = a;
+  char* str = a;
+  fluff* flp = a;
+  fluff** flpp = a;
+}
+
diff --git a/gdb/testsuite/gdb.cp/realcpp.exp b/gdb/testsuite/gdb.cp/realcpp.exp
new file mode 100644
index 0000000..4e92e75
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/realcpp.exp
@@ -0,0 +1,891 @@
+# Copyright 2008 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/>.
+
+# This file is part of the gdb testsuite.
+
+###
+#
+# SOME IMPORTANT NOTES
+#
+###
+
+# The "info func" tests here aren't complete. I've commented them
+# out for now.
+
+# A helper proc which sets a breakpoint at FUNC and attempts to
+# run to the breakpoint.
+proc test_breakpoint {func} {
+    global DEC
+
+    # Restart every time
+    if {![runto_main]} {
+	perror "could not run to main when attempting to break at $func"
+	continue
+    } else {
+	gdb_breakpoint "$func"
+	set i [expr {[string last : $func] + 1}]
+	set efunc [escape [string range $func $i end]]
+	gdb_test "continue" \
+	    "Continuing.\r\n\r\nBreakpoint $DEC+,.*$efunc.*" \
+	    "continue to $func"
+    }
+}
+
+# Escape expect-reserved characters in the string
+proc escape {string} {
+    regsub -all {\*} $string {\*} string
+    regsub -all {\(} $string {\(} string
+    regsub -all {\)} $string {\)} string
+    regsub -all {\]} $string {\]} string
+    regsub -all {\[} $string {\[} string
+    regsub -all {\+} $string {\+} string
+    regsub -all {\^} $string {\^} string
+    regsub -all {\!} $string {\!} string
+    return $string
+}
+
+# Add a function to the list of tested functions
+# FUNC is the name of the function (which will be passed to gdb commands)
+# TYPE is the type of the function, as expected from the "print" command
+# PRINT is the name of the function, as expected result of the print command
+#  *OR* "-", indicating that FUNC should be used (needed for virtual/inherited
+#   funcs)
+# LST is either the expected result of the list command (the comment from
+#  the source code) *OR* "-", in which case FUNC will be used
+# INF is the expected result of "info func"
+#
+# If any of PRINT, LST, or INF is "", the test will be skipped
+#
+# Usage:
+# add NAME TYPE PRINT LST INFO
+# add NAME TYPE PRINT - INFO
+proc add {func type print lst inf} {
+    global all_functions CONVAR ADDR
+
+    set all_functions($func,type) $type
+    if {$print == "-"} {
+	set print $func
+    }
+
+    # An exception: since gdb canonicalizes C++ output,
+    # "(void)" must be mutated to "()".
+    set print [regsub {\(void\)} $print {()}]
+
+    set all_functions($func,print) \
+	"$CONVAR = {[escape $type]} $ADDR <[escape $print].*>"
+    if {$lst == "-"} {
+	set lst "$func"
+    }
+    set all_functions($func,list) ".*// [escape $lst]"
+    set all_functions($func,info_func) $inf
+}
+
+proc get {func cmd} {
+    global all_functions
+    return $all_functions($func,$cmd)
+}
+
+# Returns a list of function names for a given command
+proc get_functions {cmd} {
+    global all_functions
+    set result {}
+    foreach i [array names all_functions *,$cmd] {
+	if {$all_functions($i) != ""} {
+	    set idx [string last , $i]
+	    if {$idx != -1} {
+		lappend result [string range $i 0 [expr {$idx - 1}]]
+	    }
+	}
+    }
+
+    return [lsort $result]
+}
+
+# Some convenience variables for this test
+set DEC {[0-9]}; # a decimal number
+set HEX {[0-9a-fA-F]}; # a hexidecimal number
+set CONVAR "\\\$$DEC+"; # convenience variable regexp
+set ADDR "0x$HEX+"; # address
+
+# An array of functions/methods that we are testing...
+# Each element consists is indexed by NAME,COMMAND, where
+# NAME is the function name and COMMAND is the gdb command that
+# we are testing. The value of the array for any index pair is
+# the expected result of running COMMAND with the NAME as argument.
+# If the value is blank, the test will be skipped for the given function.
+
+# The array holding all functions/methods to test. Valid subindexes
+# are (none need character escaping -- "add" will take care of that):
+
+# add name type print_name list info_func
+# NAME,type: value is type of function 
+# NAME,print: value is print name of function (careful w/inherited/virtual!)
+# NAME,list: value is comment in source code on first line of function
+#   (without the leading "//")
+# NAME,info_func: value is the expected result of "info func"
+array set all_functions {}
+
+# "Normal" functions/methods
+add {main} \
+    {int (int, char **)} \
+    - \
+    - \
+    {int main(int, char **);}
+add {derived::a_function} \
+    {void (const derived * const)} \
+    - \
+    - \
+    {void derived::a_function();}
+add {base1::a_function} \
+    {void (const base1 * const)} \
+    - \
+    - \
+    {void base1::a_function();}
+add {base2::a_function} \
+    {void (const base2 * const)} \
+    - \
+    - \
+    {void base2::a_function();}
+
+# Constructors
+add {derived::derived} \
+    {void (derived * const)} \
+    - \
+    - \
+    {void derived::derived();}
+add {base1::base1(void)} \
+    {void (base1 * const, const void ** const)} \
+    - \
+    - \
+    {void base1::base1();}
+add {base1::base1(int)} \
+    {void (base1 * const, int)} \
+    - \
+    - \
+    {void base1::base1(int);}
+add {base2::base2} \
+    {void (base2 * const, const void ** const)} \
+    - \
+    - \
+    {void base2::base2();}
+add {base::base(void)} \
+    {void (base * const)} \
+    - \
+    - \
+    {void base::base();}
+add {base::base(int)} \
+    {void (base * const, int)} \
+    - \
+    - \
+    {void base::base();}
+
+# Destructors
+add {base::~base} \
+    {void (base * const)} \
+    - \
+    - \
+    {void base::~base();}
+
+# Overloaded methods (all are const -- we try to use the void
+# method with and without specifying "const")
+add {base::overload(void)} \
+    {int (const base * const)} \
+    - \
+    {base::overload(void) const} \
+    {int base::overload() const;}
+add {base::overload(void) const} \
+    {int (const base * const)} \
+    - \
+    {base::overload(void) const} \
+    {int base::overload() const;}
+add {base::overload(int) const} \
+    {int (const base * const, int)} \
+    - \
+    - \
+    {int base::overload(int) const;}
+add {base::overload(short) const} \
+    {int (const base * const, short)} \
+    - \
+    - \
+    {int base::overload(short) const;}
+add {base::overload(long) const} \
+    {int (const base * const, long)} \
+    - \
+    - \
+    {int base::overload(long) const;}
+add {base::overload(char*) const} \
+    {int (const base * const, char *)} \
+    - \
+    - \
+    {int base::overload(char *) const;}
+add {base::overload(base&) const} \
+    {int (const base * const, base &)} \
+    - \
+    - \
+    {int base::overload(base &) const;}
+
+# Operators
+add {base::operator+} \
+    {int (const base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator++} \
+    {base (base * const)} \
+    - \
+    - \
+    -
+add {base::operator+=} \
+    {base (base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator-} \
+    {int (const base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator--} \
+    {base (base * const)} \
+    - \
+    - \
+    -
+add {base::operator-=} \
+    {base (base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator*} \
+    {int (const base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator*=} \
+    {base (base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator/} \
+    {int (const base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator/=} \
+    {base (base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator%} \
+    {int (const base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator%=} \
+    {base (base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator<} \
+    {bool (const base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator<=} \
+    {bool (const base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator>} \
+    {bool (const base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator>=} \
+    {bool (const base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator!=} \
+    {bool (const base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator==} \
+    {bool (const base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator!} \
+    {bool (const base * const)} \
+    - \
+    - \
+    -
+add {base::operator&&} \
+    {bool (const base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator||} \
+    {bool (const base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator<<} \
+    {int (const base * const, int)} \
+    - \
+    - \
+    -
+add {base::operator<<=} \
+    {base (base * const, int)} \
+    - \
+    - \
+    -
+add {base::operator>>} \
+    {int (const base * const, int)} \
+    - \
+    - \
+    -
+add {base::operator>>=} \
+    {base (base * const, int)} \
+    - \
+    - \
+    -
+add {base::operator~} \
+    {int (const base * const)} \
+    - \
+    - \
+    -
+add {base::operator&} \
+    {int (const base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator&=} \
+    {base (base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator|} \
+    {int (const base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator|=} \
+    {base (base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator^} \
+    {int (const base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator^=} \
+    {base (base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator=} \
+    {base (base * const, const base &)} \
+    - \
+    - \
+    -
+add {base::operator()} \
+    {void (const base * const)} \
+    - \
+    - \
+    -
+add {base::operator[]} \
+    {int (const base * const, int)} \
+    - \
+    - \
+    -
+add {base::operator new} \
+    {void *(size_t)} \
+    - \
+    - \
+    -
+add {base::operator delete} \
+    {void (void *)} \
+    - \
+    - \
+    -
+add {base::operator new[]} \
+    {void *(size_t)} \
+    - \
+    - \
+    -
+add {base::operator delete[]} \
+    {void (void *)} \
+    - \
+    - \
+    -
+add {base::operator char*} \
+    {char *(const base * const)} \
+    - \
+    - \
+    -
+add {base::operator fluff*} \
+    {fluff *(const base * const)} \
+    - \
+    - \
+    -
+add {base::operator fluff**} \
+    {fluff **(const base * const)} \
+    - \
+    - \
+    -
+add {base::operator int} \
+    {int (const base * const)} \
+    - \
+    - \
+    -
+
+# Templates
+add {tclass<char>::do_something} \
+    {void (tclass<char> * const)} \
+    - \
+    - \
+    -
+add {tclass<int>::do_something} \
+    {void (tclass<int> * const)} \
+    - \
+    - \
+    -
+add {tclass<long>::do_something} \
+    {void (tclass<long> * const)} \
+    - \
+    - \
+    -
+add {tclass<short>::do_something} \
+    {void (tclass<short> * const)} \
+    - \
+    - \
+    -
+add {tclass<base>::do_something} \
+    {void (tclass<base> * const)} \
+    - \
+    - \
+    -
+add {flubber<int, int, int, int, int>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, int, int, short>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, int, int, long>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, int, int, char>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, int, short, int>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, int, short, short>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, int, short, long>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, int, short, char>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, int, long, int>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, int, long, short>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, int, long, long>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, int, long, char>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, int, char, int>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, int, char, short>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, int, char, long>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, int, char, char>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, short, int, int>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, short, int, short>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, short, int, long>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, short, int, char>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<int, int, short, short, int>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<short, int, short, int, short>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {flubber<long, short, long, short, long>} \
+    {void (void)} \
+    - \
+    flubber \
+    -
+add {tclass<base>::do_something} \
+    {void (tclass<base> * const)} \
+    - \
+    {tclass<T>::do_something} \
+    -
+add {policy1::policy} \
+    {void (policy<int, operation_1<void*> > * const, int)} \
+    {policy<int, operation_1<void*> >::policy} \
+    {policy<T, Policy>::policy} \
+    -
+add {policy2::policy} \
+    {void (policy<int, operation_2<void*> > * const, int)} \
+    {policy<int, operation_2<void*> >::policy} \
+    {policy<T, Policy>::policy} \
+    -
+add {policy3::policy} \
+    {void (policy<int, operation_3<void*> > * const, int)} \
+    {policy<int, operation_3<void*> >::policy} \
+    {policy<T, Policy>::policy} \
+    -
+add {policy4::policy} \
+    {void (policy<int, operation_4<void*> > * const, int)} \
+    {policy<int, operation_4<void*> >::policy} \
+    {policy<T, Policy>::policy} \
+    -
+add {policy1::function} \
+    {void (void)} \
+    {operation_1<void*>::function} \
+    {operation_1<T>::function} \
+    -
+add {policy2::function} \
+    {void (void)} \
+    {operation_2<void*>::function} \
+    {operation_2<T>::function} \
+    -
+add {policy3::function} \
+    {void (void)} \
+    {operation_3<void*>::function} \
+    {operation_3<T>::function} \
+    -
+add {policy4::function} \
+    {void (void)} \
+    {operation_4<void*>::function} \
+    {operation_4<T>::function} \
+    -
+add {policyd<int, operation_1<int> >::policyd} \
+    {void (policyd<int, operation_1<int> > * const, int)} \
+    - \
+    {policyd<T, Policy>::policyd} \
+    -
+add {policyd1::policyd} \
+    {void (policyd<int, operation_1<int> > * const, int)} \
+    {policyd<int, operation_1<int> >::policyd} \
+    {policyd<T, Policy>::policyd} \
+    -
+add {policyd<int, operation_1<int> >::~policyd} \
+    {void (policyd<int, operation_1<int> > * const)} \
+    - \
+    {policyd<T, Policy>::~policyd} \
+    -
+add {policyd1::~policyd} \
+    {void (policyd<int, operation_1<int> > * const)} \
+    {policyd<int, operation_1<int> >::~policyd} \
+    {policyd<T, Policy>::~policyd} \
+    -
+add {policyd<long, operation_1<long> >::policyd} \
+    {void (policyd<long, operation_1<long> > * const, long)} \
+    - \
+    {policyd<T, Policy>::policyd} \
+    -
+add {policyd2::policyd} \
+    {void (policyd<long, operation_1<long> > * const, long)} \
+    {policyd<long, operation_1<long> >::policyd} \
+    {policyd<T, Policy>::policyd} \
+    -
+add {policyd<long, operation_1<long> >::~policyd} \
+    {void (policyd<long, operation_1<long> > * const)} \
+    - \
+    {policyd<T, Policy>::~policyd} \
+    -
+add {policyd2::~policyd} \
+    {void (policyd<long, operation_1<long> > * const)} \
+    {policyd<long, operation_1<long> >::~policyd} \
+    {policyd<T, Policy>::~policyd} \
+    -
+add {policyd<char, operation_1<char> >::policyd} \
+    {void (policyd<char, operation_1<char> > * const, char)} \
+    - \
+    {policyd<T, Policy>::policyd} \
+    -
+add {policyd3::policyd} \
+    {void (policyd<char, operation_1<char> > * const, char)} \
+    {policyd<char, operation_1<char> >::policyd} \
+    {policyd<T, Policy>::policyd} \
+    -
+add {policyd<char, operation_1<char> >::~policyd} \
+    {void (policyd<char, operation_1<char> > * const)} \
+    - \
+    {policyd<T, Policy>::~policyd} \
+    -
+add {policyd3::~policyd} \
+    {void (policyd<char, operation_1<char> > * const)} \
+    {policyd<char, operation_1<char> >::~policyd} \
+    {policyd<T, Policy>::~policyd} \
+    -
+add {policyd<base, operation_1<base> >::policyd} \
+    {void (policyd<base, operation_1<base> > * const, base)} \
+    - \
+    {policyd<T, Policy>::policyd} \
+    -
+add {policyd4::policyd} \
+    {void (policyd<base, operation_1<base> > * const, base)} \
+    {policyd<base, operation_1<base> >::policyd} \
+    {policyd<T, Policy>::policyd} \
+    -
+add {policyd<base, operation_1<base> >::~policyd} \
+    {void (policyd<base, operation_1<base> > * const)} \
+    - \
+    {policyd<T, Policy>::~policyd} \
+    -
+add {policyd4::~policyd} \
+    {void (policyd<base, operation_1<base> > * const)} \
+    {policyd<base, operation_1<base> >::~policyd} \
+    {policyd<T, Policy>::~policyd} \
+    -
+add {policyd<tclass<int>, operation_1<tclass<int> > >::policyd} \
+    {void (policyd<tclass<int>, operation_1<tclass<int> > > * const, tclass<int>)} \
+    - \
+    {policyd<T, Policy>::policyd} \
+    -
+add {policyd5::policyd} \
+    {void (policyd<tclass<int>, operation_1<tclass<int> > > * const, tclass<int>)} \
+    {policyd<tclass<int>, operation_1<tclass<int> > >::policyd} \
+    {policyd<T, Policy>::policyd} \
+    -
+add {policyd<tclass<int>, operation_1<tclass<int> > >::~policyd} \
+    {void (policyd<tclass<int>, operation_1<tclass<int> > > * const)} \
+    - \
+    {policyd<T, Policy>::~policyd} \
+    -
+add {policyd5::~policyd} \
+    {void (policyd<tclass<int>, operation_1<tclass<int> > > * const)} \
+    {policyd<tclass<int>, operation_1<tclass<int> > >::~policyd} \
+    {policyd<T, Policy>::~policyd} \
+    -
+add {policyd<int, operation_1<int> >::function} \
+    {void (void)} \
+    {operation_1<int>::function}\
+    {operation_1<T>::function} \
+    -
+add {policyd1::function} \
+    {void (void)} \
+    {operation_1<int>::function} \
+    {operation_1<T>::function} \
+    -
+add {policyd2::function} \
+    {void (void)} \
+    {operation_1<long>::function} \
+    {operation_1<T>::function} \
+    -
+add {policyd<char, operation_1<char> >::function} \
+    {void (void)} \
+    {operation_1<char>::function} \
+    {operation_1<T>::function} \
+    -
+add {policyd3::function} \
+    {void (void)} \
+    {operation_1<char>::function} \
+    {operation_1<T>::function} \
+    -
+add {policyd<base, operation_1<base> >::function} \
+    {void (void)} \
+    {operation_1<base>::function} \
+    {operation_1<T>::function} \
+    -
+add {policyd4::function} \
+    {void (void)} \
+    {operation_1<base>::function} \
+    {operation_1<T>::function} \
+    -
+add {policyd<tclass<int>, operation_1<tclass<int> > >::function} \
+    {void (void)} \
+    {operation_1<tclass<int> >::function} \
+    {operation_1<T>::function} \
+    -
+add {policyd5::function} \
+    {void (void)} \
+    {operation_1<tclass<int> >::function} \
+    {operation_1<T>::function} \
+    -
+# The below test default template arguments
+add {policyd<int>::policyd} \
+    {void (policyd<int, operation_1<int> > * const, int)} \
+    - \
+    {policyd<T, Policy>::policyd} \
+    -
+add {policyd<long>::policyd} \
+    {void (policyd<long, operation_1<long> > * const, long)} \
+    - \
+    {policyd<T, Policy>::policyd} \
+    -
+add {policyd<char>::policyd} \
+    {void (policyd<char, operation_1<char> > * const, char)} \
+    - \
+    {policyd<T, Policy>::policyd} \
+    -
+add {policyd<base>::policyd} \
+    {void (policyd<base, operation_1<base> > * const, base)} \
+    - \
+    {policyd<T, Policy>::policyd} \
+    -
+add {policyd<tclass<int> >::policyd} \
+    {void (policyd<tclass<int> >, operation_1<tclass<int> > > * const, int)} \
+    - \
+    {policyd<T, Policy>::policyd} \
+    -
+
+# Start the test
+if {$tracelevel} {
+    strace $tracelevel
+}
+
+if {[skip_cplus_tests]} { continue }
+
+#
+# test running programs
+#
+set prms_id 0
+set bug_id 0
+
+set testfile "realcpp"
+set srcfile "${testfile}.cc"
+set binfile [file join $objdir $subdir $testfile]
+
+if  {[gdb_compile [file join $srcdir $subdir $srcfile] $binfile \
+	  executable {debug c++}] != "" } {
+    untested "$testfile.exp"
+    return -1
+}
+
+if {[get_compiler_info $binfile "c++"]} {
+    return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir [file join $srcdir $subdir]
+gdb_load $binfile
+
+# Set the listsize to one. This will help with testing "list".
+gdb_test "set listsize 1"
+
+# "print METHOD"
+foreach name [get_functions print] {
+    gdb_test "print $name" [get $name print] "print $name"
+}
+
+# "list METHOD"
+foreach name [get_functions list] {
+    gdb_test "list $name" [get $name list] "list $name"
+}
+
+# Running to breakpoint -- use any function we can "list"
+foreach name [get_functions list] {
+    # Skip "main", since test_breakpoint uses it
+    if {[string compare $name "main"] != 0} {
+	test_breakpoint $name
+    }
+}
+
+# "info func METHOD"
+if {false} {
+foreach name [get_functions "info_func"] {
+    regsub -all {\*} $name {\*} n
+    regsub -all {\^} $n {\^} n
+    regsub -all {\]} $n {\]} n
+    regsub -all {\[} $n {\[} n
+    gdb_test "info func $n" [get $name info_func] "info func $name"
+}
+}
+
+# What of these is not covered by above?
+# operator-specific tests ('p a + b', 'print cout << "hello"', etc)
+# overloaded operators & ctors
+# operator names with spaces in them (other than delete and new)
+# ptype of classes/templates
+# backtraces
+# printing data members
+# catching, throwing exceptions
+# STL (esp containers and iterators)
+# inheritance tests
+# completion scoping
+
+gdb_exit
+return 0
diff --git a/gdb/testsuite/gdb.cp/shadow.exp b/gdb/testsuite/gdb.cp/shadow.exp
index 1e5e80b..40c35a4 100644
--- a/gdb/testsuite/gdb.cp/shadow.exp
+++ b/gdb/testsuite/gdb.cp/shadow.exp
@@ -85,5 +85,4 @@ gdb_test "print x" "= 55" "Print local x not namespace x"
 gdb_breakpoint [gdb_get_line_number "marker5"]
 gdb_continue_to_breakpoint "marker5"
 
-setup_kfail "gdb/7936" "*-*-*"
 gdb_test "print x" "= 11" "Print imported namespace x"
diff --git a/gdb/testsuite/gdb.cp/shadowing.cc b/gdb/testsuite/gdb.cp/shadowing.cc
new file mode 100644
index 0000000..6d9c2f1
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/shadowing.cc
@@ -0,0 +1,48 @@
+namespace A
+{
+  int x = 11;
+}
+
+int x = 22;
+int y = 0;
+
+class B
+{
+public:
+  int x;
+
+  int
+  func()
+  {
+    x = 33;
+    y+=x; // marker1
+
+      {
+        int x = 44;
+        y+=x; // marker2
+
+          {
+            int x = 55;
+            y+=x; // marker3
+
+              {
+                int z = x; //prevent gcc from optimizing away this scope
+                using namespace A;
+                y+=x; // marker4
+
+                using A::x;
+                y+=x; // marker5
+                
+                return this->x;
+              }
+          }
+      }
+  }
+};
+
+int
+main()
+{
+  B theB;
+  return theB.func();
+}
diff --git a/gdb/testsuite/gdb.cp/shadowing.exp b/gdb/testsuite/gdb.cp/shadowing.exp
new file mode 100644
index 0000000..6922eed
--- /dev/null
+++ b/gdb/testsuite/gdb.cp/shadowing.exp
@@ -0,0 +1,91 @@
+# Copyright 2008 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/>.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+set testfile shadowing
+set srcfile ${testfile}.cc
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug c++}] != "" } {
+    untested "Couldn't compile test program"
+    return -1
+}
+
+if [get_compiler_info ${binfile}] {
+    return -1;
+}
+
+# Get things started.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto_main] then {
+    perror "couldn't run to breakpoint main"
+    continue
+}
+
+############################################
+# Test printing of class variable is not shadowed
+# by global variable
+
+gdb_breakpoint [gdb_get_line_number "marker1"]
+gdb_continue_to_breakpoint "marker1"
+
+gdb_test "print x" "= 33" "Print class x shadowing global x"
+
+
+############################################
+# Test printing local variable is not shadowed
+# by class variable
+
+gdb_breakpoint [gdb_get_line_number "marker2"]
+gdb_continue_to_breakpoint "marker2"
+
+gdb_test "print x" "= 44" "Print local x shadowing class x"
+
+############################################
+# Test inner scope x is printed not outer scope
+
+gdb_breakpoint [gdb_get_line_number "marker3"]
+gdb_continue_to_breakpoint "marker3"
+
+gdb_test "print x" "= 55" "Print inner scope x"
+
+############################################
+# Test printing local variable is not shadowed
+# by namespace variable
+
+gdb_breakpoint [gdb_get_line_number "marker4"]
+gdb_continue_to_breakpoint "marker4"
+
+gdb_test "print x" "= 55" "Print local x not namespace x"
+
+############################################
+# Test imported namespace element is printed
+
+gdb_breakpoint [gdb_get_line_number "marker5"]
+gdb_continue_to_breakpoint "marker5"
+
+if [test_compiler_info gcc-4-3-*] then { setup_xfail *-*-* }
+
+gdb_test "print x" "= 11" "Print imported namespace x"
diff --git a/gdb/testsuite/gdb.cp/userdef.cc b/gdb/testsuite/gdb.cp/userdef.cc
index 338c58a..56a735f 100644
--- a/gdb/testsuite/gdb.cp/userdef.cc
+++ b/gdb/testsuite/gdb.cp/userdef.cc
@@ -311,6 +311,11 @@ public:
   int z;
 };
 
+bool operator== (const Member &m1, const Member &m2)
+{
+  return m1.z == m2.z;
+}
+
 class Container
 {
 public:
@@ -330,8 +335,12 @@ int main (void)
  A1 two(4,5);
  A1 three(0,0);
  Container c;
+ Member mem1, mem2;
  int val;
  
+ mem1.z = 5;
+ mem2.z = 7;
+
  marker1(); // marker1-returns-here
  cout << one; // marker1-returns-here
  cout << two;
diff --git a/gdb/testsuite/gdb.cp/userdef.exp b/gdb/testsuite/gdb.cp/userdef.exp
index 2bbf95e..25cade7 100644
--- a/gdb/testsuite/gdb.cp/userdef.exp
+++ b/gdb/testsuite/gdb.cp/userdef.exp
@@ -113,6 +113,7 @@ gdb_test "print one > two" "\\\$\[0-9\]* = 0\[\r\n\]"
 gdb_test "print one >= two" "\\\$\[0-9\]* = 0\[\r\n\]"
 
 gdb_test "print one == two" "\\\$\[0-9\]* = 0\[\r\n\]"
+gdb_test "print one.operator== (two)" "\\\$\[0-9\]* = 0\[\r\n\]"
 
 gdb_test "print one != two" "\\\$\[0-9\]* = 1\[\r\n\]"
 
@@ -155,5 +156,8 @@ gdb_test "print *c" "\\\$\[0-9\]* = \\(Member &\\) @$hex: {z = .*}"
 gdb_test "print &*c" "\\\$\[0-9\]* = \\(Member \\*\\) $hex"
 gdb_test "ptype &*c" "type = (struct|class) Member {(\[\r\n \]+public:)?\[\r\n \]+int z;\[\r\n\]+} &\\*"
 
+gdb_test "print operator== (mem1, mem2)" " = false"
+gdb_test "print operator== (mem1, mem1)" " = true"
+
 gdb_exit
 return 0
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-aranges.S b/gdb/testsuite/gdb.dwarf2/dw2-aranges.S
new file mode 100644
index 0000000..d5b9ca5
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-aranges.S
@@ -0,0 +1,140 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2004, 2007, 2008, 2009 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 .debug_aranges containing zero address_size.  */
+
+/* Dummy function to provide debug information for.  */
+
+	.text
+.Lbegin_text1:
+	.globl main
+	.type main, %function
+main:
+.Lbegin_main:
+	.int 0
+.Lend_main:
+	.size main, .-main
+.Lend_text1:
+
+/* Debug information */
+
+	.section .debug_info
+.Lcu1_begin:
+	/* CU header */
+	.4byte	.Lcu1_end - .Lcu1_start		/* Length of Compilation Unit */
+.Lcu1_start:
+	.2byte	2				/* DWARF Version */
+	.4byte	.Labbrev1_begin			/* Offset into abbrev section */
+	.byte	4				/* Pointer size */
+
+	/* CU die */
+	.uleb128 1				/* Abbrev: DW_TAG_compile_unit */
+	.4byte	.Lend_text1			/* DW_AT_high_pc */
+	.4byte	.Lbegin_text1			/* DW_AT_low_pc */
+	.ascii	"file1.txt\0"			/* DW_AT_name */
+	.ascii	"GNU C 3.3.3\0"			/* DW_AT_producer */
+	.byte	1				/* DW_AT_language (C) */
+
+	/* main */
+	.uleb128	2			/* Abbrev: DW_TAG_subprogram */
+	.byte		1			/* DW_AT_external */
+	.byte		1			/* DW_AT_decl_file */
+	.byte		2			/* DW_AT_decl_line */
+	.ascii		"main\0"		/* DW_AT_name */
+	.4byte		.Ltype_int-.Lcu1_begin	/* DW_AT_type */
+	.4byte		.Lbegin_main	/* DW_AT_low_pc */
+	.4byte		.Lend_main		/* DW_AT_high_pc */
+	.byte		1			/* DW_AT_frame_base: length */
+	.byte		0x55			/* DW_AT_frame_base: DW_OP_reg5 */
+
+.Ltype_int:
+	.uleb128	3			/* Abbrev: DW_TAG_base_type */
+	.ascii		"int\0"			/* DW_AT_name */
+	.byte		4			/* DW_AT_byte_size */
+	.byte		5			/* DW_AT_encoding */
+
+	.byte		0			/* End of children of CU */
+
+.Lcu1_end:
+
+/* Abbrev table */
+	.section .debug_abbrev
+.Labbrev1_begin:
+	.uleb128	1			/* Abbrev code */
+	.uleb128	0x11			/* DW_TAG_compile_unit */
+	.byte		1			/* has_children */
+	.uleb128	0x12			/* DW_AT_high_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.uleb128	0x11			/* DW_AT_low_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x25			/* DW_AT_producer */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x13			/* DW_AT_language */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	2			/* Abbrev code */
+	.uleb128	0x2e			/* DW_TAG_subprogram */
+	.byte		0			/* has_children */
+	.uleb128	0x3f			/* DW_AT_external */
+	.uleb128	0xc			/* DW_FORM_flag */
+	.uleb128	0x3a			/* DW_AT_decl_file */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x3b			/* DW_AT_decl_line */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x49			/* DW_AT_type */
+	.uleb128	0x13			/* DW_FORM_ref4 */
+	.uleb128	0x11			/* DW_AT_low_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.uleb128	0x12			/* DW_AT_high_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.uleb128	0x40			/* DW_AT_frame_base */
+	.uleb128	0xa			/* DW_FORM_block1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	3			/* Abbrev code */
+	.uleb128	0x24			/* DW_TAG_base_type */
+	.byte		0			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0xb			/* DW_AT_byte_size */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x3e			/* DW_AT_encoding */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+/* aranges table */
+	.section .debug_aranges
+	.long	.Laranges_end - 1f
+1:
+	.2byte	2				/* aranges Version */
+	.4byte	.Lcu1_begin - .debug_info	/* Offset into .debug_info section */
+	/* The GDB crasher is this zero value.  */
+	.byte		0			/* aranges address_size */
+	.byte		0			/* aranges segment_size */
+
+.Laranges_end:
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-aranges.exp b/gdb/testsuite/gdb.dwarf2/dw2-aranges.exp
new file mode 100644
index 0000000..39632d5
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-aranges.exp
@@ -0,0 +1,40 @@
+# Copyright 2004, 2005, 2007, 2008, 2009 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 .debug_aranges containing zero address_size.
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+# For now pick a sampling of likely targets.
+if {![istarget *-*-linux*]
+    && ![istarget *-*-gnu*]
+    && ![istarget *-*-elf*]
+    && ![istarget *-*-openbsd*]
+    && ![istarget arm-*-eabi*]
+    && ![istarget powerpc-*-eabi*]} {
+    return 0  
+}
+
+set testfile "dw2-aranges"
+set srcfile ${testfile}.S
+set binfile ${objdir}/${subdir}/${testfile}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {nodebug}] != "" } {
+    return -1
+}
+
+clean_restart $testfile
+
+# Failed gdb_load would abort the testcase execution earlier.
+pass "file loaded"
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-bound-loclist.S b/gdb/testsuite/gdb.dwarf2/dw2-bound-loclist.S
new file mode 100644
index 0000000..9353698
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-bound-loclist.S
@@ -0,0 +1,176 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2010 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/>.  */
+
+/* Debug information */
+
+/* We will `break *main' at the very first instruction.  */
+#define main_length 1
+
+	.section	.data
+vardata:
+	/* See DW_OP_lit3 + 1 (0-based).  */
+	.string		"seennotseen"
+
+	.section	.debug_info
+.Lcu1_begin:
+	.4byte		.Lcu1_end - .Lcu1_start	/* Length of Compilation Unit */
+.Lcu1_start:
+	.2byte		2			/* DWARF version number */
+	.4byte		.Ldebug_abbrev0		/* Offset Into Abbrev. Section */
+	.byte		4			/* Pointer Size (in bytes) */
+
+	/* CU die */
+	.uleb128	1			/* Abbrev: DW_TAG_compile_unit */
+	.4byte		.Lproducer		/* DW_AT_producer */
+	/* Use C++ to exploit a bug in parsing DW_AT_name "".  */
+	.byte		4			/* DW_AT_language (C++) -  */
+	.4byte		main			/* DW_AT_low_pc */
+	.byte		main_length		/* DW_AT_high_pc */
+
+.Larray_type:
+	.uleb128	2			/* Abbrev: DW_TAG_array_type */
+	.4byte		.Lchar_type-.Lcu1_begin	/* DW_AT_type */
+
+	.uleb128	3			/* Abbrev: DW_TAG_subrange_type */
+	.4byte		.Luint_type-.Lcu1_begin	/* DW_AT_type */
+	.byte		0			/* DW_AT_lower_bound */
+	.4byte		.Llen_var-.Lcu1_begin	/* DW_AT_upper_bound */
+	.byte		0			/* End of children of die */
+
+.Luint_type:
+	.uleb128	4			/* Abbrev: DW_TAG_base_type */
+	.4byte		.Luint_str		/* DW_AT_name */
+	.byte		4			/* DW_AT_byte_size */
+	.byte		7			/* DW_AT_encoding */
+
+.Lchar_type:
+	.uleb128	4			/* Abbrev: DW_TAG_base_type */
+	.4byte		.Lchar_str		/* DW_AT_name */
+	.byte		1			/* DW_AT_byte_size */
+	.byte		6			/* DW_AT_encoding */
+
+.Llen_var:
+	.uleb128	5			/* Abbrev: DW_TAG_variable artificial */
+	.byte		1			/* DW_AT_artificial */
+	.4byte		.Luint_type-.Lcu1_begin	/* DW_AT_type */
+	.4byte		.Llen_loclist-.Lloclist	/* DW_AT_location */
+
+	.uleb128	6			/* Abbrev: DW_TAG_variable DW_FORM_string */
+	.string		"a_string"		/* DW_AT_name */
+	.4byte		.Larray_type-.Lcu1_begin/* DW_AT_type */
+	.byte		2f - 1f			/* DW_AT_location */
+1:	.byte		3			/*   DW_OP_addr */
+	.4byte		vardata			/*   <addr> */
+2:
+
+	.byte		0			/* End of children of CU */
+.Lcu1_end:
+
+	.section	.debug_loc
+.Lloclist:
+.Llen_loclist:
+	.4byte	0			# Location list begin address
+	.4byte	main_length		# Location list end address
+	.value	2f-1f	# Location expression size
+1:	.byte	0x33	# DW_OP_lit3
+	.byte	0x9f	# DW_OP_stack_value
+2:
+	.quad	0x0	# Location list terminator begin (*.LLST2)
+	.quad	0x0	# Location list terminator end (*.LLST2)
+
+	.section .debug_abbrev
+.Ldebug_abbrev0:
+	.uleb128	1			/* Abbrev code */
+	.uleb128	0x11			/* DW_TAG_compile_unit */
+	.byte		0x1			/* has_children */
+	.uleb128	0x25			/* DW_AT_producer */
+	.uleb128	0xe			/* DW_FORM_strp */
+	.uleb128	0x13			/* DW_AT_language */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x11			/* DW_AT_low_pc */
+	.uleb128	0x1			/* DW_FORM_addr */
+	.uleb128	0x12			/* DW_AT_high_pc */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	2			/* Abbrev code */
+	.uleb128	0x1			/* TAG: DW_TAG_array_type */
+	.byte		0x1			/* DW_children_yes */
+	.uleb128	0x49			/* DW_AT_type */
+	.uleb128	0x13			/* DW_FORM_ref4 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	3			/* Abbrev code */
+	.uleb128	0x21			/* DW_TAG_subrange_type */
+	.byte		0x0			/* no children */
+	.uleb128	0x49			/* DW_AT_type */
+	.uleb128	0x13			/* DW_FORM_ref4 */
+	.uleb128	0x22			/* DW_AT_lower_bound */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x2f			/* DW_AT_upper_bound */
+	.uleb128	0x13			/* DW_FORM_ref4 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	4			/* Abbrev code */
+	.uleb128	0x24			/* DW_TAG_base_type */
+	.byte		0x0			/* no_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0xe			/* DW_FORM_strp */
+	.uleb128	0xb			/* DW_AT_byte_size */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x3e			/* DW_AT_encoding */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	5			/* Abbrev code */
+	.uleb128	0x34			/* DW_TAG_variable */
+	.byte		0x0			/* no_children */
+	.uleb128	0x34			/* DW_AT_artificial */
+	.uleb128	0x0c			/* DW_FORM_flag */
+	.uleb128	0x49			/* DW_AT_type */
+	.uleb128	0x13			/* DW_FORM_ref4 */
+	.uleb128	0x02			/* DW_AT_location */
+	.uleb128	0x06			/* DW_FORM_data4 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	6			/* Abbrev code */
+	.uleb128	0x34			/* DW_TAG_variable */
+	.byte		0x0			/* no_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x49			/* DW_AT_type */
+	.uleb128	0x13			/* DW_FORM_ref4 */
+	.uleb128	0x2			/* DW_AT_location */
+	.uleb128	0xa			/* DW_FORM_block1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.byte		0x0			/* Terminator */
+
+/* String table */
+	.section .debug_str
+.Lproducer:
+	.string		"GNU C 3.3.3"
+.Lchar_str:
+	.string		"char"
+.Luint_str:
+	.string		"unsigned int"
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-bound-loclist.exp b/gdb/testsuite/gdb.dwarf2/dw2-bound-loclist.exp
new file mode 100644
index 0000000..28db005
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-bound-loclist.exp
@@ -0,0 +1,48 @@
+# Copyright 2010 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 printing variable with dynamic bounds which reference a different
+# (artificial in the GCC case) variable containing loclist as its location.
+# This testcase uses value (not address) of the referenced variable:
+# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43762
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+# For now pick a sampling of likely targets.
+if {![istarget *-*-linux*]
+    && ![istarget *-*-gnu*]
+    && ![istarget *-*-elf*]
+    && ![istarget *-*-openbsd*]
+    && ![istarget arm-*-eabi*]
+    && ![istarget powerpc-*-eabi*]} {
+    return 0
+}
+
+set testfile dw2-bound-loclist
+if { [prepare_for_testing ${testfile}.exp ${testfile} [list ${testfile}.S main.c] {}] } {
+    return -1
+}
+
+# Verify it behaves at least as an unbound array without inferior.
+
+gdb_test "p a_string" { = 0x[0-9a-f]+ "seennotseen"}
+gdb_test "ptype a_string" {type = char \[\]}
+
+# Not runto_main as dw2-bound-loclist.S handles only the first byte of main.
+if ![runto "*main"] {
+    return -1
+}
+
+gdb_test "p a_string" { = "seen"}
+gdb_test "ptype a_string" {type = char \[4\]}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-empty-namespace.S b/gdb/testsuite/gdb.dwarf2/dw2-empty-namespace.S
new file mode 100644
index 0000000..7b03ff1
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-empty-namespace.S
@@ -0,0 +1,108 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2009 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 G++ 4.1 producing DW_TAG_namespace with DW_AT_name "::".  */
+
+	.data
+var:	.4byte	1
+
+	.section .debug_info
+.Lcu1_begin:
+	/* CU header */
+	.4byte	.Lcu1_end - .Lcu1_start		/* Length of Compilation Unit */
+.Lcu1_start:
+	.2byte	2				/* DWARF Version */
+	.4byte	.Labbrev1_begin			/* Offset into abbrev section */
+	.byte	4				/* Pointer size */
+
+	/* CU die */
+	.uleb128 1				/* Abbrev: DW_TAG_compile_unit */
+	.ascii	"file1.txt\0"			/* DW_AT_name */
+	.ascii	"GNU C 3.3.3\0"			/* DW_AT_producer */
+	.byte	4				/* DW_LANG_C_plus_plus (C++) */
+
+.Ltype_int:
+	.uleb128	2			/* Abbrev: DW_TAG_base_type */
+	.ascii		"int\0"			/* DW_AT_name */
+	.byte		4			/* DW_AT_byte_size */
+	.byte		5			/* DW_AT_encoding */
+
+	.uleb128	3			/* Abbrev: DW_TAG_namespace */
+	.ascii		"::\0"			/* DW_AT_name */
+
+	.uleb128	7			/* Abbrev: DW_TAG_variable (location) */
+	.ascii		"var\0"			/* DW_AT_name */
+	.byte		2f - 1f			/* DW_AT_location */
+1:	.byte		3			/*   DW_OP_addr */
+	.4byte		var			/*   <addr> */
+2:	.4byte		.Ltype_int-.Lcu1_begin	/* DW_AT_type */
+
+	.byte		0			/* End of children of DW_TAG_namespace */
+
+	.byte		0			/* End of children of CU */
+
+.Lcu1_end:
+
+/* Abbrev table */
+	.section .debug_abbrev
+.Labbrev1_begin:
+	.uleb128	1			/* Abbrev code */
+	.uleb128	0x11			/* DW_TAG_compile_unit */
+	.byte		1			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x25			/* DW_AT_producer */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x13			/* DW_AT_language */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	2			/* Abbrev code */
+	.uleb128	0x24			/* DW_TAG_base_type */
+	.byte		0			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0xb			/* DW_AT_byte_size */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.uleb128	0x3e			/* DW_AT_encoding */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	3			/* Abbrev code */
+	.uleb128	0x39			/* DW_TAG_namespace */
+	.byte		1			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	7			/* Abbrev code (location) */
+	.uleb128	0x34			/* DW_TAG_variable */
+	.byte		0			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x2			/* DW_AT_location */
+	.uleb128	0xa			/* DW_FORM_block1 */
+	.uleb128	0x49			/* DW_AT_type */
+	.uleb128	0x13			/* DW_FORM_ref4 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-empty-namespace.exp b/gdb/testsuite/gdb.dwarf2/dw2-empty-namespace.exp
new file mode 100644
index 0000000..1a8da16
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-empty-namespace.exp
@@ -0,0 +1,43 @@
+# Copyright 2009 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 G++ 4.1 producing DW_TAG_namespace with DW_AT_name "::".
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+# For now pick a sampling of likely targets.
+if {![istarget *-*-linux*]
+    && ![istarget *-*-gnu*]
+    && ![istarget *-*-elf*]
+    && ![istarget *-*-openbsd*]
+    && ![istarget arm-*-eabi*]
+    && ![istarget powerpc-*-eabi*]} {
+    return 0  
+}
+
+set testfile "dw2-empty-namespace"
+set srcfile ${testfile}.S
+set executable ${testfile}.x
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objdir}/${subdir}/${executable}" object {nodebug}] != "" } {
+    return -1
+}
+
+clean_restart $executable
+
+# `p var' below can work without identified DWARF DIE just based on its ELF symbol.
+# Catch it here as `type = <data variable, no debug info>'.
+gdb_test "ptype var" "type = int"
+
+gdb_test "p var" " = 1"
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-stripped.c b/gdb/testsuite/gdb.dwarf2/dw2-stripped.c
new file mode 100644
index 0000000..1f02d90
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-stripped.c
@@ -0,0 +1,42 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2004 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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+   USA.  */
+
+
+/* The function `func1' traced into must have debug info on offset > 0;
+   (DW_UNSND (attr)).  This is the reason of `func0' existence.  */
+
+void
+func0(int a, int b)
+{
+}
+
+/* `func1' being traced into must have some arguments to dump.  */
+
+void
+func1(int a, int b)
+{
+  func0 (a,b);
+}
+
+int
+main(void)
+{
+  func1 (1, 2);
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-stripped.exp b/gdb/testsuite/gdb.dwarf2/dw2-stripped.exp
new file mode 100644
index 0000000..1c6e84a
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-stripped.exp
@@ -0,0 +1,79 @@
+# Copyright 2006 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Minimal DWARF-2 unit test
+
+# This test can only be run on targets which support DWARF-2.
+# For now pick a sampling of likely targets.
+if {![istarget *-*-linux*]
+    && ![istarget *-*-gnu*]
+    && ![istarget *-*-elf*]
+    && ![istarget *-*-openbsd*]
+    && ![istarget arm-*-eabi*]
+    && ![istarget powerpc-*-eabi*]} {
+    return 0  
+}
+
+set testfile "dw2-stripped"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}.x
+
+remote_exec build "rm -f ${binfile}"
+
+# get the value of gcc_compiled
+if [get_compiler_info ${binfile}] {
+    return -1
+}
+
+# This test can only be run on gcc as we use additional_flags=FIXME
+if {$gcc_compiled == 0} {
+    return 0
+}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-ggdb3}] != "" } {
+    return -1
+}
+
+remote_exec build "objcopy -R .debug_loc ${binfile}"
+set strip_output [remote_exec build "objdump -h ${binfile}"]
+
+set test "stripping test file preservation"
+if [ regexp ".debug_info " $strip_output]  {
+    pass "$test (.debug_info preserved)"
+} else {
+    fail "$test (.debug_info got also stripped)"
+}
+
+set test "stripping test file functionality"
+if [ regexp ".debug_loc " $strip_output]  {
+    fail "$test (.debug_loc still present)"
+} else {
+    pass "$test (.debug_loc stripped)"
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+# For C programs, "start" should stop in main().
+
+gdb_test "start" \
+         ".*main \\(\\) at .*" \
+         "start"
+gdb_test "step" \
+         "func.* \\(.*\\) at .*" \
+         "step"
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-struct-member-data-location.S b/gdb/testsuite/gdb.dwarf2/dw2-struct-member-data-location.S
new file mode 100644
index 0000000..5fcdd84
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-struct-member-data-location.S
@@ -0,0 +1,83 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2009 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/>.  */
+
+/* Debug information */
+
+	.section .debug_info
+.Lcu1_begin:
+	/* CU header */
+	.4byte	.Lcu1_end - .Lcu1_start		/* Length of Compilation Unit */
+.Lcu1_start:
+	.2byte	2				/* DWARF Version */
+	.4byte	.Labbrev1_begin			/* Offset into abbrev section */
+	.byte	4				/* Pointer size */
+
+	/* CU die */
+	.uleb128 1				/* Abbrev: DW_TAG_compile_unit */
+	.ascii	"dw2-struct-member-data-location.c\0"	/* DW_AT_name */
+	.ascii	"GNU C 4.3.2\0"			/* DW_AT_producer */
+	.byte	1				/* DW_AT_language (C) */
+
+.Ltype_uchar:
+	.uleb128	2			/* Abbrev: DW_TAG_structure_type */
+	.ascii		"some_struct\0"		/* DW_AT_name */
+
+	.uleb128	3			/* Abbrev: DW_TAG_member */
+	.ascii		"field\0"		/* DW_AT_name */
+	.byte		0			/* DW_AT_data_member_location */
+
+	.byte		0			/* End of children of some_struct */
+
+	.byte		0			/* End of children of CU */
+
+.Lcu1_end:
+
+/* Abbrev table */
+	.section .debug_abbrev
+.Labbrev1_begin:
+	.uleb128	1			/* Abbrev code */
+	.uleb128	0x11			/* DW_TAG_compile_unit */
+	.byte		1			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x25			/* DW_AT_producer */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x13			/* DW_AT_language */
+	.uleb128	0xb			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	2			/* Abbrev code */
+	.uleb128	0x13			/* DW_TAG_structure_type */
+	.byte		1			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.uleb128	3			/* Abbrev code */
+	.uleb128	0x0d			/* DW_TAG_member */
+	.byte		0			/* has_children */
+	.uleb128	0x3			/* DW_AT_name */
+	.uleb128	0x8			/* DW_FORM_string */
+	.uleb128	0x38			/* DW_AT_data_member_location */
+	.uleb128	0x0b			/* DW_FORM_data1 */
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
+
+	.byte		0x0			/* Terminator */
+	.byte		0x0			/* Terminator */
diff --git a/gdb/testsuite/gdb.dwarf2/dw2-struct-member-data-location.exp b/gdb/testsuite/gdb.dwarf2/dw2-struct-member-data-location.exp
new file mode 100644
index 0000000..c41151c
--- /dev/null
+++ b/gdb/testsuite/gdb.dwarf2/dw2-struct-member-data-location.exp
@@ -0,0 +1,37 @@
+# Copyright 2009 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/>.
+
+# This test can only be run on targets which support DWARF-2 and use gas.
+# For now pick a sampling of likely targets.
+if {![istarget *-*-linux*]
+    && ![istarget *-*-gnu*]
+    && ![istarget *-*-elf*]
+    && ![istarget *-*-openbsd*]
+    && ![istarget arm-*-eabi*]
+    && ![istarget powerpc-*-eabi*]} {
+    return 0  
+}
+
+set testfile "dw2-struct-member-data-location"
+set srcfile ${testfile}.S
+set binfile ${testfile}.x
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objdir}/${subdir}/${binfile}" object {nodebug}] != "" } {
+    return -1
+}
+
+clean_restart $binfile
+
+gdb_test "ptype struct some_struct" "type = struct some_struct {\[\r\n \t\]*void field;\[\r\n \t\]*}"
diff --git a/gdb/testsuite/gdb.fortran/dwarf-stride.exp b/gdb/testsuite/gdb.fortran/dwarf-stride.exp
new file mode 100644
index 0000000..cd3486b
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/dwarf-stride.exp
@@ -0,0 +1,42 @@
+# Copyright 2009 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+
+# This file was written by Jan Kratochvil <jan.kratochvil@redhat.com>.
+
+# This file is part of the gdb testsuite.  Array element stride must not be
+# specified in the number of elements but in a number of bytes instead.
+# Original problem:
+# (gdb) p c40pt(1)
+# $1 = '0-hello', ' ' <repeats 33 times>
+# (gdb) p c40pt(2)
+# warning: Fortran array stride not divisible by the element size
+
+set testfile dwarf-stride
+set srcfile ${testfile}.f90
+
+if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile} {debug f77}] } {
+    return -1
+}
+
+if ![runto MAIN__] then {
+    perror "couldn't run to breakpoint MAIN__"
+    continue
+}
+
+gdb_breakpoint [gdb_get_line_number "break-here"]
+gdb_continue_to_breakpoint "break-here" ".*break-here.*"
+gdb_test "p c40pt(1)" " = '0-hello.*"
+gdb_test "p c40pt(2)" " = '1-hello.*"
diff --git a/gdb/testsuite/gdb.fortran/dwarf-stride.f90 b/gdb/testsuite/gdb.fortran/dwarf-stride.f90
new file mode 100644
index 0000000..e492b3a
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/dwarf-stride.f90
@@ -0,0 +1,40 @@
+! Copyright 2009 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 2 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, write to the Free Software
+! Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+!
+! File written by Alan Matsuoka.
+
+program repro
+
+  type small_stride
+     character*40 long_string
+     integer      small_pad
+  end type small_stride
+
+  type(small_stride), dimension (20), target :: unpleasant
+  character*40, pointer, dimension(:):: c40pt
+
+  integer i
+
+  do i = 0,19
+     unpleasant(i+1)%small_pad = i+1
+     unpleasant(i+1)%long_string = char (ichar('0') + i) // '-hello'
+  end do
+
+  c40pt => unpleasant%long_string
+
+  print *, c40pt  ! break-here
+
+end program repro
diff --git a/gdb/testsuite/gdb.fortran/dynamic.exp b/gdb/testsuite/gdb.fortran/dynamic.exp
new file mode 100644
index 0000000..0ccebe0
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/dynamic.exp
@@ -0,0 +1,145 @@
+# Copyright 2007 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+
+# This file was written by Jan Kratochvil <jan.kratochvil@redhat.com>.
+
+# This file is part of the gdb testsuite.  It contains tests for dynamically
+# allocated Fortran arrays.
+# It depends on the GCC dynamic Fortran arrays DWARF support:
+# 	http://gcc.gnu.org/bugzilla/show_bug.cgi?id=22244
+
+set testfile "dynamic"
+set srcfile ${testfile}.f90
+set binfile ${objdir}/${subdir}/${testfile}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug f77 quiet}] != "" } {
+    untested "Couldn't compile ${srcfile}"
+    return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto MAIN__] then {
+    perror "couldn't run to breakpoint MAIN__"
+    continue
+}
+
+gdb_breakpoint [gdb_get_line_number "varx-init"]
+gdb_continue_to_breakpoint "varx-init"
+gdb_test "p varx" "\\$\[0-9\]* = <(object|the array) is not allocated>" "p varx unallocated"
+gdb_test "ptype varx" "type = <(object|the array) is not allocated>" "ptype varx unallocated"
+gdb_test "p varx(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "p varx(1,5,17) unallocated"
+gdb_test "p varx(1,5,17)=1" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "p varx(1,5,17)=1 unallocated"
+gdb_test "ptype varx(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "ptype varx(1,5,17) unallocated"
+
+gdb_breakpoint [gdb_get_line_number "varx-allocated"]
+gdb_continue_to_breakpoint "varx-allocated"
+# $1 = (( ( 0, 0, 0, 0, 0, 0) ( 0, 0, 0, 0, 0, 0) --- , 0) ) ( ( 0, 0, ...) ...) ...)
+gdb_test "ptype varx" "type = real(\\(kind=4\\)|\\*4) \\(6,5:15,17:28\\)" "ptype varx allocated"
+# Intel Fortran Compiler 10.1.008 uses -1 there, GCC uses 1.
+gdb_test "p l" "\\$\[0-9\]* = (\\.TRUE\\.|4294967295)" "p l if varx allocated"
+
+gdb_breakpoint [gdb_get_line_number "varx-filled"]
+gdb_continue_to_breakpoint "varx-filled"
+gdb_test "p varx(2, 5, 17)" "\\$\[0-9\]* = 6"
+gdb_test "p varx(1, 5, 17)" "\\$\[0-9\]* = 7"
+gdb_test "p varx(2, 6, 18)" "\\$\[0-9\]* = 8"
+gdb_test "p varx(6, 15, 28)" "\\$\[0-9\]* = 9"
+# The latter one is for the Intel Fortran Compiler 10.1.008 pointer type.
+gdb_test "p varv" "\\$\[0-9\]* = (<(object|the array) is not associated>|.*(Cannot access it|Unable to access the object) because the object is not associated.)" "p varv unassociated"
+gdb_test "ptype varv" "type = (<(object|the array) is not associated>|.*(Cannot access it|Unable to access the object) because the object is not associated.)" "ptype varv unassociated"
+
+gdb_breakpoint [gdb_get_line_number "varv-associated"]
+gdb_continue_to_breakpoint "varv-associated"
+gdb_test "p varx(3, 7, 19)" "\\$\[0-9\]* = 6" "p varx(3, 7, 19) with varv associated"
+gdb_test "p varv(3, 7, 19)" "\\$\[0-9\]* = 6" "p varv(3, 7, 19) associated"
+# Intel Fortran Compiler 10.1.008 uses -1 there, GCC uses 1.
+gdb_test "p l" "\\$\[0-9\]* = (\\.TRUE\\.|4294967295)" "p l if varv associated"
+gdb_test "ptype varx" "type = real(\\(kind=4\\)|\\*4) \\(6,5:15,17:28\\)" "ptype varx with varv associated"
+# Intel Fortran Compiler 10.1.008 uses the pointer type.
+gdb_test "ptype varv" "type = (PTR TO -> \\( )?real(\\(kind=4\\)|\\*4) \\(6,5:15,17:28\\)\\)?" "ptype varv associated"
+
+gdb_breakpoint [gdb_get_line_number "varv-filled"]
+gdb_continue_to_breakpoint "varv-filled"
+gdb_test "p varx(3, 7, 19)" "\\$\[0-9\]* = 10" "p varx(3, 7, 19) with varv filled"
+gdb_test "p varv(3, 7, 19)" "\\$\[0-9\]* = 10" "p varv(3, 7, 19) filled"
+
+gdb_breakpoint [gdb_get_line_number "varv-deassociated"]
+gdb_continue_to_breakpoint "varv-deassociated"
+# The latter one is for the Intel Fortran Compiler 10.1.008 pointer type.
+gdb_test "p varv" "\\$\[0-9\]* = (<(object|the array) is not associated>|.*(Cannot access it|Unable to access the object) because the object is not associated.)" "p varv deassociated"
+gdb_test "ptype varv" "type = (<(object|the array) is not associated>|.*(Cannot access it|Unable to access the object) because the object is not associated.)" "ptype varv deassociated"
+gdb_test "p l" "\\$\[0-9\]* = \\.FALSE\\." "p l if varv deassociated"
+gdb_test "p varv(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not associated\\."
+gdb_test "ptype varv(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not associated\\."
+
+gdb_breakpoint [gdb_get_line_number "varx-deallocated"]
+gdb_continue_to_breakpoint "varx-deallocated"
+gdb_test "p varx" "\\$\[0-9\]* = <(object|the array) is not allocated>" "p varx deallocated"
+gdb_test "ptype varx" "type = <(object|the array) is not allocated>" "ptype varx deallocated"
+gdb_test "p l" "\\$\[0-9\]* = \\.FALSE\\." "p l if varx deallocated"
+gdb_test "p varx(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "p varx(1,5,17) deallocated"
+gdb_test "ptype varx(1,5,17)" "(Cannot access it|Unable to access the object) because the (object|array) is not allocated\\." "ptype varx(1,5,17) deallocated"
+
+gdb_breakpoint [gdb_get_line_number "vary-passed"]
+gdb_continue_to_breakpoint "vary-passed"
+# $1 = (( ( 1, 1, 1, 1, 1, 1) ( 1, 1, 1, 1, 1, 1) --- , 1) ) ( ( 1, 1, ...) ...) ...)
+gdb_test "p vary" "\\$\[0-9\]* = \\(\[()1, .\]*\\)"
+
+gdb_breakpoint [gdb_get_line_number "vary-filled"]
+gdb_continue_to_breakpoint "vary-filled"
+gdb_test "ptype vary" "type = real(\\(kind=4\\)|\\*4) \\(10,10\\)"
+gdb_test "p vary(1, 1)" "\\$\[0-9\]* = 8"
+gdb_test "p vary(2, 2)" "\\$\[0-9\]* = 9"
+gdb_test "p vary(1, 3)" "\\$\[0-9\]* = 10"
+# $1 = (( ( 3, 3, 3, 3, 3, 3) ( 3, 3, 3, 3, 3, 3) --- , 3) ) ( ( 3, 3, ...) ...) ...)
+gdb_test "p varw" "\\$\[0-9\]* = \\(\[()3, .\]*\\)"
+
+gdb_breakpoint [gdb_get_line_number "varw-almostfilled"]
+gdb_continue_to_breakpoint "varw-almostfilled"
+gdb_test "ptype varw" "type = real(\\(kind=4\\)|\\*4) \\(5,4,3\\)"
+gdb_test "p varw(3,1,1)=1" "\\$\[0-9\]* = 1"
+# $1 = (( ( 6, 5, 1, 5, 5, 5) ( 5, 5, 5, 5, 5, 5) --- , 5) ) ( ( 5, 5, ...) ...) ...)
+gdb_test "p varw" "\\$\[0-9\]* = \\( *\\( *\\( *6, *5, *1,\[()5, .\]*\\)" "p varw filled"
+# "up" works with GCC but other Fortran compilers may copy the values into the
+# outer function only on the exit of the inner function.
+# We need both variants as depending on the arch we optionally may still be
+# executing the caller line or not after `finish'.
+gdb_test "finish" ".*(call bar \\(y, x\\)|call foo \\(x, z\\(2:6, 4:7, 6:8\\)\\))"
+gdb_test "p z(2,4,5)" "\\$\[0-9\]* = 3"
+gdb_test "p z(2,4,6)" "\\$\[0-9\]* = 6"
+gdb_test "p z(2,4,7)" "\\$\[0-9\]* = 5"
+gdb_test "p z(4,4,6)" "\\$\[0-9\]* = 1"
+
+gdb_breakpoint [gdb_get_line_number "varz-almostfilled"]
+gdb_continue_to_breakpoint "varz-almostfilled"
+# GCC uses the pointer type here, Intel Fortran Compiler 10.1.008 does not.
+gdb_test "ptype varz" "type = (PTR TO -> \\( )?real(\\(kind=4\\)|\\*4) \\(\\*\\)\\)?"
+# Intel Fortran Compiler 10.1.008 has a bug here - (2:11,7:7)
+# as it produces DW_AT_lower_bound == DW_AT_upper_bound == 7.
+gdb_test "ptype vart" "type = (PTR TO -> \\( )?real(\\(kind=4\\)|\\*4) \\(2:11,7:\\*\\)\\)?"
+gdb_test "p varz" "\\$\[0-9\]* = \\(\\)"
+gdb_test "p vart" "\\$\[0-9\]* = \\(\\)"
+gdb_test "p varz(3)" "\\$\[0-9\]* = 4"
+# maps to foo::vary(1,1)
+gdb_test "p vart(2,7)" "\\$\[0-9\]* = 8"
+# maps to foo::vary(2,2)
+gdb_test "p vart(3,8)" "\\$\[0-9\]* = 9"
+# maps to foo::vary(1,3)
+gdb_test "p vart(2,9)" "\\$\[0-9\]* = 10"
diff --git a/gdb/testsuite/gdb.fortran/dynamic.f90 b/gdb/testsuite/gdb.fortran/dynamic.f90
new file mode 100644
index 0000000..0f43564
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/dynamic.f90
@@ -0,0 +1,98 @@
+! Copyright 2007 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 2 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, write to the Free Software
+! Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+!
+! Ihis file is the Fortran source file for dynamic.exp.
+! Original file written by Jakub Jelinek <jakub@redhat.com>.
+! Modified for the GDB testcase by Jan Kratochvil <jan.kratochvil@redhat.com>.
+
+subroutine baz
+  real, target, allocatable :: varx (:, :, :)
+  real, pointer :: varv (:, :, :)
+  real, target :: varu (1, 2, 3)
+  logical :: l
+  allocate (varx (1:6, 5:15, 17:28))            ! varx-init
+  l = allocated (varx)
+  varx(:, :, :) = 6                             ! varx-allocated
+  varx(1, 5, 17) = 7
+  varx(2, 6, 18) = 8
+  varx(6, 15, 28) = 9
+  varv => varx                                  ! varx-filled
+  l = associated (varv)
+  varv(3, 7, 19) = 10                           ! varv-associated
+  varv => null ()                               ! varv-filled
+  l = associated (varv)
+  deallocate (varx)                             ! varv-deassociated
+  l = allocated (varx)
+  varu(:, :, :) = 10                            ! varx-deallocated
+  allocate (varv (1:6, 5:15, 17:28))
+  l = associated (varv)
+  varv(:, :, :) = 6
+  varv(1, 5, 17) = 7
+  varv(2, 6, 18) = 8
+  varv(6, 15, 28) = 9
+  deallocate (varv)
+  l = associated (varv)
+  varv => varu
+  varv(1, 1, 1) = 6
+  varv(1, 2, 3) = 7
+  l = associated (varv)
+end subroutine baz
+subroutine foo (vary, varw)
+  real :: vary (:, :)
+  real :: varw (:, :, :)
+  vary(:, :) = 4                                ! vary-passed
+  vary(1, 1) = 8
+  vary(2, 2) = 9
+  vary(1, 3) = 10
+  varw(:, :, :) = 5                             ! vary-filled
+  varw(1, 1, 1) = 6
+  varw(2, 2, 2) = 7                             ! varw-almostfilled
+end subroutine foo
+subroutine bar (varz, vart)
+  real :: varz (*)
+  real :: vart (2:11, 7:*)
+  varz(1:3) = 4
+  varz(2) = 5                                   ! varz-almostfilled
+  vart(2,7) = vart(2,7)
+end subroutine bar
+program test
+  interface
+    subroutine foo (vary, varw)
+    real :: vary (:, :)
+    real :: varw (:, :, :)
+    end subroutine
+  end interface
+  interface
+    subroutine bar (varz, vart)
+    real :: varz (*)
+    real :: vart (2:11, 7:*)
+    end subroutine
+  end interface
+  real :: x (10, 10), y (5), z(8, 8, 8)
+  x(:,:) = 1
+  y(:) = 2
+  z(:,:,:) = 3
+  call baz
+  call foo (x, z(2:6, 4:7, 6:8))
+  call bar (y, x)
+  if (x (1, 1) .ne. 8 .or. x (2, 2) .ne. 9 .or. x (1, 2) .ne. 4) call abort
+  if (x (1, 3) .ne. 10) call abort
+  if (z (2, 4, 6) .ne. 6 .or. z (3, 5, 7) .ne. 7 .or. z (2, 4, 7) .ne. 5) call abort
+  if (any (y .ne. (/4, 5, 4, 2, 2/))) call abort
+  call foo (transpose (x), z)
+  if (x (1, 1) .ne. 8 .or. x (2, 2) .ne. 9 .or. x (1, 2) .ne. 4) call abort
+  if (x (3, 1) .ne. 10) call abort
+end
diff --git a/gdb/testsuite/gdb.fortran/library-module-lib.f90 b/gdb/testsuite/gdb.fortran/library-module-lib.f90
new file mode 100644
index 0000000..6369d34
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/library-module-lib.f90
@@ -0,0 +1,28 @@
+! Copyright 2009 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/>.
+
+module lib
+        integer :: var_i = 1
+contains
+        subroutine lib_func
+        if (var_i .ne. 1) call abort
+        var_i = 2
+        end subroutine lib_func
+end module lib
+
+module libmany
+        integer :: var_j = 3
+        integer :: var_k = 4
+end module libmany
diff --git a/gdb/testsuite/gdb.fortran/library-module-main.f90 b/gdb/testsuite/gdb.fortran/library-module-main.f90
new file mode 100644
index 0000000..de63a65
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/library-module-main.f90
@@ -0,0 +1,23 @@
+! Copyright 2009 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/>.
+
+        use lib
+	use libmany, only: var_j
+        if (var_i .ne. 1) call abort
+	call lib_func
+        if (var_i .ne. 2) call abort
+        if (var_j .ne. 3) call abort
+        var_i = var_i                 ! i-is-2
+end
diff --git a/gdb/testsuite/gdb.fortran/library-module.exp b/gdb/testsuite/gdb.fortran/library-module.exp
new file mode 100644
index 0000000..4b4ea4c
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/library-module.exp
@@ -0,0 +1,53 @@
+# Copyright 2009 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/>.
+
+set testfile "library-module"
+set srcfile ${testfile}-main.f90
+set srclibfile ${testfile}-lib.f90
+set libfile ${testfile}-lib.so
+set binfile ${testfile}
+
+# Required for -fPIC by gdb_compile_shlib.
+if [get_compiler_info not-used] {
+   warning "Could not get compiler info"
+   return -1
+}
+
+if  { [gdb_compile_shlib "${srcdir}/${subdir}/${srclibfile}" $objdir/$subdir/$libfile {debug f77}] != "" } {
+    untested "Couldn't compile ${srclibfile}"
+    return -1
+}
+
+# prepare_for_testing cannot be used as linking with $libfile cannot be passed
+# just for the linking phase (and not the source compilation phase).  And any
+# warnings on ignored $libfile abort the process.
+
+if  { [gdb_compile [list $srcdir/$subdir/$srcfile $objdir/$subdir/$libfile] $objdir/$subdir/$binfile executable {debug f77}] != "" } {
+    untested "Couldn't compile ${srcfile}"
+    return -1
+}
+
+clean_restart $binfile
+
+if ![runto MAIN__] then {
+    perror "couldn't run to breakpoint MAIN__"
+    continue
+}
+
+gdb_breakpoint [gdb_get_line_number "i-is-2"]
+gdb_continue_to_breakpoint "i-is-2" ".*i-is-2.*"
+gdb_test "print var_i" " = 2"
+gdb_test "print var_j" " = 3"
+gdb_test "print var_k" "No symbol \"var_k\" in current context\\."
diff --git a/gdb/testsuite/gdb.fortran/module.exp b/gdb/testsuite/gdb.fortran/module.exp
index 0acce4f..5e1034f 100644
--- a/gdb/testsuite/gdb.fortran/module.exp
+++ b/gdb/testsuite/gdb.fortran/module.exp
@@ -15,21 +15,41 @@
 
 set testfile "module"
 set srcfile ${testfile}.f90
-set binfile ${objdir}/${subdir}/${testfile}
 
-if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug f77 quiet}] != "" } {
-    untested "Couldn't compile ${srcfile}"
+if { [prepare_for_testing $testfile.exp $testfile $srcfile {debug f77}] } {
     return -1
 }
 
-gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-gdb_load ${binfile}
-
 if ![runto MAIN__] then {
     perror "couldn't run to breakpoint MAIN__"
     continue
 }
 
-gdb_test "print i" " = 42"
+# Do not use simple single-letter names as GDB would pick up for expectedly
+# nonexisting symbols some static variables from system libraries debuginfos.
+
+gdb_breakpoint [gdb_get_line_number "i-is-1"]
+gdb_continue_to_breakpoint "i-is-1" ".*i-is-1.*"
+gdb_test "print var_i" " = 1" "print var_i value 1"
+
+gdb_breakpoint [gdb_get_line_number "i-is-2"]
+gdb_continue_to_breakpoint "i-is-2" ".*i-is-2.*"
+gdb_test "print var_i" " = 2" "print var_i value 2"
+
+gdb_breakpoint [gdb_get_line_number "a-b-c-d"]
+gdb_continue_to_breakpoint "a-b-c-d" ".*a-b-c-d.*"
+gdb_test "print var_a" "No symbol \"var_a\" in current context\\."
+gdb_test "print var_b" " = 11"
+gdb_test "print var_c" "No symbol \"var_c\" in current context\\."
+gdb_test "print var_d" " = 12"
+gdb_test "print var_i" " = 14" "print var_i value 14"
+
+# Breakpoint would work in language "c".
+gdb_test "show language" {The current source language is "(auto; currently )?fortran".}
+
+# gcc-4.4.2: The main program is always MAIN__ in .symtab so "runto" above
+# works.  But DWARF DW_TAG_subprogram contains the name specified by
+# the "program" Fortran statement.
+if [gdb_breakpoint "module"] {
+    pass "setting breakpoint at module"
+}
diff --git a/gdb/testsuite/gdb.fortran/module.f90 b/gdb/testsuite/gdb.fortran/module.f90
index 81ef376..a8428cb 100644
--- a/gdb/testsuite/gdb.fortran/module.f90
+++ b/gdb/testsuite/gdb.fortran/module.f90
@@ -13,10 +13,39 @@
 ! You should have received a copy of the GNU General Public License
 ! along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-module mod
-        integer :: i = 42
-end module mod
+module mod1
+        integer :: var_i = 1
+end module mod1
 
-        use mod
-        print *, i
+module mod2
+        integer :: var_i = 2
+end module mod2
+
+module modmany
+        integer :: var_a = 10, var_b = 11, var_c = 12, var_i = 14
+end module modmany
+
+        subroutine sub1
+        use mod1
+        if (var_i .ne. 1) call abort
+        var_i = var_i                         ! i-is-1
+        end
+
+        subroutine sub2
+        use mod2
+        if (var_i .ne. 2) call abort
+        var_i = var_i                         ! i-is-2
+        end
+
+        program module
+
+        use modmany, only: var_b, var_d => var_c, var_i
+
+        call sub1
+        call sub2
+
+        if (var_b .ne. 11) call abort
+        if (var_d .ne. 12) call abort
+        if (var_i .ne. 14) call abort
+        var_b = var_b                         ! a-b-c-d
 end
diff --git a/gdb/testsuite/gdb.fortran/string.exp b/gdb/testsuite/gdb.fortran/string.exp
new file mode 100644
index 0000000..b1120c3
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/string.exp
@@ -0,0 +1,59 @@
+# Copyright 2008 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+
+# This file was written by Jan Kratochvil <jan.kratochvil@redhat.com>.
+
+# This file is part of the gdb testsuite.  It contains tests for Fortran
+# strings with dynamic length.
+
+set testfile "string"
+set srcfile ${testfile}.f90
+set binfile ${objdir}/${subdir}/${testfile}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug f77 quiet}] != "" } {
+    untested "Couldn't compile ${srcfile}"
+    return -1
+}
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if ![runto MAIN__] then {
+    perror "couldn't run to breakpoint MAIN__"
+    continue
+}
+
+gdb_breakpoint [gdb_get_line_number "var-init"]
+gdb_continue_to_breakpoint "var-init"
+gdb_test "ptype c" "type = character(\\(kind=1\\)|\\*1)"
+gdb_test "ptype d" "type = character(\\(kind=8\\)|\\*8)"
+gdb_test "ptype e" "type = character(\\(kind=4\\)|\\*4)"
+gdb_test "ptype f" "type = character(\\(kind=4\\)|\\*4) \\(7,8:10\\)"
+gdb_test "ptype *e" "Attempt to take contents of a non-pointer value."
+gdb_test "ptype *f" "type = character(\\(kind=4\\)|\\*4) \\(7\\)"
+gdb_test "p c" "\\$\[0-9\]* = 'c'"
+gdb_test "p d" "\\$\[0-9\]* = 'd       '"
+gdb_test "p e" "\\$\[0-9\]* = 'g   '"
+gdb_test "p f" "\\$\[0-9\]* = \\(\\( 'h   ', 'h   ', 'h   ', 'h   ', 'h   ', 'h   ', 'h   '\\) \\( 'h   ', 'h   ', 'h   ', 'h   ', 'h   ', 'h   ', 'h   '\\) \\( 'h   ', 'h   ', 'h   ', 'h   ', 'h   ', 'h   ', 'h   '\\) \\)"
+gdb_test "p *e" "Attempt to take contents of a non-pointer value."
+gdb_test "p *f" "Attempt to take contents of a non-pointer value."
+
+gdb_breakpoint [gdb_get_line_number "var-finish"]
+gdb_continue_to_breakpoint "var-finish"
+gdb_test "p e" "\\$\[0-9\]* = 'e   '" "p e re-set"
+gdb_test "p f" "\\$\[0-9\]* = \\(\\( 'f   ', 'f   ', 'f   ', 'f   ', 'f   ', 'f   ', 'f   '\\) \\( 'f2  ', 'f   ', 'f   ', 'f   ', 'f   ', 'f   ', 'f   '\\) \\( 'f   ', 'f   ', 'f   ', 'f   ', 'f   ', 'f   ', 'f   '\\) \\)" "p *f re-set"
diff --git a/gdb/testsuite/gdb.fortran/string.f90 b/gdb/testsuite/gdb.fortran/string.f90
new file mode 100644
index 0000000..226dc5d
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/string.f90
@@ -0,0 +1,37 @@
+! Copyright 2008 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 2 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, write to the Free Software
+! Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+!
+! Ihis file is the Fortran source file for dynamic.exp.
+! Original file written by Jakub Jelinek <jakub@redhat.com>.
+! Modified for the GDB testcase by Jan Kratochvil <jan.kratochvil@redhat.com>.
+
+subroutine foo (e, f)
+  character (len=1) :: c
+  character (len=8) :: d
+  character (len=*) :: e
+  character (len=*) :: f (1:7, 8:10)
+  c = 'c'
+  d = 'd'
+  e = 'e'                                       ! var-init
+  f = 'f'
+  f(1,9) = 'f2'
+  c = 'c'                                       ! var-finish
+end subroutine foo
+  character (len=4) :: g, h (1:7, 8:10)
+  g = 'g'
+  h = 'h'
+  call foo (g, h)
+end
diff --git a/gdb/testsuite/gdb.gdb/selftest.exp b/gdb/testsuite/gdb.gdb/selftest.exp
index 9e787f0..5ca15d5 100644
--- a/gdb/testsuite/gdb.gdb/selftest.exp
+++ b/gdb/testsuite/gdb.gdb/selftest.exp
@@ -95,6 +95,10 @@ proc do_steps_and_nexts {} {
 		set description "step over ttyarg initialization"
 		set command "step"
 	    }
+	    -re ".*python_script = 0.*$gdb_prompt $" {
+		set description "step over python_script initialization"
+		set command "step"
+	    }
 	    -re ".*time_at_startup = get_run_time.*$gdb_prompt $" {
 		set description "next over get_run_time and everything it calls"
 		set command "next"
diff --git a/gdb/testsuite/gdb.java/jmain.exp b/gdb/testsuite/gdb.java/jmain.exp
index ab95247..9814921 100644
--- a/gdb/testsuite/gdb.java/jmain.exp
+++ b/gdb/testsuite/gdb.java/jmain.exp
@@ -65,7 +65,7 @@ gdb_test "break jmain.main" "${bpmain}"
 
 # Check that a fully qualified "main" works.
 gdb_load "${binfile}"
-set cmd "break \'${testfile}.main(java.lang.String\[\])\'"
+set cmd "break ${testfile}.main(java.lang.String\[\])"
 set msg $cmd
 gdb_test_multiple $cmd $msg {
     -re "${bpmain}\r\n$gdb_prompt $" {
@@ -79,7 +79,7 @@ gdb_test_multiple $cmd $msg {
 	gdb_test "n" "" ""
 
 	# Check again with a method signature at the end.
-	set cmd "break \'${testfile}.main(java.lang.String\[\])void\'"
+	set cmd "break ${testfile}.main(java.lang.String\[\])void"
 	set msg $cmd
 	gdb_test_multiple $cmd $msg {
 	    -re "${bpmain}\r\n$gdb_prompt $" {
diff --git a/gdb/testsuite/gdb.java/jmisc.exp b/gdb/testsuite/gdb.java/jmisc.exp
index 6f7188d..e3ab657 100644
--- a/gdb/testsuite/gdb.java/jmisc.exp
+++ b/gdb/testsuite/gdb.java/jmisc.exp
@@ -71,8 +71,8 @@ if ![set_lang_java] then {
     # signature.
     runto_main
     set function "${testfile}.main(java.lang.String\[\])"
-    gdb_breakpoint "\'$function\'" { allow-pending }
-    gdb_breakpoint "\'${function}void\'" { allow-pending }
+    gdb_breakpoint "$function" { allow-pending }
+    gdb_breakpoint "${function}void" { allow-pending }
     gdb_continue_to_breakpoint $function
 
     send_gdb "ptype jmisc\n"   
diff --git a/gdb/testsuite/gdb.java/jnpe.exp b/gdb/testsuite/gdb.java/jnpe.exp
new file mode 100644
index 0000000..e71391e
--- /dev/null
+++ b/gdb/testsuite/gdb.java/jnpe.exp
@@ -0,0 +1,77 @@
+# Copyright 2009 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/>.
+
+if $tracelevel then {
+  strace $tracelevel
+}
+
+load_lib "java.exp"
+
+set testfile "jnpe"
+set srcfile ${testfile}.java
+set binfile ${objdir}/${subdir}/${testfile}
+if  { [compile_java_from_source ${srcdir}/$subdir/${srcfile} ${binfile} "-g"] != "" } {
+    untested "Couldn't compile ${srcdir}/$subdir/${srcfile}"
+    return -1
+}
+
+set prms_id 0
+set bug_id 0
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+set line [gdb_get_line_number "break here" $testfile.java]
+gdb_test "break $testfile.java:$line" ""
+
+gdb_test "run" \
+  "// break here.*" \
+  "run java next-over-throw"
+
+# See whether we have the needed unwinder hooks.
+set ok 1
+gdb_test_multiple "print _Unwind_DebugHook" "check for unwinder hook in java" {
+    -re "= .*_Unwind_DebugHook.*\r\n$gdb_prompt $" {
+	pass "check for unwinder hook in java"
+    }
+    -re "No symbol .* in current context.?\r\n$gdb_prompt $" {
+	# Pass the test so we don't get bogus fails in the results.
+	setup_xfail *-*-*
+	fail "check for unwinder hook in java"
+	set ok 0
+    }
+}
+if {!$ok} {
+    untested jnpe.exp
+    return -1
+}
+
+gdb_test "handle SIGSEGV nostop noprint" \
+  "SIGSEGV.*fault" \
+  "disable SIGSEGV for next-over-NPE"
+
+# The line where we stop differ according to gcj; check just we did not already
+# execute the catch point.
+
+gdb_test "next" \
+  "" \
+  "next over NPE"
+
+gdb_breakpoint [gdb_get_line_number "catch point"]
+gdb_continue_to_breakpoint "catch point" ".*// catch point.*"
diff --git a/gdb/testsuite/gdb.java/jnpe.java b/gdb/testsuite/gdb.java/jnpe.java
new file mode 100644
index 0000000..3524830
--- /dev/null
+++ b/gdb/testsuite/gdb.java/jnpe.java
@@ -0,0 +1,38 @@
+// Test next-over-NPE.
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2009 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/>.
+   */
+
+public class jnpe
+{
+  public static String npe ()
+  {
+    return ((Object) null).toString();
+  }
+
+  public static void main (String[] args)
+  {
+    try
+      {
+	System.out.println (npe ()); // break here
+      }
+    catch (NullPointerException n)
+      {
+	System.out.println ("success"); // catch point
+      }
+  }
+}
diff --git a/gdb/testsuite/gdb.java/jprint.exp b/gdb/testsuite/gdb.java/jprint.exp
index 29dbf4b..447ca73 100644
--- a/gdb/testsuite/gdb.java/jprint.exp
+++ b/gdb/testsuite/gdb.java/jprint.exp
@@ -70,8 +70,8 @@ if ![set_lang_java] then {
     # signature.
     runto_main
     set function "${testfile}.main(java.lang.String\[\])"
-    gdb_breakpoint "\'$function\'" { allow-pending }
-    gdb_breakpoint "\'${function}void\'" { allow-pending }
+    gdb_breakpoint "$function" { allow-pending }
+    gdb_breakpoint "${function}void" { allow-pending }
     gdb_continue_to_breakpoint $function
 
     gdb_test "p jvclass.addprint(4,5,6)" "sum is 15\r\n.*" "unambiguous static call"
diff --git a/gdb/testsuite/gdb.opt/array-from-register-func.c b/gdb/testsuite/gdb.opt/array-from-register-func.c
new file mode 100644
index 0000000..729f457
--- /dev/null
+++ b/gdb/testsuite/gdb.opt/array-from-register-func.c
@@ -0,0 +1,22 @@
+/* This file is part of GDB, the GNU debugger.
+
+   Copyright 2009 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 *arr)
+{
+  return arr[0];
+}
diff --git a/gdb/testsuite/gdb.opt/array-from-register.c b/gdb/testsuite/gdb.opt/array-from-register.c
new file mode 100644
index 0000000..3090e7e
--- /dev/null
+++ b/gdb/testsuite/gdb.opt/array-from-register.c
@@ -0,0 +1,28 @@
+/* This file is part of GDB, the GNU debugger.
+
+   Copyright 2009 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/>.  */
+
+extern int func (int *arr);
+
+int
+main (void)
+{
+  int arr[] = { 42 };
+
+  func (arr);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.opt/array-from-register.exp b/gdb/testsuite/gdb.opt/array-from-register.exp
new file mode 100644
index 0000000..f2de718
--- /dev/null
+++ b/gdb/testsuite/gdb.opt/array-from-register.exp
@@ -0,0 +1,33 @@
+# Copyright 2009 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# This file is part of the gdb testsuite.
+
+if { [prepare_for_testing array-from-register.exp "array-from-register"      \
+			  {array-from-register.c array-from-register-func.c} \
+			  {debug optimize=-O2}] } {
+    return -1
+}
+
+if ![runto func] then {
+    return -1
+}
+
+gdb_test "p arr" "\\$\[0-9\]+ = \\(int \\*\\) *0x\[0-9a-f\]+"
+
+# Seen regression:
+# Address requested for identifier "arr" which is in register $rdi
+gdb_test "p arr\[0\]" "\\$\[0-9\]+ = 42"
diff --git a/gdb/testsuite/gdb.opt/fortran-string.exp b/gdb/testsuite/gdb.opt/fortran-string.exp
new file mode 100644
index 0000000..f997eec
--- /dev/null
+++ b/gdb/testsuite/gdb.opt/fortran-string.exp
@@ -0,0 +1,41 @@
+# Copyright 2009 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+
+# This file was written by Jan Kratochvil <jan.kratochvil@redhat.com>.
+
+# Test GDB can cope with Fortran strings having their length present in a CPU
+# register.  With -O0 the string length is passed on the stack.  To make this
+# test meaningful the follow assertion should pass.  It is not being checked
+# here as the "_s" symbol is compiler dependent:
+#   (gdb) info address _s
+#   Symbol "_s" is a variable in register XX.
+
+set test fortran-string
+set srcfile ${test}.f90
+if { [prepare_for_testing ${test}.exp ${test} ${srcfile} {debug f77 additional_flags=-O2}] } {
+    return -1
+}
+
+if ![runto MAIN__] then {
+    perror "couldn't run to breakpoint MAIN__"
+    continue
+}
+
+gdb_breakpoint [gdb_get_line_number "s = s"]
+gdb_continue_to_breakpoint "s = s"
+gdb_test "frame" ".*s='foo'.*"
+gdb_test "ptype s" "type = character\\*3"
+gdb_test "p s" "\\$\[0-9\]* = 'foo'"
diff --git a/gdb/testsuite/gdb.opt/fortran-string.f90 b/gdb/testsuite/gdb.opt/fortran-string.f90
new file mode 100644
index 0000000..e48d520
--- /dev/null
+++ b/gdb/testsuite/gdb.opt/fortran-string.f90
@@ -0,0 +1,28 @@
+! Copyright 2009 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 2 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, write to the Free Software
+! Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+!
+! Ihis file is the Fortran source file for dynamic.exp.
+! Original file written by Jakub Jelinek <jakub@redhat.com>.
+! Modified for the GDB testcase by Jan Kratochvil <jan.kratochvil@redhat.com>.
+
+  subroutine f(s)
+  character*(*) s
+  s = s
+  end
+
+  program main
+  call f ('foo')
+  end
diff --git a/gdb/testsuite/gdb.python/py-cmd.exp b/gdb/testsuite/gdb.python/py-cmd.exp
index 2a3ed0d..ff5de33 100644
--- a/gdb/testsuite/gdb.python/py-cmd.exp
+++ b/gdb/testsuite/gdb.python/py-cmd.exp
@@ -20,36 +20,15 @@ if $tracelevel then {
     strace $tracelevel
 }
 
-# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}...
-# Run a test named NAME, consisting of multiple lines of input.
-# After each input line INPUT, search for result line RESULT.
-# Succeed if all results are seen; fail otherwise.
-proc gdb_py_test_multiple {name args} {
-    global gdb_prompt
-    foreach {input result} $args {
-	if {[gdb_test_multiple $input "$name - $input" {
-	    -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
-		pass "$name - $input"
-	    }
-	}]} {
-	    return 1
-	}
-    }
-    return 0
-}
-
 # Start with a fresh gdb.
 
 gdb_exit
 gdb_start
 gdb_reinitialize_dir $srcdir/$subdir
 
-gdb_test_multiple "python print 'hello, world!'" "verify python support" {
-    -re "not supported.*$gdb_prompt $"	{
-      unsupported "python support is disabled"
-      return -1
-    }
-    -re "$gdb_prompt $"	{}
+if ![python_supported] then {
+  unsupported "python support is disabled"
+  return -1
 }
 
 # Test a simple command.
diff --git a/gdb/testsuite/gdb.python/py-frame.exp b/gdb/testsuite/gdb.python/py-frame.exp
index 86fe660..4c7295f 100644
--- a/gdb/testsuite/gdb.python/py-frame.exp
+++ b/gdb/testsuite/gdb.python/py-frame.exp
@@ -20,40 +20,28 @@ if $tracelevel then {
     strace $tracelevel
 }
 
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+if ![python_supported] then {
+  unsupported "python support is disabled"
+  return -1
+}
+
 set testfile "py-frame"
 set srcfile ${testfile}.c
 set binfile ${objdir}/${subdir}/${testfile}
+
 if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
     untested "Couldn't compile ${srcfile}"
     return -1
 }
 
-# Run a command in GDB, and report a failure if a Python exception is thrown.
-# If report_pass is true, report a pass if no exception is thrown.
-proc gdb_py_test_silent_cmd {cmd name report_pass} {
-  global gdb_prompt
-
-  gdb_test_multiple $cmd $name {
-      -re "Traceback.*$gdb_prompt $"  { fail $name }
-      -re "$gdb_prompt $"	      { if $report_pass { pass $name } }
-  }
-}
-
-# Start with a fresh gdb.
-
-gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
 gdb_load ${binfile}
 
-gdb_test_multiple "python print 'hello, world!'" "verify python support" {
-    -re "not supported.*$gdb_prompt $"	{
-      unsupported "python support is disabled"
-      return -1
-    }
-    -re "$gdb_prompt $"	{}
-}
-
 # The following tests require execution.
 
 if ![runto_main] then {
@@ -65,19 +53,20 @@ gdb_breakpoint "f2"
 gdb_continue_to_breakpoint "breakpoint at f2"
 gdb_test "up" "" ""
 
-gdb_py_test_silent_cmd "python f1 = gdb.selected_frame ()" "get second frame" 0
-gdb_py_test_silent_cmd "python f0 = f1.newer ()" "get first frame" 0
+gdb_py_test_silent_cmd "python frames = gdb.selected_thread ().frames ()" "get frames list" 1
+gdb_test "python print frames" "\\(<gdb.Frame object at 0x\[\[:xdigit:\]\]+>, <gdb.Frame object at 0x\[\[:xdigit:\]\]+>, <gdb.Frame object at 0x\[\[:xdigit:\]\]+>\\)" "verify frames list"
+gdb_py_test_silent_cmd "python f0 = frames\[0\]" "get first frame" 0
+gdb_py_test_silent_cmd "python f1 = frames\[1\]" "get second frame" 0
 
 gdb_test "python print 'result =', f0 == f1" " = False" "test equality comparison (false)"
 gdb_test "python print 'result =', f0 == f0" " = True" "test equality comparison (true)"
-gdb_test "python print 'result =', f0 != f1" " = True" "test inequality comparison (true)"
-gdb_test "python print 'result =', f0 != f0" " = False" "test inequality comparison (false)"
 gdb_test "python print 'result =', f0.is_valid ()" " = True" "test Frame.is_valid"
 gdb_test "python print 'result =', f0.name ()" " = f2" "test Frame.name"
 gdb_test "python print 'result =', f0.type () == gdb.NORMAL_FRAME" " = True" "test Frame.type"
 gdb_test "python print 'result =', f0.unwind_stop_reason () == gdb.FRAME_UNWIND_NO_REASON" " = True" "test Frame.type"
 gdb_test "python print 'result =', gdb.frame_stop_reason_string (gdb.FRAME_UNWIND_INNER_ID)" " = previous frame inner to this frame \\(corrupt stack\\?\\)" "test gdb.frame_stop_reason_string"
 gdb_test "python print 'result =', f0.pc ()" " = \[0-9\]+" "test Frame.pc"
+gdb_test "python print 'result =', f0.function ()" " = symbol for f2" "test Frame.function"
 gdb_test "python print 'result =', f0.older () == f1" " = True" "test Frame.older"
 gdb_test "python print 'result =', f1.newer () == f0" " = True" "test Frame.newer"
 gdb_test "python print 'result =', f0.read_var ('variable_which_surely_doesnt_exist')" \
@@ -85,4 +74,7 @@ gdb_test "python print 'result =', f0.read_var ('variable_which_surely_doesnt_ex
   "test Frame.read_var - error"
 gdb_test "python print 'result =', f0.read_var ('a')" " = 1" "test Frame.read_var - success"
 
+gdb_test "python print 'result =', gdb.selected_thread ().newest_frame () == f0" " = True" "test gdb.newest_frame"
 gdb_test "python print 'result =', gdb.selected_frame () == f1" " = True" "test gdb.selected_frame"
+
+gdb_test "python print 'result =', f0.block ()" "<gdb.Block object at 0x\[\[:xdigit:\]\]+>" "test Frame.block"
diff --git a/gdb/testsuite/gdb.python/py-function.exp b/gdb/testsuite/gdb.python/py-function.exp
index 461295d..ea33596 100644
--- a/gdb/testsuite/gdb.python/py-function.exp
+++ b/gdb/testsuite/gdb.python/py-function.exp
@@ -20,36 +20,15 @@ if $tracelevel then {
     strace $tracelevel
 }
 
-# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}...
-# Run a test named NAME, consisting of multiple lines of input.
-# After each input line INPUT, search for result line RESULT.
-# Succeed if all results are seen; fail otherwise.
-proc gdb_py_test_multiple {name args} {
-    global gdb_prompt
-    foreach {input result} $args {
-	if {[gdb_test_multiple $input "$name - $input" {
-	    -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
-		pass "$name - $input"
-	    }
-	}]} {
-	    return 1
-	}
-    }
-    return 0
-}
-
 # Start with a fresh gdb.
 
 gdb_exit
 gdb_start
 gdb_reinitialize_dir $srcdir/$subdir
 
-gdb_test_multiple "python print 'hello, world!'" "verify python support" {
-    -re "not supported.*$gdb_prompt $"	{
-      unsupported "python support is disabled"
-      return -1
-    }
-    -re "$gdb_prompt $"	{}
+if ![python_supported] then {
+  unsupported "python support is disabled"
+  return -1
 }
 
 gdb_py_test_multiple "input convenience function" \
diff --git a/gdb/testsuite/gdb.python/py-inferior.c b/gdb/testsuite/gdb.python/py-inferior.c
new file mode 100644
index 0000000..0b48299
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-inferior.c
@@ -0,0 +1,49 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+
+#define CHUNK_SIZE 16000 /* same as findcmd.c's */
+#define BUF_SIZE (2 * CHUNK_SIZE) /* at least two chunks */
+
+static int8_t int8_search_buf[100];
+static int16_t int16_search_buf[100];
+static int32_t int32_search_buf[100];
+static int64_t int64_search_buf[100];
+
+static char *search_buf;
+static int search_buf_size;
+
+static int x;
+
+
+int f2 (int a)
+{
+  char *str = "hello, testsuite";
+
+  puts (str);	/* Break here.  */
+
+  return ++a;
+}
+
+int f1 (int a, int b)
+{
+  return f2(a) + b;
+}
+
+static void
+init_bufs ()
+{
+  search_buf_size = BUF_SIZE;
+  search_buf = malloc (search_buf_size);
+  if (search_buf == NULL)
+    exit (1);
+  memset (search_buf, 'x', search_buf_size);
+}
+
+int main (int argc, char *argv[])
+{
+  init_bufs ();
+
+  return f1 (1, 2);
+}
diff --git a/gdb/testsuite/gdb.python/py-inferior.exp b/gdb/testsuite/gdb.python/py-inferior.exp
new file mode 100644
index 0000000..719b178
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-inferior.exp
@@ -0,0 +1,201 @@
+# Copyright (C) 2009 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/>.
+
+# This file is part of the GDB testsuite.  It tests the mechanism
+# exposing inferiors to Python.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+if ![python_supported] then {
+  unsupported "python support is disabled"
+  return -1
+}
+
+set testfile "py-inferior"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+    untested "Couldn't compile ${srcfile}"
+    return -1
+}
+
+gdb_load ${binfile}
+
+# The following tests require execution.
+
+if ![runto_main] then {
+    fail "Can't run to main"
+    return 0
+}
+
+runto [gdb_get_line_number "Break here."]
+
+# Test basic gdb.Inferior attributes and methods.
+
+gdb_py_test_silent_cmd "python inferiors = gdb.inferiors ()" "get inferiors list" 1
+gdb_test "python print inferiors" "\\(<gdb.Inferior object at 0x\[\[:xdigit:\]\]+>,\\)" "verify inferiors list"
+gdb_py_test_silent_cmd "python i0 = inferiors\[0\]" "get first inferior" 0
+
+gdb_test "python print 'result =', i0 == inferiors\[0\]" " = True" "test equality comparison (true)"
+gdb_test "python print 'result =', i0.num" " = \[0-9\]+" "test Inferior.num"
+gdb_test "python print 'result =', i0.pid" " = \[0-9\]+" "test Inferior.pid"
+gdb_test "python print 'result =', i0.was_attached" " = False" "test Inferior.was_attached"
+gdb_test "python print i0.threads ()" "\\(<gdb.InferiorThread object at 0x\[\[:xdigit:\]\]+>,\\)" "test Inferior.threads"
+
+# Test memory read and write operations.
+
+gdb_py_test_silent_cmd "python addr = gdb.selected_frame ().read_var ('str')" \
+  "read str address" 0
+gdb_py_test_silent_cmd "python str = gdb.inferiors()\[0\].read_memory (addr, 5)" \
+  "read str contents" 1
+gdb_py_test_silent_cmd "python str\[1\] = 'a'" "change str" 0
+gdb_py_test_silent_cmd "python gdb.inferiors()\[0\].write_memory (addr, str)" \
+  "write str" 1
+gdb_test "print str" " = 0x\[\[:xdigit:\]\]+ \"hallo, testsuite\"" \
+  "ensure str was changed in the inferior"
+
+# Test memory search.
+
+set hex_number {0x[0-9a-fA-F][0-9a-fA-F]*}
+set dec_number {[0-9]+}
+set history_prefix {[$][0-9]* = }
+set newline {[\r\n]+}
+set pattern_not_found "${newline}.]"
+set one_pattern_found "${newline}.${dec_number}L]"
+set two_patterns_found "${newline}.${dec_number}L, ${dec_number}L]"
+
+# Test string pattern.
+
+gdb_test "set *(int32_t*) &int8_search_buf\[10\] = 0x61616161" "" ""
+gdb_test "py search_buf = gdb.selected_frame ().read_var ('int8_search_buf')" "" ""
+gdb_test "py start_addr = search_buf.address" "" ""
+gdb_test "py length = search_buf.type.sizeof" "" ""
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, 'aaa')" \
+  "${two_patterns_found}" "find string pattern"
+
+# Test not finding pattern because search range too small, with
+# potential find at the edge of the range.
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, 10+3, 'aaaa')" \
+  "${pattern_not_found}" "pattern not found at end of range"
+
+# Increase the search range by 1 and we should find the pattern.
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, 10+3+1, \['a', 'a', 'a', 'a'\])" \
+  "${one_pattern_found}" "pattern found at end of range"
+
+# Test max-count with size, with different parameter position
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, \[0x61, 0x61\], 1, 1)" \
+  "${one_pattern_found}" "size = 1, max_count = 1"
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, \[0x61, 0x61\], 1, 2)" \
+  "${two_patterns_found}" "size = 1, max_count = 2, normal ordering"
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, \[0x61, 0x61\], size = 1, max_count = 2)" \
+  "${two_patterns_found}" "size = 1, max_count = 2, normal ordering, with keywords"
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, \[0x61, 0x61\], max_count = 2, size = 1)" \
+  "${two_patterns_found}" "size = 1, max_count = 2, inverted ordering"
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, \['a', 'a'\], max_count = 2)" \
+  "${two_patterns_found}" "max_count = 2, with keyword"
+
+# Test 16-bit pattern.
+
+gdb_test "set int16_search_buf\[10\] = 0x1234" "" ""
+gdb_test "py search_buf = gdb.selected_frame ().read_var ('int16_search_buf')" "" ""
+gdb_test "py start_addr = search_buf.address" "" ""
+gdb_test "py length = search_buf.type.sizeof" "" ""
+gdb_test "py pattern = gdb.parse_and_eval ('(int16_t) 0x1234')" "" ""
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, 0x1234, 2)" \
+  "${one_pattern_found}" "find 16-bit pattern, with python pattern"
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, pattern)" \
+  "${one_pattern_found}" "find 16-bit pattern, with value pattern"
+
+# Test 32-bit pattern.
+
+gdb_test "set int32_search_buf\[10\] = 0x12345678" "" ""
+gdb_test "py search_buf = gdb.selected_frame ().read_var ('int32_search_buf')" "" ""
+gdb_test "py start_addr = search_buf.address" "" ""
+gdb_test "py length = search_buf.type.sizeof" "" ""
+gdb_test "py pattern = gdb.parse_and_eval ('(int32_t) 0x12345678')" "" ""
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, 0x12345678, 4)" \
+  "${one_pattern_found}" "find 32-bit pattern, with python pattern"
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, pattern)" \
+  "${one_pattern_found}" "find 32-bit pattern, with value pattern"
+
+# Test 64-bit pattern.
+
+gdb_test "set int64_search_buf\[10\] = 0xfedcba9876543210LL" "" ""
+gdb_test "py search_buf = gdb.selected_frame ().read_var ('int64_search_buf')" "" ""
+gdb_test "py start_addr = search_buf.address" "" ""
+gdb_test "py length = search_buf.type.sizeof" "" ""
+gdb_test "py pattern = gdb.parse_and_eval ('(int64_t) 0xfedcba9876543210LL')" "" ""
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, 0xfedcba9876543210, 8)" \
+  "${one_pattern_found}" "find 64-bit pattern, with python pattern"
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, pattern)" \
+  "${one_pattern_found}" "find 64-bit pattern, with value pattern"
+
+# Test mixed-sized patterns.
+
+gdb_test "set *(int8_t*) &search_buf\[10\] = 0x62" "" ""
+gdb_test "set *(int16_t*) &search_buf\[11\] = 0x6363" "" ""
+gdb_test "set *(int32_t*) &search_buf\[13\] = 0x64646464" "" ""
+gdb_test "py search_buf = gdb.selected_frame ().read_var ('search_buf')" "" ""
+gdb_test "py start_addr = search_buf\[0\].address" "" ""
+gdb_test "py pattern1 = gdb.parse_and_eval ('(int8_t) 0x62')" "" ""
+gdb_test "py pattern2 = gdb.parse_and_eval ('(int16_t) 0x6363')" "" ""
+gdb_test "py pattern3 = gdb.parse_and_eval ('(int32_t) 0x64646464')" "" ""
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, 100, \[pattern1, pattern2, pattern3\])" \
+    "${one_pattern_found}" "find mixed-sized pattern"
+
+# Test search spanning a large range, in the particular case of native
+# targets, test the search spanning multiple chunks.
+# Remote targets may implement the search differently.
+
+set CHUNK_SIZE 16000 ;
+
+gdb_test "set *(int32_t*) &search_buf\[0*${CHUNK_SIZE}+100\] = 0x12345678" "" ""
+gdb_test "set *(int32_t*) &search_buf\[1*${CHUNK_SIZE}+100\] = 0x12345678" "" ""
+gdb_test "py start_addr = gdb.selected_frame ().read_var ('search_buf')" "" ""
+gdb_test "py length = gdb.selected_frame ().read_var ('search_buf_size')" "" ""
+
+gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, 0x12345678, 4)" \
+  "${two_patterns_found}" "search spanning large range"
+
+# For native targets, test a pattern straddling a chunk boundary.
+
+if [isnative] {
+    gdb_test "set *(int32_t*) &search_buf\[${CHUNK_SIZE}-1\] = 0xfdb97531" "" ""
+
+    gdb_test "py print gdb.inferiors()\[0\].search_memory (start_addr, length, 0xfdb97531, 4)" \
+      "${one_pattern_found}" "find pattern straddling chunk boundary"
+}
diff --git a/gdb/testsuite/gdb.python/py-infthread.c b/gdb/testsuite/gdb.python/py-infthread.c
new file mode 100644
index 0000000..22eb9f2
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-infthread.c
@@ -0,0 +1,14 @@
+int f2 (int a)
+{
+  return ++a;
+}
+
+int f1 (int a, int b)
+{
+  return f2(a) + b;
+}
+
+int main (int argc, char *argv[])
+{
+  return f1 (1, 2);
+}
diff --git a/gdb/testsuite/gdb.python/py-infthread.exp b/gdb/testsuite/gdb.python/py-infthread.exp
new file mode 100644
index 0000000..e9d18b7
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-infthread.exp
@@ -0,0 +1,58 @@
+# Copyright (C) 2009 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/>.
+
+# This file is part of the GDB testsuite.  It tests the mechanism
+# exposing inferior threads to Python.
+
+if $tracelevel then {
+    strace $tracelevel
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+if ![python_supported] then {
+  unsupported "python support is disabled"
+  return -1
+}
+
+set testfile "py-infthread"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+    untested "Couldn't compile ${srcfile}"
+    return -1
+}
+
+gdb_load ${binfile}
+
+# The following tests require execution.
+
+if ![runto_main] then {
+    fail "Can't run to main"
+    return 0
+}
+
+runto [gdb_get_line_number "Break here."]
+
+# Test basic gdb.Inferior attributes and methods.
+
+gdb_py_test_silent_cmd "python t0 = gdb.selected_thread ()" "test gdb.selected_thread" 1
+gdb_test "python print t0" "\\<gdb.InferiorThread object at 0x\[\[:xdigit:\]\]+>" "verify InferiorThread object"
+gdb_test "python print 'result =', t0.num" " = \[0-9\]+" "test Inferior.num"
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.exp b/gdb/testsuite/gdb.python/py-prettyprint.exp
index 2626895..cd0d7e7 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.exp
+++ b/gdb/testsuite/gdb.python/py-prettyprint.exp
@@ -27,12 +27,20 @@ set binfile ${objdir}/${subdir}/${testfile}
 # Start with a fresh gdb.
 gdb_exit
 gdb_start
-gdb_test_multiple "python print 'hello, world!'" "verify python support" {
-    -re "not supported.*$gdb_prompt $"	{
-      unsupported "python support is disabled"
-      return -1
-    }
-    -re "$gdb_prompt $"	{}
+if ![python_supported] then {
+  unsupported "python support is disabled"
+  return -1
+}
+
+# Run a command in GDB, and report a failure if a Python exception is thrown.
+# If report_pass is true, report a pass if no exception is thrown.
+proc gdb_py_test_silent_cmd {cmd name report_pass} {
+  global gdb_prompt
+
+  gdb_test_multiple $cmd $name {
+      -re "Traceback.*$gdb_prompt $"  { fail $name }
+      -re "$gdb_prompt $"	      { if $report_pass { pass $name } }
+  }
 }
 
 # Run a command in GDB, and report a failure if a Python exception is thrown.
@@ -105,6 +113,8 @@ proc run_lang_tests {lang} {
     gdb_test "print estring" "\"embedded x\\\\201\\\\202\\\\203\\\\204\""
     gdb_test "print c" " = container \"container\" with 2 elements = {$nl *.0. = 23,$nl *.1. = 72$nl}"
 
+    gdb_test "print nullstr" "RuntimeError: Error reading string from inferior.*"
+
     gdb_test "continue" "Program exited normally\."
 
     remote_file host delete ${remote_python_file}
diff --git a/gdb/testsuite/gdb.python/py-template.exp b/gdb/testsuite/gdb.python/py-template.exp
index 713ad5f..5d17b26 100644
--- a/gdb/testsuite/gdb.python/py-template.exp
+++ b/gdb/testsuite/gdb.python/py-template.exp
@@ -20,6 +20,17 @@ if $tracelevel then {
     strace $tracelevel
 }
 
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+
+if ![python_supported] then {
+  unsupported "python support is disabled"
+  return -1
+}
+
 set testfile "py-template"
 set srcfile ${testfile}.cc
 set binfile ${objdir}/${subdir}/${testfile}
@@ -29,20 +40,6 @@ if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable \
     return -1
 }
 
-# Start with a fresh gdb.
-
-gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-
-gdb_test_multiple "python print 23" "verify python support" {
-    -re "not supported.*$gdb_prompt $"	{
-      unsupported "python support is disabled"
-      return -1
-    }
-    -re "$gdb_prompt $"	{}
-}
-
 proc test_template_arg {type} {
     global testfile srcdir subdir srcfile binfile
     if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
diff --git a/gdb/testsuite/gdb.python/py-value.exp b/gdb/testsuite/gdb.python/py-value.exp
index d980a3d..6a75595 100644
--- a/gdb/testsuite/gdb.python/py-value.exp
+++ b/gdb/testsuite/gdb.python/py-value.exp
@@ -307,6 +307,15 @@ proc test_value_after_death {} {
     "print value's type"
 }
 
+# Regression test for a cast failure.  The bug was that if we cast a
+# value to its own type, gdb could crash.  This happened because we
+# could end up double-freeing a struct value.
+proc test_cast_regression {} {
+  gdb_test "python v = gdb.Value(5)" "" "create value for cast test"
+  gdb_test "python v = v.cast(v.type)" "" "cast value for cast test"
+  gdb_test "python print v" "5" "print value for cast test"
+}
+
 # Regression test for invalid subscript operations.  The bug was that
 # the type of the value was not being checked before allowing a
 # subscript operation to proceed.
@@ -392,16 +401,23 @@ proc test_parse_and_eval {} {
 gdb_exit
 gdb_start
 gdb_reinitialize_dir $srcdir/$subdir
-gdb_load ${binfile}
 
-gdb_test_multiple "python print 'hello, world!'" "verify python support" {
-    -re "not supported.*$gdb_prompt $"	{
-      unsupported "python support is disabled"
-      return -1
-    }
-    -re "$gdb_prompt $"	{}
+if ![python_supported] then {
+  unsupported "python support is disabled"
+  return -1
 }
 
+set testfile "py-value"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+    untested "Couldn't compile ${srcfile}"
+    return -1
+}
+
+gdb_load ${binfile}
+
 test_value_creation
 test_value_numeric_ops
 test_value_boolean
@@ -419,6 +435,7 @@ if ![runto_main] then {
 test_value_in_inferior
 test_lazy_strings
 test_value_after_death
+test_cast_regression
 
 # The following test recompiles the binary to test either C or C++
 # values. 
diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c b/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c
new file mode 100644
index 0000000..4dc308b
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c
@@ -0,0 +1,175 @@
+/* Test case for forgotten hw-watchpoints after fork()-off of a process.
+
+   Copyright 2008, 2009 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <string.h>
+#include <errno.h>
+
+static void
+delay (void)
+{
+  int i = usleep (1000000 / 100);
+  assert (i == 0 || errno == EINTR);
+}
+
+#if defined FOLLOW_PARENT
+
+static void
+forkoff (int nr)
+{
+  pid_t child, pid_got;
+  int exit_code = 42 + nr;
+  int status, i;
+
+  child = fork ();
+  switch (child)
+    {
+    case -1:
+      assert (0);
+    case 0:
+      printf ("child%d: %d\n", nr, (int) getpid ());
+      /* Delay to get both the "child%d" and "parent%d" message printed without
+	 a race breaking expect by its endless wait on `$gdb_prompt$':
+	 Breakpoint 3, breakpoint () at ../../../gdb/testsuite/gdb.threads/watchpoint-fork.c:33
+	 33      }
+	 (gdb) parent2: 14223  */
+      i = sleep (1);
+      assert (i == 0);
+
+      /* We must not get caught here (against a forgotten breakpoint).  */
+      var++;
+      breakpoint ();
+
+      _exit (exit_code);
+    default:
+      printf ("parent%d: %d\n", nr, (int) child);
+      /* Delay to get both the "child%d" and "parent%d" message printed, see
+	 above.  */
+      i = sleep (1);
+      assert (i == 0);
+
+      pid_got = wait (&status);
+      assert (pid_got == child);
+      assert (WIFEXITED (status));
+      assert (WEXITSTATUS (status) == exit_code);
+
+      /* We must get caught here (against a false watchpoint removal).  */
+      breakpoint ();
+    }
+}
+
+#elif defined FOLLOW_CHILD
+
+static volatile int usr1_got;
+
+static void
+handler_usr1 (int signo)
+{
+  usr1_got++;
+}
+
+static void
+forkoff (int nr)
+{
+  pid_t child;
+  int i, loop;
+  struct sigaction act, oldact;
+#ifdef THREAD
+  void *thread_result;
+#endif
+
+  memset (&act, 0, sizeof act);
+  act.sa_flags = SA_RESTART;
+  act.sa_handler = handler_usr1;
+  sigemptyset (&act.sa_mask);
+  i = sigaction (SIGUSR1, &act, &oldact);
+  assert (i == 0);
+
+  child = fork ();
+  switch (child)
+    {
+    case -1:
+      assert (0);
+    default:
+      printf ("parent%d: %d\n", nr, (int) child);
+
+      /* Sleep for a while to possibly get incorrectly ATTACH_THREADed by GDB
+	 tracing the child fork with no longer valid thread/lwp entries of the
+	 parent.  */
+
+      i = sleep (2);
+      assert (i == 0);
+
+      /* We must not get caught here (against a forgotten breakpoint).  */
+
+      var++;
+      breakpoint ();
+
+#ifdef THREAD
+      /* And neither got caught our thread.  */
+
+      step = 99;
+      i = pthread_join (thread, &thread_result);
+      assert (i == 0);
+      assert (thread_result == (void *) 99UL);
+#endif
+
+      /* Be sure our child knows we did not get caught above.  */
+
+      i = kill (child, SIGUSR1);
+      assert (i == 0);
+
+      /* Sleep for a while to check GDB's `info threads' no longer tracks us in
+	 the child fork.  */
+
+      i = sleep (2);
+      assert (i == 0);
+
+      _exit (0);
+    case 0:
+      printf ("child%d: %d\n", nr, (int) getpid ());
+
+      /* Let the parent signal us about its success.  Be careful of races.  */
+
+      for (loop = 0; loop < 1000; loop++)
+	{
+	  /* Parent either died (and USR1_GOT is zero) or it succeeded.  */
+	  if (kill (getppid (), 0) != 0)
+	    break;
+	  /* Parent succeeded?  */
+	  if (usr1_got)
+	    break;
+
+	  delay ();
+	}
+      assert (usr1_got);
+
+      /* We must get caught here (against a false watchpoint removal).  */
+
+      breakpoint ();
+    }
+
+  i = sigaction (SIGUSR1, &oldact, NULL);
+  assert (i == 0);
+}
+
+#else
+# error "!FOLLOW_PARENT && !FOLLOW_CHILD"
+#endif
diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c b/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c
new file mode 100644
index 0000000..edacfc0
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c
@@ -0,0 +1,157 @@
+/* Test case for forgotten hw-watchpoints after fork()-off of a process.
+
+   Copyright 2008, 2009 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <assert.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include <asm/unistd.h>
+#include <unistd.h>
+#define gettid() syscall (__NR_gettid)
+
+/* Non-atomic `var++' should not hurt as we synchronize the threads by the STEP
+   variable.  Hit-comments need to be duplicite there to catch both at-stops
+   and behind-stops, depending on the target.  */
+
+static volatile int var;
+
+static void
+dummy (void)
+{
+}
+
+static void
+breakpoint (void)
+{
+}
+
+/* Include here the functions:
+   static void forkoff (int nr);
+   static void delay (void);  */
+
+static pthread_t thread;
+static volatile int step;
+#define THREAD
+
+#include "watchpoint-fork-forkoff.c"
+
+static void *
+start (void *arg)
+{
+  if (step >= 3)
+    goto step_3;
+
+  while (step != 1)
+    delay ();
+
+  var++;	/* validity-thread-B */
+  dummy ();	/* validity-thread-B */
+  step = 2;
+  while (step != 3)
+    {
+      if (step == 99)
+	goto step_99;
+      delay ();
+    }
+
+step_3:
+  if (step >= 5)
+    goto step_5;
+
+  var++;	/* after-fork1-B */
+  dummy ();	/* after-fork1-B */
+  step = 4;
+  while (step != 5)
+    {
+      if (step == 99)
+	goto step_99;
+      delay ();
+    }
+
+step_5:
+  var++;	/* after-fork2-B */
+  dummy ();	/* after-fork2-B */
+  return (void *) 5UL;
+
+step_99:
+  /* We must not get caught here (against a forgotten breakpoint).  */
+  var++;
+  breakpoint ();
+  return (void *) 99UL;
+}
+
+int
+main (void)
+{
+  int i;
+  void *thread_result;
+
+  setbuf (stdout, NULL);
+  printf ("main: %d\n", (int) gettid ());
+
+  /* General watchpoints validity.  */
+  var++;	/* validity-first */
+  dummy ();	/* validity-first */
+
+  i = pthread_create (&thread, NULL, start, NULL);
+  assert (i == 0);
+
+  var++;	/* validity-thread-A */
+  dummy ();	/* validity-thread-A */
+  step = 1;
+  while (step != 2)
+    delay ();
+
+  /* Hardware watchpoints got disarmed here.  */
+  forkoff (1);
+
+  var++;	/* after-fork1-A */
+  dummy ();	/* after-fork1-A */
+  step = 3;
+#ifdef FOLLOW_CHILD
+  /* Spawn new thread as it was deleted in the child of FORK.  */
+  i = pthread_create (&thread, NULL, start, NULL);
+  assert (i == 0);
+#endif
+  while (step != 4)
+    delay ();
+
+  /* A sanity check for double hardware watchpoints removal.  */
+  forkoff (2);
+
+  var++;	/* after-fork2-A */
+  dummy ();	/* after-fork2-A */
+  step = 5;
+#ifdef FOLLOW_CHILD
+  /* Spawn new thread as it was deleted in the child of FORK.  */
+  i = pthread_create (&thread, NULL, start, NULL);
+  assert (i == 0);
+#endif
+
+  i = pthread_join (thread, &thread_result);
+  assert (i == 0);
+  assert (thread_result == (void *) 5UL);
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork.c b/gdb/testsuite/gdb.threads/watchpoint-fork.c
new file mode 100644
index 0000000..5f62e7f
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/watchpoint-fork.c
@@ -0,0 +1,57 @@
+/* Test case for forgotten hw-watchpoints after fork()-off of a process.
+
+   Copyright 2008, 2009 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <assert.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static volatile int var;
+
+static void
+breakpoint (void)
+{
+}
+
+/* Include here the function:
+   static void forkoff (int nr);  */
+
+#include "watchpoint-fork-forkoff.c"
+
+int
+main (void)
+{
+  setbuf (stdout, NULL);
+  printf ("main: %d\n", (int) getpid ());
+
+  /* General watchpoints validity.  */
+  var++;
+  /* Hardware watchpoints got disarmed here.  */
+  forkoff (1);
+  /* This watchpoint got lost before.  */
+  var++;
+  /* A sanity check for double hardware watchpoints removal.  */
+  forkoff (2);
+  var++;
+
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork.exp b/gdb/testsuite/gdb.threads/watchpoint-fork.exp
new file mode 100644
index 0000000..1dc93ab
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/watchpoint-fork.exp
@@ -0,0 +1,130 @@
+# Copyright 2008, 2009 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 case for forgotten hw-watchpoints after fork()-off of a process.
+
+proc test {type symbol} {
+    global objdir subdir srcdir
+
+    set test watchpoint-fork
+
+    global pf_prefix
+    set prefix_test $pf_prefix
+    lappend pf_prefix "$type:"
+    set prefix_mt $pf_prefix
+
+    # no threads
+
+    set pf_prefix $prefix_mt
+    lappend pf_prefix "singlethreaded:"
+
+    set executable ${test}-${type}
+    if { [gdb_compile ${srcdir}/${subdir}/${test}.c ${objdir}/${subdir}/${executable} executable [list debug additional_flags=-D$symbol]] != "" } {
+	untested ${test}.exp
+	return -1
+    }
+    clean_restart $executable
+
+    gdb_test "show detach-on-fork" "Whether gdb will detach the child of a fork is on."
+    gdb_test "set follow-fork-mode $type"
+    gdb_test "show follow-fork-mode" "Debugger response to a program call of fork or vfork is \"$type\"."
+    # Testcase uses it for the `follow-fork-mode child' type.
+    gdb_test "handle SIGUSR1 nostop noprint pass"
+
+    if { ![runto_main] } then {
+	gdb_suppress_tests
+	return
+    }
+
+    # Install the watchpoint only after getting into MAIN - workaround some PPC
+    # problem.
+    gdb_test "watch var" "atchpoint 2: var" "Set the watchpoint"
+
+    # It is never hit but it should not be left over in the fork()ed-off child.
+    gdb_breakpoint "breakpoint"
+
+    gdb_test "continue" \
+	     "atchpoint 2: var.*Old value = 0.*New value = 1.*forkoff *\\(1\\).*" "watchpoints work"
+    gdb_test "continue" \
+	     "reakpoint 3, breakpoint.*" "breakpoint after the first fork"
+    gdb_test "continue" \
+	     "atchpoint 2: var.*Old value = 1.*New value = 2.*forkoff *\\(2\\).*" "watchpoint after the first fork"
+    gdb_test "continue" \
+	     "reakpoint 3, breakpoint.*" "breakpoint after the second fork"
+    gdb_test "continue" \
+	     "atchpoint 2: var.*Old value = 2.*New value = 3.*return *0;" "watchpoint after the second fork"
+    gdb_test "continue" "Continuing..*Program exited normally." "finish"
+
+
+    # threads
+
+    set pf_prefix $prefix_mt
+    lappend pf_prefix "multithreaded:"
+
+    set executable ${test}-mt-${type}
+    if { [gdb_compile_pthreads ${srcdir}/${subdir}/${test}-mt.c ${objdir}/${subdir}/${executable} executable [list debug additional_flags=-D$symbol]] != "" } {
+	untested ${test}.exp
+	return -1
+    }
+    clean_restart $executable
+
+    gdb_test "set follow-fork-mode $type"
+    # Testcase uses it for the `follow-fork-mode child' type.
+    gdb_test "handle SIGUSR1 nostop noprint pass"
+
+    if { ![runto_main] } then {
+	gdb_suppress_tests
+	return
+    }
+
+    # Install the watchpoint only after getting into MAIN - workaround some PPC
+    # problem.
+    gdb_test "watch var" "atchpoint 2: var" "Set the watchpoint"
+
+    # It is never hit but it should not be left over in the fork()ed-off child.
+    gdb_breakpoint "breakpoint"
+
+    gdb_test "continue" \
+	     "atchpoint 2: var.*Old value = 0.*New value = 1.*validity-first.*" "singlethread watchpoints work"
+    gdb_test "continue" \
+	     "atchpoint 2: var.*Old value = 1.*New value = 2.*validity-thread-A.*" "multithreaded watchpoints work at A"
+    gdb_test "continue" \
+	     "atchpoint 2: var.*Old value = 2.*New value = 3.*validity-thread-B.*" "multithreaded watchpoints work at B"
+    gdb_test "continue" \
+	     "reakpoint 3, breakpoint.*" "breakpoint (A) after the first fork"
+    gdb_test "continue" \
+	     "atchpoint 2: var.*Old value = 3.*New value = 4.*after-fork1-A.*" "watchpoint A after the first fork"
+    gdb_test "continue" \
+	     "atchpoint 2: var.*Old value = 4.*New value = 5.*after-fork1-B.*" "watchpoint B after the first fork"
+    gdb_test "continue" \
+	     "reakpoint 3, breakpoint.*" "breakpoint (A) after the second fork"
+    gdb_test "continue" \
+	     "atchpoint 2: var.*Old value = 5.*New value = 6.*after-fork2-A.*" "watchpoint A after the second fork"
+    gdb_test "continue" \
+	     "atchpoint 2: var.*Old value = 6.*New value = 7.*after-fork2-B.*" "watchpoint B after the second fork"
+    gdb_test "continue" "Continuing..*Program exited normally." "finish"
+
+
+    # cleanup
+
+    set pf_prefix $prefix_test
+}
+
+test parent FOLLOW_PARENT
+
+# Only GNU/Linux is known to support `set follow-fork-mode child'.
+if {[istarget "*-*-linux*"]} {
+    test child FOLLOW_CHILD
+}
diff --git a/gdb/testsuite/lib/cp-support.exp b/gdb/testsuite/lib/cp-support.exp
index 6fbee84..1189cfd 100644
--- a/gdb/testsuite/lib/cp-support.exp
+++ b/gdb/testsuite/lib/cp-support.exp
@@ -222,7 +222,7 @@ proc cp_test_ptype_class { in_command in_testname in_key in_tag in_class_table {
 
     set parse_okay 0
     gdb_test_multiple "$in_command" "$in_testname // parse failed" {
-	-re "type = (struct|class)${wsopt}(\[A-Za-z0-9_\]*)${wsopt}((:\[^\{\]*)?)${wsopt}\{(.*)\}${wsopt}(\[^\r\n\]*)\[\r\n\]+$gdb_prompt $" {
+	-re "type = (struct|class)${wsopt}(\[A-Za-z0-9_:\]*)${wsopt}((:\[^\{\]*)?)${wsopt}\{(.*)\}${wsopt}(\[^\r\n\]*)\[\r\n\]+$gdb_prompt $" {
 	    set parse_okay          1
 	    set actual_key          $expect_out(1,string)
 	    set actual_tag          $expect_out(2,string)
@@ -231,6 +231,7 @@ proc cp_test_ptype_class { in_command in_testname in_key in_tag in_class_table {
 	    set actual_tail         $expect_out(6,string)
 	}
     }
+    
     if { ! $parse_okay } then { return }
 
     # Check the actual key.  It would be nice to require that it match
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 627941d..1f9b228 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -27,6 +27,7 @@ if {$tool == ""} {
 }
 
 load_lib libgloss.exp
+load_lib python-support.exp
 
 global GDB
 
diff --git a/gdb/testsuite/lib/python-support.exp b/gdb/testsuite/lib/python-support.exp
new file mode 100644
index 0000000..b8e9836
--- /dev/null
+++ b/gdb/testsuite/lib/python-support.exp
@@ -0,0 +1,53 @@
+global python_supported_saved
+
+# Return 1 if Python scripting is supported in GDB, 0 if not.
+proc python_supported { } {
+  global gdb_prompt
+  global python_supported_saved
+
+  if [info exists python_supported_saved] {
+      verbose "python_supported:  returning saved $python_supported_saved" 2
+      return $python_supported_saved
+  }
+
+  gdb_test_multiple "python print 'hello, world!'" "verify python support" {
+    -re "not supported.*$gdb_prompt $"	{
+      return [set python_supported_saved 0]
+    }
+    -re "$gdb_prompt $"	{
+      return [set python_supported_saved 1]
+    }
+  }
+
+  return [set python_supported_saved 0]
+}
+
+# Run a command in GDB, and report a failure if a Python exception is thrown.
+# If report_pass is true, report a pass if no exception is thrown.
+proc gdb_py_test_silent_cmd {cmd name report_pass} {
+  global gdb_prompt
+
+  gdb_test_multiple $cmd $name {
+      -re "Traceback.*$gdb_prompt $"  { fail $name }
+      -re "$gdb_prompt $"	      { if $report_pass { pass $name } }
+  }
+}
+
+# Usage: gdb_py_test_multiple NAME INPUT RESULT {INPUT RESULT}...
+# Run a test named NAME, consisting of multiple lines of input.
+# After each input line INPUT, search for result line RESULT.
+# Succeed if all results are seen; fail otherwise.
+proc gdb_py_test_multiple {name args} {
+    global gdb_prompt
+
+    foreach {input result} $args {
+	if {[gdb_test_multiple $input "$name - $input" {
+	    -re "\[\r\n\]*($result)\[\r\n\]+($gdb_prompt | *>)$" {
+		pass "$name - $input"
+	    }
+	}]} {
+	    return 1
+	}
+    }
+    return 0
+}
diff --git a/gdb/thread.c b/gdb/thread.c
index 16a207c..c3cff06 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -61,7 +61,6 @@ static int thread_alive (struct thread_info *);
 static void info_threads_command (char *, int);
 static void thread_apply_command (char *, int);
 static void restore_current_thread (ptid_t);
-static void prune_threads (void);
 
 /* Frontend view of the thread state.  Possible extensions: stepping,
    finishing, until(ling),...  */
@@ -517,7 +516,7 @@ thread_alive (struct thread_info *tp)
   return 1;
 }
 
-static void
+void
 prune_threads (void)
 {
   struct thread_info *tp, *next;
diff --git a/gdb/top.c b/gdb/top.c
index 90e8f1e..489e24a 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -337,6 +337,7 @@ void
 prepare_execute_command (void)
 {
   free_all_values ();
+  free_all_types ();
 
   /* With multiple threads running while the one we're examining is stopped,
      the dcache can get stale without us being able to detect it.
diff --git a/gdb/typeprint.c b/gdb/typeprint.c
index ce9f551..5f9d739 100644
--- a/gdb/typeprint.c
+++ b/gdb/typeprint.c
@@ -36,6 +36,7 @@
 #include "gdb_string.h"
 #include "exceptions.h"
 #include "valprint.h"
+#include "dwarf2loc.h"
 #include <errno.h>
 
 extern void _initialize_typeprint (void);
@@ -77,6 +78,9 @@ void
 type_print (struct type *type, char *varstring, struct ui_file *stream,
 	    int show)
 {
+  if (show >= 0)
+    type = check_typedef (type);
+
   LA_PRINT_TYPE (type, varstring, stream, show, 0);
 }
 
@@ -115,7 +119,8 @@ whatis_exp (char *exp, int show)
 {
   struct expression *expr;
   struct value *val;
-  struct cleanup *old_chain = NULL;
+  /* Required at least for the object_address_set call.  */
+  struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
   struct type *real_type = NULL;
   struct type *type;
   int full = 0;
@@ -126,12 +131,13 @@ whatis_exp (char *exp, int show)
   if (exp)
     {
       expr = parse_expression (exp);
-      old_chain = make_cleanup (free_current_contents, &expr);
+      make_cleanup (free_current_contents, &expr);
       val = evaluate_type (expr);
     }
   else
     val = access_value_history (0);
 
+  object_address_set (value_raw_address (val));
   type = value_type (val);
 
   get_user_print_options (&opts);
@@ -168,8 +174,7 @@ whatis_exp (char *exp, int show)
   type_print (type, "", gdb_stdout, show);
   printf_filtered ("\n");
 
-  if (exp)
-    do_cleanups (old_chain);
+  do_cleanups (old_chain);
 }
 
 static void
diff --git a/gdb/typeprint.h b/gdb/typeprint.h
index 7d7e6bc..6ee65cf 100644
--- a/gdb/typeprint.h
+++ b/gdb/typeprint.h
@@ -20,10 +20,13 @@
 #ifndef TYPEPRINT_H
 #define TYPEPRINT_H
 
+enum language;
 struct ui_file;
 
 void print_type_scalar (struct type * type, LONGEST, struct ui_file *);
 
 void c_type_print_varspec_suffix (struct type *, struct ui_file *, int,
 				  int, int);
+
+void c_type_print_args (struct type *, struct ui_file *, int, enum language);
 #endif
diff --git a/gdb/ui-file.c b/gdb/ui-file.c
index e6aaf93..1760b4c 100644
--- a/gdb/ui-file.c
+++ b/gdb/ui-file.c
@@ -22,6 +22,7 @@
 
 #include "defs.h"
 #include "ui-file.h"
+#include "gdb_obstack.h"
 #include "gdb_string.h"
 #include "gdb_select.h"
 
@@ -264,7 +265,7 @@ set_ui_file_data (struct ui_file *file, void *data,
 }
 
 /* ui_file utility function for converting a ``struct ui_file'' into
-   a memory buffer''. */
+   a memory buffer. */
 
 struct accumulated_ui_file
 {
@@ -298,6 +299,23 @@ ui_file_xstrdup (struct ui_file *file, long *length)
     *length = acc.length;
   return acc.buffer;
 }
+
+static void
+do_ui_file_obsavestring (void *context, const char *buffer, long length)
+{
+  struct obstack *obstack = (struct obstack *) context;
+  obstack_grow (obstack, buffer, length);
+}
+
+char *
+ui_file_obsavestring (struct ui_file *file, struct obstack *obstack,
+		      long *length)
+{
+  ui_file_put (file, do_ui_file_obsavestring, obstack);
+  *length = obstack_object_size (obstack);
+  obstack_1grow (obstack, '\0');
+  return obstack_finish (obstack);
+}
 
 /* A pure memory based ``struct ui_file'' that can be used an output
    buffer. The buffers accumulated contents are available via
diff --git a/gdb/ui-file.h b/gdb/ui-file.h
index 6155699..bb94f4b 100644
--- a/gdb/ui-file.h
+++ b/gdb/ui-file.h
@@ -20,6 +20,7 @@
 #ifndef UI_FILE_H
 #define UI_FILE_H
 
+struct obstack;
 struct ui_file;
 
 /* Create a generic ui_file object with null methods. */
@@ -78,7 +79,10 @@ extern void ui_file_put (struct ui_file *src, ui_file_put_method_ftype *write, v
    minus that appended NUL. */
 extern char *ui_file_xstrdup (struct ui_file *file, long *length);
 
-
+/* Similar to ui_file_xstrdup, but return a new string allocated on
+   OBSTACK.  */
+extern char *ui_file_obsavestring (struct ui_file *file,
+				   struct obstack *obstack, long *length);
 
 extern long ui_file_read (struct ui_file *file, char *buf, long length_buf);
 
diff --git a/gdb/valarith.c b/gdb/valarith.c
index 9f91f4e..753927f 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -31,6 +31,7 @@
 #include "dfp.h"
 #include <math.h>
 #include "infcall.h"
+#include "exceptions.h"
 
 /* Define whether or not the C operator '/' truncates towards zero for
    differently signed operands (truncation direction is undefined in C). */
@@ -146,7 +147,6 @@ an integer nor a pointer of the same type."));
 struct value *
 value_subscript (struct value *array, LONGEST index)
 {
-  struct value *bound;
   int c_style = current_language->c_style_arrays;
   struct type *tarray;
 
@@ -161,12 +161,26 @@ value_subscript (struct value *array, LONGEST index)
       get_discrete_bounds (range_type, &lowerbound, &upperbound);
 
       if (VALUE_LVAL (array) != lval_memory)
-	return value_subscripted_rvalue (array, index, lowerbound);
+	{
+	  if (index >= lowerbound && index <= upperbound)
+	    {
+	      CORE_ADDR element_size = TYPE_LENGTH (TYPE_TARGET_TYPE (tarray));
+	      CORE_ADDR offset = (index - lowerbound) * element_size;
+
+	      return value_subscripted_rvalue (array, offset);
+	    }
+	  error (_("array or string index out of range"));
+	}
 
       if (c_style == 0)
 	{
 	  if (index >= lowerbound && index <= upperbound)
-	    return value_subscripted_rvalue (array, index, lowerbound);
+	    {
+	      CORE_ADDR element_size = TYPE_LENGTH (TYPE_TARGET_TYPE (tarray));
+	      CORE_ADDR offset = (index - lowerbound) * element_size;
+
+	      return value_subscripted_rvalue (array, offset);
+	    }
 	  /* Emit warning unless we have an array of unknown size.
 	     An array of unknown size has lowerbound 0 and upperbound -1.  */
 	  if (upperbound > -1)
@@ -185,33 +199,37 @@ value_subscript (struct value *array, LONGEST index)
     error (_("not an array or string"));
 }
 
-/* Return the value of EXPR[IDX], expr an aggregate rvalue
-   (eg, a vector register).  This routine used to promote floats
-   to doubles, but no longer does.  */
+/* Return the value of *((void *) ARRAY + ELEMENT), ARRAY an aggregate rvalue
+   (eg, a vector register).  This routine used to promote floats to doubles,
+   but no longer does.  OFFSET is zero-based with 0 for the lowermost existing
+   element, it must be expressed in bytes (therefore multiplied by
+   check_typedef (TYPE_TARGET_TYPE (array_type)).  */
 
 struct value *
-value_subscripted_rvalue (struct value *array, LONGEST index, int lowerbound)
+value_subscripted_rvalue (struct value *array, CORE_ADDR offset)
 {
   struct type *array_type = check_typedef (value_type (array));
   struct type *elt_type = check_typedef (TYPE_TARGET_TYPE (array_type));
-  unsigned int elt_size = TYPE_LENGTH (elt_type);
-  unsigned int elt_offs = elt_size * longest_to_int (index - lowerbound);
   struct value *v;
 
-  if (index < lowerbound || elt_offs >= TYPE_LENGTH (array_type))
-    error (_("no such vector element"));
+  /* Do not check TYPE_LENGTH (array_type) as we may have been given the
+     innermost dimension of a multi-dimensional Fortran array where its length
+     is shorter than the possibly accessed element offset.  */
 
   v = allocate_value (elt_type);
   if (VALUE_LVAL (array) == lval_memory && value_lazy (array))
     set_value_lazy (v, 1);
   else
-    memcpy (value_contents_writeable (v),
-	    value_contents (array) + elt_offs, elt_size);
+    {
+      unsigned int elt_size = TYPE_LENGTH (elt_type);
+      memcpy (value_contents_writeable (v),
+	      value_contents (array) + offset, elt_size);
+    }
 
   set_value_component_location (v, array);
   VALUE_REGNUM (v) = VALUE_REGNUM (array);
   VALUE_FRAME_ID (v) = VALUE_FRAME_ID (array);
-  set_value_offset (v, value_offset (array) + elt_offs);
+  set_value_offset (v, value_offset (array) + offset);
   return v;
 }
 
@@ -318,6 +336,68 @@ unop_user_defined_p (enum exp_opcode op, struct value *arg1)
     }
 }
 
+/* Try to find OPERATOR as through argument dependent lookup.  */
+
+static struct value *
+value_user_defined_adl_op (struct value **args, int nargs, char *operator)
+{
+
+  struct symbol *symp;
+  struct type **arg_types;
+  int i;
+
+  /* This function, if found, will not be a member function
+     and does not expect a pointer as its first argument
+     rather the explicit structure.  */
+  args[0] = value_ind (args[0]);
+
+  arg_types = (struct type **)alloca (nargs * (sizeof (struct type *)));
+  /* Prepare list of argument types for overload resolution */
+  for (i = 0; i < nargs; i++)
+    arg_types [i] = value_type (args [i]);
+
+  find_overload_match (arg_types, nargs, operator, 0 /* not method */,
+                       0 /* strict match */, NULL,
+                       NULL /* pass NULL symbol since symbol is unknown */,
+                       NULL, &symp, NULL);
+
+  if (symp)
+    return value_of_variable (symp, 0);
+
+  return NULL;
+}
+
+/* Lookup user defined operator NAME. First try to find it as a member
+   of the struct ARGP[0]. If not found try to find the operator through
+   argument dependent lookup.  */
+
+static struct value *
+value_user_defined_op (struct value **argp, struct value **args, char *name,
+                       int *static_memfuncp, int nargs)
+{
+  struct value *result = NULL;
+  volatile struct gdb_exception except;
+
+  TRY_CATCH (except, RETURN_MASK_ERROR)
+    {
+      result = value_struct_elt (argp, args, name, static_memfuncp,
+                                 "structure");
+    }
+
+  if (except.reason < 0)
+    {
+
+      if (current_language->la_language == language_cplus)
+        /* Try ADL.  */
+        result = value_user_defined_adl_op (args, nargs, name);
+
+      if (!result)
+        error ("%s", except.message);
+    }
+
+  return result;
+}
+
 /* We know either arg1 or arg2 is a structure, so try to find the right
    user defined function.  Create an argument vector that calls 
    arg1.operator @ (arg1,arg2) and return that value (where '@' is any
@@ -458,7 +538,8 @@ value_x_binop (struct value *arg1, struct value *arg2, enum exp_opcode op,
       error (_("Invalid binary operation specified."));
     }
 
-  argvec[0] = value_struct_elt (&arg1, argvec + 1, tstr, &static_memfuncp, "structure");
+  argvec[0] = value_user_defined_op (&arg1, argvec + 1, tstr,
+                                     &static_memfuncp, 2);
 
   if (argvec[0])
     {
@@ -555,7 +636,8 @@ value_x_unop (struct value *arg1, enum exp_opcode op, enum noside noside)
       error (_("Invalid unary operation specified."));
     }
 
-  argvec[0] = value_struct_elt (&arg1, argvec + 1, tstr, &static_memfuncp, "structure");
+  argvec[0] = value_user_defined_op (&arg1, argvec + 1, tstr,
+                                     &static_memfuncp, 1);
 
   if (argvec[0])
     {
diff --git a/gdb/valops.c b/gdb/valops.c
index b94c411..9875f96 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -38,6 +38,7 @@
 #include "cp-support.h"
 #include "dfp.h"
 #include "user-regs.h"
+#include "dwarf2loc.h"
 
 #include <errno.h>
 #include "gdb_string.h"
@@ -397,8 +398,6 @@ value_cast (struct type *type, struct value *arg2)
 	  new_length = val_length / element_length;
 	  if (val_length % element_length != 0)
 	    warning (_("array element type size does not 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,
@@ -845,6 +844,64 @@ value_one (struct type *type, enum lval_type lv)
   return val;
 }
 
+/* object_address_set must be already called before this function.  */
+
+const char *
+object_address_data_not_valid (struct type *type)
+{
+  /* Attributes are present only at the target type of a typedef.  Make the
+     call conditional as it would otherwise loop through type_length_get.  */
+  if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF)
+    CHECK_TYPEDEF (type);
+
+  /* DW_AT_associated has a preference over DW_AT_allocated.  */
+  if (TYPE_NOT_ASSOCIATED (type)
+      || (TYPE_ASSOCIATED (type) != NULL
+	  && 0 == dwarf_locexpr_baton_eval (TYPE_ASSOCIATED (type))))
+    return N_("object is not associated");
+
+  if (TYPE_NOT_ALLOCATED (type)
+      || (TYPE_ALLOCATED (type) != NULL
+	  && 0 == dwarf_locexpr_baton_eval (TYPE_ALLOCATED (type))))
+    return N_("object is not allocated");
+
+  return NULL;
+}
+
+/* Return non-zero if the variable is valid.  If it is valid the function
+   may store the data address (DW_AT_DATA_LOCATION) of TYPE at *ADDRESS_RETURN.
+   You must set *ADDRESS_RETURN from value_raw_address (VAL) before calling this
+   function.  If no DW_AT_DATA_LOCATION is present for TYPE the address at
+   *ADDRESS_RETURN is left unchanged.  ADDRESS_RETURN must not be NULL, use
+   object_address_data_not_valid () for just the data validity check.  */
+
+int
+object_address_get_data (struct type *type, CORE_ADDR *address_return)
+{
+  gdb_assert (address_return != NULL);
+
+  object_address_set (*address_return);
+
+  /* TYPE_DATA_LOCATION_DWARF_BLOCK / TYPE_DATA_LOCATION_ADDR are present only
+     at the target type of a typedef.  */
+  CHECK_TYPEDEF (type);
+
+  if (object_address_data_not_valid (type) != NULL)
+    {
+      /* Do not try to evaluate DW_AT_data_location as it may even crash
+	 (it would just return the value zero in the gfortran case).  */
+      return 0;
+    }
+
+  if (TYPE_DATA_LOCATION_IS_ADDR (type))
+    *address_return = TYPE_DATA_LOCATION_ADDR (type);
+  else if (TYPE_DATA_LOCATION_DWARF_BLOCK (type) != NULL)
+    *address_return
+      = dwarf_locexpr_baton_eval (TYPE_DATA_LOCATION_DWARF_BLOCK (type));
+
+  return 1;
+}
+
 /* Helper function for value_at, value_at_lazy, and value_at_lazy_stack.  */
 
 static struct value *
@@ -936,15 +993,21 @@ value_fetch_lazy (struct value *val)
     }
   else if (VALUE_LVAL (val) == lval_memory)
     {
-      CORE_ADDR addr = value_address (val);
-      int length = TYPE_LENGTH (check_typedef (value_enclosing_type (val)));
+      CORE_ADDR addr = value_raw_address (val);
 
-      if (length)
+      if (object_address_get_data (value_type (val), &addr))
 	{
-	  if (value_stack (val))
-	    read_stack (addr, value_contents_all_raw (val), length);
-	  else
-	    read_memory (addr, value_contents_all_raw (val), length);
+	  struct type *type = value_enclosing_type (val);
+	  int length = TYPE_LENGTH (check_typedef (type));
+
+	  if (length)
+	    {
+	      addr += value_offset (val);
+	      if (value_stack (val))
+		read_stack (addr, value_contents_all_raw (val), length);
+	      else
+		read_memory (addr, value_contents_all_raw (val), length);
+	    }
 	}
     }
   else if (VALUE_LVAL (val) == lval_register)
@@ -1352,7 +1415,18 @@ address_of_variable (struct symbol *var, struct block *b)
   if ((VALUE_LVAL (val) == lval_memory && value_lazy (val))
       || TYPE_CODE (type) == TYPE_CODE_FUNC)
     {
-      CORE_ADDR addr = value_address (val);
+      CORE_ADDR addr;
+
+      if (VALUE_LVAL (val) == lval_memory)
+	{
+	  addr = value_raw_address (val);
+	  if (!object_address_get_data (type, &addr))
+	    error (_("Can't take address of memory lvalue \"%s\"."),
+		   SYMBOL_PRINT_NAME (var));
+	  set_value_address (val, addr);
+	}
+
+      addr = value_address (val);
       return value_from_pointer (lookup_pointer_type (type), addr);
     }
 
@@ -1458,6 +1532,7 @@ struct value *
 value_coerce_array (struct value *arg1)
 {
   struct type *type = check_typedef (value_type (arg1));
+  CORE_ADDR address;
 
   /* If the user tries to do something requiring a pointer with an
      array that has not yet been pushed to the target, then this would
@@ -1467,8 +1542,12 @@ value_coerce_array (struct value *arg1)
   if (VALUE_LVAL (arg1) != lval_memory)
     error (_("Attempt to take address of value not located in memory."));
 
+  address = value_raw_address (arg1);
+  if (!object_address_get_data (type, &address))
+    error (_("Attempt to take address of non-valid value."));
+
   return value_from_pointer (lookup_pointer_type (TYPE_TARGET_TYPE (type)),
-			     value_address (arg1));
+			     address + value_offset (arg1));
 }
 
 /* Given a value which is a function, return a value which is a pointer
@@ -2336,7 +2415,7 @@ find_overload_match (struct type **arg_types, int nargs,
   int boffset;
   int ix;
   int static_offset;
-  struct cleanup *old_cleanups = NULL;
+  struct cleanup *old_cleanups = make_cleanup (null_cleanup, NULL);
 
   const char *obj_type_name = NULL;
   char *func_name = NULL;
@@ -2346,12 +2425,25 @@ find_overload_match (struct type **arg_types, int nargs,
   if (method)
     {
       gdb_assert (obj);
+
+      /* OBJ may be a pointer value rather than the object itself.  */
+      obj = coerce_ref (obj);
+      while (TYPE_CODE (check_typedef (value_type (obj))) == TYPE_CODE_PTR)
+	obj = coerce_ref (value_ind (obj));
       obj_type_name = TYPE_NAME (value_type (obj));
-      /* Hack: evaluate_subexp_standard often passes in a pointer
-         value rather than the object itself, so try again.  */
-      if ((!obj_type_name || !*obj_type_name) 
-	  && (TYPE_CODE (value_type (obj)) == TYPE_CODE_PTR))
-	obj_type_name = TYPE_NAME (TYPE_TARGET_TYPE (value_type (obj)));
+
+      /* First check whether this is a data member, e.g. a pointer to
+	 a function.  */
+      if (TYPE_CODE (check_typedef (value_type (obj))) == TYPE_CODE_STRUCT)
+	{
+	  *valp = search_struct_field (name, obj, 0,
+				       check_typedef (value_type (obj)), 0);
+	  if (*valp)
+	    {
+	      *staticp = 1;
+	      return 0;
+	    }
+	}
 
       fns_ptr = value_find_oload_method_list (&temp, name, 
 					      0, &num_fns, 
@@ -2371,23 +2463,45 @@ find_overload_match (struct type **arg_types, int nargs,
     }
   else
     {
-      const char *qualified_name = SYMBOL_CPLUS_DEMANGLED_NAME (fsym);
+      const char *qualified_name = NULL;
 
-      /* If we have a C++ name, try to extract just the function
-	 part.  */
-      if (qualified_name)
-	func_name = cp_func_name (qualified_name);
-
-      /* If there was no C++ name, this must be a C-style function.
-	 Just return the same symbol.  Do the same if cp_func_name
-	 fails for some reason.  */
+      if (fsym)
+        {
+          qualified_name = SYMBOL_NATURAL_NAME (fsym);
+
+          /* If we have a function with a C++ name, try to extract just
+	     the function part.  Do not try this for non-functions (e.g.
+	     function pointers).  */
+          if (qualified_name
+              && TYPE_CODE (check_typedef (SYMBOL_TYPE (fsym))) == TYPE_CODE_FUNC)
+            {
+              func_name = cp_func_name (qualified_name);
+
+              /* If cp_func_name did not remove anything, the name of the
+	         symbol did not include scope or argument types - it was
+	         probably a C-style function.  */
+              if (func_name && strcmp (func_name, qualified_name) == 0)
+                {
+                  xfree (func_name);
+                  func_name = NULL;
+                }
+            }
+        }
+      else
+        {
+          func_name = (char *) name;
+          qualified_name = name;
+        }
+      
+      /* If there was no C++ name, this must be a C-style function or
+	 not a function at all.  Just return the same symbol.  Do the
+	 same if cp_func_name fails for some reason.  */
       if (func_name == NULL)
         {
 	  *symp = fsym;
           return 0;
         }
 
-      old_cleanups = make_cleanup (xfree, func_name);
       make_cleanup (xfree, oload_syms);
       make_cleanup (xfree, oload_champ_bv);
 
@@ -2398,8 +2512,11 @@ find_overload_match (struct type **arg_types, int nargs,
 						&oload_champ_bv);
     }
 
-  /* Check how bad the best match is.  */
+  /* Did we find a match ?  */
+  if (oload_champ == -1)
+    error ("No symbol \"%s\" in current context.", name);
 
+  /* Check how bad the best match is.  */
   match_quality =
     classify_oload_match (oload_champ_bv, nargs,
 			  oload_method_static (method, fns_ptr,
@@ -2456,8 +2573,8 @@ find_overload_match (struct type **arg_types, int nargs,
 	}
       *objp = temp;
     }
-  if (old_cleanups != NULL)
-    do_cleanups (old_cleanups);
+
+  do_cleanups (old_cleanups);
 
   switch (match_quality)
     {
@@ -2565,6 +2682,12 @@ find_oload_champ_namespace_loop (struct type **arg_types, int nargs,
   new_namespace[namespace_len] = '\0';
   new_oload_syms = make_symbol_overload_list (func_name,
 					      new_namespace);
+
+  /* If we have reached the deepesst level perform argument
+     determined lookup.  */
+  if (!searched_deeper)
+    make_symbol_overload_list_adl (arg_types, nargs, func_name);
+
   while (new_oload_syms[num_fns])
     ++num_fns;
 
@@ -2597,7 +2720,6 @@ find_oload_champ_namespace_loop (struct type **arg_types, int nargs,
     }
   else
     {
-      gdb_assert (new_oload_champ != -1);
       *oload_syms = new_oload_syms;
       *oload_champ = new_oload_champ;
       *oload_champ_bv = new_oload_champ_bv;
@@ -3117,9 +3239,9 @@ value_maybe_namespace_elt (const struct type *curtype,
   struct symbol *sym;
   struct value *result;
 
-  sym = cp_lookup_symbol_namespace (namespace_name, name, NULL,
-				    get_selected_block (0), 
-				    VAR_DOMAIN, 1);
+  sym = cp_lookup_symbol_namespace(namespace_name, name,
+                                   get_selected_block (0), 
+                                   VAR_DOMAIN);
 
   if (sym == NULL)
     return NULL;
@@ -3261,7 +3383,7 @@ value_of_local (const char *name, int complain)
 
   /* Calling lookup_block_symbol is necessary to get the LOC_REGISTER
      symbol instead of the LOC_ARG one (if both exist).  */
-  sym = lookup_block_symbol (b, name, NULL, VAR_DOMAIN);
+  sym = lookup_block_symbol (b, name, VAR_DOMAIN);
   if (sym == NULL)
     {
       if (complain)
@@ -3315,8 +3437,6 @@ value_slice (struct value *array, int lowbound, int length)
       || lowbound + length - 1 > upperbound)
     error (_("slice out of range"));
 
-  /* 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, 
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 3f21ae4..9b15b1a 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -236,7 +236,6 @@ scalar_type_p (struct type *type)
     case TYPE_CODE_STRUCT:
     case TYPE_CODE_UNION:
     case TYPE_CODE_SET:
-    case TYPE_CODE_STRING:
     case TYPE_CODE_BITSTRING:
       return 0;
     default:
@@ -1154,6 +1153,7 @@ val_print_array_elements (struct type *type, const gdb_byte *valaddr,
 
   for (; i < len && things_printed < options->print_max; i++)
     {
+      size_t elt_offset = i * eltlen;
       if (i != 0)
 	{
 	  if (options->prettyprint_arrays)
@@ -1173,7 +1173,7 @@ val_print_array_elements (struct type *type, const gdb_byte *valaddr,
       rep1 = i + 1;
       reps = 1;
       while ((rep1 < len) &&
-	     !memcmp (valaddr + i * eltlen, valaddr + rep1 * eltlen, eltlen))
+	     !memcmp (valaddr + elt_offset, valaddr + rep1 * eltlen, eltlen))
 	{
 	  ++reps;
 	  ++rep1;
diff --git a/gdb/value.c b/gdb/value.c
index a462ee4..968cdf4 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -37,8 +37,10 @@
 #include "block.h"
 #include "dfp.h"
 #include "objfiles.h"
+#include "cli/cli-decode.h"
 #include "valprint.h"
 #include "cli/cli-decode.h"
+#include "observer.h"
 
 #include "python/python.h"
 
@@ -170,6 +172,14 @@ struct value
      taken off this list.  */
   struct value *next;
 
+  /* The reference count.  A value that is still on the `all_values'
+     list will have a reference count of 0.  A call to `release_value'
+     will increment the reference count (and remove the value from the
+     list, the first time).  A call to `value_free' will decrement the
+     reference count, and will free the value when there are no more
+     references.  */
+  int refcount;
+
   /* Register number if the value is from a register.  */
   short regnum;
 
@@ -631,6 +641,13 @@ value_free (struct value *val)
       if (val->parent != NULL)
 	value_free (val->parent);
 
+#if 0
+      /* We need type GC instead.  This can fail when an objfile is
+	 reclaimed and then a value is later freed.  */
+      type_decref (val->type);
+      type_decref (val->enclosing_type);
+#endif
+
       if (VALUE_LVAL (val) == lval_computed)
 	{
 	  struct lval_funcs *funcs = val->location.computed.funcs;
@@ -735,6 +752,7 @@ value_copy (struct value *arg)
     val = allocate_value_lazy (encl_type);
   else
     val = allocate_value (encl_type);
+
   val->type = arg->type;
   VALUE_LVAL (val) = VALUE_LVAL (arg);
   val->location = arg->location;
@@ -770,12 +788,15 @@ value_copy (struct value *arg)
 void
 set_value_component_location (struct value *component, struct value *whole)
 {
+  CORE_ADDR addr;
+
   if (VALUE_LVAL (whole) == lval_internalvar)
     VALUE_LVAL (component) = lval_internalvar_component;
   else
     VALUE_LVAL (component) = VALUE_LVAL (whole);
 
   component->location = whole->location;
+
   if (VALUE_LVAL (whole) == lval_computed)
     {
       struct lval_funcs *funcs = whole->location.computed.funcs;
@@ -783,6 +804,12 @@ set_value_component_location (struct value *component, struct value *whole)
       if (funcs->copy_closure)
         component->location.computed.closure = funcs->copy_closure (whole);
     }
+
+  addr = value_raw_address (component);
+  object_address_get_data (value_type (whole), &addr);
+  if (component->lval != lval_internalvar
+      && component->lval != lval_internalvar_component)
+    set_value_address (component, addr);
 }
 
 
@@ -913,6 +940,29 @@ show_values (char *num_exp, int from_tty)
       num_exp[1] = '\0';
     }
 }
+
+/* Sanity check for memory leaks and proper types reference counting.  */
+
+static void
+value_history_cleanup (void *unused)
+{
+  while (value_history_chain)
+    {
+      struct value_history_chunk *chunk = value_history_chain;
+      int i;
+
+      for (i = 0; i < ARRAY_SIZE (chunk->values); i++)
+      	value_free (chunk->values[i]);
+
+      value_history_chain = chunk->next;
+      xfree (chunk);
+    }
+  value_history_count = 0;
+
+  /* Free the unreferenced types above.  */
+  free_all_values ();
+  free_all_types ();
+}
 
 /* Internal variables.  These are variables within the debugger
    that hold values assigned by debugger commands.
@@ -1388,6 +1438,40 @@ call_internal_function (struct gdbarch *gdbarch,
   return (*ifn->handler) (gdbarch, language, ifn->cookie, argc, argv);
 }
 
+/* Call type_mark_used for any TYPEs referenced from this GDB source file.  */
+
+static void
+value_types_mark_used (void)
+{
+  struct internalvar *var;
+  struct value_history_chunk *chunk;
+
+  for (var = internalvars; var != NULL; var = var->next)
+    switch (var->kind)
+      {
+      case INTERNALVAR_VALUE:
+	type_mark_used (value_type (var->u.value));
+	break;
+
+      case INTERNALVAR_INTEGER:
+	type_mark_used (var->u.integer.type);
+	break;
+
+      case INTERNALVAR_POINTER:
+	type_mark_used (var->u.pointer.type);
+	break;
+      }
+
+  for (chunk = value_history_chain; chunk != NULL; chunk = chunk->next)
+    {
+      int i;
+
+      for (i = 0; i < ARRAY_SIZE (chunk->values); i++)
+	if (chunk->values[i])
+	  type_mark_used (value_type (chunk->values[i]));
+    }
+}
+
 /* The 'function' command.  This does nothing -- it is just a
    placeholder to let "help function NAME" work.  This is also used as
    the implementation of the sub-command that is created when
@@ -1435,11 +1519,10 @@ preserve_one_value (struct value *value, struct objfile *objfile,
 		    htab_t copied_types)
 {
   if (TYPE_OBJFILE (value->type) == objfile)
-    value->type = copy_type_recursive (objfile, value->type, copied_types);
+    value->type = copy_type_recursive (value->type, copied_types);
 
   if (TYPE_OBJFILE (value->enclosing_type) == objfile)
-    value->enclosing_type = copy_type_recursive (objfile,
-						 value->enclosing_type,
+    value->enclosing_type = copy_type_recursive (value->enclosing_type,
 						 copied_types);
 }
 
@@ -1454,13 +1537,13 @@ preserve_one_internalvar (struct internalvar *var, struct objfile *objfile,
     case INTERNALVAR_INTEGER:
       if (var->u.integer.type && TYPE_OBJFILE (var->u.integer.type) == objfile)
 	var->u.integer.type
-	  = copy_type_recursive (objfile, var->u.integer.type, copied_types);
+	  = copy_type_recursive (var->u.integer.type, copied_types);
       break;
 
     case INTERNALVAR_POINTER:
       if (TYPE_OBJFILE (var->u.pointer.type) == objfile)
 	var->u.pointer.type
-	  = copy_type_recursive (objfile, var->u.pointer.type, copied_types);
+	  = copy_type_recursive (var->u.pointer.type, copied_types);
       break;
 
     case INTERNALVAR_VALUE:
@@ -2192,6 +2275,42 @@ pack_long (gdb_byte *buf, struct type *type, LONGEST num)
 }
 
 
+/* Pack NUM into BUF using a target format of TYPE.  */
+
+void
+pack_unsigned_long (gdb_byte *buf, struct type *type, ULONGEST num)
+{
+  enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
+  int len;
+
+  type = check_typedef (type);
+  len = TYPE_LENGTH (type);
+
+  switch (TYPE_CODE (type))
+    {
+    case TYPE_CODE_INT:
+    case TYPE_CODE_CHAR:
+    case TYPE_CODE_ENUM:
+    case TYPE_CODE_FLAGS:
+    case TYPE_CODE_BOOL:
+    case TYPE_CODE_RANGE:
+    case TYPE_CODE_MEMBERPTR:
+      store_unsigned_integer (buf, len, byte_order, num);
+      break;
+
+    case TYPE_CODE_REF:
+    case TYPE_CODE_PTR:
+      store_typed_address (buf, type, (CORE_ADDR) num);
+      break;
+
+    default:
+      error (_("\
+Unexpected type (%d) encountered for unsigned integer constant."),
+	     TYPE_CODE (type));
+    }
+}
+
+
 /* Convert C numbers into newly allocated values.  */
 
 struct value *
@@ -2205,6 +2324,19 @@ value_from_longest (struct type *type, LONGEST num)
 }
 
 
+/* Convert C unsigned numbers into newly allocated values.  */
+
+struct value *
+value_from_ulongest (struct type *type, ULONGEST num)
+{
+  struct value *val = allocate_value (type);
+
+  pack_unsigned_long (value_contents_raw (val), type, num);
+
+  return val;
+}
+
+
 /* Create a value representing a pointer of type TYPE to the address
    ADDR.  */
 struct value *
@@ -2363,4 +2495,8 @@ VARIABLE is already initialized."));
   add_prefix_cmd ("function", no_class, function_command, _("\
 Placeholder command for showing help on convenience functions."),
 		  &functionlist, "function ", 0, &cmdlist);
+
+  make_final_cleanup (value_history_cleanup, NULL);
+
+  observer_attach_mark_used (value_types_mark_used);
 }
diff --git a/gdb/value.h b/gdb/value.h
index 1f2086e..dd503ad 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -342,11 +342,16 @@ extern LONGEST unpack_field_as_long (struct type *type,
 extern void pack_long (gdb_byte *buf, struct type *type, LONGEST num);
 
 extern struct value *value_from_longest (struct type *type, LONGEST num);
+extern struct value *value_from_ulongest (struct type *type, ULONGEST num);
 extern struct value *value_from_pointer (struct type *type, CORE_ADDR addr);
 extern struct value *value_from_double (struct type *type, DOUBLEST num);
 extern struct value *value_from_decfloat (struct type *type,
 					  const gdb_byte *decbytes);
 
+extern const char *object_address_data_not_valid (struct type *type);
+extern int object_address_get_data (struct type *type,
+				    CORE_ADDR *address_return);
+
 extern struct value *value_at (struct type *type, CORE_ADDR addr);
 extern struct value *value_at_lazy (struct type *type, CORE_ADDR addr);
 
@@ -694,7 +699,7 @@ extern struct value *value_allocate_space_in_inferior (int);
 extern struct value *value_of_local (const char *name, int complain);
 
 extern struct value *value_subscripted_rvalue (struct value *array,
-					       LONGEST index, int lowerbound);
+					       CORE_ADDR offset);
 
 /* User function handler.  */
 
diff --git a/gdb/varobj.c b/gdb/varobj.c
index b4b2461..3a7a884 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -26,6 +26,8 @@
 #include "gdbcmd.h"
 #include "block.h"
 #include "valprint.h"
+#include "objfiles.h"
+#include "parser-defs.h"
 
 #include "gdb_assert.h"
 #include "gdb_string.h"
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index acd7b50..0929a33 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -3030,6 +3030,7 @@ static struct sym_fns xcoff_sym_fns =
   xcoff_new_init,		/* sym_new_init: init anything gbl to entire symtab */
   xcoff_symfile_init,		/* sym_init: read initial info, setup for sym_read() */
   xcoff_initial_scan,		/* sym_read: read a symbol file into symtab */
+  NULL,				/* sym_read_psymbols */
   xcoff_symfile_finish,		/* sym_finish: finished with file, cleanup */
   xcoff_symfile_offsets,	/* sym_offsets: xlate offsets ext->int form */
   default_symfile_segments,	/* sym_segments: Get segment information from
diff --git a/gdb/xtensa-linux-tdep.c b/gdb/xtensa-linux-tdep.c
index 667d9b3..0d86219 100644
--- a/gdb/xtensa-linux-tdep.c
+++ b/gdb/xtensa-linux-tdep.c
@@ -22,6 +22,7 @@
 
 #include "solib-svr4.h"
 #include "symtab.h"
+#include "linux-tdep.h"
 
 /* OS specific initialization of gdbarch.  */
 
@@ -30,6 +31,9 @@ xtensa_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
   set_solib_svr4_fetch_link_map_offsets
     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+
+  set_gdbarch_convert_from_func_ptr_addr (gdbarch,
+					  linux_convert_from_func_ptr_addr);
 }
 
 /* Provide a prototype to silence -Wmissing-prototypes.  */