[gccgo] Don't lower len/cap of function call

Submitted by Ian Taylor on Sept. 9, 2010, 6:21 a.m.

Details

Message ID mcrk4mve8tf.fsf@google.com
State New
Headers show

Commit Message

Ian Taylor Sept. 9, 2010, 6:21 a.m.
If len or cap is called with a function call as an argument, then the
function call has to be evaluated.  This is true even if the result is
known at compile time, as when the function returns an array.  This
patch makes sure that the function is called.  Committed to gccgo
branch.

Ian

Patch hide | download patch | download mbox

diff -r 8151188f1b79 go/expressions.cc
--- a/go/expressions.cc	Wed Sep 08 22:46:45 2010 -0700
+++ b/go/expressions.cc	Wed Sep 08 23:19:22 2010 -0700
@@ -6346,6 +6346,38 @@ 
   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.
 
@@ -6404,6 +6436,20 @@ 
     }
   else 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->is_constant())
+	    {
+	      Find_call_expression find_call;
+	      Expression::traverse(&arg, &find_call);
+	      if (find_call.found())
+		return this;
+	    }
+	}
+
       mpz_t ival;
       mpz_init(ival);
       Type* type;