aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/class.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r--gcc/cp/class.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index a91e63a6301..d3d9aed7ff7 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1302,6 +1302,89 @@ handle_using_decl (tree using_decl, tree t)
alter_access (t, decl, access);
}
+/* walk_tree callback for check_abi_tags: if the type at *TP involves any
+ types with abi tags, add the corresponding identifiers to the VEC in
+ *DATA and set IDENTIFIER_MARKED. */
+
+struct abi_tag_data
+{
+ tree t;
+ tree subob;
+};
+
+static tree
+find_abi_tags_r (tree *tp, int */*walk_subtrees*/, void *data)
+{
+ if (!TAGGED_TYPE_P (*tp))
+ return NULL_TREE;
+
+ if (tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (*tp)))
+ {
+ struct abi_tag_data *p = static_cast<struct abi_tag_data*>(data);
+ for (tree list = TREE_VALUE (attributes); list;
+ list = TREE_CHAIN (list))
+ {
+ tree tag = TREE_VALUE (list);
+ tree id = get_identifier (TREE_STRING_POINTER (tag));
+ if (!IDENTIFIER_MARKED (id))
+ {
+ if (TYPE_P (p->subob))
+ {
+ warning (OPT_Wabi_tag, "%qT does not have the %E abi tag "
+ "that base %qT has", p->t, tag, p->subob);
+ inform (location_of (p->subob), "%qT declared here",
+ p->subob);
+ }
+ else
+ {
+ warning (OPT_Wabi_tag, "%qT does not have the %E abi tag "
+ "that %qT (used in the type of %qD) has",
+ p->t, tag, *tp, p->subob);
+ inform (location_of (p->subob), "%qD declared here",
+ p->subob);
+ inform (location_of (*tp), "%qT declared here", *tp);
+ }
+ }
+ }
+ }
+ return NULL_TREE;
+}
+
+/* Check that class T has all the abi tags that subobject SUBOB has, or
+ warn if not. */
+
+static void
+check_abi_tags (tree t, tree subob)
+{
+ tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (t));
+ if (attributes)
+ {
+ for (tree list = TREE_VALUE (attributes); list;
+ list = TREE_CHAIN (list))
+ {
+ tree tag = TREE_VALUE (list);
+ tree id = get_identifier (TREE_STRING_POINTER (tag));
+ IDENTIFIER_MARKED (id) = true;
+ }
+ }
+
+ tree subtype = TYPE_P (subob) ? subob : TREE_TYPE (subob);
+ struct abi_tag_data data = { t, subob };
+
+ cp_walk_tree_without_duplicates (&subtype, find_abi_tags_r, &data);
+
+ if (attributes)
+ {
+ for (tree list = TREE_VALUE (attributes); list;
+ list = TREE_CHAIN (list))
+ {
+ tree tag = TREE_VALUE (list);
+ tree id = get_identifier (TREE_STRING_POINTER (tag));
+ IDENTIFIER_MARKED (id) = false;
+ }
+ }
+}
+
/* Run through the base classes of T, updating CANT_HAVE_CONST_CTOR_P,
and NO_CONST_ASN_REF_P. Also set flag bits in T based on
properties of the bases. */
@@ -1431,6 +1514,8 @@ check_bases (tree t,
if (tm_attr)
seen_tm_mask |= tm_attr_to_mask (tm_attr);
}
+
+ check_abi_tags (t, basetype);
}
/* If one of the base classes had TM attributes, and the current class
@@ -3147,6 +3232,9 @@ check_field_decl (tree field,
&& !TYPE_HAS_CONST_COPY_ASSIGN (type))
*no_const_asn_ref = 1;
}
+
+ check_abi_tags (t, field);
+
if (DECL_INITIAL (field) != NULL_TREE)
{
/* `build_class_init_list' does not recognize