What do you think of the following plan for turning cgraph into a class hierarchy? We cannot finish it until we have gengtype understanding single inheritance, but we can start changing APIs in preparation.
EXISTING ########################################### enum symtab_type { SYMTAB_SYMBOL, SYMTAB_FUNCTION, SYMTAB_VARIABLE }; struct symtab_node_base /* marked SYMTAB_SYMBOL */ embeds symtab_type struct cgraph_node /* marked SYMTAB_FUNCTION */ embeds leading struct symtab_node_base symbol; struct cgraph_local_info local; struct cgraph_global_info global; struct cgraph_rtl_info rtl; struct cgraph_clone_info clone; struct cgraph_thunk_info thunk; typedef struct cgraph_node *cgraph_node_ptr; struct varpool_node /* marked SYMTAB_VARIABLE */ embeds leading struct symtab_node_base symbol; cgraph.h:typedef struct varpool_node *varpool_node_ptr; union symtab_node_def struct symtab_node_base GTY ((tag ("SYMTAB_SYMBOL"))) symbol; struct cgraph_node GTY ((tag ("SYMTAB_FUNCTION"))) x_function; struct varpool_node GTY ((tag ("SYMTAB_VARIABLE"))) x_variable; typedef union symtab_node_def *symtab_node; typedef const union symtab_node_def *const_symtab_node; static inline struct cgraph_node *cgraph (symtab_node node); static inline struct varpool_node *varpool (symtab_node node); APPROACH ########################################### Add converters and testers. Change callers to use those. Change callers to use type-safe parameters. Change implementation to class hierarchy. Add accessors. CONVERTERS AND TESTERS ########################################### add symtab_node_base &symtab_node_def::ref_symbol() { return symbol; } symtab_node_base &cgraph_node::ref_symbol() { return symbol; } symtab_node_base &varpool_node::ref_symbol() { return symbol; } change node->symbol.whatever to node->ref_symbol().whatever ---- should not need to add these cgraph_node &symtab_node_def::ref_cgraph() { gcc_assert (symbol.type == SYMTAB_FUNCTION); return x_function; } varpool_node &symtab_node_def::ref_varpool() { gcc_assert (symbol.type == SYMTAB_VARIABLE); return x_variable; } ---- add symtab_node_base *symtab_node_def::try_symbol() { return &symbol; } cgraph_node *symtab_node_def::try_cgraph() { return symbol.type == SYMTAB_FUNCTION ? &x_function : NULL; } varpool_node *symtab_node_def::try_varpool() { return symbol.type == SYMTAB_VARIABLE ? &x_variable : NULL; } change if (symtab_function_p (node) && cgraph (node)->analyzed) return cgraph (node); to if (cgraph_node *p = node->try_cgraph()) if (p->analyzed) return p; change if (symtab_function_p (node) && cgraph (node)->callers) .... to if (cgraph_node *p = node->try_cgraph()) if (p->callers) .... change if (symtab_function_p (node)) { struct cgraph_node *cnode = cgraph (node); .... to if (cgraph_node *cnode = node->try_cgraph ()) { .... likewise "symtab_variable_p (node)" and "varpool (node)" ---- If there are any "symtab_function_p (node)" expressions left, add bool symtab_node_def::is_cgraph() { return symbol.type == SYMTAB_FUNCTION; } bool symtab_node_def::is_varpool() { return symbol.type == SYMTAB_VARIABLE; } change symtab_function_p (node) to node->is_cgraph () likewise "symtab_variable_p (node)" ---- Though we would like to avoid doing so, if there are any "cgraph (node)" or "varpool (node)" expressions left, add symtab_node_base *symtab_node_def::ptr_symbol() { return &symbol; } cgraph_node *symtab_node_def::ptr_cgraph() { gcc_assert (symbol.type == SYMTAB_FUNCTION); { return &x_function; } varpool_node *symtab_node_def::ptr_varpool() { gcc_assert (symbol.type == SYMTAB_VARIABLE); { return &x_variable; } change cgraph (node) => node->ptr_cgraph() likewise "varpool (node)" TYPE SAFETY ########################################### If a function asserts that its symtab_node parameter is symtab_function_p, then convert the function to take a cgraph_node* and change the callers to convert as above. PROPOSED HIERARCHY ########################################### enum symtab_type { SYMTAB_SYMBOL, SYMTAB_FUNCTION, SYMTAB_VARIABLE }; struct symtab_node_base /* marked SYMTAB_SYMBOL */ embeds symtab_type cgraph_node : symtab_node_base /* marked SYMTAB_FUNCTION */ varpool_node : symtab_node_base /* marked SYMTAB_VARIABLE */ changing typedef union symtab_node_def *symtab_node; typedef const union symtab_node_def *const_symtab_node; to typedef symtab_node_base *symtab_node; typedef const symtab_node_base *const_symtab_node; changing used of symtab_node_def to symtab_node_base -- Lawrence Crowl