@@ -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%>",
@@ -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);
new file mode 100644
@@ -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
new file mode 100644
@@ -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'" } */
new file mode 100644
@@ -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" } */
new file mode 100644
@@ -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" } */
new file mode 100644
@@ -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" } */
new file mode 100644
@@ -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 } */
+}
new file mode 100644
@@ -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'" } */
new file mode 100644
@@ -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" } */
@@ -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
^~~~
new file mode 100644
@@ -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
@@ -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