aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2018-03-29 14:43:01 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2018-03-29 14:43:01 +0000
commit9fa1b6610bb2efe94d5b23bde7bd72dc82d2587c (patch)
tree6c668bbd9b0202aef0d490ddb3cf228f557bb0dd /gcc
parent059cc8aca774e50555bc116436348d2898404685 (diff)
downloadgcc-9fa1b6610bb2efe94d5b23bde7bd72dc82d2587c.zip
gcc-9fa1b6610bb2efe94d5b23bde7bd72dc82d2587c.tar.gz
gcc-9fa1b6610bb2efe94d5b23bde7bd72dc82d2587c.tar.bz2
More underlining of bad arguments (PR c++/85110)
As of r256448, the C++ frontend underlines many bad arguments in its diagnostics; those where perform_overload_resolution returns a non-NULL candidate, but there's a failure in convert_like_real. However, for the case where perform_overload_resolution fails, but there's a single non-viable candidate, the error is diagnosed by cp_build_function_call_vec, and that currently doesn't underline the bad argument: $ cat test.cc void callee (int one, const char **two, int three); void caller (const char *fmt) { callee (1, fmt, 3); } We emit: $ g++ test.cc test.cc: In function 'void caller(const char*)': test.cc:6:20: error: cannot convert 'const char*' to 'const char**' for argument '2' to 'void callee(int, const char**, int)' callee (1, fmt, 3); ^ It's going through convert_for_assignment, and implicitly using input_location. This patch updates convert_for_assignment for this case, using an EXPR_LOCATION if there is one, or falling back to input_location otherwise, underlining the argument in question: test.cc: In function 'void caller(const char*)': test.cc:6:14: error: cannot convert 'const char*' to 'const char**' for argument '2' to 'void callee(int, const char**, int)' callee (1, fmt, 3); ^~~ gcc/cp/ChangeLog: PR c++/85110 * typeck.c (convert_for_assignment): When complaining due to conversions for an argument, attempt to use the location of the argument. gcc/testsuite/ChangeLog: PR c++/85110 * g++.dg/diagnostic/param-type-mismatch-2.C: New test. From-SVN: r258957
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/typeck.c5
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C175
4 files changed, 190 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b7a4f43..3441058 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2018-03-29 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/85110
+ * typeck.c (convert_for_assignment): When complaining due to
+ conversions for an argument, attempt to use the location of the
+ argument.
+
2018-03-28 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/85028
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index d3183b5..d454c6c 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -8782,8 +8782,9 @@ convert_for_assignment (tree type, tree rhs,
parmnum, complain, flags);
}
else if (fndecl)
- error ("cannot convert %qH to %qI for argument %qP to %qD",
- rhstype, type, parmnum, fndecl);
+ error_at (EXPR_LOC_OR_LOC (rhs, input_location),
+ "cannot convert %qH to %qI for argument %qP to %qD",
+ rhstype, type, parmnum, fndecl);
else
switch (errtype)
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 788dbaa..912d406 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2018-03-29 David Malcolm <dmalcolm@redhat.com>
+
+ PR c++/85110
+ * g++.dg/diagnostic/param-type-mismatch-2.C: New test.
+
2018-03-29 Jakub Jelinek <jakub@redhat.com>
PR c++/85108
diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
new file mode 100644
index 0000000..ae84248
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
@@ -0,0 +1,175 @@
+// { dg-options "-fdiagnostics-show-caret" }
+
+/* A collection of calls where argument 2 is of the wrong type. */
+
+/* decl, with argname. */
+
+extern int callee_1 (int one, const char **two, float three);
+
+int test_1 (int first, const char *second, float third)
+{
+ return callee_1 (first, second, third); // { dg-error "27: cannot convert 'const char\\*' to 'const char\\*\\*' for argument '2' to 'int callee_1\\(int, const char\\*\\*, float\\)'" }
+ /* { dg-begin-multiline-output "" }
+ return callee_1 (first, second, third);
+ ^~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* decl, without argname. */
+
+extern int callee_2 (int, const char **, float);
+
+int test_2 (int first, const char *second, float third)
+{
+ return callee_2 (first, second, third); // { dg-error "27: cannot convert 'const char\\*' to 'const char\\*\\*' for argument '2' to 'int callee_2\\(int, const char\\*\\*, float\\)'" }
+ /* { dg-begin-multiline-output "" }
+ return callee_2 (first, second, third);
+ ^~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* defn, with argname. */
+
+static int callee_3 (int one, const char **two, float three)
+{
+ return callee_2 (one, two, three);
+}
+
+int test_3 (int first, const char *second, float third)
+{
+ return callee_3 (first, second, third); // { dg-error "27: cannot convert 'const char\\*' to 'const char\\*\\*' for argument '2' to 'int callee_3\\(int, const char\\*\\*, float\\)'" }
+ /* { dg-begin-multiline-output "" }
+ return callee_3 (first, second, third);
+ ^~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* static member, with argname. */
+
+struct s4 { static int member_1 (int one, const char **two, float three); }; // { dg-line s4_member_1 }
+
+int test_4 (int first, const char *second, float third)
+{
+ return s4::member_1 (first, second, third); // { dg-error "no matching function for call to 's4::member_1\\(int&, const char\\*&, float&\\)'" }
+ /* { dg-begin-multiline-output "" }
+ return s4::member_1 (first, second, third);
+ ^
+ { dg-end-multiline-output "" } */
+ // { dg-message "candidate: 'static int s4::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s4_member_1 }
+ /* { dg-begin-multiline-output "" }
+ struct s4 { static int member_1 (int one, const char **two, float three); };
+ ^~~~~~~~
+ { dg-end-multiline-output "" } */
+ // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s4_member_1 }
+ // TODO: underline the pertinent param
+}
+
+/* non-static member, with argname. */
+
+struct s5 { int member_1 (int one, const char **two, float three); }; // { dg-line s5_member_1 }
+
+int test_5 (int first, const char *second, float third)
+{
+ s5 inst;
+ return inst.member_1 (first, second, third); // { dg-error "no matching function for call to 's5::member_1\\(int&, const char\\*&, float&\\)'" }
+ /* { dg-begin-multiline-output "" }
+ return inst.member_1 (first, second, third);
+ ^
+ { dg-end-multiline-output "" } */
+ // { dg-message "candidate: 'int s5::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s5_member_1 }
+ /* { dg-begin-multiline-output "" }
+ struct s5 { int member_1 (int one, const char **two, float three); };
+ ^~~~~~~~
+ { dg-end-multiline-output "" } */
+ // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s5_member_1 }
+ // TODO: underline the pertinent param
+}
+
+/* non-static member, with argname, via a ptr. */
+
+struct s6 { int member_1 (int one, const char **two, float three); }; // { dg-line s6_member_1 }
+
+int test_6 (int first, const char *second, float third, s6 *ptr)
+{
+ return ptr->member_1 (first, second, third); // { dg-error "no matching function for call to 's6::member_1\\(int&, const char\\*&, float&\\)'" }
+ /* { dg-begin-multiline-output "" }
+ return ptr->member_1 (first, second, third);
+ ^
+ { dg-end-multiline-output "" } */
+ // { dg-message "candidate: 'int s6::member_1\\(int, const char\\*\\*, float\\)'" "" { target *-*-* } s6_member_1 }
+ /* { dg-begin-multiline-output "" }
+ struct s6 { int member_1 (int one, const char **two, float three); };
+ ^~~~~~~~
+ { dg-end-multiline-output "" } */
+ // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s6_member_1 }
+ // TODO: underline the pertinent param
+}
+
+/* Template function. */
+
+template <typename T>
+int test_7 (int one, T two, float three); // { dg-line test_7_decl }
+
+int test_7 (int first, const char *second, float third)
+{
+ return test_7 <const char **> (first, second, third); // { dg-line test_7_usage }
+ // { dg-error "no matching function" "" { target *-*-* } test_7_usage }
+ /* { dg-begin-multiline-output "" }
+ return test_7 <const char **> (first, second, third);
+ ^
+ { dg-end-multiline-output "" } */
+ // { dg-message "candidate: 'template<class T> int test_7\\(int, T, float\\)'" "" { target *-*-* } test_7_decl }
+ /* { dg-begin-multiline-output "" }
+ int test_7 (int one, T two, float three);
+ ^~~~~~
+ { dg-end-multiline-output "" } */
+ // { dg-message "template argument deduction/substitution failed:" "" { target *-*-* } test_7_decl }
+ // { dg-message "cannot convert 'second' \\(type 'const char\\*'\\) to type 'const char\\*\\*'" "" { target *-*-* } test_7_usage }
+ /* { dg-begin-multiline-output "" }
+ return test_7 <const char **> (first, second, third);
+ ^~~~~~
+ { dg-end-multiline-output "" } */
+}
+
+/* Template class, static function. */
+
+template <typename T>
+struct s8 { static int member_1 (int one, T two, float three); }; // { dg-line s8_member_1 }
+
+int test_8 (int first, const char *second, float third)
+{
+ return s8 <const char **>::member_1 (first, second, third); // { dg-error "no matching function for call to 's8<const char\\*\\*>::member_1\\(int&, const char\\*&, float&\\)'" }
+ /* { dg-begin-multiline-output "" }
+ return s8 <const char **>::member_1 (first, second, third);
+ ^
+ { dg-end-multiline-output "" } */
+ // { dg-message "candidate: 'static int s8<T>::member_1\\(int, T, float\\)" "" { target *-*-* } s8_member_1 }
+ /* { dg-begin-multiline-output "" }
+ struct s8 { static int member_1 (int one, T two, float three); };
+ ^~~~~~~~
+ { dg-end-multiline-output "" } */
+ // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s8_member_1 }
+ // TODO: underline the pertinent param
+}
+
+/* Template class, non-static function. */
+
+template <typename T>
+struct s9 { int member_1 (int one, T two, float three); }; // { dg-line s9_member_1 }
+
+int test_9 (int first, const char *second, float third)
+{
+ s9 <const char **> inst;
+ return inst.member_1 (first, second, third); // { dg-error "no matching function for call to 's9<const char\\*\\*>::member_1\\(int&, const char\\*&, float&\\)'" }
+ /* { dg-begin-multiline-output "" }
+ return inst.member_1 (first, second, third);
+ ^
+ { dg-end-multiline-output "" } */
+ // { dg-message "candidate: 'int s9<T>::member_1\\(int, T, float\\)" "" { target *-*-* } s9_member_1 }
+ /* { dg-begin-multiline-output "" }
+ struct s9 { int member_1 (int one, T two, float three); };
+ ^~~~~~~~
+ { dg-end-multiline-output "" } */
+ // { dg-message "no known conversion for argument 2 from 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } s9_member_1 }
+ // TODO: underline the pertinent param
+}