Index: src/asmjs/asm-typer.cc |
diff --git a/src/asmjs/asm-typer.cc b/src/asmjs/asm-typer.cc |
index b265884bd0b8eb26c91f6ab30669edd25e1f2d87..d123e5637ace7df2576826b6c8d1f800f31ba199 100644 |
--- a/src/asmjs/asm-typer.cc |
+++ b/src/asmjs/asm-typer.cc |
@@ -1225,10 +1225,12 @@ AsmType* AsmTyper::ValidateFunction(FunctionDeclaration* fun_decl) { |
if (as_block != nullptr) { |
statements = as_block->statements(); |
} else { |
- // We don't check whether AsReturnStatement() below returns non-null -- |
- // we leave that to the ReturnTypeAnnotations method. |
- RECURSE(return_type_ = |
- ReturnTypeAnnotations(last_statement->AsReturnStatement())); |
+ if (auto* ret_statement = last_statement->AsReturnStatement()) { |
+ RECURSE(return_type_ = |
+ ReturnTypeAnnotations(ret_statement->expression())); |
+ } else { |
+ return_type_ = AsmType::Void(); |
+ } |
} |
} |
} while (return_type_ == AsmType::None()); |
@@ -2747,15 +2749,8 @@ AsmType* AsmTyper::ParameterTypeAnnotations(Variable* parameter, |
} |
// 5.2 ReturnTypeAnnotations |
-AsmType* AsmTyper::ReturnTypeAnnotations(ReturnStatement* statement) { |
- if (statement == nullptr) { |
- return AsmType::Void(); |
- } |
- |
- auto* ret_expr = statement->expression(); |
- if (ret_expr == nullptr) { |
- return AsmType::Void(); |
- } |
+AsmType* AsmTyper::ReturnTypeAnnotations(Expression* ret_expr) { |
+ DCHECK_NOT_NULL(ret_expr); |
if (auto* binop = ret_expr->AsBinaryOperation()) { |
if (IsDoubleAnnotation(binop)) { |
@@ -2763,14 +2758,14 @@ AsmType* AsmTyper::ReturnTypeAnnotations(ReturnStatement* statement) { |
} else if (IsIntAnnotation(binop)) { |
return AsmType::Signed(); |
} |
- FAIL(statement, "Invalid return type annotation."); |
+ FAIL(ret_expr, "Invalid return type annotation."); |
} |
if (auto* call = ret_expr->AsCall()) { |
if (IsCallToFround(call)) { |
return AsmType::Float(); |
} |
- FAIL(statement, "Invalid function call in return statement."); |
+ FAIL(ret_expr, "Invalid function call in return statement."); |
} |
if (auto* literal = ret_expr->AsLiteral()) { |
@@ -2789,28 +2784,46 @@ AsmType* AsmTyper::ReturnTypeAnnotations(ReturnStatement* statement) { |
// return undefined |
return AsmType::Void(); |
} |
- FAIL(statement, "Invalid literal in return statement."); |
+ FAIL(ret_expr, "Invalid literal in return statement."); |
} |
if (auto* proxy = ret_expr->AsVariableProxy()) { |
auto* var_info = Lookup(proxy->var()); |
if (var_info == nullptr) { |
- FAIL(statement, "Undeclared identifier in return statement."); |
+ FAIL(ret_expr, "Undeclared identifier in return statement."); |
} |
if (var_info->mutability() != VariableInfo::kConstGlobal) { |
- FAIL(statement, "Identifier in return statement is not const."); |
+ FAIL(ret_expr, "Identifier in return statement is not const."); |
} |
if (!var_info->type()->IsReturnType()) { |
- FAIL(statement, "Constant in return must be signed, float, or double."); |
+ FAIL(ret_expr, "Constant in return must be signed, float, or double."); |
} |
return var_info->type(); |
} |
- FAIL(statement, "Invalid return type expression."); |
+ // NOTE: This is not strictly valid asm.js, but is emitted by some versions of |
+ // Emscripten. |
+ if (auto* cond = ret_expr->AsConditional()) { |
+ AsmType* a = AsmType::None(); |
+ AsmType* b = AsmType::None(); |
+ RECURSE(a = ReturnTypeAnnotations(cond->then_expression())); |
+ if (a->IsA(AsmType::None())) { |
+ return a; |
+ } |
+ RECURSE(b = ReturnTypeAnnotations(cond->else_expression())); |
+ if (b->IsA(AsmType::None())) { |
+ return b; |
+ } |
+ if (a->IsExactly(b)) { |
+ return a; |
+ } |
+ } |
+ |
+ FAIL(ret_expr, "Invalid return type expression."); |
} |
// 5.4 VariableTypeAnnotations |