From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27594 invoked by alias); 22 May 2002 19:32:17 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 27546 invoked from network); 22 May 2002 19:32:09 -0000 Received: from unknown (HELO zwingli.cygnus.com) (208.245.165.35) by sources.redhat.com with SMTP; 22 May 2002 19:32:09 -0000 Received: by zwingli.cygnus.com (Postfix, from userid 442) id 8A1735EA11; Wed, 22 May 2002 14:32:07 -0500 (EST) To: gdb-patches@sources.redhat.com Subject: Re: RFA: test macro scoping References: <20020522041427.CE78E5EA11@zwingli.cygnus.com> From: Jim Blandy Date: Wed, 22 May 2002 13:17:00 -0000 In-Reply-To: <20020522041427.CE78E5EA11@zwingli.cygnus.com> Message-ID: User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.1 MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2002-05/txt/msg00861.txt.bz2 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 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?' 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 > > * 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_ 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 > + > + #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_ is #defined until just before the > + definition of the function . > + > + A macro named BEFORE_ is not #defined until just before the > + definition of . > + > + The macro WHERE is redefined before each function to the > + token list ``before ''. > + > + 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.