Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance improvements for CXX frontend #1363

Merged
merged 5 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 20 additions & 16 deletions cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/ScopeManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,6 @@ class ScopeManager : ScopeProvider {
*/
private val aliases = mutableMapOf<PhysicalLocation.ArtifactLocation, MutableSet<Alias>>()

/**
* The language frontend tied to the scope manager. Can be used to implement language specific
* scope resolution or lookup.
*/
var lang: LanguageFrontend<*, *>? = null

/** True, if the scope manager is currently in a [BlockScope]. */
val isInBlock: Boolean
get() = this.firstScopeOrNull { it is BlockScope } != null
Expand Down Expand Up @@ -568,10 +562,7 @@ class ScopeManager : ScopeProvider {
}
}

/**
* Only used by the [de.fraunhofer.aisec.cpg.graph.TypeManager], adds typedefs to the current
* [ValueDeclarationScope].
*/
/** Only used by the [TypeManager], adds typedefs to the current [ValueDeclarationScope]. */
fun addTypedef(typedef: TypedefDeclaration) {
val scope = this.firstScopeIsInstanceOrNull<ValueDeclarationScope>()
if (scope == null) {
Expand All @@ -580,12 +571,6 @@ class ScopeManager : ScopeProvider {
}

scope.addTypedef(typedef)

if (scope.astNode == null) {
lang?.currentTU?.addTypedef(typedef)
} else {
scope.astNode?.addTypedef(typedef)
}
}

private fun getCurrentTypedefs(searchScope: Scope?): Collection<TypedefDeclaration> {
Expand Down Expand Up @@ -878,6 +863,25 @@ class ScopeManager : ScopeProvider {
list += Alias(from, to)
}

fun typedefFor(alias: Type): Type? {
var current = currentScope

// We need to build a path from the current scope to the top most one. This ensures us that
// a local definition overwrites / shadows one that was there on a higher scope.
while (current != null) {
if (current is ValueDeclarationScope) {
val decl = current.typedefs[alias]
if (decl != null) {
return decl.type
}
}

current = current.parent
}

return null
}

/** Returns the current scope for the [ScopeProvider] interface. */
override val scope: Scope?
get() = currentScope
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,10 +252,7 @@ class TypeManager {

fun resolvePossibleTypedef(alias: Type, scopeManager: ScopeManager): Type {
val finalToCheck = alias.root
val applicable =
scopeManager.currentTypedefs
.firstOrNull { t: TypedefDeclaration -> t.alias.root == finalToCheck }
?.type
val applicable = scopeManager.typedefFor(finalToCheck)
return applicable ?: alias
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,6 @@ abstract class LanguageFrontend<in AstNode, TypeNode>(
val typeManager: TypeManager = ctx.typeManager
val config: TranslationConfiguration = ctx.config

init {
this.scopeManager.lang = this
}

var currentTU: TranslationUnitDeclaration? = null

@Throws(TranslationException::class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import de.fraunhofer.aisec.cpg.frontends.Language
import de.fraunhofer.aisec.cpg.graph.declarations.MethodDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.TypedefDeclaration
import de.fraunhofer.aisec.cpg.graph.edge.*
import de.fraunhofer.aisec.cpg.graph.edge.Properties
import de.fraunhofer.aisec.cpg.graph.scopes.GlobalScope
Expand Down Expand Up @@ -203,8 +202,6 @@ open class Node : IVisitable<Node>, Persistable, LanguageProvider, ScopeProvider
/** Virtual property for accessing the parents of the Program Dependence Graph (PDG). */
var prevPDG: MutableSet<Node> by PropertyEdgeSetDelegate(Node::prevPDGEdges, false)

var typedefs: MutableSet<TypedefDeclaration> = HashSet()

/**
* If a node is marked as being inferred, it means that it was created artificially and does not
* necessarily have a real counterpart in the scanned source code. However, the nodes
Expand Down Expand Up @@ -333,10 +330,6 @@ open class Node : IVisitable<Node>, Persistable, LanguageProvider, ScopeProvider
}
}

fun addTypedef(typedef: TypedefDeclaration) {
typedefs.add(typedef)
}

fun addAnnotations(annotations: Collection<Annotation>) {
this.annotations.addAll(annotations)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,21 @@ val Statement.cyclomaticComplexity: Int
// add one for each branch (and include the children)
stmt.caseExpression?.let { i += it.cyclomaticComplexity }
}
is DoStatement -> {
// add one for the do statement (and include the children)
i += (stmt.statement?.cyclomaticComplexity ?: 0) + 1
}
is WhileStatement -> {
// add one for the while statement (and include the children)
i += (stmt.statement?.cyclomaticComplexity ?: 0) + 1
}
is GotoStatement -> {
// add one
i++
}
is StatementHolder -> {
i += stmt.cyclomaticComplexity
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class DeclarationHandler(lang: CXXLanguageFrontend) :
* done yet.
*/
private fun handleUsingDirective(using: CPPASTUsingDirective): Declaration {
return newUsingDeclaration(using.rawSignature, using.qualifiedName.toString())
return newUsingDeclaration(qualifiedName = using.qualifiedName.toString(), rawNode = using)
}

/**
Expand Down Expand Up @@ -704,18 +704,15 @@ class DeclarationHandler(lang: CXXLanguageFrontend) :

fun handleTranslationUnit(translationUnit: IASTTranslationUnit): TranslationUnitDeclaration {
val node =
newTranslationUnitDeclaration(
translationUnit.filePath,
translationUnit.rawSignature,
translationUnit
)
newTranslationUnitDeclaration(translationUnit.filePath, rawNode = translationUnit)

// There might have been errors in the previous translation unit and in any case
// we need to reset the scope manager scope to global, to avoid spilling scope errors into
// other translation units
frontend.scopeManager.resetToGlobal(node)
frontend.currentTU = node
val problematicIncludes = HashMap<String?, HashSet<ProblemDeclaration>>()

for (declaration in translationUnit.declarations) {
if (declaration is CPPASTLinkageSpecification) {
continue // do not care about these for now
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ class DeclaratorHandler(lang: CXXLanguageFrontend) :
ctx.name.toString(),
unknownType(), // Type will be filled out later by
// handleSimpleDeclaration
ctx.rawSignature,
implicitInitializerAllowed,
implicitInitializerAllowed = implicitInitializerAllowed,
rawNode = ctx
)

// Add this declaration to the current scope
Expand All @@ -142,10 +142,10 @@ class DeclaratorHandler(lang: CXXLanguageFrontend) :
name.localName,
unknownType(),
emptyList(),
ctx.rawSignature,
frontend.locationOf(ctx),
initializer,
true
location = frontend.locationOf(ctx),
initializer = initializer,
implicitInitializerAllowed = true,
rawNode = ctx
)

frontend.scopeManager.addDeclaration(declaration)
Expand Down Expand Up @@ -401,19 +401,24 @@ class DeclaratorHandler(lang: CXXLanguageFrontend) :
val recordDeclaration = frontend.scopeManager.currentRecord
if (recordDeclaration == null) {
// variable
result = newVariableDeclaration(name, unknownType(), ctx.rawSignature, true)
result =
newVariableDeclaration(
name,
unknownType(),
implicitInitializerAllowed = true,
rawNode = ctx
)
} else {
// field
val code = ctx.rawSignature
result =
newFieldDeclaration(
name,
unknownType(),
emptyList(),
code,
frontend.locationOf(ctx),
null,
false,
location = frontend.locationOf(ctx),
initializer = null,
implicitInitializerAllowed = false,
rawNode = ctx
)
}

Expand All @@ -435,7 +440,7 @@ class DeclaratorHandler(lang: CXXLanguageFrontend) :
newRecordDeclaration(
ctx.name.toString(),
kind,
ctx.rawSignature,
rawNode = ctx,
)

// Handle C++ classes
Expand Down Expand Up @@ -483,7 +488,7 @@ class DeclaratorHandler(lang: CXXLanguageFrontend) :
private fun handleTemplateTypeParameter(
ctx: CPPASTSimpleTypeTemplateParameter
): TypeParameterDeclaration {
return newTypeParameterDeclaration(ctx.rawSignature, ctx.rawSignature, ctx)
return newTypeParameterDeclaration(ctx.rawSignature, rawNode = ctx)
}

private fun processMembers(ctx: IASTCompositeTypeSpecifier) {
Expand Down
Loading
Loading