1
# DP: escape: Analyze multiple result type assertions.
3
For multi-result type assertions, the object being converted is hidden
4
behind unsafe conversions and calls to runtime methods. This change
5
allows the analysis to make edges between the result of the assertion
6
and the object being asserted.
8
Index: b/src/gcc/go/gofrontend/expressions.h
9
===================================================================
10
--- a/src/gcc/go/gofrontend/expressions.h
11
+++ b/src/gcc/go/gofrontend/expressions.h
12
@@ -32,6 +32,7 @@ class Temporary_reference_expression;
13
class Set_and_use_temporary_expression;
14
class String_expression;
15
class Type_conversion_expression;
16
+class Unsafe_type_conversion_expression;
17
class Unary_expression;
18
class Binary_expression;
19
class Call_expression;
20
@@ -571,6 +572,15 @@ class Expression
21
conversion_expression()
22
{ return this->convert<Type_conversion_expression, EXPRESSION_CONVERSION>(); }
24
+ // If this is an unsafe conversion expression, return the
25
+ // Unsafe_type_conversion_expression structure. Otherwise, return NULL.
26
+ Unsafe_type_conversion_expression*
27
+ unsafe_conversion_expression()
29
+ return this->convert<Unsafe_type_conversion_expression,
30
+ EXPRESSION_UNSAFE_CONVERSION>();
33
// Return whether this is the expression nil.
35
is_nil_expression() const
36
@@ -1505,6 +1515,57 @@ class Type_conversion_expression : publi
37
bool may_convert_function_types_;
40
+// An unsafe type conversion, used to pass values to builtin functions.
42
+class Unsafe_type_conversion_expression : public Expression
45
+ Unsafe_type_conversion_expression(Type* type, Expression* expr,
47
+ : Expression(EXPRESSION_UNSAFE_CONVERSION, location),
48
+ type_(type), expr_(expr)
53
+ { return this->expr_; }
57
+ do_traverse(Traverse* traverse);
60
+ do_is_immutable() const;
64
+ { return this->type_; }
67
+ do_determine_type(const Type_context*)
68
+ { this->expr_->determine_type_no_context(); }
73
+ return new Unsafe_type_conversion_expression(this->type_,
74
+ this->expr_->copy(),
79
+ do_get_backend(Translate_context*);
82
+ do_dump_expression(Ast_dump_context*) const;
85
+ // The type to convert to.
87
+ // The expression to convert.
91
// A Unary expression.
93
class Unary_expression : public Expression
94
@@ -2024,6 +2085,10 @@ class Call_result_expression : public Ex
96
{ return this->call_; }
100
+ { return this->index_; }
104
do_traverse(Traverse*);
105
Index: b/src/gcc/go/gofrontend/escape.cc
106
===================================================================
107
--- a/src/gcc/go/gofrontend/escape.cc
108
+++ b/src/gcc/go/gofrontend/escape.cc
109
@@ -547,6 +547,41 @@ Build_connection_graphs::resolve_var_ref
110
expr = expr->type_guard_expression()->expr();
113
+ case Expression::EXPRESSION_UNSAFE_CONVERSION:
115
+ Expression* e = expr->unsafe_conversion_expression()->expr();
116
+ if (e->call_result_expression() != NULL
117
+ && e->call_result_expression()->index() == 0)
119
+ // a, ok := p.(T) gets lowered into a call to one of the interface
120
+ // to type conversion functions instead of a type guard expression.
121
+ // We only want to make a connection between a and p, the bool
122
+ // result should not escape because p escapes.
123
+ e = e->call_result_expression()->call();
126
+ e->call_expression()->fn()->func_expression()->named_object();
127
+ std::string fn_name = fn->name();
128
+ if (fn->package() == NULL
129
+ && fn->is_function_declaration()
130
+ && !fn->func_declaration_value()->asm_name().empty())
132
+ if (fn_name == "ifaceI2E2"
133
+ || fn_name == "ifaceI2I2")
134
+ e = e->call_expression()->args()->at(0);
135
+ else if (fn_name == "ifaceE2I2"
136
+ || fn_name == "ifaceI2I2"
137
+ || fn_name == "ifaceE2T2P"
138
+ || fn_name == "ifaceI2T2P"
139
+ || fn_name == "ifaceE2T2"
140
+ || fn_name == "ifaceI2T2")
141
+ e = e->call_expression()->args()->at(1);
151
Index: b/src/gcc/go/gofrontend/expressions.cc
152
===================================================================
153
--- a/src/gcc/go/gofrontend/expressions.cc
154
+++ b/src/gcc/go/gofrontend/expressions.cc
155
@@ -3391,52 +3391,7 @@ Expression::make_cast(Type* type, Expres
156
return new Type_conversion_expression(type, val, location);
159
-// An unsafe type conversion, used to pass values to builtin functions.
161
-class Unsafe_type_conversion_expression : public Expression
164
- Unsafe_type_conversion_expression(Type* type, Expression* expr,
166
- : Expression(EXPRESSION_UNSAFE_CONVERSION, location),
167
- type_(type), expr_(expr)
172
- do_traverse(Traverse* traverse);
175
- do_is_immutable() const;
179
- { return this->type_; }
182
- do_determine_type(const Type_context*)
183
- { this->expr_->determine_type_no_context(); }
188
- return new Unsafe_type_conversion_expression(this->type_,
189
- this->expr_->copy(),
194
- do_get_backend(Translate_context*);
197
- do_dump_expression(Ast_dump_context*) const;
200
- // The type to convert to.
202
- // The expression to convert.
205
+// Class Unsafe_type_conversion_expression.