diff options
author | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-04-28 14:43:54 +0000 |
---|---|---|
committer | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-04-28 14:43:54 +0000 |
commit | 64e66cdd487b36df702e38f4228ba3e10874b08d (patch) | |
tree | a17f7c17ea0ce441d4b64b71aa5dccabfc9653b0 /gcc/cp/tree.c | |
parent | 8c522687a0dbe28caaab2fa3ef40d1826b8e4d03 (diff) | |
download | gcc-64e66cdd487b36df702e38f4228ba3e10874b08d.tar.gz |
PR c++/50800
* tree.c (strip_typedefs): Add remove_attributes parm.
(strip_typedefs_expr): Likewise.
(apply_identity_attributes): New subroutine of strip_typedefs.
* pt.c (canonicalize_type_argument): Let strip_typedefs handle attrs.
(convert_nontype_argument, unify): Likewise.
* cp-tree.h: Adjust.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@222530 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/tree.c')
-rw-r--r-- | gcc/cp/tree.c | 131 |
1 files changed, 99 insertions, 32 deletions
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 9a4779f4a3c..d00f0d7eab1 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -55,6 +55,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple-expr.h" #include "gimplify.h" #include "wide-int.h" +#include "attribs.h" static tree bot_manip (tree *, int *, void *); static tree bot_replace (tree *, int *, void *); @@ -1175,6 +1176,52 @@ cv_unqualified (tree type) return cp_build_qualified_type (type, quals); } +/* Subroutine of strip_typedefs. We want to apply to RESULT the attributes + from ATTRIBS that affect type identity, and no others. If any are not + applied, set *remove_attributes to true. */ + +static tree +apply_identity_attributes (tree result, tree attribs, bool *remove_attributes) +{ + tree first_ident = NULL_TREE; + tree new_attribs = NULL_TREE; + tree *p = &new_attribs; + + for (tree a = attribs; a; a = TREE_CHAIN (a)) + { + const attribute_spec *as + = lookup_attribute_spec (get_attribute_name (a)); + if (as && as->affects_type_identity) + { + if (!first_ident) + first_ident = a; + else if (first_ident == error_mark_node) + { + *p = tree_cons (TREE_PURPOSE (a), TREE_VALUE (a), NULL_TREE); + p = &TREE_CHAIN (*p); + } + } + else if (first_ident) + { + for (tree a2 = first_ident; a2; a2 = TREE_CHAIN (a2)) + { + *p = tree_cons (TREE_PURPOSE (a2), TREE_VALUE (a2), NULL_TREE); + p = &TREE_CHAIN (*p); + } + first_ident = error_mark_node; + } + } + if (first_ident != error_mark_node) + new_attribs = first_ident; + + if (first_ident == attribs) + /* All attributes affected type identity. */; + else + *remove_attributes = true; + + return cp_build_type_attribute_variant (result, new_attribs); +} + /* Builds a qualified variant of T that is not a typedef variant. E.g. consider the following declarations: typedef const int ConstInt; @@ -1193,10 +1240,14 @@ cv_unqualified (tree type) * If T is a type that needs structural equality its TYPE_CANONICAL (T) will be NULL. * TYPE_CANONICAL (T) desn't carry type attributes - and loses template parameter names. */ + and loses template parameter names. + + If REMOVE_ATTRIBUTES is non-null, also strip attributes that don't + affect type identity, and set the referent to true if any were + stripped. */ tree -strip_typedefs (tree t) +strip_typedefs (tree t, bool *remove_attributes) { tree result = NULL, type = NULL, t0 = NULL; @@ -1210,7 +1261,7 @@ strip_typedefs (tree t) for (; t; t = TREE_CHAIN (t)) { gcc_assert (!TREE_PURPOSE (t)); - tree elt = strip_typedefs (TREE_VALUE (t)); + tree elt = strip_typedefs (TREE_VALUE (t), remove_attributes); if (elt != TREE_VALUE (t)) changed = true; vec_safe_push (vec, elt); @@ -1235,28 +1286,28 @@ strip_typedefs (tree t) switch (TREE_CODE (t)) { case POINTER_TYPE: - type = strip_typedefs (TREE_TYPE (t)); + type = strip_typedefs (TREE_TYPE (t), remove_attributes); result = build_pointer_type (type); break; case REFERENCE_TYPE: - type = strip_typedefs (TREE_TYPE (t)); + type = strip_typedefs (TREE_TYPE (t), remove_attributes); result = cp_build_reference_type (type, TYPE_REF_IS_RVALUE (t)); break; case OFFSET_TYPE: - t0 = strip_typedefs (TYPE_OFFSET_BASETYPE (t)); - type = strip_typedefs (TREE_TYPE (t)); + t0 = strip_typedefs (TYPE_OFFSET_BASETYPE (t), remove_attributes); + type = strip_typedefs (TREE_TYPE (t), remove_attributes); result = build_offset_type (t0, type); break; case RECORD_TYPE: if (TYPE_PTRMEMFUNC_P (t)) { - t0 = strip_typedefs (TYPE_PTRMEMFUNC_FN_TYPE (t)); + t0 = strip_typedefs (TYPE_PTRMEMFUNC_FN_TYPE (t), remove_attributes); result = build_ptrmemfunc_type (t0); } break; case ARRAY_TYPE: - type = strip_typedefs (TREE_TYPE (t)); - t0 = strip_typedefs (TYPE_DOMAIN (t));; + type = strip_typedefs (TREE_TYPE (t), remove_attributes); + t0 = strip_typedefs (TYPE_DOMAIN (t), remove_attributes); result = build_cplus_array_type (type, t0); break; case FUNCTION_TYPE: @@ -1269,7 +1320,8 @@ strip_typedefs (tree t) { if (arg_node == void_list_node) break; - arg_type = strip_typedefs (TREE_VALUE (arg_node)); + arg_type = strip_typedefs (TREE_VALUE (arg_node), + remove_attributes); gcc_assert (arg_type); arg_types = @@ -1284,7 +1336,7 @@ strip_typedefs (tree t) if (arg_node) arg_types = chainon (arg_types, void_list_node); - type = strip_typedefs (TREE_TYPE (t)); + type = strip_typedefs (TREE_TYPE (t), remove_attributes); if (TREE_CODE (t) == METHOD_TYPE) { tree class_type = TREE_TYPE (TREE_VALUE (arg_types)); @@ -1325,9 +1377,9 @@ strip_typedefs (tree t) tree arg = TREE_VEC_ELT (args, i); tree strip_arg; if (TYPE_P (arg)) - strip_arg = strip_typedefs (arg); + strip_arg = strip_typedefs (arg, remove_attributes); else - strip_arg = strip_typedefs_expr (arg); + strip_arg = strip_typedefs_expr (arg, remove_attributes); TREE_VEC_ELT (new_args, i) = strip_arg; if (strip_arg != arg) changed = true; @@ -1343,12 +1395,14 @@ strip_typedefs (tree t) else ggc_free (new_args); } - result = make_typename_type (strip_typedefs (TYPE_CONTEXT (t)), + result = make_typename_type (strip_typedefs (TYPE_CONTEXT (t), + remove_attributes), fullname, typename_type, tf_none); } break; case DECLTYPE_TYPE: - result = strip_typedefs_expr (DECLTYPE_TYPE_EXPR (t)); + result = strip_typedefs_expr (DECLTYPE_TYPE_EXPR (t), + remove_attributes); if (result == DECLTYPE_TYPE_EXPR (t)) return t; else @@ -1367,14 +1421,25 @@ strip_typedefs (tree t) || TYPE_ALIGN (t) != TYPE_ALIGN (result)) { gcc_assert (TYPE_USER_ALIGN (t)); - if (TYPE_ALIGN (t) == TYPE_ALIGN (result)) - result = build_variant_type_copy (result); + if (remove_attributes) + *remove_attributes = true; else - result = build_aligned_type (result, TYPE_ALIGN (t)); - TYPE_USER_ALIGN (result) = true; + { + if (TYPE_ALIGN (t) == TYPE_ALIGN (result)) + result = build_variant_type_copy (result); + else + result = build_aligned_type (result, TYPE_ALIGN (t)); + TYPE_USER_ALIGN (result) = true; + } } if (TYPE_ATTRIBUTES (t)) - result = cp_build_type_attribute_variant (result, TYPE_ATTRIBUTES (t)); + { + if (remove_attributes) + result = apply_identity_attributes (result, TYPE_ATTRIBUTES (t), + remove_attributes); + else + result = cp_build_type_attribute_variant (result, TYPE_ATTRIBUTES (t)); + } return cp_build_qualified_type (result, cp_type_quals (t)); } @@ -1389,7 +1454,7 @@ strip_typedefs (tree t) sizeof(TT) is replaced by sizeof(T). */ tree -strip_typedefs_expr (tree t) +strip_typedefs_expr (tree t, bool *remove_attributes) { unsigned i,n; tree r, type, *ops; @@ -1404,7 +1469,7 @@ strip_typedefs_expr (tree t) /* Some expressions have type operands, so let's handle types here rather than check TYPE_P in multiple places below. */ if (TYPE_P (t)) - return strip_typedefs (t); + return strip_typedefs (t, remove_attributes); code = TREE_CODE (t); switch (code) @@ -1418,8 +1483,8 @@ strip_typedefs_expr (tree t) case TRAIT_EXPR: { - tree type1 = strip_typedefs (TRAIT_EXPR_TYPE1 (t)); - tree type2 = strip_typedefs (TRAIT_EXPR_TYPE2 (t)); + tree type1 = strip_typedefs (TRAIT_EXPR_TYPE1 (t), remove_attributes); + tree type2 = strip_typedefs (TRAIT_EXPR_TYPE2 (t), remove_attributes); if (type1 == TRAIT_EXPR_TYPE1 (t) && type2 == TRAIT_EXPR_TYPE2 (t)) return t; @@ -1436,7 +1501,7 @@ strip_typedefs_expr (tree t) tree it; for (it = t; it; it = TREE_CHAIN (it)) { - tree val = strip_typedefs_expr (TREE_VALUE (t)); + tree val = strip_typedefs_expr (TREE_VALUE (t), remove_attributes); vec_safe_push (vec, val); if (val != TREE_VALUE (t)) changed = true; @@ -1462,7 +1527,8 @@ strip_typedefs_expr (tree t) vec_safe_reserve (vec, n); for (i = 0; i < n; ++i) { - tree op = strip_typedefs_expr (TREE_VEC_ELT (t, i)); + tree op = strip_typedefs_expr (TREE_VEC_ELT (t, i), + remove_attributes); vec->quick_push (op); if (op != TREE_VEC_ELT (t, i)) changed = true; @@ -1487,17 +1553,18 @@ strip_typedefs_expr (tree t) vec<constructor_elt, va_gc> *vec = vec_safe_copy (CONSTRUCTOR_ELTS (t)); n = CONSTRUCTOR_NELTS (t); - type = strip_typedefs (TREE_TYPE (t)); + type = strip_typedefs (TREE_TYPE (t), remove_attributes); for (i = 0; i < n; ++i) { constructor_elt *e = &(*vec)[i]; - tree op = strip_typedefs_expr (e->value); + tree op = strip_typedefs_expr (e->value, remove_attributes); if (op != e->value) { changed = true; e->value = op; } - gcc_checking_assert (e->index == strip_typedefs_expr (e->index)); + gcc_checking_assert + (e->index == strip_typedefs_expr (e->index, remove_attributes)); } if (!changed && type == TREE_TYPE (t)) @@ -1538,12 +1605,12 @@ strip_typedefs_expr (tree t) case REINTERPRET_CAST_EXPR: case CAST_EXPR: case NEW_EXPR: - type = strip_typedefs (type); + type = strip_typedefs (type, remove_attributes); /* fallthrough */ default: for (i = 0; i < n; ++i) - ops[i] = strip_typedefs_expr (TREE_OPERAND (t, i)); + ops[i] = strip_typedefs_expr (TREE_OPERAND (t, i), remove_attributes); break; } |