This patch to the Go frontend fixes the handling of pointer indirection through a circular type. The gcc middle-end can not represent a circular type, as such a construct can not exist in C (in Go you get one by writing "type T *T"). We handle this by using void* and introducing a type cast on the indirection. With the use of the Gcc_backend interface, we now use a general void* rather than specifically ptr_type_node which is what we used before. This patch updates the handling of pointer indirection to check for this case. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r 520f034862ee go/expressions.cc --- a/go/expressions.cc Wed Feb 29 21:08:49 2012 -0800 +++ b/go/expressions.cc Wed Feb 29 21:56:03 2012 -0800 @@ -4705,29 +4705,33 @@ // need to check for nil. We don't bother to check for small // structs because we expect the system to crash on a nil // pointer dereference. - HOST_WIDE_INT s = int_size_in_bytes(TREE_TYPE(TREE_TYPE(expr))); - if (s == -1 || s >= 4096) + tree target_type_tree = TREE_TYPE(TREE_TYPE(expr)); + if (!VOID_TYPE_P(target_type_tree)) { - if (!DECL_P(expr)) - expr = save_expr(expr); - tree compare = fold_build2_loc(loc.gcc_location(), EQ_EXPR, - boolean_type_node, - expr, - fold_convert(TREE_TYPE(expr), - null_pointer_node)); - tree crash = Gogo::runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE, - loc); - expr = fold_build2_loc(loc.gcc_location(), COMPOUND_EXPR, - TREE_TYPE(expr), build3(COND_EXPR, - void_type_node, - compare, crash, - NULL_TREE), - expr); + HOST_WIDE_INT s = int_size_in_bytes(target_type_tree); + if (s == -1 || s >= 4096) + { + if (!DECL_P(expr)) + expr = save_expr(expr); + tree compare = fold_build2_loc(loc.gcc_location(), EQ_EXPR, + boolean_type_node, + expr, + fold_convert(TREE_TYPE(expr), + null_pointer_node)); + tree crash = Gogo::runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE, + loc); + expr = fold_build2_loc(loc.gcc_location(), COMPOUND_EXPR, + TREE_TYPE(expr), build3(COND_EXPR, + void_type_node, + compare, crash, + NULL_TREE), + expr); + } } // If the type of EXPR is a recursive pointer type, then we // need to insert a cast before indirecting. - if (TREE_TYPE(TREE_TYPE(expr)) == ptr_type_node) + if (VOID_TYPE_P(target_type_tree)) { Type* pt = this->expr_->type()->points_to(); tree ind = type_to_tree(pt->get_backend(context->gogo()));