[wip] gdb/testsuite: all the optimised code test cases

All the test cases pulled from this series:

  https://inbox.sourceware.org/gdb-patches/AS1PR01MB946510286FBF2497A6F03E83E4922@AS1PR01MB9465.eurprd01.prod.exchangelabs.com

Rebased on top of current HEAD.  Some of these tests are probably
duplicates of tests that have been upstreamed into other locations,
e.g. see recent additions to gdb.opt/

Also, I moved these tests into their own commit to make it easier for
me to move them between branches for testing, but when it comes to
upstreaming, these tests should be merged into the appropriate GDB
related commit, and not left as a commit on their own.
This commit is contained in:
Andrew Burgess
2024-09-19 14:41:16 +01:00
parent 8a2fb168c9
commit 94a1302434
9 changed files with 307 additions and 110 deletions

View File

@@ -0,0 +1,39 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2024 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/>. */
static int test0 (void)
{
asm (""); /* line 20 */
return 1; /* line 21 */
}
int __attribute__((noinline, noclone))
#ifdef __CET__
__attribute__((nocf_check))
#endif
test1 (int x)
{
asm ("");
return x+1; /* line 31 */
}
int
main()
{ test1 (test0 ()); /* line 36 */
test1 (test0 ()); /* line 37 */
return 0; /* line 38 */
}

View File

@@ -0,0 +1,51 @@
# Copyright 2024 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/>.
standard_testfile .c
if { ![test_compiler_info gcc*] || ![supports_statement_frontiers] } {
untested "this test needs gcc with statement frontiers"
return -1
}
global srcfile testfile
set options {debug nowarnings optimize=-O2}
lappend options additional_flags=-gstatement-frontiers
if { [prepare_for_testing "failed to prepare" $binfile \
$srcfile $options] } {
return -1
}
if ![runto_main] {
return
}
gdb_test "frame 0" "\\s*\\#0\\s+main.*${srcfile}:36.*" "in main"
gdb_test_multiple "step" "step into test0" {
-re ".*test0.*${srcfile}:20.*$::gdb_prompt $" {
gdb_test "step" ".*line 21.*" $gdb_test_name
}
-re ".*test0.*${srcfile}:21.*$::gdb_prompt $" {
pass $gdb_test_name
}
}
gdb_test "frame 1" "\\s*\\#1\\s+main.*${srcfile}:36.*" "frame1"
gdb_test "step" ".*test1.*${srcfile}:31.*" "step into test1"
gdb_test "frame 1" "\\s*\\#1.*in main.*${srcfile}:36.*" "frame2"
gdb_test "step" ".*main.*${srcfile}:37.*" "step back to main"
gdb_test "next" ".*return 0;.*" "step over test0+1"
gdb_test "frame 0" "\\s*\\#0\\s+main.*${srcfile}:38.*" "in main again"

View File

@@ -0,0 +1,39 @@
/* Copyright 2024 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/>. */
volatile int global = 0;
__attribute__((noinline, noclone)) void
foo (int arg)
{
global += arg;
}
inline __attribute__((always_inline)) int
bar (int val)
{
if (__builtin_expect(global == val, 0))
return 1;
foo (1);
return 1;
}
int
main (void)
{
if ((__builtin_expect(global, 0) && bar (1)) || bar (2))
return 1;
return 0;
}

View File

@@ -0,0 +1,43 @@
# Copyright 2024 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/>.
standard_testfile .c
if { [test_compiler_info gcc*] && ![supports_statement_frontiers] } {
untested "this test needs gcc with statement frontiers"
return -1
}
global srcfile testfile
set options {debug nowarnings optimize=-O2}
if { [supports_statement_frontiers] } {
lappend options additional_flags=-gstatement-frontiers
}
if { [prepare_for_testing "failed to prepare" $binfile \
$srcfile $options] } {
return -1
}
if ![runto_main] {
return
}
gdb_test "break bar" ".*Breakpoint 2 at .*" "break at bar"
gdb_test "break foo" ".*Breakpoint 3 at .*" "break at foo"
gdb_test "continue" ".*Breakpoint .* bar .*" "continue to bar"
gdb_test "continue" ".*Breakpoint .* foo .*" "continue to foo"
gdb_test "continue" ".* exited .*" "continue to exit"

View File

@@ -0,0 +1,33 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2024 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/>. */
/* PR 25987 */
struct MyClass;
struct ptr {
MyClass* get() { return t; } /* line 21 */
MyClass* t;
};
struct MyClass { void call(); };
void MyClass::call() {
*(volatile char*)-1 = 1; /* line 26 */
}
static void intermediate(ptr p) {
p.get()->call(); /* line 29 */
}
int main() {
intermediate(ptr{new MyClass});
}

View File

@@ -0,0 +1,51 @@
# Copyright 2024 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/>.
# PR 25987
standard_testfile .cc
if { ![test_compiler_info gcc*] || ![supports_statement_frontiers] } {
untested "this test needs gcc with statement frontiers"
return -1
}
set options {c++ debug nowarnings optimize=-Og}
lappend options additional_flags=-gstatement-frontiers
if { [prepare_for_testing "failed to prepare" $testfile \
$srcfile $options] } {
return -1
}
if ![runto_main] {
return
}
gdb_test "bt" "\\s*\\#0\\s+main.*" "in main"
#break at the empty inline function ptr::get
gdb_test "b get" ".*" "break at get"
gdb_test "c" ".*" "continue to get"
#call frame 1 is at line 29
gdb_test "bt" [multi_line "\\s*\\#0\\s+ptr::get\[^\r\]*${srcfile}:21" \
"\\s*\\#1\\s+intermediate\[^\r\]*${srcfile}:29" \
".*"] \
"at get"
#print a local value here
gdb_test "p t" ".*(\\\$1 = \\(MyClass \\*\\) 0x|value has been optimized out).*" "print t"
gdb_test "c" ".*SIGSEGV.*" "continue to SIGSEGV"
#call frame 1 is at line 29
gdb_test "bt" [multi_line "\\s*\\#0\\s+\[^\r\]*MyClass::call\[^\r\]*${srcfile}:26" \
"\\s*\\#1\\s+0x\[^\r\]*intermediate\[^\r\]*${srcfile}:29" \
".*"] \
"at call"

View File

@@ -47,8 +47,7 @@ tree_check (tree *t, int i)
int __attribute__((noinline, noclone))
get_alias_set (tree *t)
{
if (t != NULL
{ if (t != NULL
&& TREE_TYPE (t).z != 1
&& TREE_TYPE (t).z != 2
&& TREE_TYPE (t).z != 3)
@@ -60,7 +59,6 @@ tree xx;
int
main()
{
get_alias_set (&xx); /* Beginning of main */
{ get_alias_set (&xx);
return 0;
} // main

View File

@@ -15,7 +15,8 @@
standard_testfile .cc
if {[test_compiler_info gcc*] && ![supports_statement_frontiers] } {
if { ![test_compiler_info gcc*] || ![supports_statement_frontiers] } {
untested "this test needs gcc with statement frontiers"
return -1
}
@@ -24,17 +25,8 @@ if {[test_compiler_info gcc*] && ![supports_statement_frontiers] } {
proc do_test { use_header } {
global srcfile testfile
if { $use_header } {
# This test will not pass due to poor debug information
# generated by GCC (at least up to 10.x). See
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94474
return
}
set options {c++ debug nowarnings optimize=-O2}
if { [supports_statement_frontiers] } {
lappend options additional_flags=-gstatement-frontiers
}
lappend options additional_flags=-gstatement-frontiers
if { $use_header } {
lappend options additional_flags=-DUSE_NEXT_INLINE_H
set executable "$testfile-with-header"
@@ -53,8 +45,6 @@ proc do_test { use_header } {
with_test_prefix $prefix {
set main_location [gdb_get_line_number "Beginning of main" $srcfile]
if {![runto_main]} {
return
}
@@ -81,94 +71,24 @@ proc do_test { use_header } {
clean_restart $executable
if ![runto $main_location qualified] {
if ![runto_main] {
return
}
gdb_test "bt" "\\s*\\#0\\s+main.*" "in main"
gdb_test "step" \
[multi_line \
"get_alias_set \\(t=\[^\r\n\]+\\) at \[^\r\n\]+:$::decimal" \
"$::decimal\\s+if \\(t != NULL\\s*"] \
"step into get_alias_set"
gdb_test "step" ".*" "step into get_alias_set"
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"not in inline 1"
gdb_test "next" ".*TREE_TYPE.*" "next step 1"
gdb_test "bt" "#0\\s+get_alias_set\[^\r\n\]*${srcfile}:.*" \
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"not in inline 2"
# It's possible that this first failure (when not using a header
# file) is GCC's fault, though the remaining failures would best
# be fixed by adding location views support (though it could be
# that some easier heuristic could be figured out). Still, it is
# not certain that the first failure wouldn't also be fixed by
# having location view support, so for now it is tagged as such.
set have_kfail [expr [test_compiler_info gcc*] && !$use_header]
set ok 1
gdb_test_multiple "next" "next step 2" {
-re -wrap "return x;" {
set ok 0
send_gdb "next\n"
exp_continue
}
-re -wrap ".*TREE_TYPE.* != 2" {
if { $ok } {
pass $gdb_test_name
} else {
if { $have_kfail } {
setup_kfail "*-*-*" symtab/25507
}
fail $gdb_test_name
}
}
}
gdb_test "next" ".*TREE_TYPE.*" "next step 2"
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"not in inline 3"
set ok 1
gdb_test_multiple "next" "next step 3" {
-re -wrap "return x;" {
set ok 0
send_gdb "next\n"
exp_continue
}
-re -wrap ".*TREE_TYPE.* != 3\\)" {
if { $ok } {
pass $gdb_test_name
} else {
if { $have_kfail } {
setup_kfail "*-*-*" symtab/25507
}
fail $gdb_test_name
}
}
}
gdb_test "next" ".*TREE_TYPE.*" "next step 3"
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"not in inline 4"
set ok 1
gdb_test_multiple "next" "next step 4" {
-re -wrap "(if \\(t != NULL|\} // get_alias_set)" {
send_gdb "next\n"
exp_continue
}
-re -wrap "return x;" {
set ok 0
send_gdb "next\n"
exp_continue
}
-re -wrap "return 0.*" {
if { $ok } {
pass $gdb_test_name
} else {
if { $have_kfail } {
setup_kfail "*-*-*" symtab/25507
}
fail $gdb_test_name
}
}
}
gdb_test "next" "return 0.*" "next step 4"
gdb_test "bt" \
"\\s*\\#0\\s+(main|get_alias_set)\[^\r\]*${srcfile}:.*" \
"not in inline 5"
@@ -180,11 +100,7 @@ proc do_test { use_header } {
}
gdb_test "bt" "\\s*\\#0\\s+main.*" "in main pass 2"
gdb_test "step" \
[multi_line \
"get_alias_set \\(t=\[^\r\n\]+\\) at \[^\r\n\]+:$::decimal" \
"$::decimal\\s+if \\(t != NULL\\s*"] \
"step into get_alias_set, pass 2"
gdb_test "step" ".*" "step into get_alias_set pass 2"
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"in get_alias_set pass 2"
gdb_test "step" ".*TREE_TYPE.*" "step 1"
@@ -194,6 +110,8 @@ proc do_test { use_header } {
gdb_test "bt" "\\s*\\#0\\s+\[^\r\]*tree_check\[^\r\]*${hdrfile}:.*" \
"in inline 1 pass 2"
gdb_test "step" ".*return x.*" "step 3"
gdb_test "bt" "\\s*\\#0\\s+\[^\r\]*tree_check\[^\r\]*${hdrfile}:.*" \
"return from inline 1 pass 2"
gdb_test "step" ".*TREE_TYPE.*" "step 4"
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"not in inline 2 pass 2"
@@ -201,13 +119,17 @@ proc do_test { use_header } {
gdb_test "bt" "\\s*\\#0\\s+\[^\r\]*tree_check\[^\r\]*${hdrfile}:.*" \
"in inline 2 pass 2"
gdb_test "step" ".*return x.*" "step 6"
gdb_test "bt" "\\s*\\#0\\s+\[^\r\]*tree_check\[^\r\]*${hdrfile}:.*" \
"return from inline 2 pass 2"
gdb_test "step" ".*TREE_TYPE.*" "step 7"
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"not in inline 3 pass 2"
gdb_test "step" ".*if \\(t->x != i\\).*" "step 8"
gdb_test "bt" "\\s*\\#0\\s+\[^\r\]*tree_check\[^\r\]*${hdrfile}:.*" \
"in inline 3 pass 2"
gdb_test "step" "return x.*" "step 9"
gdb_test "step" ".*return x.*" "step 9"
gdb_test "bt" "\\s*\\#0\\s+\[^\r\]*tree_check\[^\r\]*${hdrfile}:.*" \
"return from inline 3 pass 2"
gdb_test "step" "return 0.*" "step 10"
gdb_test "bt" \
"\\s*\\#0\\s+(main|get_alias_set)\[^\r\]*${srcfile}:.*" \
@@ -219,19 +141,15 @@ proc do_test { use_header } {
return
}
gdb_test "bt" "#0\\s+main.*" "in main pass 3"
gdb_test "step" \
[multi_line \
"get_alias_set \\(t=\[^\r\n\]+\\) at \[^\r\n\]+:$::decimal" \
"$::decimal\\s+if \\(t != NULL\\s*"] \
"step into get_alias_set, pass 3"
gdb_test "bt" "#0\\s+get_alias_set\[^\r\n\]*${srcfile}:.*" \
gdb_test "bt" "\\s*\\#0\\s+main.*" "in main pass 3"
gdb_test "step" ".*" "step into get_alias_set pass 3"
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"in get_alias_set pass 3"
gdb_test "step" ".*TREE_TYPE.*" "step 1 pass 3"
gdb_test "bt" "#0\\s+get_alias_set\[^\r\n\]*${srcfile}:.*" \
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"not in inline 1 pass 3"
gdb_test "step" ".*if \\(t->x != i\\).*" "step 2 pass 3"
gdb_test "bt" "#0\\s+\[^\r\n\]*tree_check\[^\r\n\]*${hdrfile}:.*" \
gdb_test "bt" "\\s*\\#0\\s+\[^\r\]*tree_check\[^\r\]*${hdrfile}:.*" \
"in inline 1 pass 3"
gdb_test_multiple "p t->x = 2" "change value pass 3" {
-re ".*value has been optimized out.*$::gdb_prompt $" {
@@ -242,8 +160,33 @@ proc do_test { use_header } {
}
}
gdb_test "step" ".*abort.*" "step 3, pass 3"
gdb_test "bt" "#0\\s+\[^\r\n\]*tree_check\[^\r\n\]*${hdrfile}:.*" \
gdb_test "bt" "\\s*\\#0\\s+\[^\r\]*tree_check\[^\r\]*${hdrfile}:.*" \
"abort from inline 1 pass 3"
clean_restart ${executable}
if ![runto_main] {
return
}
gdb_test "bt" "\\s*\\#0\\s+main.*" "in main pass 4"
gdb_test "skip tree_check" ".*" "skip tree_check pass 4"
gdb_test "step" ".*" "step into get_alias_set pass 4"
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"in get_alias_set pass 4"
gdb_test "step" ".*TREE_TYPE.*" "step 1 pass 4"
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"not in inline 1 pass 4"
gdb_test "step" ".*TREE_TYPE.*" "step 2 pass 4"
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"not in inline 2 pass 4"
gdb_test "step" ".*TREE_TYPE.*" "step 3 pass 4"
gdb_test "bt" "\\s*\\#0\\s+get_alias_set\[^\r\]*${srcfile}:.*" \
"not in inline 3 pass 4"
gdb_test "step" "return 0.*" "step 4 pass 4"
gdb_test "bt" \
"\\s*\\#0\\s+(main|get_alias_set)\[^\r\]*${srcfile}:.*" \
"not in inline 4 pass 4"
}
}

View File

@@ -168,7 +168,7 @@ gdb_test_multiple "maint info line-table gdb.dwarf2/dw2-ranges-base.c" \
-re ".*linetable: \\(\\(struct linetable \\*\\) 0x0\\):\r\nNo line table.\r\n" {
exp_continue
}
-re ".*linetable: \\(\\(struct linetable \\*\\) $hex\\):\r\nINDEX\[ \t\]+LINE\[ \t\]+REL-ADDRESS\[ \t\]+UNREL-ADDRESS\[ \t\]+IS-STMT\[ \t\]PROLOGUE-END\[ \t\]EPILOGUE-BEGIN *\r\n" {
-re ".*linetable: \\(\\(struct linetable \\*\\) $hex\\):\r\nINDEX\[ \t\]+LINE\[ \t\]+REL-ADDRESS\[ \t\]+UNREL-ADDRESS\[ \t\]+IS-STMT\[ \t\]IS-WEAK\[ \t\]PROLOGUE-END\[ \t\]EPILOGUE-BEGIN *\r\n" {
exp_continue
}
}