Skip to content

Commit 5b7a0d7

Browse files
powerboat9CohenArthur
authored andcommitted
Add checks to ExpandVisitor
This should help detect issues like #3444. gcc/rust/ChangeLog: * ast/rust-ast.h (Stmt::get_node_id): Make virtual. (Type::get_node_id): Likewise. (AssociatedItem::get_node_id): New virtual member function. * ast/rust-expr.h (TypeCastExpr::get_casted_expr_ptr): New member function. (TypeCastExpr::get_type_to_cast_to_ptr): Likewise. (ClosureExprInner::get_definition_expr_ptr): Likewise. * ast/rust-item.h (TypeAlias::get_node_id): New member function to override AssociatedItem::get_node_id. (ConstantItem::get_node_id): Likewise. * expand/rust-expand-visitor.cc (ExpandVisitor::maybe_expand_expr): Adjust macro_invoc_expect_id. (ExpandVisitor::maybe_expand_type): Likewise and add an overload for std::unique_ptr<TypeNoBounds>. (ExpandVisitor::visit): Check macro_invoc_expect_id and generally improve visitors so that the testsuite will still pass. * expand/rust-expand-visitor.h (ExpandVisitor::ExpandVisitor): Initialize member variable macro_invoc_expect_id. (ExpandVisitor::maybe_expand_type): Add an overload for std::unique_ptr<TypeNoBounds>. (ExpandVisitor::expand_macro_children): Adjust macro_invoc_expect_id. (ExpandVisitor::visit): Add an overload for TypeCastExpr. (ExpandVisitor::macro_invoc_expect_id): New member variable. gcc/testsuite/ChangeLog: * rust/compile/macros/mbe/macro49.rs: Add missing lang items. Signed-off-by: Owen Avery <[email protected]>
1 parent d4c6693 commit 5b7a0d7

File tree

6 files changed

+96
-5
lines changed

6 files changed

+96
-5
lines changed

gcc/rust/ast/rust-ast.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,7 +1137,9 @@ class Stmt : public Visitable
11371137

11381138
virtual void mark_for_strip () = 0;
11391139
virtual bool is_marked_for_strip () const = 0;
1140-
NodeId get_node_id () const { return node_id; }
1140+
1141+
// TODO: put this in a virtual base class?
1142+
virtual NodeId get_node_id () const { return node_id; }
11411143

11421144
virtual Kind get_stmt_kind () = 0;
11431145

@@ -1536,7 +1538,8 @@ class Type : public Visitable
15361538

15371539
virtual location_t get_locus () const = 0;
15381540

1539-
NodeId get_node_id () const { return node_id; }
1541+
// TODO: put this in a virtual base class?
1542+
virtual NodeId get_node_id () const { return node_id; }
15401543
virtual Type *reconstruct_impl () const = 0;
15411544

15421545
protected:
@@ -1799,6 +1802,8 @@ class AssociatedItem : public Visitable
17991802
virtual bool is_marked_for_strip () const = 0;
18001803

18011804
virtual location_t get_locus () const = 0;
1805+
1806+
virtual NodeId get_node_id () const = 0;
18021807
};
18031808

18041809
// Item used in trait declarations - abstract base class

gcc/rust/ast/rust-expr.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -865,13 +865,25 @@ class TypeCastExpr : public OperatorExpr
865865
return *main_or_left_expr;
866866
}
867867

868+
std::unique_ptr<Expr> &get_casted_expr_ptr ()
869+
{
870+
rust_assert (main_or_left_expr != nullptr);
871+
return main_or_left_expr;
872+
}
873+
868874
// TODO: is this better? Or is a "vis_block" better?
869875
TypeNoBounds &get_type_to_cast_to ()
870876
{
871877
rust_assert (type_to_convert_to != nullptr);
872878
return *type_to_convert_to;
873879
}
874880

881+
std::unique_ptr<TypeNoBounds> &get_type_to_cast_to_ptr ()
882+
{
883+
rust_assert (type_to_convert_to != nullptr);
884+
return type_to_convert_to;
885+
}
886+
875887
Expr::Kind get_expr_kind () const override { return Expr::Kind::TypeCast; }
876888

877889
protected:
@@ -2597,6 +2609,12 @@ class ClosureExprInner : public ClosureExpr
25972609
return *closure_inner;
25982610
}
25992611

2612+
std::unique_ptr<Expr> &get_definition_expr_ptr ()
2613+
{
2614+
rust_assert (closure_inner != nullptr);
2615+
return closure_inner;
2616+
}
2617+
26002618
protected:
26012619
/* Use covariance to implement clone function as returning this object rather
26022620
* than base */

gcc/rust/ast/rust-item.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,6 +1567,9 @@ class TypeAlias : public VisItem, public AssociatedItem
15671567

15681568
location_t get_locus () const override final { return locus; }
15691569

1570+
// needed to override AssociatedItem::get_node_id
1571+
NodeId get_node_id () const override final { return VisItem::get_node_id (); }
1572+
15701573
void accept_vis (ASTVisitor &vis) override;
15711574

15721575
// Invalid if existing type is null, so base stripping on that.
@@ -2515,6 +2518,9 @@ class ConstantItem : public VisItem, public AssociatedItem
25152518

25162519
location_t get_locus () const override final { return locus; }
25172520

2521+
// needed to override AssociatedItem::get_node_id
2522+
NodeId get_node_id () const override final { return VisItem::get_node_id (); }
2523+
25182524
void accept_vis (ASTVisitor &vis) override;
25192525

25202526
// Invalid if type or expression are null, so base stripping on that.

gcc/rust/expand/rust-expand-visitor.cc

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,10 +329,15 @@ ExpandVisitor::expand_inner_stmts (AST::BlockExpr &expr)
329329
void
330330
ExpandVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
331331
{
332+
NodeId old_expect = expr->get_node_id ();
333+
std::swap (macro_invoc_expect_id, old_expect);
334+
332335
expander.push_context (MacroExpander::ContextType::EXPR);
333336
expr->accept_vis (*this);
334337
expander.pop_context ();
335338

339+
std::swap (macro_invoc_expect_id, old_expect);
340+
336341
auto final_fragment = expander.take_expanded_fragment ();
337342
if (final_fragment.should_expand ()
338343
&& final_fragment.is_expression_fragment ())
@@ -342,14 +347,37 @@ ExpandVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
342347
void
343348
ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type)
344349
{
345-
expander.push_context (MacroExpander::ContextType::TYPE);
350+
NodeId old_expect = type->get_node_id ();
351+
std::swap (macro_invoc_expect_id, old_expect);
346352

353+
expander.push_context (MacroExpander::ContextType::TYPE);
347354
type->accept_vis (*this);
355+
expander.pop_context ();
356+
357+
std::swap (macro_invoc_expect_id, old_expect);
358+
348359
auto final_fragment = expander.take_expanded_fragment ();
349360
if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
350361
type = final_fragment.take_type_fragment ();
362+
}
363+
364+
// HACK: maybe we shouldn't have TypeNoBounds as a base class
365+
void
366+
ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type)
367+
{
368+
NodeId old_expect = type->get_node_id ();
369+
std::swap (macro_invoc_expect_id, old_expect);
351370

371+
expander.push_context (MacroExpander::ContextType::TYPE);
372+
type->accept_vis (*this);
352373
expander.pop_context ();
374+
375+
std::swap (macro_invoc_expect_id, old_expect);
376+
377+
auto final_fragment = expander.take_expanded_fragment ();
378+
if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
379+
type = std::make_unique<AST::ParenthesisedType> (
380+
final_fragment.take_type_fragment (), BUILTINS_LOCATION);
353381
}
354382

355383
// FIXME: Can this be refactored into a `scoped` method? Which takes a
@@ -465,6 +493,14 @@ ExpandVisitor::visit (AST::ConstGenericParam &)
465493
void
466494
ExpandVisitor::visit (AST::MacroInvocation &macro_invoc)
467495
{
496+
if (macro_invoc_expect_id != macro_invoc.get_node_id ())
497+
{
498+
rust_internal_error_at (
499+
macro_invoc.get_locus (),
500+
"attempting to expand node with id %d into position with node id %d",
501+
(int) macro_invoc.get_node_id (), (int) macro_invoc_expect_id);
502+
}
503+
468504
// TODO: Can we do the AST fragment replacing here? Probably not, right?
469505
expander.expand_invoc (macro_invoc, macro_invoc.has_semicolon ()
470506
? AST::InvocKind::Semicoloned
@@ -568,6 +604,13 @@ ExpandVisitor::visit (AST::LazyBooleanExpr &expr)
568604
maybe_expand_expr (expr.get_right_expr_ptr ());
569605
}
570606

607+
void
608+
ExpandVisitor::visit (AST::TypeCastExpr &expr)
609+
{
610+
maybe_expand_expr (expr.get_casted_expr_ptr ());
611+
maybe_expand_type (expr.get_type_to_cast_to_ptr ());
612+
}
613+
571614
void
572615
ExpandVisitor::visit (AST::AssignmentExpr &expr)
573616
{
@@ -615,7 +658,7 @@ ExpandVisitor::visit (AST::ClosureExprInner &expr)
615658
{
616659
expand_closure_params (expr.get_params ());
617660

618-
visit (expr.get_definition_expr ());
661+
maybe_expand_expr (expr.get_definition_expr_ptr ());
619662
}
620663

621664
void

gcc/rust/expand/rust-expand-visitor.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ bool is_builtin (AST::Attribute &attr);
3838
class ExpandVisitor : public AST::DefaultASTVisitor
3939
{
4040
public:
41-
ExpandVisitor (MacroExpander &expander) : expander (expander) {}
41+
ExpandVisitor (MacroExpander &expander)
42+
: expander (expander), macro_invoc_expect_id (UNKNOWN_NODEID)
43+
{}
4244

4345
/* Expand all of the macro invocations currently contained in a crate */
4446
void go (AST::Crate &crate);
@@ -56,6 +58,7 @@ class ExpandVisitor : public AST::DefaultASTVisitor
5658
type : Core guidelines R33, this function reseat the pointer.
5759
*/
5860
void maybe_expand_type (std::unique_ptr<AST::Type> &type);
61+
void maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type);
5962

6063
/**
6164
* Expand all macro invocations in lieu of types within a vector of struct
@@ -128,7 +131,10 @@ class ExpandVisitor : public AST::DefaultASTVisitor
128131
auto &value = *it;
129132

130133
// Perform expansion
134+
NodeId old_expect = value->get_node_id ();
135+
std::swap (macro_invoc_expect_id, old_expect);
131136
value->accept_vis (*this);
137+
std::swap (macro_invoc_expect_id, old_expect);
132138

133139
auto final_fragment = expander.take_expanded_fragment ();
134140

@@ -214,6 +220,7 @@ class ExpandVisitor : public AST::DefaultASTVisitor
214220
void visit (AST::ArithmeticOrLogicalExpr &expr) override;
215221
void visit (AST::ComparisonExpr &expr) override;
216222
void visit (AST::LazyBooleanExpr &expr) override;
223+
void visit (AST::TypeCastExpr &expr) override;
217224
void visit (AST::AssignmentExpr &expr) override;
218225
void visit (AST::CompoundAssignmentExpr &expr) override;
219226
void visit (AST::GroupedExpr &expr) override;
@@ -287,6 +294,7 @@ class ExpandVisitor : public AST::DefaultASTVisitor
287294

288295
private:
289296
MacroExpander &expander;
297+
NodeId macro_invoc_expect_id;
290298
};
291299

292300
} // namespace Rust

gcc/testsuite/rust/compile/macros/mbe/macro49.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
#[lang = "sized"]
2+
pub trait Sized {}
3+
4+
#[lang = "fn_once"]
5+
trait FnOnce<Args> {
6+
#[lang = "fn_once_output"]
7+
type Output;
8+
9+
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
10+
}
11+
112
macro_rules! closure {
213
() => {{
314
14 + 15

0 commit comments

Comments
 (0)