summaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/expressions.cc
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2015-04-17 17:10:12 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2015-04-17 17:10:12 +0000
commitda244e597db59cc4fa58a8427ab1027dca2bbf45 (patch)
treed1dced696fcc3d7e6802d825c7ddf09b50b62bda /gcc/go/gofrontend/expressions.cc
parent868af6b6b6980d2e7008d2c6676e02166b275763 (diff)
downloadgcc-da244e597db59cc4fa58a8427ab1027dca2bbf45.tar.gz
compiler: Escape analysis.
By Chris Manghane. Comprises three changes to gofrontend repository: compiler: Add escape information to export data. compiler: Stack-allocate non-escaping variables. This change allows variables initialized through make or new to be allocated on the stack via a temporary variable if they do not escape their function. It also improves the analysis to consider situations where variables escape in the standard library and go testsuite such as: *nested composite literals and composite literal arguments *method receivers always escaping *escape via statements in closures referring to enclosing variables *escape via calls with multiple return results compiler: Basic escape analysis for the go frontend. This is an implementation of the algorithm described in "Escape Analysis in Java" by Choi et. al. It relies on dataflow information to discover variable references to one another. Handles assignments to closures and association between closures variables and the variables of the enclosing scope. Dataflow analysis does not discover references through range statements e.g. for _, v := range a will not recognize that all values of v are references to a. * Make-lang.in (GO_OBJS): Add go/escape.o. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@222188 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/go/gofrontend/expressions.cc')
-rw-r--r--gcc/go/gofrontend/expressions.cc786
1 files changed, 119 insertions, 667 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 40d9aa7726b..53edb99a2db 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -3017,100 +3017,7 @@ Expression::make_iota()
return &iota_expression;
}
-// A type conversion expression.
-
-class Type_conversion_expression : public Expression
-{
- public:
- Type_conversion_expression(Type* type, Expression* expr,
- Location location)
- : Expression(EXPRESSION_CONVERSION, location),
- type_(type), expr_(expr), may_convert_function_types_(false)
- { }
-
- // Return the type to which we are converting.
- Type*
- type() const
- { return this->type_; }
-
- // Return the expression which we are converting.
- Expression*
- expr() const
- { return this->expr_; }
-
- // Permit converting from one function type to another. This is
- // used internally for method expressions.
- void
- set_may_convert_function_types()
- {
- this->may_convert_function_types_ = true;
- }
-
- // Import a type conversion expression.
- static Expression*
- do_import(Import*);
-
- protected:
- int
- do_traverse(Traverse* traverse);
-
- Expression*
- do_lower(Gogo*, Named_object*, Statement_inserter*, int);
-
- Expression*
- do_flatten(Gogo*, Named_object*, Statement_inserter*);
-
- bool
- do_is_constant() const;
-
- bool
- do_is_immutable() const;
-
- bool
- do_numeric_constant_value(Numeric_constant*) const;
-
- bool
- do_string_constant_value(std::string*) const;
-
- Type*
- do_type()
- { return this->type_; }
-
- void
- do_determine_type(const Type_context*)
- {
- Type_context subcontext(this->type_, false);
- this->expr_->determine_type(&subcontext);
- }
-
- void
- do_check_types(Gogo*);
-
- Expression*
- do_copy()
- {
- return new Type_conversion_expression(this->type_, this->expr_->copy(),
- this->location());
- }
-
- Bexpression*
- do_get_backend(Translate_context* context);
-
- void
- do_export(Export*) const;
-
- void
- do_dump_expression(Ast_dump_context*) const;
-
- private:
- // The type to convert to.
- Type* type_;
- // The expression to convert.
- Expression* expr_;
- // True if this is permitted to convert function types. This is
- // used internally for method expressions.
- bool may_convert_function_types_;
-};
+// Class Type_conversion_expression.
// Traversal.
@@ -3300,6 +3207,15 @@ Type_conversion_expression::do_string_constant_value(std::string* val) const
return false;
}
+// Determine the resulting type of the conversion.
+
+void
+Type_conversion_expression::do_determine_type(const Type_context*)
+{
+ Type_context subcontext(this->type_, false);
+ this->expr_->determine_type(&subcontext);
+}
+
// Check that types are convertible.
void
@@ -3750,6 +3666,19 @@ Unary_expression::do_flatten(Gogo* gogo, Named_object*,
}
}
+ if (this->op_ == OPERATOR_AND)
+ {
+ if (this->expr_->var_expression() != NULL)
+ {
+ Named_object* var = this->expr_->var_expression()->named_object();
+ if (var->is_variable())
+ this->escapes_ = var->var_value()->escapes();
+ if (var->is_result_variable())
+ this->escapes_ = var->result_var_value()->escapes();
+ }
+ this->expr_->address_taken(this->escapes_);
+ }
+
if (this->create_temp_ && !this->expr_->is_variable())
{
Temporary_statement* temp =
@@ -4070,10 +3999,7 @@ Unary_expression::do_check_types(Gogo*)
}
}
else
- {
- this->expr_->address_taken(this->escapes_);
- this->expr_->issue_nil_check();
- }
+ this->expr_->issue_nil_check();
break;
case OPERATOR_MULT:
@@ -6360,13 +6286,15 @@ Bound_method_expression::create_thunk(Gogo* gogo, const Method* method,
Function_type* new_fntype = orig_fntype->copy_with_names();
- Named_object* new_no = gogo->start_function(Gogo::thunk_name(), new_fntype,
+ std::string thunk_name = Gogo::thunk_name();
+ Named_object* new_no = gogo->start_function(thunk_name, new_fntype,
false, loc);
Variable* cvar = new Variable(closure_type, NULL, false, false, false, loc);
cvar->set_is_used();
cvar->set_is_closure();
- Named_object* cp = Named_object::make_variable("$closure", NULL, cvar);
+ Named_object* cp = Named_object::make_variable("$closure" + thunk_name,
+ NULL, cvar);
new_no->func_value()->set_closure_var(cp);
gogo->start_block(loc);
@@ -8080,7 +8008,9 @@ Builtin_call_expression::do_copy()
{
Call_expression* bce =
new Builtin_call_expression(this->gogo_, this->fn()->copy(),
- this->args()->copy(),
+ (this->args() == NULL
+ ? NULL
+ : this->args()->copy()),
this->is_varargs(),
this->location());
@@ -9505,52 +9435,7 @@ Expression::make_call(Expression* fn, Expression_list* args, bool is_varargs,
return new Call_expression(fn, args, is_varargs, location);
}
-// A single result from a call which returns multiple results.
-
-class Call_result_expression : public Expression
-{
- public:
- Call_result_expression(Call_expression* call, unsigned int index)
- : Expression(EXPRESSION_CALL_RESULT, call->location()),
- call_(call), index_(index)
- { }
-
- protected:
- int
- do_traverse(Traverse*);
-
- Type*
- do_type();
-
- void
- do_determine_type(const Type_context*);
-
- void
- do_check_types(Gogo*);
-
- Expression*
- do_copy()
- {
- return new Call_result_expression(this->call_->call_expression(),
- this->index_);
- }
-
- bool
- do_must_eval_in_order() const
- { return true; }
-
- Bexpression*
- do_get_backend(Translate_context*);
-
- void
- do_dump_expression(Ast_dump_context*) const;
-
- private:
- // The underlying call expression.
- Expression* call_;
- // Which result we want.
- unsigned int index_;
-};
+// Class Call_result_expression.
// Traverse a call result.
@@ -9813,85 +9698,7 @@ Expression::make_index(Expression* left, Expression* start, Expression* end,
return new Index_expression(left, start, end, cap, location);
}
-// An array index. This is used for both indexing and slicing.
-
-class Array_index_expression : public Expression
-{
- public:
- Array_index_expression(Expression* array, Expression* start,
- Expression* end, Expression* cap, Location location)
- : Expression(EXPRESSION_ARRAY_INDEX, location),
- array_(array), start_(start), end_(end), cap_(cap), type_(NULL)
- { }
-
- protected:
- int
- do_traverse(Traverse*);
-
- Expression*
- do_flatten(Gogo*, Named_object*, Statement_inserter*);
-
- Type*
- do_type();
-
- void
- do_determine_type(const Type_context*);
-
- void
- do_check_types(Gogo*);
-
- Expression*
- do_copy()
- {
- return Expression::make_array_index(this->array_->copy(),
- this->start_->copy(),
- (this->end_ == NULL
- ? NULL
- : this->end_->copy()),
- (this->cap_ == NULL
- ? NULL
- : this->cap_->copy()),
- this->location());
- }
-
- bool
- do_must_eval_subexpressions_in_order(int* skip) const
- {
- *skip = 1;
- return true;
- }
-
- bool
- do_is_addressable() const;
-
- void
- do_address_taken(bool escapes)
- { this->array_->address_taken(escapes); }
-
- void
- do_issue_nil_check()
- { this->array_->issue_nil_check(); }
-
- Bexpression*
- do_get_backend(Translate_context*);
-
- void
- do_dump_expression(Ast_dump_context*) const;
-
- private:
- // The array we are getting a value from.
- Expression* array_;
- // The start or only index.
- Expression* start_;
- // The end index of a slice. This may be NULL for a simple array
- // index, or it may be a nil expression for the length of the array.
- Expression* end_;
- // The capacity argument of a slice. This may be NULL for an array index or
- // slice.
- Expression* cap_;
- // The type of the expression.
- Type* type_;
-};
+// Class Array_index_expression.
// Array index traversal.
@@ -11187,13 +10994,15 @@ Interface_field_reference_expression::create_thunk(Gogo* gogo,
Function_type* new_fntype = orig_fntype->copy_with_names();
- Named_object* new_no = gogo->start_function(Gogo::thunk_name(), new_fntype,
+ std::string thunk_name = Gogo::thunk_name();
+ Named_object* new_no = gogo->start_function(thunk_name, new_fntype,
false, loc);
Variable* cvar = new Variable(closure_type, NULL, false, false, false, loc);
cvar->set_is_used();
cvar->set_is_closure();
- Named_object* cp = Named_object::make_variable("$closure", NULL, cvar);
+ Named_object* cp = Named_object::make_variable("$closure" + thunk_name,
+ NULL, cvar);
new_no->func_value()->set_closure_var(cp);
gogo->start_block(loc);
@@ -11593,43 +11402,45 @@ Expression::make_selector(Expression* left, const std::string& name,
return new Selector_expression(left, name, location);
}
-// Implement the builtin function new.
+// Class Allocation_expression.
-class Allocation_expression : public Expression
+int
+Allocation_expression::do_traverse(Traverse* traverse)
{
- public:
- Allocation_expression(Type* type, Location location)
- : Expression(EXPRESSION_ALLOCATION, location),
- type_(type)
- { }
-
- protected:
- int
- do_traverse(Traverse* traverse)
- { return Type::traverse(this->type_, traverse); }
-
- Type*
- do_type()
- { return Type::make_pointer_type(this->type_); }
+ return Type::traverse(this->type_, traverse);
+}
- void
- do_determine_type(const Type_context*)
- { }
+Type*
+Allocation_expression::do_type()
+{
+ return Type::make_pointer_type(this->type_);
+}
- Expression*
- do_copy()
- { return new Allocation_expression(this->type_, this->location()); }
+// Make a copy of an allocation expression.
- Bexpression*
- do_get_backend(Translate_context*);
+Expression*
+Allocation_expression::do_copy()
+{
+ Allocation_expression* alloc =
+ new Allocation_expression(this->type_, this->location());
+ if (this->allocate_on_stack_)
+ alloc->set_allocate_on_stack();
+ return alloc;
+}
- void
- do_dump_expression(Ast_dump_context*) const;
-
- private:
- // The type we are allocating.
- Type* type_;
-};
+Expression*
+Allocation_expression::do_flatten(Gogo*, Named_object*,
+ Statement_inserter* inserter)
+{
+ if (this->allocate_on_stack_)
+ {
+ this->stack_temp_ = Statement::make_temporary(this->type_, NULL,
+ this->location());
+ this->stack_temp_->set_is_address_taken();
+ inserter->insert(this->stack_temp_);
+ }
+ return this;
+}
// Return the backend representation for an allocation expression.
@@ -11638,6 +11449,15 @@ Allocation_expression::do_get_backend(Translate_context* context)
{
Gogo* gogo = context->gogo();
Location loc = this->location();
+
+ if (this->stack_temp_ != NULL)
+ {
+ Expression* ref =
+ Expression::make_temporary_reference(this->stack_temp_, loc);
+ ref = Expression::make_unary(OPERATOR_AND, ref, loc);
+ return ref->get_backend(context);
+ }
+
Bexpression* space =
gogo->allocate_memory(this->type_, loc)->get_backend(context);
Btype* pbtype = gogo->backend()->pointer_type(this->type_->get_backend(gogo));
@@ -11663,80 +11483,7 @@ Expression::make_allocation(Type* type, Location location)
return new Allocation_expression(type, location);
}
-// Construct a struct.
-
-class Struct_construction_expression : public Expression
-{
- public:
- Struct_construction_expression(Type* type, Expression_list* vals,
- Location location)
- : Expression(EXPRESSION_STRUCT_CONSTRUCTION, location),
- type_(type), vals_(vals), traverse_order_(NULL)
- { }
-
- // Set the traversal order, used to ensure that we implement the
- // order of evaluation rules. Takes ownership of the argument.
- void
- set_traverse_order(std::vector<int>* traverse_order)
- { this->traverse_order_ = traverse_order; }
-
- // Return whether this is a constant initializer.
- bool
- is_constant_struct() const;
-
- protected:
- int
- do_traverse(Traverse* traverse);
-
- bool
- do_is_immutable() const;
-
- Type*
- do_type()
- { return this->type_; }
-
- void
- do_determine_type(const Type_context*);
-
- void
- do_check_types(Gogo*);
-
- Expression*
- do_copy()
- {
- Struct_construction_expression* ret =
- new Struct_construction_expression(this->type_,
- (this->vals_ == NULL
- ? NULL
- : this->vals_->copy()),
- this->location());
- if (this->traverse_order_ != NULL)
- ret->set_traverse_order(this->traverse_order_);
- return ret;
- }
-
- Expression*
- do_flatten(Gogo*, Named_object*, Statement_inserter*);
-
- Bexpression*
- do_get_backend(Translate_context*);
-
- void
- do_export(Export*) const;
-
- void
- do_dump_expression(Ast_dump_context*) const;
-
- private:
- // The type of the struct to construct.
- Type* type_;
- // The list of values, in order of the fields in the struct. A NULL
- // entry means that the field should be zero-initialized.
- Expression_list* vals_;
- // If not NULL, the order in which to traverse vals_. This is used
- // so that we implement the order of evaluation rules correctly.
- std::vector<int>* traverse_order_;
-};
+// Class Struct_construction_expression.
// Traversal.
@@ -12003,80 +11750,7 @@ Expression::make_struct_composite_literal(Type* type, Expression_list* vals,
return new Struct_construction_expression(type, vals, location);
}
-// Construct an array. This class is not used directly; instead we
-// use the child classes, Fixed_array_construction_expression and
-// Slice_construction_expression.
-
-class Array_construction_expression : public Expression
-{
- protected:
- Array_construction_expression(Expression_classification classification,
- Type* type,
- const std::vector<unsigned long>* indexes,
- Expression_list* vals, Location location)
- : Expression(classification, location),
- type_(type), indexes_(indexes), vals_(vals)
- { go_assert(indexes == NULL || indexes->size() == vals->size()); }
-
- public:
- // Return whether this is a constant initializer.
- bool
- is_constant_array() const;
-
- // Return the number of elements.
- size_t
- element_count() const
- { return this->vals_ == NULL ? 0 : this->vals_->size(); }
-
-protected:
- virtual int
- do_traverse(Traverse* traverse);
-
- bool
- do_is_immutable() const;
-
- Type*
- do_type()
- { return this->type_; }
-
- void
- do_determine_type(const Type_context*);
-
- void
- do_check_types(Gogo*);
-
- void
- do_export(Export*) const;
-
- // The indexes.
- const std::vector<unsigned long>*
- indexes()
- { return this->indexes_; }
-
- // The list of values.
- Expression_list*
- vals()
- { return this->vals_; }
-
- Expression*
- do_flatten(Gogo*, Named_object*, Statement_inserter*);
-
- // Get the backend constructor for the array values.
- Bexpression*
- get_constructor(Translate_context* context, Btype* btype);
-
- void
- do_dump_expression(Ast_dump_context*) const;
-
- private:
- // The type of the array to construct.
- Type* type_;
- // The list of indexes into the array, one for each value. This may
- // be NULL, in which case the indexes start at zero and increment.
- const std::vector<unsigned long>* indexes_;
- // The list of values. This may be NULL if there are no values.
- Expression_list* vals_;
-};
+// Class Array_construction_expression.
// Traversal.
@@ -12332,34 +12006,14 @@ Array_construction_expression::do_dump_expression(
}
-// Construct a fixed array.
-
-class Fixed_array_construction_expression :
- public Array_construction_expression
-{
- public:
- Fixed_array_construction_expression(Type* type,
- const std::vector<unsigned long>* indexes,
- Expression_list* vals, Location location)
- : Array_construction_expression(EXPRESSION_FIXED_ARRAY_CONSTRUCTION,
- type, indexes, vals, location)
- { go_assert(type->array_type() != NULL && !type->is_slice_type()); }
-
- protected:
- Expression*
- do_copy()
- {
- return new Fixed_array_construction_expression(this->type(),
- this->indexes(),
- (this->vals() == NULL
- ? NULL
- : this->vals()->copy()),
- this->location());
- }
+// Class Fixed_array_construction_expression.
- Bexpression*
- do_get_backend(Translate_context*);
-};
+Fixed_array_construction_expression::Fixed_array_construction_expression(
+ Type* type, const std::vector<unsigned long>* indexes,
+ Expression_list* vals, Location location)
+ : Array_construction_expression(EXPRESSION_FIXED_ARRAY_CONSTRUCTION,
+ type, indexes, vals, location)
+{ go_assert(type->array_type() != NULL && !type->is_slice_type()); }
// Return the backend representation for constructing a fixed array.
@@ -12379,60 +12033,34 @@ Expression::make_array_composite_literal(Type* type, Expression_list* vals,
return new Fixed_array_construction_expression(type, NULL, vals, location);
}
-// Construct a slice.
+// Class Slice_construction_expression.
-class Slice_construction_expression : public Array_construction_expression
+Slice_construction_expression::Slice_construction_expression(
+ Type* type, const std::vector<unsigned long>* indexes,
+ Expression_list* vals, Location location)
+ : Array_construction_expression(EXPRESSION_SLICE_CONSTRUCTION,
+ type, indexes, vals, location),
+ valtype_(NULL)
{
- public:
- Slice_construction_expression(Type* type,
- const std::vector<unsigned long>* indexes,
- Expression_list* vals, Location location)
- : Array_construction_expression(EXPRESSION_SLICE_CONSTRUCTION,
- type, indexes, vals, location),
- valtype_(NULL)
- {
- go_assert(type->is_slice_type());
-
- unsigned long lenval;
- Expression* length;
- if (vals == NULL || vals->empty())
- lenval = 0;
- else
- {
- if (this->indexes() == NULL)
- lenval = vals->size();
- else
- lenval = indexes->back() + 1;
- }
- Type* int_type = Type::lookup_integer_type("int");
- length = Expression::make_integer_ul(lenval, int_type, location);
- Type* element_type = type->array_type()->element_type();
- this->valtype_ = Type::make_array_type(element_type, length);
- }
-
- protected:
- // Note that taking the address of a slice literal is invalid.
-
- int
- do_traverse(Traverse* traverse);
+ go_assert(type->is_slice_type());
- Expression*
- do_copy()
- {
- return new Slice_construction_expression(this->type(), this->indexes(),
- (this->vals() == NULL
- ? NULL
- : this->vals()->copy()),
- this->location());
- }
+ unsigned long lenval;
+ Expression* length;
+ if (vals == NULL || vals->empty())
+ lenval = 0;
+ else
+ {
+ if (this->indexes() == NULL)
+ lenval = vals->size();
+ else
+ lenval = indexes->back() + 1;
+ }
+ Type* int_type = Type::lookup_integer_type("int");
+ length = Expression::make_integer_ul(lenval, int_type, location);
+ Type* element_type = type->array_type()->element_type();
+ this->valtype_ = Type::make_array_type(element_type, length);
+}
- Bexpression*
- do_get_backend(Translate_context*);
-
- private:
- // The type of the values in this slice.
- Type* valtype_;
-};
// Traversal.
@@ -12514,63 +12142,7 @@ Expression::make_slice_composite_literal(Type* type, Expression_list* vals,
return new Slice_construction_expression(type, NULL, vals, location);
}
-// Construct a map.
-
-class Map_construction_expression : public Expression
-{
- public:
- Map_construction_expression(Type* type, Expression_list* vals,
- Location location)
- : Expression(EXPRESSION_MAP_CONSTRUCTION, location),
- type_(type), vals_(vals), element_type_(NULL), constructor_temp_(NULL)
- { go_assert(vals == NULL || vals->size() % 2 == 0); }
-
- protected:
- int
- do_traverse(Traverse* traverse);
-
- Expression*
- do_flatten(Gogo*, Named_object*, Statement_inserter*);
-
- Type*
- do_type()
- { return this->type_; }
-
- void
- do_determine_type(const Type_context*);
-
- void
- do_check_types(Gogo*);
-
- Expression*
- do_copy()
- {
- return new Map_construction_expression(this->type_,
- (this->vals_ == NULL
- ? NULL
- : this->vals_->copy()),
- this->location());
- }
-
- Bexpression*
- do_get_backend(Translate_context*);
-
- void
- do_export(Export*) const;
-
- void
- do_dump_expression(Ast_dump_context*) const;
-
- private:
- // The type of the map to construct.
- Type* type_;
- // The list of values.
- Expression_list* vals_;
- // The type of the key-value pair struct for each map element.
- Struct_type* element_type_;
- // A temporary reference to the variable storing the constructor initializer.
- Temporary_statement* constructor_temp_;
-};
+// Class Map_construction_expression.
// Traversal.
@@ -13680,53 +13252,11 @@ Expression::make_type_guard(Expression* expr, Type* type,
// Class Heap_expression.
-// When you take the address of an escaping expression, it is allocated
-// on the heap. This class implements that.
+// Return the type of the expression stored on the heap.
-class Heap_expression : public Expression
-{
- public:
- Heap_expression(Expression* expr, Location location)
- : Expression(EXPRESSION_HEAP, location),
- expr_(expr)
- { }
-
- protected:
- int
- do_traverse(Traverse* traverse)
- { return Expression::traverse(&this->expr_, traverse); }
-
- Type*
- do_type()
- { return Type::make_pointer_type(this->expr_->type()); }
-
- void
- do_determine_type(const Type_context*)
- { this->expr_->determine_type_no_context(); }
-
- Expression*
- do_copy()
- {
- return Expression::make_heap_expression(this->expr_->copy(),
- this->location());
- }
-
- Bexpression*
- do_get_backend(Translate_context*);
-
- // We only export global objects, and the parser does not generate
- // this in global scope.
- void
- do_export(Export*) const
- { go_unreachable(); }
-
- void
- do_dump_expression(Ast_dump_context*) const;
-
- private:
- // The expression which is being put on the heap.
- Expression* expr_;
-};
+Type*
+Heap_expression::do_type()
+{ return Type::make_pointer_type(this->expr_->type()); }
// Return the backend representation for allocating an expression on the heap.
@@ -14964,48 +14494,7 @@ Expression::make_label_addr(Label* label, Location location)
return new Label_addr_expression(label, location);
}
-// Conditional expressions.
-
-class Conditional_expression : public Expression
-{
- public:
- Conditional_expression(Expression* cond, Expression* then_expr,
- Expression* else_expr, Location location)
- : Expression(EXPRESSION_CONDITIONAL, location),
- cond_(cond), then_(then_expr), else_(else_expr)
- {}
-
- protected:
- int
- do_traverse(Traverse*);
-
- Type*
- do_type();
-
- void
- do_determine_type(const Type_context*);
-
- Expression*
- do_copy()
- {
- return new Conditional_expression(this->cond_->copy(), this->then_->copy(),
- this->else_->copy(), this->location());
- }
-
- Bexpression*
- do_get_backend(Translate_context* context);
-
- void
- do_dump_expression(Ast_dump_context*) const;
-
- private:
- // The condition to be checked.
- Expression* cond_;
- // The expression to execute if the condition is true.
- Expression* then_;
- // The expression to execute if the condition is false.
- Expression* else_;
-};
+// Class Conditional_expression.
// Traversal.
@@ -15084,44 +14573,7 @@ Expression::make_conditional(Expression* cond, Expression* then,
return new Conditional_expression(cond, then, else_expr, location);
}
-// Compound expressions.
-
-class Compound_expression : public Expression
-{
- public:
- Compound_expression(Expression* init, Expression* expr, Location location)
- : Expression(EXPRESSION_COMPOUND, location), init_(init), expr_(expr)
- {}
-
- protected:
- int
- do_traverse(Traverse*);
-
- Type*
- do_type();
-
- void
- do_determine_type(const Type_context*);
-
- Expression*
- do_copy()
- {
- return new Compound_expression(this->init_->copy(), this->expr_->copy(),
- this->location());
- }
-
- Bexpression*
- do_get_backend(Translate_context* context);
-
- void
- do_dump_expression(Ast_dump_context*) const;
-
- private:
- // The expression that is evaluated first and discarded.
- Expression* init_;
- // The expression that is evaluated and returned.
- Expression* expr_;
-};
+// Class Compound_expression.
// Traversal.