+2007-06-23 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/16876
+ PR middle-end/29478
+ * tree.h (CALL_CANNOT_INLINE_P): New macro to access static_flag
+ for CALL_EXPRs.
+ * tree-inline.c (initialize_inlined_parameters): Do not call
+ lang_hooks.tree_inlining.convert_parm_for_inlining.
+ * cgraphbuild.c (initialize_inline_failed): Set inline failed
+ reason for mismatched types.
+ * gimplify.c (gimplify_call_expr): Verify the call expression
+ arguments match the called function type signature. Otherwise
+ mark the call expression to be not considered for inlining
+ using CALL_CANNOT_INLINE_P flag.
+ * ipa-inline.c (cgraph_mark_inline): Honor CALL_CANNOT_INLINE_P on the
+ edges call expression.
+ (cgraph_decide_inlining_of_small_function): Likewise.
+ (cgraph_decide_inlining): Likewise.
+ * c-objc-common.h (LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING):
+ Remove define.
+ * c-tree.h (c_convert_parm_for_inlining): Remove declaration.
+ * c-typeck.c (c_convert_parm_for_inlining): Remove.
+ * langhooks-def.h (lhd_tree_inlining_convert_parm_for_inlining):
+ Remove declaration.
+ (LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING): Remove define.
+ * langhooks.c (lhd_tree_inlining_convert_parm_for_inlining):
+ Remove.
+ * langhooks.h (struct lang_hooks_for_tree_inlining): Remove
+ convert_parm_for_inlining member.
+
2007-06-23 Richard Earnshaw <rearnsha@arm.com>
PR target/31152
#undef LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS
#define LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS \
c_disregard_inline_limits
-#undef LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING
-#define LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
- c_convert_parm_for_inlining
#undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN
#define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN c_dump_tree
extern void c_finish_case (tree);
extern tree build_asm_expr (tree, tree, tree, tree, bool);
extern tree build_asm_stmt (tree, tree);
-extern tree c_convert_parm_for_inlining (tree, tree, tree, int);
extern int c_types_compatible_p (tree, tree);
extern tree c_begin_compound_stmt (bool);
extern tree c_end_compound_stmt (tree, bool);
return error_mark_node;
}
-
-/* Convert VALUE for assignment into inlined parameter PARM. ARGNUM
- is used for error and warning reporting and indicates which argument
- is being processed. */
-
-tree
-c_convert_parm_for_inlining (tree parm, tree value, tree fn, int argnum)
-{
- tree ret, type;
-
- /* If FN was prototyped at the call site, the value has been converted
- already in convert_arguments.
- However, we might see a prototype now that was not in place when
- the function call was seen, so check that the VALUE actually matches
- PARM before taking an early exit. */
- if (!value
- || (TYPE_ARG_TYPES (TREE_TYPE (fn))
- && (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
- == TYPE_MAIN_VARIANT (TREE_TYPE (value)))))
- return value;
-
- type = TREE_TYPE (parm);
- ret = convert_for_assignment (type, value,
- ic_argpass_nonproto, fn,
- fn, argnum);
- if (targetm.calls.promote_prototypes (TREE_TYPE (fn))
- && INTEGRAL_TYPE_P (type)
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- ret = default_conversion (ret);
- return ret;
-}
\f
/* If VALUE is a compound expr all of whose expressions are constant, then
return its value. Otherwise, return error_mark_node.
"considered for inlining");
else if (!node->local.inlinable)
e->inline_failed = N_("function not inlinable");
+ else if (CALL_CANNOT_INLINE_P (e->call_stmt))
+ e->inline_failed = N_("mismatched arguments");
else
e->inline_failed = N_("function not considered for inlining");
}
static enum gimplify_status
gimplify_call_expr (tree *expr_p, tree *pre_p, bool want_value)
{
- tree decl;
+ tree decl, parms, p;
enum gimplify_status ret;
int i, nargs;
nargs = call_expr_nargs (*expr_p);
+ /* Get argument types for verification. */
+ decl = get_callee_fndecl (*expr_p);
+ parms = NULL_TREE;
+ if (decl)
+ parms = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ else if (POINTER_TYPE_P (TREE_TYPE (CALL_EXPR_FN (*expr_p))))
+ parms = TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (*expr_p))));
+
+ /* Verify if the type of the argument matches that of the function
+ declaration. If we cannot verify this or there is a mismatch,
+ mark the call expression so it doesn't get inlined later. */
+ if (parms)
+ {
+ for (i = 0, p = parms; i < nargs; i++, p = TREE_CHAIN (p))
+ if (!p
+ || TREE_VALUE (p) == error_mark_node
+ || CALL_EXPR_ARG (*expr_p, i) == error_mark_node
+ || !lang_hooks.types_compatible_p
+ (TREE_TYPE (CALL_EXPR_ARG (*expr_p, i)), TREE_VALUE (p)))
+ {
+ CALL_CANNOT_INLINE_P (*expr_p) = 1;
+ break;
+ }
+ }
+ else if (decl && DECL_ARGUMENTS (decl))
+ {
+ for (i = 0, p = DECL_ARGUMENTS (decl); i < nargs;
+ i++, p = TREE_CHAIN (p))
+ if (!p
+ || p == error_mark_node
+ || CALL_EXPR_ARG (*expr_p, i) == error_mark_node
+ || !lang_hooks.types_compatible_p
+ (TREE_TYPE (CALL_EXPR_ARG (*expr_p, i)), TREE_TYPE (p)))
+ {
+ CALL_CANNOT_INLINE_P (*expr_p) = 1;
+ break;
+ }
+ }
+ else if (nargs != 0)
+ CALL_CANNOT_INLINE_P (*expr_p) = 1;
+
+ /* Finally, gimplify the function arguments. */
for (i = (PUSH_ARGS_REVERSED ? nargs - 1 : 0);
PUSH_ARGS_REVERSED ? i >= 0 : i < nargs;
PUSH_ARGS_REVERSED ? i-- : i++)
struct cgraph_node *to = edge->caller;
struct cgraph_node *what = edge->callee;
struct cgraph_edge *e, *next;
- int times = 0;
/* Look for all calls, mark them inline and clone recursively
all inlined functions. */
for (e = what->callers; e; e = next)
{
next = e->next_caller;
- if (e->caller == to && e->inline_failed)
+ if (e->caller == to && e->inline_failed
+ && !CALL_CANNOT_INLINE_P (e->call_stmt))
{
cgraph_mark_inline_edge (e, true);
if (e == edge)
edge = next;
- times++;
}
}
- gcc_assert (times);
+
return edge;
}
}
gcc_assert (edge->aux);
edge->aux = NULL;
- if (!edge->inline_failed)
+ if (!edge->inline_failed || CALL_CANNOT_INLINE_P (edge->call_stmt))
continue;
/* When not having profile info ready we don't weight by any way the
for (e = node->callers; e; e = next)
{
next = e->next_caller;
- if (!e->inline_failed)
+ if (!e->inline_failed || CALL_CANNOT_INLINE_P (e->call_stmt))
continue;
if (cgraph_recursive_inlining_p (e->caller, e->callee,
&e->inline_failed))
extern int lhd_tree_inlining_cannot_inline_tree_fn (tree *);
extern int lhd_tree_inlining_disregard_inline_limits (tree);
extern int lhd_tree_inlining_auto_var_in_fn_p (tree, tree);
-extern tree lhd_tree_inlining_convert_parm_for_inlining (tree, tree, tree, int);
extern void lhd_initialize_diagnostics (struct diagnostic_context *);
extern tree lhd_callgraph_analyze_expr (tree *, int *, tree);
lhd_tree_inlining_auto_var_in_fn_p
#define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P \
hook_bool_tree_tree_false
-#define LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
- lhd_tree_inlining_convert_parm_for_inlining
#define LANG_HOOKS_TREE_INLINING_INITIALIZER { \
LANG_HOOKS_TREE_INLINING_WALK_SUBTREES, \
LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS, \
LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P, \
LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P, \
- LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
}
#define LANG_HOOKS_CALLGRAPH_ANALYZE_EXPR lhd_callgraph_analyze_expr
|| TREE_CODE (var) == RESULT_DECL));
}
-/* lang_hooks.tree_inlining.convert_parm_for_inlining performs any
- language-specific conversion before assigning VALUE to PARM. */
-
-tree
-lhd_tree_inlining_convert_parm_for_inlining (tree parm ATTRIBUTE_UNUSED,
- tree value,
- tree fndecl ATTRIBUTE_UNUSED,
- int argnum ATTRIBUTE_UNUSED)
-{
- return value;
-}
-
/* lang_hooks.tree_dump.dump_tree: Dump language-specific parts of tree
nodes. Returns nonzero if it does not want the usual dumping of the
second argument. */
int (*disregard_inline_limits) (tree);
int (*auto_var_in_fn_p) (tree, tree);
bool (*var_mod_type_p) (tree, tree);
- tree (*convert_parm_for_inlining) (tree, tree, tree, int);
};
struct lang_hooks_for_callgraph
+2007-06-23 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/16876
+ PR middle-end/29478
+ * gcc.dg/pr29254.c: The warning is bogus.
+ * gcc.dg/warn-1.c: Likewise.
+ * gcc.dg/assign-warn-3.c: Likewise.
+ * gcc.dg/noncompile/pr16876.c: The testcase is bogus, remove.
+
2007-06-23 Richard Earnshaw <rearnsha@arm.com>
* gcc.c-torture/execute/20070623-1.c: New.
/* This is valid to execute, so maybe shouldn't warn at all. */
void f0(x) signed char *x; { }
-void g0(unsigned char *x) { f0(x); } /* { dg-warning "warning: pointer targets in passing argument 1 of 'f0' differ in signedness" } */
+void g0(unsigned char *x) { f0(x); } /* { dg-bogus "warning: pointer targets in passing argument 1 of 'f0' differ in signedness" } */
/* This is undefined on execution but still must compile. */
void f1(x) int *x; { }
-void g1(unsigned int *x) { f1(x); } /* { dg-warning "warning: pointer targets in passing argument 1 of 'f1' differ in signedness" } */
+void g1(unsigned int *x) { f1(x); } /* { dg-bogus "warning: pointer targets in passing argument 1 of 'f1' differ in signedness" } */
+++ /dev/null
-/* { dg-options "-O -finline-functions" } */
-
-static void g();
-struct bigstack {
- char space[4096];
-};
-
-
-void f() {
- g(0); /* { dg-error "incompatible type for argument 1 of 'g'" } */
-}
-
-static void g(struct bigstack bstack) {
- g(bstack);
-}
/* { dg-do compile } */
/* { dg-options "-O3 -Werror" } */
-/* { dg-message "warnings being treated as errors" "" {target "*-*-*"} 0 } */
list_compare (int * list1)
{
func2 (const int * fb)
{
- func1 ((int *) fb); /* { dg-error "discards qualifiers" } */
+ func1 ((int *) fb); /* { dg-bogus "discards qualifiers" } */
}
{
void *vp;
- foo (vp); /* { dg-warning "passing argument 1 of" } */
+ foo (vp); /* { dg-bogus "passing argument 1 of" } */
}
tree a;
tree p;
tree vars = NULL_TREE;
- int argnum = 0;
call_expr_arg_iterator iter;
tree static_chain = CALL_EXPR_STATIC_CHAIN (exp);
equivalent VAR_DECL, appropriately initialized. */
for (p = parms, a = first_call_expr_arg (exp, &iter); p;
a = next_call_expr_arg (&iter), p = TREE_CHAIN (p))
- {
- tree value;
-
- ++argnum;
-
- /* Find the initializer. */
- value = lang_hooks.tree_inlining.convert_parm_for_inlining
- (p, a, fn, argnum);
-
- setup_one_parameter (id, p, value, fn, bb, &vars);
- }
+ setup_one_parameter (id, p, a, fn, bb, &vars);
/* Initialize the static chain. */
p = DECL_STRUCT_FUNCTION (fn)->static_chain_decl;
POINTER_TYPE, REFERENCE_TYPE
MOVE_NONTEMPORAL in
GIMPLE_MODIFY_STMT
- CASE_HIGH_SEEN in CASE_LABEL_EXPR
+ CASE_HIGH_SEEN in
+ CASE_LABEL_EXPR
+ CALL_CANNOT_INLINE_P in
+ CALL_EXPR
public_flag:
#define CASE_HIGH_SEEN(NODE) \
(CASE_LABEL_EXPR_CHECK (NODE)->base.static_flag)
+/* Used to mark a CALL_EXPR as not suitable for inlining. */
+#define CALL_CANNOT_INLINE_P(NODE) ((NODE)->base.static_flag)
+
/* In an expr node (usually a conversion) this means the node was made
implicitly and should not lead to any sort of warning. In a decl node,
warnings concerning the decl should be suppressed. This is used at