diff mbox series

[PR,c++/84647] undeclared fn called in auto default arg in ptr decl

Message ID or7eqkb0ss.fsf@lxoliva.fsfla.org
State New
Headers show
Series [PR,c++/84647] undeclared fn called in auto default arg in ptr decl | expand

Commit Message

Alexandre Oliva March 10, 2018, 11:57 a.m. UTC
We ICEd when attempting to convert a default arg for an auto parm, the
default arg amounting to a call to an undeclared function, in a
declaration of a pointer to function variable.  It's all wrong, but
because of the bogus implicit template, we accept the typeless
expression at first.  Later on, after we finish the implicit template
because it's bogus (but deferring the reporting of the error to the end
of cp_parser_init_declarator), no longer processing_template_decl, we
attempt to perform the impossible conversion from NULL type to an
unresolved and unresolvable type placeholder.  We crash in
implicit_conversion because FROM is NULL, and then (once we arrange to
return a NULL conversion there) in perform_implicit_conversion_flags
when trying to determine whether the expr is an invalid use of a
nonstatic memfn.

This patch makes implicit_conversion return NULL when the FROM type is
NULL, and reports a proper error for typeless EXPRs in
perform_implicit_conversion_flags.  I considered testing for
!processing_template_decl, but decided not to bother.

FWIW, I'd tried temporarily incrementing processing_template_decl while
completing the parsing of the bogus implicit template, but that didn't
go very well: we'd skip the conversion all right, but start_decl would
attempt to push_template_decl, and that would silently return
error_mark_node, which would in turn silence the bogus implicit template
error.  With -fpermissive, all the other errors (misplaced auto,
unexpected default arg in pointer declaration, and undeclared function
call) would be turned to warnings or vanish altogether, so compilation
would complete in spite of the bogus parsing and the failed template
declaration.  I decided not to explore that path further, and ended up
working around the errors in the conversion, so as to make sure we'd get
at least some error (we get all of them with the enclosed testcase).

Regstrapped on i686- and x86_64-linux-gnu.  Ok to install?

for  gcc/cp/ChangeLog

	PR c++/84647
	* call.c (implicit_conversion): Return NULL conv for NULL
	from type.
	(perform_implicit_conversion_flags): If conv is NULL, check
	for NULL expr type and report an error instead of ICEing.

for  gcc/testsuite/ChangeLog

	PR c++/84647
	* g++.dg/cpp0x/pr84647.C: New.

---
 gcc/cp/call.c                        |   10 ++++++++++
 gcc/testsuite/g++.dg/cpp0x/pr84647.C |    3 +++
 2 files changed, 13 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/pr84647.C

Comments

Jason Merrill March 20, 2018, 6:21 p.m. UTC | #1
On Sat, Mar 10, 2018 at 6:57 AM, Alexandre Oliva <aoliva@redhat.com> wrote:
> We ICEd when attempting to convert a default arg for an auto parm, the
> default arg amounting to a call to an undeclared function, in a
> declaration of a pointer to function variable.

This seems to have been fixed by my patch for 84798, so now we don't
try to parse an implicit template.

Jason
diff mbox series

Patch

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 45c22aaa312c..cb95fe35891a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -1836,6 +1836,9 @@  implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
       from = TREE_TYPE (expr);
     }
 
+  if (!from)
+    return NULL;
+
   if (TREE_CODE (to) == REFERENCE_TYPE)
     conv = reference_binding (to, from, expr, c_cast_p, flags, complain);
   else
@@ -10586,6 +10589,13 @@  perform_implicit_conversion_flags (tree type, tree expr,
 	     Call instantiate_type to get good error messages.  */
 	  if (TREE_TYPE (expr) == unknown_type_node)
 	    instantiate_type (type, expr, complain);
+	  /* We may find this if we parse a default argument as part
+	     of a bogus implicit template function declaration.  It
+	     might be a template-dependent expression, or a call of an
+	     undeclared function.  */
+	  else if (!TREE_TYPE (expr))
+	    error_at (loc, "cannot convert typeless expression %qE",
+		      expr);
 	  else if (invalid_nonstatic_memfn_p (loc, expr, complain))
 	    /* We gave an error.  */;
 	  else
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr84647.C b/gcc/testsuite/g++.dg/cpp0x/pr84647.C
new file mode 100644
index 000000000000..63292bd8f692
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr84647.C
@@ -0,0 +1,3 @@ 
+// { dg-do compile { target c++11 } }
+
+void (*a)(auto b = c()); // { dg-error "parameter declaration|depend on a template|undeclared name|not declared|default arguments|typeless expression|implicit template" }