diff options
author | Jason Merrill <jason@redhat.com> | 2021-04-13 16:18:54 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2021-04-13 20:17:58 -0400 |
commit | 006783f4b165dff25aae3697920fcf54754dddd4 (patch) | |
tree | 0d473b30518596d5f997103a4f1c01786aee9d3c /gcc | |
parent | 6d0d35d518a12ee43c1fbd77df73a66d02305a69 (diff) | |
download | gcc-006783f4b165dff25aae3697920fcf54754dddd4.zip gcc-006783f4b165dff25aae3697920fcf54754dddd4.tar.gz gcc-006783f4b165dff25aae3697920fcf54754dddd4.tar.bz2 |
c++: debug location of variable cleanups [PR88742]
PR49951 complained about the debugger jumping back to the declaration of a
local variable when we run its destructor. That was fixed in 4.7, but broke
again in 4.8. PR58123 fixed an inconsistency in the behavior, but not the
jumping around. This patch addresses the issue by setting EXPR_LOCATION on
a cleanup destructor call to the location of the closing brace of the
compound-statement, or whatever token ends the scope of the variable.
The change to cp_parser_compound_statement is so input_location is the }
rather than the ; of the last substatement.
gcc/cp/ChangeLog:
PR c++/88742
PR c++/49951
PR c++/58123
* semantics.c (set_cleanup_locs): New.
(do_poplevel): Call it.
* parser.c (cp_parser_compound_statement): Consume the }
before finish_compound_stmt.
gcc/testsuite/ChangeLog:
PR c++/88742
* g++.dg/debug/cleanup1.C: New test.
* c-c++-common/Wimplicit-fallthrough-6.c: Adjust diagnostic line.
* c-c++-common/Wimplicit-fallthrough-7.c: Likewise.
* g++.dg/cpp2a/constexpr-dtor3.C: Likewise.
* g++.dg/ext/constexpr-attr-cleanup1.C: Likewise.
* g++.dg/tm/inherit2.C: Likewise.
* g++.dg/tm/unsafe1.C: Likewise.
* g++.dg/warn/Wimplicit-fallthrough-1.C: Likewise.
* g++.dg/gcov/gcov-2.C: Adjust coverage counts.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/parser.c | 5 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 19 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/Wimplicit-fallthrough-6.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/debug/cleanup1.C | 41 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/constexpr-attr-cleanup1.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/gcov/gcov-2.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/tm/inherit2.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/tm/unsafe1.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-1.C | 4 |
11 files changed, 85 insertions, 24 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 8b7801b..aec3aa3 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -12126,11 +12126,12 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, if (function_body) maybe_splice_retval_cleanup (compound_stmt); - /* Finish the compound-statement. */ - finish_compound_stmt (compound_stmt); /* Consume the `}'. */ braces.require_close (parser); + /* Finish the compound-statement. */ + finish_compound_stmt (compound_stmt); + return compound_stmt; } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 8eaaaef..1257722 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -602,6 +602,22 @@ add_decl_expr (tree decl) add_stmt (r); } +/* Set EXPR_LOCATION of the cleanups of any CLEANUP_STMT in STMTS to LOC. */ + +static void +set_cleanup_locs (tree stmts, location_t loc) +{ + if (TREE_CODE (stmts) == CLEANUP_STMT) + { + protected_set_expr_location (CLEANUP_EXPR (stmts), loc); + set_cleanup_locs (CLEANUP_BODY (stmts), loc); + } + else if (TREE_CODE (stmts) == STATEMENT_LIST) + for (tree_stmt_iterator i = tsi_start (stmts); + !tsi_end_p (i); tsi_next (&i)) + set_cleanup_locs (tsi_stmt (i), loc); +} + /* Finish a scope. */ tree @@ -614,6 +630,9 @@ do_poplevel (tree stmt_list) stmt_list = pop_stmt_list (stmt_list); + /* input_location is the last token of the scope, usually a }. */ + set_cleanup_locs (stmt_list, input_location); + if (!processing_template_decl) { stmt_list = c_build_bind_expr (input_location, block, stmt_list); diff --git a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-6.c b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-6.c index 32d5feb..9593f67 100644 --- a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-6.c +++ b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-6.c @@ -121,8 +121,8 @@ L1: int j = 0; bar (j); if (j == 8) - return; /* { dg-warning "statement may fall through" "" { target c++ } } */ - } + return; + } /* { dg-warning "statement may fall through" "" { target c++ } } */ case 2: bar (99); } @@ -151,8 +151,8 @@ L1: if (j == 8) bar (1); else - return; /* { dg-warning "statement may fall through" "" { target c++ } } */ - } + return; + } /* { dg-warning "statement may fall through" "" { target c++ } } */ case 2: bar (99); } @@ -181,8 +181,8 @@ L1: if (j == 8) bar (1); else - bar (2); /* { dg-warning "statement may fall through" "" { target c++ } } */ - } + bar (2); + } /* { dg-warning "statement may fall through" "" { target c++ } } */ case 2: bar (99); } @@ -281,8 +281,8 @@ L1: case 1: { /* { dg-warning "statement may fall through" "" { target c } } */ int j = 9; - switch (j); /* { dg-warning "statement may fall through" "" { target c++ } } */ - } + switch (j); + } /* { dg-warning "statement may fall through" "" { target c++ } } */ case 2: bar (99); } diff --git a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c index a602216..343b625 100644 --- a/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c +++ b/gcc/testsuite/c-c++-common/Wimplicit-fallthrough-7.c @@ -22,8 +22,8 @@ f (int i) { case 1: { /* { dg-warning "statement may fall through" "" { target c } } */ - int a[i]; /* { dg-warning "statement may fall through" "" { target c++ } } */ - } + int a[i]; + } /* { dg-warning "statement may fall through" "" { target c++ } } */ case 2: bar (99); } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C index 193ae93..7700bb7 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-dtor3.C @@ -149,9 +149,9 @@ constexpr int x3 = f3 (); constexpr int f4 () { - W7 w13 = 5; // { dg-message "in 'constexpr' expansion of" } + W7 w13 = 5; return 0; -} +} // { dg-message "in 'constexpr' expansion of" } constexpr int x4 = f4 (); // { dg-message "in 'constexpr' expansion of" } diff --git a/gcc/testsuite/g++.dg/debug/cleanup1.C b/gcc/testsuite/g++.dg/debug/cleanup1.C new file mode 100644 index 0000000..ae0515a --- /dev/null +++ b/gcc/testsuite/g++.dg/debug/cleanup1.C @@ -0,0 +1,41 @@ +// PR c++/88742 +// { dg-additional-options -fdump-tree-gimple-lineno } + + +class C { +public: + C() {} + ~C() {} + operator int() { return 1; } +}; + +int main() { + C a; + C b; + C c; + + if (C e = C()) + { + if (C d = C()) + { + } + else + { + return 42; + } // { dg-final { scan-tree-dump-times ":25:9. C::~C" 1 "gimple" } } + } // { dg-final { scan-tree-dump-times ":26:5. C::~C" 1 "gimple" } } + + while (C f = C()) + { + break; + } // { dg-final { scan-tree-dump-times ":31:5. C::~C" 1 "gimple" } } + + for (C h = C(); C i = C(); ) + break; // { dg-final { scan-tree-dump-times ":34:10. C::~C" 2 "gimple" } } + + switch (C g = C()) + { + default: + break; + } // { dg-final { scan-tree-dump-times ":40:5. C::~C" 1 "gimple" } } +} // { dg-final { scan-tree-dump-times ":41:1. C::~C" 3 "gimple" } } diff --git a/gcc/testsuite/g++.dg/ext/constexpr-attr-cleanup1.C b/gcc/testsuite/g++.dg/ext/constexpr-attr-cleanup1.C index b6e7c69..ab5fd17 100644 --- a/gcc/testsuite/g++.dg/ext/constexpr-attr-cleanup1.C +++ b/gcc/testsuite/g++.dg/ext/constexpr-attr-cleanup1.C @@ -15,9 +15,9 @@ cleanup2 (int *x) constexpr bool foo () { - int a __attribute__((cleanup (cleanup))) = 1; // { dg-message "in 'constexpr' expansion of" } + int a __attribute__((cleanup (cleanup))) = 1; return true; -} +} // { dg-message "in 'constexpr' expansion of" } constexpr bool bar () diff --git a/gcc/testsuite/g++.dg/gcov/gcov-2.C b/gcc/testsuite/g++.dg/gcov/gcov-2.C index 6d002f5..2b4cdd8 100644 --- a/gcc/testsuite/g++.dg/gcov/gcov-2.C +++ b/gcc/testsuite/g++.dg/gcov/gcov-2.C @@ -20,9 +20,9 @@ private: void foo() { - C c; /* count(2) */ + C c; /* count(1) */ c.seti (1); /* count(1) */ -} +} /* count(1) */ int main() { diff --git a/gcc/testsuite/g++.dg/tm/inherit2.C b/gcc/testsuite/g++.dg/tm/inherit2.C index 3b696a9..366f9b3 100644 --- a/gcc/testsuite/g++.dg/tm/inherit2.C +++ b/gcc/testsuite/g++.dg/tm/inherit2.C @@ -26,8 +26,8 @@ int main() B b; // ok D1 d1; // ok B& b1 = d1; - D2 x; // { dg-error "" "destructor of D2 is not transaction-safe" } + D2 x; b1.f(); // ok, calls D1::f() delete b2; // undefined behavior: calls unsafe destructor of D2 - } + } // { dg-error "" "destructor of D2 is not transaction-safe" } } diff --git a/gcc/testsuite/g++.dg/tm/unsafe1.C b/gcc/testsuite/g++.dg/tm/unsafe1.C index 49dd564..710fb1a 100644 --- a/gcc/testsuite/g++.dg/tm/unsafe1.C +++ b/gcc/testsuite/g++.dg/tm/unsafe1.C @@ -5,8 +5,8 @@ struct S { virtual ~S(); }; void f() transaction_safe { - S s; // { dg-error "unsafe" "invocation of unsafe destructor" } -} + S s; +} // { dg-error "unsafe" "invocation of unsafe destructor" } int g(int x) { // is transaction-safe if (x <= 0) diff --git a/gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-1.C b/gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-1.C index 053ed68..b5ebd3d 100644 --- a/gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-1.C +++ b/gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-1.C @@ -25,8 +25,8 @@ fn2 () switch (0) { case 0: { - A b; // { dg-warning "statement may fall through" } - } + A b; + } // { dg-warning "statement may fall through" } default: a = 0; } |