diff options
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r-- | gcc/cp/class.c | 88 |
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 |