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

login
register
mail settings
Submitter Ian Taylor
Date Sept. 9, 2010, 6:21 a.m.
Message ID <mcrk4mve8tf.fsf@google.com>
Download mbox | patch
Permalink /patch/64257/
State New
Headers show

Comments

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

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;