Repository: joernio/joern (scala)

Issue:
oldc vs newc Parsing-Difference casting
I already mentioned the issue on Discord, but I think it makes sense to have them all on GitHub.
When looking at the arguments of a `<operator>.cast` call there is a difference between the new and old parser.

c code:
```c
(char*) buf;
```

newc:
```scala
joern> cpg.call.id(3074457345618261032L).argument.l 
res11: List[Expression] = List(
  Unknown(
    id -> 3074457345618261033L,
    argumentIndex -> 2,
    argumentName -> None,
    code -> "char*",
    columnNumber -> Some(value = 15),
    containedRef -> "<empty>",
    dynamicTypeHintFullName -> ArraySeq(),
    lineNumber -> Some(value = 9),
    order -> 2,
    parserTypeName -> "CASTTypeId",
    typeFullName -> "<empty>"
  ),
  Identifier(
    id -> 3074457345618261034L,
    argumentIndex -> 1,
    argumentName -> None,
    code -> "buf",
    columnNumber -> Some(value = 22),
    dynamicTypeHintFullName -> ArraySeq(),
    lineNumber -> Some(value = 9),
    name -> "buf",
    order -> 1,
    typeFullName -> "char[]"
  )
)
```

oldc:
```scala
joern> cpg.call.id(1000469L).argument.l 
res17: List[Expression] = List(
  Unknown(
    id -> 1000470L,
    argumentIndex -> 1,
    argumentName -> None,
    code -> "char*",
    columnNumber -> Some(value = 15),
    containedRef -> "<empty>",
    dynamicTypeHintFullName -> ArraySeq(),
    lineNumber -> Some(value = 9),
    order -> 1,
    parserTypeName -> "CastTarget",
    typeFullName -> "<empty>"
  ),
  Identifier(
    id -> 1000471L,
    argumentIndex -> 2,
    argumentName -> None,
    code -> "buf",
    columnNumber -> Some(value = 22),
    dynamicTypeHintFullName -> ArraySeq(),
    lineNumber -> Some(value = 9),
    name -> "buf",
    order -> 2,
    typeFullName -> "char [ ]"
  )
)
```

The big difference is that the order of the arguments is reversed. I think the old order is more intuitive as the casted type is in front of the variable.

The fix is probably just changing the numbers [here](https://github.com/joernio/joern/blob/master/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstForExpressionsCreator.scala#L219).

Pull request:
To be  consistent with the old frontend.

Fixes: https://github.com/joernio/joern/issues/776

Patch:
diff --git a/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstForExpressionsCreator.scala b/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstForExpressionsCreator.scala
index f7e3593b8908..4594b80ee27a 100644
--- a/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstForExpressionsCreator.scala
+++ b/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstForExpressionsCreator.scala
@@ -220,9 +220,9 @@ trait AstForExpressionsCreator {
     val cpgCastExpression =
       newCallNode(castExpression, Operators.cast, Operators.cast, DispatchTypes.STATIC_DISPATCH, order)
 
-    val expr = astForExpression(castExpression.getOperand, 1)
+    val expr = astForExpression(castExpression.getOperand, 2)
     val argNode = castExpression.getTypeId
-    val arg = newUnknown(argNode, 2)
+    val arg = newUnknown(argNode, 1)
 
     var ast = Ast(cpgCastExpression)
       .withChild(Ast(arg))
@@ -274,17 +274,16 @@ trait AstForExpressionsCreator {
     val cpgCastExpression =
       newCallNode(typeIdInit, Operators.cast, Operators.cast, DispatchTypes.STATIC_DISPATCH, order)
 
-    // TODO: how to represent the initializer here?
-    val expr = newUnknown(typeIdInit.getInitializer, 1)
+    val expr = astForNode(typeIdInit.getInitializer, 2)
 
     val typeNode = typeIdInit.getTypeId
-    val typeAst = newUnknown(typeNode, 2)
+    val typeAst = newUnknown(typeNode, 1)
 
-    Ast(cpgCastExpression)
+    val ast = Ast(cpgCastExpression)
       .withChild(Ast(typeAst))
-      .withChild(Ast(expr))
+      .withChild(expr)
       .withArgEdge(cpgCastExpression, typeAst)
-      .withArgEdge(cpgCastExpression, expr)
+    if (expr.root.isDefined) ast.withArgEdge(cpgCastExpression, expr.root.get) else ast
   }
 
   private def astForConstructorExpression(c: ICPPASTSimpleTypeConstructorExpression, order: Int): Ast = {
diff --git a/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstForTypesCreator.scala b/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstForTypesCreator.scala
index 31fbb52fead6..c20b44e52af6 100644
--- a/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstForTypesCreator.scala
+++ b/joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstForTypesCreator.scala
@@ -246,8 +246,8 @@ trait AstForTypesCreator {
               case d =>
                 astForDeclarator(declaration, d, order)
             }
-          case _ if declaration.getDeclarators.isEmpty => Seq(astForNode(declaration, order))
           case _ if nodeSignature(declaration) == ";"  => Seq.empty
+          case _ if declaration.getDeclarators.isEmpty => Seq(astForNode(declaration, order))
         }
       case alias: CPPASTAliasDeclaration                   => Seq(astForAliasDeclaration(alias, order))
       case functDef: IASTFunctionDefinition                => Seq(astForFunctionDefinition(functDef, order))


Test patch:
diff --git a/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/AstCreationPassTests.scala b/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/AstCreationPassTests.scala
index 8d800e88d3b5..01d0c2cd702b 100644
--- a/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/AstCreationPassTests.scala
+++ b/joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/AstCreationPassTests.scala
@@ -1180,8 +1180,8 @@ class AstCreationPassTests
     ) { cpg =>
       inside(cpg.call.name(Operators.cast).l) {
         case List(call: Call) =>
-          call.argument(1).code shouldBe "{ 1 }"
-          call.argument(2).code shouldBe "int"
+          call.argument(2).code shouldBe "{ 1 }"
+          call.argument(1).code shouldBe "int"
       }
     }
 
@@ -1365,11 +1365,11 @@ class AstCreationPassTests
         |""".stripMargin
     ) { cpg =>
       inside(cpg.call.name(Operators.cast).astChildren.l) {
-        case List(call: Call, tpe: Unknown) =>
+        case List(tpe: Unknown, call: Call) =>
           call.code shouldBe "end - str"
-          call.argumentIndex shouldBe 1
+          call.argumentIndex shouldBe 2
           tpe.code shouldBe "int"
-          tpe.argumentIndex shouldBe 2
+          tpe.argumentIndex shouldBe 1
       }
     }