OSDN Git Service

compiler: len(<-c) is not a constant.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 21 Sep 2012 17:48:42 +0000 (17:48 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 21 Sep 2012 17:48:42 +0000 (17:48 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_7-branch@191617 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/go/gofrontend/expressions.cc

index cfc775d..6ab90dd 100644 (file)
@@ -6685,38 +6685,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.
 
@@ -6737,20 +6705,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);
@@ -7067,8 +7021,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
@@ -7091,6 +7079,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;