aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorDodji Seketeli <dodji@redhat.com>2009-05-28 11:24:18 +0000
committerDodji Seketeli <dodji@gcc.gnu.org>2009-05-28 13:24:18 +0200
commitcd41d410da230dafae73a791281ef058c06a6c72 (patch)
treeb90e673a3046b819f2c25ca56d8e3043b60045f4 /gcc/cp
parent233215fe7cedf3cfa908f11c9543e1f7f10e3283 (diff)
downloadgcc-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/ChangeLog16
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/cvt.c2
-rw-r--r--gcc/cp/error.c2
-rw-r--r--gcc/cp/mangle.c11
-rw-r--r--gcc/cp/pt.c4
-rw-r--r--gcc/cp/tree.c108
-rw-r--r--gcc/cp/typeck.c8
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)