Skip to content

Commit

Permalink
[c2cpg] Fix missing type register call for implicit this access (#5219)
Browse files Browse the repository at this point in the history
also fix type cleaning
  • Loading branch information
max-leuthaeuser authored Jan 10, 2025
1 parent d657796 commit d427219
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As
}

// Sadly, there is no predefined List / Enum of this within Eclipse CDT:
private val ReservedTypeKeywords: List[String] =
private val ReservedKeywordsAtTypes: List[String] =
List(
"const",
"static",
Expand All @@ -142,51 +142,48 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As
"class"
)

private val KeepTypeKeywords: List[String] = List("unsigned", "volatile", "const", "static")
private val KeywordsAtTypesToKeep: List[String] = List("unsigned", "volatile", "static", "const")

protected def cleanType(rawType: String, stripKeywords: Boolean = true): String = {
if (rawType == Defines.Any) return rawType
val tpe =
if (stripKeywords) {
ReservedTypeKeywords.foldLeft(rawType) { (cur, repl) =>
if (cur.startsWith(s"$repl ") || cur.contains(s" $repl ")) {
cur.replace(s" $repl ", " ").replace(s"$repl ", "")
} else cur
}
} else {
rawType
val tpe = if (stripKeywords) {
ReservedKeywordsAtTypes.foldLeft(rawType) { (cur, repl) =>
if (cur.startsWith(s"$repl ") || cur.contains(s" $repl ")) {
cur.replace(s" $repl ", " ").replace(s"$repl ", "")
} else cur
}
StringUtils.normalizeSpace(tpe.stripSuffix(" ()")) match {
} else {
rawType
}
val normalizedTpe = StringUtils.normalizeSpace(tpe.stripSuffix(" ()"))
replaceWhitespaceAfterKeyword(normalizedTpe) match {
case "" => Defines.Any
case t if t.startsWith("[*this]") || t.startsWith("[this]") => t
case t if t.startsWith("[*this]") || t.startsWith("[this]") => normalizedTpe
case t if t.startsWith("[") && t.endsWith("]") => Defines.Array
case t if t.contains("->") => Defines.Function
case t if t.contains("?") => Defines.Any
case t if t.contains("#") => Defines.Any
case t if t.contains("::{") || t.contains("}::") => Defines.Any
case t if t.contains("{") || t.contains("}") => Defines.Any
case t if t.contains("org.eclipse.cdt.internal.core.dom.parser.ProblemType") => Defines.Any
case t if t.contains("( ") => replaceWhitespaceAfterTypeKeyword(fixQualifiedName(t.substring(0, t.indexOf("( "))))
case t if t.contains(Defines.QualifiedNameSeparator) => replaceWhitespaceAfterTypeKeyword(fixQualifiedName(t))
case t if KeepTypeKeywords.exists(k => t.startsWith(s"$k ")) => replaceWhitespaceAfterTypeKeyword(t)
case t if t.contains("[") && t.contains("]") => replaceWhitespaceAfterTypeKeyword(t)
case t if t.contains("<") && t.contains(">") => replaceWhitespaceAfterTypeKeyword(t)
case t if t.contains("*") => replaceWhitespaceAfterTypeKeyword(t)
case someType => someType
case t if t.contains("( ") => fixQualifiedName(t.substring(0, t.indexOf("( ")))
case t if t.contains(Defines.QualifiedNameSeparator) => fixQualifiedName(t)
case someType => someType
}
}

private def replaceWhitespaceAfterTypeKeyword(tpe: String): String = {
if (KeepTypeKeywords.exists(k => tpe.startsWith(s"$k ") || tpe.contains(s" $k "))) {
KeepTypeKeywords.foldLeft(tpe) { (cur, repl) =>
private def replaceWhitespaceAfterKeyword(tpe: String): String = {
val keywordsToKeep = ReservedKeywordsAtTypes ++ KeywordsAtTypesToKeep
if (keywordsToKeep.exists(k => tpe.startsWith(s"$k ") || tpe.contains(s" $k "))) {
keywordsToKeep.foldLeft(tpe) { (cur, repl) =>
val prefixStartsWith = s"$repl "
val prefixContains = s" $repl "
if (cur.startsWith(prefixStartsWith)) {
prefixStartsWith + replaceWhitespaceAfterTypeKeyword(cur.substring(prefixStartsWith.length))
prefixStartsWith + replaceWhitespaceAfterKeyword(cur.substring(prefixStartsWith.length))
} else if (cur.contains(prefixContains)) {
val front = tpe.substring(0, tpe.indexOf(prefixContains))
val back = tpe.substring(tpe.indexOf(prefixContains) + prefixContains.length)
s"${replaceWhitespaceAfterTypeKeyword(front)}$prefixContains${replaceWhitespaceAfterTypeKeyword(back)}"
s"${replaceWhitespaceAfterKeyword(front)}$prefixContains${replaceWhitespaceAfterKeyword(back)}"
} else {
cur
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ trait AstForPrimitivesCreator(implicit withSchemaValidation: ValidationMode) { t

private def syntheticThisAccess(ident: CPPASTIdExpression, identifierName: String): String | Ast = {
val tpe = ident.getName.getBinding match {
case f: CPPField => cleanType(f.getType.toString)
case f: CPPField => f.getType.toString
case _ => typeFor(ident)
}
Try(ident.getEvaluation).toOption match {
Expand All @@ -125,7 +125,8 @@ trait AstForPrimitivesCreator(implicit withSchemaValidation: ValidationMode) { t
val code = s"this->$identifierName"
val thisIdentifier = identifierNode(ident, "this", "this", ownerType)
val member = fieldIdentifierNode(ident, identifierName, identifierName)
val ma = callNode(ident, code, op, op, DispatchTypes.STATIC_DISPATCH, None, Some(tpe))
val ma =
callNode(ident, code, op, op, DispatchTypes.STATIC_DISPATCH, None, Some(registerType(cleanType(tpe))))
callAst(ma, Seq(Ast(thisIdentifier).withRefEdge(thisIdentifier, variable), Ast(member)))
case None => tpe
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,13 @@ class ClassTypeTests extends C2CpgSuite(FileDefaults.CppExt) {
del.name shouldBe "delete"
del.fullName shouldBe "Foo.delete:void(void*)"
eq.name shouldBe "=="
eq.fullName shouldBe "Foo.==:bool(Foo &,Foo &)"
eq.fullName shouldBe "Foo.==:bool(Foo&,Foo&)"
plus.name shouldBe "+"
plus.fullName shouldBe "Foo.+:Foo &(Foo &,Foo &)"
plus.fullName shouldBe "Foo.+:Foo&(Foo&,Foo&)"
apply.name shouldBe "()"
apply.fullName shouldBe "Foo.():Foo &(Foo &)"
apply.fullName shouldBe "Foo.():Foo&(Foo&)"
idx.name shouldBe "[]"
idx.fullName shouldBe "Foo.[]:Foo &(int)"
idx.fullName shouldBe "Foo.[]:Foo&(int)"
}

"generate correct fullnames in classes with conversions" in {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,18 @@ class LocalQueryTests extends C2CpgSuite {
"""
|void foo() {
| static const Foo::Bar bar{};
| static extern std::vector<int> vec;
|}
|""".stripMargin,
"test.cpp"
)
val List(barLocal) = cpg.method.name("foo").local.l
barLocal.name shouldBe "bar"
val List(barLocal) = cpg.method.name("foo").local.nameExact("bar").l
barLocal.typeFullName shouldBe "Foo.Bar"
barLocal.code shouldBe "static const Foo.Bar bar"

val List(vecLocal) = cpg.method.name("foo").local.nameExact("vec").l
vecLocal.typeFullName shouldBe "std.vector<int>"
vecLocal.code shouldBe "static extern std.vector<int> vec"
}
}

Expand Down

0 comments on commit d427219

Please sign in to comment.