Skip to content

Commit 47d2033

Browse files
authored
Merge pull request #22754 from MathiasVP/ignore-path-dependent-destructors-in-translation-classes
C++: Ignore destructor calls on temporaries in IR translation classes
2 parents ce33a8a + 87f7afa commit 47d2033

7 files changed

Lines changed: 212 additions & 8 deletions

File tree

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ private predicate isInConditionalEvaluation(Expr e) {
303303
isInConditionalEvaluation(getRealParent(e))
304304
}
305305

306-
private predicate isConditionalTemporaryDestructorCall(DestructorCall dc) {
306+
predicate isConditionalTemporaryDestructorCall(DestructorCall dc) {
307307
exists(TemporaryObjectExpr temp |
308308
temp = dc.getQualifier().(ReuseExpr).getReusedExpr() and
309309
isInConditionalEvaluation(temp)

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,12 @@ abstract class TranslatedExpr extends TranslatedElement {
107107
}
108108

109109
final private TranslatedExpr getImplicitDestructorCall(int index) {
110-
result.getExpr() = expr.getImplicitDestructorCall(index)
110+
result.getExpr() =
111+
rank[index + 1](DestructorCall dc, int i |
112+
dc = expr.getImplicitDestructorCall(i) and not isConditionalTemporaryDestructorCall(dc)
113+
|
114+
dc order by i
115+
)
111116
}
112117

113118
final override predicate hasAnImplicitDestructorCall() {

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

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -297,11 +297,20 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
297297

298298
abstract TranslatedElement getChildInternal(int id);
299299

300+
DestructorCall getImplicitDestructorCall(int index) {
301+
result =
302+
rank[index + 1](DestructorCall dc, int i |
303+
dc = stmt.getImplicitDestructorCall(i) and not isConditionalTemporaryDestructorCall(dc)
304+
|
305+
dc order by i
306+
)
307+
}
308+
300309
final override TranslatedElement getChild(int id) {
301310
result = this.getChildInternal(id)
302311
or
303312
exists(int destructorIndex |
304-
result.(TranslatedExpr).getExpr() = stmt.getImplicitDestructorCall(destructorIndex) and
313+
result.(TranslatedExpr).getExpr() = this.getImplicitDestructorCall(destructorIndex) and
305314
id = this.getFirstDestructorCallIndex() + destructorIndex
306315
)
307316
}
@@ -313,7 +322,7 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
313322
}
314323

315324
final override predicate hasAnImplicitDestructorCall() {
316-
exists(stmt.getAnImplicitDestructorCall())
325+
exists(this.getImplicitDestructorCall(_))
317326
}
318327

319328
final override string toString() { result = stmt.toString() }
@@ -1227,7 +1236,7 @@ class TranslatedWhileStmt extends TranslatedLoop {
12271236
id = 1 and result = this.getBody()
12281237
or
12291238
exists(int n |
1230-
result.getAst() = stmt.getImplicitDestructorCall(n) and
1239+
result.getAst() = this.getImplicitDestructorCall(n) and
12311240
id = 2 + n
12321241
)
12331242
}
@@ -1289,7 +1298,7 @@ class TranslatedForStmt extends TranslatedLoop {
12891298
id = 3 and result = this.getBody()
12901299
or
12911300
exists(int n |
1292-
result.getAst() = stmt.getImplicitDestructorCall(n) and
1301+
result.getAst() = this.getImplicitDestructorCall(n) and
12931302
id = 4 + n
12941303
)
12951304
}
@@ -1492,13 +1501,13 @@ class TranslatedJumpStmt extends TranslatedStmt {
14921501
}
14931502

14941503
private TranslatedCall getTranslatedImplicitDestructorCall(int id) {
1495-
result.getExpr() = stmt.getImplicitDestructorCall(id)
1504+
result.getExpr() = this.getImplicitDestructorCall(id)
14961505
}
14971506

14981507
override TranslatedElement getLastChild() {
14991508
result =
15001509
this.getTranslatedImplicitDestructorCall(max(int id |
1501-
exists(stmt.getImplicitDestructorCall(id))
1510+
exists(this.getImplicitDestructorCall(id))
15021511
))
15031512
}
15041513

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

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4304,6 +4304,89 @@ destructors_for_temps.cpp:
43044304
# 103| Type = [IntType] int
43054305
# 103| ValueCategory = prvalue
43064306
# 104| getStmt(1): [ReturnStmt] return ...
4307+
# 106| [CopyAssignmentOperator] ClassWithArrayAndDestructor& ClassWithArrayAndDestructor::operator=(ClassWithArrayAndDestructor const&)
4308+
# 106| <params>:
4309+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
4310+
#-----| Type = [LValueReferenceType] const ClassWithArrayAndDestructor &
4311+
# 106| [Constructor] void ClassWithArrayAndDestructor::ClassWithArrayAndDestructor()
4312+
# 106| <params>:
4313+
# 106| [Destructor] void ClassWithArrayAndDestructor::~ClassWithArrayAndDestructor()
4314+
# 106| <params>:
4315+
# 108| [TopLevelFunction] void temp_test13(bool)
4316+
# 108| <params>:
4317+
# 108| getParameter(0): [Parameter] b
4318+
# 108| Type = [BoolType] bool
4319+
# 108| getEntryPoint(): [BlockStmt] { ... }
4320+
# 109| getStmt(0): [DeclStmt] declaration
4321+
# 109| getDeclarationEntry(0): [VariableDeclarationEntry] definition of t
4322+
# 109| Type = [LValueReferenceType] const int &
4323+
# 109| getVariable().getInitializer(): [Initializer] initializer for t
4324+
# 109| getExpr(): [ConditionalExpr] ... ? ... : ...
4325+
# 109| Type = [IntType] int
4326+
# 109| ValueCategory = lvalue
4327+
# 109| getCondition(): [VariableAccess] b
4328+
# 109| Type = [BoolType] bool
4329+
# 109| ValueCategory = prvalue(load)
4330+
# 109| getThen(): [ArrayExpr] access to array
4331+
# 109| Type = [IntType] int
4332+
# 109| ValueCategory = lvalue
4333+
# 109| getArrayBase(): [ValueFieldAccess] a
4334+
# 109| Type = [ArrayType] int[2]
4335+
# 109| ValueCategory = prvalue
4336+
# 109| getQualifier(): [Literal] 0
4337+
# 109| Type = [Struct] ClassWithArrayAndDestructor
4338+
# 109| Value = [Literal] 0
4339+
# 109| ValueCategory = prvalue
4340+
# 109| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
4341+
# 109| Type = [Struct] ClassWithArrayAndDestructor
4342+
# 109| ValueCategory = prvalue(load)
4343+
# 109| getArrayOffset(): [Literal] 0
4344+
# 109| Type = [IntType] int
4345+
# 109| Value = [Literal] 0
4346+
# 109| ValueCategory = prvalue
4347+
# 109| getArrayBase().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
4348+
# 109| Type = [IntPointerType] int *
4349+
# 109| ValueCategory = prvalue
4350+
# 109| getElse(): [ArrayExpr] access to array
4351+
# 109| Type = [IntType] int
4352+
# 109| ValueCategory = lvalue
4353+
# 109| getArrayBase(): [ValueFieldAccess] a
4354+
# 109| Type = [ArrayType] int[2]
4355+
# 109| ValueCategory = prvalue
4356+
# 109| getQualifier(): [Literal] 0
4357+
# 109| Type = [Struct] ClassWithArrayAndDestructor
4358+
# 109| Value = [Literal] 0
4359+
# 109| ValueCategory = prvalue
4360+
# 109| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
4361+
# 109| Type = [Struct] ClassWithArrayAndDestructor
4362+
# 109| ValueCategory = prvalue(load)
4363+
# 109| getArrayOffset(): [Literal] 1
4364+
# 109| Type = [IntType] int
4365+
# 109| Value = [Literal] 1
4366+
# 109| ValueCategory = prvalue
4367+
# 109| getArrayBase().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
4368+
# 109| Type = [IntPointerType] int *
4369+
# 109| ValueCategory = prvalue
4370+
# 109| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithArrayAndDestructor
4371+
# 109| Type = [VoidType] void
4372+
# 109| ValueCategory = prvalue
4373+
# 109| getQualifier(): [ReuseExpr] reuse of temporary object
4374+
# 109| Type = [Struct] ClassWithArrayAndDestructor
4375+
# 109| ValueCategory = xvalue
4376+
# 109| getImplicitDestructorCall(1): [DestructorCall] call to ~ClassWithArrayAndDestructor
4377+
# 109| Type = [VoidType] void
4378+
# 109| ValueCategory = prvalue
4379+
# 109| getQualifier(): [ReuseExpr] reuse of temporary object
4380+
# 109| Type = [Struct] ClassWithArrayAndDestructor
4381+
# 109| ValueCategory = xvalue
4382+
# 109| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
4383+
# 109| Type = [LValueReferenceType] const int &
4384+
# 109| ValueCategory = prvalue
4385+
# 109| getExpr(): [CStyleCast] (const int)...
4386+
# 109| Conversion = [GlvalueConversion] glvalue conversion
4387+
# 109| Type = [SpecifiedType] const int
4388+
# 109| ValueCategory = lvalue
4389+
# 110| getStmt(1): [ReturnStmt] return ...
43074390
generic.c:
43084391
# 1| [TopLevelFunction] void c11_generic_test_with_load(unsigned int, int)
43094392
# 1| <params>:

‎cpp/ql/test/library-tests/ir/ir/aliased_ir.expected‎

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3280,6 +3280,57 @@ destructors_for_temps.cpp:
32803280
# 102| v102_9(void) = AliasedUse : ~m103_26
32813281
# 102| v102_10(void) = ExitFunction :
32823282

3283+
# 108| void temp_test13(bool)
3284+
# 108| Block 0
3285+
# 108| v108_1(void) = EnterFunction :
3286+
# 108| m108_2(unknown) = AliasedDefinition :
3287+
# 108| m108_3(unknown) = InitializeNonLocal :
3288+
# 108| m108_4(unknown) = Chi : total:m108_2, partial:m108_3
3289+
# 108| r108_5(glval<bool>) = VariableAddress[b] :
3290+
# 108| m108_6(bool) = InitializeParameter[b] : &:r108_5
3291+
# 109| r109_1(glval<int &>) = VariableAddress[t] :
3292+
# 109| r109_2(glval<bool>) = VariableAddress[b] :
3293+
# 109| r109_3(bool) = Load[b] : &:r109_2, m108_6
3294+
# 109| v109_4(void) = ConditionalBranch : r109_3
3295+
#-----| False -> Block 3
3296+
#-----| True -> Block 2
3297+
3298+
# 109| Block 1
3299+
# 109| m109_5(glval<int>) = Phi : from 2:m109_19, from 3:m109_28
3300+
# 109| r109_6(glval<unknown>) = VariableAddress[#temp109:18] :
3301+
# 109| r109_7(glval<int>) = Load[#temp109:18] : &:r109_6, m109_5
3302+
# 109| r109_8(glval<int>) = Convert : r109_7
3303+
# 109| r109_9(int &) = CopyValue : r109_8
3304+
# 109| m109_10(int &) = Store[t] : &:r109_1, r109_9
3305+
# 110| v110_1(void) = NoOp :
3306+
# 108| v108_7(void) = ReturnVoid :
3307+
# 108| v108_8(void) = AliasedUse : m108_3
3308+
# 108| v108_9(void) = ExitFunction :
3309+
3310+
# 109| Block 2
3311+
# 109| r109_11(glval<ClassWithArrayAndDestructor>) = VariableAddress[#temp109:22] :
3312+
# 109| r109_12(ClassWithArrayAndDestructor) = Constant[0] :
3313+
# 109| m109_13(ClassWithArrayAndDestructor) = Store[#temp109:22] : &:r109_11, r109_12
3314+
# 109| r109_14(glval<int[2]>) = FieldAddress[a] : r109_11
3315+
# 109| r109_15(int *) = Convert : r109_14
3316+
# 109| r109_16(int) = Constant[0] :
3317+
# 109| r109_17(glval<int>) = PointerAdd[4] : r109_15, r109_16
3318+
# 109| r109_18(glval<unknown>) = VariableAddress[#temp109:18] :
3319+
# 109| m109_19(glval<int>) = Store[#temp109:18] : &:r109_18, r109_17
3320+
#-----| Goto -> Block 1
3321+
3322+
# 109| Block 3
3323+
# 109| r109_20(glval<ClassWithArrayAndDestructor>) = VariableAddress[#temp109:59] :
3324+
# 109| r109_21(ClassWithArrayAndDestructor) = Constant[0] :
3325+
# 109| m109_22(ClassWithArrayAndDestructor) = Store[#temp109:59] : &:r109_20, r109_21
3326+
# 109| r109_23(glval<int[2]>) = FieldAddress[a] : r109_20
3327+
# 109| r109_24(int *) = Convert : r109_23
3328+
# 109| r109_25(int) = Constant[1] :
3329+
# 109| r109_26(glval<int>) = PointerAdd[4] : r109_24, r109_25
3330+
# 109| r109_27(glval<unknown>) = VariableAddress[#temp109:18] :
3331+
# 109| m109_28(glval<int>) = Store[#temp109:18] : &:r109_27, r109_26
3332+
#-----| Goto -> Block 1
3333+
32833334
generic.c:
32843335
# 1| void c11_generic_test_with_load(unsigned int, int)
32853336
# 1| Block 0

‎cpp/ql/test/library-tests/ir/ir/destructors_for_temps.cpp‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,11 @@ void temp_test11() {
101101

102102
void temp_test12(ClassWithDestructor3 x) {
103103
x.getClassWithDestructor2().get_x() + 5;
104+
}
105+
106+
struct ClassWithArrayAndDestructor { int a[2]; ~ClassWithArrayAndDestructor(); };
107+
108+
void temp_test13(bool b) {
109+
const int &t = b ? ClassWithArrayAndDestructor().a[0] : ClassWithArrayAndDestructor().a[1];
110+
return;
104111
}

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

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2901,6 +2901,55 @@ destructors_for_temps.cpp:
29012901
# 102| v102_7(void) = AliasedUse : ~m?
29022902
# 102| v102_8(void) = ExitFunction :
29032903

2904+
# 108| void temp_test13(bool)
2905+
# 108| Block 0
2906+
# 108| v108_1(void) = EnterFunction :
2907+
# 108| mu108_2(unknown) = AliasedDefinition :
2908+
# 108| mu108_3(unknown) = InitializeNonLocal :
2909+
# 108| r108_4(glval<bool>) = VariableAddress[b] :
2910+
# 108| mu108_5(bool) = InitializeParameter[b] : &:r108_4
2911+
# 109| r109_1(glval<int &>) = VariableAddress[t] :
2912+
# 109| r109_2(glval<bool>) = VariableAddress[b] :
2913+
# 109| r109_3(bool) = Load[b] : &:r109_2, ~m?
2914+
# 109| v109_4(void) = ConditionalBranch : r109_3
2915+
#-----| False -> Block 3
2916+
#-----| True -> Block 2
2917+
2918+
# 109| Block 1
2919+
# 109| r109_5(glval<unknown>) = VariableAddress[#temp109:18] :
2920+
# 109| r109_6(glval<int>) = Load[#temp109:18] : &:r109_5, ~m?
2921+
# 109| r109_7(glval<int>) = Convert : r109_6
2922+
# 109| r109_8(int &) = CopyValue : r109_7
2923+
# 109| mu109_9(int &) = Store[t] : &:r109_1, r109_8
2924+
# 110| v110_1(void) = NoOp :
2925+
# 108| v108_6(void) = ReturnVoid :
2926+
# 108| v108_7(void) = AliasedUse : ~m?
2927+
# 108| v108_8(void) = ExitFunction :
2928+
2929+
# 109| Block 2
2930+
# 109| r109_10(glval<ClassWithArrayAndDestructor>) = VariableAddress[#temp109:22] :
2931+
# 109| r109_11(ClassWithArrayAndDestructor) = Constant[0] :
2932+
# 109| mu109_12(ClassWithArrayAndDestructor) = Store[#temp109:22] : &:r109_10, r109_11
2933+
# 109| r109_13(glval<int[2]>) = FieldAddress[a] : r109_10
2934+
# 109| r109_14(int *) = Convert : r109_13
2935+
# 109| r109_15(int) = Constant[0] :
2936+
# 109| r109_16(glval<int>) = PointerAdd[4] : r109_14, r109_15
2937+
# 109| r109_17(glval<unknown>) = VariableAddress[#temp109:18] :
2938+
# 109| mu109_18(glval<int>) = Store[#temp109:18] : &:r109_17, r109_16
2939+
#-----| Goto -> Block 1
2940+
2941+
# 109| Block 3
2942+
# 109| r109_19(glval<ClassWithArrayAndDestructor>) = VariableAddress[#temp109:59] :
2943+
# 109| r109_20(ClassWithArrayAndDestructor) = Constant[0] :
2944+
# 109| mu109_21(ClassWithArrayAndDestructor) = Store[#temp109:59] : &:r109_19, r109_20
2945+
# 109| r109_22(glval<int[2]>) = FieldAddress[a] : r109_19
2946+
# 109| r109_23(int *) = Convert : r109_22
2947+
# 109| r109_24(int) = Constant[1] :
2948+
# 109| r109_25(glval<int>) = PointerAdd[4] : r109_23, r109_24
2949+
# 109| r109_26(glval<unknown>) = VariableAddress[#temp109:18] :
2950+
# 109| mu109_27(glval<int>) = Store[#temp109:18] : &:r109_26, r109_25
2951+
#-----| Goto -> Block 1
2952+
29042953
generic.c:
29052954
# 1| void c11_generic_test_with_load(unsigned int, int)
29062955
# 1| Block 0

0 commit comments

Comments
 (0)