diff mbox

[C++,Patch/RFC] PR 80145

Message ID f0392178-1d4c-b33d-ff95-81b9cb31c290@oracle.com
State New
Headers show

Commit Message

Paolo Carlini March 23, 2017, 7:07 p.m. UTC
Hi,

this ICE on invalid code isn't a regression, thus a patch probably 
doesn't qualify for Stage 4, but IMHO I made good progress on it and I'm 
sending what I have now anyway... The ICE happens during error recovery 
after a sensible diagnostic for the first declaration in:

auto* foo() { return 0; }
auto* foo();

After the error, finish_function does:

apply_deduced_return_type (fndecl, void_type_node);
fntype = TREE_TYPE (fndecl);

which then is inconsistent with the auto* return type of the second 
declaration and leads to an ICE in merge_types (which duplicate_decls 
thought was safe to call because types_match is true (evidently: 
decls_match uses fndecl_declared_return_type)). Thus, in terms of error 
recovery, I think that in cases like the one at issue it makes sense not 
to replace auto* after the error and leave the return type untouched: 
certainly the below passes testing and avoids ICEing on the testcase at 
issue and a variant of it.

Thanks,
Paolo.

//////////////////

Comments

Paolo Carlini May 8, 2017, 10:45 a.m. UTC | #1
Hi,

gently pinging this...

On 23/03/2017 20:07, Paolo Carlini wrote:
> Hi,
>
> this ICE on invalid code isn't a regression, thus a patch probably 
> doesn't qualify for Stage 4, but IMHO I made good progress on it and 
> I'm sending what I have now anyway... The ICE happens during error 
> recovery after a sensible diagnostic for the first declaration in:
>
> auto* foo() { return 0; }
> auto* foo();
>
> After the error, finish_function does:
>
> apply_deduced_return_type (fndecl, void_type_node);
> fntype = TREE_TYPE (fndecl);
>
> which then is inconsistent with the auto* return type of the second 
> declaration and leads to an ICE in merge_types (which duplicate_decls 
> thought was safe to call because types_match is true (evidently: 
> decls_match uses fndecl_declared_return_type)). Thus, in terms of 
> error recovery, I think that in cases like the one at issue it makes 
> sense not to replace auto* after the error and leave the return type 
> untouched: certainly the below passes testing and avoids ICEing on the 
> testcase at issue and a variant of it.
Thanks,
Paolo.
Li, Pan2 via Gcc-patches May 8, 2017, 1:09 p.m. UTC | #2
OK.

On Thu, Mar 23, 2017 at 3:07 PM, Paolo Carlini <paolo.carlini@oracle.com> wrote:
> Hi,
>
> this ICE on invalid code isn't a regression, thus a patch probably doesn't
> qualify for Stage 4, but IMHO I made good progress on it and I'm sending
> what I have now anyway... The ICE happens during error recovery after a
> sensible diagnostic for the first declaration in:
>
> auto* foo() { return 0; }
> auto* foo();
>
> After the error, finish_function does:
>
> apply_deduced_return_type (fndecl, void_type_node);
> fntype = TREE_TYPE (fndecl);
>
> which then is inconsistent with the auto* return type of the second
> declaration and leads to an ICE in merge_types (which duplicate_decls
> thought was safe to call because types_match is true (evidently: decls_match
> uses fndecl_declared_return_type)). Thus, in terms of error recovery, I
> think that in cases like the one at issue it makes sense not to replace
> auto* after the error and leave the return type untouched: certainly the
> below passes testing and avoids ICEing on the testcase at issue and a
> variant of it.
>
> Thanks,
> Paolo.
>
> //////////////////
>
diff mbox

Patch

Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 246414)
+++ cp/decl.c	(working copy)
@@ -15573,16 +15573,19 @@  finish_function (int flags)
   if (!processing_template_decl && FNDECL_USED_AUTO (fndecl)
       && TREE_TYPE (fntype) == current_function_auto_return_pattern)
     {
-      if (!is_auto (current_function_auto_return_pattern)
-	  && !current_function_returns_value && !current_function_returns_null)
+      if (is_auto (current_function_auto_return_pattern))
 	{
+	  apply_deduced_return_type (fndecl, void_type_node);
+	  fntype = TREE_TYPE (fndecl);
+	}
+      else if (!current_function_returns_value
+	       && !current_function_returns_null)
+	{
 	  error ("no return statements in function returning %qT",
 		 current_function_auto_return_pattern);
 	  inform (input_location, "only plain %<auto%> return type can be "
 		  "deduced to %<void%>");
 	}
-      apply_deduced_return_type (fndecl, void_type_node);
-      fntype = TREE_TYPE (fndecl);
     }
 
   // If this is a concept, check that the definition is reasonable.
Index: testsuite/g++.dg/cpp1y/auto-fn37.C
===================================================================
--- testsuite/g++.dg/cpp1y/auto-fn37.C	(revision 0)
+++ testsuite/g++.dg/cpp1y/auto-fn37.C	(working copy)
@@ -0,0 +1,5 @@ 
+// PR c++/80145
+// { dg-do compile { target c++14 } }
+
+auto* foo() { return 0; }  // { dg-error "unable to deduce" }
+auto* foo();
Index: testsuite/g++.dg/cpp1y/auto-fn38.C
===================================================================
--- testsuite/g++.dg/cpp1y/auto-fn38.C	(revision 0)
+++ testsuite/g++.dg/cpp1y/auto-fn38.C	(working copy)
@@ -0,0 +1,5 @@ 
+// PR c++/80145
+// { dg-do compile { target c++14 } }
+
+auto* foo() { }  // { dg-error "no return statements" }
+auto* foo();