OSDN Git Service

* Makefile.tpl ([+compare-target+]): Compare all stage
[pf3gnuchains/gcc-fork.git] / gcc / c-pragma.c
index 6e4043a..751c895 100644 (file)
@@ -43,8 +43,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_BAD2(gmsgid, arg) \
   do { warning (OPT_Wpragmas, gmsgid, arg); return; } while (0)
 
-typedef struct align_stack GTY(())
-{
+typedef struct GTY(()) align_stack {
   int                 alignment;
   tree                id;
   struct align_stack * prev;
@@ -113,8 +112,8 @@ pop_alignment (tree id)
          }
       if (entry == NULL)
        warning (OPT_Wpragmas, "\
-#pragma pack(pop, %s) encountered without matching #pragma pack(push, %s)"
-                , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
+#pragma pack(pop, %E) encountered without matching #pragma pack(push, %E)"
+                , id, id);
     }
 
   entry = alignment_stack->prev;
@@ -180,7 +179,7 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
       else if (!strcmp (op, "pop"))
        action = pop;
       else
-       GCC_BAD2 ("unknown action %qs for %<#pragma pack%> - ignored", op);
+       GCC_BAD2 ("unknown action %qE for %<#pragma pack%> - ignored", x);
 
       while ((token = pragma_lex (&x)) == CPP_COMMA)
        {
@@ -244,14 +243,12 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
 }
 #endif  /* HANDLE_PRAGMA_PACK */
 
-struct def_pragma_macro_value GTY(())
-{
+struct GTY(()) def_pragma_macro_value {
   struct def_pragma_macro_value *prev;
   cpp_macro *value;
 };
 
-struct def_pragma_macro GTY(())
-{
+struct GTY(()) def_pragma_macro {
   hashval_t hash;
   const char *name;
   struct def_pragma_macro_value value;
@@ -866,15 +863,11 @@ handle_pragma_diagnostic(cpp_reader *ARG_UNUSED(dummy))
   GCC_BAD ("unknown option after %<#pragma GCC diagnostic%> kind");
 }
 
-/* Stack of the #pragma GCC options created with #pragma GCC option push.  */
-static GTY(()) VEC(tree,gc) *option_stack;
-
-/*  Parse #pragma GCC option (xxx) to set target specific options.  */
+/*  Parse #pragma GCC target (xxx) to set target specific options.  */
 static void
-handle_pragma_option(cpp_reader *ARG_UNUSED(dummy))
+handle_pragma_target(cpp_reader *ARG_UNUSED(dummy))
 {
   enum cpp_ttype token;
-  const char *name;
   tree x;
   bool close_paren_needed_p = false;
 
@@ -884,12 +877,6 @@ handle_pragma_option(cpp_reader *ARG_UNUSED(dummy))
       return;
     }
 
-  if (!targetm.target_option.pragma_parse)
-    {
-      error ("#pragma GCC option is not supported for this system");
-      return;
-    }
-
   token = pragma_lex (&x);
   if (token == CPP_OPEN_PAREN)
     {
@@ -897,76 +884,9 @@ handle_pragma_option(cpp_reader *ARG_UNUSED(dummy))
       token = pragma_lex (&x);
     }
 
-  if (token == CPP_NAME)
-    {
-      bool call_pragma_parse_p = false;
-      bool ok_p;
-
-      name = IDENTIFIER_POINTER (x);
-      if (strcmp (name, "reset") == 0)
-       {
-         current_option_pragma = NULL_TREE;
-         call_pragma_parse_p = true;
-       }
-
-      else if (strcmp (name, "push") == 0)
-       VEC_safe_push (tree, gc, option_stack,
-                      copy_list (current_option_pragma));
-
-      else if (strcmp (name, "pop") == 0)
-       {
-         int len = VEC_length (tree, option_stack);
-         if (len == 0)
-           {
-             GCC_BAD ("%<#pragma GCC option pop%> without a %<#pragma GCC "
-                      "option push%>");
-             return;
-           }
-         else
-           {
-             VEC_truncate (tree, option_stack, len-1);
-             current_option_pragma = ((len > 1)
-                                      ? VEC_last (tree, option_stack)
-                                      : NULL_TREE);
-
-             call_pragma_parse_p = true;
-           }
-       }
-
-      else
-       {
-         GCC_BAD ("%<#pragma GCC option%> is not a string or "
-                  "push/pop/reset");
-         return;
-       }
-
-      token = pragma_lex (&x);
-      if (close_paren_needed_p)
-       {
-         if (token == CPP_CLOSE_PAREN)
-           token = pragma_lex (&x);
-         else
-           GCC_BAD ("%<#pragma GCC option ([push|pop|reset])%> does not "
-                    "have a final %<)%>.");
-       }
-
-      if (token != CPP_EOF)
-       {
-         GCC_BAD ("%<#pragma GCC option [push|pop|reset]%> is badly "
-                  "formed");
-         return;
-       }
-
-      /* See if we need to call the pragma_parse hook.  This must occur at the
-        end after processing all of the tokens, or we may get spurious errors
-        when we define or undef macros.  */
-      ok_p = targetm.target_option.pragma_parse (current_option_pragma);
-      gcc_assert (ok_p);
-    }
-
-  else if (token != CPP_STRING)
+  if (token != CPP_STRING)
     {
-      GCC_BAD ("%<#pragma GCC option%> is not a string or push/pop/reset");
+      GCC_BAD ("%<#pragma GCC option%> is not a string");
       return;
     }
 
@@ -993,34 +913,29 @@ handle_pragma_option(cpp_reader *ARG_UNUSED(dummy))
          if (token == CPP_CLOSE_PAREN)
            token = pragma_lex (&x);
          else
-           GCC_BAD ("%<#pragma GCC option (string [,string]...)%> does "
+           GCC_BAD ("%<#pragma GCC target (string [,string]...)%> does "
                     "not have a final %<)%>.");
        }
 
       if (token != CPP_EOF)
        {
-         error ("#pragma GCC option string... is badly formed");
+         error ("#pragma GCC target string... is badly formed");
          return;
        }
 
       /* put arguments in the order the user typed them.  */
       args = nreverse (args);
 
-      if (targetm.target_option.pragma_parse (args))
-       current_option_pragma = args;
+      if (targetm.target_option.pragma_parse (args, NULL_TREE))
+       current_target_pragma = args;
     }
 }
 
-/* Stack of the #pragma GCC optimize options created with #pragma GCC optimize
-   push.  */
-static GTY(()) VEC(tree,gc) *optimize_stack;
-
 /* Handle #pragma GCC optimize to set optimization options.  */
 static void
-handle_pragma_optimize(cpp_reader *ARG_UNUSED(dummy))
+handle_pragma_optimize (cpp_reader *ARG_UNUSED(dummy))
 {
   enum cpp_ttype token;
-  const char *name;
   tree x;
   bool close_paren_needed_p = false;
   tree optimization_previous_node = optimization_current_node;
@@ -1038,95 +953,9 @@ handle_pragma_optimize(cpp_reader *ARG_UNUSED(dummy))
       token = pragma_lex (&x);
     }
 
-  if (token == CPP_NAME)
-    {
-      bool call_opt_p = false;
-
-      name = IDENTIFIER_POINTER (x);
-      if (strcmp (name, "reset") == 0)
-       {
-         struct cl_optimization *def
-           = TREE_OPTIMIZATION (optimization_default_node);
-         current_optimize_pragma = NULL_TREE;
-         optimization_current_node = optimization_default_node;
-         cl_optimization_restore (def);
-         call_opt_p = true;
-       }
-
-      else if (strcmp (name, "push") == 0)
-       VEC_safe_push (tree, gc, optimize_stack, current_optimize_pragma);
-
-      else if (strcmp (name, "pop") == 0)
-       {
-         int len = VEC_length (tree, optimize_stack);
-         if (len == 0)
-           {
-             GCC_BAD ("%<#pragma GCC optimize pop%> without a %<#pragma "
-                      "GCC optimize push%>");
-             return;
-           }
-         else
-           {
-             VEC_truncate (tree, optimize_stack, len-1);
-             current_optimize_pragma
-               = ((len > 1)
-                  ? VEC_last (tree, optimize_stack)
-                  : NULL_TREE);
-
-             call_opt_p = true;
-             if (current_optimize_pragma)
-               {
-                 bool ok_p
-                   = parse_optimize_options (current_optimize_pragma, false);
-                 gcc_assert (ok_p);    /* should be parsed previously.  */
-                 optimization_current_node = build_optimization_node ();
-               }
-             else
-               {
-                 struct cl_optimization *opt
-                   = TREE_OPTIMIZATION (optimization_default_node);
-                 optimization_current_node = optimization_default_node;
-                 cl_optimization_restore (opt);
-               }
-           }
-       }
-
-      else
-       {
-         GCC_BAD ("%<#pragma GCC optimize%> is not a string or "
-                  "push/pop/reset");
-         return;
-       }
-
-      token = pragma_lex (&x);
-      if (close_paren_needed_p)
-       {
-         if (token == CPP_CLOSE_PAREN)
-           token = pragma_lex (&x);
-         else
-           GCC_BAD ("%<#pragma GCC optimize ([push|pop|reset])%> does not "
-                    "have a final %<)%>.");
-       }
-
-      if (token != CPP_EOF)
-       {
-         GCC_BAD ("%<#pragma GCC optimize [push|pop|reset]%> is badly "
-                  "formed");
-         return;
-       }
-
-      if (call_opt_p &&
-         (optimization_previous_node != optimization_current_node))
-       c_cpp_builtins_optimize_pragma (parse_in,
-                                       optimization_previous_node,
-                                       optimization_current_node);
-
-    }
-
-  else if (token != CPP_STRING && token != CPP_NUMBER)
+  if (token != CPP_STRING && token != CPP_NUMBER)
     {
-      GCC_BAD ("%<#pragma GCC optimize%> is not a string, number, or "
-              "push/pop/reset");
+      GCC_BAD ("%<#pragma GCC optimize%> is not a string or number");
       return;
     }
 
@@ -1166,6 +995,7 @@ handle_pragma_optimize(cpp_reader *ARG_UNUSED(dummy))
       args = nreverse (args);
 
       parse_optimize_options (args, false);
+      current_optimize_pragma = chainon (current_optimize_pragma, args);
       optimization_current_node = build_optimization_node ();
       c_cpp_builtins_optimize_pragma (parse_in,
                                      optimization_previous_node,
@@ -1173,6 +1003,275 @@ handle_pragma_optimize(cpp_reader *ARG_UNUSED(dummy))
     }
 }
 
+/* Stack of the #pragma GCC options created with #pragma GCC push_option.  Save
+   both the binary representation of the options and the TREE_LIST of
+   strings that will be added to the function's attribute list.  */
+typedef struct GTY(()) opt_stack {
+  struct opt_stack *prev;
+  tree target_binary;
+  tree target_strings;
+  tree optimize_binary;
+  tree optimize_strings;
+} opt_stack;
+
+static GTY(()) struct opt_stack * options_stack;
+
+/* Handle #pragma GCC push_options to save the current target and optimization
+   options.  */
+
+static void
+handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy))
+{
+  enum cpp_ttype token;
+  tree x = 0;
+  opt_stack *p;
+
+  token = pragma_lex (&x);
+  if (token != CPP_EOF)
+    {
+      warning (OPT_Wpragmas, "junk at end of %<#pragma push_options%>");
+      return;
+    }
+
+  p = GGC_NEW (opt_stack);
+  p->prev = options_stack;
+  options_stack = p;
+
+  /* Save optimization and target flags in binary format.  */
+  p->optimize_binary = build_optimization_node ();
+  p->target_binary = build_target_option_node ();
+
+  /* Save optimization and target flags in string list format.  */
+  p->optimize_strings = copy_list (current_optimize_pragma);
+  p->target_strings = copy_list (current_target_pragma);
+}
+
+/* Handle #pragma GCC pop_options to restore the current target and
+   optimization options from a previous push_options.  */
+
+static void
+handle_pragma_pop_options (cpp_reader *ARG_UNUSED(dummy))
+{
+  enum cpp_ttype token;
+  tree x = 0;
+  opt_stack *p;
+
+  token = pragma_lex (&x);
+  if (token != CPP_EOF)
+    {
+      warning (OPT_Wpragmas, "junk at end of %<#pragma pop_options%>");
+      return;
+    }
+
+  if (! options_stack)
+    {
+      warning (OPT_Wpragmas,
+              "%<#pragma GCC pop_options%> without a corresponding "
+              "%<#pragma GCC push_options%>");
+      return;
+    }
+
+  p = options_stack;
+  options_stack = p->prev;
+
+  if (p->target_binary != target_option_current_node)
+    {
+      (void) targetm.target_option.pragma_parse (NULL_TREE, p->target_binary);
+      target_option_current_node = p->target_binary;
+    }
+
+  if (p->optimize_binary != optimization_current_node)
+    {
+      tree old_optimize = optimization_current_node;
+      cl_optimization_restore (TREE_OPTIMIZATION (p->optimize_binary));
+      c_cpp_builtins_optimize_pragma (parse_in, old_optimize,
+                                     p->optimize_binary);
+      optimization_current_node = p->optimize_binary;
+    }
+
+  current_target_pragma = p->target_strings;
+  current_optimize_pragma = p->optimize_strings;
+}
+
+/* Handle #pragma GCC reset_options to restore the current target and
+   optimization options to the original options used on the command line.  */
+
+static void
+handle_pragma_reset_options (cpp_reader *ARG_UNUSED(dummy))
+{
+  enum cpp_ttype token;
+  tree x = 0;
+  tree new_optimize = optimization_default_node;
+  tree new_target = target_option_default_node;
+
+  token = pragma_lex (&x);
+  if (token != CPP_EOF)
+    {
+      warning (OPT_Wpragmas, "junk at end of %<#pragma reset_options%>");
+      return;
+    }
+
+  if (new_target != target_option_current_node)
+    {
+      (void) targetm.target_option.pragma_parse (NULL_TREE, new_target);
+      target_option_current_node = new_target;
+    }
+
+  if (new_optimize != optimization_current_node)
+    {
+      tree old_optimize = optimization_current_node;
+      cl_optimization_restore (TREE_OPTIMIZATION (new_optimize));
+      c_cpp_builtins_optimize_pragma (parse_in, old_optimize, new_optimize);
+      optimization_current_node = new_optimize;
+    }
+
+  current_target_pragma = NULL_TREE;
+  current_optimize_pragma = NULL_TREE;
+}
+
+/* Print a plain user-specified message.  */
+
+static void
+handle_pragma_message (cpp_reader *ARG_UNUSED(dummy))
+{
+  enum cpp_ttype token;
+  tree x, message = 0;
+
+  token = pragma_lex (&x);
+  if (token == CPP_OPEN_PAREN)
+    {
+      token = pragma_lex (&x);
+      if (token == CPP_STRING)
+        message = x;
+      else
+        GCC_BAD ("expected a string after %<#pragma message%>");
+      if (pragma_lex (&x) != CPP_CLOSE_PAREN)
+        GCC_BAD ("malformed %<#pragma message%>, ignored");
+    }
+  else if (token == CPP_STRING)
+    message = x;
+  else
+    GCC_BAD ("expected a string after %<#pragma message%>");
+
+  gcc_assert (message);
+
+  if (pragma_lex (&x) != CPP_EOF)
+    warning (OPT_Wpragmas, "junk at end of %<#pragma message%>");
+
+  if (TREE_STRING_LENGTH (message) > 1)
+    inform (input_location, "#pragma message: %s", TREE_STRING_POINTER (message));
+}
+
+/* Mark whether the current location is valid for a STDC pragma.  */
+
+static bool valid_location_for_stdc_pragma;
+
+void
+mark_valid_location_for_stdc_pragma (bool flag)
+{
+  valid_location_for_stdc_pragma = flag;
+}
+
+/* Return true if the current location is valid for a STDC pragma.  */
+
+bool
+valid_location_for_stdc_pragma_p (void)
+{
+  return valid_location_for_stdc_pragma;
+}
+
+enum pragma_switch_t { PRAGMA_ON, PRAGMA_OFF, PRAGMA_DEFAULT, PRAGMA_BAD };
+
+/* A STDC pragma must appear outside of external declarations or
+   preceding all explicit declarations and statements inside a compound
+   statement; its behavior is undefined if used in any other context.
+   It takes a switch of ON, OFF, or DEFAULT.  */
+
+static enum pragma_switch_t
+handle_stdc_pragma (const char *pname)
+{
+  const char *arg;
+  tree t;
+  enum pragma_switch_t ret;
+
+  if (!valid_location_for_stdc_pragma_p ())
+    {
+      warning (OPT_Wpragmas, "invalid location for %<pragma %s%>, ignored",
+              pname);
+      return PRAGMA_BAD;
+    }
+
+  if (pragma_lex (&t) != CPP_NAME)
+    {
+      warning (OPT_Wpragmas, "malformed %<#pragma %s%>, ignored", pname);
+      return PRAGMA_BAD;
+    }
+
+  arg = IDENTIFIER_POINTER (t);
+
+  if (!strcmp (arg, "ON"))
+    ret = PRAGMA_ON;
+  else if (!strcmp (arg, "OFF"))
+    ret = PRAGMA_OFF;
+  else if (!strcmp (arg, "DEFAULT"))
+    ret = PRAGMA_DEFAULT;
+  else
+    {
+      warning (OPT_Wpragmas, "malformed %<#pragma %s%>, ignored", pname);
+      return PRAGMA_BAD;
+    }
+
+  if (pragma_lex (&t) != CPP_EOF)
+    {
+      warning (OPT_Wpragmas, "junk at end of %<#pragma %s%>", pname);
+      return PRAGMA_BAD;
+    }
+
+  return ret;
+}
+
+/* #pragma STDC FLOAT_CONST_DECIMAL64 ON
+   #pragma STDC FLOAT_CONST_DECIMAL64 OFF
+   #pragma STDC FLOAT_CONST_DECIMAL64 DEFAULT */
+
+static void
+handle_pragma_float_const_decimal64 (cpp_reader *ARG_UNUSED (dummy))
+{
+  if (c_dialect_cxx ())
+    {
+      if (warn_unknown_pragmas > in_system_header)
+       warning (OPT_Wunknown_pragmas,
+                "%<#pragma STDC FLOAT_CONST_DECIMAL64%> is not supported"
+                " for C++");
+      return;
+    }
+
+  if (!targetm.decimal_float_supported_p ())
+    {
+      if (warn_unknown_pragmas > in_system_header)
+       warning (OPT_Wunknown_pragmas,
+                "%<#pragma STDC FLOAT_CONST_DECIMAL64%> is not supported"
+                " on this target");
+      return;
+    }
+
+  pedwarn (input_location, OPT_pedantic,
+          "ISO C does not support %<#pragma STDC FLOAT_CONST_DECIMAL64%>");
+
+  switch (handle_stdc_pragma ("STDC FLOAT_CONST_DECIMAL64"))
+    {
+    case PRAGMA_ON:
+      set_float_const_decimal64 ();
+      break;
+    case PRAGMA_OFF:
+    case PRAGMA_DEFAULT:
+      clear_float_const_decimal64 ();
+      break;
+    case PRAGMA_BAD:
+      break;
+    }
+}
+
 /* A vector of registered pragma callbacks.  */
 
 DEF_VEC_O (pragma_handler);
@@ -1335,12 +1434,20 @@ init_pragma (void)
 #endif
 
   c_register_pragma ("GCC", "diagnostic", handle_pragma_diagnostic);
-  c_register_pragma ("GCC", "option", handle_pragma_option);
+  c_register_pragma ("GCC", "target", handle_pragma_target);
   c_register_pragma ("GCC", "optimize", handle_pragma_optimize);
+  c_register_pragma ("GCC", "push_options", handle_pragma_push_options);
+  c_register_pragma ("GCC", "pop_options", handle_pragma_pop_options);
+  c_register_pragma ("GCC", "reset_options", handle_pragma_reset_options);
+
+  c_register_pragma ("STDC", "FLOAT_CONST_DECIMAL64",
+                    handle_pragma_float_const_decimal64);
 
   c_register_pragma_with_expansion (0, "redefine_extname", handle_pragma_redefine_extname);
   c_register_pragma (0, "extern_prefix", handle_pragma_extern_prefix);
 
+  c_register_pragma_with_expansion (0, "message", handle_pragma_message);
+
 #ifdef REGISTER_TARGET_PRAGMAS
   REGISTER_TARGET_PRAGMAS ();
 #endif