public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
@ 2014-05-07  9:32 Herman, Andrei
  2014-05-07  9:36 ` pinskia
                   ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Herman, Andrei @ 2014-05-07  9:32 UTC (permalink / raw)
  To: gcc-patches; +Cc: Herman_Andrei@mentor.com

[-- Attachment #1: Type: text/plain, Size: 1497 bytes --]


Hi,

Currently GCC only emits DWARF debug information (DW_TAG_lexical_block DIEs)
for compound statements containing significant local declarations.
However, code coverage tools that process the DWARF debug information to
implement block/path coverage need more complete lexical block information. 

This patch adds the necessary functionality under the control of a new 
command line argument: -fforce-dwarf-lexical-blocks.

When this flag is set, a DW_TAG_lexical_block DIE will be emitted 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 labeled
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. 
Consequently, any case in a switch statement that does not flow through to 
the next case, will have its own dwarf lexical block.

The complete change proposal contains 4 patches (attached first 3):
1. Add command line option -fforce-dwarf-lexical-blocks
2. Use of flag_force_dwarf_blocks
3. Create label scopes

A forth patch, extending the proposed functionality to C++ will be submitted in a separate message.

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

Best regards,
Andrei Herman
Mentor Graphics Corporation
Israel branch 


[-- Attachment #2: gcc_c_ChangeLog --]
[-- Type: application/octet-stream, Size: 1265 bytes --]

2014-02-24  Andrei Herman  <Andrei_Herman@codesourcery.com>

	* c-parser.c (c_parser_declaration_or_fndef): Force a block for
	function body.
	(c_parser_statement_after_labels): Likewise for compound statement.
	(c_parser_c99_block_statement): Likewise for switch and loop statement
	if its not a compound statement.
	(c_parser_if_body): Likewise for if-then statement.
	(c_parser_else_body): Likewise for if-else statement.

2014-03-10  Andrei Herman  <Andrei_Herman@codesourcery.com>

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

	* c-parser.c (c_parser_label): Add parameter.  Create a label scope
	for the first label of a statement.
	(c_parser_force_block_for_label): New.
	(c_parser_compound_statement_nostart): Pass last_label when calling
	c_parser_label.
	(c_parser_statement): Likewise.
	(c_parser_if_body, c_parser_else_body): Likewise.

	* 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.

[-- Attachment #3: gcc_c-family_ChangeLog --]
[-- Type: application/octet-stream, Size: 372 bytes --]

2014-03-10  Andrei Herman  <Andrei_Herman@codesourcery.com>

	* 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 label scopes.
	(block_list_stack, cur_block_info): New macros.
	(push_block_info, pop_block_info): New.

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


[-- Attachment #4: gcc_ChangeLog --]
[-- Type: application/octet-stream, Size: 383 bytes --]

2014-02-24  Andrei Herman  <Andrei_Herman@codesourcery.com>

	* common.opt: Add force_dwarf_lexical_blocks flag.
	* opts.c (finish_options): Limit its use to dwarf4.
	* doc/invoke.texi: Document new option.

2014-02-24  Andrei Herman  <Andrei_Herman@codesourcery.com>

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


[-- Attachment #5: 0001-Add-command-line-option-fforce_dwarf_lexical_blocks.patch --]
[-- Type: application/octet-stream, Size: 3291 bytes --]

From b751b208ddb62f8c7e32ea2834020658279a407f Mon Sep 17 00:00:00 2001
From: Andrei Herman <Andrei_Herman@codesourcery.com>
Date: Wed, 12 Feb 2014 17:28:37 +0200
Subject: [PATCH 1/3]         Add command line option -fforce_dwarf_lexical_blocks.

        * gcc/common.opt: Add force_dwarf_lexical_blocks flag.
        * gcc/opts.c (finish_options): Limit its use to dwarf4.
        * gcc/doc/invoke.texi: Document the new option.

Signed-off-by: Andrei Herman <Andrei_Herman@codesourcery.com>
---
 gcc/common.opt      |    4 ++++
 gcc/doc/invoke.texi |   10 ++++++++++
 gcc/opts.c          |   13 +++++++++++++
 3 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/gcc/common.opt b/gcc/common.opt
index d334cf2..2f17f6f 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1175,6 +1175,10 @@ fforce-addr
 Common Ignore
 Does nothing.  Preserved for backward compatibility.
 
+fforce-dwarf-lexical-blocks
+Common Report Var(flag_force_dwarf_blocks)
+Force generation of lexical blocks in dwarf output
+
 fforward-propagate
 Common Report Var(flag_forward_propagate) Optimization
 Perform a forward propagation pass on RTL
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 4d1b657..a897e79 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -329,6 +329,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
@@ -5180,6 +5181,15 @@ 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, 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 available when using DWARF Version 4 or higher.
+
 @item -fdebug-types-section
 @opindex fdebug-types-section
 @opindex fno-debug-types-section
diff --git a/gcc/opts.c b/gcc/opts.c
index 7dee0e7..50eab60 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -866,6 +866,19 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
   /* The -gsplit-dwarf option requires -gpubnames.  */
   if (opts->x_dwarf_split_debug_info)
     opts->x_debug_generate_pub_sections = 1;
+
+  /* The -fforce_dwarf_lexical_blocks option is only relevant when debug info
+     is in DWARF4 format */
+  if (opts->x_flag_force_dwarf_blocks)
+    {
+      if (opts->x_write_symbols != DWARF2_DEBUG || opts->x_dwarf_version < 4)
+        {
+          inform (loc,
+                  "-fforce-dwarf-lexical-blocks is only supported with "
+                  "DWARF4 debug format");
+          opts->x_flag_force_dwarf_blocks = 0;
+        }
+    }
 }
 
 #define LEFT_COLUMN	27
-- 
1.7.1


[-- Attachment #6: 0002-Use-flag_force_dwarf_blocks.patch --]
[-- Type: application/octet-stream, Size: 7102 bytes --]

From d16088a15739bdf417fc752ad05f63b6566ecaaf Mon Sep 17 00:00:00 2001
From: Andrei Herman <Andrei_Herman@codesourcery.com>
Date: Thu, 13 Feb 2014 17:39:52 +0200
Subject: [PATCH 2/3]     Use flag_force_dwarf_blocks.

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

    * gcc/c/c-parser.c (c_parser_declaration_or_fndef): Force a block for
    function body.
    (c_parser_statement_after_labels): Likewise for compound statement.
    (c_parser_c99_block_statement): Likewise for switch and loop statement
    if its not a compound statement.
    (c_parser_if_body): Likewise for if-then statement.
    (c_parser_else_body): Likewise for if-else statement.

    * gcc/dwarf2out.c (gen_block_die): Force output a lexical block
    die even without vars.

Signed-off-by: Andrei Herman <Andrei_Herman@codesourcery.com>
---
 gcc/c/c-parser.c |   37 ++++++++++++++++++++++++++++++-------
 gcc/dwarf2out.c  |   39 ++++++++++++++++++++++++---------------
 2 files changed, 54 insertions(+), 22 deletions(-)

diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 66625aa..d22f79a 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1918,7 +1918,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)
@@ -4858,6 +4868,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:
@@ -5044,10 +5056,14 @@ 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;
   c_parser_statement (parser);
-  return c_end_compound_stmt (loc, block, flag_isoc99);
+  return c_end_compound_stmt (loc, block, flag_isoc99 || force_scope);
 }
 
 /* Parse the body of an if statement.  This is just parsing a
@@ -5061,7 +5077,9 @@ 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;
   while (c_parser_next_token_is_keyword (parser, RID_CASE)
 	 || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
@@ -5082,7 +5100,8 @@ 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);
+  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
@@ -5093,7 +5112,11 @@ 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);
   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)
@@ -5110,7 +5133,7 @@ c_parser_else_body (c_parser *parser)
     }
   else
     c_parser_statement_after_labels (parser);
-  return c_end_compound_stmt (else_loc, block, flag_isoc99);
+  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/dwarf2out.c b/gcc/dwarf2out.c
index d1ca4ba..0e8850b 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -19908,21 +19908,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
-- 
1.7.1


[-- Attachment #7: 0003-Create-label-scopes.patch --]
[-- Type: application/octet-stream, Size: 15211 bytes --]

From c122c455af66f54fac63ad8b46141197990965ca Mon Sep 17 00:00:00 2001
From: Andrei Herman <Andrei_Herman@codesourcery.com>
Date: Mon, 10 Mar 2014 18:16:26 +0200
Subject: [PATCH 3/3]         Create label scopes.

        When flag_force_dwarf_blocks is true, create lexical block
        for the first label of a statement.

        * gcc/c-family/c-common.h (struct block_loc_s): New.
        (stmt_tree_s): Add stack of block_loc structs for statement
        lists of label scopes.
        (block_list_stack): New macro.
        (cur_block_info): New macro.
        (push_block_info): New.
        (pop_block_info): New.

        * gcc/c-family/c-semantics.c (push_block_info): New.
        (pop_block_info): New.

        * gcc/c/c-decl.c (get_enclosing_non_label_scope): New.
        (clear_keep_current_level): New.
        (pushdecl): Add declarations to enclosing non-label scope.

        * gcc/c/c-parser.c (c_parser_force_block_for_label): New.
        (c_parser_compound_statement_nostart): Pass previous value of
        last_label to c_parser_label.
        (c_parser_label): New argument. If this is the first label of
        a statement, create a label scope for it.
        (c_parser_statement): Pass last_label to c_parser_label.
        (c_parser_if_body, c_parser_else_body): Likewise.

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

        * gcc/c/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.

Signed-off-by: Andrei Herman <Andrei_Herman@codesourcery.com>
---
 gcc/c-family/c-common.h    |   20 +++++++++++++++
 gcc/c-family/c-semantics.c |   30 +++++++++++++++++++++++
 gcc/c/c-decl.c             |   38 +++++++++++++++++++++++++++++
 gcc/c/c-parser.c           |   57 ++++++++++++++++++++++++++++++++++++++-----
 gcc/c/c-tree.h             |    1 +
 gcc/c/c-typeck.c           |   49 ++++++++++++++++++++++++++++++++++---
 6 files changed, 184 insertions(+), 11 deletions(-)

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index f074ab1..928c6d6 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -481,12 +481,24 @@ typedef enum ref_operator {
   RO_ARROW_STAR
 } ref_operator;
 
+/* Information about a statement list created for a label.  */
+
+struct GTY(()) block_loc_s {
+  tree block;
+  location_t loc;
+};
+
+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 statement lists of labels.  */
+  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
@@ -522,6 +534,12 @@ struct GTY(()) c_language_function {
 
 #define building_stmt_list_p() (stmt_list_stack && !stmt_list_stack->is_empty())
 
+#define block_list_stack (current_stmt_tree ()->x_cur_block_list)
+
+/* When building a statement-tree, this is the block list element
+   corresponding to the innermost statement list created for a label.  */
+#define cur_block_info	 (block_list_stack->last ())
+
 /* Language-specific hooks.  */
 
 /* If non-NULL, this function is called after a precompile header file
@@ -533,6 +551,8 @@ 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);
+extern tree pop_block_info (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..5755332 100644
--- a/gcc/c-family/c-semantics.c
+++ b/gcc/c-family/c-semantics.c
@@ -29,6 +29,36 @@ 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 for a label.  */
+
+void
+push_block_info (tree block, location_t loc)
+{
+  if (TREE_CODE(block) != STATEMENT_LIST)
+    return;
+
+  block_loc tl;
+  size_t length = tree_code_size (TREE_CODE(block)) + sizeof(location_t);
+  tl = (block_loc) ggc_alloc_cleared_atomic (length);
+  tl->block = block;
+  tl->loc = loc;
+  vec_safe_push (block_list_stack, tl);
+}
+
+/* Pop the block_loc struct and return the statement list and its location.  */
+
+tree
+pop_block_info (location_t &loc)
+{
+  block_loc  tl = NULL;
+  tl = block_list_stack->pop ();
+
+  gcc_assert (tl != NULL);
+
+  loc = tl->loc;
+  return tl->block;
+}
+
 /* Create an empty statement tree rooted at T.  */
 
 tree
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 7a7d68e..b916bc0 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);
 \f
+/* For a given scope, if this scope is a label scope (has been created
+   for a label), then find and return the nearest enclosing scope which
+   is not a label scope.  Otherwise just return the scope as is.  */
+ 
+static c_scope *
+get_enclosing_non_label_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 this scope.  */
+
+void
+clear_keep_current_level (void)
+{
+  current_scope->keep = false;
+}
+
 /* Set the flag for the FLOAT_CONST_DECIMAL64 pragma being ON.  */
 
 void
@@ -2641,6 +2674,11 @@ pushdecl (tree x)
       return x;
     }
 
+  if (flag_force_dwarf_blocks)
+    /* If the current scope is a label scope, put the declaration in the
+       nearest enclosing non-label scope.  */
+    scope = get_enclosing_non_label_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 d22f79a..779cffb 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 *);
@@ -4476,6 +4476,24 @@ 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 (!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);
+}
+
 /* 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).  */
@@ -4546,10 +4564,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))
@@ -4665,7 +4683,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)
 {
   location_t loc1 = c_parser_peek_token (parser)->location;
   tree label = NULL_TREE;
@@ -4727,6 +4745,19 @@ 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).
@@ -4848,11 +4879,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);
 }
 
@@ -5081,11 +5116,15 @@ c_parser_if_body (c_parser *parser, bool *if_p)
     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;
+  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))
     {
@@ -5117,11 +5156,15 @@ c_parser_else_body (c_parser *parser)
   if (force_scope)
     keep_next_level ();
   tree block = c_begin_compound_stmt (flag_isoc99 || force_scope);
+  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;
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 84d5e0b..e584595 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 da6a6fc..16ed442 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -9072,6 +9072,25 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
   return args;
 }
 \f
+/* If current scope is a label scope, pop it from block info stack
+   and close it's 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)
+        {
+          location_t loc;
+          tree block = pop_block_info (loc);
+          add_stmt(c_end_compound_stmt (loc, block, true));
+        }
+      else
+        break;
+    }
+}
+
 /* Generate a goto statement to LABEL.  LOC is the location of the
    GOTO.  */
 
@@ -9085,7 +9104,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;
+    }
   }
 }
 
@@ -9101,7 +9125,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
@@ -9260,7 +9289,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;
+  }
 }
 \f
 struct c_switch {
@@ -9633,7 +9667,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.  */
@@ -9885,6 +9924,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 ();
     }
 
-- 
1.7.1


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
  2014-05-07  9:32 [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option Herman, Andrei
@ 2014-05-07  9:36 ` pinskia
  2014-05-07  9:43   ` Herman, Andrei
  2014-05-07 15:59 ` Mike Stump
  2014-05-07 18:01 ` Joseph S. Myers
  2 siblings, 1 reply; 17+ messages in thread
From: pinskia @ 2014-05-07  9:36 UTC (permalink / raw)
  To: Herman, Andrei; +Cc: gcc-patches, Herman_Andrei@mentor.com



> On May 7, 2014, at 2:32 AM, "Herman, Andrei" <Andrei_Herman@codesourcery.com> wrote:
> 
> 
> Hi,
> 
> Currently GCC only emits DWARF debug information (DW_TAG_lexical_block DIEs)
> for compound statements containing significant local declarations.
> However, code coverage tools that process the DWARF debug information to
> implement block/path coverage need more complete lexical block information. 
> 
> This patch adds the necessary functionality under the control of a new 
> command line argument: -fforce-dwarf-lexical-blocks.
> 
> When this flag is set, a DW_TAG_lexical_block DIE will be emitted 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 labeled
> 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. 
> Consequently, any case in a switch statement that does not flow through to 
> the next case, will have its own dwarf lexical block.
> 
> The complete change proposal contains 4 patches (attached first 3):
> 1. Add command line option -fforce-dwarf-lexical-blocks

This option since it is specific to the c frontend should go into c.opt instead of common.opt. Unless you are going to extend this to Ada, Java and fortran. 

Thanks,
Andrew


> 2. Use of flag_force_dwarf_blocks
> 3. Create label scopes
> 
> A forth patch, extending the proposed functionality to C++ will be submitted in a separate message.
> 
> Attached are the proposed ChangeLog additions, named according to the directory each one belongs to.
> 
> Best regards,
> Andrei Herman
> Mentor Graphics Corporation
> Israel branch 
> 
> <gcc_c_ChangeLog>
> <gcc_c-family_ChangeLog>
> <gcc_ChangeLog>
> <0001-Add-command-line-option-fforce_dwarf_lexical_blocks.patch>
> <0002-Use-flag_force_dwarf_blocks.patch>
> <0003-Create-label-scopes.patch>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
  2014-05-07  9:36 ` pinskia
@ 2014-05-07  9:43   ` Herman, Andrei
  0 siblings, 0 replies; 17+ messages in thread
From: Herman, Andrei @ 2014-05-07  9:43 UTC (permalink / raw)
  To: pinskia; +Cc: gcc-patches, Herman, Andrei, Rozenman, Alex, Inge, Meador

Thanks for the note.
I will make the needed changes and resubmit.

Regards,
Andrei Herman
Mentor Graphics Corporation
Israel branch 

> -----Original Message-----
> From: pinskia@gmail.com [mailto:pinskia@gmail.com]
> Sent: Wednesday, May 07, 2014 12:37 PM
> To: Herman, Andrei
> Cc: gcc-patches@gcc.gnu.org; Herman_Andrei@mentor.com
> Subject: Re: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line
> option
> 
> 
> 
> > On May 7, 2014, at 2:32 AM, "Herman, Andrei"
> <Andrei_Herman@codesourcery.com> wrote:
> >
> >
> > Hi,
> >
> > Currently GCC only emits DWARF debug information
> (DW_TAG_lexical_block
> > DIEs) for compound statements containing significant local declarations.
> > However, code coverage tools that process the DWARF debug information
> > to implement block/path coverage need more complete lexical block
> information.
> >
> > This patch adds the necessary functionality under the control of a new
> > command line argument: -fforce-dwarf-lexical-blocks.
> >
> > When this flag is set, a DW_TAG_lexical_block DIE will be emitted 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
> > labeled 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.
> > Consequently, any case in a switch statement that does not flow
> > through to the next case, will have its own dwarf lexical block.
> >
> > The complete change proposal contains 4 patches (attached first 3):
> > 1. Add command line option -fforce-dwarf-lexical-blocks
> 
> This option since it is specific to the c frontend should go into c.opt instead
> of common.opt. Unless you are going to extend this to Ada, Java and
> fortran.
> 
> Thanks,
> Andrew
> 
> 
> > 2. Use of flag_force_dwarf_blocks
> > 3. Create label scopes
> >
> > A forth patch, extending the proposed functionality to C++ will be
> submitted in a separate message.
> >
> > Attached are the proposed ChangeLog additions, named according to the
> directory each one belongs to.
> >
> > Best regards,
> > Andrei Herman
> > Mentor Graphics Corporation
> > Israel branch
> >
> > <gcc_c_ChangeLog>
> > <gcc_c-family_ChangeLog>
> > <gcc_ChangeLog>
> > <0001-Add-command-line-option-fforce_dwarf_lexical_blocks.patch>
> > <0002-Use-flag_force_dwarf_blocks.patch>
> > <0003-Create-label-scopes.patch>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
  2014-05-07  9:32 [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option Herman, Andrei
  2014-05-07  9:36 ` pinskia
@ 2014-05-07 15:59 ` Mike Stump
  2014-05-07 17:19   ` Herman, Andrei
  2014-05-07 18:01 ` Joseph S. Myers
  2 siblings, 1 reply; 17+ messages in thread
From: Mike Stump @ 2014-05-07 15:59 UTC (permalink / raw)
  To: Herman, Andrei; +Cc: gcc-patches, Herman_Andrei@mentor.com

On May 7, 2014, at 2:32 AM, Herman, Andrei <Andrei_Herman@codesourcery.com> wrote:
> However, code coverage tools that process the DWARF debug information to
> implement block/path coverage need more complete lexical block information. 

So, it would be nice to give a hint in the actual documentation, why a user might use the flag, or for a maintainer to be able to predict exactly what was desired in some obscure corner of dwarf semantics given the documentation.  I think it can be as simple as “This option is useful for code coverage tools that utilize the dwarf debug information.”  A user, upon seeing that, would then ask, do I have such a tool, say no, and then know they don’t have to contemplate the goodness of the option further.  If one is writing a coverage tool, upon seeing the documentation, they might then ask themselves, how might I use that flag profitably for my users.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
  2014-05-07 15:59 ` Mike Stump
@ 2014-05-07 17:19   ` Herman, Andrei
  2014-05-07 17:25     ` Andrew Pinski
  2014-05-07 18:01     ` Mike Stump
  0 siblings, 2 replies; 17+ messages in thread
From: Herman, Andrei @ 2014-05-07 17:19 UTC (permalink / raw)
  To: Mike Stump; +Cc: gcc-patches, Herman, Andrei

Thanks for the suggestion.
The current patch includes the following text added in gcc/doc/invoke.texi:

@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 available when using DWARF Version 4 or higher.

I can add the suggested sentence at the beginning of the description, to save time for users not interested in the more detailed explanation.

Regards,
Andrei Herman
Mentor Graphics Corporation
Israel branch 


> -----Original Message-----
> From: Mike Stump [mailto:mikestump@comcast.net]
> Sent: Wednesday, May 07, 2014 7:00 PM
> To: Herman, Andrei
> Cc: gcc-patches@gcc.gnu.org; Herman_Andrei@mentor.com
> Subject: Re: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line
> option
> 
> On May 7, 2014, at 2:32 AM, Herman, Andrei
> <Andrei_Herman@codesourcery.com> wrote:
> > However, code coverage tools that process the DWARF debug information
> > to implement block/path coverage need more complete lexical block
> information.
> 
> So, it would be nice to give a hint in the actual documentation, why a user
> might use the flag, or for a maintainer to be able to predict exactly what
> was desired in some obscure corner of dwarf semantics given the
> documentation.  I think it can be as simple as "This option is useful for code
> coverage tools that utilize the dwarf debug information."  A user, upon
> seeing that, would then ask, do I have such a tool, say no, and then know
> they don't have to contemplate the goodness of the option further.  If one
> is writing a coverage tool, upon seeing the documentation, they might then
> ask themselves, how might I use that flag profitably for my users.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
  2014-05-07 17:19   ` Herman, Andrei
@ 2014-05-07 17:25     ` Andrew Pinski
  2014-05-07 18:01     ` Mike Stump
  1 sibling, 0 replies; 17+ messages in thread
From: Andrew Pinski @ 2014-05-07 17:25 UTC (permalink / raw)
  To: Herman, Andrei; +Cc: Mike Stump, gcc-patches

On Wed, May 7, 2014 at 10:19 AM, Herman, Andrei
<Andrei_Herman@codesourcery.com> wrote:
> Thanks for the suggestion.
> The current patch includes the following text added in gcc/doc/invoke.texi:
>
> @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 available when using DWARF Version 4 or higher.
>
> I can add the suggested sentence at the beginning of the description, to save time for users not interested in the more detailed explanation.

Also be explicit that the option only applies to C/C++ code in the
documentation.

Thanks,
Andrew Pinski

>
> Regards,
> Andrei Herman
> Mentor Graphics Corporation
> Israel branch
>
>
>> -----Original Message-----
>> From: Mike Stump [mailto:mikestump@comcast.net]
>> Sent: Wednesday, May 07, 2014 7:00 PM
>> To: Herman, Andrei
>> Cc: gcc-patches@gcc.gnu.org; Herman_Andrei@mentor.com
>> Subject: Re: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line
>> option
>>
>> On May 7, 2014, at 2:32 AM, Herman, Andrei
>> <Andrei_Herman@codesourcery.com> wrote:
>> > However, code coverage tools that process the DWARF debug information
>> > to implement block/path coverage need more complete lexical block
>> information.
>>
>> So, it would be nice to give a hint in the actual documentation, why a user
>> might use the flag, or for a maintainer to be able to predict exactly what
>> was desired in some obscure corner of dwarf semantics given the
>> documentation.  I think it can be as simple as "This option is useful for code
>> coverage tools that utilize the dwarf debug information."  A user, upon
>> seeing that, would then ask, do I have such a tool, say no, and then know
>> they don't have to contemplate the goodness of the option further.  If one
>> is writing a coverage tool, upon seeing the documentation, they might then
>> ask themselves, how might I use that flag profitably for my users.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
  2014-05-07 17:19   ` Herman, Andrei
  2014-05-07 17:25     ` Andrew Pinski
@ 2014-05-07 18:01     ` Mike Stump
  1 sibling, 0 replies; 17+ messages in thread
From: Mike Stump @ 2014-05-07 18:01 UTC (permalink / raw)
  To: Herman, Andrei; +Cc: gcc-patches

On May 7, 2014, at 10:19 AM, Herman, Andrei <Andrei_Herman@codesourcery.com> wrote:
> Thanks for the suggestion.

> I can add the suggested sentence at the beginning of the description, to save time for users not interested in the more detailed explanation.

I’d put it at the end…  I think the description you have it more important.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
  2014-05-07  9:32 [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option Herman, Andrei
  2014-05-07  9:36 ` pinskia
  2014-05-07 15:59 ` Mike Stump
@ 2014-05-07 18:01 ` Joseph S. Myers
  2014-05-08 14:57   ` Herman, Andrei
  2 siblings, 1 reply; 17+ messages in thread
From: Joseph S. Myers @ 2014-05-07 18:01 UTC (permalink / raw)
  To: Herman, Andrei; +Cc: gcc-patches, Herman_Andrei@mentor.com

On Wed, 7 May 2014, Herman, Andrei wrote:

> When this flag is set, a DW_TAG_lexical_block DIE will be emitted 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 labeled
> 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. 
> Consequently, any case in a switch statement that does not flow through to 
> the next case, will have its own dwarf lexical block.

The documentation appears to suggest it's purely about debug info and has 
no effect on language semantics.  However, the implementation appears to 
force C99 scoping rules.  I don't think it's appropriate for a debug info 
option to have that effect; that is, gcc.dg/c90-scope-1.c should still 
pass even with the option enabled (more generally, the whole C testsuite 
should be verified to work with the option enabled).  I suspect the 
changes adding scopes for labels would also affect language semantics; 
it's valid in C to have a declaration (not having variably modified type) 
after one case in a switch statement that gets used in another case even 
when control does not flow through.

If you can't avoid affecting language semantics then you need to be very 
clear in the documentation that the option makes some invalid programs 
valid and vice versa and changes the semantics of some valid programs 
(even if you then assert the affected cases are uncommon in real C code).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
  2014-05-07 18:01 ` Joseph S. Myers
@ 2014-05-08 14:57   ` Herman, Andrei
  2014-05-08 17:26     ` Joseph S. Myers
  0 siblings, 1 reply; 17+ messages in thread
From: Herman, Andrei @ 2014-05-08 14:57 UTC (permalink / raw)
  To: Myers, Joseph; +Cc: gcc-patches, Herman, Andrei

> -----Original Message-----
> From: Joseph Myers [mailto:joseph@codesourcery.com]
> Sent: Wednesday, May 07, 2014 9:01 PM
> To: Herman, Andrei
> Cc: gcc-patches@gcc.gnu.org; Herman_Andrei@mentor.com
> Subject: Re: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line
> option
> 
> On Wed, 7 May 2014, Herman, Andrei wrote:
> 
> > When this flag is set, a DW_TAG_lexical_block DIE will be emitted 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
> > labeled 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.
> > Consequently, any case in a switch statement that does not flow
> > through to the next case, will have its own dwarf lexical block.
> 
> The documentation appears to suggest it's purely about debug info and has
> no effect on language semantics.  However, the implementation appears to
> force C99 scoping rules.  I don't think it's appropriate for a debug info option

You are right. The C99 scoping rules are forced with this option.

> to have that effect; that is, gcc.dg/c90-scope-1.c should still pass even with
> the option enabled (more generally, the whole C testsuite should be verified
> to work with the option enabled).  I suspect the changes adding scopes for
> labels would also affect language semantics; it's valid in C to have a
> declaration (not having variably modified type) after one case in a switch
> statement that gets used in another case even when control does not flow
> through.

The changes in gcc/c/c-decl.c  are meant to deal with this problem. Declarations
that would fall into the scope of a newly created label scope are moved into the 
enclosing "normal" (non label) scope, where they actually belong.

> 
> If you can't avoid affecting language semantics then you need to be very
> clear in the documentation that the option makes some invalid programs
> valid and vice versa and changes the semantics of some valid programs
> (even if you then assert the affected cases are uncommon in real C code).
> 

Here is the changed documentation:

@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 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.
Note that when this option is used, it will enforce the scoping rules of the
C99 standard, which may make some programs that are invalid, to become valid
and vice versa.

> --
> Joseph S. Myers
> joseph@codesourcery.com

Regards,
Andrei Herman
Mentor Graphics
Israel branch

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
  2014-05-08 14:57   ` Herman, Andrei
@ 2014-05-08 17:26     ` Joseph S. Myers
  2014-05-08 17:44       ` Herman, Andrei
  0 siblings, 1 reply; 17+ messages in thread
From: Joseph S. Myers @ 2014-05-08 17:26 UTC (permalink / raw)
  To: Herman, Andrei; +Cc: gcc-patches

On Thu, 8 May 2014, Herman, Andrei wrote:

> The changes in gcc/c/c-decl.c  are meant to deal with this problem. Declarations
> that would fall into the scope of a newly created label scope are moved into the 
> enclosing "normal" (non label) scope, where they actually belong.

Shouldn't you be able to do something like that for the other cases as 
well, to avoid forcing C99 scoping rules?

In any case, I think you need to run the complete "gcc" testsuite with 
this option enabled and compare with the results for a default testsuite 
run.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
  2014-05-08 17:26     ` Joseph S. Myers
@ 2014-05-08 17:44       ` Herman, Andrei
  2014-05-08 21:01         ` Joseph S. Myers
  0 siblings, 1 reply; 17+ messages in thread
From: Herman, Andrei @ 2014-05-08 17:44 UTC (permalink / raw)
  To: Myers, Joseph; +Cc: gcc-patches, Herman, Andrei

> -----Original Message-----
> From: Joseph Myers [mailto:joseph@codesourcery.com]
> Sent: Thursday, May 08, 2014 8:27 PM
> To: Herman, Andrei
> Cc: gcc-patches@gcc.gnu.org
> Subject: RE: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line
> option
> 
> On Thu, 8 May 2014, Herman, Andrei wrote:
> 
> > The changes in gcc/c/c-decl.c  are meant to deal with this problem.
> > Declarations that would fall into the scope of a newly created label
> > scope are moved into the enclosing "normal" (non label) scope, where
> they actually belong.
> 
> Shouldn't you be able to do something like that for the other cases as well,
> to avoid forcing C99 scoping rules?

I will think about it if you think it's critical.

> 
> In any case, I think you need to run the complete "gcc" testsuite with this
> option enabled and compare with the results for a default testsuite run.

I will definitely run the complete testsuites without and with the option enabled.

> 
> --
> Joseph S. Myers
> joseph@codesourcery.com


Thanks and regards,
Andrei Herman
Mentor Graphics Corporation
Israel branch 


^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
  2014-05-08 17:44       ` Herman, Andrei
@ 2014-05-08 21:01         ` Joseph S. Myers
  0 siblings, 0 replies; 17+ messages in thread
From: Joseph S. Myers @ 2014-05-08 21:01 UTC (permalink / raw)
  To: Herman, Andrei; +Cc: gcc-patches

On Thu, 8 May 2014, Herman, Andrei wrote:

> > > Declarations that would fall into the scope of a newly created label
> > > scope are moved into the enclosing "normal" (non label) scope, where
> > they actually belong.
> > 
> > Shouldn't you be able to do something like that for the other cases as well,
> > to avoid forcing C99 scoping rules?
> 
> I will think about it if you think it's critical.

I think it's logically the right design of the option.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
  2014-07-28 13:50   ` Herman, Andrei
@ 2014-08-14 21:14     ` Joseph S. Myers
  0 siblings, 0 replies; 17+ messages in thread
From: Joseph S. Myers @ 2014-08-14 21:14 UTC (permalink / raw)
  To: Herman, Andrei; +Cc: gcc-patches, Alex_Rozenman

On Mon, 28 Jul 2014, Herman, Andrei wrote:

> 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.

The front-end parts of these patches are OK with the changes indicated 
below if the non-front-end parts are approved.

> +  /* 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 it's deliberate not to give the diagnostic for write_symbols != 
DWARF2_DEBUG, please add a comment explaining why the diagnostic is not 
given in that case.

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

As previously noted, should also be enabled for ObjC and ObjC++ unless 
there is a clear reason not to do so.

> +/* Information about a statement list created for a label (is_label=true)
> +   or for a forced c99 scope.  The -fforce-dwarf-lexical-blocks will

"The -fforce-dwarf-lexical-blocks option".

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
  2014-06-19 21:09 ` Joseph S. Myers
  2014-06-21 17:06   ` Herman, Andrei
@ 2014-07-28 13:50   ` Herman, Andrei
  2014-08-14 21:14     ` Joseph S. Myers
  1 sibling, 1 reply; 17+ messages in thread
From: Herman, Andrei @ 2014-07-28 13:50 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches, Alex_Rozenman, Andrei_Herman

[-- Attachment #1: Type: text/plain, Size: 3503 bytes --]

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".
>

[-- Attachment #2: 0001-Add-command-line-option-fforce-dwarf-lexical-blocks.patch --]
[-- Type: text/plain, Size: 3492 bytes --]

From 113007fbf8de51f14f77ba9e652abbcc45c8316a Mon Sep 17 00:00:00 2001
From: Andrei Herman <Andrei_Herman@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_Herman@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


[-- Attachment #3: 0002-Support-flag_force_dwarf_blocks-in-C.patch --]
[-- Type: text/plain, Size: 25303 bytes --]

From 8e3003aee8035aa0ad2163bbb98e442e38e5fa70 Mon Sep 17 00:00:00 2001
From: Andrei Herman <Andrei_Herman@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_Herman@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);
 \f
+/* 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;
 }
 \f
+/* 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;
+  }
 }
 \f
 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


[-- Attachment #4: 0003-Support-flag_force_dwarf_blocks-in-Cplusplus.patch --]
[-- Type: text/plain, Size: 14741 bytes --]

From 2f78a621e79f9646e42dbce5e40b7dd55e827239 Mon Sep 17 00:00:00 2001
From: Andrei Herman <Andrei_Herman@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_Herman@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


[-- Attachment #5: gcc_c_ChangeLog --]
[-- Type: text/plain, Size: 1215 bytes --]

2014-07-27  Andrei Herman  <Andrei_Herman@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.

[-- Attachment #6: gcc_c-family_ChangeLog --]
[-- Type: text/plain, Size: 554 bytes --]

2014-07-27  Andrei Herman  <Andrei_Herman@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.

[-- Attachment #7: gcc_ChangeLog --]
[-- Type: text/plain, Size: 429 bytes --]

2014-07-27  Andrei Herman  <Andrei_Herman@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.

[-- Attachment #8: gcc_cp_ChangeLog --]
[-- Type: text/plain, Size: 1218 bytes --]

2014-07-27  Andrei Herman  <Andrei_Herman@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.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
  2014-06-19 21:09 ` Joseph S. Myers
@ 2014-06-21 17:06   ` Herman, Andrei
  2014-07-28 13:50   ` Herman, Andrei
  1 sibling, 0 replies; 17+ messages in thread
From: Herman, Andrei @ 2014-06-21 17:06 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: gcc-patches, Alex_Rozenman

I will be on vacation until July 13.
I'll have access to my e-mail occasionally.

If you could send me please your comments, both style and content, 
pertaining to all three patches related to this subject, I will make all 
the needed changes and I could submit a new version, as soon as I get back.

Thanks and 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".
>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
  2014-06-01 10:33 Herman, Andrei
@ 2014-06-19 21:09 ` Joseph S. Myers
  2014-06-21 17:06   ` Herman, Andrei
  2014-07-28 13:50   ` Herman, Andrei
  0 siblings, 2 replies; 17+ messages in thread
From: Joseph S. Myers @ 2014-06-19 21:09 UTC (permalink / raw)
  To: Herman, Andrei; +Cc: gcc-patches, Alex_Rozenman

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".

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option
@ 2014-06-01 10:33 Herman, Andrei
  2014-06-19 21:09 ` Joseph S. Myers
  0 siblings, 1 reply; 17+ messages in thread
From: Herman, Andrei @ 2014-06-01 10:33 UTC (permalink / raw)
  To: gcc-patches; +Cc: Alex_Rozenman

[-- Attachment #1: Type: text/plain, Size: 1795 bytes --]

Hi,

Currently GCC only emits DWARF debug information (DW_TAG_lexical_block 
DIEs) for compound statements containing significant local declarations.
However, code coverage tools that process the DWARF debug information to
implement block/path coverage need more complete lexical block information.

This patch adds the necessary functionality under the control of a new
command line argument: -fforce-dwarf-lexical-blocks.

When this flag is set, a DW_TAG_lexical_block DIE will be emitted 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 
labeled 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.
Consequently, any case in a switch statement that does not flow through 
to the next case, will have its own dwarf lexical block.

The complete change proposal contains 3 patches (attached first 2):
   1.  Add command line option -fforce-dwarf-lexical-blocks
   2.  Use of flag_force_dwarf_blocks in C.

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

A third patch, extending the proposed functionality to C++ will be 
submitted in a separate message.

NOTE: This is a second submit, with changes made according to 
maintainer's sugestions.

All check-c and check-c++ tests have been run for unix target.
The only test that failed with the -fforce-dwarf-lexical-blocks set
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


[-- Attachment #2: 0001-Add-command-line-option-fforce-dwarf-lexical-blocks.patch --]
[-- Type: text/plain, Size: 3474 bytes --]

From 6dd5796f04ca249e8e59026208e90e7619534a80 Mon Sep 17 00:00:00 2001
From: Andrei Herman <Andrei_Herman@codesourcery.com>
Date: Sun, 1 Jun 2014 11:13:09 +0300
Subject: [PATCH 1/2]             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_Herman@codesourcery.com>
---
 gcc/c-family/c-opts.c |   13 +++++++++++++
 gcc/c-family/c.opt    |    4 ++++
 gcc/doc/invoke.texi   |   12 ++++++++++++
 3 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index 29e9a35..7c9dbfc 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -936,6 +936,19 @@ 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..b66389e 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..5bf154a 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, 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.
+
 @item -fdebug-types-section
 @opindex fdebug-types-section
 @opindex fno-debug-types-section
-- 
1.7.1


[-- Attachment #3: 0002-Use-flag_force_dwarf_blocks.patch --]
[-- Type: text/plain, Size: 24102 bytes --]

From f107431bf094ed2491d8338c4f0157d8b4c7b433 Mon Sep 17 00:00:00 2001
From: Andrei Herman <Andrei_Herman@codesourcery.com>
Date: Sun, 1 Jun 2014 12:35:17 +0300
Subject: [PATCH 2/2]         Use flag_force_dwarf_blocks.

        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_Herman@codesourcery.com>
---
 gcc/c-family/c-common.h    |   23 +++++++++
 gcc/c-family/c-semantics.c |   46 ++++++++++++++++++
 gcc/c/c-decl.c             |   39 +++++++++++++++
 gcc/c/c-parser.c           |  111 ++++++++++++++++++++++++++++++++++++++------
 gcc/c/c-tree.h             |    1 +
 gcc/c/c-typeck.c           |   49 ++++++++++++++++++--
 gcc/dwarf2out.c            |   39 +++++++++------
 gcc/function.c             |    7 +++
 gcc/tree-ssa-live.c        |    6 ++-
 9 files changed, 287 insertions(+), 34 deletions(-)

diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 0d34004..bda689b 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 tree pop_block_info (location_t &);
+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..ec3045f 100644
--- a/gcc/c-family/c-semantics.c
+++ b/gcc/c-family/c-semantics.c
@@ -29,6 +29,52 @@ 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)
+{
+  if (TREE_CODE(block) != STATEMENT_LIST)
+    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 and return the statement list and its location.  */
+
+tree
+pop_block_info (location_t &loc)
+{
+  block_loc  tl = NULL;
+  tl = block_list_stack->pop ();
+
+  gcc_assert (tl != NULL);
+
+  loc = tl->loc;
+  return tl->block;
+}
+
+/* Pop the last block_loc element if it referes to BLOCK and LOC.  */ 
+
+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..b0d4c0f 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -538,6 +538,32 @@ static tree grokdeclarator (const struct c_declarator *,
 static tree grokparms (struct c_arg_info *, bool);
 static void layout_array_type (tree);
 \f
+/* For a given scope, if this 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 +906,14 @@ keep_next_level (void)
   keep_next_level_flag = true;
 }
 
+/* Clear the flag that forces creation of a block for this 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 +2708,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..f373855 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))
@@ -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)
 {
   location_t loc1 = c_parser_peek_token (parser)->location;
   tree label = NULL_TREE;
@@ -4741,6 +4774,19 @@ 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 +4908,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 +4932,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 +5120,18 @@ 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 (force_scope && !flag_isoc99)
+    push_block_info (block, loc, false);
   c_parser_statement (parser);
-  return c_end_compound_stmt (loc, block, flag_isoc99);
+  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 +5145,21 @@ 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 (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 +5174,10 @@ 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);
+  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 +5188,22 @@ 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 (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 +5215,9 @@ c_parser_else_body (c_parser *parser)
     }
   else
     c_parser_statement_after_labels (parser);
-  return c_end_compound_stmt (else_loc, block, flag_isoc99);
+  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..1c8eb2f 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -9132,6 +9132,25 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
   return args;
 }
 \f
+/* If current scope is a label scope, pop it from block info stack
+   and close it's 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)
+        {
+          location_t loc;
+          tree block = pop_block_info (loc);
+          add_stmt(c_end_compound_stmt (loc, block, true));
+        }
+      else
+        break;
+    }
+}
+
 /* Generate a goto statement to LABEL.  LOC is the location of the
    GOTO.  */
 
@@ -9145,7 +9164,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 +9185,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 +9354,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;
+  }
 }
 \f
 struct c_switch {
@@ -9698,7 +9732,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 +9990,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..3b8be30 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..7a6418b 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -4117,6 +4117,13 @@ reorder_blocks (void)
   if (block == NULL_TREE)
     return;
 
+  /* In case we added another block level to functions, use it as top 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..9aa4124 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.7.1


[-- Attachment #4: gcc_c_ChangeLog --]
[-- Type: text/plain, Size: 1222 bytes --]

2014-06-01  Andrei Herman  <Andrei_Herman@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.

[-- Attachment #5: gcc_c-family_ChangeLog --]
[-- Type: text/plain, Size: 555 bytes --]

2014-06-01  Andrei Herman  <Andrei_Herman@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.


[-- Attachment #6: gcc_ChangeLog --]
[-- Type: text/plain, Size: 429 bytes --]

2014-06-01  Andrei Herman  <Andrei_Herman@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.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2014-08-14 21:14 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-07  9:32 [PATCH GCC]Add 'force-dwarf-lexical-blocks' command line option Herman, Andrei
2014-05-07  9:36 ` pinskia
2014-05-07  9:43   ` Herman, Andrei
2014-05-07 15:59 ` Mike Stump
2014-05-07 17:19   ` Herman, Andrei
2014-05-07 17:25     ` Andrew Pinski
2014-05-07 18:01     ` Mike Stump
2014-05-07 18:01 ` Joseph S. Myers
2014-05-08 14:57   ` Herman, Andrei
2014-05-08 17:26     ` Joseph S. Myers
2014-05-08 17:44       ` Herman, Andrei
2014-05-08 21:01         ` Joseph S. Myers
2014-06-01 10:33 Herman, Andrei
2014-06-19 21:09 ` Joseph S. Myers
2014-06-21 17:06   ` Herman, Andrei
2014-07-28 13:50   ` Herman, Andrei
2014-08-14 21:14     ` Joseph S. Myers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).