This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: RFA: test macro scoping
Here is a revision of this patch, using names based on `macscp'
instead of `macros'. `macros' was supposed to stand for `macro
scoping', but it really just looks like the plural of `macro'. I'm
planning to post patches for macro expansion (`macexp') and macro
commands (`maccmd'), so the name `macscp' fits better.
There are no other differences between this patch and its predecessor.
Jim Blandy <jimb@redhat.com> writes:
> 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.