Chromium Code Reviews| Index: src/asmjs/asm-typer.cc |
| diff --git a/src/asmjs/asm-typer.cc b/src/asmjs/asm-typer.cc |
| index b265884bd0b8eb26c91f6ab30669edd25e1f2d87..ce23dc22bbe8b526eaa64224f827fb75f0a3e220 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 |
| + // Emscipten. |
|
Mircea Trofin
2017/01/26 07:47:27
Emscripten
bradn
2017/01/26 07:50:42
Done.
|
| + if (auto* cond = ret_expr->AsConditional()) { |
| + AsmType* a; |
|
Mircea Trofin
2017/01/26 07:47:27
init a and b?
bradn
2017/01/26 07:50:42
Done.
|
| + AsmType* b; |
| + 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 |