blob: 4edfcf2e7b6ec1110c1b19d2788a4eddc2108d6d [file] [log] [blame]
# Copyright (C) 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
# the Free Software Foundation; either version 2 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Please email any bugs, comments, and/or additions to this file to:
# bug-gdb@prep.ai.mit.edu
# Test Apple local varobj features.
#
# Written by Jason Molenda (jmolenda@apple.com)
# Initially, make use of the -stack-list-locals feature where
# varobjs are created for all locals, and variables in a block
# below the current block may not yet be in scope.
if [target_info exists noobjc64] {
verbose "Disable Objective-C tests on 64-bit PowerPC."
return
}
load_lib mi-support.exp
set MIFLAGS "-i=mi1"
gdb_exit
if [mi_gdb_start] {
continue
}
set testfile "objc-prog"
set srcfile ${testfile}.m
set binfile ${objdir}/${subdir}/${testfile}
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug additional_flags=-DFAKEARGV\ -framework\ Foundation}] != "" } {
gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
}
mi_delete_breakpoints
mi_gdb_reinitialize_dir $srcdir/$subdir
mi_gdb_load ${binfile}
send_gdb "100-break-insert randomFunc\n"
gdb_expect {
-re "100\\^done,bkpt=\{number=\"1\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"$hex\",func=\".*randomFunc.*\",file=\".*$srcfile\",line=\"($decimal)\",shlib=\"$binfile\",times=\"0\"\}\[\r\n\]+$mi_gdb_prompt$" {
set randomFunc_line_number $expect_out(1,string)
pass "break-insert randomFunc operation"
}
-re ".*$mi_gdb_prompt$" {
set randomFunc_line_number -1
fail "break-insert randomFunc operation"
}
timeout {
fail "(timeout) break-insert randomFunc operation"
}
}
send_gdb "200-break-insert blocky\n"
gdb_expect {
-re "200\\^done,bkpt=\{number=\"2\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"($hex)\",func=\"blocky\",file=\".*$srcfile\",line=\"($decimal)\",shlib=\"$binfile\",times=\"0\"\}\[\r\n\]+$mi_gdb_prompt$" {
set blocky_address $expect_out(1,string)
set blocky_line_number $expect_out(2,string)
pass "break-insert blocky operation"
}
-re ".*$mi_gdb_prompt$" {
set blocky_line_number -1
fail "break-insert blocky operation"
}
timeout {
fail "(timeout) break-insert blocky operation"
}
}
send_gdb "100-break-insert main\n"
gdb_expect {
-re "100\\^done,bkpt=\{number=\"3\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"$hex\",func=\"main\",file=\".*$srcfile\",line=\"($decimal)\",shlib=\"$binfile\",times=\"0\"\}\[\r\n\]+$mi_gdb_prompt$" {
set main_line_number $expect_out(1,string)
pass "break-insert main operation"
}
-re ".*$mi_gdb_prompt$" {
set main_line_number -1
fail "break-insert main operation"
}
timeout {
fail "(timeout) break-insert main operation"
}
}
mi_run_cmd
# The running part has been checked already by mi_run_cmd
mi_get_bp_stopped "3" "\[01\]" "" "main" "$srcfile" ".*" "run to main"
# Create a varobj for the currently uninitialized "object" variable. Then we will
# make sure it's type change is picked up properly when we make it a MyClass, and
# later when we make it a MyChild.
mi_gdb_test "80-var-create objectVar * object" \
{80\^done,name="objectVar",numchild="1",type="(id|struct objc_object \*)",typecode="PTR",dynamic_type="",resolved_type="(id|struct objc_object \*)",in_scope="true",block_start_addr=".*",block_end_addr=".*"} \
"created varobj for uninitialized object - no dynamic type - no error"
# Run to randomFunc twice, once as MyClass, once as MyChild, and make sure the dynamic
# type and the ivars are correct. Each time, return to main to test that objectVar is okay.
mi_continue_to 1 {-\[MyClass randomFunc\]} ".*" $srcfile $randomFunc_line_number "continue to randomFunc"
mi_gdb_test "101-var-create firstSelf * self" \
{101\^done,name="firstSelf",numchild="3",type="MyClass \*",typecode="PTR",dynamic_type="MyClass \*",resolved_type="MyClass \*",in_scope="true",block_start_addr=".*",block_end_addr=".*"} "randomFunc called for MyClass object"
mi_gdb_test "102-var-delete firstSelf" \
{102\^done,ndeleted="1"} "Delete firstSelf"
mi_finish_to main ".*" "$srcfile" ".*" ".*" {\(struct objc_object \*\) 0x.*} "finished from randomFunc first time"
mi_gdb_test "103-var-update objectVar" \
{103\^done,changelist=\[varobj={name="objectVar",in_scope="true",type_changed="true",new_type="(id|struct objc_object \*)",new_dynamic_type="MyClass \*",new_resolved_type="(id|struct objc_object \*)",new_typecode="PTR",new_num_children="3"}\]} \
"Update objectVar as MyClass"
mi_gdb_test "104-var-list-children objectVar" \
{104\^done,numchild="3",children=\[child={name="objectVar.(isa|NSObject)",exp="(isa|NSObject)",numchild="(0|1)",type="(Class|NSObject|struct objc_class \*)",typecode="(PTR|STRUCT)",dynamic_type="",resolved_type="(Class|NSObject|struct objc_class \*)"},child={name="objectVar.object",exp="object",numchild="(1|3)",type="(id|NSObject|struct objc_object \*)",typecode="PTR",dynamic_type="(class NSConstantString|NSCFString) \*",resolved_type="(id|NSObject|struct objc_object \*)"},child={name="objectVar._object2",exp="_object2",numchild="(3|1)",type="(id|struct objc_object \*)",typecode="PTR",dynamic_type="(class NSConstantString|NSCFString) \*",resolved_type="(id|struct objc_object \*)"}\]} "List objectVar's children as MyClass"
mi_continue_to 1 {-\[MyClass randomFunc\]} ".*" $srcfile $randomFunc_line_number "continue to randomFunc"
mi_gdb_test "105-var-create secondSelf * self" \
{105\^done,name="secondSelf",numchild="2",type="MyClass \*",typecode="PTR",dynamic_type="MyChild \*",resolved_type="MyClass \*",in_scope="true",block_start_addr=".*",block_end_addr=".*"} "randomFunc called for MyChild object"
mi_gdb_test "106-var-list-children secondSelf" \
{106\^done,numchild="2",children=\[child={name="secondSelf.MyClass",exp="MyClass",numchild="3",type="MyClass",typecode="STRUCT",dynamic_type="",resolved_type="MyClass"},child={name="secondSelf.some_val",exp="some_val",numchild="0",type="int",typecode="INT",dynamic_type="",resolved_type="int"}\]} "List secondSelf's children"
mi_gdb_test "107-var-evaluate-expression secondSelf.some_val" \
{107\^done,value="5"} "secondSelf.some_value is 5"
mi_gdb_test "108-var-delete secondSelf" \
{108\^done,ndeleted="3"} "Delete secondSelf"
mi_finish_to main ".*" "$srcfile" ".*" ".*" {\(struct objc_object \*\) 0x.*} "finished from randomFunc second time"
mi_gdb_test "109-var-update objectVar" \
{109\^done,changelist=\[varobj={name="objectVar",in_scope="true",type_changed="true",new_type="(id|struct objc_object \*)",new_dynamic_type="MyChild \*",new_resolved_type="(id|struct objc_object \*)",new_typecode="PTR",new_num_children="2"}\]} \
"Update objectVar as MyChild"
mi_gdb_test "110-var-list-children objectVar" \
{110\^done,numchild="2",children=\[child={name="objectVar.MyClass",exp="MyClass",numchild="3",type="MyClass",typecode="STRUCT",dynamic_type="",resolved_type="MyClass"},child={name="objectVar.some_val",exp="some_val",numchild="0",type="int",typecode="INT",dynamic_type="",resolved_type="int"}\]} "List objectVar's children"
mi_gdb_test "111-var-evaluate-expression objectVar.some_val" \
{111\^done,value="5"} "objectVar.some_value is 5"
mi_gdb_test "112-var-delete objectVar" \
{112\^done,ndeleted="3"} "Delete objectVar"
mi_continue_to "2" "blocky" ".*" "$srcfile" $blocky_line_number "continue to blocky"
# Normal stack-list-locals behavior
mi_gdb_test "120-stack-list-locals 0 0" "120\\^done,locals=\\\[\{name=\"outer\"\}\\\]" "normal stack-list-locals behavior"
mi_gdb_test "121-stack-list-locals 0" "121\\^done,locals=\\\[\{name=\"outer\"\}\\\]" "normal stack-list-locals behavior #2"
# Test local extension of -stack-list-locals which works over all blocks.
mi_gdb_test "122-stack-list-locals 0 1" "122\\^done,locals=\\\[\{name=\"outer\"\},\{name=\"inner1\"\},\{name=\"inner2\"\},\{name=\"outer\"\},\{name=\"flooooo\"\},\{name=\"chhhhh\"\}\\\]" "list locals in all subblocks"
mi_next "step forward"
mi_next "step forward again"
mi_gdb_test "123-stack-list-locals 0" "123\\^done,locals=\\\[\{name=\"inner1\"\},\{name=\"inner2\"\},\{name=\"outer\"\}\\\]"
# Apple local behavior - -stack-list-locals's first arg can be '2', in which
# case varobjs are created for all loals.
mi_gdb_test "124-stack-list-locals 2" \
"124\\^done,locals=\\\[varobj=\{exp=\"inner1\",value=\"97 'a'\",name=\"var1\",numchild=\"0\",type=\"char\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"char\",in_scope=\"true\",block_start_addr=\".*\",block_end_addr=\".*\"\},varobj=\{exp=\"inner2\",value=\".*\",name=\"var2\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\",block_start_addr=\".*\",block_end_addr=\".*\"\},varobj=\{exp=\"outer\",value=\"5\",name=\"var3\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\",block_start_addr=\".*\",block_end_addr=\".*\"\\}\\\]" \
"create varobjs for all locals in current scope"
# Note the importance of var7 - the second 'outer' variable -- its in_scope
# value is 'false'. God help me, this may be the only test of that
# functionality we have in the whole testsuite.
mi_gdb_test "125-stack-list-locals 2 1" \
"125\\^done,locals=\\\[varobj=\{exp=\"outer\",value=\"5\",name=\"var4\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\",block_start_addr=\".*\",block_end_addr=\".*\"\\},varobj=\{exp=\"inner1\",value=\"97 'a'\",name=\"var5\",numchild=\"0\",type=\"char\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"char\",in_scope=\"true\"\,block_start_addr=\".*\",block_end_addr=\".*\"\},varobj=\{exp=\"inner2\",value=\".*\",name=\"var6\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\"\,block_start_addr=\".*\",block_end_addr=\".*\"\},varobj=\{exp=\"outer\",value=\".*\",name=\"var7\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"false\",block_start_addr=\".*\",block_end_addr=\".*\"\\},varobj=\{exp=\"flooooo\",value=\".*\",name=\"var8\",numchild=\"0\",type=\"float\",typecode=\"FLT\",dynamic_type=\"\",resolved_type=\"float\",in_scope=\"false\"\,block_start_addr=\".*\",block_end_addr=\".*\"\},varobj=\{exp=\"chhhhh\",value=\".*\",name=\"var9\",numchild=\"0\",type=\"char\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"char\",in_scope=\"false\",block_start_addr=\".*\",block_end_addr=\".*\"\\}\\\]" \
"create varobjs for all blocks visible"
# The breakpoint on blocky() is on the first line of code in the func;
# this second breakpoint should be about seven statements farther down -
# on the line that reads "inner2 = 99".
set second_blocky_bp [expr $blocky_line_number + 7]
mi_gdb_test "130-break-insert $second_blocky_bp" \
"130\\^done,bkpt=\{number=\"4\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"$hex\",func=\"blocky\",file=\".*$srcfile\",line=\"$second_blocky_bp\",shlib=\"$binfile\",times=\"0\"\}" \
"break-insert operation 4"
mi_continue_to "4" "blocky" ".*" "$srcfile" "$second_blocky_bp" "continue to line $second_blocky_bp"
mi_gdb_test "131-var-update *" "131\\^done,changelist=\\\[varobj=\{name=\"var5\",in_scope=\"true\",type_changed=\"false\"\},varobj=\{name=\"var1\",in_scope=\"true\",type_changed=\"false\"\}\\\]" "simple var-update change"
# test variable scoping for -var-create - +XXXX
# where XXXX can be:
# address: +0x11223344
# file:line: +file.ext:12
set outer_line_number 1
mi_gdb_test "140-var-create outer_at_line_$outer_line_number +$srcfile:$outer_line_number outer" \
"140\\^done,name=\"outer_at_line_$outer_line_number\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\",block_start_addr=\".*\",block_end_addr=\".*\"" \
"140 var-create for outer where file:line is $srcfile:$outer_line_number"
mi_gdb_test "141-var-evaluate-expression outer_at_line_$outer_line_number" \
"141\\^done,value=\"15\"" \
"141 var-evaluate-expression for outer where file:line is $srcfile:$outer_line_number"
set outer_line_number $blocky_line_number
mi_gdb_test "142-var-create outer_at_line_$outer_line_number +$srcfile:$outer_line_number outer" \
"142\\^done,name=\"outer_at_line_$outer_line_number\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\",block_start_addr=\".*\",block_end_addr=\".*\"" \
"142 var-create for outer where file:line is $srcfile:$outer_line_number"
mi_gdb_test "143-var-evaluate-expression outer_at_line_$outer_line_number" \
"143\\^done,value=\"5\"" \
"143 var-evaluate-expression for outer where file:line is $srcfile:$outer_line_number"
# test invalid line number of zero which should default to the global value
mi_gdb_test "144-var-create outer0 +$srcfile:0 outer" \
"144\\^done,name=\"outer0\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\",block_start_addr=\"no block\",block_end_addr=\"no block\"" \
"144 var-create for outer where file:line is $srcfile:0 (invalid line number of zero)"
mi_gdb_test "145-var-evaluate-expression outer0" \
"145\\^done,value=\"15\"" \
"145 var-evaluate-expression for outer where file:line is $srcfile:0"
# test invalid line number that is too large for the file which should default to the global value
mi_gdb_test "146-var-create outer999999 +$srcfile:999999 outer" \
"146\\^done,name=\"outer999999\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\",block_start_addr=\"no block\",block_end_addr=\"no block\"" \
"146 var-create for outer where file:line is $srcfile:999999 (invalid line number of 999999)"
mi_gdb_test "147-var-evaluate-expression outer999999" \
"147\\^done,value=\"15\"" \
"147 var-evaluate-expression for outer where file:line is $srcfile:999999"
# test using an invalid file which should end up just use the selected frame
# to evaluate the variable
mi_gdb_test "148-var-create invalid_file_var +invalid_file.c:33 outer" \
{148\^error,msg="mi_cmd_var_create: invalid file and line in block expression: \\"\+invalid_file.c:33\\""} \
"148 var-create for outer where file:line is invalid_file.c:33 (invalid file)"
# test using the valid address for the block function which should pick up the first local value of 5
mi_gdb_test "149-var-create outer_addr$blocky_address +$blocky_address outer" \
"149\\^done,name=\"outer_addr$blocky_address\",numchild=\"0\",type=\"int\",typecode=\"INT\",dynamic_type=\"\",resolved_type=\"int\",in_scope=\"true\",block_start_addr=\".*\",block_end_addr=\".*\"" \
"149 var-create for outer where address is $blocky_address (address of blocky function)"
mi_gdb_test "150-var-evaluate-expression outer_addr$blocky_address" \
"150\\^done,value=\"5\"" \
"150 var-evaluate-expression for outer at address $blocky_address"
# test using an invalid address for the block address which needs to fail gracefully
mi_gdb_test "151-var-create outer_addr0xffffffff +0xffffffff outer" \
"151\\^error,msg=\"mi_cmd_var_create: unable to create variable object\"" \
"151 var-create using +0xffffffff (invalid address)"
mi_finish_to "main" ".*" "$srcfile" ".*" ".*" ".*" "back to main"
# Now make sure all the varobj's went away -
mi_gdb_test "132-var-update *" "132\\^done,changelist=\\\[varobj=\{name=\"outer_addr$blocky_address\",in_scope=\"false\"\},varobj=\{name=\"outer_at_line_122\",in_scope=\"false\"\},varobj=\{name=\"var6\",in_scope=\"false\"\},varobj=\{name=\"var5\",in_scope=\"false\"\},varobj=\{name=\"var4\",in_scope=\"false\"\},varobj=\{name=\"var3\",in_scope=\"false\"\},varobj=\{name=\"var2\",in_scope=\"false\"\},varobj=\{name=\"var1\",in_scope=\"false\"\}\\\]" "all varobjs go out of scope"
mi_gdb_exit
return 0