From abc9d0dc6edeeabbd65fedb43cf840875156da91 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 16 May 2012 20:31:10 +0000 Subject: [PATCH] PR macros/13205: * macrotab.h: (macro_define_special): Declare. (enum macro_special_kind): New. (struct macro_definition) : Update comments. * macrotab.c (new_macro_definition): Unconditionally set 'argc'. (macro_define_object_internal): New function. (macro_define_object): Use it. (macro_define_special): New function. (fixup_definition): New function. (macro_lookup_definition, foreach_macro_in_scope) (foreach_macro): Use fixup_definition. * macroexp.h (macro_stringify): Declare. * macroexp.c (free_buffer_return_text): New function. (stringify): Constify "arg". (macro_stringify): New function. * dwarf2read.c (macro_start_file): Call macro_define_special. testsuite * gdb.base/macscp1.c (macscp_expr): Add comment. * gdb.base/macscp.exp: Test __FILE__ and __LINE__. --- gdb/ChangeLog | 19 ++++++++ gdb/dwarf2read.c | 9 ++-- gdb/macroexp.c | 28 +++++++++++- gdb/macroexp.h | 5 +++ gdb/macrotab.c | 72 +++++++++++++++++++++++++++---- gdb/macrotab.h | 28 ++++++++++-- gdb/testsuite/ChangeLog | 5 +++ gdb/testsuite/gdb.base/macscp.exp | 10 ++++- gdb/testsuite/gdb.base/macscp1.c | 2 +- 9 files changed, 160 insertions(+), 18 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 0a35572656..c0d6ab9621 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,22 @@ +2012-05-16 Tom Tromey + + PR macros/13205: + * macrotab.h: (macro_define_special): Declare. + (enum macro_special_kind): New. + (struct macro_definition) : Update comments. + * macrotab.c (new_macro_definition): Unconditionally set 'argc'. + (macro_define_object_internal): New function. + (macro_define_object): Use it. + (macro_define_special): New function. + (fixup_definition): New function. + (macro_lookup_definition, foreach_macro_in_scope) + (foreach_macro): Use fixup_definition. + * macroexp.h (macro_stringify): Declare. + * macroexp.c (free_buffer_return_text): New function. + (stringify): Constify "arg". + (macro_stringify): New function. + * dwarf2read.c (macro_start_file): Call macro_define_special. + 2012-05-16 Maciej W. Rozycki Maciej W. Rozycki diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index f06dea68e6..f89742b180 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -15572,9 +15572,12 @@ macro_start_file (int file, int line, objfile->macro_cache); if (! current_file) - /* If we have no current file, then this must be the start_file - directive for the compilation unit's main source file. */ - current_file = macro_set_main (pending_macros, full_name); + { + /* If we have no current file, then this must be the start_file + directive for the compilation unit's main source file. */ + current_file = macro_set_main (pending_macros, full_name); + macro_define_special (pending_macros); + } else current_file = macro_include (current_file, line, full_name); diff --git a/gdb/macroexp.c b/gdb/macroexp.c index d5e4e40326..22b904e624 100644 --- a/gdb/macroexp.c +++ b/gdb/macroexp.c @@ -113,6 +113,17 @@ free_buffer (struct macro_buffer *b) xfree (b->text); } +/* Like free_buffer, but return the text as an xstrdup()d string. + This only exists to try to make the API relatively clean. */ + +static char * +free_buffer_return_text (struct macro_buffer *b) +{ + gdb_assert (! b->shared); + gdb_assert (b->size); + /* Nothing to do. */ + return b->text; +} /* A cleanup function for macro buffers. */ static void @@ -639,7 +650,7 @@ append_tokens_without_splicing (struct macro_buffer *dest, stringify; it is LEN bytes long. */ static void -stringify (struct macro_buffer *dest, char *arg, int len) +stringify (struct macro_buffer *dest, const char *arg, int len) { /* Trim initial whitespace from ARG. */ while (len > 0 && macro_is_whitespace (*arg)) @@ -682,6 +693,21 @@ stringify (struct macro_buffer *dest, char *arg, int len) dest->last_token = dest->len; } +/* See macroexp.h. */ + +char * +macro_stringify (const char *str) +{ + struct macro_buffer buffer; + int len = strlen (str); + char *result; + + init_buffer (&buffer, len); + stringify (&buffer, str, len); + + return free_buffer_return_text (&buffer); +} + /* Expanding macros! */ diff --git a/gdb/macroexp.h b/gdb/macroexp.h index 289619eba9..dba03f6722 100644 --- a/gdb/macroexp.h +++ b/gdb/macroexp.h @@ -91,4 +91,9 @@ int macro_is_identifier_nondigit (int c); int macro_is_digit (int c); +/* Stringify STR according to C rules and return an xmalloc'd pointer + to the result. */ + +char *macro_stringify (const char *str); + #endif /* MACROEXP_H */ diff --git a/gdb/macrotab.c b/gdb/macrotab.c index 7428839889..e65e5dc842 100644 --- a/gdb/macrotab.c +++ b/gdb/macrotab.c @@ -28,6 +28,7 @@ #include "gdb_assert.h" #include "bcache.h" #include "complaints.h" +#include "macroexp.h" /* The macro table structure. */ @@ -565,6 +566,7 @@ new_macro_definition (struct macro_table *t, d->table = t; d->kind = kind; d->replacement = macro_bcache_str (t, replacement); + d->argc = argc; if (kind == macro_function_like) { @@ -579,7 +581,6 @@ new_macro_definition (struct macro_table *t, /* Now bcache the array of argument pointers itself. */ d->argv = macro_bcache (t, cached_argv, cached_argv_size); - d->argc = argc; } /* We don't bcache the entire definition structure because it's got @@ -742,10 +743,12 @@ check_for_redefinition (struct macro_source_file *source, int line, return 0; } +/* A helper function to define a new object-like macro. */ -void -macro_define_object (struct macro_source_file *source, int line, - const char *name, const char *replacement) +static void +macro_define_object_internal (struct macro_source_file *source, int line, + const char *name, const char *replacement, + enum macro_special_kind kind) { struct macro_table *t = source->table; struct macro_key *k = NULL; @@ -771,10 +774,28 @@ macro_define_object (struct macro_source_file *source, int line, return; k = new_macro_key (t, name, source, line); - d = new_macro_definition (t, macro_object_like, 0, 0, replacement); + d = new_macro_definition (t, macro_object_like, kind, 0, replacement); splay_tree_insert (t->definitions, (splay_tree_key) k, (splay_tree_value) d); } +void +macro_define_object (struct macro_source_file *source, int line, + const char *name, const char *replacement) +{ + macro_define_object_internal (source, line, name, replacement, + macro_ordinary); +} + +/* See macrotab.h. */ + +void +macro_define_special (struct macro_table *table) +{ + macro_define_object_internal (table->main_source, -1, "__FILE__", "", + macro_FILE); + macro_define_object_internal (table->main_source, -1, "__LINE__", "", + macro_LINE); +} void macro_define_function (struct macro_source_file *source, int line, @@ -859,6 +880,36 @@ macro_undef (struct macro_source_file *source, int line, } } +/* A helper function that rewrites the definition of a special macro, + when needed. */ + +static struct macro_definition * +fixup_definition (const char *filename, int line, struct macro_definition *def) +{ + static char *saved_expansion; + + if (saved_expansion) + { + xfree (saved_expansion); + saved_expansion = NULL; + } + + if (def->kind == macro_object_like) + { + if (def->argc == macro_FILE) + { + saved_expansion = macro_stringify (filename); + def->replacement = saved_expansion; + } + else if (def->argc == macro_LINE) + { + saved_expansion = xstrprintf ("%d", line); + def->replacement = saved_expansion; + } + } + + return def; +} struct macro_definition * macro_lookup_definition (struct macro_source_file *source, @@ -867,7 +918,8 @@ macro_lookup_definition (struct macro_source_file *source, splay_tree_node n = find_definition (name, source, line); if (n) - return (struct macro_definition *) n->value; + return fixup_definition (source->filename, line, + (struct macro_definition *) n->value); else return 0; } @@ -910,7 +962,9 @@ foreach_macro (splay_tree_node node, void *arg) { struct macro_for_each_data *datum = (struct macro_for_each_data *) arg; struct macro_key *key = (struct macro_key *) node->key; - struct macro_definition *def = (struct macro_definition *) node->value; + struct macro_definition *def + = fixup_definition (key->start_file->filename, key->start_line, + (struct macro_definition *) node->value); (*datum->fn) (key->name, def, key->start_file, key->start_line, datum->user_data); @@ -936,7 +990,9 @@ foreach_macro_in_scope (splay_tree_node node, void *info) { struct macro_for_each_data *datum = (struct macro_for_each_data *) info; struct macro_key *key = (struct macro_key *) node->key; - struct macro_definition *def = (struct macro_definition *) node->value; + struct macro_definition *def + = fixup_definition (datum->file->filename, datum->line, + (struct macro_definition *) node->value); /* See if this macro is defined before the passed-in line, and extends past that line. */ diff --git a/gdb/macrotab.h b/gdb/macrotab.h index 8316cc375d..92f165611d 100644 --- a/gdb/macrotab.h +++ b/gdb/macrotab.h @@ -212,6 +212,10 @@ struct macro_source_file *macro_include (struct macro_source_file *source, int line, const char *included); +/* Define any special macros, like __FILE__ or __LINE__. This should + be called once, on the main source file. */ + +void macro_define_special (struct macro_table *table); /* Find any source file structure for a file named NAME, either included into SOURCE, or SOURCE itself. Return zero if we have @@ -261,6 +265,17 @@ enum macro_kind macro_function_like }; +/* Different kinds of special macros. */ + +enum macro_special_kind +{ + /* Ordinary. */ + macro_ordinary, + /* The special macro __FILE__. */ + macro_FILE, + /* The special macro __LINE__. */ + macro_LINE +}; /* A preprocessor symbol definition. */ struct macro_definition @@ -273,12 +288,17 @@ struct macro_definition /* If `kind' is `macro_function_like', the number of arguments it takes, and their names. The names, and the array of pointers to - them, are in the table's bcache, if it has one. */ - int argc : 31; + them, are in the table's bcache, if it has one. If `kind' is + `macro_object_like', then this is actually a `macro_special_kind' + describing the macro. */ + int argc : 30; const char * const *argv; - /* The replacement string (body) of the macro. This is in the - table's bcache, if it has one. */ + /* The replacement string (body) of the macro. For ordinary macros, + this is in the table's bcache, if it has one. For special macros + like __FILE__, this value is only valid until the next use of any + special macro definition; that is, it is reset each time any + special macro is looked up or iterated over. */ const char *replacement; }; diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 93e0a0dd5a..236007d301 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-05-16 Tom Tromey + + * gdb.base/macscp1.c (macscp_expr): Add comment. + * gdb.base/macscp.exp: Test __FILE__ and __LINE__. + 2012-05-16 Maciej W. Rozycki * gdb.base/return-nodebug.exp: Also test float and double types. diff --git a/gdb/testsuite/gdb.base/macscp.exp b/gdb/testsuite/gdb.base/macscp.exp index fa2173a417..44a526b4fe 100644 --- a/gdb/testsuite/gdb.base/macscp.exp +++ b/gdb/testsuite/gdb.base/macscp.exp @@ -227,6 +227,10 @@ list_and_check_macro macscp3_2 WHERE {macscp3.h macscp1.c {before macscp3_2}} gdb_test "info macro FROM_COMMANDLINE" \ "Defined at \[^\r\n\]*:0\r\n-DFROM_COMMANDLINE=ARG" +gdb_test "info macro __FILE__" "#define __FILE__ \".*macscp3.h\"" \ + "info macro __FILE__ before running" +gdb_test "info macro __LINE__" "#define __LINE__ 26" \ + "info macro __LINE__ before running" # Although GDB's macro table structures distinguish between multiple # #inclusions of the same file, GDB's other structures don't. So the @@ -466,7 +470,7 @@ gdb_test "print MACRO_TO_EXPAND" \ " = 0" \ "print expression with macro after removing override" -gdb_test "next" "foo = 2;" "next to definition 2" +gdb_test "next" "foo = 2;.*" "next to definition 2" gdb_test "print MACRO_TO_EXPAND" \ "No symbol \"MACRO_TO_EXPAND\" in current context\." \ @@ -673,3 +677,7 @@ gdb_test_no_output "macro define si_addr fields.fault.si_addr" \ gdb_test "macro expand siginfo.si_addr" \ "expands to: siginfo.fields.fault.si_addr" \ "macro expand siginfo.si_addr" + +gdb_test "print __FILE__" " = \".*macscp1.c\"" +gdb_test "print __LINE__" \ + " = [gdb_get_line_number {stopping point for line test}]" diff --git a/gdb/testsuite/gdb.base/macscp1.c b/gdb/testsuite/gdb.base/macscp1.c index e754b2684d..b1eb0b4490 100644 --- a/gdb/testsuite/gdb.base/macscp1.c +++ b/gdb/testsuite/gdb.base/macscp1.c @@ -91,7 +91,7 @@ macscp_expr (void) #define MACRO_TO_EXPAND foo foo = 1; #undef MACRO_TO_EXPAND - foo = 2; + foo = 2; /* stopping point for line test */ } #define TWENTY_THREE 23 -- 2.34.1