2001-10-12 Jakub Jelinek * tree-inline.c (initialize_inlined_parameters): Fail if less arguments are passed than expected. (expand_call_inline): Cleanup if initialize_inlined_parameters fails. * g++.dg/other/inline1.C: New test. --- gcc/tree-inline.c.jj Tue Oct 9 16:03:13 2001 +++ gcc/tree-inline.c Fri Oct 12 17:08:23 2001 @@ -474,20 +474,28 @@ initialize_inlined_parameters (id, args, /* Loop through the parameter declarations, replacing each with an equivalent VAR_DECL, appropriately initialized. */ - for (p = parms, a = args; p; - a = a ? TREE_CHAIN (a) : a, p = TREE_CHAIN (p)) + for (p = parms, a = args; p; a = TREE_CHAIN (a), p = TREE_CHAIN (p)) { #ifndef INLINER_FOR_JAVA tree init_stmt; tree cleanup; #endif /* not INLINER_FOR_JAVA */ tree var; tree value; tree var_sub; + if (a == NULL_TREE) + { + pop_srcloc (); + /* If less arguments were passed than actually required, + issue warning and avoid inlining. */ + warning ("too few arguments passed to inline function, suppressing inlining"); + return error_mark_node; + } + /* Find the initializer. */ value = (*lang_hooks.tree_inlining.convert_parm_for_inlining) - (p, a ? TREE_VALUE (a) : NULL_TREE, fn); + (p, TREE_VALUE (a), fn); /* If the parameter is never assigned to, we may not need to create a new variable here at all. Instead, we may be able @@ -863,6 +871,14 @@ expand_call_inline (tp, walk_subtrees, d /* Initialize the parameters. */ arg_inits = initialize_inlined_parameters (id, TREE_OPERAND (t, 1), fn); + if (arg_inits == error_mark_node) + { + /* Clean up. */ + splay_tree_delete (id->decl_map); + id->decl_map = st; + return NULL_TREE; + } + /* Expand any inlined calls in the initializers. Do this before we push FN on the stack of functions we are inlining; we want to inline calls to FN that appear in the initializers for the --- gcc/testsuite/g++.dg/other/inline1.C.jj Fri Oct 12 16:54:05 2001 +++ gcc/testsuite/g++.dg/other/inline1.C Fri Oct 12 17:14:35 2001 @@ -0,0 +1,38 @@ +// { dg-do compile { target i?86-*-* } } +// { dg-options -O } + +typedef unsigned int u4; +typedef unsigned long long u8; +typedef u8 (*u8tou8)(u8); + +struct C { + static inline u8 a(u4 x, u4 y); + static inline u8 b(unsigned char *p) { return c(*(u8 *)p); } + static inline u8 c(u8 x) { // { dg-warning "too few arguments" "too few" } + return ((u8tou8)a)(x); + } +}; + +inline u8 C::a(u4 x, u4 y) { + return x + y; +} + +u8 n = 0x123456789abcdef; + +struct B { + unsigned char *e; + B() { e = (unsigned char *) &n; } + u8 f() { + return C::b(e); + } +}; + +struct A { + B *g; + void foo (); +}; + +void A::foo () +{ + g->f(); +}