Here, we got ourselves into infinite recursion in fold, resulting in a stack overflow. I believe the crux is that we're passing UNARY_PLUS_EXPR, a C++-only code, into fold which can't really fold e.g. 1 + UNARY_PLUS_EXPR <1>. I think cp_fold should be able to fold this to 2, but currently is not. But I noticed that cxx_eval_constant_expression seems to handle this: if (tcode == UNARY_PLUS_EXPR) r = fold_convert (TREE_TYPE (t), op); so I tweaked cp_fold to do something similar. With this patch we're able to fold the expression above properly and fold doesn't run into infinite looping anymore.
I made the test a run-time test to sanity-check we're generating the correct value. Bootstrapped/regtested on x86_64-linux, ok for trunk? 2016-03-10 Marek Polacek <pola...@redhat.com> PR c++/70153 * cp-gimplify.c (cp_fold): Handle UNARY_PLUS_EXPR. * g++.dg/delayedfold/unary-plus1.C: New test. diff --git gcc/cp/cp-gimplify.c gcc/cp/cp-gimplify.c index 6af3760..db23efe 100644 --- gcc/cp/cp-gimplify.c +++ gcc/cp/cp-gimplify.c @@ -2009,6 +2009,8 @@ cp_fold (tree x) else x = fold_build1_loc (loc, code, TREE_TYPE (x), op0); } + else if (code == UNARY_PLUS_EXPR) + x = fold_convert (TREE_TYPE (x), op0); else x = fold (x); diff --git gcc/testsuite/g++.dg/delayedfold/unary-plus1.C gcc/testsuite/g++.dg/delayedfold/unary-plus1.C index e69de29..5ebee22 100644 --- gcc/testsuite/g++.dg/delayedfold/unary-plus1.C +++ gcc/testsuite/g++.dg/delayedfold/unary-plus1.C @@ -0,0 +1,15 @@ +// PR c++/70153 +// { dg-do run } + +unsigned long long int +foo (unsigned long long int i) +{ + return 2ULL * ((1 + (unsigned long int) +1) * i); +} + +int +main (void) +{ + if (foo (3ULL) != 12ULL) + __builtin_abort (); +} Marek