We currently ICE when emitting the error message for this invalid code:

=== cut here ===
struct foo {
  template<int> void not_const() {}
};
void fn(const foo& obj) {
  obj.not_const<5>();
}
=== cut here ===

The problem is that get_fndecl_argument_location assumes that it has a
FUNCTION_DECL in its hands to find the location of the bad argument. It might
however have a TEMPLATE_DECL if there's a single candidate that cannot be
instantiated, like here.

This patch simply defaults to using the FNDECL's location in this case, which
fixes this PR.

Successfully tested on x86_64-pc-linux-gnu.

        PR c++/115364

gcc/cp/ChangeLog:

        * call.cc (get_fndecl_argument_location): Use FNDECL's location for
        TEMPLATE_DECLs.

gcc/testsuite/ChangeLog:

        * g++.dg/overload/template7.C: New test.

---
 gcc/cp/call.cc                            | 4 ++++
 gcc/testsuite/g++.dg/overload/template7.C | 9 +++++++++
 2 files changed, 13 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/overload/template7.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 7bbc1fb0c78..d5ff2311e63 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -8347,6 +8347,10 @@ get_fndecl_argument_location (tree fndecl, int argnum)
   if (DECL_ARTIFICIAL (fndecl))
     return DECL_SOURCE_LOCATION (fndecl);
 
+  /* Use FNDECL's location for TEMPLATE_DECLs.  */
+  if (TREE_CODE (fndecl) == TEMPLATE_DECL)
+    return DECL_SOURCE_LOCATION (fndecl);
+
   int i;
   tree param;
 
diff --git a/gcc/testsuite/g++.dg/overload/template7.C 
b/gcc/testsuite/g++.dg/overload/template7.C
new file mode 100644
index 00000000000..67191c4ff62
--- /dev/null
+++ b/gcc/testsuite/g++.dg/overload/template7.C
@@ -0,0 +1,9 @@
+// PR c++/115364
+// { dg-do compile }
+
+struct foo {
+  template<int> void not_const() {} // { dg-note "initializing" }
+};
+void fn(const foo& obj) {
+  obj.not_const<5>(); // { dg-error "cannot convert" }
+}
-- 
2.44.0


Reply via email to