diff options
author | lrh2000 <lrh2000@pku.edu.cn> | 2021-04-10 22:53:32 +0800 |
---|---|---|
committer | lrh2000 <lrh2000@pku.edu.cn> | 2021-04-18 10:11:53 +0800 |
commit | c5fdf8cc544f9647e2cf28a2da431bfa1faacd15 (patch) | |
tree | f67b95885d2f3573acd86e815750e0e1ec92b58f /gcc | |
parent | 498758a1c238a539b364ac2c632742a9b64ab4a5 (diff) | |
download | gcc-c5fdf8cc544f9647e2cf28a2da431bfa1faacd15.zip gcc-c5fdf8cc544f9647e2cf28a2da431bfa1faacd15.tar.gz gcc-c5fdf8cc544f9647e2cf28a2da431bfa1faacd15.tar.bz2 |
The trailing expression is not necessarily without a block
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/ast/rust-expr.h | 10 | ||||
-rw-r--r-- | gcc/rust/ast/rust-stmt.h | 9 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 5 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-stmt.h | 3 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-expr.h | 10 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-stmt.h | 9 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir.h | 2 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse-impl.h | 61 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse.h | 14 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check.cc | 6 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compile/unused.rs | 2 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/xfail_compile/implicit_returns_err1.rs | 4 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/xfail_compile/implicit_returns_err3.rs | 3 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/xfail_compile/stmt_with_block_err1.rs | 17 |
14 files changed, 105 insertions, 50 deletions
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index dde833f..eb56b65 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -2828,7 +2828,7 @@ class BlockExpr : public ExprWithBlock std::vector<Attribute> outer_attrs; std::vector<Attribute> inner_attrs; std::vector<std::unique_ptr<Stmt> > statements; - std::unique_ptr<ExprWithoutBlock> expr; + std::unique_ptr<Expr> expr; Location locus; bool marked_for_strip = false; @@ -2842,7 +2842,7 @@ public: bool has_tail_expr () const { return expr != nullptr; } BlockExpr (std::vector<std::unique_ptr<Stmt> > block_statements, - std::unique_ptr<ExprWithoutBlock> block_expr, + std::unique_ptr<Expr> block_expr, std::vector<Attribute> inner_attribs, std::vector<Attribute> outer_attribs, Location locus) : outer_attrs (std::move (outer_attribs)), @@ -2859,7 +2859,7 @@ public: { // guard to protect from null pointer dereference if (other.expr != nullptr) - expr = other.expr->clone_expr_without_block (); + expr = other.expr->clone_expr (); statements.reserve (other.statements.size ()); for (const auto &e : other.statements) @@ -2877,7 +2877,7 @@ public: // guard to protect from null pointer dereference if (other.expr != nullptr) - expr = other.expr->clone_expr_without_block (); + expr = other.expr->clone_expr (); else expr = nullptr; @@ -2929,7 +2929,7 @@ public: std::vector<std::unique_ptr<Stmt> > &get_statements () { return statements; } // TODO: is this better? Or is a "vis_block" better? - std::unique_ptr<ExprWithoutBlock> &get_tail_expr () + std::unique_ptr<Expr> &get_tail_expr () { rust_assert (has_tail_expr ()); return expr; diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index c840112..7294677 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -269,14 +269,17 @@ protected: class ExprStmtWithBlock : public ExprStmt { std::unique_ptr<ExprWithBlock> expr; + bool semicolon_followed; public: std::string as_string () const override; std::vector<LetStmt *> locals; - ExprStmtWithBlock (std::unique_ptr<ExprWithBlock> expr, Location locus) - : ExprStmt (locus), expr (std::move (expr)) + ExprStmtWithBlock (std::unique_ptr<ExprWithBlock> expr, Location locus, + bool semicolon_followed) + : ExprStmt (locus), expr (std::move (expr)), + semicolon_followed (semicolon_followed) {} // Copy constructor with clone @@ -318,6 +321,8 @@ public: return expr; } + bool is_semicolon_followed () const { return semicolon_followed; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index a2f5247..d0e0c66 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -416,10 +416,11 @@ HIRCompileBase::compile_function_body ( // dead code elimination should remove any bad trailing expressions Bexpression *compiled_expr = CompileExpr::Compile (function_body->expr.get (), ctx); - rust_assert (compiled_expr != nullptr); if (has_return_type) { + rust_assert (compiled_expr != nullptr); + std::vector<Bexpression *> retstmts; retstmts.push_back (compiled_expr); @@ -428,7 +429,7 @@ HIRCompileBase::compile_function_body ( function_body->get_final_expr ()->get_locus_slow ()); ctx->add_statement (ret); } - else + else if (compiled_expr) { Bstatement *final_stmt = ctx->get_backend ()->expression_statement (fndecl, compiled_expr); diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h b/gcc/rust/hir/rust-ast-lower-stmt.h index e15714c..2d3f59d 100644 --- a/gcc/rust/hir/rust-ast-lower-stmt.h +++ b/gcc/rust/hir/rust-ast-lower-stmt.h @@ -59,7 +59,8 @@ public: translated = new HIR::ExprStmtWithBlock (mapping, std::unique_ptr<HIR::ExprWithBlock> (expr), - stmt.get_locus ()); + stmt.get_locus (), + !stmt.is_semicolon_followed ()); mappings->insert_location (crate_num, mapping.get_hirid (), stmt.get_locus ()); mappings->insert_hir_stmt (crate_num, mapping.get_hirid (), translated); diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 1748c6a..26f36c4d 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -2498,7 +2498,7 @@ public: std::vector<Attribute> inner_attrs; std::vector<std::unique_ptr<Stmt> > statements; - std::unique_ptr<ExprWithoutBlock> expr; // inlined from Statements + std::unique_ptr<Expr> expr; // inlined from Statements bool tail_reachable; Location locus; @@ -2515,7 +2515,7 @@ public: BlockExpr (Analysis::NodeMapping mappings, std::vector<std::unique_ptr<Stmt> > block_statements, - std::unique_ptr<ExprWithoutBlock> block_expr, bool tail_reachable, + std::unique_ptr<Expr> block_expr, bool tail_reachable, std::vector<Attribute> inner_attribs, std::vector<Attribute> outer_attribs, Location locus) : ExprWithBlock (std::move (mappings), std::move (outer_attribs)), @@ -2531,7 +2531,7 @@ public: { // guard to protect from null pointer dereference if (other.expr != nullptr) - expr = other.expr->clone_expr_without_block (); + expr = other.expr->clone_expr (); statements.reserve (other.statements.size ()); for (const auto &e : other.statements) @@ -2543,7 +2543,7 @@ public: { ExprWithBlock::operator= (other); // statements = other.statements; - expr = other.expr->clone_expr_without_block (); + expr = other.expr->clone_expr (); inner_attrs = other.inner_attrs; locus = other.locus; // outer_attrs = other.outer_attrs; @@ -2589,7 +2589,7 @@ public: return statements[statements.size () - 1]->get_locus_slow (); } - std::unique_ptr<ExprWithoutBlock> &get_final_expr () { return expr; } + std::unique_ptr<Expr> &get_final_expr () { return expr; } std::vector<std::unique_ptr<Stmt> > &get_statements () { return statements; } diff --git a/gcc/rust/hir/tree/rust-hir-stmt.h b/gcc/rust/hir/tree/rust-hir-stmt.h index 3384aaa..e34fa7e 100644 --- a/gcc/rust/hir/tree/rust-hir-stmt.h +++ b/gcc/rust/hir/tree/rust-hir-stmt.h @@ -193,13 +193,16 @@ protected: class ExprStmtWithBlock : public ExprStmt { std::unique_ptr<ExprWithBlock> expr; + bool must_be_unit; public: std::string as_string () const override; ExprStmtWithBlock (Analysis::NodeMapping mappings, - std::unique_ptr<ExprWithBlock> expr, Location locus) - : ExprStmt (std::move (mappings), locus), expr (std::move (expr)) + std::unique_ptr<ExprWithBlock> expr, Location locus, + bool must_be_unit) + : ExprStmt (std::move (mappings), locus), expr (std::move (expr)), + must_be_unit (must_be_unit) {} // Copy constructor with clone @@ -224,6 +227,8 @@ public: ExprWithBlock *get_expr () { return expr.get (); } + bool is_unit_check_needed () const override { return must_be_unit; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h index 5198635..9bda63a 100644 --- a/gcc/rust/hir/tree/rust-hir.h +++ b/gcc/rust/hir/tree/rust-hir.h @@ -723,6 +723,8 @@ public: * methods. */ virtual Location get_locus_slow () const { return Location (); } + virtual bool is_unit_check_needed () const { return false; } + const Analysis::NodeMapping &get_mappings () const { return mappings; } protected: diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 9697169..6d38ace 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -7022,11 +7022,9 @@ Parser<ManagedTokenSource>::parse_expr_stmt ( } } -/* Parses a expression statement containing an expression with block. - * Disambiguates internally. */ template <typename ManagedTokenSource> -std::unique_ptr<AST::ExprStmtWithBlock> -Parser<ManagedTokenSource>::parse_expr_stmt_with_block ( +std::unique_ptr<AST::ExprWithBlock> +Parser<ManagedTokenSource>::parse_expr_with_block ( std::vector<AST::Attribute> outer_attrs) { std::unique_ptr<AST::ExprWithBlock> expr_parsed = nullptr; @@ -7113,9 +7111,23 @@ Parser<ManagedTokenSource>::parse_expr_stmt_with_block ( return nullptr; } + return expr_parsed; +} + +/* Parses a expression statement containing an expression with block. + * Disambiguates internally. */ +template <typename ManagedTokenSource> +std::unique_ptr<AST::ExprStmtWithBlock> +Parser<ManagedTokenSource>::parse_expr_stmt_with_block ( + std::vector<AST::Attribute> outer_attrs) +{ + auto expr_parsed = parse_expr_with_block (std::move (outer_attrs)); + auto locus = expr_parsed->get_locus (); + // return expr stmt created from expr return std::unique_ptr<AST::ExprStmtWithBlock> ( - new AST::ExprStmtWithBlock (std::move (expr_parsed), t->get_locus ())); + new AST::ExprStmtWithBlock (std::move (expr_parsed), locus, + lexer.peek_token ()->get_id () == SEMICOLON)); } /* Parses an expression statement containing an expression without block. @@ -7286,7 +7298,7 @@ Parser<ManagedTokenSource>::parse_block_expr ( // parse statements and expression std::vector<std::unique_ptr<AST::Stmt>> stmts; - std::unique_ptr<AST::ExprWithoutBlock> expr = nullptr; + std::unique_ptr<AST::Expr> expr = nullptr; const_TokenPtr t = lexer.peek_token (); while (t->get_id () != RIGHT_CURLY) @@ -11438,6 +11450,29 @@ Parser<ManagedTokenSource>::parse_struct_pattern_field_partial ( } } +template <typename ManagedTokenSource> +ExprOrStmt +Parser<ManagedTokenSource>::parse_stmt_or_expr_with_block ( + std::vector<AST::Attribute> outer_attrs) +{ + auto expr = parse_expr_with_block (std::move (outer_attrs)); + auto tok = lexer.peek_token (); + + // tail expr in a block expr + if (tok->get_id () == RIGHT_CURLY) + return ExprOrStmt (std::move (expr)); + + // internal block expr must either have semicolons followed, or evaluate to () + auto locus = expr->get_locus_slow (); + std::unique_ptr<AST::ExprStmtWithBlock> stmt ( + new AST::ExprStmtWithBlock (std::move (expr), locus, + tok->get_id () == SEMICOLON)); + if (tok->get_id () == SEMICOLON) + lexer.skip_token (); + + return ExprOrStmt (std::move (stmt)); +} + /* Parses a statement or expression (depending on whether a trailing semicolon * exists). Useful for block expressions where it cannot be determined through * lookahead whether it is a statement or expression to be parsed. */ @@ -11508,9 +11543,7 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr_without_block () { case LEFT_CURLY: { // unsafe block - std::unique_ptr<AST::ExprStmtWithBlock> stmt ( - parse_expr_stmt_with_block (std::move (outer_attrs))); - return ExprOrStmt (std::move (stmt)); + return parse_stmt_or_expr_with_block (std::move (outer_attrs)); } case TRAIT: { // unsafe trait @@ -11577,11 +11610,7 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr_without_block () case MATCH_TOK: case LEFT_CURLY: case ASYNC: { - // all expressions with block, so cannot be final expr without block in - // function - std::unique_ptr<AST::ExprStmtWithBlock> stmt ( - parse_expr_stmt_with_block (std::move (outer_attrs))); - return ExprOrStmt (std::move (stmt)); + return parse_stmt_or_expr_with_block (std::move (outer_attrs)); } case LIFETIME: { /* FIXME: are there any expressions without blocks that can have @@ -11592,9 +11621,7 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr_without_block () && (t2->get_id () == LOOP || t2->get_id () == WHILE || t2->get_id () == FOR)) { - std::unique_ptr<AST::ExprStmtWithBlock> stmt ( - parse_expr_stmt_with_block (std::move (outer_attrs))); - return ExprOrStmt (std::move (stmt)); + return parse_stmt_or_expr_with_block (std::move (outer_attrs)); } else { diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index f6faa96..47f55ea 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -27,7 +27,7 @@ namespace Rust { * probably take up the same amount of space. */ struct ExprOrStmt { - std::unique_ptr<AST::ExprWithoutBlock> expr; + std::unique_ptr<AST::Expr> expr; std::unique_ptr<AST::Stmt> stmt; /* I was going to resist the urge to make this a real class and make it POD, @@ -35,9 +35,7 @@ struct ExprOrStmt * constructor. */ // expression constructor - ExprOrStmt (std::unique_ptr<AST::ExprWithoutBlock> expr) - : expr (std::move (expr)) - {} + ExprOrStmt (std::unique_ptr<AST::Expr> expr) : expr (std::move (expr)) {} // statement constructor ExprOrStmt (std::unique_ptr<AST::Stmt> stmt) : stmt (std::move (stmt)) {} @@ -63,9 +61,7 @@ struct ExprOrStmt private: // private constructor only used for creating error state expr or stmt objects - ExprOrStmt (AST::ExprWithoutBlock *expr, AST::Stmt *stmt) - : expr (expr), stmt (stmt) - {} + ExprOrStmt (AST::Expr *expr, AST::Stmt *stmt) : expr (expr), stmt (stmt) {} // make this work: have a disambiguation specifically for known statements // (i.e. ';' and 'let'). then, have a special "parse expr or stmt" function @@ -487,6 +483,8 @@ private: ParseRestrictions restrictions = ParseRestrictions ()); // Expression-related (non-Pratt parsed) + std::unique_ptr<AST::ExprWithBlock> + parse_expr_with_block (std::vector<AST::Attribute> outer_attrs); std::unique_ptr<AST::ExprWithoutBlock> parse_expr_without_block (std::vector<AST::Attribute> outer_attrs = std::vector<AST::Attribute> ()); @@ -592,6 +590,8 @@ private: parse_expr_stmt_without_block (std::vector<AST::Attribute> outer_attrs); ExprOrStmt parse_stmt_or_expr_without_block (); ExprOrStmt + parse_stmt_or_expr_with_block (std::vector<AST::Attribute> outer_attrs); + ExprOrStmt parse_macro_invocation_maybe_semi (std::vector<AST::Attribute> outer_attrs); ExprOrStmt parse_path_based_stmt_or_expr (std::vector<AST::Attribute> outer_attrs); diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index c8394c8..f1503be 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -143,10 +143,10 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) delete block_tyty; block_tyty = resolved; } - else if (!resolved->is_unit ()) + else if (s->is_unit_check_needed () && !resolved->is_unit ()) { - rust_error_at (s->get_locus_slow (), "expected () got %s", - resolved->as_string ().c_str ()); + auto unit = new TyTy::TupleType (s->get_mappings ().get_hirid ()); + resolved = unit->unify (resolved); } return true; diff --git a/gcc/testsuite/rust.test/compile/unused.rs b/gcc/testsuite/rust.test/compile/unused.rs index a4987b5..0564aa1 100644 --- a/gcc/testsuite/rust.test/compile/unused.rs +++ b/gcc/testsuite/rust.test/compile/unused.rs @@ -14,4 +14,4 @@ fn f() { fn main() { f(); -}
\ No newline at end of file +} diff --git a/gcc/testsuite/rust.test/xfail_compile/implicit_returns_err1.rs b/gcc/testsuite/rust.test/xfail_compile/implicit_returns_err1.rs index 37eb562..973ba80 100644 --- a/gcc/testsuite/rust.test/xfail_compile/implicit_returns_err1.rs +++ b/gcc/testsuite/rust.test/xfail_compile/implicit_returns_err1.rs @@ -1,7 +1,5 @@ -// { dg-error "expected .* got .*" "" { target { *-*-* } } 0 } - fn test(x: i32) -> i32 { - if x > 1 { + if x > 1 { // { dg-error "expected .... got .<integer>." } 1 } else { 2 diff --git a/gcc/testsuite/rust.test/xfail_compile/implicit_returns_err3.rs b/gcc/testsuite/rust.test/xfail_compile/implicit_returns_err3.rs index 2a64fcf..37b1c62 100644 --- a/gcc/testsuite/rust.test/xfail_compile/implicit_returns_err3.rs +++ b/gcc/testsuite/rust.test/xfail_compile/implicit_returns_err3.rs @@ -1,5 +1,4 @@ -// { dg-error "expected .* got .*" "" { target { *-*-* } } 0 } -fn test(x: i32) -> i32 { +fn test(x: i32) -> i32 { // { dg-error "expected .i32. got ...." } if x > 1 { 1 } diff --git a/gcc/testsuite/rust.test/xfail_compile/stmt_with_block_err1.rs b/gcc/testsuite/rust.test/xfail_compile/stmt_with_block_err1.rs new file mode 100644 index 0000000..8780d0f --- /dev/null +++ b/gcc/testsuite/rust.test/xfail_compile/stmt_with_block_err1.rs @@ -0,0 +1,17 @@ +fn test(x: i32) -> i32 { + if x > 1 { // { dg-error "expected .... got .<integer>." } + 1 + } else { + 2 + } + + { // { dg-error "expected .... got .<integer>." } + 3 + } + + 3 +} + +fn main() { + let a = test(0); +} |