Mercurial > hg > CbC > CbC_gcc
diff gcc/c-family/c-pragma.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | 561a7518be6b |
children | 84e7813d76e9 |
line wrap: on
line diff
--- a/gcc/c-family/c-pragma.c Sun Aug 21 07:07:55 2011 +0900 +++ b/gcc/c-family/c-pragma.c Fri Oct 27 22:46:09 2017 +0900 @@ -1,6 +1,5 @@ /* 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-2017 Free Software Foundation, Inc. This file is part of GCC. @@ -21,22 +20,17 @@ #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 "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 "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 "diagnostic.h" #include "opts.h" #include "plugin.h" @@ -45,11 +39,11 @@ #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; @@ -72,9 +66,7 @@ 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; @@ -223,6 +215,7 @@ align = maximum_field_alignment; break; } + /* FALLTHRU */ default: GCC_BAD2 ("alignment must be a small power of two, not %d", align); } @@ -235,16 +228,14 @@ } } -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 *); @@ -263,6 +254,7 @@ 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); @@ -280,7 +272,7 @@ /* 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. */ @@ -289,16 +281,22 @@ /* 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; } } @@ -311,8 +309,12 @@ tree alias_id, id, decl; int i; pending_weak *pe; + symtab_node *target; - FOR_EACH_VEC_ELT (pending_weak, pending_weaks, i, pe) + if (vec_safe_is_empty (pending_weaks)) + return; + + FOR_EACH_VEC_ELT (*pending_weaks, i, pe) { alias_id = pe->name; id = pe->value; @@ -320,13 +322,22 @@ 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); } @@ -356,22 +367,85 @@ 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: @@ -401,15 +475,13 @@ 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 *); @@ -417,8 +489,9 @@ 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"); @@ -428,26 +501,41 @@ 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 @@ -456,14 +544,14 @@ 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) @@ -472,33 +560,12 @@ 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. */ @@ -511,7 +578,7 @@ /* 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; @@ -528,28 +595,26 @@ "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). */ @@ -590,13 +655,13 @@ } /* 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 @@ -608,8 +673,7 @@ 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")) @@ -629,14 +693,14 @@ 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; } @@ -689,17 +753,19 @@ static void handle_pragma_diagnostic(cpp_reader *ARG_UNUSED(dummy)) { - const char *kind_string, *option_string; - unsigned int option_index; - enum cpp_ttype token; + tree x; + location_t loc; + enum cpp_ttype token = pragma_lex (&x, &loc); + if (token != CPP_NAME) + { + warning_at (loc, OPT_Wpragmas, + "missing [error|warning|ignored|push|pop]" + " after %<#pragma GCC diagnostic%>"); + return; + } + diagnostic_t kind; - tree x; - struct cl_option_handlers handlers; - - token = pragma_lex (&x); - if (token != CPP_NAME) - GCC_BAD ("missing [error|warning|ignored] after %<#pragma GCC diagnostic%>"); - kind_string = IDENTIFIER_POINTER (x); + const char *kind_string = IDENTIFIER_POINTER (x); if (strcmp (kind_string, "error") == 0) kind = DK_ERROR; else if (strcmp (kind_string, "warning") == 0) @@ -717,23 +783,62 @@ 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. */ @@ -800,7 +905,7 @@ args = nreverse (args); if (targetm.target_option.pragma_parse (args, NULL_TREE)) - current_target_pragma = args; + current_target_pragma = chainon (current_target_pragma, args); } } @@ -869,7 +974,7 @@ 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); @@ -879,13 +984,13 @@ /* 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; @@ -897,7 +1002,6 @@ { enum cpp_ttype token; tree x = 0; - opt_stack *p; token = pragma_lex (&x); if (token != CPP_EOF) @@ -906,13 +1010,13 @@ 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); @@ -1114,7 +1218,7 @@ { 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++"); @@ -1123,14 +1227,14 @@ 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")) @@ -1147,48 +1251,82 @@ } } -/* A vector of registered pragma callbacks. */ +/* A vector of registered pragma callbacks, which is never freed. */ -DEF_VEC_O (pragma_handler); -DEF_VEC_ALLOC_O (pragma_handler, heap); +static vec<internal_pragma_handler> registered_pragmas; -static VEC(pragma_handler, heap) *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 }, + { "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 }, { "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) { @@ -1197,14 +1335,33 @@ return; } - if (id >= PRAGMA_FIRST_EXTERNAL - && (id < PRAGMA_FIRST_EXTERNAL - + VEC_length (pragma_ns_name, registered_pp_pragmas))) + 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_CILK_SIMD) { - *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 = NULL; + *name = "simd"; + return; + } + + if (id == PRAGMA_CILK_GRAINSIZE) + { + *space = "cilk"; + *name = "grainsize"; + return; + } + + if (id >= PRAGMA_FIRST_EXTERNAL + && (id < PRAGMA_FIRST_EXTERNAL + registered_pp_pragmas.length ())) + { + *space = registered_pp_pragmas[id - PRAGMA_FIRST_EXTERNAL].space; + *name = registered_pp_pragmas[id - PRAGMA_FIRST_EXTERNAL].name; return; } @@ -1216,7 +1373,7 @@ 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; @@ -1229,53 +1386,132 @@ 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 handler) +c_register_pragma (const char *space, const char *name, + pragma_handler_1arg handler) { - c_register_pragma_1 (space, name, handler, false); + 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_with_data (const char *space, const char *name, + pragma_handler_2arg handler, void * data) +{ + 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) { - c_register_pragma_1 (space, name, handler, true); + 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) +{ + 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); @@ -1285,17 +1521,40 @@ 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_cilkplus) + cpp_register_deferred_pragma (parse_in, NULL, "simd", PRAGMA_CILK_SIMD, + true, false); 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_cilkplus) + cpp_register_deferred_pragma (parse_in, "cilk", "grainsize", + PRAGMA_CILK_GRAINSIZE, true, 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); @@ -1308,8 +1567,8 @@ 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); @@ -1317,6 +1576,10 @@ 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); }