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 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" } -- Alexandre Oliva, freedom fighter http://FSFLA.org/~lxoliva/ You must be the change you wish to see in the world. -- Gandhi Be Free! -- http://FSFLA.org/ FSF Latin America board member Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer