@@ -534,16 +534,11 @@ module Public {
534534 CallExpr getCall ( ) { result = this .getExpr ( ) }
535535
536536 /**
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.
545540 */
546- Node getArgument ( int i ) {
541+ Node getSyntacticArgument ( int i ) {
547542 if expr .getArgument ( 0 ) .getType ( ) instanceof TupleType
548543 then result = DataFlow:: extractTupleElement ( DataFlow:: exprNode ( expr .getArgument ( 0 ) ) , i )
549544 else
@@ -555,12 +550,62 @@ module Public {
555550 )
556551 }
557552
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+
558590 /** Gets the data flow node corresponding to an argument of this call. */
559591 Node getAnArgument ( ) { result = this .getArgument ( _) }
560592
561593 /** Gets the number of arguments of this call, if it can be determined. */
562594 int getNumArgument ( ) { result = count ( this .getAnArgument ( ) ) }
563595
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+
564609 /** Gets a function passed as the `i`th argument of this call. */
565610 FunctionNode getCallback ( int i ) { result .getASuccessor * ( ) = this .getArgument ( i ) }
566611
0 commit comments