@@ -3,6 +3,7 @@ private import semmle.code.cpp.ir.implementation.Opcode
3
3
private import semmle.code.cpp.ir.implementation.internal.OperandTag
4
4
private import semmle.code.cpp.ir.internal.CppType
5
5
private import semmle.code.cpp.models.interfaces.SideEffect
6
+ private import semmle.code.cpp.models.interfaces.Throwing
6
7
private import InstructionTag
7
8
private import SideEffects
8
9
private import TranslatedElement
@@ -40,10 +41,10 @@ abstract class TranslatedCall extends TranslatedExpr {
40
41
id = this .getNumberOfArguments ( ) and result = this .getSideEffects ( )
41
42
}
42
43
43
- final override Instruction getFirstInstruction ( ) {
44
+ final override Instruction getFirstInstruction ( EdgeKind kind ) {
44
45
if exists ( this .getQualifier ( ) )
45
- then result = this .getQualifier ( ) .getFirstInstruction ( )
46
- else result = this .getFirstCallTargetInstruction ( )
46
+ then result = this .getQualifier ( ) .getFirstInstruction ( kind )
47
+ else result = this .getFirstCallTargetInstruction ( kind )
47
48
}
48
49
49
50
override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType resultType ) {
@@ -52,34 +53,43 @@ abstract class TranslatedCall extends TranslatedExpr {
52
53
resultType = getTypeForPRValue ( this .getCallResultType ( ) )
53
54
}
54
55
55
- override Instruction getChildSuccessor ( TranslatedElement child ) {
56
+ override Instruction getChildSuccessor ( TranslatedElement child , EdgeKind kind ) {
56
57
child = this .getQualifier ( ) and
57
- result = this .getFirstCallTargetInstruction ( )
58
+ result = this .getFirstCallTargetInstruction ( kind )
58
59
or
59
60
child = this .getCallTarget ( ) and
60
- result = this .getFirstArgumentOrCallInstruction ( )
61
+ result = this .getFirstArgumentOrCallInstruction ( kind )
61
62
or
62
63
exists ( int argIndex |
63
64
child = this .getArgument ( argIndex ) and
64
65
if exists ( this .getArgument ( argIndex + 1 ) )
65
- then result = this .getArgument ( argIndex + 1 ) .getFirstInstruction ( )
66
- else result = this .getInstruction ( CallTag ( ) )
66
+ then result = this .getArgument ( argIndex + 1 ) .getFirstInstruction ( kind )
67
+ else (
68
+ result = this .getInstruction ( CallTag ( ) ) and kind instanceof GotoEdge
69
+ )
67
70
)
68
71
or
69
72
child = this .getSideEffects ( ) and
70
73
if this .isNoReturn ( )
71
74
then
75
+ kind instanceof GotoEdge and
72
76
result =
73
77
any ( UnreachedInstruction instr |
74
78
this .getEnclosingFunction ( ) .getFunction ( ) = instr .getEnclosingFunction ( )
75
79
)
76
- else result = this .getParent ( ) .getChildSuccessor ( this )
80
+ else (
81
+ not this .mustThrowException ( ) and
82
+ result = this .getParent ( ) .getChildSuccessor ( this , kind )
83
+ or
84
+ this .mayThrowException ( ) and
85
+ kind instanceof ExceptionEdge and
86
+ result = this .getParent ( ) .getExceptionSuccessorInstruction ( any ( GotoEdge edge ) )
87
+ )
77
88
}
78
89
79
90
override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) {
80
- kind instanceof GotoEdge and
81
91
tag = CallTag ( ) and
82
- result = this .getSideEffects ( ) .getFirstInstruction ( )
92
+ result = this .getSideEffects ( ) .getFirstInstruction ( kind )
83
93
}
84
94
85
95
override Instruction getInstructionRegisterOperand ( InstructionTag tag , OperandTag operandTag ) {
@@ -100,6 +110,16 @@ abstract class TranslatedCall extends TranslatedExpr {
100
110
101
111
final override Instruction getResult ( ) { result = this .getInstruction ( CallTag ( ) ) }
102
112
113
+ /**
114
+ * Holds if the evaluation of this call may throw an exception.
115
+ */
116
+ abstract predicate mayThrowException ( ) ;
117
+
118
+ /**
119
+ * Holds if the evaluation of this call always throws an exception.
120
+ */
121
+ abstract predicate mustThrowException ( ) ;
122
+
103
123
/**
104
124
* Gets the result type of the call.
105
125
*/
@@ -121,8 +141,8 @@ abstract class TranslatedCall extends TranslatedExpr {
121
141
* it can be overridden by a subclass for cases where there is a call target
122
142
* that is not computed from an expression (e.g. a direct call).
123
143
*/
124
- Instruction getFirstCallTargetInstruction ( ) {
125
- result = this .getCallTarget ( ) .getFirstInstruction ( )
144
+ Instruction getFirstCallTargetInstruction ( EdgeKind kind ) {
145
+ result = this .getCallTarget ( ) .getFirstInstruction ( kind )
126
146
}
127
147
128
148
/**
@@ -159,10 +179,12 @@ abstract class TranslatedCall extends TranslatedExpr {
159
179
* If there are any arguments, gets the first instruction of the first
160
180
* argument. Otherwise, returns the call instruction.
161
181
*/
162
- final Instruction getFirstArgumentOrCallInstruction ( ) {
182
+ final Instruction getFirstArgumentOrCallInstruction ( EdgeKind kind ) {
163
183
if this .hasArguments ( )
164
- then result = this .getArgument ( 0 ) .getFirstInstruction ( )
165
- else result = this .getInstruction ( CallTag ( ) )
184
+ then result = this .getArgument ( 0 ) .getFirstInstruction ( kind )
185
+ else (
186
+ kind instanceof GotoEdge and result = this .getInstruction ( CallTag ( ) )
187
+ )
166
188
}
167
189
168
190
/**
@@ -203,24 +225,25 @@ abstract class TranslatedSideEffects extends TranslatedElement {
203
225
)
204
226
}
205
227
206
- final override Instruction getChildSuccessor ( TranslatedElement te ) {
228
+ final override Instruction getChildSuccessor ( TranslatedElement te , EdgeKind kind ) {
207
229
exists ( int i |
208
230
this .getChild ( i ) = te and
209
231
if exists ( this .getChild ( i + 1 ) )
210
- then result = this .getChild ( i + 1 ) .getFirstInstruction ( )
211
- else result = this .getParent ( ) .getChildSuccessor ( this )
232
+ then result = this .getChild ( i + 1 ) .getFirstInstruction ( kind )
233
+ else result = this .getParent ( ) .getChildSuccessor ( this , kind )
212
234
)
213
235
}
214
236
215
237
final override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType type ) {
216
238
none ( )
217
239
}
218
240
219
- final override Instruction getFirstInstruction ( ) {
220
- result = this .getChild ( 0 ) .getFirstInstruction ( )
241
+ final override Instruction getFirstInstruction ( EdgeKind kind ) {
242
+ result = this .getChild ( 0 ) .getFirstInstruction ( kind )
221
243
or
222
244
// Some functions, like `std::move()`, have no side effects whatsoever.
223
- not exists ( this .getChild ( 0 ) ) and result = this .getParent ( ) .getChildSuccessor ( this )
245
+ not exists ( this .getChild ( 0 ) ) and
246
+ result = this .getParent ( ) .getChildSuccessor ( this , kind )
224
247
}
225
248
226
249
final override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) { none ( ) }
@@ -235,8 +258,9 @@ abstract class TranslatedSideEffects extends TranslatedElement {
235
258
* (`TranslatedAllocatorCall`).
236
259
*/
237
260
abstract class TranslatedDirectCall extends TranslatedCall {
238
- final override Instruction getFirstCallTargetInstruction ( ) {
239
- result = this .getInstruction ( CallTargetTag ( ) )
261
+ final override Instruction getFirstCallTargetInstruction ( EdgeKind kind ) {
262
+ result = this .getInstruction ( CallTargetTag ( ) ) and
263
+ kind instanceof GotoEdge
240
264
}
241
265
242
266
final override Instruction getCallTargetResult ( ) { result = this .getInstruction ( CallTargetTag ( ) ) }
@@ -253,8 +277,7 @@ abstract class TranslatedDirectCall extends TranslatedCall {
253
277
result = TranslatedCall .super .getInstructionSuccessor ( tag , kind )
254
278
or
255
279
tag = CallTargetTag ( ) and
256
- kind instanceof GotoEdge and
257
- result = this .getFirstArgumentOrCallInstruction ( )
280
+ result = this .getFirstArgumentOrCallInstruction ( kind )
258
281
}
259
282
}
260
283
@@ -290,6 +313,15 @@ class TranslatedExprCall extends TranslatedCallExpr {
290
313
override TranslatedExpr getCallTarget ( ) {
291
314
result = getTranslatedExpr ( expr .getExpr ( ) .getFullyConverted ( ) )
292
315
}
316
+
317
+ final override predicate mayThrowException ( ) {
318
+ // We assume that a call to a function pointer will not throw an exception.
319
+ // This is not sound in general, but this will greatly reduce the number of
320
+ // exceptional edges.
321
+ none ( )
322
+ }
323
+
324
+ final override predicate mustThrowException ( ) { none ( ) }
293
325
}
294
326
295
327
/**
@@ -311,6 +343,14 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall {
311
343
exists ( this .getQualifier ( ) ) and
312
344
not exists ( MemberFunction func | expr .getTarget ( ) = func and func .isStatic ( ) )
313
345
}
346
+
347
+ final override predicate mayThrowException ( ) {
348
+ expr .getTarget ( ) .( ThrowingFunction ) .mayThrowException ( _)
349
+ }
350
+
351
+ final override predicate mustThrowException ( ) {
352
+ expr .getTarget ( ) .( ThrowingFunction ) .mayThrowException ( true )
353
+ }
314
354
}
315
355
316
356
/**
@@ -376,10 +416,11 @@ private int initializeAllocationGroup() { result = 3 }
376
416
abstract class TranslatedSideEffect extends TranslatedElement {
377
417
final override TranslatedElement getChild ( int n ) { none ( ) }
378
418
379
- final override Instruction getChildSuccessor ( TranslatedElement child ) { none ( ) }
419
+ final override Instruction getChildSuccessor ( TranslatedElement child , EdgeKind kind ) { none ( ) }
380
420
381
- final override Instruction getFirstInstruction ( ) {
382
- result = this .getInstruction ( OnlyInstructionTag ( ) )
421
+ final override Instruction getFirstInstruction ( EdgeKind kind ) {
422
+ result = this .getInstruction ( OnlyInstructionTag ( ) ) and
423
+ kind instanceof GotoEdge
383
424
}
384
425
385
426
final override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType type ) {
@@ -388,9 +429,8 @@ abstract class TranslatedSideEffect extends TranslatedElement {
388
429
}
389
430
390
431
final override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) {
391
- result = this .getParent ( ) .getChildSuccessor ( this ) and
392
- tag = OnlyInstructionTag ( ) and
393
- kind instanceof GotoEdge
432
+ result = this .getParent ( ) .getChildSuccessor ( this , kind ) and
433
+ tag = OnlyInstructionTag ( )
394
434
}
395
435
396
436
final override Declaration getFunction ( ) { result = this .getParent ( ) .getFunction ( ) }
0 commit comments