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