#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;
}
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;
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)
{
}
#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;
static int
dpm_eq (const void *pa, const void *pb)
{
- const struct def_pragma_macro *a = pa, *b = pb;
+ const struct def_pragma_macro *const a = (const struct def_pragma_macro *) pa,
+ *const b = (const struct def_pragma_macro *) pb;
return a->hash == b->hash && strcmp (a->name, b->name) == 0;
}
dummy.name = macroname;
slot = htab_find_slot_with_hash (pushed_macro_table, &dummy,
dummy.hash, INSERT);
- c = *slot;
+ c = (struct def_pragma_macro *) *slot;
if (c == NULL)
{
- *slot = c = ggc_alloc (sizeof (struct def_pragma_macro));
+ *slot = c = GGC_NEW (struct def_pragma_macro);
c->hash = dummy.hash;
c->name = ggc_alloc_string (macroname, TREE_STRING_LENGTH (id) - 1);
c->value.prev = NULL;
else
{
struct def_pragma_macro_value *v;
- v = ggc_alloc (sizeof (struct def_pragma_macro_value));
+ v = GGC_NEW (struct def_pragma_macro_value);
*v = c->value;
c->value.prev = v;
}
dummy.hash, NO_INSERT);
if (slot == NULL)
return;
- c = *slot;
+ c = (struct def_pragma_macro *) *slot;
cpp_pop_definition (reader, c->name, c->value.value);
if (TREE_VALUE (t) == NULL)
continue;
- decl = build_decl (FUNCTION_DECL, alias_id, default_function_type);
+ decl = build_decl (UNKNOWN_LOCATION,
+ FUNCTION_DECL, alias_id, default_function_type);
DECL_ARTIFICIAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
GCC_BAD ("unknown option after %<#pragma GCC diagnostic%> kind");
}
+/* Parse #pragma GCC target (xxx) to set target specific options. */
+static void
+handle_pragma_target(cpp_reader *ARG_UNUSED(dummy))
+{
+ enum cpp_ttype token;
+ tree x;
+ bool close_paren_needed_p = false;
+
+ if (cfun)
+ {
+ error ("#pragma GCC option is not allowed inside functions");
+ return;
+ }
+
+ token = pragma_lex (&x);
+ if (token == CPP_OPEN_PAREN)
+ {
+ close_paren_needed_p = true;
+ token = pragma_lex (&x);
+ }
+
+ if (token != CPP_STRING)
+ {
+ GCC_BAD ("%<#pragma GCC option%> is not a string");
+ return;
+ }
+
+ /* Strings are user options. */
+ else
+ {
+ tree args = NULL_TREE;
+
+ do
+ {
+ /* Build up the strings now as a tree linked list. Skip empty
+ strings. */
+ if (TREE_STRING_LENGTH (x) > 0)
+ args = tree_cons (NULL_TREE, x, args);
+
+ token = pragma_lex (&x);
+ while (token == CPP_COMMA)
+ token = pragma_lex (&x);
+ }
+ while (token == CPP_STRING);
+
+ if (close_paren_needed_p)
+ {
+ if (token == CPP_CLOSE_PAREN)
+ token = pragma_lex (&x);
+ else
+ GCC_BAD ("%<#pragma GCC target (string [,string]...)%> does "
+ "not have a final %<)%>.");
+ }
+
+ if (token != CPP_EOF)
+ {
+ 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, NULL_TREE))
+ current_target_pragma = args;
+ }
+}
+
+/* Handle #pragma GCC optimize to set optimization options. */
+static void
+handle_pragma_optimize (cpp_reader *ARG_UNUSED(dummy))
+{
+ enum cpp_ttype token;
+ tree x;
+ bool close_paren_needed_p = false;
+ tree optimization_previous_node = optimization_current_node;
+
+ if (cfun)
+ {
+ error ("#pragma GCC optimize is not allowed inside functions");
+ return;
+ }
+
+ token = pragma_lex (&x);
+ if (token == CPP_OPEN_PAREN)
+ {
+ close_paren_needed_p = true;
+ token = pragma_lex (&x);
+ }
+
+ if (token != CPP_STRING && token != CPP_NUMBER)
+ {
+ GCC_BAD ("%<#pragma GCC optimize%> is not a string or number");
+ return;
+ }
+
+ /* Strings/numbers are user options. */
+ else
+ {
+ tree args = NULL_TREE;
+
+ do
+ {
+ /* Build up the numbers/strings now as a list. */
+ if (token != CPP_STRING || TREE_STRING_LENGTH (x) > 0)
+ args = tree_cons (NULL_TREE, x, args);
+
+ token = pragma_lex (&x);
+ while (token == CPP_COMMA)
+ token = pragma_lex (&x);
+ }
+ while (token == CPP_STRING || token == CPP_NUMBER);
+
+ if (close_paren_needed_p)
+ {
+ if (token == CPP_CLOSE_PAREN)
+ token = pragma_lex (&x);
+ else
+ GCC_BAD ("%<#pragma GCC optimize (string [,string]...)%> does "
+ "not have a final %<)%>.");
+ }
+
+ if (token != CPP_EOF)
+ {
+ error ("#pragma GCC optimize string... is badly formed");
+ return;
+ }
+
+ /* put arguments in the order the user typed them. */
+ 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,
+ optimization_current_node);
+ }
+}
+
+/* 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);
{ "section", PRAGMA_OMP_SECTION },
{ "sections", PRAGMA_OMP_SECTIONS },
{ "single", PRAGMA_OMP_SINGLE },
+ { "task", PRAGMA_OMP_TASK },
+ { "taskwait", PRAGMA_OMP_TASKWAIT },
{ "threadprivate", PRAGMA_OMP_THREADPRIVATE }
};
#endif
c_register_pragma ("GCC", "diagnostic", handle_pragma_diagnostic);
+ 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