diff --git a/cpg-console/src/main/kotlin/de/fraunhofer/aisec/cpg/console/Extensions.kt b/cpg-console/src/main/kotlin/de/fraunhofer/aisec/cpg/console/Extensions.kt index 5a233a8602..4dcb8101a1 100644 --- a/cpg-console/src/main/kotlin/de/fraunhofer/aisec/cpg/console/Extensions.kt +++ b/cpg-console/src/main/kotlin/de/fraunhofer/aisec/cpg/console/Extensions.kt @@ -244,7 +244,7 @@ fun getFanciesFor(original: Node?, node: Node?): List> ) { - val types = outer.language?.primitiveTypeNames?.toMutableSet() ?: mutableSetOf() + val types = outer.language.primitiveTypeNames.toMutableSet() types += node.type.name.toString() // check for primitive types 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 c14dd1b970..4c691cb6b8 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 @@ -532,7 +532,8 @@ class ScopeManager : ScopeProvider { helper?.type is FunctionPointerType && it is FunctionDeclaration -> { val fptrType = helper.type as FunctionPointerType // TODO(oxisto): Support multiple return values - val returnType = it.returnTypes.firstOrNull() ?: IncompleteType() + val returnType = + it.returnTypes.firstOrNull() ?: IncompleteType(ref.language) returnType == fptrType.returnType && it.matchesSignature(fptrType.parameters) != IncompatibleSignature diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TranslationResult.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TranslationResult.kt index 7b4b3ddfb6..5372e73840 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TranslationResult.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TranslationResult.kt @@ -25,7 +25,9 @@ */ package de.fraunhofer.aisec.cpg +import de.fraunhofer.aisec.cpg.frontends.Language import de.fraunhofer.aisec.cpg.frontends.LanguageFrontend +import de.fraunhofer.aisec.cpg.frontends.multiLanguage import de.fraunhofer.aisec.cpg.graph.Component import de.fraunhofer.aisec.cpg.graph.Name import de.fraunhofer.aisec.cpg.graph.Node @@ -173,6 +175,12 @@ class TranslationResult( override val config: TranslationConfiguration get() = finalCtx.config + override var language: Language<*> + get() { + return multiLanguage() + } + set(_) {} + companion object { const val SOURCE_LOCATIONS_TO_FRONTEND = "sourceLocationsToFrontend" const val APPLICATION_LOCAL_NAME = "application" diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TypeManager.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TypeManager.kt index 61b0d0f0be..12b24e9e00 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TypeManager.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/TypeManager.kt @@ -25,7 +25,6 @@ */ package de.fraunhofer.aisec.cpg -import de.fraunhofer.aisec.cpg.frontends.CastNotPossible import de.fraunhofer.aisec.cpg.frontends.CastResult import de.fraunhofer.aisec.cpg.frontends.Language import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration @@ -183,7 +182,7 @@ class TypeManager { fun createOrGetTypeParameter( templateDeclaration: TemplateDeclaration, typeName: String, - language: Language<*>? + language: Language<*> ): ParameterizedType { var parameterizedType = getTypeParameter(templateDeclaration, typeName) if (parameterizedType == null) { @@ -271,7 +270,7 @@ internal fun Type.getAncestors(depth: Int): Set { * Optionally, the nodes that hold the respective type can be supplied as [hint] and [targetHint]. */ fun Type.tryCast(targetType: Type, hint: HasType? = null, targetHint: HasType? = null): CastResult { - return this.language?.tryCast(this, targetType, hint, targetHint) ?: CastNotPossible + return this.language.tryCast(this, targetType, hint, targetHint) } /** @@ -351,7 +350,7 @@ val Collection.commonType: Type? context(Pass<*>) fun Reference.nameIsType(): Type? { // First, check if it is a simple type - var type = language?.getSimpleTypeOf(name) + var type = language.getSimpleTypeOf(name) if (type != null) { return type } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/Language.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/Language.kt index a2c0c5d9e2..4620dcae5c 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/Language.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/Language.kt @@ -33,6 +33,7 @@ import com.fasterxml.jackson.databind.annotation.JsonSerialize import de.fraunhofer.aisec.cpg.* import de.fraunhofer.aisec.cpg.graph.Name import de.fraunhofer.aisec.cpg.graph.Node +import de.fraunhofer.aisec.cpg.graph.OverlayNode import de.fraunhofer.aisec.cpg.graph.declarations.Declaration import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration import de.fraunhofer.aisec.cpg.graph.edges.ast.TemplateArguments @@ -78,11 +79,12 @@ data class ImplicitCast(override var depthDistance: Int) : CastResult(depthDista * the [Node.language] property. */ abstract class Language> : Node() { + /** The file extensions without the dot */ abstract val fileExtensions: List /** The namespace delimiter used by the language. Often, this is "." */ - abstract val namespaceDelimiter: String + open val namespaceDelimiter: String = "." @get:JsonSerialize(using = KClassSerializer::class) /** The class of the frontend which is used to parse files of this language. */ @@ -146,10 +148,8 @@ abstract class Language> : Node() { } init { - this.also { language -> - this.language = language - language::class.simpleName?.let { this.name = Name(it) } - } + this.language = this + this::class.simpleName?.let { this.name = Name(it) } } private fun arithmeticOpTypePropagation(lhs: Type, rhs: Type): Type { @@ -158,8 +158,8 @@ abstract class Language> : Node() { lhs !is FloatingPointType && lhs is NumericType && rhs is FloatingPointType -> rhs lhs is FloatingPointType && rhs is FloatingPointType || lhs is IntegerType && rhs is IntegerType -> - // We take the one with the bigger bitwidth - if (((lhs as NumericType).bitWidth ?: 0) >= ((rhs as NumericType).bitWidth ?: 0)) { + // We take the one with the bigger bit-width + if ((lhs.bitWidth ?: 0) >= (rhs.bitWidth ?: 0)) { lhs } else { rhs @@ -239,8 +239,8 @@ abstract class Language> : Node() { /** * This function checks, if [type] can be cast into [targetType]. Note, this also takes the - * [WrapState] of the type into account, which means that pointer types of derived types will - * not match with a non-pointer type of its base type. But, if both are pointer types, they will + * "type" of the type into account, which means that pointer types of derived types will not + * match with a non-pointer type of its base type. But, if both are pointer types, they will * match. * * Optionally, the nodes that hold the respective type can be supplied as [hint] and @@ -400,3 +400,54 @@ internal class KClassSerializer : JsonSerializer>() { gen.writeString(value.qualifiedName) } } + +/** + * Represents a language definition with no known implementation or specifics. The class is used as + * a placeholder or to handle cases where the language is not explicitly defined or supported. + */ +object UnknownLanguage : Language() { + override val fileExtensions: List + get() = listOf() + + override val frontend: KClass = Nothing::class + override val builtInTypes: Map = mapOf() + override val compoundAssignmentOperators: Set = setOf() +} + +/** + * Represents a "language" that is not really a language. The class is used in cases where the + * language is not explicitly defined or supported, for example in an [OverlayNode]. + */ +object NoLanguage : Language() { + override val fileExtensions = listOf() + override val frontend: KClass = Nothing::class + override val builtInTypes: Map = mapOf() + override val compoundAssignmentOperators: Set = setOf() +} + +/** + * Represents a composite language definition composed of multiple languages. + * + * @property languages A list of languages that are part of this composite language definition. + */ +class MultipleLanguages(val languages: Set>) : Language() { + override val fileExtensions = languages.flatMap { it.fileExtensions } + override val frontend: KClass = Nothing::class + override val builtInTypes: Map = mapOf() + override val compoundAssignmentOperators: Set = setOf() +} + +/** + * Returns the single language of a node and its children. If the node has multiple children with + * different languages, it returns a [MultipleLanguages] object. + */ +fun Node.multiLanguage(): Language<*> { + val languages = astChildren.map { it.language }.toSet() + return if (languages.size == 1) { + languages.single() + } else if (languages.size > 1) { + MultipleLanguages(languages = languages) + } else { + UnknownLanguage + } +} diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Component.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Component.kt index 10f4edaf7d..1fbdabecca 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Component.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Component.kt @@ -26,6 +26,8 @@ package de.fraunhofer.aisec.cpg.graph import de.fraunhofer.aisec.cpg.PopulatedByPass +import de.fraunhofer.aisec.cpg.frontends.Language +import de.fraunhofer.aisec.cpg.frontends.multiLanguage import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration import de.fraunhofer.aisec.cpg.graph.edges.ast.astEdgesOf import de.fraunhofer.aisec.cpg.graph.edges.unwrapping @@ -65,4 +67,10 @@ open class Component : Node() { /** All outgoing interactions such as sending data to the network or some kind of IPC. */ val outgoingInteractions: MutableList = mutableListOf() + + override var language: Language<*> + get() { + return multiLanguage() + } + set(_) {} } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Interfaces.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Interfaces.kt index 103a71d9ad..cbc4a74dd7 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Interfaces.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Interfaces.kt @@ -37,7 +37,7 @@ import de.fraunhofer.aisec.cpg.sarif.PhysicalLocation /** A simple interface that a node has [language]. */ interface HasLanguage { - var language: Language<*>? + var language: Language<*> } /** A simple interface that a node has [name] and [location]. */ diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Name.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Name.kt index c8cf38536a..7490ca519e 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Name.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Name.kt @@ -141,8 +141,9 @@ class Name( * (such as a [Node], a [Language], a [LanguageFrontend] or a [Handler]) to parse a fully qualified * name. */ -fun LanguageProvider?.parseName(fqn: CharSequence) = - parseName(fqn, this?.language?.namespaceDelimiter ?: ".") +fun LanguageProvider.parseName(fqn: CharSequence): Name { + return parseName(fqn, this.language.namespaceDelimiter) +} /** Tries to parse the given fully qualified name using the specified [delimiter] into a [Name]. */ internal fun parseName(fqn: CharSequence, delimiter: String, vararg splitDelimiters: String): Name { diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Node.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Node.kt index d0ba1a34b3..7ada182428 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Node.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/Node.kt @@ -32,6 +32,7 @@ import de.fraunhofer.aisec.cpg.TranslationContext import de.fraunhofer.aisec.cpg.TypeManager import de.fraunhofer.aisec.cpg.frontends.Handler import de.fraunhofer.aisec.cpg.frontends.Language +import de.fraunhofer.aisec.cpg.frontends.UnknownLanguage import de.fraunhofer.aisec.cpg.graph.declarations.MethodDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration @@ -93,7 +94,7 @@ abstract class Node : */ @Relationship(value = "LANGUAGE", direction = Relationship.Direction.OUTGOING) @JsonBackReference - override var language: Language<*>? = null + override var language: Language<*> = UnknownLanguage /** * The scope this node "lives" in / in which it is defined. This property is set in diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/NodeBuilder.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/NodeBuilder.kt index 5a2e01a263..fa5140d650 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/NodeBuilder.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/NodeBuilder.kt @@ -59,7 +59,7 @@ interface MetadataProvider * each [Node], but also transformation steps, such as [Handler]. */ interface LanguageProvider : MetadataProvider { - val language: Language<*>? + val language: Language<*> } /** diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/OverlayNode.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/OverlayNode.kt index d187aee975..e92021c0b7 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/OverlayNode.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/OverlayNode.kt @@ -25,6 +25,7 @@ */ package de.fraunhofer.aisec.cpg.graph +import de.fraunhofer.aisec.cpg.frontends.NoLanguage import de.fraunhofer.aisec.cpg.graph.edges.overlay.OverlaySingleEdge import de.fraunhofer.aisec.cpg.graph.edges.unwrapping import org.neo4j.ogm.annotation.Relationship @@ -34,6 +35,11 @@ import org.neo4j.ogm.annotation.Relationship * typically having shared edges to extend the original graph. */ abstract class OverlayNode() : Node() { + + init { + this.language = NoLanguage + } + @Relationship(value = "OVERLAY", direction = Relationship.Direction.INCOMING) /** All [OverlayNode]s nodes are connected to an original cpg [Node] by this. */ val underlyingNodeEdge: OverlaySingleEdge = diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/TypeBuilder.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/TypeBuilder.kt index 10f318283f..ce43d403a2 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/TypeBuilder.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/TypeBuilder.kt @@ -45,8 +45,8 @@ fun LanguageProvider.autoType(): Type { return AutoType(this.language) } -fun MetadataProvider?.incompleteType(): Type { - return IncompleteType() +fun LanguageProvider.incompleteType(): Type { + return IncompleteType(this.language) } /** Returns a [PointerType] that describes an array reference to the current type. */ diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ValueDeclaration.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ValueDeclaration.kt index b87b0c382e..0fb0017658 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ValueDeclaration.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/declarations/ValueDeclaration.kt @@ -27,6 +27,7 @@ package de.fraunhofer.aisec.cpg.graph.declarations import de.fraunhofer.aisec.cpg.PopulatedByPass import de.fraunhofer.aisec.cpg.frontends.Language +import de.fraunhofer.aisec.cpg.frontends.UnknownLanguage import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.edges.flows.Usages import de.fraunhofer.aisec.cpg.graph.edges.unwrapping @@ -44,11 +45,11 @@ abstract class ValueDeclaration : Declaration(), HasType, HasAliases { override val typeObservers: MutableSet = identitySetOf() - override var language: Language<*>? = null + override var language: Language<*> = UnknownLanguage set(value) { // We need to adjust an eventual unknown type, once we know the language field = value - if (value != null && type is UnknownType) { + if (type is UnknownType) { type = UnknownType.getUnknownType(value) } } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/AssignExpression.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/AssignExpression.kt index 89ae115c2a..a265648530 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/AssignExpression.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/AssignExpression.kt @@ -110,7 +110,7 @@ class AssignExpression : */ val isCompoundAssignment: Boolean get() { - return operatorCode in (language?.compoundAssignmentOperators ?: setOf()) + return operatorCode in language.compoundAssignmentOperators } /** @@ -120,7 +120,7 @@ class AssignExpression : */ val isSimpleAssignment: Boolean get() { - return operatorCode in (language?.simpleAssignmentOperators ?: setOf()) + return operatorCode in language.simpleAssignmentOperators } @Relationship("DECLARATIONS") var declarationEdges = astEdgesOf() diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/BinaryOperator.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/BinaryOperator.kt index 06cce9f422..17cc2e543f 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/BinaryOperator.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/BinaryOperator.kt @@ -68,11 +68,11 @@ open class BinaryOperator : set(value) { field = value if ( - (operatorCode in (language?.compoundAssignmentOperators ?: setOf())) || - (operatorCode == "=") + (operatorCode in language.compoundAssignmentOperators) || + (operatorCode in language.simpleAssignmentOperators) ) { throw TranslationException( - "Creating a BinaryOperator with an assignment operator code is not allowed. The class AssignExpression should be used instead." + "Creating a BinaryOperator with an assignment operator code is not allowed. The class AssignExpression must be used instead." ) } } @@ -95,14 +95,8 @@ open class BinaryOperator : this.type = newType } else { // Otherwise, we have a special language-specific function to deal with type propagation - val type = language?.propagateTypeOfBinaryOperation(this) - if (type != null) { - this.type = type - } else { - // If we don't know how to propagate the types of this particular binary operation, - // we just leave the type alone. We cannot take newType because it is just "half" of - // the operation (either from lhs or rhs) and would lead to very incorrect results. - } + val type = language.propagateTypeOfBinaryOperation(this) + this.type = type } } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/Expression.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/Expression.kt index 409fefcfd7..285564988c 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/Expression.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/expressions/Expression.kt @@ -26,6 +26,7 @@ package de.fraunhofer.aisec.cpg.graph.statements.expressions import de.fraunhofer.aisec.cpg.frontends.Language +import de.fraunhofer.aisec.cpg.frontends.UnknownLanguage import de.fraunhofer.aisec.cpg.graph.* import de.fraunhofer.aisec.cpg.graph.statements.Statement import de.fraunhofer.aisec.cpg.graph.types.* @@ -49,11 +50,11 @@ import org.neo4j.ogm.annotation.Transient abstract class Expression : Statement(), HasType { @Transient override val typeObservers: MutableSet = identitySetOf() - override var language: Language<*>? = null + override var language: Language<*> = UnknownLanguage set(value) { // We need to adjust an eventual unknown type, once we know the language field = value - if (value != null && type is UnknownType) { + if (type is UnknownType) { type = UnknownType.getUnknownType(value) } } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/AutoType.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/AutoType.kt index 681790d96d..2dcca508e3 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/AutoType.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/AutoType.kt @@ -35,7 +35,7 @@ import de.fraunhofer.aisec.cpg.graph.unknownType * * Note: This is intentionally a distinct type and not the [UnknownType]. */ -class AutoType(override var language: Language<*>?) : Type("auto", language) { +class AutoType(override var language: Language<*>) : Type("auto", language) { override fun reference(pointer: PointerType.PointerOrigin?): Type { return PointerType(this, pointer) } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/BooleanType.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/BooleanType.kt index 2acab30cfc..7ae986fa55 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/BooleanType.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/BooleanType.kt @@ -31,6 +31,6 @@ import de.fraunhofer.aisec.cpg.frontends.Language class BooleanType( typeName: CharSequence = "bool", bitWidth: Int? = 1, - language: Language<*>? = null, + language: Language<*>, modifier: Modifier = Modifier.NOT_APPLICABLE ) : NumericType(typeName, bitWidth, language, modifier) diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/FloatingPointType.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/FloatingPointType.kt index 542cf881d5..a6b60fc9fe 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/FloatingPointType.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/FloatingPointType.kt @@ -31,6 +31,6 @@ import de.fraunhofer.aisec.cpg.frontends.Language class FloatingPointType( typeName: CharSequence = "", bitWidth: Int? = null, - language: Language<*>? = null, + language: Language<*>, modifier: Modifier = Modifier.SIGNED ) : NumericType(typeName, bitWidth, language, modifier) diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/FunctionPointerType.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/FunctionPointerType.kt index ad2660733f..56c3f1e534 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/FunctionPointerType.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/FunctionPointerType.kt @@ -26,6 +26,7 @@ package de.fraunhofer.aisec.cpg.graph.types import de.fraunhofer.aisec.cpg.frontends.Language +import de.fraunhofer.aisec.cpg.frontends.UnknownLanguage import de.fraunhofer.aisec.cpg.graph.types.PointerType.PointerOrigin import java.util.* import org.apache.commons.lang3.builder.ToStringBuilder @@ -48,7 +49,7 @@ class FunctionPointerType : Type { constructor( parameters: List = listOf(), - language: Language<*>? = null, + language: Language<*>, returnType: Type = UnknownType.getUnknownType(language) ) : super(EMPTY_NAME, language) { this.parameters = parameters @@ -58,7 +59,7 @@ class FunctionPointerType : Type { constructor( type: Type, parameters: List = listOf(), - language: Language<*>? = null, + language: Language<*> = UnknownLanguage, returnType: Type = UnknownType.getUnknownType(language) ) : super(type) { this.parameters = parameters diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/FunctionType.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/FunctionType.kt index 55550fc462..54839f6645 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/FunctionType.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/FunctionType.kt @@ -42,7 +42,7 @@ constructor( typeName: String = "", var parameters: List = listOf(), var returnTypes: List = listOf(), - language: Language<*>? = null + language: Language<*> ) : Type(typeName, language) { override fun reference(pointer: PointerType.PointerOrigin?): Type { diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/IncompleteType.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/IncompleteType.kt index 6806271eef..51ac03215a 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/IncompleteType.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/IncompleteType.kt @@ -37,7 +37,7 @@ import de.fraunhofer.aisec.cpg.graph.types.PointerType.PointerOrigin * unknown size apart from void. Therefore, this Type is not called VoidType */ class IncompleteType : Type { - @JvmOverloads constructor(language: Language<*>? = null) : super("void", language) + constructor(language: Language<*>) : super("void", language) /** @return PointerType to a IncompleteType, e.g. void* */ override fun reference(pointer: PointerOrigin?): Type { diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/IntegerType.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/IntegerType.kt index f63d600f4a..721b7762cf 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/IntegerType.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/IntegerType.kt @@ -31,6 +31,6 @@ import de.fraunhofer.aisec.cpg.frontends.Language class IntegerType( typeName: CharSequence = "", bitWidth: Int? = null, - language: Language<*>? = null, + language: Language<*>, modifier: Modifier = Modifier.SIGNED ) : NumericType(typeName, bitWidth, language, modifier) diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/NumericType.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/NumericType.kt index 20a1db8032..96ffdc5eee 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/NumericType.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/NumericType.kt @@ -32,7 +32,7 @@ import java.util.* open class NumericType( typeName: CharSequence = "", val bitWidth: Int? = null, - language: Language<*>? = null, + language: Language<*>, val modifier: Modifier = Modifier.SIGNED ) : ObjectType(typeName, listOf(), true, language) { diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/ObjectType.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/ObjectType.kt index 3bb8fa44dd..159b308bdd 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/ObjectType.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/ObjectType.kt @@ -60,7 +60,7 @@ open class ObjectType : Type { typeName: CharSequence, generics: List, primitive: Boolean, - language: Language<*>? + language: Language<*> ) : super(typeName, language) { this.generics = generics isPrimitive = primitive @@ -71,7 +71,7 @@ open class ObjectType : Type { type: Type?, generics: List, primitive: Boolean, - language: Language<*>? + language: Language<*> ) : super(type) { this.language = language this.generics = generics diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/ParameterizedType.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/ParameterizedType.kt index 12a8ebc2ce..6e92137382 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/ParameterizedType.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/ParameterizedType.kt @@ -37,7 +37,7 @@ class ParameterizedType : Type { language = type.language } - constructor(typeName: String?, language: Language<*>?) : super(typeName) { + constructor(typeName: String?, language: Language<*>) : super(typeName) { this.language = language } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/StringType.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/StringType.kt index 3ecbc2fd9e..54ca9fdb0e 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/StringType.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/StringType.kt @@ -29,7 +29,7 @@ import de.fraunhofer.aisec.cpg.frontends.Language class StringType( typeName: CharSequence = "", - language: Language<*>? = null, + language: Language<*>, generics: List = listOf() ) : ObjectType(typeName, generics, false, language) { diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/Type.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/Type.kt index 1c38508df0..f4808a29c9 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/Type.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/types/Type.kt @@ -95,7 +95,7 @@ abstract class Type : Node { typeOrigin = type?.typeOrigin } - constructor(typeName: CharSequence, language: Language<*>?) { + constructor(typeName: CharSequence, language: Language<*>) { name = if (this is FunctionType) { Name(typeName.toString(), null, language) @@ -106,7 +106,7 @@ abstract class Type : Node { typeOrigin = Origin.UNRESOLVED } - constructor(fullTypeName: Name, language: Language<*>?) { + constructor(fullTypeName: Name, language: Language<*>) { name = fullTypeName.clone() typeOrigin = Origin.UNRESOLVED this.language = language diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/ControlFlowSensitiveDFGPass.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/ControlFlowSensitiveDFGPass.kt index e9b06fc1ab..9254db21b9 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/ControlFlowSensitiveDFGPass.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/ControlFlowSensitiveDFGPass.kt @@ -523,8 +523,7 @@ open class ControlFlowSensitiveDFGPass(ctx: TranslationContext) : EOGStarterPass protected fun isCompoundAssignment(currentNode: Node): Boolean { contract { returns(true) implies (currentNode is AssignExpression) } return currentNode is AssignExpression && - currentNode.operatorCode in - (currentNode.language?.compoundAssignmentOperators ?: setOf()) && + currentNode.operatorCode in currentNode.language.compoundAssignmentOperators && (currentNode.lhs.singleOrNull() as? Reference)?.refersTo != null } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/DFGPass.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/DFGPass.kt index 49b5028ff0..b6210d4333 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/DFGPass.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/DFGPass.kt @@ -471,7 +471,7 @@ class DFGPass(ctx: TranslationContext) : ComponentPass(ctx) { node.rhs.nextDFGEdges += node } } - in node.language?.compoundAssignmentOperators ?: setOf() -> { + in node.language.compoundAssignmentOperators -> { node.lhs.let { node.prevDFGEdges += it node.nextDFGEdges += it diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/EvaluationOrderGraphPass.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/EvaluationOrderGraphPass.kt index 6b043a39d2..37ad2c7c7d 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/EvaluationOrderGraphPass.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/EvaluationOrderGraphPass.kt @@ -578,8 +578,7 @@ open class EvaluationOrderGraphPass(ctx: TranslationContext) : TranslationUnitPa // value. If the language has the trait of short-circuit evaluation, we check if the // operatorCode is amongst the operators that lead to such an evaluation. if ( - lang != null && - lang is HasShortCircuitOperators && + lang is HasShortCircuitOperators && (lang.conjunctiveOperators.contains(node.operatorCode) || lang.disjunctiveOperators.contains(node.operatorCode)) ) { diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/inference/DFGFunctionSummaries.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/inference/DFGFunctionSummaries.kt index 873aa1d873..7677d6e681 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/inference/DFGFunctionSummaries.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/inference/DFGFunctionSummaries.kt @@ -115,7 +115,7 @@ class DFGFunctionSummaries { if (functionToDFGEntryMap.isEmpty()) return null val language = functionDecl.language - val languageName = language?.javaClass?.name + val languageName = language.javaClass.name val methodName = functionDecl.name val typeManager = functionDecl.ctx?.typeManager ?: return null diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/inference/Inference.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/inference/Inference.kt index 2073b108af..6a09e242c8 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/inference/Inference.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/inference/Inference.kt @@ -65,7 +65,7 @@ class Inference internal constructor(val start: Node, override val ctx: Translat ContextProvider, RawNodeTypeProvider { - override val language: Language<*>? + override val language: Language<*> get() = start.language override val isInferred: Boolean @@ -569,22 +569,20 @@ class Inference internal constructor(val start: Node, override val ctx: Translat is UnaryOperator -> { // If it's a boolean operator, the return type is probably a boolean if (holder.operatorCode == "!") { - return hint.language?.builtInTypes?.values?.firstOrNull { it is BooleanType } + return hint.language.builtInTypes.values.firstOrNull { it is BooleanType } } // If it's a numeric operator, return the largest numeric type that we have; we // prefer integers to floats if (holder.operatorCode in listOf("+", "-", "++", "--")) { val numericTypes = - hint.language - ?.builtInTypes - ?.values - ?.filterIsInstance() - ?.sortedWith( + hint.language.builtInTypes.values + .filterIsInstance() + .sortedWith( compareBy { it.bitWidth } .then { a, b -> preferIntegerType(a, b) } ) - return numericTypes?.lastOrNull() + return numericTypes.lastOrNull() } } is ConstructExpression -> { diff --git a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/LanguageTest.kt b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/LanguageTest.kt index 4a98cfe482..f734a33e7d 100644 --- a/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/LanguageTest.kt +++ b/cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/LanguageTest.kt @@ -25,7 +25,15 @@ */ package de.fraunhofer.aisec.cpg.frontends +import de.fraunhofer.aisec.cpg.ScopeManager +import de.fraunhofer.aisec.cpg.TranslationConfiguration +import de.fraunhofer.aisec.cpg.TranslationContext +import de.fraunhofer.aisec.cpg.TranslationManager +import de.fraunhofer.aisec.cpg.TranslationResult +import de.fraunhofer.aisec.cpg.TypeManager +import de.fraunhofer.aisec.cpg.graph.Component import de.fraunhofer.aisec.cpg.graph.newRecordDeclaration +import de.fraunhofer.aisec.cpg.graph.newTranslationUnitDeclaration import de.fraunhofer.aisec.cpg.graph.objectType import de.fraunhofer.aisec.cpg.graph.pointer import de.fraunhofer.aisec.cpg.tryCast @@ -63,4 +71,48 @@ class LanguageTest { assertIs(matches) } } + + @Test + fun testMultiLanguage() { + class OtherLanguage : TestLanguage() + + val otherLanguage = OtherLanguage() + val testLanguage = TestLanguage() + + val result = + TranslationResult( + translationManager = TranslationManager.builder().build(), + finalCtx = + TranslationContext( + config = TranslationConfiguration.builder().build(), + scopeManager = ScopeManager(), + typeManager = TypeManager(), + ), + ) + + val comp1 = + with(TestLanguageFrontend("::", language = otherLanguage)) { + val tu = newTranslationUnitDeclaration("tu-language-other") + val comp = Component() + comp.addTranslationUnit(tu) + comp + } + result.components += comp1 + + val comp2 = + with(TestLanguageFrontend("::", language = testLanguage)) { + val tu = newTranslationUnitDeclaration("tu-language-test") + val comp = Component() + comp.addTranslationUnit(tu) + comp + } + result.components += comp2 + + val language = result.language + assertIs(language) + assertEquals(setOf(otherLanguage, testLanguage), language.languages) + + assertEquals(otherLanguage, result.components.getOrNull(0)?.language) + assertEquals(testLanguage, result.components.getOrNull(1)?.language) + } } diff --git a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CPPLanguage.kt b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CPPLanguage.kt index c5fc9815fd..c1188494d5 100644 --- a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CPPLanguage.kt +++ b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CPPLanguage.kt @@ -130,7 +130,7 @@ open class CPPLanguage : IntegerType("unsigned long long int", 64, this, NumericType.Modifier.UNSIGNED), // Boolean type - "bool" to BooleanType("bool"), + "bool" to BooleanType("bool", language = this), // Character types "signed char" to IntegerType("signed char", 8, this, NumericType.Modifier.SIGNED), diff --git a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXLanguageFrontend.kt b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXLanguageFrontend.kt index 28b5ee5ed8..0768841c2a 100644 --- a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXLanguageFrontend.kt +++ b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/CXXLanguageFrontend.kt @@ -572,7 +572,7 @@ open class CXXLanguageFrontend(language: Language, ctx: Tra } // void type specifier.type == IASTSimpleDeclSpecifier.t_void -> { - IncompleteType() + incompleteType() } // __typeof__ type specifier.type == IASTSimpleDeclSpecifier.t_typeof -> { diff --git a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/DeclarationHandler.kt b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/DeclarationHandler.kt index 0656e7d21e..3e723dd13c 100644 --- a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/DeclarationHandler.kt +++ b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/cxx/DeclarationHandler.kt @@ -181,7 +181,7 @@ class DeclarationHandler(lang: CXXLanguageFrontend) : declaration.isDefinition = true // We also need to set the return type, based on the function type. - declaration.returnTypes = type?.returnTypes ?: listOf(IncompleteType()) + declaration.returnTypes = type?.returnTypes ?: listOf(incompleteType()) // We want to determine, whether this is a function definition that is external to its // scope. This is a usual case in C++, where the named scope, such as a record or namespace @@ -368,7 +368,7 @@ class DeclarationHandler(lang: CXXLanguageFrontend) : val parameterizedTypes = frontend.typeManager.getAllParameterizedType(templateDeclaration) // Loop through all the methods and adjust their receiver types - for (method in (innerDeclaration as? RecordDeclaration)?.methods ?: listOf()) { + for (method in innerDeclaration.methods) { // Add ParameterizedTypes to type method.receiver?.let { it.type = addParameterizedTypesToType(it.type, parameterizedTypes) @@ -389,6 +389,7 @@ class DeclarationHandler(lang: CXXLanguageFrontend) : constructor.type.typeName, (constructor.type as? FunctionType)?.parameters ?: listOf(), constructor.returnTypes, + this.language, ) } } @@ -464,7 +465,7 @@ class DeclarationHandler(lang: CXXLanguageFrontend) : // [handleFunctionDefinition]. if (declaration is FunctionDeclaration) { declaration.returnTypes = - (type as? FunctionType)?.returnTypes ?: listOf(IncompleteType()) + (type as? FunctionType)?.returnTypes ?: listOf(incompleteType()) } // We also need to set the type, based on the declarator type. diff --git a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/CXXExtraPass.kt b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/CXXExtraPass.kt index 0bd84d65fe..74463a9808 100644 --- a/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/CXXExtraPass.kt +++ b/cpg-language-cxx/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/CXXExtraPass.kt @@ -165,9 +165,10 @@ class CXXExtraPass(ctx: TranslationContext) : ComponentPass(ctx) { initializer.language = node.language initializer.type = node.type node.initializer = initializer - node.templateParameters?.let { - SymbolResolver.addImplicitTemplateParametersToCall(it, initializer) - } + SymbolResolver.addImplicitTemplateParametersToCall( + node.templateParameters, + initializer + ) } else if ( currInitializer !is ConstructExpression && currInitializer is CallExpression && diff --git a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/types/TypeTests.kt b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/types/TypeTests.kt index 2fd4c7d2ab..b592d36fde 100644 --- a/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/types/TypeTests.kt +++ b/cpg-language-cxx/src/test/kotlin/de/fraunhofer/aisec/cpg/enhancements/types/TypeTests.kt @@ -40,11 +40,11 @@ internal class TypeTests : BaseTest() { val objectType: Type = IntegerType("int", 32, CPPLanguage(), NumericType.Modifier.SIGNED) val pointerType: Type = PointerType(objectType, PointerType.PointerOrigin.POINTER) val unknownType: Type = UnknownType.getUnknownType(CPPLanguage()) - val incompleteType: Type = IncompleteType() + val incompleteType: Type = IncompleteType(CPPLanguage()) val parameterList = listOf(IntegerType("int", 32, CPPLanguage(), NumericType.Modifier.SIGNED)) val functionPointerType: Type = - FunctionPointerType(parameterList, CPPLanguage(), IncompleteType()) + FunctionPointerType(parameterList, CPPLanguage(), IncompleteType(CPPLanguage())) // Test 1: ObjectType becomes PointerType containing the original ObjectType as ElementType assertEquals( @@ -79,11 +79,11 @@ internal class TypeTests : BaseTest() { val objectType: Type = IntegerType("int", 32, CPPLanguage(), NumericType.Modifier.SIGNED) val pointerType: Type = PointerType(objectType, PointerType.PointerOrigin.POINTER) val unknownType: Type = UnknownType.getUnknownType(CPPLanguage()) - val incompleteType: Type = IncompleteType() + val incompleteType: Type = IncompleteType(CPPLanguage()) val parameterList = listOf(IntegerType("int", 32, CPPLanguage(), NumericType.Modifier.SIGNED)) val functionPointerType: Type = - FunctionPointerType(parameterList, CPPLanguage(), IncompleteType()) + FunctionPointerType(parameterList, CPPLanguage(), IncompleteType(CPPLanguage())) // Test 1: Dereferencing an ObjectType results in an UnknownType, since we cannot track the // type @@ -120,12 +120,13 @@ internal class TypeTests : BaseTest() { ) { it.registerLanguage() } - val noParamType = FunctionPointerType(emptyList(), CPPLanguage(), IncompleteType()) + val noParamType = + FunctionPointerType(emptyList(), CPPLanguage(), IncompleteType(CPPLanguage())) val oneParamType = FunctionPointerType( listOf(tu.primitiveType("int")), CPPLanguage(), - IncompleteType() + IncompleteType(CPPLanguage()) ) val twoParamType = FunctionPointerType( diff --git a/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/GoExtraPass.kt b/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/GoExtraPass.kt index e4fe1773c0..a096cdb0cc 100644 --- a/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/GoExtraPass.kt +++ b/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/GoExtraPass.kt @@ -223,7 +223,8 @@ class GoExtraPass(ctx: TranslationContext) : ComponentPass(ctx) { FunctionType( funcTypeName(func.signatureTypes, func.returnTypes), func.signatureTypes, - func.returnTypes + func.returnTypes, + func.language ) ) scopeManager.addDeclaration(func) diff --git a/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/java/JavaLanguageFrontendTest.kt b/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/java/JavaLanguageFrontendTest.kt index 25e0434595..9f0008ca1c 100644 --- a/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/java/JavaLanguageFrontendTest.kt +++ b/cpg-language-java/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/java/JavaLanguageFrontendTest.kt @@ -660,16 +660,13 @@ internal class JavaLanguageFrontendTest : BaseTest() { } class MyJavaLanguage : JavaLanguage() { - override val fileExtensions = listOf("java") - override val namespaceDelimiter = "." - override val superClassKeyword = "super" override val frontend = MyJavaLanguageFrontend::class } val file = File("src/test/resources/compiling/RecordDeclaration.java") val tu = analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true) { - it.registerLanguage(MyJavaLanguage()) + it.registerLanguage() } assertNotNull(tu) diff --git a/cpg-language-python/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/PythonAddDeclarationsPass.kt b/cpg-language-python/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/PythonAddDeclarationsPass.kt index 3931fa671e..fce17d9798 100644 --- a/cpg-language-python/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/PythonAddDeclarationsPass.kt +++ b/cpg-language-python/src/main/kotlin/de/fraunhofer/aisec/cpg/passes/PythonAddDeclarationsPass.kt @@ -27,6 +27,7 @@ package de.fraunhofer.aisec.cpg.passes import de.fraunhofer.aisec.cpg.TranslationContext import de.fraunhofer.aisec.cpg.frontends.Language +import de.fraunhofer.aisec.cpg.frontends.UnknownLanguage import de.fraunhofer.aisec.cpg.frontends.python.PythonLanguage import de.fraunhofer.aisec.cpg.frontends.python.PythonLanguageFrontend import de.fraunhofer.aisec.cpg.graph.* @@ -207,6 +208,6 @@ class PythonAddDeclarationsPass(ctx: TranslationContext) : ComponentPass(ctx), L } } - override val language: Language<*>? - get() = ctx.config.languages.firstOrNull { it is PythonLanguage } + override val language: Language<*> + get() = ctx.config.languages.firstOrNull { it is PythonLanguage } ?: UnknownLanguage }