diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 4f8932c4a289..30054e647e21 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -4,6 +4,7 @@ private import semmle.code.cpp.ir.implementation.internal.OperandTag private import semmle.code.cpp.ir.internal.CppType private import semmle.code.cpp.models.interfaces.SideEffect private import semmle.code.cpp.models.interfaces.Throwing +private import semmle.code.cpp.models.interfaces.NonThrowing private import InstructionTag private import SideEffects private import TranslatedElement @@ -84,12 +85,14 @@ abstract class TranslatedCall extends TranslatedExpr { this.getEnclosingFunction().getFunction() = instr.getEnclosingFunction() ) else ( - not this.mustThrowException() and + not this.mustThrowException(_) and result = this.getParent().getChildSuccessor(this, kind) or - this.mayThrowException() and - kind instanceof CppExceptionEdge and - result = this.getParent().getExceptionSuccessorInstruction(any(GotoEdge edge)) + exists(ExceptionEdge e | this.hasExceptionBehavior(e) | + this.mayThrowException(e) and + kind = e and + result = this.getParent().getExceptionSuccessorInstruction(any(GotoEdge edge)) + ) ) } @@ -118,13 +121,42 @@ abstract class TranslatedCall extends TranslatedExpr { /** * Holds if the evaluation of this call may throw an exception. + * The edge `e` determines what type of exception is being considered, + * `CppExceptionEdge` or `SehExceptionEdge`. */ - abstract predicate mayThrowException(); + abstract predicate mayThrowException(ExceptionEdge e); /** * Holds if the evaluation of this call always throws an exception. + * The edge `e` determines what type of exception is being considered, + * `CppExceptionEdge` or `SehExceptionEdge`. + */ + abstract predicate mustThrowException(ExceptionEdge e); + + /** + * Holds when the call target is known to never raise an exception. + * The edge `e` determines what type of exception is being considered, + * `CppExceptionEdge` or `SehExceptionEdge`. + * + * Note that `alwaysRaiseException`, `mayRaiseException`, + * and `neverRaiseException` may conflict (e.g., all hold for a given target). + * Conflicting results are resolved during IR generation. */ - abstract predicate mustThrowException(); + abstract predicate neverThrowException(ExceptionEdge e); + + /** + * Holds if the call has any exception behavior defined for exception edge type `e`, + * i.e., if the function is known to throw or never throw an exception. + * This handles cases where a function has no annotation to specify + * if a function throws or doesn't throw. + */ + final predicate hasExceptionBehavior(ExceptionEdge e) { + this.mayThrowException(e) + or + this.mustThrowException(e) + or + this.neverThrowException(e) + } /** * Gets the result type of the call. @@ -320,6 +352,39 @@ abstract class TranslatedCallExpr extends TranslatedNonConstantExpr, TranslatedC final override int getNumberOfArguments() { result = expr.getNumberOfArguments() } final override predicate isNoReturn() { any(Options opt).exits(expr.getTarget()) } + + override predicate mustThrowException(ExceptionEdge e) { + // Functions that always raise exceptions only occur with Seh exceptions + // Use the `AlwaysSehThrowingFunction` instance unless the function is known to never throw + not this.neverThrowException(e) and + expr.getTarget() instanceof AlwaysSehThrowingFunction and + e instanceof SehExceptionEdge + } + + override predicate mayThrowException(ExceptionEdge e) { + // by default, all functions may throw exceptions of any kind + // unless explicitly annotated to never throw + // Only consider a call to "may" throw an Seh exception + // if inside a MicrosoftTryStmt + not this.neverThrowException(e) and + ( + this.mustThrowException(e) + or + // for now assuming all calls may throw for Seh only + e instanceof SehExceptionEdge and + exists(MicrosoftTryStmt trystmt | trystmt.getAChild*() = expr) + ) + } + + override predicate neverThrowException(ExceptionEdge e) { + // currently, only functions can only explicitly stipulate they + // never through a C++ exception + // NOTE: we cannot simply check if not exists may and must throw. + // since an annotation exists to override any other behavior + // i.e., `NonCppThrowingFunction`. + e instanceof CppExceptionEdge and + expr.getTarget() instanceof NonCppThrowingFunction + } } /** @@ -332,14 +397,16 @@ class TranslatedExprCall extends TranslatedCallExpr { result = getTranslatedExpr(expr.getExpr().getFullyConverted()) } - final override predicate mayThrowException() { + final override predicate mayThrowException(ExceptionEdge e) { none() } + + final override predicate mustThrowException(ExceptionEdge e) { none() } + + final override predicate neverThrowException(ExceptionEdge e) { // We assume that a call to a function pointer will not throw an exception. // This is not sound in general, but this will greatly reduce the number of // exceptional edges. - none() + any() } - - final override predicate mustThrowException() { none() } } /** @@ -361,18 +428,6 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall { exists(this.getQualifier()) and not exists(MemberFunction func | expr.getTarget() = func and func.isStatic()) } - - final override predicate mayThrowException() { - expr.getTarget().(ThrowingFunction).mayThrowException(_) - or - expr.getTarget() instanceof AlwaysSehThrowingFunction - } - - final override predicate mustThrowException() { - expr.getTarget().(ThrowingFunction).mayThrowException(true) - or - expr.getTarget() instanceof AlwaysSehThrowingFunction - } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index 573df94a740e..74f846d68a2c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -2375,14 +2375,16 @@ class TranslatedAllocatorCall extends TTranslatedAllocatorCall, TranslatedDirect result = getTranslatedExpr(expr.getAllocatorCall().getArgument(index).getFullyConverted()) } - final override predicate mayThrowException() { + final override predicate mayThrowException(ExceptionEdge e) { none() } + + final override predicate mustThrowException(ExceptionEdge e) { none() } + + final override predicate neverThrowException(ExceptionEdge e) { // We assume that a call to `new` or `new[]` will never throw. This is not // sound in general, but this will greatly reduce the number of exceptional // edges. - none() + any() } - - final override predicate mustThrowException() { none() } } TranslatedAllocatorCall getTranslatedAllocatorCall(NewOrNewArrayExpr newExpr) { @@ -2448,14 +2450,16 @@ class TranslatedDeleteOrDeleteArrayExpr extends TranslatedNonConstantExpr, Trans result = getTranslatedExpr(expr.getExprWithReuse().getFullyConverted()) } - final override predicate mayThrowException() { + final override predicate mayThrowException(ExceptionEdge e) { none() } + + final override predicate mustThrowException(ExceptionEdge e) { none() } + + final override predicate neverThrowException(ExceptionEdge e) { // We assume that a call to `delete` or `delete[]` will never throw. This is not // sound in general, but this will greatly reduce the number of exceptional // edges. - none() + any() } - - final override predicate mustThrowException() { none() } } TranslatedDeleteOrDeleteArrayExpr getTranslatedDeleteOrDeleteArray(DeleteOrDeleteArrayExpr newExpr) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll index 57f718bcb6ab..83736ae98d04 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll @@ -214,7 +214,7 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction { exists(ThrowExpr throw | throw.getEnclosingFunction() = func) or exists(FunctionCall call | call.getEnclosingFunction() = func | - getTranslatedExpr(call).(TranslatedCallExpr).mayThrowException() + getTranslatedExpr(call).(TranslatedCallExpr).mayThrowException(_) ) ) or diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll index cc2948067092..e9279a109ad9 100644 --- a/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll +++ b/cpp/ql/lib/semmle/code/cpp/models/interfaces/Throwing.qll @@ -12,8 +12,14 @@ import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs /** * A function that is known to raise an exception. + * + * DEPRECATED: This was originally used to differentiate Seh and C++ exception use. + * `AlwaysSehThrowingFunction` should be used instead for Seh exceptions that are + * known to always throw and + * `NonCppThrowingFunction` in `semmle.code.cpp.models.interfaces.NonThrowing` + * should be used for C++ exceptions that are known to never throw. */ -abstract class ThrowingFunction extends Function { +abstract deprecated class ThrowingFunction extends Function { /** * Holds if this function may throw an exception during evaluation. * If `unconditional` is `true` the function always throws an exception. diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected index 224ac9a0ed9b..da2136cba1d4 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -3120,7 +3120,7 @@ ir.c: # 25| v25_4(void) = Call[ExRaiseAccessViolation] : func:r25_1, 0:r25_3 # 25| m25_5(unknown) = ^CallSideEffect : ~m21_4 # 25| m25_6(unknown) = Chi : total:m21_4, partial:m25_5 -#-----| C++ Exception -> Block 3 +#-----| SEH Exception -> Block 3 # 26| Block 1 # 26| r26_1(int) = Constant[0] : @@ -3167,7 +3167,7 @@ ir.c: # 36| v36_3(void) = Call[ExRaiseAccessViolation] : func:r36_1, 0:r36_2 # 36| m36_4(unknown) = ^CallSideEffect : ~m32_4 # 36| m36_5(unknown) = Chi : total:m32_4, partial:m36_4 -#-----| C++ Exception -> Block 4 +#-----| SEH Exception -> Block 4 # 32| Block 1 # 32| v32_5(void) = Unwind : @@ -3202,7 +3202,7 @@ ir.c: # 40| v40_3(void) = Call[ExRaiseAccessViolation] : func:r40_1, 0:r40_2 # 40| m40_4(unknown) = ^CallSideEffect : ~m36_5 # 40| m40_5(unknown) = Chi : total:m36_5, partial:m40_4 -#-----| C++ Exception -> Block 1 +#-----| SEH Exception -> Block 1 # 32| Block 6 # 32| v32_8(void) = Unreached : @@ -3241,7 +3241,7 @@ ir.c: # 62| v62_3(void) = Call[ExRaiseAccessViolation] : func:r62_1, 0:r62_2 # 62| m62_4(unknown) = ^CallSideEffect : ~m57_4 # 62| m62_5(unknown) = Chi : total:m57_4, partial:m62_4 -#-----| C++ Exception -> Block 1 +#-----| SEH Exception -> Block 1 # 66| Block 1 # 66| r66_1(int) = Constant[1] : @@ -3263,7 +3263,7 @@ ir.c: # 73| v73_3(void) = Call[ExRaiseAccessViolation] : func:r73_1, 0:r73_2 # 73| m73_4(unknown) = ^CallSideEffect : ~m70_4 # 73| m73_5(unknown) = Chi : total:m70_4, partial:m73_4 -#-----| C++ Exception -> Block 2 +#-----| SEH Exception -> Block 2 # 70| Block 1 # 70| v70_5(void) = Unwind : @@ -3276,7 +3276,7 @@ ir.c: # 76| v76_3(void) = Call[ExRaiseAccessViolation] : func:r76_1, 0:r76_2 # 76| m76_4(unknown) = ^CallSideEffect : ~m73_5 # 76| m76_5(unknown) = Chi : total:m73_5, partial:m76_4 -#-----| C++ Exception -> Block 1 +#-----| SEH Exception -> Block 1 # 80| void raise_access_violation() # 80| Block 0 @@ -3289,7 +3289,7 @@ ir.c: # 81| v81_3(void) = Call[ExRaiseAccessViolation] : func:r81_1, 0:r81_2 # 81| m81_4(unknown) = ^CallSideEffect : ~m80_4 # 81| m81_5(unknown) = Chi : total:m80_4, partial:m81_4 -#-----| C++ Exception -> Block 1 +#-----| SEH Exception -> Block 1 # 80| Block 1 # 80| v80_5(void) = Unwind : @@ -38731,20 +38731,33 @@ struct_init.cpp: try_except.c: # 6| void f() # 6| Block 0 -# 6| v6_1(void) = EnterFunction : -# 6| m6_2(unknown) = AliasedDefinition : -# 6| m6_3(unknown) = InitializeNonLocal : -# 6| m6_4(unknown) = Chi : total:m6_2, partial:m6_3 -# 7| r7_1(glval) = VariableAddress[x] : -# 7| m7_2(int) = Uninitialized[x] : &:r7_1 -# 7| r7_3(glval) = VariableAddress[y] : -# 7| r7_4(int) = Constant[0] : -# 7| m7_5(int) = Store[y] : &:r7_3, r7_4 -# 9| r9_1(glval) = FunctionAddress[ProbeFunction] : -# 9| r9_2(int) = Constant[0] : -# 9| v9_3(void) = Call[ProbeFunction] : func:r9_1, 0:r9_2 -# 9| m9_4(unknown) = ^CallSideEffect : ~m6_4 -# 9| m9_5(unknown) = Chi : total:m6_4, partial:m9_4 +# 6| v6_1(void) = EnterFunction : +# 6| m6_2(unknown) = AliasedDefinition : +# 6| m6_3(unknown) = InitializeNonLocal : +# 6| m6_4(unknown) = Chi : total:m6_2, partial:m6_3 +# 7| r7_1(glval) = VariableAddress[x] : +# 7| m7_2(int) = Uninitialized[x] : &:r7_1 +# 7| r7_3(glval) = VariableAddress[y] : +# 7| r7_4(int) = Constant[0] : +# 7| m7_5(int) = Store[y] : &:r7_3, r7_4 +# 9| r9_1(glval) = FunctionAddress[ProbeFunction] : +# 9| r9_2(int) = Constant[0] : +# 9| v9_3(void) = Call[ProbeFunction] : func:r9_1, 0:r9_2 +# 9| m9_4(unknown) = ^CallSideEffect : ~m6_4 +# 9| m9_5(unknown) = Chi : total:m6_4, partial:m9_4 +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 5 + +# 6| Block 1 +# 6| m6_5(unknown) = Phi : from 2:~m13_4, from 6:~m11_5 +# 6| v6_6(void) = AliasedUse : ~m6_5 +# 6| v6_7(void) = ExitFunction : + +# 6| Block 2 +# 6| v6_8(void) = Unwind : +#-----| Goto -> Block 1 + +# 10| Block 3 # 10| r10_1(glval) = VariableAddress[y] : # 10| r10_2(int) = Load[y] : &:r10_1, m7_5 # 10| r10_3(glval) = VariableAddress[x] : @@ -38754,13 +38767,32 @@ try_except.c: # 11| v11_3(void) = Call[ProbeFunction] : func:r11_1, 0:r11_2 # 11| m11_4(unknown) = ^CallSideEffect : ~m9_5 # 11| m11_5(unknown) = Chi : total:m9_5, partial:m11_4 -# 16| v16_1(void) = NoOp : -# 6| v6_5(void) = ReturnVoid : -# 6| v6_6(void) = AliasedUse : ~m11_5 -# 6| v6_7(void) = ExitFunction : +#-----| Goto -> Block 6 +#-----| SEH Exception -> Block 5 -# 6| Block 1 -# 6| v6_8(void) = Unreached : +# 13| Block 4 +# 13| r13_1(int) = Constant[0] : +# 13| r13_2(bool) = CompareEQ : r13_5, r13_1 +# 13| v13_3(void) = ConditionalBranch : r13_2 +#-----| False -> Block 7 +#-----| True -> Block 2 + +# 13| Block 5 +# 13| m13_4(unknown) = Phi : from 0:~m9_5, from 3:~m11_5 +# 13| r13_5(int) = Constant[0] : +# 13| r13_6(int) = Constant[-1] : +# 13| r13_7(bool) = CompareEQ : r13_5, r13_6 +# 13| v13_8(void) = ConditionalBranch : r13_7 +#-----| False -> Block 4 +#-----| True -> Block 7 + +# 16| Block 6 +# 16| v16_1(void) = NoOp : +# 6| v6_9(void) = ReturnVoid : +#-----| Goto -> Block 1 + +# 6| Block 7 +# 6| v6_10(void) = Unreached : # 18| void g() # 18| Block 0 @@ -38778,6 +38810,18 @@ try_except.c: # 21| v21_3(void) = Call[ProbeFunction] : func:r21_1, 0:r21_2 # 21| m21_4(unknown) = ^CallSideEffect : ~m18_4 # 21| m21_5(unknown) = Chi : total:m18_4, partial:m21_4 +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 4 + +# 18| Block 1 +# 18| v18_5(void) = AliasedUse : ~m26_8 +# 18| v18_6(void) = ExitFunction : + +# 18| Block 2 +# 18| v18_7(void) = Unwind : +#-----| Goto -> Block 1 + +# 22| Block 3 # 22| r22_1(glval) = VariableAddress[y] : # 22| r22_2(int) = Load[y] : &:r22_1, m19_5 # 22| r22_3(glval) = VariableAddress[x] : @@ -38787,16 +38831,24 @@ try_except.c: # 23| v23_3(void) = Call[ProbeFunction] : func:r23_1, 0:r23_2 # 23| m23_4(unknown) = ^CallSideEffect : ~m21_5 # 23| m23_5(unknown) = Chi : total:m21_5, partial:m23_4 -# 26| r26_1(glval) = FunctionAddress[sink] : -# 26| r26_2(glval) = VariableAddress[x] : -# 26| r26_3(int) = Load[x] : &:r26_2, m22_4 -# 26| v26_4(void) = Call[sink] : func:r26_1, 0:r26_3 -# 26| m26_5(unknown) = ^CallSideEffect : ~m23_5 -# 26| m26_6(unknown) = Chi : total:m23_5, partial:m26_5 -# 28| v28_1(void) = NoOp : -# 18| v18_5(void) = ReturnVoid : -# 18| v18_6(void) = AliasedUse : ~m26_6 -# 18| v18_7(void) = ExitFunction : +#-----| SEH Exception -> Block 4 + +# 26| Block 4 +# 26| m26_1(unknown) = Phi : from 0:~m21_5, from 3:~m23_5 +# 26| m26_2(int) = Phi : from 0:m19_2, from 3:m22_4 +# 26| r26_3(glval) = FunctionAddress[sink] : +# 26| r26_4(glval) = VariableAddress[x] : +# 26| r26_5(int) = Load[x] : &:r26_4, m26_2 +# 26| v26_6(void) = Call[sink] : func:r26_3, 0:r26_5 +# 26| m26_7(unknown) = ^CallSideEffect : ~m26_1 +# 26| m26_8(unknown) = Chi : total:m26_1, partial:m26_7 +#-----| Goto -> Block 5 +#-----| SEH Exception -> Block 2 + +# 28| Block 5 +# 28| v28_1(void) = NoOp : +# 18| v18_8(void) = ReturnVoid : +#-----| Goto -> Block 1 # 32| void h(int) # 32| Block 0 @@ -38812,43 +38864,97 @@ try_except.c: # 35| r35_1(glval) = VariableAddress[b] : # 35| r35_2(int) = Load[b] : &:r35_1, m32_6 # 35| v35_3(void) = ConditionalBranch : r35_2 -#-----| False -> Block 2 -#-----| True -> Block 1 +#-----| False -> Block 8 +#-----| True -> Block 3 -# 36| Block 1 +# 32| Block 1 +# 32| m32_7(unknown) = Phi : from 2:~m40_6, from 8:~m42_1 +# 32| v32_8(void) = AliasedUse : ~m32_7 +# 32| v32_9(void) = ExitFunction : + +# 32| Block 2 +# 32| v32_10(void) = Unwind : +#-----| Goto -> Block 1 + +# 36| Block 3 # 36| r36_1(glval) = FunctionAddress[AfxThrowMemoryException] : # 36| v36_2(void) = Call[AfxThrowMemoryException] : func:r36_1 # 36| m36_3(unknown) = ^CallSideEffect : ~m32_4 # 36| m36_4(unknown) = Chi : total:m32_4, partial:m36_3 -#-----| Goto -> Block 2 +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 6 -# 42| Block 2 -# 42| m42_1(unknown) = Phi : from 0:~m32_4, from 1:~m36_4 -# 42| v42_2(void) = NoOp : -# 32| v32_7(void) = ReturnVoid : -# 32| v32_8(void) = AliasedUse : ~m42_1 -# 32| v32_9(void) = ExitFunction : +# 39| Block 4 +# 39| r39_1(int) = Constant[0] : +# 39| r39_2(bool) = CompareEQ : r39_7, r39_1 +# 39| v39_3(void) = ConditionalBranch : r39_2 +#-----| False -> Block 5 +#-----| True -> Block 9 -# 32| Block 3 -# 32| v32_10(void) = Unreached : +# 39| Block 5 +# 39| r39_4(int) = Constant[1] : +# 39| r39_5(bool) = CompareEQ : r39_7, r39_4 +# 39| v39_6(void) = ConditionalBranch : r39_5 +#-----| False -> Block 9 +#-----| True -> Block 7 + +# 39| Block 6 +# 39| r39_7(int) = Constant[1] : +# 39| r39_8(int) = Constant[-1] : +# 39| r39_9(bool) = CompareEQ : r39_7, r39_8 +# 39| v39_10(void) = ConditionalBranch : r39_9 +#-----| False -> Block 4 +#-----| True -> Block 9 + +# 40| Block 7 +# 40| r40_1(glval) = FunctionAddress[sink] : +# 40| r40_2(glval) = VariableAddress[x] : +# 40| r40_3(int) = Load[x] : &:r40_2, m33_3 +# 40| v40_4(void) = Call[sink] : func:r40_1, 0:r40_3 +# 40| m40_5(unknown) = ^CallSideEffect : ~m36_4 +# 40| m40_6(unknown) = Chi : total:m36_4, partial:m40_5 +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 2 + +# 42| Block 8 +# 42| m42_1(unknown) = Phi : from 0:~m32_4, from 3:~m36_4, from 7:~m40_6 +# 42| v42_2(void) = NoOp : +# 32| v32_11(void) = ReturnVoid : +#-----| Goto -> Block 1 + +# 32| Block 9 +# 32| v32_12(void) = Unreached : try_except.cpp: # 6| void f_cpp() # 6| Block 0 -# 6| v6_1(void) = EnterFunction : -# 6| m6_2(unknown) = AliasedDefinition : -# 6| m6_3(unknown) = InitializeNonLocal : -# 6| m6_4(unknown) = Chi : total:m6_2, partial:m6_3 -# 7| r7_1(glval) = VariableAddress[x] : -# 7| m7_2(int) = Uninitialized[x] : &:r7_1 -# 7| r7_3(glval) = VariableAddress[y] : -# 7| r7_4(int) = Constant[0] : -# 7| m7_5(int) = Store[y] : &:r7_3, r7_4 -# 9| r9_1(glval) = FunctionAddress[ProbeFunction] : -# 9| r9_2(int) = Constant[0] : -# 9| v9_3(void) = Call[ProbeFunction] : func:r9_1, 0:r9_2 -# 9| m9_4(unknown) = ^CallSideEffect : ~m6_4 -# 9| m9_5(unknown) = Chi : total:m6_4, partial:m9_4 +# 6| v6_1(void) = EnterFunction : +# 6| m6_2(unknown) = AliasedDefinition : +# 6| m6_3(unknown) = InitializeNonLocal : +# 6| m6_4(unknown) = Chi : total:m6_2, partial:m6_3 +# 7| r7_1(glval) = VariableAddress[x] : +# 7| m7_2(int) = Uninitialized[x] : &:r7_1 +# 7| r7_3(glval) = VariableAddress[y] : +# 7| r7_4(int) = Constant[0] : +# 7| m7_5(int) = Store[y] : &:r7_3, r7_4 +# 9| r9_1(glval) = FunctionAddress[ProbeFunction] : +# 9| r9_2(int) = Constant[0] : +# 9| v9_3(void) = Call[ProbeFunction] : func:r9_1, 0:r9_2 +# 9| m9_4(unknown) = ^CallSideEffect : ~m6_4 +# 9| m9_5(unknown) = Chi : total:m6_4, partial:m9_4 +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 5 + +# 6| Block 1 +# 6| m6_5(unknown) = Phi : from 2:~m13_4, from 6:~m11_5 +# 6| v6_6(void) = AliasedUse : ~m6_5 +# 6| v6_7(void) = ExitFunction : + +# 6| Block 2 +# 6| v6_8(void) = Unwind : +#-----| Goto -> Block 1 + +# 10| Block 3 # 10| r10_1(glval) = VariableAddress[y] : # 10| r10_2(int) = Load[y] : &:r10_1, m7_5 # 10| r10_3(glval) = VariableAddress[x] : @@ -38858,13 +38964,32 @@ try_except.cpp: # 11| v11_3(void) = Call[ProbeFunction] : func:r11_1, 0:r11_2 # 11| m11_4(unknown) = ^CallSideEffect : ~m9_5 # 11| m11_5(unknown) = Chi : total:m9_5, partial:m11_4 -# 16| v16_1(void) = NoOp : -# 6| v6_5(void) = ReturnVoid : -# 6| v6_6(void) = AliasedUse : ~m11_5 -# 6| v6_7(void) = ExitFunction : +#-----| Goto -> Block 6 +#-----| SEH Exception -> Block 5 -# 6| Block 1 -# 6| v6_8(void) = Unreached : +# 13| Block 4 +# 13| r13_1(int) = Constant[0] : +# 13| r13_2(bool) = CompareEQ : r13_5, r13_1 +# 13| v13_3(void) = ConditionalBranch : r13_2 +#-----| False -> Block 7 +#-----| True -> Block 2 + +# 13| Block 5 +# 13| m13_4(unknown) = Phi : from 0:~m9_5, from 3:~m11_5 +# 13| r13_5(int) = Constant[0] : +# 13| r13_6(int) = Constant[-1] : +# 13| r13_7(bool) = CompareEQ : r13_5, r13_6 +# 13| v13_8(void) = ConditionalBranch : r13_7 +#-----| False -> Block 4 +#-----| True -> Block 7 + +# 16| Block 6 +# 16| v16_1(void) = NoOp : +# 6| v6_9(void) = ReturnVoid : +#-----| Goto -> Block 1 + +# 6| Block 7 +# 6| v6_10(void) = Unreached : # 18| void g_cpp() # 18| Block 0 @@ -38882,6 +39007,18 @@ try_except.cpp: # 21| v21_3(void) = Call[ProbeFunction] : func:r21_1, 0:r21_2 # 21| m21_4(unknown) = ^CallSideEffect : ~m18_4 # 21| m21_5(unknown) = Chi : total:m18_4, partial:m21_4 +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 4 + +# 18| Block 1 +# 18| v18_5(void) = AliasedUse : ~m26_8 +# 18| v18_6(void) = ExitFunction : + +# 18| Block 2 +# 18| v18_7(void) = Unwind : +#-----| Goto -> Block 1 + +# 22| Block 3 # 22| r22_1(glval) = VariableAddress[y] : # 22| r22_2(int) = Load[y] : &:r22_1, m19_5 # 22| r22_3(glval) = VariableAddress[x] : @@ -38891,16 +39028,24 @@ try_except.cpp: # 23| v23_3(void) = Call[ProbeFunction] : func:r23_1, 0:r23_2 # 23| m23_4(unknown) = ^CallSideEffect : ~m21_5 # 23| m23_5(unknown) = Chi : total:m21_5, partial:m23_4 -# 26| r26_1(glval) = FunctionAddress[sink] : -# 26| r26_2(glval) = VariableAddress[x] : -# 26| r26_3(int) = Load[x] : &:r26_2, m22_4 -# 26| v26_4(void) = Call[sink] : func:r26_1, 0:r26_3 -# 26| m26_5(unknown) = ^CallSideEffect : ~m23_5 -# 26| m26_6(unknown) = Chi : total:m23_5, partial:m26_5 -# 28| v28_1(void) = NoOp : -# 18| v18_5(void) = ReturnVoid : -# 18| v18_6(void) = AliasedUse : ~m26_6 -# 18| v18_7(void) = ExitFunction : +#-----| SEH Exception -> Block 4 + +# 26| Block 4 +# 26| m26_1(unknown) = Phi : from 0:~m21_5, from 3:~m23_5 +# 26| m26_2(int) = Phi : from 0:m19_2, from 3:m22_4 +# 26| r26_3(glval) = FunctionAddress[sink] : +# 26| r26_4(glval) = VariableAddress[x] : +# 26| r26_5(int) = Load[x] : &:r26_4, m26_2 +# 26| v26_6(void) = Call[sink] : func:r26_3, 0:r26_5 +# 26| m26_7(unknown) = ^CallSideEffect : ~m26_1 +# 26| m26_8(unknown) = Chi : total:m26_1, partial:m26_7 +#-----| Goto -> Block 5 +#-----| SEH Exception -> Block 2 + +# 28| Block 5 +# 28| v28_1(void) = NoOp : +# 18| v18_8(void) = ReturnVoid : +#-----| Goto -> Block 1 # 32| void h_cpp(int) # 32| Block 0 @@ -38918,25 +39063,66 @@ try_except.cpp: # 35| r35_3(int) = Constant[0] : # 35| r35_4(bool) = CompareNE : r35_2, r35_3 # 35| v35_5(void) = ConditionalBranch : r35_4 -#-----| False -> Block 2 -#-----| True -> Block 1 +#-----| False -> Block 8 +#-----| True -> Block 3 -# 36| Block 1 +# 32| Block 1 +# 32| m32_7(unknown) = Phi : from 2:~m40_6, from 8:~m42_1 +# 32| v32_8(void) = AliasedUse : ~m32_7 +# 32| v32_9(void) = ExitFunction : + +# 32| Block 2 +# 32| v32_10(void) = Unwind : +#-----| Goto -> Block 1 + +# 36| Block 3 # 36| r36_1(glval) = FunctionAddress[AfxThrowMemoryException] : # 36| v36_2(void) = Call[AfxThrowMemoryException] : func:r36_1 # 36| m36_3(unknown) = ^CallSideEffect : ~m32_4 # 36| m36_4(unknown) = Chi : total:m32_4, partial:m36_3 -#-----| Goto -> Block 2 +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 6 -# 42| Block 2 -# 42| m42_1(unknown) = Phi : from 0:~m32_4, from 1:~m36_4 -# 42| v42_2(void) = NoOp : -# 32| v32_7(void) = ReturnVoid : -# 32| v32_8(void) = AliasedUse : ~m42_1 -# 32| v32_9(void) = ExitFunction : +# 39| Block 4 +# 39| r39_1(int) = Constant[0] : +# 39| r39_2(bool) = CompareEQ : r39_7, r39_1 +# 39| v39_3(void) = ConditionalBranch : r39_2 +#-----| False -> Block 5 +#-----| True -> Block 9 + +# 39| Block 5 +# 39| r39_4(int) = Constant[1] : +# 39| r39_5(bool) = CompareEQ : r39_7, r39_4 +# 39| v39_6(void) = ConditionalBranch : r39_5 +#-----| False -> Block 9 +#-----| True -> Block 7 + +# 39| Block 6 +# 39| r39_7(int) = Constant[1] : +# 39| r39_8(int) = Constant[-1] : +# 39| r39_9(bool) = CompareEQ : r39_7, r39_8 +# 39| v39_10(void) = ConditionalBranch : r39_9 +#-----| False -> Block 4 +#-----| True -> Block 9 -# 32| Block 3 -# 32| v32_10(void) = Unreached : +# 40| Block 7 +# 40| r40_1(glval) = FunctionAddress[sink] : +# 40| r40_2(glval) = VariableAddress[x] : +# 40| r40_3(int) = Load[x] : &:r40_2, m33_3 +# 40| v40_4(void) = Call[sink] : func:r40_1, 0:r40_3 +# 40| m40_5(unknown) = ^CallSideEffect : ~m36_4 +# 40| m40_6(unknown) = Chi : total:m36_4, partial:m40_5 +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 2 + +# 42| Block 8 +# 42| m42_1(unknown) = Phi : from 0:~m32_4, from 3:~m36_4, from 7:~m40_6 +# 42| v42_2(void) = NoOp : +# 32| v32_11(void) = ReturnVoid : +#-----| Goto -> Block 1 + +# 32| Block 9 +# 32| v32_12(void) = Unreached : # 44| void throw_cpp(int) # 44| Block 0 @@ -38954,53 +39140,62 @@ try_except.cpp: # 47| r47_3(int) = Constant[0] : # 47| r47_4(bool) = CompareNE : r47_2, r47_3 # 47| v47_5(void) = ConditionalBranch : r47_4 -#-----| False -> Block 6 -#-----| True -> Block 1 +#-----| False -> Block 8 +#-----| True -> Block 3 + +# 44| Block 1 +# 44| m44_7(unknown) = Phi : from 2:~m52_6, from 8:~m54_1 +# 44| v44_8(void) = AliasedUse : ~m44_7 +# 44| v44_9(void) = ExitFunction : + +# 44| Block 2 +# 44| v44_10(void) = Unwind : +#-----| Goto -> Block 1 -# 48| Block 1 +# 48| Block 3 # 48| r48_1(glval) = VariableAddress[#throw48:13] : # 48| r48_2(int) = Constant[1] : # 48| m48_3(int) = Store[#throw48:13] : &:r48_1, r48_2 # 48| v48_4(void) = ThrowValue : &:r48_1, m48_3 -#-----| C++ Exception -> Block 4 +#-----| C++ Exception -> Block 6 -# 51| Block 2 +# 51| Block 4 # 51| r51_1(int) = Constant[0] : # 51| r51_2(bool) = CompareEQ : r51_7, r51_1 # 51| v51_3(void) = ConditionalBranch : r51_2 -#-----| False -> Block 3 -#-----| True -> Block 7 +#-----| False -> Block 5 +#-----| True -> Block 9 -# 51| Block 3 +# 51| Block 5 # 51| r51_4(int) = Constant[1] : # 51| r51_5(bool) = CompareEQ : r51_7, r51_4 # 51| v51_6(void) = ConditionalBranch : r51_5 -#-----| False -> Block 7 -#-----| True -> Block 5 +#-----| False -> Block 9 +#-----| True -> Block 7 -# 51| Block 4 +# 51| Block 6 # 51| r51_7(int) = Constant[1] : # 51| r51_8(int) = Constant[-1] : # 51| r51_9(bool) = CompareEQ : r51_7, r51_8 # 51| v51_10(void) = ConditionalBranch : r51_9 -#-----| False -> Block 2 -#-----| True -> Block 7 +#-----| False -> Block 4 +#-----| True -> Block 9 -# 52| Block 5 +# 52| Block 7 # 52| r52_1(glval) = FunctionAddress[sink] : # 52| r52_2(glval) = VariableAddress[x] : # 52| r52_3(int) = Load[x] : &:r52_2, m45_3 # 52| v52_4(void) = Call[sink] : func:r52_1, 0:r52_3 # 52| m52_5(unknown) = ^CallSideEffect : ~m44_4 # 52| m52_6(unknown) = Chi : total:m44_4, partial:m52_5 -#-----| Goto -> Block 6 +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 2 -# 54| Block 6 -# 54| m54_1(unknown) = Phi : from 0:~m44_4, from 5:~m52_6 -# 54| v54_2(void) = NoOp : -# 44| v44_7(void) = ReturnVoid : -# 44| v44_8(void) = AliasedUse : ~m54_1 -# 44| v44_9(void) = ExitFunction : +# 54| Block 8 +# 54| m54_1(unknown) = Phi : from 0:~m44_4, from 7:~m52_6 +# 54| v54_2(void) = NoOp : +# 44| v44_11(void) = ReturnVoid : +#-----| Goto -> Block 1 -# 44| Block 7 -# 44| v44_10(void) = Unreached : +# 44| Block 9 +# 44| v44_12(void) = Unreached : diff --git a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected index 7b5d32c65438..0e6d67a5ae9a 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected @@ -21,14 +21,6 @@ lostReachability backEdgeCountMismatch useNotDominatedByDefinition | ir.cpp:1535:8:1535:8 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:1535:8:1535:8 | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | -| try_except.c:13:13:13:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() | -| try_except.c:13:13:13:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:6:6:6:6 | void f() | void f() | -| try_except.c:39:15:39:15 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:32:6:32:6 | void h(int) | void h(int) | -| try_except.c:39:15:39:15 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.c:32:6:32:6 | void h(int) | void h(int) | -| try_except.cpp:13:13:13:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.cpp:6:6:6:10 | void f_cpp() | void f_cpp() | -| try_except.cpp:13:13:13:13 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.cpp:6:6:6:10 | void f_cpp() | void f_cpp() | -| try_except.cpp:39:15:39:15 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.cpp:32:6:32:10 | void h_cpp(int) | void h_cpp(int) | -| try_except.cpp:39:15:39:15 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | try_except.cpp:32:6:32:10 | void h_cpp(int) | void h_cpp(int) | switchInstructionWithoutDefaultEdge notMarkedAsConflated wronglyMarkedAsConflated diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 8600049dd225..dfaea0dc04e4 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -2884,7 +2884,7 @@ ir.c: # 25| r25_3(int) = Load[x] : &:r25_2, ~m? # 25| v25_4(void) = Call[ExRaiseAccessViolation] : func:r25_1, 0:r25_3 # 25| mu25_5(unknown) = ^CallSideEffect : ~m? -#-----| C++ Exception -> Block 6 +#-----| SEH Exception -> Block 6 # 21| Block 1 # 21| v21_6(void) = AliasedUse : ~m? @@ -2941,7 +2941,7 @@ ir.c: # 36| r36_2(int) = Constant[0] : # 36| v36_3(void) = Call[ExRaiseAccessViolation] : func:r36_1, 0:r36_2 # 36| mu36_4(unknown) = ^CallSideEffect : ~m? -#-----| C++ Exception -> Block 5 +#-----| SEH Exception -> Block 5 # 32| Block 1 # 32| v32_4(void) = AliasedUse : ~m? @@ -2977,7 +2977,7 @@ ir.c: # 40| r40_2(int) = Constant[1] : # 40| v40_3(void) = Call[ExRaiseAccessViolation] : func:r40_1, 0:r40_2 # 40| mu40_4(unknown) = ^CallSideEffect : ~m? -#-----| C++ Exception -> Block 2 +#-----| SEH Exception -> Block 2 # 42| Block 7 # 42| v42_1(void) = NoOp : @@ -3022,7 +3022,7 @@ ir.c: # 62| r62_2(int) = Constant[0] : # 62| v62_3(void) = Call[ExRaiseAccessViolation] : func:r62_1, 0:r62_2 # 62| mu62_4(unknown) = ^CallSideEffect : ~m? -#-----| C++ Exception -> Block 3 +#-----| SEH Exception -> Block 3 # 57| Block 1 # 57| v57_4(void) = AliasedUse : ~m? @@ -3049,7 +3049,7 @@ ir.c: # 73| r73_2(int) = Constant[0] : # 73| v73_3(void) = Call[ExRaiseAccessViolation] : func:r73_1, 0:r73_2 # 73| mu73_4(unknown) = ^CallSideEffect : ~m? -#-----| C++ Exception -> Block 3 +#-----| SEH Exception -> Block 3 # 70| Block 1 # 70| v70_4(void) = AliasedUse : ~m? @@ -3064,7 +3064,7 @@ ir.c: # 76| r76_2(int) = Constant[0] : # 76| v76_3(void) = Call[ExRaiseAccessViolation] : func:r76_1, 0:r76_2 # 76| mu76_4(unknown) = ^CallSideEffect : ~m? -#-----| C++ Exception -> Block 2 +#-----| SEH Exception -> Block 2 # 78| Block 4 # 78| v78_1(void) = NoOp : @@ -3080,7 +3080,7 @@ ir.c: # 81| r81_2(int) = Constant[1] : # 81| v81_3(void) = Call[ExRaiseAccessViolation] : func:r81_1, 0:r81_2 # 81| mu81_4(unknown) = ^CallSideEffect : ~m? -#-----| C++ Exception -> Block 2 +#-----| SEH Exception -> Block 2 # 80| Block 1 # 80| v80_4(void) = AliasedUse : ~m? @@ -36973,27 +36973,20 @@ struct_init.cpp: try_except.c: # 6| void f() # 6| Block 0 -# 6| v6_1(void) = EnterFunction : -# 6| mu6_2(unknown) = AliasedDefinition : -# 6| mu6_3(unknown) = InitializeNonLocal : -# 7| r7_1(glval) = VariableAddress[x] : -# 7| mu7_2(int) = Uninitialized[x] : &:r7_1 -# 7| r7_3(glval) = VariableAddress[y] : -# 7| r7_4(int) = Constant[0] : -# 7| mu7_5(int) = Store[y] : &:r7_3, r7_4 -# 9| r9_1(glval) = FunctionAddress[ProbeFunction] : -# 9| r9_2(int) = Constant[0] : -# 9| v9_3(void) = Call[ProbeFunction] : func:r9_1, 0:r9_2 -# 9| mu9_4(unknown) = ^CallSideEffect : ~m? -# 10| r10_1(glval) = VariableAddress[y] : -# 10| r10_2(int) = Load[y] : &:r10_1, ~m? -# 10| r10_3(glval) = VariableAddress[x] : -# 10| mu10_4(int) = Store[x] : &:r10_3, r10_2 -# 11| r11_1(glval) = FunctionAddress[ProbeFunction] : -# 11| r11_2(int) = Constant[0] : -# 11| v11_3(void) = Call[ProbeFunction] : func:r11_1, 0:r11_2 -# 11| mu11_4(unknown) = ^CallSideEffect : ~m? -#-----| Goto -> Block 7 +# 6| v6_1(void) = EnterFunction : +# 6| mu6_2(unknown) = AliasedDefinition : +# 6| mu6_3(unknown) = InitializeNonLocal : +# 7| r7_1(glval) = VariableAddress[x] : +# 7| mu7_2(int) = Uninitialized[x] : &:r7_1 +# 7| r7_3(glval) = VariableAddress[y] : +# 7| r7_4(int) = Constant[0] : +# 7| mu7_5(int) = Store[y] : &:r7_3, r7_4 +# 9| r9_1(glval) = FunctionAddress[ProbeFunction] : +# 9| r9_2(int) = Constant[0] : +# 9| v9_3(void) = Call[ProbeFunction] : func:r9_1, 0:r9_2 +# 9| mu9_4(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 6 # 6| Block 1 # 6| v6_4(void) = AliasedUse : ~m? @@ -37003,36 +36996,49 @@ try_except.c: # 6| v6_6(void) = Unwind : #-----| Goto -> Block 1 -# 13| Block 3 +# 10| Block 3 +# 10| r10_1(glval) = VariableAddress[y] : +# 10| r10_2(int) = Load[y] : &:r10_1, ~m? +# 10| r10_3(glval) = VariableAddress[x] : +# 10| mu10_4(int) = Store[x] : &:r10_3, r10_2 +# 11| r11_1(glval) = FunctionAddress[ProbeFunction] : +# 11| r11_2(int) = Constant[0] : +# 11| v11_3(void) = Call[ProbeFunction] : func:r11_1, 0:r11_2 +# 11| mu11_4(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 6 + +# 13| Block 4 # 13| r13_1(int) = Constant[0] : # 13| r13_2(bool) = CompareEQ : r13_7, r13_1 # 13| v13_3(void) = ConditionalBranch : r13_2 -#-----| False -> Block 4 +#-----| False -> Block 5 #-----| True -> Block 2 -# 13| Block 4 +# 13| Block 5 # 13| r13_4(int) = Constant[1] : # 13| r13_5(bool) = CompareEQ : r13_7, r13_4 # 13| v13_6(void) = ConditionalBranch : r13_5 -#-----| True -> Block 6 +#-----| True -> Block 7 -# 13| Block 5 +# 13| Block 6 # 13| r13_7(int) = Constant[0] : # 13| r13_8(int) = Constant[-1] : # 13| r13_9(bool) = CompareEQ : r13_7, r13_8 # 13| v13_10(void) = ConditionalBranch : r13_9 -#-----| False -> Block 3 +#-----| False -> Block 4 #-----| True -> Block 2 -# 14| Block 6 +# 14| Block 7 # 14| r14_1(glval) = FunctionAddress[sink] : # 14| r14_2(glval) = VariableAddress[x] : # 14| r14_3(int) = Load[x] : &:r14_2, ~m? # 14| v14_4(void) = Call[sink] : func:r14_1, 0:r14_3 # 14| mu14_5(unknown) = ^CallSideEffect : ~m? -#-----| Goto -> Block 7 +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 2 -# 16| Block 7 +# 16| Block 8 # 16| v16_1(void) = NoOp : # 6| v6_7(void) = ReturnVoid : #-----| Goto -> Block 1 @@ -37051,6 +37057,18 @@ try_except.c: # 21| r21_2(int) = Constant[0] : # 21| v21_3(void) = Call[ProbeFunction] : func:r21_1, 0:r21_2 # 21| mu21_4(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 4 + +# 18| Block 1 +# 18| v18_4(void) = AliasedUse : ~m? +# 18| v18_5(void) = ExitFunction : + +# 18| Block 2 +# 18| v18_6(void) = Unwind : +#-----| Goto -> Block 1 + +# 22| Block 3 # 22| r22_1(glval) = VariableAddress[y] : # 22| r22_2(int) = Load[y] : &:r22_1, ~m? # 22| r22_3(glval) = VariableAddress[x] : @@ -37059,21 +37077,20 @@ try_except.c: # 23| r23_2(int) = Constant[0] : # 23| v23_3(void) = Call[ProbeFunction] : func:r23_1, 0:r23_2 # 23| mu23_4(unknown) = ^CallSideEffect : ~m? -# 26| r26_1(glval) = FunctionAddress[sink] : -# 26| r26_2(glval) = VariableAddress[x] : -# 26| r26_3(int) = Load[x] : &:r26_2, ~m? -# 26| v26_4(void) = Call[sink] : func:r26_1, 0:r26_3 -# 26| mu26_5(unknown) = ^CallSideEffect : ~m? -# 28| v28_1(void) = NoOp : -# 18| v18_4(void) = ReturnVoid : -#-----| Goto -> Block 1 +#-----| SEH Exception -> Block 4 -# 18| Block 1 -# 18| v18_5(void) = AliasedUse : ~m? -# 18| v18_6(void) = ExitFunction : +# 26| Block 4 +# 26| r26_1(glval) = FunctionAddress[sink] : +# 26| r26_2(glval) = VariableAddress[x] : +# 26| r26_3(int) = Load[x] : &:r26_2, ~m? +# 26| v26_4(void) = Call[sink] : func:r26_1, 0:r26_3 +# 26| mu26_5(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 5 +#-----| SEH Exception -> Block 2 -# 18| Block 2 -# 18| v18_7(void) = Unwind : +# 28| Block 5 +# 28| v28_1(void) = NoOp : +# 18| v18_7(void) = ReturnVoid : #-----| Goto -> Block 1 # 32| void h(int) @@ -37105,6 +37122,7 @@ try_except.c: # 36| v36_2(void) = Call[AfxThrowMemoryException] : func:r36_1 # 36| mu36_3(unknown) = ^CallSideEffect : ~m? #-----| Goto -> Block 8 +#-----| SEH Exception -> Block 6 # 39| Block 4 # 39| r39_1(int) = Constant[0] : @@ -37134,6 +37152,7 @@ try_except.c: # 40| v40_4(void) = Call[sink] : func:r40_1, 0:r40_3 # 40| mu40_5(unknown) = ^CallSideEffect : ~m? #-----| Goto -> Block 8 +#-----| SEH Exception -> Block 2 # 42| Block 8 # 42| v42_1(void) = NoOp : @@ -37143,27 +37162,20 @@ try_except.c: try_except.cpp: # 6| void f_cpp() # 6| Block 0 -# 6| v6_1(void) = EnterFunction : -# 6| mu6_2(unknown) = AliasedDefinition : -# 6| mu6_3(unknown) = InitializeNonLocal : -# 7| r7_1(glval) = VariableAddress[x] : -# 7| mu7_2(int) = Uninitialized[x] : &:r7_1 -# 7| r7_3(glval) = VariableAddress[y] : -# 7| r7_4(int) = Constant[0] : -# 7| mu7_5(int) = Store[y] : &:r7_3, r7_4 -# 9| r9_1(glval) = FunctionAddress[ProbeFunction] : -# 9| r9_2(int) = Constant[0] : -# 9| v9_3(void) = Call[ProbeFunction] : func:r9_1, 0:r9_2 -# 9| mu9_4(unknown) = ^CallSideEffect : ~m? -# 10| r10_1(glval) = VariableAddress[y] : -# 10| r10_2(int) = Load[y] : &:r10_1, ~m? -# 10| r10_3(glval) = VariableAddress[x] : -# 10| mu10_4(int) = Store[x] : &:r10_3, r10_2 -# 11| r11_1(glval) = FunctionAddress[ProbeFunction] : -# 11| r11_2(int) = Constant[0] : -# 11| v11_3(void) = Call[ProbeFunction] : func:r11_1, 0:r11_2 -# 11| mu11_4(unknown) = ^CallSideEffect : ~m? -#-----| Goto -> Block 7 +# 6| v6_1(void) = EnterFunction : +# 6| mu6_2(unknown) = AliasedDefinition : +# 6| mu6_3(unknown) = InitializeNonLocal : +# 7| r7_1(glval) = VariableAddress[x] : +# 7| mu7_2(int) = Uninitialized[x] : &:r7_1 +# 7| r7_3(glval) = VariableAddress[y] : +# 7| r7_4(int) = Constant[0] : +# 7| mu7_5(int) = Store[y] : &:r7_3, r7_4 +# 9| r9_1(glval) = FunctionAddress[ProbeFunction] : +# 9| r9_2(int) = Constant[0] : +# 9| v9_3(void) = Call[ProbeFunction] : func:r9_1, 0:r9_2 +# 9| mu9_4(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 6 # 6| Block 1 # 6| v6_4(void) = AliasedUse : ~m? @@ -37173,36 +37185,49 @@ try_except.cpp: # 6| v6_6(void) = Unwind : #-----| Goto -> Block 1 -# 13| Block 3 +# 10| Block 3 +# 10| r10_1(glval) = VariableAddress[y] : +# 10| r10_2(int) = Load[y] : &:r10_1, ~m? +# 10| r10_3(glval) = VariableAddress[x] : +# 10| mu10_4(int) = Store[x] : &:r10_3, r10_2 +# 11| r11_1(glval) = FunctionAddress[ProbeFunction] : +# 11| r11_2(int) = Constant[0] : +# 11| v11_3(void) = Call[ProbeFunction] : func:r11_1, 0:r11_2 +# 11| mu11_4(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 6 + +# 13| Block 4 # 13| r13_1(int) = Constant[0] : # 13| r13_2(bool) = CompareEQ : r13_7, r13_1 # 13| v13_3(void) = ConditionalBranch : r13_2 -#-----| False -> Block 4 +#-----| False -> Block 5 #-----| True -> Block 2 -# 13| Block 4 +# 13| Block 5 # 13| r13_4(int) = Constant[1] : # 13| r13_5(bool) = CompareEQ : r13_7, r13_4 # 13| v13_6(void) = ConditionalBranch : r13_5 -#-----| True -> Block 6 +#-----| True -> Block 7 -# 13| Block 5 +# 13| Block 6 # 13| r13_7(int) = Constant[0] : # 13| r13_8(int) = Constant[-1] : # 13| r13_9(bool) = CompareEQ : r13_7, r13_8 # 13| v13_10(void) = ConditionalBranch : r13_9 -#-----| False -> Block 3 +#-----| False -> Block 4 #-----| True -> Block 2 -# 14| Block 6 +# 14| Block 7 # 14| r14_1(glval) = FunctionAddress[sink] : # 14| r14_2(glval) = VariableAddress[x] : # 14| r14_3(int) = Load[x] : &:r14_2, ~m? # 14| v14_4(void) = Call[sink] : func:r14_1, 0:r14_3 # 14| mu14_5(unknown) = ^CallSideEffect : ~m? -#-----| Goto -> Block 7 +#-----| Goto -> Block 8 +#-----| SEH Exception -> Block 2 -# 16| Block 7 +# 16| Block 8 # 16| v16_1(void) = NoOp : # 6| v6_7(void) = ReturnVoid : #-----| Goto -> Block 1 @@ -37221,6 +37246,18 @@ try_except.cpp: # 21| r21_2(int) = Constant[0] : # 21| v21_3(void) = Call[ProbeFunction] : func:r21_1, 0:r21_2 # 21| mu21_4(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 3 +#-----| SEH Exception -> Block 4 + +# 18| Block 1 +# 18| v18_4(void) = AliasedUse : ~m? +# 18| v18_5(void) = ExitFunction : + +# 18| Block 2 +# 18| v18_6(void) = Unwind : +#-----| Goto -> Block 1 + +# 22| Block 3 # 22| r22_1(glval) = VariableAddress[y] : # 22| r22_2(int) = Load[y] : &:r22_1, ~m? # 22| r22_3(glval) = VariableAddress[x] : @@ -37229,21 +37266,20 @@ try_except.cpp: # 23| r23_2(int) = Constant[0] : # 23| v23_3(void) = Call[ProbeFunction] : func:r23_1, 0:r23_2 # 23| mu23_4(unknown) = ^CallSideEffect : ~m? -# 26| r26_1(glval) = FunctionAddress[sink] : -# 26| r26_2(glval) = VariableAddress[x] : -# 26| r26_3(int) = Load[x] : &:r26_2, ~m? -# 26| v26_4(void) = Call[sink] : func:r26_1, 0:r26_3 -# 26| mu26_5(unknown) = ^CallSideEffect : ~m? -# 28| v28_1(void) = NoOp : -# 18| v18_4(void) = ReturnVoid : -#-----| Goto -> Block 1 +#-----| SEH Exception -> Block 4 -# 18| Block 1 -# 18| v18_5(void) = AliasedUse : ~m? -# 18| v18_6(void) = ExitFunction : +# 26| Block 4 +# 26| r26_1(glval) = FunctionAddress[sink] : +# 26| r26_2(glval) = VariableAddress[x] : +# 26| r26_3(int) = Load[x] : &:r26_2, ~m? +# 26| v26_4(void) = Call[sink] : func:r26_1, 0:r26_3 +# 26| mu26_5(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 5 +#-----| SEH Exception -> Block 2 -# 18| Block 2 -# 18| v18_7(void) = Unwind : +# 28| Block 5 +# 28| v28_1(void) = NoOp : +# 18| v18_7(void) = ReturnVoid : #-----| Goto -> Block 1 # 32| void h_cpp(int) @@ -37277,6 +37313,7 @@ try_except.cpp: # 36| v36_2(void) = Call[AfxThrowMemoryException] : func:r36_1 # 36| mu36_3(unknown) = ^CallSideEffect : ~m? #-----| Goto -> Block 8 +#-----| SEH Exception -> Block 6 # 39| Block 4 # 39| r39_1(int) = Constant[0] : @@ -37306,6 +37343,7 @@ try_except.cpp: # 40| v40_4(void) = Call[sink] : func:r40_1, 0:r40_3 # 40| mu40_5(unknown) = ^CallSideEffect : ~m? #-----| Goto -> Block 8 +#-----| SEH Exception -> Block 2 # 42| Block 8 # 42| v42_1(void) = NoOp : @@ -37373,6 +37411,7 @@ try_except.cpp: # 52| v52_4(void) = Call[sink] : func:r52_1, 0:r52_3 # 52| mu52_5(unknown) = ^CallSideEffect : ~m? #-----| Goto -> Block 8 +#-----| SEH Exception -> Block 2 # 54| Block 8 # 54| v54_1(void) = NoOp : diff --git a/cpp/ql/test/library-tests/ir/ir/try_except.cpp b/cpp/ql/test/library-tests/ir/ir/try_except.cpp index 9bf297263b75..0874b557bd93 100644 --- a/cpp/ql/test/library-tests/ir/ir/try_except.cpp +++ b/cpp/ql/test/library-tests/ir/ir/try_except.cpp @@ -45,7 +45,7 @@ void throw_cpp(int b) { int x = 0; __try { if (b) { - throw 1; + throw 1; // invalid use of throw in Seh exception } } __except (1) { diff --git a/cpp/ql/test/library-tests/syntax-zoo/ms_try_mix.cpp b/cpp/ql/test/library-tests/syntax-zoo/ms_try_mix.cpp index 28fa24d4c920..b7de011dc141 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/ms_try_mix.cpp +++ b/cpp/ql/test/library-tests/syntax-zoo/ms_try_mix.cpp @@ -15,7 +15,7 @@ void ms_except_mix(int b1) { __try { C c102(102); if (b1) { - throw 1; + throw 1; // invalid use of throw in Seh exception } C c103(103); } @@ -32,7 +32,7 @@ void ms_finally_mix(int b2) { __try { C c106(106); if (b2) { - throw 2; + throw 2; // invalid use of throw in Seh exception } C c107(107); } @@ -50,7 +50,7 @@ void ms_empty_finally_at_end() { C c201(201); __try { - throw 3; + throw 3; // invalid use of throw in Seh exception } __finally { }