diff options
author | Dodji Seketeli <dodji@redhat.com> | 2009-05-28 11:24:18 +0000 |
---|---|---|
committer | Dodji Seketeli <dodji@gcc.gnu.org> | 2009-05-28 13:24:18 +0200 |
commit | cd41d410da230dafae73a791281ef058c06a6c72 (patch) | |
tree | b90e673a3046b819f2c25ca56d8e3043b60045f4 /gcc/cp | |
parent | 233215fe7cedf3cfa908f11c9543e1f7f10e3283 (diff) | |
download | gcc-cd41d410da230dafae73a791281ef058c06a6c72.zip gcc-cd41d410da230dafae73a791281ef058c06a6c72.tar.gz gcc-cd41d410da230dafae73a791281ef058c06a6c72.tar.bz2 |
Fix for PR c++/PR39754
gcc/cp/ChangeLog:
PR c++/39754
* cp-tree.h (canonical_type_variant): Remove this function declaration.
(strip_typedefs): New function declaration.
* tree.c (strip_typedefs): New function definition.
(canonical_type_variant): Remove function definition.
* cvt.c (convert_from_reference): No need to use
canonical_type_variant.
* typeck.c (cp_build_indirect_ref): Likewise.
* error.c (dump_template_bindings): Use strip_typedefs instead of
canonical_type_variant.
* pt.c (convert_template_argument, unify): Likewise.
* mangle.c (canonicalize_for_substitution): Don't use
canonical_type_variant.
gcc/testsuite/ChangeLog:
PR c++/39754
* g++.dg/template/canon-type-1.C: New test.
* g++.dg/template/canon-type-2.C: Likewise.
* g++.dg/template/canon-type-3.C: Likewise.
* g++.dg/template/canon-type-4.C: Likewise.
* g++.dg/template/canon-type-5.C: Likewise.
* g++.dg/template/canon-type-6.C: Likewise.
* g++.dg/template/canon-type-7.C: Likewise.
From-SVN: r147951
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 2 | ||||
-rw-r--r-- | gcc/cp/error.c | 2 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 11 | ||||
-rw-r--r-- | gcc/cp/pt.c | 4 | ||||
-rw-r--r-- | gcc/cp/tree.c | 108 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 8 |
8 files changed, 131 insertions, 22 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9efd93e..11be689 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2009-05-28 Dodji Seketeli <dodji@redhat.com> + + PR c++/39754 + * cp-tree.h (canonical_type_variant): Remove this function declaration. + (strip_typedefs): New function declaration. + * tree.c (strip_typedefs): New function definition. + (canonical_type_variant): Remove function definition. + * cvt.c (convert_from_reference): No need to use + canonical_type_variant. + * typeck.c (cp_build_indirect_ref): Likewise. + * error.c (dump_template_bindings): Use strip_typedefs instead of + canonical_type_variant. + * pt.c (convert_template_argument, unify): Likewise. + * mangle.c (canonicalize_for_substitution): Don't use + canonical_type_variant. + 2009-05-27 Jason Merrill <jason@redhat.com> * call.c (implicit_conversion): Handle conversion from diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e473695..e31726c 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4827,7 +4827,7 @@ extern void init_tree (void); extern int pod_type_p (const_tree); extern bool class_tmpl_impl_spec_p (const_tree); extern int zero_init_p (const_tree); -extern tree canonical_type_variant (tree); +extern tree strip_typedefs (tree); extern tree copy_binfo (tree, tree, tree, tree *, int); extern int member_p (const_tree); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 3220fe6..596e81c 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -508,7 +508,7 @@ convert_from_reference (tree val) { if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE) { - tree t = canonical_type_variant (TREE_TYPE (TREE_TYPE (val))); + tree t = TREE_TYPE (TREE_TYPE (val)); tree ref = build1 (INDIRECT_REF, t, val); /* We *must* set TREE_READONLY when dereferencing a pointer to const, diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 3c7a8d5..0bfb28e 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -322,7 +322,7 @@ dump_template_bindings (tree parms, tree args, VEC(tree,gc)* typenames) t = tsubst (t, args, tf_none, NULL_TREE); /* Strip typedefs. We can't just use TFF_CHASE_TYPEDEF because pp_simple_type_specifier doesn't know about it. */ - t = canonical_type_variant (t); + t = strip_typedefs (t); dump_type (t, TFF_PLAIN_IDENTIFIER); } } diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index ff77981..c905304 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -338,9 +338,14 @@ canonicalize_for_substitution (tree node) /* For a TYPE_DECL, use the type instead. */ if (TREE_CODE (node) == TYPE_DECL) node = TREE_TYPE (node); - if (TYPE_P (node)) - node = canonical_type_variant (node); - + if (TYPE_P (node) + && TYPE_CANONICAL (node) != node + && TYPE_MAIN_VARIANT (node) != node) + /* Here we want to strip the topmost typedef only. + We need to do that so is_std_substitution can do proper + name matching. */ + node = cp_build_qualified_type (TYPE_MAIN_VARIANT (node), + cp_type_quals (node)); return node; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 4181377..72ea5b2 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5073,7 +5073,7 @@ convert_template_argument (tree parm, the typedef, which is confusing if those future uses do not themselves also use the typedef. */ if (TYPE_P (val)) - val = canonical_type_variant (val); + val = strip_typedefs (val); } else { @@ -13675,7 +13675,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) return 1; /* Strip typedefs as in convert_template_argument. */ - arg = canonical_type_variant (arg); + arg = strip_typedefs (arg); } /* If ARG is a parameter pack or an expansion, we cannot unify diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index dece159..b40ef10 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -911,19 +911,111 @@ cp_build_qualified_type_real (tree type, return result; } -/* Returns the canonical version of TYPE. In other words, if TYPE is - a typedef, returns the underlying type. The cv-qualification of - the type returned matches the type input; they will always be - compatible types. */ +/* Builds a qualified variant of T that is not a typedef variant. + E.g. consider the following declarations: + typedef const int ConstInt; + typedef ConstInt* PtrConstInt; + If T is PtrConstInt, this function returns a type representing + const int*. + In other words, if T is a typedef, the function returns the underlying type. + The cv-qualification and attributes of the type returned match the + input type. + They will always be compatible types. + The returned type is built so that all of its subtypes + recursively have their typedefs stripped as well. + + This is different from just returning TYPE_CANONICAL (T) + Because of several reasons: + * 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 looses template parameter names. */ tree -canonical_type_variant (tree t) +strip_typedefs (tree t) { - if (t == error_mark_node) - return error_mark_node; + tree result = NULL, type = NULL, t0 = NULL; + + if (!t || t == error_mark_node || t == TYPE_CANONICAL (t)) + return t; + + gcc_assert (TYPE_P (t)); + + switch (TREE_CODE (t)) + { + case POINTER_TYPE: + type = strip_typedefs (TREE_TYPE (t)); + result = build_pointer_type (type); + break; + case REFERENCE_TYPE: + type = strip_typedefs (TREE_TYPE (t)); + 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)); + result = build_offset_type (t0, type); + break; + case RECORD_TYPE: + if (TYPE_PTRMEMFUNC_P (t)) + { + t0 = strip_typedefs (TYPE_PTRMEMFUNC_FN_TYPE (t)); + result = build_ptrmemfunc_type (t0); + } + break; + case ARRAY_TYPE: + type = strip_typedefs (TREE_TYPE (t)); + t0 = strip_typedefs (TYPE_DOMAIN (t));; + result = build_cplus_array_type (type, t0); + break; + case FUNCTION_TYPE: + case METHOD_TYPE: + { + tree arg_types = NULL, arg_node, arg_type; + for (arg_node = TYPE_ARG_TYPES (t); + arg_node; + arg_node = TREE_CHAIN (arg_node)) + { + if (arg_node == void_list_node) + break; + arg_type = strip_typedefs (TREE_VALUE (arg_node)); + gcc_assert (arg_type); + + arg_types = + tree_cons (TREE_PURPOSE (arg_node), arg_type, arg_types); + } + + if (arg_types) + arg_types = nreverse (arg_types); + + /* A list of parameters not ending with an ellipsis + must end with void_list_node. */ + if (arg_node) + arg_types = chainon (arg_types, void_list_node); - return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t)); + type = strip_typedefs (TREE_TYPE (t)); + if (TREE_CODE (t) == METHOD_TYPE) + { + tree class_type = TREE_TYPE (TREE_VALUE (arg_types)); + gcc_assert (class_type); + result = + build_method_type_directly (class_type, type, + TREE_CHAIN (arg_types)); + } + else + result = build_function_type (type, + arg_types); + } + break; + default: + break; + } + + if (!result) + result = TYPE_MAIN_VARIANT (t); + return cp_build_qualified_type (result, cp_type_quals (t)); } + /* Makes a copy of BINFO and TYPE, which is to be inherited into a graph dominated by T. If BINFO is NULL, TYPE is a dependent base, diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 29ae831..eb28a3d2 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2494,12 +2494,8 @@ cp_build_indirect_ref (tree ptr, const char *errorstring, /* [expr.unary.op] If the type of the expression is "pointer to T," the type - of the result is "T." - - We must use the canonical variant because certain parts of - the back end, like fold, do pointer comparisons between - types. */ - tree t = canonical_type_variant (TREE_TYPE (type)); + of the result is "T." */ + tree t = TREE_TYPE (type); if (CONVERT_EXPR_P (ptr) || TREE_CODE (ptr) == VIEW_CONVERT_EXPR) |