commit 3a3cc7bf76eab3ef239991e686c114baeaf4672e (tree)
parent cca49b84b659ecd6b942e84129f873443ffc7966
Author: Andrew Kelley <superjoe30@gmail.com>
Date: Wed, 14 Dec 2016 15:43:24 -0500
IR: panic with a TODO instead of generating invalid code
for returning from a function without running maybe and error defers
Diffstat:
| M | src/ir.cpp | | | 36 | ++++++++++++++++++++++++++++++++++-- |
1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/src/ir.cpp b/src/ir.cpp
@@ -1709,6 +1709,24 @@ static IrInstruction *ir_build_alignof(IrBuilder *irb, Scope *scope, AstNode *so
return &instruction->base;
}
+static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
+ results[ReturnKindUnconditional] = 0;
+ results[ReturnKindError] = 0;
+ results[ReturnKindMaybe] = 0;
+
+ while (inner_scope != outer_scope) {
+ assert(inner_scope);
+ if (inner_scope->id == ScopeIdDefer) {
+ AstNode *defer_node = inner_scope->source_node;
+ assert(defer_node->type == NodeTypeDefer);
+ ReturnKind defer_kind = defer_node->data.defer.kind;
+ results[defer_kind] += 1;
+
+ }
+ inner_scope = inner_scope->parent;
+ }
+}
+
static void ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope,
bool gen_error_defers, bool gen_maybe_defers)
{
@@ -1762,8 +1780,22 @@ static IrInstruction *ir_gen_return(IrBuilder *irb, Scope *scope, AstNode *node,
return_value = ir_build_const_void(irb, scope, node);
}
- // TODO conditionally gen maybe defers and error defers
- ir_gen_defers_for_block(irb, scope, outer_scope, false, false);
+ size_t defer_counts[3];
+ ir_count_defers(irb, scope, outer_scope, defer_counts);
+ if (defer_counts[ReturnKindError] > 0) {
+ // TODO in this situation we need to make a conditional
+ // branch on the return value. we potentially must make multiple conditional branches,
+ // if unconditional defers are interleaved with error defers.
+ zig_panic("TODO handle error defers");
+ } else if (defer_counts[ReturnKindMaybe] > 0) {
+ // TODO in this situation we need to make a conditional
+ // branch on the maybe value. we potentially must make multiple conditional branches,
+ // if unconditional defers are interleaved with error defers.
+ zig_panic("TODO handle maybe defers");
+ } else {
+ // generate unconditional defers
+ ir_gen_defers_for_block(irb, scope, outer_scope, false, false);
+ }
return ir_build_return(irb, scope, node, return_value);
}
case ReturnKindError: