This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[3.4 PATCH] PR c++/20995: Type-unsafe trees for templates
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Mark Mitchell <mark at codesourcery dot com>
- Date: Sun, 24 Apr 2005 12:24:19 -0600 (MDT)
- Subject: [3.4 PATCH] PR c++/20995: Type-unsafe trees for templates
The following patch is my proposed solution for PR c++/20995. Looking
through the code in the C++ front-end, I'll admit that I'm a bit shocked
and in one of those how could C++ templates have ever worked dazes.
It turns out that the trees constructed whilst parsing templates are
(and probably have always been) type-unsafe. From what I can see,
it's not unusual for the g++ front-end to construct PLUS_EXPR nodes
in template declarations, where one operand is of integer type and
the other of floating point type, for example.
The issue involves the flow of events through build_x_binary_op,
build_x_unary_op and build_x_conditional_expr, etc... Whilst
parsing these functions are called with the parsed potentially
mismatched arguments. These are then stored in orig_expr, or
orig_arg1 and orig_arg2. Then there's some processing involving
build_non_dependent_expr, before the initial trees are build
by calling the corresponding build_unary_op, build_new_op or
build_conditional_expr respectively. It's these low level functions
without the "_x_" that apply the default conversions to arguments,
decide the result type etc... However, it's the final step that
fatal: If processing_template_decl is true, the g++ front-end
throws away the constructued/folded/type-safe result and instead
calls build_min_non_dep with the original unpromoted/mismatched
arguments!
The implication of this change is that the trees constructed by
g++ whilst processing templates are not valid "generic" trees and
can't safely be passed to "fold" or other functions that expect
the usual invariants to apply.
For gcc 4.x, this issue has been resolved by Mark's patch for bugzilla
PR c++/17642, that introduces a new function fold_if_not_in_template,
that avoids ever calling "fold" whilst processing template declarations.
That PR was also just another symptom of the fact that g++ doesn't
create valid trees for templates until they are instantiated.
Unfortunately, Mark's full solution to PR c++/17642 is (IMHO) a bit
too invasive for the gcc 3.4 release branch. Instead, the patch below
is a minimal set of changes that are sufficient to resolve PR20995
which is an regression on the gcc-3_4-branch, originally misattributed
to the middle-end.
This certainly puts a a slightly different light the C++ front-end
maintainers arguments that they shouldn't call fold. I strongly
agree that until they have valid trees they certainly shouldn't be
calling fold. The java front-end for example, doesn't know the
types of expressions whilst parsing, but deduces/infers them later.
Like current g++, it doesn't call "fold" before it knows the types.
The following patch has been tested against the gcc-3_4-branch on
i686-pc-linux-gnu with a full "make bootstrap", all default languages,
and regression tested with a top-level "make -k check" with no new
failures.
Ok for the 3.4 branch?
2005-04-24 Roger Sayle <roger@eyesopen.com>
PR c++/20955
* call.c (build_conditional_expr): Don't call fold on the resulting
COND_EXPR when processing templates.
* typeck.c (build_binary_op): Don't call fold when processing
templates as we may construct trees with mismatched types.
* g++.dg/opt/pr20955-1.C: New test case.
Index: call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.452.2.24
diff -c -3 -p -r1.452.2.24 call.c
*** call.c 4 Apr 2005 05:45:35 -0000 1.452.2.24
--- call.c 23 Apr 2005 20:50:09 -0000
*************** build_conditional_expr (tree arg1, tree
*** 3278,3284 ****
}
valid_operands:
! result = fold (build (COND_EXPR, result_type, arg1, arg2, arg3));
/* We can't use result_type below, as fold might have returned a
throw_expr. */
--- 3278,3287 ----
}
valid_operands:
! result = build (COND_EXPR, result_type, arg1, arg2, arg3);
! if (!processing_template_decl)
! result = fold (result);
!
/* We can't use result_type below, as fold might have returned a
throw_expr. */
Index: typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.519.2.24
diff -c -3 -p -r1.519.2.24 typeck.c
*** typeck.c 17 Apr 2005 03:37:15 -0000 1.519.2.24
--- typeck.c 23 Apr 2005 20:50:10 -0000
*************** build_binary_op (enum tree_code code, tr
*** 3458,3464 ****
tree result = build (resultcode, build_type, op0, op1);
tree folded;
! folded = fold (result);
if (folded == result)
TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
if (final_type != 0)
--- 3458,3465 ----
tree result = build (resultcode, build_type, op0, op1);
tree folded;
! /* It's not safe to fold the type-unsafe trees in template decls. */
! folded = processing_template_decl ? result : fold (result);
if (folded == result)
TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
if (final_type != 0)
/* { dg-do compile } */
/* { dg-options "-O2" } */
template<int N> void foo()
{
double d = (N ? 0.0 : 0) + 1;
}
Roger
--
Roger Sayle, E-mail: roger@eyesopen.com
OpenEye Scientific Software, WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road, Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507. Fax: (+1) 505-473-0833