summaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.cp/gdb2495.exp
blob: bfc99bd99c3b5575796abf8115f471503e7d819d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# Copyright 2009-2022 Free Software Foundation, Inc.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


# In gdb inferior function calls, if a C++ exception is raised in the
# dummy-frame, and the exception handler is (normally, and expected to
# be) out-of-frame, the default C++ handler will (wrongly) be called
# in an inferior function call.
# This is incorrect as an exception can normally and legally be handled
# out-of-frame.  The confines of the dummy frame prevent the unwinder
# from finding the correct handler (or any handler, unless it is
# in-frame).  The default handler calls std::terminate.  This will kill
# the inferior.  Assert that terminate should never be called in an
# inferior function call.  These tests test the functionality around
# unwinding that sequence and also tests the flag behaviour gating this
# functionality.
#
# PR c++/9600.

# This test is largely based of gdb.base/callfuncs.exp.

if { [skip_cplus_tests] } { continue }

if [target_info exists gdb,nosignals] {
    verbose "Skipping gdb2495.exp because of nosignals."
    continue
}

standard_testfile .cc

# Create and source the file that provides information about the compiler
# used to compile the test case.
if [get_compiler_info "c++"] {
    return -1
}

# Some targets can't do function calls, so don't even bother with this
# test.
if [target_info exists gdb,cannot_call_functions] {
    unsupported "this target can not call functions"
    continue
}

if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} {
    return -1
}

if ![runto_main] then {
    perror "couldn't run to main"
    continue
}

# See http://sourceware.org/gdb/bugs/2495

# Test normal baseline behaviour. Call a function that
# does not raise an exception.
gdb_test "p exceptions.no_throw_function()" " = 1"
# And one that does but handles it in-frame.
gdb_test "p exceptions.throw_function_with_handler()" " = 2"
# Both should return normally.

# Test basic unwind.  Call a function that raises an exception but
# does not handle it.  It should be rewound.
gdb_test "p exceptions.throw_function()" \
    "The program being debugged entered a std::terminate call, .*" \
    "call a function that raises an exception without a handler."

# Make sure that after rewinding we are back at the call parent.
gdb_test "bt" \
    "#0  main.*" \
    "bt after returning from a popped frame"

# Make sure the only breakpoint is the one set via the runto_main
# call and that the std::terminate breakpoint has evaporated and
# cleaned-up.
gdb_test "info breakpoints" \
    "gdb2495\.cc.*"

# Turn off this new behaviour.
gdb_test_no_output "set unwind-on-terminating-exception off"

# Check that it is turned off.
gdb_test "show unwind-on-terminating-exception" \
    "exception is unhandled while in a call dummy is off.*" \
    "turn off unwind on terminating exception flag"

# Check that the old behaviour is restored.
gdb_test "p exceptions.throw_function()" \
    "The program being debugged was signaled while in a function called .*" \
    "call a function that raises an exception with unwinding off.."

# Restart the inferior back at main.
if ![runto_main] then {
    perror "couldn't run to main"
    continue
}


# Check to see if the new behaviour alters the unwind signal
# behaviour; it should not.  Test both on and off states.

# Turn on unwind on signal behaviour.
gdb_test_no_output "set unwindonsignal on"

# Check that it is turned on.
gdb_test "show unwindonsignal" \
    "signal is received while in a call dummy is on.*" \
    "turn on unwind on signal"

# Check to see if new behaviour interferes with
# normal signal handling in inferior function calls.
gdb_test "p exceptions.raise_signal(1)" \
    "To change this behavior use \"set unwindonsignal off\".*" \
    "check for unwindonsignal off message"

# And reverse - turn off again.
gdb_test_no_output "set unwindonsignal off"

# Check that it is actually turned off.
gdb_test "show unwindonsignal" \
    "signal is received while in a call dummy is off.*" \
    "turn off unwind on signal"

# Check to see if new behaviour interferes with
# normal signal handling in inferior function calls.
gdb_test "p exceptions.raise_signal(1)" \
    "To change this behavior use \"set unwindonsignal on\".*" \
    "check for unwindonsignal on message"