Patchwork C++ PATCH for c++/53816 (ICE with local reference in template)

login
register
mail settings
Submitter Jason Merrill
Date July 3, 2012, 3:26 a.m.
Message ID <4FF26683.8050304@redhat.com>
Download mbox | patch
Permalink /patch/168678/
State New
Headers show

Comments

Jason Merrill - July 3, 2012, 3:26 a.m.
resolves_to_fixed_type_p has caused a lot of ICEs in templates over the 
years because it wants to look inside the DECL_INITIAL of variables with 
non-constant initializers which are still in pre-tsubst form.  Checking 
processing_template_decl to prevent this isn't strong enough, because 
fold_non_dependent_expr clears processing_template_decl in order to do 
its tsubst folding.  But instead we can test whether the current 
function is not completely instantiated.

Tested x86_64-pc-linux-gnu, applying to trunk and 4.7 (more conservative 
version).

Patch

commit a4d190b1380fe956f7758994e7de27366dbcc0bb
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Jul 2 16:44:12 2012 -0400

    	PR c++/53816
    	* class.c (resolves_to_fixed_type_p): Check uses_template_parms
    	(current_function_decl) instead of processing_template_decl.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 503a01e..633bff3 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6479,7 +6479,11 @@  resolves_to_fixed_type_p (tree instance, int* nonnull)
   int cdtorp = 0;
   tree fixed;
 
-  if (processing_template_decl)
+  /* processing_template_decl can be false in a template if we're in
+     fold_non_dependent_expr, but we still want to suppress this check.  */
+  if (processing_template_decl
+      || (current_function_decl
+	  && uses_template_parms (current_function_decl)))
     {
       /* In a template we only care about the type of the result.  */
       if (nonnull)
diff --git a/gcc/testsuite/g++.dg/template/ref6.C b/gcc/testsuite/g++.dg/template/ref6.C
new file mode 100644
index 0000000..2e1254a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/ref6.C
@@ -0,0 +1,15 @@ 
+// PR c++/53816
+
+template <typename T>
+struct S { int v () const; };
+template <typename T>
+struct V : public S<T> {};
+struct U
+{
+  V<int> v;
+  template<typename T>
+  struct W
+  {
+    W (U const &x) { V<int> const &v = x.v; v.v(); }
+  };
+};