old-cross-binutils/gdb/testsuite/gdb.cp/cpexprs.exp
Keith Seitz cec808ecec * gdb.cp/cp-relocate.exp: Remove single-quoting of C++ methods.
* gdb.cp/cplusfuncs.cc (dm_type_short): New function.
        (dm_type_long): New function.
        (dm_type_unsigned_short): New function.
        (dm_type_unsigned_long): New function.
        (myint): New typedef.
        * gdb.cp/cplusfuncs.exp (probe_demangler): Add tests for short,
        long, unsigned shor and long, operator char*, and typedef.
        (test_lookup_operator_functions): Add operator char* test.
        (test_paddr_operator_functions): Likewise.
        (test_paddr_overloaded_functions): Use probe values for
        short, long, and unsigned short and long.
        (test_paddr_hairy_functions): If the demangler probe detected
        gdb type printers, "expect" them. Otherwise "expect" the v2 or v3
        demangler.
        * gdb.cp/expand-sals.exp: Backtrace may contain class names.
        * gdb.cp/member-ptr.exp: Refine expected result for "print pmf"
        and "print null_pmf".
        Add test "ptype a.*pmf".
        * gdb.cp/overload.exp: Allow optional "int" to appear with
        "short" and "long".
        * gdb.cp/ovldbreak.exp: Use append to construct super-duper
        long expect value for men_overload1arg.
        Allow "int" to appear with "short" and "long".
        When testing "info break", add argument for main (void).
        Also allow "int" to appear with "short" and "long".
        Ditto with "unsigned" and "long long".
	* gdb.java/jmain.exp: Do not enclose methods names in single
	quotes.
	* gdb.java/jmisc.exp: Likewise.
	* gdb.java/jprint.exp: Likewise.
	* gdb.python/py-symbol.exp: Update expected "linkage_name" value.

	From Jan Kratochvil  <jan.kratochvil@redhat.com>:
	* gdb.cp/exception.exp (backtrace after first throw)
	(backtrace after second throw): Allow a namespace before __cxa_throw.
	(backtrace after first catch, backtrace after second catch): Allow
	a namespace before __cxa_begin_catch.

	* gdb.cp/cpexprs.exp: New file.
	* gdb.cp/cpexprs.cc: New file.

	From Daniel Jacobowitz  <dan@codesourcery.com>
	* gdb.cp/cpexprs.exp (escape): Delete.  Change all callers
	to use string_to_regexp.
	(ctor, dtor): New functions.  Use them to match constructor
	and destructor function types.
	(Top level): Use runto_main.
2010-03-09 18:08:05 +00:00

724 lines
18 KiB
Text

# cpexprs.exp - C++ expressions tests
#
# Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
#
# Contributed by Red Hat, originally written by Keith Seitz.
#
# 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.
# A helper proc which sets a breakpoint at FUNC and attempts to
# run to the breakpoint.
proc test_breakpoint {func} {
global DEC
# Restart every time
if {![runto_main]} {
perror "could not run to main when attempting to break at $func"
} else {
gdb_breakpoint "$func"
set i [expr {[string last : $func] + 1}]
set efunc [string_to_regexp [string range $func $i end]]
gdb_test "continue" \
"Continuing.\r\n\r\nBreakpoint $DEC+,.*$efunc.*" \
"continue to $func"
}
}
# Add a function to the list of tested functions
# FUNC is the name of the function (which will be passed to gdb commands)
# TYPE is the type of the function, as expected from the "print" command
# PRINT is the name of the function, as expected result of the print command
# *OR* "-", indicating that FUNC should be used (needed for virtual/inherited
# funcs)
# LST is either the expected result of the list command (the comment from
# the source code) *OR* "-", in which case FUNC will be used
#
# Usage:
# add NAME TYPE PRINT LST
# add NAME TYPE PRINT -
proc add {func type print lst} {
global all_functions CONVAR ADDR
set all_functions($func,type) $type
if {$print == "-"} {
set print $func
}
# An exception: since gdb canonicalizes C++ output,
# "(void)" must be mutated to "()".
regsub {\(void\)} $print {()} print
set all_functions($func,print) \
"$CONVAR = {[string_to_regexp $type]} $ADDR <[string_to_regexp $print].*>"
if {$lst == "-"} {
set lst "$func"
}
set all_functions($func,list) ".*// [string_to_regexp $lst]"
}
proc get {func cmd} {
global all_functions
return $all_functions($func,$cmd)
}
# Returns a list of function names for a given command
proc get_functions {cmd} {
global all_functions
set result {}
foreach i [array names all_functions *,$cmd] {
if {$all_functions($i) != ""} {
set idx [string last , $i]
if {$idx != -1} {
lappend result [string range $i 0 [expr {$idx - 1}]]
}
}
}
return [lsort $result]
}
# Some convenience variables for this test
set DEC {[0-9]}; # a decimal number
set HEX {[0-9a-fA-F]}; # a hexidecimal number
set CONVAR "\\\$$DEC+"; # convenience variable regexp
set ADDR "0x$HEX+"; # address
# An array of functions/methods that we are testing...
# Each element consists is indexed by NAME,COMMAND, where
# NAME is the function name and COMMAND is the gdb command that
# we are testing. The value of the array for any index pair is
# the expected result of running COMMAND with the NAME as argument.
# The array holding all functions/methods to test. Valid subindexes
# are (none need character escaping -- "add" will take care of that):
# add name type print_name list
# NAME,type: value is type of function
# NAME,print: value is print name of function (careful w/inherited/virtual!)
# NAME,list: value is comment in source code on first line of function
# (without the leading "//")
array set all_functions {}
# "Normal" functions/methods
add {main} \
{int (int, char **)} \
- \
-
add {derived::a_function} \
{void (const derived * const)} \
- \
-
add {base1::a_function} \
{void (const base1 * const)} \
- \
-
add {base2::a_function} \
{void (const base2 * const)} \
- \
-
# Constructors
# On targets using the ARM EABI, the constructor is expected to return
# "this".
proc ctor { type arglist } {
if { [istarget arm*-*eabi*] } {
set ret "$type *"
} else {
set ret "void "
}
if { $arglist != "" } {
set arglist ", $arglist"
}
return "${ret}($type * const$arglist)"
}
add {derived::derived} \
[ctor derived ""] \
- \
-
add {base1::base1(void)} \
[ctor base1 "const void ** const"] \
- \
-
add {base1::base1(int)} \
[ctor base1 "int"] \
- \
-
add {base2::base2} \
[ctor base2 "const void ** const"] \
- \
-
add {base::base(void)} \
[ctor base ""] \
- \
-
add {base::base(int)} \
[ctor base "int"] \
- \
-
# Destructors
# On targets using the ARM EABI, some destructors are expected
# to return "this". Others are void. For internal reasons,
# GCC returns void * instead of $type *; RealView appears to do
# the same.
proc dtor { type } {
if { [istarget arm*-*eabi*] } {
set ret "void *"
} else {
set ret "void "
}
return "${ret}($type * const)"
}
add {base::~base} \
[dtor base] \
- \
-
# Overloaded methods (all are const -- we try to use the void
# method with and without specifying "const")
add {base::overload(void)} \
{int (const base * const)} \
- \
{base::overload(void) const}
add {base::overload(void) const} \
{int (const base * const)} \
- \
{base::overload(void) const}
add {base::overload(int) const} \
{int (const base * const, int)} \
- \
-
add {base::overload(short) const} \
{int (const base * const, short)} \
- \
-
add {base::overload(long) const} \
{int (const base * const, long)} \
- \
-
add {base::overload(char*) const} \
{int (const base * const, char *)} \
- \
-
add {base::overload(base&) const} \
{int (const base * const, base &)} \
- \
-
# Operators
add {base::operator+} \
{int (const base * const, const base &)} \
- \
-
add {base::operator++} \
{base (base * const)} \
- \
-
add {base::operator+=} \
{base (base * const, const base &)} \
- \
-
add {base::operator-} \
{int (const base * const, const base &)} \
- \
-
add {base::operator--} \
{base (base * const)} \
- \
-
add {base::operator-=} \
{base (base * const, const base &)} \
- \
-
add {base::operator*} \
{int (const base * const, const base &)} \
- \
-
add {base::operator*=} \
{base (base * const, const base &)} \
- \
-
add {base::operator/} \
{int (const base * const, const base &)} \
- \
-
add {base::operator/=} \
{base (base * const, const base &)} \
- \
-
add {base::operator%} \
{int (const base * const, const base &)} \
- \
-
add {base::operator%=} \
{base (base * const, const base &)} \
- \
-
add {base::operator<} \
{bool (const base * const, const base &)} \
- \
-
add {base::operator<=} \
{bool (const base * const, const base &)} \
- \
-
add {base::operator>} \
{bool (const base * const, const base &)} \
- \
-
add {base::operator>=} \
{bool (const base * const, const base &)} \
- \
-
add {base::operator!=} \
{bool (const base * const, const base &)} \
- \
-
add {base::operator==} \
{bool (const base * const, const base &)} \
- \
-
add {base::operator!} \
{bool (const base * const)} \
- \
-
add {base::operator&&} \
{bool (const base * const, const base &)} \
- \
-
add {base::operator||} \
{bool (const base * const, const base &)} \
- \
-
add {base::operator<<} \
{int (const base * const, int)} \
- \
-
add {base::operator<<=} \
{base (base * const, int)} \
- \
-
add {base::operator>>} \
{int (const base * const, int)} \
- \
-
add {base::operator>>=} \
{base (base * const, int)} \
- \
-
add {base::operator~} \
{int (const base * const)} \
- \
-
add {base::operator&} \
{int (const base * const, const base &)} \
- \
-
add {base::operator&=} \
{base (base * const, const base &)} \
- \
-
add {base::operator|} \
{int (const base * const, const base &)} \
- \
-
add {base::operator|=} \
{base (base * const, const base &)} \
- \
-
add {base::operator^} \
{int (const base * const, const base &)} \
- \
-
add {base::operator^=} \
{base (base * const, const base &)} \
- \
-
add {base::operator=} \
{base (base * const, const base &)} \
- \
-
add {base::operator()} \
{void (const base * const)} \
- \
-
add {base::operator[]} \
{int (const base * const, int)} \
- \
-
add {base::operator new} \
{void *(size_t)} \
- \
-
add {base::operator delete} \
{void (void *)} \
- \
-
add {base::operator new[]} \
{void *(size_t)} \
- \
-
add {base::operator delete[]} \
{void (void *)} \
- \
-
add {base::operator char*} \
{char *(const base * const)} \
- \
-
add {base::operator fluff*} \
{fluff *(const base * const)} \
- \
-
add {base::operator fluff**} \
{fluff **(const base * const)} \
- \
-
add {base::operator int} \
{int (const base * const)} \
- \
-
# Templates
add {tclass<char>::do_something} \
{void (tclass<char> * const)} \
- \
-
add {tclass<int>::do_something} \
{void (tclass<int> * const)} \
- \
-
add {tclass<long>::do_something} \
{void (tclass<long> * const)} \
- \
-
add {tclass<short>::do_something} \
{void (tclass<short> * const)} \
- \
-
add {tclass<base>::do_something} \
{void (tclass<base> * const)} \
- \
-
add {flubber<int, int, int, int, int>} \
{void (void)} \
- \
flubber
add {flubber<int, int, int, int, short>} \
{void (void)} \
- \
flubber
add {flubber<int, int, int, int, long>} \
{void (void)} \
- \
flubber
add {flubber<int, int, int, int, char>} \
{void (void)} \
- \
flubber
add {flubber<int, int, int, short, int>} \
{void (void)} \
- \
flubber
add {flubber<int, int, int, short, short>} \
{void (void)} \
- \
flubber
add {flubber<int, int, int, short, long>} \
{void (void)} \
- \
flubber
add {flubber<int, int, int, short, char>} \
{void (void)} \
- \
flubber
add {flubber<int, int, int, long, int>} \
{void (void)} \
- \
flubber
add {flubber<int, int, int, long, short>} \
{void (void)} \
- \
flubber
add {flubber<int, int, int, long, long>} \
{void (void)} \
- \
flubber
add {flubber<int, int, int, long, char>} \
{void (void)} \
- \
flubber
add {flubber<int, int, int, char, int>} \
{void (void)} \
- \
flubber
add {flubber<int, int, int, char, short>} \
{void (void)} \
- \
flubber
add {flubber<int, int, int, char, long>} \
{void (void)} \
- \
flubber
add {flubber<int, int, int, char, char>} \
{void (void)} \
- \
flubber
add {flubber<int, int, short, int, int>} \
{void (void)} \
- \
flubber
add {flubber<int, int, short, int, short>} \
{void (void)} \
- \
flubber
add {flubber<int, int, short, int, long>} \
{void (void)} \
- \
flubber
add {flubber<int, int, short, int, char>} \
{void (void)} \
- \
flubber
add {flubber<int, int, short, short, int>} \
{void (void)} \
- \
flubber
add {flubber<short, int, short, int, short>} \
{void (void)} \
- \
flubber
add {flubber<long, short, long, short, long>} \
{void (void)} \
- \
flubber
add {tclass<base>::do_something} \
{void (tclass<base> * const)} \
- \
{tclass<T>::do_something}
add {policy1::policy} \
[ctor "policy<int, operation_1<void*> >" "int"] \
{policy<int, operation_1<void*> >::policy} \
{policy<T, Policy>::policy}
add {policy2::policy} \
[ctor "policy<int, operation_2<void*> >" int] \
{policy<int, operation_2<void*> >::policy} \
{policy<T, Policy>::policy}
add {policy3::policy} \
[ctor "policy<int, operation_3<void*> >" "int"] \
{policy<int, operation_3<void*> >::policy} \
{policy<T, Policy>::policy}
add {policy4::policy} \
[ctor "policy<int, operation_4<void*> >" "int"] \
{policy<int, operation_4<void*> >::policy} \
{policy<T, Policy>::policy}
add {policy1::function} \
{void (void)} \
{operation_1<void*>::function} \
{operation_1<T>::function}
add {policy2::function} \
{void (void)} \
{operation_2<void*>::function} \
{operation_2<T>::function}
add {policy3::function} \
{void (void)} \
{operation_3<void*>::function} \
{operation_3<T>::function}
add {policy4::function} \
{void (void)} \
{operation_4<void*>::function} \
{operation_4<T>::function}
add {policyd<int, operation_1<int> >::policyd} \
[ctor "policyd<int, operation_1<int> >" "int"] \
- \
{policyd<T, Policy>::policyd}
add {policyd1::policyd} \
[ctor "policyd<int, operation_1<int> >" "int"] \
{policyd<int, operation_1<int> >::policyd} \
{policyd<T, Policy>::policyd}
add {policyd<int, operation_1<int> >::~policyd} \
[dtor "policyd<int, operation_1<int> >"] \
- \
{policyd<T, Policy>::~policyd}
add {policyd1::~policyd} \
[dtor "policyd<int, operation_1<int> >"] \
{policyd<int, operation_1<int> >::~policyd} \
{policyd<T, Policy>::~policyd}
add {policyd<long, operation_1<long> >::policyd} \
[ctor "policyd<long, operation_1<long> >" "long"] \
- \
{policyd<T, Policy>::policyd}
add {policyd2::policyd} \
[ctor "policyd<long, operation_1<long> >" "long"] \
{policyd<long, operation_1<long> >::policyd} \
{policyd<T, Policy>::policyd}
add {policyd<long, operation_1<long> >::~policyd} \
[dtor "policyd<long, operation_1<long> >"] \
- \
{policyd<T, Policy>::~policyd}
add {policyd2::~policyd} \
[dtor "policyd<long, operation_1<long> >"] \
{policyd<long, operation_1<long> >::~policyd} \
{policyd<T, Policy>::~policyd}
add {policyd<char, operation_1<char> >::policyd} \
[ctor "policyd<char, operation_1<char> >" "char"] \
- \
{policyd<T, Policy>::policyd}
add {policyd3::policyd} \
[ctor "policyd<char, operation_1<char> >" "char"] \
{policyd<char, operation_1<char> >::policyd} \
{policyd<T, Policy>::policyd}
add {policyd<char, operation_1<char> >::~policyd} \
[dtor "policyd<char, operation_1<char> >"] \
- \
{policyd<T, Policy>::~policyd}
add {policyd3::~policyd} \
[dtor "policyd<char, operation_1<char> >"] \
{policyd<char, operation_1<char> >::~policyd} \
{policyd<T, Policy>::~policyd}
add {policyd<base, operation_1<base> >::policyd} \
[ctor "policyd<base, operation_1<base> >" "base"] \
- \
{policyd<T, Policy>::policyd}
add {policyd4::policyd} \
[ctor "policyd<base, operation_1<base> >" "base"] \
{policyd<base, operation_1<base> >::policyd} \
{policyd<T, Policy>::policyd}
add {policyd<base, operation_1<base> >::~policyd} \
[dtor "policyd<base, operation_1<base> >"] \
- \
{policyd<T, Policy>::~policyd}
add {policyd4::~policyd} \
[dtor "policyd<base, operation_1<base> >"] \
{policyd<base, operation_1<base> >::~policyd} \
{policyd<T, Policy>::~policyd}
add {policyd<tclass<int>, operation_1<tclass<int> > >::policyd} \
[ctor "policyd<tclass<int>, operation_1<tclass<int> > >" "tclass<int>"] \
- \
{policyd<T, Policy>::policyd}
add {policyd5::policyd} \
[ctor "policyd<tclass<int>, operation_1<tclass<int> > >" "tclass<int>"] \
{policyd<tclass<int>, operation_1<tclass<int> > >::policyd} \
{policyd<T, Policy>::policyd}
add {policyd<tclass<int>, operation_1<tclass<int> > >::~policyd} \
[dtor "policyd<tclass<int>, operation_1<tclass<int> > >"] \
- \
{policyd<T, Policy>::~policyd}
add {policyd5::~policyd} \
[dtor "policyd<tclass<int>, operation_1<tclass<int> > >"] \
{policyd<tclass<int>, operation_1<tclass<int> > >::~policyd} \
{policyd<T, Policy>::~policyd}
add {policyd<int, operation_1<int> >::function} \
{void (void)} \
{operation_1<int>::function}\
{operation_1<T>::function}
add {policyd1::function} \
{void (void)} \
{operation_1<int>::function} \
{operation_1<T>::function}
add {policyd2::function} \
{void (void)} \
{operation_1<long>::function} \
{operation_1<T>::function}
add {policyd<char, operation_1<char> >::function} \
{void (void)} \
{operation_1<char>::function} \
{operation_1<T>::function}
add {policyd3::function} \
{void (void)} \
{operation_1<char>::function} \
{operation_1<T>::function}
add {policyd<base, operation_1<base> >::function} \
{void (void)} \
{operation_1<base>::function} \
{operation_1<T>::function}
add {policyd4::function} \
{void (void)} \
{operation_1<base>::function} \
{operation_1<T>::function}
add {policyd<tclass<int>, operation_1<tclass<int> > >::function} \
{void (void)} \
{operation_1<tclass<int> >::function} \
{operation_1<T>::function}
add {policyd5::function} \
{void (void)} \
{operation_1<tclass<int> >::function} \
{operation_1<T>::function}
# Start the test
if {$tracelevel} {
strace $tracelevel
}
if {[skip_cplus_tests]} { continue }
#
# test running programs
#
set prms_id 0
set bug_id 0
set testfile "cpexprs"
set srcfile "${testfile}.cc"
set binfile [file join $objdir $subdir $testfile]
if {[gdb_compile [file join $srcdir $subdir $srcfile] $binfile \
executable {debug c++}] != "" } {
untested "$testfile.exp"
return -1
}
if {[get_compiler_info $binfile "c++"]} {
return -1
}
gdb_exit
gdb_start
gdb_reinitialize_dir [file join $srcdir $subdir]
gdb_load $binfile
if {![runto_main]} {
perror "couldn't run to breakpoint"
continue
}
# Set the listsize to one. This will help with testing "list".
gdb_test "set listsize 1"
# "print METHOD"
foreach name [get_functions print] {
gdb_test "print $name" [get $name print] "print $name"
}
# "list METHOD"
foreach name [get_functions list] {
gdb_test "list $name" [get $name list] "list $name"
}
# Running to breakpoint -- use any function we can "list"
foreach name [get_functions list] {
# Skip "main", since test_breakpoint uses it
if {[string compare $name "main"] != 0} {
test_breakpoint $name
}
}
gdb_exit
return 0