Skip to content

Commit 181a83c

Browse files
authored
[rust2cpg] fix macro call expr returning multiple statements. (#6224)
1 parent 529f827 commit 181a83c

2 files changed

Lines changed: 42 additions & 3 deletions

File tree

joern-cli/frontends/rust2cpg/src/main/scala/io/joern/rust2cpg/astcreation/RustVisitor.scala

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,11 +1643,9 @@ trait RustVisitor(implicit withSchemaValidation: ValidationMode) { this: AstCrea
16431643
// MacroExpr =
16441644
// MacroCall
16451645
private def visitMacroExpr(macroExpr: MacroExpr): Ast = {
1646-
// Even though it wraps a MacroCall, in this context it should always be a single expression, i.e.
1647-
// no MacroStmts/MacroItems. Logging just in case.
16481646
visitMacroCall(macroExpr.macroCall) match {
16491647
case exprAst :: Nil => exprAst
1650-
case _ => notHandledYet(macroExpr.macroCall)
1648+
case asts => blockAst(blockNode(macroExpr), asts.toList)
16511649
}
16521650
}
16531651

joern-cli/frontends/rust2cpg/src/test/scala/io/joern/rust2cpg/passes/ast/MacroTests.scala

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,47 @@ class MacroTests extends Rust2CpgSuite(noSysRoot = true) {
9999
}
100100
}
101101

102+
"macro call expression expanding to multiple statements" should {
103+
val cpg = code("""
104+
|macro_rules! three { () => { let mut s = 1; s += 2; s }; }
105+
|fn main() {
106+
| let x = { three!() };
107+
|}
108+
|""".stripMargin)
109+
110+
"have correct locals" in {
111+
inside(cpg.local.sortBy(_.order).l) { case xLocal :: sLocal :: Nil =>
112+
xLocal.name shouldBe "x"
113+
xLocal.typeFullName shouldBe "i32"
114+
sLocal.name shouldBe "s"
115+
sLocal.typeFullName shouldBe "i32"
116+
}
117+
}
118+
119+
"have correct assignments" in {
120+
cpg.method.nameExact("main").block.assignment.sortBy(_.order).code.l shouldBe List(
121+
"let x = { three!() };",
122+
"let mut s = 1;",
123+
"s+=2"
124+
)
125+
}
126+
127+
"have correct children" in {
128+
inside(cpg.method.nameExact("main").block.assignment.source.isBlock.astChildren.l) { case (three: Block) :: Nil =>
129+
inside(three.astChildren.l) {
130+
case (local: Local) :: (assign: Call) :: (assignPlus: Call) :: (ident: Identifier) :: Nil =>
131+
local.name shouldBe "s"
132+
assign.code shouldBe "let mut s = 1;"
133+
assign.methodFullName shouldBe Operators.assignment
134+
assignPlus.code shouldBe "s+=2"
135+
assignPlus.methodFullName shouldBe Operators.assignmentPlus
136+
ident.name shouldBe "s"
137+
ident.typeFullName shouldBe "i32"
138+
}
139+
}
140+
}
141+
}
142+
102143
"a type macro" should {
103144
val cpg = code("""
104145
|macro_rules! int_type { () => { i128 }; }

0 commit comments

Comments
 (0)