Skip to content

Commit 427bac2

Browse files
Fix for types and namespaces with the same fullName. Fix for anonymous namespaces. Renamed namespace suffix to <extension> as this is what they actually represent.
1 parent aeb4b48 commit 427bac2

File tree

6 files changed

+50
-20
lines changed

6 files changed

+50
-20
lines changed

joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/AstCreatorHelper.scala

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,18 @@ trait AstCreatorHelper { this: AstCreator =>
6767
}
6868

6969
protected def scopeLocalUniqueNamespaceFullName(fullName: String): String = {
70-
scopeLocalUniqueNames.get(fullName) match {
70+
val newFullName = fullName match {
71+
case "" => "<namespace>"
72+
case s"$p." => s"$p.<namespace>"
73+
case other => other
74+
}
75+
scopeLocalUniqueNames.get(newFullName) match {
7176
case None =>
72-
scopeLocalUniqueNames.update(fullName, 0)
73-
fullName
77+
scopeLocalUniqueNames.update(newFullName, 0)
78+
newFullName
7479
case Some(index) =>
75-
val suffix = s"${Defines.DuplicateSuffix}$index"
76-
s"$fullName$suffix"
80+
val suffix = s"${Defines.NamespaceExtension}$index"
81+
s"$newFullName$suffix"
7782
}
7883
}
7984

joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/Defines.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ object Defines {
2323
val OperatorCall: String = "<operator>()"
2424
val OperatorNew: String = "<operator>.new"
2525
val DuplicateSuffix = "<duplicate>"
26+
val NamespaceExtension = "<extension>"
2627
val ConstSuffix = "<const>"
2728
val GlobalTag = "<global>"
2829
val UnknownTag = "<unknown>"

joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/FullNameProvider.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ object FullNameProvider {
2222
"<const>",
2323
"<duplicate>",
2424
"<enum>",
25+
"<extension>",
2526
"<global>",
2627
"<iterator>",
2728
"<lambda>",

joern-cli/frontends/c2cpg/src/main/scala/io/joern/c2cpg/astcreation/TypeNameProvider.scala

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,12 @@ trait TypeNameProvider { this: AstCreator =>
179179
val (uniqueName, uniqueNameFullName) = scopeLocalUniqueName(name_, fullName_, "enum")
180180
TypeFullNameInfo(uniqueName, uniqueNameFullName)
181181
case n: ICPPASTNamespaceDefinition =>
182-
val name_ = shortName(n)
182+
val name = shortName(n) match {
183+
case "" => "<namespace>"
184+
case other => other
185+
}
183186
val fullName_ = fullName(n)
184-
val (uniqueName, uniqueNameFullName) =
185-
scopeLocalUniqueName(name_, fullName_, "namespace")
186-
TypeFullNameInfo(uniqueName, scopeLocalUniqueNamespaceFullName(uniqueNameFullName))
187+
TypeFullNameInfo(name, scopeLocalUniqueNamespaceFullName(fullName_))
187188
case s: IASTCompositeTypeSpecifier =>
188189
val fullName_ = registerType(cleanType(fullName(s)))
189190
val name_ = shortName(s) match {

joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/cpp/features17/Cpp17FeaturesTests.scala

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,26 @@ class Cpp17FeaturesTests extends AstC2CpgSuite(fileSuffix = FileDefaults.CppExt)
320320
)
321321
}
322322

323+
"handle namespaces and classes with the same name" in {
324+
val cpg = code("""
325+
|namespace A {
326+
| class A {}
327+
|}
328+
|
329+
|namespace A {
330+
| class B {}
331+
|}
332+
|""".stripMargin)
333+
cpg.namespaceBlock.nameNot("<global>").name.sorted shouldBe Seq("A", "A")
334+
cpg.namespaceBlock.nameNot("<global>").fullName.sorted shouldBe Seq("Test0.cpp:A", "Test0.cpp:A<extension>0")
335+
336+
cpg.typeDecl.nameNot("<global>").name.sorted shouldBe Seq("A", "B")
337+
338+
// We get these fullNames directly from CDT, so they do not include the filename prefix.
339+
// Classes in anonymous namespaces have no fullName prefix at all according to the CDT fullName resolution.
340+
cpg.typeDecl.nameNot("<global>").fullName.sorted shouldBe Seq("A.A", "A.B")
341+
}
342+
323343
"handle the same namespace appearing multiple times in the same file" in {
324344
val cpg = code("""
325345
|namespace A { // old
@@ -351,8 +371,10 @@ class Cpp17FeaturesTests extends AstC2CpgSuite(fileSuffix = FileDefaults.CppExt)
351371
|}
352372
|""".stripMargin)
353373
cpg.namespaceBlock.nameNot("<global>").name.sorted shouldBe Seq(
354-
"<namespace>0",
355-
"<namespace>1",
374+
// Within a translation unit each unnamed namespace definition maps to the same unique name:
375+
// multiple unnamed namespace definitions in the same scope denote the same unnamed namespace
376+
"<namespace>",
377+
"<namespace>",
356378
"A",
357379
"A",
358380
"B",
@@ -363,16 +385,16 @@ class Cpp17FeaturesTests extends AstC2CpgSuite(fileSuffix = FileDefaults.CppExt)
363385
"X"
364386
)
365387
cpg.namespaceBlock.nameNot("<global>").fullName.sorted shouldBe Seq(
366-
"Test0.cpp:<namespace>0",
367-
"Test0.cpp:<namespace>1",
388+
"Test0.cpp:<namespace>",
389+
"Test0.cpp:<namespace><extension>0",
368390
"Test0.cpp:A",
369391
"Test0.cpp:A.B",
370392
"Test0.cpp:A.B.C",
371-
"Test0.cpp:A.B.C<duplicate>0",
372-
"Test0.cpp:A.B<duplicate>0",
373-
"Test0.cpp:A<duplicate>0",
393+
"Test0.cpp:A.B.C<extension>0",
394+
"Test0.cpp:A.B<extension>0",
395+
"Test0.cpp:A<extension>0",
374396
"Test0.cpp:X",
375-
"Test0.cpp:X<duplicate>0"
397+
"Test0.cpp:X<extension>0"
376398
)
377399
cpg.typeDecl.nameNot("<global>").name.sorted shouldBe Seq(
378400
"Bar",

joern-cli/frontends/c2cpg/src/test/scala/io/joern/c2cpg/passes/types/NamespaceTypeTests.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,9 @@ class NamespaceTypeTests extends C2CpgSuite(fileSuffix = FileDefaults.CppExt) {
119119
| j++; // ok, increments ::A::(unique)::j
120120
|}""".stripMargin)
121121
inside(cpg.namespaceBlock.nameNot("<global>").sortBy(_.fullName).l) { case List(unnamed1, namespaceA, unnamed2) =>
122-
unnamed1.fullName shouldBe "Test0.cpp:<namespace>0"
122+
unnamed1.fullName shouldBe "Test0.cpp:<namespace>"
123123
namespaceA.fullName shouldBe "Test0.cpp:A"
124-
unnamed2.fullName shouldBe "Test0.cpp:A.<namespace>0"
124+
unnamed2.fullName shouldBe "Test0.cpp:A.<namespace>"
125125
}
126126

127127
inside(cpg.method.internal.nameNot("<global>").fullName.l) { case List(f, g, h) =>
@@ -195,7 +195,7 @@ class NamespaceTypeTests extends C2CpgSuite(fileSuffix = FileDefaults.CppExt) {
195195
|}""".stripMargin)
196196
inside(cpg.namespaceBlock.nameNot("<global>").l) { case List(a1, a2) =>
197197
a1.fullName shouldBe "Test0.cpp:A"
198-
a2.fullName shouldBe "Test0.cpp:A<duplicate>0"
198+
a2.fullName shouldBe "Test0.cpp:A<extension>0"
199199
}
200200

201201
inside(cpg.method.internal.nameNot("<global>").l) { case List(foo, bar, f1, f2) =>

0 commit comments

Comments
 (0)