/* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack.
- Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 1992-2019 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-#include "tree.h"
-#include "function.h" /* For cfun. FIXME: Does the parser know
- when it is inside a function, so that
- we don't have to look at cfun? */
-#include "cpplib.h"
-#include "c-pragma.h"
-#include "flags.h"
-#include "c-common.h"
-#include "output.h"
-#include "tm_p.h" /* For REGISTER_TARGET_PRAGMAS (why is
- this not a target hook?). */
-#include "vec.h"
-#include "vecprim.h"
#include "target.h"
+#include "function.h" /* For cfun. */
+#include "c-common.h"
+#include "memmodel.h"
+#include "tm_p.h" /* For REGISTER_TARGET_PRAGMAS. */
+#include "stringpool.h"
+#include "cgraph.h"
#include "diagnostic.h"
+#include "attribs.h"
+#include "varasm.h"
+#include "c-pragma.h"
#include "opts.h"
#include "plugin.h"
#define GCC_BAD2(gmsgid, arg) \
do { warning (OPT_Wpragmas, gmsgid, arg); return; } while (0)
-typedef struct GTY(()) align_stack {
+struct GTY(()) align_stack {
int alignment;
tree id;
struct align_stack * prev;
-} align_stack;
+};
static GTY(()) struct align_stack * alignment_stack;
static void
push_alignment (int alignment, tree id)
{
- align_stack * entry;
-
- entry = ggc_alloc_align_stack ();
+ align_stack * entry = ggc_alloc<align_stack> ();
entry->alignment = alignment;
entry->id = id;
warning (OPT_Wpragmas, "junk at end of %<#pragma pack%>");
if (flag_pack_struct)
- GCC_BAD ("#pragma pack has no effect with -fpack-struct - ignored");
+ GCC_BAD ("#pragma pack has no effect with %<-fpack-struct%> - ignored");
if (action != pop)
switch (align)
align = maximum_field_alignment;
break;
}
+ /* FALLTHRU */
default:
GCC_BAD2 ("alignment must be a small power of two, not %d", align);
}
}
}
-typedef struct GTY(()) pending_weak_d
+struct GTY(()) pending_weak
{
tree name;
tree value;
-} pending_weak;
+};
-DEF_VEC_O(pending_weak);
-DEF_VEC_ALLOC_O(pending_weak,gc);
-static GTY(()) VEC(pending_weak,gc) *pending_weaks;
+static GTY(()) vec<pending_weak, va_gc> *pending_weaks;
static void apply_pragma_weak (tree, tree);
static void handle_pragma_weak (cpp_reader *);
if (SUPPORTS_WEAK && DECL_EXTERNAL (decl) && TREE_USED (decl)
&& !DECL_WEAK (decl) /* Don't complain about a redundant #pragma. */
+ && DECL_ASSEMBLER_NAME_SET_P (decl)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
warning (OPT_Wpragmas, "applying #pragma weak %q+D after first use "
"results in unspecified behavior", decl);
/* Avoid asking for DECL_ASSEMBLER_NAME when it's not needed. */
/* No weak symbols pending, take the short-cut. */
- if (!pending_weaks)
+ if (vec_safe_is_empty (pending_weaks))
return;
/* If it's not visible outside this file, it doesn't matter whether
it's weak. */
/* If it's not a function or a variable, it can't be weak.
FIXME: what kinds of things are visible outside this file but
aren't functions or variables? Should this be an assert instead? */
- if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
+ if (!VAR_OR_FUNCTION_DECL_P (decl))
return;
- id = DECL_ASSEMBLER_NAME (decl);
+ if (DECL_ASSEMBLER_NAME_SET_P (decl))
+ id = DECL_ASSEMBLER_NAME (decl);
+ else
+ {
+ id = DECL_ASSEMBLER_NAME (decl);
+ SET_DECL_ASSEMBLER_NAME (decl, NULL_TREE);
+ }
- FOR_EACH_VEC_ELT (pending_weak, pending_weaks, i, pe)
+ FOR_EACH_VEC_ELT (*pending_weaks, i, pe)
if (id == pe->name)
{
apply_pragma_weak (decl, pe->value);
- VEC_unordered_remove (pending_weak, pending_weaks, i);
+ pending_weaks->unordered_remove (i);
break;
}
}
tree alias_id, id, decl;
int i;
pending_weak *pe;
+ symtab_node *target;
+
+ if (vec_safe_is_empty (pending_weaks))
+ return;
- FOR_EACH_VEC_ELT (pending_weak, pending_weaks, i, pe)
+ FOR_EACH_VEC_ELT (*pending_weaks, i, pe)
{
alias_id = pe->name;
id = pe->value;
if (id == NULL)
continue;
+ target = symtab_node::get_for_asmname (id);
decl = build_decl (UNKNOWN_LOCATION,
- FUNCTION_DECL, alias_id, default_function_type);
+ target ? TREE_CODE (target->decl) : FUNCTION_DECL,
+ alias_id, default_function_type);
DECL_ARTIFICIAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
- DECL_EXTERNAL (decl) = 1;
DECL_WEAK (decl) = 1;
+ if (VAR_P (decl))
+ TREE_STATIC (decl) = 1;
+ if (!target)
+ {
+ error ("%q+D aliased to undefined symbol %qE",
+ decl, id);
+ continue;
+ }
assemble_alias (decl, id);
}
decl = identifier_global_value (name);
if (decl && DECL_P (decl))
{
+ if (!VAR_OR_FUNCTION_DECL_P (decl))
+ GCC_BAD2 ("%<#pragma weak%> declaration of %q+D not allowed,"
+ " ignored", decl);
apply_pragma_weak (decl, value);
if (value)
- assemble_alias (decl, value);
+ {
+ DECL_EXTERNAL (decl) = 0;
+ if (VAR_P (decl))
+ TREE_STATIC (decl) = 1;
+ assemble_alias (decl, value);
+ }
}
else
{
- pending_weak *pe;
- pe = VEC_safe_push (pending_weak, gc, pending_weaks, NULL);
- pe->name = name;
- pe->value = value;
+ pending_weak pe = {name, value};
+ vec_safe_push (pending_weaks, pe);
}
}
+static enum scalar_storage_order_kind global_sso;
+
+void
+maybe_apply_pragma_scalar_storage_order (tree type)
+{
+ if (global_sso == SSO_NATIVE)
+ return;
+
+ gcc_assert (RECORD_OR_UNION_TYPE_P (type));
+
+ if (lookup_attribute ("scalar_storage_order", TYPE_ATTRIBUTES (type)))
+ return;
+
+ if (global_sso == SSO_BIG_ENDIAN)
+ TYPE_REVERSE_STORAGE_ORDER (type) = !BYTES_BIG_ENDIAN;
+ else if (global_sso == SSO_LITTLE_ENDIAN)
+ TYPE_REVERSE_STORAGE_ORDER (type) = BYTES_BIG_ENDIAN;
+ else
+ gcc_unreachable ();
+}
+
+static void
+handle_pragma_scalar_storage_order (cpp_reader *ARG_UNUSED(dummy))
+{
+ const char *kind_string;
+ enum cpp_ttype token;
+ tree x;
+
+ if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
+ {
+ error ("scalar_storage_order is not supported because endianness "
+ "is not uniform");
+ return;
+ }
+
+ if (c_dialect_cxx ())
+ {
+ if (warn_unknown_pragmas > in_system_header_at (input_location))
+ warning (OPT_Wunknown_pragmas,
+ "%<#pragma scalar_storage_order%> is not supported for C++");
+ return;
+ }
+
+ token = pragma_lex (&x);
+ if (token != CPP_NAME)
+ GCC_BAD ("missing [big-endian|little-endian|default] after %<#pragma scalar_storage_order%>");
+ kind_string = IDENTIFIER_POINTER (x);
+ if (strcmp (kind_string, "default") == 0)
+ global_sso = default_sso;
+ else if (strcmp (kind_string, "big") == 0)
+ global_sso = SSO_BIG_ENDIAN;
+ else if (strcmp (kind_string, "little") == 0)
+ global_sso = SSO_LITTLE_ENDIAN;
+ else
+ GCC_BAD ("expected [big-endian|little-endian|default] after %<#pragma scalar_storage_order%>");
+}
+
/* GCC supports two #pragma directives for renaming the external
symbol associated with a declaration (DECL_ASSEMBLER_NAME), for
- compatibility with the Solaris and Tru64 system headers. GCC also
+ compatibility with the Solaris and VMS system headers. GCC also
has its own notation for this, __asm__("name") annotations.
Corner cases of these features and their interaction:
if it appears afterward, we have no way of knowing whether a modified
DECL_ASSEMBLER_NAME is due to #pragma extern_prefix.) */
-typedef struct GTY(()) pending_redefinition_d {
+struct GTY(()) pending_redefinition {
tree oldname;
tree newname;
-} pending_redefinition;
+};
-DEF_VEC_O(pending_redefinition);
-DEF_VEC_ALLOC_O(pending_redefinition,gc);
-static GTY(()) VEC(pending_redefinition,gc) *pending_redefine_extname;
+static GTY(()) vec<pending_redefinition, va_gc> *pending_redefine_extname;
static void handle_pragma_redefine_extname (cpp_reader *);
static void
handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy))
{
- tree oldname, newname, decl, x;
+ tree oldname, newname, decls, x;
enum cpp_ttype t;
+ bool found;
if (pragma_lex (&oldname) != CPP_NAME)
GCC_BAD ("malformed #pragma redefine_extname, ignored");
if (t != CPP_EOF)
warning (OPT_Wpragmas, "junk at end of %<#pragma redefine_extname%>");
- decl = identifier_global_value (oldname);
- if (decl
- && (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
- && (TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == VAR_DECL)
- && has_c_linkage (decl))
+ found = false;
+ for (decls = c_linkage_bindings (oldname);
+ decls; )
{
- if (DECL_ASSEMBLER_NAME_SET_P (decl))
+ tree decl;
+ if (TREE_CODE (decls) == TREE_LIST)
{
- const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- name = targetm.strip_name_encoding (name);
-
- if (strcmp (name, IDENTIFIER_POINTER (newname)))
- warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
- "conflict with previous rename");
+ decl = TREE_VALUE (decls);
+ decls = TREE_CHAIN (decls);
}
else
- change_decl_assembler_name (decl, newname);
+ {
+ decl = decls;
+ decls = NULL_TREE;
+ }
+
+ if ((TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
+ && VAR_OR_FUNCTION_DECL_P (decl))
+ {
+ found = true;
+ if (DECL_ASSEMBLER_NAME_SET_P (decl))
+ {
+ const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ name = targetm.strip_name_encoding (name);
+
+ if (!id_equal (newname, name))
+ warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
+ "conflict with previous rename");
+ }
+ else
+ symtab->change_decl_assembler_name (decl, newname);
+ }
}
- else
+
+ if (!found)
/* We have to add this to the rename list even if there's already
a global value that doesn't meet the above criteria, because in
C++ "struct foo {...};" puts "foo" in the current namespace but
add_to_renaming_pragma_list (oldname, newname);
}
-/* This is called from here and from ia64.c. */
+/* This is called from here and from ia64-c.c. */
void
add_to_renaming_pragma_list (tree oldname, tree newname)
{
unsigned ix;
pending_redefinition *p;
- FOR_EACH_VEC_ELT (pending_redefinition, pending_redefine_extname, ix, p)
+ FOR_EACH_VEC_SAFE_ELT (pending_redefine_extname, ix, p)
if (oldname == p->oldname)
{
if (p->newname != newname)
return;
}
- p = VEC_safe_push (pending_redefinition, gc, pending_redefine_extname, NULL);
- p->oldname = oldname;
- p->newname = newname;
+ pending_redefinition e = {oldname, newname};
+ vec_safe_push (pending_redefine_extname, e);
}
-static GTY(()) tree pragma_extern_prefix;
-
-/* #pragma extern_prefix "prefix" */
-static void
-handle_pragma_extern_prefix (cpp_reader * ARG_UNUSED (dummy))
-{
- tree prefix, x;
- enum cpp_ttype t;
-
- if (pragma_lex (&prefix) != CPP_STRING)
- GCC_BAD ("malformed #pragma extern_prefix, ignored");
- t = pragma_lex (&x);
- if (t != CPP_EOF)
- warning (OPT_Wpragmas, "junk at end of %<#pragma extern_prefix%>");
-
- if (targetm.handle_pragma_extern_prefix)
- /* Note that the length includes the null terminator. */
- pragma_extern_prefix = (TREE_STRING_LENGTH (prefix) > 1 ? prefix : NULL);
- else if (warn_unknown_pragmas > in_system_header)
- warning (OPT_Wunknown_pragmas,
- "#pragma extern_prefix not supported on this target");
-}
+/* The current prefix set by #pragma extern_prefix. */
+GTY(()) tree pragma_extern_prefix;
/* Hook from the front ends to apply the results of one of the preceding
pragmas that rename variables. */
/* The renaming pragmas are only applied to declarations with
external linkage. */
- if ((TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
+ if (!VAR_OR_FUNCTION_DECL_P (decl)
|| (!TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
|| !has_c_linkage (decl))
return asmname;
"conflict with previous rename");
/* Take any pending redefine_extname off the list. */
- FOR_EACH_VEC_ELT (pending_redefinition, pending_redefine_extname, ix, p)
+ FOR_EACH_VEC_SAFE_ELT (pending_redefine_extname, ix, p)
if (DECL_NAME (decl) == p->oldname)
{
/* Only warn if there is a conflict. */
- if (strcmp (IDENTIFIER_POINTER (p->newname), oldname))
+ if (!id_equal (p->newname, oldname))
warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
"conflict with previous rename");
- VEC_unordered_remove (pending_redefinition,
- pending_redefine_extname, ix);
+ pending_redefine_extname->unordered_remove (ix);
break;
}
- return 0;
+ return NULL_TREE;
}
/* Find out if we have a pending #pragma redefine_extname. */
- FOR_EACH_VEC_ELT (pending_redefinition, pending_redefine_extname, ix, p)
+ FOR_EACH_VEC_SAFE_ELT (pending_redefine_extname, ix, p)
if (DECL_NAME (decl) == p->oldname)
{
tree newname = p->newname;
- VEC_unordered_remove (pending_redefinition,
- pending_redefine_extname, ix);
+ pending_redefine_extname->unordered_remove (ix);
/* If we already have an asmname, #pragma redefine_extname is
ignored (with a warning if it conflicts). */
}
/* Nada. */
- return 0;
+ return NULL_TREE;
}
static void handle_pragma_visibility (cpp_reader *);
-static VEC (int, heap) *visstack;
+static vec<int> visstack;
/* Push the visibility indicated by STR onto the top of the #pragma
visibility stack. KIND is 0 for #pragma GCC visibility, 1 for
void
push_visibility (const char *str, int kind)
{
- VEC_safe_push (int, heap, visstack,
- ((int) default_visibility) | (kind << 8));
+ visstack.safe_push (((int) default_visibility) | (kind << 8));
if (!strcmp (str, "default"))
default_visibility = VISIBILITY_DEFAULT;
else if (!strcmp (str, "internal"))
bool
pop_visibility (int kind)
{
- if (!VEC_length (int, visstack))
+ if (!visstack.length ())
return false;
- if ((VEC_last (int, visstack) >> 8) != kind)
+ if ((visstack.last () >> 8) != kind)
return false;
default_visibility
- = (enum symbol_visibility) (VEC_pop (int, visstack) & 0xff);
+ = (enum symbol_visibility) (visstack.pop () & 0xff);
visibility_options.inpragma
- = VEC_length (int, visstack) != 0;
+ = visstack.length () != 0;
return true;
}
static void
handle_pragma_diagnostic(cpp_reader *ARG_UNUSED(dummy))
{
- const char *kind_string, *option_string;
- unsigned int option_index;
- enum cpp_ttype token;
- diagnostic_t kind;
tree x;
- struct cl_option_handlers handlers;
-
- token = pragma_lex (&x);
+ location_t loc;
+ enum cpp_ttype token = pragma_lex (&x, &loc);
if (token != CPP_NAME)
- GCC_BAD ("missing [error|warning|ignored] after %<#pragma GCC diagnostic%>");
- kind_string = IDENTIFIER_POINTER (x);
+ {
+ warning_at (loc, OPT_Wpragmas,
+ "missing [error|warning|ignored|push|pop]"
+ " after %<#pragma GCC diagnostic%>");
+ return;
+ }
+
+ diagnostic_t kind;
+ const char *kind_string = IDENTIFIER_POINTER (x);
if (strcmp (kind_string, "error") == 0)
kind = DK_ERROR;
else if (strcmp (kind_string, "warning") == 0)
return;
}
else
- GCC_BAD ("expected [error|warning|ignored|push|pop] after %<#pragma GCC diagnostic%>");
+ {
+ warning_at (loc, OPT_Wpragmas,
+ "expected [error|warning|ignored|push|pop]"
+ " after %<#pragma GCC diagnostic%>");
+ return;
+ }
- token = pragma_lex (&x);
+ token = pragma_lex (&x, &loc);
if (token != CPP_STRING)
- GCC_BAD ("missing option after %<#pragma GCC diagnostic%> kind");
- option_string = TREE_STRING_POINTER (x);
- set_default_handlers (&handlers);
- for (option_index = 0; option_index < cl_options_count; option_index++)
- if (strcmp (cl_options[option_index].opt_text, option_string) == 0)
- {
- control_warning_option (option_index, (int) kind, kind != DK_IGNORED,
- input_location, c_family_lang_mask, &handlers,
- &global_options, &global_options_set,
- global_dc);
- return;
- }
- GCC_BAD ("unknown option after %<#pragma GCC diagnostic%> kind");
+ {
+ warning_at (loc, OPT_Wpragmas,
+ "missing option after %<#pragma GCC diagnostic%> kind");
+ return;
+ }
+
+ const char *option_string = TREE_STRING_POINTER (x);
+ unsigned int lang_mask = c_common_option_lang_mask () | CL_COMMON;
+ /* option_string + 1 to skip the initial '-' */
+ unsigned int option_index = find_opt (option_string + 1, lang_mask);
+ if (option_index == OPT_SPECIAL_unknown)
+ {
+ warning_at (loc, OPT_Wpragmas,
+ "unknown option after %<#pragma GCC diagnostic%> kind");
+ return;
+ }
+ else if (!(cl_options[option_index].flags & CL_WARNING))
+ {
+ warning_at (loc, OPT_Wpragmas,
+ "%qs is not an option that controls warnings", option_string);
+ return;
+ }
+ else if (!(cl_options[option_index].flags & lang_mask))
+ {
+ char *ok_langs = write_langs (cl_options[option_index].flags);
+ char *bad_lang = write_langs (c_common_option_lang_mask ());
+ warning_at (loc, OPT_Wpragmas,
+ "option %qs is valid for %s but not for %s",
+ option_string, ok_langs, bad_lang);
+ free (ok_langs);
+ free (bad_lang);
+ return;
+ }
+
+ struct cl_option_handlers handlers;
+ set_default_handlers (&handlers, NULL);
+ const char *arg = NULL;
+ if (cl_options[option_index].flags & CL_JOINED)
+ arg = option_string + 1 + cl_options[option_index].opt_len;
+ /* FIXME: input_location isn't the best location here, but it is
+ what we used to do here before and changing it breaks e.g.
+ PR69543 and PR69558. */
+ control_warning_option (option_index, (int) kind,
+ arg, kind != DK_IGNORED,
+ input_location, lang_mask, &handlers,
+ &global_options, &global_options_set,
+ global_dc);
}
/* Parse #pragma GCC target (xxx) to set target specific options. */
args = nreverse (args);
if (targetm.target_option.pragma_parse (args, NULL_TREE))
- current_target_pragma = args;
+ current_target_pragma = chainon (current_target_pragma, args);
}
}
parse_optimize_options (args, false);
current_optimize_pragma = chainon (current_optimize_pragma, args);
- optimization_current_node = build_optimization_node ();
+ optimization_current_node = build_optimization_node (&global_options);
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 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;
{
enum cpp_ttype token;
tree x = 0;
- opt_stack *p;
token = pragma_lex (&x);
if (token != CPP_EOF)
return;
}
- p = ggc_alloc_opt_stack ();
+ opt_stack *p = ggc_alloc<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 ();
+ p->optimize_binary = build_optimization_node (&global_options);
+ p->target_binary = build_target_option_node (&global_options);
/* Save optimization and target flags in string list format. */
p->optimize_strings = copy_list (current_optimize_pragma);
{
if (c_dialect_cxx ())
{
- if (warn_unknown_pragmas > in_system_header)
+ if (warn_unknown_pragmas > in_system_header_at (input_location))
warning (OPT_Wunknown_pragmas,
"%<#pragma STDC FLOAT_CONST_DECIMAL64%> is not supported"
" for C++");
if (!targetm.decimal_float_supported_p ())
{
- if (warn_unknown_pragmas > in_system_header)
+ if (warn_unknown_pragmas > in_system_header_at (input_location))
warning (OPT_Wunknown_pragmas,
"%<#pragma STDC FLOAT_CONST_DECIMAL64%> is not supported"
" on this target");
return;
}
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (input_location, OPT_Wpedantic,
"ISO C does not support %<#pragma STDC FLOAT_CONST_DECIMAL64%>");
switch (handle_stdc_pragma ("STDC FLOAT_CONST_DECIMAL64"))
}
}
-/* A vector of registered pragma callbacks. */
-
-DEF_VEC_O (pragma_handler);
-DEF_VEC_ALLOC_O (pragma_handler, heap);
+/* A vector of registered pragma callbacks, which is never freed. */
-static VEC(pragma_handler, heap) *registered_pragmas;
+static vec<internal_pragma_handler> registered_pragmas;
-typedef struct
+struct pragma_ns_name
{
const char *space;
const char *name;
-} pragma_ns_name;
+};
-DEF_VEC_O (pragma_ns_name);
-DEF_VEC_ALLOC_O (pragma_ns_name, heap);
-static VEC(pragma_ns_name, heap) *registered_pp_pragmas;
+static vec<pragma_ns_name> registered_pp_pragmas;
struct omp_pragma_def { const char *name; unsigned int id; };
+static const struct omp_pragma_def oacc_pragmas[] = {
+ { "atomic", PRAGMA_OACC_ATOMIC },
+ { "cache", PRAGMA_OACC_CACHE },
+ { "data", PRAGMA_OACC_DATA },
+ { "declare", PRAGMA_OACC_DECLARE },
+ { "enter", PRAGMA_OACC_ENTER_DATA },
+ { "exit", PRAGMA_OACC_EXIT_DATA },
+ { "host_data", PRAGMA_OACC_HOST_DATA },
+ { "kernels", PRAGMA_OACC_KERNELS },
+ { "loop", PRAGMA_OACC_LOOP },
+ { "parallel", PRAGMA_OACC_PARALLEL },
+ { "routine", PRAGMA_OACC_ROUTINE },
+ { "update", PRAGMA_OACC_UPDATE },
+ { "wait", PRAGMA_OACC_WAIT }
+};
static const struct omp_pragma_def omp_pragmas[] = {
{ "atomic", PRAGMA_OMP_ATOMIC },
{ "barrier", PRAGMA_OMP_BARRIER },
+ { "cancel", PRAGMA_OMP_CANCEL },
+ { "cancellation", PRAGMA_OMP_CANCELLATION_POINT },
{ "critical", PRAGMA_OMP_CRITICAL },
+ { "depobj", PRAGMA_OMP_DEPOBJ },
+ { "end", PRAGMA_OMP_END_DECLARE_TARGET },
{ "flush", PRAGMA_OMP_FLUSH },
- { "for", PRAGMA_OMP_FOR },
{ "master", PRAGMA_OMP_MASTER },
- { "ordered", PRAGMA_OMP_ORDERED },
- { "parallel", PRAGMA_OMP_PARALLEL },
+ { "requires", PRAGMA_OMP_REQUIRES },
{ "section", PRAGMA_OMP_SECTION },
{ "sections", PRAGMA_OMP_SECTIONS },
{ "single", PRAGMA_OMP_SINGLE },
{ "task", PRAGMA_OMP_TASK },
+ { "taskgroup", PRAGMA_OMP_TASKGROUP },
{ "taskwait", PRAGMA_OMP_TASKWAIT },
+ { "taskyield", PRAGMA_OMP_TASKYIELD },
{ "threadprivate", PRAGMA_OMP_THREADPRIVATE }
};
+static const struct omp_pragma_def omp_pragmas_simd[] = {
+ { "declare", PRAGMA_OMP_DECLARE },
+ { "distribute", PRAGMA_OMP_DISTRIBUTE },
+ { "for", PRAGMA_OMP_FOR },
+ { "ordered", PRAGMA_OMP_ORDERED },
+ { "parallel", PRAGMA_OMP_PARALLEL },
+ { "simd", PRAGMA_OMP_SIMD },
+ { "target", PRAGMA_OMP_TARGET },
+ { "taskloop", PRAGMA_OMP_TASKLOOP },
+ { "teams", PRAGMA_OMP_TEAMS },
+};
void
c_pp_lookup_pragma (unsigned int id, const char **space, const char **name)
{
+ const int n_oacc_pragmas = sizeof (oacc_pragmas) / sizeof (*oacc_pragmas);
const int n_omp_pragmas = sizeof (omp_pragmas) / sizeof (*omp_pragmas);
+ const int n_omp_pragmas_simd = sizeof (omp_pragmas_simd)
+ / sizeof (*omp_pragmas);
int i;
+ for (i = 0; i < n_oacc_pragmas; ++i)
+ if (oacc_pragmas[i].id == id)
+ {
+ *space = "acc";
+ *name = oacc_pragmas[i].name;
+ return;
+ }
+
for (i = 0; i < n_omp_pragmas; ++i)
if (omp_pragmas[i].id == id)
{
return;
}
+ for (i = 0; i < n_omp_pragmas_simd; ++i)
+ if (omp_pragmas_simd[i].id == id)
+ {
+ *space = "omp";
+ *name = omp_pragmas_simd[i].name;
+ return;
+ }
+
if (id >= PRAGMA_FIRST_EXTERNAL
- && (id < PRAGMA_FIRST_EXTERNAL
- + VEC_length (pragma_ns_name, registered_pp_pragmas)))
+ && (id < PRAGMA_FIRST_EXTERNAL + registered_pp_pragmas.length ()))
{
- *space = VEC_index (pragma_ns_name, registered_pp_pragmas,
- id - PRAGMA_FIRST_EXTERNAL)->space;
- *name = VEC_index (pragma_ns_name, registered_pp_pragmas,
- id - PRAGMA_FIRST_EXTERNAL)->name;
+ *space = registered_pp_pragmas[id - PRAGMA_FIRST_EXTERNAL].space;
+ *name = registered_pp_pragmas[id - PRAGMA_FIRST_EXTERNAL].name;
return;
}
static void
c_register_pragma_1 (const char *space, const char *name,
- pragma_handler handler, bool allow_expansion)
+ internal_pragma_handler ihandler, bool allow_expansion)
{
unsigned id;
ns_name.space = space;
ns_name.name = name;
- VEC_safe_push (pragma_ns_name, heap, registered_pp_pragmas, &ns_name);
- id = VEC_length (pragma_ns_name, registered_pp_pragmas);
+ registered_pp_pragmas.safe_push (ns_name);
+ id = registered_pp_pragmas.length ();
id += PRAGMA_FIRST_EXTERNAL - 1;
}
else
{
- VEC_safe_push (pragma_handler, heap, registered_pragmas, &handler);
- id = VEC_length (pragma_handler, registered_pragmas);
+ registered_pragmas.safe_push (ihandler);
+ id = registered_pragmas.length ();
id += PRAGMA_FIRST_EXTERNAL - 1;
- /* The C++ front end allocates 6 bits in cp_token; the C front end
- allocates 7 bits in c_token. At present this is sufficient. */
- gcc_assert (id < 64);
+ /* The C front end allocates 8 bits in c_token. The C++ front end
+ keeps the pragma kind in the form of INTEGER_CST, so no small
+ limit applies. At present this is sufficient. */
+ gcc_assert (id < 256);
}
cpp_register_deferred_pragma (parse_in, space, name, id,
allow_expansion, false);
}
+/* Register a C pragma handler, using a space and a name. It disallows pragma
+ expansion (if you want it, use c_register_pragma_with_expansion instead). */
+void
+c_register_pragma (const char *space, const char *name,
+ pragma_handler_1arg handler)
+{
+ internal_pragma_handler ihandler;
+
+ ihandler.handler.handler_1arg = handler;
+ ihandler.extra_data = false;
+ ihandler.data = NULL;
+ c_register_pragma_1 (space, name, ihandler, false);
+}
+
+/* Register a C pragma handler, using a space and a name, it also carries an
+ extra data field which can be used by the handler. It disallows pragma
+ expansion (if you want it, use c_register_pragma_with_expansion_and_data
+ instead). */
void
-c_register_pragma (const char *space, const char *name, pragma_handler handler)
+c_register_pragma_with_data (const char *space, const char *name,
+ pragma_handler_2arg handler, void * data)
{
- c_register_pragma_1 (space, name, handler, false);
+ internal_pragma_handler ihandler;
+
+ ihandler.handler.handler_2arg = handler;
+ ihandler.extra_data = true;
+ ihandler.data = data;
+ c_register_pragma_1 (space, name, ihandler, false);
}
+/* Register a C pragma handler, using a space and a name. It allows pragma
+ expansion as in the following example:
+
+ #define NUMBER 10
+ #pragma count (NUMBER)
+
+ Name expansion is still disallowed. */
void
c_register_pragma_with_expansion (const char *space, const char *name,
- pragma_handler handler)
+ pragma_handler_1arg handler)
+{
+ internal_pragma_handler ihandler;
+
+ ihandler.handler.handler_1arg = handler;
+ ihandler.extra_data = false;
+ ihandler.data = NULL;
+ c_register_pragma_1 (space, name, ihandler, true);
+}
+
+/* Register a C pragma handler, using a space and a name, it also carries an
+ extra data field which can be used by the handler. It allows pragma
+ expansion as in the following example:
+
+ #define NUMBER 10
+ #pragma count (NUMBER)
+
+ Name expansion is still disallowed. */
+void
+c_register_pragma_with_expansion_and_data (const char *space, const char *name,
+ pragma_handler_2arg handler,
+ void *data)
{
- c_register_pragma_1 (space, name, handler, true);
+ internal_pragma_handler ihandler;
+
+ ihandler.handler.handler_2arg = handler;
+ ihandler.extra_data = true;
+ ihandler.data = data;
+ c_register_pragma_1 (space, name, ihandler, true);
}
void
c_invoke_pragma_handler (unsigned int id)
{
- pragma_handler handler;
+ internal_pragma_handler *ihandler;
+ pragma_handler_1arg handler_1arg;
+ pragma_handler_2arg handler_2arg;
id -= PRAGMA_FIRST_EXTERNAL;
- handler = *VEC_index (pragma_handler, registered_pragmas, id);
-
- handler (parse_in);
+ ihandler = ®istered_pragmas[id];
+ if (ihandler->extra_data)
+ {
+ handler_2arg = ihandler->handler.handler_2arg;
+ handler_2arg (parse_in, ihandler->data);
+ }
+ else
+ {
+ handler_1arg = ihandler->handler.handler_1arg;
+ handler_1arg (parse_in);
+ }
}
/* Set up front-end pragmas. */
void
init_pragma (void)
{
+ if (flag_openacc)
+ {
+ const int n_oacc_pragmas
+ = sizeof (oacc_pragmas) / sizeof (*oacc_pragmas);
+ int i;
+
+ for (i = 0; i < n_oacc_pragmas; ++i)
+ cpp_register_deferred_pragma (parse_in, "acc", oacc_pragmas[i].name,
+ oacc_pragmas[i].id, true, true);
+ }
+
if (flag_openmp)
{
const int n_omp_pragmas = sizeof (omp_pragmas) / sizeof (*omp_pragmas);
cpp_register_deferred_pragma (parse_in, "omp", omp_pragmas[i].name,
omp_pragmas[i].id, true, true);
}
+ if (flag_openmp || flag_openmp_simd)
+ {
+ const int n_omp_pragmas_simd = sizeof (omp_pragmas_simd)
+ / sizeof (*omp_pragmas);
+ int i;
+
+ for (i = 0; i < n_omp_pragmas_simd; ++i)
+ cpp_register_deferred_pragma (parse_in, "omp", omp_pragmas_simd[i].name,
+ omp_pragmas_simd[i].id, true, true);
+ }
if (!flag_preprocess_only)
cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess",
PRAGMA_GCC_PCH_PREPROCESS, false, false);
+ if (!flag_preprocess_only)
+ cpp_register_deferred_pragma (parse_in, "GCC", "ivdep", PRAGMA_IVDEP, false,
+ false);
+
+ if (!flag_preprocess_only)
+ cpp_register_deferred_pragma (parse_in, "GCC", "unroll", PRAGMA_UNROLL,
+ false, false);
+
#ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION
c_register_pragma_with_expansion (0, "pack", handle_pragma_pack);
#else
c_register_pragma (0, "pack", handle_pragma_pack);
#endif
c_register_pragma (0, "weak", handle_pragma_weak);
+
c_register_pragma ("GCC", "visibility", handle_pragma_visibility);
c_register_pragma ("GCC", "diagnostic", handle_pragma_diagnostic);
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, "redefine_extname",
+ handle_pragma_redefine_extname);
c_register_pragma_with_expansion (0, "message", handle_pragma_message);
REGISTER_TARGET_PRAGMAS ();
#endif
+ global_sso = default_sso;
+ c_register_pragma (0, "scalar_storage_order",
+ handle_pragma_scalar_storage_order);
+
/* Allow plugins to register their own pragmas. */
invoke_plugin_callbacks (PLUGIN_PRAGMAS, NULL);
}