diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 87393299949b570c3820b8e471ca989f14f50bfb..8a7df7d97df44e7af1bfac2a7078327623b0bc5a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,28 @@
+2013-10-29  David Malcolm  <dmalcolm@redhat.com>
+
+	* cgraph.h (symtab_node_base): Convert to a class;
+	add GTY((desc ("%h.type"), tag ("SYMTAB_SYMBOL"))), and take
+	chain_next/prev from symtab_node_def.
+	(cgraph_node): Inherit from symtab_node; add GTY option
+	tag ("SYMTAB_FUNCTION").
+	(varpool_node): Inherit from symtab_node; add GTY option
+	tag ("SYMTAB_VARIABLE").
+	(symtab_node_def): Remove.
+	(is_a_helper <cgraph_node>::test (symtab_node_def *)): Convert to...
+	(is_a_helper <cgraph_node>::test (symtab_node_base *)): ...this.
+	(is_a_helper <varpool_node>::test (symtab_node_def *)): Convert to...
+	(is_a_helper <varpool_node>::test (symtab_node_base *)): ...this.
+
+	* ipa-ref.h (symtab_node_def): Drop.
+	(symtab_node): Change underlying type from symtab_node_def to
+	symtab_node_base.
+	(const_symtab_node): Likwise.
+
+	* is-a.h: Update examples in comment.
+
+	* symtab.c (symtab_hash): Change symtab_node_def to symtab_node_base.
+	(assembler_name_hash): Likewise.
+
 2013-10-29  Martin Liska <marxin.liska@gmail.com>
 
        * doc/tree-ssa.texi (gimple_phi_result): Document.
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 77064194cf50b7c467acc4dc46f9e3aa7c346c49..4cc20491f6e94466f80781243e81a79f75d4f629 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -39,8 +39,11 @@ enum symtab_type
 
 /* Base of all entries in the symbol table.
    The symtab_node is inherited by cgraph and varpol nodes.  */
-struct GTY(()) symtab_node_base
+class GTY((desc ("%h.type"), tag ("SYMTAB_SYMBOL"),
+	   chain_next ("%h.next"), chain_prev ("%h.previous")))
+  symtab_node_base
 {
+public:
   /* Type of the symbol.  */
   ENUM_BITFIELD (symtab_type) type : 8;
 
@@ -251,25 +254,19 @@ struct GTY(()) cgraph_clone_info
 /* The cgraph data structure.
    Each function decl has assigned cgraph_node listing callees and callers.  */
 
-struct GTY(()) cgraph_node {
-  struct symtab_node_base symbol;
+struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node_base {
+public:
   struct cgraph_edge *callees;
   struct cgraph_edge *callers;
   /* List of edges representing indirect calls with a yet undetermined
      callee.  */
   struct cgraph_edge *indirect_calls;
   /* For nested functions points to function the node is nested in.  */
-  struct cgraph_node *
-    GTY ((nested_ptr (union symtab_node_def, "(struct cgraph_node *)(%h)", "(symtab_node)%h")))
-    origin;
+  struct cgraph_node *origin;
   /* Points to first nested function, if any.  */
-  struct cgraph_node *
-    GTY ((nested_ptr (union symtab_node_def, "(struct cgraph_node *)(%h)", "(symtab_node)%h")))
-    nested;
+  struct cgraph_node *nested;
   /* Pointer to the next function with same origin, if any.  */
-  struct cgraph_node *
-    GTY ((nested_ptr (union symtab_node_def, "(struct cgraph_node *)(%h)", "(symtab_node)%h")))
-    next_nested;
+  struct cgraph_node *next_nested;
   /* Pointer to the next clone.  */
   struct cgraph_node *next_sibling_clone;
   struct cgraph_node *prev_sibling_clone;
@@ -517,9 +514,8 @@ typedef struct cgraph_edge *cgraph_edge_p;
 /* The varpool data structure.
    Each static variable decl has assigned varpool_node.  */
 
-struct GTY(()) varpool_node {
-  struct symtab_node_base symbol;
-
+class GTY((tag ("SYMTAB_VARIABLE"))) varpool_node : public symtab_node_base {
+public:
   /* Set when variable is scheduled to be assembled.  */
   unsigned output : 1;
 };
@@ -535,22 +531,12 @@ struct GTY(()) asm_node {
   int order;
 };
 
-/* Symbol table entry.  */
-union GTY((desc ("%h.symbol.type"), chain_next ("%h.symbol.next"),
-	   chain_prev ("%h.symbol.previous"))) symtab_node_def {
-  struct symtab_node_base GTY ((tag ("SYMTAB_SYMBOL"))) symbol;
-  /* To access the following fields,
-     use the use dyn_cast or as_a to obtain the concrete type.  */
-  struct cgraph_node GTY ((tag ("SYMTAB_FUNCTION"))) x_function;
-  struct varpool_node GTY ((tag ("SYMTAB_VARIABLE"))) x_variable;
-};
-
 /* Report whether or not THIS symtab node is a function, aka cgraph_node.  */
 
 template <>
 template <>
 inline bool
-is_a_helper <cgraph_node>::test (symtab_node_def *p)
+is_a_helper <cgraph_node>::test (symtab_node_base *p)
 {
   return p->symbol.type == SYMTAB_FUNCTION;
 }
@@ -560,7 +546,7 @@ is_a_helper <cgraph_node>::test (symtab_node_def *p)
 template <>
 template <>
 inline bool
-is_a_helper <varpool_node>::test (symtab_node_def *p)
+is_a_helper <varpool_node>::test (symtab_node_base *p)
 {
   return p->symbol.type == SYMTAB_VARIABLE;
 }
diff --git a/gcc/ipa-ref.h b/gcc/ipa-ref.h
index e0553bb660925f0b0aaae417553167a59da99d09..dc6e238568c3cb3b2094929f7f5da4e0bc0fd640 100644
--- a/gcc/ipa-ref.h
+++ b/gcc/ipa-ref.h
@@ -20,9 +20,9 @@ along with GCC; see the file COPYING3.  If not see
 
 struct cgraph_node;
 struct varpool_node;
-union symtab_node_def;
-typedef union symtab_node_def *symtab_node;
-typedef const union symtab_node_def *const_symtab_node;
+class symtab_node_base;
+typedef symtab_node_base *symtab_node;
+typedef const symtab_node_base *const_symtab_node;
 
 
 /* How the reference is done.  */
diff --git a/gcc/is-a.h b/gcc/is-a.h
index b5ee8543abe5d09e9487f7cc6c374f0e2454a47b..ccf12be3d90fa3645b80acecb358fcb2d954d185 100644
--- a/gcc/is-a.h
+++ b/gcc/is-a.h
@@ -31,7 +31,7 @@ bool is_a <TYPE> (pointer)
 
     Tests whether the pointer actually points to a more derived TYPE.
 
-    Suppose you have a symtab_node_def *ptr, AKA symtab_node ptr.  You can test
+    Suppose you have a symtab_node_base *ptr, AKA symtab_node ptr.  You can test
     whether it points to a 'derived' cgraph_node as follows.
 
       if (is_a <cgraph_node> (ptr))
@@ -110,7 +110,7 @@ example,
   template <>
   template <>
   inline bool
-  is_a_helper <cgraph_node>::test (symtab_node_def *p)
+  is_a_helper <cgraph_node>::test (symtab_node_base *p)
   {
     return p->symbol.type == SYMTAB_FUNCTION;
   }
@@ -122,7 +122,7 @@ when needed may result in a crash.  For example,
   template <>
   template <>
   inline bool
-  is_a_helper <cgraph_node>::cast (symtab_node_def *p)
+  is_a_helper <cgraph_node>::cast (symtab_node_base *p)
   {
     return &p->x_function;
   }
diff --git a/gcc/symtab.c b/gcc/symtab.c
index acffbdd6f654eb9e024ec7c8d47502abf7015244..7232291e1cba8aa13abfd4fad11b2219c2c660f6 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -49,9 +49,9 @@ const char * const ld_plugin_symbol_resolution_names[]=
 };
 
 /* Hash table used to convert declarations into nodes.  */
-static GTY((param_is (union symtab_node_def))) htab_t symtab_hash;
+static GTY((param_is (symtab_node_base))) htab_t symtab_hash;
 /* Hash table used to convert assembler names into nodes.  */
-static GTY((param_is (union symtab_node_def))) htab_t assembler_name_hash;
+static GTY((param_is (symtab_node_base))) htab_t assembler_name_hash;
 
 /* Linked list of symbol table nodes.  */
 symtab_node symtab_nodes;