[C++] PR 62207 ("[7/8/9 Regression] ICE: tree check: expected tree that contains 'decl minimal' structure, have 'overload' in tsubst_copy, at cp/pt.c")

Message ID 5ef65014-32c6-97e4-92d9-60bf7dc466b1@oracle.com
State New
Headers show
Series
  • [C++] PR 62207 ("[7/8/9 Regression] ICE: tree check: expected tree that contains 'decl minimal' structure, have 'overload' in tsubst_copy, at cp/pt.c")
Related show

Commit Message

Paolo Carlini April 1, 2019, 9:36 a.m.
Hi,

A rather long standing issue. The error-recovery problem is that, in 
various circumstances, we flag as erroneous a local variable declaration 
and then, when we need to come back to it later on, lookup_name doesn't 
find it, keeps looking and may find instead a completely unrelated 
non-variable declaration with the same name. In principle, we could 
probably set up things in such a way that during error-recovery the 
erroneous entity is found anyway, marked as erroneous of course, but I 
don't think we want to attempt that now... Thus, I'm proposing to just 
check for VAR_P in the relevant case of tsubst_copy and bail-out. 
Setting instead r = NULL_TREE and trying to continue works rather well 
but leads to duplicate diagnostics in some cases (eg, for 
template/crash131.C).

By the way, something else I actually tried is returning immediately 
from tsubst_expr when the tsubst call in case DECL_EXPR returns 
error_mark_node and then bail out immediately from the for loop over the 
STATEMENT_LIST. That also passes the testsuite, but, if you want, you 
can certainly notice that the loop over the statements ends early, for 
example we would not provide any diagnostics for an additional Y<f> y2; 
in template/crash131.C. Which interestingly is true for current clang too ;)

Tested x86_64-linux.

Thanks, Paolo.

/////////////////////
/cp
2019-04-01  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/62207
	* pt.c (tsubst_copy): Deal with lookup_name not returing a variable.

/testsuite
2019-04-01  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/62207
	* g++.dg/template/crash130.C: New.
	* g++.dg/template/crash131.C: Likewise.

Comments

Jason Merrill April 1, 2019, 1:36 p.m. | #1
OK.

Jason

Patch

Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 270012)
+++ cp/pt.c	(working copy)
@@ -15579,12 +15579,23 @@  tsubst_copy (tree t, tree args, tsubst_flags_t com
 	    {
 	      /* First try name lookup to find the instantiation.  */
 	      r = lookup_name (DECL_NAME (t));
-	      if (r && !is_capture_proxy (r))
+	      if (r)
 		{
-		  /* Make sure that the one we found is the one we want.  */
-		  tree ctx = enclosing_instantiation_of (DECL_CONTEXT (t));
-		  if (ctx != DECL_CONTEXT (r))
-		    r = NULL_TREE;
+		  if (!VAR_P (r))
+		    {
+		      /* During error-recovery we may find a non-variable,
+			 even an OVERLOAD: just bail out and avoid ICEs and
+			 duplicate diagnostics (c++/62207).  */
+		      gcc_assert (seen_error ());
+		      return error_mark_node;
+		    }
+		  if (!is_capture_proxy (r))
+		    {
+		      /* Make sure the one we found is the one we want.  */
+		      tree ctx = enclosing_instantiation_of (DECL_CONTEXT (t));
+		      if (ctx != DECL_CONTEXT (r))
+			r = NULL_TREE;
+		    }
 		}
 
 	      if (r)
@@ -15620,7 +15631,7 @@  tsubst_copy (tree t, tree args, tsubst_flags_t com
 		    }
 		  gcc_assert (cp_unevaluated_operand || TREE_STATIC (r)
 			      || decl_constant_var_p (r)
-			      || errorcount || sorrycount);
+			      || seen_error ());
 		  if (!processing_template_decl
 		      && !TREE_STATIC (r))
 		    r = process_outer_var_ref (r, complain);
Index: testsuite/g++.dg/template/crash130.C
===================================================================
--- testsuite/g++.dg/template/crash130.C	(nonexistent)
+++ testsuite/g++.dg/template/crash130.C	(working copy)
@@ -0,0 +1,15 @@ 
+// PR c++/62207
+
+template<typename T> void foo(T)
+{
+  X;  // { dg-error "not declared" }
+  X;
+}
+
+void X();
+void X(int);
+
+void bar()
+{
+  foo(0);
+}
Index: testsuite/g++.dg/template/crash131.C
===================================================================
--- testsuite/g++.dg/template/crash131.C	(nonexistent)
+++ testsuite/g++.dg/template/crash131.C	(working copy)
@@ -0,0 +1,16 @@ 
+// PR c++/62207
+
+template<class F>
+class X {
+public:
+  template<F f> class Y {};
+  template<F f> void y() {}
+  X(F f)
+  {
+    Y<f> y;  // { dg-error "not a constant" }
+
+    y.value();
+  }
+};
+
+int main() { X<int> x(1); }