diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll index 617fa9ffd898..cb4f75c1501a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll @@ -72,7 +72,19 @@ newtype TInstructionTag = AsmInputTag(int elementIndex) { exists(AsmStmt asm | exists(asm.getChild(elementIndex))) } or ThisAddressTag() or ThisLoadTag() or - StructuredBindingAccessTag() + StructuredBindingAccessTag() or + // The next three cases handle generation of the constants -1, 0 and 1 for __except handling. + TryExceptGenerateNegativeOne() or + TryExceptGenerateZero() or + TryExceptGenerateOne() or + // The next three cases handle generation of comparisons for __except handling. + TryExceptCompareNegativeOne() or + TryExceptCompareZero() or + TryExceptCompareOne() or + // The next three cases handle generation of branching for __except handling. + TryExceptCompareNegativeOneBranch() or + TryExceptCompareZeroBranch() or + TryExceptCompareOneBranch() class InstructionTag extends TInstructionTag { final string toString() { result = "Tag" } @@ -224,4 +236,22 @@ string getInstructionTagId(TInstructionTag tag) { tag = ThisLoadTag() and result = "ThisLoad" or tag = StructuredBindingAccessTag() and result = "StructuredBindingAccess" + or + tag = TryExceptCompareNegativeOne() and result = "TryExceptCompareNegativeOne" + or + tag = TryExceptCompareZero() and result = "TryExceptCompareZero" + or + tag = TryExceptCompareOne() and result = "TryExceptCompareOne" + or + tag = TryExceptGenerateNegativeOne() and result = "TryExceptGenerateNegativeOne" + or + tag = TryExceptGenerateZero() and result = "TryExceptGenerateNegativeOne" + or + tag = TryExceptGenerateOne() and result = "TryExceptGenerateOne" + or + tag = TryExceptCompareNegativeOneBranch() and result = "TryExceptCompareNegativeOneBranch" + or + tag = TryExceptCompareZeroBranch() and result = "TryExceptCompareZeroBranch" + or + tag = TryExceptCompareOneBranch() and result = "TryExceptCompareOneBranch" } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index 3a350ea0e1a8..81c04c736b49 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -675,6 +675,7 @@ newtype TTranslatedElement = } or // A statement TTranslatedStmt(Stmt stmt) { translateStmt(stmt) } or + TTranslatedMicrosoftTryExceptHandler(MicrosoftTryExceptStmt stmt) or // A function TTranslatedFunction(Function func) { translateFunction(func) } or // A constructor init list diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll index ee14c9847bc8..9140620cddcb 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll @@ -13,6 +13,222 @@ private import TranslatedInitialization TranslatedStmt getTranslatedStmt(Stmt stmt) { result.getAst() = stmt } +TranslatedMicrosoftTryExceptHandler getTranslatedMicrosoftTryExceptHandler( + MicrosoftTryExceptStmt tryExcept +) { + result.getAst() = tryExcept.getExcept() +} + +class TranslatedMicrosoftTryExceptHandler extends TranslatedElement, + TTranslatedMicrosoftTryExceptHandler { + MicrosoftTryExceptStmt tryExcept; + + TranslatedMicrosoftTryExceptHandler() { this = TTranslatedMicrosoftTryExceptHandler(tryExcept) } + + final override string toString() { result = tryExcept.toString() } + + final override Locatable getAst() { result = tryExcept.getExcept() } + + override Instruction getFirstInstruction() { result = this.getChild(0).getFirstInstruction() } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { + // t1 = -1 + tag = TryExceptGenerateNegativeOne() and + opcode instanceof Opcode::Constant and + resultType = getIntType() + or + // t2 = cmp t1, condition + tag = TryExceptCompareNegativeOne() and + opcode instanceof Opcode::CompareEQ and + resultType = getBoolType() + or + // if t2 goto ... else goto ... + tag = TryExceptCompareNegativeOneBranch() and + opcode instanceof Opcode::ConditionalBranch and + resultType = getVoidType() + or + // t1 = 0 + tag = TryExceptGenerateZero() and + opcode instanceof Opcode::Constant and + resultType = getIntType() + or + // t2 = cmp t1, condition + tag = TryExceptCompareZero() and + opcode instanceof Opcode::CompareEQ and + resultType = getBoolType() + or + // if t2 goto ... else goto ... + tag = TryExceptCompareZeroBranch() and + opcode instanceof Opcode::ConditionalBranch and + resultType = getVoidType() + or + // t1 = 1 + tag = TryExceptGenerateOne() and + opcode instanceof Opcode::Constant and + resultType = getIntType() + or + // t2 = cmp t1, condition + tag = TryExceptCompareOne() and + opcode instanceof Opcode::CompareEQ and + resultType = getBoolType() + or + // if t2 goto ... else goto ... + tag = TryExceptCompareOneBranch() and + opcode instanceof Opcode::ConditionalBranch and + resultType = getVoidType() + or + // unwind stack + tag = UnwindTag() and + opcode instanceof Opcode::Unwind and + resultType = getVoidType() + } + + final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { + tag = TryExceptCompareNegativeOne() and + ( + operandTag instanceof LeftOperandTag and + result = this.getTranslatedCondition().getResult() + or + operandTag instanceof RightOperandTag and + result = this.getInstruction(TryExceptGenerateNegativeOne()) + ) + or + tag = TryExceptCompareNegativeOneBranch() and + operandTag instanceof ConditionOperandTag and + result = this.getInstruction(TryExceptCompareNegativeOne()) + or + tag = TryExceptCompareZero() and + ( + operandTag instanceof LeftOperandTag and + result = this.getTranslatedCondition().getResult() + or + operandTag instanceof RightOperandTag and + result = this.getInstruction(TryExceptGenerateZero()) + ) + or + tag = TryExceptCompareZeroBranch() and + operandTag instanceof ConditionOperandTag and + result = this.getInstruction(TryExceptCompareZero()) + or + tag = TryExceptCompareOne() and + ( + operandTag instanceof LeftOperandTag and + result = this.getTranslatedCondition().getResult() + or + operandTag instanceof RightOperandTag and + result = this.getInstruction(TryExceptGenerateOne()) + ) + or + tag = TryExceptCompareOneBranch() and + operandTag instanceof ConditionOperandTag and + result = this.getInstruction(TryExceptCompareOne()) + } + + override string getInstructionConstantValue(InstructionTag tag) { + tag = TryExceptGenerateNegativeOne() and + result = "-1" + or + tag = TryExceptGenerateZero() and + result = "0" + or + tag = TryExceptGenerateOne() and + result = "1" + } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + // Generate -1 -> Compare condition + tag = TryExceptGenerateNegativeOne() and + kind instanceof GotoEdge and + result = this.getInstruction(TryExceptCompareNegativeOne()) + or + // Compare condition -> Branch + tag = TryExceptCompareNegativeOne() and + kind instanceof GotoEdge and + result = this.getInstruction(TryExceptCompareNegativeOneBranch()) + or + // Branch -> Unwind or Generate 0 + tag = TryExceptCompareNegativeOneBranch() and + ( + kind instanceof TrueEdge and + // TODO: This is not really correct. The semantics of `EXCEPTION_CONTINUE_EXECUTION` is that + // we should continue execution at the point where the exception occurred. But we don't have + // any instruction to model this behavior. + result = this.getInstruction(UnwindTag()) + or + kind instanceof FalseEdge and + result = this.getInstruction(TryExceptGenerateZero()) + ) + or + // Generate 0 -> Compare condition + tag = TryExceptGenerateZero() and + kind instanceof GotoEdge and + result = this.getInstruction(TryExceptCompareZero()) + or + // Compare condition -> Branch + tag = TryExceptCompareZero() and + kind instanceof GotoEdge and + result = this.getInstruction(TryExceptCompareZeroBranch()) + or + // Branch -> Unwind or Generate 1 + tag = TryExceptCompareZeroBranch() and + ( + kind instanceof TrueEdge and + result = this.getInstruction(UnwindTag()) + or + kind instanceof FalseEdge and + result = this.getInstruction(TryExceptGenerateOne()) + ) + or + // Generate 1 -> Compare condition + tag = TryExceptGenerateOne() and + kind instanceof GotoEdge and + result = this.getInstruction(TryExceptCompareOne()) + or + // Compare condition -> Branch + tag = TryExceptCompareOne() and + kind instanceof GotoEdge and + result = this.getInstruction(TryExceptCompareOneBranch()) + or + // Branch -> Handler (the condition value is always 0, -1 or 1, and we've checked for 0 or -1 already.) + tag = TryExceptCompareOneBranch() and + ( + kind instanceof TrueEdge and + result = this.getTranslatedHandler().getFirstInstruction() + ) + or + // Unwind -> Parent + tag = UnwindTag() and + kind instanceof GotoEdge and + result = this.getParent().getChildSuccessor(this) + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = this.getTranslatedCondition() and + result = this.getInstruction(TryExceptGenerateNegativeOne()) + or + child = this.getTranslatedHandler() and + result = this.getParent().getChildSuccessor(this) + } + + private TranslatedExpr getTranslatedCondition() { + result = getTranslatedExpr(tryExcept.getCondition()) + } + + private TranslatedStmt getTranslatedHandler() { + result = getTranslatedStmt(tryExcept.getExcept()) + } + + override TranslatedElement getChild(int id) { + id = 0 and + result = this.getTranslatedCondition() + or + id = 1 and + result = this.getTranslatedHandler() + } + + final override Function getFunction() { result = tryExcept.getEnclosingFunction() } +} + abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt { Stmt stmt; @@ -249,15 +465,57 @@ class TranslatedUnreachableReturnStmt extends TranslatedReturnStmt { } /** - * The IR translation of a C++ `try` statement. + * A C/C++ `try` statement, or a `__try __except` or `__try __finally` statement. + */ +private class TryOrMicrosoftTryStmt extends Stmt { + TryOrMicrosoftTryStmt() { + this instanceof TryStmt or + this instanceof MicrosoftTryStmt + } + + /** Gets the number of `catch block`s of this statement. */ + int getNumberOfCatchClauses() { + result = this.(TryStmt).getNumberOfCatchClauses() + or + this instanceof MicrosoftTryExceptStmt and + result = 1 + or + this instanceof MicrosoftTryFinallyStmt and + result = 0 + } + + /** Gets the `body` statement of this statement. */ + Stmt getStmt() { + result = this.(TryStmt).getStmt() + or + result = this.(MicrosoftTryStmt).getStmt() + } + + /** Gets the `i`th translated handler of this statement. */ + TranslatedElement getTranslatedHandler(int index) { + result = getTranslatedStmt(this.(TryStmt).getChild(index + 1)) + or + index = 0 and + result = getTranslatedMicrosoftTryExceptHandler(this) + } + + /** Gets the `finally` statement (usually a BlockStmt), if any. */ + Stmt getFinally() { result = this.(MicrosoftTryFinallyStmt).getFinally() } +} + +/** + * The IR translation of a C++ `try` (or a `__try __except` or `__try __finally`) statement. */ class TranslatedTryStmt extends TranslatedStmt { - override TryStmt stmt; + override TryOrMicrosoftTryStmt stmt; override TranslatedElement getChild(int id) { id = 0 and result = getBody() or result = getHandler(id - 1) + or + id = stmt.getNumberOfCatchClauses() + 1 and + result = this.getFinally() } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { @@ -269,8 +527,20 @@ class TranslatedTryStmt extends TranslatedStmt { override Instruction getFirstInstruction() { result = getBody().getFirstInstruction() } override Instruction getChildSuccessor(TranslatedElement child) { - // All children go to the successor of the `try`. - child = getAChild() and result = getParent().getChildSuccessor(this) + // All non-finally children go to the successor of the `try` if + // there is no finally block, but if there is a finally block + // then we go to that one. + child = [this.getBody(), this.getHandler(_)] and + ( + not exists(this.getFinally()) and + result = this.getParent().getChildSuccessor(this) + or + result = this.getFinally().getFirstInstruction() + ) + or + // And after the finally block we go to the successor of the `try`. + child = this.getFinally() and + result = this.getParent().getChildSuccessor(this) } final Instruction getNextHandler(TranslatedHandler handler) { @@ -290,9 +560,9 @@ class TranslatedTryStmt extends TranslatedStmt { result = getHandler(0).getFirstInstruction() } - private TranslatedHandler getHandler(int index) { - result = getTranslatedStmt(stmt.getChild(index + 1)) - } + private TranslatedElement getHandler(int index) { result = stmt.getTranslatedHandler(index) } + + private TranslatedStmt getFinally() { result = getTranslatedStmt(stmt.getFinally()) } private TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) } } diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 4153f37c0243..c86e4dc5b8fd 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -14822,3 +14822,348 @@ struct_init.cpp: # 41| Type = [PointerType] Info * # 41| ValueCategory = prvalue # 42| getStmt(2): [ReturnStmt] return ... +try_except.c: +# 3| [TopLevelFunction] void ProbeFunction() +# 3| : +# 4| [TopLevelFunction] void sink() +# 4| : +# 6| [TopLevelFunction] void f() +# 6| : +# 6| getEntryPoint(): [BlockStmt] { ... } +# 7| getStmt(0): [DeclStmt] declaration +# 7| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x +# 7| Type = [IntType] int +# 7| getDeclarationEntry(1): [VariableDeclarationEntry] definition of y +# 7| Type = [IntType] int +# 7| getVariable().getInitializer(): [Initializer] initializer for y +# 7| getExpr(): [Literal] 0 +# 7| Type = [IntType] int +# 7| Value = [Literal] 0 +# 7| ValueCategory = prvalue +# 8| getStmt(1): [MicrosoftTryExceptStmt] __try { ... } __except( ... ) { ... } +# 8| getStmt(): [BlockStmt] { ... } +# 9| getStmt(0): [ExprStmt] ExprStmt +# 9| getExpr(): [FunctionCall] call to ProbeFunction +# 9| Type = [VoidType] void +# 9| ValueCategory = prvalue +# 9| getArgument(0): [Literal] 0 +# 9| Type = [IntType] int +# 9| Value = [Literal] 0 +# 9| ValueCategory = prvalue +# 10| getStmt(1): [ExprStmt] ExprStmt +# 10| getExpr(): [AssignExpr] ... = ... +# 10| Type = [IntType] int +# 10| ValueCategory = prvalue +# 10| getLValue(): [VariableAccess] x +# 10| Type = [IntType] int +# 10| ValueCategory = lvalue +# 10| getRValue(): [VariableAccess] y +# 10| Type = [IntType] int +# 10| ValueCategory = prvalue(load) +# 11| getStmt(2): [ExprStmt] ExprStmt +# 11| getExpr(): [FunctionCall] call to ProbeFunction +# 11| Type = [VoidType] void +# 11| ValueCategory = prvalue +# 11| getArgument(0): [Literal] 0 +# 11| Type = [IntType] int +# 11| Value = [Literal] 0 +# 11| ValueCategory = prvalue +# 13| getCondition(): [Literal] 0 +# 13| Type = [IntType] int +# 13| Value = [Literal] 0 +# 13| ValueCategory = prvalue +# 13| getExcept(): [BlockStmt] { ... } +# 14| getStmt(0): [ExprStmt] ExprStmt +# 14| getExpr(): [FunctionCall] call to sink +# 14| Type = [VoidType] void +# 14| ValueCategory = prvalue +# 14| getArgument(0): [VariableAccess] x +# 14| Type = [IntType] int +# 14| ValueCategory = prvalue(load) +# 16| getStmt(2): [ReturnStmt] return ... +# 18| [TopLevelFunction] void g() +# 18| : +# 18| getEntryPoint(): [BlockStmt] { ... } +# 19| getStmt(0): [DeclStmt] declaration +# 19| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x +# 19| Type = [IntType] int +# 19| getDeclarationEntry(1): [VariableDeclarationEntry] definition of y +# 19| Type = [IntType] int +# 19| getVariable().getInitializer(): [Initializer] initializer for y +# 19| getExpr(): [Literal] 0 +# 19| Type = [IntType] int +# 19| Value = [Literal] 0 +# 19| ValueCategory = prvalue +# 20| getStmt(1): [MicrosoftTryFinallyStmt] __try { ... } __finally { ... } +# 20| getStmt(): [BlockStmt] { ... } +# 21| getStmt(0): [ExprStmt] ExprStmt +# 21| getExpr(): [FunctionCall] call to ProbeFunction +# 21| Type = [VoidType] void +# 21| ValueCategory = prvalue +# 21| getArgument(0): [Literal] 0 +# 21| Type = [IntType] int +# 21| Value = [Literal] 0 +# 21| ValueCategory = prvalue +# 22| getStmt(1): [ExprStmt] ExprStmt +# 22| getExpr(): [AssignExpr] ... = ... +# 22| Type = [IntType] int +# 22| ValueCategory = prvalue +# 22| getLValue(): [VariableAccess] x +# 22| Type = [IntType] int +# 22| ValueCategory = lvalue +# 22| getRValue(): [VariableAccess] y +# 22| Type = [IntType] int +# 22| ValueCategory = prvalue(load) +# 23| getStmt(2): [ExprStmt] ExprStmt +# 23| getExpr(): [FunctionCall] call to ProbeFunction +# 23| Type = [VoidType] void +# 23| ValueCategory = prvalue +# 23| getArgument(0): [Literal] 0 +# 23| Type = [IntType] int +# 23| Value = [Literal] 0 +# 23| ValueCategory = prvalue +# 25| getFinally(): [BlockStmt] { ... } +# 26| getStmt(0): [ExprStmt] ExprStmt +# 26| getExpr(): [FunctionCall] call to sink +# 26| Type = [VoidType] void +# 26| ValueCategory = prvalue +# 26| getArgument(0): [VariableAccess] x +# 26| Type = [IntType] int +# 26| ValueCategory = prvalue(load) +# 28| getStmt(2): [ReturnStmt] return ... +# 30| [TopLevelFunction] void AfxThrowMemoryException() +# 30| : +# 32| [TopLevelFunction] void h(int) +# 32| : +# 32| getParameter(0): [Parameter] b +# 32| Type = [IntType] int +# 32| getEntryPoint(): [BlockStmt] { ... } +# 33| getStmt(0): [DeclStmt] declaration +# 33| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x +# 33| Type = [IntType] int +# 33| getVariable().getInitializer(): [Initializer] initializer for x +# 33| getExpr(): [Literal] 0 +# 33| Type = [IntType] int +# 33| Value = [Literal] 0 +# 33| ValueCategory = prvalue +# 34| getStmt(1): [MicrosoftTryExceptStmt] __try { ... } __except( ... ) { ... } +# 34| getStmt(): [BlockStmt] { ... } +# 35| getStmt(0): [IfStmt] if (...) ... +# 35| getCondition(): [VariableAccess] b +# 35| Type = [IntType] int +# 35| ValueCategory = prvalue(load) +# 35| getThen(): [BlockStmt] { ... } +# 36| getStmt(0): [ExprStmt] ExprStmt +# 36| getExpr(): [FunctionCall] call to AfxThrowMemoryException +# 36| Type = [VoidType] void +# 36| ValueCategory = prvalue +# 39| getCondition(): [Literal] 1 +# 39| Type = [IntType] int +# 39| Value = [Literal] 1 +# 39| ValueCategory = prvalue +# 39| getExcept(): [BlockStmt] { ... } +# 40| getStmt(0): [ExprStmt] ExprStmt +# 40| getExpr(): [FunctionCall] call to sink +# 40| Type = [VoidType] void +# 40| ValueCategory = prvalue +# 40| getArgument(0): [VariableAccess] x +# 40| Type = [IntType] int +# 40| ValueCategory = prvalue(load) +# 42| getStmt(2): [ReturnStmt] return ... +try_except.cpp: +# 3| [TopLevelFunction] void ProbeFunction() +# 3| : +# 4| [TopLevelFunction] void sink() +# 4| : +# 6| [TopLevelFunction] void f_cpp() +# 6| : +# 6| getEntryPoint(): [BlockStmt] { ... } +# 7| getStmt(0): [DeclStmt] declaration +# 7| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x +# 7| Type = [IntType] int +# 7| getDeclarationEntry(1): [VariableDeclarationEntry] definition of y +# 7| Type = [IntType] int +# 7| getVariable().getInitializer(): [Initializer] initializer for y +# 7| getExpr(): [Literal] 0 +# 7| Type = [IntType] int +# 7| Value = [Literal] 0 +# 7| ValueCategory = prvalue +# 8| getStmt(1): [MicrosoftTryExceptStmt] __try { ... } __except( ... ) { ... } +# 8| getStmt(): [BlockStmt] { ... } +# 9| getStmt(0): [ExprStmt] ExprStmt +# 9| getExpr(): [FunctionCall] call to ProbeFunction +# 9| Type = [VoidType] void +# 9| ValueCategory = prvalue +# 9| getArgument(0): [Literal] 0 +# 9| Type = [IntType] int +# 9| Value = [Literal] 0 +# 9| ValueCategory = prvalue +# 10| getStmt(1): [ExprStmt] ExprStmt +# 10| getExpr(): [AssignExpr] ... = ... +# 10| Type = [IntType] int +# 10| ValueCategory = lvalue +# 10| getLValue(): [VariableAccess] x +# 10| Type = [IntType] int +# 10| ValueCategory = lvalue +# 10| getRValue(): [VariableAccess] y +# 10| Type = [IntType] int +# 10| ValueCategory = prvalue(load) +# 11| getStmt(2): [ExprStmt] ExprStmt +# 11| getExpr(): [FunctionCall] call to ProbeFunction +# 11| Type = [VoidType] void +# 11| ValueCategory = prvalue +# 11| getArgument(0): [Literal] 0 +# 11| Type = [IntType] int +# 11| Value = [Literal] 0 +# 11| ValueCategory = prvalue +# 13| getCondition(): [Literal] 0 +# 13| Type = [IntType] int +# 13| Value = [Literal] 0 +# 13| ValueCategory = prvalue +# 13| getExcept(): [BlockStmt] { ... } +# 14| getStmt(0): [ExprStmt] ExprStmt +# 14| getExpr(): [FunctionCall] call to sink +# 14| Type = [VoidType] void +# 14| ValueCategory = prvalue +# 14| getArgument(0): [VariableAccess] x +# 14| Type = [IntType] int +# 14| ValueCategory = prvalue(load) +# 16| getStmt(2): [ReturnStmt] return ... +# 18| [TopLevelFunction] void g_cpp() +# 18| : +# 18| getEntryPoint(): [BlockStmt] { ... } +# 19| getStmt(0): [DeclStmt] declaration +# 19| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x +# 19| Type = [IntType] int +# 19| getDeclarationEntry(1): [VariableDeclarationEntry] definition of y +# 19| Type = [IntType] int +# 19| getVariable().getInitializer(): [Initializer] initializer for y +# 19| getExpr(): [Literal] 0 +# 19| Type = [IntType] int +# 19| Value = [Literal] 0 +# 19| ValueCategory = prvalue +# 20| getStmt(1): [MicrosoftTryFinallyStmt] __try { ... } __finally { ... } +# 20| getStmt(): [BlockStmt] { ... } +# 21| getStmt(0): [ExprStmt] ExprStmt +# 21| getExpr(): [FunctionCall] call to ProbeFunction +# 21| Type = [VoidType] void +# 21| ValueCategory = prvalue +# 21| getArgument(0): [Literal] 0 +# 21| Type = [IntType] int +# 21| Value = [Literal] 0 +# 21| ValueCategory = prvalue +# 22| getStmt(1): [ExprStmt] ExprStmt +# 22| getExpr(): [AssignExpr] ... = ... +# 22| Type = [IntType] int +# 22| ValueCategory = lvalue +# 22| getLValue(): [VariableAccess] x +# 22| Type = [IntType] int +# 22| ValueCategory = lvalue +# 22| getRValue(): [VariableAccess] y +# 22| Type = [IntType] int +# 22| ValueCategory = prvalue(load) +# 23| getStmt(2): [ExprStmt] ExprStmt +# 23| getExpr(): [FunctionCall] call to ProbeFunction +# 23| Type = [VoidType] void +# 23| ValueCategory = prvalue +# 23| getArgument(0): [Literal] 0 +# 23| Type = [IntType] int +# 23| Value = [Literal] 0 +# 23| ValueCategory = prvalue +# 25| getFinally(): [BlockStmt] { ... } +# 26| getStmt(0): [ExprStmt] ExprStmt +# 26| getExpr(): [FunctionCall] call to sink +# 26| Type = [VoidType] void +# 26| ValueCategory = prvalue +# 26| getArgument(0): [VariableAccess] x +# 26| Type = [IntType] int +# 26| ValueCategory = prvalue(load) +# 28| getStmt(2): [ReturnStmt] return ... +# 30| [TopLevelFunction] void AfxThrowMemoryException() +# 30| : +# 32| [TopLevelFunction] void h_cpp(int) +# 32| : +# 32| getParameter(0): [Parameter] b +# 32| Type = [IntType] int +# 32| getEntryPoint(): [BlockStmt] { ... } +# 33| getStmt(0): [DeclStmt] declaration +# 33| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x +# 33| Type = [IntType] int +# 33| getVariable().getInitializer(): [Initializer] initializer for x +# 33| getExpr(): [Literal] 0 +# 33| Type = [IntType] int +# 33| Value = [Literal] 0 +# 33| ValueCategory = prvalue +# 34| getStmt(1): [MicrosoftTryExceptStmt] __try { ... } __except( ... ) { ... } +# 34| getStmt(): [BlockStmt] { ... } +# 35| getStmt(0): [IfStmt] if (...) ... +# 35| getCondition(): [VariableAccess] b +# 35| Type = [IntType] int +# 35| ValueCategory = prvalue(load) +# 35| getThen(): [BlockStmt] { ... } +# 36| getStmt(0): [ExprStmt] ExprStmt +# 36| getExpr(): [FunctionCall] call to AfxThrowMemoryException +# 36| Type = [VoidType] void +# 36| ValueCategory = prvalue +# 35| getCondition().getFullyConverted(): [CStyleCast] (bool)... +# 35| Conversion = [BoolConversion] conversion to bool +# 35| Type = [BoolType] bool +# 35| ValueCategory = prvalue +# 39| getCondition(): [Literal] 1 +# 39| Type = [IntType] int +# 39| Value = [Literal] 1 +# 39| ValueCategory = prvalue +# 39| getExcept(): [BlockStmt] { ... } +# 40| getStmt(0): [ExprStmt] ExprStmt +# 40| getExpr(): [FunctionCall] call to sink +# 40| Type = [VoidType] void +# 40| ValueCategory = prvalue +# 40| getArgument(0): [VariableAccess] x +# 40| Type = [IntType] int +# 40| ValueCategory = prvalue(load) +# 42| getStmt(2): [ReturnStmt] return ... +# 44| [TopLevelFunction] void throw_cpp(int) +# 44| : +# 44| getParameter(0): [Parameter] b +# 44| Type = [IntType] int +# 44| getEntryPoint(): [BlockStmt] { ... } +# 45| getStmt(0): [DeclStmt] declaration +# 45| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x +# 45| Type = [IntType] int +# 45| getVariable().getInitializer(): [Initializer] initializer for x +# 45| getExpr(): [Literal] 0 +# 45| Type = [IntType] int +# 45| Value = [Literal] 0 +# 45| ValueCategory = prvalue +# 46| getStmt(1): [MicrosoftTryExceptStmt] __try { ... } __except( ... ) { ... } +# 46| getStmt(): [BlockStmt] { ... } +# 47| getStmt(0): [IfStmt] if (...) ... +# 47| getCondition(): [VariableAccess] b +# 47| Type = [IntType] int +# 47| ValueCategory = prvalue(load) +# 47| getThen(): [BlockStmt] { ... } +# 48| getStmt(0): [ExprStmt] ExprStmt +# 48| getExpr(): [ThrowExpr] throw ... +# 48| Type = [IntType] int +# 48| ValueCategory = prvalue +# 48| getExpr(): [Literal] 1 +# 48| Type = [IntType] int +# 48| Value = [Literal] 1 +# 48| ValueCategory = prvalue +# 47| getCondition().getFullyConverted(): [CStyleCast] (bool)... +# 47| Conversion = [BoolConversion] conversion to bool +# 47| Type = [BoolType] bool +# 47| ValueCategory = prvalue +# 51| getCondition(): [Literal] 1 +# 51| Type = [IntType] int +# 51| Value = [Literal] 1 +# 51| ValueCategory = prvalue +# 51| getExcept(): [BlockStmt] { ... } +# 52| getStmt(0): [ExprStmt] ExprStmt +# 52| getExpr(): [FunctionCall] call to sink +# 52| Type = [VoidType] void +# 52| ValueCategory = prvalue +# 52| getArgument(0): [VariableAccess] x +# 52| Type = [IntType] int +# 52| ValueCategory = prvalue(load) +# 54| getStmt(2): [ReturnStmt] return ... diff --git a/cpp/ql/test/library-tests/ir/ir/operand_locations.expected b/cpp/ql/test/library-tests/ir/ir/operand_locations.expected index eb63841daba9..3bbbd4f099a5 100644 --- a/cpp/ql/test/library-tests/ir/ir/operand_locations.expected +++ b/cpp/ql/test/library-tests/ir/ir/operand_locations.expected @@ -9140,3 +9140,162 @@ | struct_init.cpp:41:21:41:32 | ChiTotal | total:m41_7 | | struct_init.cpp:41:21:41:32 | SideEffect | ~m41_7 | | struct_init.cpp:41:21:41:32 | Unary | r41_3 | +| try_except.c:6:6:6:6 | ChiPartial | partial:m6_3 | +| try_except.c:6:6:6:6 | ChiTotal | total:m6_2 | +| try_except.c:6:6:6:6 | SideEffect | ~m11_5 | +| try_except.c:7:7:7:7 | Address | &:r7_1 | +| try_except.c:7:10:7:10 | Address | &:r7_3 | +| try_except.c:7:13:7:14 | StoreValue | r7_4 | +| try_except.c:9:5:9:17 | CallTarget | func:r9_1 | +| try_except.c:9:5:9:17 | ChiPartial | partial:m9_4 | +| try_except.c:9:5:9:17 | ChiTotal | total:m6_4 | +| try_except.c:9:5:9:17 | SideEffect | ~m6_4 | +| try_except.c:9:19:9:19 | Arg(0) | 0:r9_2 | +| try_except.c:10:5:10:5 | Address | &:r10_3 | +| try_except.c:10:9:10:9 | Address | &:r10_1 | +| try_except.c:10:9:10:9 | Load | m7_5 | +| try_except.c:10:9:10:9 | StoreValue | r10_2 | +| try_except.c:11:5:11:17 | CallTarget | func:r11_1 | +| try_except.c:11:5:11:17 | ChiPartial | partial:m11_4 | +| try_except.c:11:5:11:17 | ChiTotal | total:m9_5 | +| try_except.c:11:5:11:17 | SideEffect | ~m9_5 | +| try_except.c:11:19:11:19 | Arg(0) | 0:r11_2 | +| try_except.c:18:6:18:6 | ChiPartial | partial:m18_3 | +| try_except.c:18:6:18:6 | ChiTotal | total:m18_2 | +| try_except.c:18:6:18:6 | SideEffect | ~m26_6 | +| try_except.c:19:7:19:7 | Address | &:r19_1 | +| try_except.c:19:10:19:10 | Address | &:r19_3 | +| try_except.c:19:13:19:14 | StoreValue | r19_4 | +| try_except.c:21:5:21:17 | CallTarget | func:r21_1 | +| try_except.c:21:5:21:17 | ChiPartial | partial:m21_4 | +| try_except.c:21:5:21:17 | ChiTotal | total:m18_4 | +| try_except.c:21:5:21:17 | SideEffect | ~m18_4 | +| try_except.c:21:19:21:19 | Arg(0) | 0:r21_2 | +| try_except.c:22:5:22:5 | Address | &:r22_3 | +| try_except.c:22:9:22:9 | Address | &:r22_1 | +| try_except.c:22:9:22:9 | Load | m19_5 | +| try_except.c:22:9:22:9 | StoreValue | r22_2 | +| try_except.c:23:5:23:17 | CallTarget | func:r23_1 | +| try_except.c:23:5:23:17 | ChiPartial | partial:m23_4 | +| try_except.c:23:5:23:17 | ChiTotal | total:m21_5 | +| try_except.c:23:5:23:17 | SideEffect | ~m21_5 | +| try_except.c:23:19:23:19 | Arg(0) | 0:r23_2 | +| try_except.c:26:5:26:8 | CallTarget | func:r26_1 | +| try_except.c:26:5:26:8 | ChiPartial | partial:m26_5 | +| try_except.c:26:5:26:8 | ChiTotal | total:m23_5 | +| try_except.c:26:5:26:8 | SideEffect | ~m23_5 | +| try_except.c:26:10:26:10 | Address | &:r26_2 | +| try_except.c:26:10:26:10 | Arg(0) | 0:r26_3 | +| try_except.c:26:10:26:10 | Load | m22_4 | +| try_except.c:32:6:32:6 | ChiPartial | partial:m32_3 | +| try_except.c:32:6:32:6 | ChiTotal | total:m32_2 | +| try_except.c:32:6:32:6 | SideEffect | ~m42_1 | +| try_except.c:32:12:32:12 | Address | &:r32_5 | +| try_except.c:33:7:33:7 | Address | &:r33_1 | +| try_except.c:33:10:33:11 | StoreValue | r33_2 | +| try_except.c:35:13:35:13 | Address | &:r35_1 | +| try_except.c:35:13:35:13 | Condition | r35_2 | +| try_except.c:35:13:35:13 | Load | m32_6 | +| try_except.c:36:13:36:35 | CallTarget | func:r36_1 | +| try_except.c:36:13:36:35 | ChiPartial | partial:m36_3 | +| try_except.c:36:13:36:35 | ChiTotal | total:m32_4 | +| try_except.c:36:13:36:35 | SideEffect | ~m32_4 | +| try_except.c:42:1:42:1 | Phi | from 0:~m32_4 | +| try_except.c:42:1:42:1 | Phi | from 1:~m36_4 | +| try_except.cpp:6:6:6:10 | ChiPartial | partial:m6_3 | +| try_except.cpp:6:6:6:10 | ChiTotal | total:m6_2 | +| try_except.cpp:6:6:6:10 | SideEffect | ~m11_5 | +| try_except.cpp:7:7:7:7 | Address | &:r7_1 | +| try_except.cpp:7:10:7:10 | Address | &:r7_3 | +| try_except.cpp:7:13:7:14 | StoreValue | r7_4 | +| try_except.cpp:9:5:9:17 | CallTarget | func:r9_1 | +| try_except.cpp:9:5:9:17 | ChiPartial | partial:m9_4 | +| try_except.cpp:9:5:9:17 | ChiTotal | total:m6_4 | +| try_except.cpp:9:5:9:17 | SideEffect | ~m6_4 | +| try_except.cpp:9:19:9:19 | Arg(0) | 0:r9_2 | +| try_except.cpp:10:5:10:5 | Address | &:r10_3 | +| try_except.cpp:10:9:10:9 | Address | &:r10_1 | +| try_except.cpp:10:9:10:9 | Load | m7_5 | +| try_except.cpp:10:9:10:9 | StoreValue | r10_2 | +| try_except.cpp:11:5:11:17 | CallTarget | func:r11_1 | +| try_except.cpp:11:5:11:17 | ChiPartial | partial:m11_4 | +| try_except.cpp:11:5:11:17 | ChiTotal | total:m9_5 | +| try_except.cpp:11:5:11:17 | SideEffect | ~m9_5 | +| try_except.cpp:11:19:11:19 | Arg(0) | 0:r11_2 | +| try_except.cpp:18:6:18:10 | ChiPartial | partial:m18_3 | +| try_except.cpp:18:6:18:10 | ChiTotal | total:m18_2 | +| try_except.cpp:18:6:18:10 | SideEffect | ~m26_6 | +| try_except.cpp:19:7:19:7 | Address | &:r19_1 | +| try_except.cpp:19:10:19:10 | Address | &:r19_3 | +| try_except.cpp:19:13:19:14 | StoreValue | r19_4 | +| try_except.cpp:21:5:21:17 | CallTarget | func:r21_1 | +| try_except.cpp:21:5:21:17 | ChiPartial | partial:m21_4 | +| try_except.cpp:21:5:21:17 | ChiTotal | total:m18_4 | +| try_except.cpp:21:5:21:17 | SideEffect | ~m18_4 | +| try_except.cpp:21:19:21:19 | Arg(0) | 0:r21_2 | +| try_except.cpp:22:5:22:5 | Address | &:r22_3 | +| try_except.cpp:22:9:22:9 | Address | &:r22_1 | +| try_except.cpp:22:9:22:9 | Load | m19_5 | +| try_except.cpp:22:9:22:9 | StoreValue | r22_2 | +| try_except.cpp:23:5:23:17 | CallTarget | func:r23_1 | +| try_except.cpp:23:5:23:17 | ChiPartial | partial:m23_4 | +| try_except.cpp:23:5:23:17 | ChiTotal | total:m21_5 | +| try_except.cpp:23:5:23:17 | SideEffect | ~m21_5 | +| try_except.cpp:23:19:23:19 | Arg(0) | 0:r23_2 | +| try_except.cpp:26:5:26:8 | CallTarget | func:r26_1 | +| try_except.cpp:26:5:26:8 | ChiPartial | partial:m26_5 | +| try_except.cpp:26:5:26:8 | ChiTotal | total:m23_5 | +| try_except.cpp:26:5:26:8 | SideEffect | ~m23_5 | +| try_except.cpp:26:10:26:10 | Address | &:r26_2 | +| try_except.cpp:26:10:26:10 | Arg(0) | 0:r26_3 | +| try_except.cpp:26:10:26:10 | Load | m22_4 | +| try_except.cpp:32:6:32:10 | ChiPartial | partial:m32_3 | +| try_except.cpp:32:6:32:10 | ChiTotal | total:m32_2 | +| try_except.cpp:32:6:32:10 | SideEffect | ~m42_1 | +| try_except.cpp:32:16:32:16 | Address | &:r32_5 | +| try_except.cpp:33:7:33:7 | Address | &:r33_1 | +| try_except.cpp:33:10:33:11 | StoreValue | r33_2 | +| try_except.cpp:35:13:35:13 | Address | &:r35_1 | +| try_except.cpp:35:13:35:13 | Condition | r35_4 | +| try_except.cpp:35:13:35:13 | Left | r35_2 | +| try_except.cpp:35:13:35:13 | Load | m32_6 | +| try_except.cpp:35:13:35:13 | Right | r35_3 | +| try_except.cpp:36:13:36:35 | CallTarget | func:r36_1 | +| try_except.cpp:36:13:36:35 | ChiPartial | partial:m36_3 | +| try_except.cpp:36:13:36:35 | ChiTotal | total:m32_4 | +| try_except.cpp:36:13:36:35 | SideEffect | ~m32_4 | +| try_except.cpp:42:1:42:1 | Phi | from 0:~m32_4 | +| try_except.cpp:42:1:42:1 | Phi | from 1:~m36_4 | +| try_except.cpp:44:6:44:14 | ChiPartial | partial:m44_3 | +| try_except.cpp:44:6:44:14 | ChiTotal | total:m44_2 | +| try_except.cpp:44:6:44:14 | SideEffect | ~m54_1 | +| try_except.cpp:44:20:44:20 | Address | &:r44_5 | +| try_except.cpp:45:7:45:7 | Address | &:r45_1 | +| try_except.cpp:45:10:45:11 | StoreValue | r45_2 | +| try_except.cpp:47:13:47:13 | Address | &:r47_1 | +| try_except.cpp:47:13:47:13 | Condition | r47_4 | +| try_except.cpp:47:13:47:13 | Left | r47_2 | +| try_except.cpp:47:13:47:13 | Load | m44_6 | +| try_except.cpp:47:13:47:13 | Right | r47_3 | +| try_except.cpp:48:13:48:19 | Address | &:r48_1 | +| try_except.cpp:48:13:48:19 | Address | &:r48_1 | +| try_except.cpp:48:13:48:19 | Load | m48_3 | +| try_except.cpp:48:19:48:19 | StoreValue | r48_2 | +| try_except.cpp:51:15:51:15 | Left | r51_7 | +| try_except.cpp:51:15:51:15 | Left | r51_7 | +| try_except.cpp:51:15:51:15 | Left | r51_7 | +| try_except.cpp:51:18:53:5 | Condition | r51_2 | +| try_except.cpp:51:18:53:5 | Condition | r51_5 | +| try_except.cpp:51:18:53:5 | Condition | r51_9 | +| try_except.cpp:51:18:53:5 | Right | r51_1 | +| try_except.cpp:51:18:53:5 | Right | r51_4 | +| try_except.cpp:51:18:53:5 | Right | r51_8 | +| try_except.cpp:52:9:52:12 | CallTarget | func:r52_1 | +| try_except.cpp:52:9:52:12 | ChiPartial | partial:m52_5 | +| try_except.cpp:52:9:52:12 | ChiTotal | total:m44_4 | +| try_except.cpp:52:9:52:12 | SideEffect | ~m44_4 | +| try_except.cpp:52:14:52:14 | Address | &:r52_2 | +| try_except.cpp:52:14:52:14 | Arg(0) | 0:r52_3 | +| try_except.cpp:52:14:52:14 | Load | m45_3 | +| try_except.cpp:54:1:54:1 | Phi | from 0:~m44_4 | +| try_except.cpp:54:1:54:1 | Phi | from 5:~m52_6 | 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 600d74bc9169..4f3f9315c014 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected @@ -19,6 +19,14 @@ useNotDominatedByDefinition | ir.cpp:1486:8:1486:8 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:1486:8:1486:8 | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | | ir.cpp:1751:51:1751:51 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | ir.cpp:1750:5:1750:34 | int implicit_copy_constructor_test(CopyConstructorTestNonVirtualClass const&, CopyConstructorTestVirtualClass const&) | int implicit_copy_constructor_test(CopyConstructorTestNonVirtualClass const&, CopyConstructorTestVirtualClass const&) | | ir.cpp:1752:48:1752:48 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | ir.cpp:1750:5:1750:34 | int implicit_copy_constructor_test(CopyConstructorTestNonVirtualClass const&, CopyConstructorTestVirtualClass const&) | int implicit_copy_constructor_test(CopyConstructorTestNonVirtualClass const&, CopyConstructorTestVirtualClass const&) | +| 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 cb8bd0465da8..6f9186e3b8db 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -10410,3 +10410,390 @@ struct_init.cpp: # 36| v36_9(void) = ReturnVoid : # 36| v36_10(void) = AliasedUse : ~m? # 36| v36_11(void) = ExitFunction : + +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 6 + +# 13| Block 1 +# 13| r13_1(int) = Constant[0] : +# 13| r13_2(bool) = CompareEQ : r13_8, r13_1 +# 13| v13_3(void) = ConditionalBranch : r13_2 +#-----| False -> Block 2 +#-----| True -> Block 3 + +# 13| Block 2 +# 13| r13_4(int) = Constant[1] : +# 13| r13_5(bool) = CompareEQ : r13_8, r13_4 +# 13| v13_6(void) = ConditionalBranch : r13_5 +#-----| True -> Block 5 + +# 13| Block 3 +# 13| v13_7(void) = Unwind : +#-----| Goto -> Block 6 + +# 13| Block 4 +# 13| r13_8(int) = Constant[0] : +# 13| r13_9(int) = Constant[-1] : +# 13| r13_10(bool) = CompareEQ : r13_8, r13_9 +# 13| v13_11(void) = ConditionalBranch : r13_10 +#-----| False -> Block 1 +#-----| True -> Block 3 + +# 14| Block 5 +# 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 6 + +# 16| Block 6 +# 16| v16_1(void) = NoOp : +# 6| v6_4(void) = ReturnVoid : +# 6| v6_5(void) = AliasedUse : ~m? +# 6| v6_6(void) = ExitFunction : + +# 18| void g() +# 18| Block 0 +# 18| v18_1(void) = EnterFunction : +# 18| mu18_2(unknown) = AliasedDefinition : +# 18| mu18_3(unknown) = InitializeNonLocal : +# 19| r19_1(glval) = VariableAddress[x] : +# 19| mu19_2(int) = Uninitialized[x] : &:r19_1 +# 19| r19_3(glval) = VariableAddress[y] : +# 19| r19_4(int) = Constant[0] : +# 19| mu19_5(int) = Store[y] : &:r19_3, r19_4 +# 21| r21_1(glval) = FunctionAddress[ProbeFunction] : +# 21| r21_2(int) = Constant[0] : +# 21| v21_3(void) = Call[ProbeFunction] : func:r21_1, 0:r21_2 +# 21| mu21_4(unknown) = ^CallSideEffect : ~m? +# 22| r22_1(glval) = VariableAddress[y] : +# 22| r22_2(int) = Load[y] : &:r22_1, ~m? +# 22| r22_3(glval) = VariableAddress[x] : +# 22| mu22_4(int) = Store[x] : &:r22_3, r22_2 +# 23| r23_1(glval) = FunctionAddress[ProbeFunction] : +# 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 : +# 18| v18_5(void) = AliasedUse : ~m? +# 18| v18_6(void) = ExitFunction : + +# 32| void h(int) +# 32| Block 0 +# 32| v32_1(void) = EnterFunction : +# 32| mu32_2(unknown) = AliasedDefinition : +# 32| mu32_3(unknown) = InitializeNonLocal : +# 32| r32_4(glval) = VariableAddress[b] : +# 32| mu32_5(int) = InitializeParameter[b] : &:r32_4 +# 33| r33_1(glval) = VariableAddress[x] : +# 33| r33_2(int) = Constant[0] : +# 33| mu33_3(int) = Store[x] : &:r33_1, r33_2 +# 35| r35_1(glval) = VariableAddress[b] : +# 35| r35_2(int) = Load[b] : &:r35_1, ~m? +# 35| v35_3(void) = ConditionalBranch : r35_2 +#-----| False -> Block 7 +#-----| True -> Block 1 + +# 36| Block 1 +# 36| r36_1(glval) = FunctionAddress[AfxThrowMemoryException] : +# 36| v36_2(void) = Call[AfxThrowMemoryException] : func:r36_1 +# 36| mu36_3(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 7 + +# 39| Block 2 +# 39| r39_1(int) = Constant[0] : +# 39| r39_2(bool) = CompareEQ : r39_8, r39_1 +# 39| v39_3(void) = ConditionalBranch : r39_2 +#-----| False -> Block 3 +#-----| True -> Block 4 + +# 39| Block 3 +# 39| r39_4(int) = Constant[1] : +# 39| r39_5(bool) = CompareEQ : r39_8, r39_4 +# 39| v39_6(void) = ConditionalBranch : r39_5 +#-----| True -> Block 6 + +# 39| Block 4 +# 39| v39_7(void) = Unwind : +#-----| Goto -> Block 7 + +# 39| Block 5 +# 39| r39_8(int) = Constant[1] : +# 39| r39_9(int) = Constant[-1] : +# 39| r39_10(bool) = CompareEQ : r39_8, r39_9 +# 39| v39_11(void) = ConditionalBranch : r39_10 +#-----| False -> Block 2 +#-----| True -> Block 4 + +# 40| Block 6 +# 40| r40_1(glval) = FunctionAddress[sink] : +# 40| r40_2(glval) = VariableAddress[x] : +# 40| r40_3(int) = Load[x] : &:r40_2, ~m? +# 40| v40_4(void) = Call[sink] : func:r40_1, 0:r40_3 +# 40| mu40_5(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 7 + +# 42| Block 7 +# 42| v42_1(void) = NoOp : +# 32| v32_6(void) = ReturnVoid : +# 32| v32_7(void) = AliasedUse : ~m? +# 32| v32_8(void) = ExitFunction : + +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 6 + +# 13| Block 1 +# 13| r13_1(int) = Constant[0] : +# 13| r13_2(bool) = CompareEQ : r13_8, r13_1 +# 13| v13_3(void) = ConditionalBranch : r13_2 +#-----| False -> Block 2 +#-----| True -> Block 3 + +# 13| Block 2 +# 13| r13_4(int) = Constant[1] : +# 13| r13_5(bool) = CompareEQ : r13_8, r13_4 +# 13| v13_6(void) = ConditionalBranch : r13_5 +#-----| True -> Block 5 + +# 13| Block 3 +# 13| v13_7(void) = Unwind : +#-----| Goto -> Block 6 + +# 13| Block 4 +# 13| r13_8(int) = Constant[0] : +# 13| r13_9(int) = Constant[-1] : +# 13| r13_10(bool) = CompareEQ : r13_8, r13_9 +# 13| v13_11(void) = ConditionalBranch : r13_10 +#-----| False -> Block 1 +#-----| True -> Block 3 + +# 14| Block 5 +# 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 6 + +# 16| Block 6 +# 16| v16_1(void) = NoOp : +# 6| v6_4(void) = ReturnVoid : +# 6| v6_5(void) = AliasedUse : ~m? +# 6| v6_6(void) = ExitFunction : + +# 18| void g_cpp() +# 18| Block 0 +# 18| v18_1(void) = EnterFunction : +# 18| mu18_2(unknown) = AliasedDefinition : +# 18| mu18_3(unknown) = InitializeNonLocal : +# 19| r19_1(glval) = VariableAddress[x] : +# 19| mu19_2(int) = Uninitialized[x] : &:r19_1 +# 19| r19_3(glval) = VariableAddress[y] : +# 19| r19_4(int) = Constant[0] : +# 19| mu19_5(int) = Store[y] : &:r19_3, r19_4 +# 21| r21_1(glval) = FunctionAddress[ProbeFunction] : +# 21| r21_2(int) = Constant[0] : +# 21| v21_3(void) = Call[ProbeFunction] : func:r21_1, 0:r21_2 +# 21| mu21_4(unknown) = ^CallSideEffect : ~m? +# 22| r22_1(glval) = VariableAddress[y] : +# 22| r22_2(int) = Load[y] : &:r22_1, ~m? +# 22| r22_3(glval) = VariableAddress[x] : +# 22| mu22_4(int) = Store[x] : &:r22_3, r22_2 +# 23| r23_1(glval) = FunctionAddress[ProbeFunction] : +# 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 : +# 18| v18_5(void) = AliasedUse : ~m? +# 18| v18_6(void) = ExitFunction : + +# 32| void h_cpp(int) +# 32| Block 0 +# 32| v32_1(void) = EnterFunction : +# 32| mu32_2(unknown) = AliasedDefinition : +# 32| mu32_3(unknown) = InitializeNonLocal : +# 32| r32_4(glval) = VariableAddress[b] : +# 32| mu32_5(int) = InitializeParameter[b] : &:r32_4 +# 33| r33_1(glval) = VariableAddress[x] : +# 33| r33_2(int) = Constant[0] : +# 33| mu33_3(int) = Store[x] : &:r33_1, r33_2 +# 35| r35_1(glval) = VariableAddress[b] : +# 35| r35_2(int) = Load[b] : &:r35_1, ~m? +# 35| r35_3(int) = Constant[0] : +# 35| r35_4(bool) = CompareNE : r35_2, r35_3 +# 35| v35_5(void) = ConditionalBranch : r35_4 +#-----| False -> Block 7 +#-----| True -> Block 1 + +# 36| Block 1 +# 36| r36_1(glval) = FunctionAddress[AfxThrowMemoryException] : +# 36| v36_2(void) = Call[AfxThrowMemoryException] : func:r36_1 +# 36| mu36_3(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 7 + +# 39| Block 2 +# 39| r39_1(int) = Constant[0] : +# 39| r39_2(bool) = CompareEQ : r39_8, r39_1 +# 39| v39_3(void) = ConditionalBranch : r39_2 +#-----| False -> Block 3 +#-----| True -> Block 4 + +# 39| Block 3 +# 39| r39_4(int) = Constant[1] : +# 39| r39_5(bool) = CompareEQ : r39_8, r39_4 +# 39| v39_6(void) = ConditionalBranch : r39_5 +#-----| True -> Block 6 + +# 39| Block 4 +# 39| v39_7(void) = Unwind : +#-----| Goto -> Block 7 + +# 39| Block 5 +# 39| r39_8(int) = Constant[1] : +# 39| r39_9(int) = Constant[-1] : +# 39| r39_10(bool) = CompareEQ : r39_8, r39_9 +# 39| v39_11(void) = ConditionalBranch : r39_10 +#-----| False -> Block 2 +#-----| True -> Block 4 + +# 40| Block 6 +# 40| r40_1(glval) = FunctionAddress[sink] : +# 40| r40_2(glval) = VariableAddress[x] : +# 40| r40_3(int) = Load[x] : &:r40_2, ~m? +# 40| v40_4(void) = Call[sink] : func:r40_1, 0:r40_3 +# 40| mu40_5(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 7 + +# 42| Block 7 +# 42| v42_1(void) = NoOp : +# 32| v32_6(void) = ReturnVoid : +# 32| v32_7(void) = AliasedUse : ~m? +# 32| v32_8(void) = ExitFunction : + +# 44| void throw_cpp(int) +# 44| Block 0 +# 44| v44_1(void) = EnterFunction : +# 44| mu44_2(unknown) = AliasedDefinition : +# 44| mu44_3(unknown) = InitializeNonLocal : +# 44| r44_4(glval) = VariableAddress[b] : +# 44| mu44_5(int) = InitializeParameter[b] : &:r44_4 +# 45| r45_1(glval) = VariableAddress[x] : +# 45| r45_2(int) = Constant[0] : +# 45| mu45_3(int) = Store[x] : &:r45_1, r45_2 +# 47| r47_1(glval) = VariableAddress[b] : +# 47| r47_2(int) = Load[b] : &:r47_1, ~m? +# 47| r47_3(int) = Constant[0] : +# 47| r47_4(bool) = CompareNE : r47_2, r47_3 +# 47| v47_5(void) = ConditionalBranch : r47_4 +#-----| False -> Block 9 +#-----| True -> Block 3 + +# 44| Block 1 +# 44| v44_6(void) = AliasedUse : ~m? +# 44| v44_7(void) = ExitFunction : + +# 44| Block 2 +# 44| v44_8(void) = Unwind : +#-----| Goto -> Block 1 + +# 48| Block 3 +# 48| r48_1(glval) = VariableAddress[#throw48:13] : +# 48| r48_2(int) = Constant[1] : +# 48| mu48_3(int) = Store[#throw48:13] : &:r48_1, r48_2 +# 48| v48_4(void) = ThrowValue : &:r48_1, ~m? +#-----| Exception -> Block 7 + +# 51| Block 4 +# 51| r51_1(int) = Constant[0] : +# 51| r51_2(bool) = CompareEQ : r51_8, r51_1 +# 51| v51_3(void) = ConditionalBranch : r51_2 +#-----| False -> Block 5 +#-----| True -> Block 6 + +# 51| Block 5 +# 51| r51_4(int) = Constant[1] : +# 51| r51_5(bool) = CompareEQ : r51_8, r51_4 +# 51| v51_6(void) = ConditionalBranch : r51_5 +#-----| True -> Block 8 + +# 51| Block 6 +# 51| v51_7(void) = Unwind : +#-----| Goto -> Block 9 + +# 51| Block 7 +# 51| r51_8(int) = Constant[1] : +# 51| r51_9(int) = Constant[-1] : +# 51| r51_10(bool) = CompareEQ : r51_8, r51_9 +# 51| v51_11(void) = ConditionalBranch : r51_10 +#-----| False -> Block 4 +#-----| True -> Block 6 + +# 52| Block 8 +# 52| r52_1(glval) = FunctionAddress[sink] : +# 52| r52_2(glval) = VariableAddress[x] : +# 52| r52_3(int) = Load[x] : &:r52_2, ~m? +# 52| v52_4(void) = Call[sink] : func:r52_1, 0:r52_3 +# 52| mu52_5(unknown) = ^CallSideEffect : ~m? +#-----| Goto -> Block 9 + +# 54| Block 9 +# 54| v54_1(void) = NoOp : +# 44| v44_9(void) = ReturnVoid : +#-----| Goto -> Block 1 diff --git a/cpp/ql/test/library-tests/ir/ir/try_except.c b/cpp/ql/test/library-tests/ir/ir/try_except.c new file mode 100644 index 000000000000..410068dae5ea --- /dev/null +++ b/cpp/ql/test/library-tests/ir/ir/try_except.c @@ -0,0 +1,42 @@ +// semmle-extractor-options: --microsoft + +void ProbeFunction(); +void sink(); + +void f() { + int x, y = 0; + __try { + ProbeFunction(0); + x = y; + ProbeFunction(0); + } + __except (0) { + sink(x); + } +} + +void g() { + int x, y = 0; + __try { + ProbeFunction(0); + x = y; + ProbeFunction(0); + } + __finally { + sink(x); + } +} + +void AfxThrowMemoryException(); + +void h(int b) { + int x = 0; + __try { + if (b) { + AfxThrowMemoryException(); + } + } + __except (1) { + sink(x); + } +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/ir/ir/try_except.cpp b/cpp/ql/test/library-tests/ir/ir/try_except.cpp new file mode 100644 index 000000000000..fd8c5f59f1a4 --- /dev/null +++ b/cpp/ql/test/library-tests/ir/ir/try_except.cpp @@ -0,0 +1,54 @@ +// semmle-extractor-options: --microsoft + +void ProbeFunction(...); +void sink(...); + +void f_cpp() { + int x, y = 0; + __try { + ProbeFunction(0); + x = y; + ProbeFunction(0); + } + __except (0) { + sink(x); + } +} + +void g_cpp() { + int x, y = 0; + __try { + ProbeFunction(0); + x = y; + ProbeFunction(0); + } + __finally { + sink(x); + } +} + +void AfxThrowMemoryException(); + +void h_cpp(int b) { + int x = 0; + __try { + if (b) { + AfxThrowMemoryException(); + } + } + __except (1) { + sink(x); + } +} + +void throw_cpp(int b) { + int x = 0; + __try { + if (b) { + throw 1; + } + } + __except (1) { + sink(x); + } +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_consistency.expected index e06e22a5e67b..ec7962a50358 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_consistency.expected @@ -13,10 +13,8 @@ instructionWithoutSuccessor | condition_decls.cpp:41:22:41:23 | Chi: call to BoxedInt | Instruction 'Chi: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) | | condition_decls.cpp:48:52:48:53 | Chi: call to BoxedInt | Instruction 'Chi: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) | | misc.c:171:10:171:13 | Uninitialized: definition of str2 | Instruction 'Uninitialized: definition of str2' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | -| ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x | Instruction 'Uninitialized: definition of x' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | -| ms_try_mix.cpp:11:12:11:15 | Chi: call to C | Instruction 'Chi: call to C' has no successors in function '$@'. | ms_try_mix.cpp:10:6:10:18 | void ms_except_mix(int) | void ms_except_mix(int) | -| ms_try_mix.cpp:28:12:28:15 | Chi: call to C | Instruction 'Chi: call to C' has no successors in function '$@'. | ms_try_mix.cpp:27:6:27:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | -| ms_try_mix.cpp:48:10:48:13 | Chi: call to C | Instruction 'Chi: call to C' has no successors in function '$@'. | ms_try_mix.cpp:47:6:47:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | +| ms_try_mix.cpp:33:13:33:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:27:6:27:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | +| ms_try_mix.cpp:51:5:51:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:47:6:47:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | | stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:6:21:6 | void stmtexpr::g(int) | void stmtexpr::g(int) | | vla.c:5:9:5:14 | Uninitialized: definition of matrix | Instruction 'Uninitialized: definition of matrix' has no successors in function '$@'. | vla.c:3:5:3:8 | int main(int, char**) | int main(int, char**) | | vla.c:11:6:11:16 | Chi: vla_typedef | Instruction 'Chi: vla_typedef' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() | diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected index 8b1094228a94..fa8172cad704 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected @@ -2316,12 +2316,34 @@ postWithInFlow | ms_assume.cpp:28:18:28:23 | buffer [post update] | PostUpdateNode should not be the target of local flow. | | ms_assume.cpp:28:18:28:23 | buffer [post update] | PostUpdateNode should not be the target of local flow. | | ms_assume.cpp:34:1:34:1 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_except.cpp:7:13:7:13 | x [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_except.cpp:14:13:14:13 | x [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_except.cpp:17:13:17:13 | x [post update] | PostUpdateNode should not be the target of local flow. | | ms_try_mix.cpp:11:7:11:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | | ms_try_mix.cpp:11:7:11:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:14:11:14:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:14:11:14:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:16:13:16:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:18:11:18:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:18:11:18:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:21:11:21:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:21:11:21:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:24:7:24:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:24:7:24:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | ms_try_mix.cpp:28:7:28:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | | ms_try_mix.cpp:28:7:28:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:31:11:31:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:31:11:31:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:33:13:33:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:35:11:35:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:35:11:35:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:38:11:38:14 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:38:11:38:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:41:7:41:10 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:41:7:41:10 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | ms_try_mix.cpp:48:5:48:8 | Argument this [post update] | PostUpdateNode should not be the target of local flow. | | ms_try_mix.cpp:48:5:48:8 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| ms_try_mix.cpp:51:5:51:11 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | newexpr.cpp:8:2:8:20 | Call [post update] | PostUpdateNode should not be the target of local flow. | | newexpr.cpp:8:2:8:20 | new [post update] | PostUpdateNode should not be the target of local flow. | | newexpr.cpp:8:2:8:20 | new [post update] | PostUpdateNode should not be the target of local flow. | diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected index 90e261c5c341..d68bb1cfde78 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected @@ -31,26 +31,8 @@ instructionWithoutSuccessor | misc.c:174:17:174:22 | CallSideEffect: call to getInt | Instruction 'CallSideEffect: call to getInt' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | | misc.c:174:30:174:35 | CallSideEffect: call to getInt | Instruction 'CallSideEffect: call to getInt' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | | misc.c:174:55:174:60 | Store: (char ****)... | Instruction 'Store: (char ****)...' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | -| ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x | Instruction 'Uninitialized: definition of x' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | -| ms_try_except.cpp:7:13:7:17 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | -| ms_try_except.cpp:9:19:9:19 | Load: j | Instruction 'Load: j' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | -| ms_try_except.cpp:10:13:10:17 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | -| ms_try_except.cpp:14:13:14:17 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | -| ms_try_except.cpp:17:13:17:17 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | -| ms_try_except.cpp:19:17:19:21 | Sub: ... - ... | Instruction 'Sub: ... - ...' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | -| ms_try_except.cpp:20:9:20:13 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | -| ms_try_mix.cpp:11:12:11:15 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect: call to C' has no successors in function '$@'. | ms_try_mix.cpp:10:6:10:18 | void ms_except_mix(int) | void ms_except_mix(int) | -| ms_try_mix.cpp:16:13:16:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:10:6:10:18 | void ms_except_mix(int) | void ms_except_mix(int) | -| ms_try_mix.cpp:18:16:18:19 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect: call to C' has no successors in function '$@'. | ms_try_mix.cpp:10:6:10:18 | void ms_except_mix(int) | void ms_except_mix(int) | -| ms_try_mix.cpp:20:15:20:39 | Constant: 1 | Instruction 'Constant: 1' has no successors in function '$@'. | ms_try_mix.cpp:10:6:10:18 | void ms_except_mix(int) | void ms_except_mix(int) | -| ms_try_mix.cpp:21:16:21:19 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect: call to C' has no successors in function '$@'. | ms_try_mix.cpp:10:6:10:18 | void ms_except_mix(int) | void ms_except_mix(int) | -| ms_try_mix.cpp:28:12:28:15 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect: call to C' has no successors in function '$@'. | ms_try_mix.cpp:27:6:27:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | | ms_try_mix.cpp:33:13:33:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:27:6:27:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | -| ms_try_mix.cpp:35:16:35:19 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect: call to C' has no successors in function '$@'. | ms_try_mix.cpp:27:6:27:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | -| ms_try_mix.cpp:38:16:38:19 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect: call to C' has no successors in function '$@'. | ms_try_mix.cpp:27:6:27:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | -| ms_try_mix.cpp:48:10:48:13 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect: call to C' has no successors in function '$@'. | ms_try_mix.cpp:47:6:47:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | | ms_try_mix.cpp:51:5:51:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:47:6:47:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | -| ms_try_mix.cpp:53:13:54:3 | NoOp: { ... } | Instruction 'NoOp: { ... }' has no successors in function '$@'. | ms_try_mix.cpp:47:6:47:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | | stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:6:21:6 | void stmtexpr::g(int) | void stmtexpr::g(int) | | stmt_expr.cpp:29:11:32:11 | CopyValue: (statement expression) | Instruction 'CopyValue: (statement expression)' has no successors in function '$@'. | stmt_expr.cpp:21:6:21:6 | void stmtexpr::g(int) | void stmtexpr::g(int) | | stmt_in_type.cpp:5:53:5:53 | Constant: 1 | Instruction 'Constant: 1' has no successors in function '$@'. | stmt_in_type.cpp:2:6:2:12 | void cpp_fun() | void cpp_fun() | @@ -135,6 +117,10 @@ backEdgeCountMismatch useNotDominatedByDefinition | VacuousDestructorCall.cpp:2:29:2:29 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | void CallDestructor(int, int*) | void CallDestructor(int, int*) | | misc.c:219:47:219:48 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | misc.c:219:5:219:26 | int assign_designated_init(someStruct*) | int assign_designated_init(someStruct*) | +| ms_try_except.cpp:9:19:9:19 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | +| ms_try_except.cpp:9:19:9:19 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | +| ms_try_except.cpp:19:17:19:21 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | +| ms_try_except.cpp:19:17:19:21 | Left | Operand 'Left' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | | static_init_templates.cpp:15:1:15:18 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | static_init_templates.cpp:15:1:15:18 | void MyClass::MyClass() | void MyClass::MyClass() | | try_catch.cpp:21:9:21:9 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | try_catch.cpp:19:6:19:23 | void throw_from_nonstmt(int) | void throw_from_nonstmt(int) | | vla.c:3:27:3:30 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | int main(int, char**) | int main(int, char**) | diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_consistency.expected index 06ed8ac215b4..fe94102942f0 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_consistency.expected @@ -13,10 +13,8 @@ instructionWithoutSuccessor | condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:40:6:40:20 | void while_decl_bind(int) | void while_decl_bind(int) | | condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | Instruction 'IndirectMayWriteSideEffect: call to BoxedInt' has no successors in function '$@'. | condition_decls.cpp:47:6:47:18 | void for_decl_bind(int) | void for_decl_bind(int) | | misc.c:171:10:171:13 | Uninitialized: definition of str2 | Instruction 'Uninitialized: definition of str2' has no successors in function '$@'. | misc.c:168:6:168:8 | void vla() | void vla() | -| ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x | Instruction 'Uninitialized: definition of x' has no successors in function '$@'. | ms_try_except.cpp:2:6:2:18 | void ms_try_except(int) | void ms_try_except(int) | -| ms_try_mix.cpp:11:12:11:15 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect: call to C' has no successors in function '$@'. | ms_try_mix.cpp:10:6:10:18 | void ms_except_mix(int) | void ms_except_mix(int) | -| ms_try_mix.cpp:28:12:28:15 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect: call to C' has no successors in function '$@'. | ms_try_mix.cpp:27:6:27:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | -| ms_try_mix.cpp:48:10:48:13 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect: call to C' has no successors in function '$@'. | ms_try_mix.cpp:47:6:47:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | +| ms_try_mix.cpp:33:13:33:19 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:27:6:27:19 | void ms_finally_mix(int) | void ms_finally_mix(int) | +| ms_try_mix.cpp:51:5:51:11 | ThrowValue: throw ... | Instruction 'ThrowValue: throw ...' has no successors in function '$@'. | ms_try_mix.cpp:47:6:47:28 | void ms_empty_finally_at_end() | void ms_empty_finally_at_end() | | stmt_expr.cpp:27:5:27:15 | Store: ... = ... | Instruction 'Store: ... = ...' has no successors in function '$@'. | stmt_expr.cpp:21:6:21:6 | void stmtexpr::g(int) | void stmtexpr::g(int) | | vla.c:5:9:5:14 | Uninitialized: definition of matrix | Instruction 'Uninitialized: definition of matrix' has no successors in function '$@'. | vla.c:3:5:3:8 | int main(int, char**) | int main(int, char**) | | vla.c:11:6:11:16 | InitializeNonLocal: vla_typedef | Instruction 'InitializeNonLocal: vla_typedef' has no successors in function '$@'. | vla.c:11:6:11:16 | void vla_typedef() | void vla_typedef() |