[patch] Fix PR c++/26739: ICE on template redefinition as friend

Volker Reichelt reichelt@igpm.rwth-aachen.de
Wed Apr 19 09:29:00 GMT 2006

Mainline currently ICEs on the following invalid code snippet:

  template<char> void foo() {}

  template<int> struct A
      template<char> friend void foo() {}

  A<0> a;

The error message is:

  PR26739.cc: In instantiation of 'A<0>':
  PR26739.cc:8:   instantiated from here
  PR26739.cc:5: error: redefinition of 'template<char <anonymous> > void foo()'
  PR26739.cc:1: error: 'template<char <anonymous> > void foo()' previously declared here
  PR26739.cc:5: internal compiler error: tree check: expected var_decl or function_decl or type_decl or template_decl, have error_mark in tsubst_friend_function, at cp/pt.c:5286

The offending code is indeed in tsubst_friend_function which
(apart from the comments) looks like this:

      old_decl = pushdecl_namespace_level (new_friend, /*is_friend=*/true);
      pop_nested_namespace (ns);

      if (old_decl != new_friend)
	  if (!new_friend_is_defn)
	      DECL_TEMPLATE_INFO (old_decl) = new_friend_template_info;

The problem is that pushdecl_namespace_level returns an error_mark_node
for the testcase above. This causes the ICE when the compiler tries to
access DECL_TEMPLATE_INFO (old_decl).

The patch below fixes this by returning early if pushdecl_namespace_level

Bootstrapped and regtested on x86_64-unknown-linux-gnu.
Ok for mainline?

However, I'm unsure about a testcase, because I'm not familiar with
g++.old-deja: The ICE was triggered by g++.old-deja/g++.pt/friend36.C,
but the test still passed (I only found the ICE in the logs).
Is it possible to modify the original testcase to trigger on the ICE
or should I rather add a new test with appropriate error markers to



2006-04-18  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>

	PR c++/26739
	* pt.c (tsubst_friend_function): Return early if
	pushdecl_namespace_level fails.

--- gcc/gcc/cp/pt.c	2006-04-18 19:20:10 +0200
+++ gcc/gcc/cp/pt.c	2006-04-18 19:13:01 +0200
@@ -5236,6 +5236,9 @@ tsubst_friend_function (tree decl, tree 
       old_decl = pushdecl_namespace_level (new_friend, /*is_friend=*/true);
       pop_nested_namespace (ns);
+      if (old_decl == error_mark_node)
+	return error_mark_node;
       if (old_decl != new_friend)
 	  /* This new friend declaration matched an existing

More information about the Gcc-patches mailing list