aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.threads/omp-par-scope.exp
blob: 60e065439a485139cb906a67ed2ec2a425391020 (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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# Copyright 2017-2023 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/>.

# This file is part of the gdb testsuite.

# Tests which verify (or not) that GDB can access in-scope variables
# when stopped within an OpenMP parallel region.

standard_testfile

set have_nested_function_support 0
set opts {openmp debug}
if [support_nested_function_tests] {
    lappend opts "additional_flags=-DHAVE_NESTED_FUNCTION_SUPPORT"
    set have_nested_function_support 1
}

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

# gdb_openmp_setup may be defined to set auto-load safe-path and possibly
# sysroot.  These settings are required for gdb to be able to find
# the libgomp python plugin.  (sysroot only needs to be defined for
# remote debugging.)
#
# This approach has both pros and cons.  On the plus side, it's easy
# to automatically set a precise auto-load safe-path.  (It's easy because
# the output of ldd on the binary may be examined to learn the location
# of libgomp.so.)
#
# However, making these settings is also a drawback due to potentially
# overriding settings made by a board file.  Therefore, this proc
# is optional and will only be called if it's defined.

if {[info procs gdb_openmp_setup] != ""} {
    if {[gdb_openmp_setup $binfile] != ""} {
	untested "could not set up OpenMP environment"
	return -1
    }
}

if {![runto_main]} {
    return -1
}

# We want to invoke setup_kfail (and in some cases setup_xfail) when
# GDB does not yet have support for finding the values of variables in
# (non-master) threads.  We'll check this by looking at the output of
# "maint print thread-parent".  If this command is undefined, then GDB
# does not yet have thread parent support, and it makes sense to kfail
# tests which won't work.  It's possible for GDB to have this support,
# but not work.  E.g. it may be the case that the plugin doesn't
# exist or is not found.  We may eventually need to add additional
# constraints related to setting allow_kfail to 0.  But, for the moment,
# this simple test should be sufficient.

set allow_kfail 1
gdb_test_multiple "maint print thread-parent" "maint print thread-parent" {
    -re "Undefined maintenance print command.*$gdb_prompt" {
	pass "maint print thread-parent (does not exist)"
    }
    -re "No parent found.*" {
	pass "maint print thread-parent"
	set allow_kfail 0
    }
}

# Determine whether to xfail some of the tests based on GCC version.
#
# This may need to be tweaked somewhat.  Testing shows that GCC 7.3.1
# needs the xfails.  GCC 8.3.1 and 9.1.1 do not.  The assumption made
# below is that all versions of gcc 8 and above won't require the
# XFAIL setup and that all versions of gcc 7 and below will, but it's
# possible that there are versions in between 7.3.1 and 8.3.1 for
# which this assumption is invalid.

set have_older_gcc 0
if {[test_compiler_info {gcc-[0-7]-*}]} {
    set have_older_gcc 1
}

# maybe_setup_kfail will set up a kfail for gdb/22214 when COND holds in
# addition to considering the values of $have_older_gcc and $allow_kfail.
#
# When $have_older_gcc evaluates to true, setup_xfail will invoked
# instead.

proc maybe_setup_kfail {cond} {
    global have_older_gcc allow_kfail
    if {$have_older_gcc} {
	setup_xfail *-*-*
    } elseif {[uplevel 1 [list expr $cond]] && $allow_kfail} {
	setup_kfail "gdb/22214" *-*-*
    }
}

with_test_prefix "single_scope" {

    gdb_breakpoint [gdb_get_line_number "single_scope: thread_num="]
    gdb_breakpoint [gdb_get_line_number "single_scope: s1="]

    foreach pref {"first thread" "second thread"} {
	with_test_prefix $pref {
	    gdb_continue_to_breakpoint "at printf"

	    if {$have_older_gcc} { setup_xfail "*-*-*" }
	    set thread_num [get_valueof "" thread_num "unknown"]
	    if {$have_older_gcc} { setup_xfail "*-*-*" }
	    gdb_test "print s1" "= -41"
	    gdb_test "print s2" "= \[12\]02"
	    if {$have_older_gcc} { setup_xfail "*-*-*" }
	    gdb_test "print s3" "= -43"
	    gdb_test "print i1" "= 11"
	    gdb_test "print i2" "= \[12]12"
	    maybe_setup_kfail {$thread_num != 0}
	    gdb_test "print i3" "= 13"
	}
    }

    with_test_prefix "after parallel region" {
	gdb_continue_to_breakpoint "at printf"

	gdb_test "print s1" "= -41"
	gdb_test "print s2" "= -42"
	gdb_test "print s3" "= -43"
	gdb_test "print i1" "= 11"
	gdb_test "print i2" "= 12"
	gdb_test "print i3" "= 13"
    }

}

with_test_prefix "multi_scope" {
    gdb_breakpoint [gdb_get_line_number "multi_scope: thread_num="]
    gdb_breakpoint [gdb_get_line_number "multi_scope: i01="]

    foreach pref {"first thread" "second thread"} {
	with_test_prefix $pref {
	    gdb_continue_to_breakpoint "at printf"

	    if {$have_older_gcc} { setup_xfail "*-*-*" }
	    set thread_num [get_valueof "" thread_num "unknown"]

	    gdb_test "print i01" "= 1"
	    maybe_setup_kfail {$thread_num != 0}
	    gdb_test "print i02" "= 2"
	    gdb_test "print i11" "= 11"
	    maybe_setup_kfail {$thread_num != 0}
	    gdb_test "print i12" "= 12"
	    gdb_test "print i21" "= \[12\]21"
	    maybe_setup_kfail {$thread_num != 0}
	    gdb_test "print i22" "= 22"
	    gdb_test "print file_scope_var" "= 9876"
	}
    }

    with_test_prefix "after parallel" {
	gdb_continue_to_breakpoint "at printf"

	gdb_test "print i01" "= 1"
	gdb_test "print i02" "= 2"
	gdb_test "print i11" "= 11"
	gdb_test "print i12" "= 12"
	gdb_test "print i21" "= -21"
	gdb_test "print i22" "= 22"
	gdb_test "print file_scope_var" "= 9876"
    }
}

# Nested functions in C are a GNU extension, so only do the nested function
# tests if compiling with -DHAVE_NESTED_FUNCTION_SUPPORT was successful.

if $have_nested_function_support {
    with_test_prefix "nested_func" {
	gdb_breakpoint [gdb_get_line_number "nested_func: tn="]

	foreach call_prefix {"1st call" "2nd call"} {
	    with_test_prefix $call_prefix {
		foreach thread_prefix {"1st thread" "2nd thread"} {
		    with_test_prefix $thread_prefix {
			gdb_continue_to_breakpoint "at printf"

			if {$have_older_gcc} { setup_xfail "*-*-*" }
			set thread_num [get_valueof "" "tn" "unknown"]

			gdb_test "print file_scope_var" "= 9876"
			if {$have_older_gcc} { setup_xfail *-*-* }
			gdb_test "print s1" "= -42"
			if {$call_prefix eq "1st call"} {
			    gdb_test "print i" "= 1"
			} else {
			    gdb_test "print i" "= 101"
			}
			gdb_test "print j" "= \[12\]000"
			maybe_setup_kfail {$thread_num != 0}
			if {$call_prefix eq "1st call"} {
			    gdb_test "print k" "= 3"
			} else {
			    gdb_test "print k" "= 103"
			}
			if {$call_prefix eq "1st call"} {
			    gdb_test "print p" "= 10"
			} else {
			    gdb_test "print p" "= 20"
			}
			gdb_test "print q" "= \[12\]001"
			maybe_setup_kfail {$thread_num != 0}
			if {$call_prefix eq "1st call"} {
			    gdb_test "print r" "= 12"
			} else {
			    gdb_test "print r" "= 22"
			}
			gdb_test "print x" "= 4"
			gdb_test "print y" "= \[12\]002"
			maybe_setup_kfail {$thread_num != 0}
			gdb_test "print z" "= 6"
			if {$have_older_gcc} { setup_xfail "*-*-*" }
			gdb_test "print tn" "= \[01\]"
		    }
		}
	    }
	}
    }
}

with_test_prefix "nested_parallel" {
    gdb_breakpoint [gdb_get_line_number "nested_parallel (inner threads)"]

    with_test_prefix "inner_threads" {
	foreach pref {"1st stop" "2nd stop" "3rd stop" "4th stop"} {
	    with_test_prefix $pref {
		gdb_continue_to_breakpoint "at printf"

		# Don't need setup_xfail here due to fact that num is made
		# made known to the inner parallel region.
		set thread_num [get_valueof "" "num" "unknown"]

		if {$have_older_gcc} { setup_xfail "*-*-*" }
		set inner_thread_num [get_valueof "" "inner_num" "unknown"]

		gdb_test "print file_scope_var" "= 9876"
		gdb_test "print num" "= \[01\]"
		maybe_setup_kfail {$thread_num != 0 || $inner_thread_num != 0}
		gdb_test "print i" "= 1"
		maybe_setup_kfail {$thread_num != 0 || $inner_thread_num != 0}
		gdb_test "print j" "= 2"
		if {$have_older_gcc || ($inner_thread_num != 0 && $allow_kfail)} { setup_xfail *-*-* }
		gdb_test "print l" "= 10\[24\]"
		if {$have_older_gcc ||( $inner_thread_num != 0 && $allow_kfail)} { setup_xfail *-*-* }
		gdb_test "print k" "= 10\[13\]"
	    }
	}
    }

    with_test_prefix "outer_threads" {
	gdb_breakpoint [gdb_get_line_number "nested_parallel (outer threads)"]

	with_test_prefix "outer stop" {
	    gdb_continue_to_breakpoint "at printf"

	    if {$have_older_gcc} { setup_xfail "*-*-*" }
	    # Use get_local_valueof instead of get_valueof to avoid picking up
	    # some random 'num' in a shared library.
	    set thread_num [get_local_valueof "num" "unknown"]

	    gdb_test "print file_scope_var" "= 9876"
	    if {$have_older_gcc} { setup_xfail "*-*-*" }
	    gdb_test "print num" "= \[01\]"
	    maybe_setup_kfail {$thread_num != 0}
	    gdb_test "print i" "= 1"
	    maybe_setup_kfail {$thread_num != 0}
	    gdb_test "print j" "= 2"
	    gdb_test "print l" "= 10\[24\]"
	    if {$have_older_gcc} { setup_xfail "*-*-*" }
	    gdb_test "print k" "= 10\[13\]"
	}
    }
}