Skip to content

Commit

Permalink
[c2cpg] Safe getEvaluation for CPP (#4647)
Browse files Browse the repository at this point in the history
ICPPASTExpression.getEvaluation may fail throwing an unrecoverable exception in case of unresolved includes etc.
  • Loading branch information
max-leuthaeuser committed Jun 6, 2024
1 parent ba38297 commit a5cd07d
Showing 1 changed file with 37 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTArrayRangeDesignator
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalMemberAccess
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethod
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation
import org.eclipse.cdt.internal.core.model.ASTStringUtil

import java.nio.file.{Path, Paths}
import scala.annotation.nowarn
import scala.collection.mutable
import scala.util.Try

object AstCreatorHelper {

Expand Down Expand Up @@ -155,13 +157,18 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As
}
}

private def safeGetEvaluation(expr: ICPPASTExpression): Option[ICPPEvaluation] = {
// In case of unresolved includes etc. this may fail throwing an unrecoverable exception
Try(expr.getEvaluation).toOption
}

@nowarn
protected def typeFor(node: IASTNode, stripKeywords: Boolean = true): String = {
import org.eclipse.cdt.core.dom.ast.ASTSignatureUtil.getNodeSignature
node match {
case f: CPPASTFieldReference =>
f.getFieldOwner.getEvaluation match {
case evaluation: EvalBinding => cleanType(evaluation.getType.toString, stripKeywords)
safeGetEvaluation(f.getFieldOwner) match {
case Some(evaluation: EvalBinding) => cleanType(evaluation.getType.toString, stripKeywords)
case _ => cleanType(ASTTypeUtil.getType(f.getFieldOwner.getExpressionType), stripKeywords)
}
case f: IASTFieldReference =>
Expand All @@ -184,10 +191,10 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As
}.mkString
s"$tpe$arr"
case s: CPPASTIdExpression =>
s.getEvaluation match {
case evaluation: EvalMemberAccess =>
safeGetEvaluation(s) match {
case Some(evaluation: EvalMemberAccess) =>
cleanType(evaluation.getOwnerType.toString, stripKeywords)
case evalBinding: EvalBinding =>
case Some(evalBinding: EvalBinding) =>
evalBinding.getBinding match {
case m: CPPMethod => cleanType(fullName(m.getDefinition))
case _ => cleanType(ASTTypeUtil.getNodeType(s), stripKeywords)
Expand Down Expand Up @@ -277,16 +284,20 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As

protected def fullName(node: IASTNode): String = {
val qualifiedName: String = node match {
case d: CPPASTIdExpression if d.getEvaluation.isInstanceOf[EvalBinding] =>
val evaluation = d.getEvaluation.asInstanceOf[EvalBinding]
evaluation.getBinding match {
case f: CPPFunction if f.getDeclarations != null =>
f.getDeclarations.headOption.map(n => s"${fullName(n)}").getOrElse(f.getName)
case f: CPPFunction if f.getDefinition != null =>
s"${fullName(f.getDefinition)}"
case other =>
other.getName
case d: CPPASTIdExpression =>
safeGetEvaluation(d) match {
case Some(evalBinding: EvalBinding) =>
evalBinding.getBinding match {
case f: CPPFunction if f.getDeclarations != null =>
f.getDeclarations.headOption.map(n => s"${fullName(n)}").getOrElse(f.getName)
case f: CPPFunction if f.getDefinition != null =>
s"${fullName(f.getDefinition)}"
case other =>
other.getName
}
case _ => ASTStringUtil.getSimpleName(d.getName)
}

case alias: ICPPASTNamespaceAlias => alias.getMappingName.toString
case namespace: ICPPASTNamespaceDefinition if ASTStringUtil.getSimpleName(namespace.getName).nonEmpty =>
s"${fullName(namespace.getParent)}.${ASTStringUtil.getSimpleName(namespace.getName)}"
Expand Down Expand Up @@ -348,15 +359,18 @@ trait AstCreatorHelper(implicit withSchemaValidation: ValidationMode) { this: As
.isEmpty && f.getDeclarator.getNestedDeclarator != null =>
shortName(f.getDeclarator.getNestedDeclarator)
case f: IASTFunctionDefinition => ASTStringUtil.getSimpleName(f.getDeclarator.getName)
case d: CPPASTIdExpression if d.getEvaluation.isInstanceOf[EvalBinding] =>
val evaluation = d.getEvaluation.asInstanceOf[EvalBinding]
evaluation.getBinding match {
case f: CPPFunction if f.getDeclarations != null =>
f.getDeclarations.headOption.map(n => ASTStringUtil.getSimpleName(n.getName)).getOrElse(f.getName)
case f: CPPFunction if f.getDefinition != null =>
ASTStringUtil.getSimpleName(f.getDefinition.getName)
case other =>
other.getName
case d: CPPASTIdExpression =>
safeGetEvaluation(d) match {
case Some(evalBinding: EvalBinding) =>
evalBinding.getBinding match {
case f: CPPFunction if f.getDeclarations != null =>
f.getDeclarations.headOption.map(n => ASTStringUtil.getSimpleName(n.getName)).getOrElse(f.getName)
case f: CPPFunction if f.getDefinition != null =>
ASTStringUtil.getSimpleName(f.getDefinition.getName)
case other =>
other.getName
}
case _ => lastNameOfQualifiedName(ASTStringUtil.getSimpleName(d.getName))
}
case d: IASTIdExpression => lastNameOfQualifiedName(ASTStringUtil.getSimpleName(d.getName))
case u: IASTUnaryExpression => shortName(u.getOperand)
Expand Down

0 comments on commit a5cd07d

Please sign in to comment.