diff mbox

[02/18] enforce TREE_CHAIN and TREE_TYPE accesses

Message ID 1299817406-16745-3-git-send-email-froydnj@codesourcery.com
State New
Headers show

Commit Message

Nathan Froyd March 11, 2011, 4:23 a.m. UTC
Now that we have a structure where not every node might include
TREE_CHAIN or TREE_TYPE, we need to make sure that when we call said
accessors that the argument is properly typed.  This requires a number
of changes:

- It's not enough for FEs to assume that FE-specific DECLs are the only
  tree that needs to be marked specially; we need to mark things as
  TS_TYPED or TS_COMMON.

- To facilitate doing so, move the MARK_* macros for initializing
  tree_contains_struct to tree.h so they are accessible to FEs.

- Additionally, rearrange *_init_ts methods for the C-family languages
  so that we can share code where code needs to be shared.

- Finally, various places need to check for TS_COMMON structure before
  blindly calling TREE_CHAIN.

-Nathan

gcc/ada/
	* gcc-interface/ada-tree.h (union lang_tree_node): Check for
	TS_COMMON before calling TREE_CHAIN.
	* gcc-interface/misc.c (gnat_init_ts): New function.
	(LANG_HOOKS_INIT_TS): Define.

gcc/
	* c-decl.c (union lang_tree_node): Check for TS_COMMON before
	calling TREE_CHAIN.
	* print-tree.c (print_node): Likewise.
	* tree-inline.c (copy_tree_r): Likewise.
	* c-lang.c (LANG_HOOKS_INIT_TS): Define.
	* lto-streamer-in.c (lto_input_tree_pointers): Check for TS_TYPED
	instead of TS_COMMON.
	* lto-streamer-out.c (lto_output_tree_pointers): Likewise.
	* tree.c (initialize_tree_contains_struct): Handle TS_TYPED.
	(copy_node_stat): Zero TREE_CHAIN only if necessary.
	(MARK_TS_BASE, MARK_TS_TYPED, MARK_TS_COMMON): Move these...
	(MARK_TS_DECL_COMMON, MARK_TS_DECL_COMMON, MARK_TS_DECL_WRTL):
	...and these...
	(MARK_TS_DECL_WITH_VIS, MARK_TS_DECL_NON_COMMON): ...and these...
	* tree.h: ...here.
	(TREE_CHAIN): Check for a TS_COMMON structure.
	(TREE_TYPE): Check for a TS_TYPED structure.

gcc/c-family/
	* c-common.h (c_common_init_ts): Declare.
	* c-common.c (c_common_init_ts): Define.

gcc/cp/
	* cp-lang.c (cp_init_ts): Call cp_common_init_ts.  Move
	tree_contains_struct initialization to...
	* cp-objcp-common.c (cp_common_init_ts): ...here.  Use MARK_*
	macros.
	* cp-objcp-common.h (cp_common_init_ts): Declare.
	* cp-tree.h (union lang_tree_node): Check for TS_COMMON before
	calling TREE_CHAIN.

gcc/fortran/
	* f95-lang.c (union lang_tree_node): Check for TS_COMMON before
	calling TREE_CHAIN.

gcc/go/
	* go-lang.c (union lang_tree_node): Check for TS_COMMON before
	calling TREE_CHAIN.

gcc/java/
	* java-tree.h (union lang_tree_node): Check for TS_COMMON before
	calling TREE_CHAIN.

gcc/lto/
	* lto-tree.h (union lang_tree_node): Check for TS_COMMON before
	calling TREE_CHAIN.
	* lto.c (lto_fixup_common): Likewise.

gcc/objc/
	* objc-lang.c (objc_init_ts): Move code for this function...
	* objc-act.c (objc_common_init_ts): ...here. Define.
	* objc-act.h (objc_common_init_ts): Declare.

gcc/objcp/
	* objcp-lang.c (objcxx_init_ts): Call objc_common_init_ts and
	cp_common_init_ts.

Comments

Mike Stump March 11, 2011, 8:12 a.m. UTC | #1
The objective c bits are ok.
Richard Biener March 11, 2011, 1:21 p.m. UTC | #2
On Fri, Mar 11, 2011 at 5:23 AM, Nathan Froyd <froydnj@codesourcery.com> wrote:
> Now that we have a structure where not every node might include
> TREE_CHAIN or TREE_TYPE, we need to make sure that when we call said
> accessors that the argument is properly typed.  This requires a number
> of changes:
>
> - It's not enough for FEs to assume that FE-specific DECLs are the only
>  tree that needs to be marked specially; we need to mark things as
>  TS_TYPED or TS_COMMON.
>
> - To facilitate doing so, move the MARK_* macros for initializing
>  tree_contains_struct to tree.h so they are accessible to FEs.
>
> - Additionally, rearrange *_init_ts methods for the C-family languages
>  so that we can share code where code needs to be shared.
>
> - Finally, various places need to check for TS_COMMON structure before
>  blindly calling TREE_CHAIN.

The middle-end changes are ok for 4.7.

Thanks,
Richard.

> -Nathan
>
> gcc/ada/
>        * gcc-interface/ada-tree.h (union lang_tree_node): Check for
>        TS_COMMON before calling TREE_CHAIN.
>        * gcc-interface/misc.c (gnat_init_ts): New function.
>        (LANG_HOOKS_INIT_TS): Define.
>
> gcc/
>        * c-decl.c (union lang_tree_node): Check for TS_COMMON before
>        calling TREE_CHAIN.
>        * print-tree.c (print_node): Likewise.
>        * tree-inline.c (copy_tree_r): Likewise.
>        * c-lang.c (LANG_HOOKS_INIT_TS): Define.
>        * lto-streamer-in.c (lto_input_tree_pointers): Check for TS_TYPED
>        instead of TS_COMMON.
>        * lto-streamer-out.c (lto_output_tree_pointers): Likewise.
>        * tree.c (initialize_tree_contains_struct): Handle TS_TYPED.
>        (copy_node_stat): Zero TREE_CHAIN only if necessary.
>        (MARK_TS_BASE, MARK_TS_TYPED, MARK_TS_COMMON): Move these...
>        (MARK_TS_DECL_COMMON, MARK_TS_DECL_COMMON, MARK_TS_DECL_WRTL):
>        ...and these...
>        (MARK_TS_DECL_WITH_VIS, MARK_TS_DECL_NON_COMMON): ...and these...
>        * tree.h: ...here.
>        (TREE_CHAIN): Check for a TS_COMMON structure.
>        (TREE_TYPE): Check for a TS_TYPED structure.
>
> gcc/c-family/
>        * c-common.h (c_common_init_ts): Declare.
>        * c-common.c (c_common_init_ts): Define.
>
> gcc/cp/
>        * cp-lang.c (cp_init_ts): Call cp_common_init_ts.  Move
>        tree_contains_struct initialization to...
>        * cp-objcp-common.c (cp_common_init_ts): ...here.  Use MARK_*
>        macros.
>        * cp-objcp-common.h (cp_common_init_ts): Declare.
>        * cp-tree.h (union lang_tree_node): Check for TS_COMMON before
>        calling TREE_CHAIN.
>
> gcc/fortran/
>        * f95-lang.c (union lang_tree_node): Check for TS_COMMON before
>        calling TREE_CHAIN.
>
> gcc/go/
>        * go-lang.c (union lang_tree_node): Check for TS_COMMON before
>        calling TREE_CHAIN.
>
> gcc/java/
>        * java-tree.h (union lang_tree_node): Check for TS_COMMON before
>        calling TREE_CHAIN.
>
> gcc/lto/
>        * lto-tree.h (union lang_tree_node): Check for TS_COMMON before
>        calling TREE_CHAIN.
>        * lto.c (lto_fixup_common): Likewise.
>
> gcc/objc/
>        * objc-lang.c (objc_init_ts): Move code for this function...
>        * objc-act.c (objc_common_init_ts): ...here. Define.
>        * objc-act.h (objc_common_init_ts): Declare.
>
> gcc/objcp/
>        * objcp-lang.c (objcxx_init_ts): Call objc_common_init_ts and
>        cp_common_init_ts.
>
> diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h
> index 9002fa1..3542349 100644
> --- a/gcc/ada/gcc-interface/ada-tree.h
> +++ b/gcc/ada/gcc-interface/ada-tree.h
> @@ -25,7 +25,7 @@
>
>  /* The resulting tree type.  */
>  union GTY((desc ("0"),
> -          chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
> +          chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL")))
>   lang_tree_node
>  {
>   union tree_node GTY((tag ("0"),
> diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
> index 4f7a5e1..89823ca 100644
> --- a/gcc/ada/gcc-interface/misc.c
> +++ b/gcc/ada/gcc-interface/misc.c
> @@ -696,6 +696,20 @@ gnat_eh_personality (void)
>   return gnat_eh_personality_decl;
>  }
>
> +/* Initialize language-specific bits of tree_contains_struct.  */
> +
> +static void
> +gnat_init_ts (void)
> +{
> +  MARK_TS_COMMON (UNCONSTRAINED_ARRAY_TYPE);
> +
> +  MARK_TS_TYPED (UNCONSTRAINED_ARRAY_REF);
> +  MARK_TS_TYPED (LOOP_STMT);
> +  MARK_TS_TYPED (STMT_STMT);
> +  MARK_TS_TYPED (EXIT_STMT);
> +  MARK_TS_TYPED (NULL_EXPR);
> +}
> +
>  /* Definitions for our language-specific hooks.  */
>
>  #undef  LANG_HOOKS_NAME
> @@ -754,6 +768,8 @@ gnat_eh_personality (void)
>  #define LANG_HOOKS_EH_PERSONALITY      gnat_eh_personality
>  #undef  LANG_HOOKS_DEEP_UNSHARING
>  #define LANG_HOOKS_DEEP_UNSHARING      true
> +#undef  LANG_HOOKS_INIT_TS
> +#define LANG_HOOKS_INIT_TS             gnat_init_ts
>
>  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
>
> diff --git a/gcc/c-decl.c b/gcc/c-decl.c
> index b438b06..14aef5f 100644
> --- a/gcc/c-decl.c
> +++ b/gcc/c-decl.c
> @@ -242,7 +242,7 @@ extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate
>  /* The resulting tree type.  */
>
>  union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
> -       chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : ((union lang_tree_node *) TREE_CHAIN (&%h.generic))")))  lang_tree_node
> +       chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL")))  lang_tree_node
>  {
>   union tree_node GTY ((tag ("0"),
>                        desc ("tree_node_structure (&%h)")))
> diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
> index d696b5f..7207335 100644
> --- a/gcc/c-family/c-common.c
> +++ b/gcc/c-family/c-common.c
> @@ -9692,4 +9692,13 @@ keyword_is_decl_specifier (enum rid keyword)
>     }
>  }
>
> +/* Initialize language-specific-bits of tree_contains_struct.  */
> +
> +void
> +c_common_init_ts (void)
> +{
> +  MARK_TS_TYPED (C_MAYBE_CONST_EXPR);
> +  MARK_TS_TYPED (EXCESS_PRECISION_EXPR);
> +}
> +
>  #include "gt-c-family-c-common.h"
> diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
> index 406def9..7e4f0a1 100644
> --- a/gcc/c-family/c-common.h
> +++ b/gcc/c-family/c-common.h
> @@ -707,6 +707,7 @@ extern tree c_common_fixed_point_type_for_size (unsigned int, unsigned int,
>  extern tree c_common_unsigned_type (tree);
>  extern tree c_common_signed_type (tree);
>  extern tree c_common_signed_or_unsigned_type (int, tree);
> +extern void c_common_init_ts (void);
>  extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int);
>  extern bool decl_with_nonnull_addr_p (const_tree);
>  extern tree c_fully_fold (tree, bool, bool *);
> diff --git a/gcc/c-lang.c b/gcc/c-lang.c
> index 0ca2e7c..ae1b081 100644
> --- a/gcc/c-lang.c
> +++ b/gcc/c-lang.c
> @@ -43,6 +43,8 @@ enum c_language_kind c_language = clk_c;
>  #define LANG_HOOKS_NAME "GNU C"
>  #undef LANG_HOOKS_INIT
>  #define LANG_HOOKS_INIT c_objc_common_init
> +#undef LANG_HOOKS_INIT_TS
> +#define LANG_HOOKS_INIT_TS c_common_init_ts
>
>  /* Each front end provides its own lang hook initializer.  */
>  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
> diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
> index e5c1c09..6506930 100644
> --- a/gcc/cp/cp-lang.c
> +++ b/gcc/cp/cp-lang.c
> @@ -100,32 +100,12 @@ objcp_tsubst_copy_and_build (tree t ATTRIBUTE_UNUSED,
>   return NULL_TREE;
>  }
>
> -
>  static void
>  cp_init_ts (void)
>  {
> -  tree_contains_struct[NAMESPACE_DECL][TS_DECL_NON_COMMON] = 1;
> -  tree_contains_struct[USING_DECL][TS_DECL_NON_COMMON] = 1;
> -  tree_contains_struct[TEMPLATE_DECL][TS_DECL_NON_COMMON] = 1;
> -
> -  tree_contains_struct[NAMESPACE_DECL][TS_DECL_WITH_VIS] = 1;
> -  tree_contains_struct[USING_DECL][TS_DECL_WITH_VIS] = 1;
> -  tree_contains_struct[TEMPLATE_DECL][TS_DECL_WITH_VIS] = 1;
> -
> -  tree_contains_struct[NAMESPACE_DECL][TS_DECL_WRTL] = 1;
> -  tree_contains_struct[USING_DECL][TS_DECL_WRTL] = 1;
> -  tree_contains_struct[TEMPLATE_DECL][TS_DECL_WRTL] = 1;
> -
> -  tree_contains_struct[NAMESPACE_DECL][TS_DECL_COMMON] = 1;
> -  tree_contains_struct[USING_DECL][TS_DECL_COMMON] = 1;
> -  tree_contains_struct[TEMPLATE_DECL][TS_DECL_COMMON] = 1;
> -
> -  tree_contains_struct[NAMESPACE_DECL][TS_DECL_MINIMAL] = 1;
> -  tree_contains_struct[USING_DECL][TS_DECL_MINIMAL] = 1;
> -  tree_contains_struct[TEMPLATE_DECL][TS_DECL_MINIMAL] = 1;
> +  cp_common_init_ts ();
>
>   init_shadowed_var_for_decl ();
> -
>  }
>
>  static const char *
> diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
> index f045d29..66d2d27 100644
> --- a/gcc/cp/cp-objcp-common.c
> +++ b/gcc/cp/cp-objcp-common.c
> @@ -222,5 +222,78 @@ init_shadowed_var_for_decl (void)
>                                           tree_decl_map_eq, 0);
>  }
>
> +void
> +cp_common_init_ts (void)
> +{
> +  MARK_TS_DECL_NON_COMMON (NAMESPACE_DECL);
> +  MARK_TS_DECL_NON_COMMON (USING_DECL);
> +  MARK_TS_DECL_NON_COMMON (TEMPLATE_DECL);
> +
> +  MARK_TS_COMMON (TEMPLATE_TEMPLATE_PARM);
> +  MARK_TS_COMMON (TEMPLATE_TYPE_PARM);
> +  MARK_TS_COMMON (TEMPLATE_PARM_INDEX);
> +  MARK_TS_COMMON (OVERLOAD);
> +  MARK_TS_COMMON (TEMPLATE_INFO);
> +  MARK_TS_COMMON (FOR_STMT);
> +  MARK_TS_COMMON (TYPENAME_TYPE);
> +  MARK_TS_COMMON (TYPEOF_TYPE);
> +  MARK_TS_COMMON (IF_STMT);
> +  MARK_TS_COMMON (BASELINK);
> +  MARK_TS_COMMON (SWITCH_STMT);
> +  MARK_TS_COMMON (TYPE_PACK_EXPANSION);
> +  MARK_TS_COMMON (EXPR_PACK_EXPANSION);
> +  MARK_TS_COMMON (DECLTYPE_TYPE);
> +  MARK_TS_COMMON (BOUND_TEMPLATE_TEMPLATE_PARM);
> +  MARK_TS_COMMON (UNBOUND_CLASS_TEMPLATE);
> +  MARK_TS_COMMON (RANGE_FOR_STMT);
> +
> +  MARK_TS_TYPED (AGGR_INIT_EXPR);
> +  MARK_TS_TYPED (EXPR_STMT);
> +  MARK_TS_TYPED (EH_SPEC_BLOCK);
> +  MARK_TS_TYPED (CLEANUP_STMT);
> +  MARK_TS_TYPED (SCOPE_REF);
> +  MARK_TS_TYPED (CAST_EXPR);
> +  MARK_TS_TYPED (NON_DEPENDENT_EXPR);
> +  MARK_TS_TYPED (MODOP_EXPR);
> +  MARK_TS_TYPED (TRY_BLOCK);
> +  MARK_TS_TYPED (THROW_EXPR);
> +  MARK_TS_TYPED (HANDLER);
> +  MARK_TS_TYPED (REINTERPRET_CAST_EXPR);
> +  MARK_TS_TYPED (CONST_CAST_EXPR);
> +  MARK_TS_TYPED (STATIC_CAST_EXPR);
> +  MARK_TS_TYPED (DYNAMIC_CAST_EXPR);
> +  MARK_TS_TYPED (TEMPLATE_ID_EXPR);
> +  MARK_TS_TYPED (ARROW_EXPR);
> +  MARK_TS_TYPED (SIZEOF_EXPR);
> +  MARK_TS_TYPED (ALIGNOF_EXPR);
> +  MARK_TS_TYPED (AT_ENCODE_EXPR);
> +  MARK_TS_TYPED (UNARY_PLUS_EXPR);
> +  MARK_TS_TYPED (TRAIT_EXPR);
> +  MARK_TS_TYPED (TYPE_ARGUMENT_PACK);
> +  MARK_TS_TYPED (NOEXCEPT_EXPR);
> +  MARK_TS_TYPED (NONTYPE_ARGUMENT_PACK);
> +  MARK_TS_TYPED (WHILE_STMT);
> +  MARK_TS_TYPED (NEW_EXPR);
> +  MARK_TS_TYPED (VEC_NEW_EXPR);
> +  MARK_TS_TYPED (BREAK_STMT);
> +  MARK_TS_TYPED (MEMBER_REF);
> +  MARK_TS_TYPED (DOTSTAR_EXPR);
> +  MARK_TS_TYPED (DO_STMT);
> +  MARK_TS_TYPED (DELETE_EXPR);
> +  MARK_TS_TYPED (VEC_DELETE_EXPR);
> +  MARK_TS_TYPED (CONTINUE_STMT);
> +  MARK_TS_TYPED (TAG_DEFN);
> +  MARK_TS_TYPED (PSEUDO_DTOR_EXPR);
> +  MARK_TS_TYPED (TYPEID_EXPR);
> +  MARK_TS_TYPED (MUST_NOT_THROW_EXPR);
> +  MARK_TS_TYPED (STMT_EXPR);
> +  MARK_TS_TYPED (OFFSET_REF);
> +  MARK_TS_TYPED (OFFSETOF_EXPR);
> +  MARK_TS_TYPED (PTRMEM_CST);
> +  MARK_TS_TYPED (EMPTY_CLASS_EXPR);
> +  MARK_TS_TYPED (VEC_INIT_EXPR);
> +  MARK_TS_TYPED (USING_STMT);
> +  MARK_TS_TYPED (LAMBDA_EXPR);
> +}
>
>  #include "gt-cp-cp-objcp-common.h"
> diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
> index 38da59e..c668ad8 100644
> --- a/gcc/cp/cp-objcp-common.h
> +++ b/gcc/cp/cp-objcp-common.h
> @@ -28,6 +28,7 @@ extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t,
>                                         tree, bool);
>
>  extern bool cp_function_decl_explicit_p (tree decl);
> +extern void cp_common_init_ts (void);
>
>  /* Lang hooks that are shared between C++ and ObjC++ are defined here.  Hooks
>    specific to C++ or ObjC++ go in cp/cp-lang.c and objcp/objcp-lang.c,
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 238d0cf..1783915 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -702,7 +702,7 @@ enum cp_tree_node_structure_enum {
>
>  /* The resulting tree type.  */
>  union GTY((desc ("cp_tree_node_structure (&%h)"),
> -       chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)"))) lang_tree_node {
> +       chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL"))) lang_tree_node {
>   union tree_node GTY ((tag ("TS_CP_GENERIC"),
>                        desc ("tree_node_structure (&%h)"))) generic;
>   struct template_parm_index_s GTY ((tag ("TS_CP_TPI"))) tpi;
> diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
> index a3ac860..687f60b 100644
> --- a/gcc/fortran/f95-lang.c
> +++ b/gcc/fortran/f95-lang.c
> @@ -59,7 +59,7 @@ lang_identifier {
>  /* The resulting tree type.  */
>
>  union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
> -     chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
> +     chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL")))
>
>  lang_tree_node {
>   union tree_node GTY((tag ("0"),
> diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
> index b59e72d..5132e97 100644
> --- a/gcc/go/go-lang.c
> +++ b/gcc/go/go-lang.c
> @@ -65,7 +65,7 @@ struct GTY(()) lang_identifier
>  /* The resulting tree type.  */
>
>  union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
> -          chain_next ("(union lang_tree_node *) TREE_CHAIN (&%h.generic)")))
> +          chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL")))
>  lang_tree_node
>  {
>   union tree_node GTY((tag ("0"),
> diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
> index 3addcca..e422b4a 100644
> --- a/gcc/java/java-tree.h
> +++ b/gcc/java/java-tree.h
> @@ -587,7 +587,7 @@ struct GTY(()) lang_identifier {
>
>  /* The resulting tree type.  */
>  union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
> -       chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
> +       chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL")))
>
>   lang_tree_node {
>   union tree_node GTY ((tag ("0"),
> diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
> index 7409c1a..45809b8 100644
> --- a/gcc/lto-streamer-in.c
> +++ b/gcc/lto-streamer-in.c
> @@ -2326,7 +2326,7 @@ lto_input_tree_pointers (struct lto_input_block *ib, struct data_in *data_in,
>
>   code = TREE_CODE (expr);
>
> -  if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
> +  if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
>     lto_input_ts_common_tree_pointers (ib, data_in, expr);
>
>   if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
> diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
> index 29d171b..a4e8b70 100644
> --- a/gcc/lto-streamer-out.c
> +++ b/gcc/lto-streamer-out.c
> @@ -1169,7 +1169,7 @@ lto_output_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
>
>   code = TREE_CODE (expr);
>
> -  if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
> +  if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
>     lto_output_ts_common_tree_pointers (ob, expr, ref_p);
>
>   if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
> diff --git a/gcc/lto/lto-tree.h b/gcc/lto/lto-tree.h
> index d187fe2..847348c 100644
> --- a/gcc/lto/lto-tree.h
> +++ b/gcc/lto/lto-tree.h
> @@ -48,7 +48,7 @@ enum lto_tree_node_structure_enum {
>  };
>
>  union GTY((desc ("lto_tree_node_structure (&%h)"),
> -         chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
> +         chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL")))
>     lang_tree_node
>  {
>   union tree_node GTY ((tag ("TS_LTO_GENERIC"),
> diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
> index 71c8cdb..78a7977 100644
> --- a/gcc/lto/lto.c
> +++ b/gcc/lto/lto.c
> @@ -1618,7 +1618,8 @@ lto_fixup_common (tree t, void *data)
>
>   /* This is not very efficient because we cannot do tail-recursion with
>      a long chain of trees. */
> -  LTO_FIXUP_SUBTREE (TREE_CHAIN (t));
> +  if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_COMMON))
> +    LTO_FIXUP_SUBTREE (TREE_CHAIN (t));
>  }
>
>  /* Fix up fields of a decl_minimal T.  DATA points to fix-up states.  */
> diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
> index 049dc00..e5bd52a 100644
> --- a/gcc/objc/objc-act.c
> +++ b/gcc/objc/objc-act.c
> @@ -10541,4 +10541,22 @@ objc_v2_encode_prop_attr (tree property)
>   return get_identifier (string);
>  }
>
> +void
> +objc_common_init_ts (void)
> +{
> +  c_common_init_ts ();
> +
> +  MARK_TS_DECL_NON_COMMON (CLASS_METHOD_DECL);
> +  MARK_TS_DECL_NON_COMMON (INSTANCE_METHOD_DECL);
> +  MARK_TS_DECL_NON_COMMON (KEYWORD_DECL);
> +  MARK_TS_DECL_NON_COMMON (PROPERTY_DECL);
> +
> +  MARK_TS_COMMON (CLASS_INTERFACE_TYPE);
> +  MARK_TS_COMMON (PROTOCOL_INTERFACE_TYPE);
> +  MARK_TS_COMMON (CLASS_IMPLEMENTATION_TYPE);
> +
> +  MARK_TS_TYPED (MESSAGE_SEND_EXPR);
> +  MARK_TS_TYPED (PROPERTY_REF);
> +}
> +
>  #include "gt-objc-objc-act.h"
> diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
> index 3983d4b..909181a 100644
> --- a/gcc/objc/objc-act.h
> +++ b/gcc/objc/objc-act.h
> @@ -28,6 +28,7 @@ bool objc_init (void);
>  const char *objc_printable_name (tree, int);
>  tree objc_fold_obj_type_ref (tree, tree);
>  int objc_gimplify_expr (tree *, gimple_seq *, gimple_seq *);
> +void objc_common_init_ts (void);
>
>  /* NB: The remaining public functions are prototyped in c-common.h, for the
>    benefit of stub-objc.c and objc-act.c.  */
> diff --git a/gcc/objc/objc-lang.c b/gcc/objc/objc-lang.c
> index fd65776..169b894 100644
> --- a/gcc/objc/objc-lang.c
> +++ b/gcc/objc/objc-lang.c
> @@ -36,7 +36,6 @@ along with GCC; see the file COPYING3.  If not see
>  #include "c-lang.h"
>
>  enum c_language_kind c_language = clk_objc;
> -static void objc_init_ts (void);
>
>  /* Lang hooks common to C and ObjC are declared in c-objc-common.h;
>    consequently, there should be very few hooks below.  */
> @@ -50,7 +49,7 @@ static void objc_init_ts (void);
>  #undef LANG_HOOKS_GIMPLIFY_EXPR
>  #define LANG_HOOKS_GIMPLIFY_EXPR objc_gimplify_expr
>  #undef LANG_HOOKS_INIT_TS
> -#define LANG_HOOKS_INIT_TS objc_init_ts
> +#define LANG_HOOKS_INIT_TS objc_common_init_ts
>
>  /* Each front end provides its own lang hook initializer.  */
>  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
> @@ -58,33 +57,4 @@ struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
>  /* Lang hook routines common to C and ObjC appear in c-objc-common.c;
>    there should be very few (if any) routines below.  */
>
> -static void
> -objc_init_ts (void)
> -{
> -  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_NON_COMMON] = 1;
> -  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_NON_COMMON] = 1;
> -  tree_contains_struct[KEYWORD_DECL][TS_DECL_NON_COMMON] = 1;
> -  tree_contains_struct[PROPERTY_DECL][TS_DECL_NON_COMMON] = 1;
> -
> -  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_WITH_VIS] = 1;
> -  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_WITH_VIS] = 1;
> -  tree_contains_struct[KEYWORD_DECL][TS_DECL_WITH_VIS] = 1;
> -  tree_contains_struct[PROPERTY_DECL][TS_DECL_WITH_VIS] = 1;
> -
> -  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_WRTL] = 1;
> -  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_WRTL] = 1;
> -  tree_contains_struct[KEYWORD_DECL][TS_DECL_WRTL] = 1;
> -  tree_contains_struct[PROPERTY_DECL][TS_DECL_WRTL] = 1;
> -
> -  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_MINIMAL] = 1;
> -  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_MINIMAL] = 1;
> -  tree_contains_struct[KEYWORD_DECL][TS_DECL_MINIMAL] = 1;
> -  tree_contains_struct[PROPERTY_DECL][TS_DECL_MINIMAL] = 1;
> -
> -  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_COMMON] = 1;
> -  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_COMMON] = 1;
> -  tree_contains_struct[KEYWORD_DECL][TS_DECL_COMMON] = 1;
> -  tree_contains_struct[PROPERTY_DECL][TS_DECL_COMMON] = 1;
> -}
> -
>  #include "gtype-objc.h"
> diff --git a/gcc/objcp/objcp-lang.c b/gcc/objcp/objcp-lang.c
> index fe2be66..0019022 100644
> --- a/gcc/objcp/objcp-lang.c
> +++ b/gcc/objcp/objcp-lang.c
> @@ -89,52 +89,8 @@ objcp_tsubst_copy_and_build (tree t, tree args, tsubst_flags_t complain,
>  static void
>  objcxx_init_ts (void)
>  {
> -  /* objc decls */
> -  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_NON_COMMON] = 1;
> -  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_NON_COMMON] = 1;
> -  tree_contains_struct[KEYWORD_DECL][TS_DECL_NON_COMMON] = 1;
> -  tree_contains_struct[PROPERTY_DECL][TS_DECL_NON_COMMON] = 1;
> -
> -  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_WITH_VIS] = 1;
> -  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_WITH_VIS] = 1;
> -  tree_contains_struct[KEYWORD_DECL][TS_DECL_WITH_VIS] = 1;
> -  tree_contains_struct[PROPERTY_DECL][TS_DECL_WITH_VIS] = 1;
> -
> -  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_WRTL] = 1;
> -  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_WRTL] = 1;
> -  tree_contains_struct[KEYWORD_DECL][TS_DECL_WRTL] = 1;
> -  tree_contains_struct[PROPERTY_DECL][TS_DECL_WRTL] = 1;
> -
> -  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_MINIMAL] = 1;
> -  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_MINIMAL] = 1;
> -  tree_contains_struct[KEYWORD_DECL][TS_DECL_MINIMAL] = 1;
> -  tree_contains_struct[PROPERTY_DECL][TS_DECL_MINIMAL] = 1;
> -
> -  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_COMMON] = 1;
> -  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_COMMON] = 1;
> -  tree_contains_struct[KEYWORD_DECL][TS_DECL_COMMON] = 1;
> -  tree_contains_struct[PROPERTY_DECL][TS_DECL_COMMON] = 1;
> -
> -  /* C++ decls */
> -  tree_contains_struct[NAMESPACE_DECL][TS_DECL_NON_COMMON] = 1;
> -  tree_contains_struct[USING_DECL][TS_DECL_NON_COMMON] = 1;
> -  tree_contains_struct[TEMPLATE_DECL][TS_DECL_NON_COMMON] = 1;
> -
> -  tree_contains_struct[NAMESPACE_DECL][TS_DECL_WITH_VIS] = 1;
> -  tree_contains_struct[USING_DECL][TS_DECL_WITH_VIS] = 1;
> -  tree_contains_struct[TEMPLATE_DECL][TS_DECL_WITH_VIS] = 1;
> -
> -  tree_contains_struct[NAMESPACE_DECL][TS_DECL_WRTL] = 1;
> -  tree_contains_struct[USING_DECL][TS_DECL_WRTL] = 1;
> -  tree_contains_struct[TEMPLATE_DECL][TS_DECL_WRTL] = 1;
> -
> -  tree_contains_struct[NAMESPACE_DECL][TS_DECL_COMMON] = 1;
> -  tree_contains_struct[USING_DECL][TS_DECL_COMMON] = 1;
> -  tree_contains_struct[TEMPLATE_DECL][TS_DECL_COMMON] = 1;
> -
> -  tree_contains_struct[NAMESPACE_DECL][TS_DECL_MINIMAL] = 1;
> -  tree_contains_struct[USING_DECL][TS_DECL_MINIMAL] = 1;
> -  tree_contains_struct[TEMPLATE_DECL][TS_DECL_MINIMAL] = 1;
> +  objc_common_init_ts ();
> +  cp_common_init_ts ();
>
>   init_shadowed_var_for_decl ();
>  }
> diff --git a/gcc/print-tree.c b/gcc/print-tree.c
> index dfd3589..b0c6899 100644
> --- a/gcc/print-tree.c
> +++ b/gcc/print-tree.c
> @@ -756,7 +756,8 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
>              print_node (file, temp, TREE_OPERAND (node, i), indent + 4);
>            }
>        }
> -      print_node (file, "chain", TREE_CHAIN (node), indent + 4);
> +      if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
> +       print_node (file, "chain", TREE_CHAIN (node), indent + 4);
>       break;
>
>     case tcc_constant:
> diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
> index de30cfd..45c7e88 100644
> --- a/gcc/tree-inline.c
> +++ b/gcc/tree-inline.c
> @@ -4295,7 +4295,8 @@ copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
>         here.  */
>       tree chain = NULL_TREE, new_tree;
>
> -      chain = TREE_CHAIN (*tp);
> +      if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
> +       chain = TREE_CHAIN (*tp);
>
>       /* Copy the node.  */
>       new_tree = copy_node (*tp);
> diff --git a/gcc/tree.c b/gcc/tree.c
> index 798bc08..68f40c9 100644
> --- a/gcc/tree.c
> +++ b/gcc/tree.c
> @@ -351,53 +351,6 @@ initialize_tree_contains_struct (void)
>  {
>   unsigned i;
>
> -#define MARK_TS_BASE(C)                                        \
> -  do {                                                 \
> -    tree_contains_struct[C][TS_BASE] = 1;              \
> -  } while (0)
> -
> -#define MARK_TS_TYPED(C)                               \
> -  do {                                                 \
> -    MARK_TS_BASE (C);                                  \
> -    tree_contains_struct[C][TS_TYPED] = 1;             \
> -  } while (0)
> -
> -#define MARK_TS_COMMON(C)                              \
> -  do {                                                 \
> -    MARK_TS_TYPED (C);                                 \
> -    tree_contains_struct[C][TS_COMMON] = 1;            \
> -  } while (0)
> -
> -#define MARK_TS_DECL_MINIMAL(C)                                \
> -  do {                                                 \
> -    MARK_TS_COMMON (C);                                        \
> -    tree_contains_struct[C][TS_DECL_MINIMAL] = 1;      \
> -  } while (0)
> -
> -#define MARK_TS_DECL_COMMON(C)                         \
> -  do {                                                 \
> -    MARK_TS_DECL_MINIMAL (C);                          \
> -    tree_contains_struct[C][TS_DECL_COMMON] = 1;       \
> -  } while (0)
> -
> -#define MARK_TS_DECL_WRTL(C)                           \
> -  do {                                                 \
> -    MARK_TS_DECL_COMMON (C);                           \
> -    tree_contains_struct[C][TS_DECL_WRTL] = 1;         \
> -  } while (0)
> -
> -#define MARK_TS_DECL_WITH_VIS(C)                       \
> -  do {                                                 \
> -    MARK_TS_DECL_WRTL (C);                             \
> -    tree_contains_struct[C][TS_DECL_WITH_VIS] = 1;     \
> -  } while (0)
> -
> -#define MARK_TS_DECL_NON_COMMON(C)                     \
> -  do {                                                 \
> -    MARK_TS_DECL_WITH_VIS (C);                         \
> -    tree_contains_struct[C][TS_DECL_NON_COMMON] = 1;   \
> -  } while (0)
> -
>   for (i = ERROR_MARK; i < LAST_AND_UNUSED_TREE_CODE; i++)
>     {
>       enum tree_code code;
> @@ -412,10 +365,14 @@ initialize_tree_contains_struct (void)
>       /* Mark all the structures that TS is derived from.  */
>       switch (ts_code)
>        {
> -       case TS_COMMON:
> +       case TS_TYPED:
>          MARK_TS_BASE (code);
>          break;
>
> +       case TS_COMMON:
> +         MARK_TS_TYPED (code);
> +         break;
> +
>        case TS_INT_CST:
>        case TS_REAL_CST:
>        case TS_FIXED_CST:
> @@ -521,14 +478,6 @@ initialize_tree_contains_struct (void)
>   gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL]);
>   gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_MINIMAL]);
>   gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_COMMON]);
> -
> -#undef MARK_TS_BASE
> -#undef MARK_TS_COMMON
> -#undef MARK_TS_DECL_MINIMAL
> -#undef MARK_TS_DECL_COMMON
> -#undef MARK_TS_DECL_WRTL
> -#undef MARK_TS_DECL_WITH_VIS
> -#undef MARK_TS_DECL_NON_COMMON
>  }
>
>
> @@ -944,7 +893,7 @@ make_node_stat (enum tree_code code MEM_STAT_DECL)
>  }
>
>  /* Return a new node with the same contents as NODE except that its
> -   TREE_CHAIN is zero and it has a fresh uid.  */
> +   TREE_CHAIN, if it has one, is zero and it has a fresh uid.  */
>
>  tree
>  copy_node_stat (tree node MEM_STAT_DECL)
> @@ -959,7 +908,8 @@ copy_node_stat (tree node MEM_STAT_DECL)
>   t = ggc_alloc_zone_tree_node_stat (&tree_zone, length PASS_MEM_STAT);
>   memcpy (t, node, length);
>
> -  TREE_CHAIN (t) = 0;
> +  if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
> +    TREE_CHAIN (t) = 0;
>   TREE_ASM_WRITTEN (t) = 0;
>   TREE_VISITED (t) = 0;
>   if (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL)
> diff --git a/gcc/tree.h b/gcc/tree.h
> index 2f772e1..4ad2d3e 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -50,6 +50,54 @@ MAX_TREE_CODES
>  extern unsigned char tree_contains_struct[MAX_TREE_CODES][64];
>  #define CODE_CONTAINS_STRUCT(CODE, STRUCT) (tree_contains_struct[(CODE)][(STRUCT)])
>
> +/* Macros for initializing `tree_contains_struct'.  */
> +#define MARK_TS_BASE(C)                                        \
> +  do {                                                 \
> +    tree_contains_struct[C][TS_BASE] = 1;              \
> +  } while (0)
> +
> +#define MARK_TS_TYPED(C)                               \
> +  do {                                                 \
> +    MARK_TS_BASE (C);                                  \
> +    tree_contains_struct[C][TS_TYPED] = 1;             \
> +  } while (0)
> +
> +#define MARK_TS_COMMON(C)                              \
> +  do {                                                 \
> +    MARK_TS_TYPED (C);                                 \
> +    tree_contains_struct[C][TS_COMMON] = 1;            \
> +  } while (0)
> +
> +#define MARK_TS_DECL_MINIMAL(C)                                \
> +  do {                                                 \
> +    MARK_TS_COMMON (C);                                        \
> +    tree_contains_struct[C][TS_DECL_MINIMAL] = 1;      \
> +  } while (0)
> +
> +#define MARK_TS_DECL_COMMON(C)                         \
> +  do {                                                 \
> +    MARK_TS_DECL_MINIMAL (C);                          \
> +    tree_contains_struct[C][TS_DECL_COMMON] = 1;       \
> +  } while (0)
> +
> +#define MARK_TS_DECL_WRTL(C)                           \
> +  do {                                                 \
> +    MARK_TS_DECL_COMMON (C);                           \
> +    tree_contains_struct[C][TS_DECL_WRTL] = 1;         \
> +  } while (0)
> +
> +#define MARK_TS_DECL_WITH_VIS(C)                       \
> +  do {                                                 \
> +    MARK_TS_DECL_WRTL (C);                             \
> +    tree_contains_struct[C][TS_DECL_WITH_VIS] = 1;     \
> +  } while (0)
> +
> +#define MARK_TS_DECL_NON_COMMON(C)                     \
> +  do {                                                 \
> +    MARK_TS_DECL_WITH_VIS (C);                         \
> +    tree_contains_struct[C][TS_DECL_NON_COMMON] = 1;   \
> +  } while (0)
> +
>  /* Number of language-independent tree codes.  */
>  #define NUM_TREE_CODES ((int) LAST_AND_UNUSED_TREE_CODE)
>
> @@ -864,7 +912,7 @@ enum tree_node_structure_enum {
>    are chained together.  */
>
>  #define TREE_CHAIN(NODE) __extension__ \
> -(*({__typeof (NODE) const __t = (NODE);                                \
> +(*({__typeof (NODE) const __t = CONTAINS_STRUCT_CHECK (NODE, TS_COMMON);\
>     &__t->common.chain; }))
>
>  /* In all nodes that are expressions, this is the data type of the expression.
> @@ -872,7 +920,7 @@ enum tree_node_structure_enum {
>    In ARRAY_TYPE nodes, this is the type of the elements.
>    In VECTOR_TYPE nodes, this is the type of the elements.  */
>  #define TREE_TYPE(NODE) __extension__ \
> -(*({__typeof (NODE) const __t = (NODE);                                        \
> +(*({__typeof (NODE) const __t = CONTAINS_STRUCT_CHECK (NODE, TS_TYPED); \
>     &__t->typed.type; }))
>
>  extern void tree_contains_struct_check_failed (const_tree,
> --
> 1.7.0.4
>
>
Tom Tromey March 11, 2011, 3:24 p.m. UTC | #3
>>>>> "Nathan" == Nathan Froyd <froydnj@codesourcery.com> writes:

Nathan> gcc/java/
Nathan> 	* java-tree.h (union lang_tree_node): Check for TS_COMMON before
Nathan> 	calling TREE_CHAIN.

This is ok.

Tom
Eric Botcazou March 12, 2011, 12:08 p.m. UTC | #4
> gcc/ada/
> 	* gcc-interface/ada-tree.h (union lang_tree_node): Check for
> 	TS_COMMON before calling TREE_CHAIN.
> 	* gcc-interface/misc.c (gnat_init_ts): New function.
> 	(LANG_HOOKS_INIT_TS): Define.

I presume that PLUS_NOMOD_EXPR, MINUS_NOMOD_EXPR and ATTR_ADDR_EXPR need not 
be marked in gnat_init_ts?  If so, please add a single comment to that effect 
in the function and reorder the lines to match the order in ada-tree.def.

OK with these changes.
Nathan Froyd March 21, 2011, 1:50 p.m. UTC | #5
On Sat, Mar 12, 2011 at 01:08:23PM +0100, Eric Botcazou wrote:
> > gcc/ada/
> > 	* gcc-interface/ada-tree.h (union lang_tree_node): Check for
> > 	TS_COMMON before calling TREE_CHAIN.
> > 	* gcc-interface/misc.c (gnat_init_ts): New function.
> > 	(LANG_HOOKS_INIT_TS): Define.
> 
> I presume that PLUS_NOMOD_EXPR, MINUS_NOMOD_EXPR and ATTR_ADDR_EXPR need not 
> be marked in gnat_init_ts?  If so, please add a single comment to that effect 
> in the function and reorder the lines to match the order in ada-tree.def.

Well, they never have their TREE_TYPE taken during bootstrap and test,
at least...

You're right, though; they should probably be marked as such for
completeness.  OK to commit with those additions and reordering as above
sight unseen, or would you like to see the patch?

-Nathan
Eric Botcazou March 21, 2011, 5:45 p.m. UTC | #6
> You're right, though; they should probably be marked as such for
> completeness.  OK to commit with those additions and reordering as above
> sight unseen, or would you like to see the patch?

Note that I didn't ask for that, only for a comment explaining why they were 
set aside.  So it's up to you and, yes, you can commit without reposting.
Nathan Froyd April 13, 2011, 2:43 a.m. UTC | #7
On Thu, Mar 10, 2011 at 11:23:10PM -0500, Nathan Froyd wrote:
> Now that we have a structure where not every node might include
> TREE_CHAIN or TREE_TYPE, we need to make sure that when we call said
> accessors that the argument is properly typed.  This requires a number
> of changes:

http://gcc.gnu.org/ml/gcc-patches/2011-03/msg00565.html

Ping.  I was going to commit this, but I realized I hadn't received
approval for the go or LTO bits.  They probably qualify as obvious,
given that they're exactly the same as all the other languages, but just
to rubber-stamp everything...

> gcc/go/
> 	* go-lang.c (union lang_tree_node): Check for TS_COMMON before
> 	calling TREE_CHAIN.
> 
> gcc/lto/
> 	* lto-tree.h (union lang_tree_node): Check for TS_COMMON before
> 	calling TREE_CHAIN.
> 	* lto.c (lto_fixup_common): Likewise.

Thanks,
-Nathan
Diego Novillo April 13, 2011, 2:57 a.m. UTC | #8
On Tue, Apr 12, 2011 at 22:43, Nathan Froyd <froydnj@codesourcery.com> wrote:
> On Thu, Mar 10, 2011 at 11:23:10PM -0500, Nathan Froyd wrote:
>> Now that we have a structure where not every node might include
>> TREE_CHAIN or TREE_TYPE, we need to make sure that when we call said
>> accessors that the argument is properly typed.  This requires a number
>> of changes:
>
> http://gcc.gnu.org/ml/gcc-patches/2011-03/msg00565.html
>
> Ping.  I was going to commit this, but I realized I hadn't received
> approval for the go or LTO bits.  They probably qualify as obvious,
> given that they're exactly the same as all the other languages, but just
> to rubber-stamp everything...
>
>> gcc/go/
>>       * go-lang.c (union lang_tree_node): Check for TS_COMMON before
>>       calling TREE_CHAIN.
>>
>> gcc/lto/
>>       * lto-tree.h (union lang_tree_node): Check for TS_COMMON before
>>       calling TREE_CHAIN.
>>       * lto.c (lto_fixup_common): Likewise.

OK.


Diego.
Ian Lance Taylor April 13, 2011, 4:02 a.m. UTC | #9
Nathan Froyd <froydnj@codesourcery.com> writes:

> On Thu, Mar 10, 2011 at 11:23:10PM -0500, Nathan Froyd wrote:
>> Now that we have a structure where not every node might include
>> TREE_CHAIN or TREE_TYPE, we need to make sure that when we call said
>> accessors that the argument is properly typed.  This requires a number
>> of changes:
>
> http://gcc.gnu.org/ml/gcc-patches/2011-03/msg00565.html
>
> Ping.  I was going to commit this, but I realized I hadn't received
> approval for the go or LTO bits.  They probably qualify as obvious,
> given that they're exactly the same as all the other languages, but just
> to rubber-stamp everything...
>
>> gcc/go/
>> 	* go-lang.c (union lang_tree_node): Check for TS_COMMON before
>> 	calling TREE_CHAIN.
>> 
>> gcc/lto/
>> 	* lto-tree.h (union lang_tree_node): Check for TS_COMMON before
>> 	calling TREE_CHAIN.
>> 	* lto.c (lto_fixup_common): Likewise.

This is OK.

Thanks.

Ian
diff mbox

Patch

diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h
index 9002fa1..3542349 100644
--- a/gcc/ada/gcc-interface/ada-tree.h
+++ b/gcc/ada/gcc-interface/ada-tree.h
@@ -25,7 +25,7 @@ 
 
 /* The resulting tree type.  */
 union GTY((desc ("0"),
-	   chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
+	   chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL")))
   lang_tree_node
 {
   union tree_node GTY((tag ("0"),
diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 4f7a5e1..89823ca 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -696,6 +696,20 @@  gnat_eh_personality (void)
   return gnat_eh_personality_decl;
 }
 
+/* Initialize language-specific bits of tree_contains_struct.  */
+
+static void
+gnat_init_ts (void)
+{
+  MARK_TS_COMMON (UNCONSTRAINED_ARRAY_TYPE);
+
+  MARK_TS_TYPED (UNCONSTRAINED_ARRAY_REF);
+  MARK_TS_TYPED (LOOP_STMT);
+  MARK_TS_TYPED (STMT_STMT);
+  MARK_TS_TYPED (EXIT_STMT);
+  MARK_TS_TYPED (NULL_EXPR);
+}
+
 /* Definitions for our language-specific hooks.  */
 
 #undef  LANG_HOOKS_NAME
@@ -754,6 +768,8 @@  gnat_eh_personality (void)
 #define LANG_HOOKS_EH_PERSONALITY	gnat_eh_personality
 #undef  LANG_HOOKS_DEEP_UNSHARING
 #define LANG_HOOKS_DEEP_UNSHARING	true
+#undef  LANG_HOOKS_INIT_TS
+#define LANG_HOOKS_INIT_TS		gnat_init_ts
 
 struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
 
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index b438b06..14aef5f 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -242,7 +242,7 @@  extern char C_SIZEOF_STRUCT_LANG_IDENTIFIER_isnt_accurate
 /* The resulting tree type.  */
 
 union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
-       chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : ((union lang_tree_node *) TREE_CHAIN (&%h.generic))")))  lang_tree_node
+       chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL")))  lang_tree_node
  {
   union tree_node GTY ((tag ("0"),
 			desc ("tree_node_structure (&%h)")))
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index d696b5f..7207335 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -9692,4 +9692,13 @@  keyword_is_decl_specifier (enum rid keyword)
     }
 }
 
+/* Initialize language-specific-bits of tree_contains_struct.  */
+
+void
+c_common_init_ts (void)
+{
+  MARK_TS_TYPED (C_MAYBE_CONST_EXPR);
+  MARK_TS_TYPED (EXCESS_PRECISION_EXPR);
+}
+
 #include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 406def9..7e4f0a1 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -707,6 +707,7 @@  extern tree c_common_fixed_point_type_for_size (unsigned int, unsigned int,
 extern tree c_common_unsigned_type (tree);
 extern tree c_common_signed_type (tree);
 extern tree c_common_signed_or_unsigned_type (int, tree);
+extern void c_common_init_ts (void);
 extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int);
 extern bool decl_with_nonnull_addr_p (const_tree);
 extern tree c_fully_fold (tree, bool, bool *);
diff --git a/gcc/c-lang.c b/gcc/c-lang.c
index 0ca2e7c..ae1b081 100644
--- a/gcc/c-lang.c
+++ b/gcc/c-lang.c
@@ -43,6 +43,8 @@  enum c_language_kind c_language = clk_c;
 #define LANG_HOOKS_NAME "GNU C"
 #undef LANG_HOOKS_INIT
 #define LANG_HOOKS_INIT c_objc_common_init
+#undef LANG_HOOKS_INIT_TS
+#define LANG_HOOKS_INIT_TS c_common_init_ts
 
 /* Each front end provides its own lang hook initializer.  */
 struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index e5c1c09..6506930 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -100,32 +100,12 @@  objcp_tsubst_copy_and_build (tree t ATTRIBUTE_UNUSED,
   return NULL_TREE;
 }
 
-
 static void
 cp_init_ts (void)
 {
-  tree_contains_struct[NAMESPACE_DECL][TS_DECL_NON_COMMON] = 1;
-  tree_contains_struct[USING_DECL][TS_DECL_NON_COMMON] = 1;
-  tree_contains_struct[TEMPLATE_DECL][TS_DECL_NON_COMMON] = 1;
-
-  tree_contains_struct[NAMESPACE_DECL][TS_DECL_WITH_VIS] = 1;
-  tree_contains_struct[USING_DECL][TS_DECL_WITH_VIS] = 1;
-  tree_contains_struct[TEMPLATE_DECL][TS_DECL_WITH_VIS] = 1;
-
-  tree_contains_struct[NAMESPACE_DECL][TS_DECL_WRTL] = 1;
-  tree_contains_struct[USING_DECL][TS_DECL_WRTL] = 1;
-  tree_contains_struct[TEMPLATE_DECL][TS_DECL_WRTL] = 1;
-
-  tree_contains_struct[NAMESPACE_DECL][TS_DECL_COMMON] = 1;
-  tree_contains_struct[USING_DECL][TS_DECL_COMMON] = 1;
-  tree_contains_struct[TEMPLATE_DECL][TS_DECL_COMMON] = 1;
-
-  tree_contains_struct[NAMESPACE_DECL][TS_DECL_MINIMAL] = 1;
-  tree_contains_struct[USING_DECL][TS_DECL_MINIMAL] = 1;
-  tree_contains_struct[TEMPLATE_DECL][TS_DECL_MINIMAL] = 1;
+  cp_common_init_ts ();
 
   init_shadowed_var_for_decl ();
-
 }
 
 static const char *
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index f045d29..66d2d27 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -222,5 +222,78 @@  init_shadowed_var_for_decl (void)
 					   tree_decl_map_eq, 0);
 }
 
+void
+cp_common_init_ts (void)
+{
+  MARK_TS_DECL_NON_COMMON (NAMESPACE_DECL);
+  MARK_TS_DECL_NON_COMMON (USING_DECL);
+  MARK_TS_DECL_NON_COMMON (TEMPLATE_DECL);
+
+  MARK_TS_COMMON (TEMPLATE_TEMPLATE_PARM);
+  MARK_TS_COMMON (TEMPLATE_TYPE_PARM);
+  MARK_TS_COMMON (TEMPLATE_PARM_INDEX);
+  MARK_TS_COMMON (OVERLOAD);
+  MARK_TS_COMMON (TEMPLATE_INFO);
+  MARK_TS_COMMON (FOR_STMT);
+  MARK_TS_COMMON (TYPENAME_TYPE);
+  MARK_TS_COMMON (TYPEOF_TYPE);
+  MARK_TS_COMMON (IF_STMT);
+  MARK_TS_COMMON (BASELINK);
+  MARK_TS_COMMON (SWITCH_STMT);
+  MARK_TS_COMMON (TYPE_PACK_EXPANSION);
+  MARK_TS_COMMON (EXPR_PACK_EXPANSION);
+  MARK_TS_COMMON (DECLTYPE_TYPE);
+  MARK_TS_COMMON (BOUND_TEMPLATE_TEMPLATE_PARM);
+  MARK_TS_COMMON (UNBOUND_CLASS_TEMPLATE);
+  MARK_TS_COMMON (RANGE_FOR_STMT);
+
+  MARK_TS_TYPED (AGGR_INIT_EXPR);
+  MARK_TS_TYPED (EXPR_STMT);
+  MARK_TS_TYPED (EH_SPEC_BLOCK);
+  MARK_TS_TYPED (CLEANUP_STMT);
+  MARK_TS_TYPED (SCOPE_REF);
+  MARK_TS_TYPED (CAST_EXPR);
+  MARK_TS_TYPED (NON_DEPENDENT_EXPR);
+  MARK_TS_TYPED (MODOP_EXPR);
+  MARK_TS_TYPED (TRY_BLOCK);
+  MARK_TS_TYPED (THROW_EXPR);
+  MARK_TS_TYPED (HANDLER);
+  MARK_TS_TYPED (REINTERPRET_CAST_EXPR);
+  MARK_TS_TYPED (CONST_CAST_EXPR);
+  MARK_TS_TYPED (STATIC_CAST_EXPR);
+  MARK_TS_TYPED (DYNAMIC_CAST_EXPR);
+  MARK_TS_TYPED (TEMPLATE_ID_EXPR);
+  MARK_TS_TYPED (ARROW_EXPR);
+  MARK_TS_TYPED (SIZEOF_EXPR);
+  MARK_TS_TYPED (ALIGNOF_EXPR);
+  MARK_TS_TYPED (AT_ENCODE_EXPR);
+  MARK_TS_TYPED (UNARY_PLUS_EXPR);
+  MARK_TS_TYPED (TRAIT_EXPR);
+  MARK_TS_TYPED (TYPE_ARGUMENT_PACK);
+  MARK_TS_TYPED (NOEXCEPT_EXPR);
+  MARK_TS_TYPED (NONTYPE_ARGUMENT_PACK);
+  MARK_TS_TYPED (WHILE_STMT);
+  MARK_TS_TYPED (NEW_EXPR);
+  MARK_TS_TYPED (VEC_NEW_EXPR);
+  MARK_TS_TYPED (BREAK_STMT);
+  MARK_TS_TYPED (MEMBER_REF);
+  MARK_TS_TYPED (DOTSTAR_EXPR);
+  MARK_TS_TYPED (DO_STMT);
+  MARK_TS_TYPED (DELETE_EXPR);
+  MARK_TS_TYPED (VEC_DELETE_EXPR);
+  MARK_TS_TYPED (CONTINUE_STMT);
+  MARK_TS_TYPED (TAG_DEFN);
+  MARK_TS_TYPED (PSEUDO_DTOR_EXPR);
+  MARK_TS_TYPED (TYPEID_EXPR);
+  MARK_TS_TYPED (MUST_NOT_THROW_EXPR);
+  MARK_TS_TYPED (STMT_EXPR);
+  MARK_TS_TYPED (OFFSET_REF);
+  MARK_TS_TYPED (OFFSETOF_EXPR);
+  MARK_TS_TYPED (PTRMEM_CST);
+  MARK_TS_TYPED (EMPTY_CLASS_EXPR);
+  MARK_TS_TYPED (VEC_INIT_EXPR);
+  MARK_TS_TYPED (USING_STMT);
+  MARK_TS_TYPED (LAMBDA_EXPR);
+}
 
 #include "gt-cp-cp-objcp-common.h"
diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
index 38da59e..c668ad8 100644
--- a/gcc/cp/cp-objcp-common.h
+++ b/gcc/cp/cp-objcp-common.h
@@ -28,6 +28,7 @@  extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t,
 					 tree, bool);
 
 extern bool cp_function_decl_explicit_p (tree decl);
+extern void cp_common_init_ts (void);
 
 /* Lang hooks that are shared between C++ and ObjC++ are defined here.  Hooks
    specific to C++ or ObjC++ go in cp/cp-lang.c and objcp/objcp-lang.c,
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 238d0cf..1783915 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -702,7 +702,7 @@  enum cp_tree_node_structure_enum {
 
 /* The resulting tree type.  */
 union GTY((desc ("cp_tree_node_structure (&%h)"),
-       chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)"))) lang_tree_node {
+       chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL"))) lang_tree_node {
   union tree_node GTY ((tag ("TS_CP_GENERIC"),
 			desc ("tree_node_structure (&%h)"))) generic;
   struct template_parm_index_s GTY ((tag ("TS_CP_TPI"))) tpi;
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index a3ac860..687f60b 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -59,7 +59,7 @@  lang_identifier {
 /* The resulting tree type.  */
 
 union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
-     chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
+     chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL")))
 
 lang_tree_node {
   union tree_node GTY((tag ("0"),
diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
index b59e72d..5132e97 100644
--- a/gcc/go/go-lang.c
+++ b/gcc/go/go-lang.c
@@ -65,7 +65,7 @@  struct GTY(()) lang_identifier
 /* The resulting tree type.  */
 
 union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
-	   chain_next ("(union lang_tree_node *) TREE_CHAIN (&%h.generic)")))
+	   chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL")))
 lang_tree_node
 {
   union tree_node GTY((tag ("0"),
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index 3addcca..e422b4a 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -587,7 +587,7 @@  struct GTY(()) lang_identifier {
 
 /* The resulting tree type.  */
 union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
-       chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
+       chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL")))
  
   lang_tree_node {
   union tree_node GTY ((tag ("0"), 
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index 7409c1a..45809b8 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -2326,7 +2326,7 @@  lto_input_tree_pointers (struct lto_input_block *ib, struct data_in *data_in,
 
   code = TREE_CODE (expr);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
+  if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
     lto_input_ts_common_tree_pointers (ib, data_in, expr);
 
   if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 29d171b..a4e8b70 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -1169,7 +1169,7 @@  lto_output_tree_pointers (struct output_block *ob, tree expr, bool ref_p)
 
   code = TREE_CODE (expr);
 
-  if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
+  if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
     lto_output_ts_common_tree_pointers (ob, expr, ref_p);
 
   if (CODE_CONTAINS_STRUCT (code, TS_VECTOR))
diff --git a/gcc/lto/lto-tree.h b/gcc/lto/lto-tree.h
index d187fe2..847348c 100644
--- a/gcc/lto/lto-tree.h
+++ b/gcc/lto/lto-tree.h
@@ -48,7 +48,7 @@  enum lto_tree_node_structure_enum {
 };
 
 union GTY((desc ("lto_tree_node_structure (&%h)"),
-	  chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
+	  chain_next ("CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL")))
     lang_tree_node
 {
   union tree_node GTY ((tag ("TS_LTO_GENERIC"),
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 71c8cdb..78a7977 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -1618,7 +1618,8 @@  lto_fixup_common (tree t, void *data)
 
   /* This is not very efficient because we cannot do tail-recursion with
      a long chain of trees. */
-  LTO_FIXUP_SUBTREE (TREE_CHAIN (t));
+  if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_COMMON))
+    LTO_FIXUP_SUBTREE (TREE_CHAIN (t));
 }
 
 /* Fix up fields of a decl_minimal T.  DATA points to fix-up states.  */
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 049dc00..e5bd52a 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -10541,4 +10541,22 @@  objc_v2_encode_prop_attr (tree property)
   return get_identifier (string);
 }
 
+void
+objc_common_init_ts (void)
+{
+  c_common_init_ts ();
+
+  MARK_TS_DECL_NON_COMMON (CLASS_METHOD_DECL);
+  MARK_TS_DECL_NON_COMMON (INSTANCE_METHOD_DECL);
+  MARK_TS_DECL_NON_COMMON (KEYWORD_DECL);
+  MARK_TS_DECL_NON_COMMON (PROPERTY_DECL);
+
+  MARK_TS_COMMON (CLASS_INTERFACE_TYPE);
+  MARK_TS_COMMON (PROTOCOL_INTERFACE_TYPE);
+  MARK_TS_COMMON (CLASS_IMPLEMENTATION_TYPE);
+
+  MARK_TS_TYPED (MESSAGE_SEND_EXPR);
+  MARK_TS_TYPED (PROPERTY_REF);
+}
+
 #include "gt-objc-objc-act.h"
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 3983d4b..909181a 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -28,6 +28,7 @@  bool objc_init (void);
 const char *objc_printable_name (tree, int);
 tree objc_fold_obj_type_ref (tree, tree);
 int objc_gimplify_expr (tree *, gimple_seq *, gimple_seq *);
+void objc_common_init_ts (void);
 
 /* NB: The remaining public functions are prototyped in c-common.h, for the
    benefit of stub-objc.c and objc-act.c.  */
diff --git a/gcc/objc/objc-lang.c b/gcc/objc/objc-lang.c
index fd65776..169b894 100644
--- a/gcc/objc/objc-lang.c
+++ b/gcc/objc/objc-lang.c
@@ -36,7 +36,6 @@  along with GCC; see the file COPYING3.  If not see
 #include "c-lang.h"
 
 enum c_language_kind c_language = clk_objc;
-static void objc_init_ts (void);
 
 /* Lang hooks common to C and ObjC are declared in c-objc-common.h;
    consequently, there should be very few hooks below.  */
@@ -50,7 +49,7 @@  static void objc_init_ts (void);
 #undef LANG_HOOKS_GIMPLIFY_EXPR 
 #define LANG_HOOKS_GIMPLIFY_EXPR objc_gimplify_expr
 #undef LANG_HOOKS_INIT_TS
-#define LANG_HOOKS_INIT_TS objc_init_ts
+#define LANG_HOOKS_INIT_TS objc_common_init_ts
 
 /* Each front end provides its own lang hook initializer.  */
 struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
@@ -58,33 +57,4 @@  struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
 /* Lang hook routines common to C and ObjC appear in c-objc-common.c;
    there should be very few (if any) routines below.  */
 
-static void
-objc_init_ts (void)
-{
-  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_NON_COMMON] = 1;
-  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_NON_COMMON] = 1;
-  tree_contains_struct[KEYWORD_DECL][TS_DECL_NON_COMMON] = 1;
-  tree_contains_struct[PROPERTY_DECL][TS_DECL_NON_COMMON] = 1;
-  
-  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_WITH_VIS] = 1;
-  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_WITH_VIS] = 1;
-  tree_contains_struct[KEYWORD_DECL][TS_DECL_WITH_VIS] = 1;
-  tree_contains_struct[PROPERTY_DECL][TS_DECL_WITH_VIS] = 1;
-
-  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_WRTL] = 1;
-  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_WRTL] = 1;
-  tree_contains_struct[KEYWORD_DECL][TS_DECL_WRTL] = 1;
-  tree_contains_struct[PROPERTY_DECL][TS_DECL_WRTL] = 1;
-  
-  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_MINIMAL] = 1;
-  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_MINIMAL] = 1;
-  tree_contains_struct[KEYWORD_DECL][TS_DECL_MINIMAL] = 1;
-  tree_contains_struct[PROPERTY_DECL][TS_DECL_MINIMAL] = 1;
-  
-  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_COMMON] = 1;
-  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_COMMON] = 1;
-  tree_contains_struct[KEYWORD_DECL][TS_DECL_COMMON] = 1;
-  tree_contains_struct[PROPERTY_DECL][TS_DECL_COMMON] = 1;
-}
-
 #include "gtype-objc.h"
diff --git a/gcc/objcp/objcp-lang.c b/gcc/objcp/objcp-lang.c
index fe2be66..0019022 100644
--- a/gcc/objcp/objcp-lang.c
+++ b/gcc/objcp/objcp-lang.c
@@ -89,52 +89,8 @@  objcp_tsubst_copy_and_build (tree t, tree args, tsubst_flags_t complain,
 static void
 objcxx_init_ts (void)
 {
-  /* objc decls */
-  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_NON_COMMON] = 1;
-  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_NON_COMMON] = 1;
-  tree_contains_struct[KEYWORD_DECL][TS_DECL_NON_COMMON] = 1;
-  tree_contains_struct[PROPERTY_DECL][TS_DECL_NON_COMMON] = 1;
-  
-  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_WITH_VIS] = 1;
-  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_WITH_VIS] = 1;
-  tree_contains_struct[KEYWORD_DECL][TS_DECL_WITH_VIS] = 1;
-  tree_contains_struct[PROPERTY_DECL][TS_DECL_WITH_VIS] = 1;
-
-  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_WRTL] = 1;
-  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_WRTL] = 1;
-  tree_contains_struct[KEYWORD_DECL][TS_DECL_WRTL] = 1;
-  tree_contains_struct[PROPERTY_DECL][TS_DECL_WRTL] = 1;
-  
-  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_MINIMAL] = 1;
-  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_MINIMAL] = 1;
-  tree_contains_struct[KEYWORD_DECL][TS_DECL_MINIMAL] = 1;
-  tree_contains_struct[PROPERTY_DECL][TS_DECL_MINIMAL] = 1;
-  
-  tree_contains_struct[CLASS_METHOD_DECL][TS_DECL_COMMON] = 1;
-  tree_contains_struct[INSTANCE_METHOD_DECL][TS_DECL_COMMON] = 1;
-  tree_contains_struct[KEYWORD_DECL][TS_DECL_COMMON] = 1;
-  tree_contains_struct[PROPERTY_DECL][TS_DECL_COMMON] = 1;
-  
-  /* C++ decls */
-  tree_contains_struct[NAMESPACE_DECL][TS_DECL_NON_COMMON] = 1;
-  tree_contains_struct[USING_DECL][TS_DECL_NON_COMMON] = 1;
-  tree_contains_struct[TEMPLATE_DECL][TS_DECL_NON_COMMON] = 1;
-
-  tree_contains_struct[NAMESPACE_DECL][TS_DECL_WITH_VIS] = 1;
-  tree_contains_struct[USING_DECL][TS_DECL_WITH_VIS] = 1;
-  tree_contains_struct[TEMPLATE_DECL][TS_DECL_WITH_VIS] = 1;
-
-  tree_contains_struct[NAMESPACE_DECL][TS_DECL_WRTL] = 1;
-  tree_contains_struct[USING_DECL][TS_DECL_WRTL] = 1;
-  tree_contains_struct[TEMPLATE_DECL][TS_DECL_WRTL] = 1;
-  
-  tree_contains_struct[NAMESPACE_DECL][TS_DECL_COMMON] = 1;
-  tree_contains_struct[USING_DECL][TS_DECL_COMMON] = 1;
-  tree_contains_struct[TEMPLATE_DECL][TS_DECL_COMMON] = 1;
- 
-  tree_contains_struct[NAMESPACE_DECL][TS_DECL_MINIMAL] = 1;
-  tree_contains_struct[USING_DECL][TS_DECL_MINIMAL] = 1;
-  tree_contains_struct[TEMPLATE_DECL][TS_DECL_MINIMAL] = 1;
+  objc_common_init_ts ();
+  cp_common_init_ts ();
 
   init_shadowed_var_for_decl ();
 }
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index dfd3589..b0c6899 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -756,7 +756,8 @@  print_node (FILE *file, const char *prefix, tree node, int indent)
 	      print_node (file, temp, TREE_OPERAND (node, i), indent + 4);
 	    }
 	}
-      print_node (file, "chain", TREE_CHAIN (node), indent + 4);
+      if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
+	print_node (file, "chain", TREE_CHAIN (node), indent + 4);
       break;
 
     case tcc_constant:
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index de30cfd..45c7e88 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -4295,7 +4295,8 @@  copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
 	 here.  */
       tree chain = NULL_TREE, new_tree;
 
-      chain = TREE_CHAIN (*tp);
+      if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
+	chain = TREE_CHAIN (*tp);
 
       /* Copy the node.  */
       new_tree = copy_node (*tp);
diff --git a/gcc/tree.c b/gcc/tree.c
index 798bc08..68f40c9 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -351,53 +351,6 @@  initialize_tree_contains_struct (void)
 {
   unsigned i;
 
-#define MARK_TS_BASE(C)					\
-  do {							\
-    tree_contains_struct[C][TS_BASE] = 1;		\
-  } while (0)
-
-#define MARK_TS_TYPED(C)				\
-  do {							\
-    MARK_TS_BASE (C);					\
-    tree_contains_struct[C][TS_TYPED] = 1;		\
-  } while (0)
-
-#define MARK_TS_COMMON(C)				\
-  do {							\
-    MARK_TS_TYPED (C);					\
-    tree_contains_struct[C][TS_COMMON] = 1;		\
-  } while (0)
-
-#define MARK_TS_DECL_MINIMAL(C)				\
-  do {							\
-    MARK_TS_COMMON (C);					\
-    tree_contains_struct[C][TS_DECL_MINIMAL] = 1;	\
-  } while (0)
-
-#define MARK_TS_DECL_COMMON(C)				\
-  do {							\
-    MARK_TS_DECL_MINIMAL (C);				\
-    tree_contains_struct[C][TS_DECL_COMMON] = 1;	\
-  } while (0)
-
-#define MARK_TS_DECL_WRTL(C)				\
-  do {							\
-    MARK_TS_DECL_COMMON (C);				\
-    tree_contains_struct[C][TS_DECL_WRTL] = 1;		\
-  } while (0)
-
-#define MARK_TS_DECL_WITH_VIS(C)			\
-  do {							\
-    MARK_TS_DECL_WRTL (C);				\
-    tree_contains_struct[C][TS_DECL_WITH_VIS] = 1;	\
-  } while (0)
-
-#define MARK_TS_DECL_NON_COMMON(C)			\
-  do {							\
-    MARK_TS_DECL_WITH_VIS (C);				\
-    tree_contains_struct[C][TS_DECL_NON_COMMON] = 1;	\
-  } while (0)
-
   for (i = ERROR_MARK; i < LAST_AND_UNUSED_TREE_CODE; i++)
     {
       enum tree_code code;
@@ -412,10 +365,14 @@  initialize_tree_contains_struct (void)
       /* Mark all the structures that TS is derived from.  */
       switch (ts_code)
 	{
-	case TS_COMMON:
+	case TS_TYPED:
 	  MARK_TS_BASE (code);
 	  break;
 
+	case TS_COMMON:
+	  MARK_TS_TYPED (code);
+	  break;
+
 	case TS_INT_CST:
 	case TS_REAL_CST:
 	case TS_FIXED_CST:
@@ -521,14 +478,6 @@  initialize_tree_contains_struct (void)
   gcc_assert (tree_contains_struct[FUNCTION_DECL][TS_FUNCTION_DECL]);
   gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_MINIMAL]);
   gcc_assert (tree_contains_struct[IMPORTED_DECL][TS_DECL_COMMON]);
-
-#undef MARK_TS_BASE
-#undef MARK_TS_COMMON
-#undef MARK_TS_DECL_MINIMAL
-#undef MARK_TS_DECL_COMMON
-#undef MARK_TS_DECL_WRTL
-#undef MARK_TS_DECL_WITH_VIS
-#undef MARK_TS_DECL_NON_COMMON
 }
 
 
@@ -944,7 +893,7 @@  make_node_stat (enum tree_code code MEM_STAT_DECL)
 }
 
 /* Return a new node with the same contents as NODE except that its
-   TREE_CHAIN is zero and it has a fresh uid.  */
+   TREE_CHAIN, if it has one, is zero and it has a fresh uid.  */
 
 tree
 copy_node_stat (tree node MEM_STAT_DECL)
@@ -959,7 +908,8 @@  copy_node_stat (tree node MEM_STAT_DECL)
   t = ggc_alloc_zone_tree_node_stat (&tree_zone, length PASS_MEM_STAT);
   memcpy (t, node, length);
 
-  TREE_CHAIN (t) = 0;
+  if (CODE_CONTAINS_STRUCT (code, TS_COMMON))
+    TREE_CHAIN (t) = 0;
   TREE_ASM_WRITTEN (t) = 0;
   TREE_VISITED (t) = 0;
   if (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL)
diff --git a/gcc/tree.h b/gcc/tree.h
index 2f772e1..4ad2d3e 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -50,6 +50,54 @@  MAX_TREE_CODES
 extern unsigned char tree_contains_struct[MAX_TREE_CODES][64];
 #define CODE_CONTAINS_STRUCT(CODE, STRUCT) (tree_contains_struct[(CODE)][(STRUCT)])
 
+/* Macros for initializing `tree_contains_struct'.  */
+#define MARK_TS_BASE(C)					\
+  do {							\
+    tree_contains_struct[C][TS_BASE] = 1;		\
+  } while (0)
+
+#define MARK_TS_TYPED(C)				\
+  do {							\
+    MARK_TS_BASE (C);					\
+    tree_contains_struct[C][TS_TYPED] = 1;		\
+  } while (0)
+
+#define MARK_TS_COMMON(C)				\
+  do {							\
+    MARK_TS_TYPED (C);					\
+    tree_contains_struct[C][TS_COMMON] = 1;		\
+  } while (0)
+
+#define MARK_TS_DECL_MINIMAL(C)				\
+  do {							\
+    MARK_TS_COMMON (C);					\
+    tree_contains_struct[C][TS_DECL_MINIMAL] = 1;	\
+  } while (0)
+
+#define MARK_TS_DECL_COMMON(C)				\
+  do {							\
+    MARK_TS_DECL_MINIMAL (C);				\
+    tree_contains_struct[C][TS_DECL_COMMON] = 1;	\
+  } while (0)
+
+#define MARK_TS_DECL_WRTL(C)				\
+  do {							\
+    MARK_TS_DECL_COMMON (C);				\
+    tree_contains_struct[C][TS_DECL_WRTL] = 1;		\
+  } while (0)
+
+#define MARK_TS_DECL_WITH_VIS(C)			\
+  do {							\
+    MARK_TS_DECL_WRTL (C);				\
+    tree_contains_struct[C][TS_DECL_WITH_VIS] = 1;	\
+  } while (0)
+
+#define MARK_TS_DECL_NON_COMMON(C)			\
+  do {							\
+    MARK_TS_DECL_WITH_VIS (C);				\
+    tree_contains_struct[C][TS_DECL_NON_COMMON] = 1;	\
+  } while (0)
+
 /* Number of language-independent tree codes.  */
 #define NUM_TREE_CODES ((int) LAST_AND_UNUSED_TREE_CODE)
 
@@ -864,7 +912,7 @@  enum tree_node_structure_enum {
    are chained together.  */
 
 #define TREE_CHAIN(NODE) __extension__ \
-(*({__typeof (NODE) const __t = (NODE);				\
+(*({__typeof (NODE) const __t = CONTAINS_STRUCT_CHECK (NODE, TS_COMMON);\
     &__t->common.chain; }))
 
 /* In all nodes that are expressions, this is the data type of the expression.
@@ -872,7 +920,7 @@  enum tree_node_structure_enum {
    In ARRAY_TYPE nodes, this is the type of the elements.
    In VECTOR_TYPE nodes, this is the type of the elements.  */
 #define TREE_TYPE(NODE) __extension__ \
-(*({__typeof (NODE) const __t = (NODE);					\
+(*({__typeof (NODE) const __t = CONTAINS_STRUCT_CHECK (NODE, TS_TYPED); \
     &__t->typed.type; }))
 
 extern void tree_contains_struct_check_failed (const_tree,