aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2012-09-21 17:48:30 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2012-09-21 17:48:30 +0000
commit211993b35244486d8b496344a94f1bd109b2e7d2 (patch)
tree62e004ec784224e59aaae5e4b46ebea79d45fd2b /gcc
parent7f0919843b3218d66300278ee169bf4707dd33ea (diff)
downloadgcc-211993b35244486d8b496344a94f1bd109b2e7d2.zip
gcc-211993b35244486d8b496344a94f1bd109b2e7d2.tar.gz
gcc-211993b35244486d8b496344a94f1bd109b2e7d2.tar.bz2
compiler: len(<-c) is not a constant.
From-SVN: r191616
Diffstat (limited to 'gcc')
-rw-r--r--gcc/go/gofrontend/expressions.cc95
1 files changed, 47 insertions, 48 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index ea24849..922b7df 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -6679,38 +6679,6 @@ Builtin_call_expression::do_set_recover_arg(Expression* arg)
this->set_args(new_args);
}
-// A traversal class which looks for a call expression.
-
-class Find_call_expression : public Traverse
-{
- public:
- Find_call_expression()
- : Traverse(traverse_expressions),
- found_(false)
- { }
-
- int
- expression(Expression**);
-
- bool
- found()
- { return this->found_; }
-
- private:
- bool found_;
-};
-
-int
-Find_call_expression::expression(Expression** pexpr)
-{
- if ((*pexpr)->call_expression() != NULL)
- {
- this->found_ = true;
- return TRAVERSE_EXIT;
- }
- return TRAVERSE_CONTINUE;
-}
-
// Lower a builtin call expression. This turns new and make into
// specific expressions. We also convert to a constant if we can.
@@ -6731,20 +6699,6 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
if (this->is_constant())
{
- // We can only lower len and cap if there are no function calls
- // in the arguments. Otherwise we have to make the call.
- if (this->code_ == BUILTIN_LEN || this->code_ == BUILTIN_CAP)
- {
- Expression* arg = this->one_arg();
- if (arg != NULL && !arg->is_constant())
- {
- Find_call_expression find_call;
- Expression::traverse(&arg, &find_call);
- if (find_call.found())
- return this;
- }
- }
-
Numeric_constant nc;
if (this->numeric_constant_value(&nc))
return nc.expression(loc);
@@ -7061,8 +7015,42 @@ Builtin_call_expression::one_arg() const
return args->front();
}
-// Return whether this is constant: len of a string, or len or cap of
-// a fixed array, or unsafe.Sizeof, unsafe.Offsetof, unsafe.Alignof.
+// A traversal class which looks for a call or receive expression.
+
+class Find_call_expression : public Traverse
+{
+ public:
+ Find_call_expression()
+ : Traverse(traverse_expressions),
+ found_(false)
+ { }
+
+ int
+ expression(Expression**);
+
+ bool
+ found()
+ { return this->found_; }
+
+ private:
+ bool found_;
+};
+
+int
+Find_call_expression::expression(Expression** pexpr)
+{
+ if ((*pexpr)->call_expression() != NULL
+ || (*pexpr)->receive_expression() != NULL)
+ {
+ this->found_ = true;
+ return TRAVERSE_EXIT;
+ }
+ return TRAVERSE_CONTINUE;
+}
+
+// Return whether this is constant: len of a string constant, or len
+// or cap of an array, or unsafe.Sizeof, unsafe.Offsetof,
+// unsafe.Alignof.
bool
Builtin_call_expression::do_is_constant() const
@@ -7085,6 +7073,17 @@ Builtin_call_expression::do_is_constant() const
&& !arg_type->points_to()->is_slice_type())
arg_type = arg_type->points_to();
+ // The len and cap functions are only constant if there are no
+ // function calls or channel operations in the arguments.
+ // Otherwise we have to make the call.
+ if (!arg->is_constant())
+ {
+ Find_call_expression find_call;
+ Expression::traverse(&arg, &find_call);
+ if (find_call.found())
+ return false;
+ }
+
if (arg_type->array_type() != NULL
&& arg_type->array_type()->length() != NULL)
return true;