@@ -3,6 +3,7 @@ private import semmle.code.cpp.ir.implementation.Opcode
33private import semmle.code.cpp.ir.implementation.internal.OperandTag
44private import semmle.code.cpp.ir.internal.CppType
55private import semmle.code.cpp.models.interfaces.SideEffect
6+ private import semmle.code.cpp.models.interfaces.Throwing
67private import InstructionTag
78private import SideEffects
89private import TranslatedElement
@@ -40,10 +41,10 @@ abstract class TranslatedCall extends TranslatedExpr {
4041 id = this .getNumberOfArguments ( ) and result = this .getSideEffects ( )
4142 }
4243
43- final override Instruction getFirstInstruction ( ) {
44+ final override Instruction getFirstInstruction ( EdgeKind kind ) {
4445 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 )
4748 }
4849
4950 override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType resultType ) {
@@ -52,34 +53,43 @@ abstract class TranslatedCall extends TranslatedExpr {
5253 resultType = getTypeForPRValue ( this .getCallResultType ( ) )
5354 }
5455
55- override Instruction getChildSuccessor ( TranslatedElement child ) {
56+ override Instruction getChildSuccessor ( TranslatedElement child , EdgeKind kind ) {
5657 child = this .getQualifier ( ) and
57- result = this .getFirstCallTargetInstruction ( )
58+ result = this .getFirstCallTargetInstruction ( kind )
5859 or
5960 child = this .getCallTarget ( ) and
60- result = this .getFirstArgumentOrCallInstruction ( )
61+ result = this .getFirstArgumentOrCallInstruction ( kind )
6162 or
6263 exists ( int argIndex |
6364 child = this .getArgument ( argIndex ) and
6465 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+ )
6770 )
6871 or
6972 child = this .getSideEffects ( ) and
7073 if this .isNoReturn ( )
7174 then
75+ kind instanceof GotoEdge and
7276 result =
7377 any ( UnreachedInstruction instr |
7478 this .getEnclosingFunction ( ) .getFunction ( ) = instr .getEnclosingFunction ( )
7579 )
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+ )
7788 }
7889
7990 override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) {
80- kind instanceof GotoEdge and
8191 tag = CallTag ( ) and
82- result = this .getSideEffects ( ) .getFirstInstruction ( )
92+ result = this .getSideEffects ( ) .getFirstInstruction ( kind )
8393 }
8494
8595 override Instruction getInstructionRegisterOperand ( InstructionTag tag , OperandTag operandTag ) {
@@ -100,6 +110,16 @@ abstract class TranslatedCall extends TranslatedExpr {
100110
101111 final override Instruction getResult ( ) { result = this .getInstruction ( CallTag ( ) ) }
102112
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+
103123 /**
104124 * Gets the result type of the call.
105125 */
@@ -121,8 +141,8 @@ abstract class TranslatedCall extends TranslatedExpr {
121141 * it can be overridden by a subclass for cases where there is a call target
122142 * that is not computed from an expression (e.g. a direct call).
123143 */
124- Instruction getFirstCallTargetInstruction ( ) {
125- result = this .getCallTarget ( ) .getFirstInstruction ( )
144+ Instruction getFirstCallTargetInstruction ( EdgeKind kind ) {
145+ result = this .getCallTarget ( ) .getFirstInstruction ( kind )
126146 }
127147
128148 /**
@@ -159,10 +179,12 @@ abstract class TranslatedCall extends TranslatedExpr {
159179 * If there are any arguments, gets the first instruction of the first
160180 * argument. Otherwise, returns the call instruction.
161181 */
162- final Instruction getFirstArgumentOrCallInstruction ( ) {
182+ final Instruction getFirstArgumentOrCallInstruction ( EdgeKind kind ) {
163183 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+ )
166188 }
167189
168190 /**
@@ -203,24 +225,25 @@ abstract class TranslatedSideEffects extends TranslatedElement {
203225 )
204226 }
205227
206- final override Instruction getChildSuccessor ( TranslatedElement te ) {
228+ final override Instruction getChildSuccessor ( TranslatedElement te , EdgeKind kind ) {
207229 exists ( int i |
208230 this .getChild ( i ) = te and
209231 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 )
212234 )
213235 }
214236
215237 final override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType type ) {
216238 none ( )
217239 }
218240
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 )
221243 or
222244 // 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 )
224247 }
225248
226249 final override Instruction getInstructionSuccessor ( InstructionTag tag , EdgeKind kind ) { none ( ) }
@@ -235,8 +258,9 @@ abstract class TranslatedSideEffects extends TranslatedElement {
235258 * (`TranslatedAllocatorCall`).
236259 */
237260abstract 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
240264 }
241265
242266 final override Instruction getCallTargetResult ( ) { result = this .getInstruction ( CallTargetTag ( ) ) }
@@ -253,8 +277,7 @@ abstract class TranslatedDirectCall extends TranslatedCall {
253277 result = TranslatedCall .super .getInstructionSuccessor ( tag , kind )
254278 or
255279 tag = CallTargetTag ( ) and
256- kind instanceof GotoEdge and
257- result = this .getFirstArgumentOrCallInstruction ( )
280+ result = this .getFirstArgumentOrCallInstruction ( kind )
258281 }
259282}
260283
@@ -290,6 +313,15 @@ class TranslatedExprCall extends TranslatedCallExpr {
290313 override TranslatedExpr getCallTarget ( ) {
291314 result = getTranslatedExpr ( expr .getExpr ( ) .getFullyConverted ( ) )
292315 }
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 ( ) }
293325}
294326
295327/**
@@ -311,6 +343,14 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall {
311343 exists ( this .getQualifier ( ) ) and
312344 not exists ( MemberFunction func | expr .getTarget ( ) = func and func .isStatic ( ) )
313345 }
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+ }
314354}
315355
316356/**
@@ -376,10 +416,11 @@ private int initializeAllocationGroup() { result = 3 }
376416abstract class TranslatedSideEffect extends TranslatedElement {
377417 final override TranslatedElement getChild ( int n ) { none ( ) }
378418
379- final override Instruction getChildSuccessor ( TranslatedElement child ) { none ( ) }
419+ final override Instruction getChildSuccessor ( TranslatedElement child , EdgeKind kind ) { none ( ) }
380420
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
383424 }
384425
385426 final override predicate hasInstruction ( Opcode opcode , InstructionTag tag , CppType type ) {
@@ -388,9 +429,8 @@ abstract class TranslatedSideEffect extends TranslatedElement {
388429 }
389430
390431 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 ( )
394434 }
395435
396436 final override Declaration getFunction ( ) { result = this .getParent ( ) .getFunction ( ) }
0 commit comments