This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Re: [C++] SEGV in mapcar() with a CALL_EXPR
- To: gcc-bugs@gcc.gnu.org
- Subject: [PATCH] Re: [C++] SEGV in mapcar() with a CALL_EXPR
- From: Daniel Jacobowitz <drow@false.org>
- Date: Fri, 6 Aug 1999 18:51:29 -0400
- Cc: gcc-patches@gcc.gnu.org
- References: <19990804131959.A4656@them.org>
OK, I sat down with this for a while, and I came up with a patch.
As I suspected below, the problem seems to be that there IS an rtl in
the slot in question, which just happens to satisfy
TREE_CODE (TREE_OPERAND (t, 2)) == TREE_LIST. I took an unused
lang_flag (TREE_LANG_FLAG_5 in this case), and used it to flag whether
or not the node was actually supposed to contain a tree.
To be honest, I'm more surprised that this reuse of operand 2 and
preexpand_calls(), which is where the RTL got filled in, don't kill
each other more often.
One of the other flags could probably be reused instead of adding a
new one. I didn't want to try to figure out which flag, if any, would
never be applicable to these CALL_EXPRs.
Also, where mapcar now says:
if (TREE_OPERAND (t, 2)
&& CALL_EXPR_RTL_IS_TREE (t)
&& TREE_CODE (TREE_OPERAND (t, 2)) == TREE_LIST)
the last check is redundant - perhaps enable-checking should flag an
error if the operand is NOT a list, because it certainly should be.
Passes 'make check' on powerpc-*-linux-gnu with no regressions.
For cp/ChangeLog:
Fri Aug 6 18:43:19 EDT 1999 Daniel Jacobowitz <dan@debian.org>
* cp-tree.h (CALL_EXPR_RTL_IS_TREE): Add and document.
* lex.c (make_call_declarator): Set CALL_EXPR_RTL_IS_TREE
if appropriate.
(set_quals_and_spec): Likewise.
* tree.c (mapcar): Check CALL_EXPR_RTL_IS_TREE.
On Wed, Aug 04, 1999 at 01:19:59PM -0400, Daniel Jacobowitz wrote:
> Attached is a testcase for this elusive little segfault on
> powerpc-*-linux-gnu. It's exceedingly sensitive - the problem
> disappeared if I used an absolute -I path instead of a relative one.
> And now that I have looked at what is going on, I think I understand
> why.
>
> In cp/tree.c:mapcar, around line 1887, is this code snippet:
>
> /* tree.def says that operand two is RTL, but
> make_call_declarator puts trees in there. */
> if (TREE_OPERAND (t, 2)
> && TREE_CODE (TREE_OPERAND (t, 2)) == TREE_LIST)
> TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
> else
> TREE_OPERAND (t, 2) = NULL_TREE;
> return t;
>
> The problem is, from what I can tell, that there is actually an RTL in
> this slot which purely by coincidence meets that condition. In this
> case, from what I can tell, the rtl is (reg:SI 85).
>
> More gory details:
>
> (gdb) p debug_tree(t)
> <call_expr 0x1033afb8
> type <reference_type 0x106883c8
> type <record_type 0x1065d440 Header allocated from permanent_obstack
> permanent needs-constructing type_1 type_5 BLK
> size <integer_cst 0x1069ef58 constant permanent 68256>
> align 32 symtab 0 alias set 0 fields <field_decl 0x10692968 Signature> context <record_type 0x1065d180 pkgCache>
> needs-constructor X() X(constX&) this=(X&) n_parents 0 use_template=0 interface-only
> member-functions <tree_vec 0x10686548 allocated from permanent_obstack
> permanent
> elt 0 <overload 0x1069ed48>
> elt 2 <function_decl 0x1069e1d0 CheckSizes>
> elt 3 <function_decl 0x1069ebd0 __as>>
> pointer_to_this <pointer_type 0x1065d4f0> reference_to_this <reference_type 0x106883c8> chain <type_decl 0x1065d598 Header>>
> allocated from permanent_obstack
> unsigned permanent SI
> size <integer_cst 0x10344c80 constant permanent 32>
> align 32 symtab 0 alias set -1>
> allocated from function obstack
> side-effects
> arg 0 <addr_expr 0x1033afd8
> type <pointer_type 0x10753098 type <method_type 0x10688498>
> allocated from permanent_obstack
> unsigned permanent SI size <integer_cst 0x10344c80 32>
> align 32 symtab 0 alias set -1>
> allocated from function obstack
>
> arg 0 <function_decl 0x10688520 Head type <method_type 0x10688498>
> allocated from permanent_obstack
> used permanent public static external inline defer-output decl_5 SI file ../build/include/apt-pkg/pkgcache.h line 94
> frame_size 0 context <record_type 0x1065d180 pkgCache> arguments <parm_decl 0x106885b0 this>
> result <result_decl 0x10692328> initial <block 0x10699400>
> decl-main-variant 0x10688520
> (mem/f:SI (symbol_ref:SI ("Head__8pkgCache")) 550)
> saved-insns 0x10699438 chain <function_decl 0x106887c8 PkgBegin>>>
> arg 1 <tree_list 0x1033aff0 allocated from function obstack
>
> value <nop_expr 0x1033b008 type <pointer_type 0x1065d230>
> allocated from function obstack
>
> arg 0 <convert_expr 0x1033b020 type <pointer_type 0x10787698>
> allocated from function obstack
> arg 0 <parm_decl 0x10824860 Cache>>>>
> rtl 2 (reg:SI 85)
> >
> $36 = void
> (gdb) list
> 1886
> 1887 /* tree.def says that operand two is RTL, but
> 1888 make_call_declarator puts trees in there. */
> 1889 if (TREE_OPERAND (t, 2)
> 1890 && TREE_CODE (TREE_OPERAND (t, 2)) == TREE_LIST)
> 1891 TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
> 1892 else
> 1893 TREE_OPERAND (t, 2) = NULL_TREE;
> 1894 return t;
> 1895
> (gdb) where
> #0 mapcar (t=0x1033afb8, func=0x1025b290 <permanent_p>) at /usr/src/gcc/gcc-2.95/gcc/cp/tree.c:1891
> ...
> (gdb) cont
> Continuing.
>
> Program received signal SIGSEGV, Segmentation fault.
> 0x1025b2a4 in permanent_p (t=0x220000) at /usr/src/gcc/gcc-2.95/gcc/cp/tree.c:1998
> 1998 return TREE_PERMANENT (t) ? t : NULL_TREE;
> (gdb) bt
> #0 0x1025b2a4 in permanent_p (t=0x220000) at /usr/src/gcc/gcc-2.95/gcc/cp/tree.c:1998
> #1 0x1025a6e0 in mapcar (t=0x220000, func=0x1025b290 <permanent_p>)
> at /usr/src/gcc/gcc-2.95/gcc/cp/tree.c:1743
> #2 0x1025a8ac in mapcar (t=0x1033b038, func=0x1025b290 <permanent_p>)
> at /usr/src/gcc/gcc-2.95/gcc/cp/tree.c:1790
> #3 0x1025abc0 in mapcar (t=0x1033afb8, func=0x1025b290 <permanent_p>)
> at /usr/src/gcc/gcc-2.95/gcc/cp/tree.c:1891
> #4 0x1025ac24 in mapcar (t=0x1033afa0, func=0x1025b290 <permanent_p>)
> at /usr/src/gcc/gcc-2.95/gcc/cp/tree.c:1908
> #5 0x1025ac24 in mapcar (t=0x1033af88, func=0x1025b290 <permanent_p>)
> at /usr/src/gcc/gcc-2.95/gcc/cp/tree.c:1908
> #6 0x1025ac24 in mapcar (t=0x1033af70, func=0x1025b290 <permanent_p>)
> at /usr/src/gcc/gcc-2.95/gcc/cp/tree.c:1908
> #7 0x1025aab8 in mapcar (t=0x1033af50, func=0x1025b290 <permanent_p>)
> at /usr/src/gcc/gcc-2.95/gcc/cp/tree.c:1836
> #8 0x1025aaf0 in mapcar (t=0x1033af38, func=0x1025b290 <permanent_p>)
> at /usr/src/gcc/gcc-2.95/gcc/cp/tree.c:1877
> #9 0x1025aaf0 in mapcar (t=0x1033af20, func=0x1025b290 <permanent_p>)
> at /usr/src/gcc/gcc-2.95/gcc/cp/tree.c:1877
> #10 0x10246528 in build_new_1 (exp=0x1033be98) at /usr/src/gcc/gcc-2.95/gcc/cp/init.c:2470
> #11 0x101f42f8 in cplus_expand_expr (exp=0x1033be98, target=0x1025b290, tmode=VOIDmode,
> modifier=EXPAND_NORMAL) at /usr/src/gcc/gcc-2.95/gcc/cp/expr.c:247
> #12 0x10047bc0 in expand_expr (exp=0x1033be98, target=0x0, tmode=VOIDmode, modifier=EXPAND_NORMAL)
> at /usr/src/gcc/gcc-2.95/gcc/expr.c:8226
> #13 0x10045158 in expand_expr (exp=0x1033bed0, target=0x0, tmode=SImode, modifier=EXPAND_NORMAL)
> at /usr/src/gcc/gcc-2.95/gcc/expr.c:6869
> #14 0x1003f2ec in store_expr (exp=0x1033bed0, target=0x107dd0f8, want_value=0)
> at /usr/src/gcc/gcc-2.95/gcc/expr.c:3715
> #15 0x100415c4 in store_field (target=0x107dd0d8, bitsize=32, bitpos=0, mode=SImode, exp=0x1033bed0,
> value_mode=VOIDmode, unsignedp=1, align=4, total_size=20, alias_set=802)
> at /usr/src/gcc/gcc-2.95/gcc/expr.c:4773
> #16 0x1003eaf8 in expand_assignment (to=0x1033bbe0, from=0x1033bed0, want_value=0,
> suggest_reg=271827272) at /usr/src/gcc/gcc-2.95/gcc/expr.c:3413
> #17 0x10047478 in expand_expr (exp=0x1033bee8, target=0x1033bed0, tmode=VOIDmode,
> modifier=EXPAND_NORMAL) at /usr/src/gcc/gcc-2.95/gcc/expr.c:7949
> #18 0x1002dd90 in expand_expr_stmt (exp=0x1033bee8) at /usr/src/gcc/gcc-2.95/gcc/stmt.c:1669
> #19 0x101f2d40 in cplus_expand_expr_stmt (exp=0x1033bee8) at /usr/src/gcc/gcc-2.95/gcc/cp/decl.c:14855
> #20 0x1025448c in finish_expr_stmt (expr=0x1033bee8) at /usr/src/gcc/gcc-2.95/gcc/cp/semantics.c:82
> #21 0x1022a90c in yyparse () at parse.y:3282
> #22 0x1000517c in compile_file ()
> #23 0x1000a090 in main ()
> #24 0xfedbe94 in ()
>
>
>
> And last but not least,
> .ident "GCC: (GNU) 2.95 19990728 (release)"
Dan
/--------------------------------\ /--------------------------------\
| Daniel Jacobowitz |__| SCS Class of 2002 |
| Debian GNU/Linux Developer __ Carnegie Mellon University |
| dan@debian.org | | dmj+@andrew.cmu.edu |
\--------------------------------/ \--------------------------------/
diff -rcp ../egcs/for-unstable/gcc-2.95/gcc/cp/cp-tree.h gcc-2.95/gcc/cp/cp-tree.h
*** ../egcs/for-unstable/gcc-2.95/gcc/cp/cp-tree.h Thu Jun 24 09:16:17 1999
--- gcc-2.95/gcc/cp/cp-tree.h Fri Aug 6 17:41:45 1999
*************** Boston, MA 02111-1307, USA. */
*** 52,58 ****
4: BINFO_NEW_VTABLE_MARKED.
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
or FIELD_DECL).
! 5: Not used.
6: Not used.
Usage of TYPE_LANG_FLAG_?:
--- 52,58 ----
4: BINFO_NEW_VTABLE_MARKED.
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
or FIELD_DECL).
! 5: CALL_EXPR_RTL_IS_TREE.
6: Not used.
Usage of TYPE_LANG_FLAG_?:
*************** extern int flag_new_for_scope;
*** 1614,1619 ****
--- 1614,1622 ----
/* Nonzero for _TYPE means that the _TYPE defines a destructor. */
#define TYPE_HAS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_2(NODE))
+
+ /* Nonzero for CALL_EXPR means that operands[2] is a cv_qualifier tree */
+ #define CALL_EXPR_RTL_IS_TREE(NODE) (TREE_LANG_FLAG_5(NODE))
#if 0
/* Nonzero for _TYPE node means that creating an object of this type
diff -rcp ../egcs/for-unstable/gcc-2.95/gcc/cp/lex.c gcc-2.95/gcc/cp/lex.c
*** ../egcs/for-unstable/gcc-2.95/gcc/cp/lex.c Thu Jun 24 09:16:26 1999
--- gcc-2.95/gcc/cp/lex.c Fri Aug 6 16:14:25 1999
*************** make_call_declarator (target, parms, cv_
*** 226,231 ****
--- 226,233 ----
tree target, parms, cv_qualifiers, exception_specification;
{
target = build_parse_node (CALL_EXPR, target, parms, cv_qualifiers);
+ if (cv_qualifiers != NULL_TREE)
+ CALL_EXPR_RTL_IS_TREE (target) = 1;
TREE_TYPE (target) = exception_specification;
return target;
}
*************** set_quals_and_spec (call_declarator, cv_
*** 235,240 ****
--- 237,246 ----
tree call_declarator, cv_qualifiers, exception_specification;
{
TREE_OPERAND (call_declarator, 2) = cv_qualifiers;
+ if (cv_qualifiers != NULL_TREE)
+ CALL_EXPR_RTL_IS_TREE (call_declarator) = 1;
+ else
+ CALL_EXPR_RTL_IS_TREE (call_declarator) = 0;
TREE_TYPE (call_declarator) = exception_specification;
}
diff -rcp ../egcs/for-unstable/gcc-2.95/gcc/cp/tree.c gcc-2.95/gcc/cp/tree.c
*** ../egcs/for-unstable/gcc-2.95/gcc/cp/tree.c Thu Jun 24 09:16:27 1999
--- gcc-2.95/gcc/cp/tree.c Fri Aug 6 16:08:20 1999
*************** mapcar (t, func)
*** 1887,1892 ****
--- 1887,1893 ----
/* tree.def says that operand two is RTL, but
make_call_declarator puts trees in there. */
if (TREE_OPERAND (t, 2)
+ && CALL_EXPR_RTL_IS_TREE (t)
&& TREE_CODE (TREE_OPERAND (t, 2)) == TREE_LIST)
TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
else