aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDouglas Gregor <doug.gregor@gmail.com>2007-07-04 06:32:30 +0000
committerDoug Gregor <dgregor@gcc.gnu.org>2007-07-04 06:32:30 +0000
commit8de08f4c8650d8b1b00901d0ada78ffd87a7cfa9 (patch)
tree57e6f75b199598a710c4e2a6c1666ad20df96b3c /gcc
parent2d1a1007a08a449f45c830d78e955ed9bb2a23ca (diff)
downloadgcc-8de08f4c8650d8b1b00901d0ada78ffd87a7cfa9.zip
gcc-8de08f4c8650d8b1b00901d0ada78ffd87a7cfa9.tar.gz
gcc-8de08f4c8650d8b1b00901d0ada78ffd87a7cfa9.tar.bz2
tree.c (maybe_canonicalize_argtypes): New.
2007-07-04 Douglas Gregor <doug.gregor@gmail.com> * tree.c (maybe_canonicalize_argtypes): New. (build_function_type): Set canonical type. (build_method_type_directly): Ditto. (reconstruct_complex_type): Rebuild the METHOD_TYPE node properly. 2007-07-04 Douglas Gregor <doug.gregor@gmail.com> * decl.c (build_ptrmemfunc_type): Always use structural equality tests when comparing pointer-to-member-function types, because the handling of TYPE_GET_PTRMEMFUNC_TYPE currently defeats canonical types. From-SVN: r126303
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/decl.c8
-rw-r--r--gcc/tree.c126
4 files changed, 133 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dc785cb..abeacc3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2007-07-04 Douglas Gregor <doug.gregor@gmail.com>
+
+ * tree.c (maybe_canonicalize_argtypes): New.
+ (build_function_type): Set canonical type.
+ (build_method_type_directly): Ditto.
+ (reconstruct_complex_type): Rebuild the METHOD_TYPE node
+ properly.
+
2007-07-03 Andrew Pinski <andrew_pinski@playstation.sony.com>
* tree-ssa-loop-ivopts.c (strip_offset_1): Treat POINTER_PLUS_EXPR
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 17b76c0..1621175 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2007-07-04 Douglas Gregor <doug.gregor@gmail.com>
+
+ * decl.c (build_ptrmemfunc_type): Always use structural equality
+ tests when comparing pointer-to-member-function types, because the
+ handling of TYPE_GET_PTRMEMFUNC_TYPE currently defeats canonical
+ types.
+
2007-07-03 Mark Mitchell <mark@codesourcery.com>
* init.c (build_new): Tweak comment.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 1fae5f8..630cec1 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6602,10 +6602,10 @@ build_ptrmemfunc_type (tree type)
later. */
TYPE_SET_PTRMEMFUNC_TYPE (type, t);
- if (TYPE_STRUCTURAL_EQUALITY_P (type))
- SET_TYPE_STRUCTURAL_EQUALITY (t);
- else if (TYPE_CANONICAL (type) != type)
- TYPE_CANONICAL (t) = build_ptrmemfunc_type (TYPE_CANONICAL (type));
+ /* Managing canonical types for the RECORD_TYPE behind a
+ pointer-to-member function is a nightmare, so use structural
+ equality for now. */
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
return t;
}
diff --git a/gcc/tree.c b/gcc/tree.c
index 72a2593..8feaf47 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -5647,6 +5647,82 @@ get_inner_array_type (tree array)
return type;
}
+/* Computes the canonical argument types from the argument type list
+ ARGTYPES.
+
+ ANY_STRUCTURAL_P points to a boolean that states whether any of the
+ other types that work with ARGTYPES (e.g., the return type of the
+ function) are structural. *ANY_STRUCTURAL_P will be set TRUE if any
+ of those types or any of the argument types in ARGTYPES are
+ structural.
+
+ ANY_NONCANONICAL_P points to a boolean that states whether any of
+ the other types that work with ARGTYPES (e.g., the return type of
+ the function) are non-canonical type nodes. *ANY_NONCANONICAL_P
+ will be set TRUE if any of those types or any of the argument types
+ in ARGTYPES are non-canonical.
+
+ Returns a canonical argument list, which may be ARGTYPES when the
+ canonical argument list is unneeded (i.e., *ANY_STRUCTURAL_P is
+ true) or would not differ from ARGTYPES. */
+
+static tree
+maybe_canonicalize_argtypes(tree argtypes,
+ bool *any_structural_p,
+ bool *any_noncanonical_p)
+{
+ tree arg;
+ bool any_noncanonical_argtypes_p = false;
+
+ for (arg = argtypes; arg && !(*any_structural_p); arg = TREE_CHAIN (arg))
+ {
+ if (!TREE_VALUE (arg) || TREE_VALUE (arg) == error_mark_node)
+ /* Fail gracefully by stating that the type is structural. */
+ *any_structural_p = true;
+ else if (TYPE_STRUCTURAL_EQUALITY_P (TREE_VALUE (arg)))
+ *any_structural_p = true;
+ else if (TYPE_CANONICAL (TREE_VALUE (arg)) != TREE_VALUE (arg)
+ || TREE_PURPOSE (arg))
+ /* If the argument has a default argument, we consider it
+ non-canonical even though the type itself is canonical.
+ That way, different variants of function and method types
+ with default arguments will all point to the variant with
+ no defaults as their canonical type. */
+ any_noncanonical_argtypes_p = true;
+ }
+
+ if (*any_structural_p)
+ return argtypes;
+
+ if (any_noncanonical_argtypes_p)
+ {
+ /* Build the canonical list of argument types. */
+ tree canon_argtypes = NULL_TREE;
+ bool is_void = false;
+
+ for (arg = argtypes; arg; arg = TREE_CHAIN (arg))
+ {
+ if (arg == void_list_node)
+ is_void = true;
+ else
+ canon_argtypes = tree_cons (NULL_TREE,
+ TYPE_CANONICAL (TREE_VALUE (arg)),
+ canon_argtypes);
+ }
+
+ canon_argtypes = nreverse (canon_argtypes);
+ if (is_void)
+ canon_argtypes = chainon (canon_argtypes, void_list_node);
+
+ /* There is a non-canonical type. */
+ *any_noncanonical_p = true;
+ return canon_argtypes;
+ }
+
+ /* The canonical argument types are the same as ARGTYPES. */
+ return argtypes;
+}
+
/* Construct, lay out and return
the type of functions returning type VALUE_TYPE
given arguments of types ARG_TYPES.
@@ -5659,6 +5735,8 @@ build_function_type (tree value_type, tree arg_types)
{
tree t;
hashval_t hashcode = 0;
+ bool any_structural_p, any_noncanonical_p;
+ tree canon_argtypes;
if (TREE_CODE (value_type) == FUNCTION_TYPE)
{
@@ -5671,14 +5749,23 @@ build_function_type (tree value_type, tree arg_types)
TREE_TYPE (t) = value_type;
TYPE_ARG_TYPES (t) = arg_types;
- /* We don't have canonicalization of function types, yet. */
- SET_TYPE_STRUCTURAL_EQUALITY (t);
-
/* If we already have such a type, use the old one. */
hashcode = iterative_hash_object (TYPE_HASH (value_type), hashcode);
hashcode = type_hash_list (arg_types, hashcode);
t = type_hash_canon (hashcode, t);
+ /* Set up the canonical type. */
+ any_structural_p = TYPE_STRUCTURAL_EQUALITY_P (value_type);
+ any_noncanonical_p = TYPE_CANONICAL (value_type) != value_type;
+ canon_argtypes = maybe_canonicalize_argtypes (arg_types,
+ &any_structural_p,
+ &any_noncanonical_p);
+ if (any_structural_p)
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else if (any_noncanonical_p)
+ TYPE_CANONICAL (t) = build_function_type (TYPE_CANONICAL (value_type),
+ canon_argtypes);
+
if (!COMPLETE_TYPE_P (t))
layout_type (t);
return t;
@@ -5728,6 +5815,8 @@ build_method_type_directly (tree basetype,
tree t;
tree ptype;
int hashcode = 0;
+ bool any_structural_p, any_noncanonical_p;
+ tree canon_argtypes;
/* Make a node of the sort we want. */
t = make_node (METHOD_TYPE);
@@ -5741,15 +5830,29 @@ build_method_type_directly (tree basetype,
argtypes = tree_cons (NULL_TREE, ptype, argtypes);
TYPE_ARG_TYPES (t) = argtypes;
- /* We don't have canonicalization of method types yet. */
- SET_TYPE_STRUCTURAL_EQUALITY (t);
-
/* If we already have such a type, use the old one. */
hashcode = iterative_hash_object (TYPE_HASH (basetype), hashcode);
hashcode = iterative_hash_object (TYPE_HASH (rettype), hashcode);
hashcode = type_hash_list (argtypes, hashcode);
t = type_hash_canon (hashcode, t);
+ /* Set up the canonical type. */
+ any_structural_p
+ = (TYPE_STRUCTURAL_EQUALITY_P (basetype)
+ || TYPE_STRUCTURAL_EQUALITY_P (rettype));
+ any_noncanonical_p
+ = (TYPE_CANONICAL (basetype) != basetype
+ || TYPE_CANONICAL (rettype) != rettype);
+ canon_argtypes = maybe_canonicalize_argtypes (TREE_CHAIN (argtypes),
+ &any_structural_p,
+ &any_noncanonical_p);
+ if (any_structural_p)
+ SET_TYPE_STRUCTURAL_EQUALITY (t);
+ else if (any_noncanonical_p)
+ TYPE_CANONICAL (t)
+ = build_method_type_directly (TYPE_CANONICAL (basetype),
+ TYPE_CANONICAL (rettype),
+ canon_argtypes);
if (!COMPLETE_TYPE_P (t))
layout_type (t);
@@ -7329,15 +7432,14 @@ reconstruct_complex_type (tree type, tree bottom)
}
else if (TREE_CODE (type) == METHOD_TYPE)
{
- tree argtypes;
inner = reconstruct_complex_type (TREE_TYPE (type), bottom);
/* The build_method_type_directly() routine prepends 'this' to argument list,
so we must compensate by getting rid of it. */
- argtypes = TYPE_ARG_TYPES (type);
- outer = build_method_type_directly (TYPE_METHOD_BASETYPE (type),
- inner,
- TYPE_ARG_TYPES (type));
- TYPE_ARG_TYPES (outer) = argtypes;
+ outer
+ = build_method_type_directly
+ (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))),
+ inner,
+ TREE_CHAIN (TYPE_ARG_TYPES (type)));
}
else
return bottom;