Again, other conditions for being an aggregate are checked
elsewhere. */
CLASSTYPE_NON_AGGREGATE (t)
- |= ((cxx_dialect < cxx20
- ? type_has_user_provided_or_explicit_constructor (t)
- : TYPE_HAS_USER_CONSTRUCTOR (t))
+ |= (type_has_user_provided_or_explicit_constructor (t)
|| TYPE_POLYMORPHIC_P (t));
/* This is the C++98/03 definition of POD; it changed in C++0x, but we
retain the old definition internally for ABI reasons. */
CLASSTYPE_NON_LAYOUT_POD_P (t) = true;
}
+ /* P1008: Prohibit aggregates with user-declared constructors. */
+ if (cxx_dialect >= cxx20 && TYPE_HAS_USER_CONSTRUCTOR (t))
+ {
+ CLASSTYPE_NON_AGGREGATE (t) = true;
+ if (!CLASSTYPE_NON_LAYOUT_POD_P (t))
+ {
+ /* c++/120012: The C++20 aggregate change affected layout. */
+ if (!abi_version_at_least (21))
+ CLASSTYPE_NON_LAYOUT_POD_P (t) = true;
+ if (abi_version_crosses (21))
+ CLASSTYPE_NON_AGGREGATE_POD (t) = true;
+ }
+ }
+
/* If the only explicitly declared default constructor is user-provided,
set TYPE_HAS_COMPLEX_DFLT. */
if (!TYPE_HAS_COMPLEX_DFLT (t)
static void
check_non_pod_aggregate (tree field)
{
- if (!abi_version_crosses (17) || cxx_dialect < cxx14)
+ if ((!abi_version_crosses (17) || cxx_dialect < cxx14)
+ && (!abi_version_crosses (21) || cxx_dialect < cxx20))
return;
if (TREE_CODE (field) != FIELD_DECL
|| (!DECL_FIELD_IS_BASE (field)
tree type = TREE_TYPE (field);
if (TYPE_IDENTIFIER (type) == as_base_identifier)
type = TYPE_CONTEXT (type);
- if (!CLASS_TYPE_P (type) || !CLASSTYPE_NON_POD_AGGREGATE (type))
+ if (!CLASS_TYPE_P (type) || (!CLASSTYPE_NON_POD_AGGREGATE (type)
+ && !CLASSTYPE_NON_AGGREGATE_POD (type)))
return;
tree size = end_of_class (type, (DECL_FIELD_IS_BASE (field)
? eoc_nvsize : eoc_nv_or_dsize));
{
location_t loc = DECL_SOURCE_LOCATION (next);
if (DECL_FIELD_IS_BASE (next))
- warning_at (loc, OPT_Wabi,"offset of %qT base class for "
- "%<-std=c++14%> and up changes in "
- "%<-fabi-version=17%> (GCC 12)", TREE_TYPE (next));
+ {
+ if (abi_version_crosses (17)
+ && CLASSTYPE_NON_POD_AGGREGATE (type))
+ warning_at (loc, OPT_Wabi,"offset of %qT base class for "
+ "%<-std=c++14%> and up changes in "
+ "%<-fabi-version=17%> (GCC 12)", TREE_TYPE (next));
+ else if (abi_version_crosses (21)
+ && CLASSTYPE_NON_AGGREGATE_POD (type))
+ warning_at (loc, OPT_Wabi,"offset of %qT base class for "
+ "%<-std=c++20%> and up changes in "
+ "%<-fabi-version=21%> (GCC 16)", TREE_TYPE (next));
+ }
else
- warning_at (loc, OPT_Wabi, "offset of %qD for "
- "%<-std=c++14%> and up changes in "
- "%<-fabi-version=17%> (GCC 12)", next);
+ {
+ if (abi_version_crosses (17)
+ && CLASSTYPE_NON_POD_AGGREGATE (type))
+ warning_at (loc, OPT_Wabi, "offset of %qD for "
+ "%<-std=c++14%> and up changes in "
+ "%<-fabi-version=17%> (GCC 12)", next);
+ else if (abi_version_crosses (21)
+ && CLASSTYPE_NON_AGGREGATE_POD (type))
+ warning_at (loc, OPT_Wabi, "offset of %qD for "
+ "%<-std=c++20%> and up changes in "
+ "%<-fabi-version=21%> (GCC 16)", next);
+ }
}
}
unsigned unique_obj_representations_set : 1;
bool erroneous : 1;
bool non_pod_aggregate : 1;
+ bool non_aggregate_pod : 1;
/* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template. If
/* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or
remove a flag. */
- unsigned dummy : 3;
+ unsigned dummy : 2;
tree primary_base;
vec<tree_pair_s, va_gc> *vcall_indices;
with a hash_set only filled in when abi_version_crosses (17). */
#define CLASSTYPE_NON_POD_AGGREGATE(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->non_pod_aggregate)
+
+/* True if this class is layout-POD though it's not an aggregate in C++20 and
+ above (c++/120012). This could also be a hash_set. */
+#define CLASSTYPE_NON_AGGREGATE_POD(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->non_aggregate_pod)
\f
/* Additional macros for inheritance information. */