This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Add proper handling for non-local references in nested functions


Pedro,

On 03/10/2015 04:25 PM, Pedro Alves wrote:
I would have helped this reader to include an example of "non-local references
in nested subprograms" in the mail body :-)  Given the reference to
"subprograms" in the subject, I assumed this was an Ada-specific
patch.  I happened to skim the patch anyway, until I saw at the end
that this also handles C nested functions.  Nice!  :-)

Oh indeed, sorry about that! Being used to "subprogram" in the Ada world, I thought it was a better match, but never mind: I've replaced all occurences with "function" instead. Thanks for having had a look at the patch anyway. ;-)

Right, that's a problem.  We've been moving in the opposite direction...
The block knows which symbols it has inside.  When we look up symbols,
we always know which block we're searching the symbols in...  If
you need to know which block a symbol look up found a symbol in,
there's the "block_found" for that.  That's obviously an ugly hack, but
it's there and so you can use it.

I knew about the "block_found" alternative: I nevertheless tried to avoid it because I believed it was a better design to attach this information to symbols themselves... but of course runtime performance matters too. The updated patch switched to the "block_found" way: it makes the patch more complex but indeed it does not make the the symbol structure grow.

I left TODO's in the patch, though: in the Python user interface (for instance in Frame.read_var), we sometimes accept gdb.Symbol objects and end up reading the corresponding variables. In such cases, we cannot use block_found since the lookup was done possibly a long time before; on the other hand there's almost always a gdb.Block argument around, so I guess we expect Python developpers to keep track of blocks corresponding to their symbols... which sounds wrong to me. It's okay for performance not to store blocks in GDB internal symbols data structures but on the other hand I don't think we should expose this design tweak in a public API.

I did not try it because it implies a kind of API change: what about storing the origin block in gdb.Symbol instances? My guess is that the size of gdb.Symbol is not as critical as for struct symbol. The block arguments in the Python API would then be used only when a string is passed instead of a gdb.Symbol. This would also fix the problem we still have for gdb.Symbol.value, which does not take any block argument. Thoughts?

If someone is motivated to clean this up, it'd be better to make the
symbol lookup functions return a structure that included both symbol
and block (and maybe more), in the spirit of struct
bound_minimal_symbol:

This would look cleaner indeed. It's a big change itself though so if most consider this as a good idea I don't mind doing it... although it would be for another commit!

For the block->static_link case, maybe put the static link chain
in a separate hash indexed by block?

This is what I did in the updated patch: I don't think there's a realistic use case for gdbarch-owned block having a static link so I added a hashed table to all objfiles. It's indexed by blocks and contains static links for these (if they have one). Then we perform lookups when reading variables...

Thank you for your review, Pedro! :-)

gdb/ChangeLog:
2015-03-20  Pierre-Marie de Rodat  <derodat@adacore.com>

* ada-lang.c (ada_read_var_value): Add a VAR_BLOCK argument and pass
        it to default_read_var_value.
        * block.c (block_static_link): New accessor.
        * block.h (block_static_link): Declare it.
        * buildsym.c (finish_block_internal): Add a static_link
        argument.  If there is a static link, associate it to the new
        block.
        (finish_block): Add a static link argument and pass it to
        finish_block_internal.
        (end_symtab_get_static_block): Update calls to finish_block and
        to finish_block_internal.
        (end_symtab_with_blockvector): Update call to
        finish_block_internal.
        * buildsym.h: Forward-declare struct dynamic_prop.
        (struct context_stack): Add a static_link field.
        (finish_block): Add a static link argument.
        * coffread.c (coff_symtab_read): Update calls to finish_block.
        * dbxread.c (process_one_symbol): Likewise.
        * xcoffread.c (read_xcoff_symtab): Likewise.
        * compile/compile-c-symbols.c (convert_one_symbol): Add a
        VAR_BLOCK parameter and pass it to calls to read_var_value.
        (convert_symbol_sym): Pass the block corresponding to SYM to the
        call to convert_one_symbol.
        * compile/compile-loc2c.c (do_compile_dwarf_expr_to_c): Update
        call to read_var_value.
        * dwarf2loc.c (block_op_get_frame_base): New.
        (dwarf2_block_frame_base_locexpr_funcs): Implement the
        get_frame_base method.
        (dwarf2_block_frame_base_loclist_funcs): Likewise.
        (dwarf2locexpr_baton_eval): Add a frame argument and use it
        instead of the selected frame in order to evaluate the
        expression.
        (dwarf2_evaluate_property): Add a frame argument.  Update call
        to dwarf2_locexpr_baton_eval to provide a frame in available and
        to handle the absence of address stack.
        * dwarf2loc.h (dwarf2_evaluate_property): Add a frame argument.
        * dwarf2read.c (attr_to_dynamic_prop): Add a forward
        declaration.
        (read_func_scope): Record any available static link description.
        Update call to finish_block.
        (read_lexical_block_scope): Update call to finish_block.
        * findvar.c (follow_static_link): New.
        (get_hosting_frame): New.
        (default_read_var_value): Add a VAR_BLOCK argument.  Use
        get_hosting_frame to handle non-local references.
        (read_var_value): Add a VAR_BLOCK argument and pass it to the
        LA_READ_VAR_VALUE method.
        * gdbtypes.c (resolve_dynamic_range): Update calls to
        dwarf2_evaluate_property.
        (resolve_dynamic_type_internal): Likewise.
        * infcmd.c (finish_command_continuation): Update call to
        read_var_value.
        * infrun.c (insert_exception_resume_breakpoint): Likewise.
        * language.h (struct language_defn): Add a VAR_BLOCK argument to
        the LA_READ_VAR_VALUE method.
        * objfiles.c (objfile_register_static_link): New.
        (objfile_lookup_static_link): New.
        (free_objfile): Free the STATIC_LINKS hashed map if needed.
        * objfiles.h: Include hashtab.h.
        (struct objfile): Add a STATIC_LINKS field.
        (objfile_register_static_link): New.
        (objfile_lookup_static_link): New.
        * printcmd.c (print_variable_and_value): Update call to
        read_var_value.
        * python/py-finishbreakpoint.c (bpfinishpy_init): Likewise.
        * python/py-frame.c (frapy_read_var): Pass the block found to
        read_var_value.
        * python/py-framefilter.c (extract_sym): Add a SYM_BLOCK
        parameter and set the pointed value to NULL (TODO).
        (enumerate_args): Update call to extract_sym.
        (enumerate_locals): Update calls to extract_sym and to
        read_var_value.
        * python/py-symbol.c (sympy_value): Update call to
        read_var_value (TODO).
        * stack.c (read_frame_local): Update call to read_var_value.
        (read_frame_arg): Likewise.
        (return_command): Likewise.
        * symtab.h (struct symbol_block_ops): Add a get_frame_base
        method.
        (struct symbol): Add a block field.
        (SYMBOL_BLOCK): New accessor.
        * valops.c (find_function_in_inferior): Pass the block found to
        value_of_variable.
        (value_of_variable): Remove frame/block handling and pass the
        block argument to read_var_value, which does this job now.
        (value_struct_elt_for_reference): Update calls to
        read_var_value.
        (value_of_this): Pass the block found to read_var_value.
        * value.c (value_static_field): Likewise.
        * value.h (read_var_value): Add a VAR_BLOCK argument.
        (default_read_var_value): Likewise.

gdb/testsuite/ChangeLog:
2015-03-20  Pierre-Marie de Rodat  <derodat@adacore.com>

        * gdb.base/nested-subp1.exp: New file.
        * gdb.base/nested-subp1.c: New file.
        * gdb.base/nested-subp2.exp: New file.
        * gdb.base/nested-subp2.c: New file.
        * gdb.base/nested-subp3.exp: New file.
        * gdb.base/nested-subp3.c: New file.

--
Pierre-Marie de Rodat
>From 24b0a788e642e892b5efb467bed627c7585662a7 Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <derodat@adacore.com>
Date: Thu, 5 Feb 2015 17:00:06 +0100
Subject: [PATCH] DWARF: handle non-local references in nested functions

GDB's current behavior when dealing with non-local references in the
context of nested fuctions is approximative:

  - code using valops.c:value_of_variable read the first available stack
    frame that holds the corresponding variable (whereas there can be
    multiple candidates for this);

  - code directly relying on read_var_value will instead read non-local
    variables in frames where they are not even defined.

This change adds the necessary context to symbol reads (to get the block
they belong to) and to blocks (the static link property, if any) so that
GDB can make the proper decisions when dealing with non-local varibale
references.

gdb/ChangeLog:
2015-03-20  Pierre-Marie de Rodat  <derodat@adacore.com>

	* ada-lang.c (ada_read_var_value): Add a VAR_BLOCK argument and pass
	it to default_read_var_value.
	* block.c (block_static_link): New accessor.
	* block.h (block_static_link): Declare it.
	* buildsym.c (finish_block_internal): Add a static_link
	argument.  If there is a static link, associate it to the new
	block.
	(finish_block): Add a static link argument and pass it to
	finish_block_internal.
	(end_symtab_get_static_block): Update calls to finish_block and
	to finish_block_internal.
	(end_symtab_with_blockvector): Update call to
	finish_block_internal.
	* buildsym.h: Forward-declare struct dynamic_prop.
	(struct context_stack): Add a static_link field.
	(finish_block): Add a static link argument.
	* coffread.c (coff_symtab_read): Update calls to finish_block.
	* dbxread.c (process_one_symbol): Likewise.
	* xcoffread.c (read_xcoff_symtab): Likewise.
	* compile/compile-c-symbols.c (convert_one_symbol): Add a
	VAR_BLOCK parameter and pass it to calls to read_var_value.
	(convert_symbol_sym): Pass the block corresponding to SYM to the
	call to convert_one_symbol.
	* compile/compile-loc2c.c (do_compile_dwarf_expr_to_c): Update
	call to read_var_value.
	* dwarf2loc.c (block_op_get_frame_base): New.
	(dwarf2_block_frame_base_locexpr_funcs): Implement the
	get_frame_base method.
	(dwarf2_block_frame_base_loclist_funcs): Likewise.
	(dwarf2locexpr_baton_eval): Add a frame argument and use it
	instead of the selected frame in order to evaluate the
	expression.
	(dwarf2_evaluate_property): Add a frame argument.  Update call
	to dwarf2_locexpr_baton_eval to provide a frame in available and
	to handle the absence of address stack.
	* dwarf2loc.h (dwarf2_evaluate_property): Add a frame argument.
	* dwarf2read.c (attr_to_dynamic_prop): Add a forward
	declaration.
	(read_func_scope): Record any available static link description.
	Update call to finish_block.
	(read_lexical_block_scope): Update call to finish_block.
	* findvar.c (follow_static_link): New.
	(get_hosting_frame): New.
	(default_read_var_value): Add a VAR_BLOCK argument.  Use
	get_hosting_frame to handle non-local references.
	(read_var_value): Add a VAR_BLOCK argument and pass it to the
	LA_READ_VAR_VALUE method.
	* gdbtypes.c (resolve_dynamic_range): Update calls to
	dwarf2_evaluate_property.
	(resolve_dynamic_type_internal): Likewise.
	* infcmd.c (finish_command_continuation): Update call to
	read_var_value.
	* infrun.c (insert_exception_resume_breakpoint): Likewise.
	* language.h (struct language_defn): Add a VAR_BLOCK argument to
	the LA_READ_VAR_VALUE method.
	* objfiles.c (objfile_register_static_link): New.
	(objfile_lookup_static_link): New.
	(free_objfile): Free the STATIC_LINKS hashed map if needed.
	* objfiles.h: Include hashtab.h.
	(struct objfile): Add a STATIC_LINKS field.
	(objfile_register_static_link): New.
	(objfile_lookup_static_link): New.
	* printcmd.c (print_variable_and_value): Update call to
	read_var_value.
	* python/py-finishbreakpoint.c (bpfinishpy_init): Likewise.
	* python/py-frame.c (frapy_read_var): Pass the block found to
	read_var_value.
	* python/py-framefilter.c (extract_sym): Add a SYM_BLOCK
	parameter and set the pointed value to NULL (TODO).
	(enumerate_args): Update call to extract_sym.
	(enumerate_locals): Update calls to extract_sym and to
	read_var_value.
	* python/py-symbol.c (sympy_value): Update call to
	read_var_value (TODO).
	* stack.c (read_frame_local): Update call to read_var_value.
	(read_frame_arg): Likewise.
	(return_command): Likewise.
	* symtab.h (struct symbol_block_ops): Add a get_frame_base
	method.
	(struct symbol): Add a block field.
	(SYMBOL_BLOCK): New accessor.
	* valops.c (find_function_in_inferior): Pass the block found to
	value_of_variable.
	(value_of_variable): Remove frame/block handling and pass the
	block argument to read_var_value, which does this job now.
	(value_struct_elt_for_reference): Update calls to
	read_var_value.
	(value_of_this): Pass the block found to read_var_value.
	* value.c (value_static_field): Likewise.
	* value.h (read_var_value): Add a VAR_BLOCK argument.
	(default_read_var_value): Likewise.

gdb/testsuite/ChangeLog:
2015-03-20  Pierre-Marie de Rodat  <derodat@adacore.com>

	* gdb.base/nested-subp1.exp: New file.
	* gdb.base/nested-subp1.c: New file.
	* gdb.base/nested-subp2.exp: New file.
	* gdb.base/nested-subp2.c: New file.
	* gdb.base/nested-subp3.exp: New file.
	* gdb.base/nested-subp3.c: New file.
---
 gdb/ada-lang.c                          |   5 +-
 gdb/block.c                             |  13 +++
 gdb/block.h                             |   2 +
 gdb/buildsym.c                          |  17 ++--
 gdb/buildsym.h                          |  14 ++-
 gdb/coffread.c                          |   4 +-
 gdb/compile/compile-c-symbols.c         |  18 ++--
 gdb/compile/compile-loc2c.c             |   2 +-
 gdb/dbxread.c                           |   8 +-
 gdb/dwarf2loc.c                         |  52 ++++++++--
 gdb/dwarf2loc.h                         |  11 ++-
 gdb/dwarf2read.c                        |  19 +++-
 gdb/findvar.c                           | 168 +++++++++++++++++++++++++++++++-
 gdb/gdbtypes.c                          |   6 +-
 gdb/infcmd.c                            |   2 +-
 gdb/infrun.c                            |   2 +-
 gdb/language.h                          |  12 ++-
 gdb/objfiles.c                          |  36 +++++++
 gdb/objfiles.h                          |  18 ++++
 gdb/printcmd.c                          |   6 +-
 gdb/python/py-finishbreakpoint.c        |   2 +-
 gdb/python/py-frame.c                   |   5 +-
 gdb/python/py-framefilter.c             |  28 ++++--
 gdb/python/py-symbol.c                  |   5 +-
 gdb/stack.c                             |   8 +-
 gdb/symtab.h                            |  18 ++++
 gdb/testsuite/gdb.base/nested-subp1.c   |  35 +++++++
 gdb/testsuite/gdb.base/nested-subp1.exp |  58 +++++++++++
 gdb/testsuite/gdb.base/nested-subp2.c   |  45 +++++++++
 gdb/testsuite/gdb.base/nested-subp2.exp |  67 +++++++++++++
 gdb/testsuite/gdb.base/nested-subp3.c   |  66 +++++++++++++
 gdb/testsuite/gdb.base/nested-subp3.exp |  60 ++++++++++++
 gdb/valops.c                            |  33 ++-----
 gdb/value.c                             |   3 +-
 gdb/value.h                             |   2 +
 gdb/xcoffread.c                         |   4 +-
 36 files changed, 758 insertions(+), 96 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/nested-subp1.c
 create mode 100644 gdb/testsuite/gdb.base/nested-subp1.exp
 create mode 100644 gdb/testsuite/gdb.base/nested-subp2.c
 create mode 100644 gdb/testsuite/gdb.base/nested-subp2.exp
 create mode 100644 gdb/testsuite/gdb.base/nested-subp3.c
 create mode 100644 gdb/testsuite/gdb.base/nested-subp3.exp

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 124e370..a88d7c1 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -13625,7 +13625,8 @@ ada_get_symbol_name_cmp (const char *lookup_name)
 /* Implement the "la_read_var_value" language_defn method for Ada.  */
 
 static struct value *
-ada_read_var_value (struct symbol *var, struct frame_info *frame)
+ada_read_var_value (struct symbol *var, const struct block *var_block,
+		    struct frame_info *frame)
 {
   const struct block *frame_block = NULL;
   struct symbol *renaming_sym = NULL;
@@ -13641,7 +13642,7 @@ ada_read_var_value (struct symbol *var, struct frame_info *frame)
 
   /* This is a typical case where we expect the default_read_var_value
      function to work.  */
-  return default_read_var_value (var, frame);
+  return default_read_var_value (var, var_block, frame);
 }
 
 const struct language_defn ada_language_defn = {
diff --git a/gdb/block.c b/gdb/block.c
index 00a7012..db2e868 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -428,6 +428,19 @@ set_block_compunit_symtab (struct block *block, struct compunit_symtab *cu)
   gb->compunit_symtab = cu;
 }
 
+struct dynamic_prop *
+block_static_link (const struct block *block)
+{
+  struct objfile *objfile = block_objfile (block);
+
+  /* Only objfile-owned blocks that materialize top function scopes can have
+     static links.  */
+  if (objfile == NULL || BLOCK_FUNCTION (block) == NULL)
+    return NULL;
+
+  return (struct dynamic_prop *) objfile_lookup_static_link (objfile, block);
+}
+
 /* Return the compunit of the global block.  */
 
 static struct compunit_symtab *
diff --git a/gdb/block.h b/gdb/block.h
index bdc5888..5f0ccf3 100644
--- a/gdb/block.h
+++ b/gdb/block.h
@@ -190,6 +190,8 @@ extern struct block *allocate_global_block (struct obstack *obstack);
 extern void set_block_compunit_symtab (struct block *,
 				       struct compunit_symtab *);
 
+extern struct dynamic_prop *block_static_link (const struct block *block);
+
 /* A block iterator.  This structure should be treated as though it
    were opaque; it is only defined here because we want to support
    stack allocation of iterators.  */
diff --git a/gdb/buildsym.c b/gdb/buildsym.c
index 2a24a25..a2be2cb 100644
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -331,7 +331,8 @@ free_pending_blocks (void)
    file).  Put the block on the list of pending blocks.  */
 
 static struct block *
-finish_block_internal (struct symbol *symbol, struct pending **listhead,
+finish_block_internal (struct symbol *symbol, struct dynamic_prop *static_link,
+		       struct pending **listhead,
 		       struct pending_block *old_blocks,
 		       CORE_ADDR start, CORE_ADDR end,
 		       int is_global, int expandable)
@@ -422,6 +423,9 @@ finish_block_internal (struct symbol *symbol, struct pending **listhead,
       BLOCK_FUNCTION (block) = NULL;
     }
 
+  if (static_link != NULL)
+    objfile_register_static_link (objfile, block, static_link);
+
   /* Now "free" the links of the list, and empty the list.  */
 
   for (next = *listhead; next; next = next1)
@@ -512,11 +516,12 @@ finish_block_internal (struct symbol *symbol, struct pending **listhead,
 }
 
 struct block *
-finish_block (struct symbol *symbol, struct pending **listhead,
+finish_block (struct symbol *symbol, struct dynamic_prop *static_link,
+	      struct pending **listhead,
 	      struct pending_block *old_blocks,
 	      CORE_ADDR start, CORE_ADDR end)
 {
-  return finish_block_internal (symbol, listhead, old_blocks,
+  return finish_block_internal (symbol, static_link, listhead, old_blocks,
 				start, end, 0, 0);
 }
 
@@ -1218,7 +1223,7 @@ end_symtab_get_static_block (CORE_ADDR end_addr, int expandable, int required)
       struct context_stack *cstk = pop_context ();
 
       /* Make a block for the local symbols within.  */
-      finish_block (cstk->name, &local_symbols, cstk->old_blocks,
+      finish_block (cstk->name, NULL, &local_symbols, cstk->old_blocks,
 		    cstk->start_addr, end_addr);
 
       if (context_stack_depth > 0)
@@ -1289,7 +1294,7 @@ end_symtab_get_static_block (CORE_ADDR end_addr, int expandable, int required)
   else
     {
       /* Define the STATIC_BLOCK.  */
-      return finish_block_internal (NULL, &file_symbols, NULL,
+      return finish_block_internal (NULL, NULL, &file_symbols, NULL,
 				    last_source_start_addr, end_addr,
 				    0, expandable);
     }
@@ -1317,7 +1322,7 @@ end_symtab_with_blockvector (struct block *static_block,
   end_addr = BLOCK_END (static_block);
 
   /* Create the GLOBAL_BLOCK and build the blockvector.  */
-  finish_block_internal (NULL, &global_symbols, NULL,
+  finish_block_internal (NULL, NULL, &global_symbols, NULL,
 			 last_source_start_addr, end_addr,
 			 1, expandable);
   blockvector = make_blockvector ();
diff --git a/gdb/buildsym.h b/gdb/buildsym.h
index f98203e..8828ad2 100644
--- a/gdb/buildsym.h
+++ b/gdb/buildsym.h
@@ -39,6 +39,8 @@ struct compunit_symtab;
 struct block;
 struct pending_block;
 
+struct dynamic_prop;
+
 #ifndef EXTERN
 #define	EXTERN extern
 #endif
@@ -141,6 +143,11 @@ struct context_stack
 
     struct symbol *name;
 
+    /* Expression that computes the frame base of the lexically enclosing
+       function, if any.  NULL otherwise.  */
+
+    struct dynamic_prop *static_link;
+
     /* PC where this context starts */
 
     CORE_ADDR start_addr;
@@ -192,9 +199,10 @@ extern struct symbol *find_symbol_in_list (struct pending *list,
 					   char *name, int length);
 
 extern struct block *finish_block (struct symbol *symbol,
-                                   struct pending **listhead,
-                                   struct pending_block *old_blocks,
-                                   CORE_ADDR start, CORE_ADDR end);
+				   struct dynamic_prop *static_link,
+				   struct pending **listhead, struct
+				   pending_block *old_blocks, CORE_ADDR start,
+				   CORE_ADDR end);
 
 extern void record_block_range (struct block *,
                                 CORE_ADDR start, CORE_ADDR end_inclusive);
diff --git a/gdb/coffread.c b/gdb/coffread.c
index 28f7b18..894271c 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -1129,7 +1129,7 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms,
 		enter_linenos (fcn_line_ptr, fcn_first_line,
 			       fcn_last_line, objfile);
 
-	      finish_block (newobj->name, &local_symbols,
+	      finish_block (newobj->name, NULL, &local_symbols,
 			    newobj->old_blocks, newobj->start_addr,
 			    fcn_cs_saved.c_value
 			    + fcn_aux_saved.x_sym.x_misc.x_fsize
@@ -1173,7 +1173,7 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms,
 		    cs->c_value + ANOFFSET (objfile->section_offsets,
 					    SECT_OFF_TEXT (objfile));
 		  /* Make a block for the local symbols within.  */
-		  finish_block (0, &local_symbols, newobj->old_blocks,
+		  finish_block (0, NULL, &local_symbols, newobj->old_blocks,
 				newobj->start_addr, tmpaddr);
 		}
 	      /* Now pop locals of block just finished.  */
diff --git a/gdb/compile/compile-c-symbols.c b/gdb/compile/compile-c-symbols.c
index 15efeff..88fc65e 100644
--- a/gdb/compile/compile-c-symbols.c
+++ b/gdb/compile/compile-c-symbols.c
@@ -135,16 +135,16 @@ symbol_substitution_name (struct symbol *sym)
   return concat ("__", SYMBOL_NATURAL_NAME (sym), "_ptr", (char *) NULL);
 }
 
-/* Convert a given symbol, SYM, to the compiler's representation.
-   CONTEXT is the compiler instance.  IS_GLOBAL is true if the
-   symbol came from the global scope.  IS_LOCAL is true if the symbol
-   came from a local scope.  (Note that the two are not strictly
-   inverses because the symbol might have come from the static
-   scope.)  */
+/* Convert a given symbol, SYM (located in VAR_BLOCK, if any), to the
+   compiler's representation.  CONTEXT is the compiler instance.  IS_GLOBAL is
+   true if the symbol came from the global scope.  IS_LOCAL is true if the
+   symbol came from a local scope.  (Note that the two are not strictly
+   inverses because the symbol might have come from the static scope.)  */
 
 static void
 convert_one_symbol (struct compile_c_instance *context,
 		    struct symbol *sym,
+		    const struct block *var_block,
 		    int is_global,
 		    int is_local)
 {
@@ -248,7 +248,7 @@ convert_one_symbol (struct compile_c_instance *context,
 			 SYMBOL_PRINT_NAME (sym));
 	      }
 
-	    val = read_var_value (sym, frame);
+	    val = read_var_value (sym, var_block, frame);
 	    if (VALUE_LVAL (val) != lval_memory)
 	      error (_("Symbol \"%s\" cannot be used for compilation "
 		       "evaluation as its address has not been found."),
@@ -341,7 +341,7 @@ convert_symbol_sym (struct compile_c_instance *context, const char *identifier,
 	    fprintf_unfiltered (gdb_stdout,
 				"gcc_convert_symbol \"%s\": global symbol\n",
 				identifier);
-	  convert_one_symbol (context, global_sym, 1, 0);
+	  convert_one_symbol (context, global_sym, NULL, 1, 0);
 	}
     }
 
@@ -349,7 +349,7 @@ convert_symbol_sym (struct compile_c_instance *context, const char *identifier,
     fprintf_unfiltered (gdb_stdout,
 			"gcc_convert_symbol \"%s\": local symbol\n",
 			identifier);
-  convert_one_symbol (context, sym, 0, is_local_symbol);
+  convert_one_symbol (context, sym, found_block, 0, is_local_symbol);
 }
 
 /* Convert a minimal symbol to its gcc form.  CONTEXT is the compiler
diff --git a/gdb/compile/compile-loc2c.c b/gdb/compile/compile-loc2c.c
index 6a3615d..192671b 100644
--- a/gdb/compile/compile-loc2c.c
+++ b/gdb/compile/compile-loc2c.c
@@ -632,7 +632,7 @@ do_compile_dwarf_expr_to_c (int indent, struct ui_file *stream,
 		 "there is no selected frame"),
 	       SYMBOL_PRINT_NAME (sym));
 
-      val = read_var_value (sym, frame);
+      val = read_var_value (sym, NULL, frame);
       if (VALUE_LVAL (val) != lval_memory)
 	error (_("Symbol \"%s\" cannot be used for compilation evaluation "
 		 "as its address has not been found."),
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index c8f974f..1b92fed 100644
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -2782,8 +2782,8 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, char *name,
 	  newobj = pop_context ();
 
 	  /* Make a block for the local symbols within.  */
-	  block = finish_block (newobj->name, &local_symbols,
-				newobj->old_blocks,
+	  block = finish_block (newobj->name, NULL,
+				&local_symbols, newobj->old_blocks,
 				newobj->start_addr, newobj->start_addr + valu);
 
 	  /* For C++, set the block's scope.  */
@@ -2884,7 +2884,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, char *name,
 		  newobj->start_addr = valu;
 		}
 	      /* Make a block for the local symbols within.  */
-	      finish_block (0, &local_symbols, newobj->old_blocks,
+	      finish_block (0, NULL, &local_symbols, newobj->old_blocks,
 			    newobj->start_addr, valu);
 	    }
 	}
@@ -3186,7 +3186,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, char *name,
 
 		  newobj = pop_context ();
 		  /* Make a block for the local symbols within.  */
-		  block = finish_block (newobj->name, &local_symbols,
+		  block = finish_block (newobj->name, NULL, &local_symbols,
 					newobj->old_blocks, newobj->start_addr,
 					valu);
 
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index e674933..f0b8a14 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -381,12 +381,42 @@ locexpr_find_frame_base_location (struct symbol *framefunc, CORE_ADDR pc,
   *start = symbaton->data;
 }
 
+/* Implement the struct symbol_block_ops::get_frame_base method */
+
+static CORE_ADDR
+block_op_get_frame_base (struct symbol *framefunc, struct frame_info *frame)
+{
+  if (SYMBOL_BLOCK_OPS (framefunc)->find_frame_base_location != NULL)
+    {
+      struct gdbarch *gdbarch = get_frame_arch (frame);
+      struct type *type = builtin_type (gdbarch)->builtin_data_ptr;
+      struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (framefunc);
+      const gdb_byte *start;
+      size_t length;
+      struct value *result;
+
+      SYMBOL_BLOCK_OPS (framefunc)->find_frame_base_location
+        (framefunc, get_frame_pc (frame), &start, &length);
+      result = dwarf2_evaluate_loc_desc (type, frame, start, length,
+					 dlbaton->per_cu);
+
+      /* The DW_AT_frame_base attribute contains a location description which
+	 computes the base address itself.  However, the call to
+	 dwarf2_evaluate_loc_desc returns a value representing a variable at
+	 that address.  The frame base address is thus this variable's address.
+	 */
+      return value_address (result);
+    }
+  return 0;
+}
+
 /* Vector for inferior functions as represented by LOC_BLOCK, if the inferior
    function uses DWARF expression for its DW_AT_frame_base.  */
 
 const struct symbol_block_ops dwarf2_block_frame_base_locexpr_funcs =
 {
-  locexpr_find_frame_base_location
+  locexpr_find_frame_base_location,
+  block_op_get_frame_base
 };
 
 /* Implement find_frame_base_location method for LOC_BLOCK functions using
@@ -406,7 +436,8 @@ loclist_find_frame_base_location (struct symbol *framefunc, CORE_ADDR pc,
 
 const struct symbol_block_ops dwarf2_block_frame_base_loclist_funcs =
 {
-  loclist_find_frame_base_location
+  loclist_find_frame_base_location,
+  block_op_get_frame_base
 };
 
 /* See dwarf2loc.h.  */
@@ -2397,13 +2428,14 @@ dwarf2_evaluate_loc_desc (struct type *type, struct frame_info *frame,
 }
 
 /* Evaluates a dwarf expression and stores the result in VAL, expecting
-   that the dwarf expression only produces a single CORE_ADDR.  ADDR is a
-   context (location of a variable) and might be needed to evaluate the
-   location expression.
+   that the dwarf expression only produces a single CORE_ADDR.  FRAME is the
+   frame in which the expression is evaluated.  ADDR is a context (location of
+   a variable) and might be needed to evaluate the location expression.
    Returns 1 on success, 0 otherwise.   */
 
 static int
 dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
+			   struct frame_info *frame,
 			   CORE_ADDR addr,
 			   CORE_ADDR *valp)
 {
@@ -2418,7 +2450,7 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
   ctx = new_dwarf_expr_context ();
   cleanup = make_cleanup_free_dwarf_expr_context (ctx);
 
-  baton.frame = get_selected_frame (NULL);
+  baton.frame = frame;
   baton.per_cu = dlbaton->per_cu;
   baton.obj_address = addr;
 
@@ -2462,19 +2494,24 @@ dwarf2_locexpr_baton_eval (const struct dwarf2_locexpr_baton *dlbaton,
 
 int
 dwarf2_evaluate_property (const struct dynamic_prop *prop,
+			  struct frame_info *frame,
 			  struct property_addr_info *addr_stack,
 			  CORE_ADDR *value)
 {
   if (prop == NULL)
     return 0;
 
+  if (frame == NULL && has_stack_frames ())
+    frame = get_selected_frame (NULL);
+
   switch (prop->kind)
     {
     case PROP_LOCEXPR:
       {
 	const struct dwarf2_property_baton *baton = prop->data.baton;
 
-	if (dwarf2_locexpr_baton_eval (&baton->locexpr, addr_stack->addr,
+	if (dwarf2_locexpr_baton_eval (&baton->locexpr, frame,
+				       addr_stack ? addr_stack->addr : 0,
 				       value))
 	  {
 	    if (baton->referenced_type)
@@ -2491,7 +2528,6 @@ dwarf2_evaluate_property (const struct dynamic_prop *prop,
     case PROP_LOCLIST:
       {
 	struct dwarf2_property_baton *baton = prop->data.baton;
-	struct frame_info *frame = get_selected_frame (NULL);
 	CORE_ADDR pc = get_frame_address_in_block (frame);
 	const gdb_byte *data;
 	struct value *val;
diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h
index 0932456..234e5ef 100644
--- a/gdb/dwarf2loc.h
+++ b/gdb/dwarf2loc.h
@@ -119,12 +119,19 @@ struct property_addr_info
   struct property_addr_info *next;
 };
 
-/* Converts a dynamic property into a static one.  ADDR_STACK is the stack
-   of addresses that might be needed to evaluate the property.
+/* Converts a dynamic property into a static one.  FRAME is the frame in which
+   the property is evaluated; if NULL, the selected frame (if any) is used
+   instead.
+
+   ADDR_STACK is the stack of addresses that might be needed to evaluate the
+   property. When evaluating a property that is not related to a type, it can
+   be NULL.
+
    Returns 1 if PROP could be converted and the static value is passed back
    into VALUE, otherwise returns 0.  */
 
 int dwarf2_evaluate_property (const struct dynamic_prop *prop,
+			      struct frame_info *frame,
 			      struct property_addr_info *addr_stack,
 			      CORE_ADDR *value);
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index c185d51..8a1a3c7 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -1728,6 +1728,10 @@ static void load_full_type_unit (struct dwarf2_per_cu_data *per_cu);
 
 static void read_signatured_type (struct signatured_type *);
 
+static int attr_to_dynamic_prop (const struct attribute *attr,
+				 struct die_info *die, struct dwarf2_cu *cu,
+				 struct dynamic_prop *prop);
+
 /* memory allocation interface */
 
 static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *);
@@ -11363,6 +11367,16 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
   if (attr)
     dwarf2_symbol_mark_computed (attr, newobj->name, cu, 1);
 
+  /* If there is a location for the static link, record it.  */
+  newobj->static_link = NULL;
+  attr = dwarf2_attr (die, DW_AT_static_link, cu);
+  if (attr)
+    {
+      newobj->static_link = obstack_alloc (&objfile->objfile_obstack,
+					sizeof (*newobj->static_link));
+      attr_to_dynamic_prop (attr, die, cu, newobj->static_link);
+    }
+
   cu->list_in_scope = &local_symbols;
 
   if (die->child != NULL)
@@ -11413,7 +11427,8 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
 
   newobj = pop_context ();
   /* Make a block for the local symbols within.  */
-  block = finish_block (newobj->name, &local_symbols, newobj->old_blocks,
+  block = finish_block (newobj->name, &newobj->static_link,
+			&local_symbols, newobj->old_blocks,
                         lowpc, highpc);
 
   /* For C++, set the block's scope.  */
@@ -11496,7 +11511,7 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
   if (local_symbols != NULL || using_directives != NULL)
     {
       struct block *block
-        = finish_block (0, &local_symbols, newobj->old_blocks,
+        = finish_block (0, NULL, &local_symbols, newobj->old_blocks,
 			newobj->start_addr, highpc);
 
       /* Note that recording ranges after traversing children, as we
diff --git a/gdb/findvar.c b/gdb/findvar.c
index 128bf5e..5443b70 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -32,6 +32,7 @@
 #include "block.h"
 #include "objfiles.h"
 #include "language.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
@@ -409,11 +410,166 @@ minsym_lookup_iterator_cb (struct objfile *objfile, void *cb_data)
   return (data->result.minsym != NULL);
 }
 
+/* Given static link expression and the frame it lives in, look for the frame
+   the static links points to and return it.  Return NULL if we could not find
+   such a frame.   */
+
+static struct frame_info *
+follow_static_link (struct frame_info *frame,
+		    const struct dynamic_prop *static_link)
+{
+  CORE_ADDR upper_frame_base;
+
+  if (!dwarf2_evaluate_property (static_link, frame, NULL, &upper_frame_base))
+    return NULL;
+
+  /* Now climb up the stack frame until we reach the frame we are interested
+     in.  */
+  for (; frame != NULL; frame = get_prev_frame (frame))
+    {
+      struct symbol *framefunc = get_frame_function (frame);
+
+      /* Protect ourselves against bad things such as circular call stacks.  */
+      QUIT;
+
+      /* If we don't know how to compute FRAME's base address, don't give up:
+	 maybe the frame we are looking for is upper in the stace frame.  */
+      if (framefunc != NULL
+	  && SYMBOL_BLOCK_OPS (framefunc)->get_frame_base
+	  && (SYMBOL_BLOCK_OPS (framefunc)->get_frame_base (framefunc, frame)
+	      == upper_frame_base))
+	break;
+    }
+
+  return frame;
+}
+
+/* Assuming VAR is a symbol that can be reached from FRAME thanks to lexical
+   rules, look for the frame that is actually hosting VAR and return it.  If,
+   for some reason, we found no such frame, return NULL.
+
+   This kind of computation is necessary to correctly handle lexically nested
+   functions.
+
+   Note that in some cases, we know what scope VAR comes from but we cannot
+   reach the specific frame that hosts the instance of VAR we are looking for.
+   For backward compatibility purposes (with old compilers), we then look for
+   the first frame that can host it.  */
+
+static struct frame_info *
+get_hosting_frame (struct symbol *var, const struct block *var_block,
+		   struct frame_info *frame)
+{
+  const struct block *frame_block;
+
+  if (!symbol_read_needs_frame (var))
+    return NULL;
+
+  /* Some symbols for local variables have no block: this happens when they are
+     not produced by a debug information reader, for instance when GDB creates
+     synthetic symbols.  Without block information, we must assume they are
+     local to FRAME. In this case, there is nothing to do.  */
+  else if (var_block == NULL)
+    return frame;
+
+  /* We currently assume that all symbols with a location list need a frame.
+     This is true in practice because selecting the location description
+     requires to compute the CFA, hence requires a frame.  However we have
+     tests that embed global/static symbols with null location lists.
+     We want to get <optimized out> instead of <frame required> when evaluating
+     them so return a frame instead of raising an error.  */
+  else if (var_block == block_global_block (var_block)
+	   || var_block == block_static_block (var_block))
+    return frame;
+
+  /* We have to handle the "my_func::my_local_var" notation.  This requires us
+     to look for upper frames when we find no block for the current frame: here
+     and below, handle when frame_block == NULL.  */
+  if (frame != NULL)
+    frame_block = get_frame_block (frame, NULL);
+
+  /* Climb up the call stack until reaching the frame we are looking for.  */
+  while (frame != NULL && frame_block != var_block)
+    {
+      /* Protect ourselves against bad things such as circular call stacks.  */
+      QUIT;
+
+      if (frame_block == NULL)
+	{
+	  frame = get_prev_frame (frame);
+	  if (frame == NULL)
+	    break;
+	  frame_block = get_frame_block (frame, NULL);
+	}
+
+      /* If we failed to find the proper frame, fallback to the heuristic
+	 method below.  */
+      else if (frame_block == block_global_block (frame_block))
+	{
+	  frame = NULL;
+	  break;
+	}
+
+      /* Assuming we have a block for this frame: if we are at the function
+	 level, the immediate upper lexical block is in an outer function:
+	 follow the static link.  */
+      else if (BLOCK_FUNCTION (frame_block))
+	{
+	  const struct dynamic_prop *static_link
+	    = block_static_link (frame_block);
+	  int could_climb_up = 0;
+
+	  if (static_link != NULL)
+	    {
+	      frame = follow_static_link (frame, static_link);
+	      if (frame != NULL)
+		{
+		  frame_block = get_frame_block (frame, NULL);
+		  could_climb_up = frame_block != NULL;
+		}
+	    }
+	  if (!could_climb_up)
+	    {
+	      frame = NULL;
+	      break;
+	    }
+	}
+
+      else
+	/* We must be in some function nested lexical block.  Just get the
+	   outer block: both must share the same frame.  */
+	frame_block = BLOCK_SUPERBLOCK (frame_block);
+    }
+
+  /* Old compilers may not provide a static link, or they may provide an
+     invalid one.  For such cases, fallback on the old way to evaluate
+     non-local references: just climb up the call stack and pick the first
+     frame that contains the variable we are looking for.  */
+  if (frame == NULL)
+    {
+      frame = block_innermost_frame (var_block);
+      if (!frame)
+	{
+	  if (BLOCK_FUNCTION (var_block)
+	      && !block_inlined_p (var_block)
+	      && SYMBOL_PRINT_NAME (BLOCK_FUNCTION (var_block)))
+	    error (_("No frame is currently executing in block %s."),
+		   SYMBOL_PRINT_NAME (BLOCK_FUNCTION (var_block)));
+	  else
+	    error (_("No frame is currently executing in specified"
+		     " block"));
+	}
+    }
+
+  return frame;
+}
+
 /* A default implementation for the "la_read_var_value" hook in
    the language vector which should work in most situations.  */
 
 struct value *
-default_read_var_value (struct symbol *var, struct frame_info *frame)
+default_read_var_value (struct symbol *var, const struct block *var_block,
+			struct frame_info *frame)
 {
   struct value *v;
   struct type *type = SYMBOL_TYPE (var);
@@ -427,7 +583,10 @@ default_read_var_value (struct symbol *var, struct frame_info *frame)
   check_typedef (type);
 
   if (symbol_read_needs_frame (var))
-    gdb_assert (frame);
+    gdb_assert (frame != NULL);
+
+  if (frame != NULL)
+    frame = get_hosting_frame (var, var_block, frame);
 
   if (SYMBOL_COMPUTED_OPS (var) != NULL)
     return SYMBOL_COMPUTED_OPS (var)->read_variable (var, frame);
@@ -610,14 +769,15 @@ default_read_var_value (struct symbol *var, struct frame_info *frame)
 /* Calls VAR's language la_read_var_value hook with the given arguments.  */
 
 struct value *
-read_var_value (struct symbol *var, struct frame_info *frame)
+read_var_value (struct symbol *var, const struct block *var_block,
+		struct frame_info *frame)
 {
   const struct language_defn *lang = language_def (SYMBOL_LANGUAGE (var));
 
   gdb_assert (lang != NULL);
   gdb_assert (lang->la_read_var_value != NULL);
 
-  return lang->la_read_var_value (var, frame);
+  return lang->la_read_var_value (var, var_block, frame);
 }
 
 /* Install default attributes for register values.  */
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 4cbbe95..93faca2 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -1835,7 +1835,7 @@ resolve_dynamic_range (struct type *dyn_range_type,
   gdb_assert (TYPE_CODE (dyn_range_type) == TYPE_CODE_RANGE);
 
   prop = &TYPE_RANGE_DATA (dyn_range_type)->low;
-  if (dwarf2_evaluate_property (prop, addr_stack, &value))
+  if (dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
     {
       low_bound.kind = PROP_CONST;
       low_bound.data.const_val = value;
@@ -1847,7 +1847,7 @@ resolve_dynamic_range (struct type *dyn_range_type,
     }
 
   prop = &TYPE_RANGE_DATA (dyn_range_type)->high;
-  if (dwarf2_evaluate_property (prop, addr_stack, &value))
+  if (dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
     {
       high_bound.kind = PROP_CONST;
       high_bound.data.const_val = value;
@@ -2080,7 +2080,7 @@ resolve_dynamic_type_internal (struct type *type,
 
   /* Resolve data_location attribute.  */
   prop = TYPE_DATA_LOCATION (resolved_type);
-  if (dwarf2_evaluate_property (prop, addr_stack, &value))
+  if (dwarf2_evaluate_property (prop, NULL, addr_stack, &value))
     {
       TYPE_DATA_LOCATION_ADDR (resolved_type) = value;
       TYPE_DATA_LOCATION_KIND (resolved_type) = PROP_CONST;
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 0211b5d..cbdce47 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1671,7 +1671,7 @@ finish_command_continuation (void *arg, int err)
 	    {
 	      struct value *func;
 
-	      func = read_var_value (a->function, get_current_frame ());
+	      func = read_var_value (a->function, NULL, get_current_frame ());
 	      TRY
 		{
 		  /* print_return_value can throw an exception in some
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 0f8f531..1beed93 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -6038,7 +6038,7 @@ insert_exception_resume_breakpoint (struct thread_info *tp,
       struct breakpoint *bp;
 
       vsym = lookup_symbol (SYMBOL_LINKAGE_NAME (sym), b, VAR_DOMAIN, NULL);
-      value = read_var_value (vsym, frame);
+      value = read_var_value (vsym, NULL, frame);
       /* If the value was optimized out, revert to the old behavior.  */
       if (! value_optimized_out (value))
 	{
diff --git a/gdb/language.h b/gdb/language.h
index 436fd6e..1ab0699 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -241,13 +241,19 @@ struct language_defn
     void (*la_value_print) (struct value *, struct ui_file *,
 			    const struct value_print_options *);
 
-    /* Given a symbol VAR, and a stack frame id FRAME, read the value
-       of the variable an return (pointer to a) struct value containing
-       the value.
+    /* Given a symbol VAR, the corresponding block VAR_BLOCK (if any) and a
+       stack frame id FRAME, read the value of the variable and return (pointer
+       to a) struct value containing the value.
+
+       VAR_BLOCK is needed there's a possibility for VAR to be outside FRAME.
+       This is what happens if FRAME correspond to a nested function and VAR is
+       defined in the outer function.  If callers know that VAR is located in
+       FRAME, NULL can be passed as VAR_BLOCK.
 
        Throw an error if the variable cannot be found.  */
 
     struct value *(*la_read_var_value) (struct symbol *var,
+					const struct block *var_block,
 					struct frame_info *frame);
 
     /* PC is possibly an unknown languages trampoline.
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index ff20bc8..152626f 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -199,6 +199,37 @@ set_objfile_main_name (struct objfile *objfile,
   objfile->per_bfd->language_of_main = lang;
 }
 
+/* Register STATIC_LINK as the static link for BLOCK, which is part of OBJFILE.
+   Must not be called more than once for each BLOCK.  */
+
+void
+objfile_register_static_link (struct objfile *objfile,
+			      const struct block *block,
+			      struct dynamic_prop *static_link)
+{
+  void **slot;
+
+  if (objfile->static_links == NULL)
+    objfile->static_links = htab_create_alloc
+      (1, htab_hash_pointer, htab_eq_pointer, NULL, xcalloc, xfree);
+
+  slot = htab_find_slot (objfile->static_links, block, INSERT);
+  gdb_assert (*slot == NULL);
+  *slot = static_link;
+}
+
+/* Look for a static link for BLOCK, which is part of OBJFILE.  Return NULL if
+   none was found.  */
+
+struct dynamic_prop *
+objfile_lookup_static_link (struct objfile *objfile,
+			    const struct block *block)
+{
+  if (objfile->static_links == NULL)
+    return NULL;
+  return htab_find (objfile->static_links, block);
+}
+
 
 
 /* Called via bfd_map_over_sections to build up the section table that
@@ -652,6 +683,11 @@ free_objfile (struct objfile *objfile)
   /* Rebuild section map next time we need it.  */
   get_objfile_pspace_data (objfile->pspace)->section_map_dirty = 1;
 
+  /* Free the map for static links.  There's no need to free static link
+     themselves since they were allocated on the objstack.  */
+  if (objfile->static_links != NULL)
+    htab_delete (objfile->static_links);
+
   /* The last thing we do is free the objfile struct itself.  */
   xfree (objfile);
 }
diff --git a/gdb/objfiles.h b/gdb/objfiles.h
index a0dc69b..aa2e966 100644
--- a/gdb/objfiles.h
+++ b/gdb/objfiles.h
@@ -20,6 +20,7 @@
 #if !defined (OBJFILES_H)
 #define OBJFILES_H
 
+#include "hashtab.h"
 #include "gdb_obstack.h"	/* For obstack internals.  */
 #include "symfile.h"		/* For struct psymbol_allocation_list.  */
 #include "progspace.h"
@@ -412,6 +413,16 @@ struct objfile
        table, so we have to keep them here to relocate them
        properly.  */
     struct symbol *template_symbols;
+
+    /* Associate a static link (struct dynamic_prop *) to all blocks (struct
+       block *) that have one.  For nested functions, the static link is the
+       expression that computes the frame base of the lexically enclosing
+       function.
+
+       Very few blocks have a static link, so it's more memory efficient to
+       store these here.  Static links must be allocated on the objfile's
+       obstack.  */
+    struct htab *static_links;
   };
 
 /* Defines for the objfile flag word.  */
@@ -719,4 +730,11 @@ extern const char *objfile_debug_name (const struct objfile *objfile);
 extern void set_objfile_main_name (struct objfile *objfile,
 				   const char *name, enum language lang);
 
+extern void objfile_register_static_link (struct objfile *objfile,
+					  const struct block *block,
+					  struct dynamic_prop *static_link);
+
+extern struct dynamic_prop *objfile_lookup_static_link
+  (struct objfile *objfile, const struct block *block);
+
 #endif /* !defined (OBJFILES_H) */
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index 05c68a0..46a8c9d 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -1990,7 +1990,11 @@ print_variable_and_value (const char *name, struct symbol *var,
       struct value *val;
       struct value_print_options opts;
 
-      val = read_var_value (var, frame);
+      /* READ_VAR_VALUE needs a block in order to deal with non-local
+	 references (i.e. to handlee nested functions). In this context, we
+	 print variables that are local to this frame, so we can avoid passing
+	 a block to it.  */
+      val = read_var_value (var, NULL, frame);
       get_user_print_options (&opts);
       opts.deref_ref = 1;
       common_val_print (val, stream, indent, &opts, current_language);
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
index 34e9643..9dca373 100644
--- a/gdb/python/py-finishbreakpoint.c
+++ b/gdb/python/py-finishbreakpoint.c
@@ -262,7 +262,7 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
                   /* Ignore Python errors at this stage.  */
                   self_bpfinish->return_type = type_to_type_object (ret_type);
                   PyErr_Clear ();
-                  func_value = read_var_value (function, frame);
+                  func_value = read_var_value (function, NULL, frame);
                   self_bpfinish->function_value =
                       value_to_value_object (func_value);
                   PyErr_Clear ();
diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index cd6e859..270c570 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -504,6 +504,7 @@ frapy_read_var (PyObject *self, PyObject *args)
   struct frame_info *frame;
   PyObject *sym_obj, *block_obj = NULL;
   struct symbol *var = NULL;	/* gcc-4.3.2 false warning.  */
+  const struct block *block = NULL;
   struct value *val = NULL;
 
   if (!PyArg_ParseTuple (args, "O|O", &sym_obj, &block_obj))
@@ -514,7 +515,6 @@ frapy_read_var (PyObject *self, PyObject *args)
   else if (gdbpy_is_string (sym_obj))
     {
       char *var_name;
-      const struct block *block = NULL;
       struct cleanup *cleanup;
 
       var_name = python_string_to_target_string (sym_obj);
@@ -541,6 +541,7 @@ frapy_read_var (PyObject *self, PyObject *args)
 	  if (!block)
 	    block = get_frame_block (frame, NULL);
 	  var = lookup_symbol (var_name, block, VAR_DOMAIN, NULL);
+	  block = block_found;
 	}
       CATCH (except, RETURN_MASK_ALL)
 	{
@@ -572,7 +573,7 @@ frapy_read_var (PyObject *self, PyObject *args)
     {
       FRAPY_REQUIRE_VALID (self, frame);
 
-      val = read_var_value (var, frame);
+      val = read_var_value (var, block, frame);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c
index e3336b1..397ac86 100644
--- a/gdb/python/py-framefilter.c
+++ b/gdb/python/py-framefilter.c
@@ -43,16 +43,17 @@ enum mi_print_types
    NAME is a  pass-through argument where the name of  the symbol will
    be written.  NAME is allocated in  this function, but the caller is
    responsible for clean up.  SYM is a pass-through argument where the
-   symbol will be written.  In the case of the API returning a string,
-   this will be set to NULL.  LANGUAGE is also a pass-through argument
-   denoting the language attributed to the Symbol.  In the case of SYM
-   being  NULL, this  will be  set to  the current  language.  Returns
-   EXT_LANG_BT_ERROR on error with the appropriate Python exception set, and
-   EXT_LANG_BT_OK on success.  */
+   symbol will be written and  SYM_BLOCK is a pass-through argument to
+   write  the block where the symbol lies in.  In the case of the  API
+   returning a  string,  this will be set to NULL.  LANGUAGE is also a
+   pass-through  argument  denoting  the  language  attributed  to the
+   Symbol.  In the case of SYM being  NULL, this  will be  set to  the
+   current  language.  Returns  EXT_LANG_BT_ERROR  on  error  with the
+   appropriate Python exception set, and EXT_LANG_BT_OK on success.  */
 
 static enum ext_lang_bt_status
 extract_sym (PyObject *obj, char **name, struct symbol **sym,
-	     const struct language_defn **language)
+	     struct block **sym_block, const struct language_defn **language)
 {
   PyObject *result = PyObject_CallMethod (obj, "symbol", NULL);
 
@@ -75,12 +76,17 @@ extract_sym (PyObject *obj, char **name, struct symbol **sym,
 	python_language.  */
       *language = python_language;
       *sym = NULL;
+      *sym_block = NULL;
     }
   else
     {
       /* This type checks 'result' during the conversion so we
 	 just call it unconditionally and check the return.  */
       *sym = symbol_object_to_symbol (result);
+      /* TODO:  How should we find the corresponding block for this symbol?
+	 Should we lookup all blocks in the owning objfile?  Should we store
+	 the bloc kin the Symbol object?  */
+      *sym_block = NULL;
 
       Py_DECREF (result);
 
@@ -537,10 +543,11 @@ enumerate_args (PyObject *iter,
       const struct language_defn *language;
       char *sym_name;
       struct symbol *sym;
+      struct block *sym_block;
       struct value *val;
       enum ext_lang_bt_status success = EXT_LANG_BT_ERROR;
 
-      success = extract_sym (item, &sym_name, &sym, &language);
+      success = extract_sym (item, &sym_name, &sym, &sym_block, &language);
       if (success == EXT_LANG_BT_ERROR)
 	{
 	  Py_DECREF (item);
@@ -736,12 +743,13 @@ enumerate_locals (PyObject *iter,
       struct value *val;
       enum ext_lang_bt_status success = EXT_LANG_BT_ERROR;
       struct symbol *sym;
+      struct block *sym_block;
       int local_indent = 8 + (8 * indent);
       struct cleanup *locals_cleanups;
 
       locals_cleanups = make_cleanup_py_decref (item);
 
-      success = extract_sym (item, &sym_name, &sym, &language);
+      success = extract_sym (item, &sym_name, &sym, &sym_block, &language);
       if (success == EXT_LANG_BT_ERROR)
 	{
 	  do_cleanups (locals_cleanups);
@@ -769,7 +777,7 @@ enumerate_locals (PyObject *iter,
 	{
 	  TRY
 	    {
-	      val = read_var_value (sym, frame);
+	      val = read_var_value (sym, sym_block, frame);
 	    }
 	  CATCH (except, RETURN_MASK_ERROR)
 	    {
diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c
index 4306f61..c8f7ecc 100644
--- a/gdb/python/py-symbol.c
+++ b/gdb/python/py-symbol.c
@@ -278,7 +278,10 @@ sympy_value (PyObject *self, PyObject *args)
       if (symbol_read_needs_frame (symbol) && frame_info == NULL)
 	error (_("symbol requires a frame to compute its value"));
 
-      value = read_var_value (symbol, frame_info);
+      /* TODO:  How should we find the corresponding block for this symbol?
+	 Should we lookup all blocks in the owning objfile?  Should we store
+	 the bloc kin the Symbol object?  */
+      value = read_var_value (symbol, NULL, frame_info);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
diff --git a/gdb/stack.c b/gdb/stack.c
index 76a2360..ffaac3c 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -320,7 +320,7 @@ read_frame_local (struct symbol *sym, struct frame_info *frame,
 
   TRY
     {
-      argp->val = read_var_value (sym, frame);
+      argp->val = read_var_value (sym, NULL, frame);
     }
   CATCH (except, RETURN_MASK_ERROR)
     {
@@ -346,7 +346,7 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame,
     {
       TRY
 	{
-	  val = read_var_value (sym, frame);
+	  val = read_var_value (sym, NULL, frame);
 	}
       CATCH (except, RETURN_MASK_ERROR)
 	{
@@ -473,7 +473,7 @@ read_frame_arg (struct symbol *sym, struct frame_info *frame,
 
 	  TRY
 	    {
-	      val = read_var_value (sym, frame);
+	      val = read_var_value (sym, NULL, frame);
 	    }
 	  CATCH (except, RETURN_MASK_ERROR)
 	    {
@@ -2450,7 +2450,7 @@ return_command (char *retval_exp, int from_tty)
 	value_fetch_lazy (return_value);
 
       if (thisfun != NULL)
-	function = read_var_value (thisfun, thisframe);
+	function = read_var_value (thisfun, NULL, thisframe);
 
       rv_conv = RETURN_VALUE_REGISTER_CONVENTION;
       if (TYPE_CODE (return_type) == TYPE_CODE_VOID)
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 6a0b8da..c18bf9c 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -665,6 +665,24 @@ struct symbol_block_ops
      uninitialized in such case.  */
   void (*find_frame_base_location) (struct symbol *framefunc, CORE_ADDR pc,
 				    const gdb_byte **start, size_t *length);
+
+  /* Return the frame base address.  FRAME is the frame for which we want to
+     compute the base address while FRAMEFUNC is the symbol for the
+     corresponding function.
+
+     This method is designed to work with static links (nested functions
+     handling).  Static links are function properties whose evaluation return
+     the frame base address for the enclosing frame.  However, there are
+     multiple definitions for "frame base": the content of the frame base
+     register, the CFA as defined by DWARF unwinding information, ...
+
+     So this specific method is supposed to compute the frame base address such
+     as for nested fuctions, the static link computes the same address.  For
+     instance, considering DWARF debugging information, the static link is
+     computed with DW_AT_static_link and this method must be used to compute
+     the corresponding DW_AT_frame_base attribute.  */
+  CORE_ADDR (*get_frame_base) (struct symbol *framefunc,
+			       struct frame_info *frame);
 };
 
 /* Functions used with LOC_REGISTER and LOC_REGPARM_ADDR.  */
diff --git a/gdb/testsuite/gdb.base/nested-subp1.c b/gdb/testsuite/gdb.base/nested-subp1.c
new file mode 100644
index 0000000..afae926
--- /dev/null
+++ b/gdb/testsuite/gdb.base/nested-subp1.c
@@ -0,0 +1,35 @@
+/* This test program is part of GDB, the GNU debugger.
+
+   Copyright 2015 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 foo (int i1)
+{
+  int nested (int i2)
+  {
+    /* Here with i1 and i2, we can test that GDB can fetch both a local and a
+       non-local variable in the most simple nested function situation: the
+       parent block instance is accessible as the directly upper frame.  */
+    return i1 * i2; /* STOP */
+  }
+
+  return nested (i1 + 1);
+}
+
+int
+main ()
+{
+  return !foo (1);
+}
diff --git a/gdb/testsuite/gdb.base/nested-subp1.exp b/gdb/testsuite/gdb.base/nested-subp1.exp
new file mode 100644
index 0000000..d2a8013
--- /dev/null
+++ b/gdb/testsuite/gdb.base/nested-subp1.exp
@@ -0,0 +1,58 @@
+# Copyright 2015 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/>.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@gnu.org
+
+# This file is part of the gdb testsuite.
+
+#
+# Test nested functions related functionality.
+#
+
+standard_testfile
+
+
+set testcase "nested-subp1"
+
+if { [gdb_compile "${srcdir}/${subdir}/${testcase}.c" \
+                  [standard_output_file "${testcase}"] \
+                  "${testcase}" \
+                  [list debug "additional_flags=-std=gnu99"]] != "" } {
+    return -1
+}
+
+
+# Run until the variables we are interested in are visible.
+
+clean_restart "${testcase}"
+if ![runto_main] {
+    perror "could not run to main"
+    continue
+}
+
+set bp_location [gdb_get_line_number "STOP" "${testcase}.c"]
+gdb_test "break ${testcase}.c:${bp_location}" \
+         "Breakpoint \[0-9\]+ at 0x\[0-9a-fA-F\]+: .*" \
+         "breakpoint to the STOP marker"
+gdb_test "continue" \
+         "Breakpoint \[0-9\]+, nested .*" \
+         "continue to the STOP marker"
+
+
+# Check we get correct values for both local and non-local variable references.
+
+gdb_test "print i1" "1"
+gdb_test "print i2" "2"
diff --git a/gdb/testsuite/gdb.base/nested-subp2.c b/gdb/testsuite/gdb.base/nested-subp2.c
new file mode 100644
index 0000000..bfda0d2
--- /dev/null
+++ b/gdb/testsuite/gdb.base/nested-subp2.c
@@ -0,0 +1,45 @@
+/* This test program is part of GDB, the GNU debugger.
+
+   Copyright 2015 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+void iter_str (const char *str, void (*callback) (char c))
+{
+  for (; *str != '\0'; ++str)
+    callback (*str);
+}
+
+int length_str (const char *str)
+{
+  int count = 0;
+
+  void increment (char c)
+  {
+    /* Here with COUNT, we can test that GDB can read a non-local variable even
+       though it's not directly in the upper stack frame.  */
+    count += 1; /* STOP */
+  }
+
+  iter_str (str, &increment);
+  return count;
+}
+
+int
+main ()
+{
+  if (length_str ("foo") == 3)
+    return 0;
+  return 1;
+}
diff --git a/gdb/testsuite/gdb.base/nested-subp2.exp b/gdb/testsuite/gdb.base/nested-subp2.exp
new file mode 100644
index 0000000..9694959
--- /dev/null
+++ b/gdb/testsuite/gdb.base/nested-subp2.exp
@@ -0,0 +1,67 @@
+# Copyright 2015 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/>.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@gnu.org
+
+# This file is part of the gdb testsuite.
+
+#
+# Test nested functions related functionality.
+#
+
+standard_testfile
+
+
+set testcase "nested-subp2"
+
+if { [gdb_compile "${srcdir}/${subdir}/${testcase}.c" \
+                  [standard_output_file "${testcase}"] \
+                  "${testcase}" \
+                  [list debug "additional_flags=-std=gnu99"]] != "" } {
+    return -1
+}
+
+
+# Run until the variables we are interested in are visible.
+
+clean_restart "${testcase}"
+if ![runto_main] {
+    perror "could not run to main"
+    continue
+}
+
+set bp_location [gdb_get_line_number "STOP" "${testcase}.c"]
+gdb_test "break ${testcase}.c:${bp_location}" \
+         "Breakpoint \[0-9\]+ at 0x\[0-9a-fA-F\]+: .*" \
+         "breakpoint to the STOP marker"
+gdb_test "continue" \
+         "Breakpoint \[0-9\]+, increment .*" \
+         "continue to the STOP marker"
+
+
+# Check we get correct values for both local and non-local variable references.
+
+gdb_test "print c"     "102 'f'"
+gdb_test "print count" "0"
+
+
+# Same but a little later: make sure we were looking at the proper places.
+
+gdb_test "continue" \
+         "Breakpoint \[0-9\]+, increment .*" \
+         "continue to the STOP marker"
+gdb_test "print c"     "111 'o'"
+gdb_test "print count" "1"
diff --git a/gdb/testsuite/gdb.base/nested-subp3.c b/gdb/testsuite/gdb.base/nested-subp3.c
new file mode 100644
index 0000000..aea10f2
--- /dev/null
+++ b/gdb/testsuite/gdb.base/nested-subp3.c
@@ -0,0 +1,66 @@
+/* This test program is part of GDB, the GNU debugger.
+
+   Copyright 2015 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>
+
+typedef void (*callback_t) (void);
+
+void process (callback_t cb);
+void parent (int first, callback_t cb);
+
+void
+ignore (int unused)
+{
+  (void) unused;
+}
+
+void
+process (callback_t cb)
+{
+  parent (0, cb);
+}
+
+void
+parent (int first, callback_t cb)
+{
+  void child (void)
+  {
+    /* When reaching this, there are two block instances for PARENT on the
+       stack: the one that is right in the upper frame is not the one actually
+       used for non-local references, so GDB has to follow the static link in
+       order to get the correct instance, and thus in order to read the proper
+       variables.
+
+       As a simple check, we can verify that under GDB, the following is true:
+       parent_first == first (which should be one: see the IF block below).  */
+    const int parent_first = first;
+    ignore (parent_first); /* STOP */
+    ignore (first);
+  }
+
+  if (first)
+    process (&child);
+  else
+    cb ();
+}
+
+int
+main ()
+{
+  parent (1, NULL);
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/nested-subp3.exp b/gdb/testsuite/gdb.base/nested-subp3.exp
new file mode 100644
index 0000000..0d2c50c
--- /dev/null
+++ b/gdb/testsuite/gdb.base/nested-subp3.exp
@@ -0,0 +1,60 @@
+# Copyright 2015 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/>.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@gnu.org
+
+# This file is part of the gdb testsuite.
+
+#
+# Test nested functions related functionality.
+#
+
+standard_testfile
+
+
+set testcase "nested-subp3"
+
+if { [gdb_compile "${srcdir}/${subdir}/${testcase}.c" \
+                  [standard_output_file "${testcase}"] \
+                  "${testcase}" \
+                  [list debug "additional_flags=-std=gnu99"]] != "" } {
+    return -1
+}
+
+
+# Run until the variables we are interested in are visible.
+
+clean_restart "${testcase}"
+if ![runto_main] {
+    perror "could not run to main"
+    continue
+}
+
+set bp_location [gdb_get_line_number "STOP" "${testcase}.c"]
+gdb_test "break ${testcase}.c:${bp_location}" \
+         "Breakpoint \[0-9\]+ at 0x\[0-9a-fA-F\]+: .*" \
+         "breakpoint to the STOP marker"
+gdb_test "continue" \
+         "Breakpoint \[0-9\]+, child .*" \
+         "continue to the STOP marker"
+
+
+# Check we get correct values for both local and non-local variable references.
+
+# Note that in order to get the following test passing, one has to use a
+# patched GCC: see <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53927>.
+gdb_test "print first"        "1"
+gdb_test "print parent_first" "1"
diff --git a/gdb/valops.c b/gdb/valops.c
index 66c63c1..b82eff2 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -132,6 +132,7 @@ find_function_in_inferior (const char *name, struct objfile **objf_p)
   sym = lookup_symbol (name, 0, VAR_DOMAIN, 0);
   if (sym != NULL)
     {
+      const struct block *b = block_found;
       if (SYMBOL_CLASS (sym) != LOC_BLOCK)
 	{
 	  error (_("\"%s\" exists in this program but is not a function."),
@@ -141,7 +142,7 @@ find_function_in_inferior (const char *name, struct objfile **objf_p)
       if (objf_p)
 	*objf_p = symbol_objfile (sym);
 
-      return value_of_variable (sym, NULL);
+      return value_of_variable (sym, b);
     }
   else
     {
@@ -1290,27 +1291,12 @@ value_repeat (struct value *arg1, int count)
 struct value *
 value_of_variable (struct symbol *var, const struct block *b)
 {
-  struct frame_info *frame;
+  struct frame_info *frame = NULL;
 
-  if (!symbol_read_needs_frame (var))
-    frame = NULL;
-  else if (!b)
+  if (symbol_read_needs_frame (var))
     frame = get_selected_frame (_("No frame selected."));
-  else
-    {
-      frame = block_innermost_frame (b);
-      if (!frame)
-	{
-	  if (BLOCK_FUNCTION (b) && !block_inlined_p (b)
-	      && SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b)))
-	    error (_("No frame is currently executing in block %s."),
-		   SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b)));
-	  else
-	    error (_("No frame is currently executing in specified block"));
-	}
-    }
 
-  return read_var_value (var, frame);
+  return read_var_value (var, b, frame);
 }
 
 struct value *
@@ -3462,9 +3448,9 @@ value_struct_elt_for_reference (struct type *domain, int offset,
 		return NULL;
 
 	      if (want_address)
-		return value_addr (read_var_value (s, 0));
+		return value_addr (read_var_value (s, 0, 0));
 	      else
-		return read_var_value (s, 0);
+		return read_var_value (s, 0, 0);
 	    }
 
 	  if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
@@ -3492,7 +3478,7 @@ value_struct_elt_for_reference (struct type *domain, int offset,
 	      if (s == NULL)
 		return NULL;
 
-	      v = read_var_value (s, 0);
+	      v = read_var_value (s, 0, 0);
 	      if (!want_address)
 		result = v;
 	      else
@@ -3740,11 +3726,12 @@ value_of_this (const struct language_defn *lang)
   b = get_frame_block (frame, NULL);
 
   sym = lookup_language_this (lang, b);
+  b = block_found;
   if (sym == NULL)
     error (_("current stack frame does not contain a variable named `%s'"),
 	   lang->la_name_of_this);
 
-  return read_var_value (sym, frame);
+  return read_var_value (sym, b, frame);
 }
 
 /* Return the value of the local variable, if one exists.  Return NULL
diff --git a/gdb/value.c b/gdb/value.c
index cb56849..e33bab6 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -2905,6 +2905,7 @@ value_static_field (struct type *type, int fieldno)
       const char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno);
       /* TYPE_FIELD_NAME (type, fieldno); */
       struct symbol *sym = lookup_symbol (phys_name, 0, VAR_DOMAIN, 0);
+      const struct block *b = block_found;
 
       if (sym == NULL)
 	{
@@ -2922,7 +2923,7 @@ value_static_field (struct type *type, int fieldno)
 	    }
 	}
       else
-	retval = value_of_variable (sym, NULL);
+	retval = value_of_variable (sym, b);
       break;
     }
     default:
diff --git a/gdb/value.h b/gdb/value.h
index 21baa32..9f9e7c6 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -670,9 +670,11 @@ struct value *value_of_register_lazy (struct frame_info *frame, int regnum);
 extern int symbol_read_needs_frame (struct symbol *);
 
 extern struct value *read_var_value (struct symbol *var,
+				     const struct block *var_block,
 				     struct frame_info *frame);
 
 extern struct value *default_read_var_value (struct symbol *var,
+					     const struct block *var_block,
 					     struct frame_info *frame);
 
 extern struct value *allocate_value (struct type *type);
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index 3cb6eda..e8265c8 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -1388,8 +1388,8 @@ read_xcoff_symtab (struct objfile *objfile, struct partial_symtab *pst)
 		  break;
 		}
 
-	      finish_block (newobj->name, &local_symbols, newobj->old_blocks,
-			    newobj->start_addr,
+	      finish_block (newobj->name, NULL, &local_symbols,
+			    newobj->old_blocks, newobj->start_addr,
 			    (fcn_cs_saved.c_value
 			     + fcn_aux_saved.x_sym.x_misc.x_fsize
 			     + ANOFFSET (objfile->section_offsets,
-- 
2.3.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]