Patchwork [C++] fix semi-random template specialization ICE

login
register
mail settings
Submitter Alexandre Oliva
Date May 3, 2012, 6:17 p.m.
Message ID <or8vh9yvrg.fsf@livre.localdomain>
Download mbox | patch
Permalink /patch/156756/
State New
Headers show

Comments

Alexandre Oliva - May 3, 2012, 6:17 p.m.
I've recently started getting “libstdc++-v3/include/functional:2057:63:
internal compiler error: tree check: expected tree_vec, have error_mark
in comp_template_args_with_info, at cp/pt.c:7038” on i686-linux-gnu,
building libstdc++-v3/src/c++11/functexcept.cc -fPIC, at stage1 and on
non-bootstrapped builds.  The problem would not occur on
x86_64-linux-gnu with the -m32 multilib.

Jakub reported getting similar errors in the testsuite, but not in the
libstdc++-v3 build.

Bisection revealted the patch that exposed the latent error was r186948,
but I gather it only introduced more potentially-failing specializations
in libstdc++-v3 at spots that wouldn't trigger the bug before.

I couldn't pinpoint the exact source of randomness that causes the build
to fail at precisely the same point on a given machine at a certain
stage, but not on others.  What I do know is that it occurs while
iterating on a hash table, which, depending on how the hash is computed,
may explain why we visit some nodes before others depending on
environmentally-deterministic causes.

Anyway, the problem is that, for some unsuitable candidate template
specializations, tsubst returns error_mark_node, which tsubst_decl
stores in argvec, and later on register_specialization gets this
error_mark_node and tries to access it as a tree_vec.

The trivial patch that avoids the misbehavior is returning
error_mark_node as soon as we get that for argvec.  Bootstrapped on
i686-pc-linux-gnu and x86_64-linux-gnu, regstrapped on the latter.

Ok to install?
Martin Jambor - May 4, 2012, 11:48 a.m.
Hi,

On Thu, May 03, 2012 at 03:17:23PM -0300, Alexandre Oliva wrote:
> I've recently started getting “libstdc++-v3/include/functional:2057:63:
> internal compiler error: tree check: expected tree_vec, have error_mark
> in comp_template_args_with_info, at cp/pt.c:7038” on i686-linux-gnu,
> building libstdc++-v3/src/c++11/functexcept.cc -fPIC, at stage1 and on
> non-bootstrapped builds.  The problem would not occur on
> x86_64-linux-gnu with the -m32 multilib.

I suppose this is PR 53209.

Thanks for dealing with this!

Martin

> 
> Jakub reported getting similar errors in the testsuite, but not in the
> libstdc++-v3 build.
> 
> Bisection revealted the patch that exposed the latent error was r186948,
> but I gather it only introduced more potentially-failing specializations
> in libstdc++-v3 at spots that wouldn't trigger the bug before.
> 
> I couldn't pinpoint the exact source of randomness that causes the build
> to fail at precisely the same point on a given machine at a certain
> stage, but not on others.  What I do know is that it occurs while
> iterating on a hash table, which, depending on how the hash is computed,
> may explain why we visit some nodes before others depending on
> environmentally-deterministic causes.
> 
> Anyway, the problem is that, for some unsuitable candidate template
> specializations, tsubst returns error_mark_node, which tsubst_decl
> stores in argvec, and later on register_specialization gets this
> error_mark_node and tries to access it as a tree_vec.
> 
> The trivial patch that avoids the misbehavior is returning
> error_mark_node as soon as we get that for argvec.  Bootstrapped on
> i686-pc-linux-gnu and x86_64-linux-gnu, regstrapped on the latter.
> 
> Ok to install?
> 

> for  gcc/cp/ChangeLog
> from  Alexandre Oliva  <aoliva@redhat.com>
> 
> 	* pt.c (tsubst_decl): Bail out if argvec is error_mark_node.
> 
> Index: gcc/cp/pt.c
> ===================================================================
> --- gcc/cp/pt.c.orig	2012-04-30 15:34:44.018432544 -0300
> +++ gcc/cp/pt.c	2012-04-30 15:34:47.988375071 -0300
> @@ -10626,6 +10626,8 @@ tsubst_decl (tree t, tree args, tsubst_f
>  		tmpl = DECL_TI_TEMPLATE (t);
>  		gen_tmpl = most_general_template (tmpl);
>  		argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
> +		if (argvec == error_mark_node)
> +		  RETURN (error_mark_node);
>  		hash = hash_tmpl_and_args (gen_tmpl, argvec);
>  		spec = retrieve_specialization (gen_tmpl, argvec, hash);
>  	      }

> 
> 
> -- 
> 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 Brazil Compiler Engineer
H.J. Lu - May 6, 2012, 6:45 p.m.
On Fri, May 4, 2012 at 4:48 AM, Martin Jambor <mjambor@suse.cz> wrote:
> Hi,
>
> On Thu, May 03, 2012 at 03:17:23PM -0300, Alexandre Oliva wrote:
>> I've recently started getting “libstdc++-v3/include/functional:2057:63:
>> internal compiler error: tree check: expected tree_vec, have error_mark
>> in comp_template_args_with_info, at cp/pt.c:7038” on i686-linux-gnu,
>> building libstdc++-v3/src/c++11/functexcept.cc -fPIC, at stage1 and on
>> non-bootstrapped builds.  The problem would not occur on
>> x86_64-linux-gnu with the -m32 multilib.
>
> I suppose this is PR 53209.
>
> Thanks for dealing with this!
>
> Martin
>
>>
>> Jakub reported getting similar errors in the testsuite, but not in the
>> libstdc++-v3 build.
>>
>> Bisection revealted the patch that exposed the latent error was r186948,
>> but I gather it only introduced more potentially-failing specializations
>> in libstdc++-v3 at spots that wouldn't trigger the bug before.
>>
>> I couldn't pinpoint the exact source of randomness that causes the build
>> to fail at precisely the same point on a given machine at a certain
>> stage, but not on others.  What I do know is that it occurs while
>> iterating on a hash table, which, depending on how the hash is computed,
>> may explain why we visit some nodes before others depending on
>> environmentally-deterministic causes.
>>
>> Anyway, the problem is that, for some unsuitable candidate template
>> specializations, tsubst returns error_mark_node, which tsubst_decl
>> stores in argvec, and later on register_specialization gets this
>> error_mark_node and tries to access it as a tree_vec.
>>
>> The trivial patch that avoids the misbehavior is returning
>> error_mark_node as soon as we get that for argvec.  Bootstrapped on
>> i686-pc-linux-gnu and x86_64-linux-gnu, regstrapped on the latter.
>>
>> Ok to install?
>>
>
>> for  gcc/cp/ChangeLog
>> from  Alexandre Oliva  <aoliva@redhat.com>
>>
>>       * pt.c (tsubst_decl): Bail out if argvec is error_mark_node.
>>
>> Index: gcc/cp/pt.c
>> ===================================================================
>> --- gcc/cp/pt.c.orig  2012-04-30 15:34:44.018432544 -0300
>> +++ gcc/cp/pt.c       2012-04-30 15:34:47.988375071 -0300
>> @@ -10626,6 +10626,8 @@ tsubst_decl (tree t, tree args, tsubst_f
>>               tmpl = DECL_TI_TEMPLATE (t);
>>               gen_tmpl = most_general_template (tmpl);
>>               argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
>> +             if (argvec == error_mark_node)
>> +               RETURN (error_mark_node);
>>               hash = hash_tmpl_and_args (gen_tmpl, argvec);
>>               spec = retrieve_specialization (gen_tmpl, argvec, hash);
>>             }
>

This does fix:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53209

Can someone review it?

Thanks.
Dodji Seketeli - May 10, 2012, 8:18 a.m.
Alexandre Oliva <aoliva@redhat.com> a écrit:

[...]

> Anyway, the problem is that, for some unsuitable candidate template
> specializations, tsubst returns error_mark_node, which tsubst_decl
> stores in argvec, and later on register_specialization gets this
> error_mark_node and tries to access it as a tree_vec.
>
> The trivial patch that avoids the misbehavior is returning
> error_mark_node as soon as we get that for argvec.  Bootstrapped on
> i686-pc-linux-gnu and x86_64-linux-gnu, regstrapped on the latter.
>
> Ok to install?

FYI, this has been reported as
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53209, so you might add a
reference to that bug in the ChangeLog.

Other than that, I cannot approve or reject this patch, but FWIW, it
looks fine to me.

Let's CC jason.

> for  gcc/cp/ChangeLog
> from  Alexandre Oliva  <aoliva@redhat.com>
>
> 	* pt.c (tsubst_decl): Bail out if argvec is error_mark_node.
>
> Index: gcc/cp/pt.c
> ===================================================================
> --- gcc/cp/pt.c.orig	2012-04-30 15:34:44.018432544 -0300
> +++ gcc/cp/pt.c	2012-04-30 15:34:47.988375071 -0300
> @@ -10626,6 +10626,8 @@ tsubst_decl (tree t, tree args, tsubst_f
>  		tmpl = DECL_TI_TEMPLATE (t);
>  		gen_tmpl = most_general_template (tmpl);
>  		argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
> +		if (argvec == error_mark_node)
> +		  RETURN (error_mark_node);
>  		hash = hash_tmpl_and_args (gen_tmpl, argvec);
>  		spec = retrieve_specialization (gen_tmpl, argvec, hash);
>  	      }

Thanks.
Jason Merrill - May 10, 2012, 1:14 p.m.
OK.

Jason
Alexandre Oliva - May 14, 2012, 5:22 a.m.
On May 10, 2012, Jason Merrill <jason@redhat.com> wrote:

> OK.

Thanks, installed a few days ago.

Is it ok for the 4.7 branch too?  I didn't realize the bug could occur
there as well, but PR c++/53209 suggests it does.  Regstrapping now.
Jason Merrill - May 14, 2012, 12:53 p.m.
On 05/14/2012 01:22 AM, Alexandre Oliva wrote:
> Is it ok for the 4.7 branch too?

Yes.

Jason

Patch

for  gcc/cp/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* pt.c (tsubst_decl): Bail out if argvec is error_mark_node.

Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c.orig	2012-04-30 15:34:44.018432544 -0300
+++ gcc/cp/pt.c	2012-04-30 15:34:47.988375071 -0300
@@ -10626,6 +10626,8 @@  tsubst_decl (tree t, tree args, tsubst_f
 		tmpl = DECL_TI_TEMPLATE (t);
 		gen_tmpl = most_general_template (tmpl);
 		argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
+		if (argvec == error_mark_node)
+		  RETURN (error_mark_node);
 		hash = hash_tmpl_and_args (gen_tmpl, argvec);
 		spec = retrieve_specialization (gen_tmpl, argvec, hash);
 	      }