Hi!

Seems libcpp has been ICEing on push_macro of a builtin macro since 2010,
but it became more urgent with Martin's __has_builtin builtin macro
addition, because the mingw headers already do use
#pragma push_macro("__has_builtin")
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
...
#pragma pop_macro("__has_builtin")
and so GCC ICEs any time it sees that.

The following patch fixes it by handling builtin macros properly,
noting that they were builtin previously and when restoring them into
the builtin state from whatever other state changing them according to
the builtin_array.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2019-10-31  Jakub Jelinek  <ja...@redhat.com>

        PR preprocessor/92296
        * internal.h (struct def_pragma_macro): Add is_builtin bitfield.
        (_cpp_restore_special_builtin): Declare.
        * init.c (_cpp_restore_special_builtin): New function.
        * directives.c (do_pragma_push_macro): For NT_BUILTIN_MACRO
        set is_builtin and don't try to grab definition.
        (cpp_pop_definition): Use _cpp_restore_special_builtin to restore
        builtin macros.

        * c-c++-common/cpp/pr92296-1.c: New test.
        * c-c++-common/cpp/pr92296-2.c: New test.

--- libcpp/internal.h.jj        2019-10-03 00:26:24.755766153 +0200
+++ libcpp/internal.h   2019-10-31 12:14:58.554037427 +0100
@@ -391,6 +391,8 @@ struct def_pragma_macro {
 
   /* Mark if we save an undefined macro.  */
   unsigned int is_undef : 1;
+  /* Nonzero if it was a builtin macro.  */
+  unsigned int is_builtin : 1;
 };
 
 /* A cpp_reader encapsulates the "state" of a pre-processor run.
@@ -722,6 +724,8 @@ extern void *_cpp_commit_buff (cpp_reade
 /* In init.c.  */
 extern void _cpp_maybe_push_include_file (cpp_reader *);
 extern const char *cpp_named_operator2name (enum cpp_ttype type);
+extern void _cpp_restore_special_builtin (cpp_reader *pfile,
+                                         struct def_pragma_macro *);
 
 /* In directives.c */
 extern int _cpp_test_assertion (cpp_reader *, unsigned int *);
--- libcpp/init.c.jj    2019-10-29 09:26:09.740514434 +0100
+++ libcpp/init.c       2019-10-31 12:14:40.954308484 +0100
@@ -497,6 +497,25 @@ cpp_init_special_builtins (cpp_reader *p
     }
 }
 
+/* Restore macro C to builtin macro definition.  */
+
+void
+_cpp_restore_special_builtin (cpp_reader *pfile, struct def_pragma_macro *c)
+{
+  const struct builtin_macro *b;
+  size_t len = strlen (c->name);
+
+  for (b = builtin_array; b < builtin_array + ARRAY_SIZE (builtin_array); b++)
+    if (b->len == len && memcmp (c->name, b->name, len + 1) == 0)
+      {
+       cpp_hashnode *hp = cpp_lookup (pfile, b->name, b->len);
+       hp->type = NT_BUILTIN_MACRO;
+       if (b->always_warn_if_redefined)
+         hp->flags |= NODE_WARN;
+       hp->value.builtin = (enum cpp_builtin_type) b->value;
+      }
+}
+
 /* Read the builtins table above and enter them, and language-specific
    macros, into the hash table.  HOSTED is true if this is a hosted
    environment.  */
--- libcpp/directives.c.jj      2019-09-09 12:22:36.965261910 +0200
+++ libcpp/directives.c 2019-10-31 12:15:15.223780690 +0100
@@ -1582,6 +1582,8 @@ do_pragma_push_macro (cpp_reader *pfile)
   node = _cpp_lex_identifier (pfile, c->name);
   if (node->type == NT_VOID)
     c->is_undef = 1;
+  else if (node->type == NT_BUILTIN_MACRO)
+    c->is_builtin = 1;
   else
     {
       defn = cpp_macro_definition (pfile, node);
@@ -2470,6 +2472,11 @@ cpp_pop_definition (cpp_reader *pfile, s
 
   if (c->is_undef)
     return;
+  if (c->is_builtin)
+    {
+      _cpp_restore_special_builtin (pfile, c);
+      return;
+    }
 
   {
     size_t namelen;
--- gcc/testsuite/c-c++-common/cpp/pr92296-1.c.jj       2019-10-31 
12:45:41.975688125 +0100
+++ gcc/testsuite/c-c++-common/cpp/pr92296-1.c  2019-10-31 12:26:12.051664723 
+0100
@@ -0,0 +1,35 @@
+/* PR preprocessor/92296 */
+/* { dg-do preprocess } */
+
+#pragma push_macro("__TIMESTAMP__")
+#pragma pop_macro("__TIMESTAMP__")
+
+#pragma push_macro("__TIME__")
+#pragma pop_macro("__TIME__")
+
+#pragma push_macro("__DATE__")
+#pragma pop_macro("__DATE__")
+
+#pragma push_macro("__FILE__")
+#pragma pop_macro("__FILE__")
+
+#pragma push_macro("__BASE_FILE__")
+#pragma pop_macro("__BASE_FILE__")
+
+#pragma push_macro("__LINE__")
+#pragma pop_macro("__LINE__")
+
+#pragma push_macro("__INCLUDE_LEVEL__")
+#pragma pop_macro("__INCLUDE_LEVEL__")
+
+#pragma push_macro("__COUNTER__")
+#pragma pop_macro("__COUNTER__")
+
+#pragma push_macro("__has_attribute")
+#pragma pop_macro("__has_attribute")
+
+#pragma push_macro("__has_cpp_attribute")
+#pragma pop_macro("__has_cpp_attribute")
+
+#pragma push_macro("__has_builtin")
+#pragma pop_macro("__has_builtin")
--- gcc/testsuite/c-c++-common/cpp/pr92296-2.c.jj       2019-10-31 
12:45:45.081640352 +0100
+++ gcc/testsuite/c-c++-common/cpp/pr92296-2.c  2019-10-31 12:52:56.046011224 
+0100
@@ -0,0 +1,80 @@
+/* PR preprocessor/92296 */
+/* { dg-do preprocess } */
+/* { dg-options "-Wno-builtin-macro-redefined" } */
+
+#pragma push_macro("__TIMESTAMP__")
+#undef __TIMESTAMP__
+#define __TIMESTAMP__ "Thu Oct 31 12:00:00 2019"
+timestamp1 = __TIMESTAMP__
+#pragma pop_macro("__TIMESTAMP__")
+timestamp2 = __TIMESTAMP__
+
+#pragma push_macro("__TIME__")
+#undef __TIME__
+#define __TIME__ "12:00:00"
+time1 = __TIME__
+#pragma pop_macro("__TIME__")
+time2 = __TIME__
+
+#pragma push_macro("__DATE__")
+#undef __DATE__
+#define __DATE__ "Oct 31 2019"
+date1 = __DATE__
+#pragma pop_macro("__DATE__")
+date2 = __DATE__
+
+#pragma push_macro("__FILE__")
+#undef __FILE__
+#define __FILE__ "pr92296-3.c"
+file1 = __FILE__       /* { dg-final { scan-file pr92296-2.i "file1 = 
\"pr92296-3.c\"" } } */
+#pragma pop_macro("__FILE__")
+file2 = __FILE__       /* { dg-final { scan-file-not pr92296-2.i "file2 = 
\"pr92296-3.c\"" } } */
+
+#pragma push_macro("__BASE_FILE__")
+#undef __BASE_FILE__
+#define __BASE_FILE__ "pr92296-4.c"
+filebase1 = __BASE_FILE__      /* { dg-final { scan-file pr92296-2.i 
"filebase1 = \"pr92296-4.c\"" } } */
+#pragma pop_macro("__BASE_FILE__")
+filebase2 = __BASE_FILE__      /* { dg-final { scan-file-not pr92296-2.i 
"filebase2 = \"pr92296-4.c\"" } } */
+
+#pragma push_macro("__LINE__")
+#undef __LINE__                /* { dg-warning "undefining" } */
+#define __LINE__ 142
+line1 = __LINE__       /* { dg-final { scan-file pr92296-2.i "line1 = 142" } } 
*/
+#pragma pop_macro("__LINE__")
+line2 = __LINE__       /* { dg-final { scan-file pr92296-2.i "line2 = 45" } } 
*/
+
+#pragma push_macro("__INCLUDE_LEVEL__")
+#undef __INCLUDE_LEVEL__       /* { dg-warning "undefining" } */
+#define __INCLUDE_LEVEL__ 42
+includelevel1 = __INCLUDE_LEVEL__      /* { dg-final { scan-file pr92296-2.i 
"includelevel1 = 42" } } */
+#pragma pop_macro("__INCLUDE_LEVEL__")
+includelevel2 = __INCLUDE_LEVEL__      /* { dg-final { scan-file pr92296-2.i 
"includelevel2 = 0" } } */
+
+#pragma push_macro("__COUNTER__")
+#undef __COUNTER__     /* { dg-warning "undefining" } */
+#define __COUNTER__ 172
+counter1 = __COUNTER__ /* { dg-final { scan-file pr92296-2.i "counter1 = 172" 
} } */
+#pragma pop_macro("__COUNTER__")
+counter2 = __COUNTER__ /* { dg-final { scan-file-not pr92296-2.i "counter2 = 
172" } } */
+
+#pragma push_macro("__has_attribute")
+#undef __has_attribute /* { dg-warning "undefining" } */
+#define __has_attribute(x) 0
+hasattr1 = __has_attribute(noreturn)   /* { dg-final { scan-file pr92296-2.i 
"hasattr1 = 0" } } */
+#pragma pop_macro("__has_attribute")
+hasattr2 = __has_attribute(noreturn)   /* { dg-final { scan-file-not 
pr92296-2.i "hasattr2 = 0" } } */
+
+#pragma push_macro("__has_cpp_attribute")
+#undef __has_cpp_attribute     /* { dg-warning "undefining" } */
+#define __has_cpp_attribute(x) 0
+hasattrcpp1 = __has_cpp_attribute(noreturn)    /* { dg-final { scan-file 
pr92296-2.i "hasattrcpp1 = 0" } } */
+#pragma pop_macro("__has_cpp_attribute")
+hasattrcpp2 = __has_cpp_attribute(noreturn)    /* { dg-final { scan-file-not 
pr92296-2.i "hasattrcpp2 = 0" } } */
+
+#pragma push_macro("__has_builtin")
+#undef __has_builtin   /* { dg-warning "undefining" } */
+#define __has_builtin(x) 0
+hasbuiltin1 = __has_builtin(__builtin_expect)  /* { dg-final { scan-file 
pr92296-2.i "hasbuiltin1 = 0" } } */
+#pragma pop_macro("__has_builtin")
+hasbuiltin2 = __has_builtin(__builtin_expect)  /* { dg-final { scan-file 
pr92296-2.i "hasbuiltin2 = 1" } } */

        Jakub

Reply via email to