This patch reworks pragma parsing in c-pragma.cc, with the
following improvements:

- it replaces the GCC_BAD* macros (that contained "return") in favor
of helper classes and functions for emitting diagnostics, making control
flow more explicit

- the -Wpragmas diagnostics are reworded from the form e.g.:
  DESCRIPTION OF PROBLEM; ignored
to:
  ignoring malformed '#pragma FOO': DESCRIPTION OF PROBLEM

- the locations of the warnings are fixed to more accurately
reflect the location of the problem

- the names of the pragmas are URLified into links to the
documentation for the pragma.  For example, in:

  warning: ignoring malformed '#pragma weak': expected name [-Wpragmas]

in a suitable terminal, the "#pragma weak" within quotes is a link
to https://gcc.gnu.org/onlinedocs/gcc/Weak-Pragmas.html; similarly with

  warning: '#pragma pack' has no effect with '-fpack-struct' - ignored 
[-Wpragmas]

the "#pragma pack" text is linkified to
  https://gcc.gnu.org/onlinedocs/gcc/Structure-Layout-Pragmas.html
and the "-fpack-struct" text is linkified to:
  https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#index-fpack-struct

I have a more general and maintainable approach to adding URLs to
diagnostics which is in a followup.

gcc/c-family/ChangeLog:
        * c-pragma.cc (GCC_BAD): Delete.
        (GCC_BAD2): Delete.
        (GCC_BAD_AT): Delete.
        (GCC_BAD2_AT): Delete.
        (get_doc_url): New.
        (class pragma_parser): New.
        (handle_pragma_pack): Delete redundant forward decl.
        (pop_alignment): Add param "p" and use it to get doc urls.
        (enum class pack_action): Move here from within
        handle_pragma_pack.
        (class pragma_pack_parser): New.
        (handle_pragma_pack): Rewrite using pragma_pack_parser
        and enum class pack_action, eliminating uses of GCC_BAD*,
        rewording diagnostics.
        (handle_pragma_weak): Rewrite using pragma_parser, eliminating
        uses of GCC_BAD*, rewording diagnostics.
        (class pragma_scalar_storage_order_parser): New.
        (handle_pragma_scalar_storage_order): Rewrite using above,
        eliminating uses of GCC_BAD*, rewording diagnostics.
        (handle_pragma_redefine_extname): Rewrite using pragma_parser,
        eliminating uses of GCC_BAD*, rewording diagnostics.  Fix overlong
        line.
        (handle_pragma_visibility): Remove redundant forward decl.
        (push_visibility): Add "const pragma_parser *" param.  Rewrite to
        eliminate uses of GCC_BAD*.  Add note that warning was ignored.
        (handle_pragma_visibility): Rewrite using pragma_parser,
        eliminating uses of GCC_BAD*, rewording diagnostics.
        (handle_pragma_target): Fix name of pragma in "error".  Eliminate
        uses of GCC_BAD*.
        (handle_pragma_optimize): Eliminate uses of GCC_BAD.
        (handle_pragma_message): Rewrite using pragma_parser, eliminating
        uses of GCC_BAD*, rewording diagnostics.
        * c-pragma.h (class pragma_parser): New forward decl.
        (push_visibility): Add optional "const pragma_parser *" param.

gcc/testsuite/ChangeLog:
        * c-c++-common/pragma-message-parsing.c: New test.
        * c-c++-common/pragma-optimize-parsing.c: New test.
        * c-c++-common/pragma-pack-parsing-1.c: New test.
        * c-c++-common/pragma-pack-parsing-2.c: New test.
        * c-c++-common/pragma-redefine_extname-parsing.c: New test.
        * c-c++-common/pragma-target-parsing.c: New test.
        * c-c++-common/pragma-visibility-parsing.c: New test.
        * c-c++-common/pragma-weak-parsing.c: New test.
        * gcc.dg/bad-pragma-locations.c: Update for changes to wording and
        location of -Wpragmas.
        * gcc.dg/pragma-scalar_storate_order-parsing.c: New test.
        * gcc.dg/sso-6.c: Update for changes to wording of -Wpragmas.
---
 gcc/c-family/c-pragma.cc                      | 569 ++++++++++++++----
 gcc/c-family/c-pragma.h                       |   5 +-
 .../c-c++-common/pragma-message-parsing.c     |  21 +
 .../c-c++-common/pragma-optimize-parsing.c    |  16 +
 .../c-c++-common/pragma-pack-parsing-1.c      |  19 +
 .../c-c++-common/pragma-pack-parsing-2.c      |   4 +
 .../pragma-redefine_extname-parsing.c         |   9 +
 .../c-c++-common/pragma-target-parsing.c      |  14 +
 .../c-c++-common/pragma-visibility-parsing.c  |  13 +
 .../c-c++-common/pragma-weak-parsing.c        |  24 +
 gcc/testsuite/gcc.dg/bad-pragma-locations.c   |  22 +-
 .../pragma-scalar_storate_order-parsing.c     |   8 +
 gcc/testsuite/gcc.dg/sso-6.c                  |   2 +-
 13 files changed, 588 insertions(+), 138 deletions(-)
 create mode 100644 gcc/testsuite/c-c++-common/pragma-message-parsing.c
 create mode 100644 gcc/testsuite/c-c++-common/pragma-optimize-parsing.c
 create mode 100644 gcc/testsuite/c-c++-common/pragma-pack-parsing-1.c
 create mode 100644 gcc/testsuite/c-c++-common/pragma-pack-parsing-2.c
 create mode 100644 gcc/testsuite/c-c++-common/pragma-redefine_extname-parsing.c
 create mode 100644 gcc/testsuite/c-c++-common/pragma-target-parsing.c
 create mode 100644 gcc/testsuite/c-c++-common/pragma-visibility-parsing.c
 create mode 100644 gcc/testsuite/c-c++-common/pragma-weak-parsing.c
 create mode 100644 gcc/testsuite/gcc.dg/pragma-scalar_storate_order-parsing.c

diff --git a/gcc/c-family/c-pragma.cc b/gcc/c-family/c-pragma.cc
index df3e3e6b3b0..6df8683af77 100644
--- a/gcc/c-family/c-pragma.cc
+++ b/gcc/c-family/c-pragma.cc
@@ -35,14 +35,161 @@ along with GCC; see the file COPYING3.  If not see
 #include "plugin.h"
 #include "opt-suggestions.h"
 
-#define GCC_BAD(gmsgid) \
-  do { warning (OPT_Wpragmas, gmsgid); return; } while (0)
-#define GCC_BAD2(gmsgid, arg) \
-  do { warning (OPT_Wpragmas, gmsgid, arg); return; } while (0)
-#define GCC_BAD_AT(loc, gmsgid)                                        \
-  do { warning_at (loc, OPT_Wpragmas, gmsgid); return; } while (0)
-#define GCC_BAD2_AT(loc, gmsgid, arg)                  \
-  do { warning_at (loc, OPT_Wpragmas, gmsgid, arg); return; } while (0)
+label_text
+get_doc_url (const char *doc_url_suffix)
+{
+  if (!doc_url_suffix)
+    return label_text ();
+  return label_text::take (concat (DOCUMENTATION_ROOT_URL,
+                                  doc_url_suffix,
+                                  nullptr));
+}
+
+/* A class for implementing parsing within pragma-handling callbacks.
+   Provides various wrappers around pragma_lex.  */
+
+class pragma_parser
+{
+public:
+  pragma_parser (const char *space, const char *name,
+                const char *doc_url_suffix)
+  : m_start_loc (input_location),
+    m_space (space),
+    m_name (name),
+    m_doc_url_suffix (doc_url_suffix),
+    m_last_loc (m_start_loc)
+  {
+    // SPACE can be null.
+    gcc_assert (name);
+    // DOC_URL_SUFFIX can be null
+  }
+
+  location_t
+  get_last_location () const
+  {
+    return m_last_loc;
+  }
+
+  bool
+  require_token (enum cpp_ttype required_ttype, const char *desc)
+  {
+    tree x = NULL_TREE;
+
+    enum cpp_ttype ttype = pragma_lex (&x, &m_last_loc);
+    if (ttype != required_ttype)
+      {
+       label_text doc_url (get_doc_url ());
+       if (m_space)
+         warning_at (m_last_loc, OPT_Wpragmas,
+                     "ignoring malformed %<%{#pragma %s %s%}%>:"
+                     " expected %qs",
+                     doc_url.get (), m_space, m_name,
+                     desc);
+       else
+         warning_at (m_last_loc, OPT_Wpragmas,
+                     "ignoring malformed %<%{#pragma %s%}%>:"
+                     " expected %qs",
+                     doc_url.get (), m_name,
+                     desc);
+       return false;
+      }
+    return true;
+  }
+
+  bool
+  require_open_paren ()
+  {
+    return require_token (CPP_OPEN_PAREN, "(");
+  }
+
+  bool
+  require_close_paren ()
+  {
+    return require_token (CPP_CLOSE_PAREN, ")");
+  }
+
+  tree require_name ()
+  {
+    tree x = NULL_TREE;
+
+    enum cpp_ttype ttype = pragma_lex (&x, &m_last_loc);
+    if (ttype != CPP_NAME)
+      {
+       label_text doc_url (get_doc_url ());
+       if (m_space)
+         warning_at (m_last_loc, OPT_Wpragmas,
+                     "ignoring malformed %<%{#pragma %s %s%}%>:"
+                     "expected name",
+                     doc_url.get (), m_space, m_name);
+       else
+         warning_at (m_last_loc, OPT_Wpragmas,
+                     "ignoring malformed %<%{#pragma %s%}%>:"
+                     " expected name",
+                     doc_url.get (), m_name);
+       return NULL_TREE;
+      }
+
+    return x;
+  }
+
+  tree require_symbol_name ()
+  {
+    tree x = NULL_TREE;
+
+    enum cpp_ttype ttype = pragma_lex (&x, &m_last_loc);
+    if (ttype != CPP_NAME)
+      {
+       label_text doc_url (get_doc_url ());
+       if (m_space)
+         warning_at (m_last_loc, OPT_Wpragmas,
+                     "ignoring malformed %<%{#pragma %s %s%}%>:"
+                     " expected symbol name",
+                     doc_url.get (), m_space, m_name);
+       else
+         warning_at (m_last_loc, OPT_Wpragmas,
+                     "ignoring malformed %<%{#pragma %s%}%>:"
+                     " expected symbol name",
+                     doc_url.get (), m_name);
+       return NULL_TREE;
+      }
+
+    return x;
+  }
+
+  void
+  check_for_trailing_junk ()
+  {
+    tree x = NULL_TREE;
+    enum cpp_ttype t = pragma_lex (&x, &m_last_loc);
+    warn_about_any_trailing_junk (t, m_last_loc);
+  }
+
+  void
+  warn_about_any_trailing_junk (enum cpp_ttype t, location_t loc) const
+  {
+    if (t == CPP_EOF)
+      return;
+    label_text doc_url (get_doc_url ());
+    if (m_space)
+      warning_at (loc, OPT_Wpragmas, "junk at end of %<%{#pragma %s %s%}%>",
+                 doc_url.get (), m_space, m_name);
+    else
+      warning_at (loc, OPT_Wpragmas, "junk at end of %<%{#pragma %s%}%>",
+                 doc_url.get (), m_name);
+  }
+
+  label_text
+  get_doc_url () const
+  {
+    return ::get_doc_url (m_doc_url_suffix);
+  }
+
+  const location_t m_start_loc;
+  const char *const m_space;
+  const char *const m_name;
+  const char *m_doc_url_suffix;
+  location_t m_last_loc;
+};
 
 struct GTY(()) align_stack {
   int                 alignment;
@@ -52,8 +199,6 @@ struct GTY(()) align_stack {
 
 static GTY(()) struct align_stack * alignment_stack;
 
-static void handle_pragma_pack (cpp_reader *);
-
 /* If we have a "global" #pragma pack(<n>) in effect when the first
    #pragma pack(push,<n>) is encountered, this stores the value of
    maximum_field_alignment in effect.  When the final pop_alignment()
@@ -65,7 +210,7 @@ static int default_alignment;
        : &alignment_stack->alignment) = (ALIGN))
 
 static void push_alignment (int, tree);
-static void pop_alignment (tree);
+static void pop_alignment (tree, const pragma_parser &p);
 
 /* Push an alignment value onto the stack.  */
 static void
@@ -90,13 +235,19 @@ push_alignment (int alignment, tree id)
 
 /* Undo a push of an alignment onto the stack.  */
 static void
-pop_alignment (tree id)
+pop_alignment (tree id, const pragma_parser &p)
 {
   align_stack * entry;
 
   if (alignment_stack == NULL)
-    GCC_BAD ("%<#pragma pack (pop)%> encountered without matching "
-            "%<#pragma pack (push)%>");
+    {
+      label_text doc_url (p.get_doc_url ());
+      warning (OPT_Wpragmas,
+              "%<%{#pragma pack (pop)%}%> encountered without matching "
+              "%<%{#pragma pack (push)%}%>",
+              doc_url.get (), doc_url.get ());
+      return;
+    }
 
   /* If we got an identifier, strip away everything above the target
      entry so that the next step will restore the state just below it.  */
@@ -109,10 +260,12 @@ pop_alignment (tree id)
            break;
          }
       if (entry == NULL)
-       warning (OPT_Wpragmas,
-                "%<#pragma pack(pop, %E)%> encountered without matching "
-                "%<#pragma pack(push, %E)%>"
-                , id, id);
+       {
+         warning (OPT_Wpragmas,
+                  "%<#pragma pack(pop, %E)%> encountered without matching "
+                  "%<#pragma pack(push, %E)%>",
+                  id, id);
+       }
     }
 
   entry = alignment_stack->prev;
@@ -122,6 +275,41 @@ pop_alignment (tree id)
   alignment_stack = entry;
 }
 
+enum class pack_action { set, push, pop };
+
+class pragma_pack_parser : public pragma_parser
+{
+public:
+  pragma_pack_parser ()
+  : pragma_parser (nullptr, "pack", "gcc/Structure-Layout-Pragmas.html")
+  {
+  }
+
+  bool require_integer (tree x, location_t loc) const
+  {
+    if (TREE_CODE (x) == INTEGER_CST)
+      return true;
+
+    label_text doc_url (get_doc_url ());
+    warning_at (loc, OPT_Wpragmas,
+               "ignoring malformed %<%{#pragma pack%}%>:"
+               " invalid constant",
+               doc_url.get ());
+    return false;
+  }
+
+  void complain_about_malformed_action (pack_action action) const
+  {
+    label_text doc_url (get_doc_url ());
+    if (action != pack_action::pop)
+      warning_at (m_last_loc, OPT_Wpragmas,
+                 "ignoring malformed %<#pragma pack(push[, id][, <n>])%>");
+    else
+      warning_at (m_last_loc, OPT_Wpragmas,
+                 "ignoring malformed %<#pragma pack(pop[, id])%>");
+  }
+};
+
 /* #pragma pack ()
    #pragma pack (N)
 
@@ -134,46 +322,50 @@ pop_alignment (tree id)
 static void
 handle_pragma_pack (cpp_reader *)
 {
+  pragma_pack_parser p;
+
   location_t loc;
   tree x, id = 0;
   int align = -1;
+  location_t align_loc = input_location;
   enum cpp_ttype token;
-  enum { set, push, pop } action;
+  enum pack_action action;
 
-  if (pragma_lex (&x) != CPP_OPEN_PAREN)
-    GCC_BAD ("missing %<(%> after %<#pragma pack%> - ignored");
+  if (!p.require_open_paren ())
+    return;
 
   token = pragma_lex (&x, &loc);
   if (token == CPP_CLOSE_PAREN)
     {
-      action = set;
+      action = pack_action::set;
       align = initial_max_fld_align;
     }
   else if (token == CPP_NUMBER)
     {
-      if (TREE_CODE (x) != INTEGER_CST)
-       GCC_BAD_AT (loc, "invalid constant in %<#pragma pack%> - ignored");
+      if (!p.require_integer (x, loc))
+       return;
       align = TREE_INT_CST_LOW (x);
-      action = set;
-      if (pragma_lex (&x) != CPP_CLOSE_PAREN)
-       GCC_BAD ("malformed %<#pragma pack%> - ignored");
+      align_loc = loc;
+      action = pack_action::set;
+      if (!p.require_close_paren ())
+       return;
     }
   else if (token == CPP_NAME)
     {
-#define GCC_BAD_ACTION do { if (action != pop) \
-         GCC_BAD ("malformed %<#pragma pack(push[, id][, <n>])%> - ignored"); \
-       else \
-         GCC_BAD ("malformed %<#pragma pack(pop[, id])%> - ignored"); \
-       } while (0)
-
       const char *op = IDENTIFIER_POINTER (x);
       if (!strcmp (op, "push"))
-       action = push;
+       action = pack_action::push;
       else if (!strcmp (op, "pop"))
-       action = pop;
+       action = pack_action::pop;
       else
-       GCC_BAD2_AT (loc, "unknown action %qE for %<#pragma pack%> - ignored",
-                    x);
+       {
+         label_text doc_url (p.get_doc_url ());
+         warning_at (loc, OPT_Wpragmas,
+                     "ignoring malformed %<%{#pragma pack%}%>:"
+                     " unknown action %qE",
+                     doc_url.get (), x);
+         return;
+       }
 
       while ((token = pragma_lex (&x)) == CPP_COMMA)
        {
@@ -182,33 +374,56 @@ handle_pragma_pack (cpp_reader *)
            {
              id = x;
            }
-         else if (token == CPP_NUMBER && action == push && align == -1)
+         else if (token == CPP_NUMBER
+                  && action == pack_action::push
+                  && align == -1)
            {
-             if (TREE_CODE (x) != INTEGER_CST)
-               GCC_BAD_AT (loc,
-                           "invalid constant in %<#pragma pack%> - ignored");
+             if (!p.require_integer (x, loc))
+               return;
              align = TREE_INT_CST_LOW (x);
+             align_loc = loc;
              if (align == -1)
-               action = set;
+               action = pack_action::set;
            }
          else
-           GCC_BAD_ACTION;
+           {
+             p.complain_about_malformed_action (action);
+             return;
+           }
        }
 
       if (token != CPP_CLOSE_PAREN)
-       GCC_BAD_ACTION;
-#undef GCC_BAD_ACTION
+       {
+         p.complain_about_malformed_action (action);
+         return;
+       }
     }
   else
-    GCC_BAD ("malformed %<#pragma pack%> - ignored");
+    {
+      label_text doc_url (p.get_doc_url ());
+      warning_at (loc, OPT_Wpragmas,
+                 "ignoring malformed %<%{#pragma pack%}%>:"
+                 " expected %<)%>, integer, %<push%>, or %<pop%>",
+                 doc_url.get ());
+      return;
+    }
 
   if (pragma_lex (&x, &loc) != CPP_EOF)
     warning_at (loc, OPT_Wpragmas, "junk at end of %<#pragma pack%>");
 
   if (flag_pack_struct)
-    GCC_BAD ("%<#pragma pack%> has no effect with %<-fpack-struct%> - 
ignored");
+    {
+      label_text pragma_doc_url (p.get_doc_url ());
+      label_text option_doc_url
+       (get_doc_url ("gcc/Code-Gen-Options.html#index-fpack-struct"));
+      warning (OPT_Wpragmas,
+              "%<%{#pragma pack%}%> has no effect with %<%{-fpack-struct%}%>"
+              " - ignored",
+              pragma_doc_url.get (), option_doc_url.get ());
+      return;
+    }
 
-  if (action != pop)
+  if (action != pack_action::pop)
     switch (align)
       {
       case 0:
@@ -220,21 +435,28 @@ handle_pragma_pack (cpp_reader *)
        align *= BITS_PER_UNIT;
        break;
       case -1:
-       if (action == push)
+       if (action == pack_action::push)
          {
            align = maximum_field_alignment;
            break;
          }
        /* FALLTHRU */
       default:
-       GCC_BAD2 ("alignment must be a small power of two, not %d", align);
+       {
+         label_text doc_url (p.get_doc_url ());
+         warning_at (align_loc, OPT_Wpragmas,
+                     "ignoring malformed %<%{#pragma pack%}%>:"
+                     " alignment must be a small power of two, not %d",
+                     doc_url.get (), align);
+         return;
+       }
       }
 
   switch (action)
     {
-    case set:   SET_GLOBAL_ALIGNMENT (align);  break;
-    case push:  push_alignment (align, id);    break;
-    case pop:   pop_alignment (id);           break;
+    case pack_action::set:   SET_GLOBAL_ALIGNMENT (align);  break;
+    case pack_action::push:  push_alignment (align, id);    break;
+    case pack_action::pop:   pop_alignment (id, p);           break;
     }
 }
 
@@ -357,29 +579,46 @@ maybe_apply_pending_pragma_weaks (void)
 static void
 handle_pragma_weak (cpp_reader *)
 {
-  tree name, value, x, decl;
+  pragma_parser p (nullptr, "weak", "gcc/Weak-Pragmas.html");
+
+  tree x, decl;
   enum cpp_ttype t;
+  location_t loc;
+  location_t name_loc;
 
-  value = 0;
+  tree name = p.require_name ();
+  if (!name)
+    return;
+  name_loc = p.get_last_location ();
 
-  if (pragma_lex (&name) != CPP_NAME)
-    GCC_BAD ("malformed %<#pragma weak%>, ignored");
-  t = pragma_lex (&x);
+  tree value = NULL_TREE;
+  t = pragma_lex (&x, &loc);
   if (t == CPP_EQ)
     {
-      if (pragma_lex (&value) != CPP_NAME)
-       GCC_BAD ("malformed %<#pragma weak%>, ignored");
-      t = pragma_lex (&x);
+      value = p.require_name ();
+      if (!value)
+       return;
+      t = pragma_lex (&x, &loc);
     }
-  if (t != CPP_EOF)
-    warning (OPT_Wpragmas, "junk at end of %<#pragma weak%>");
+  p.warn_about_any_trailing_junk (t, loc);
 
   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);
+       {
+         auto_diagnostic_group d;
+         label_text doc_url (p.get_doc_url ());
+         if (warning_at (name_loc, OPT_Wpragmas,
+                         "%<%{#pragma weak%}%> declaration of %qD not allowed,"
+                         " ignored",
+                         doc_url.get (), decl))
+           if (DECL_SOURCE_LOCATION (decl) != UNKNOWN_LOCATION)
+             inform (DECL_SOURCE_LOCATION (decl),
+                     "%qD is not a variable or function",
+                     decl);
+         return;
+       }
       apply_pragma_weak (decl, value);
       if (value)
        {
@@ -417,12 +656,29 @@ maybe_apply_pragma_scalar_storage_order (tree type)
     gcc_unreachable ();
 }
 
+class pragma_scalar_storage_order_parser : public pragma_parser
+{
+public:
+  pragma_scalar_storage_order_parser ()
+   : pragma_parser (nullptr, "scalar_storage_order",
+                   "gcc/Structure-Layout-Pragmas.html")
+  {
+  }
+
+  void complain_about_arg (location_t arg_loc) const
+  {
+    label_text doc_url (get_doc_url ());
+    warning_at (arg_loc, OPT_Wpragmas,
+               "ignoring malformed %<%{#pragma scalar_storage_order%}%>:"
+               " expected %<big-endian%>, %<little-endian%>, or %<default%>",
+               doc_url.get ());
+  }
+};
+
 static void
 handle_pragma_scalar_storage_order (cpp_reader *)
 {
-  const char *kind_string;
-  enum cpp_ttype token;
-  tree x;
+  pragma_scalar_storage_order_parser p;
 
   if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
     {
@@ -439,11 +695,15 @@ handle_pragma_scalar_storage_order (cpp_reader *)
       return;
     }
 
-  token = pragma_lex (&x);
+  tree x;
+  location_t arg_loc;
+  enum cpp_ttype token = pragma_lex (&x, &arg_loc);
   if (token != CPP_NAME)
-    GCC_BAD ("missing %<big-endian%>, %<little-endian%>, or %<default%> after "
-            "%<#pragma scalar_storage_order%>");
-  kind_string = IDENTIFIER_POINTER (x);
+    {
+      p.complain_about_arg (arg_loc);
+      return;
+    }
+  const char *kind_string = IDENTIFIER_POINTER (x);
   if (strcmp (kind_string, "default") == 0)
     global_sso = default_sso;
   else if (strcmp (kind_string, "big") == 0)
@@ -451,8 +711,7 @@ handle_pragma_scalar_storage_order (cpp_reader *)
   else if (strcmp (kind_string, "little") == 0)
     global_sso = SSO_LITTLE_ENDIAN;
   else
-    GCC_BAD ("expected %<big-endian%>, %<little-endian%>, or %<default%> after 
"
-            "%<#pragma scalar_storage_order%>");
+    p.complain_about_arg (arg_loc);
 }
 
 /* GCC supports two #pragma directives for renaming the external
@@ -501,20 +760,19 @@ static void handle_pragma_redefine_extname (cpp_reader *);
 static void
 handle_pragma_redefine_extname (cpp_reader *)
 {
-  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 (pragma_lex (&newname) != CPP_NAME)
-    GCC_BAD ("malformed %<#pragma redefine_extname%>, ignored");
-  t = pragma_lex (&x);
-  if (t != CPP_EOF)
-    warning (OPT_Wpragmas, "junk at end of %<#pragma redefine_extname%>");
-
-  found = false;
-  for (decls = c_linkage_bindings (oldname);
+  pragma_parser p (nullptr, "redefine_extname",
+                  "gcc/Symbol-Renaming-Pragmas.html");
+
+  tree oldname = p.require_symbol_name ();
+  if (!oldname)
+    return;
+  tree newname = p.require_symbol_name ();
+  if (!newname)
+    return;
+  p.check_for_trailing_junk ();
+
+  bool found = false;
+  for (tree decls = c_linkage_bindings (oldname);
        decls; )
     {
       tree decl;
@@ -535,7 +793,8 @@ handle_pragma_redefine_extname (cpp_reader *)
          found = true;
          if (DECL_ASSEMBLER_NAME_SET_P (decl))
            {
-             const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME 
(decl));
+             const char *name
+               = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
              name = targetm.strip_name_encoding (name);
 
              if (!id_equal (newname, name))
@@ -671,8 +930,6 @@ maybe_apply_renaming_pragma (tree decl, tree asmname)
 }
 
 
-static void handle_pragma_visibility (cpp_reader *);
-
 static vec<int> visstack;
 
 /* Push the visibility indicated by STR onto the top of the #pragma
@@ -683,7 +940,7 @@ static vec<int> visstack;
    KIND and pop using a different one.  */
 
 void
-push_visibility (const char *str, int kind)
+push_visibility (const char *str, int kind, const pragma_parser *p)
 {
   visstack.safe_push (((int) default_visibility) | (kind << 8));
   if (!strcmp (str, "default"))
@@ -695,8 +952,23 @@ push_visibility (const char *str, int kind)
   else if (!strcmp (str, "protected"))
     default_visibility = VISIBILITY_PROTECTED;
   else
-    GCC_BAD ("%<#pragma GCC visibility push()%> must specify %<default%>, "
-            "%<internal%>, %<hidden%> or %<protected%>");
+    {
+      auto_diagnostic_group d;
+      location_t loc = p ? p->get_last_location () : input_location;
+      if (warning_at (loc,
+                     OPT_Wpragmas,
+                     "%<#pragma GCC visibility push()%> must specify"
+                     " %<default%>, %<internal%>, %<hidden%>"
+                     " or %<protected%>"))
+       if (p)
+         {
+           label_text doc_url (p->get_doc_url ());
+           inform (loc,
+                   "ignoring malformed %<%{#pragma GCC visibility%}%>",
+                   doc_url.get ());
+         }
+      return;
+    }
   visibility_options.inpragma = 1;
 }
 
@@ -723,6 +995,8 @@ pop_visibility (int kind)
 static void
 handle_pragma_visibility (cpp_reader *)
 {
+  pragma_parser p ("GCC", "visibility", "gcc/Visibility-Pragmas.html");
+
   /* Form is #pragma GCC visibility push(hidden)|pop */
   tree x;
   enum cpp_ttype token;
@@ -738,30 +1012,41 @@ handle_pragma_visibility (cpp_reader *)
        action = pop;
     }
   if (bad == action)
-    GCC_BAD ("%<#pragma GCC visibility%> must be followed by %<push%> "
-            "or %<pop%>");
+    {
+      label_text doc_url (p.get_doc_url ());
+      warning (OPT_Wpragmas,
+              "%<%{#pragma GCC visibility%}%> must be followed by %<push%> "
+              "or %<pop%>",
+              doc_url.get ());
+      return;
+    }
   else
     {
       if (pop == action)
        {
          if (! pop_visibility (0))
-           GCC_BAD ("no matching push for %<#pragma GCC visibility pop%>");
+           {
+             label_text doc_url (p.get_doc_url ());
+             warning (OPT_Wpragmas,
+                      "no matching push for"
+                      " %<%{#pragma GCC visibility pop%}%>",
+                      doc_url.get ());
+             return;
+           }
        }
       else
        {
-         if (pragma_lex (&x) != CPP_OPEN_PAREN)
-           GCC_BAD ("missing %<(%> after %<#pragma GCC visibility push%> - 
ignored");
-         token = pragma_lex (&x);
-         if (token != CPP_NAME)
-           GCC_BAD ("malformed %<#pragma GCC visibility push%>");
-         else
-           push_visibility (IDENTIFIER_POINTER (x), 0);
-         if (pragma_lex (&x) != CPP_CLOSE_PAREN)
-           GCC_BAD ("missing %<(%> after %<#pragma GCC visibility push%> - 
ignored");
+         if (!p.require_open_paren ())
+           return;
+         x = p.require_name ();
+         if (!x)
+           return;
+         push_visibility (IDENTIFIER_POINTER (x), 0, &p);
+         if (!p.require_close_paren ())
+           return;
        }
     }
-  if (pragma_lex (&x) != CPP_EOF)
-    warning (OPT_Wpragmas, "junk at end of %<#pragma GCC visibility%>");
+  p.check_for_trailing_junk ();
 }
 
 /* Helper routines for parsing #pragma GCC diagnostic.  */
@@ -1051,7 +1336,7 @@ handle_pragma_target(cpp_reader *)
 
   if (cfun)
     {
-      error ("%<#pragma GCC option%> is not allowed inside functions");
+      error ("%<#pragma GCC target option%> is not allowed inside functions");
       return;
     }
 
@@ -1063,7 +1348,12 @@ handle_pragma_target(cpp_reader *)
     }
 
   if (token != CPP_STRING)
-    GCC_BAD_AT (loc, "%<#pragma GCC option%> is not a string");
+    {
+      warning_at (loc, OPT_Wpragmas,
+                 "ignoring malformed %<#pragma GCC target%>:"
+                 " expected a string option");
+      return;
+    }
 
   /* Strings are user options.  */
   else
@@ -1088,8 +1378,12 @@ handle_pragma_target(cpp_reader *)
          if (token == CPP_CLOSE_PAREN)
            token = pragma_lex (&x);
          else
-           GCC_BAD ("%<#pragma GCC target (string [,string]...)%> does "
-                    "not have a final %<)%>");
+           {
+             warning (OPT_Wpragmas,
+                      "%<#pragma GCC target (string [,string]...)%> does "
+                      "not have a final %<)%>");
+             return;
+           }
        }
 
       if (token != CPP_EOF)
@@ -1135,7 +1429,11 @@ handle_pragma_optimize (cpp_reader *)
     }
 
   if (token != CPP_STRING && token != CPP_NUMBER)
-    GCC_BAD ("%<#pragma GCC optimize%> is not a string or number");
+    {
+      warning (OPT_Wpragmas,
+              "%<#pragma GCC optimize%> is not a string or number");
+      return;
+    }
 
   /* Strings/numbers are user options.  */
   else
@@ -1159,8 +1457,12 @@ handle_pragma_optimize (cpp_reader *)
          if (token == CPP_CLOSE_PAREN)
            token = pragma_lex (&x);
          else
-           GCC_BAD ("%<#pragma GCC optimize (string [,string]...)%> does "
-                    "not have a final %<)%>");
+           {
+             warning (OPT_Wpragmas,
+                      "%<#pragma GCC optimize (string [,string]...)%> does "
+                      "not have a final %<)%>");
+             return;
+           }
        }
 
       if (token != CPP_EOF)
@@ -1336,33 +1638,50 @@ handle_pragma_reset_options (cpp_reader *)
 static void
 handle_pragma_message (cpp_reader *)
 {
+  pragma_parser p (nullptr, "message", "gcc/Diagnostic-Pragmas.html");
+
   location_t loc;
   enum cpp_ttype token;
   tree x, message = 0;
 
-  token = pragma_lex (&x);
+  token = pragma_lex (&x, &loc);
   if (token == CPP_OPEN_PAREN)
     {
-      token = pragma_lex (&x);
+      token = pragma_lex (&x, &loc);
       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");
+       {
+         label_text doc_url (p.get_doc_url ());
+         warning_at (loc, OPT_Wpragmas,
+                     "expected a string after %<%{#pragma message%}%>",
+                     doc_url.get ());
+         return;
+       }
+      if (!p.require_close_paren ())
+       return;
     }
   else if (token == CPP_STRING)
     message = x;
   else if (token == CPP_STRING_USERDEF)
-    GCC_BAD ("string literal with user-defined suffix is invalid in this "
-            "context");
+    {
+      warning_at (loc, OPT_Wpragmas,
+                 "string literal with user-defined suffix is invalid in this "
+                 "context");
+      return;
+    }
   else
-    GCC_BAD ("expected a string after %<#pragma message%>");
+    {
+      label_text doc_url (p.get_doc_url ());
+      warning_at (loc, OPT_Wpragmas,
+                 "expected a string after %<%{#pragma message%}%>",
+                 doc_url.get ());
+      return;
+    }
 
   gcc_assert (message);
 
-  if (pragma_lex (&x, &loc) != CPP_EOF)
-    warning_at (loc, OPT_Wpragmas, "junk at end of %<#pragma message%>");
+  p.check_for_trailing_junk ();
 
   if (TREE_STRING_LENGTH (message) > 1)
     inform (input_location, "%<#pragma message: %s%>",
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index 682157a4517..abaf897d84d 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -203,10 +203,13 @@ enum pragma_omp_clause {
 
 extern struct cpp_reader* parse_in;
 
+class pragma_parser;
+
 /* It's safe to always leave visibility pragma enabled as if
    visibility is not supported on the host OS platform the
    statements are ignored.  */
-extern void push_visibility (const char *, int);
+extern void push_visibility (const char *, int,
+                            const pragma_parser *p = nullptr);
 extern bool pop_visibility (int);
 
 extern void init_pragma (void);
diff --git a/gcc/testsuite/c-c++-common/pragma-message-parsing.c 
b/gcc/testsuite/c-c++-common/pragma-message-parsing.c
new file mode 100644
index 00000000000..4acb9d16c51
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pragma-message-parsing.c
@@ -0,0 +1,21 @@
+/* Test that we provide good warnings for malformed '#pragma message'.  */
+
+#pragma message  /* { dg-line no_arg } */
+/* { dg-warning "expected a string after '#pragma message'" "" { target *-*-* 
} no_arg } */
+
+#pragma message 1066  /* { dg-line bad_arg } */
+/* { dg-warning "17: expected a string after '#pragma message'" "" { target 
*-*-* } bad_arg } */
+
+#pragma message "foo" /* { dg-message "#pragma message: foo" } */
+
+#pragma message(1066)  /* { dg-line parens_bad_arg } */
+/* { dg-warning "17: expected a string after '#pragma message'" "" { target 
*-*-* } parens_bad_arg } */
+
+#pragma message("bar") /* { dg-message "#pragma message: bar" } */
+
+#pragma message("foo") bar  /* { dg-warning "24: junk at end of '#pragma 
message'" } */
+
+#if defined(__cplusplus) && __cplusplus >= 201103L
+unsigned operator ""_w(const char*);
+#pragma message "foo"_w /* { dg-message "17: string literal with user-defined 
suffix is invalid in this context" "" { target { c++11 } } } */
+#endif
diff --git a/gcc/testsuite/c-c++-common/pragma-optimize-parsing.c 
b/gcc/testsuite/c-c++-common/pragma-optimize-parsing.c
new file mode 100644
index 00000000000..4808ce3992a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pragma-optimize-parsing.c
@@ -0,0 +1,16 @@
+/* Test that we provide good warnings for malformed '#pragma GCC optimize'.  */
+
+#pragma GCC optimize /* { dg-warning "'#pragma GCC optimize' is not a string 
or number" } */
+#pragma GCC optimize 3
+#pragma GCC optimize(  /* { dg-warning "'#pragma GCC optimize' is not a string 
or number" } */
+#pragma GCC optimize() /* { dg-warning "'#pragma GCC optimize' is not a string 
or number" } */
+#pragma GCC optimize(3, )
+#pragma GCC optimize("-O3", )
+#pragma GCC optimize(3, /* { dg-warning "'#pragma GCC optimize \\(string 
\\\[,string\\\]...\\)' does not have a final '\\)'" } */
+
+void foo ()
+{
+#pragma GCC optimize /* { dg-error "#pragma GCC optimize' is not allowed 
inside functions" } */ 
+}
+
+#pragma GCC optimize("-Ofan-noise", ) /* { dg-error "argument to '-O' should 
be a non-negative integer, 'g', 's', 'z' or 'fast'" } */
diff --git a/gcc/testsuite/c-c++-common/pragma-pack-parsing-1.c 
b/gcc/testsuite/c-c++-common/pragma-pack-parsing-1.c
new file mode 100644
index 00000000000..0e3d806388a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pragma-pack-parsing-1.c
@@ -0,0 +1,19 @@
+/* Test that we provide good warnings for malformed '#pragma pack'.  */
+
+#pragma pack  /* { dg-warning "ignoring malformed '#pragma pack': expected 
'\\('" } */
+
+#pragma pack 42  /* { dg-warning "14: ignoring malformed '#pragma pack': 
expected '\\('" } */
+
+#pragma pack(3.141)  /* { dg-warning "14: ignoring malformed '#pragma pack': 
invalid constant" } */
+
+#pragma pack((  /* { dg-warning "14: ignoring malformed '#pragma pack': 
expected '\\)', integer, 'push', or 'pop'" }  */
+
+#pragma pack(42  /* { dg-warning "ignoring malformed '#pragma pack': expected 
'\\)'" } */
+
+#pragma pack(42)  /* { dg-warning "14: ignoring malformed '#pragma pack': 
alignment must be a small power of two, not 42" }  */
+
+#pragma pack(foo  /* { dg-warning "14: ignoring malformed '#pragma pack': 
unknown action 'foo'" } */
+
+#pragma pack(push, 3.141  /* { dg-warning "20: ignoring malformed '#pragma 
pack': invalid constant" }  */
+
+#pragma pack(push, 42)  /* { dg-warning "20: ignoring malformed '#pragma 
pack': alignment must be a small power of two, not 42" }  */
diff --git a/gcc/testsuite/c-c++-common/pragma-pack-parsing-2.c 
b/gcc/testsuite/c-c++-common/pragma-pack-parsing-2.c
new file mode 100644
index 00000000000..efca44e8734
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pragma-pack-parsing-2.c
@@ -0,0 +1,4 @@
+/* Test that we provide good warnings for malformed '#pragma pack'.  */
+/* { dg-options "-fpack-struct" } */
+
+#pragma pack(16) /* { dg-warning "'#pragma pack' has no effect with 
'-fpack-struct' - ignored" } */
diff --git a/gcc/testsuite/c-c++-common/pragma-redefine_extname-parsing.c 
b/gcc/testsuite/c-c++-common/pragma-redefine_extname-parsing.c
new file mode 100644
index 00000000000..19f4f1b766e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pragma-redefine_extname-parsing.c
@@ -0,0 +1,9 @@
+/* Test that we provide good warnings for malformed '#pragma 
redefine_extname'.  */
+
+/* Missing old name.  */
+#pragma redefine_extname /* { dg-warning "ignoring malformed '#pragma 
redefine_extname': expected symbol name" } */
+#pragma redefine_extname 42 /* { dg-warning "26: ignoring malformed '#pragma 
redefine_extname': expected symbol name" } */
+
+/* Missing new name.  */
+#pragma redefine_extname foo /* { dg-warning "ignoring malformed '#pragma 
redefine_extname': expected symbol name" } */
+#pragma redefine_extname foo 42 /* { dg-warning "30: ignoring malformed 
'#pragma redefine_extname': expected symbol name" } */
diff --git a/gcc/testsuite/c-c++-common/pragma-target-parsing.c 
b/gcc/testsuite/c-c++-common/pragma-target-parsing.c
new file mode 100644
index 00000000000..37e331626e9
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pragma-target-parsing.c
@@ -0,0 +1,14 @@
+/* Test that we provide good warnings for malformed '#pragma target'.  */
+
+#pragma GCC target /* { dg-warning "ignoring malformed '#pragma GCC target': 
expected a string option" } */
+#pragma GCC target 1066 /* { dg-warning "ignoring malformed '#pragma GCC 
target': expected a string option" } */
+#pragma GCC target( /* { dg-warning "ignoring malformed '#pragma GCC target': 
expected a string option" } */
+#pragma GCC target() /* { dg-warning "ignoring malformed '#pragma GCC target': 
expected a string option" } */
+#pragma GCC target("", )
+#pragma GCC target("",  /* { dg-warning "'#pragma GCC target \\(string 
\\\[,string\\\]...\\)' does not have a final '\\)'" } */
+
+void foo ()
+{
+#pragma GCC target /* { dg-error "#pragma GCC target option' is not allowed 
inside functions" } */
+  /* { dg-warning "ignoring malformed '#pragma GCC target': expected a string 
option" "" { target c++ } .-1 } */
+}
diff --git a/gcc/testsuite/c-c++-common/pragma-visibility-parsing.c 
b/gcc/testsuite/c-c++-common/pragma-visibility-parsing.c
new file mode 100644
index 00000000000..19ad6758b8c
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pragma-visibility-parsing.c
@@ -0,0 +1,13 @@
+/* Test that we provide good warnings for malformed '#pragma GCC visibility'.  
*/
+
+#pragma GCC visibility /* { dg-line no_action } */
+/* { dg-warning "'#pragma GCC visibility' must be followed by 'push' or 'pop'" 
"" { target *-*-* } no_action } */
+
+#pragma GCC visibility push 1066  /* { dg-warning "29: ignoring malformed 
'#pragma GCC visibility': expected '\\('" } */
+
+#pragma GCC visibility push(foo) /* { dg-line bad_push_arg } */
+/* { dg-warning "29: '#pragma GCC visibility push\\(\\)' must specify 
'default', 'internal', 'hidden' or 'protected'" "" { target *-*-* } 
bad_push_arg }
+   { dg-message "ignoring malformed '#pragma GCC visibility'" "" { target 
*-*-* } bad_push_arg } */
+
+#pragma GCC visibility push(default)
+#pragma GCC visibility pop 1066  /* { dg-warning "28: junk at end of '#pragma 
GCC visibility'" } */
diff --git a/gcc/testsuite/c-c++-common/pragma-weak-parsing.c 
b/gcc/testsuite/c-c++-common/pragma-weak-parsing.c
new file mode 100644
index 00000000000..902044a2b20
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pragma-weak-parsing.c
@@ -0,0 +1,24 @@
+/* Test that we provide good warnings for malformed '#pragma weak'.  */
+
+int bar;
+
+#pragma weak  /* { dg-warning "ignoring malformed '#pragma weak': expected 
name" } */
+
+#pragma weak 42  /* { dg-warning "14: ignoring malformed '#pragma weak': 
expected name" } */
+
+/* This should be OK.  */
+#pragma weak foo
+
+#pragma weak foo 1066  /* { dg-warning "18: junk at end of '#pragma weak'" } */
+
+#pragma weak foo =  /* { dg-warning "ignoring malformed '#pragma weak': 
expected name" } */
+
+#pragma weak foo = 1066  /* { dg-warning "20: ignoring malformed '#pragma 
weak': expected name" } */
+
+/* This should be OK.  */
+#pragma weak foo = bar
+
+#pragma weak foo = bar baz /* { dg-warning "24: junk at end of '#pragma weak'" 
} */
+
+typedef int foo_t; /* { dg-message "13: 'foo_t' is not a variable or function" 
} */
+#pragma weak foo_t /* { dg-warning "14: '#pragma weak' declaration of 'foo_t' 
not allowed, ignored" } */
diff --git a/gcc/testsuite/gcc.dg/bad-pragma-locations.c 
b/gcc/testsuite/gcc.dg/bad-pragma-locations.c
index 8068839881d..6bf821d8e2a 100644
--- a/gcc/testsuite/gcc.dg/bad-pragma-locations.c
+++ b/gcc/testsuite/gcc.dg/bad-pragma-locations.c
@@ -7,42 +7,42 @@
 /* pack 
****************************************************************************/
 
 #pragma pack
-/* { dg-warning "missing '\\(' after '#pragma pack' - ignored" "" { target 
*-*-* } .-1 }
+/* { dg-warning "ignoring malformed '#pragma pack': expected '\\('" "" { 
target *-*-* } .-1 }
    { dg-begin-multiline-output "" }
  #pragma pack
-         ^~~~
+             ^
    { dg-end-multiline-output "" }  */
 
 #pragma pack (
-/* { dg-warning "malformed '#pragma pack' - ignored" "" { target *-*-* } .-1 }
+/* { dg-warning "ignoring malformed '#pragma pack': expected '\\)', integer, 
'push', or 'pop'" "" { target *-*-* } .-1 }
    { dg-begin-multiline-output "" }
  #pragma pack (
-         ^~~~
+               ^
    { dg-end-multiline-output "" }  */
 
 #pragma pack (32
-/* { dg-warning "malformed '#pragma pack' - ignored" "" { target *-*-* } .-1 }
+/* { dg-warning "ignoring malformed '#pragma pack': expected '\\)'" "" { 
target *-*-* } .-1 }
    { dg-begin-multiline-output "" }
  #pragma pack (32
-         ^~~~
+                 ^
    { dg-end-multiline-output "" }  */
 
 #pragma pack (3.14159
-/* { dg-warning "invalid constant in '#pragma pack' - ignored" "" { target 
*-*-* } .-1 }
+/* { dg-warning "ignoring malformed '#pragma pack': invalid constant" "" { 
target *-*-* } .-1 }
    { dg-begin-multiline-output "" }
  #pragma pack (3.14159
                ^~~~~~~
    { dg-end-multiline-output "" }  */
 
 #pragma pack (push, 3.14159
-/* { dg-warning "invalid constant in '#pragma pack' - ignored" "" { target 
*-*-* } .-1 }
+/* { dg-warning "ignoring malformed '#pragma pack': invalid constant" "" { 
target *-*-* } .-1 }
    { dg-begin-multiline-output "" }
  #pragma pack (push, 3.14159
                      ^~~~~~~
    { dg-end-multiline-output "" }  */
 
 #pragma pack (toothbrush
-/* { dg-warning "unknown action 'toothbrush' for '#pragma pack' - ignored" "" 
{ target *-*-* } .-1 }
+/* { dg-warning "ignoring malformed '#pragma pack': unknown action 
'toothbrush'" "" { target *-*-* } .-1 }
    { dg-begin-multiline-output "" }
  #pragma pack (toothbrush
                ^~~~~~~~~~
@@ -58,14 +58,14 @@
 /* target 
****************************************************************************/
 
 #pragma GCC target 42
-/* { dg-warning "#pragma GCC option' is not a string" "" { target *-*-* } .-1 }
+/* { dg-warning "ignoring malformed '#pragma GCC target': expected a string 
option" "" { target *-*-* } .-1 }
    { dg-begin-multiline-output "" }
  #pragma GCC target 42
                     ^~
    { dg-end-multiline-output "" }  */
 
 #pragma GCC target ( 1776
-/* { dg-warning "#pragma GCC option' is not a string" "" { target *-*-* } .-1 }
+/* { dg-warning "ignoring malformed '#pragma GCC target': expected a string 
option" "" { target *-*-* } .-1 }
    { dg-begin-multiline-output "" }
  #pragma GCC target ( 1776
                       ^~~~
diff --git a/gcc/testsuite/gcc.dg/pragma-scalar_storate_order-parsing.c 
b/gcc/testsuite/gcc.dg/pragma-scalar_storate_order-parsing.c
new file mode 100644
index 00000000000..b20f41caba8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pragma-scalar_storate_order-parsing.c
@@ -0,0 +1,8 @@
+/* Test that we provide good warnings for malformed '#pragma 
scalar_storage_order'.  */
+
+#pragma scalar_storage_order /* { dg-warning "ignoring malformed '#pragma 
scalar_storage_order': expected 'big-endian', 'little-endian', or 'default'" } 
*/
+#pragma scalar_storage_order 1066 /* { dg-warning "ignoring malformed '#pragma 
scalar_storage_order': expected 'big-endian', 'little-endian', or 'default'" } 
*/
+#pragma scalar_storage_order foo /* { dg-warning "ignoring malformed '#pragma 
scalar_storage_order': expected 'big-endian', 'little-endian', or 'default'" } 
*/
+#pragma scalar_storage_order little-endian
+#pragma scalar_storage_order big-endian
+#pragma scalar_storage_order default
diff --git a/gcc/testsuite/gcc.dg/sso-6.c b/gcc/testsuite/gcc.dg/sso-6.c
index 559253293b5..3654ffcb847 100644
--- a/gcc/testsuite/gcc.dg/sso-6.c
+++ b/gcc/testsuite/gcc.dg/sso-6.c
@@ -3,7 +3,7 @@
 /* { dg-do run } */
 /* { dg-require-effective-target int32plus } */
 
-#pragma scalar_storage_order /* { dg-warning "missing .big-endian., 
.little-endian., or .default." } */
+#pragma scalar_storage_order /* { dg-warning "expected .big-endian., 
.little-endian., or .default." } */
 
 #pragma scalar_storage_order big-endian
 
-- 
2.26.3

Reply via email to