Bugzilla – Bug 165
[llvmg++] call through array of pointers to member functions fails assertion
Last modified: 2003-12-08 00:35:45
You need to log in before you can comment on or make changes to this bug.
The following test program involving a call through a pointer-to-member function fails an assertion in llvm-g++ of the "tree not handled yet" flavor. The tree it prints is a SAVE_EXPR. It looks to me as though c_llvm_expand_lvalue_expr() needs to be extended to allow for a SAVE_EXPR lvalue. I noted that if I take out the call to opcode(), the assert no longer fails. /**********************************/ extern "C" void abort(); class Evil { public: void fun () { abort (); } void step (unsigned int instr); unsigned short opcode (const unsigned int instr) const; }; typedef void (Evil::*memfunptr) (); void Evil::step (unsigned int instr) { static const memfunptr jumpTable[] = { &Evil::fun }; (this->*jumpTable[opcode (instr)]) (); } /************************/ The resulting long and tedious llvm-g++ barf is as follows: ERROR: In function c_llvm_expand_lvalue_expr:5926, tree not handled by LLVM yet! <save_expr 0x40018340 type <record_type 0x40190e00 readonly DI size <integer_cst 0x4001a618 constant 64> unit size <integer_cst 0x4001a99c constant 8> align 32 symtab 0 alias set -1 fields <field_decl 0x40190cb0 __pfn type <pointer_type 0x401904d0> unsigned SI file cpu.ii line 10 size <integer_cst 0x4001a9b0 constant 32> unit size <integer_cst 0x4001a9d8 constant 4> align 32 offset_align 32 offset <integer_cst 0x4001aa64 constant 0> bit offset <integer_cst 0x4001ab04 constant 0> context <record_type 0x40190b60> arguments <integer_cst 0x4001aa64 0> chain <field_decl 0x40190d20 __delta>> ptrmemfunc fn type <pointer_type 0x401904d0 type <method_type 0x4018d230> readonly unsigned SI size <integer_cst 0x4001a9b0 32> unit size <integer_cst 0x4001a9d8 4> align 32 symtab 0 alias set -1> pointer_to_this <pointer_type 0x40191000>> side-effects readonly arg 0 <array_ref 0x401584c8 type <record_type 0x40190e00> side-effects readonly arg 0 <var_decl 0x40190ee0 jumpTable type <array_type 0x40190e70> readonly addressable asm_written used static tree_1 decl_6 DI file cpu.ii line 10 size <integer_cst 0x4001a618 64> unit size <integer_cst 0x4001a99c 8> align 32 context <function_decl 0x4018d5b0 step> initial <constructor 0x4018ea14>> arg 1 <nop_expr 0x4018eb54 type <integer_type 0x4001c4d0 int> side-effects arg 0 <call_expr 0x401584b0 type <integer_type 0x4001c460 short unsigned int> side-effects arg 0 <addr_expr 0x4018eb40 type <pointer_type 0x401915b0> constant arg 0 <function_decl 0x4018d850 opcode>> arg 1 <tree_list 0x4018eb18 value <nop_expr 0x4018eb04 type <pointer_type 0x4018d000> readonly arg 0 <nop_expr 0x4018eaf0 type <pointer_type 0x4018d000> readonly arg 0 <parm_decl 0x40190310 this>>> chain <tree_list 0x4018eb2c value <parm_decl 0x40190150 instr>>>>>> arg 1 <function_decl 0x4018d5b0 step type <method_type 0x4018d540 type <void_type 0x40023bd0 void> DI size <integer_cst 0x4001a618 64> unit size <integer_cst 0x4001a99c 8> align 32 symtab 0 alias set -1 method basetype <record_type 0x4018bee0 Evil> arg-types <tree_list 0x40186e10 value <pointer_type 0x4018d000> chain <tree_list 0x40186dfc value <integer_type 0x4001c540 unsigned int> chain <tree_list 0x4015a8e8 tree_2 value <void_type 0x40023bd0 void>>>>> asm_written public static decl_5 QI file cpu.ii line 9 context <record_type 0x4018bee0 Evil> arguments <parm_decl 0x40190310 this type <pointer_type 0x4018d310> readonly unsigned SI file cpu.ii line 9 size <integer_cst 0x4001a9b0 32> unit size <integer_cst 0x4001a9d8 4> align 32 context <function_decl 0x4018d5b0 step> initial <pointer_type 0x4018d310> arg-type <pointer_type 0x4018d310> chain <parm_decl 0x40190150 instr>> result <result_decl 0x40190380 type <void_type 0x40023bd0 void> VOID file cpu.ii line 9 align 8 context <function_decl 0x4018d5b0 step>> initial <block 0x40184de8> chain <function_decl 0x4018d850 opcode type <method_type 0x4018d930> addressable used public external QI file cpu.ii line 6 context <record_type 0x4018bee0 Evil> arguments <parm_decl 0x4018da80 this> >> rtl 2 (nil) rtl 3 (nil) > cpu.ii: In member function `void Evil::step(unsigned int)': cpu.ii:11: internal compiler error: in c_llvm_expand_lvalue_expr, at llvm-expand.c:5926 Please submit a full bug report, with preprocessed source if appropriate. See <URL:http://llvm.cs.uiuc.edu> for instructions.
Cute. This is definitely a bug, and should be relatively easy to fix. Nice 1.1 fodder. :) -Chris
Minor fix to summary. Procrastinate, procrastinate.
Fixed. Testcase here: test/Regression/C++Frontend/2003-12-08-ArrayOfPtrToMemberFunc.cpp Patch here: $ diff -u llvm-expand.c~ llvm-expand.c --- llvm-expand.c~ Fri Nov 28 22:21:26 2003 +++ llvm-expand.c Mon Dec 8 00:27:54 2003 @@ -5044,6 +5044,37 @@ llvm_expand_expr(Fn, exp, Result); break; + case SAVE_EXPR: + /* Return the innermost context enclosing DECL that is a FUNCTION_DECL, or + zero if none. */ + context = decl_function_context (exp); + + /* If this SAVE_EXPR was at global context, assume we are an + initialization function and move it into our context. */ + if (context == 0) + SAVE_EXPR_CONTEXT (exp) = current_function_decl; + + /* We treat inline_function_decl as an alias for the current function + because that is the inline function whose vars, types, etc. + are being merged into the current function. + See expand_inline_function. */ + if (context == current_function_decl) + context = 0; + + /* If this is non-local, handle it. */ + if (context) LLVM_TODO_TREE(exp); /* Don't handle nested functions yet! */ + + /* If the expression has not been computed yet... */ + if (SAVE_EXPR_LLVM(exp) == 0) { + /* Expand the saved expression. This does not handle bit-fields yet. */ + Result = llvm_expand_lvalue_expr(Fn, TREE_OPERAND(exp, 0), 0, 0); + SAVE_EXPR_LLVM(exp) = Result; + TREE_USED(exp) = 1; + } else { + Result = SAVE_EXPR_LLVM(exp); + } + break; + case COND_EXPR: { /* ?: expression */ /* Allocate a new temporary to hold the result of the expression */ llvm_basicblock *TrueBlock = llvm_basicblock_new("cond_true"); Thanks for the bug report! -Chris
whoops, I thought the midair collision was just due to fixing pointers, which I had covered. fix my bogus fix