@@ -534,16 +534,11 @@ module Public {
534
534
CallExpr getCall ( ) { result = this .getExpr ( ) }
535
535
536
536
/**
537
- * Gets the data flow node corresponding to the `i`th argument of this call.
538
- *
539
- * Note that the first argument in calls to the built-in function `make` is a type, which is
540
- * not a data-flow node. It is skipped for the purposes of this predicate, so the (syntactically)
541
- * second argument becomes the first argument in terms of data flow.
542
- *
543
- * For calls of the form `f(g())` where `g` has multiple results, the arguments of the call to
544
- * `i` are the (implicit) element extraction nodes for the call to `g`.
537
+ * Gets the `i`th argument of this call, where tuple extraction has been
538
+ * done but arguments corresponding to a variadic parameter are still
539
+ * considered separate.
545
540
*/
546
- Node getArgument ( int i ) {
541
+ Node getSyntacticArgument ( int i ) {
547
542
if expr .getArgument ( 0 ) .getType ( ) instanceof TupleType
548
543
then result = DataFlow:: extractTupleElement ( DataFlow:: exprNode ( expr .getArgument ( 0 ) ) , i )
549
544
else
@@ -555,12 +550,62 @@ module Public {
555
550
)
556
551
}
557
552
553
+ /**
554
+ * Gets the data flow node corresponding to an argument of this call, where
555
+ * tuple extraction has been done but arguments corresponding to a variadic
556
+ * parameter are still considered separate.
557
+ */
558
+ Node getASyntacticArgument ( ) { result = this .getSyntacticArgument ( _) }
559
+
560
+ /**
561
+ * Gets the data flow node corresponding to the `i`th argument of this call.
562
+ *
563
+ * Note that the first argument in calls to the built-in function `make` is a type, which is
564
+ * not a data-flow node. It is skipped for the purposes of this predicate, so the (syntactically)
565
+ * second argument becomes the first argument in terms of data flow.
566
+ *
567
+ * For calls of the form `f(g())` where `g` has multiple results, the arguments of the call to
568
+ * `i` are the (implicit) element extraction nodes for the call to `g`.
569
+ *
570
+ * For calls to variadic functions without an ellipsis (`...`), there is a single argument of type
571
+ * `ImplicitVarargsSlice` corresponding to the variadic parameter. This is in contrast to the member
572
+ * predicate `getArgument` on `CallExpr`, which gets the syntactic arguments.
573
+ */
574
+ Node getArgument ( int i ) {
575
+ exists ( SignatureType t , int lastParamIndex |
576
+ t = this .getACalleeIncludingExternals ( ) .getType ( ) and
577
+ lastParamIndex = t .getNumParameter ( ) - 1
578
+ |
579
+ if
580
+ not this .hasEllipsis ( ) and
581
+ t .isVariadic ( ) and
582
+ i >= lastParamIndex
583
+ then
584
+ result .( ImplicitVarargsSlice ) .getCallNode ( ) = this and
585
+ i = lastParamIndex
586
+ else result = this .getSyntacticArgument ( i )
587
+ )
588
+ }
589
+
558
590
/** Gets the data flow node corresponding to an argument of this call. */
559
591
Node getAnArgument ( ) { result = this .getArgument ( _) }
560
592
561
593
/** Gets the number of arguments of this call, if it can be determined. */
562
594
int getNumArgument ( ) { result = count ( this .getAnArgument ( ) ) }
563
595
596
+ /**
597
+ * Gets the 'i'th argument without an ellipsis after it which is passed to
598
+ * the varargs parameter of the target of this call (if there is one).
599
+ */
600
+ Node getImplicitVarargsArgument ( int i ) {
601
+ not this .hasEllipsis ( ) and
602
+ i >= 0 and
603
+ exists ( Function f | f = this .getTarget ( ) |
604
+ f .isVariadic ( ) and
605
+ result = this .getSyntacticArgument ( f .getNumParameter ( ) - 1 + i )
606
+ )
607
+ }
608
+
564
609
/** Gets a function passed as the `i`th argument of this call. */
565
610
FunctionNode getCallback ( int i ) { result .getASuccessor * ( ) = this .getArgument ( i ) }
566
611
0 commit comments