[patch] gdb.c++/local.exp: make usable with gcc

Michael Elizabeth Chastain
2002-04-09T03:15:27Z

This is about as much fun as a trip to the dentist. And about as
necessary, too.

gdb.c++/local.exp has four tests for classes defined in nested scopes.
In sound-byte terms, the tests "were never known to work with gcc".
Most tests in most configurations FAILed or XFAILed (look at one of the
weekly attention reports). Those that did PASS were passing because
their error messages were deemed legal output.

There is some nice testing functionality buried in here so I polished it
up and ran it on my testbed. The big change was to access the nested
classes inside the scope where they are defined rather than outside.
The four tests reveal two genuine gdb bugs, which now result in FAILs.

The bugs are:

. For a nested class definition with v3 dwarf-2 (plus 2.96-rh dwarf-2),
gdb prints two copies of the member function declaration.

. gdb treats the commands "ptype InnerLocal::NestedInnerLocal" as a
field lookup in the InnerLocal class, failing to find the nested
class named NestedInnerLocal. This happens with both v2 and v3,
both dwarf-2 and stabs+.

I'm going to put this up for comment for 24 hours and then commit.
After commit, I will file PR's for the bugs.

Michael C

===

2002-04-08 Michael Chastain <mec@shout.net>

* gdb.c++/local.cc (main): Move call to marker1() inside nested
scope so that the nested scope tests will make sense.
* gdb.c++/local.exp: Write patterns that actually work with gcc
(the HP patterns "were never known to work with gcc").
Keep the old aCC patterns too.

Index: local.cc
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.c++/local.cc,v
retrieving revision 1.1.1.1
diff -c -3 -p -r1.1.1.1 local.cc
*** local.cc 16 Apr 1999 01:34:32 -0000 1.1.1.1
--- local.cc 9 Apr 2002 03:04:08 -0000
*************** int main()
*** 56,67 ****

il.ilc = 'b';
il.ip = &c;
}
- marker1();
}
-
-
-
-
-
-
--- 56,61 ----

il.ilc = 'b';
il.ip = &c;
+ marker1();
}
}
Index: local.exp
===================================================================
RCS file: /cvs/src/src/gdb/testsuite/gdb.c++/local.exp,v
retrieving revision 1.6
diff -c -3 -p -r1.6 local.exp
*** local.exp 23 Apr 2001 17:02:05 -0000 1.6
--- local.exp 9 Apr 2002 03:04:08 -0000
***************
*** 1,4 ****
! # Copyright 1998, 1999, 2000, 2001 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
--- 1,4 ----
! # Copyright 1998, 1999, 2000, 2001, 2002 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
***************
*** 19,24 ****
--- 19,25 ----

# tests for local variables
# Written by Satish Pai <pai@apollo.hp.com> 1997-07-08
+ # Cleaned by Michael Chastain <mec@shout.net> 2002-04-08

# This file is part of the gdb testsuite
*************** if ![runto 'marker1'] then {
*** 68,95 ****

gdb_test "up" ".*main.*" "up from marker1"

-
- # srikanth, These tests have always been run only with aCC. Now in
- # the new scheme of things, we run it twice, once with aCC, and once
- # with g++. Flag these tests as expected failures when run with g++.
- # as these are failing now and were never known to pass with g++.
- global gcc_compiled
- if {$gcc_compiled} then {
- setup_xfail "*-*-*"
- }
-
# Local classes in g++ get names like "main.1::InnerLocal", just like local
# static variables. Some targets use "___" instead of ".".
set sep "(\[.\]|___)\[0-9\]"

send_gdb "ptype Local\n"
gdb_expect {
! -re "type = class Local \{\r\n\[\t \]*public:\r\n\[\t \]*int loc1;\r\n\r\n\[\t \]*.char loc_foo\\(char\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.cc:10\\).*$gdb_prompt $" { pass "ptype Local" }
! -re "type = class Local \{\r\n\[\t \]*public:\r\n\[\t \]*int loc1;\r\n\r\n\[\t \]*.char loc_foo\\(char\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.cc:\[0-9\]*\\).*$gdb_prompt $" { pass "ptype Local (incorrect line number?)" }
! -re "type = class Local \{\r\n\[\t \]*public:\r\n\[\t \]*int loc1;\r\n\r\n\[\t \]*Local & operator=\\((foobar__Fi${sep}::|)Local const &\\);\r\n\[\t \]*Local\\((foobar__Fi${sep}::|)Local const &\\);\r\n\[\t \]*Local\\(void\\);\r\n\[\t \]*char loc_foo\\(char\\);\r\n\[\t \]*\}*.*$gdb_prompt $" { pass "ptype Local" }
! -re "type = class Local \{\r\n\[\t \]*public:\r\n\[\t \]*int loc1;\r\n\r\n\[\t \]*char loc_foo\\(char\\);\r\n\[\t \]*\\(Local at.*local\\.cc:\[0-9\]*\\)\r\n\}.*$gdb_prompt $" { pass "ptype Local (aCC)" }
! -re ".*$gdb_prompt $" { fail "ptype Local" }
! timeout { fail "(timeout) ptype Local" }
}

# DTS CLLbs14316 and CLLbs17058
--- 69,111 ----

gdb_test "up" ".*main.*" "up from marker1"

# Local classes in g++ get names like "main.1::InnerLocal", just like local
# static variables. Some targets use "___" instead of ".".
+
+ # ---
+ # Pattern 1:
+ # PASS
+ # dwarf-2
+ # gcc 2.95.3
+ #
+ # Pattern 2:
+ # FAIL
+ # This has a duplicate "char loc_foo" line. This is a bug.
+ # Historically this has been an XFAIL.
+ # dwarf-2
+ # gcc 2.96-rh, 3.0.4, gcc-3_1-branch, HEAD
+ #
+ # Pattern 3:
+ # PASS
+ # stabs+
+ # gcc 2.95.3, 2.96-rh, 3.0.4, gcc-3_1-branch, HEAD
+ #
+ # Pattern 4:
+ # This an old pattern from the hppa aCC version of this file.
+ # I left it alone.
+ #
+ # chastain 2002-04-08
+
set sep "(\[.\]|___)\[0-9\]"

send_gdb "ptype Local\n"
gdb_expect {
! -re "type = class Local \{\[\r\n\t \]*public:\[\r\n\t \]*int loc1;\[\r\n\t \]*char loc_foo\\((const *|)char\\);\[\r\n\t \]*\}.*$gdb_prompt $" { pass "ptype Local" }
! -re "type = class Local \{\[\r\n\t \]*public:\[\r\n\t \]*int loc1;\[\r\n\t \]*char loc_foo\\((const *|)char\\);\[\r\n\t \]*char loc_foo\\((const *|)char\\);\[\r\n\t \]*\}.*$gdb_prompt $" { fail "ptype Local (double loc_foo)" }
! -re "type = class Local \{\[\r\n\t \]*public:\[\r\n\t \]*int loc1;\[\r\n\t \]*Local & operator *=\\((foobar__Fi${sep}::|)Local const *&\\);\[\r\n\t \]*Local\\((foobar__Fi${sep}::|)Local const *&\\);\[\r\n\t \]*Local\\((void|)\\);\[\r\n\t \]*char loc_foo\\(char\\);\[\r\n\t \]*\}.*$gdb_prompt $" { pass "ptype Local" }
! -re "type = class Local \{\r\n\[\t \]*public:\r\n\[\t \]*int loc1;\r\n\r\n\[\t \]*char loc_foo\\(char\\);\r\n\[\t \]*\\(Local at.*local\\.cc:\[0-9\]*\\)\r\n\}.*$gdb_prompt $" { xpass "ptype Local (old aCC)" }
! -re ".*$gdb_prompt $" { fail "ptype Local" }
! timeout { fail "(timeout) ptype Local" }
}

# DTS CLLbs14316 and CLLbs17058
*************** gdb_expect {
*** 99,147 ****
# There is a number at the end of InnerLocal4 which should not be there,
# DTS CLLbs14316
# The line number for the class
! setup_xfail "hppa*-*-*" CLLbs14316
send_gdb "ptype InnerLocal\n"
gdb_expect {
! -re "type = class InnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*char ilc;\r\n\[\t \]*int \\*ip;\r\n\[\t \]*InnerLocal::NestedInnerLocal nest1;\r\n\r\n\[\t \]*.int il_foo\\(const unsigned char &\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.cc:36\\).*$gdb_prompt $" { pass "ptype InnerLocal" }
! -re "type = class InnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*char ilc;\r\n\[\t \]*int \\*ip;\r\n\[\t \]*class InnerLocal::NestedInnerLocal nest1;\r\n\r\n\[\t \]*.int il_foo\\(const unsigned char &\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.cc:36\\).*$gdb_prompt $" { pass "ptype InnerLocal" }
! -re "type = class InnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*char ilc;\r\n\[\t \]*int \\*ip;\r\n\[\t \]*InnerLocal::NestedInnerLocal nest1;\r\n\r\n\[\t \]*.int il_foo\\(const unsigned char &\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.cc:\[0-9\]*\\).*$gdb_prompt $" { pass "ptype InnerLocal (incorrect line number?" }
! -re "type = class InnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*char ilc;\r\n\[\t \]*int \\*ip;\r\n\[\t \]*class InnerLocal::NestedInnerLocal nest1;\r\n\r\n\[\t \]*.int il_foo\\(const unsigned char &\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.cc:\[0-9\]*\\).*$gdb_prompt $" { pass "ptype InnerLocal (incorrect line number?" }
! -re "type = class InnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*char ilc;\r\n\[\t \]*int \\*ip;\r\n\[\t \]*InnerLocal::NestedInnerLocal nest1;\r\n\r\n\[\t \]*.int il_foo\\(unsigned char const &\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.cc:36\\).*$gdb_prompt $" { pass "ptype InnerLocal HP aCC" }
! -re "type = class InnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*char ilc;\r\n\[\t \]*int \\*ip;\r\n\[\t \]*NestedInnerLocal nest1;\r\n\r\n\[\t \]*InnerLocal & operator=\\((main${sep}::|)InnerLocal const &\\);\r\n\[\t \]*InnerLocal\\((main${sep}::|)InnerLocal const &\\);\r\n\[\t \]*InnerLocal\\(void\\);\r\n\[\t \]*int il_foo\\(unsigned char const &\\);\r\n\*\}\r\n*.*$gdb_prompt $" { pass "ptype InnerLocal" }
! -re "type = class InnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*char ilc;\r\n\[\t \]*int \\*ip;\r\n\[\t \]*class InnerLocal4::NestedInnerLocal nest1;\r\n\r\n\[\t \]*int il_foo\\(unsigned char const &\\);\r\n\[\t \]*\\(Local at.*local\.cc:\[0-9\]+\\)\r\n\}.*$gdb_prompt $" { pass "ptype InnerLocal (aCC)" }
! -re ".*$gdb_prompt $" { fail "ptype InnerLocal" }
! timeout { fail "(timeout) ptype InnerLocal" }
}

send_gdb "ptype NestedInnerLocal\n"
gdb_expect {
! -re "type = class InnerLocal::NestedInnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*int nil;\r\n\r\n\[\t \]*.int nil_foo\\(int\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.cc:44\\).*$gdb_prompt $" { pass "ptype NestedInnerLocal" }
! -re "type = class InnerLocal::NestedInnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*int nil;\r\n\r\n\[\t \]*.int nil_foo\\(int\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.cc:\[0-9\]*\\).*$gdb_prompt $" { pass "ptype NestedInnerLocal (incorrect line number?)" }
! -re "type = class NestedInnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*int nil;\r\n\r\n\[\t \]*NestedInnerLocal & operator=\\((main${sep}::InnerLocal::|)NestedInnerLocal const &\\);\r\n\[\t \]*NestedInnerLocal\\((main${sep}::InnerLocal::|)NestedInnerLocal const &\\);\r\n\[\t \]*NestedInnerLocal\\(void\\);\r\n\[\t \]*int nil_foo\\(int\\);\r\n\}\r\n*.*$gdb_prompt $" { pass "ptype NestedInnerLocal" }
! -re "No symbol.*in current context.*$gdb_prompt $" { pass "ptype NestedInnerLocal (known aCC limitation)" }
! -re ".*$gdb_prompt $" { fail "ptype NestedInnerLocal" }
! timeout { fail "(timeout) ptype NestedInnerLocal" }
! }
!
! # srikanth, These tests have always been run only with aCC. Now in
! # the new scheme of things, we run it twice, once with aCC, and once
! # with g++. Flag these tests as expected failures when run with g++.
! # as these are failing now and were never known to pass with g++.
! global gcc_compiled
! if {$gcc_compiled} then {
! setup_xfail "*-*-*"
}

# gdb incorrectly interprets the NestedInnerLocal in
# InnerLocal::NestedInnerLocal as field name instead of a type name;
# See CLLbs14784.
! setup_xfail *-*-* CLLbs14784
send_gdb "ptype InnerLocal::NestedInnerLocal\n"
gdb_expect {
! -re "type = class InnerLocal::NestedInnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*int nil;\r\n\r\n\[\t \]*.int nil_foo\\(int\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.cc:44\\).*$gdb_prompt $" { pass "ptype InnerLocal::NestedInnerLocal" }
! -re "type = class InnerLocal::NestedInnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*int nil;\r\n\r\n\[\t \]*.int nil_foo\\(int\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.cc:\[0-9\]*\\).*$gdb_prompt $" { pass "ptype InnerLocal::NestedInnerLocal (incorrect line number?)" }
! -re ".*$gdb_prompt $" { fail "ptype InnerLocal::NestedInnerLocal" }
! timeout { fail "(timeout) ptype InnerLocal::NestedInnerLocal" }
}
-
-
--- 115,193 ----
# There is a number at the end of InnerLocal4 which should not be there,
# DTS CLLbs14316
# The line number for the class
! # setup_xfail "hppa*-*-*" CLLbs14316
!
! # ---
! # Pattern 1:
! # PASS
! # dwarf-2
! # 2.95.3, 2.96-rh, 3.0.4, gcc-3_1-branch, HEAD
! #
! # Pattern 2:
! # PASS
! # stabs+
! # 2.95.3, 2.96-rh, 3.0.4, gcc-3_1-branch, HEAD
! #
! # Pattern 3:
! # Old hppa pattern.
! #
! # Pattern 4:
! # Old hppa pattern.
! #
! # chastain 2002-04-08
!
send_gdb "ptype InnerLocal\n"
gdb_expect {
! -re "type = class InnerLocal \{\[\r\n\t \]*public:\[\r\n\t \]*char ilc;\[\r\n\t \]*int \\* *ip;\[\r\n\t \]*NestedInnerLocal nest1;\[\r\n\t \]*int il_foo\\((unsigned char const|const unsigned char) *&\\);\[\r\n\t \]*\}.*$gdb_prompt $" { pass "ptype InnerLocal" }
! -re "type = class InnerLocal \{\[\r\n\t \]*public:\[\r\n\t \]*char ilc;\[\r\n\t \]*int \\* *ip;\[\r\n\t \]*NestedInnerLocal nest1;\[\r\n\t \]*InnerLocal *& operator *=\\((main${sep}::|)InnerLocal const *&\\);\[\r\n\t \]*InnerLocal\\((main${sep}::|)InnerLocal const *&\\);\[\r\n\t \]*InnerLocal\\((void|)\\);\[\r\n\t \]*int il_foo\\(unsigned char const *&\\);\[\r\n\t \]*\}.*$gdb_prompt $" { pass "ptype InnerLocal" }
! -re "type = class InnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*char ilc;\r\n\[\t \]*int \\*ip;\r\n\[\t \]*InnerLocal::NestedInnerLocal nest1;\r\n\r\n\[\t \]*.int il_foo\\(unsigned char const &\\);\r\n\[\t \]*\}\[\t \]*\\(Local at.*local\\.cc:36\\).*$gdb_prompt $" { pass "ptype InnerLocal (old HP aCC)" }
! -re "type = class InnerLocal \{\r\n\[\t \]*public:\r\n\[\t \]*char ilc;\r\n\[\t \]*int \\*ip;\r\n\[\t \]*class InnerLocal4::NestedInnerLocal nest1;\r\n\r\n\[\t \]*int il_foo\\(unsigned char const &\\);\r\n\[\t \]*\\(Local at.*local\.cc:\[0-9\]+\\)\r\n\}.*$gdb_prompt $" { pass "ptype InnerLocal (old HP aCC)" }
! -re ".*$gdb_prompt $" { fail "ptype InnerLocal" }
! timeout { fail "(timeout) ptype InnerLocal" }
}

+ #---
+ # Pattern 1:
+ # PASS
+ # dwarf-2
+ # gcc 2.95.3, 2.96-rh, 3.0.4, gcc-3_1-branch, HEAD
+ #
+ # Pattern 2:
+ # PASS
+ # stabs+
+ # gcc 2.95.3, 2.96-rh, 3.0.4, gcc-3_1-branch, HEAD
+ #
+ # chastain 2002-04-08
+
send_gdb "ptype NestedInnerLocal\n"
gdb_expect {
! -re "type = class NestedInnerLocal \{\[\r\n\t \]*public:\[\r\n\t \]*int nil;\[\r\n\t \]*int nil_foo\\(int\\);\[\r\n\t \]*\}.*$gdb_prompt $" { pass "ptype NestedInnerLocal" }
! -re "type = class NestedInnerLocal \{\[\r\n\t \]*public:\[\r\n\t \]*int nil;\[\r\n\t \]*NestedInnerLocal *& *operator *= *\\((main${sep}::|)InnerLocal::NestedInnerLocal const *&\\);\[\r\n\t \]*NestedInnerLocal\\((main${sep}::|)InnerLocal::NestedInnerLocal const *&\\);\[\r\n\t \]*NestedInnerLocal\\((void|)\\);\[\r\n\t \]*int nil_foo\\(int\\);\[\r\n\t \]*\}.*$gdb_prompt $" { pass "ptype NestedInnerLocal" }
! -re ".*$gdb_prompt $" { fail "ptype NestedInnerLocal" }
! timeout { fail "(timeout) ptype NestedInnerLocal" }
}

# gdb incorrectly interprets the NestedInnerLocal in
# InnerLocal::NestedInnerLocal as field name instead of a type name;
# See CLLbs14784.
!
! #---
! # Pattern 3:
! # FAIL
! # The comment above, about CLLbs14784, is still correct.
! # dwarf-2
! # gcc 2.95.3, 2.96-rh, 3.0.4, gcc-3_1-branch, HEAD
! # stabs+
! # gcc 2.95.3, 2.96-rh, 3.0.4, gcc-3_1-branch, HEAD
! #
! # chastain 2002-04-08
!
send_gdb "ptype InnerLocal::NestedInnerLocal\n"
gdb_expect {
! -re "type = class InnerLocal::NestedInnerLocal \{\[\r\n\t \]*public:\[\r\n\t \]*int nil;\[\r\n\t \]*int nil_foo\\(int\\);\[\r\n\t \]*\}.*$gdb_prompt $" { pass "ptype InnerLocal::NestedInnerLocal" }
! -re "type = class InnerLocal::NestedInnerLocal \{\[\r\n\t \]*public:\[\r\n\t \]*int nil;\[\r\n\t \]*NestedInnerLocal *& *operator *= *\\((main${sep}::|)InnerLocal::NestedInnerLocal const *&\\);\[\r\n\t \]*NestedInnerLocal\\((main${sep}::|)InnerLocal::NestedInnerLocal const *&\\);\[\r\n\t \]*NestedInnerLocal\\((void|)\\);\[\r\n\t \]*int nil_foo\\(int\\);\[\r\n\t \]*\}.*$gdb_prompt $" { pass "ptype InnerLocal::NestedInnerLocal" }
! -re "There is no field named NestedInnerLocal.*$gdb_prompt $" { fail "ptype InnerLocal::NestedInnerLocal (bogus field lookup)" }
! -re "No symbol .*NestedInnerLocal.* in current context.*$gdb_prompt $" { fail "ptype InnerLocal::NestedInnerLocal (bogus symbol lookup)" }
! -re ".*$gdb_prompt $" { fail "ptype InnerLocal::NestedInnerLocal" }
! timeout { fail "(timeout) ptype InnerLocal::NestedInnerLocal" }
}