diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/ScopeManager.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/ScopeManager.kt index 830bdf7f1ec..76de6e6baa4 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/ScopeManager.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/ScopeManager.kt @@ -621,9 +621,9 @@ class ScopeManager : ScopeProvider { * TODO: We should merge this function with [.resolveFunction] */ @JvmOverloads - fun resolveReference(ref: Reference, startScope: Scope? = currentScope): ValueDeclaration? { + fun resolveReference(ref: Reference, startScope: Scope? = ref.scope): ValueDeclaration? { // Retrieve a unique tag for the particular reference based on the current scope - val tag = ref.buildUniqueTag(startScope) + val tag = ref.uniqueTag // If we find a match in our symbol table, we can immediately return the declaration var decl = symbolTable[tag] diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/Reference.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/Reference.kt index 0c7c1922a4f..a70262fe62c 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/Reference.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/Reference.kt @@ -32,7 +32,6 @@ import de.fraunhofer.aisec.cpg.graph.declarations.Declaration import de.fraunhofer.aisec.cpg.graph.declarations.ValueDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration import de.fraunhofer.aisec.cpg.graph.edge.Properties -import de.fraunhofer.aisec.cpg.graph.scopes.Scope import de.fraunhofer.aisec.cpg.graph.types.HasType import de.fraunhofer.aisec.cpg.graph.types.Type import de.fraunhofer.aisec.cpg.passes.SymbolResolver @@ -160,8 +159,9 @@ open class Reference : Expression(), HasType.TypeObserver { * Its purpose is to cache symbol resolutions, similar to LLVMs system of Unified Symbol * Resolution (USR). */ - fun buildUniqueTag(startScope: Scope?): ReferenceTag { - return Objects.hash(this.name, this.resolutionHelper, startScope) + val uniqueTag: ReferenceTag + get() { + return Objects.hash(this.name, this.resolutionHelper, this.scope) } } diff --git a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/SymbolResolverTest.kt b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/SymbolResolverTest.kt index 0f141ca244f..24415bf6ee1 100644 --- a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/SymbolResolverTest.kt +++ b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/passes/SymbolResolverTest.kt @@ -31,6 +31,8 @@ import de.fraunhofer.aisec.cpg.TestUtils.assertRefersTo import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.statements.expressions.ConstructExpression import de.fraunhofer.aisec.cpg.graph.statements.expressions.MemberCallExpression +import de.fraunhofer.aisec.cpg.graph.statements.expressions.Reference +import de.fraunhofer.aisec.cpg.graph.statements.expressions.ReferenceTag import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertIs @@ -71,4 +73,23 @@ class SymbolResolverTest { assertNotNull(construct) assertInvokes(construct, constructor) } + + @Test + fun testUniqueTags() { + val result = GraphExamples.getConditionalExpression() + + val map = mutableMapOf>() + + val refs = result.refs + refs.forEach { + // Build a unique tag based on the scope of the reference is in (since this is usually + // the start scope) + val list = map.computeIfAbsent(it.uniqueTag) { mutableListOf() } + list += it + + // All elements in the list must have the same scope and name + assertEquals(1, list.map { ref -> ref.scope }.toSet().size) + assertEquals(1, list.map { ref -> ref.name }.toSet().size) + } + } }