@@ -1382,16 +1382,89 @@ predicate neverSkipInPathGraph(Node n) {
13821382 exists ( n .asIndirectDefinition ( ) )
13831383}
13841384
1385- class LambdaCallKind = Unit ;
1385+ private newtype TLambdaCallKind =
1386+ TFunctionPointer ( ) or
1387+ TFunctor ( )
1388+
1389+ class LambdaCallKind extends TLambdaCallKind {
1390+ predicate isFunctionPointer ( ) { this = TFunctionPointer ( ) }
1391+
1392+ predicate isFunctor ( ) { this = TFunctor ( ) }
1393+
1394+ string toString ( ) {
1395+ this .isFunctionPointer ( ) and
1396+ result = "Function pointer kind"
1397+ or
1398+ this .isFunctor ( ) and
1399+ result = "Functor kind"
1400+ }
1401+ }
1402+
1403+ private class ConstructorCallInstruction extends CallInstruction {
1404+ Cpp:: Class constructedType ;
1405+
1406+ ConstructorCallInstruction ( ) {
1407+ this .getStaticCallTarget ( ) .( Cpp:: Constructor ) .getDeclaringType ( ) = constructedType
1408+ }
1409+
1410+ Cpp:: Class getConstructedType ( ) { result = constructedType }
1411+ }
1412+
1413+ private class OperatorCall extends Cpp:: MemberFunction {
1414+ OperatorCall ( ) { this .hasName ( "operator()" ) }
1415+ }
1416+
1417+ private predicate isFunctorCreationWithoutConstructor ( Node creation , OperatorCall operator ) {
1418+ exists ( UninitializedInstruction init , Instruction dest |
1419+ // A construction of an object with no constructor. In this case we use
1420+ // the `UninitializedInstruction` as the creation node.
1421+ init = creation .asInstruction ( ) and
1422+ dest = init .getDestinationAddress ( ) and
1423+ not any ( ConstructorCallInstruction constructorCall ) .getThisArgument ( ) = dest and
1424+ operator .getDeclaringType ( ) = init .getResultType ( )
1425+ )
1426+ or
1427+ // Workaround for an extractor bug. In this snippet:
1428+ // ```
1429+ // struct S { };
1430+ // void f(S);
1431+ // f(S());
1432+ // ```
1433+ // The expression `S()` is represented as a 0 literal in the database.
1434+ exists ( ConstantValueInstruction constant |
1435+ constant .getValue ( ) = "0" and
1436+ creation .asInstruction ( ) = constant and
1437+ constant .getResultType ( ) = operator .getDeclaringType ( )
1438+ )
1439+ }
1440+
1441+ private predicate isFunctorCreationWithConstructor ( Node creation , OperatorCall operator ) {
1442+ exists ( DataFlowCall constructorCall , IndirectionPosition pos |
1443+ // A construction of an object with a constructor. In this case we use
1444+ // the post-update node of the qualifier
1445+ pos .getArgumentIndex ( ) = - 1 and
1446+ isArgumentNode ( creation .( PostUpdateNode ) .getPreUpdateNode ( ) , constructorCall , pos ) and
1447+ operator .getDeclaringType ( ) =
1448+ constructorCall .asCallInstruction ( ) .( ConstructorCallInstruction ) .getConstructedType ( )
1449+ )
1450+ }
13861451
13871452/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
13881453predicate lambdaCreation ( Node creation , LambdaCallKind kind , DataFlowCallable c ) {
1389- creation .asInstruction ( ) .( FunctionAddressInstruction ) .getFunctionSymbol ( ) = c .asSourceCallable ( ) and
1390- exists ( kind )
1454+ kind .isFunctionPointer ( ) and
1455+ creation .asInstruction ( ) .( FunctionAddressInstruction ) .getFunctionSymbol ( ) = c .asSourceCallable ( )
1456+ or
1457+ kind .isFunctor ( ) and
1458+ exists ( OperatorCall operator | operator = c .asSourceCallable ( ) |
1459+ isFunctorCreationWithoutConstructor ( creation , operator )
1460+ or
1461+ isFunctorCreationWithConstructor ( creation , operator )
1462+ )
13911463}
13921464
13931465/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
13941466predicate lambdaCall ( DataFlowCall call , LambdaCallKind kind , Node receiver ) {
1467+ kind .isFunctionPointer ( ) and
13951468 (
13961469 call .( SummaryCall ) .getReceiver ( ) = receiver .( FlowSummaryNode ) .getSummaryNode ( )
13971470 or
@@ -1400,8 +1473,15 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
14001473 // has a result for `getStaticCallTarget`.
14011474 not exists ( call .getStaticCallTarget ( ) ) and
14021475 call .asCallInstruction ( ) .getCallTargetOperand ( ) = receiver .asOperand ( )
1403- ) and
1404- exists ( kind )
1476+ )
1477+ or
1478+ kind .isFunctor ( ) and
1479+ (
1480+ call .( SummaryCall ) .getReceiver ( ) = receiver .( FlowSummaryNode ) .getSummaryNode ( )
1481+ or
1482+ not exists ( call .getStaticCallTarget ( ) ) and
1483+ call .asCallInstruction ( ) .getThisArgumentOperand ( ) = receiver .asOperand ( )
1484+ )
14051485}
14061486
14071487/** Extra data-flow steps needed for lambda flow analysis. */
0 commit comments