This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: test macro scoping



This test only checks GDB's ability to figure out which macros are in
scope where.  (`macros' is supposed to be an abbreviation for `macro
scope'; should I rename these to `macrosc<mumble>?'  I need a spot for
the file number...)

This introduces about 23 new failures.  They reflect a genuine bug,
but one that will take a lot of work to fix.  If I understand the
conventions correctly, such bugs are supposed to be marked with
"setup_kfail", with a reference to a GDB PR describing the bug,
commented out.  So I've filed gdb/555, and marked the failing tests
attributable to that bug accordingly.  If this isn't right, please set
me straight.

More tests will be forthcoming for the macro commands and macro
expansion.

2002-05-21  Jim Blandy  <jimb@redhat.com>

	* macros.exp, macros1.c, macros2.h, macros3.h, macros4.h: New
	tests.

Index: gdb/testsuite/gdb.base/macros.exp
===================================================================
RCS file: gdb/testsuite/gdb.base/macros.exp
diff -N gdb/testsuite/gdb.base/macros.exp
*** gdb/testsuite/gdb.base/macros.exp	1 Jan 1970 00:00:00 -0000
--- gdb/testsuite/gdb.base/macros.exp	22 May 2002 03:39:23 -0000
***************
*** 0 ****
--- 1,403 ----
+ # Test macro scoping.
+ # Copyright 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
+ 
+ if $tracelevel then {
+     strace $tracelevel
+ }
+ 
+ set prms_id 0
+ set bug_id 0
+ 
+ set testfile "macros"
+ set binfile ${objdir}/${subdir}/${testfile}
+ 
+ if  {[gdb_compile "${srcdir}/${subdir}/macros1.c" "${binfile}" executable {debug}] != "" } {
+     gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+ }
+ 
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load ${binfile}
+ 
+ 
+ # Ask GDB to show the current definition of MACRO, and return a list
+ # describing the result.
+ #
+ # The return value has the form {FILE1 FILE2 ... DEF}, which means
+ # that MACRO has the definition `DEF', and was defined in `FILE1',
+ # which was included from `FILE2', included from ... .
+ #
+ # If GDB says that MACRO has no definition, return the string `undefined'.
+ #
+ # If GDB complains that it doesn't have any information about
+ # preprocessor macro definitions, return the string `no-macro-info'.
+ # 
+ # If expect times out waiting for GDB, we return the string `timeout'.
+ #
+ # If GDB's output doesn't otherwise match what we're expecting, we
+ # return the empty string.
+ 
+ proc show_macro {macro} {
+     global gdb_prompt
+     global decimal
+ 
+     set filepat {macros[0-9]+\.[ch]}
+     set definition {}
+     set location {}
+ 
+     send_gdb "show macro ${macro}\n"
+ 
+     set debug_me 0
+ 
+     if {$debug_me} {exp_internal 1}
+     gdb_expect {
+         -re "Defined at \[^\r\n\]*(${filepat}):${decimal}\[\r\n\]" {
+             # `location' and `definition' should be empty when we see
+             # this message.
+             if {[llength $location] == 0 && [llength $definition] == 0} {
+                 set location $expect_out(1,string)
+                 exp_continue
+             } else {
+                 # Exit this expect loop, with a result indicating failure.
+                 set definition {}
+             }
+         }
+         -re "The symbol `${macro}' has no definition as a C/C\\+\\+ preprocessor macro\[^\r\n\]*\[\r\n\]" {
+             # `location' and `definition' should be empty when we see
+             # this message.
+             if {[llength $location] == 0 && [llength $definition] == 0} {
+                 set definition undefined
+                 exp_continue
+             } else {
+                 # Exit this expect loop, with a result indicating failure.
+                 set definition {}
+             }
+         }
+         -re "^\[\r\n\]*  included at \[^\r\n\]*(${filepat}):${decimal}\[\r\n\]" {
+             # `location' should *not* be empty when we see this
+             # message.  It should have recorded at least the initial
+             # `Defined at ' message (for definitions) or ` at' message
+             # (for undefined symbols).
+             if {[llength $location] != 0} {
+                 lappend location $expect_out(1,string)
+                 exp_continue
+             } else {
+                 # Exit this expect loop, with a result indicating failure.
+                 set definition {}
+             }
+         }
+         -re "^\[\r\n\]*at \[^\r\n\]*(${filepat}):${decimal}\[\r\n\]" {
+             # This appears after a `has no definition' message.
+             # `location' should be empty when we see it.
+             if {[string compare $definition undefined] == 0 \
+                     && [llength $location] == 0} {
+                 set location $expect_out(1,string)
+                 exp_continue
+             } else {
+                 # Exit this expect loop, with a result indicating failure.
+                 set definition {}
+             }
+         }
+         -re "#define ${macro} (\[^\r\n\]*)\[\r\n\]" {
+             # `definition' should be empty when we see this message.
+             if {[string compare $definition ""] == 0} {
+                 set definition $expect_out(1,string)
+                 exp_continue
+             } else {
+                 # Exit this expect loop, with a result indicating failure.
+                 set definition {}
+             }
+         }
+         -re "has no preprocessor macro information.*$gdb_prompt $" {
+             set definition no-macro-info
+         }
+         -re "$gdb_prompt $" {
+             # Exit the expect loop; let the existing value of `definition'
+             # indicate failure or success.
+         }
+         timeout {
+             set definition timeout
+         }
+     }
+     if {$debug_me} {exp_internal 0}
+ 
+     switch -exact -- $definition {
+         no-macro-info { return no-macro-info }
+         timeout { return timeout }
+         undefined -
+         default {
+             if {[llength $location] >= 1} {
+                 return [concat $location [list $definition]]
+             } else {
+                 return {}
+             }
+         }
+     }
+ }
+ 
+ 
+ # Call show_macro to show the definition of MACRO.  Expect a result of
+ # EXPECTED.  Use WHERE in pass/fail messages to identify the context.
+ # Return non-zero if we should abort the entire test file, or zero if
+ # we can continue.
+ proc check_macro {macro expected where} {
+     set func_def [show_macro $macro]
+     if {[string compare $func_def $expected] == 0} {
+         pass "show macro $macro $where"
+     } else {
+         switch -exact -- $func_def {
+             no-macro-info {
+                 xfail "executable includes no macro debugging information"
+                 return 1
+             }
+             timeout {
+                 fail "show macro $macro $where (timeout)"
+             }
+             default {
+                 fail "show macro $macro $where"
+             }
+         }
+     }
+     return 0
+ }
+     
+ 
+ # List the function FUNC, and then show the definition of MACRO,
+ # expecting the result EXPECTED.
+ proc list_and_check_macro {func macro expected} {
+     gdb_test "list $func" ".*${func}.*"
+     return [check_macro $macro $expected "after `list $func'"]
+ }
+ 
+ 
+ if {[list_and_check_macro main WHERE {macros1.c {before macros1_3}}]} {
+     return 0
+ }
+ list_and_check_macro macros2_2 WHERE {macros2.h macros1.c {before macros2_2}}
+ list_and_check_macro macros3_2 WHERE {macros3.h macros1.c {before macros3_2}}
+ 
+ 
+ # Although GDB's macro table structures distinguish between multiple
+ # #inclusions of the same file, GDB's other structures don't.  So the
+ # `list' command here doesn't reliably select one #inclusion or the
+ # other, even though it could.  It would be nice to eventually change
+ # GDB's structures to handle this correctly.
+ gdb_test "list macros4_2_from_macros2" ".*macros4_2_, MACROS4_INCLUSION.*"
+ switch -exact -- [show_macro WHERE] {
+     {macros4.h macros2.h macros1.c {before macros4_2_..., from macros2.h}} {
+         pass "show macro WHERE after `list macros_4_2_from_macros2'"
+     }
+     {macros4.h macros3.h macros1.c {before macros4_2_..., from macros3.h}} {
+         # setup_kfail "gdb/555"
+         fail "show macro WHERE after `list macros_4_2_from_macros2' (gdb/555)"
+     }
+     timeout { 
+         fail "show macro WHERE after `list macros_4_2_from_macros2' (timeout)"
+     }
+     default { fail "show macro WHERE after `list macros_4_2_from_macros2'" }
+ }
+ 
+ gdb_test "list macros4_2_from_macros3" ".*macros4_2_, MACROS4_INCLUSION.*"
+ switch -exact -- [show_macro WHERE] {
+     {macros4.h macros3.h macros1.c {before macros4_2_..., from macros3.h}} {
+         pass "show macro WHERE after `list macros_4_2_from_macros3'"
+     }
+     {macros4.h macros2.h macros1.c {before macros4_2_..., from macros2.h}} {
+         # setup_kfail "gdb/555"
+         fail "show macro WHERE after `list macros_4_2_from_macros3' (gdb/555)"
+     }
+     timeout {
+         fail "show macro WHERE after `list macros_4_2_from_macros3' (timeout)"
+     }
+     default { fail "show macro WHERE after `list macros_4_2_from_macros3'" }
+ }
+ 
+ 
+ #### Test the selection of the macro scope by the current frame.
+ 
+ ### A table of functions, in the order they will be reached, which is
+ ### also the order they appear in the preprocessed output.  Each entry
+ ### has the form {FUNCNAME WHERE KFAILWHERE}, where:
+ ### - FUNCNAME is the name of the function,
+ ### - WHERE is the definition we expect to see for the macro `WHERE', as
+ ###   returned by `show_macro', and
+ ### - KFAILWHERE is an alternate definition which should be reported
+ ###   as a `known failure', due to GDB's inability to distinguish multiple
+ ###   #inclusions of the same file.
+ ### KFAILWHERE may be omitted.
+ 
+ set funcs {
+     {
+         macros1_1
+         {macros1.c {before macros1_1}}
+     }
+     {
+         macros2_1
+         {macros2.h macros1.c {before macros2_1}}
+     }
+     {
+         macros4_1_from_macros2
+         {macros4.h macros2.h macros1.c {before macros4_1_..., from macros2.h}}
+         {macros4.h macros3.h macros1.c {before macros4_1_..., from macros3.h}}
+     }
+     {
+         macros4_2_from_macros2
+         {macros4.h macros2.h macros1.c {before macros4_2_..., from macros2.h}}
+         {macros4.h macros3.h macros1.c {before macros4_2_..., from macros3.h}}
+     }
+     {
+         macros2_2
+         {macros2.h macros1.c {before macros2_2}}
+     }
+     {
+         macros1_2
+         {macros1.c {before macros1_2}}
+     }
+     {
+         macros3_1
+         {macros3.h macros1.c {before macros3_1}}
+     }
+     {
+         macros4_1_from_macros3
+         {macros4.h macros3.h macros1.c {before macros4_1_..., from macros3.h}}
+         {macros4.h macros2.h macros1.c {before macros4_1_..., from macros2.h}}
+     }
+     {
+         macros4_2_from_macros3
+         {macros4.h macros3.h macros1.c {before macros4_2_..., from macros3.h}}
+         {macros4.h macros2.h macros1.c {before macros4_2_..., from macros2.h}}
+     }
+     {
+         macros3_2
+         {macros3.h macros1.c {before macros3_2}}
+     }
+     {
+         macros1_3
+         {macros1.c {before macros1_3}}
+     }
+ }
+ 
+ 
+ # Start the program running.
+ if {! [runto_main]} {
+     fail "macro tests suppressed: couldn't run to main"
+     return 0
+ }
+ 
+ # Set a breakpoint on each of the functions.
+ foreach func_entry $funcs {
+     set func [lindex $func_entry 0]
+     gdb_test "break $func" "Breakpoint.*"
+ }
+ 
+ # Run to each of the breakpoints and check the definition (or lack
+ # thereof) of each macro.
+ for {set i 0} {$i < [llength $funcs]} {incr i} {
+     set func_entry [lindex $funcs $i]
+     set func [lindex $func_entry 0]
+     set expected [lindex $func_entry 1]
+     set kfail_expected [lindex $func_entry 2]
+ 
+     # Run to the breakpoint for $func.
+     gdb_test "continue" "Breakpoint $decimal, $func .*" "continue to $func"
+ 
+     # Check the macro WHERE.
+     set result [show_macro WHERE]
+     if {[string compare $result $expected] == 0} {
+         pass "show macro WHERE stopped in $func"
+     } elseif {[string compare $result $kfail_expected] == 0} {
+         # setup_kfail "gdb/555"
+         fail "show macro WHERE stopped in $func (gdb/555)"
+     } elseif {[string compare $result timeout] == 0} {
+         fail "show macro WHERE stopped in $func (timeout)"
+     } else {
+         fail "show macro WHERE stopped in $func"
+     }
+ 
+     # Check that the BEFORE_<func> macros for all prior functions are
+     # #defined, and that those for all subsequent functions are not.
+     for {set j 0} {$j < [llength $funcs]} {incr j} {
+         if {$j != $i} {
+             set func_j_entry [lindex $funcs $j]
+             set func_j [lindex $func_j_entry 0]
+ 
+             set before_macro "BEFORE_[string toupper $func_j]"
+             set test_name \
+                     "$before_macro defined/undefined when stopped at $func"
+             set result [show_macro $before_macro]
+ 
+             # We can't get the right scope info when we're stopped in
+             # the macro4_ functions.
+             if {[string match macros4_* $func]} {
+                 # setup_kfail "gdb/555"
+                 set test_name "$test_name (gdb/555)"
+             }
+             if {$j < $i} {
+                 if {[llength $result] >= 2 && \
+                         [string compare [lindex $result end] {}] == 0} {
+                     pass $test_name
+                 } elseif {[string compare $result timeout] == 0} {
+                     fail "$test_name (timeout)"
+                 } else {
+                     fail "$test_name"
+                 }
+             } elseif {$j > $i} {
+                 switch -- [lindex $result end] {
+                     undefined { pass $test_name }
+                     timeout { fail "$test_name (timeout)" }
+                     default { 
+                         fail "$test_name"
+                     }
+                 }
+             }
+ 
+             set until_macro "UNTIL_[string toupper $func_j]"
+             set test_name \
+                     "$until_macro defined/undefined when stopped at $func"
+             set result [show_macro $until_macro]
+ 
+             # We can't get the right scope info when we're stopped in
+             # the macro4_ functions.
+             if {[string match macros4_* $func]} {
+                 # setup_kfail "gdb/555"
+                 set test_name "$test_name (gdb/555)"
+             }
+             if {$j <= $i} {
+                 switch -- [lindex $result end] {
+                     undefined { pass $test_name }
+                     timeout { fail "$test_name (timeout)" }
+                     default { 
+                         fail "$test_name"
+                     }
+                 }
+             } elseif {$j > $i} {
+                 if {[llength $result] >= 2 && \
+                         [string compare [lindex $result end] {}] == 0} {
+                     pass $test_name
+                 } elseif {[string compare $result timeout] == 0} {
+                     fail "$test_name (timeout)"
+                 } else {
+                     fail "$test_name"
+                 }
+             }
+         }
+     }
+ }
Index: gdb/testsuite/gdb.base/macros1.c
===================================================================
RCS file: gdb/testsuite/gdb.base/macros1.c
diff -N gdb/testsuite/gdb.base/macros1.c
*** gdb/testsuite/gdb.base/macros1.c	1 Jan 1970 00:00:00 -0000
--- gdb/testsuite/gdb.base/macros1.c	22 May 2002 03:39:23 -0000
***************
*** 0 ****
--- 1,80 ----
+ #include <stdio.h>
+ 
+ #define SPLICE(a, b) INNER_SPLICE(a, b)
+ #define INNER_SPLICE(a, b) a ## b
+ #define STRINGIFY(a) INNER_STRINGIFY(a)
+ #define INNER_STRINGIFY(a) #a
+ 
+ /* A macro named UNTIL_<func> is #defined until just before the
+    definition of the function <func>.
+ 
+    A macro named BEFORE_<func> is not #defined until just before the
+    definition of <func>.
+ 
+    The macro WHERE is redefined before each function <func> to the
+    token list ``before <func>''.
+ 
+    The macros IN_MACROS2_H and IN_MACROS3_H are defined while
+    processing those header files; macros4.h uses them to choose
+    appropriate function names, output strings, and macro definitions.  */
+ 
+ #define UNTIL_MACROS1_1
+ #define UNTIL_MACROS2_1
+ #define UNTIL_MACROS4_1_FROM_MACROS2
+ #define UNTIL_MACROS4_2_FROM_MACROS2
+ #define UNTIL_MACROS2_2
+ #define UNTIL_MACROS1_2
+ #define UNTIL_MACROS3_1
+ #define UNTIL_MACROS4_1_FROM_MACROS3
+ #define UNTIL_MACROS4_2_FROM_MACROS3
+ #define UNTIL_MACROS3_2
+ #define UNTIL_MACROS1_3
+ 
+ #define WHERE before macros1_1
+ #define BEFORE_MACROS1_1
+ #undef UNTIL_MACROS1_1
+ void
+ macros1_1 ()
+ {
+   puts ("macros1_1");
+ }
+ 
+ #include "macros2.h"
+ 
+ #undef WHERE
+ #define WHERE before macros1_2
+ #define BEFORE_MACROS1_2
+ #undef UNTIL_MACROS1_2
+ void
+ macros1_2 ()
+ {
+   puts ("macros1_2");
+ }
+ 
+ #include "macros3.h"
+ 
+ #undef WHERE
+ #define WHERE before macros1_3
+ #define BEFORE_MACROS1_3
+ #undef UNTIL_MACROS1_3
+ void
+ macros1_3 ()
+ {
+   puts ("macros1_3");
+ }
+ 
+ int
+ main (int argc, char **argv)
+ {
+   macros1_1 ();
+   macros2_1 ();
+   macros4_1_from_macros2 ();
+   macros4_2_from_macros2 ();
+   macros2_2 ();
+   macros1_2 ();
+   macros3_1 ();
+   macros4_1_from_macros3 ();
+   macros4_2_from_macros3 ();
+   macros3_2 ();
+   macros1_3 ();
+ }
Index: gdb/testsuite/gdb.base/macros2.h
===================================================================
RCS file: gdb/testsuite/gdb.base/macros2.h
diff -N gdb/testsuite/gdb.base/macros2.h
*** gdb/testsuite/gdb.base/macros2.h	1 Jan 1970 00:00:00 -0000
--- gdb/testsuite/gdb.base/macros2.h	22 May 2002 03:39:23 -0000
***************
*** 0 ****
--- 1,25 ----
+ #define IN_MACROS2_H
+ 
+ #undef WHERE
+ #define WHERE before macros2_1
+ #define BEFORE_MACROS2_1
+ #undef UNTIL_MACROS2_1
+ void
+ macros2_1 ()
+ {
+   puts ("macros2_1");
+ }
+ 
+ #include "macros4.h"
+ 
+ #undef WHERE
+ #define WHERE before macros2_2
+ #define BEFORE_MACROS2_2
+ #undef UNTIL_MACROS2_2
+ void
+ macros2_2 ()
+ {
+   puts ("macros2_2");
+ }
+ 
+ #undef IN_MACROS2_H
Index: gdb/testsuite/gdb.base/macros3.h
===================================================================
RCS file: gdb/testsuite/gdb.base/macros3.h
diff -N gdb/testsuite/gdb.base/macros3.h
*** gdb/testsuite/gdb.base/macros3.h	1 Jan 1970 00:00:00 -0000
--- gdb/testsuite/gdb.base/macros3.h	22 May 2002 03:39:23 -0000
***************
*** 0 ****
--- 1,25 ----
+ #define IN_MACROS3_H
+ 
+ #undef WHERE
+ #define WHERE before macros3_1
+ #define BEFORE_MACROS3_1
+ #undef UNTIL_MACROS3_1
+ void
+ macros3_1 ()
+ {
+   puts ("macros3_1");
+ }
+ 
+ #include "macros4.h"
+ 
+ #undef WHERE
+ #define WHERE before macros3_2
+ #define BEFORE_MACROS3_2
+ #undef UNTIL_MACROS3_2
+ void
+ macros3_2 ()
+ {
+   puts ("macros3_2");
+ }
+ 
+ #undef IN_MACROS3_H
Index: gdb/testsuite/gdb.base/macros4.h
===================================================================
RCS file: gdb/testsuite/gdb.base/macros4.h
diff -N gdb/testsuite/gdb.base/macros4.h
*** gdb/testsuite/gdb.base/macros4.h	1 Jan 1970 00:00:00 -0000
--- gdb/testsuite/gdb.base/macros4.h	22 May 2002 03:39:23 -0000
***************
*** 0 ****
--- 1,44 ----
+ /* Put together a macro we can use as part of function names.  */
+ #undef MACROS4_INCLUSION
+ #ifdef IN_MACROS2_H
+ #define MACROS4_INCLUSION from_macros2
+ #endif
+ #ifdef IN_MACROS3_H
+ #define MACROS4_INCLUSION from_macros3
+ #endif
+ 
+ #undef WHERE
+ #ifdef IN_MACROS2_H
+ #define WHERE before macros4_1_..., from macros2.h
+ #define BEFORE_MACROS4_1_FROM_MACROS2
+ #undef UNTIL_MACROS4_1_FROM_MACROS2
+ #endif
+ #ifdef IN_MACROS3_H
+ #define WHERE before macros4_1_..., from macros3.h
+ #define BEFORE_MACROS4_1_FROM_MACROS3
+ #undef UNTIL_MACROS4_1_FROM_MACROS3
+ #endif
+ void
+ SPLICE (macros4_1_, MACROS4_INCLUSION) ()
+ {
+   puts ("macros4_1_" STRINGIFY(MACROS4_INCLUSION));
+ }
+ 
+ #undef WHERE
+ #ifdef IN_MACROS2_H
+ #define WHERE before macros4_2_..., from macros2.h
+ #define BEFORE_MACROS4_2_FROM_MACROS2
+ #undef UNTIL_MACROS4_2_FROM_MACROS2
+ #endif
+ #ifdef IN_MACROS3_H
+ #define WHERE before macros4_2_..., from macros3.h
+ #define BEFORE_MACROS4_2_FROM_MACROS3
+ #undef UNTIL_MACROS4_2_FROM_MACROS3
+ #endif
+ void
+ SPLICE (macros4_2_, MACROS4_INCLUSION) ()
+ {
+   puts ("macros4_2_" STRINGIFY(MACROS4_INCLUSION));
+ }
+ 
+ #define DEFINED_IN_MACROS4 this was defined in macros4.h.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]