diff options
author | Douglas Gregor <doug.gregor@gmail.com> | 2007-07-04 06:32:30 +0000 |
---|---|---|
committer | Doug Gregor <dgregor@gcc.gnu.org> | 2007-07-04 06:32:30 +0000 |
commit | 8de08f4c8650d8b1b00901d0ada78ffd87a7cfa9 (patch) | |
tree | 57e6f75b199598a710c4e2a6c1666ad20df96b3c /gcc | |
parent | 2d1a1007a08a449f45c830d78e955ed9bb2a23ca (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/decl.c | 8 | ||||
-rw-r--r-- | gcc/tree.c | 126 |
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; } @@ -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; |