[committed] c: more precise locations for some -Wpragmas diagnostics

Message ID 20211109233003.1758273-1-dmalcolm@redhat.com
State Committed
Commit 8722a17067f1590e82f49b3fd385647b762a45dc
Headers
Series [committed] c: more precise locations for some -Wpragmas diagnostics |

Commit Message

David Malcolm Nov. 9, 2021, 11:30 p.m. UTC
  Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as 8722a17067f1590e82f49b3fd385647b762a45dc.

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                     | 33 +++++---
 gcc/testsuite/gcc.dg/bad-pragma-locations.c | 86 +++++++++++++++++++++
 2 files changed, 107 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/bad-pragma-locations.c
  

Patch

diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index a9be8df0384..b2ad991008a 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -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
index 00000000000..8068839881d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/bad-pragma-locations.c
@@ -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 "" }  */