Commit bedf03a2 by Jason Merrill Committed by Jason Merrill

Implement P0840, language support for empty objects.

	The [[no_unique_address]] attribute on a non-static data member
	enables the equivalent of the empty base optimization.

gcc/cp/
	* tree.c (handle_no_unique_addr_attribute): New.
	(cxx_attribute_table): Add [[no_unique_address]].
	* class.c (field_poverlapping_p): New.
	(layout_class_type): Check it.  Adjust DECL_SIZE of potentially
	overlapping fields.
	(layout_empty_base_or_field): Rename from layout_empty_base, handle
	FIELD_DECL as well.
	(build_base_field, record_subobject_offsets): Adjust.
c-family/
	* c-lex.c (c_common_has_attribute): Add no_unique_address.

From-SVN: r264813
parent 749c0e1d
2018-10-01 Jason Merrill <jason@redhat.com>
* c-lex.c (c_common_has_attribute): Add no_unique_address.
2018-10-01 Eric Botcazou <ebotcazou@adacore.com>
* c-ada-spec.c (get_underlying_decl): Get to the main type variant.
......
......@@ -356,6 +356,8 @@ c_common_has_attribute (cpp_reader *pfile)
|| is_attribute_p ("nodiscard", attr_name)
|| is_attribute_p ("fallthrough", attr_name))
result = 201603;
else if (is_attribute_p ("no_unique_address", attr_name))
result = 20180312;
if (result)
attr_name = NULL_TREE;
}
......
2018-10-03 Jason Merrill <jason@redhat.com>
Implement P0840, language support for empty objects.
* tree.c (handle_no_unique_addr_attribute): New.
(cxx_attribute_table): Add [[no_unique_address]].
* class.c (field_poverlapping_p): New.
(layout_class_type): Check it. Adjust DECL_SIZE of potentially
overlapping fields.
(layout_empty_base_or_field): Rename from layout_empty_base, handle
FIELD_DECL as well.
(build_base_field, record_subobject_offsets): Adjust.
2018-10-03 Martin Liska <mliska@suse.cz>
PR gcov-profile/86109
......
......@@ -4428,6 +4428,31 @@ handle_nodiscard_attribute (tree *node, tree name, tree /*args*/,
return NULL_TREE;
}
/* Handle a C++2a "no_unique_address" attribute; arguments as in
struct attribute_spec.handler. */
static tree
handle_no_unique_addr_attribute (tree* node,
tree name,
tree /*args*/,
int /*flags*/,
bool* no_add_attrs)
{
if (TREE_CODE (*node) != FIELD_DECL)
{
warning (OPT_Wattributes, "%qE attribute can only be applied to "
"non-static data members", name);
*no_add_attrs = true;
}
else if (DECL_C_BIT_FIELD (*node))
{
warning (OPT_Wattributes, "%qE attribute cannot be applied to "
"a bit-field", name);
*no_add_attrs = true;
}
return NULL_TREE;
}
/* Table of valid C++ attributes. */
const struct attribute_spec cxx_attribute_table[] =
{
......@@ -4449,6 +4474,8 @@ const struct attribute_spec std_attribute_table[] =
handle_unused_attribute, NULL },
{ "nodiscard", 0, 0, false, false, false, false,
handle_nodiscard_attribute, NULL },
{ "no_unique_address", 0, 0, true, false, false, false,
handle_no_unique_addr_attribute, NULL },
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
};
......
......@@ -37,6 +37,16 @@ struct B
B (long c) {m = c;}
};
#if __cpp_attributes
struct B2
{
[[no_unique_address]] Inter empty;
NonPod m;
B2 (long c) {m = c;}
};
#endif
struct C : NonPod, Inter
{
C (long c) : NonPod (c), Inter () {}
......@@ -65,6 +75,7 @@ int main ()
if (b2.m.m != 0x32333435)
return 2; // we copied padding, which clobbered b2.m.m
{
B c (0x12131415);
was = c.m.m;
c = 0x22232425;
......@@ -76,6 +87,22 @@ int main ()
if (c.m.m != 0x22232425)
return 4;
}
#if __cpp_attributes
{
B2 c (0x12131415);
was = c.m.m;
c = 0x22232425;
if (was != now)
return 3;
B2 d (0x32333435);
c.empty = d.empty;
if (c.m.m != 0x22232425)
return 4;
}
#endif
C e (0x32333435);
......
......@@ -9,9 +9,20 @@ struct B {
struct C : public B, public A {};
#if __cpp_attributes
struct C2 : public B
{
[[no_unique_address]] A a;
} c2;
#endif
C c;
int main () {
if ((void*) (A*) &c != &c)
return 1;
#if __cpp_attributes
if ((void*)&c2.a != &c2)
return 2;
#endif
}
......@@ -5,10 +5,20 @@ struct E1 {};
struct E2 : public E1 {};
struct S1 { int i; };
struct S2 : public S1, E2 {};
#if __cpp_attributes
struct S22 : public S1
{
[[no_unique_address]] E2 e2;
} s22;
#endif
S2 s2;
int main () {
if ((char *)(E2*) &s2 != (char *)&s2)
return 1;
#if __cpp_attributes
if ((char *)&s22.e2 != (char *)&s22)
return 2;
#endif
}
// { dg-do run { target c++2a } }
struct B { };
struct A
{
[[no_unique_address]] B b;
int i;
};
struct C
{
B b;
int i;
};
struct D: B { };
struct E
{
B b [[no_unique_address]];
D d [[no_unique_address]];
};
constexpr bool same (void *x, void *y) { return x == y; }
int main()
{
A a;
if (!same(&a.b, &a.i))
__builtin_abort();
C c;
if (same(&c.b, &c.i))
__builtin_abort();
E e;
if (same (&e.b, &e.d))
__builtin_abort();
}
// { dg-do compile { target c++11 } }
struct A
{
virtual void f();
char c;
};
struct B1 : A
{
char c2;
};
struct B2
{
A a [[no_unique_address]];
char c2;
};
struct C
{
char c;
};
struct D: virtual C
{
virtual void f();
};
struct B3: D
{
char c2;
};
struct B4
{
D d [[no_unique_address]];
char c2;
};
#define SA(X) static_assert ((X), #X)
SA (sizeof (B2) == sizeof (B1));
SA (sizeof (B3) == sizeof (B4));
// { dg-do compile { target c++11 } }
struct A {
unsigned char i : 1;
};
struct B: A
{
unsigned char j : 7;
};
struct B2
{
[[no_unique_address]] A a;
unsigned char j : 7;
};
#define SA(X) static_assert ((X), #X)
SA (sizeof (B) == sizeof (B2));
// { dg-do compile { target c++2a } }
[[no_unique_address]] struct B { }; // { dg-warning "attribute" }
[[no_unique_address]] int i; // { dg-warning "attribute" }
[[no_unique_address]] void f(); // { dg-warning "attribute" }
struct A
{
[[no_unique_address]] B b;
[[no_unique_address]] void f(); // { dg-warning "attribute" }
[[no_unique_address]] static B c; // { dg-warning "attribute" }
int i;
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment