This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH][RFC] Another approach to fixing "bad" inlining


> The case we have to handle is for example
>
> int foo();
>
> int bar(struct X x) { return foo(x); }
>
> int foo(int y);
>
> where this is undefined at runtime only, so we may not issue an error.
> Obviously inlining this is going to be difficult at the point we need
> to create assigments between the call expression parameter x and the
> formal parameter decl y.

We ran into the same problem a few years ago with C functions casted to 
incompatible function types.  Inlining in this case led to ICEs in the RTL 
expander.  We "solved" the problem by generating an explicit trap in lieu
of the bogus function call:

  /* Check that the function is called through a compatible prototype.
     If it is not, replace the call by a trap, wrapped up in a compound
     expression if necessary.  This has the nice side-effect to prevent
     the tree-inliner from generating invalid assignment trees which may
     blow up in the RTL expander later.  */
  if ((TREE_CODE (function) == NOP_EXPR
       || TREE_CODE (function) == CONVERT_EXPR)
      && TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
      && TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
      && !comptypes (fntype, TREE_TYPE (tem)))
    {
      tree return_type = TREE_TYPE (fntype);
      tree trap = build_function_call (built_in_decls[BUILT_IN_TRAP],
				       NULL_TREE);

      /* This situation leads to run-time undefined behavior.  We can't,
	 therefore, simply error unless we can prove that all possible
	 executions of the program must execute the code.  */
      warning (0, "function called through a non-compatible type");

      /* We can, however, treat "undefined" any way we please.
	 Call abort to encourage the user to fix the program.  */
      inform ("if this code is reached, the program will abort");

      if (VOID_TYPE_P (return_type))
	return trap;
      else
	{
	  tree rhs;

	  if (AGGREGATE_TYPE_P (return_type))
	    rhs = build_compound_literal (return_type,
					  build_constructor (return_type, 0));
	  else
	    rhs = fold_convert (return_type, integer_zero_node);

	  return build2 (COMPOUND_EXPR, return_type, trap, rhs);
	}
    }

-- 
Eric Botcazou


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]