Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 820f4a5

Browse files
author
Robert Marsh
committed
C++: custom destructor handling for for loops
1 parent 85d1d07 commit 820f4a5

3 files changed

Lines changed: 241 additions & 9 deletions

File tree

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -908,7 +908,7 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
908908
child = this.getCondition() and result = this.getBody().getFirstInstruction(kind)
909909
}
910910

911-
final override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
911+
override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
912912
child = this.getCondition() and
913913
result = this.getParent().getChildSuccessor(this, kind)
914914
}
@@ -943,6 +943,15 @@ class TranslatedDoStmt extends TranslatedLoop {
943943
class TranslatedForStmt extends TranslatedLoop {
944944
override ForStmt stmt;
945945

946+
override predicate handlesDestructorsExplicitly() { any() }
947+
948+
final override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
949+
child = this.getCondition() and
950+
if this.hasImplicitDestructorCalls()
951+
then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
952+
else result = this.getParent().getChildSuccessor(this, kind)
953+
}
954+
946955
override TranslatedElement getChildInternal(int id) {
947956
id = 0 and result = this.getInitialization()
948957
or
@@ -951,6 +960,11 @@ class TranslatedForStmt extends TranslatedLoop {
951960
id = 2 and result = this.getUpdate()
952961
or
953962
id = 3 and result = this.getBody()
963+
or
964+
exists(int n |
965+
result.getAst() = stmt.getImplicitDestructorCall(n) and
966+
id = 4 + n
967+
)
954968
}
955969

956970
private TranslatedStmt getInitialization() {
@@ -981,6 +995,12 @@ class TranslatedForStmt extends TranslatedLoop {
981995
)
982996
or
983997
child = this.getUpdate() and result = this.getFirstConditionInstruction(kind)
998+
or
999+
exists(int lastDestructorIndex |
1000+
lastDestructorIndex = max(int n | exists(this.getChild(n)) and n >= this.getFirstDestructorCallIndex()) and
1001+
child = this.getChild(lastDestructorIndex) and
1002+
result = this.getParent().getChildSuccessor(this, kind)
1003+
)
9841004
}
9851005
}
9861006

cpp/ql/test/library-tests/ir/ir/PrintAST.expected

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5553,6 +5553,8 @@ ir.cpp:
55535553
# 605| Type = [RValueReferenceType] String &&
55545554
# 607| [ConstMemberFunction] char const* String::c_str() const
55555555
# 607| <params>:
5556+
# 608| [MemberFunction] char String::pop_back()
5557+
# 608| <params>:
55565558
# 613| [TopLevelFunction] String ReturnObject()
55575559
# 613| <params>:
55585560
# 615| [TopLevelFunction] void DeclareObject()
@@ -16132,6 +16134,219 @@ ir.cpp:
1613216134
# 2112| getExpr(): [VariableAccess] end
1613316135
# 2112| Type = [CharPointerType] char *
1613416136
# 2112| ValueCategory = prvalue(load)
16137+
# 2115| [TopLevelFunction] void TryCatchDestructors(bool)
16138+
# 2115| <params>:
16139+
# 2115| getParameter(0): [Parameter] b
16140+
# 2115| Type = [BoolType] bool
16141+
# 2115| getEntryPoint(): [BlockStmt] { ... }
16142+
# 2116| getStmt(0): [TryStmt] try { ... }
16143+
# 2116| getStmt(): [BlockStmt] { ... }
16144+
# 2117| getStmt(0): [DeclStmt] declaration
16145+
# 2117| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
16146+
# 2117| Type = [Struct] String
16147+
# 2117| getVariable().getInitializer(): [Initializer] initializer for s
16148+
# 2117| getExpr(): [ConstructorCall] call to String
16149+
# 2117| Type = [VoidType] void
16150+
# 2117| ValueCategory = prvalue
16151+
# 2118| getStmt(1): [IfStmt] if (...) ...
16152+
# 2118| getCondition(): [VariableAccess] b
16153+
# 2118| Type = [BoolType] bool
16154+
# 2118| ValueCategory = prvalue(load)
16155+
# 2118| getThen(): [BlockStmt] { ... }
16156+
# 2119| getStmt(0): [ExprStmt] ExprStmt
16157+
# 2119| getExpr(): [ThrowExpr] throw ...
16158+
# 2119| Type = [PointerType] const char *
16159+
# 2119| ValueCategory = prvalue
16160+
# 2119| getExpr(): string literal
16161+
# 2119| Type = [ArrayType] const char[15]
16162+
# 2119| Value = [StringLiteral] "string literal"
16163+
# 2119| ValueCategory = lvalue
16164+
# 2122| getImplicitDestructorCall(0): [DestructorCall] call to ~String
16165+
# 2122| Type = [VoidType] void
16166+
# 2122| ValueCategory = prvalue
16167+
# 2122| getQualifier(): [VariableAccess] s
16168+
# 2122| Type = [Struct] String
16169+
# 2122| ValueCategory = lvalue
16170+
# 2119| getExpr().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
16171+
# 2119| Type = [PointerType] const char *
16172+
# 2119| ValueCategory = prvalue
16173+
# 2121| getStmt(2): [DeclStmt] declaration
16174+
# 2121| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s2
16175+
# 2121| Type = [Struct] String
16176+
# 2121| getVariable().getInitializer(): [Initializer] initializer for s2
16177+
# 2121| getExpr(): [ConstructorCall] call to String
16178+
# 2121| Type = [VoidType] void
16179+
# 2121| ValueCategory = prvalue
16180+
# 2122| getImplicitDestructorCall(0): [DestructorCall] call to ~String
16181+
# 2122| Type = [VoidType] void
16182+
# 2122| ValueCategory = prvalue
16183+
# 2122| getQualifier(): [VariableAccess] s2
16184+
# 2122| Type = [Struct] String
16185+
# 2122| ValueCategory = lvalue
16186+
# 2122| getImplicitDestructorCall(1): [DestructorCall] call to ~String
16187+
# 2122| Type = [VoidType] void
16188+
# 2122| ValueCategory = prvalue
16189+
# 2122| getQualifier(): [VariableAccess] s
16190+
# 2122| Type = [Struct] String
16191+
# 2122| ValueCategory = lvalue
16192+
# 2123| getChild(1): [Handler] <handler>
16193+
# 2123| getBlock(): [CatchBlock] { ... }
16194+
# 2124| getStmt(0): [ExprStmt] ExprStmt
16195+
# 2124| getExpr(): [ThrowExpr] throw ...
16196+
# 2124| Type = [Struct] String
16197+
# 2124| ValueCategory = prvalue
16198+
# 2124| getExpr(): [ConstructorCall] call to String
16199+
# 2124| Type = [VoidType] void
16200+
# 2124| ValueCategory = prvalue
16201+
# 2124| getArgument(0): [VariableAccess] s
16202+
# 2124| Type = [PointerType] const char *
16203+
# 2124| ValueCategory = prvalue(load)
16204+
# 2126| getChild(2): [Handler] <handler>
16205+
# 2126| getBlock(): [CatchBlock] { ... }
16206+
# 2128| getChild(3): [Handler] <handler>
16207+
# 2128| getBlock(): [CatchAnyBlock] { ... }
16208+
# 2129| getStmt(0): [ExprStmt] ExprStmt
16209+
# 2129| getExpr(): [ReThrowExpr] re-throw exception
16210+
# 2129| Type = [VoidType] void
16211+
# 2129| ValueCategory = prvalue
16212+
# 2131| getStmt(1): [ReturnStmt] return ...
16213+
# 2133| [TopLevelFunction] void IfDestructors(bool)
16214+
# 2133| <params>:
16215+
# 2133| getParameter(0): [Parameter] b
16216+
# 2133| Type = [BoolType] bool
16217+
# 2133| getEntryPoint(): [BlockStmt] { ... }
16218+
# 2134| getStmt(0): [DeclStmt] declaration
16219+
# 2134| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s1
16220+
# 2134| Type = [Struct] String
16221+
# 2134| getVariable().getInitializer(): [Initializer] initializer for s1
16222+
# 2134| getExpr(): [ConstructorCall] call to String
16223+
# 2134| Type = [VoidType] void
16224+
# 2134| ValueCategory = prvalue
16225+
# 2135| getStmt(1): [IfStmt] if (...) ...
16226+
# 2135| getCondition(): [VariableAccess] b
16227+
# 2135| Type = [BoolType] bool
16228+
# 2135| ValueCategory = prvalue(load)
16229+
# 2135| getThen(): [BlockStmt] { ... }
16230+
# 2136| getStmt(0): [DeclStmt] declaration
16231+
# 2136| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s2
16232+
# 2136| Type = [Struct] String
16233+
# 2136| getVariable().getInitializer(): [Initializer] initializer for s2
16234+
# 2136| getExpr(): [ConstructorCall] call to String
16235+
# 2136| Type = [VoidType] void
16236+
# 2136| ValueCategory = prvalue
16237+
# 2137| getImplicitDestructorCall(0): [DestructorCall] call to ~String
16238+
# 2137| Type = [VoidType] void
16239+
# 2137| ValueCategory = prvalue
16240+
# 2137| getQualifier(): [VariableAccess] s2
16241+
# 2137| Type = [Struct] String
16242+
# 2137| ValueCategory = lvalue
16243+
# 2137| getElse(): [BlockStmt] { ... }
16244+
# 2138| getStmt(0): [DeclStmt] declaration
16245+
# 2138| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s3
16246+
# 2138| Type = [Struct] String
16247+
# 2138| getVariable().getInitializer(): [Initializer] initializer for s3
16248+
# 2138| getExpr(): [ConstructorCall] call to String
16249+
# 2138| Type = [VoidType] void
16250+
# 2138| ValueCategory = prvalue
16251+
# 2139| getImplicitDestructorCall(0): [DestructorCall] call to ~String
16252+
# 2139| Type = [VoidType] void
16253+
# 2139| ValueCategory = prvalue
16254+
# 2139| getQualifier(): [VariableAccess] s3
16255+
# 2139| Type = [Struct] String
16256+
# 2139| ValueCategory = lvalue
16257+
# 2140| getStmt(2): [DeclStmt] declaration
16258+
# 2140| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s4
16259+
# 2140| Type = [Struct] String
16260+
# 2140| getVariable().getInitializer(): [Initializer] initializer for s4
16261+
# 2140| getExpr(): [ConstructorCall] call to String
16262+
# 2140| Type = [VoidType] void
16263+
# 2140| ValueCategory = prvalue
16264+
# 2141| getStmt(3): [ReturnStmt] return ...
16265+
# 2141| getImplicitDestructorCall(0): [DestructorCall] call to ~String
16266+
# 2141| Type = [VoidType] void
16267+
# 2141| ValueCategory = prvalue
16268+
# 2141| getQualifier(): [VariableAccess] s4
16269+
# 2141| Type = [Struct] String
16270+
# 2141| ValueCategory = lvalue
16271+
# 2141| getImplicitDestructorCall(1): [DestructorCall] call to ~String
16272+
# 2141| Type = [VoidType] void
16273+
# 2141| ValueCategory = prvalue
16274+
# 2141| getQualifier(): [VariableAccess] s1
16275+
# 2141| Type = [Struct] String
16276+
# 2141| ValueCategory = lvalue
16277+
# 2143| [TopLevelFunction] void ForDestructors()
16278+
# 2143| <params>:
16279+
# 2143| getEntryPoint(): [BlockStmt] { ... }
16280+
# 2144| getStmt(0): [DeclStmt] declaration
16281+
# 2144| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
16282+
# 2144| Type = [PlainCharType] char
16283+
# 2144| getVariable().getInitializer(): [Initializer] initializer for c
16284+
# 2144| getExpr(): [CharLiteral] 97
16285+
# 2144| Type = [PlainCharType] char
16286+
# 2144| Value = [CharLiteral] 97
16287+
# 2144| ValueCategory = prvalue
16288+
# 2145| getStmt(1): [ForStmt] for(...;...;...) ...
16289+
# 2145| getInitialization(): [DeclStmt] declaration
16290+
# 2145| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
16291+
# 2145| Type = [Struct] String
16292+
# 2145| getVariable().getInitializer(): [Initializer] initializer for s
16293+
# 2145| getExpr(): [ConstructorCall] call to String
16294+
# 2145| Type = [VoidType] void
16295+
# 2145| ValueCategory = prvalue
16296+
# 2145| getArgument(0): hello
16297+
# 2145| Type = [ArrayType] const char[6]
16298+
# 2145| Value = [StringLiteral] "hello"
16299+
# 2145| ValueCategory = lvalue
16300+
# 2145| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
16301+
# 2145| Type = [PointerType] const char *
16302+
# 2145| ValueCategory = prvalue
16303+
# 2145| getCondition(): [NEExpr] ... != ...
16304+
# 2145| Type = [BoolType] bool
16305+
# 2145| ValueCategory = prvalue
16306+
# 2145| getLeftOperand(): [VariableAccess] c
16307+
# 2145| Type = [PlainCharType] char
16308+
# 2145| ValueCategory = prvalue(load)
16309+
# 2145| getRightOperand(): [Literal] 0
16310+
# 2145| Type = [IntType] int
16311+
# 2145| Value = [Literal] 0
16312+
# 2145| ValueCategory = prvalue
16313+
# 2145| getLeftOperand().getFullyConverted(): [CStyleCast] (int)...
16314+
# 2145| Conversion = [IntegralConversion] integral conversion
16315+
# 2145| Type = [IntType] int
16316+
# 2145| ValueCategory = prvalue
16317+
# 2145| getUpdate(): [AssignExpr] ... = ...
16318+
# 2145| Type = [PlainCharType] char
16319+
# 2145| ValueCategory = lvalue
16320+
# 2145| getLValue(): [VariableAccess] c
16321+
# 2145| Type = [PlainCharType] char
16322+
# 2145| ValueCategory = lvalue
16323+
# 2145| getRValue(): [FunctionCall] call to pop_back
16324+
# 2145| Type = [PlainCharType] char
16325+
# 2145| ValueCategory = prvalue
16326+
# 2145| getQualifier(): [VariableAccess] s
16327+
# 2145| Type = [Struct] String
16328+
# 2145| ValueCategory = lvalue
16329+
# 2145| getStmt(): [BlockStmt] { ... }
16330+
# 2146| getStmt(0): [DeclStmt] declaration
16331+
# 2146| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s2
16332+
# 2146| Type = [Struct] String
16333+
# 2146| getVariable().getInitializer(): [Initializer] initializer for s2
16334+
# 2146| getExpr(): [ConstructorCall] call to String
16335+
# 2146| Type = [VoidType] void
16336+
# 2146| ValueCategory = prvalue
16337+
# 2147| getImplicitDestructorCall(0): [DestructorCall] call to ~String
16338+
# 2147| Type = [VoidType] void
16339+
# 2147| ValueCategory = prvalue
16340+
# 2147| getQualifier(): [VariableAccess] s2
16341+
# 2147| Type = [Struct] String
16342+
# 2147| ValueCategory = lvalue
16343+
# 2145| getImplicitDestructorCall(0): [DestructorCall] call to ~String
16344+
# 2145| Type = [VoidType] void
16345+
# 2145| ValueCategory = prvalue
16346+
# 2145| getQualifier(): [VariableAccess] s
16347+
# 2145| Type = [Struct] String
16348+
# 2145| ValueCategory = lvalue
16349+
# 2148| getStmt(2): [ReturnStmt] return ...
1613516350
perf-regression.cpp:
1613616351
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
1613716352
# 4| <params>:

cpp/ql/test/library-tests/ir/ir/raw_ir.expected

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12053,7 +12053,7 @@ ir.cpp:
1205312053
# 2145| r2145_13(int) = Constant[0] :
1205412054
# 2145| r2145_14(bool) = CompareNE : r2145_12, r2145_13
1205512055
# 2145| v2145_15(void) = ConditionalBranch : r2145_14
12056-
#-----| False -> Block 4
12056+
#-----| False -> Block 3
1205712057
#-----| True -> Block 2
1205812058

1205912059
# 2146| Block 2
@@ -12086,13 +12086,10 @@ ir.cpp:
1208612086
# 2145| mu2145_27(unknown) = ^CallSideEffect : ~m?
1208712087
# 2145| v2145_28(void) = ^IndirectReadSideEffect[-1] : &:r2145_24, ~m?
1208812088
# 2145| mu2145_29(String) = ^IndirectMayWriteSideEffect[-1] : &:r2145_24
12089-
#-----| Goto -> Block 4
12090-
12091-
# 2148| Block 4
12092-
# 2148| v2148_1(void) = NoOp :
12093-
# 2143| v2143_4(void) = ReturnVoid :
12094-
# 2143| v2143_5(void) = AliasedUse : ~m?
12095-
# 2143| v2143_6(void) = ExitFunction :
12089+
# 2148| v2148_1(void) = NoOp :
12090+
# 2143| v2143_4(void) = ReturnVoid :
12091+
# 2143| v2143_5(void) = AliasedUse : ~m?
12092+
# 2143| v2143_6(void) = ExitFunction :
1209612093

1209712094
perf-regression.cpp:
1209812095
# 6| void Big::Big()

0 commit comments

Comments
 (0)