]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
C++: improvements to diagnostics using %P (more PR c++/85110)
authordmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 6 Dec 2018 15:25:12 +0000 (15:25 +0000)
committerdmalcolm <dmalcolm@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 6 Dec 2018 15:25:12 +0000 (15:25 +0000)
This patch is based on grepping the C++ frontend for %P
i.e. diagnostics that refer to a parameter number.  It fixes up
these diagnostics to highlight the pertinent param where appropriate
(and possible), along with various other tweaks, as described in the
ChangeLog.

gcc/cp/ChangeLog:
PR c++/85110
* call.c (conversion_null_warnings): Try to use the location of
the expression for the warnings.  Add notes showing the parameter
of the function decl, where available.
(get_fndecl_argument_location): For implicitly-declared functions,
use the fndecl location rather than that of the param.
(maybe_inform_about_fndecl_for_bogus_argument_init): New function.
(convert_like_real): Use it in various places to avoid repetition.
(complain_about_bad_argument): Likewise.
* cp-tree.h (maybe_inform_about_fndecl_for_bogus_argument_init):
New declaration.
* decl2.c (check_default_args): Put all diagnostics for the fndecl
into a diagnostic group.  Use the location of the parameter when
complaining about parameters with missing default arguments in
preference to that of the fndecl.  Attempt to record the location
of the first parameter with a default argument and emit a note
for the first parameter that's missing one.
* typeck.c (convert_arguments): When complaining about parameters
with incomplete types, attempt to use the location of the
argument.  Where available, add a note showing the pertinent
parameter in the fndecl.
(convert_for_assignment): When complaining about bad conversions
at function calls, use the location of the unstripped argument.
(convert_for_initialization): When checking for bogus references,
add an auto_diagnostic_group, and update the note to use the
location of the pertinent parameter, rather than just the callee.

gcc/testsuite/ChangeLog:
PR c++/85110
* g++.dg/diagnostic/missing-default-args.C: New test.
* g++.dg/diagnostic/param-type-mismatch-3.C: New test.
* g++.dg/diagnostic/param-type-mismatch.C: Add tests for invalid
references and incomplete types.
* g++.dg/warn/Wconversion-null-4.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@266856 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/diagnostic/missing-default-args.C [new file with mode: 0644]
gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
gcc/testsuite/g++.dg/warn/Wconversion-null-4.C [new file with mode: 0644]

index 704e01defcfdec897092451874288257da4e4afc..bda9c59411d82d857af71e9e797d16414ca6112a 100644 (file)
@@ -1,3 +1,32 @@
+2018-12-06  David Malcolm  <dmalcolm@redhat.com>
+
+       PR c++/85110
+       * call.c (conversion_null_warnings): Try to use the location of
+       the expression for the warnings.  Add notes showing the parameter
+       of the function decl, where available.
+       (get_fndecl_argument_location): For implicitly-declared functions,
+       use the fndecl location rather than that of the param.
+       (maybe_inform_about_fndecl_for_bogus_argument_init): New function.
+       (convert_like_real): Use it in various places to avoid repetition.
+       (complain_about_bad_argument): Likewise.
+       * cp-tree.h (maybe_inform_about_fndecl_for_bogus_argument_init):
+       New declaration.
+       * decl2.c (check_default_args): Put all diagnostics for the fndecl
+       into a diagnostic group.  Use the location of the parameter when
+       complaining about parameters with missing default arguments in
+       preference to that of the fndecl.  Attempt to record the location
+       of the first parameter with a default argument and emit a note
+       for the first parameter that's missing one.
+       * typeck.c (convert_arguments): When complaining about parameters
+       with incomplete types, attempt to use the location of the
+       argument.  Where available, add a note showing the pertinent
+       parameter in the fndecl.
+       (convert_for_assignment): When complaining about bad conversions
+       at function calls, use the location of the unstripped argument.
+       (convert_for_initialization): When checking for bogus references,
+       add an auto_diagnostic_group, and update the note to use the
+       location of the pertinent parameter, rather than just the callee.
+
 2018-12-06  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * decl2.c (grokbitfield): Use DECL_SOURCE_LOCATION in error message;
index ee099cc7277fcf34b1b932694020b485f89fc5ee..148e2d5580fc9dcfd3caed281a1ed5ab82ceba80 100644 (file)
@@ -6681,13 +6681,17 @@ conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
   if (null_node_p (expr) && TREE_CODE (totype) != BOOLEAN_TYPE
       && ARITHMETIC_TYPE_P (totype))
     {
-      location_t loc =
-       expansion_point_location_if_in_system_header (input_location);
-
+      location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+      loc = expansion_point_location_if_in_system_header (loc);
       if (fn)
-       warning_at (loc, OPT_Wconversion_null,
-                   "passing NULL to non-pointer argument %P of %qD",
-                   argnum, fn);
+       {
+         auto_diagnostic_group d;
+         if (warning_at (loc, OPT_Wconversion_null,
+                         "passing NULL to non-pointer argument %P of %qD",
+                         argnum, fn))
+           inform (get_fndecl_argument_location (fn, argnum),
+                   "  declared here");
+       }
       else
        warning_at (loc, OPT_Wconversion_null,
                    "converting to non-pointer type %qT from NULL", totype);
@@ -6697,12 +6701,18 @@ conversion_null_warnings (tree totype, tree expr, tree fn, int argnum)
   else if (TREE_CODE (TREE_TYPE (expr)) == BOOLEAN_TYPE
           && TYPE_PTR_P (totype))
     {
+      location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
       if (fn)
-       warning_at (input_location, OPT_Wconversion_null,
-                   "converting %<false%> to pointer type for argument %P "
-                   "of %qD", argnum, fn);
+       {
+         auto_diagnostic_group d;
+         if (warning_at (loc, OPT_Wconversion_null,
+                         "converting %<false%> to pointer type for argument "
+                         "%P of %qD", argnum, fn))
+           inform (get_fndecl_argument_location (fn, argnum),
+                   "  declared here");
+       }
       else
-       warning_at (input_location, OPT_Wconversion_null,
+       warning_at (loc, OPT_Wconversion_null,
                    "converting %<false%> to pointer type %qT", totype);
     }
   /* Handle zero as null pointer warnings for cases other
@@ -6740,6 +6750,11 @@ maybe_print_user_conv_context (conversion *convs)
 location_t
 get_fndecl_argument_location (tree fndecl, int argnum)
 {
+  /* The locations of implicitly-declared functions are likely to be
+     more meaningful than those of their parameters.  */
+  if (DECL_ARTIFICIAL (fndecl))
+    return DECL_SOURCE_LOCATION (fndecl);
+
   int i;
   tree param;
 
@@ -6757,6 +6772,18 @@ get_fndecl_argument_location (tree fndecl, int argnum)
   return DECL_SOURCE_LOCATION (param);
 }
 
+/* If FNDECL is non-NULL, issue a note highlighting ARGNUM
+   within its declaration (or the fndecl itself if something went
+   wrong).  */
+
+void
+maybe_inform_about_fndecl_for_bogus_argument_init (tree fn, int argnum)
+{
+  if (fn)
+    inform (get_fndecl_argument_location (fn, argnum),
+           "  initializing argument %P of %qD", argnum, fn);
+}
+
 /* Perform the conversions in CONVS on the expression EXPR.  FN and
    ARGNUM are used for diagnostics.  ARGNUM is zero based, -1
    indicates the `this' argument of a method.  INNER is nonzero when
@@ -6834,9 +6861,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
                                             complain);
              else
                expr = cp_convert (totype, expr, complain);
-             if (complained && fn)
-               inform (DECL_SOURCE_LOCATION (fn),
-                       "  initializing argument %P of %qD", argnum, fn);
+             if (complained)
+               maybe_inform_about_fndecl_for_bogus_argument_init (fn, argnum);
              return expr;
            }
          else if (t->kind == ck_user || !t->bad_p)
@@ -6863,9 +6889,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
                                  "invalid conversion from %qH to %qI",
                                  TREE_TYPE (expr), totype);
        }
-      if (complained && fn)
-       inform (get_fndecl_argument_location (fn, argnum),
-               "  initializing argument %P of %qD", argnum, fn);
+      if (complained)
+       maybe_inform_about_fndecl_for_bogus_argument_init (fn, argnum);
 
       return cp_convert (totype, expr, complain);
     }
@@ -6987,9 +7012,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
                       ? LOOKUP_IMPLICIT : LOOKUP_NORMAL);
          build_user_type_conversion (totype, convs->u.expr, flags, complain);
          gcc_assert (seen_error ());
-         if (fn)
-           inform (DECL_SOURCE_LOCATION (fn),
-                   "  initializing argument %P of %qD", argnum, fn);
+         maybe_inform_about_fndecl_for_bogus_argument_init (fn, argnum);
        }
       return error_mark_node;
 
@@ -7083,9 +7106,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
            {
              auto_diagnostic_group d;
              maybe_print_user_conv_context (convs);
-             if (fn)
-               inform (DECL_SOURCE_LOCATION (fn),
-                       "  initializing argument %P of %qD", argnum, fn);
+             maybe_inform_about_fndecl_for_bogus_argument_init (fn, argnum);
            }
          return error_mark_node;
        }
@@ -7136,9 +7157,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
        {
          auto_diagnostic_group d;
          maybe_print_user_conv_context (convs);
-         if (fn)
-           inform (DECL_SOURCE_LOCATION (fn),
-                   "  initializing argument %P of %qD", argnum, fn);
+         maybe_inform_about_fndecl_for_bogus_argument_init (fn, argnum);
        }
 
       return build_cplus_new (totype, expr, complain);
@@ -7165,9 +7184,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
            else
              gcc_unreachable ();
            maybe_print_user_conv_context (convs);
-           if (fn)
-             inform (DECL_SOURCE_LOCATION (fn),
-                     "  initializing argument %P of %qD", argnum, fn);
+           maybe_inform_about_fndecl_for_bogus_argument_init (fn, argnum);
+
            return error_mark_node;
          }
 
@@ -9299,8 +9317,8 @@ complain_about_bad_argument (location_t arg_loc,
   error_at (&richloc,
            "cannot convert %qH to %qI",
            from_type, to_type);
-  inform (get_fndecl_argument_location (fndecl, parmnum),
-         "  initializing argument %P of %qD", parmnum, fndecl);
+  maybe_inform_about_fndecl_for_bogus_argument_init (fndecl,
+                                                    parmnum);
 }
 
 /* Subroutine of build_new_method_call_1, for where there are no viable
index 111a123bb34c50af51a92d3d82621307492c62b1..c1f99315b06dbaf0e6103f2a65b377864e0a001e 100644 (file)
@@ -6145,6 +6145,7 @@ extern location_t get_fndecl_argument_location  (tree, int);
 extern void complain_about_bad_argument        (location_t arg_loc,
                                                 tree from_type, tree to_type,
                                                 tree fndecl, int parmnum);
+extern void maybe_inform_about_fndecl_for_bogus_argument_init (tree, int);
 
 
 /* A class for recording information about access failures (e.g. private
index 79abdaebe861b9006e566e2bfecf0b41813cae77..f996a277dae15f70f40de4a5a645b77cbad65f68 100644 (file)
@@ -5182,14 +5182,37 @@ check_default_args (tree x)
 {
   tree arg = TYPE_ARG_TYPES (TREE_TYPE (x));
   bool saw_def = false;
+  bool noted_first_def = false;
+  int idx_of_first_default_arg = 0;
+  location_t loc_of_first_default_arg = UNKNOWN_LOCATION;
   int i = 0 - (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE);
+  tree fndecl = STRIP_TEMPLATE (x);
+  auto_diagnostic_group d;
   for (; arg && arg != void_list_node; arg = TREE_CHAIN (arg), ++i)
     {
       if (TREE_PURPOSE (arg))
-       saw_def = true;
+       {
+         if (!saw_def)
+           {
+             saw_def = true;
+             idx_of_first_default_arg = i;
+             location_t loc = get_fndecl_argument_location (fndecl, i);
+             if (loc != DECL_SOURCE_LOCATION (x))
+               loc_of_first_default_arg = loc;
+           }
+       }
       else if (saw_def && !PACK_EXPANSION_P (TREE_VALUE (arg)))
        {
-         error ("default argument missing for parameter %P of %q+#D", i, x);
+         error_at (get_fndecl_argument_location (fndecl, i),
+                   "default argument missing for parameter %P of %q#D", i, x);
+         if (loc_of_first_default_arg != UNKNOWN_LOCATION
+             && !noted_first_def)
+           {
+             inform (loc_of_first_default_arg,
+                     "...following parameter %P which has a default argument",
+                     idx_of_first_default_arg);
+             noted_first_def = true;
+           }
          TREE_PURPOSE (arg) = error_mark_node;
        }
     }
index 86c95d7b87fb207900c0f32607249e247ef13557..ac0c81155b5a7db77896976c20b9dbf042df133e 100644 (file)
@@ -4013,11 +4013,19 @@ convert_arguments (tree typelist, vec<tree, va_gc> **values, tree fndecl,
            {
               if (complain & tf_error)
                 {
+                 location_t loc = EXPR_LOC_OR_LOC (val, input_location);
                   if (fndecl)
-                    error ("parameter %P of %qD has incomplete type %qT",
-                           i, fndecl, type);
+                   {
+                     auto_diagnostic_group d;
+                     error_at (loc,
+                               "parameter %P of %qD has incomplete type %qT",
+                               i, fndecl, type);
+                     inform (get_fndecl_argument_location (fndecl, i),
+                             "  declared here");
+                   }
                   else
-                    error ("parameter %P has incomplete type %qT", i, type);
+                   error_at (loc, "parameter %P has incomplete type %qT", i,
+                             type);
                 }
              parmval = error_mark_node;
            }
@@ -8801,6 +8809,8 @@ convert_for_assignment (tree type, tree rhs,
   tree rhstype;
   enum tree_code coder;
 
+  location_t rhs_loc = EXPR_LOC_OR_LOC (rhs, input_location);
+
   /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
   if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
     rhs = TREE_OPERAND (rhs, 0);
@@ -8907,7 +8917,7 @@ convert_for_assignment (tree type, tree rhs,
                                                   parmnum, complain, flags);
                }
              else if (fndecl)
-               complain_about_bad_argument (cp_expr_location (rhs),
+               complain_about_bad_argument (rhs_loc,
                                             rhstype, type,
                                             fndecl, parmnum);
              else
@@ -9074,6 +9084,7 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
 
   if (codel == REFERENCE_TYPE)
     {
+      auto_diagnostic_group d;
       /* This should eventually happen in convert_arguments.  */
       int savew = 0, savee = 0;
 
@@ -9083,9 +9094,8 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
 
       if (fndecl
          && (warningcount + werrorcount > savew || errorcount > savee))
-       inform (DECL_SOURCE_LOCATION (fndecl),
+       inform (get_fndecl_argument_location (fndecl, parmnum),
                "in passing argument %P of %qD", parmnum, fndecl);
-
       return rhs;
     }
 
index bda8476a4ad8e3e3def708bbe9ff83644a5c0f56..1adb751cd34bd6fe8c0ba5778bffb599c1c82a9b 100644 (file)
@@ -1,3 +1,12 @@
+2018-12-06  David Malcolm  <dmalcolm@redhat.com>
+
+       PR c++/85110
+       * g++.dg/diagnostic/missing-default-args.C: New test.
+       * g++.dg/diagnostic/param-type-mismatch-3.C: New test.
+       * g++.dg/diagnostic/param-type-mismatch.C: Add tests for invalid
+       references and incomplete types.
+       * g++.dg/warn/Wconversion-null-4.C: New test.
+
 2018-12-06  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/87598
diff --git a/gcc/testsuite/g++.dg/diagnostic/missing-default-args.C b/gcc/testsuite/g++.dg/diagnostic/missing-default-args.C
new file mode 100644 (file)
index 0000000..2e9401d
--- /dev/null
@@ -0,0 +1,73 @@
+// { dg-options "-fdiagnostics-show-caret" }
+
+/* Function.  */
+
+void test_1 (int a, int b = 42, int c, int d); // { dg-line test_1 }
+
+// { dg-error "default argument missing for parameter 3 of " "" { target *-*-* } test_1 }
+/* { dg-begin-multiline-output "" }
+ void test_1 (int a, int b = 42, int c, int d);
+                                 ~~~~^
+   { dg-end-multiline-output "" } */
+// { dg-message "...following parameter 2 which has a default argument" "" { target *-*-* } test_1 }
+/* { dg-begin-multiline-output "" }
+ void test_1 (int a, int b = 42, int c, int d);
+                     ~~~~^~~~~~
+   { dg-end-multiline-output "" } */
+// { dg-error "default argument missing for parameter 4 of " "" { target *-*-* } test_1 }
+/* { dg-begin-multiline-output "" }
+ void test_1 (int a, int b = 42, int c, int d);
+                                        ~~~~^
+   { dg-end-multiline-output "" } */
+
+
+/* Non-static member fn.  */
+
+struct test_2
+{
+  void member_2 (int a, int b = 42, int c); // { dg-line test_2 }
+};
+// { dg-error "default argument missing for parameter 3 of " "" { target *-*-* } test_2 }
+/* { dg-begin-multiline-output "" }
+   void member_2 (int a, int b = 42, int c);
+                                     ~~~~^
+   { dg-end-multiline-output "" } */
+// { dg-message "...following parameter 2 which has a default argument" "" { target *-*-* } test_2 }
+/* { dg-begin-multiline-output "" }
+   void member_2 (int a, int b = 42, int c);
+                         ~~~~^~~~~~
+   { dg-end-multiline-output "" } */
+
+
+/* Static member fn.  */
+
+struct test_3
+{
+  static void member_3 (int a, int b = 42, int c); // { dg-line test_3 }
+};
+// { dg-error "default argument missing for parameter 3 of " "" { target *-*-* } test_3 }
+/* { dg-begin-multiline-output "" }
+   static void member_3 (int a, int b = 42, int c);
+                                            ~~~~^
+   { dg-end-multiline-output "" } */
+// { dg-message "...following parameter 2 which has a default argument" "" { target *-*-* } test_3 }
+/* { dg-begin-multiline-output "" }
+   static void member_3 (int a, int b = 42, int c);
+                                ~~~~^~~~~~
+   { dg-end-multiline-output "" } */
+
+
+/* Template.  */
+
+template <typename Type>
+void test_4 (int a, int b = 42, int c); // { dg-line test_4 }
+// { dg-error "default argument missing for parameter 3 of " "" { target *-*-* } test_4 }
+/* { dg-begin-multiline-output "" }
+ void test_4 (int a, int b = 42, int c);
+                                 ~~~~^
+   { dg-end-multiline-output "" } */
+// { dg-message "...following parameter 2 which has a default argument" "" { target *-*-* } test_4 }
+/* { dg-begin-multiline-output "" }
+ void test_4 (int a, int b = 42, int c);
+                     ~~~~^~~~~~
+   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-3.C b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-3.C
new file mode 100644 (file)
index 0000000..3ffbbd8
--- /dev/null
@@ -0,0 +1,26 @@
+// { dg-do compile { target c++14 } }
+// { dg-options "-fdiagnostics-show-caret" }
+
+void f2(int, char (*)(int), int) { } // { dg-line f2 }
+
+void test_1 ()
+{
+  auto glambda = [](auto a) { return a; }; // { dg-line candidate }
+  int (*fp)(int) = glambda;
+  f2(1, glambda, 3); // { dg-error "invalid user-defined conversion" }
+  /* { dg-begin-multiline-output "" }
+   f2(1, glambda, 3);
+         ^~~~~~~
+     { dg-end-multiline-output "" } */
+  // { dg-message "candidate is: " "" { target *-*-* } candidate }
+  /* { dg-begin-multiline-output "" }
+   auto glambda = [](auto a) { return a; };
+                  ^
+     { dg-end-multiline-output "" } */
+  // { dg-message "no known conversion from " "" { target *-*-* } candidate }
+  // { dg-message "initializing argument 2 of " "" { target *-*-* } f2 }
+  /* { dg-begin-multiline-output "" }
+ void f2(int, char (*)(int), int) { }
+              ^~~~~~~~~~~~~
+     { dg-end-multiline-output "" } */
+}
index cb5c3602a66aaa2d7f29d1c004b6d314db27d201..54ffb06d7ace383adf5c0c7ca544adc46c9db945 100644 (file)
@@ -224,4 +224,45 @@ int test_11 (int first, int second, float third)
      { dg-end-multiline-output "" } */
 }
 
+/* Bad reference.  */
+
+struct s12;
+
+extern int callee_12 (int one, s12 &second, float three); // { dg-line callee_12 }
+
+int test_12 (int first, int second, float third)
+{
+  return callee_12 (first, second, third); // { dg-error "invalid initialization of reference of " }
+  /* { dg-begin-multiline-output "" }
+   return callee_12 (first, second, third);
+                            ^~~~~~
+     { dg-end-multiline-output "" } */
+  // { dg-message "in passing argument 2 of " "" { target *-*-* } callee_12 }
+  /* { dg-begin-multiline-output "" }
+ extern int callee_12 (int one, s12 &second, float three);
+                                ~~~~~^~~~~~
+     { dg-end-multiline-output "" } */
+}
+
+/* Incomplete type.  */
+
+struct s13;
+
+extern int callee_13 (int one, s13 second, float three); // { dg-line callee_13 }
+
+int test_13 (int first, int second, float third)
+{
+  return callee_13 (first, second, third); // { dg-error "has incomplete type" }
+  /* { dg-begin-multiline-output "" }
+   return callee_13 (first, second, third);
+                            ^~~~~~
+     { dg-end-multiline-output "" } */
+  // { dg-message "declared here" "" { target *-*-* } callee_13 }
+  /* { dg-begin-multiline-output "" }
+ extern int callee_13 (int one, s13 second, float three);
+                                ~~~~^~~~~~
+     { dg-end-multiline-output "" } */
+}
+
+
 // TODO: template callsite
diff --git a/gcc/testsuite/g++.dg/warn/Wconversion-null-4.C b/gcc/testsuite/g++.dg/warn/Wconversion-null-4.C
new file mode 100644 (file)
index 0000000..465dc5a
--- /dev/null
@@ -0,0 +1,43 @@
+// { dg-do compile  }
+// { dg-options "-Wconversion-null -fdiagnostics-show-caret" }
+
+#include <stddef.h>
+
+void callee_1 (int, int, int) {} // { dg-message "declared here" }
+
+void caller_1 (void)
+{
+  callee_1 (0, NULL, 2); // { dg-warning "passing NULL to non-pointer argument 2 of" }
+  /* { dg-begin-multiline-output "" }
+   callee_1 (0, NULL, 2);
+                ^~~~
+     { dg-end-multiline-output "" } */
+  /* { dg-begin-multiline-output "" }
+ void callee_1 (int, int, int) {}
+                     ^~~
+     { dg-end-multiline-output "" } */
+}
+
+void callee_2 (int, void *, int) {} // { dg-message "declared here" "" { target { ! c++11 } } }
+// { dg-message "initializing argument 2 of " "" { target c++11 } .-1 }
+
+void caller_2 (void)
+{
+  callee_2 (0, false, 2); // { dg-warning "converting 'false' to pointer type for argument 2 of " "" { target { ! c++11 } } }
+  // { dg-error "cannot convert" "" { target c++11 } .-1 }
+
+  /* { dg-begin-multiline-output "" }
+   callee_2 (0, false, 2);
+                ^~~~~
+     { dg-end-multiline-output "" { target { ! c++11 } } } */
+  /* { dg-begin-multiline-output "" }
+   callee_2 (0, false, 2);
+                ^~~~~
+                |
+                bool
+     { dg-end-multiline-output "" { target c++11 } } */
+  /* { dg-begin-multiline-output "" }
+ void callee_2 (int, void *, int) {}
+                     ^~~~~~
+     { dg-end-multiline-output "" } */
+}