blob: 36e0e682c387246443964f2c9e06b9ae7a32abbe [file] [log] [blame]
/* PR c++/84850 - -Wclass-memaccess on a memcpy in a copy assignment
operator with no nontrivial bases or members
{ dg-do compile }
{ dg-options "-Wclass-memaccess -ftrack-macro-expansion=0" } */
typedef __SIZE_TYPE__ size_t;
extern "C" void* memcpy (void*, const void*, size_t);
extern "C" void* memset (void*, int, size_t);
template <int>
struct EmptyClass { };
template <int>
struct TrivialClass
{
bool a;
int b;
void *c;
double d[2];
void (*e)();
};
template <int>
struct HasDefault
{
HasDefault ();
};
/* Verify that raw memory accesses from non-static members of a class with
an empty base is not diagnosed. */
struct EmptyWithBase: EmptyClass<0>, EmptyClass<1>, EmptyClass<2>
{
EmptyWithBase ()
{
memset (this, 0, sizeof *this);
}
EmptyWithBase (const EmptyWithBase &x)
{
memcpy (this, &x, sizeof *this);
}
~EmptyWithBase ()
{
memset (this, 0, sizeof *this);
}
void operator= (const EmptyWithBase &x)
{
memcpy (this, &x, sizeof *this);
}
void clear ()
{
memset (this, 0, sizeof *this); // { dg-bogus "\\\[-Wclass-memaccess" }
}
void copy (const void *p)
{
memcpy (this, p, sizeof *this); // { dg-bogus "\\\[-Wclass-memaccess" }
}
static void bad_clear (EmptyWithBase &x)
{
memset (&x, 0, sizeof x); // { dg-warning "\\\[-Wclass-memaccess" }
}
static void bad_copy (EmptyWithBase &x, const void *p)
{
memcpy (&x, p, sizeof x); // { dg-warning "\\\[-Wclass-memaccess" }
}
};
/* Verify that raw memory accesses from non-static members of a class with
all trivial members is not diagnosed. */
struct HasTrivialMembers
{
bool a;
int b;
void *c;
double d[2];
void (*e)();
TrivialClass<1> trivial;
HasTrivialMembers ()
{
memset (this, 0, sizeof *this);
}
HasTrivialMembers (const HasTrivialMembers &x)
{
memcpy (this, &x, sizeof *this);
}
~HasTrivialMembers ()
{
memset (this, 0, sizeof *this);
}
void operator= (const HasTrivialMembers &x)
{
memcpy (this, &x, sizeof *this);
}
void clear ()
{
memset (this, 0, sizeof *this); // { dg-bogus "\\\[-Wclass-memaccess" }
}
void copy (const void *p)
{
memcpy (this, p, sizeof *this); // { dg-bogus "\\\[-Wclass-memaccess" }
}
static void bad_clear (HasTrivialMembers &x)
{
memset (&x, 0, sizeof x); // { dg-warning "\\\[-Wclass-memaccess" }
}
static void bad_copy (HasTrivialMembers &x, const void *p)
{
memcpy (&x, p, sizeof x); // { dg-warning "\\\[-Wclass-memaccess" }
}
};
/* Verify that raw memory accesses from non-static members of a class with
a trivial base class and no non-trivial members is not diagnosed. */
struct HasTrivialBase: TrivialClass<1>
{
TrivialClass<2> a[2];
HasTrivialBase ()
{
memset (this, 0, sizeof *this); // { dg-bogus "\\\[-Wclass-memaccess" }
}
HasTrivialBase (const HasTrivialBase &x)
{
memcpy (this, &x, sizeof *this); // { dg-bogus "\\\[-Wclass-memaccess" }
}
~HasTrivialBase ()
{
memset (this, 0, sizeof *this); // { dg-bogus "\\\[-Wclass-memaccess" }
}
void operator= (const HasTrivialBase &x)
{
memcpy (this, &x, sizeof *this);
}
void clear ()
{
memset (this, 0, sizeof *this); // { dg-bogus "\\\[-Wclass-memaccess" }
}
void copy (void *p)
{
memcpy (this, p, sizeof *this); // { dg-bogus "\\\[-Wclass-memaccess" }
}
};
struct HasTrivialBases: TrivialClass<1>, TrivialClass<2>
{
TrivialClass<3> a[2];
HasTrivialBases ()
{
memset (this, 0, sizeof *this); // { dg-bogus "\\\[-Wclass-memaccess" }
}
HasTrivialBases (const HasTrivialBases &x)
{
memcpy (this, &x, sizeof *this); // { dg-bogus "\\\[-Wclass-memaccess" }
}
~HasTrivialBases ()
{
memset (this, 0, sizeof *this); // { dg-bogus "\\\[-Wclass-memaccess" }
}
void operator= (const HasTrivialBases &x)
{
memcpy (this, &x, sizeof *this);
}
void clear ()
{
memset (this, 0, sizeof *this); // { dg-bogus "\\\[-Wclass-memaccess" }
}
void copy (void *p)
{
memcpy (this, p, sizeof *this); // { dg-bogus "\\\[-Wclass-memaccess" }
}
};
struct DerivesFromNontrivialClass: HasDefault<1> { };
/* Verify that raw memory accesses from members of a class with a non-trivial
base class is diagnosed. */
struct HasNonTrivialBase: TrivialClass<1>, TrivialClass<2>,
DerivesFromNontrivialClass,
TrivialClass<3>, TrivialClass<4>
{
HasNonTrivialBase ()
{
memset (this, 0, sizeof *this); // { dg-warning "\\\[-Wclass-memaccess" }
}
HasNonTrivialBase (const HasNonTrivialBase &x)
{
memcpy (this, &x, sizeof *this); // { dg-warning "\\\[-Wclass-memaccess" }
}
~HasNonTrivialBase ()
{
memset (this, 0, sizeof *this); // { dg-warning "\\\[-Wclass-memaccess" }
}
HasNonTrivialBase& operator= (const HasNonTrivialBase &x)
{
memcpy (this, &x, sizeof *this); // { dg-warning "\\\[-Wclass-memaccess" }
return *this;
}
void clear ()
{
memset (this, 0, sizeof *this); // { dg-warning "\\\[-Wclass-memaccess" }
}
void copy (void *p)
{
memcpy (this, p, sizeof *this); // { dg-warning "\\\[-Wclass-memaccess" }
}
};
struct DerivesIndidirectlyFromNontrivialClass:
TrivialClass<1>, TrivialClass<2>,
DerivesFromNontrivialClass,
TrivialClass<3>, TrivialClass<4> { };
/* Verify that raw memory accesses from members of a class with a non-trivial
indirect base class is diagnosed. */
struct HasIndirectNonTrivialBase: TrivialClass<5>, TrivialClass<6>,
TrivialClass<7>, TrivialClass<8>,
DerivesIndidirectlyFromNontrivialClass
{
HasIndirectNonTrivialBase ()
{
memset (this, 0, sizeof *this); // { dg-warning "\\\[-Wclass-memaccess" }
}
HasIndirectNonTrivialBase (const HasIndirectNonTrivialBase &x)
{
memcpy (this, &x, sizeof *this); // { dg-warning "\\\[-Wclass-memaccess" }
}
~HasIndirectNonTrivialBase ()
{
memset (this, 0, sizeof *this); // { dg-warning "\\\[-Wclass-memaccess" }
}
HasIndirectNonTrivialBase& operator= (const HasIndirectNonTrivialBase &x)
{
memcpy (this, &x, sizeof *this); // { dg-warning "\\\[-Wclass-memaccess" }
return *this;
}
void clear ()
{
memset (this, 0, sizeof *this); // { dg-warning "\\\[-Wclass-memaccess" }
}
void copy (void *p)
{
memcpy (this, p, sizeof *this); // { dg-warning "\\\[-Wclass-memaccess" }
}
};