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 */

Reply via email to