This patch from Chris Manghane fixes escape analysis to correctly
handle calls to interface conversion functions that return multiple
results.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu.  Committed to mainline.

Ian
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE     (revision 225715)
+++ gcc/go/gofrontend/MERGE     (working copy)
@@ -1,4 +1,4 @@
-a5122ab435cf40c22b110487eb5f189ee28e77f4
+1b3d945d201bcb1238f15ef154c6e4671e4c6f5c
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: gcc/go/gofrontend/escape.cc
===================================================================
--- gcc/go/gofrontend/escape.cc (revision 225715)
+++ gcc/go/gofrontend/escape.cc (working copy)
@@ -547,6 +547,41 @@ Build_connection_graphs::resolve_var_ref
        expr = expr->type_guard_expression()->expr();
        break;
 
+      case Expression::EXPRESSION_UNSAFE_CONVERSION:
+       {
+         Expression* e = expr->unsafe_conversion_expression()->expr();
+         if (e->call_result_expression() != NULL
+             && e->call_result_expression()->index() == 0)
+           {
+             // a, ok := p.(T) gets lowered into a call to one of the interface
+             // to type conversion functions instead of a type guard 
expression.
+             // We only want to make a connection between a and p, the bool
+             // result should not escape because p escapes.
+             e = e->call_result_expression()->call();
+
+             Named_object* fn =
+               e->call_expression()->fn()->func_expression()->named_object();
+             std::string fn_name = fn->name();
+             if (fn->package() == NULL
+                 && fn->is_function_declaration()
+                 && !fn->func_declaration_value()->asm_name().empty())
+               {
+                 if (fn_name == "ifaceI2E2"
+                     || fn_name == "ifaceI2I2")
+                   e = e->call_expression()->args()->at(0);
+                 else if (fn_name == "ifaceE2I2"
+                          || fn_name == "ifaceI2I2"
+                          || fn_name == "ifaceE2T2P"
+                          || fn_name == "ifaceI2T2P"
+                          || fn_name == "ifaceE2T2"
+                          || fn_name == "ifaceI2T2")
+                   e = e->call_expression()->args()->at(1);
+               }
+           }
+         expr = e;
+       }
+       break;
+
       default:
        done = true;
        break;
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc    (revision 225715)
+++ gcc/go/gofrontend/expressions.cc    (working copy)
@@ -3391,52 +3391,7 @@ Expression::make_cast(Type* type, Expres
   return new Type_conversion_expression(type, val, location);
 }
 
-// An unsafe type conversion, used to pass values to builtin functions.
-
-class Unsafe_type_conversion_expression : public Expression
-{
- public:
-  Unsafe_type_conversion_expression(Type* type, Expression* expr,
-                                   Location location)
-    : Expression(EXPRESSION_UNSAFE_CONVERSION, location),
-      type_(type), expr_(expr)
-  { }
-
- protected:
-  int
-  do_traverse(Traverse* traverse);
-
-  bool
-  do_is_immutable() const;
-
-  Type*
-  do_type()
-  { return this->type_; }
-
-  void
-  do_determine_type(const Type_context*)
-  { this->expr_->determine_type_no_context(); }
-
-  Expression*
-  do_copy()
-  {
-    return new Unsafe_type_conversion_expression(this->type_,
-                                                this->expr_->copy(),
-                                                this->location());
-  }
-
-  Bexpression*
-  do_get_backend(Translate_context*);
-
-  void
-  do_dump_expression(Ast_dump_context*) const;
-
- private:
-  // The type to convert to.
-  Type* type_;
-  // The expression to convert.
-  Expression* expr_;
-};
+// Class Unsafe_type_conversion_expression.
 
 // Traversal.
 
Index: gcc/go/gofrontend/expressions.h
===================================================================
--- gcc/go/gofrontend/expressions.h     (revision 225715)
+++ gcc/go/gofrontend/expressions.h     (working copy)
@@ -32,6 +32,7 @@ class Temporary_reference_expression;
 class Set_and_use_temporary_expression;
 class String_expression;
 class Type_conversion_expression;
+class Unsafe_type_conversion_expression;
 class Unary_expression;
 class Binary_expression;
 class Call_expression;
@@ -571,6 +572,15 @@ class Expression
   conversion_expression()
   { return this->convert<Type_conversion_expression, EXPRESSION_CONVERSION>(); 
}
 
+  // If this is an unsafe conversion expression, return the
+  // Unsafe_type_conversion_expression structure.  Otherwise, return NULL.
+  Unsafe_type_conversion_expression*
+  unsafe_conversion_expression()
+  {
+    return this->convert<Unsafe_type_conversion_expression,
+                        EXPRESSION_UNSAFE_CONVERSION>();
+  }
+
   // Return whether this is the expression nil.
   bool
   is_nil_expression() const
@@ -1505,6 +1515,57 @@ class Type_conversion_expression : publi
   bool may_convert_function_types_;
 };
 
+// An unsafe type conversion, used to pass values to builtin functions.
+
+class Unsafe_type_conversion_expression : public Expression
+{
+ public:
+  Unsafe_type_conversion_expression(Type* type, Expression* expr,
+                                   Location location)
+    : Expression(EXPRESSION_UNSAFE_CONVERSION, location),
+      type_(type), expr_(expr)
+  { }
+
+  Expression*
+  expr() const
+  { return this->expr_; }
+
+ protected:
+  int
+  do_traverse(Traverse* traverse);
+
+  bool
+  do_is_immutable() const;
+
+  Type*
+  do_type()
+  { return this->type_; }
+
+  void
+  do_determine_type(const Type_context*)
+  { this->expr_->determine_type_no_context(); }
+
+  Expression*
+  do_copy()
+  {
+    return new Unsafe_type_conversion_expression(this->type_,
+                                                this->expr_->copy(),
+                                                this->location());
+  }
+
+  Bexpression*
+  do_get_backend(Translate_context*);
+
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
+ private:
+  // The type to convert to.
+  Type* type_;
+  // The expression to convert.
+  Expression* expr_;
+};
+
 // A Unary expression.
 
 class Unary_expression : public Expression
@@ -2024,6 +2085,10 @@ class Call_result_expression : public Ex
   call() const
   { return this->call_; }
 
+  unsigned int
+  index() const
+  { return this->index_; }
+
  protected:
   int
   do_traverse(Traverse*);

Reply via email to