The Go language spec clarified that a lookup on nil map should work and return a zero value. This patch to the Go frontend and the Go library implements that. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline. (This patch requires rebuilding the entire Go library, as the signature of one of the runtime support functions changed.)
Ian
diff -r 72af58e2d1a6 go/runtime.def --- a/go/runtime.def Tue Sep 20 17:55:35 2011 -0700 +++ b/go/runtime.def Wed Sep 21 10:25:43 2011 -0700 @@ -87,8 +87,8 @@ R1(POINTER)) // Look up a key in a map returning whether it is present. -DEF_GO_RUNTIME(MAPACCESS2, "runtime.mapaccess2", P3(MAP, POINTER, POINTER), - R1(BOOL)) +DEF_GO_RUNTIME(MAPACCESS2, "runtime.mapaccess2", + P4(TYPE, MAP, POINTER, POINTER), R1(BOOL)) // Tuple assignment to a map element. DEF_GO_RUNTIME(MAPASSIGN2, "runtime.mapassign2", diff -r 72af58e2d1a6 go/statements.cc --- a/go/statements.cc Tue Sep 20 17:55:35 2011 -0700 +++ b/go/statements.cc Wed Sep 21 10:25:43 2011 -0700 @@ -1085,14 +1085,16 @@ Statement::make_temporary(Type::lookup_bool_type(), NULL, loc); b->add_statement(present_temp); - // present_temp = mapaccess2(MAP, &key_temp, &val_temp) + // present_temp = mapaccess2(DESCRIPTOR, MAP, &key_temp, &val_temp) + Expression* a1 = Expression::make_type_descriptor(map_type, loc); + Expression* a2 = map_index->map(); Temporary_reference_expression* ref = Expression::make_temporary_reference(key_temp, loc); - Expression* a1 = Expression::make_unary(OPERATOR_AND, ref, loc); + Expression* a3 = Expression::make_unary(OPERATOR_AND, ref, loc); ref = Expression::make_temporary_reference(val_temp, loc); - Expression* a2 = Expression::make_unary(OPERATOR_AND, ref, loc); - Expression* call = Runtime::make_call(Runtime::MAPACCESS2, loc, 3, - map_index->map(), a1, a2); + Expression* a4 = Expression::make_unary(OPERATOR_AND, ref, loc); + Expression* call = Runtime::make_call(Runtime::MAPACCESS2, loc, 4, + a1, a2, a3, a4); ref = Expression::make_temporary_reference(present_temp, loc); ref->set_is_lvalue(); diff -r 72af58e2d1a6 libgo/runtime/go-map-delete.c --- a/libgo/runtime/go-map-delete.c Tue Sep 20 17:55:35 2011 -0700 +++ b/libgo/runtime/go-map-delete.c Wed Sep 21 10:25:43 2011 -0700 @@ -9,6 +9,7 @@ #include "go-alloc.h" #include "go-assert.h" +#include "go-panic.h" #include "map.h" /* Delete the entry matching KEY from MAP. */ @@ -25,6 +26,9 @@ size_t bucket_index; void **pentry; + if (map == NULL) + __go_panic_msg ("assignment to entry in nil map"); + descriptor = map->__descriptor; key_descriptor = descriptor->__map_descriptor->__key_type; diff -r 72af58e2d1a6 libgo/runtime/go-map-index.c --- a/libgo/runtime/go-map-index.c Tue Sep 20 17:55:35 2011 -0700 +++ b/libgo/runtime/go-map-index.c Wed Sep 21 10:25:43 2011 -0700 @@ -9,6 +9,7 @@ #include "go-alloc.h" #include "go-assert.h" +#include "go-panic.h" #include "map.h" /* Rehash MAP to a larger size. */ @@ -85,6 +86,13 @@ size_t bucket_index; char *entry; + if (map == NULL) + { + if (insert) + __go_panic_msg ("assignment to entry in nil map"); + return NULL; + } + descriptor = map->__descriptor; key_descriptor = descriptor->__map_descriptor->__key_type; diff -r 72af58e2d1a6 libgo/runtime/map.goc --- a/libgo/runtime/map.goc Tue Sep 20 17:55:35 2011 -0700 +++ b/libgo/runtime/map.goc Wed Sep 21 10:25:43 2011 -0700 @@ -9,17 +9,18 @@ typedef unsigned char byte; typedef _Bool bool; -typedef struct __go_map hmap; +typedef struct __go_map_type MapType; +typedef struct __go_map Hmap; typedef struct __go_hash_iter hiter; /* Access a value in a map, returning a value and a presence indicator. */ -func mapaccess2(h *hmap, key *byte, val *byte) (present bool) { +func mapaccess2(t *MapType, h *Hmap, key *byte, val *byte) (present bool) { byte *mapval; size_t valsize; mapval = __go_map_index(h, key, 0); - valsize = h->__descriptor->__map_descriptor->__val_type->__size; + valsize = t->__val_type->__size; if (mapval == nil) { __builtin_memset(val, 0, valsize); present = 0; @@ -31,7 +32,7 @@ /* Optionally assign a value to a map (m[k] = v, p). */ -func mapassign2(h *hmap, key *byte, val *byte, p bool) { +func mapassign2(h *Hmap, key *byte, val *byte, p bool) { if (!p) { __go_map_delete(h, key); } else { @@ -46,7 +47,7 @@ /* Initialize a range over a map. */ -func mapiterinit(h *hmap, it *hiter) { +func mapiterinit(h *Hmap, it *hiter) { __go_mapiterinit(h, it); }