c: more precise locations for some -Wpragmas diagnostics
authorDavid Malcolm <dmalcolm@redhat.com>
Thu, 4 Nov 2021 21:58:27 +0000 (17:58 -0400)
committerDavid Malcolm <dmalcolm@redhat.com>
Tue, 9 Nov 2021 23:25:44 +0000 (18:25 -0500)
gcc/c-family/ChangeLog:
* c-pragma.c (GCC_BAD_AT): New macro.
(GCC_BAD2_AT): New macro.
(handle_pragma_pack): Use the location of the pertinent token when
issuing diagnostics about invalid constants/actions, and trailing
junk.
(handle_pragma_target): Likewise for non-string "GCC option".
(handle_pragma_message): Likewise for trailing junk.

gcc/testsuite/ChangeLog:
* gcc.dg/bad-pragma-locations.c: New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
gcc/c-family/c-pragma.c
gcc/testsuite/gcc.dg/bad-pragma-locations.c [new file with mode: 0644]

index a9be8df..b2ad991 100644 (file)
@@ -39,6 +39,10 @@ along with GCC; see the file COPYING3.  If not see
   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)
 
 struct GTY(()) align_stack {
   int                 alignment;
@@ -130,6 +134,7 @@ pop_alignment (tree id)
 static void
 handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
 {
+  location_t loc;
   tree x, id = 0;
   int align = -1;
   enum cpp_ttype token;
@@ -138,7 +143,7 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
   if (pragma_lex (&x) != CPP_OPEN_PAREN)
     GCC_BAD ("missing %<(%> after %<#pragma pack%> - ignored");
 
-  token = pragma_lex (&x);
+  token = pragma_lex (&x, &loc);
   if (token == CPP_CLOSE_PAREN)
     {
       action = set;
@@ -147,7 +152,7 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
   else if (token == CPP_NUMBER)
     {
       if (TREE_CODE (x) != INTEGER_CST)
-       GCC_BAD ("invalid constant in %<#pragma pack%> - ignored");
+       GCC_BAD_AT (loc, "invalid constant in %<#pragma pack%> - ignored");
       align = TREE_INT_CST_LOW (x);
       action = set;
       if (pragma_lex (&x) != CPP_CLOSE_PAREN)
@@ -167,11 +172,12 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
       else if (!strcmp (op, "pop"))
        action = pop;
       else
-       GCC_BAD2 ("unknown action %qE for %<#pragma pack%> - ignored", x);
+       GCC_BAD2_AT (loc, "unknown action %qE for %<#pragma pack%> - ignored",
+                    x);
 
       while ((token = pragma_lex (&x)) == CPP_COMMA)
        {
-         token = pragma_lex (&x);
+         token = pragma_lex (&x, &loc);
          if (token == CPP_NAME && id == 0)
            {
              id = x;
@@ -179,7 +185,8 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
          else if (token == CPP_NUMBER && action == push && align == -1)
            {
              if (TREE_CODE (x) != INTEGER_CST)
-               GCC_BAD ("invalid constant in %<#pragma pack%> - ignored");
+               GCC_BAD_AT (loc,
+                           "invalid constant in %<#pragma pack%> - ignored");
              align = TREE_INT_CST_LOW (x);
              if (align == -1)
                action = set;
@@ -195,8 +202,8 @@ handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
   else
     GCC_BAD ("malformed %<#pragma pack%> - ignored");
 
-  if (pragma_lex (&x) != CPP_EOF)
-    warning (OPT_Wpragmas, "junk at end of %<#pragma pack%>");
+  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");
@@ -857,6 +864,7 @@ handle_pragma_diagnostic(cpp_reader *ARG_UNUSED(dummy))
 static void
 handle_pragma_target(cpp_reader *ARG_UNUSED(dummy))
 {
+  location_t loc;
   enum cpp_ttype token;
   tree x;
   bool close_paren_needed_p = false;
@@ -867,16 +875,16 @@ handle_pragma_target(cpp_reader *ARG_UNUSED(dummy))
       return;
     }
 
-  token = pragma_lex (&x);
+  token = pragma_lex (&x, &loc);
   if (token == CPP_OPEN_PAREN)
     {
       close_paren_needed_p = true;
-      token = pragma_lex (&x);
+      token = pragma_lex (&x, &loc);
     }
 
   if (token != CPP_STRING)
     {
-      GCC_BAD ("%<#pragma GCC option%> is not a string");
+      GCC_BAD_AT (loc, "%<#pragma GCC option%> is not a string");
       return;
     }
 
@@ -1149,6 +1157,7 @@ handle_pragma_reset_options (cpp_reader *ARG_UNUSED(dummy))
 static void
 handle_pragma_message (cpp_reader *ARG_UNUSED(dummy))
 {
+  location_t loc;
   enum cpp_ttype token;
   tree x, message = 0;
 
@@ -1170,8 +1179,8 @@ handle_pragma_message (cpp_reader *ARG_UNUSED(dummy))
 
   gcc_assert (message);
 
-  if (pragma_lex (&x) != CPP_EOF)
-    warning (OPT_Wpragmas, "junk at end of %<#pragma message%>");
+  if (pragma_lex (&x, &loc) != CPP_EOF)
+    warning_at (loc, OPT_Wpragmas, "junk at end of %<#pragma message%>");
 
   if (TREE_STRING_LENGTH (message) > 1)
     inform (input_location, "%<#pragma message: %s%>",
diff --git a/gcc/testsuite/gcc.dg/bad-pragma-locations.c b/gcc/testsuite/gcc.dg/bad-pragma-locations.c
new file mode 100644 (file)
index 0000000..8068839
--- /dev/null
@@ -0,0 +1,86 @@
+/* Verify that we use precise locations when emitting diagnostics
+   about pragmas.  */
+
+/* { dg-do assemble } */
+/* { dg-options "-fdiagnostics-show-caret" } */
+
+/* pack ****************************************************************************/
+
+#pragma pack
+/* { dg-warning "missing '\\(' after '#pragma pack' - ignored" "" { target *-*-* } .-1 }
+   { dg-begin-multiline-output "" }
+ #pragma pack
+         ^~~~
+   { dg-end-multiline-output "" }  */
+
+#pragma pack (
+/* { dg-warning "malformed '#pragma pack' - ignored" "" { target *-*-* } .-1 }
+   { dg-begin-multiline-output "" }
+ #pragma pack (
+         ^~~~
+   { dg-end-multiline-output "" }  */
+
+#pragma pack (32
+/* { dg-warning "malformed '#pragma pack' - ignored" "" { 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-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-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-begin-multiline-output "" }
+ #pragma pack (toothbrush
+               ^~~~~~~~~~
+   { dg-end-multiline-output "" }  */
+
+#pragma pack() pyjamas
+/* { dg-warning "junk at end of '#pragma pack'" "" { target *-*-* } .-1 }
+   { dg-begin-multiline-output "" }
+ #pragma pack() pyjamas
+                ^~~~~~~
+   { dg-end-multiline-output "" }  */
+
+/* target ****************************************************************************/
+
+#pragma GCC target 42
+/* { dg-warning "#pragma GCC option' is not a string" "" { 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-begin-multiline-output "" }
+ #pragma GCC target ( 1776
+                      ^~~~
+   { dg-end-multiline-output "" }  */
+
+/* message ****************************************************************************/
+
+#pragma message "foo" int
+/* { dg-warning "junk at end of '#pragma message'" "" { target *-*-* } .-1 }
+   { dg-message "'#pragma message: foo'" "" { target *-*-* } .-2 }
+   { dg-begin-multiline-output "" }
+ #pragma message "foo" int
+                       ^~~
+   { dg-end-multiline-output "" }
+   { dg-begin-multiline-output "" }
+ #pragma message "foo" int
+         ^~~~~~~
+   { dg-end-multiline-output "" }  */