Skip to content

Commit 8c925a2

Browse files
committed
C++: Provide the predicates that can be used to traverse the AST as metadata.
1 parent fa344d2 commit 8c925a2

File tree

3 files changed

+5494
-5205
lines changed

3 files changed

+5494
-5205
lines changed

cpp/ql/src/semmle/code/cpp/PrintAST.qll

Lines changed: 290 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ class PrintASTNode extends TPrintASTNode {
182182
result = childIndex.toString()
183183
}
184184

185+
abstract string getChildAccessorPredicate(int childIndex);
186+
185187
/**
186188
* Gets the label for the edge from this node to the specified child,
187189
* including labels for edges to nodes that represent conversions.
@@ -261,6 +263,10 @@ class ExprNode extends ASTNode {
261263
result = expr.getValueCategoryString()
262264
}
263265

266+
override string getChildAccessorPredicate(int childIndex) {
267+
result = getChildAccessor(ast, getChildInternal(childIndex).getAST())
268+
}
269+
264270
/**
265271
* Gets the value of this expression, if it is a constant.
266272
*/
@@ -322,6 +328,8 @@ class DeclarationEntryNode extends BaseASTNode, TDeclarationEntryNode {
322328

323329
override PrintASTNode getChildInternal(int childIndex) { none() }
324330

331+
override string getChildAccessorPredicate(int childIndex) { none() }
332+
325333
override string getProperty(string key) {
326334
result = BaseASTNode.super.getProperty(key)
327335
or
@@ -341,6 +349,11 @@ class VariableDeclarationEntryNode extends DeclarationEntryNode {
341349
result.getAST() = ast.getVariable().getInitializer()
342350
}
343351

352+
override string getChildAccessorPredicate(int childIndex) {
353+
childIndex = 0 and
354+
result = "getVariable().getInitializer()"
355+
}
356+
344357
override string getChildEdgeLabelInternal(int childIndex) { childIndex = 0 and result = "init" }
345358
}
346359

@@ -361,6 +374,10 @@ class StmtNode extends ASTNode {
361374
)
362375
)
363376
}
377+
378+
override string getChildAccessorPredicate(int childIndex) {
379+
result = getChildAccessor(ast, getChildInternal(childIndex).getAST())
380+
}
364381
}
365382

366383
/**
@@ -389,6 +406,8 @@ class ParameterNode extends ASTNode {
389406

390407
final override PrintASTNode getChildInternal(int childIndex) { none() }
391408

409+
final override string getChildAccessorPredicate(int childIndex) { none() }
410+
392411
final override string getProperty(string key) {
393412
result = super.getProperty(key)
394413
or
@@ -410,6 +429,11 @@ class InitializerNode extends ASTNode {
410429
result.getAST() = init.getExpr()
411430
}
412431

432+
override string getChildAccessorPredicate(int childIndex) {
433+
childIndex = 0 and
434+
result = "getExpr()"
435+
}
436+
413437
override string getChildEdgeLabelInternal(int childIndex) {
414438
childIndex = 0 and
415439
result = "expr"
@@ -432,6 +456,11 @@ class ParametersNode extends PrintASTNode, TParametersNode {
432456
result.getAST() = func.getParameter(childIndex)
433457
}
434458

459+
override string getChildAccessorPredicate(int childIndex) {
460+
exists(getChild(childIndex)) and
461+
result = "getParameter(" + childIndex.toString() + ")"
462+
}
463+
435464
/**
436465
* Gets the `Function` for which this node represents the parameters.
437466
*/
@@ -454,6 +483,11 @@ class ConstructorInitializersNode extends PrintASTNode, TConstructorInitializers
454483
result.getAST() = ctor.getInitializer(childIndex)
455484
}
456485

486+
final override string getChildAccessorPredicate(int childIndex) {
487+
exists(getChild(childIndex)) and
488+
result = "getInitializer(" + childIndex.toString() + ")"
489+
}
490+
457491
/**
458492
* Gets the `Constructor` for which this node represents the initializer list.
459493
*/
@@ -476,6 +510,11 @@ class DestructorDestructionsNode extends PrintASTNode, TDestructorDestructionsNo
476510
result.getAST() = dtor.getDestruction(childIndex)
477511
}
478512

513+
final override string getChildAccessorPredicate(int childIndex) {
514+
exists(getChild(childIndex)) and
515+
result = "getDestruction(" + childIndex.toString() + ")"
516+
}
517+
479518
/**
480519
* Gets the `Destructor` for which this node represents the destruction list.
481520
*/
@@ -506,6 +545,20 @@ class FunctionNode extends ASTNode {
506545
result.(DestructorDestructionsNode).getDestructor() = func
507546
}
508547

548+
override string getChildAccessorPredicate(int childIndex) {
549+
childIndex = 0 and
550+
result = "..."
551+
or
552+
childIndex = 1 and
553+
result = "..."
554+
or
555+
childIndex = 2 and
556+
result = "getEntryPoint()"
557+
or
558+
childIndex = 3 and
559+
result = "..."
560+
}
561+
509562
override string getChildEdgeLabelInternal(int childIndex) {
510563
childIndex = 0 and result = "params"
511564
or
@@ -570,6 +623,239 @@ class ArrayAggregateLiteralNode extends ExprNode {
570623
}
571624
}
572625

626+
string getChildAccessor(Locatable parent, Element child) {
627+
shouldPrintFunction(getEnclosingFunction(parent)) and
628+
(
629+
exists(Stmt s | s = parent.(Stmt) |
630+
namedStmtChildPredicates(s, child, result)
631+
or
632+
not exists(string p | namedStmtChildPredicates(s, child, p)) and
633+
exists(int n | s.getChild(n) = child and result = "getChild(" + n + ")")
634+
)
635+
or
636+
exists(Expr expr | expr = parent.(Expr) |
637+
namedExprChildPredicates(expr, child, result)
638+
or
639+
not exists(string p | namedExprChildPredicates(expr, child, p)) and
640+
exists(int n | expr.getChild(n) = child and result = "getChild(" + n + ")")
641+
)
642+
)
643+
}
644+
645+
predicate namedStmtChildPredicates(Locatable s, Element e, string pred) {
646+
shouldPrintFunction(getEnclosingFunction(s)) and
647+
(
648+
exists(int n | s.(BlockStmt).getStmt(n) = e and pred = "getStmt(" + n + ")")
649+
or
650+
s.(ComputedGotoStmt).getExpr() = e and pred = "getExpr()"
651+
or
652+
s.(ConstexprIfStmt).getCondition() = e and pred = "getCondition()"
653+
or
654+
s.(ConstexprIfStmt).getThen() = e and pred = "getThen()"
655+
or
656+
s.(ConstexprIfStmt).getElse() = e and pred = "getElse()"
657+
or
658+
s.(IfStmt).getCondition() = e and pred = "getCondition()"
659+
or
660+
s.(IfStmt).getThen() = e and pred = "getThen()"
661+
or
662+
s.(IfStmt).getElse() = e and pred = "getElse()"
663+
or
664+
s.(SwitchStmt).getExpr() = e and pred = "getExpr()"
665+
or
666+
s.(SwitchStmt).getStmt() = e and pred = "getStmt()"
667+
or
668+
s.(DoStmt).getCondition() = e and pred = "getCondition()"
669+
or
670+
s.(DoStmt).getStmt() = e and pred = "getStmt()"
671+
or
672+
s.(ForStmt).getInitialization() = e and pred = "getInitialization()"
673+
or
674+
s.(ForStmt).getCondition() = e and pred = "getCondition()"
675+
or
676+
s.(ForStmt).getUpdate() = e and pred = "getUpdate()"
677+
or
678+
s.(ForStmt).getStmt() = e and pred = "getStmt()"
679+
or
680+
s.(RangeBasedForStmt).getChild(0) = e and pred = "getChild(0)" // TODO: could be omitted
681+
or
682+
s.(RangeBasedForStmt).getBeginEndDeclaration() = e and pred = "getBeginEndDeclaration()"
683+
or
684+
s.(RangeBasedForStmt).getCondition() = e and pred = "getCondition()"
685+
or
686+
s.(RangeBasedForStmt).getUpdate() = e and pred = "getUpdate()"
687+
or
688+
s.(RangeBasedForStmt).getChild(4) = e and pred = "getChild(4)" // TODO: could be omitted
689+
or
690+
s.(RangeBasedForStmt).getStmt() = e and pred = "getStmt()"
691+
or
692+
s.(WhileStmt).getCondition() = e and pred = "getCondition()"
693+
or
694+
s.(WhileStmt).getStmt() = e and pred = "getStmt()"
695+
or
696+
exists(int n |
697+
s.(DeclStmt).getDeclarationEntry(n) = e and pred = "getDeclarationEntry(" + n.toString() + ")"
698+
)
699+
or
700+
// EmptyStmt does not have children
701+
s.(ExprStmt).getExpr() = e and pred = "getExpr()"
702+
or
703+
s.(Handler).getBlock() = e and pred = "getBlock()"
704+
or
705+
s.(JumpStmt).getTarget() = e and pred = "getTarget()"
706+
or
707+
s.(MicrosoftTryStmt).getStmt() = e and pred = "getStmt()"
708+
or
709+
s.(MicrosoftTryExceptStmt).getCondition() = e and pred = "getCondition()"
710+
or
711+
s.(MicrosoftTryExceptStmt).getExcept() = e and pred = "getExcept()"
712+
or
713+
s.(MicrosoftTryFinallyStmt).getFinally() = e and pred = "getFinally()"
714+
or
715+
s.(ReturnStmt).getExpr() = e and pred = "getExpr()"
716+
or
717+
s.(SwitchCase).getExpr() = e and pred = "getExpr()"
718+
or
719+
s.(SwitchCase).getEndExpr() = e and pred = "getEndExpr()"
720+
or
721+
s.(TryStmt).getStmt() = e and pred = "getStmt()"
722+
or
723+
s.(VlaDimensionStmt).getDimensionExpr() = e and pred = "getDimensionExpr()"
724+
)
725+
}
726+
727+
predicate namedExprChildPredicates(Expr expr, Element ele, string pred) {
728+
shouldPrintFunction(expr.getEnclosingFunction()) and
729+
(
730+
expr.(Access).getTarget() = ele and pred = "getTarget()"
731+
or
732+
expr.(VariableAccess).getQualifier() = ele and pred = "getQualifier()"
733+
or
734+
exists(Field f |
735+
expr.(ClassAggregateLiteral).getFieldExpr(f) = ele and
736+
pred = "getFieldExpr(" + f.toString() + ")"
737+
)
738+
or
739+
exists(int n |
740+
expr.(ArrayOrVectorAggregateLiteral).getElementExpr(n) = ele and
741+
pred = "getElementExpr(" + n.toString() + ")"
742+
)
743+
or
744+
expr.(AlignofExprOperator).getExprOperand() = ele and pred = "getExprOperand()"
745+
or
746+
expr.(ArrayExpr).getArrayBase() = ele and pred = "getArrayBase()"
747+
or
748+
expr.(ArrayExpr).getArrayOffset() = ele and pred = "getArrayOffset()"
749+
or
750+
expr.(AssumeExpr).getOperand() = ele and pred = "getOperand()"
751+
or
752+
expr.(BuiltInComplexOperation).getRealOperand() = ele and pred = "getRealOperand()"
753+
or
754+
expr.(BuiltInComplexOperation).getImaginaryOperand() = ele and pred = "getImaginaryOperand()"
755+
or
756+
expr.(BuiltInVarArg).getVAList() = ele and pred = "getVAList()"
757+
or
758+
expr.(BuiltInVarArgCopy).getDestinationVAList() = ele and pred = "getDestinationVAList()"
759+
or
760+
expr.(BuiltInVarArgCopy).getSourceVAList() = ele and pred = "getSourceVAList()"
761+
or
762+
expr.(BuiltInVarArgsEnd).getVAList() = ele and pred = "getVAList()"
763+
or
764+
expr.(BuiltInVarArgsStart).getVAList() = ele and pred = "getVAList()"
765+
or
766+
expr.(BuiltInVarArgsStart).getLastNamedParameter() = ele and pred = "getLastNamedParameter()"
767+
or
768+
expr.(Call).getQualifier() = ele and pred = "getQualifier()"
769+
or
770+
exists(int n | expr.(Call).getArgument(n) = ele and pred = "getArgument(" + n.toString() + ")")
771+
or
772+
expr.(ExprCall).getExpr() = ele and pred = "getExpr()"
773+
or
774+
expr.(OverloadedArrayExpr).getArrayBase() = ele and pred = "getArrayBase()"
775+
or
776+
expr.(OverloadedArrayExpr).getArrayOffset() = ele and pred = "getArrayOffset()"
777+
or
778+
expr.(OverloadedPointerDereferenceExpr).getExpr() = ele and pred = "getExpr()"
779+
or
780+
expr.(CommaExpr).getLeftOperand() = ele and pred = "getLeftOperand()"
781+
or
782+
expr.(CommaExpr).getRightOperand() = ele and pred = "getRightOperand()"
783+
or
784+
expr.(ConditionDeclExpr).getVariableAccess() = ele and pred = "getVariableAccess()"
785+
or
786+
expr.(ConstructorFieldInit).getExpr() = ele and pred = "getExpr()"
787+
or
788+
expr.(Conversion).getExpr() = ele and pred = "getExpr()"
789+
or
790+
expr.(DeleteArrayExpr).getAllocatorCall() = ele and pred = "getAllocatorCall()"
791+
or
792+
expr.(DeleteArrayExpr).getDestructorCall() = ele and pred = "getDestructorCall()"
793+
or
794+
expr.(DeleteArrayExpr).getExpr() = ele and pred = "getExpr()"
795+
or
796+
expr.(DeleteExpr).getAllocatorCall() = ele and pred = "getAllocatorCall()"
797+
or
798+
expr.(DeleteExpr).getDestructorCall() = ele and pred = "getDestructorCall()"
799+
or
800+
expr.(DeleteExpr).getExpr() = ele and pred = "getExpr()"
801+
or
802+
expr.(DestructorFieldDestruction).getExpr() = ele and pred = "getExpr()"
803+
or
804+
expr.(FoldExpr).getInitExpr() = ele and pred = "getInitExpr()"
805+
or
806+
expr.(FoldExpr).getPackExpr() = ele and pred = "getPackExpr()"
807+
or
808+
expr.(LambdaExpression).getInitializer() = ele and pred = "getInitializer()"
809+
or
810+
expr.(NewOrNewArrayExpr).getAllocatorCall() = ele and pred = "getAllocatorCall()"
811+
or
812+
expr.(NewOrNewArrayExpr).getAlignmentArgument() = ele and pred = "getAlignmentArgument()"
813+
or
814+
expr.(NewArrayExpr).getInitializer() = ele and pred = "getInitializer()"
815+
or
816+
expr.(NewArrayExpr).getExtent() = ele and pred = "getExtent()"
817+
or
818+
expr.(NewExpr).getInitializer() = ele and pred = "getInitializer()"
819+
or
820+
expr.(NoExceptExpr).getExpr() = ele and pred = "getExpr()"
821+
or
822+
expr.(Assignment).getLValue() = ele and pred = "getLValue()"
823+
or
824+
expr.(Assignment).getRValue() = ele and pred = "getRValue()"
825+
or
826+
not expr instanceof RelationalOperation and
827+
expr.(BinaryOperation).getLeftOperand() = ele and
828+
pred = "getLeftOperand()"
829+
or
830+
not expr instanceof RelationalOperation and
831+
expr.(BinaryOperation).getRightOperand() = ele and
832+
pred = "getRightOperand()"
833+
or
834+
expr.(RelationalOperation).getGreaterOperand() = ele and pred = "getGreaterOperand()"
835+
or
836+
expr.(RelationalOperation).getLesserOperand() = ele and pred = "getLesserOperand()"
837+
or
838+
expr.(ConditionalExpr).getCondition() = ele and pred = "getCondition()"
839+
or
840+
// If ConditionalExpr is in two-operand form, getThen() = getCondition() holds
841+
not expr.(ConditionalExpr).isTwoOperand() and
842+
expr.(ConditionalExpr).getThen() = ele and
843+
pred = "getThen()"
844+
or
845+
expr.(ConditionalExpr).getElse() = ele and pred = "getElse()"
846+
or
847+
expr.(UnaryOperation).getOperand() = ele and pred = "getOperand()"
848+
or
849+
expr.(SizeofExprOperator).getExprOperand() = ele and pred = "getExprOperand()"
850+
or
851+
//expr.(StmtExpr).getStmt() = ele and pred = "getStmt()" // TODO confirm via test that this is a/the child
852+
//or
853+
expr.(ThrowExpr).getExpr() = ele and pred = "getExpr()"
854+
or
855+
expr.(TypeidOperator).getExpr() = ele and pred = "getExpr()"
856+
)
857+
}
858+
573859
/** Holds if `node` belongs to the output tree, and its property `key` has the given `value`. */
574860
query predicate nodes(PrintASTNode node, string key, string value) {
575861
node.shouldPrint() and
@@ -586,9 +872,12 @@ query predicate edges(PrintASTNode source, PrintASTNode target, string key, stri
586872
target.shouldPrint() and
587873
target = source.getChild(childIndex) and
588874
(
589-
key = "semmle.label" and value = source.getChildEdgeLabel(childIndex)
875+
key = "semmle.label" and value = source.getChildAccessorPredicate(childIndex) //source.getChildEdgeLabel(childIndex)
590876
or
591877
key = "semmle.order" and value = childIndex.toString()
878+
or
879+
key = "semmle.predicate" and
880+
value = source.getChildAccessorPredicate(childIndex)
592881
)
593882
)
594883
}

0 commit comments

Comments
 (0)