binutils-gdb/gdb/testsuite/gdb.cp/cpexprs.exp
Joel Brobecker 61baf725ec update copyright year range in GDB files
This applies the second part of GDB's End of Year Procedure, which
updates the copyright year range in all of GDB's files.

gdb/ChangeLog:

        Update copyright year range in all GDB files.
2017-01-01 10:52:34 +04:00

751 lines
19 KiB
Plaintext

# cpexprs.exp - C++ expressions tests
#
# Copyright 2008-2017 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
# Return to the top of the test function every time.
delete_breakpoints
if { ! [gdb_breakpoint test_function] } {
fail "set test_function breakpoint for $func"
} elseif { [gdb_test "continue" \
"Continuing.\r\n\r\nBreakpoint $DEC+,.*test_function.*" \
""] != 0 } {
fail "continue to test_function for $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_type_regexp {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 = {$type} $ADDR <[string_to_regexp $print].*>"
if {$lst == "-"} {
set lst "$func"
}
set all_functions($func,list) ".*// [string_to_regexp $lst]"
}
proc add {func type print lst} {
add_type_regexp $func [string_to_regexp $type] $print $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 {test_function} \
{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_ret { type } {
if { [istarget arm*-*eabi*] || [is_aarch32_target] } {
return "$type *"
} else {
return "void "
}
}
proc ctor_prefix { type } {
set ret [ctor_ret $type]
return "${ret}($type * const"
}
proc ctor { type arglist } {
if { $arglist != "" } {
set arglist ", $arglist"
}
return "[ctor_prefix $type]$arglist)"
}
add {derived::derived} \
[ctor derived ""] \
- \
-
add_type_regexp {base1::base1(void)} \
"[string_to_regexp [ctor_prefix base1]], (const )?void \\*\\*( const)?\\)" \
- \
-
add {base1::base1(int)} \
[ctor base1 "int"] \
- \
-
add_type_regexp {base2::base2} \
"[string_to_regexp [ctor_prefix 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*] || [is_aarch32_target] } {
set ret "void *"
} else {
set ret "void "
}
return "${ret}($type * const)"
}
add {base::~base} \
[dtor base] \
- \
-
# Overloaded methods (all are 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 {[skip_cplus_tests]} { continue }
# On SPU this test fails because the executable exceeds local storage size.
if { [istarget "spu*-*-*"] } {
return 0
}
#
# test running programs
#
standard_testfile .cc
if {[get_compiler_info "c++"]} {
return -1
}
if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} {
return -1
}
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 "test_function", since test_breakpoint uses it
if {[string compare $name "test_function"] != 0} {
test_breakpoint $name
}
}
# Test c/v gets recognized even without quoting.
foreach cv {{} { const} { volatile} { const volatile}} {
set test "p 'CV::m(int)$cv'"
gdb_test_multiple $test $test {
-re "( = {.*} 0x\[0-9a-f\]+ <CV::m.*>)\r\n$gdb_prompt $" {
# = {void (CV * const, CV::t)} 0x400944 <CV::m(int)>
set correct $expect_out(1,string)
pass $test
}
}
if {"$cv" != ""} {
setup_kfail c++/14186 *-*-*
}
gdb_test "p CV::m(int)$cv" [string_to_regexp $correct]
}
# Test TYPENAME:: gets recognized even in parentheses.
gdb_test "p CV_f(int)" { = {int \(int\)} 0x[0-9a-f]+ <CV_f\(int\)>}
gdb_test "p CV_f(CV::t)" { = {int \(int\)} 0x[0-9a-f]+ <CV_f\(int\)>}
gdb_test "p CV_f(CV::i)" " = 43"
gdb_test "p CV_f('cpexprs.cc'::CV::t)" \
{ = {int \(int\)} 0x[0-9a-f]+ <CV_f\(int\)>}
gdb_exit
return 0