Bug 40058 - C++ FE generates struct assignments with mismatched sizes
Summary: C++ FE generates struct assignments with mismatched sizes
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2009-05-07 10:57 UTC by Richard Biener
Modified: 2012-03-21 10:05 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Richard Biener 2009-05-07 10:57:58 UTC
struct Base {
 Base();
 int i;
 char c;
};

template <typename BaseT>
struct actor : public BaseT {
 actor(BaseT const& base);
 char c;
};

template <typename BaseT>
actor<BaseT>::actor(BaseT const& base)
    : BaseT(base) {}

actor<Base>
foo(const Base c)
{
 return actor<Base>(c);
}

with -O2 we inline the constructor and get

actor<Base> foo(Base) D.2099 (const struct Base c)
{
 struct actor D.2133;
 struct actor D.2134;

<bb 2>:
 D.2133.D.2111 = c;
 D.2134 = D.2133;
 return D.2134;

}

The assignment

 D.2133.D.2111 = c;

has on the LHS a size of 40 (from the FIELD_DECL) and on the
RHS a size of 64, from the decl.  In the un-inlined constructor we had
the bogus

actor<BaseT>::actor(const BaseT&) [with BaseT = Base] D.2105 (struct
actor * const this, const struct Base & base)
{
<bb 2>:
 this_1(D)->D.2111 = *base_2(D);
 return;

}

with the same issue (size 40 on the lhs, size 64 on the rhs).

"Size" in term of what the FIELD_DECL DECL_SIZE says for the component-refs,
which is according to people what is relevant - not the type size.  Likewise
for the RHS the DECL_SIZE (which is equal to TYPE_SIZE).

For less contrived examples the FE generates a memcpy to carefully _not_
overwrite padding that may be used in tail packing.

Eventually from the above you can construct a wrong-code testcase if expansion
chooses the wrong size for the expansion of the assignment.
Comment 1 Jason Merrill 2010-02-10 05:46:49 UTC
Your comment to the patch that removed LANG_HOOKS_EXPR_SIZE suggests that this isn't a problem anymore:

http://gcc.gnu.org/ml/gcc-patches/2009-08/msg01593.html
Comment 2 Richard Biener 2010-02-10 09:42:12 UTC
We still have these constructs and expand still properly deals with them
(it uses the size of the LHS).

I'm not sure what's the best thing to do about this bug.  Eventually better
documenting what sizes in an assignment are really relevant.

The FE now indeed emits memcpy whenever there is not a DECL or FIELD_DECL
on the LHS that specifies sizes, like for

void bar (Base *p, Base *q)
{
  *p = *q;
}

;; Function void bar(Base*, Base*) (null)
;; enabled by -tree-original

<<cleanup_point <<< Unknown tree: expr_stmt
  (void) (struct Base *) __builtin_memcpy (NON_LVALUE_EXPR <p>, (const struct Base &) (const struct Base *) NON_LVALUE_EXPR <q>, 5) >>>
>>;


So the langhook was no longer necessary.
Comment 3 Martin Jambor 2012-03-21 10:05:24 UTC
If this ever gets fixed, we can remove a test in SRA as in:

http://gcc.gnu.org/ml/gcc-patches/2012-03/msg01356.html