Skip to content

Commit

Permalink
Less test errors
Browse files Browse the repository at this point in the history
  • Loading branch information
oxisto committed Sep 8, 2023
1 parent 53aaa64 commit 5c7b07d
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ private constructor(
fun defaultPasses(): Builder {
registerPass<TypeHierarchyResolver>()
registerPass<ImportResolver>()
registerPass<MagicFixItPass>()
registerPass<SymbolResolver>()
registerPass<DFGPass>()
registerPass<EvaluationOrderGraphPass>() // creates EOG
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ import java.lang.reflect.Field
import java.util.*
import java.util.function.BiConsumer
import java.util.function.Consumer
import java.util.function.Predicate
import java.util.stream.Collectors
import org.neo4j.ogm.annotation.Relationship
import org.slf4j.LoggerFactory

Expand Down Expand Up @@ -258,6 +256,8 @@ object SubgraphWalker {
var backlog: Deque<Node>? = null
private set

var strategy: (Node) -> Iterator<Node> = Strategy::AST_FORWARD

/**
* This callback is triggered whenever a new node is visited for the first time. This is the
* place where usual graph manipulation will happen. The current node is the single argument
Expand Down Expand Up @@ -316,10 +316,7 @@ object SubgraphWalker {
Consumer { c: BiConsumer<Node, Node?> -> c.accept(current, parent) }
)
val unseenChildren =
getAstChildren(current)
.stream()
.filter(Predicate.not { o: Node -> seen.contains(o) })
.collect(Collectors.toList())
strategy(current).asSequence().filter { it !in seen }.toList()
seen.addAll(unseenChildren)
unseenChildren.asReversed().forEach { child: Node ->
(todo as ArrayDeque<Pair<Node, Node?>>).push(Pair(child, current))
Expand Down Expand Up @@ -359,15 +356,20 @@ object SubgraphWalker {
* resolving declarations or other scope-related tasks.
*/
class ScopedWalker {
lateinit var strategy: (Node) -> Iterator<Node>
private var walker: IterativeGraphWalker? = null
private val scopeManager: ScopeManager

constructor(lang: LanguageFrontend<*, *>) {
scopeManager = lang.scopeManager
}

constructor(scopeManager: ScopeManager) {
constructor(
scopeManager: ScopeManager,
strategy: (Node) -> Iterator<Node> = Strategy::AST_FORWARD
) {
this.scopeManager = scopeManager
this.strategy = strategy
}

/**
Expand Down Expand Up @@ -399,6 +401,7 @@ object SubgraphWalker {
*/
fun iterate(root: Node) {
walker = IterativeGraphWalker()
walker!!.strategy = this.strategy
handlers.forEach { h -> walker?.registerOnNodeVisit { n -> handleNode(n, h) } }
walker?.iterate(root)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1043,25 +1043,3 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa
}
}
}

/**
* This function injects the [next] node in-between the current [Node] and its [Node.nextEOG] nodes.
* This is needed if implicit nodes are created after the original EOG pass.
*/
fun Node.injectNextEOG(next: Node) {
// Store the references to the old "nextEOG"
val oldNext = this.nextEOG

// Clear next EOG and set it to our new next
this.nextEOG = listOf(next)
// Add us to the prevEOG of next
next.prevEOG += this
// Add the old nextEOGs to the nextEOG of new next
next.nextEOG += oldNext

// For each oldNext, replace "us" with the new next
oldNext.forEach {
it.prevEOGEdges.removeAll { edge -> edge.start == this }
it.prevEOG += next
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2023, Fraunhofer AISEC. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $$$$$$\ $$$$$$$\ $$$$$$\
* $$ __$$\ $$ __$$\ $$ __$$\
* $$ / \__|$$ | $$ |$$ / \__|
* $$ | $$$$$$$ |$$ |$$$$\
* $$ | $$ ____/ $$ |\_$$ |
* $$ | $$\ $$ | $$ | $$ |
* \$$$$$ |$$ | \$$$$$ |
* \______/ \__| \______/
*
*/
package de.fraunhofer.aisec.cpg.passes

import de.fraunhofer.aisec.cpg.TranslationContext
import de.fraunhofer.aisec.cpg.graph.Component
import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration
import de.fraunhofer.aisec.cpg.graph.newConstructExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.ConstructExpression
import de.fraunhofer.aisec.cpg.graph.types.recordDeclaration
import de.fraunhofer.aisec.cpg.helpers.SubgraphWalker
import de.fraunhofer.aisec.cpg.passes.order.ExecuteBefore

/**
* This [Pass] is magic. I think it's mostly used by C++, so we could make it specific. However, it
* also does certain things that the Go Extra Pass also does, so we could merge some aspects of it.
*/
@ExecuteBefore(EvaluationOrderGraphPass::class)
class MagicFixItPass(ctx: TranslationContext) : ComponentPass(ctx) {
override fun accept(component: Component) {
val walker = SubgraphWalker.ScopedWalker(ctx.scopeManager)

walker.registerHandler(::fixInitializers)
for (tu in component.translationUnits) {
walker.iterate(tu)
}
}

protected fun fixInitializers(node: Node?, currClass: RecordDeclaration?) {
if (node is VariableDeclaration) {
// check if we have the corresponding class for this type
val record = node.type.root.recordDeclaration
val typeString = node.type.root.name
if (record != null) {
val currInitializer = node.initializer
if (currInitializer == null && node.isImplicitInitializerAllowed) {
val initializer = node.newConstructExpression(typeString, "$typeString()")
initializer.type = node.type
initializer.isImplicit = true
node.initializer = initializer
node.templateParameters?.let {
SymbolResolver.addImplicitTemplateParametersToCall(it, initializer)
}
} else if (
currInitializer !is ConstructExpression &&
currInitializer is CallExpression &&
currInitializer.name.localName == node.type.root.name.localName
) {
// This should actually be a construct expression, not a call!
val arguments = currInitializer.arguments
val signature = arguments.map(Node::code).joinToString(", ")
val initializer =
node.newConstructExpression(typeString, "$typeString($signature)")
initializer.type = node.type
initializer.arguments = mutableListOf(*arguments.toTypedArray())
initializer.isImplicit = true
node.initializer = initializer
currInitializer.disconnectFromGraph()
}
}
}
}

override fun cleanup() {
// Nothing to do
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import de.fraunhofer.aisec.cpg.passes.inference.inferFunction
import de.fraunhofer.aisec.cpg.passes.inference.inferMethod
import de.fraunhofer.aisec.cpg.passes.inference.startInference
import de.fraunhofer.aisec.cpg.passes.order.DependsOn
import de.fraunhofer.aisec.cpg.processing.IVisitor
import de.fraunhofer.aisec.cpg.processing.strategy.Strategy
import java.util.*
import java.util.ArrayDeque
Expand Down Expand Up @@ -94,12 +93,6 @@ open class SymbolResolver(ctx: TranslationContext) : ComponentPass(ctx) {
walker.iterate(tu)
}

walker.clearCallbacks()
walker.registerHandler(::fixInitializers)
for (tu in component.translationUnits) {
walker.iterate(tu)
}

/*walker.registerHandler(::resolveFieldUsages)
for (tu in component.translationUnits) {
currentTU = tu
Expand All @@ -119,24 +112,17 @@ open class SymbolResolver(ctx: TranslationContext) : ComponentPass(ctx) {
walker.iterate(tu)
}*/

walker.strategy = Strategy::EOG_FORWARD
walker.clearCallbacks()
walker.registerHandler(::resolveCalls)
for (tu in component.translationUnits) {
currentTU = tu

// gather all resolution start holders and their start nodes
val nodes =
tu.allChildren<ResolutionStartHolder>().flatMap { it.resolutionStartNodes }.toSet()

for (node in nodes) {
// Traverse the EOG within the node
node.accept(
Strategy::EOG_FORWARD,
object : IVisitor<Node>() {
override fun visit(t: Node) {
scopeManager.jumpTo(t.scope)
resolveCalls(scopeManager.currentRecord, null, t)
}
}
)
walker.iterate(node)
}
}
}
Expand Down Expand Up @@ -513,44 +499,6 @@ open class SymbolResolver(ctx: TranslationContext) : ComponentPass(ctx) {
)
}

protected fun fixInitializers(node: Node?, currClass: RecordDeclaration?) {
if (node is VariableDeclaration) {
// check if we have the corresponding class for this type
val record = node.type.root.recordDeclaration
val typeString = node.type.root.name
if (record != null) {
val currInitializer = node.initializer
if (currInitializer == null && node.isImplicitInitializerAllowed) {
val initializer = node.newConstructExpression(typeString, "$typeString()")
initializer.type = node.type
initializer.isImplicit = true
node.initializer = initializer
// We need to make sure that the initializer is EOG-connected
node.injectNextEOG(initializer)
node.templateParameters?.let {
addImplicitTemplateParametersToCall(it, initializer)
}
} else if (
currInitializer !is ConstructExpression &&
currInitializer is CallExpression &&
currInitializer.name.localName == node.type.root.name.localName
) {
// This should actually be a construct expression, not a call!
val arguments = currInitializer.arguments
val signature = arguments.map(Node::code).joinToString(", ")
val initializer =
node.newConstructExpression(typeString, "$typeString($signature)")
initializer.type = node.type
initializer.arguments = mutableListOf(*arguments.toTypedArray())
initializer.isImplicit = true
node.initializer = initializer
node.injectNextEOG(initializer)
currInitializer.disconnectFromGraph()
}
}
}
}

protected fun resolveCalls(currClass: RecordDeclaration?, parent: Node?, node: Node?) {
when (node) {
is TranslationUnitDeclaration -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1444,6 +1444,7 @@ internal class CXXLanguageFrontendTest : BaseTest() {
analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), false) {
it.registerPass<TypeHierarchyResolver>()
it.registerPass<ImportResolver>()
it.registerPass<MagicFixItPass>()
it.registerPass<SymbolResolver>()
it.registerPass<DFGPass>()
it.registerPass<EvaluationOrderGraphPass>() // creates EOG
Expand Down Expand Up @@ -1491,6 +1492,7 @@ internal class CXXLanguageFrontendTest : BaseTest() {
analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), false) {
it.registerPass<TypeHierarchyResolver>()
it.registerPass<ImportResolver>()
it.registerPass<MagicFixItPass>()
it.registerPass<SymbolResolver>()
it.registerPass<DFGPass>()
it.registerPass<EvaluationOrderGraphPass>() // creates EOG
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ void printLog(string logId, string message){
cout << logId << ": " << message << endl;
}

class error;

class ScopeVariables{
public:
string varName = "instance_field";
Expand Down Expand Up @@ -44,8 +46,8 @@ class ScopeVariables{
}

try {
throw string("exception_string");
} catch (const string& varName) {
throw new error();
} catch (const error& varName) {
printLog("func2_catch_varName", varName);
};
ScopeVariables scopeVariables;
Expand Down

0 comments on commit 5c7b07d

Please sign in to comment.