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: [C++ PATCH] Fix up DECL_ARG_TYPE (PR c++/36631)


On Sat, Nov 08, 2008 at 01:51:06AM -0500, Jason Merrill wrote:
> I don't understand why the caller cares about DECL_ARG_TYPE.  I'll dig  
> into this some more.

Better testcase is maybe:

// { dg-options "-O2 -Winline" }
template <typename T>
struct C
{
  C ();
  C (const C &);
  ~C ();
  inline __attribute__((always_inline)) void foo (C, C);
};

void bar (C<int> c)
{
  c.foo (c, c);
}

template <typename T>
inline __attribute__((always_inline)) void C<T>::foo (C, C)
{
}

Again, when foo PARM_DECLs are tsubsted using tsubst_decl, C is
incomplete (and is TYPE_BEING_DEFINED, so complete_type doesn't help)
and nothing fixes up DECL_ARG_TYPE until C<int>::foo is genericized.
Before that bar is genericized and gimplified, and triggers:
  /* 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 (fndecl && DECL_ARGUMENTS (fndecl))
    {
      for (i = 0, p = DECL_ARGUMENTS (fndecl);
           i < nargs;
           i++, p = TREE_CHAIN (p))
        {
          /* We cannot distinguish a varargs function from the case
             of excess parameters, still deferring the inlining decision
             to the callee is possible.  */
          if (!p)
            break;
          if (p == error_mark_node
              || CALL_EXPR_ARG (*expr_p, i) == error_mark_node
              || !fold_convertible_p (DECL_ARG_TYPE (p),
                                      CALL_EXPR_ARG (*expr_p, i)))
            {
              CALL_CANNOT_INLINE_P (*expr_p) = 1;
              break;
            }
        }
    }
in gimplify_call_expr (the call argument is REFERENCE_TYPE, but
DECL_ARG_TYPE incorrectly RECORD_TYPE (with TREE_ADDRESSABLE set).
The reason why we don't want to inline calls with mismatching
types is that it horribly confuses the inliner, we often ICE on it. 
Consider say (in C) nonportable code like:
inline int foo ();

int bar (void)
{
  return foo (64LL);
}

inline int foo (int i, int j)
{
  return i + j;
}
on i?86-*-*.  We really don't want to inline in this case.
Afterwards C<int>::foo is genericized and DECL_ARG_TYPE is fixed up,
so when we actually throw all the functions into cgraph's hands, it
actually would be able to inline it, but gimple_call_cannot_inline_p
is already set at this point.

	Jakub


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