@@ -10,6 +10,7 @@ private newtype TNode =
1010 MkInstructionNode ( IR:: Instruction insn ) or
1111 MkSsaNode ( SsaDefinition ssa ) or
1212 MkGlobalFunctionNode ( Function f ) or
13+ MkImplicitVarargsSlice ( CallExpr c ) { c .hasImplicitVarargs ( ) } or
1314 MkSummarizedParameterNode ( SummarizedCallable c , int i ) {
1415 FlowSummaryImpl:: Private:: summaryParameterNodeRange ( c , i )
1516 } or
@@ -426,6 +427,41 @@ module Public {
426427 override ResultNode getAResult ( ) { result .getRoot ( ) = this .getExpr ( ) }
427428 }
428429
430+ /**
431+ * An implicit varargs slice creation expression.
432+ *
433+ * A variadic function like `f(t1 T1, ..., Tm tm, A... x)` actually sees the
434+ * varargs parameter as a slice `[]A`. A call `f(t1, ..., tm, x1, ..., xn)`
435+ * desugars to `f(t1, ..., tm, []A{x1, ..., xn})`, and this node corresponds
436+ * to this implicit slice creation.
437+ */
438+ class ImplicitVarargsSlice extends Node , MkImplicitVarargsSlice {
439+ CallNode call ;
440+
441+ ImplicitVarargsSlice ( ) { this = MkImplicitVarargsSlice ( call .getCall ( ) ) }
442+
443+ override ControlFlow:: Root getRoot ( ) { result = call .getRoot ( ) }
444+
445+ /** Gets the call containing this varargs slice creation argument. */
446+ CallNode getCallNode ( ) { result = call }
447+
448+ override Type getType ( ) {
449+ exists ( Function f | f = call .getTarget ( ) |
450+ result = f .getParameterType ( f .getNumParameter ( ) - 1 )
451+ )
452+ }
453+
454+ override string getNodeKind ( ) { result = "implicit varargs slice" }
455+
456+ override string toString ( ) { result = "[]type{args}" }
457+
458+ override predicate hasLocationInfo (
459+ string filepath , int startline , int startcolumn , int endline , int endcolumn
460+ ) {
461+ call .hasLocationInfo ( filepath , startline , startcolumn , endline , endcolumn )
462+ }
463+ }
464+
429465 /**
430466 * Gets a possible target of call `cn`.class
431467 *
@@ -498,16 +534,11 @@ module Public {
498534 CallExpr getCall ( ) { result = this .getExpr ( ) }
499535
500536 /**
501- * Gets the data flow node corresponding to the `i`th argument of this call.
502- *
503- * Note that the first argument in calls to the built-in function `make` is a type, which is
504- * not a data-flow node. It is skipped for the purposes of this predicate, so the (syntactically)
505- * second argument becomes the first argument in terms of data flow.
506- *
507- * For calls of the form `f(g())` where `g` has multiple results, the arguments of the call to
508- * `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.
509540 */
510- Node getArgument ( int i ) {
541+ Node getSyntacticArgument ( int i ) {
511542 if expr .getArgument ( 0 ) .getType ( ) instanceof TupleType
512543 then result = DataFlow:: extractTupleElement ( DataFlow:: exprNode ( expr .getArgument ( 0 ) ) , i )
513544 else
@@ -519,12 +550,60 @@ module Public {
519550 )
520551 }
521552
553+ /**
554+ * Gets a 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+ * Returns a single `Node` corresponding to a variadic parameter. If there is no corresponding
571+ * argument with an ellipsis (`...`), then it is a `ImplicitVarargsSlice`. This is in contrast
572+ * to `getArgument` on `CallExpr`, which gets the syntactic arguments. Use
573+ * `getSyntacticArgument` to get that behavior.
574+ */
575+ Node getArgument ( int i ) {
576+ result = this .getSyntacticArgument ( i ) and
577+ not ( expr .hasImplicitVarargs ( ) and i >= expr .getCalleeType ( ) .getNumParameter ( ) - 1 )
578+ or
579+ i = expr .getCalleeType ( ) .getNumParameter ( ) - 1 and
580+ result .( ImplicitVarargsSlice ) .getCallNode ( ) = this
581+ }
582+
522583 /** Gets the data flow node corresponding to an argument of this call. */
523584 Node getAnArgument ( ) { result = this .getArgument ( _) }
524585
525586 /** Gets the number of arguments of this call, if it can be determined. */
526587 int getNumArgument ( ) { result = count ( this .getAnArgument ( ) ) }
527588
589+ /**
590+ * Gets the 'i'th argument without an ellipsis after it which is passed to
591+ * the varargs parameter of the target of this call (if there is one).
592+ */
593+ Node getImplicitVarargsArgument ( int i ) {
594+ i >= 0 and
595+ expr .hasImplicitVarargs ( ) and
596+ exists ( int lastParamIndex | lastParamIndex = expr .getCalleeType ( ) .getNumParameter ( ) - 1 |
597+ result = this .getSyntacticArgument ( lastParamIndex + i )
598+ )
599+ }
600+
601+ /**
602+ * Gets an argument without an ellipsis after it which is passed to
603+ * the varargs parameter of the target of this call (if there is one).
604+ */
605+ Node getAnImplicitVarargsArgument ( ) { result = this .getImplicitVarargsArgument ( _) }
606+
528607 /** Gets a function passed as the `i`th argument of this call. */
529608 FunctionNode getCallback ( int i ) { result .getASuccessor * ( ) = this .getArgument ( i ) }
530609
@@ -696,7 +775,11 @@ module Public {
696775 or
697776 preupd = getAWrittenNode ( )
698777 or
699- preupd instanceof ArgumentNode and
778+ (
779+ preupd instanceof ArgumentNode and not preupd instanceof ImplicitVarargsSlice
780+ or
781+ preupd = any ( CallNode c ) .getAnImplicitVarargsArgument ( )
782+ ) and
700783 mutableType ( preupd .getType ( ) )
701784 ) and
702785 (
0 commit comments