diff mbox

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

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

Commit Message

Ian Lance Taylor Sept. 9, 2010, 6:21 a.m. UTC
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
diff mbox

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;