Please find attached the fixed patch files for this change:
        1. Add command line option -fforce-dwarf-lexical-blocks.
        2. Support flag_force_dwarf_blocks in C.
        3. Support flag_force_dwarf_blocks in C++.

Attached also are the proposed ChangeLog additions, named according to the directory each one belongs to.

All check-c and check-c++ tests have been run for unix target, with and without the new option. The only test that failed with the -fforce-dwarf-lexical-blocks set and passed without this flag was: FAIL: gcc.dg/debug/dwarf2/inline2.c scan-assembler-times \\(DIE \\([^\n]*\\) DW_TAG_lexical_block 6
as expected.

Best regards,
Andrei Herman
Mentor Graphics Corporation
Israel branch


On 6/20/2014 12:09 AM, Joseph S. Myers wrote:
On Sun, 1 Jun 2014, Herman, Andrei wrote:

+  /* The -fforce-dwarf-lexical-blocks option is only relevant when debug
+     info is in DWARF4 format */
+  if (flag_force_dwarf_blocks) {

Watch coding style: the opening '{' always goes on the next line.

+fforce-dwarf-lexical-blocks
+C C++ Var(flag_force_dwarf_blocks)
+Force generation of lexical blocks in dwarf output

I don't see a good reason for this not to be supported for ObjC and ObjC++
as well.  Say DWARF, not dwarf.

+@item -fforce-dwarf-lexical-blocks
+Produce debug information (a DW_TAG_lexical_block) for every function
+body, loop body, switch body, case statement, if-then and if-else statement,
+even if the body is a single statement.  Likewise, a lexical block will be
+emitted for the first label of a statement.  This block ends at the end of the
+current lexical scope, or when a break, continue, goto or return statement is
+encountered at the same lexical scope level.  This option is usefull for
+coverage tools that utilize the dwarf debug information.
+This option only applies to C/C++ code and is available when using DWARF
+Version 4 or higher.

Use @code{} markup for keywords (if, else, break, continue, goto, return).
"useful" not "usefull".  "DWARF" not "dwarf".

+/* Create a block_loc struct for a statement list created on behalf of
+   flag_force_dwarf_blocks.  We use this for label or forced c99 scopes.  */
+
+void
+push_block_info (tree block, location_t loc, bool is_label)
+{
+  if (TREE_CODE(block) != STATEMENT_LIST)

Watch coding style: space before '(' in function and macro calls (and
similar calls such as sizeof) (many places in this patch, not just this
one).

+tree
+pop_block_info (location_t &loc)

It's not documented in codingconventions.html, but I think it's preferred
to avoid returning values through reference arguments (see e.g.
<https://gcc.gnu.org/ml/gcc-patches/2013-11/msg00198.html>).

+{
+  block_loc  tl = NULL;

Excess space between "block_loc" and "tl".

@@ -4679,7 +4712,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
    expressions being rejected later.  */

static void
-c_parser_label (c_parser *parser)
+c_parser_label (c_parser *parser, bool prev_label)

You're adding a new argument - you need to update the comment above this
function to explain the semantics of this argument.

In general, make sure that new functions have comments above them that
explain the semantics of the arguments (by name) and any return value.

+/* If current scope is a label scope, pop it from block info stack
+   and close it's compound statement.  */

"its" not "it's".

>From 113007fbf8de51f14f77ba9e652abbcc45c8316a Mon Sep 17 00:00:00 2001
From: Andrei Herman <andrei_her...@codesourcery.com>
Date: Sun, 27 Jul 2014 15:47:05 +0300
Subject: [PATCH 1/3]    Add command line option -fforce-dwarf-lexical-blocks.

        * gcc/c-family/c.opt: Add -fforce-dwarf-lexical-blocks flag.
        * gcc/c-family/c-opts.c (c_common_post_options): Limit its use
        to DWARF4.
        * gcc/doc/invoke.texi: Document the new option.

Signed-off-by: Andrei Herman <andrei_her...@codesourcery.com>
---
 gcc/c-family/c-opts.c | 15 +++++++++++++++
 gcc/c-family/c.opt    |  4 ++++
 gcc/doc/invoke.texi   | 12 ++++++++++++
 3 files changed, 31 insertions(+)

diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index 29e9a35..058a344 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -936,6 +936,21 @@ c_common_post_options (const char **pfilename)
 #endif
     }
 
+  /* The -fforce-dwarf-lexical-blocks option is only relevant when debug
+     info is in DWARF4 format.  */
+  if (flag_force_dwarf_blocks)
+    {
+      if (write_symbols != DWARF2_DEBUG)
+        flag_force_dwarf_blocks = 0;
+      if (write_symbols == DWARF2_DEBUG && dwarf_version < 4)
+        {
+          inform (input_location,
+                  "-fforce-dwarf-lexical-blocks is only supported with "
+                  "DWARF4 debug format");
+          flag_force_dwarf_blocks = 0;
+        }
+    }
+
   if (flag_preprocess_only)
     {
       /* Open the output now.  We must do so even if flag_no_output is
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index c586e65..c3e6cc2 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -960,6 +960,10 @@ ffor-scope
 C++ ObjC++ Var(flag_new_for_scope) Init(1)
 Scope of for-init-statement variables is local to the loop
 
+fforce-dwarf-lexical-blocks
+C C++ Var(flag_force_dwarf_blocks)
+Force generation of lexical blocks in DWARF output
+
 ffreestanding
 C ObjC C++ ObjC++
 Do not assume that standard C libraries and \"main\" exist
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 9475594..56f0a6e 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -333,6 +333,7 @@ Objective-C and Objective-C++ Dialects}.
 -feliminate-unused-debug-symbols -femit-class-debug-always @gol
 -fenable-@var{kind}-@var{pass} @gol
 -fenable-@var{kind}-@var{pass}=@var{range-list} @gol
+-fforce-dwarf-lexical-blocks @gol
 -fdebug-types-section -fmem-report-wpa @gol
 -fmem-report -fpre-ipa-mem-report -fpost-ipa-mem-report -fprofile-arcs @gol
 -fopt-info @gol
@@ -5200,6 +5201,17 @@ normally emits debugging information for classes because 
using this
 option increases the size of debugging information by as much as a
 factor of two.
 
+@item -fforce-dwarf-lexical-blocks
+Produce debug information (a DW_TAG_lexical_block) for every function
+body, loop body, @code{switch} body, @code{case} statement, @code{if} and
+@code{else} statement, even if the body is a single statement.  Likewise, a
+lexical block will be emitted for the first label of a statement.  This block
+ends at the end of the current lexical scope, or when a @code{break},
+@code{continue}, @code{goto} or @code{return} statement is encountered at the
+same lexical scope level.  This option is useful for coverage tools that
+utilize the DWARF debug information.  This option only applies to C/C++ code
+and is available when using DWARF Version 4 or higher.
+
 @item -fdebug-types-section
 @opindex fdebug-types-section
 @opindex fno-debug-types-section
-- 
1.8.3

>From 8e3003aee8035aa0ad2163bbb98e442e38e5fa70 Mon Sep 17 00:00:00 2001
From: Andrei Herman <andrei_her...@codesourcery.com>
Date: Sun, 27 Jul 2014 16:00:52 +0300
Subject: [PATCH 2/3]    Support flag_force_dwarf_blocks in C.

        When flag_force_dwarf_blocks is true, create lexical blocks
        for function body, compound statement, loop body, switch body,
        if-then/if-else statements and labels.

        * c-common.h (struct block_loc_s, block_loc): New.
        (stmt_tree_s): Add x_cur_block_list stack of block_loc structs
        for statement lists of forced scopes (label and c99).
        (block_list_stack, cur_block_info): New macros.
        (push_block_info, pop_block_info, check_pop_block_info): New.

        * c-semantics.c (push_block_info): New.
        (pop_block_info): New.
        (check_pop_block_info): New.

        * c-parser.c (c_parser_declaration_or_fndef): Force a block for
        function body.
        (c_parser_force_block_for_label): New.
        (c_parser_label): Add parameter.  Create a label scope for the first
        label of a statement.
        (c_parser_compound_statement_nostart): Pass last_label when calling
        c_parser_label.
        (c_parser_statement): Likewise.
        (c_parser_statement_after_labels): Force a block for compound statement.
        (c_parser_c99_block_statement): Likewise for switch and loop statement
        if its not a compound statement.  Push/pop the forced scope.
        (c_parser_if_body): Likewise for if-then statement.  Pass last_label
        when calling c_parser_label.
        (c_parser_else_body): Likewise for if-else statement.

        * c-decl.c (get_enclosing_non_forced_scope): New.
        (clear_keep_current_level): New.
        (pushdecl): If current scope is a forced scope, put the declaration
        in the enclosing non-forced scope.

        * c-tree.h (clear_keep_current_level): New.

        * c-typeck.c (pop_scope_for_labels): New.
        (c_finish_goto_label, c_finish_goto_ptr, c_finish_return,
        c_finish_bc_stmt): Call pop_scope_for_labels to close current
        label scope if any.
        (c_end_compound_stmt): Likewise.

        * dwarf2out.c (gen_block_die): Force output a lexical block die
        even for blocks without any local declaration.

        * function.c (reorder_blocks): Skip the forced block, when function
        has no inner blocks.

        * tree-ssa-live.c (remove_unused_scope_block_p): Mark the function
        level forced block as used.

Signed-off-by: Andrei Herman <andrei_her...@codesourcery.com>
---
 gcc/c-family/c-common.h    |  23 ++++++++
 gcc/c-family/c-semantics.c |  55 +++++++++++++++++++
 gcc/c/c-decl.c             |  38 +++++++++++++
 gcc/c/c-parser.c           | 130 +++++++++++++++++++++++++++++++++++++++------
 gcc/c/c-tree.h             |   1 +
 gcc/c/c-typeck.c           |  48 +++++++++++++++--
 gcc/dwarf2out.c            |  39 ++++++++------
 gcc/function.c             |   8 +++
 gcc/tree-ssa-live.c        |   6 ++-
 9 files changed, 313 insertions(+), 35 deletions(-)

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 0d34004..dff875c 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -476,12 +476,27 @@ typedef enum ref_operator {
   RO_ARROW_STAR
 } ref_operator;
 
+/* Information about a statement list created for a label (is_label=true)
+   or for a forced c99 scope.  The -fforce-dwarf-lexical-blocks will
+   force such a scope even if flag_isoc99 is not set.  */
+
+struct GTY(()) block_loc_s {
+  tree block;
+  location_t loc;
+  bool is_label;
+};
+
+typedef struct block_loc_s *block_loc;
+
 /* Information about a statement tree.  */
 
 struct GTY(()) stmt_tree_s {
   /* A stack of statement lists being collected.  */
   vec<tree, va_gc> *x_cur_stmt_list;
 
+  /* A stack of block-loc structs related to forced statement lists.  */
+  vec<block_loc, va_gc> *x_cur_block_list;
+
   /* In C++, Nonzero if we should treat statements as full
      expressions.  In particular, this variable is non-zero if at the
      end of a statement we should destroy any temporaries created
@@ -510,11 +525,16 @@ struct GTY(()) c_language_function {
 };
 
 #define stmt_list_stack (current_stmt_tree ()->x_cur_stmt_list)
+#define block_list_stack (current_stmt_tree ()->x_cur_block_list)
 
 /* When building a statement-tree, this is the current statement list
    being collected.  */
 #define cur_stmt_list  (stmt_list_stack->last ())
 
+/* When building a statement-tree, this is the block list element
+   corresponding to the innermost forced statement list created.  */
+#define cur_block_info  (block_list_stack->last ())
+
 #define building_stmt_list_p() (stmt_list_stack && 
!stmt_list_stack->is_empty())
 
 /* Language-specific hooks.  */
@@ -528,6 +548,9 @@ extern void pop_file_scope (void);
 extern stmt_tree current_stmt_tree (void);
 extern tree push_stmt_list (void);
 extern tree pop_stmt_list (tree);
+extern void push_block_info (tree, location_t, bool);
+extern block_loc pop_block_info ();
+extern void check_pop_block_info (tree, location_t);
 extern tree add_stmt (tree);
 extern void push_cleanup (tree, tree, bool);
 extern tree pushdecl_top_level (tree);
diff --git a/gcc/c-family/c-semantics.c b/gcc/c-family/c-semantics.c
index f25805a..d9e76bd 100644
--- a/gcc/c-family/c-semantics.c
+++ b/gcc/c-family/c-semantics.c
@@ -29,6 +29,61 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "tree-iterator.h"
 
+/* Create a block_loc struct for a statement list created on behalf of
+   flag_force_dwarf_blocks.  We use this for label or forced c99 scopes.  */
+
+void
+push_block_info (tree block, location_t loc, bool is_label)
+{
+  switch (TREE_CODE (block))
+    {
+    case BIND_EXPR:
+      block = BIND_EXPR_BODY (block);
+      /* Fall through.  */
+    case STATEMENT_LIST:
+      break;
+    default:
+      return;
+    }
+
+  block_loc tl;
+  tl = (block_loc) ggc_internal_cleared_alloc (sizeof (struct block_loc_s));
+  tl->block = block;
+  tl->loc = loc;
+  tl->is_label = is_label;
+  vec_safe_push (block_list_stack, tl);
+}
+
+/* Pop the block_loc struct from the block info stack and return it.  */
+
+block_loc
+pop_block_info ()
+{
+  block_loc tl = NULL;
+  if (block_list_stack && !block_list_stack->is_empty ())
+    tl = block_list_stack->pop ();
+
+  gcc_assert (tl != NULL);
+
+  return tl;
+}
+
+/* Pop the last block_loc element if it referes to BLOCK and LOC, and it is
+   not a label scope.  */
+
+void
+check_pop_block_info (tree block, location_t loc)
+{
+  if (block_list_stack && !block_list_stack->is_empty ())
+    {
+      if (block == cur_block_info->block && loc == cur_block_info->loc
+          && !cur_block_info->is_label)
+        {
+          block_list_stack->pop ();
+        }
+    }
+}
+
 /* Create an empty statement tree rooted at T.  */
 
 tree
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index e8e6bd2..85edc0d 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -538,6 +538,31 @@ static tree grokdeclarator (const struct c_declarator *,
 static tree grokparms (struct c_arg_info *, bool);
 static void layout_array_type (tree);
 
+/* If SCOPE has been forced by flag_force_dwarf_blocks (either for a label,
+   or for a c99 block), then find and return the nearest enclosing scope which
+   is not a forced scope.  Otherwise just return the scope as is.  */
+
+static c_scope *
+get_enclosing_non_forced_scope (c_scope * scope)
+{
+  if (block_list_stack && !block_list_stack->is_empty ())
+    {
+      int six = stmt_list_stack->length () - 1;
+      int bix = block_list_stack->length () - 1;
+      while (six >= 0 && bix >= 0)
+        {
+          if ((*stmt_list_stack)[six] == (*block_list_stack)[bix]->block)
+            {
+              scope = scope->outer;
+              six--; bix--;
+            }
+          else
+            return scope;
+        }
+    }
+  return scope;
+}
+
 /* T is a statement.  Add it to the statement-tree.  This is the
    C/ObjC version--C++ has a slightly different version of this
    function.  */
@@ -880,6 +905,14 @@ keep_next_level (void)
   keep_next_level_flag = true;
 }
 
+/* Clear the flag that forces creation of a block for the current scope.  */
+
+void
+clear_keep_current_level (void)
+{
+  current_scope->keep = false;
+}
+
 /* Set the flag for the FLOAT_CONST_DECIMAL64 pragma being ON.  */
 
 void
@@ -2674,6 +2707,11 @@ pushdecl (tree x)
       return x;
     }
 
+  if (flag_force_dwarf_blocks)
+    /* If the current scope is a forced scope (by flag_force_dwarf_blocks),
+       put the declaration in the nearest enclosing normal scope.  */
+    scope = get_enclosing_non_forced_scope (scope);
+
   /* First, see if there is another declaration with the same name in
      the current scope.  If there is, duplicate_decls may do all the
      work for us.  If duplicate_decls returns false, that indicates
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 88edf36..d1c0d21 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1167,7 +1167,7 @@ static void c_parser_initval (c_parser *, struct c_expr *,
                              struct obstack *);
 static tree c_parser_compound_statement (c_parser *);
 static void c_parser_compound_statement_nostart (c_parser *);
-static void c_parser_label (c_parser *);
+static void c_parser_label (c_parser *, bool);
 static void c_parser_statement (c_parser *);
 static void c_parser_statement_after_labels (c_parser *);
 static void c_parser_if_statement (c_parser *);
@@ -1930,7 +1930,17 @@ c_parser_declaration_or_fndef (c_parser *parser, bool 
fndef_ok,
                                   omp_declare_simd_clauses);
       DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
        = c_parser_peek_token (parser)->location;
-      fnbody = c_parser_compound_statement (parser);
+      if (flag_force_dwarf_blocks)
+        {
+          /* Force creating a block to represent the function body.  */
+          tree block = c_begin_compound_stmt (true);
+          location_t loc = c_parser_peek_token (parser)->location;
+          keep_next_level ();
+          add_stmt (c_parser_compound_statement (parser));
+          fnbody = c_end_compound_stmt (loc, block, true);
+        }
+      else
+        fnbody = c_parser_compound_statement (parser);
       if (flag_cilkplus && contains_array_notation_expr (fnbody))
        fnbody = expand_array_notation_exprs (fnbody);
       if (nested)
@@ -4490,6 +4500,29 @@ c_parser_compound_statement (c_parser *parser)
   return c_end_compound_stmt (brace_loc, stmt, true);
 }
 
+/* Force creation of a new scope for a LABEL.  If not followed by a compound
+   statement, make it a block (otherwise, the compound statement will create
+   the block).  Push the created scope onto the block_info stack, so we can
+   identify it as a label scope.  */
+
+static void
+c_parser_force_block_for_label (c_parser *parser, tree label)
+{
+  if (!flag_force_dwarf_blocks || label == NULL_TREE)
+    return;
+
+  /* If the current statement list is a statement expression,
+     do nothing.  */
+  if (STATEMENT_LIST_STMT_EXPR (cur_stmt_list))
+    return;
+
+  if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+    keep_next_level ();
+  tree block = c_begin_compound_stmt (true);
+  location_t loc = c_parser_peek_token (parser)->location;
+  push_block_info (block, loc, true);
+}
+
 /* Parse a compound statement except for the opening brace.  This is
    used for parsing both compound statements and statement expressions
    (which follow different paths to handling the opening).  */
@@ -4560,10 +4593,10 @@ c_parser_compound_statement_nostart (c_parser *parser)
            label_loc = c_parser_peek_2nd_token (parser)->location;
          else
            label_loc = c_parser_peek_token (parser)->location;
+         mark_valid_location_for_stdc_pragma (false);
+         c_parser_label (parser, last_label);
          last_label = true;
          last_stmt = false;
-         mark_valid_location_for_stdc_pragma (false);
-         c_parser_label (parser);
        }
       else if (!last_label
               && c_parser_next_tokens_start_declaration (parser))
@@ -4676,10 +4709,14 @@ c_parser_compound_statement_nostart (c_parser *parser)
 
    The use of attributes on labels is a GNU extension.  The syntax in
    GNU C accepts any expressions without commas, non-constant
-   expressions being rejected later.  */
+   expressions being rejected later.
+
+   PREV_LABEL is true if this is not the first label of the following statement
+   (like in label1: label2: statement;).  When flag_force_dwarf_blocks is true,
+   we only want to force a block for the first label of a statement.  */
 
 static void
-c_parser_label (c_parser *parser)
+c_parser_label (c_parser *parser, bool prev_label)
 {
   location_t loc1 = c_parser_peek_token (parser)->location;
   tree label = NULL_TREE;
@@ -4741,6 +4778,23 @@ c_parser_label (c_parser *parser)
                                         vNULL);
        }
     }
+  if (label && flag_force_dwarf_blocks)
+    {
+      if (!prev_label)
+        {
+          /* If this is the first label on the statement, create a label scope
+             for it.  */
+          c_parser_force_block_for_label (parser, label);
+        }
+      else
+        {
+          /* The first label may not have seen the open brace and therefor set
+             the keep flag in current scope.  If we see it now, we should clear
+             the flag (the next compound statement will create the block).  */
+          if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
+            clear_keep_current_level ();
+        }
+    }
 }
 
 /* Parse a statement (C90 6.6, C99 6.8).
@@ -4862,11 +4916,15 @@ c_parser_label (c_parser *parser)
 static void
 c_parser_statement (c_parser *parser)
 {
+  bool last_label = false;
   while (c_parser_next_token_is_keyword (parser, RID_CASE)
         || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
         || (c_parser_next_token_is (parser, CPP_NAME)
             && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
-    c_parser_label (parser);
+    {
+      c_parser_label (parser, last_label);
+      last_label = true;
+    }
   c_parser_statement_after_labels (parser);
 }
 
@@ -4882,6 +4940,8 @@ c_parser_statement_after_labels (c_parser *parser)
   switch (c_parser_peek_token (parser)->type)
     {
     case CPP_OPEN_BRACE:
+      if (flag_force_dwarf_blocks)
+        keep_next_level ();
       add_stmt (c_parser_compound_statement (parser));
       break;
     case CPP_KEYWORD:
@@ -5068,10 +5128,21 @@ c_parser_paren_condition (c_parser *parser)
 static tree
 c_parser_c99_block_statement (c_parser *parser)
 {
-  tree block = c_begin_compound_stmt (flag_isoc99);
+  bool force_scope = flag_force_dwarf_blocks
+    && !c_parser_next_token_is (parser, CPP_OPEN_BRACE);
+  if (force_scope)
+    keep_next_level ();
+  tree block = c_begin_compound_stmt (flag_isoc99 || force_scope);
   location_t loc = c_parser_peek_token (parser)->location;
+  /* If we forced a scope which is not isoc99, push it onto the block_info
+     stack, so we can identify it as a forced scope.  */
+  if (force_scope && !flag_isoc99)
+    push_block_info (block, loc, false);
   c_parser_statement (parser);
-  return c_end_compound_stmt (loc, block, flag_isoc99);
+  /* Remove the forced scope from the block_info stack, if needed.  */
+  if (force_scope && !flag_isoc99)
+    check_pop_block_info (block, loc);
+  return c_end_compound_stmt (loc, block, flag_isoc99 || force_scope);
 }
 
 /* Parse the body of an if statement.  This is just parsing a
@@ -5085,13 +5156,23 @@ c_parser_c99_block_statement (c_parser *parser)
 static tree
 c_parser_if_body (c_parser *parser, bool *if_p)
 {
-  tree block = c_begin_compound_stmt (flag_isoc99);
+  if (flag_force_dwarf_blocks)
+    keep_next_level ();
+  tree block = c_begin_compound_stmt (flag_isoc99 || flag_force_dwarf_blocks);
   location_t body_loc = c_parser_peek_token (parser)->location;
+  /* If we forced a scope which is not isoc99, push it onto the block_info
+     stack, so we can identify it as a forced scope.  */
+  if (flag_force_dwarf_blocks && !flag_isoc99)
+    push_block_info (block, body_loc, false);
+  bool last_label = false;
   while (c_parser_next_token_is_keyword (parser, RID_CASE)
         || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
         || (c_parser_next_token_is (parser, CPP_NAME)
             && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
-    c_parser_label (parser);
+    {
+      c_parser_label (parser, last_label);
+      last_label = true;
+    }
   *if_p = c_parser_next_token_is_keyword (parser, RID_IF);
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
     {
@@ -5106,7 +5187,11 @@ c_parser_if_body (c_parser *parser, bool *if_p)
     add_stmt (c_parser_compound_statement (parser));
   else
     c_parser_statement_after_labels (parser);
-  return c_end_compound_stmt (body_loc, block, flag_isoc99);
+  /* Remove the forced scope from the block_info stack, if needed.  */
+  if (flag_force_dwarf_blocks && !flag_isoc99)
+    check_pop_block_info (block, body_loc);
+  return c_end_compound_stmt (body_loc, block,
+                              flag_isoc99 || flag_force_dwarf_blocks);
 }
 
 /* Parse the else body of an if statement.  This is just parsing a
@@ -5117,12 +5202,24 @@ static tree
 c_parser_else_body (c_parser *parser)
 {
   location_t else_loc = c_parser_peek_token (parser)->location;
-  tree block = c_begin_compound_stmt (flag_isoc99);
+  bool force_scope = flag_force_dwarf_blocks
+    && !c_parser_next_token_is (parser, CPP_OPEN_BRACE);
+  if (force_scope)
+    keep_next_level ();
+  tree block = c_begin_compound_stmt (flag_isoc99 || force_scope);
+  /* If we forced a scope which is not isoc99, push it onto the block_info
+     stack, so we can identify it as a forced scope.  */
+  if (force_scope && !flag_isoc99)
+    push_block_info (block, else_loc, false);
+  bool last_label = false;
   while (c_parser_next_token_is_keyword (parser, RID_CASE)
         || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
         || (c_parser_next_token_is (parser, CPP_NAME)
             && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
-    c_parser_label (parser);
+    {
+      c_parser_label (parser, last_label);
+      last_label = true;
+    }
   if (c_parser_next_token_is (parser, CPP_SEMICOLON))
     {
       location_t loc = c_parser_peek_token (parser)->location;
@@ -5134,7 +5231,10 @@ c_parser_else_body (c_parser *parser)
     }
   else
     c_parser_statement_after_labels (parser);
-  return c_end_compound_stmt (else_loc, block, flag_isoc99);
+  /* Remove the forced scope from the block_info stack, if needed.  */
+  if (force_scope && !flag_isoc99)
+    check_pop_block_info (block, else_loc);
+  return c_end_compound_stmt (else_loc, block, flag_isoc99 || force_scope);
 }
 
 /* Parse an if statement (C90 6.6.4, C99 6.8.4).
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index e7dcb35..bb40d82 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -504,6 +504,7 @@ extern tree groktypename (struct c_type_name *, tree *, 
bool *);
 extern tree grokparm (const struct c_parm *, tree *);
 extern tree implicitly_declare (location_t, tree);
 extern void keep_next_level (void);
+extern void clear_keep_current_level (void);
 extern void pending_xref_error (void);
 extern void c_push_function_context (void);
 extern void c_pop_function_context (void);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 6ca584b..2fad758 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -9132,6 +9132,24 @@ build_asm_expr (location_t loc, tree string, tree 
outputs, tree inputs,
   return args;
 }
 
+/* If current scope is a forced scope, pop it from block info stack
+   and close its compound statement.  */
+
+static void
+pop_scope_for_labels (void)
+{
+  while (block_list_stack && !block_list_stack->is_empty ())
+    {
+      if (cur_stmt_list == cur_block_info->block && cur_block_info->is_label)
+        {
+          block_loc tl = pop_block_info ();
+          add_stmt (c_end_compound_stmt (tl->loc, tl->block, true));
+        }
+      else
+        break;
+    }
+}
+
 /* Generate a goto statement to LABEL.  LOC is the location of the
    GOTO.  */
 
@@ -9145,7 +9163,12 @@ c_finish_goto_label (location_t loc, tree label)
   {
     tree t = build1 (GOTO_EXPR, void_type_node, decl);
     SET_EXPR_LOCATION (t, loc);
-    return add_stmt (t);
+    {
+      tree stmt = add_stmt (t);
+      if (flag_force_dwarf_blocks)
+        pop_scope_for_labels ();
+      return stmt;
+    }
   }
 }
 
@@ -9161,7 +9184,12 @@ c_finish_goto_ptr (location_t loc, tree expr)
   expr = convert (ptr_type_node, expr);
   t = build1 (GOTO_EXPR, void_type_node, expr);
   SET_EXPR_LOCATION (t, loc);
-  return add_stmt (t);
+  {
+    tree stmt = add_stmt (t);
+    if (flag_force_dwarf_blocks)
+      pop_scope_for_labels ();
+    return stmt;
+  }
 }
 
 /* Generate a C `return' statement.  RETVAL is the expression for what
@@ -9325,7 +9353,12 @@ c_finish_return (location_t loc, tree retval, tree 
origtype)
 
   ret_stmt = build_stmt (loc, RETURN_EXPR, retval);
   TREE_NO_WARNING (ret_stmt) |= no_warning;
-  return add_stmt (ret_stmt);
+  {
+    tree stmt = add_stmt (ret_stmt);
+    if (flag_force_dwarf_blocks)
+      pop_scope_for_labels ();
+    return stmt;
+  }
 }
 
 struct c_switch {
@@ -9698,7 +9731,12 @@ c_finish_bc_stmt (location_t loc, tree *label_p, bool 
is_break)
   if (!is_break)
     add_stmt (build_predict_expr (PRED_CONTINUE, NOT_TAKEN));
 
-  return add_stmt (build1 (GOTO_EXPR, void_type_node, label));
+  {
+    tree stmt = add_stmt (build1 (GOTO_EXPR, void_type_node, label));
+    if (flag_force_dwarf_blocks)
+      pop_scope_for_labels ();
+    return stmt;
+  }
 }
 
 /* A helper routine for c_process_expr_stmt and c_finish_stmt_expr.  */
@@ -9951,6 +9989,8 @@ c_end_compound_stmt (location_t loc, tree stmt, bool 
do_scope)
     {
       if (c_dialect_objc ())
        objc_clear_super_receiver ();
+      if (flag_force_dwarf_blocks)
+        pop_scope_for_labels ();
       block = pop_scope ();
     }
 
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 7c93074..e8eb19a 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -20129,21 +20129,30 @@ gen_block_die (tree stmt, dw_die_ref context_die, int 
depth)
     must_output_die = 1;
   else
     {
-      /* Determine if this block directly contains any "significant"
-        local declarations which we will need to output DIEs for.  */
-      if (debug_info_level > DINFO_LEVEL_TERSE)
-       /* We are not in terse mode so *any* local declaration counts
-          as being a "significant" one.  */
-       must_output_die = ((BLOCK_VARS (stmt) != NULL
-                           || BLOCK_NUM_NONLOCALIZED_VARS (stmt))
-                          && (TREE_USED (stmt)
-                              || TREE_ASM_WRITTEN (stmt)
-                              || BLOCK_ABSTRACT (stmt)));
-      else if ((TREE_USED (stmt)
-               || TREE_ASM_WRITTEN (stmt)
-               || BLOCK_ABSTRACT (stmt))
-              && !dwarf2out_ignore_block (stmt))
-       must_output_die = 1;
+      if (flag_force_dwarf_blocks)
+        {
+          must_output_die = (TREE_USED (stmt)
+                             || TREE_ASM_WRITTEN (stmt)
+                             || BLOCK_ABSTRACT (stmt));
+        }
+      else
+        {
+          /* Determine if this block directly contains any "significant"
+             local declarations which we will need to output DIEs for.  */
+          if (debug_info_level > DINFO_LEVEL_TERSE)
+            /* We are not in terse mode so *any* local declaration counts
+               as being a "significant" one.  */
+            must_output_die = ((BLOCK_VARS (stmt) != NULL
+                                || BLOCK_NUM_NONLOCALIZED_VARS (stmt))
+                               && (TREE_USED (stmt)
+                                   || TREE_ASM_WRITTEN (stmt)
+                                   || BLOCK_ABSTRACT (stmt)));
+          else if ((TREE_USED (stmt)
+                    || TREE_ASM_WRITTEN (stmt)
+                    || BLOCK_ABSTRACT (stmt))
+                   && !dwarf2out_ignore_block (stmt))
+            must_output_die = 1;
+        }
     }
 
   /* It would be a waste of space to generate a Dwarf DW_TAG_lexical_block
diff --git a/gcc/function.c b/gcc/function.c
index ec2ea26..ff3e0a2 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -4117,6 +4117,14 @@ reorder_blocks (void)
   if (block == NULL_TREE)
     return;
 
+  /* In case we added another block level to functions,
+     disregard the forced block.  */
+  if (flag_force_dwarf_blocks
+      && BLOCK_SUBBLOCKS (block) && BLOCK_CHAIN (block) == NULL_TREE
+      && BLOCK_VARS (block) == NULL_TREE
+      && BLOCK_SUBBLOCKS (BLOCK_SUBBLOCKS (block)) == NULL_TREE
+      && BLOCK_CHAIN (BLOCK_SUBBLOCKS (block)) == NULL_TREE)
+    block = BLOCK_SUBBLOCKS (block);
   auto_vec<tree, 10> block_stack;
 
   /* Reset the TREE_ASM_WRITTEN bit for all blocks.  */
diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
index 3cd3613..828c78a 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -599,7 +599,11 @@ remove_unused_scope_block_p (tree scope)
      ;
    /* Outer scope is always used.  */
    else if (!BLOCK_SUPERCONTEXT (scope)
-            || TREE_CODE (BLOCK_SUPERCONTEXT (scope)) == FUNCTION_DECL)
+            || TREE_CODE (BLOCK_SUPERCONTEXT (scope)) == FUNCTION_DECL
+            || (flag_force_dwarf_blocks
+                && BLOCK_SUPERCONTEXT (BLOCK_SUPERCONTEXT (scope))
+                && TREE_CODE (BLOCK_SUPERCONTEXT (BLOCK_SUPERCONTEXT (scope)))
+                == FUNCTION_DECL))
      unused = false;
    /* Innermost blocks with no live variables nor statements can be always
       eliminated.  */
-- 
1.8.3

>From 2f78a621e79f9646e42dbce5e40b7dd55e827239 Mon Sep 17 00:00:00 2001
From: Andrei Herman <andrei_her...@codesourcery.com>
Date: Sun, 27 Jul 2014 16:07:49 +0300
Subject: [PATCH 3/3]    Support flag_force_dwarf_blocks in C++.

        * cp-objcp-common.c (cxx_block_may_fallthru): Return false for break
        or continue, when flag_force_dwarf_blocks.

        * cp-tree.h (pop_scope_for_labels): New.

        * name-lookup.c (keep_current_level): New.
        (kept_level_p): When flag_force_dwarf_blocks, avoid creating duplicate
        blocks.

        * name-lookup.h (keep_current_level): New.

        * parser.c (cp_parser_statement): Add last_label and pass it when
        calling cp_parser_label_for_labeled_statement, to create a label scope
        for the first label of a statement.  Close forced scopes at current
        level, after labeled compound statements that do not fall through.
        (cp_parser_force_block_for_label): New.
        (pop_scope_for_labels): New.
        (cp_parser_label_for_labeled_statement): Add parameter.  Create a label
        scope for the first label of a statement.
        (cp_parser_compound_statement): Force a block for compound statement.
        (cp_parser_implicitly_scoped_statement): Likewise for if-then, if-else,
        switch and do statements.
        (cp_parser_already_scoped_statement): Likewise for for/while bodies.

        * semantics.c (do_poplevel): Close any forced scopes in given level.
        (build_data_member_initialization): Allow BIND_EXP.

Signed-off-by: Andrei Herman <andrei_her...@codesourcery.com>
---
 gcc/cp/cp-objcp-common.c |   6 +++
 gcc/cp/cp-tree.h         |   1 +
 gcc/cp/name-lookup.c     |  39 ++++++++++++++++-
 gcc/cp/name-lookup.h     |   1 +
 gcc/cp/parser.c          | 108 ++++++++++++++++++++++++++++++++++++++++++-----
 gcc/cp/semantics.c       |   5 +++
 6 files changed, 149 insertions(+), 11 deletions(-)

diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index 78dddef..9371a8e 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -238,6 +238,12 @@ cxx_block_may_fallthru (const_tree stmt)
       return false;
 
     default:
+      if (flag_force_dwarf_blocks)
+        {
+          if (TREE_CODE (stmt) == BREAK_STMT ||
+              TREE_CODE (stmt) == CONTINUE_STMT)
+            return false;
+        }
       return true;
     }
 }
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7d29c2c..4953ad9 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5501,6 +5501,7 @@ extern bool maybe_clone_body                      (tree);
 extern tree cp_convert_range_for (tree, tree, tree, bool);
 extern bool parsing_nsdmi (void);
 extern void inject_this_parameter (tree, cp_cv_quals);
+extern void pop_scope_for_labels (tree);
 
 /* in pt.c */
 extern bool check_template_shadow              (tree);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 2baeeb7..e378d6e 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -1442,6 +1442,31 @@ static bool keep_next_level_flag;
 
 static int binding_depth = 0;
 
+/* If binding level SCOPE has been forced by flag_force_dwarf_blocks,
+   then find and return the nearest enclosing binding level which is not
+   a forced level.  Otherwise just return the given level.  */
+
+static cp_binding_level *
+get_enclosing_non_forced_scope (cp_binding_level * scope)
+{
+  if (block_list_stack && !block_list_stack->is_empty ())
+    {
+      int six = stmt_list_stack->length () - 1;
+      int bix = block_list_stack->length () - 1;
+      while (six >= 0 && bix >= 0)
+        {
+          if ((*stmt_list_stack)[six] == (*block_list_stack)[bix]->block)
+            {
+              scope = scope->level_chain;
+              six--; bix--;
+            }
+          else
+            return scope;
+        }
+    }
+  return scope;
+}
+
 static void
 indent (int depth)
 {
@@ -1677,6 +1702,8 @@ innermost_nonclass_level (void)
   b = current_binding_level;
   while (b->kind == sk_class)
     b = b->level_chain;
+  if (flag_force_dwarf_blocks)
+    b = get_enclosing_non_forced_scope (b);
 
   return b;
 }
@@ -1745,7 +1772,8 @@ local_bindings_p (void)
 bool
 kept_level_p (void)
 {
-  return (current_binding_level->blocks != NULL_TREE
+  return ((!flag_force_dwarf_blocks
+           && current_binding_level->blocks != NULL_TREE)
          || current_binding_level->keep
          || current_binding_level->kind == sk_cleanup
          || current_binding_level->names != NULL_TREE
@@ -1778,6 +1806,15 @@ keep_next_level (bool keep)
   keep_next_level_flag = keep;
 }
 
+/* Same as keep_next_level, but works on the current (already
+   created) binding level.  */
+
+void
+keep_current_level (bool keep)
+{
+  current_binding_level->keep = keep;
+}
+
 /* Return the list of declarations of the current level.
    Note that this list is in reverse order unless/until
    you nreverse it; and when you do nreverse it, you must
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index 40e0338..058a6fc 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -303,6 +303,7 @@ extern void push_to_top_level (void);
 extern void pop_from_top_level (void);
 extern void pop_everything (void);
 extern void keep_next_level (bool);
+extern void keep_current_level (bool);
 extern bool is_ancestor (tree, tree);
 extern tree push_scope (tree);
 extern void pop_scope (tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c4440af..212d08e 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1978,7 +1978,7 @@ static void cp_parser_lambda_body
 static void cp_parser_statement
   (cp_parser *, tree, bool, bool *);
 static void cp_parser_label_for_labeled_statement
-(cp_parser *, tree);
+  (cp_parser *, tree, bool);
 static tree cp_parser_expression_statement
   (cp_parser *, tree);
 static tree cp_parser_compound_statement
@@ -9341,6 +9341,7 @@ cp_parser_statement (cp_parser* parser, tree 
in_statement_expr,
   tree statement, std_attrs = NULL_TREE;
   cp_token *token;
   location_t statement_location, attrs_location;
+  bool label_last = false;
 
  restart:
   if (if_p != NULL)
@@ -9379,7 +9380,8 @@ cp_parser_statement (cp_parser* parser, tree 
in_statement_expr,
          /* Looks like a labeled-statement with a case label.
             Parse the label, and then use tail recursion to parse
             the statement.  */
-         cp_parser_label_for_labeled_statement (parser, std_attrs);
+         cp_parser_label_for_labeled_statement (parser, std_attrs, label_last);
+          label_last = true;
          goto restart;
 
        case RID_IF:
@@ -9461,13 +9463,22 @@ cp_parser_statement (cp_parser* parser, tree 
in_statement_expr,
             Parse the label, and then use tail recursion to parse
             the statement.  */
 
-         cp_parser_label_for_labeled_statement (parser, std_attrs);
+         cp_parser_label_for_labeled_statement (parser, std_attrs, label_last);
+          label_last = true;
          goto restart;
        }
     }
   /* Anything that starts with a `{' must be a compound-statement.  */
   else if (token->type == CPP_OPEN_BRACE)
-    statement = cp_parser_compound_statement (parser, NULL, false, false);
+    {
+      statement = cp_parser_compound_statement (parser, NULL, false, false);
+      /* When a label is followed by a compound-statement which does
+         not fall-through (ends with some form of 'jump' statement),
+         close the forced scope(s) at current level.  */
+      if (flag_force_dwarf_blocks && label_last
+          && !block_may_fallthru (statement))
+        pop_scope_for_labels (0);
+    }
   /* CPP_PRAGMA is a #pragma inside a function body, which constitutes
      a statement all its own.  */
   else if (token->type == CPP_PRAGMA)
@@ -9480,7 +9491,10 @@ cp_parser_statement (cp_parser* parser, tree 
in_statement_expr,
       if (in_compound)
        cp_parser_pragma (parser, pragma_compound);
       else if (!cp_parser_pragma (parser, pragma_stmt))
-       goto restart;
+        {
+          label_last = false;
+          goto restart;
+        }
       return;
     }
   else if (token->type == CPP_EOF)
@@ -9528,6 +9542,53 @@ cp_parser_statement (cp_parser* parser, tree 
in_statement_expr,
                "attributes at the beginning of statement are ignored");
 }
 
+/* Force creation of a new scope for a LABEL.  If not followed by a compound
+   statement, make it a block (otherwise, the compound statement will create
+   the block).  Push the created scope onto the block_info stack, so we can
+   identify it as a label scope.  */
+
+static void
+cp_parser_force_block_for_label (cp_parser* parser, tree label)
+{
+  if (!flag_force_dwarf_blocks
+      || label == NULL_TREE || label == error_mark_node)
+    return;
+
+  if (!cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+    keep_next_level (true);
+  tree block = begin_compound_stmt (0);
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+  push_block_info (block, loc, true);
+}
+
+/* If current scope is a label scope, pop it from block info stack
+   and close its compound statement.  When called from do_poplevel, a target
+   STMT_LIST may differ from the current statement list.  This may happen at
+   the end of a scope in which some cleanups may have been left behind.
+   These will be removed here.  */
+
+void
+pop_scope_for_labels (tree stmt_list)
+{
+  while (block_list_stack && !block_list_stack->is_empty ())
+    {
+      if (cur_stmt_list == cur_block_info->block && cur_block_info->is_label)
+        {
+          block_loc tl = pop_block_info ();
+          finish_compound_stmt (tl->block);
+        }
+      else
+        /* In case we are looking for a target scope,
+           remove outstanding cleanups.  */
+        if (stmt_list && stmt_list != cur_stmt_list)
+          {
+            add_stmt (pop_stmt_list (cur_stmt_list));
+          }
+        else
+          break;
+    }
+}
+
 /* Parse the label for a labeled-statement, i.e.
 
    identifier :
@@ -9539,13 +9600,18 @@ cp_parser_statement (cp_parser* parser, tree 
in_statement_expr,
 
    When a label is parsed without errors, the label is added to the
    parse tree by the finish_* functions, so this function doesn't
-   have to return the label.  */
+   have to return the label.
+   LABEL_LAST is true when this is not the first label of the statement
+   (like in label1: label2: statement;).  When flag_force_dwarf_blocks is true,
+   we only want to force a block for the first label of a statement.  */
 
 static void
-cp_parser_label_for_labeled_statement (cp_parser* parser, tree attributes)
+cp_parser_label_for_labeled_statement (cp_parser* parser, tree attributes,
+                                       bool label_last)
 {
   cp_token *token;
   tree label = NULL_TREE;
+  tree case_label = NULL_TREE;
   bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
 
   /* The next token should be an identifier.  */
@@ -9588,7 +9654,7 @@ cp_parser_label_for_labeled_statement (cp_parser* parser, 
tree attributes)
          expr_hi = NULL_TREE;
 
        if (parser->in_switch_statement_p)
-         finish_case_label (token->location, expr, expr_hi);
+          case_label = finish_case_label (token->location, expr, expr_hi);
        else
          error_at (token->location,
                    "case label %qE not within a switch statement",
@@ -9601,14 +9667,14 @@ cp_parser_label_for_labeled_statement (cp_parser* 
parser, tree attributes)
       cp_lexer_consume_token (parser->lexer);
 
       if (parser->in_switch_statement_p)
-       finish_case_label (token->location, NULL_TREE, NULL_TREE);
+       case_label = finish_case_label (token->location, NULL_TREE, NULL_TREE);
       else
        error_at (token->location, "case label not within a switch statement");
       break;
 
     default:
       /* Anything else must be an ordinary label.  */
-      label = finish_label_stmt (cp_parser_identifier (parser));
+      case_label = label = finish_label_stmt (cp_parser_identifier (parser));
       break;
     }
 
@@ -9639,6 +9705,19 @@ cp_parser_label_for_labeled_statement (cp_parser* 
parser, tree attributes)
   if (attributes != NULL_TREE)
     cplus_decl_attributes (&label, attributes, 0);
 
+  if (flag_force_dwarf_blocks && case_label)
+    {
+      if (!label_last)
+        cp_parser_force_block_for_label (parser, case_label);
+      else
+        /* The first label may not have seen the open brace
+           and therefor set the keep flag in current scope.
+           If we see it now, we should clear the flag, as the
+           next compound statement will create the block.  */
+        if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+          keep_current_level (false);
+    }
+
   parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
 }
 
@@ -9734,6 +9813,8 @@ cp_parser_compound_statement (cp_parser *parser, tree 
in_statement_expr,
     pedwarn (input_location, OPT_Wpedantic,
             "compound-statement in constexpr function");
   /* Begin the compound-statement.  */
+  if (flag_force_dwarf_blocks)
+    keep_next_level (true);
   compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0);
   /* If the next keyword is `__label__' we have a label declaration.  */
   while (cp_lexer_next_token_is_keyword (parser->lexer, RID_LABEL))
@@ -10757,6 +10838,9 @@ cp_parser_jump_statement (cp_parser* parser)
       break;
     }
 
+  if (flag_force_dwarf_blocks)
+    pop_scope_for_labels (0);
+
   return statement;
 }
 
@@ -10818,6 +10902,8 @@ cp_parser_implicitly_scoped_statement (cp_parser* 
parser, bool *if_p)
   else
     {
       /* Create a compound-statement.  */
+      if (flag_force_dwarf_blocks)
+        keep_next_level (true);
       statement = begin_compound_stmt (0);
       /* Parse the dependent-statement.  */
       cp_parser_statement (parser, NULL_TREE, false, if_p);
@@ -10837,6 +10923,8 @@ cp_parser_implicitly_scoped_statement (cp_parser* 
parser, bool *if_p)
 static void
 cp_parser_already_scoped_statement (cp_parser* parser)
 {
+  if (flag_force_dwarf_blocks)
+    keep_current_level (true);
   /* If the token is a `{', then we must take special action.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
     cp_parser_statement (parser, NULL_TREE, false, NULL);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index edab330..1cee21a 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -451,6 +451,9 @@ do_poplevel (tree stmt_list)
 {
   tree block = NULL;
 
+  if (flag_force_dwarf_blocks && stmts_are_full_exprs_p ())
+    pop_scope_for_labels (stmt_list);
+
   if (stmts_are_full_exprs_p ())
     block = poplevel (kept_level_p (), 1, 0);
 
@@ -7585,6 +7588,8 @@ build_data_member_initialization (tree t, 
vec<constructor_elt, va_gc> **vec)
     t = TREE_OPERAND (t, 0);
   if (TREE_CODE (t) == EXPR_STMT)
     t = TREE_OPERAND (t, 0);
+  if (TREE_CODE (t) == BIND_EXPR)
+    t = BIND_EXPR_BODY (t);
   if (t == error_mark_node)
     return false;
   if (TREE_CODE (t) == STATEMENT_LIST)
-- 
1.8.3

2014-07-27  Andrei Herman  <andrei_her...@codesourcery.com>

        * c-parser.c (c_parser_declaration_or_fndef): Force a block for
        function body.
        (c_parser_force_block_for_label): New.
        (c_parser_label): Add parameter.  Create a label scope for the first
        label of a statement.
        (c_parser_compound_statement_nostart): Pass last_label when calling
        c_parser_label.
        (c_parser_statement): Likewise.
        (c_parser_statement_after_labels): Force a block for compound statement.
        (c_parser_c99_block_statement): Likewise for switch and loop statement
        if its not a compound statement.  Push/pop the forced scope.
        (c_parser_if_body): Likewise for if-then statement.  Pass last_label
        when calling c_parser_label.
        (c_parser_else_body): Likewise for if-else statement.

        * c-decl.c (get_enclosing_non_forced_scope): New.
        (clear_keep_current_level): New.
        (pushdecl): If current scope is a forced scope, put the declaration
        in the enclosing non-forced scope.

        * c-tree.h (clear_keep_current_level): New.

        * c-typeck.c (pop_scope_for_labels): New.
        (c_finish_goto_label, c_finish_goto_ptr, c_finish_return,
        c_finish_bc_stmt): Call pop_scope_for_labels to close current
        label scope if any.
        (c_end_compound_stmt): Likewise.
2014-07-27  Andrei Herman  <andrei_her...@codesourcery.com>

        * c.opt: Add -fforce-dwarf-lexical-blocks option

        * c-opts.c (c_common_post_options): Limit its use to DWARF4.

        * c-common.h (struct block_loc_s, block_loc): New.
        (stmt_tree_s): Add x_cur_block_list stack of block_loc structs
        for statement lists of forced scopes (label and c99).
        (block_list_stack, cur_block_info): New macros.
        (push_block_info, pop_block_info, check_pop_block_info): New.

        * c-semantics.c (push_block_info): New.
        (pop_block_info): New.
        (check_pop_block_info): New.
2014-07-27  Andrei Herman  <andrei_her...@codesourcery.com>

        * doc/invoke.texi: Document force-dwarf-lexical-blocks option.

        * dwarf2out.c (gen_block_die): Force output a lexical block die
        even for blocks without any local declaration.

        * function.c (reorder_blocks): Skip the forced block, when function
        has no inner blocks.

        * tree-ssa-live.c (remove_unused_scope_block_p): Mark the function
        level forced block as used.
2014-07-27  Andrei Herman  <andrei_her...@codesourcery.com>

        * cp-tree.h (pop_scope_for_labels): New.

        * parser.c (cp_parser_statement): Add last_label and pass it when
        calling cp_parser_label_for_labeled_statement, to create a label scope
        for the first label of a statement.  Close forced scopes at current
        level, after labeled compound statements that do not fall through.
        (cp_parser_force_block_for_label): New.
        (pop_scope_for_labels): New.
        (cp_parser_label_for_labeled_statement): Add parameter.  Create a label
        scope for the first label of a statement.
        (cp_parser_compound_statement): Force a block for compound statement.
        (cp_parser_implicitly_scoped_statement): Likewise for if-then, if-else,
        switch and do statements.
        (cp_parser_already_scoped_statement): Likewise for for/while bodies.

        * semantics.c (do_poplevel): Close any forced scopes in given level.
        (build_data_member_initialization): Allow BIND_EXP.

        * name-lookup.h (keep_current_level): New.

        * name-lookup.c (keep_current_level): New.
        (kept_level_p): When flag_force_dwarf_blocks, avoid creating duplicate
        blocks.

        * cp-objcp-common.c (cxx_block_may_fallthru): Return false for break
        or continue, when flag_force_dwarf_blocks.

Reply via email to