aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite
diff options
context:
space:
mode:
authorKevin Buettner <kevinb@redhat.com>2017-09-20 15:40:14 -0700
committerKevin Buettner <kevinb@redhat.com>2019-12-10 15:43:58 -0700
commit4c12d936003909cecc63edba0bebe10c6eccae98 (patch)
tree51cff2af752b33764a40aa4e132881c2b27dd1a7 /gdb/testsuite
parentbb47f919bfdb8908361de74a0daf1af208ae425b (diff)
downloadgdb-4c12d936003909cecc63edba0bebe10c6eccae98.zip
gdb-4c12d936003909cecc63edba0bebe10c6eccae98.tar.gz
gdb-4c12d936003909cecc63edba0bebe10c6eccae98.tar.bz2
OpenMP parallel region scope tests
Add tests which check for accessibility of variables from within various OpenMP parallel regions. Tested on Fedora 27, 28, 29, 30, and 31. I also tested with my OpenMP work on Fedora 30. The test has been annotated with setup_xfail and setup_kfail statements so that there are no unexpected failures on any of these platforms when using gcc. Better still, for my own testing anyway, is that there are also no XPASSes or KPASSes either. So, regardless of platform, when using gcc, and regardless of whether my (not yet public) OpenMP work is used, seeing a FAIL indicates a real problem. Fedora 27 results: # of expected passes 85 # of expected failures 65 (Note: I have not retested F27 since v1 of the patch; it's possible that the numbers will be slightly different for v2.) Fedora 28, 29, 30 results: # of expected passes 131 # of expected failures 4 # of known failures 16 Fedora 30, 31 results w/ my OpenMP work: # of expected passes 151 The above results all use gcc, either the system gcc or a development gcc (when testing against my OpenMP work in GDB). I've also tested with clang 9.0.0 and icc 19.0.5.281 20190815 on Fedora 31. Fedora 31, clang: FAIL: gdb.threads/omp-par-scope.exp: single_scope: first thread: print s1 FAIL: gdb.threads/omp-par-scope.exp: single_scope: first thread: print s3 FAIL: gdb.threads/omp-par-scope.exp: single_scope: first thread: print i1 FAIL: gdb.threads/omp-par-scope.exp: single_scope: first thread: print i3 FAIL: gdb.threads/omp-par-scope.exp: single_scope: second thread: print s1 FAIL: gdb.threads/omp-par-scope.exp: single_scope: second thread: print s3 FAIL: gdb.threads/omp-par-scope.exp: single_scope: second thread: print i1 FAIL: gdb.threads/omp-par-scope.exp: multi_scope: first thread: print i02 FAIL: gdb.threads/omp-par-scope.exp: multi_scope: first thread: print i11 FAIL: gdb.threads/omp-par-scope.exp: multi_scope: first thread: print i12 FAIL: gdb.threads/omp-par-scope.exp: multi_scope: first thread: print i22 FAIL: gdb.threads/omp-par-scope.exp: multi_scope: first thread: print file_scope_var FAIL: gdb.threads/omp-par-scope.exp: multi_scope: second thread: print i11 FAIL: gdb.threads/omp-par-scope.exp: multi_scope: second thread: print file_scope_var FAIL: gdb.threads/omp-par-scope.exp: multi_scope: after parallel: print file_scope_var FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: inner_threads: 1st stop: print file_scope_var FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: inner_threads: 1st stop: print num FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: inner_threads: 1st stop: print l FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: inner_threads: 1st stop: print k FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: inner_threads: 2nd stop: print file_scope_var FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: inner_threads: 2nd stop: print num FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: inner_threads: 3rd stop: print file_scope_var FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: inner_threads: 3rd stop: print num FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: inner_threads: 3rd stop: print l FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: inner_threads: 3rd stop: print k FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: inner_threads: 4th stop: print file_scope_var FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: inner_threads: 4th stop: print num FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: outer_threads: outer stop: print file_scope_var FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: outer_threads: outer stop: print i FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: outer_threads: outer stop: print j Fedora 31, icc: FAIL: gdb.threads/omp-par-scope.exp: multi_scope: first thread: print i12 FAIL: gdb.threads/omp-par-scope.exp: multi_scope: first thread: print i22 FAIL: gdb.threads/omp-par-scope.exp: nested_func: 1st call: 1st thread: print s1 FAIL: gdb.threads/omp-par-scope.exp: nested_func: 1st call: 1st thread: print i FAIL: gdb.threads/omp-par-scope.exp: nested_func: 1st call: 1st thread: print j FAIL: gdb.threads/omp-par-scope.exp: nested_func: 1st call: 2nd thread: print s1 FAIL: gdb.threads/omp-par-scope.exp: nested_func: 1st call: 2nd thread: print i FAIL: gdb.threads/omp-par-scope.exp: nested_func: 1st call: 2nd thread: print j FAIL: gdb.threads/omp-par-scope.exp: nested_func: 1st call: 2nd thread: print k FAIL: gdb.threads/omp-par-scope.exp: nested_func: 1st call: 2nd thread: print z FAIL: gdb.threads/omp-par-scope.exp: nested_func: 2nd call: 1st thread: print s1 FAIL: gdb.threads/omp-par-scope.exp: nested_func: 2nd call: 1st thread: print i FAIL: gdb.threads/omp-par-scope.exp: nested_func: 2nd call: 1st thread: print j FAIL: gdb.threads/omp-par-scope.exp: nested_func: 2nd call: 2nd thread: print s1 FAIL: gdb.threads/omp-par-scope.exp: nested_func: 2nd call: 2nd thread: print i FAIL: gdb.threads/omp-par-scope.exp: nested_func: 2nd call: 2nd thread: print j FAIL: gdb.threads/omp-par-scope.exp: nested_func: 2nd call: 2nd thread: print k FAIL: gdb.threads/omp-par-scope.exp: nested_func: 2nd call: 2nd thread: print z FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: inner_threads: 1st stop: print l FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: inner_threads: 1st stop: print k FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: inner_threads: 3rd stop: print l FAIL: gdb.threads/omp-par-scope.exp: nested_parallel: inner_threads: 3rd stop: print k For both clang and icc, it turns out that there are some problems with the DWARF that these compilers generate. Of the two, icc does at least nest the subprogram of the outlined function representing the parallel region within the function that it's defined, but does not handle inner scopes if they exist. clang places the subprogram for the outlined function at the same level as the containing function, so variables declared within the function aren't visible at all. I could call setup_xfail to avoid FAILs for clang and icc also, but I don't want to further complicate the test. gdb/testsuite/ChangeLog: * gdb.threads/omp-par-scope.c: New file. * gdb/threads/omp-par-scope.exp: New file. Change-Id: Icb9c991730d84ca7509380af817dfcc778e764ea
Diffstat (limited to 'gdb/testsuite')
-rw-r--r--gdb/testsuite/ChangeLog5
-rw-r--r--gdb/testsuite/gdb.threads/omp-par-scope.c166
-rw-r--r--gdb/testsuite/gdb.threads/omp-par-scope.exp290
3 files changed, 461 insertions, 0 deletions
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 4b2e132..8b846a1 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2019-12-10 Kevin Buettner <kevinb@redhat.com>
+ * gdb.threads/omp-par-scope.c: New file.
+ * gdb/threads/omp-par-scope.exp: New file.
+
+2019-12-10 Kevin Buettner <kevinb@redhat.com>
+
* lib/gdb.exp (support_nested_function_tests): New proc.
2019-12-10 Kevin Buettner <kevinb@redhat.com>
diff --git a/gdb/testsuite/gdb.threads/omp-par-scope.c b/gdb/testsuite/gdb.threads/omp-par-scope.c
new file mode 100644
index 0000000..c60e376
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/omp-par-scope.c
@@ -0,0 +1,166 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2017-2019 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/>. */
+
+#include <stdio.h>
+#include <omp.h>
+
+/* Testcase for checking access to variables in a single / outer scope.
+ Make sure that variables not referred to in the parallel section are
+ accessible from the debugger. */
+
+void
+single_scope (void)
+{
+ static int s1 = -41, s2 = -42, s3 = -43;
+ int i1 = 11, i2 = 12, i3 = 13;
+
+#pragma omp parallel num_threads (2) shared (s1, i1) private (s2, i2)
+ {
+ int thread_num = omp_get_thread_num ();
+
+ s2 = 100 * (thread_num + 1) + 2;
+ i2 = s2 + 10;
+
+ #pragma omp critical
+ printf ("single_scope: thread_num=%d, s1=%d, i1=%d, s2=%d, i2=%d\n",
+ thread_num, s1, i1, s2, i2);
+ }
+
+ printf ("single_scope: s1=%d, s2=%d, s3=%d, i1=%d, i2=%d, i3=%d\n",
+ s1, s2, s3, i1, i2, i3);
+}
+
+static int file_scope_var = 9876;
+
+/* Testcase for checking access to variables from parallel region
+ nested within more than one lexical scope. Of particular interest
+ are variables which are not referenced in the parallel section. */
+
+void
+multi_scope (void)
+{
+ int i01 = 1, i02 = 2;
+
+ {
+ int i11 = 11, i12 = 12;
+
+ {
+ int i21 = -21, i22 = 22;
+
+#pragma omp parallel num_threads (2) \
+ firstprivate (i01) \
+ shared (i11) \
+ private (i21)
+ {
+ int thread_num = omp_get_thread_num ();
+ i21 = 100 * (thread_num + 1) + 21;
+
+ #pragma omp critical
+ printf ("multi_scope: thread_num=%d, i01=%d, i11=%d, i21=%d\n",
+ thread_num, i01, i11, i21);
+ }
+
+ printf ("multi_scope: i01=%d, i02=%d, i11=%d, "
+ "i12=%d, i21=%d, i22=%d\n",
+ i01, i02, i11, i12, i21, i22);
+ }
+ }
+}
+
+/* Nested functions in C is a GNU extension. Some non-GNU compilers
+ define __GNUC__, but they don't support nested functions. So,
+ unfortunately, we can't use that for our test. */
+#if HAVE_NESTED_FUNCTION_SUPPORT
+
+/* Testcase for checking access of variables from within parallel
+ region in a lexically nested function. */
+
+void
+nested_func (void)
+{
+ static int s1 = -42;
+ int i = 1, j = 2, k = 3;
+
+ void
+ foo (int p, int q, int r)
+ {
+ int x = 4;
+
+ {
+ int y = 5, z = 6;
+#pragma omp parallel num_threads (2) shared (i, p, x) private (j, q, y)
+ {
+ int tn = omp_get_thread_num ();
+
+ j = 1000 * (tn + 1);
+ q = j + 1;
+ y = q + 1;
+ #pragma omp critical
+ printf ("nested_func: tn=%d: i=%d, p=%d, x=%d, j=%d, q=%d, y=%d\n",
+ tn, i, p, x, j, q, y);
+ }
+ }
+ }
+
+ foo (10, 11, 12);
+
+ i = 101; j = 102; k = 103;
+ foo (20, 21, 22);
+}
+#endif
+
+/* Testcase for checking access to variables from within a nested parallel
+ region. */
+
+void
+nested_parallel (void)
+{
+ int i = 1, j = 2;
+ int l = -1;
+
+ omp_set_nested (1);
+ omp_set_dynamic (0);
+#pragma omp parallel num_threads (2) private (l)
+ {
+ int num = omp_get_thread_num ();
+ int nthr = omp_get_num_threads ();
+ int off = num * nthr;
+ int k = off + 101;
+ l = off + 102;
+#pragma omp parallel num_threads (2) shared (num)
+ {
+ int inner_num = omp_get_thread_num ();
+ #pragma omp critical
+ printf ("nested_parallel (inner threads): outer thread num = %d, thread num = %d\n", num, inner_num);
+ }
+ #pragma omp critical
+ printf ("nested_parallel (outer threads) %d: k = %d, l = %d\n", num, k, l);
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ single_scope ();
+ multi_scope ();
+#if HAVE_NESTED_FUNCTION_SUPPORT
+ nested_func ();
+#endif
+ nested_parallel ();
+ return 0;
+}
+
diff --git a/gdb/testsuite/gdb.threads/omp-par-scope.exp b/gdb/testsuite/gdb.threads/omp-par-scope.exp
new file mode 100644
index 0000000..e237b91
--- /dev/null
+++ b/gdb/testsuite/gdb.threads/omp-par-scope.exp
@@ -0,0 +1,290 @@
+# Copyright 2017-2019 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]} {
+ untested "could not run to 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 "*-*-*" }
+ set thread_num [get_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\]"
+ }
+ }
+}