diff mbox

Go patch committed: Support nil maps

Message ID mcr8vph7ppb.fsf@coign.corp.google.com
State New
Headers show

Commit Message

Ian Lance Taylor Sept. 21, 2011, 5:47 p.m. UTC
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 mbox

Patch

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);
 }