This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 1/2] c-family/c/c++: pass optional vec<location_t> to c-format.c


This patch passes along the vec<location_t> of argument locations
at a callsite from the C frontend to check_function_arguments and
from there to c-format.c, so that we can underline the pertinent
argument to mismatched format codes even for tree codes like decls
and constants which lack a location_t for their usage sites.

This takes e.g.:

    printf("hello %i %i %i ", foo, bar, baz);
                     ~^
                     %s

to:

    printf("hello %i %i %i ", foo, bar, baz);
                     ~^            ~~~
                     %s

which is useful for cases where there's more than one variadic argument.

Successfully bootstrapped&regrtested on x86_64-pc-linux-gnu.

OK for trunk?

gcc/c-family/ChangeLog:
	* c-common.c (check_function_arguments): Add "arglogs" param; pass
	it to check_function_format.
	* c-common.h (check_function_arguments): Add vec<location_t> *
	param.
	(check_function_format): Likewise.
	* c-format.c (struct format_check_context): Add field "arglocs".
	(check_function_format): Add param "arglocs"; pass it to
	check_format_info.
	(check_format_info):  Add param "arglocs"; use it to initialize
	new field of format_ctx.
	(check_format_arg): Pass format_ctx->arglocs to new param of
	check_format_info_main.
	(class argument_parser): New field "arglocs".
	(argument_parser::argument_parser): Add "arglocs_" param and use
	it to initialize new field.
	(argument_parser::check_argument_type): Pass new arglocs field to
	check_format_types.
	(check_format_info_main): Add param "arglocs", and use it when
	constructing arg_parser.
	(check_format_types): Add param "arglocs"; use it if non-NULL when
	!EXPR_HAS_LOCATION (cur_param) to get at location information.

gcc/c/ChangeLog:
	* c-typeck.c (build_function_call_vec): Pass arg_loc to call
	to check_function_arguments.

gcc/cp/ChangeLog:
	* call.c (build_over_call): Pass NULL for new parameter to
	check_function_arguments.
	* typeck.c (cp_build_function_call_vec): Likewise.

gcc/testsuite/ChangeLog:
	* gcc.dg/format/diagnostic-ranges.c: Update expected results
	to show underlining of all pertinent params.
	* gcc.dg/format/pr72858.c: Likewise.
---
 gcc/c-family/c-common.c                         |   4 +-
 gcc/c-family/c-common.h                         |   4 +-
 gcc/c-family/c-format.c                         |  52 ++++++++----
 gcc/c/c-typeck.c                                |   2 +-
 gcc/cp/call.c                                   |   2 +-
 gcc/cp/typeck.c                                 |   2 +-
 gcc/testsuite/gcc.dg/format/diagnostic-ranges.c |  41 ++++------
 gcc/testsuite/gcc.dg/format/pr72858.c           | 102 +++++++++---------------
 8 files changed, 98 insertions(+), 111 deletions(-)

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 4dc3b33..156c89d 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -5539,7 +5539,7 @@ attribute_fallthrough_p (tree attr)
    diagnostics.  Return true if -Wnonnull warning has been diagnosed.  */
 bool
 check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype,
-			  int nargs, tree *argarray)
+			  int nargs, tree *argarray, vec<location_t> *arglocs)
 {
   bool warned_p = false;
 
@@ -5553,7 +5553,7 @@ check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype,
   /* Check for errors in format strings.  */
 
   if (warn_format || warn_suggest_attribute_format)
-    check_function_format (TYPE_ATTRIBUTES (fntype), nargs, argarray);
+    check_function_format (TYPE_ATTRIBUTES (fntype), nargs, argarray, arglocs);
 
   if (warn_format)
     check_function_sentinel (fntype, nargs, argarray);
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 980d396..8e36768 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -808,7 +808,7 @@ extern tree fname_decl (location_t, unsigned, tree);
 
 extern int check_user_alignment (const_tree, bool);
 extern bool check_function_arguments (location_t loc, const_tree, const_tree,
-				      int, tree *);
+				      int, tree *, vec<location_t> *);
 extern void check_function_arguments_recurse (void (*)
 					      (void *, tree,
 					       unsigned HOST_WIDE_INT),
@@ -816,7 +816,7 @@ extern void check_function_arguments_recurse (void (*)
 					      unsigned HOST_WIDE_INT);
 extern bool check_builtin_function_arguments (location_t, vec<location_t>,
 					      tree, int, tree *);
-extern void check_function_format (tree, int, tree *);
+extern void check_function_format (tree, int, tree *, vec<location_t> *);
 extern bool attribute_fallthrough_p (tree);
 extern tree handle_format_attribute (tree *, tree, tree, int, bool *);
 extern tree handle_format_arg_attribute (tree *, tree, tree, int, bool *);
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index 7c9095c..0dba979 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -989,6 +989,7 @@ struct format_check_context
   format_check_results *res;
   function_format_info *info;
   tree params;
+  vec<location_t> *arglocs;
 };
 
 /* Return the format name (as specified in the original table) for the format
@@ -1011,14 +1012,16 @@ format_flags (int format_num)
   gcc_unreachable ();
 }
 
-static void check_format_info (function_format_info *, tree);
+static void check_format_info (function_format_info *, tree,
+			       vec<location_t> *);
 static void check_format_arg (void *, tree, unsigned HOST_WIDE_INT);
 static void check_format_info_main (format_check_results *,
 				    function_format_info *, const char *,
 				    location_t, tree,
 				    int, tree,
 				    unsigned HOST_WIDE_INT,
-				    object_allocator<format_wanted_type> &);
+				    object_allocator<format_wanted_type> &,
+				    vec<location_t> *);
 
 static void init_dollar_format_checking (int, tree);
 static int maybe_read_dollar_number (const char **, int,
@@ -1033,7 +1036,8 @@ static void check_format_types (const substring_loc &fmt_loc,
 				format_wanted_type *,
 				const format_kind_info *fki,
 				int offset_to_type_start,
-				char conversion_char);
+				char conversion_char,
+				vec<location_t> *arglocs);
 static void format_type_warning (const substring_loc &fmt_loc,
 				 source_range *param_range,
 				 format_wanted_type *, tree,
@@ -1076,7 +1080,8 @@ decode_format_type (const char *s)
    attribute themselves.  */
 
 void
-check_function_format (tree attrs, int nargs, tree *argarray)
+check_function_format (tree attrs, int nargs, tree *argarray,
+		       vec<location_t> *arglocs)
 {
   tree a;
 
@@ -1097,7 +1102,7 @@ check_function_format (tree attrs, int nargs, tree *argarray)
 	      int i;
 	      for (i = nargs - 1; i >= 0; i--)
 		params = tree_cons (NULL_TREE, argarray[i], params);
-	      check_format_info (&info, params);
+	      check_format_info (&info, params, arglocs);
 	    }
 
 	  /* Attempt to detect whether the current function might benefit
@@ -1400,7 +1405,8 @@ get_flag_spec (const format_flag_spec *spec, int flag, const char *predicates)
    PARAMS is the list of argument values.  */
 
 static void
-check_format_info (function_format_info *info, tree params)
+check_format_info (function_format_info *info, tree params,
+		   vec<location_t> *arglocs)
 {
   format_check_context format_ctx;
   unsigned HOST_WIDE_INT arg_num;
@@ -1434,6 +1440,7 @@ check_format_info (function_format_info *info, tree params)
   format_ctx.res = &res;
   format_ctx.info = info;
   format_ctx.params = params;
+  format_ctx.arglocs = arglocs;
 
   check_function_arguments_recurse (check_format_arg, &format_ctx,
 				    format_tree, arg_num);
@@ -1518,6 +1525,7 @@ check_format_arg (void *ctx, tree format_tree,
   format_check_results *res = format_ctx->res;
   function_format_info *info = format_ctx->info;
   tree params = format_ctx->params;
+  vec<location_t> *arglocs = format_ctx->arglocs;
 
   int format_length;
   HOST_WIDE_INT offset;
@@ -1703,7 +1711,7 @@ check_format_arg (void *ctx, tree format_tree,
   res->number_other++;
   object_allocator <format_wanted_type> fwt_pool ("format_wanted_type pool");
   check_format_info_main (res, info, format_chars, fmt_param_loc, format_tree,
-			  format_length, params, arg_num, fwt_pool);
+			  format_length, params, arg_num, fwt_pool, arglocs);
 }
 
 /* Support class for argument_parser and check_format_info_main.
@@ -1768,7 +1776,8 @@ class argument_parser
 		   const char * const orig_format_chars,
 		   location_t format_string_loc, flag_chars_t &flag_chars,
 		   int &has_operand_number, tree first_fillin_param,
-		   object_allocator <format_wanted_type> &fwt_pool_);
+		   object_allocator <format_wanted_type> &fwt_pool_,
+		   vec<location_t> *arglocs);
 
   bool read_any_dollar ();
 
@@ -1847,6 +1856,7 @@ class argument_parser
  private:
   format_wanted_type *first_wanted_type;
   format_wanted_type *last_wanted_type;
+  vec<location_t> *arglocs;
 };
 
 /* flag_chars_t's constructor.  */
@@ -1997,7 +2007,8 @@ argument_parser (function_format_info *info_, const char *&format_chars_,
 		 flag_chars_t &flag_chars_,
 		 int &has_operand_number_,
 		 tree first_fillin_param_,
-		 object_allocator <format_wanted_type> &fwt_pool_)
+		 object_allocator <format_wanted_type> &fwt_pool_,
+		 vec<location_t> *arglocs_)
 : info (info_),
   fki (&format_types[info->format_type]),
   flag_specs (fki->flag_specs),
@@ -2013,7 +2024,8 @@ argument_parser (function_format_info *info_, const char *&format_chars_,
   has_operand_number (has_operand_number_),
   first_fillin_param (first_fillin_param_),
   first_wanted_type (NULL),
-  last_wanted_type (NULL)
+  last_wanted_type (NULL),
+  arglocs (arglocs_)
 {
 }
 
@@ -2736,7 +2748,7 @@ check_argument_type (const format_char_info *fci,
       ptrdiff_t offset_to_type_start = type_start - orig_format_chars;
       check_format_types (fmt_loc, first_wanted_type, fki,
 			  offset_to_type_start,
-			  conversion_char);
+			  conversion_char, arglocs);
     }
 
   return true;
@@ -2755,7 +2767,8 @@ check_format_info_main (format_check_results *res,
 			location_t fmt_param_loc, tree format_string_cst,
 			int format_length, tree params,
 			unsigned HOST_WIDE_INT arg_num,
-			object_allocator <format_wanted_type> &fwt_pool)
+			object_allocator <format_wanted_type> &fwt_pool,
+			vec<location_t> *arglocs)
 {
   const char * const orig_format_chars = format_chars;
   const tree first_fillin_param = params;
@@ -2802,7 +2815,7 @@ check_format_info_main (format_check_results *res,
       argument_parser arg_parser (info, format_chars, format_string_cst,
 				  orig_format_chars, format_string_loc,
 				  flag_chars, has_operand_number,
-				  first_fillin_param, fwt_pool);
+				  first_fillin_param, fwt_pool, arglocs);
 
       if (!arg_parser.read_any_dollar ())
 	return;
@@ -3032,7 +3045,8 @@ static void
 check_format_types (const substring_loc &fmt_loc,
 		    format_wanted_type *types, const format_kind_info *fki,
 		    int offset_to_type_start,
-		    char conversion_char)
+		    char conversion_char,
+		    vec<location_t> *arglocs)
 {
   for (; types != 0; types = types->next)
     {
@@ -3072,11 +3086,19 @@ check_format_types (const substring_loc &fmt_loc,
 
       source_range param_range;
       source_range *param_range_ptr;
-      if (CAN_HAVE_LOCATION_P (cur_param))
+      if (EXPR_HAS_LOCATION (cur_param))
 	{
 	  param_range = EXPR_LOCATION_RANGE (cur_param);
 	  param_range_ptr = &param_range;
 	}
+      else if (arglocs)
+	{
+	  /* arg_num is 1-based.  */
+	  gcc_assert (types->arg_num > 0);
+	  location_t param_loc = (*arglocs)[types->arg_num - 1];
+	  param_range = get_range_from_loc (line_table, param_loc);
+	  param_range_ptr = &param_range;
+	}
       else
 	param_range_ptr = NULL;
 
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index c33601f..d7ca148 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -3118,7 +3118,7 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc,
 
   /* Check that the arguments to the function are valid.  */
   bool warned_p = check_function_arguments (loc, fundecl, fntype,
-					    nargs, argarray);
+					    nargs, argarray, &arg_loc);
 
   if (name != NULL_TREE
       && !strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10))
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 3790299..067db59a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7949,7 +7949,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 	fargs[j] = maybe_constant_value (argarray[j]);
 
       warned_p = check_function_arguments (input_location, fn, TREE_TYPE (fn),
-					   nargs, fargs);
+					   nargs, fargs, NULL);
     }
 
   if (DECL_INHERITED_CTOR (fn))
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index a5a363b..63667f3 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3699,7 +3699,7 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params,
   /* Check for errors in format strings and inappropriately
      null parameters.  */
   bool warned_p = check_function_arguments (input_location, fndecl, fntype,
-					    nargs, argarray);
+					    nargs, argarray, NULL);
 
   ret = build_cxx_call (function, nargs, argarray, complain);
 
diff --git a/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c b/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
index 8cce5b3..bc6f665 100644
--- a/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
+++ b/gcc/testsuite/gcc.dg/format/diagnostic-ranges.c
@@ -8,28 +8,24 @@ void test_mismatching_types (const char *msg)
 {
   printf("hello %i", msg);  /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'const char \\*' " } */
 
-/* TODO: ideally would also underline "msg".  */
 /* { dg-begin-multiline-output "" }
    printf("hello %i", msg);
-                 ~^
+                 ~^   ~~~
                  %s
    { dg-end-multiline-output "" } */
 
 
   printf("hello %s", 42);  /* { dg-warning "format '%s' expects argument of type 'char \\*', but argument 2 has type 'int'" } */
-/* TODO: ideally would also underline "42".  */
 /* { dg-begin-multiline-output "" }
    printf("hello %s", 42);
-                 ~^
+                 ~^   ~~
                  %d
    { dg-end-multiline-output "" } */
 
-
   printf("hello %i", (long)0);  /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'long int' " } */
-/* TODO: ideally would also underline the argument.  */
 /* { dg-begin-multiline-output "" }
    printf("hello %i", (long)0);
-                 ~^
+                 ~^   ~
                  %li
    { dg-end-multiline-output "" } */
 }
@@ -38,11 +34,12 @@ void test_multiple_arguments (void)
 {
   printf ("arg0: %i  arg1: %s arg 2: %i", /* { dg-warning "29: format '%s'" } */
           100, 101, 102);
-/* TODO: ideally would also underline "101".  */
 /* { dg-begin-multiline-output "" }
    printf ("arg0: %i  arg1: %s arg 2: %i",
                             ~^
                             %d
+           100, 101, 102);
+                ~~~           
    { dg-end-multiline-output "" } */
 }
 
@@ -84,10 +81,9 @@ void test_hex (const char *msg)
      "i" is \x69 */
   printf("hello \x25\x69", msg);  /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'const char \\*' " } */
 
-/* TODO: ideally would also underline "msg".  */
 /* { dg-begin-multiline-output "" }
    printf("hello \x25\x69", msg);
-                 ~~~~^~~~
+                 ~~~~^~~~   ~~~
                  \x25s
    { dg-end-multiline-output "" } */
 }
@@ -98,10 +94,9 @@ void test_oct (const char *msg)
      "i" is octal 151.  */
   printf("hello \045\151", msg);  /* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'const char \\*' " } */
 
-/* TODO: ideally would also underline "msg".  */
 /* { dg-begin-multiline-output "" }
    printf("hello \045\151", msg);
-                 ~~~~^~~~
+                 ~~~~^~~~   ~~~
                  \045s
    { dg-end-multiline-output "" } */
 }
@@ -115,9 +110,10 @@ void test_multiple (const char *msg)
 /* { dg-begin-multiline-output "" }
    printf("prefix"  "\x25"  "\151"  "suffix",
           ^~~~~~~~
+          msg);
+          ~~~
   { dg-end-multiline-output "" } */
 
-/* TODO: ideally would also underline "msg".  */
 /* { dg-begin-multiline-output "" }
    printf("prefix"  "\x25"  "\151"  "suffix",
                      ~~~~~~~~^~~~
@@ -128,10 +124,9 @@ void test_multiple (const char *msg)
 void test_u8 (const char *msg)
 {
   printf(u8"hello %i", msg);/* { dg-warning "format '%i' expects argument of type 'int', but argument 2 has type 'const char \\*' " } */
-/* TODO: ideally would also underline "msg".  */
 /* { dg-begin-multiline-output "" }
    printf(u8"hello %i", msg);
-                   ~^
+                   ~^   ~~~
                    %s
    { dg-end-multiline-output "" } */
 }
@@ -151,7 +146,7 @@ void test_field_width_specifier (long l, int i1, int i2)
   printf (" %*.*d ", l, i1, i2); /* { dg-warning "14: field width specifier '\\*' expects argument of type 'int', but argument 2 has type 'long int'" } */
 /* { dg-begin-multiline-output "" }
    printf (" %*.*d ", l, i1, i2);
-             ~^~~~
+             ~^~~~    ~
    { dg-end-multiline-output "" } */
 }
 
@@ -160,10 +155,9 @@ void test_field_width_specifier (long l, int i1, int i2)
 void test_field_width_specifier_2 (char *d, long foo, long bar)
 {
   __builtin_sprintf (d, " %*ld ", foo, foo); /* { dg-warning "28: field width specifier '\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */
-  /* TODO: ideally we'd underline the first "foo" here".  */
   /* { dg-begin-multiline-output "" }
    __builtin_sprintf (d, " %*ld ", foo, foo);
-                           ~^~~
+                           ~^~~    ~~~
    { dg-end-multiline-output "" } */
 
   __builtin_sprintf (d, " %*ld ", foo + bar, foo); /* { dg-warning "28: field width specifier '\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */
@@ -176,10 +170,9 @@ void test_field_width_specifier_2 (char *d, long foo, long bar)
 void test_field_precision_specifier (char *d, long foo, long bar)
 {
   __builtin_sprintf (d, " %.*ld ", foo, foo); /* { dg-warning "29: field precision specifier '\\.\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */
-  /* TODO: ideally we'd underline the first "foo" here".  */
   /* { dg-begin-multiline-output "" }
    __builtin_sprintf (d, " %.*ld ", foo, foo);
-                           ~~^~~
+                           ~~^~~    ~~~
    { dg-end-multiline-output "" } */
 
   __builtin_sprintf (d, " %.*ld ", foo + bar, foo); /* { dg-warning "29: field precision specifier '\\.\\*' expects argument of type 'int', but argument 3 has type 'long int'" } */
@@ -247,7 +240,7 @@ void test_macro (const char *msg)
   printf("hello " INT_FMT " world", msg);  /* { dg-warning "10: format '%i' expects argument of type 'int', but argument 2 has type 'const char \\*' " } */
 /* { dg-begin-multiline-output "" }
    printf("hello " INT_FMT " world", msg);
-          ^~~~~~~~
+          ^~~~~~~~                   ~~~
    { dg-end-multiline-output "" } */
 /* { dg-begin-multiline-output "" }
  #define INT_FMT "%i"
@@ -263,7 +256,7 @@ void test_macro_2 (const char *msg)
   printf("hello %" PRIu32 " world", msg);  /* { dg-warning "10: format '%u' expects argument of type 'unsigned int', but argument 2 has type 'const char \\*' " } */
 /* { dg-begin-multiline-output "" }
    printf("hello %" PRIu32 " world", msg);
-          ^~~~~~~~~
+          ^~~~~~~~~                  ~~~
    { dg-end-multiline-output "" } */
 /* { dg-begin-multiline-output "" }
  #define PRIu32 "u"
@@ -313,7 +306,7 @@ void test_non_contiguous_strings (void)
                                     /* { dg-message "26: format string is defined here" "" { target *-*-* } .-1 } */
   /* { dg-begin-multiline-output "" }
    __builtin_printf(" %" "d ", 0.5);
-                    ^~~~
+                    ^~~~       ~~~
    { dg-end-multiline-output "" } */
   /* { dg-begin-multiline-output "" }
    __builtin_printf(" %" "d ", 0.5);
@@ -330,6 +323,6 @@ void test_const_arrays (void)
   __builtin_printf(a, 0.5); /* { dg-warning "20: format .%d. expects argument of type .int., but argument 2 has type .double." } */
   /* { dg-begin-multiline-output "" }
    __builtin_printf(a, 0.5);
-                    ^
+                    ^  ~~~
    { dg-end-multiline-output "" } */
 }
diff --git a/gcc/testsuite/gcc.dg/format/pr72858.c b/gcc/testsuite/gcc.dg/format/pr72858.c
index c142d24..b8c5829 100644
--- a/gcc/testsuite/gcc.dg/format/pr72858.c
+++ b/gcc/testsuite/gcc.dg/format/pr72858.c
@@ -25,56 +25,49 @@ test_x (char *d,
   sprintf (d, " %-8x ", uiexpr);
 
   sprintf (d, " %-8x ", lexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long int'" } */
-/* TODO: ideally would also underline "lexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8x ", lexpr);
-                 ~~~^
+                 ~~~^    ~~~~~
                  %-8lx
    { dg-end-multiline-output "" } */
   sprintf (d, " %-8x ", ulexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long unsigned int'" } */
-/* TODO: ideally would also underline "lexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8x ", ulexpr);
-                 ~~~^
+                 ~~~^    ~~~~~~
                  %-8lx
    { dg-end-multiline-output "" } */
 
   sprintf (d, " %-8x ", llexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long long int'" } */
-/* TODO: ideally would also underline "lexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8x ", llexpr);
-                 ~~~^
+                 ~~~^    ~~~~~~
                  %-8llx
    { dg-end-multiline-output "" } */
   sprintf (d, " %-8x ", ullexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long long unsigned int'" } */
-/* TODO: ideally would also underline "lexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8x ", ullexpr);
-                 ~~~^
+                 ~~~^    ~~~~~~~
                  %-8llx
    { dg-end-multiline-output "" } */
 
   /* Floating-point arguments.  */
 
   sprintf (d, " %-8x ", fexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'double'" } */
-/* TODO: ideally would also underline "fexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8x ", fexpr);
-                 ~~~^
+                 ~~~^    ~~~~~
                  %-8f
    { dg-end-multiline-output "" } */
   sprintf (d, " %-8x ", dexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'double'" } */
-/* TODO: ideally would also underline "dexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8x ", dexpr);
-                 ~~~^
+                 ~~~^    ~~~~~
                  %-8f
    { dg-end-multiline-output "" } */
   sprintf (d, " %-8x ", ldexpr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'long double'" } */
-/* TODO: ideally would also underline "ldexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8x ", ldexpr);
-                 ~~~^
+                 ~~~^    ~~~~~~
                  %-8Lf
    { dg-end-multiline-output "" } */
 
@@ -82,7 +75,7 @@ test_x (char *d,
   sprintf (d, " %-8x ", ptr); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'void \\*'" } */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8x ", ptr);
-                 ~~~^
+                 ~~~^    ~~~
                  %-8p
    { dg-end-multiline-output "" } */
 
@@ -92,7 +85,7 @@ test_x (char *d,
   sprintf (d, " %-8x ", s); /* { dg-warning "20: format '%x' expects argument of type 'unsigned int', but argument 3 has type 'struct s'" } */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8x ", s);
-                 ~~~^
+                 ~~~^    ~
    { dg-end-multiline-output "" } */
 }
 
@@ -109,17 +102,15 @@ test_lx (char *d,
   /* Integer arguments.  */
 
   sprintf (d, " %-8lx ", iexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'int'" } */
-/* TODO: ideally would also underline "iexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8lx ", iexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~
                  %-8x
    { dg-end-multiline-output "" } */
   sprintf (d, " %-8lx ", uiexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int'" } */
-/* TODO: ideally would also underline "uiexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8lx ", uiexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~~
                  %-8x
    { dg-end-multiline-output "" } */
 
@@ -127,41 +118,36 @@ test_lx (char *d,
   sprintf (d, " %-8lx ", ulexpr);
 
   sprintf (d, " %-8lx ", llexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long long int'" } */
-/* TODO: ideally would also underline "llexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8lx ", llexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~~
                  %-8llx
    { dg-end-multiline-output "" } */
   sprintf (d, " %-8lx ", ullexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long long unsigned int'" } */
-/* TODO: ideally would also underline "ullexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8lx ", ullexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~~~
                  %-8llx
    { dg-end-multiline-output "" } */
 
   /* Floating-point arguments.  */
 
   sprintf (d, " %-8lx ", fexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'double'" } */
-/* TODO: ideally would also underline "fexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8lx ", fexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~
                  %-8f
    { dg-end-multiline-output "" } */
   sprintf (d, " %-8lx ", dexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'double'" } */
-/* TODO: ideally would also underline "dexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8lx ", dexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~
                  %-8f
    { dg-end-multiline-output "" } */
   sprintf (d, " %-8lx ", ldexpr); /* { dg-warning "21: format '%lx' expects argument of type 'long unsigned int', but argument 3 has type 'long double'" } */
-/* TODO: ideally would also underline "ldexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8lx ", ldexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~~
                  %-8Lf
    { dg-end-multiline-output "" } */
 }
@@ -181,32 +167,28 @@ test_o (char *d,
   sprintf (d, " %-8o ", uiexpr);
 
   sprintf (d, " %-8o ", lexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long int'" } */
-/* TODO: ideally would also underline "lexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8o ", lexpr);
-                 ~~~^
+                 ~~~^    ~~~~~
                  %-8lo
    { dg-end-multiline-output "" } */
   sprintf (d, " %-8o ", ulexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long unsigned int'" } */
-/* TODO: ideally would also underline "lexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8o ", ulexpr);
-                 ~~~^
+                 ~~~^    ~~~~~~
                  %-8lo
    { dg-end-multiline-output "" } */
 
   sprintf (d, " %-8o ", llexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long long int'" } */
-/* TODO: ideally would also underline "lexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8o ", llexpr);
-                 ~~~^
+                 ~~~^    ~~~~~~
                  %-8llo
    { dg-end-multiline-output "" } */
   sprintf (d, " %-8o ", ullexpr); /* { dg-warning "20: format '%o' expects argument of type 'unsigned int', but argument 3 has type 'long long unsigned int'" } */
-/* TODO: ideally would also underline "lexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8o ", ullexpr);
-                 ~~~^
+                 ~~~^    ~~~~~~~
                  %-8llo
    { dg-end-multiline-output "" } */
 }
@@ -223,17 +205,15 @@ test_lo (char *d,
   /* Integer arguments.  */
 
   sprintf (d, " %-8lo ", iexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'int'" } */
-/* TODO: ideally would also underline "iexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8lo ", iexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~
                  %-8o
    { dg-end-multiline-output "" } */
   sprintf (d, " %-8lo ", uiexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'unsigned int'" } */
-/* TODO: ideally would also underline "uiexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8lo ", uiexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~~
                  %-8o
    { dg-end-multiline-output "" } */
 
@@ -241,17 +221,15 @@ test_lo (char *d,
   sprintf (d, " %-8lo ", ulexpr);
 
   sprintf (d, " %-8lo ", llexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'long long int'" } */
-/* TODO: ideally would also underline "llexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8lo ", llexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~~
                  %-8llo
    { dg-end-multiline-output "" } */
   sprintf (d, " %-8lo ", ullexpr); /* { dg-warning "21: format '%lo' expects argument of type 'long unsigned int', but argument 3 has type 'long long unsigned int'" } */
-/* TODO: ideally would also underline "ullexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8lo ", ullexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~~~
                  %-8llo
    { dg-end-multiline-output "" } */
 }
@@ -265,10 +243,9 @@ test_e (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
   /* Integer arguments.  */
 
   sprintf (d, " %-8e ", iexpr); /* { dg-warning "20: format '%e' expects argument of type 'double', but argument 3 has type 'int'" } */
-/* TODO: ideally would also underline "iexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8e ", iexpr);
-                 ~~~^
+                 ~~~^    ~~~~~
                  %-8d
    { dg-end-multiline-output "" } */
 
@@ -277,10 +254,9 @@ test_e (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
   sprintf (d, " %-8e ", fexpr);
   sprintf (d, " %-8e ", dexpr);
   sprintf (d, " %-8e ", ldexpr); /* { dg-warning "20: format '%e' expects argument of type 'double', but argument 3 has type 'long double'" } */
-/* TODO: ideally would also underline "ldexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8e ", ldexpr);
-                 ~~~^
+                 ~~~^    ~~~~~~
                  %-8Le
    { dg-end-multiline-output "" } */
 }
@@ -294,10 +270,9 @@ test_Le (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
   /* Integer arguments.  */
 
   sprintf (d, " %-8Le ", iexpr); /* { dg-warning "21: format '%Le' expects argument of type 'long double', but argument 3 has type 'int'" } */
-/* TODO: ideally would also underline "iexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8Le ", iexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~
                  %-8d
    { dg-end-multiline-output "" } */
 
@@ -306,14 +281,14 @@ test_Le (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
   sprintf (d, " %-8Le ", fexpr); /* { dg-warning "21: format '%Le' expects argument of type 'long double', but argument 3 has type 'double'" } */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8Le ", fexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~
                  %-8e
    { dg-end-multiline-output "" } */
 
   sprintf (d, " %-8Le ", dexpr); /* { dg-warning "21: format '%Le' expects argument of type 'long double', but argument 3 has type 'double'" } */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8Le ", dexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~
                  %-8e
    { dg-end-multiline-output "" } */
 
@@ -329,10 +304,9 @@ test_E (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
   /* Integer arguments.  */
 
   sprintf (d, " %-8E ", iexpr); /* { dg-warning "20: format '%E' expects argument of type 'double', but argument 3 has type 'int'" } */
-/* TODO: ideally would also underline "iexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8E ", iexpr);
-                 ~~~^
+                 ~~~^    ~~~~~
                  %-8d
    { dg-end-multiline-output "" } */
 
@@ -341,10 +315,9 @@ test_E (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
   sprintf (d, " %-8E ", fexpr);
   sprintf (d, " %-8E ", dexpr);
   sprintf (d, " %-8E ", ldexpr); /* { dg-warning "20: format '%E' expects argument of type 'double', but argument 3 has type 'long double'" } */
-/* TODO: ideally would also underline "ldexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8E ", ldexpr);
-                 ~~~^
+                 ~~~^    ~~~~~~
                  %-8LE
    { dg-end-multiline-output "" } */
 }
@@ -358,24 +331,23 @@ test_LE (char *d, int iexpr, float fexpr, double dexpr, long double ldexpr)
   /* Integer arguments.  */
 
   sprintf (d, " %-8LE ", iexpr); /* { dg-warning "21: format '%LE' expects argument of type 'long double', but argument 3 has type 'int'" } */
-/* TODO: ideally would also underline "iexpr".  */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8LE ", iexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~
                  %-8d
    { dg-end-multiline-output "" } */
 
   sprintf (d, " %-8LE ", fexpr); /* { dg-warning "21: format '%LE' expects argument of type 'long double', but argument 3 has type 'double'" } */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8LE ", fexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~
                  %-8E
    { dg-end-multiline-output "" } */
 
   sprintf (d, " %-8LE ", dexpr); /* { dg-warning "21: format '%LE' expects argument of type 'long double', but argument 3 has type 'double'" } */
 /* { dg-begin-multiline-output "" }
    sprintf (d, " %-8LE ", dexpr);
-                 ~~~~^
+                 ~~~~^    ~~~~~
                  %-8E
    { dg-end-multiline-output "" } */
 
@@ -394,19 +366,19 @@ test_everything (char *d, long lexpr)
   /* { dg-warning "26: field width specifier '\\*' expects argument of type 'int', but argument 3 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */
   /* { dg-begin-multiline-output "" }
    sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr);
-                       ~~~^~~~~~
+                       ~~~^~~~~~         ~~~~~
    { dg-end-multiline-output "" } */
 
   /* { dg-warning "28: field precision specifier '\\.\\*' expects argument of type 'int', but argument 4 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */
   /* { dg-begin-multiline-output "" }
    sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr);
-                       ~~~~~^~~~
+                       ~~~~~^~~~                ~~~~~
    { dg-end-multiline-output "" } */
 
   /* { dg-warning "31: format '%lld' expects argument of type 'long long int', but argument 5 has type 'long int'" "" { target *-*-* } test_everything_sprintf } */
   /* { dg-begin-multiline-output "" }
    sprintf (d, "before %-+*.*lld after", lexpr, lexpr, lexpr);
-                       ~~~~~~~~^
+                       ~~~~~~~~^                       ~~~~~
                        %-+*.*ld
    { dg-end-multiline-output "" } */
 }
-- 
1.8.5.3


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]