summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-12-05 00:22:13 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-12-05 00:22:13 +0000
commit1ad00fd41a4aa99cd44f2ab4f3780a24448f2935 (patch)
treecbe1685ae7bb4bcb0b4607d751bd180d8c95a87b
parent21efa888a9ccce5048d252b6d422810119092f9e (diff)
downloadgcc-1ad00fd41a4aa99cd44f2ab4f3780a24448f2935.tar.gz
compiler: Check for negative or inverted arguments to make.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@194173 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/go/gofrontend/expressions.cc61
-rw-r--r--gcc/testsuite/go.test/test/fixedbugs/bug273.go3
2 files changed, 45 insertions, 19 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 7a5fcf27c95..3734d9b0b23 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -6623,7 +6623,7 @@ class Builtin_call_expression : public Call_expression
lower_make();
bool
- check_int_value(Expression*);
+ check_int_value(Expression*, bool is_length);
// A pointer back to the general IR structure. This avoids a global
// variable, or passing it around everywhere.
@@ -6897,11 +6897,8 @@ Builtin_call_expression::lower_make()
else
{
len_arg = *parg;
- if (!this->check_int_value(len_arg))
- {
- this->report_error(_("bad size for make"));
- return Expression::make_error(this->location());
- }
+ if (!this->check_int_value(len_arg, true))
+ return Expression::make_error(this->location());
if (len_arg->type()->integer_type() != NULL
&& len_arg->type()->integer_type()->bits() > uintptr_bits)
have_big_args = true;
@@ -6912,11 +6909,23 @@ Builtin_call_expression::lower_make()
if (is_slice && parg != args->end())
{
cap_arg = *parg;
- if (!this->check_int_value(cap_arg))
- {
- this->report_error(_("bad capacity when making slice"));
+ if (!this->check_int_value(cap_arg, false))
+ return Expression::make_error(this->location());
+
+ Numeric_constant nclen;
+ Numeric_constant nccap;
+ unsigned long vlen;
+ unsigned long vcap;
+ if (len_arg->numeric_constant_value(&nclen)
+ && cap_arg->numeric_constant_value(&nccap)
+ && nclen.to_unsigned_long(&vlen) == Numeric_constant::NC_UL_VALID
+ && nccap.to_unsigned_long(&vcap) == Numeric_constant::NC_UL_VALID
+ && vlen > vcap)
+ {
+ this->report_error(_("len larger than cap"));
return Expression::make_error(this->location());
}
+
if (cap_arg->type()->integer_type() != NULL
&& cap_arg->type()->integer_type()->bits() > uintptr_bits)
have_big_args = true;
@@ -6973,20 +6982,36 @@ Builtin_call_expression::lower_make()
// function.
bool
-Builtin_call_expression::check_int_value(Expression* e)
+Builtin_call_expression::check_int_value(Expression* e, bool is_length)
{
- if (e->type()->integer_type() != NULL)
- return true;
-
- // Check for a floating point constant with integer value.
Numeric_constant nc;
- mpz_t ival;
- if (e->numeric_constant_value(&nc) && nc.to_int(&ival))
+ if (e->numeric_constant_value(&nc))
{
- mpz_clear(ival);
- return true;
+ unsigned long v;
+ switch (nc.to_unsigned_long(&v))
+ {
+ case Numeric_constant::NC_UL_VALID:
+ return true;
+ case Numeric_constant::NC_UL_NOTINT:
+ error_at(e->location(), "non-integer %s argument to make",
+ is_length ? "len" : "cap");
+ return false;
+ case Numeric_constant::NC_UL_NEGATIVE:
+ error_at(e->location(), "negative %s argument to make",
+ is_length ? "len" : "cap");
+ return false;
+ case Numeric_constant::NC_UL_BIG:
+ // We don't want to give a compile-time error for a 64-bit
+ // value on a 32-bit target.
+ return true;
+ }
}
+ if (e->type()->integer_type() != NULL)
+ return true;
+
+ error_at(e->location(), "non-integer %s argument to make",
+ is_length ? "len" : "cap");
return false;
}
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug273.go b/gcc/testsuite/go.test/test/fixedbugs/bug273.go
index c5e73e945c9..aabb912b913 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug273.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug273.go
@@ -11,6 +11,7 @@ package main
var bug = false
var minus1 = -1
+var five = 5
var big int64 = 10 | 1<<32
type block [1<<19]byte
@@ -40,7 +41,7 @@ func badcap() {
}
func badcap1() {
- g1 = make([]block, 10, 5)
+ g1 = make([]block, 10, five)
}
func bigcap() {