@@ -390,9 +390,10 @@
space);
space = save_expr(space);
+ tree ref = build_fold_indirect_ref_loc(location, space);
+ TREE_THIS_NOTRAP(ref) = 1;
tree set = fold_build2_loc(location, MODIFY_EXPR, void_type_node,
- build_fold_indirect_ref_loc(location, space),
- rhs_tree);
+ ref, rhs_tree);
elt->value = fold_convert_loc(location, TREE_TYPE(field), space);
@@ -3919,15 +3920,8 @@
expr,
fold_convert(TREE_TYPE(expr),
null_pointer_node));
- // FIXME: This should be a different error message.
- static tree bad_index_fndecl;
- tree crash = Gogo::call_builtin(&bad_index_fndecl,
- loc,
- "__go_bad_index",
- 0,
- void_type_node);
- TREE_NOTHROW(bad_index_fndecl) = 0;
- TREE_THIS_VOLATILE(bad_index_fndecl) = 1;
+ tree crash = Gogo::runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE,
+ loc);
expr = fold_build2_loc(loc, COMPOUND_EXPR, TREE_TYPE(expr),
build3(COND_EXPR, void_type_node,
compare, crash, NULL_TREE),
@@ -8860,14 +8854,14 @@
boolean_type_node, start_tree,
length_tree));
- static tree bad_index_fndecl;
- tree crash = Gogo::call_builtin(&bad_index_fndecl,
- loc,
- "__go_bad_index",
- 0,
- void_type_node);
- TREE_NOTHROW(bad_index_fndecl) = 0;
- TREE_THIS_VOLATILE(bad_index_fndecl) = 1;
+ int code = (array_type->length() != NULL
+ ? (this->end_ == NULL
+ ? RUNTIME_ERROR_ARRAY_INDEX_OUT_OF_BOUNDS
+ : RUNTIME_ERROR_ARRAY_SLICE_OUT_OF_BOUNDS)
+ : (this->end_ == NULL
+ ? RUNTIME_ERROR_SLICE_INDEX_OUT_OF_BOUNDS
+ : RUNTIME_ERROR_SLICE_SLICE_OUT_OF_BOUNDS));
+ tree crash = Gogo::runtime_error(code, loc);
if (this->end_ == NULL)
{
@@ -9164,15 +9158,10 @@
start_tree = fold_convert_loc(loc, length_type, start_tree);
- // FIXME: Duplicates Array_index::do_get_tree.
- static tree bad_index_fndecl;
- tree crash = Gogo::call_builtin(&bad_index_fndecl,
- this->location(),
- "__go_bad_index",
- 0,
- void_type_node);
- TREE_NOTHROW(bad_index_fndecl) = 0;
- TREE_THIS_VOLATILE(bad_index_fndecl) = 1;
+ int code = (this->end_ == NULL
+ ? RUNTIME_ERROR_STRING_INDEX_OUT_OF_BOUNDS
+ : RUNTIME_ERROR_STRING_SLICE_OUT_OF_BOUNDS);
+ tree crash = Gogo::runtime_error(code, loc);
if (this->end_ == NULL)
{
@@ -10610,8 +10599,9 @@
space = save_expr(space);
tree s = fold_convert(build_pointer_type(TREE_TYPE(values)), space);
- set = build2(MODIFY_EXPR, void_type_node,
- build_fold_indirect_ref(s), values);
+ tree ref = build_fold_indirect_ref_loc(this->location(), s);
+ TREE_THIS_NOTRAP(ref) = 1;
+ set = build2(MODIFY_EXPR, void_type_node, ref, values);
}
// Build a constructor for the open array.
@@ -11529,10 +11519,10 @@
expr_size, this->location());
space = fold_convert(build_pointer_type(TREE_TYPE(expr_tree)), space);
space = save_expr(space);
+ tree ref = build_fold_indirect_ref_loc(this->location(), space);
+ TREE_THIS_NOTRAP(ref) = 1;
tree ret = build2(COMPOUND_EXPR, TREE_TYPE(space),
- build2(MODIFY_EXPR, void_type_node,
- build_fold_indirect_ref(space),
- expr_tree),
+ build2(MODIFY_EXPR, void_type_node, ref, expr_tree),
space);
SET_EXPR_LOCATION(ret, this->location());
return ret;
@@ -122,6 +122,9 @@
/* The builtin math functions should not set errno. */
flag_errno_math = 0;
+ /* By default assume that floating point math does not trap. */
+ flag_trapping_math = 0;
+
/* We default to always showing a column number. */
flag_show_column = 1;
@@ -136,6 +139,7 @@
/* Exceptions are used to handle recovering from panics. */
flag_exceptions = 1;
+ flag_non_call_exceptions = 1;
using_eh_for_cleanups ();
return CL_Go;
@@ -908,6 +908,7 @@
{
gcc_assert(TREE_CODE(ret) == INDIRECT_REF);
ret = build_fold_indirect_ref(TREE_OPERAND(ret, 0));
+ TREE_THIS_NOTRAP(ret) = 1;
}
return ret;
}
@@ -1082,6 +1083,7 @@
space = save_expr(space);
space = fold_convert_loc(loc, result_type, space);
tree spaceref = build_fold_indirect_ref_loc(loc, space);
+ TREE_THIS_NOTRAP(spaceref) = 1;
tree set = fold_build2_loc(loc, MODIFY_EXPR, void_type_node,
spaceref, subinit);
init = fold_build2_loc(loc, COMPOUND_EXPR, TREE_TYPE(space),
@@ -1153,6 +1155,7 @@
{
gcc_assert(POINTER_TYPE_P(TREE_TYPE(ret)));
ret = build_fold_indirect_ref(ret);
+ TREE_THIS_NOTRAP(ret) = 1;
}
this->tree_ = ret;
@@ -1399,21 +1402,24 @@
val_type = TREE_TYPE(TREE_TYPE(var_decl));
}
gcc_assert(TREE_CODE(var_decl) == VAR_DECL);
+ source_location loc = DECL_SOURCE_LOCATION(var_decl);
std::string name = IDENTIFIER_POINTER(DECL_NAME(var_decl));
name += ".pointer";
tree id = get_identifier_from_string(name);
- tree parm_decl = build_decl(DECL_SOURCE_LOCATION(var_decl), PARM_DECL, id,
- build_pointer_type(val_type));
+ tree parm_decl = build_decl(loc, PARM_DECL, id, build_pointer_type(val_type));
DECL_CONTEXT(parm_decl) = current_function_decl;
DECL_ARG_TYPE(parm_decl) = TREE_TYPE(parm_decl);
gcc_assert(DECL_INITIAL(var_decl) == NULL_TREE);
// The receiver might be passed as a null pointer.
- tree check = build2(NE_EXPR, boolean_type_node, parm_decl,
- fold_convert(TREE_TYPE(parm_decl), null_pointer_node));
- tree ind = build_fold_indirect_ref(parm_decl);
+ tree check = fold_build2_loc(loc, NE_EXPR, boolean_type_node, parm_decl,
+ fold_convert_loc(loc, TREE_TYPE(parm_decl),
+ null_pointer_node));
+ tree ind = build_fold_indirect_ref_loc(loc, parm_decl);
+ TREE_THIS_NOTRAP(ind) = 1;
tree zero_init = no->var_value()->type()->get_init_tree(gogo, false);
- tree init = build3(COND_EXPR, TREE_TYPE(ind), check, ind, zero_init);
+ tree init = fold_build3_loc(loc, COND_EXPR, TREE_TYPE(ind),
+ check, ind, zero_init);
if (is_in_heap)
{
@@ -1422,11 +1428,20 @@
no->location());
space = save_expr(space);
space = fold_convert(build_pointer_type(val_type), space);
- init = build2(COMPOUND_EXPR, TREE_TYPE(space),
- build2(MODIFY_EXPR, void_type_node,
- build_fold_indirect_ref(space),
- build_fold_indirect_ref(parm_decl)),
- space);
+ tree spaceref = build_fold_indirect_ref_loc(no->location(), space);
+ TREE_THIS_NOTRAP(spaceref) = 1;
+ tree check = fold_build2_loc(loc, NE_EXPR, boolean_type_node,
+ parm_decl,
+ fold_convert_loc(loc, TREE_TYPE(parm_decl),
+ null_pointer_node));
+ tree parmref = build_fold_indirect_ref_loc(no->location(), parm_decl);
+ TREE_THIS_NOTRAP(parmref) = 1;
+ tree set = fold_build2_loc(loc, MODIFY_EXPR, void_type_node,
+ spaceref, parmref);
+ init = fold_build2_loc(loc, COMPOUND_EXPR, TREE_TYPE(space),
+ build3(COND_EXPR, void_type_node,
+ check, set, NULL_TREE),
+ space);
}
DECL_INITIAL(var_decl) = init;
@@ -1463,10 +1478,10 @@
tree space = gogo->allocate_memory(no->var_value()->type(), size, loc);
space = save_expr(space);
space = fold_convert(TREE_TYPE(var_decl), space);
+ tree spaceref = build_fold_indirect_ref_loc(loc, space);
+ TREE_THIS_NOTRAP(spaceref) = 1;
tree init = build2(COMPOUND_EXPR, TREE_TYPE(space),
- build2(MODIFY_EXPR, void_type_node,
- build_fold_indirect_ref(space),
- parm_decl),
+ build2(MODIFY_EXPR, void_type_node, spaceref, parm_decl),
space);
DECL_INITIAL(var_decl) = init;
@@ -4109,6 +4124,25 @@
return ret;
}
+// Build a call to the runtime error function.
+
+tree
+Gogo::runtime_error(int code, source_location location)
+{
+ static tree runtime_error_fndecl;
+ tree ret = Gogo::call_builtin(&runtime_error_fndecl,
+ location,
+ "__go_runtime_error",
+ 1,
+ void_type_node,
+ integer_type_node,
+ build_int_cst(integer_type_node, code));
+ // The runtime error function panics and does not return.
+ TREE_NOTHROW(runtime_error_fndecl) = 0;
+ TREE_THIS_VOLATILE(runtime_error_fndecl) = 1;
+ return ret;
+}
+
// Send VAL on CHANNEL. If BLOCKING is true, the resulting tree has a
// void type. If BLOCKING is false, the resulting tree has a boolean
// type, and it will evaluate as true if the value was sent. If
@@ -410,6 +410,10 @@
call_builtin(tree* pdecl, source_location, const char* name, int nargs,
tree rettype, ...);
+ // Build a call to the runtime error function.
+ static tree
+ runtime_error(int code, source_location);
+
// Build a builtin struct with a list of fields.
static tree
builtin_struct(tree* ptype, const char* struct_name, tree struct_type,
@@ -2556,6 +2560,45 @@
tree block_tree_;
};
+// Runtime error codes. These must match the values in
+// libgo/runtime/go-runtime-error.c.
+
+// Slice index out of bounds: negative or larger than the length of
+// the slice.
+static const int RUNTIME_ERROR_SLICE_INDEX_OUT_OF_BOUNDS = 0;
+
+// Array index out of bounds.
+static const int RUNTIME_ERROR_ARRAY_INDEX_OUT_OF_BOUNDS = 1;
+
+// String index out of bounds.
+static const int RUNTIME_ERROR_STRING_INDEX_OUT_OF_BOUNDS = 2;
+
+// Slice slice out of bounds: negative or larger than the length of
+// the slice or high bound less than low bound.
+static const int RUNTIME_ERROR_SLICE_SLICE_OUT_OF_BOUNDS = 3;
+
+// Array slice out of bounds.
+static const int RUNTIME_ERROR_ARRAY_SLICE_OUT_OF_BOUNDS = 4;
+
+// String slice out of bounds.
+static const int RUNTIME_ERROR_STRING_SLICE_OUT_OF_BOUNDS = 5;
+
+// Dereference of nil pointer. This is used when there is a
+// dereference of a pointer to a very large struct or array, to ensure
+// that a gigantic array is not used a proxy to access random memory
+// locations.
+static const int RUNTIME_ERROR_NIL_DEREFERENCE = 6;
+
+// Slice length or capacity out of bounds in make: negative or
+// overflow or length greater than capacity.
+static const int RUNTIME_ERROR_MAKE_SLICE_OUT_OF_BOUNDS = 7;
+
+// Map capacity out of bounds in make: negative or overflow.
+static const int RUNTIME_ERROR_MAKE_MAP_OUT_OF_BOUNDS = 8;
+
+// Channel capacity out of bounds in make: negative or overflow.
+static const int RUNTIME_ERROR_MAKE_CHAN_OUT_OF_BOUNDS = 9;
+
// This is used by some of the langhooks.
extern Gogo* go_get_gogo();
@@ -3751,14 +3751,8 @@
if (bad_index != NULL_TREE && bad_index != boolean_false_node)
{
- static tree bad_index_fndecl;
- tree crash = Gogo::call_builtin(&bad_index_fndecl,
- location,
- "__go_bad_makeslice",
- 0,
- void_type_node);
- TREE_NOTHROW(bad_index_fndecl) = 0;
- TREE_THIS_VOLATILE(bad_index_fndecl) = 1;
+ tree crash = Gogo::runtime_error(RUNTIME_ERROR_MAKE_SLICE_OUT_OF_BOUNDS,
+ location);
space = build2(COMPOUND_EXPR, TREE_TYPE(space),
build3(COND_EXPR, void_type_node,
bad_index, crash, NULL_TREE),
@@ -4160,16 +4154,8 @@
return ret;
else
{
- // FIXME: Wrong message.
- static tree bad_index_fndecl;
- tree crash = Gogo::call_builtin(&bad_index_fndecl,
- location,
- "__go_bad_index",
- 0,
- void_type_node);
- TREE_NOTHROW(bad_index_fndecl) = 0;
- TREE_THIS_VOLATILE(bad_index_fndecl) = 1;
-
+ tree crash = Gogo::runtime_error(RUNTIME_ERROR_MAKE_MAP_OUT_OF_BOUNDS,
+ location);
return build2(COMPOUND_EXPR, TREE_TYPE(ret),
build3(COND_EXPR, void_type_node,
bad_index, crash, NULL_TREE),
@@ -4367,16 +4353,8 @@
return ret;
else
{
- // FIXME: Wrong message.
- static tree bad_index_fndecl;
- tree crash = Gogo::call_builtin(&bad_index_fndecl,
- location,
- "__go_bad_index",
- 0,
- void_type_node);
- TREE_NOTHROW(bad_index_fndecl) = 0;
- TREE_THIS_VOLATILE(bad_index_fndecl) = 1;
-
+ tree crash = Gogo::runtime_error(RUNTIME_ERROR_MAKE_CHAN_OUT_OF_BOUNDS,
+ location);
return build2(COMPOUND_EXPR, TREE_TYPE(ret),
build3(COND_EXPR, void_type_node,
bad_index, crash, NULL_TREE),
@@ -294,8 +294,6 @@
runtime_files = \
runtime/go-assert.c \
runtime/go-assert-interface.c \
- runtime/go-bad-index.c \
- runtime/go-bad-makeslice.c \
runtime/go-byte-array-to-string.c \
runtime/go-breakpoint.c \
runtime/go-caller.c \
@@ -339,6 +337,7 @@
runtime/go-reflect-chan.c \
runtime/go-reflect-map.c \
runtime/go-rune.c \
+ runtime/go-runtime-error.c \
runtime/go-sched.c \
runtime/go-select.c \
runtime/go-semacquire.c \
@@ -1,15 +0,0 @@
-/* go-bad-index.c -- bad array/string index error in Go.
-
- Copyright 2009 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include "go-panic.h"
-
-extern void __go_bad_index () __attribute__ ((noreturn));
-
-void
-__go_bad_index ()
-{
- __go_panic_msg ("index or slice out of range");
-}
@@ -1,15 +0,0 @@
-/* go-bad-makeslice.c -- bad call to make for a slice in Go.
-
- Copyright 2010 The Go Authors. All rights reserved.
- Use of this source code is governed by a BSD-style
- license that can be found in the LICENSE file. */
-
-#include "go-panic.h"
-
-extern void __go_bad_makeslice () __attribute__ ((noreturn));
-
-void
-__go_bad_makeslice ()
-{
- __go_panic_msg ("slice len or cap out of range");
-}
@@ -0,0 +1,84 @@
+/* go-runtime-error.c -- Go runtime error.
+
+ Copyright 2010 The Go Authors. All rights reserved.
+ Use of this source code is governed by a BSD-style
+ license that can be found in the LICENSE file. */
+
+#include "go-panic.h"
+
+/* The compiler generates calls to this function. This enum values
+ are known to the compiler and used by compiled code. Any change
+ here must be reflected in the compiler. */
+
+enum
+{
+ /* Slice index out of bounds: negative or larger than the length of
+ the slice. */
+ SLICE_INDEX_OUT_OF_BOUNDS = 0,
+
+ /* Array index out of bounds. */
+ ARRAY_INDEX_OUT_OF_BOUNDS = 1,
+
+ /* String index out of bounds. */
+ STRING_INDEX_OUT_OF_BOUNDS = 2,
+
+ /* Slice slice out of bounds: negative or larger than the length of
+ the slice or high bound less than low bound. */
+ SLICE_SLICE_OUT_OF_BOUNDS = 3,
+
+ /* Array slice out of bounds. */
+ ARRAY_SLICE_OUT_OF_BOUNDS = 4,
+
+ /* String slice out of bounds. */
+ STRING_SLICE_OUT_OF_BOUNDS = 5,
+
+ /* Dereference of nil pointer. This is used when there is a
+ dereference of a pointer to a very large struct or array, to
+ ensure that a gigantic array is not used a proxy to access random
+ memory locations. */
+ NIL_DEREFERENCE = 6,
+
+ /* Slice length or capacity out of bounds in make: negative or
+ overflow or length greater than capacity. */
+ MAKE_SLICE_OUT_OF_BOUNDS = 7,
+
+ /* Map capacity out of bounds in make: negative or overflow. */
+ MAKE_MAP_OUT_OF_BOUNDS = 8,
+
+ /* Channel capacity out of bounds in make: negative or overflow. */
+ MAKE_CHAN_OUT_OF_BOUNDS = 9
+};
+
+extern void __go_runtime_error () __attribute__ ((noreturn));
+
+void
+__go_runtime_error (int i)
+{
+ switch (i)
+ {
+ case SLICE_INDEX_OUT_OF_BOUNDS:
+ case ARRAY_INDEX_OUT_OF_BOUNDS:
+ case STRING_INDEX_OUT_OF_BOUNDS:
+ __go_panic_msg ("index out of range");
+
+ case SLICE_SLICE_OUT_OF_BOUNDS:
+ case ARRAY_SLICE_OUT_OF_BOUNDS:
+ case STRING_SLICE_OUT_OF_BOUNDS:
+ __go_panic_msg ("slice bounds out of range");
+
+ case NIL_DEREFERENCE:
+ __go_panic_msg ("nil pointer dereference");
+
+ case MAKE_SLICE_OUT_OF_BOUNDS:
+ __go_panic_msg ("make slice len or cap out of range");
+
+ case MAKE_MAP_OUT_OF_BOUNDS:
+ __go_panic_msg ("make map len out of range");
+
+ case MAKE_CHAN_OUT_OF_BOUNDS:
+ __go_panic_msg ("make chan len out of range");
+
+ default:
+ __go_panic_msg ("unknown runtime error");
+ }
+}
@@ -115,7 +115,7 @@
#ifdef SIGFPE
case SIGFPE:
- msg = "division by zero or floating point error";
+ msg = "integer divide by zero or floating point error";
break;
#endif