Skip to content

Commit bf31913

Browse files
committed
C++: temporary workaround to include destructors in AST
1 parent ec6d8da commit bf31913

File tree

3 files changed

+226
-6
lines changed

3 files changed

+226
-6
lines changed

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

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ private newtype TPrintAstNode =
107107
TDestructorDestructionsNode(Destructor dtor) {
108108
dtor.hasEntryPoint() and
109109
shouldPrintDeclaration(dtor)
110+
} or
111+
TDestructorCallStmtNode(DestructorCall call, Stmt parent, int index) {
112+
synthetic_destructor_call(parent, index, call)
113+
} or
114+
TDestructorCallExprNode(DestructorCall call, Expr parent, int index) {
115+
synthetic_destructor_call(parent, index, call)
110116
}
111117

112118
/**
@@ -306,7 +312,9 @@ class ExprNode extends AstNode {
306312

307313
ExprNode() { expr = ast }
308314

309-
override AstNode getChildInternal(int childIndex) { result.getAst() = expr.getChild(childIndex) }
315+
override BaseAstNode getChildInternal(int childIndex) {
316+
result.getAst() = expr.getChild(childIndex)
317+
}
310318

311319
override string getProperty(string key) {
312320
result = super.getProperty(key)
@@ -431,18 +439,27 @@ class StmtNode extends AstNode {
431439

432440
StmtNode() { stmt = ast }
433441

434-
override BaseAstNode getChildInternal(int childIndex) {
442+
override PrintAstNode getChildInternal(int childIndex) {
435443
exists(Locatable child |
436444
child = stmt.getChild(childIndex) and
437445
(
438-
result.getAst() = child.(Expr) or
439-
result.getAst() = child.(Stmt)
446+
result.(AstNode).getAst() = child.(Expr) or
447+
result.(AstNode).getAst() = child.(Stmt)
448+
)
449+
or
450+
exists(int maxIndex, int index, DestructorCall call |
451+
maxIndex = max(int n | exists(stmt.getChild(n)) or n = -1) and
452+
result = TDestructorCallStmtNode(call, stmt, index) and
453+
childIndex = maxIndex + index + 1
440454
)
441455
)
442456
}
443457

444458
override string getChildAccessorPredicateInternal(int childIndex) {
445-
result = getChildAccessorWithoutConversions(ast, this.getChildInternal(childIndex).getAst())
459+
result = getChildAccessorWithoutConversions(ast, this.getChildInternal(childIndex).(AstNode).getAst())
460+
or
461+
this.getChildInternal(childIndex) instanceof DestructorCallStmtNode and
462+
result = "Destructor"
446463
}
447464
}
448465

@@ -454,7 +471,7 @@ class DeclStmtNode extends StmtNode {
454471

455472
DeclStmtNode() { declStmt = stmt }
456473

457-
override DeclarationEntryNode getChildInternal(int childIndex) {
474+
override BaseAstNode getChildInternal(int childIndex) {
458475
exists(DeclarationEntry entry |
459476
declStmt.getDeclarationEntry(childIndex) = entry and
460477
result = TDeclarationEntryNode(declStmt, entry)
@@ -582,6 +599,36 @@ class DestructorDestructionsNode extends PrintAstNode, TDestructorDestructionsNo
582599
final Destructor getDestructor() { result = dtor }
583600
}
584601

602+
class DestructorCallExprNode extends BaseAstNode, TDestructorCallExprNode {
603+
DestructorCall call;
604+
int index;
605+
Expr parent;
606+
607+
DestructorCallExprNode() {
608+
this = TDestructorCallExprNode(call, parent, index) and
609+
call = ast
610+
}
611+
612+
final override AstNode getChildInternal(int childIndex) { none() }
613+
614+
final override string getChildAccessorPredicateInternal(int childIndex) { none() }
615+
}
616+
617+
class DestructorCallStmtNode extends BaseAstNode, TDestructorCallStmtNode {
618+
DestructorCall call;
619+
int index;
620+
Stmt parent;
621+
622+
DestructorCallStmtNode() {
623+
this = TDestructorCallStmtNode(call, parent, index) and
624+
call = ast
625+
}
626+
627+
final override AstNode getChildInternal(int childIndex) { none() }
628+
629+
final override string getChildAccessorPredicateInternal(int childIndex) { none() }
630+
}
631+
585632
abstract private class FunctionOrGlobalOrNamespaceVariableNode extends AstNode {
586633
override string toString() { result = qlClass(ast) + getIdentityString(ast) }
587634

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
#-----| [CopyAssignmentOperator] __va_list_tag& __va_list_tag::operator=(__va_list_tag const&)
2+
#-----| <params>:
3+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
4+
#-----| Type = [LValueReferenceType] const __va_list_tag &
5+
#-----| [MoveAssignmentOperator] __va_list_tag& __va_list_tag::operator=(__va_list_tag&&)
6+
#-----| <params>:
7+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
8+
#-----| Type = [RValueReferenceType] __va_list_tag &&
9+
destructors.cpp:
10+
# 2| [CopyAssignmentOperator] C& C::operator=(C const&)
11+
# 2| <params>:
12+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
13+
#-----| Type = [LValueReferenceType] const C &
14+
# 2| [CopyConstructor] void C::C(C const&)
15+
# 2| <params>:
16+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
17+
#-----| Type = [LValueReferenceType] const C &
18+
# 4| [Constructor] void C::C(int)
19+
# 4| <params>:
20+
# 4| getParameter(0): [Parameter] x
21+
# 4| Type = [IntType] int
22+
# 5| [Destructor] void C::~C()
23+
# 5| <params>:
24+
# 8| [TopLevelFunction] void f(int, int)
25+
# 8| <params>:
26+
# 8| getParameter(0): [Parameter] b1
27+
# 8| Type = [IntType] int
28+
# 8| getParameter(1): [Parameter] b2
29+
# 8| Type = [IntType] int
30+
# 8| getEntryPoint(): [BlockStmt] { ... }
31+
# 9| getStmt(0): [DeclStmt] declaration
32+
# 10| getStmt(1): [BlockStmt] { ... }
33+
# 11| getStmt(0): [DeclStmt] declaration
34+
# 12| getStmt(1): [BlockStmt] { ... }
35+
# 13| getStmt(0): [DeclStmt] declaration
36+
# 14| Destructor: [DestructorCall] call to ~C
37+
# 15| getStmt(2): [BlockStmt] { ... }
38+
# 16| getStmt(0): [DeclStmt] declaration
39+
# 17| getStmt(1): [IfStmt] if (...) ...
40+
# 17| getCondition(): [VariableAccess] b1
41+
# 17| Type = [IntType] int
42+
# 17| ValueCategory = prvalue(load)
43+
# 17| getThen(): [GotoStmt] goto ...
44+
# 26| Destructor: [DestructorCall] call to ~C
45+
# 21| Destructor: [DestructorCall] call to ~C
46+
# 17| getCondition().getFullyConverted(): [CStyleCast] (bool)...
47+
# 17| Conversion = [BoolConversion] conversion to bool
48+
# 17| Type = [BoolType] bool
49+
# 17| ValueCategory = prvalue
50+
# 18| getStmt(2): [DeclStmt] declaration
51+
# 19| getStmt(3): [IfStmt] if (...) ...
52+
# 19| getCondition(): [VariableAccess] b2
53+
# 19| Type = [IntType] int
54+
# 19| ValueCategory = prvalue(load)
55+
# 19| getThen(): [ReturnStmt] return ...
56+
# 35| Destructor: [DestructorCall] call to ~C
57+
# 26| Destructor: [DestructorCall] call to ~C
58+
# 21| Destructor: [DestructorCall] call to ~C
59+
# 21| Destructor: [DestructorCall] call to ~C
60+
# 19| getCondition().getFullyConverted(): [CStyleCast] (bool)...
61+
# 19| Conversion = [BoolConversion] conversion to bool
62+
# 19| Type = [BoolType] bool
63+
# 19| ValueCategory = prvalue
64+
# 20| getStmt(4): [DeclStmt] declaration
65+
# 21| Destructor: [DestructorCall] call to ~C
66+
# 21| Destructor: [DestructorCall] call to ~C
67+
# 21| Destructor: [DestructorCall] call to ~C
68+
# 22| getStmt(3): [BlockStmt] { ... }
69+
# 23| getStmt(0): [DeclStmt] declaration
70+
# 24| Destructor: [DestructorCall] call to ~C
71+
# 25| getStmt(4): [DeclStmt] declaration
72+
# 26| Destructor: [DestructorCall] call to ~C
73+
# 26| Destructor: [DestructorCall] call to ~C
74+
# 27| getStmt(2): [BlockStmt] { ... }
75+
# 28| getStmt(0): [DeclStmt] declaration
76+
# 29| Destructor: [DestructorCall] call to ~C
77+
# 30| getStmt(3): [BlockStmt] { ... }
78+
# 31| getStmt(0): [LabelStmt] label ...:
79+
# 32| getStmt(1): [DeclStmt] declaration
80+
# 33| Destructor: [DestructorCall] call to ~C
81+
# 34| getStmt(4): [DeclStmt] declaration
82+
# 35| getStmt(5): [ReturnStmt] return ...
83+
# 35| Destructor: [DestructorCall] call to ~C
84+
# 35| Destructor: [DestructorCall] call to ~C
85+
destructors2.cpp:
86+
# 5| [CopyAssignmentOperator] Class2& Class2::operator=(Class2 const&)
87+
# 5| <params>:
88+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
89+
#-----| Type = [LValueReferenceType] const Class2 &
90+
# 5| [CopyConstructor] void Class2::Class2(Class2 const&)
91+
# 5| <params>:
92+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
93+
#-----| Type = [LValueReferenceType] const Class2 &
94+
# 5| <initializations>:
95+
# 5| getEntryPoint(): [BlockStmt] { ... }
96+
# 5| getStmt(0): [ReturnStmt] return ...
97+
# 7| [Constructor] void Class2::Class2()
98+
# 7| <params>:
99+
# 8| [Destructor] void Class2::~Class2()
100+
# 8| <params>:
101+
# 11| [TopLevelFunction] Class2 getClass2()
102+
# 11| <params>:
103+
# 13| [CopyAssignmentOperator] Outer& Outer::operator=(Outer const&)
104+
# 13| <params>:
105+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
106+
#-----| Type = [LValueReferenceType] const Outer &
107+
# 13| [MoveAssignmentOperator] Outer& Outer::operator=(Outer&&)
108+
# 13| <params>:
109+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
110+
#-----| Type = [RValueReferenceType] Outer &&
111+
# 15| [CopyAssignmentOperator] Outer::Inner& Outer::Inner::operator=(Outer::Inner const public&)
112+
# 15| <params>:
113+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
114+
#-----| Type = [LValueReferenceType] const Inner &
115+
# 15| [CopyConstructor] void Outer::Inner::Inner(Outer::Inner const public&)
116+
# 15| <params>:
117+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
118+
#-----| Type = [LValueReferenceType] const Inner &
119+
# 17| [Constructor] void Outer::Inner::Inner(Class2 const&)
120+
# 17| <params>:
121+
# 17| getParameter(0): [Parameter] c
122+
# 17| Type = [LValueReferenceType] const Class2 &
123+
# 17| <initializations>:
124+
# 17| getEntryPoint(): [BlockStmt] { ... }
125+
# 17| getStmt(0): [ReturnStmt] return ...
126+
# 18| [Destructor] void Outer::Inner::~Inner()
127+
# 18| <params>:
128+
# 18| getEntryPoint(): [BlockStmt] { ... }
129+
# 18| getStmt(0): [ReturnStmt] return ...
130+
# 18| <destructions>:
131+
# 21| [MemberFunction] void Outer::f2(int)
132+
# 21| <params>:
133+
# 21| getParameter(0): [Parameter] i
134+
# 21| Type = [IntType] int
135+
# 21| getEntryPoint(): [BlockStmt] { ... }
136+
# 22| getStmt(0): [DeclStmt] declaration
137+
# 23| getStmt(1): [IfStmt] if (...) ...
138+
# 23| getCondition(): [VariableAccess] i
139+
# 23| Type = [IntType] int
140+
# 23| ValueCategory = prvalue(load)
141+
# 23| getThen(): [BlockStmt] { ... }
142+
# 24| getStmt(0): [ReturnStmt] return ...
143+
# 27| Destructor: [DestructorCall] call to ~Class2
144+
# 23| getCondition().getFullyConverted(): [CStyleCast] (bool)...
145+
# 23| Conversion = [BoolConversion] conversion to bool
146+
# 23| Type = [BoolType] bool
147+
# 23| ValueCategory = prvalue
148+
# 26| getStmt(2): [DeclStmt] declaration
149+
# 27| getStmt(3): [ReturnStmt] return ...
150+
# 27| Destructor: [DestructorCall] call to ~Class2
151+
# 27| Destructor: [DestructorCall] call to ~Inner
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/**
2+
* @name Print AST
3+
* @description Outputs a representation of the Abstract Syntax Tree.
4+
* @id cpp/print-ast
5+
* @kind graph
6+
*/
7+
8+
import cpp
9+
import semmle.code.cpp.PrintAST
10+
11+
/**
12+
* Temporarily tweak this class or make a copy to control which declarations are
13+
* printed.
14+
*/
15+
class Cfg extends PrintAstConfiguration {
16+
/**
17+
* TWEAK THIS PREDICATE AS NEEDED.
18+
* Holds if the AST for `decl` should be printed.
19+
*/
20+
override predicate shouldPrintDeclaration(Declaration decl) { any() }
21+
}
22+

0 commit comments

Comments
 (0)