+ if (token != CPP_CLOSE_PAREN)
+ GCC_BAD_ACTION;
+#undef GCC_BAD_ACTION
+ }
+ else
+ GCC_BAD ("malformed '#pragma pack' - ignored");
+
+ if (c_lex (&x) != CPP_EOF)
+ warning ("junk at end of '#pragma pack'");
+
+ if (action != pop)
+ switch (align)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 16:
+ align *= BITS_PER_UNIT;
+ break;
+ default:
+ GCC_BAD2 ("alignment must be a small power of two, not %d", align);
+ }
+
+ switch (action)
+ {
+ case set: SET_GLOBAL_ALIGNMENT (align); break;
+ case push: push_alignment (align, id); break;
+ case pop: pop_alignment (id); break;
+ }
+}
+#endif /* HANDLE_PRAGMA_PACK */
+
+static GTY(()) tree pending_weaks;
+
+#ifdef HANDLE_PRAGMA_WEAK
+static void apply_pragma_weak (tree, tree);
+static void handle_pragma_weak (cpp_reader *);
+
+static void
+apply_pragma_weak (tree decl, tree value)
+{
+ if (value)
+ {
+ value = build_string (IDENTIFIER_LENGTH (value),
+ IDENTIFIER_POINTER (value));
+ decl_attributes (&decl, build_tree_list (get_identifier ("alias"),
+ build_tree_list (NULL, value)),
+ 0);
+ }
+
+ if (SUPPORTS_WEAK && DECL_EXTERNAL (decl) && TREE_USED (decl)
+ && !DECL_WEAK (decl) /* Don't complain about a redundant #pragma. */
+ && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+ warning ("%Japplying #pragma weak '%D' after first use results "
+ "in unspecified behavior", decl, decl);
+
+ declare_weak (decl);
+}
+
+void
+maybe_apply_pragma_weak (tree decl)
+{
+ tree *p, t, id;
+
+ /* Avoid asking for DECL_ASSEMBLER_NAME when it's not needed. */
+
+ /* No weak symbols pending, take the short-cut. */
+ if (!pending_weaks)
+ return;
+ /* If it's not visible outside this file, it doesn't matter whether
+ it's weak. */
+ if (!DECL_EXTERNAL (decl) && !TREE_PUBLIC (decl))
+ return;
+ /* 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 abort() instead? */
+ if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
+ return;
+
+ id = DECL_ASSEMBLER_NAME (decl);
+
+ for (p = &pending_weaks; (t = *p) ; p = &TREE_CHAIN (t))
+ if (id == TREE_PURPOSE (t))
+ {
+ apply_pragma_weak (decl, TREE_VALUE (t));
+ *p = TREE_CHAIN (t);
+ break;
+ }
+}
+
+/* #pragma weak name [= value] */
+static void
+handle_pragma_weak (cpp_reader * ARG_UNUSED (dummy))
+{
+ tree name, value, x, decl;
+ enum cpp_ttype t;
+
+ value = 0;
+
+ if (c_lex (&name) != CPP_NAME)
+ GCC_BAD ("malformed #pragma weak, ignored");
+ t = c_lex (&x);
+ if (t == CPP_EQ)
+ {
+ if (c_lex (&value) != CPP_NAME)
+ GCC_BAD ("malformed #pragma weak, ignored");
+ t = c_lex (&x);
+ }
+ if (t != CPP_EOF)
+ warning ("junk at end of #pragma weak");
+
+ decl = identifier_global_value (name);
+ if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
+ {
+ apply_pragma_weak (decl, value);
+ if (value)
+ assemble_alias (decl, value);
+ }
+ else
+ pending_weaks = tree_cons (name, value, pending_weaks);
+}
+#else
+void
+maybe_apply_pragma_weak (tree ARG_UNUSED (decl))
+{
+}
+#endif /* HANDLE_PRAGMA_WEAK */
+
+/* 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
+ has its own notation for this, __asm__("name") annotations.
+
+ Corner cases of these features and their interaction:
+
+ 1) Both pragmas silently apply only to declarations with external
+ linkage (that is, TREE_PUBLIC || DECL_EXTERNAL). Asm labels
+ do not have this restriction.
+
+ 2) In C++, both #pragmas silently apply only to extern "C" declarations.
+ Asm labels do not have this restriction.
+
+ 3) If any of the three ways of changing DECL_ASSEMBLER_NAME is
+ applied to a decl whose DECL_ASSEMBLER_NAME is already set, and the
+ new name is different, a warning issues and the name does not change.
+
+ 4) The "source name" for #pragma redefine_extname is the DECL_NAME,
+ *not* the DECL_ASSEMBLER_NAME.
+
+ 5) If #pragma extern_prefix is in effect and a declaration occurs
+ with an __asm__ name, the #pragma extern_prefix is silently
+ ignored for that declaration.
+
+ 6) If #pragma extern_prefix and #pragma redefine_extname apply to
+ the same declaration, whichever triggered first wins, and a warning
+ is issued. (We would like to have #pragma redefine_extname always
+ win, but it can appear either before or after the declaration, and
+ if it appears afterward, we have no way of knowing whether a modified
+ DECL_ASSEMBLER_NAME is due to #pragma extern_prefix.) */
+
+static GTY(()) tree pending_redefine_extname;
+
+static void handle_pragma_redefine_extname (cpp_reader *);
+
+/* #pragma redefine_extname oldname newname */
+static void
+handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy))
+{
+ tree oldname, newname, decl, x;
+ enum cpp_ttype t;
+
+ if (c_lex (&oldname) != CPP_NAME)
+ GCC_BAD ("malformed #pragma redefine_extname, ignored");
+ if (c_lex (&newname) != CPP_NAME)
+ GCC_BAD ("malformed #pragma redefine_extname, ignored");
+ t = c_lex (&x);
+ if (t != CPP_EOF)
+ warning ("junk at end of #pragma redefine_extname");
+
+ if (!flag_mudflap && !targetm.handle_pragma_redefine_extname)
+ {
+ if (warn_unknown_pragmas > in_system_header)
+ warning ("#pragma redefine_extname not supported on this target");