This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gomp] fix _Pragma


Memory management within libcpp is A Mystery.  The only thing I
tried that actually appears to work is to simply leak memory.
Fortunately, _Pragma doesn't happen very often, so I'm not 
terribly concerned about this.


r~


        PR preprocessor/25240
        * directives.c (run_directive): Remove pragma hacks.
        (destringize_and_run): Save tokens for deferred pragmas.
        * internal.h (_cpp_push_token_context): Declare.
        * macro.c (builtin_macro): Remove pragma token hack.
        (_cpp_push_token_context): Rename from push_token_context and export.

--- gcc/testsuite/gcc.dg/weak/weak-15.c	(revision 108858)
+++ gcc/testsuite/gcc.dg/weak/weak-15.c	(local)
@@ -0,0 +1,15 @@
+/* PR preprocessor/25240 */
+/* { dg-do compile } */
+/* { dg-require-weak "" } */
+/* { dg-options "-Werror" } */
+
+#define weak_extern(symbol) _weak_extern (weak symbol)
+#define _weak_extern(expr) _Pragma (#expr)
+extern void foo (void);
+weak_extern (foo)
+
+void bar (void)
+{
+  if (foo)
+    foo ();
+}
--- libcpp/directives.c	(revision 108858)
+++ libcpp/directives.c	(local)
@@ -487,9 +487,6 @@ run_directive (cpp_reader *pfile, int di
 {
   cpp_push_buffer (pfile, (const uchar *) buf, count,
 		   /* from_stage3 */ true);
-  /* Disgusting hack.  */
-  if (dir_no == T_PRAGMA && pfile->buffer->prev)
-    pfile->buffer->file = pfile->buffer->prev->file;
   start_directive (pfile);
 
   /* This is a short-term fix to prevent a leading '#' being
@@ -501,8 +498,6 @@ run_directive (cpp_reader *pfile, int di
     prepare_directive_trad (pfile);
   pfile->directive->handler (pfile);
   end_directive (pfile, 1);
-  if (dir_no == T_PRAGMA)
-    pfile->buffer->file = NULL;
   _cpp_pop_buffer (pfile);
 }
 
@@ -1466,6 +1461,11 @@ destringize_and_run (cpp_reader *pfile, 
 {
   const unsigned char *src, *limit;
   char *dest, *result;
+  cpp_context *saved_context;
+  cpp_token *saved_cur_token;
+  tokenrun *saved_cur_run;
+  cpp_token *toks;
+  int count;
 
   dest = result = (char *) alloca (in->len - 1);
   src = in->text + 1 + (in->text[0] == 'L');
@@ -1487,36 +1487,81 @@ destringize_and_run (cpp_reader *pfile, 
 
      Something like line-at-a-time lexing should remove the need for
      this.  */
-  {
-    cpp_context *saved_context = pfile->context;
-    cpp_token *saved_cur_token = pfile->cur_token;
-    tokenrun *saved_cur_run = pfile->cur_run;
-
-    pfile->context = XNEW (cpp_context);
-    pfile->context->macro = 0;
-    pfile->context->prev = 0;
-    run_directive (pfile, T_PRAGMA, result, dest - result);
-    XDELETE (pfile->context);
-    pfile->context = saved_context;
-    pfile->cur_token = saved_cur_token;
-    pfile->cur_run = saved_cur_run;
-  }
+  saved_context = pfile->context;
+  saved_cur_token = pfile->cur_token;
+  saved_cur_run = pfile->cur_run;
+
+  pfile->context = XNEW (cpp_context);
+  pfile->context->macro = 0;
+  pfile->context->prev = 0;
+
+  /* Inline run_directive, since we need to delay the _cpp_pop_buffer
+     until we've read all of the tokens that we want.  */
+  cpp_push_buffer (pfile, (const uchar *) result, dest - result,
+		   /* from_stage3 */ true);
+  /* ??? Antique Disgusting Hack.  What does this do?  */
+  if (pfile->buffer->prev)
+    pfile->buffer->file = pfile->buffer->prev->file;
+
+  start_directive (pfile);
+  _cpp_clean_line (pfile);
+  do_pragma (pfile);
+  end_directive (pfile, 1);
 
-  /* See above comment.  For the moment, we'd like
+  /* We always insert at least one token, the directive result.  It'll
+     either be a CPP_PADDING or a CPP_PRAGMA.  In the later case, we 
+     need to insert *all* of the tokens, including the CPP_PRAGMA_EOL.  */
+
+  /* If we're not handling the pragma internally, read all of the tokens from
+     the string buffer now, while the string buffer is still installed.  */
+  /* ??? Note that the token buffer allocated here is leaked.  It's not clear
+     to me what the true lifespan of the tokens are.  It would appear that
+     the lifespan is the entire parse of the main input stream, in which case
+     this may not be wrong.  */
+  if (pfile->directive_result.type == CPP_PRAGMA)
+    {
+      int maxcount;
+
+      count = 1;
+      maxcount = 50;
+      toks = XNEWVEC (cpp_token, maxcount);
+      toks[0] = pfile->directive_result;
 
-     token1 _Pragma ("foo") token2
+      do
+	{
+	  if (count == maxcount)
+	    {
+	      maxcount = maxcount * 3 / 2;
+	      toks = XRESIZEVEC (cpp_token, toks, maxcount);
+	    }
+	  toks[count++] = *cpp_get_token (pfile);
+	}
+      while (toks[count-1].type != CPP_PRAGMA_EOL);
+    }
+  else
+    {
+      count = 1;
+      toks = XNEW (cpp_token);
+      toks[0] = pfile->directive_result;
+
+      /* If we handled the entire pragma internally, make sure we get the
+	 line number correct for the next token.  */
+      if (pfile->cb.line_change)
+	pfile->cb.line_change (pfile, pfile->cur_token, false);
+    }
 
-     to be output as
+  /* Finish inlining run_directive.  */
+  pfile->buffer->file = NULL;
+  _cpp_pop_buffer (pfile);
 
-		token1
-		# 7 "file.c"
-		#pragma foo
-		# 7 "file.c"
-			       token2
+  /* Reset the old macro state before ...  */
+  XDELETE (pfile->context);
+  pfile->context = saved_context;
+  pfile->cur_token = saved_cur_token;
+  pfile->cur_run = saved_cur_run;
 
-      Getting the line markers is a little tricky.  */
-  if (pfile->cb.line_change)
-    pfile->cb.line_change (pfile, pfile->cur_token, false);
+  /* ... inserting the new tokens we collected.  */
+  _cpp_push_token_context (pfile, NULL, toks, count);
 }
 
 /* Handle the _Pragma operator.  */
--- libcpp/internal.h	(revision 108858)
+++ libcpp/internal.h	(local)
@@ -499,7 +499,10 @@ extern bool _cpp_arguments_ok (cpp_reade
 			       unsigned int);
 extern const unsigned char *_cpp_builtin_macro_text (cpp_reader *,
 						     cpp_hashnode *);
-int _cpp_warn_if_unused_macro (cpp_reader *, cpp_hashnode *, void *);
+extern int _cpp_warn_if_unused_macro (cpp_reader *, cpp_hashnode *, void *);
+extern void _cpp_push_token_context (cpp_reader *, cpp_hashnode *,
+				     const cpp_token *, unsigned int);
+
 /* In identifiers.c */
 extern void _cpp_init_hashtable (cpp_reader *, hash_table *);
 extern void _cpp_destroy_hashtable (cpp_reader *);
--- libcpp/macro.c	(revision 108858)
+++ libcpp/macro.c	(local)
@@ -42,8 +42,6 @@ struct macro_arg
 
 static int enter_macro_context (cpp_reader *, cpp_hashnode *);
 static int builtin_macro (cpp_reader *, cpp_hashnode *);
-static void push_token_context (cpp_reader *, cpp_hashnode *,
-				const cpp_token *, unsigned int);
 static void push_ptoken_context (cpp_reader *, cpp_hashnode *, _cpp_buff *,
 				 const cpp_token **, unsigned int);
 static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *);
@@ -261,13 +259,6 @@ builtin_macro (cpp_reader *pfile, cpp_ha
 	return 0;
 
       _cpp_do__Pragma (pfile);
-      if (pfile->directive_result.type == CPP_PRAGMA) 
-	{
-	  cpp_token *tok = _cpp_temp_token (pfile);
-	  *tok = pfile->directive_result;
-	  push_token_context (pfile, NULL, tok, 1);
-	}
-
       return 1;
     }
 
@@ -282,7 +273,7 @@ builtin_macro (cpp_reader *pfile, cpp_ha
 
   /* Set pfile->cur_token as required by _cpp_lex_direct.  */
   pfile->cur_token = _cpp_temp_token (pfile);
-  push_token_context (pfile, NULL, _cpp_lex_direct (pfile), 1);
+  _cpp_push_token_context (pfile, NULL, _cpp_lex_direct (pfile), 1);
   if (pfile->buffer->cur != pfile->buffer->rlimit)
     cpp_error (pfile, CPP_DL_ICE, "invalid built-in macro \"%s\"",
 	       NODE_NAME (node));
@@ -480,7 +471,7 @@ paste_all_tokens (cpp_reader *pfile, con
   while (rhs->flags & PASTE_LEFT);
 
   /* Put the resulting token in its own context.  */
-  push_token_context (pfile, NULL, lhs, 1);
+  _cpp_push_token_context (pfile, NULL, lhs, 1);
 }
 
 /* Returns TRUE if the number of arguments ARGC supplied in an
@@ -694,7 +685,7 @@ funlike_invocation_p (cpp_reader *pfile,
 	 too difficult.  We re-insert it in its own context.  */
       _cpp_backup_tokens (pfile, 1);
       if (padding)
-	push_token_context (pfile, NULL, padding, 1);
+	_cpp_push_token_context (pfile, NULL, padding, 1);
     }
 
   return NULL;
@@ -750,7 +741,7 @@ enter_macro_context (cpp_reader *pfile, 
       macro->used = 1;
 
       if (macro->paramc == 0)
-	push_token_context (pfile, node, macro->exp.tokens, macro->count);
+	_cpp_push_token_context (pfile, node, macro->exp.tokens, macro->count);
 
       return 1;
     }
@@ -943,9 +934,9 @@ push_ptoken_context (cpp_reader *pfile, 
 }
 
 /* Push a list of tokens.  */
-static void
-push_token_context (cpp_reader *pfile, cpp_hashnode *macro,
-		    const cpp_token *first, unsigned int count)
+void
+_cpp_push_token_context (cpp_reader *pfile, cpp_hashnode *macro,
+			 const cpp_token *first, unsigned int count)
 {
   cpp_context *context = next_context (pfile);
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]