Merge pull request #15318 from rdmarsh2/rdmarsh2/cpp/first-class-destructors

C++: First-class destructors in AST
This commit is contained in:
Robert Marsh
2024-01-24 16:19:10 -05:00
committed by GitHub
8 changed files with 645 additions and 1 deletions

View File

@@ -306,7 +306,14 @@ class ExprNode extends AstNode {
ExprNode() { expr = ast }
override AstNode getChildInternal(int childIndex) { result.getAst() = expr.getChild(childIndex) }
override AstNode getChildInternal(int childIndex) {
result.getAst() = expr.getChild(childIndex)
or
exists(int destructorIndex |
result.getAst() = expr.getImplicitDestructorCall(destructorIndex) and
childIndex = destructorIndex + max(int index | exists(expr.getChild(index)) or index = 0) + 1
)
}
override string getProperty(string key) {
result = super.getProperty(key)
@@ -439,6 +446,11 @@ class StmtNode extends AstNode {
result.getAst() = child.(Stmt)
)
)
or
exists(int destructorIndex |
result.getAst() = stmt.getImplicitDestructorCall(destructorIndex) and
childIndex = destructorIndex + max(int index | exists(stmt.getChild(index)) or index = 0) + 1
)
}
override string getChildAccessorPredicateInternal(int childIndex) {
@@ -662,6 +674,10 @@ private string getChildAccessorWithoutConversions(Locatable parent, Element chil
or
not namedStmtChildPredicates(s, child, _) and
exists(int n | s.getChild(n) = child and result = "getChild(" + n + ")")
or
exists(int n |
s.getImplicitDestructorCall(n) = child and result = "getImplicitDestructorCall(" + n + ")"
)
)
or
exists(Expr expr | expr = parent |
@@ -669,6 +685,11 @@ private string getChildAccessorWithoutConversions(Locatable parent, Element chil
or
not namedExprChildPredicates(expr, child, _) and
exists(int n | expr.getChild(n) = child and result = "getChild(" + n + ")")
or
exists(int n |
expr.getImplicitDestructorCall(n) = child and
result = "getImplicitDestructorCall(" + n + ")"
)
)
)
}

View File

@@ -58,6 +58,19 @@ class Expr extends StmtParent, @expr {
/** Gets the parent of this expression, if any. */
Element getParent() { exprparents(underlyingElement(this), _, unresolveElement(result)) }
/**
* Gets the `n`th compiler-generated destructor call that is performed after this expression, in
* order of destruction.
*/
DestructorCall getImplicitDestructorCall(int n) {
synthetic_destructor_call(this, max(int i | synthetic_destructor_call(this, i, _)) - n, result)
}
/**
* Gets a compiler-generated destructor call that is performed after this expression.
*/
DestructorCall getAnImplicitDestructorCall() { synthetic_destructor_call(this, _, result) }
/** Gets the location of this expression. */
override Location getLocation() {
result = this.getExprLocationOverride()

View File

@@ -59,6 +59,28 @@ class Stmt extends StmtParent, @stmt {
)
}
/**
* Gets the `n`th compiler-generated destructor call that is performed after this statement, in
* order of destruction.
*
* For instance, in the following code, `getImplicitDestructorCall(0)` for the block will be the
* destructor call for `c2`:
* ```cpp
* {
* MyClass c1;
* MyClass c2;
* }
* ```
*/
DestructorCall getImplicitDestructorCall(int n) {
synthetic_destructor_call(this, max(int i | synthetic_destructor_call(this, i, _)) - n, result)
}
/**
* Gets a compiler-generated destructor call that is performed after this statement.
*/
DestructorCall getAnImplicitDestructorCall() { synthetic_destructor_call(this, _, result) }
override Location getLocation() { stmts(underlyingElement(this), _, result) }
override string toString() { none() }

View File

@@ -0,0 +1,383 @@
#-----| [CopyAssignmentOperator] __va_list_tag& __va_list_tag::operator=(__va_list_tag const&)
#-----| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const __va_list_tag &
#-----| [MoveAssignmentOperator] __va_list_tag& __va_list_tag::operator=(__va_list_tag&&)
#-----| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] __va_list_tag &&
destructors.cpp:
# 2| [CopyAssignmentOperator] C& C::operator=(C const&)
# 2| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const C &
# 2| [CopyConstructor] void C::C(C const&)
# 2| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const C &
# 4| [Constructor] void C::C(int)
# 4| <params>:
# 4| getParameter(0): [Parameter] x
# 4| Type = [IntType] int
# 5| [Destructor] void C::~C()
# 5| <params>:
# 8| [TopLevelFunction] void f(int, int)
# 8| <params>:
# 8| getParameter(0): [Parameter] b1
# 8| Type = [IntType] int
# 8| getParameter(1): [Parameter] b2
# 8| Type = [IntType] int
# 8| getEntryPoint(): [BlockStmt] { ... }
# 9| getStmt(0): [DeclStmt] declaration
# 9| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c10
# 9| Type = [Class] C
# 9| getVariable().getInitializer(): [Initializer] initializer for c10
# 9| getExpr(): [ConstructorCall] call to C
# 9| Type = [VoidType] void
# 9| ValueCategory = prvalue
# 9| getArgument(0): [Literal] 110
# 9| Type = [IntType] int
# 9| Value = [Literal] 110
# 9| ValueCategory = prvalue
# 10| getStmt(1): [BlockStmt] { ... }
# 11| getStmt(0): [DeclStmt] declaration
# 11| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c20
# 11| Type = [Class] C
# 11| getVariable().getInitializer(): [Initializer] initializer for c20
# 11| getExpr(): [ConstructorCall] call to C
# 11| Type = [VoidType] void
# 11| ValueCategory = prvalue
# 11| getArgument(0): [Literal] 120
# 11| Type = [IntType] int
# 11| Value = [Literal] 120
# 11| ValueCategory = prvalue
# 12| getStmt(1): [BlockStmt] { ... }
# 13| getStmt(0): [DeclStmt] declaration
# 13| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c30
# 13| Type = [Class] C
# 13| getVariable().getInitializer(): [Initializer] initializer for c30
# 13| getExpr(): [ConstructorCall] call to C
# 13| Type = [VoidType] void
# 13| ValueCategory = prvalue
# 13| getArgument(0): [Literal] 130
# 13| Type = [IntType] int
# 13| Value = [Literal] 130
# 13| ValueCategory = prvalue
# 14| getImplicitDestructorCall(0): [DestructorCall] call to ~C
# 14| Type = [VoidType] void
# 14| ValueCategory = prvalue
# 14| getQualifier(): [VariableAccess] c30
# 14| Type = [Class] C
# 14| ValueCategory = lvalue
# 15| getStmt(2): [BlockStmt] { ... }
# 16| getStmt(0): [DeclStmt] declaration
# 16| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c31
# 16| Type = [Class] C
# 16| getVariable().getInitializer(): [Initializer] initializer for c31
# 16| getExpr(): [ConstructorCall] call to C
# 16| Type = [VoidType] void
# 16| ValueCategory = prvalue
# 16| getArgument(0): [Literal] 131
# 16| Type = [IntType] int
# 16| Value = [Literal] 131
# 16| ValueCategory = prvalue
# 17| getStmt(1): [IfStmt] if (...) ...
# 17| getCondition(): [VariableAccess] b1
# 17| Type = [IntType] int
# 17| ValueCategory = prvalue(load)
# 17| getThen(): [GotoStmt] goto ...
# 21| getImplicitDestructorCall(0): [DestructorCall] call to ~C
# 21| Type = [VoidType] void
# 21| ValueCategory = prvalue
# 21| getQualifier(): [VariableAccess] c31
# 21| Type = [Class] C
# 21| ValueCategory = lvalue
# 26| getImplicitDestructorCall(1): [DestructorCall] call to ~C
# 26| Type = [VoidType] void
# 26| ValueCategory = prvalue
# 26| getQualifier(): [VariableAccess] c20
# 26| Type = [Class] C
# 26| ValueCategory = lvalue
# 17| getCondition().getFullyConverted(): [CStyleCast] (bool)...
# 17| Conversion = [BoolConversion] conversion to bool
# 17| Type = [BoolType] bool
# 17| ValueCategory = prvalue
# 18| getStmt(2): [DeclStmt] declaration
# 18| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c32
# 18| Type = [Class] C
# 18| getVariable().getInitializer(): [Initializer] initializer for c32
# 18| getExpr(): [ConstructorCall] call to C
# 18| Type = [VoidType] void
# 18| ValueCategory = prvalue
# 18| getArgument(0): [Literal] 132
# 18| Type = [IntType] int
# 18| Value = [Literal] 132
# 18| ValueCategory = prvalue
# 19| getStmt(3): [IfStmt] if (...) ...
# 19| getCondition(): [VariableAccess] b2
# 19| Type = [IntType] int
# 19| ValueCategory = prvalue(load)
# 19| getThen(): [ReturnStmt] return ...
# 21| getImplicitDestructorCall(0): [DestructorCall] call to ~C
# 21| Type = [VoidType] void
# 21| ValueCategory = prvalue
# 21| getQualifier(): [VariableAccess] c32
# 21| Type = [Class] C
# 21| ValueCategory = lvalue
# 21| getImplicitDestructorCall(1): [DestructorCall] call to ~C
# 21| Type = [VoidType] void
# 21| ValueCategory = prvalue
# 21| getQualifier(): [VariableAccess] c31
# 21| Type = [Class] C
# 21| ValueCategory = lvalue
# 26| getImplicitDestructorCall(2): [DestructorCall] call to ~C
# 26| Type = [VoidType] void
# 26| ValueCategory = prvalue
# 26| getQualifier(): [VariableAccess] c20
# 26| Type = [Class] C
# 26| ValueCategory = lvalue
# 35| getImplicitDestructorCall(3): [DestructorCall] call to ~C
# 35| Type = [VoidType] void
# 35| ValueCategory = prvalue
# 35| getQualifier(): [VariableAccess] c10
# 35| Type = [Class] C
# 35| ValueCategory = lvalue
# 19| getCondition().getFullyConverted(): [CStyleCast] (bool)...
# 19| Conversion = [BoolConversion] conversion to bool
# 19| Type = [BoolType] bool
# 19| ValueCategory = prvalue
# 20| getStmt(4): [DeclStmt] declaration
# 20| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c33
# 20| Type = [Class] C
# 20| getVariable().getInitializer(): [Initializer] initializer for c33
# 20| getExpr(): [ConstructorCall] call to C
# 20| Type = [VoidType] void
# 20| ValueCategory = prvalue
# 20| getArgument(0): [Literal] 133
# 20| Type = [IntType] int
# 20| Value = [Literal] 133
# 20| ValueCategory = prvalue
# 21| getImplicitDestructorCall(0): [DestructorCall] call to ~C
# 21| Type = [VoidType] void
# 21| ValueCategory = prvalue
# 21| getQualifier(): [VariableAccess] c33
# 21| Type = [Class] C
# 21| ValueCategory = lvalue
# 21| getImplicitDestructorCall(1): [DestructorCall] call to ~C
# 21| Type = [VoidType] void
# 21| ValueCategory = prvalue
# 21| getQualifier(): [VariableAccess] c32
# 21| Type = [Class] C
# 21| ValueCategory = lvalue
# 21| getImplicitDestructorCall(2): [DestructorCall] call to ~C
# 21| Type = [VoidType] void
# 21| ValueCategory = prvalue
# 21| getQualifier(): [VariableAccess] c31
# 21| Type = [Class] C
# 21| ValueCategory = lvalue
# 22| getStmt(3): [BlockStmt] { ... }
# 23| getStmt(0): [DeclStmt] declaration
# 23| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c34
# 23| Type = [Class] C
# 23| getVariable().getInitializer(): [Initializer] initializer for c34
# 23| getExpr(): [ConstructorCall] call to C
# 23| Type = [VoidType] void
# 23| ValueCategory = prvalue
# 23| getArgument(0): [Literal] 134
# 23| Type = [IntType] int
# 23| Value = [Literal] 134
# 23| ValueCategory = prvalue
# 24| getImplicitDestructorCall(0): [DestructorCall] call to ~C
# 24| Type = [VoidType] void
# 24| ValueCategory = prvalue
# 24| getQualifier(): [VariableAccess] c34
# 24| Type = [Class] C
# 24| ValueCategory = lvalue
# 25| getStmt(4): [DeclStmt] declaration
# 25| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c21
# 25| Type = [Class] C
# 25| getVariable().getInitializer(): [Initializer] initializer for c21
# 25| getExpr(): [ConstructorCall] call to C
# 25| Type = [VoidType] void
# 25| ValueCategory = prvalue
# 25| getArgument(0): [Literal] 121
# 25| Type = [IntType] int
# 25| Value = [Literal] 121
# 25| ValueCategory = prvalue
# 26| getImplicitDestructorCall(0): [DestructorCall] call to ~C
# 26| Type = [VoidType] void
# 26| ValueCategory = prvalue
# 26| getQualifier(): [VariableAccess] c21
# 26| Type = [Class] C
# 26| ValueCategory = lvalue
# 26| getImplicitDestructorCall(1): [DestructorCall] call to ~C
# 26| Type = [VoidType] void
# 26| ValueCategory = prvalue
# 26| getQualifier(): [VariableAccess] c20
# 26| Type = [Class] C
# 26| ValueCategory = lvalue
# 27| getStmt(2): [BlockStmt] { ... }
# 28| getStmt(0): [DeclStmt] declaration
# 28| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c22
# 28| Type = [Class] C
# 28| getVariable().getInitializer(): [Initializer] initializer for c22
# 28| getExpr(): [ConstructorCall] call to C
# 28| Type = [VoidType] void
# 28| ValueCategory = prvalue
# 28| getArgument(0): [Literal] 122
# 28| Type = [IntType] int
# 28| Value = [Literal] 122
# 28| ValueCategory = prvalue
# 29| getImplicitDestructorCall(0): [DestructorCall] call to ~C
# 29| Type = [VoidType] void
# 29| ValueCategory = prvalue
# 29| getQualifier(): [VariableAccess] c22
# 29| Type = [Class] C
# 29| ValueCategory = lvalue
# 30| getStmt(3): [BlockStmt] { ... }
# 31| getStmt(0): [LabelStmt] label ...:
# 32| getStmt(1): [DeclStmt] declaration
# 32| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c23
# 32| Type = [Class] C
# 32| getVariable().getInitializer(): [Initializer] initializer for c23
# 32| getExpr(): [ConstructorCall] call to C
# 32| Type = [VoidType] void
# 32| ValueCategory = prvalue
# 32| getArgument(0): [Literal] 123
# 32| Type = [IntType] int
# 32| Value = [Literal] 123
# 32| ValueCategory = prvalue
# 33| getImplicitDestructorCall(0): [DestructorCall] call to ~C
# 33| Type = [VoidType] void
# 33| ValueCategory = prvalue
# 33| getQualifier(): [VariableAccess] c23
# 33| Type = [Class] C
# 33| ValueCategory = lvalue
# 34| getStmt(4): [DeclStmt] declaration
# 34| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c11
# 34| Type = [Class] C
# 34| getVariable().getInitializer(): [Initializer] initializer for c11
# 34| getExpr(): [ConstructorCall] call to C
# 34| Type = [VoidType] void
# 34| ValueCategory = prvalue
# 34| getArgument(0): [Literal] 111
# 34| Type = [IntType] int
# 34| Value = [Literal] 111
# 34| ValueCategory = prvalue
# 35| getStmt(5): [ReturnStmt] return ...
# 35| getImplicitDestructorCall(0): [DestructorCall] call to ~C
# 35| Type = [VoidType] void
# 35| ValueCategory = prvalue
# 35| getQualifier(): [VariableAccess] c11
# 35| Type = [Class] C
# 35| ValueCategory = lvalue
# 35| getImplicitDestructorCall(1): [DestructorCall] call to ~C
# 35| Type = [VoidType] void
# 35| ValueCategory = prvalue
# 35| getQualifier(): [VariableAccess] c10
# 35| Type = [Class] C
# 35| ValueCategory = lvalue
destructors2.cpp:
# 5| [CopyAssignmentOperator] Class2& Class2::operator=(Class2 const&)
# 5| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Class2 &
# 5| [CopyConstructor] void Class2::Class2(Class2 const&)
# 5| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Class2 &
# 5| <initializations>:
# 5| getEntryPoint(): [BlockStmt] { ... }
# 5| getStmt(0): [ReturnStmt] return ...
# 7| [Constructor] void Class2::Class2()
# 7| <params>:
# 8| [Destructor] void Class2::~Class2()
# 8| <params>:
# 11| [TopLevelFunction] Class2 getClass2()
# 11| <params>:
# 13| [CopyAssignmentOperator] Outer& Outer::operator=(Outer const&)
# 13| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Outer &
# 13| [MoveAssignmentOperator] Outer& Outer::operator=(Outer&&)
# 13| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] Outer &&
# 15| [CopyAssignmentOperator] Outer::Inner& Outer::Inner::operator=(Outer::Inner const public&)
# 15| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Inner &
# 15| [CopyConstructor] void Outer::Inner::Inner(Outer::Inner const public&)
# 15| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Inner &
# 17| [Constructor] void Outer::Inner::Inner(Class2 const&)
# 17| <params>:
# 17| getParameter(0): [Parameter] c
# 17| Type = [LValueReferenceType] const Class2 &
# 17| <initializations>:
# 17| getEntryPoint(): [BlockStmt] { ... }
# 17| getStmt(0): [ReturnStmt] return ...
# 18| [Destructor] void Outer::Inner::~Inner()
# 18| <params>:
# 18| getEntryPoint(): [BlockStmt] { ... }
# 18| getStmt(0): [ReturnStmt] return ...
# 18| <destructions>:
# 21| [MemberFunction] void Outer::f2(int)
# 21| <params>:
# 21| getParameter(0): [Parameter] i
# 21| Type = [IntType] int
# 21| getEntryPoint(): [BlockStmt] { ... }
# 22| getStmt(0): [DeclStmt] declaration
# 22| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
# 22| Type = [Class] Class2
# 22| getVariable().getInitializer(): [Initializer] initializer for c
# 22| getExpr(): [FunctionCall] call to getClass2
# 22| Type = [Class] Class2
# 22| ValueCategory = prvalue
# 23| getStmt(1): [IfStmt] if (...) ...
# 23| getCondition(): [VariableAccess] i
# 23| Type = [IntType] int
# 23| ValueCategory = prvalue(load)
# 23| getThen(): [BlockStmt] { ... }
# 24| getStmt(0): [ReturnStmt] return ...
# 27| getImplicitDestructorCall(0): [DestructorCall] call to ~Class2
# 27| Type = [VoidType] void
# 27| ValueCategory = prvalue
# 27| getQualifier(): [VariableAccess] c
# 27| Type = [Class] Class2
# 27| ValueCategory = lvalue
# 23| getCondition().getFullyConverted(): [CStyleCast] (bool)...
# 23| Conversion = [BoolConversion] conversion to bool
# 23| Type = [BoolType] bool
# 23| ValueCategory = prvalue
# 26| getStmt(2): [DeclStmt] declaration
# 26| getDeclarationEntry(0): [VariableDeclarationEntry] definition of inner
# 26| Type = [NestedClass] Inner
# 26| getVariable().getInitializer(): [Initializer] initializer for inner
# 26| getExpr(): [ConstructorCall] call to Inner
# 26| Type = [VoidType] void
# 26| ValueCategory = prvalue
# 26| getArgument(0): [VariableAccess] c
# 26| Type = [Class] Class2
# 26| ValueCategory = lvalue
# 26| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
# 26| Type = [LValueReferenceType] const Class2 &
# 26| ValueCategory = prvalue
# 26| getExpr(): [CStyleCast] (const Class2)...
# 26| Conversion = [GlvalueConversion] glvalue conversion
# 26| Type = [SpecifiedType] const Class2
# 26| ValueCategory = lvalue
# 27| getStmt(3): [ReturnStmt] return ...
# 27| getImplicitDestructorCall(0): [DestructorCall] call to ~Inner
# 27| Type = [VoidType] void
# 27| ValueCategory = prvalue
# 27| getQualifier(): [VariableAccess] inner
# 27| Type = [NestedClass] Inner
# 27| ValueCategory = lvalue
# 27| getImplicitDestructorCall(1): [DestructorCall] call to ~Class2
# 27| Type = [VoidType] void
# 27| ValueCategory = prvalue
# 27| getQualifier(): [VariableAccess] c
# 27| Type = [Class] Class2
# 27| ValueCategory = lvalue

View File

@@ -0,0 +1,10 @@
/**
* @kind graph
*/
private import cpp
private import semmle.code.cpp.PrintAST
private class PrintConfig extends PrintAstConfiguration {
override predicate shouldPrintDeclaration(Declaration decl) { any() }
}

View File

@@ -0,0 +1,22 @@
exprDestructors
stmtDestructors
| destructors2.cpp:24:13:24:19 | return ... | 0 | destructors2.cpp:27:5:27:5 | call to ~Class2 | destructors2.cpp:27:5:27:5 | c |
| destructors2.cpp:27:5:27:5 | return ... | 0 | destructors2.cpp:27:5:27:5 | call to ~Inner | destructors2.cpp:27:5:27:5 | inner |
| destructors2.cpp:27:5:27:5 | return ... | 1 | destructors2.cpp:27:5:27:5 | call to ~Class2 | destructors2.cpp:27:5:27:5 | c |
| destructors.cpp:10:5:26:5 | { ... } | 0 | destructors.cpp:26:5:26:5 | call to ~C | destructors.cpp:26:5:26:5 | c21 |
| destructors.cpp:10:5:26:5 | { ... } | 1 | destructors.cpp:26:5:26:5 | call to ~C | destructors.cpp:26:5:26:5 | c20 |
| destructors.cpp:12:9:14:9 | { ... } | 0 | destructors.cpp:14:9:14:9 | call to ~C | destructors.cpp:14:9:14:9 | c30 |
| destructors.cpp:15:9:21:9 | { ... } | 0 | destructors.cpp:21:9:21:9 | call to ~C | destructors.cpp:21:9:21:9 | c33 |
| destructors.cpp:15:9:21:9 | { ... } | 1 | destructors.cpp:21:9:21:9 | call to ~C | destructors.cpp:21:9:21:9 | c32 |
| destructors.cpp:15:9:21:9 | { ... } | 2 | destructors.cpp:21:9:21:9 | call to ~C | destructors.cpp:21:9:21:9 | c31 |
| destructors.cpp:17:21:17:29 | goto ... | 0 | destructors.cpp:21:9:21:9 | call to ~C | destructors.cpp:21:9:21:9 | c31 |
| destructors.cpp:17:21:17:29 | goto ... | 1 | destructors.cpp:26:5:26:5 | call to ~C | destructors.cpp:26:5:26:5 | c20 |
| destructors.cpp:19:21:19:27 | return ... | 0 | destructors.cpp:21:9:21:9 | call to ~C | destructors.cpp:21:9:21:9 | c32 |
| destructors.cpp:19:21:19:27 | return ... | 1 | destructors.cpp:21:9:21:9 | call to ~C | destructors.cpp:21:9:21:9 | c31 |
| destructors.cpp:19:21:19:27 | return ... | 2 | destructors.cpp:26:5:26:5 | call to ~C | destructors.cpp:26:5:26:5 | c20 |
| destructors.cpp:19:21:19:27 | return ... | 3 | destructors.cpp:35:1:35:1 | call to ~C | destructors.cpp:35:1:35:1 | c10 |
| destructors.cpp:22:9:24:9 | { ... } | 0 | destructors.cpp:24:9:24:9 | call to ~C | destructors.cpp:24:9:24:9 | c34 |
| destructors.cpp:27:5:29:5 | { ... } | 0 | destructors.cpp:29:5:29:5 | call to ~C | destructors.cpp:29:5:29:5 | c22 |
| destructors.cpp:30:5:33:5 | { ... } | 0 | destructors.cpp:33:5:33:5 | call to ~C | destructors.cpp:33:5:33:5 | c23 |
| destructors.cpp:35:1:35:1 | return ... | 0 | destructors.cpp:35:1:35:1 | call to ~C | destructors.cpp:35:1:35:1 | c11 |
| destructors.cpp:35:1:35:1 | return ... | 1 | destructors.cpp:35:1:35:1 | call to ~C | destructors.cpp:35:1:35:1 | c10 |

View File

@@ -0,0 +1,11 @@
import cpp
query predicate exprDestructors(Expr e, int i, DestructorCall d, Expr destructed) {
d = e.getImplicitDestructorCall(i) and
d.getQualifier() = destructed
}
query predicate stmtDestructors(Stmt s, int i, DestructorCall d, Expr destructed) {
d = s.getImplicitDestructorCall(i) and
d.getQualifier() = destructed
}

View File

@@ -5565,6 +5565,30 @@ ir.cpp:
# 619| Type = [PointerType] const char *
# 619| ValueCategory = prvalue
# 620| getStmt(4): [ReturnStmt] return ...
# 620| getImplicitDestructorCall(0): [DestructorCall] call to ~String
# 620| Type = [VoidType] void
# 620| ValueCategory = prvalue
# 620| getQualifier(): [VariableAccess] s4
# 620| Type = [Struct] String
# 620| ValueCategory = lvalue
# 620| getImplicitDestructorCall(1): [DestructorCall] call to ~String
# 620| Type = [VoidType] void
# 620| ValueCategory = prvalue
# 620| getQualifier(): [VariableAccess] s3
# 620| Type = [Struct] String
# 620| ValueCategory = lvalue
# 620| getImplicitDestructorCall(2): [DestructorCall] call to ~String
# 620| Type = [VoidType] void
# 620| ValueCategory = prvalue
# 620| getQualifier(): [VariableAccess] s2
# 620| Type = [Struct] String
# 620| ValueCategory = lvalue
# 620| getImplicitDestructorCall(3): [DestructorCall] call to ~String
# 620| Type = [VoidType] void
# 620| ValueCategory = prvalue
# 620| getQualifier(): [VariableAccess] s1
# 620| Type = [Struct] String
# 620| ValueCategory = lvalue
# 622| [TopLevelFunction] void CallMethods(String&, String*, String)
# 622| <params>:
# 622| getParameter(0): [Parameter] r
@@ -7312,6 +7336,24 @@ ir.cpp:
# 839| Type = [PointerType] Base *
# 839| ValueCategory = prvalue
# 840| getStmt(34): [ReturnStmt] return ...
# 840| getImplicitDestructorCall(0): [DestructorCall] call to ~Derived
# 840| Type = [VoidType] void
# 840| ValueCategory = prvalue
# 840| getQualifier(): [VariableAccess] d
# 840| Type = [Struct] Derived
# 840| ValueCategory = lvalue
# 840| getImplicitDestructorCall(1): [DestructorCall] call to ~Middle
# 840| Type = [VoidType] void
# 840| ValueCategory = prvalue
# 840| getQualifier(): [VariableAccess] m
# 840| Type = [Struct] Middle
# 840| ValueCategory = lvalue
# 840| getImplicitDestructorCall(2): [DestructorCall] call to ~Base
# 840| Type = [VoidType] void
# 840| ValueCategory = prvalue
# 840| getQualifier(): [VariableAccess] b
# 840| Type = [Struct,VirtualBaseClass] Base
# 840| ValueCategory = lvalue
# 842| [CopyAssignmentOperator] PolymorphicBase& PolymorphicBase::operator=(PolymorphicBase const&)
# 842| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
@@ -7475,6 +7517,18 @@ ir.cpp:
# 864| Type = [PointerType] const void *
# 864| ValueCategory = prvalue
# 865| getStmt(10): [ReturnStmt] return ...
# 865| getImplicitDestructorCall(0): [DestructorCall] call to ~PolymorphicDerived
# 865| Type = [VoidType] void
# 865| ValueCategory = prvalue
# 865| getQualifier(): [VariableAccess] d
# 865| Type = [Struct] PolymorphicDerived
# 865| ValueCategory = lvalue
# 865| getImplicitDestructorCall(1): [DestructorCall] call to ~PolymorphicBase
# 865| Type = [VoidType] void
# 865| ValueCategory = prvalue
# 865| getQualifier(): [VariableAccess] b
# 865| Type = [Struct] PolymorphicBase
# 865| ValueCategory = lvalue
# 867| [Constructor] void String::String()
# 867| <params>:
# 867| <initializations>:
@@ -8954,6 +9008,18 @@ ir.cpp:
# 1055| Value = [CStyleCast] 6.0
# 1055| ValueCategory = prvalue
# 1056| getStmt(15): [ReturnStmt] return ...
# 1056| getImplicitDestructorCall(0): [DestructorCall] call to ~<unnamed>
# 1056| Type = [VoidType] void
# 1056| ValueCategory = prvalue
# 1056| getQualifier(): [VariableAccess] lambda_val_explicit
# 1056| Type = [Closure,LocalClass] decltype([...](...){...})
# 1056| ValueCategory = lvalue
# 1056| getImplicitDestructorCall(1): [DestructorCall] call to ~<unnamed>
# 1056| Type = [VoidType] void
# 1056| ValueCategory = prvalue
# 1056| getQualifier(): [VariableAccess] lambda_val
# 1056| Type = [Closure,LocalClass] decltype([...](...){...})
# 1056| ValueCategory = lvalue
# 1041| [CopyAssignmentOperator] (void Lambda(int, String const&))::(lambda [] type at line 1041, col. 23)& (void Lambda(int, String const&))::(lambda [] type at line 1041, col. 23)::operator=((void Lambda(int, String const&))::(lambda [] type at line 1041, col. 23) const&)
# 1041| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
@@ -10149,6 +10215,24 @@ ir.cpp:
# 1243| Type = [PointerType] const char *
# 1243| ValueCategory = prvalue(load)
# 1244| getStmt(3): [ReturnStmt] return ...
# 1244| getImplicitDestructorCall(0): [DestructorCall] call to ~String
# 1244| Type = [VoidType] void
# 1244| ValueCategory = prvalue
# 1244| getQualifier(): [VariableAccess] c
# 1244| Type = [Struct] String
# 1244| ValueCategory = lvalue
# 1244| getImplicitDestructorCall(1): [DestructorCall] call to ~String
# 1244| Type = [VoidType] void
# 1244| ValueCategory = prvalue
# 1244| getQualifier(): [VariableAccess] b
# 1244| Type = [Struct] String
# 1244| ValueCategory = lvalue
# 1244| getImplicitDestructorCall(2): [DestructorCall] call to ~String
# 1244| Type = [VoidType] void
# 1244| ValueCategory = prvalue
# 1244| getQualifier(): [VariableAccess] a
# 1244| Type = [Struct] String
# 1244| ValueCategory = lvalue
# 1248| [TopLevelFunction] char* strcpy(char*, char const*)
# 1248| <params>:
# 1248| getParameter(0): [Parameter] destination
@@ -10403,6 +10487,12 @@ ir.cpp:
# 1286| Type = [PointerType] A *
# 1286| ValueCategory = prvalue
# 1287| getStmt(12): [ReturnStmt] return ...
# 1287| getImplicitDestructorCall(0): [DestructorCall] call to ~C
# 1287| Type = [VoidType] void
# 1287| ValueCategory = prvalue
# 1287| getQualifier(): [VariableAccess] c
# 1287| Type = [Class] C
# 1287| ValueCategory = lvalue
# 1289| [TopLevelFunction] int missingReturnValue(bool, int)
# 1289| <params>:
# 1289| getParameter(0): [Parameter] b
@@ -10957,6 +11047,12 @@ ir.cpp:
# 1376| Type = [Struct] String
# 1376| ValueCategory = prvalue
# 1377| getStmt(9): [ReturnStmt] return ...
# 1377| getImplicitDestructorCall(0): [DestructorCall] call to ~String
# 1377| Type = [VoidType] void
# 1377| ValueCategory = prvalue
# 1377| getQualifier(): [VariableAccess] s
# 1377| Type = [Struct] String
# 1377| ValueCategory = lvalue
# 1379| [TopLevelFunction] void temporary_destructor_only()
# 1379| <params>:
# 1379| getEntryPoint(): [BlockStmt] { ... }
@@ -11040,6 +11136,18 @@ ir.cpp:
# 1388| Type = [Class] destructor_only
# 1388| ValueCategory = prvalue
# 1389| getStmt(8): [ReturnStmt] return ...
# 1389| getImplicitDestructorCall(0): [DestructorCall] call to ~destructor_only
# 1389| Type = [VoidType] void
# 1389| ValueCategory = prvalue
# 1389| getQualifier(): [VariableAccess] d2
# 1389| Type = [Class] destructor_only
# 1389| ValueCategory = lvalue
# 1389| getImplicitDestructorCall(1): [DestructorCall] call to ~destructor_only
# 1389| Type = [VoidType] void
# 1389| ValueCategory = prvalue
# 1389| getQualifier(): [VariableAccess] d
# 1389| Type = [Class] destructor_only
# 1389| ValueCategory = lvalue
# 1391| [TopLevelFunction] void temporary_copy_constructor()
# 1391| <params>:
# 1391| getEntryPoint(): [BlockStmt] { ... }
@@ -14696,6 +14804,12 @@ ir.cpp:
# 1925| Value = [Literal] 10
# 1925| ValueCategory = prvalue
# 1926| getStmt(7): [ReturnStmt] return ...
# 1926| getImplicitDestructorCall(0): [DestructorCall] call to ~C
# 1926| Type = [VoidType] void
# 1926| ValueCategory = prvalue
# 1926| getQualifier(): [VariableAccess] c
# 1926| Type = [Class] C
# 1926| ValueCategory = lvalue
# 1928| [TopLevelFunction] void test_double_assign()
# 1928| <params>:
# 1928| getEntryPoint(): [BlockStmt] { ... }
@@ -15048,6 +15162,12 @@ ir.cpp:
# 1993| Type = [Class] C
# 1993| ValueCategory = lvalue
# 1994| getStmt(3): [ReturnStmt] return ...
# 1994| getImplicitDestructorCall(0): [DestructorCall] call to ~C
# 1994| Type = [VoidType] void
# 1994| ValueCategory = prvalue
# 1994| getQualifier(): [VariableAccess] c
# 1994| Type = [Class] C
# 1994| ValueCategory = lvalue
# 1996| [TopLevelFunction] void TernaryTestInt(bool, int, int, int)
# 1996| <params>:
# 1996| getParameter(0): [Parameter] a
@@ -16062,6 +16182,12 @@ smart_ptr.cpp:
# 12| Type = [CTypedefType,NestedTypedefType] type
# 12| ValueCategory = prvalue(load)
# 13| getStmt(2): [ReturnStmt] return ...
# 13| getImplicitDestructorCall(0): [DestructorCall] call to ~unique_ptr
# 13| Type = [VoidType] void
# 13| ValueCategory = prvalue
# 13| getQualifier(): [VariableAccess] up
# 13| Type = [ClassTemplateInstantiation] unique_ptr<int, default_delete<int>>
# 13| ValueCategory = lvalue
# 15| [TopLevelFunction] void shared_ptr_arg(std::shared_ptr<float>)
# 15| <params>:
# 15| getParameter(0): [Parameter] sp
@@ -16102,6 +16228,12 @@ smart_ptr.cpp:
# 19| Type = [ClassTemplateInstantiation] shared_ptr<float>
# 19| ValueCategory = lvalue
# 20| getStmt(2): [ReturnStmt] return ...
# 20| getImplicitDestructorCall(0): [DestructorCall] call to ~shared_ptr
# 20| Type = [VoidType] void
# 20| ValueCategory = prvalue
# 20| getQualifier(): [VariableAccess] sp
# 20| Type = [ClassTemplateInstantiation] shared_ptr<float>
# 20| ValueCategory = lvalue
# 22| [TopLevelFunction] void shared_ptr_const_int(std::shared_ptr<int const>)
# 22| <params>:
# 22| getParameter(0): [Parameter] (unnamed parameter 0)
@@ -16241,6 +16373,36 @@ smart_ptr.cpp:
# 47| Type = [ClassTemplateInstantiation] shared_ptr<const shared_ptr<const int>>
# 47| ValueCategory = lvalue
# 48| getStmt(10): [ReturnStmt] return ...
# 48| getImplicitDestructorCall(0): [DestructorCall] call to ~shared_ptr
# 48| Type = [VoidType] void
# 48| ValueCategory = prvalue
# 48| getQualifier(): [VariableAccess] sp_const_sp_const_int
# 48| Type = [ClassTemplateInstantiation] shared_ptr<const shared_ptr<const int>>
# 48| ValueCategory = lvalue
# 48| getImplicitDestructorCall(1): [DestructorCall] call to ~shared_ptr
# 48| Type = [VoidType] void
# 48| ValueCategory = prvalue
# 48| getQualifier(): [VariableAccess] sp_const_sp_int
# 48| Type = [ClassTemplateInstantiation] shared_ptr<const shared_ptr<int>>
# 48| ValueCategory = lvalue
# 48| getImplicitDestructorCall(2): [DestructorCall] call to ~shared_ptr
# 48| Type = [VoidType] void
# 48| ValueCategory = prvalue
# 48| getQualifier(): [VariableAccess] sp_sp_const_int
# 48| Type = [ClassTemplateInstantiation] shared_ptr<shared_ptr<const int>>
# 48| ValueCategory = lvalue
# 48| getImplicitDestructorCall(3): [DestructorCall] call to ~shared_ptr
# 48| Type = [VoidType] void
# 48| ValueCategory = prvalue
# 48| getQualifier(): [VariableAccess] sp_const_int_pointer
# 48| Type = [ClassTemplateInstantiation] shared_ptr<int *const>
# 48| ValueCategory = lvalue
# 48| getImplicitDestructorCall(4): [DestructorCall] call to ~shared_ptr
# 48| Type = [VoidType] void
# 48| ValueCategory = prvalue
# 48| getQualifier(): [VariableAccess] sp_const_int
# 48| Type = [ClassTemplateInstantiation] shared_ptr<const int>
# 48| ValueCategory = lvalue
struct_init.cpp:
# 1| [TopLevelFunction] int handler1(void*)
# 1| <params>: