Fix libcpp #pragma {push,pop}_macro handling of builtin macros (PR preprocessor/92296)
diff mbox series

Message ID 20191031171719.GN4650@tucnak
State New
Headers show
Series
  • Fix libcpp #pragma {push,pop}_macro handling of builtin macros (PR preprocessor/92296)
Related show

Commit Message

Jakub Jelinek Oct. 31, 2019, 5:17 p.m. UTC
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  <jakub@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.


	Jakub

Comments

Nathan Sidwell Oct. 31, 2019, 5:32 p.m. UTC | #1
On 10/31/19 1:17 PM, Jakub Jelinek wrote:
> 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

ew, that;s unfortunate.
> 
> 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.

ok, a nit:

> +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++)

could you write as ...?
    for (const builtin_macro *b = ...

nathan
Joseph Myers Oct. 31, 2019, 8:32 p.m. UTC | #2
On Thu, 31 Oct 2019, Jakub Jelinek wrote:

> Hi!
> 
> Seems libcpp has been ICEing on push_macro of a builtin macro since 2010,

In fact, we have both bug 69665 and bug 87181 for that.

Patch
diff mbox series

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