Skip to content

Commit 67a8639

Browse files
authored
Merge pull request github#15318 from rdmarsh2/rdmarsh2/cpp/first-class-destructors
C++: First-class destructors in AST
2 parents 32a2ea1 + 0bc0231 commit 67a8639

File tree

8 files changed

+645
-1
lines changed

8 files changed

+645
-1
lines changed

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

+22-1
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,14 @@ class ExprNode extends AstNode {
306306

307307
ExprNode() { expr = ast }
308308

309-
override AstNode getChildInternal(int childIndex) { result.getAst() = expr.getChild(childIndex) }
309+
override AstNode getChildInternal(int childIndex) {
310+
result.getAst() = expr.getChild(childIndex)
311+
or
312+
exists(int destructorIndex |
313+
result.getAst() = expr.getImplicitDestructorCall(destructorIndex) and
314+
childIndex = destructorIndex + max(int index | exists(expr.getChild(index)) or index = 0) + 1
315+
)
316+
}
310317

311318
override string getProperty(string key) {
312319
result = super.getProperty(key)
@@ -439,6 +446,11 @@ class StmtNode extends AstNode {
439446
result.getAst() = child.(Stmt)
440447
)
441448
)
449+
or
450+
exists(int destructorIndex |
451+
result.getAst() = stmt.getImplicitDestructorCall(destructorIndex) and
452+
childIndex = destructorIndex + max(int index | exists(stmt.getChild(index)) or index = 0) + 1
453+
)
442454
}
443455

444456
override string getChildAccessorPredicateInternal(int childIndex) {
@@ -662,13 +674,22 @@ private string getChildAccessorWithoutConversions(Locatable parent, Element chil
662674
or
663675
not namedStmtChildPredicates(s, child, _) and
664676
exists(int n | s.getChild(n) = child and result = "getChild(" + n + ")")
677+
or
678+
exists(int n |
679+
s.getImplicitDestructorCall(n) = child and result = "getImplicitDestructorCall(" + n + ")"
680+
)
665681
)
666682
or
667683
exists(Expr expr | expr = parent |
668684
namedExprChildPredicates(expr, child, result)
669685
or
670686
not namedExprChildPredicates(expr, child, _) and
671687
exists(int n | expr.getChild(n) = child and result = "getChild(" + n + ")")
688+
or
689+
exists(int n |
690+
expr.getImplicitDestructorCall(n) = child and
691+
result = "getImplicitDestructorCall(" + n + ")"
692+
)
672693
)
673694
)
674695
}

cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll

+13
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,19 @@ class Expr extends StmtParent, @expr {
5858
/** Gets the parent of this expression, if any. */
5959
Element getParent() { exprparents(underlyingElement(this), _, unresolveElement(result)) }
6060

61+
/**
62+
* Gets the `n`th compiler-generated destructor call that is performed after this expression, in
63+
* order of destruction.
64+
*/
65+
DestructorCall getImplicitDestructorCall(int n) {
66+
synthetic_destructor_call(this, max(int i | synthetic_destructor_call(this, i, _)) - n, result)
67+
}
68+
69+
/**
70+
* Gets a compiler-generated destructor call that is performed after this expression.
71+
*/
72+
DestructorCall getAnImplicitDestructorCall() { synthetic_destructor_call(this, _, result) }
73+
6174
/** Gets the location of this expression. */
6275
override Location getLocation() {
6376
result = this.getExprLocationOverride()

cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll

+22
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,28 @@ class Stmt extends StmtParent, @stmt {
5959
)
6060
}
6161

62+
/**
63+
* Gets the `n`th compiler-generated destructor call that is performed after this statement, in
64+
* order of destruction.
65+
*
66+
* For instance, in the following code, `getImplicitDestructorCall(0)` for the block will be the
67+
* destructor call for `c2`:
68+
* ```cpp
69+
* {
70+
* MyClass c1;
71+
* MyClass c2;
72+
* }
73+
* ```
74+
*/
75+
DestructorCall getImplicitDestructorCall(int n) {
76+
synthetic_destructor_call(this, max(int i | synthetic_destructor_call(this, i, _)) - n, result)
77+
}
78+
79+
/**
80+
* Gets a compiler-generated destructor call that is performed after this statement.
81+
*/
82+
DestructorCall getAnImplicitDestructorCall() { synthetic_destructor_call(this, _, result) }
83+
6284
override Location getLocation() { stmts(underlyingElement(this), _, result) }
6385

6486
override string toString() { none() }

0 commit comments

Comments
 (0)