@@ -124,20 +124,18 @@ class PrintASTNode extends TPrintASTNode {
124124 * regular parent/child relation traversal.
125125 */
126126 final PrintASTNode getChild ( int childIndex ) {
127- result = getChildInternal ( childIndex )
128- or
129- // We first compute the first available child index that is not used by
130- // `getChildInternal`, then we synthesize the child for fully converted
131- // expressions at `nextAvailableIndex` plus the childIndex of the non-converted
132- // expression. This ensures that both disjuncts are disjoint.
133- exists ( int nonConvertedIndex , int nextAvailableIndex , Expr expr |
134- nextAvailableIndex = max ( int idx | exists ( this .getChildInternal ( idx ) ) ) + 1 and
135- childIndex - nextAvailableIndex = nonConvertedIndex and
136- expr = getChildInternal ( nonConvertedIndex ) .( ASTNode ) .getAST ( )
127+ exists ( int nonConvertedIndex , boolean isConverted |
128+ deconstructIndex ( childIndex , nonConvertedIndex , isConverted )
137129 |
138- expr .getFullyConverted ( ) instanceof Conversion and
139- result .( ASTNode ) .getAST ( ) = expr .getFullyConverted ( ) and
140- not expr instanceof Conversion
130+ if isConverted = false
131+ then result = getChildInternal ( childIndex )
132+ else
133+ exists ( Expr expr |
134+ expr = getChildInternal ( nonConvertedIndex ) .( ASTNode ) .getAST ( ) and
135+ expr .getFullyConverted ( ) instanceof Conversion and
136+ result .( ASTNode ) .getAST ( ) = expr .getFullyConverted ( ) and
137+ not expr instanceof Conversion
138+ )
141139 )
142140 }
143141
@@ -173,36 +171,57 @@ class PrintASTNode extends TPrintASTNode {
173171 }
174172
175173 /**
176- * Gets the label for the edge from this node to the specified child. By
177- * default, this is just the index of the child, but subclasses can override
178- * this.
174+ * Gets the QL predicate that can be used to access the child at `childIndex`.
175+ * May not always return a QL predicate, see for example `FunctionNode`.
179176 */
180- string getChildEdgeLabelInternal ( int childIndex ) {
177+ final string getChildAccessorPredicate ( int childIndex ) {
181178 exists ( getChild ( childIndex ) ) and
182- result = childIndex .toString ( )
179+ exists ( int nonConvertedIndex , boolean isConverted |
180+ deconstructIndex ( childIndex , nonConvertedIndex , isConverted )
181+ |
182+ if isConverted = false
183+ then result = getChildAccessorPredicateInternal ( childIndex )
184+ else result = getChildAccessorPredicateInternal ( nonConvertedIndex ) + ".getFullyConverted()"
185+ )
183186 }
184187
185188 /**
186189 * Gets the QL predicate that can be used to access the child at `childIndex`.
187- * May not hold for all children, see for example `FunctionNode` .
190+ * INTERNAL DO NOT USE: Does not contain accessors for the synthesized nodes for conversions .
188191 */
189- abstract string getChildAccessorPredicate ( int childIndex ) ;
192+ abstract string getChildAccessorPredicateInternal ( int childIndex ) ;
190193
191194 /**
192- * Gets the label for the edge from this node to the specified child,
193- * including labels for edges to nodes that represent conversions.
195+ * Holds either if a `childIndex` is a synthesized child coming from a conversion (`isConverted = true`)
196+ * or if the child is a regular child node.
197+ * In the former case, `nonConvertedIndex` is the index of the regular, unconverted child node.
198+ * Note: This predicate contains the mapping between the converted and nonconverted indexes, but
199+ * if `nonConvertedIndex` does not have conversions attached, there will be no node at `childIndex`.
194200 */
195- final string getChildEdgeLabel ( int childIndex ) {
201+ final predicate deconstructIndex ( int childIndex , int nonConvertedIndex , boolean isConverted ) {
196202 exists ( getChildInternal ( childIndex ) ) and
197- result = getChildEdgeLabelInternal ( childIndex )
203+ nonConvertedIndex = childIndex and
204+ isConverted = false
198205 or
199206 not exists ( getChildInternal ( childIndex ) ) and
200- exists ( getChild ( childIndex ) ) and
201- exists ( int nonConvertedIndex , int nextAvailableIndex |
202- nextAvailableIndex = max ( int idx | exists ( this .getChildInternal ( idx ) ) ) + 1 and
203- childIndex - nextAvailableIndex = nonConvertedIndex
207+ exists ( getChildInternal ( nonConvertedIndex ) ) and
208+ isConverted = true and
209+ // to get the desired order of the extended `childIndex`es (including the synthesized children for conversions)
210+ // we keep the indexes in the following three disjoint intervals:
211+ // [minIndex, maxIndex: original children, without conversion
212+ // [|-1| + |maxIndex|, |minIndex| + |maxIndex|]: conversion children with negative `nonConvertedIndex`
213+ // [0 + |maxIndex| + |minIndex| + 1, maxIndex + |maxIndex| + |minIndex| + 1]: for conversion children
214+ // with positive `nonConvertedIndex`
215+ exists ( int minIndex , int maxIndex |
216+ minIndex = min ( int n | exists ( getChildInternal ( n ) ) ) and
217+ maxIndex = max ( int n | exists ( getChildInternal ( n ) ) )
204218 |
205- result = getChildEdgeLabelInternal ( nonConvertedIndex ) + " converted"
219+ if nonConvertedIndex < 0
220+ then
221+ // note that we swap the order of the negative indexes here, so that the conversion child for `-2`
222+ // comes before the conversion child for `-1`
223+ childIndex = ( minIndex - 1 - nonConvertedIndex ) .abs ( ) + maxIndex .abs ( )
224+ else childIndex = nonConvertedIndex + maxIndex .abs ( ) + minIndex .abs ( ) + 1
206225 )
207226 }
208227
@@ -267,8 +286,8 @@ class ExprNode extends ASTNode {
267286 result = expr .getValueCategoryString ( )
268287 }
269288
270- override string getChildAccessorPredicate ( int childIndex ) {
271- result = getChildAccessor ( ast , getChildInternal ( childIndex ) .getAST ( ) )
289+ override string getChildAccessorPredicateInternal ( int childIndex ) {
290+ result = getChildAccessorWithoutConversions ( ast , getChildInternal ( childIndex ) .getAST ( ) )
272291 }
273292
274293 /**
@@ -301,8 +320,6 @@ class ConversionNode extends ExprNode {
301320 result .getAST ( ) = conv .getExpr ( ) and
302321 conv .getExpr ( ) instanceof Conversion
303322 }
304-
305- override string getChildEdgeLabelInternal ( int childIndex ) { childIndex = 0 and result = "expr" }
306323}
307324
308325/**
@@ -332,7 +349,7 @@ class DeclarationEntryNode extends BaseASTNode, TDeclarationEntryNode {
332349
333350 override PrintASTNode getChildInternal ( int childIndex ) { none ( ) }
334351
335- override string getChildAccessorPredicate ( int childIndex ) { none ( ) }
352+ override string getChildAccessorPredicateInternal ( int childIndex ) { none ( ) }
336353
337354 override string getProperty ( string key ) {
338355 result = BaseASTNode .super .getProperty ( key )
@@ -353,12 +370,10 @@ class VariableDeclarationEntryNode extends DeclarationEntryNode {
353370 result .getAST ( ) = ast .getVariable ( ) .getInitializer ( )
354371 }
355372
356- override string getChildAccessorPredicate ( int childIndex ) {
373+ override string getChildAccessorPredicateInternal ( int childIndex ) {
357374 childIndex = 0 and
358375 result = "getVariable().getInitializer()"
359376 }
360-
361- override string getChildEdgeLabelInternal ( int childIndex ) { childIndex = 0 and result = "init" }
362377}
363378
364379/**
@@ -379,8 +394,8 @@ class StmtNode extends ASTNode {
379394 )
380395 }
381396
382- override string getChildAccessorPredicate ( int childIndex ) {
383- result = getChildAccessor ( ast , getChildInternal ( childIndex ) .getAST ( ) )
397+ override string getChildAccessorPredicateInternal ( int childIndex ) {
398+ result = getChildAccessorWithoutConversions ( ast , getChildInternal ( childIndex ) .getAST ( ) )
384399 }
385400}
386401
@@ -410,7 +425,7 @@ class ParameterNode extends ASTNode {
410425
411426 final override PrintASTNode getChildInternal ( int childIndex ) { none ( ) }
412427
413- final override string getChildAccessorPredicate ( int childIndex ) { none ( ) }
428+ final override string getChildAccessorPredicateInternal ( int childIndex ) { none ( ) }
414429
415430 final override string getProperty ( string key ) {
416431 result = super .getProperty ( key )
@@ -433,15 +448,10 @@ class InitializerNode extends ASTNode {
433448 result .getAST ( ) = init .getExpr ( )
434449 }
435450
436- override string getChildAccessorPredicate ( int childIndex ) {
451+ override string getChildAccessorPredicateInternal ( int childIndex ) {
437452 childIndex = 0 and
438453 result = "getExpr()"
439454 }
440-
441- override string getChildEdgeLabelInternal ( int childIndex ) {
442- childIndex = 0 and
443- result = "expr"
444- }
445455}
446456
447457/**
@@ -460,8 +470,8 @@ class ParametersNode extends PrintASTNode, TParametersNode {
460470 result .getAST ( ) = func .getParameter ( childIndex )
461471 }
462472
463- override string getChildAccessorPredicate ( int childIndex ) {
464- exists ( getChild ( childIndex ) ) and
473+ override string getChildAccessorPredicateInternal ( int childIndex ) {
474+ exists ( getChildInternal ( childIndex ) ) and
465475 result = "getParameter(" + childIndex .toString ( ) + ")"
466476 }
467477
@@ -487,8 +497,8 @@ class ConstructorInitializersNode extends PrintASTNode, TConstructorInitializers
487497 result .getAST ( ) = ctor .getInitializer ( childIndex )
488498 }
489499
490- final override string getChildAccessorPredicate ( int childIndex ) {
491- exists ( getChild ( childIndex ) ) and
500+ final override string getChildAccessorPredicateInternal ( int childIndex ) {
501+ exists ( getChildInternal ( childIndex ) ) and
492502 result = "getInitializer(" + childIndex .toString ( ) + ")"
493503 }
494504
@@ -514,8 +524,8 @@ class DestructorDestructionsNode extends PrintASTNode, TDestructorDestructionsNo
514524 result .getAST ( ) = dtor .getDestruction ( childIndex )
515525 }
516526
517- final override string getChildAccessorPredicate ( int childIndex ) {
518- exists ( getChild ( childIndex ) ) and
527+ final override string getChildAccessorPredicateInternal ( int childIndex ) {
528+ exists ( getChildInternal ( childIndex ) ) and
519529 result = "getDestruction(" + childIndex .toString ( ) + ")"
520530 }
521531
@@ -549,21 +559,14 @@ class FunctionNode extends ASTNode {
549559 result .( DestructorDestructionsNode ) .getDestructor ( ) = func
550560 }
551561
552- override string getChildAccessorPredicate ( int childIndex ) {
553- // all other children of this node are not reachable via the AST `getChild` relation
554- // or other getters. Thus, this predicate does not hold for them.
555- childIndex = 2 and
556- result = "getEntryPoint()"
557- }
558-
559- override string getChildEdgeLabelInternal ( int childIndex ) {
560- childIndex = 0 and result = "params"
562+ override string getChildAccessorPredicateInternal ( int childIndex ) {
563+ childIndex = 0 and result = "<params>"
561564 or
562- childIndex = 1 and result = "initializations"
565+ childIndex = 1 and result = "< initializations> "
563566 or
564- childIndex = 2 and result = "body "
567+ childIndex = 2 and result = "getEntryPoint() "
565568 or
566- childIndex = 3 and result = "destructions"
569+ childIndex = 3 and result = "< destructions> "
567570 }
568571
569572 private int getOrder ( ) {
@@ -588,52 +591,20 @@ class FunctionNode extends ASTNode {
588591 final Function getFunction ( ) { result = func }
589592}
590593
591- /**
592- * A node representing an `ClassAggregateLiteral`.
593- */
594- class ClassAggregateLiteralNode extends ExprNode {
595- ClassAggregateLiteral list ;
596-
597- ClassAggregateLiteralNode ( ) { list = ast }
598-
599- override string getChildEdgeLabelInternal ( int childIndex ) {
600- exists ( Field field |
601- list .getFieldExpr ( field ) = list .getChild ( childIndex ) and
602- result = "." + field .getName ( )
603- )
604- }
605- }
606-
607- /**
608- * A node representing an `ArrayAggregateLiteral`.
609- */
610- class ArrayAggregateLiteralNode extends ExprNode {
611- ArrayAggregateLiteral list ;
612-
613- ArrayAggregateLiteralNode ( ) { list = ast }
614-
615- override string getChildEdgeLabelInternal ( int childIndex ) {
616- exists ( int elementIndex |
617- list .getElementExpr ( elementIndex ) = list .getChild ( childIndex ) and
618- result = "[" + elementIndex .toString ( ) + "]"
619- )
620- }
621- }
622-
623- private string getChildAccessor ( Locatable parent , Element child ) {
594+ private string getChildAccessorWithoutConversions ( Locatable parent , Element child ) {
624595 shouldPrintFunction ( getEnclosingFunction ( parent ) ) and
625596 (
626- exists ( Stmt s | s = parent . ( Stmt ) |
597+ exists ( Stmt s | s = parent |
627598 namedStmtChildPredicates ( s , child , result )
628599 or
629- not exists ( string p | namedStmtChildPredicates ( s , child , p ) ) and
600+ not namedStmtChildPredicates ( s , child , _ ) and
630601 exists ( int n | s .getChild ( n ) = child and result = "getChild(" + n + ")" )
631602 )
632603 or
633- exists ( Expr expr | expr = parent . ( Expr ) |
604+ exists ( Expr expr | expr = parent |
634605 namedExprChildPredicates ( expr , child , result )
635606 or
636- not exists ( string p | namedExprChildPredicates ( expr , child , p ) ) and
607+ not namedExprChildPredicates ( expr , child , _ ) and
637608 exists ( int n | expr .getChild ( n ) = child and result = "getChild(" + n + ")" )
638609 )
639610 )
@@ -674,15 +645,15 @@ private predicate namedStmtChildPredicates(Locatable s, Element e, string pred)
674645 or
675646 s .( ForStmt ) .getStmt ( ) = e and pred = "getStmt()"
676647 or
677- s .( RangeBasedForStmt ) .getChild ( 0 ) = e and pred = "getChild(0)" // TODO: could be omitted
648+ s .( RangeBasedForStmt ) .getChild ( 0 ) = e and pred = "getChild(0)"
678649 or
679650 s .( RangeBasedForStmt ) .getBeginEndDeclaration ( ) = e and pred = "getBeginEndDeclaration()"
680651 or
681652 s .( RangeBasedForStmt ) .getCondition ( ) = e and pred = "getCondition()"
682653 or
683654 s .( RangeBasedForStmt ) .getUpdate ( ) = e and pred = "getUpdate()"
684655 or
685- s .( RangeBasedForStmt ) .getChild ( 4 ) = e and pred = "getChild(4)" // TODO: could be omitted
656+ s .( RangeBasedForStmt ) .getChild ( 4 ) = e and pred = "getChild(4)"
686657 or
687658 s .( RangeBasedForStmt ) .getStmt ( ) = e and pred = "getStmt()"
688659 or
@@ -845,8 +816,8 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
845816 or
846817 expr .( SizeofExprOperator ) .getExprOperand ( ) = ele and pred = "getExprOperand()"
847818 or
848- // expr.(StmtExpr).getStmt() = ele and pred = "getStmt()" // TODO confirm via test that this is a/the child
849- // or
819+ expr .( StmtExpr ) .getStmt ( ) = ele and pred = "getStmt()"
820+ or
850821 expr .( ThrowExpr ) .getExpr ( ) = ele and pred = "getExpr()"
851822 or
852823 expr .( TypeidOperator ) .getExpr ( ) = ele and pred = "getExpr()"
@@ -869,12 +840,9 @@ query predicate edges(PrintASTNode source, PrintASTNode target, string key, stri
869840 target .shouldPrint ( ) and
870841 target = source .getChild ( childIndex ) and
871842 (
872- key = "semmle.label" and value = source .getChildAccessorPredicate ( childIndex ) //source.getChildEdgeLabel(childIndex)
843+ key = "semmle.label" and value = source .getChildAccessorPredicate ( childIndex )
873844 or
874845 key = "semmle.order" and value = childIndex .toString ( )
875- or
876- key = "semmle.predicate" and
877- value = source .getChildAccessorPredicate ( childIndex )
878846 )
879847 )
880848}
0 commit comments