Skip to content

Commit 4ca98bd

Browse files
committed
CPP: Add parent class for delete and delete[]
1 parent 6573b1f commit 4ca98bd

File tree

1 file changed

+44
-84
lines changed
  • cpp/ql/lib/semmle/code/cpp/exprs

1 file changed

+44
-84
lines changed

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

Lines changed: 44 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -932,39 +932,24 @@ class NewArrayExpr extends NewOrNewArrayExpr, @new_array_expr {
932932
Expr getExtent() { result = this.getChild(2) }
933933
}
934934

935+
private class TDeleteOrDeleteArrayExpr = @delete_expr or @delete_array_expr;
936+
935937
/**
936-
* A C++ `delete` (non-array) expression.
937-
* ```
938-
* delete ptr;
939-
* ```
938+
* A C++ `delete` or `delete[]` expression.
940939
*/
941-
class DeleteExpr extends Expr, @delete_expr {
942-
override string toString() { result = "delete" }
943-
944-
override string getAPrimaryQlClass() { result = "DeleteExpr" }
945-
940+
class DeleteOrDeleteArrayExpr extends Expr, TDeleteOrDeleteArrayExpr {
946941
override int getPrecedence() { result = 16 }
947942

948-
/**
949-
* Gets the compile-time type of the object being deleted.
950-
*/
951-
Type getDeletedObjectType() {
952-
result =
953-
this.getExpr()
954-
.getFullyConverted()
955-
.getType()
956-
.stripTopLevelSpecifiers()
957-
.(PointerType)
958-
.getBaseType()
959-
}
960-
961943
/**
962944
* Gets the call to a destructor that occurs prior to the object's memory being deallocated, if any.
945+
*
946+
* In the case of `delete[]` at runtime, the destructor will be called once for each element in the array, but the
947+
* destructor call only exists once in the AST.
963948
*/
964949
DestructorCall getDestructorCall() { result = this.getChild(1) }
965950

966951
/**
967-
* Gets the destructor to be called to destroy the object, if any.
952+
* Gets the destructor to be called to destroy the object(s), if any.
968953
*/
969954
Destructor getDestructor() { result = this.getDestructorCall().getTarget() }
970955

@@ -978,6 +963,14 @@ class DeleteExpr extends Expr, @delete_expr {
978963
expr_deallocator(underlyingElement(this), unresolveElement(result), _)
979964
}
980965

966+
/**
967+
* Gets the call to a non-default `operator delete` that deallocates storage, if any.
968+
*
969+
* This will only be present when the type being deleted has a custom `operator delete` and
970+
* is not a class with a virtual destructor.
971+
*/
972+
FunctionCall getAllocatorCall() { result = this.getChild(0) }
973+
981974
/**
982975
* Holds if the deallocation function expects a size argument.
983976
*/
@@ -999,16 +992,37 @@ class DeleteExpr extends Expr, @delete_expr {
999992
}
1000993

1001994
/**
1002-
* Gets the call to a non-default `operator delete` that deallocates storage, if any.
1003-
*
1004-
* This will only be present when the type being deleted has a custom `operator delete`.
995+
* Gets the object being deleted.
1005996
*/
1006-
FunctionCall getAllocatorCall() { result = this.getChild(0) }
997+
Expr getExpr() {
998+
// If there is a destuctor call, the object being deleted is the qualifier
999+
// otherwise it is the third child.
1000+
result = this.getChild(3) or result = this.getDestructorCall().getQualifier() }
1001+
}
1002+
1003+
/**
1004+
* A C++ `delete` (non-array) expression.
1005+
* ```
1006+
* delete ptr;
1007+
* ```
1008+
*/
1009+
class DeleteExpr extends DeleteOrDeleteArrayExpr, @delete_expr {
1010+
override string toString() { result = "delete" }
1011+
1012+
override string getAPrimaryQlClass() { result = "DeleteExpr" }
10071013

10081014
/**
1009-
* Gets the object being deleted.
1015+
* Gets the compile-time type of the object being deleted.
10101016
*/
1011-
Expr getExpr() { result = this.getChild(3) or result = this.getChild(1).getChild(-1) }
1017+
Type getDeletedObjectType() {
1018+
result =
1019+
this.getExpr()
1020+
.getFullyConverted()
1021+
.getType()
1022+
.stripTopLevelSpecifiers()
1023+
.(PointerType)
1024+
.getBaseType()
1025+
}
10121026
}
10131027

10141028
/**
@@ -1017,13 +1031,11 @@ class DeleteExpr extends Expr, @delete_expr {
10171031
* delete[] arr;
10181032
* ```
10191033
*/
1020-
class DeleteArrayExpr extends Expr, @delete_array_expr {
1034+
class DeleteArrayExpr extends DeleteOrDeleteArrayExpr, @delete_array_expr {
10211035
override string toString() { result = "delete[]" }
10221036

10231037
override string getAPrimaryQlClass() { result = "DeleteArrayExpr" }
10241038

1025-
override int getPrecedence() { result = 16 }
1026-
10271039
/**
10281040
* Gets the element type of the array being deleted.
10291041
*/
@@ -1036,58 +1048,6 @@ class DeleteArrayExpr extends Expr, @delete_array_expr {
10361048
.(PointerType)
10371049
.getBaseType()
10381050
}
1039-
1040-
/**
1041-
* Gets the call to a destructor that occurs prior to the array's memory being deallocated, if any.
1042-
*
1043-
* At runtime, the destructor will be called once for each element in the array, but the
1044-
* destructor call only exists once in the AST.
1045-
*/
1046-
DestructorCall getDestructorCall() { result = this.getChild(1) }
1047-
1048-
/**
1049-
* Gets the destructor to be called to destroy each element in the array, if any.
1050-
*/
1051-
Destructor getDestructor() { result = this.getDestructorCall().getTarget() }
1052-
1053-
/**
1054-
* Gets the `operator delete[]` that deallocates storage.
1055-
*/
1056-
Function getDeallocator() {
1057-
expr_deallocator(underlyingElement(this), unresolveElement(result), _)
1058-
}
1059-
1060-
/**
1061-
* Holds if the deallocation function expects a size argument.
1062-
*/
1063-
predicate hasSizedDeallocation() {
1064-
exists(int form |
1065-
expr_deallocator(underlyingElement(this), _, form) and
1066-
form.bitAnd(1) != 0 // Bit zero is the "size" bit
1067-
)
1068-
}
1069-
1070-
/**
1071-
* Holds if the deallocation function expects an alignment argument.
1072-
*/
1073-
predicate hasAlignedDeallocation() {
1074-
exists(int form |
1075-
expr_deallocator(underlyingElement(this), _, form) and
1076-
form.bitAnd(2) != 0 // Bit one is the "alignment" bit
1077-
)
1078-
}
1079-
1080-
/**
1081-
* Gets the call to a non-default `operator delete` that deallocates storage, if any.
1082-
*
1083-
* This will only be present when the type being deleted has a custom `operator delete`.
1084-
*/
1085-
FunctionCall getAllocatorCall() { result = this.getChild(0) }
1086-
1087-
/**
1088-
* Gets the array being deleted.
1089-
*/
1090-
Expr getExpr() { result = this.getChild(3) or result = this.getChild(1).getChild(-1) }
10911051
}
10921052

10931053
/**

0 commit comments

Comments
 (0)