Attached is a suggested fix for a long-standing C pre-processor bug. Ref: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33919 Ref: http://gcc.gnu.org/ml/gcc/2004-10/msg00534.html
The patch implements the approach suggested by Harald van Dijk in the cited bug report. I am not familiar with the subtleties of the C pre-processor, and do not know if there may be some surprises or special cases not covered. The fix does appear to provide the expected result as demonstrated by the included test case. I have a specific question re: this new code. + name = _cpp_get_file_name (pfile->main_file); + if (!name) + name = "<unknown>"; I wasn't sure whether 'name' can have a NULL value, and handled that case as shown above. Would a gcc_assert() be more appropriate, or is it safe to simply assume that the name value is not NULL? Please review. Thanks, - Gary
Index: gcc/testsuite/gcc.dg/pr33919-2.h =================================================================== --- gcc/testsuite/gcc.dg/pr33919-2.h (revision 0) +++ gcc/testsuite/gcc.dg/pr33919-2.h (revision 0) @@ -0,0 +1 @@ +char *nested_inc_base_file = __BASE_FILE__; Index: gcc/testsuite/gcc.dg/pr33919.c =================================================================== --- gcc/testsuite/gcc.dg/pr33919.c (revision 0) +++ gcc/testsuite/gcc.dg/pr33919.c (revision 0) @@ -0,0 +1,35 @@ +/* PR preprocessor/pr33919 */ +/* { dg-do run } */ +/* { dg-options "-I . -include ${srcdir}/gcc.dg/pr33919-0.h" } */ + +#include "pr33919-1.h" + +typedef __SIZE_TYPE__ size_t; + +const char *base_file = __BASE_FILE__; + +extern int strcmp (const char *, const char *); +extern size_t strlen (const char *); +extern void abort (void); + +#define BASE_NAME "pr33919.c" + +int +main () +{ + size_t file_len = strlen (__FILE__); + size_t basename_len = strlen (BASE_NAME); + if (file_len < basename_len) + abort (); + if (strcmp (__FILE__ + file_len - basename_len, BASE_NAME)) + abort (); + if (strcmp (pre_inc_base_file, __FILE__)) + abort (); + if (strcmp (base_file, __FILE__)) + abort (); + if (strcmp (inc_base_file, __FILE__)) + abort (); + if (strcmp (nested_inc_base_file, __FILE__)) + abort (); + return 0; +} Index: gcc/testsuite/gcc.dg/pr33919-0.h =================================================================== --- gcc/testsuite/gcc.dg/pr33919-0.h (revision 0) +++ gcc/testsuite/gcc.dg/pr33919-0.h (revision 0) @@ -0,0 +1 @@ +char *pre_inc_base_file = __BASE_FILE__; Index: gcc/testsuite/gcc.dg/pr33919-1.h =================================================================== --- gcc/testsuite/gcc.dg/pr33919-1.h (revision 0) +++ gcc/testsuite/gcc.dg/pr33919-1.h (revision 0) @@ -0,0 +1,2 @@ +#include "pr33919-2.h" +char *inc_base_file = __BASE_FILE__; Index: gcc/testsuite/ChangeLog =================================================================== --- gcc/testsuite/ChangeLog (revision 182805) +++ gcc/testsuite/ChangeLog (working copy) @@ -1,3 +1,11 @@ +2012-01-02 Gary Funck <g...@intrepid.com> + + PR preprocessor/33919 + * gcc.dg/pr33919.c: New test. + * gcc.dg/pr33919-0.h: New test header file. + * gcc.dg/pr33919-1.h: Ditto. + * gcc.dg/pr33919-2.h: Ditto. + 2012-01-02 Paolo Carlini <paolo.carl...@oracle.com> PR c++/20140 Index: libcpp/macro.c =================================================================== --- libcpp/macro.c (revision 182805) +++ libcpp/macro.c (working copy) @@ -1,7 +1,7 @@ /* Part of CPP library. (Macro and #define handling.) Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. Written by Per Bothner, 1994. Based on CCCP program by Paul Rubin, June 1986 Adapted to ANSI C, Richard Stallman, Jan 1987 @@ -278,10 +278,9 @@ _cpp_builtin_macro_text (cpp_reader *pfi pfile->line_table->highest_line); else { - map = linemap_lookup (pfile->line_table, pfile->line_table->highest_line); - while (! MAIN_FILE_P (map)) - map = INCLUDED_FROM (pfile->line_table, map); - name = ORDINARY_MAP_FILE_NAME (map); + name = _cpp_get_file_name (pfile->main_file); + if (!name) + name = "<unknown>"; } len = strlen (name); buf = _cpp_unaligned_alloc (pfile, len * 2 + 3); Index: libcpp/files.c =================================================================== --- libcpp/files.c (revision 182805) +++ libcpp/files.c (working copy) @@ -1,7 +1,7 @@ /* Part of CPP library. File handling. Copyright (C) 1986, 1987, 1989, 1992, 1993, 1994, 1995, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003, 2004, 2005, + 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. Written by Per Bothner, 1994. Based on CCCP program by Paul Rubin, June 1986 Adapted to ANSI C, Richard Stallman, Jan 1987 @@ -1370,6 +1370,13 @@ _cpp_pop_file_buffer (cpp_reader *pfile, } } +/* Return the file name associated with FILE. */ +const char * +_cpp_get_file_name (_cpp_file *file) +{ + return file->name; +} + /* Inteface to file statistics record in _cpp_file structure. */ struct stat * _cpp_get_file_stat (_cpp_file *file) Index: libcpp/ChangeLog =================================================================== --- libcpp/ChangeLog (revision 182805) +++ libcpp/ChangeLog (working copy) @@ -1,3 +1,12 @@ +2012-01-02 Gary Funck <g...@intrepid.com> + + PR preprocessor/33919 + * files.c (_cpp_get_file_name): New. Implement file name + access function. + * internal.h (_cpp_get_file_name): New prototype. + * macro.c (_cpp_builtin_macro_text): Call _cpp_get_file_name() + to use pfile->main_file in lieu of traversing INCLUDED_FROM chain. + 2011-12-20 Joseph Myers <jos...@codesourcery.com> * include/cpplib.h (CLK_GNUC1X): Change to CLK_GNUC11. Index: libcpp/internal.h =================================================================== --- libcpp/internal.h (revision 182805) +++ libcpp/internal.h (working copy) @@ -1,6 +1,6 @@ /* Part of CPP library. Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, - 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + 2008, 2009, 2010, 2011, 2012 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 @@ -635,6 +635,7 @@ extern void _cpp_cleanup_files (cpp_read extern void _cpp_pop_file_buffer (cpp_reader *, struct _cpp_file *); extern bool _cpp_save_file_entries (cpp_reader *pfile, FILE *f); extern bool _cpp_read_file_entries (cpp_reader *, FILE *); +extern const char *_cpp_get_file_name (_cpp_file *); extern struct stat *_cpp_get_file_stat (_cpp_file *); /* In expr.c */