diff --git a/cpp/ql/lib/semmle/code/cpp/Element.qll b/cpp/ql/lib/semmle/code/cpp/Element.qll index b30503d2c94c..ffc0ede4daff 100644 --- a/cpp/ql/lib/semmle/code/cpp/Element.qll +++ b/cpp/ql/lib/semmle/code/cpp/Element.qll @@ -192,6 +192,11 @@ class Element extends ElementBase { */ predicate isAffectedByMacro() { affectedByMacro(this) } + /** Holds if this element is affected by the expansion of `mi`. */ + predicate isAffectedByMacro(MacroInvocation mi) { + affectedbymacroexpansion(underlyingElement(this), unresolveElement(mi)) + } + private Element getEnclosingElementPref() { enclosingfunction(underlyingElement(this), unresolveElement(result)) or result.(Function) = stmtEnclosingElement(this) or diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll index 60e2635f338a..851d987b1fd6 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll @@ -23,7 +23,7 @@ class Expr extends StmtParent, @expr { predicate hasChild(Expr e, int n) { e = this.getChild(n) } /** Gets the enclosing function of this expression, if any. */ - Function getEnclosingFunction() { result = exprEnclosingElement(this) } + override Function getEnclosingFunction() { result = exprEnclosingElement(this) } /** Gets the nearest enclosing set of curly braces around this expression in the source, if any. */ BlockStmt getEnclosingBlock() { result = this.getEnclosingStmt().getEnclosingBlock() } 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 be3f680aa16d..e97e903f0025 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 @@ -104,7 +104,11 @@ newtype TInstructionTag = } or SizeofVlaDimensionTag(int index) { exists(VlaDeclStmt v | exists(v.getTransitiveVlaDimensionStmt(index))) - } + } or + AssertionVarAddressTag() or + AssertionVarLoadTag() or + AssertionOpTag() or + AssertionBranchTag() class InstructionTag extends TInstructionTag { final string toString() { result = getInstructionTagId(this) } @@ -296,4 +300,12 @@ string getInstructionTagId(TInstructionTag tag) { tag = CoAwaitBranchTag() and result = "CoAwaitBranch" or tag = BoolToIntConversionTag() and result = "BoolToIntConversion" + or + tag = AssertionVarAddressTag() and result = "AssertionVarAddress" + or + tag = AssertionVarLoadTag() and result = "AssertionVarLoad" + or + tag = AssertionOpTag() and result = "AssertionOp" + or + tag = AssertionBranchTag() and result = "AssertionBranch" } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedAssertion.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedAssertion.qll new file mode 100644 index 000000000000..4c2b82ee1c0b --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedAssertion.qll @@ -0,0 +1,373 @@ +private import cpp +private import semmle.code.cpp.ir.internal.IRUtilities +private import semmle.code.cpp.ir.implementation.internal.OperandTag +private import semmle.code.cpp.ir.internal.CppType +private import semmle.code.cpp.ir.internal.TempVariableTag +private import InstructionTag +private import TranslatedElement +private import TranslatedStmt +private import TranslatedFunction + +/** + * Holds if `s` is a statement that may be an expanded assertion in a + * release build. + */ +pragma[nomagic] +private predicate stmtCandidate(Stmt s) { + not s.isFromUninstantiatedTemplate(_) and + ( + // The expansion of `__analysis_assume(x != 0);` when `__analysis_assume` is + // empty is the empty statement. + s instanceof EmptyStmt + or + // The expansion of `assert(x != 0)` when `assert` is `((void)0)` is a zero literal + // with a void type. + exists(Expr e | + e = s.(ExprStmt).getExpr() and + e.getValue() = "0" and + e.getActualType() instanceof VoidType + ) + ) +} + +pragma[nomagic] +private predicate macroInvocationLocation(int startline, Function f, MacroInvocation mi) { + mi.getMacroName() = ["assert", "__analysis_assume"] and + mi.getLocation().hasLocationInfo(_, startline, _, _, _) and + f.getEntryPoint().isAffectedByMacro(mi) +} + +pragma[nomagic] +private predicate stmtParentLocation(int startline, Function f, StmtParent p) { + p.getEnclosingFunction() = f and + p.getLocation().hasLocationInfo(_, startline, _, _, _) +} + +/** + * Holds if `mi` is a macro invocation with a name that is known + * to correspond to an assertion macro, and the macro invocation + * is the only thing on the line. + */ +pragma[nomagic] +private predicate assertion0(MacroInvocation mi, Stmt s) { + stmtCandidate(s) and + s = + unique(StmtParent p, int startline, Function f | + macroInvocationLocation(startline, f, mi) and + stmtParentLocation(startline, f, p) and + // Also do not count the elements from the expanded macro. i.e., when checking + // if `assert(x)` is the only thing on the line we do not count the + // generated `((void)0)` expression. + not p = mi.getAnExpandedElement() + | + p + ) +} + +private Function getEnclosingFunctionForMacroInvocation(MacroInvocation mi) { + exists(Stmt s | + assertion0(mi, s) and + result = s.getEnclosingFunction() + ) +} + +/** + * Holds if `arg` has two components and the `i`'th component of the string + * `arg` is `s`, and the components are separated by an operation with + * opcode `opcode`. + */ +bindingset[arg] +pragma[inline_late] +private predicate parseArgument(string arg, string s, int i, Opcode opcode) { + s = + arg.regexpCapture("([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?<=\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)", + i + 1) and + opcode instanceof Opcode::CompareLE + or + s = + arg.regexpCapture("([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?>=\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)", + i + 1) and + opcode instanceof Opcode::CompareGE + or + not arg.regexpMatch("([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?<=\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)") and + s = + arg.regexpCapture("([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?<\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)", + i + 1) and + opcode instanceof Opcode::CompareLT + or + not arg.regexpMatch("([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?>=\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)") and + s = + arg.regexpCapture("([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?>\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)", + i + 1) and + opcode instanceof Opcode::CompareGT + or + s = + arg.regexpCapture("([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?!=\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)", + i + 1) and + opcode instanceof Opcode::CompareNE + or + s = + arg.regexpCapture("([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)\\s?==\\s?([a-zA-Z_][a-zA-Z_0-9]*|[0-9]+)", + i + 1) and + opcode instanceof Opcode::CompareEQ +} + +/** Gets a local variable named `s` in `f`. */ +pragma[nomagic] +private LocalScopeVariable getAVariableWithNameInFunction(Function f, string s) { + result.getName() = s and + result.getFunction() = f +} + +/** + * Holds if the `i`'th component of the macro invocation `mi` with opcode + * `opcode` is a reference to `var`. + */ +private predicate hasVarAccessMacroArgument(MacroInvocation mi, Variable var, int i, Opcode opcode) { + exists(string arg, string s, Function f | + arg = mi.getUnexpandedArgument(0) and + f = getEnclosingFunctionForMacroInvocation(mi) and + not exists(s.toInt()) and + parseArgument(arg, s, i, opcode) and + var = unique( | | getAVariableWithNameInFunction(f, s)) + ) +} + +/** + * Holds if the `i`'th component of the macro invocation `mi` with opcode + * `opcode` is a + * constant with the value `k`. + */ +private predicate hasConstMacroArgument(MacroInvocation mi, int k, int i, Opcode opcode) { + exists(string arg, string s | + assertion0(mi, _) and + arg = mi.getUnexpandedArgument(0) and + s.toInt() = k and + parseArgument(arg, s, i, opcode) + ) +} + +predicate hasAssertionOperand(MacroInvocation mi, int i) { + hasVarAccessMacroArgument(mi, _, i, _) + or + hasConstMacroArgument(mi, _, i, _) +} + +private predicate hasAssertionOpcode(MacroInvocation mi, Opcode opcode) { + hasVarAccessMacroArgument(mi, _, _, opcode) + or + hasConstMacroArgument(mi, _, _, opcode) +} + +/** + * Holds if `mi` is a macro invocation that is an assertion that should be generated + * in the control-flow graph at `s`. + */ +predicate assertion(MacroInvocation mi, Stmt s) { + assertion0(mi, s) and + hasAssertionOperand(mi, 0) and + hasAssertionOperand(mi, 1) +} + +/** The translation of an operand of an assertion. */ +abstract private class TranslatedAssertionOperand extends TranslatedElement, + TTranslatedAssertionOperand +{ + MacroInvocation mi; + int index; + + TranslatedAssertionOperand() { this = TTranslatedAssertionOperand(mi, index) } + + MacroInvocation getMacroInvocation() { result = mi } + + /** + * Gets the statement that is being replaced by the assertion that uses this + * operand. + */ + Stmt getStmt() { assertion(mi, result) } + + final override Locatable getAst() { result = this.getStmt() } + + final override TranslatedElement getChild(int id) { none() } + + final override Declaration getFunction() { result = this.getStmt().getEnclosingFunction() } + + /** Gets the instruction which holds the result of this operand. */ + abstract Instruction getResult(); + + final override string toString() { result = "Operand of assertion: " + mi } + + /** Gets the index of this operand (i.e., `0` or `1`). */ + final int getIndex() { result = index } +} + +/** An operand of an assertion that is a variable access. */ +private class TranslatedAssertionVarAccess extends TranslatedAssertionOperand { + TranslatedAssertionVarAccess() { hasVarAccessMacroArgument(mi, _, index, _) } + + Variable getVariable() { hasVarAccessMacroArgument(mi, result, index, _) } + + final override IRUserVariable getInstructionVariable(InstructionTag tag) { + tag = AssertionVarAddressTag() and + result.getVariable() = this.getVariable() + } + + final override Instruction getFirstInstruction(EdgeKind kind) { + result = this.getInstruction(AssertionVarAddressTag()) and kind instanceof GotoEdge + } + + final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { + tag = AssertionVarAddressTag() and + kind instanceof GotoEdge and + result = this.getInstruction(AssertionVarLoadTag()) + or + tag = AssertionVarLoadTag() and + result = getTranslatedAssertionMacroInvocation(mi).getChildSuccessor(this, kind) + } + + final override Instruction getALastInstructionInternal() { + result = this.getInstruction(AssertionVarLoadTag()) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { + exists(Variable v | v = this.getVariable() | + opcode instanceof Opcode::VariableAddress and + tag = AssertionVarAddressTag() and + resultType = getTypeForGLValue(v.getType()) + or + opcode instanceof Opcode::Load and + tag = AssertionVarLoadTag() and + resultType = getTypeForPRValue(v.getType()) + ) + } + + final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { + tag = AssertionVarLoadTag() and + operandTag instanceof AddressOperandTag and + result = this.getInstruction(AssertionVarAddressTag()) + } + + final override Instruction getResult() { result = this.getInstruction(AssertionVarLoadTag()) } +} + +/** An operand of an assertion that is a constant access. */ +private class TranslatedAssertionConst extends TranslatedAssertionOperand { + TranslatedAssertionConst() { hasConstMacroArgument(mi, _, index, _) } + + int getConst() { hasConstMacroArgument(mi, result, index, _) } + + final override string getInstructionConstantValue(InstructionTag tag) { + tag = OnlyInstructionTag() and + result = this.getConst().toString() + } + + final override Instruction getFirstInstruction(EdgeKind kind) { + result = this.getInstruction(OnlyInstructionTag()) and + kind instanceof GotoEdge + } + + final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { + tag = OnlyInstructionTag() and + result = getTranslatedAssertionMacroInvocation(mi).getChildSuccessor(this, kind) + } + + final override Instruction getALastInstructionInternal() { + result = this.getInstruction(OnlyInstructionTag()) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { + opcode instanceof Opcode::Constant and + tag = OnlyInstructionTag() and + resultType = getIntType() + } + + final override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) } +} + +/** + * Gets the `TranslatedAssertionMacroInvocation` corresponding to the macro + * invocation `mi`. + */ +TranslatedAssertionMacroInvocation getTranslatedAssertionMacroInvocation(MacroInvocation mi) { + result.getMacroInvocation() = mi +} + +/** + * A synthesized assertion which would have otherwise been invisible because the + * database represents a release build where assertions are disabled. + */ +private class TranslatedAssertionMacroInvocation extends TranslatedStmt { + MacroInvocation mi; + + TranslatedAssertionMacroInvocation() { assertion(mi, stmt) } + + final override Instruction getFirstInstruction(EdgeKind kind) { + result = this.getLeft().getFirstInstruction(kind) + } + + TranslatedAssertionOperand getLeft() { + result.getMacroInvocation() = mi and + result.getIndex() = 0 + } + + TranslatedAssertionOperand getRight() { + result.getMacroInvocation() = mi and + result.getIndex() = 1 + } + + final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { + tag = AssertionOpTag() and + kind instanceof GotoEdge and + result = this.getInstruction(AssertionBranchTag()) + or + tag = AssertionBranchTag() and + kind instanceof TrueEdge and + result = this.getParent().getChildSuccessor(this, _) + } + + final override TranslatedElement getChildInternal(int id) { + id = 0 and result = this.getLeft() + or + id = 1 and result = this.getRight() + } + + final override Instruction getALastInstructionInternal() { + result = this.getInstruction(AssertionBranchTag()) + } + + final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { + tag = AssertionOpTag() and + resultType = getBoolType() and + hasAssertionOpcode(mi, opcode) + or + tag = AssertionBranchTag() and + resultType = getVoidType() and + opcode instanceof Opcode::ConditionalBranch + } + + final override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { + child = this.getLeft() and + result = this.getRight().getFirstInstruction(kind) + or + child = this.getRight() and + kind instanceof GotoEdge and + result = this.getInstruction(AssertionOpTag()) + } + + final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { + tag = AssertionOpTag() and + ( + operandTag instanceof LeftOperandTag and + result = this.getLeft().getResult() + or + operandTag instanceof RightOperandTag and + result = this.getRight().getResult() + ) + or + tag = AssertionBranchTag() and + operandTag instanceof ConditionOperandTag and + result = this.getInstruction(AssertionOpTag()) + } + + MacroInvocation getMacroInvocation() { result = mi } +} 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 330362f55603..9829388ef177 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 @@ -12,6 +12,7 @@ private import TranslatedFunction private import TranslatedStmt private import TranslatedExpr private import IRConstruction +private import TranslatedAssertion private import semmle.code.cpp.models.interfaces.SideEffect private import SideEffects @@ -138,6 +139,14 @@ private predicate ignoreExprAndDescendants(Expr expr) { // conditionally constructed (until we have a mechanism for calling these only when the // temporary's constructor was run) isConditionalTemporaryDestructorCall(expr) + or + // An assertion in a release build is often defined as `#define assert(x) ((void)0)`. + // We generate a synthetic assertion in release builds, and when we do that the + // expression `((void)0)` should not be translated. + exists(MacroInvocation mi | + assertion(mi, _) and + expr = mi.getExpr().getFullyConverted() + ) } /** @@ -909,7 +918,8 @@ newtype TTranslatedElement = } or // The side effect that initializes newly-allocated memory. TTranslatedAllocationSideEffect(AllocationExpr expr) { not ignoreSideEffects(expr) } or - TTranslatedStaticStorageDurationVarInit(Variable var) { Raw::varHasIRFunc(var) } + TTranslatedStaticStorageDurationVarInit(Variable var) { Raw::varHasIRFunc(var) } or + TTranslatedAssertionOperand(MacroInvocation mi, int index) { hasAssertionOperand(mi, index) } /** * Gets the index of the first explicitly initialized element in `initList` 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 9dccf7752aa8..d748e2f86638 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 @@ -10,6 +10,7 @@ private import TranslatedElement private import TranslatedExpr private import TranslatedFunction private import TranslatedInitialization +private import TranslatedAssertion TranslatedStmt getTranslatedStmt(Stmt stmt) { result.getAst() = stmt } @@ -324,8 +325,16 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt { class TranslatedEmptyStmt extends TranslatedStmt { TranslatedEmptyStmt() { - stmt instanceof EmptyStmt or - stmt instanceof LabelStmt or + // An assertion macro invocation can expand to + // an empty statement in release builds. In that case + // we synthedsize the check that would have occurred. + // This is handled by `TranslatedAssertion.qll` and so + // we exclude these statements here. + not assertion(_, stmt) and + stmt instanceof EmptyStmt + or + stmt instanceof LabelStmt + or stmt instanceof SwitchCase } @@ -420,6 +429,15 @@ class TranslatedDeclStmt extends TranslatedStmt { class TranslatedExprStmt extends TranslatedStmt { override ExprStmt stmt; + TranslatedExprStmt() { + // An assertion macro invocation typically expand to the + // expression `((void)0)` in release builds. In that case + // we synthedsize the check that would have occurred. + // This is handled by `TranslatedAssertion.qll` and so + // we exclude these statements here. + not assertion(_, stmt) + } + TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr().getFullyConverted()) } override TranslatedElement getChildInternal(int id) { id = 0 and result = this.getExpr() } diff --git a/cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll b/cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll index bd3a54c61594..cd7504612444 100644 --- a/cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll +++ b/cpp/ql/lib/semmle/code/cpp/stmts/Stmt.qll @@ -20,7 +20,7 @@ class Stmt extends StmtParent, @stmt { predicate hasChild(Element e, int n) { this.getChild(n) = e } /** Gets the enclosing function of this statement, if any. */ - Function getEnclosingFunction() { result = stmtEnclosingElement(this) } + override Function getEnclosingFunction() { result = stmtEnclosingElement(this) } /** * Gets the nearest enclosing block of this statement in the source, if any. @@ -159,7 +159,10 @@ private class TStmtParent = @stmt or @expr; * * This is normally a statement, but may be a `StmtExpr`. */ -class StmtParent extends ControlFlowNode, TStmtParent { } +class StmtParent extends ControlFlowNode, TStmtParent { + /** Gets the enclosing function of this element, if any. */ + Function getEnclosingFunction() { none() } +} /** * A C/C++ 'expression' statement. diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index e6f88ceb7789..9dbcf49777be 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -25131,6 +25131,438 @@ ir.cpp: # 2823| Type = [ArrayType] int[] # 2823| ValueCategory = lvalue # 2824| getStmt(5): [ReturnStmt] return ... +# 2830| [TopLevelFunction] void test_assert_simple(int, int, unsigned int, int) +# 2830| : +# 2830| getParameter(0): [Parameter] x +# 2830| Type = [IntType] int +# 2830| getParameter(1): [Parameter] y +# 2830| Type = [IntType] int +# 2830| getParameter(2): [Parameter] u +# 2830| Type = [IntType] unsigned int +# 2830| getParameter(3): [Parameter] shadowed +# 2830| Type = [IntType] int +# 2830| getEntryPoint(): [BlockStmt] { ... } +# 2831| getStmt(0): [ExprStmt] ExprStmt +# 2831| getExpr(): [Literal] 0 +# 2831| Type = [IntType] int +# 2831| Value = [Literal] 0 +# 2831| ValueCategory = prvalue +# 2831| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2831| Type = [VoidType] void +# 2831| ValueCategory = prvalue +# 2831| getExpr(): [CStyleCast] (void)... +# 2831| Conversion = [VoidConversion] conversion to void +# 2831| Type = [VoidType] void +# 2831| ValueCategory = prvalue +# 2832| getStmt(1): [ExprStmt] ExprStmt +# 2832| getExpr(): [Literal] 0 +# 2832| Type = [IntType] int +# 2832| Value = [Literal] 0 +# 2832| ValueCategory = prvalue +# 2832| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2832| Type = [VoidType] void +# 2832| ValueCategory = prvalue +# 2832| getExpr(): [CStyleCast] (void)... +# 2832| Conversion = [VoidConversion] conversion to void +# 2832| Type = [VoidType] void +# 2832| ValueCategory = prvalue +# 2833| getStmt(2): [ExprStmt] ExprStmt +# 2833| getExpr(): [Literal] 0 +# 2833| Type = [IntType] int +# 2833| Value = [Literal] 0 +# 2833| ValueCategory = prvalue +# 2833| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2833| Type = [VoidType] void +# 2833| ValueCategory = prvalue +# 2833| getExpr(): [CStyleCast] (void)... +# 2833| Conversion = [VoidConversion] conversion to void +# 2833| Type = [VoidType] void +# 2833| ValueCategory = prvalue +# 2835| getStmt(3): [EmptyStmt] ; +# 2837| getStmt(4): [ExprStmt] ExprStmt +# 2837| getExpr(): [Literal] 0 +# 2837| Type = [IntType] int +# 2837| Value = [Literal] 0 +# 2837| ValueCategory = prvalue +# 2837| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2837| Type = [VoidType] void +# 2837| ValueCategory = prvalue +# 2837| getExpr(): [CStyleCast] (void)... +# 2837| Conversion = [VoidConversion] conversion to void +# 2837| Type = [VoidType] void +# 2837| ValueCategory = prvalue +# 2839| getStmt(5): [BlockStmt] { ... } +# 2840| getStmt(0): [DeclStmt] declaration +# 2840| getDeclarationEntry(0): [VariableDeclarationEntry] definition of shadowed +# 2840| Type = [IntType] int +# 2840| getVariable().getInitializer(): [Initializer] initializer for shadowed +# 2840| getExpr(): [VariableAccess] x +# 2840| Type = [IntType] int +# 2840| ValueCategory = prvalue(load) +# 2841| getStmt(1): [ExprStmt] ExprStmt +# 2841| getExpr(): [Literal] 0 +# 2841| Type = [IntType] int +# 2841| Value = [Literal] 0 +# 2841| ValueCategory = prvalue +# 2841| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2841| Type = [VoidType] void +# 2841| ValueCategory = prvalue +# 2841| getExpr(): [CStyleCast] (void)... +# 2841| Conversion = [VoidConversion] conversion to void +# 2841| Type = [VoidType] void +# 2841| ValueCategory = prvalue +# 2843| getStmt(6): [ReturnStmt] return ... +# 2846| [TemplateFunction,TopLevelFunction] void test_assert_in_template(T, int, unsigned int) +# 2846| : +# 2846| getParameter(0): [Parameter] x +# 2846| Type = [TypeTemplateParameter] T +# 2846| getParameter(1): [Parameter] y +# 2846| Type = [IntType] int +# 2846| getParameter(2): [Parameter] u +# 2846| Type = [IntType] unsigned int +# 2846| getEntryPoint(): [BlockStmt] { ... } +# 2847| getStmt(0): [ExprStmt] ExprStmt +# 2847| getExpr(): [Literal] 0 +# 2847| Type = [IntType] int +# 2847| Value = [Literal] 0 +# 2847| ValueCategory = prvalue +# 2847| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2847| Type = [VoidType] void +# 2847| ValueCategory = prvalue +# 2847| getExpr(): [CStyleCast] (void)... +# 2847| Conversion = [VoidConversion] conversion to void +# 2847| Type = [VoidType] void +# 2847| ValueCategory = prvalue +# 2848| getStmt(1): [ExprStmt] ExprStmt +# 2848| getExpr(): [Literal] 0 +# 2848| Type = [IntType] int +# 2848| Value = [Literal] 0 +# 2848| ValueCategory = prvalue +# 2848| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2848| Type = [VoidType] void +# 2848| ValueCategory = prvalue +# 2848| getExpr(): [CStyleCast] (void)... +# 2848| Conversion = [VoidConversion] conversion to void +# 2848| Type = [VoidType] void +# 2848| ValueCategory = prvalue +# 2849| getStmt(2): [ExprStmt] ExprStmt +# 2849| getExpr(): [Literal] 0 +# 2849| Type = [IntType] int +# 2849| Value = [Literal] 0 +# 2849| ValueCategory = prvalue +# 2849| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2849| Type = [VoidType] void +# 2849| ValueCategory = prvalue +# 2849| getExpr(): [CStyleCast] (void)... +# 2849| Conversion = [VoidConversion] conversion to void +# 2849| Type = [VoidType] void +# 2849| ValueCategory = prvalue +# 2851| getStmt(3): [EmptyStmt] ; +# 2853| getStmt(4): [ExprStmt] ExprStmt +# 2853| getExpr(): [Literal] 0 +# 2853| Type = [IntType] int +# 2853| Value = [Literal] 0 +# 2853| ValueCategory = prvalue +# 2853| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2853| Type = [VoidType] void +# 2853| ValueCategory = prvalue +# 2853| getExpr(): [CStyleCast] (void)... +# 2853| Conversion = [VoidConversion] conversion to void +# 2853| Type = [VoidType] void +# 2853| ValueCategory = prvalue +# 2855| getStmt(5): [BlockStmt] { ... } +# 2856| getStmt(0): [DeclStmt] declaration +# 2856| getDeclarationEntry(0): [VariableDeclarationEntry] definition of shadowed +# 2856| Type = [IntType] int +# 2856| getVariable().getInitializer(): [Initializer] initializer for shadowed +# 2856| getExpr(): [VariableAccess] x +# 2856| Type = [TypeTemplateParameter] T +# 2856| ValueCategory = lvalue +# 2856| getExpr().getFullyConverted(): [CStyleCast] (int)... +# 2856| Type = [IntType] int +# 2856| ValueCategory = prvalue +# 2857| getStmt(1): [ExprStmt] ExprStmt +# 2857| getExpr(): [Literal] 0 +# 2857| Type = [IntType] int +# 2857| Value = [Literal] 0 +# 2857| ValueCategory = prvalue +# 2857| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2857| Type = [VoidType] void +# 2857| ValueCategory = prvalue +# 2857| getExpr(): [CStyleCast] (void)... +# 2857| Conversion = [VoidConversion] conversion to void +# 2857| Type = [VoidType] void +# 2857| ValueCategory = prvalue +# 2859| getStmt(6): [ExprStmt] ExprStmt +# 2859| getExpr(): [Literal] 0 +# 2859| Type = [IntType] int +# 2859| Value = [Literal] 0 +# 2859| ValueCategory = prvalue +# 2859| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2859| Type = [VoidType] void +# 2859| ValueCategory = prvalue +# 2859| getExpr(): [CStyleCast] (void)... +# 2859| Conversion = [VoidConversion] conversion to void +# 2859| Type = [VoidType] void +# 2859| ValueCategory = prvalue +# 2860| getStmt(7): [ReturnStmt] return ... +# 2846| [FunctionTemplateInstantiation,TopLevelFunction] void test_assert_in_template(int, int, unsigned int) +# 2846| : +# 2846| getParameter(0): [Parameter] x +# 2846| Type = [IntType] int +# 2846| getParameter(1): [Parameter] y +# 2846| Type = [IntType] int +# 2846| getParameter(2): [Parameter] u +# 2846| Type = [IntType] unsigned int +# 2846| getEntryPoint(): [BlockStmt] { ... } +# 2847| getStmt(0): [ExprStmt] ExprStmt +# 2847| getExpr(): [Literal] 0 +# 2847| Type = [IntType] int +# 2847| Value = [Literal] 0 +# 2847| ValueCategory = prvalue +# 2847| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2847| Type = [VoidType] void +# 2847| ValueCategory = prvalue +# 2847| getExpr(): [CStyleCast] (void)... +# 2847| Conversion = [VoidConversion] conversion to void +# 2847| Type = [VoidType] void +# 2847| ValueCategory = prvalue +# 2848| getStmt(1): [ExprStmt] ExprStmt +# 2848| getExpr(): [Literal] 0 +# 2848| Type = [IntType] int +# 2848| Value = [Literal] 0 +# 2848| ValueCategory = prvalue +# 2848| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2848| Type = [VoidType] void +# 2848| ValueCategory = prvalue +# 2848| getExpr(): [CStyleCast] (void)... +# 2848| Conversion = [VoidConversion] conversion to void +# 2848| Type = [VoidType] void +# 2848| ValueCategory = prvalue +# 2849| getStmt(2): [ExprStmt] ExprStmt +# 2849| getExpr(): [Literal] 0 +# 2849| Type = [IntType] int +# 2849| Value = [Literal] 0 +# 2849| ValueCategory = prvalue +# 2849| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2849| Type = [VoidType] void +# 2849| ValueCategory = prvalue +# 2849| getExpr(): [CStyleCast] (void)... +# 2849| Conversion = [VoidConversion] conversion to void +# 2849| Type = [VoidType] void +# 2849| ValueCategory = prvalue +# 2851| getStmt(3): [EmptyStmt] ; +# 2853| getStmt(4): [ExprStmt] ExprStmt +# 2853| getExpr(): [Literal] 0 +# 2853| Type = [IntType] int +# 2853| Value = [Literal] 0 +# 2853| ValueCategory = prvalue +# 2853| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2853| Type = [VoidType] void +# 2853| ValueCategory = prvalue +# 2853| getExpr(): [CStyleCast] (void)... +# 2853| Conversion = [VoidConversion] conversion to void +# 2853| Type = [VoidType] void +# 2853| ValueCategory = prvalue +# 2855| getStmt(5): [BlockStmt] { ... } +# 2856| getStmt(0): [DeclStmt] declaration +# 2856| getDeclarationEntry(0): [VariableDeclarationEntry] definition of shadowed +# 2856| Type = [IntType] int +# 2856| getVariable().getInitializer(): [Initializer] initializer for shadowed +# 2856| getExpr(): [VariableAccess] x +# 2856| Type = [IntType] int +# 2856| ValueCategory = prvalue(load) +# 2857| getStmt(1): [ExprStmt] ExprStmt +# 2857| getExpr(): [Literal] 0 +# 2857| Type = [IntType] int +# 2857| Value = [Literal] 0 +# 2857| ValueCategory = prvalue +# 2857| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2857| Type = [VoidType] void +# 2857| ValueCategory = prvalue +# 2857| getExpr(): [CStyleCast] (void)... +# 2857| Conversion = [VoidConversion] conversion to void +# 2857| Type = [VoidType] void +# 2857| ValueCategory = prvalue +# 2859| getStmt(6): [ExprStmt] ExprStmt +# 2859| getExpr(): [Literal] 0 +# 2859| Type = [IntType] int +# 2859| Value = [Literal] 0 +# 2859| ValueCategory = prvalue +# 2859| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2859| Type = [VoidType] void +# 2859| ValueCategory = prvalue +# 2859| getExpr(): [CStyleCast] (void)... +# 2859| Conversion = [VoidConversion] conversion to void +# 2859| Type = [VoidType] void +# 2859| ValueCategory = prvalue +# 2860| getStmt(7): [ReturnStmt] return ... +# 2846| [FunctionTemplateInstantiation,TopLevelFunction] void test_assert_in_template(short, int, unsigned int) +# 2846| : +# 2846| getParameter(0): [Parameter] x +# 2846| Type = [ShortType] short +# 2846| getParameter(1): [Parameter] y +# 2846| Type = [IntType] int +# 2846| getParameter(2): [Parameter] u +# 2846| Type = [IntType] unsigned int +# 2846| getEntryPoint(): [BlockStmt] { ... } +# 2847| getStmt(0): [ExprStmt] ExprStmt +# 2847| getExpr(): [Literal] 0 +# 2847| Type = [IntType] int +# 2847| Value = [Literal] 0 +# 2847| ValueCategory = prvalue +# 2847| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2847| Type = [VoidType] void +# 2847| ValueCategory = prvalue +# 2847| getExpr(): [CStyleCast] (void)... +# 2847| Conversion = [VoidConversion] conversion to void +# 2847| Type = [VoidType] void +# 2847| ValueCategory = prvalue +# 2848| getStmt(1): [ExprStmt] ExprStmt +# 2848| getExpr(): [Literal] 0 +# 2848| Type = [IntType] int +# 2848| Value = [Literal] 0 +# 2848| ValueCategory = prvalue +# 2848| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2848| Type = [VoidType] void +# 2848| ValueCategory = prvalue +# 2848| getExpr(): [CStyleCast] (void)... +# 2848| Conversion = [VoidConversion] conversion to void +# 2848| Type = [VoidType] void +# 2848| ValueCategory = prvalue +# 2849| getStmt(2): [ExprStmt] ExprStmt +# 2849| getExpr(): [Literal] 0 +# 2849| Type = [IntType] int +# 2849| Value = [Literal] 0 +# 2849| ValueCategory = prvalue +# 2849| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2849| Type = [VoidType] void +# 2849| ValueCategory = prvalue +# 2849| getExpr(): [CStyleCast] (void)... +# 2849| Conversion = [VoidConversion] conversion to void +# 2849| Type = [VoidType] void +# 2849| ValueCategory = prvalue +# 2851| getStmt(3): [EmptyStmt] ; +# 2853| getStmt(4): [ExprStmt] ExprStmt +# 2853| getExpr(): [Literal] 0 +# 2853| Type = [IntType] int +# 2853| Value = [Literal] 0 +# 2853| ValueCategory = prvalue +# 2853| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2853| Type = [VoidType] void +# 2853| ValueCategory = prvalue +# 2853| getExpr(): [CStyleCast] (void)... +# 2853| Conversion = [VoidConversion] conversion to void +# 2853| Type = [VoidType] void +# 2853| ValueCategory = prvalue +# 2855| getStmt(5): [BlockStmt] { ... } +# 2856| getStmt(0): [DeclStmt] declaration +# 2856| getDeclarationEntry(0): [VariableDeclarationEntry] definition of shadowed +# 2856| Type = [IntType] int +# 2856| getVariable().getInitializer(): [Initializer] initializer for shadowed +# 2856| getExpr(): [VariableAccess] x +# 2856| Type = [ShortType] short +# 2856| ValueCategory = prvalue(load) +# 2856| getExpr().getFullyConverted(): [CStyleCast] (int)... +# 2856| Conversion = [IntegralConversion] integral conversion +# 2856| Type = [IntType] int +# 2856| ValueCategory = prvalue +# 2857| getStmt(1): [ExprStmt] ExprStmt +# 2857| getExpr(): [Literal] 0 +# 2857| Type = [IntType] int +# 2857| Value = [Literal] 0 +# 2857| ValueCategory = prvalue +# 2857| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2857| Type = [VoidType] void +# 2857| ValueCategory = prvalue +# 2857| getExpr(): [CStyleCast] (void)... +# 2857| Conversion = [VoidConversion] conversion to void +# 2857| Type = [VoidType] void +# 2857| ValueCategory = prvalue +# 2859| getStmt(6): [ExprStmt] ExprStmt +# 2859| getExpr(): [Literal] 0 +# 2859| Type = [IntType] int +# 2859| Value = [Literal] 0 +# 2859| ValueCategory = prvalue +# 2859| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2859| Type = [VoidType] void +# 2859| ValueCategory = prvalue +# 2859| getExpr(): [CStyleCast] (void)... +# 2859| Conversion = [VoidConversion] conversion to void +# 2859| Type = [VoidType] void +# 2859| ValueCategory = prvalue +# 2860| getStmt(7): [ReturnStmt] return ... +# 2865| [TopLevelFunction] void complex_assertions(int, bool, int) +# 2865| : +# 2865| getParameter(0): [Parameter] x +# 2865| Type = [IntType] int +# 2865| getParameter(1): [Parameter] b +# 2865| Type = [BoolType] bool +# 2865| getParameter(2): [Parameter] max +# 2865| Type = [IntType] int +# 2865| getEntryPoint(): [BlockStmt] { ... } +# 2866| getStmt(0): [DeclStmt] declaration +# 2866| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y +# 2866| Type = [IntType] int +# 2866| getVariable().getInitializer(): [Initializer] initializer for y +# 2866| getExpr(): [CommaExpr] ... , ... +# 2866| Type = [IntType] int +# 2866| ValueCategory = prvalue(load) +# 2866| getLeftOperand(): [Literal] 0 +# 2866| Type = [IntType] int +# 2866| Value = [Literal] 0 +# 2866| ValueCategory = prvalue +# 2866| getRightOperand(): [VariableAccess] x +# 2866| Type = [IntType] int +# 2866| ValueCategory = prvalue(load) +# 2866| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...) +# 2866| Type = [VoidType] void +# 2866| ValueCategory = prvalue +# 2866| getExpr(): [CStyleCast] (void)... +# 2866| Conversion = [VoidConversion] conversion to void +# 2866| Type = [VoidType] void +# 2866| ValueCategory = prvalue +# 2866| getExpr().getFullyConverted(): [ParenthesisExpr] (...) +# 2866| Type = [IntType] int +# 2866| ValueCategory = prvalue(load) +# 2867| getStmt(1): [DeclStmt] declaration +# 2867| getDeclarationEntry(0): [VariableDeclarationEntry] definition of z +# 2867| Type = [IntType] int +# 2867| getVariable().getInitializer(): [Initializer] initializer for z +# 2867| getExpr(): [ConditionalExpr] ... ? ... : ... +# 2867| Type = [IntType] int +# 2867| ValueCategory = prvalue +# 2867| getCondition(): [VariableAccess] b +# 2867| Type = [BoolType] bool +# 2867| ValueCategory = prvalue(load) +# 2867| getThen(): [CommaExpr] ... , ... +# 2867| Type = [IntType] int +# 2867| Value = [CommaExpr] 0 +# 2867| ValueCategory = prvalue +# 2867| getLeftOperand(): [Literal] 0 +# 2867| Type = [IntType] int +# 2867| Value = [Literal] 0 +# 2867| ValueCategory = prvalue +# 2867| getRightOperand(): [Literal] 0 +# 2867| Type = [IntType] int +# 2867| Value = [Literal] 0 +# 2867| ValueCategory = prvalue +# 2867| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...) +# 2867| Type = [VoidType] void +# 2867| ValueCategory = prvalue +# 2867| getExpr(): [CStyleCast] (void)... +# 2867| Conversion = [VoidConversion] conversion to void +# 2867| Type = [VoidType] void +# 2867| ValueCategory = prvalue +# 2867| getElse(): [Literal] 1 +# 2867| Type = [IntType] int +# 2867| Value = [Literal] 1 +# 2867| ValueCategory = prvalue +# 2867| getThen().getFullyConverted(): [ParenthesisExpr] (...) +# 2867| Type = [IntType] int +# 2867| Value = [ParenthesisExpr] 0 +# 2867| ValueCategory = prvalue +# 2868| getStmt(2): [ReturnStmt] return ... ir23.cpp: # 1| [TopLevelFunction] bool consteval_1() # 1| : 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 94daf808a722..b7fc1b3a96b1 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -20741,6 +20741,280 @@ ir.cpp: # 2821| v2821_10(void) = AliasedUse : m2821_3 # 2821| v2821_11(void) = ExitFunction : +# 2830| void test_assert_simple(int, int, unsigned int, int) +# 2830| Block 0 +# 2830| v2830_1(void) = EnterFunction : +# 2830| m2830_2(unknown) = AliasedDefinition : +# 2830| m2830_3(unknown) = InitializeNonLocal : +# 2830| m2830_4(unknown) = Chi : total:m2830_2, partial:m2830_3 +# 2830| r2830_5(glval) = VariableAddress[x] : +# 2830| m2830_6(int) = InitializeParameter[x] : &:r2830_5 +# 2830| r2830_7(glval) = VariableAddress[y] : +# 2830| m2830_8(int) = InitializeParameter[y] : &:r2830_7 +# 2830| r2830_9(glval) = VariableAddress[u] : +# 2830| m2830_10(unsigned int) = InitializeParameter[u] : &:r2830_9 +# 2830| r2830_11(glval) = VariableAddress[shadowed] : +# 2830| m2830_12(int) = InitializeParameter[shadowed] : &:r2830_11 +# 2831| r2831_1(glval) = VariableAddress[x] : +# 2831| r2831_2(int) = Load[x] : &:r2831_1, m2830_6 +# 2831| r2831_3(int) = Constant[0] : +# 2831| r2831_4(bool) = CompareGT : r2831_2, r2831_3 +# 2831| v2831_5(void) = ConditionalBranch : r2831_4 +#-----| True -> Block 1 + +# 2832| Block 1 +# 2832| r2832_1(int) = Constant[0] : +# 2832| r2832_2(glval) = VariableAddress[x] : +# 2832| r2832_3(int) = Load[x] : &:r2832_2, m2830_6 +# 2832| r2832_4(bool) = CompareLT : r2832_1, r2832_3 +# 2832| v2832_5(void) = ConditionalBranch : r2832_4 +#-----| True -> Block 2 + +# 2833| Block 2 +# 2833| r2833_1(glval) = VariableAddress[x] : +# 2833| r2833_2(int) = Load[x] : &:r2833_1, m2830_6 +# 2833| r2833_3(glval) = VariableAddress[y] : +# 2833| r2833_4(int) = Load[y] : &:r2833_3, m2830_8 +# 2833| r2833_5(bool) = CompareLT : r2833_2, r2833_4 +# 2833| v2833_6(void) = ConditionalBranch : r2833_5 +#-----| True -> Block 3 + +# 2835| Block 3 +# 2835| r2835_1(glval) = VariableAddress[x] : +# 2835| r2835_2(int) = Load[x] : &:r2835_1, m2830_6 +# 2835| r2835_3(int) = Constant[2] : +# 2835| r2835_4(bool) = CompareNE : r2835_2, r2835_3 +# 2835| v2835_5(void) = ConditionalBranch : r2835_4 +#-----| True -> Block 4 + +# 2837| Block 4 +# 2837| r2837_1(glval) = VariableAddress[u] : +# 2837| r2837_2(unsigned int) = Load[u] : &:r2837_1, m2830_10 +# 2837| r2837_3(glval) = VariableAddress[x] : +# 2837| r2837_4(int) = Load[x] : &:r2837_3, m2830_6 +# 2837| r2837_5(bool) = CompareLT : r2837_2, r2837_4 +# 2837| v2837_6(void) = ConditionalBranch : r2837_5 +#-----| True -> Block 5 + +# 2840| Block 5 +# 2840| r2840_1(glval) = VariableAddress[shadowed] : +# 2840| r2840_2(glval) = VariableAddress[x] : +# 2840| r2840_3(int) = Load[x] : &:r2840_2, m2830_6 +# 2840| m2840_4(int) = Store[shadowed] : &:r2840_1, r2840_3 +# 2841| r2841_1(int) = Constant[0] : +# 2841| v2841_2(void) = Convert : r2841_1 +# 2843| v2843_1(void) = NoOp : +# 2830| v2830_13(void) = ReturnVoid : +# 2830| v2830_14(void) = AliasedUse : m2830_3 +# 2830| v2830_15(void) = ExitFunction : + +# 2846| void test_assert_in_template(int, int, unsigned int) +# 2846| Block 0 +# 2846| v2846_1(void) = EnterFunction : +# 2846| m2846_2(unknown) = AliasedDefinition : +# 2846| m2846_3(unknown) = InitializeNonLocal : +# 2846| m2846_4(unknown) = Chi : total:m2846_2, partial:m2846_3 +# 2846| r2846_5(glval) = VariableAddress[x] : +# 2846| m2846_6(int) = InitializeParameter[x] : &:r2846_5 +# 2846| r2846_7(glval) = VariableAddress[y] : +# 2846| m2846_8(int) = InitializeParameter[y] : &:r2846_7 +# 2846| r2846_9(glval) = VariableAddress[u] : +# 2846| m2846_10(unsigned int) = InitializeParameter[u] : &:r2846_9 +# 2847| r2847_1(glval) = VariableAddress[x] : +# 2847| r2847_2(int) = Load[x] : &:r2847_1, m2846_6 +# 2847| r2847_3(int) = Constant[0] : +# 2847| r2847_4(bool) = CompareGT : r2847_2, r2847_3 +# 2847| v2847_5(void) = ConditionalBranch : r2847_4 +#-----| True -> Block 1 + +# 2848| Block 1 +# 2848| r2848_1(int) = Constant[0] : +# 2848| r2848_2(glval) = VariableAddress[x] : +# 2848| r2848_3(int) = Load[x] : &:r2848_2, m2846_6 +# 2848| r2848_4(bool) = CompareLT : r2848_1, r2848_3 +# 2848| v2848_5(void) = ConditionalBranch : r2848_4 +#-----| True -> Block 2 + +# 2849| Block 2 +# 2849| r2849_1(glval) = VariableAddress[x] : +# 2849| r2849_2(int) = Load[x] : &:r2849_1, m2846_6 +# 2849| r2849_3(glval) = VariableAddress[y] : +# 2849| r2849_4(int) = Load[y] : &:r2849_3, m2846_8 +# 2849| r2849_5(bool) = CompareLT : r2849_2, r2849_4 +# 2849| v2849_6(void) = ConditionalBranch : r2849_5 +#-----| True -> Block 3 + +# 2851| Block 3 +# 2851| r2851_1(glval) = VariableAddress[x] : +# 2851| r2851_2(int) = Load[x] : &:r2851_1, m2846_6 +# 2851| r2851_3(int) = Constant[2] : +# 2851| r2851_4(bool) = CompareNE : r2851_2, r2851_3 +# 2851| v2851_5(void) = ConditionalBranch : r2851_4 +#-----| True -> Block 4 + +# 2853| Block 4 +# 2853| r2853_1(glval) = VariableAddress[u] : +# 2853| r2853_2(unsigned int) = Load[u] : &:r2853_1, m2846_10 +# 2853| r2853_3(glval) = VariableAddress[x] : +# 2853| r2853_4(int) = Load[x] : &:r2853_3, m2846_6 +# 2853| r2853_5(bool) = CompareLT : r2853_2, r2853_4 +# 2853| v2853_6(void) = ConditionalBranch : r2853_5 +#-----| True -> Block 5 + +# 2856| Block 5 +# 2856| r2856_1(glval) = VariableAddress[shadowed] : +# 2856| r2856_2(glval) = VariableAddress[x] : +# 2856| r2856_3(int) = Load[x] : &:r2856_2, m2846_6 +# 2856| m2856_4(int) = Store[shadowed] : &:r2856_1, r2856_3 +# 2857| r2857_1(glval) = VariableAddress[shadowed] : +# 2857| r2857_2(int) = Load[shadowed] : &:r2857_1, m2856_4 +# 2857| r2857_3(int) = Constant[0] : +# 2857| r2857_4(bool) = CompareGT : r2857_2, r2857_3 +# 2857| v2857_5(void) = ConditionalBranch : r2857_4 +#-----| True -> Block 6 + +# 2859| Block 6 +# 2859| r2859_1(glval) = VariableAddress[x] : +# 2859| r2859_2(int) = Load[x] : &:r2859_1, m2846_6 +# 2859| r2859_3(int) = Constant[0] : +# 2859| r2859_4(bool) = CompareGT : r2859_2, r2859_3 +# 2859| v2859_5(void) = ConditionalBranch : r2859_4 +#-----| True -> Block 7 + +# 2860| Block 7 +# 2860| v2860_1(void) = NoOp : +# 2846| v2846_11(void) = ReturnVoid : +# 2846| v2846_12(void) = AliasedUse : m2846_3 +# 2846| v2846_13(void) = ExitFunction : + +# 2846| void test_assert_in_template(short, int, unsigned int) +# 2846| Block 0 +# 2846| v2846_1(void) = EnterFunction : +# 2846| m2846_2(unknown) = AliasedDefinition : +# 2846| m2846_3(unknown) = InitializeNonLocal : +# 2846| m2846_4(unknown) = Chi : total:m2846_2, partial:m2846_3 +# 2846| r2846_5(glval) = VariableAddress[x] : +# 2846| m2846_6(short) = InitializeParameter[x] : &:r2846_5 +# 2846| r2846_7(glval) = VariableAddress[y] : +# 2846| m2846_8(int) = InitializeParameter[y] : &:r2846_7 +# 2846| r2846_9(glval) = VariableAddress[u] : +# 2846| m2846_10(unsigned int) = InitializeParameter[u] : &:r2846_9 +# 2847| r2847_1(glval) = VariableAddress[x] : +# 2847| r2847_2(short) = Load[x] : &:r2847_1, m2846_6 +# 2847| r2847_3(int) = Constant[0] : +# 2847| r2847_4(bool) = CompareGT : r2847_2, r2847_3 +# 2847| v2847_5(void) = ConditionalBranch : r2847_4 +#-----| True -> Block 1 + +# 2848| Block 1 +# 2848| r2848_1(int) = Constant[0] : +# 2848| r2848_2(glval) = VariableAddress[x] : +# 2848| r2848_3(short) = Load[x] : &:r2848_2, m2846_6 +# 2848| r2848_4(bool) = CompareLT : r2848_1, r2848_3 +# 2848| v2848_5(void) = ConditionalBranch : r2848_4 +#-----| True -> Block 2 + +# 2849| Block 2 +# 2849| r2849_1(glval) = VariableAddress[x] : +# 2849| r2849_2(short) = Load[x] : &:r2849_1, m2846_6 +# 2849| r2849_3(glval) = VariableAddress[y] : +# 2849| r2849_4(int) = Load[y] : &:r2849_3, m2846_8 +# 2849| r2849_5(bool) = CompareLT : r2849_2, r2849_4 +# 2849| v2849_6(void) = ConditionalBranch : r2849_5 +#-----| True -> Block 3 + +# 2851| Block 3 +# 2851| r2851_1(glval) = VariableAddress[x] : +# 2851| r2851_2(short) = Load[x] : &:r2851_1, m2846_6 +# 2851| r2851_3(int) = Constant[2] : +# 2851| r2851_4(bool) = CompareNE : r2851_2, r2851_3 +# 2851| v2851_5(void) = ConditionalBranch : r2851_4 +#-----| True -> Block 4 + +# 2853| Block 4 +# 2853| r2853_1(glval) = VariableAddress[u] : +# 2853| r2853_2(unsigned int) = Load[u] : &:r2853_1, m2846_10 +# 2853| r2853_3(glval) = VariableAddress[x] : +# 2853| r2853_4(short) = Load[x] : &:r2853_3, m2846_6 +# 2853| r2853_5(bool) = CompareLT : r2853_2, r2853_4 +# 2853| v2853_6(void) = ConditionalBranch : r2853_5 +#-----| True -> Block 5 + +# 2856| Block 5 +# 2856| r2856_1(glval) = VariableAddress[shadowed] : +# 2856| r2856_2(glval) = VariableAddress[x] : +# 2856| r2856_3(short) = Load[x] : &:r2856_2, m2846_6 +# 2856| r2856_4(int) = Convert : r2856_3 +# 2856| m2856_5(int) = Store[shadowed] : &:r2856_1, r2856_4 +# 2857| r2857_1(glval) = VariableAddress[shadowed] : +# 2857| r2857_2(int) = Load[shadowed] : &:r2857_1, m2856_5 +# 2857| r2857_3(int) = Constant[0] : +# 2857| r2857_4(bool) = CompareGT : r2857_2, r2857_3 +# 2857| v2857_5(void) = ConditionalBranch : r2857_4 +#-----| True -> Block 6 + +# 2859| Block 6 +# 2859| r2859_1(glval) = VariableAddress[x] : +# 2859| r2859_2(short) = Load[x] : &:r2859_1, m2846_6 +# 2859| r2859_3(int) = Constant[0] : +# 2859| r2859_4(bool) = CompareGT : r2859_2, r2859_3 +# 2859| v2859_5(void) = ConditionalBranch : r2859_4 +#-----| True -> Block 7 + +# 2860| Block 7 +# 2860| v2860_1(void) = NoOp : +# 2846| v2846_11(void) = ReturnVoid : +# 2846| v2846_12(void) = AliasedUse : m2846_3 +# 2846| v2846_13(void) = ExitFunction : + +# 2865| void complex_assertions(int, bool, int) +# 2865| Block 0 +# 2865| v2865_1(void) = EnterFunction : +# 2865| m2865_2(unknown) = AliasedDefinition : +# 2865| m2865_3(unknown) = InitializeNonLocal : +# 2865| m2865_4(unknown) = Chi : total:m2865_2, partial:m2865_3 +# 2865| r2865_5(glval) = VariableAddress[x] : +# 2865| m2865_6(int) = InitializeParameter[x] : &:r2865_5 +# 2865| r2865_7(glval) = VariableAddress[b] : +# 2865| m2865_8(bool) = InitializeParameter[b] : &:r2865_7 +# 2865| r2865_9(glval) = VariableAddress[max] : +# 2865| m2865_10(int) = InitializeParameter[max] : &:r2865_9 +# 2866| r2866_1(glval) = VariableAddress[y] : +# 2866| r2866_2(int) = Constant[0] : +# 2866| v2866_3(void) = Convert : r2866_2 +# 2866| r2866_4(glval) = VariableAddress[x] : +# 2866| r2866_5(int) = Load[x] : &:r2866_4, m2865_6 +# 2866| r2866_6(int) = CopyValue : r2866_5 +# 2866| m2866_7(int) = Store[y] : &:r2866_1, r2866_6 +# 2867| r2867_1(glval) = VariableAddress[z] : +# 2867| r2867_2(glval) = VariableAddress[b] : +# 2867| r2867_3(bool) = Load[b] : &:r2867_2, m2865_8 +# 2867| v2867_4(void) = ConditionalBranch : r2867_3 +#-----| False -> Block 3 +#-----| True -> Block 2 + +# 2867| Block 1 +# 2867| m2867_5(int) = Phi : from 2:m2867_11, from 3:m2867_14 +# 2867| r2867_6(glval) = VariableAddress[#temp2867:13] : +# 2867| r2867_7(int) = Load[#temp2867:13] : &:r2867_6, m2867_5 +# 2867| m2867_8(int) = Store[z] : &:r2867_1, r2867_7 +# 2868| v2868_1(void) = NoOp : +# 2865| v2865_11(void) = ReturnVoid : +# 2865| v2865_12(void) = AliasedUse : m2865_3 +# 2865| v2865_13(void) = ExitFunction : + +# 2867| Block 2 +# 2867| r2867_9(int) = Constant[0] : +# 2867| r2867_10(glval) = VariableAddress[#temp2867:13] : +# 2867| m2867_11(int) = Store[#temp2867:13] : &:r2867_10, r2867_9 +#-----| Goto -> Block 1 + +# 2867| Block 3 +# 2867| r2867_12(int) = Constant[1] : +# 2867| r2867_13(glval) = VariableAddress[#temp2867:13] : +# 2867| m2867_14(int) = Store[#temp2867:13] : &:r2867_13, r2867_12 +#-----| Goto -> Block 1 + ir23.cpp: # 1| bool consteval_1() # 1| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ir/ir.cpp b/cpp/ql/test/library-tests/ir/ir/ir.cpp index 99876f7e9a47..c915727a7b46 100644 --- a/cpp/ql/test/library-tests/ir/ir/ir.cpp +++ b/cpp/ql/test/library-tests/ir/ir/ir.cpp @@ -2823,4 +2823,48 @@ void vla_sizeof_test5(int len1, size_t len2) { size_t z = sizeof((*&tmp1)[1]); } +// Common definitions for assertions in release builds +#define assert(x) ((void)0) +#define __analysis_assume(x) + +void test_assert_simple(int x, int y, unsigned u, int shadowed) { + assert(x > 0); + assert(0 < x); + assert(x < y); + + __analysis_assume(x != 2); + + assert(u < x); + + { + int shadowed = x; + assert(shadowed > 0); + } +} + +template +void test_assert_in_template(T x, int y, unsigned u) { + assert(x > 0); + assert(0 < x); + assert(x < y); + + __analysis_assume(x != 2); + + assert(u < x); + + { + int shadowed = x; + assert(shadowed > 0); + } + assert(x> 0); +} + +template void test_assert_in_template(int, int, unsigned); +template void test_assert_in_template(short, int, unsigned); + +void complex_assertions(int x, bool b, int max) { + int y = (assert(x > 0), x); + int z = b ? (assert(x != 0), 0) : 1; +} + // semmle-extractor-options: -std=c++20 --clang 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 94e18abb9dfa..f21b569f8873 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -18880,6 +18880,275 @@ ir.cpp: # 2821| v2821_9(void) = AliasedUse : ~m? # 2821| v2821_10(void) = ExitFunction : +# 2830| void test_assert_simple(int, int, unsigned int, int) +# 2830| Block 0 +# 2830| v2830_1(void) = EnterFunction : +# 2830| mu2830_2(unknown) = AliasedDefinition : +# 2830| mu2830_3(unknown) = InitializeNonLocal : +# 2830| r2830_4(glval) = VariableAddress[x] : +# 2830| mu2830_5(int) = InitializeParameter[x] : &:r2830_4 +# 2830| r2830_6(glval) = VariableAddress[y] : +# 2830| mu2830_7(int) = InitializeParameter[y] : &:r2830_6 +# 2830| r2830_8(glval) = VariableAddress[u] : +# 2830| mu2830_9(unsigned int) = InitializeParameter[u] : &:r2830_8 +# 2830| r2830_10(glval) = VariableAddress[shadowed] : +# 2830| mu2830_11(int) = InitializeParameter[shadowed] : &:r2830_10 +# 2831| r2831_1(glval) = VariableAddress[x] : +# 2831| r2831_2(int) = Load[x] : &:r2831_1, ~m? +# 2831| r2831_3(int) = Constant[0] : +# 2831| r2831_4(bool) = CompareGT : r2831_2, r2831_3 +# 2831| v2831_5(void) = ConditionalBranch : r2831_4 +#-----| True -> Block 1 + +# 2832| Block 1 +# 2832| r2832_1(int) = Constant[0] : +# 2832| r2832_2(glval) = VariableAddress[x] : +# 2832| r2832_3(int) = Load[x] : &:r2832_2, ~m? +# 2832| r2832_4(bool) = CompareLT : r2832_1, r2832_3 +# 2832| v2832_5(void) = ConditionalBranch : r2832_4 +#-----| True -> Block 2 + +# 2833| Block 2 +# 2833| r2833_1(glval) = VariableAddress[x] : +# 2833| r2833_2(int) = Load[x] : &:r2833_1, ~m? +# 2833| r2833_3(glval) = VariableAddress[y] : +# 2833| r2833_4(int) = Load[y] : &:r2833_3, ~m? +# 2833| r2833_5(bool) = CompareLT : r2833_2, r2833_4 +# 2833| v2833_6(void) = ConditionalBranch : r2833_5 +#-----| True -> Block 3 + +# 2835| Block 3 +# 2835| r2835_1(glval) = VariableAddress[x] : +# 2835| r2835_2(int) = Load[x] : &:r2835_1, ~m? +# 2835| r2835_3(int) = Constant[2] : +# 2835| r2835_4(bool) = CompareNE : r2835_2, r2835_3 +# 2835| v2835_5(void) = ConditionalBranch : r2835_4 +#-----| True -> Block 4 + +# 2837| Block 4 +# 2837| r2837_1(glval) = VariableAddress[u] : +# 2837| r2837_2(unsigned int) = Load[u] : &:r2837_1, ~m? +# 2837| r2837_3(glval) = VariableAddress[x] : +# 2837| r2837_4(int) = Load[x] : &:r2837_3, ~m? +# 2837| r2837_5(bool) = CompareLT : r2837_2, r2837_4 +# 2837| v2837_6(void) = ConditionalBranch : r2837_5 +#-----| True -> Block 5 + +# 2840| Block 5 +# 2840| r2840_1(glval) = VariableAddress[shadowed] : +# 2840| r2840_2(glval) = VariableAddress[x] : +# 2840| r2840_3(int) = Load[x] : &:r2840_2, ~m? +# 2840| mu2840_4(int) = Store[shadowed] : &:r2840_1, r2840_3 +# 2841| r2841_1(int) = Constant[0] : +# 2841| v2841_2(void) = Convert : r2841_1 +# 2843| v2843_1(void) = NoOp : +# 2830| v2830_12(void) = ReturnVoid : +# 2830| v2830_13(void) = AliasedUse : ~m? +# 2830| v2830_14(void) = ExitFunction : + +# 2846| void test_assert_in_template(int, int, unsigned int) +# 2846| Block 0 +# 2846| v2846_1(void) = EnterFunction : +# 2846| mu2846_2(unknown) = AliasedDefinition : +# 2846| mu2846_3(unknown) = InitializeNonLocal : +# 2846| r2846_4(glval) = VariableAddress[x] : +# 2846| mu2846_5(int) = InitializeParameter[x] : &:r2846_4 +# 2846| r2846_6(glval) = VariableAddress[y] : +# 2846| mu2846_7(int) = InitializeParameter[y] : &:r2846_6 +# 2846| r2846_8(glval) = VariableAddress[u] : +# 2846| mu2846_9(unsigned int) = InitializeParameter[u] : &:r2846_8 +# 2847| r2847_1(glval) = VariableAddress[x] : +# 2847| r2847_2(int) = Load[x] : &:r2847_1, ~m? +# 2847| r2847_3(int) = Constant[0] : +# 2847| r2847_4(bool) = CompareGT : r2847_2, r2847_3 +# 2847| v2847_5(void) = ConditionalBranch : r2847_4 +#-----| True -> Block 1 + +# 2848| Block 1 +# 2848| r2848_1(int) = Constant[0] : +# 2848| r2848_2(glval) = VariableAddress[x] : +# 2848| r2848_3(int) = Load[x] : &:r2848_2, ~m? +# 2848| r2848_4(bool) = CompareLT : r2848_1, r2848_3 +# 2848| v2848_5(void) = ConditionalBranch : r2848_4 +#-----| True -> Block 2 + +# 2849| Block 2 +# 2849| r2849_1(glval) = VariableAddress[x] : +# 2849| r2849_2(int) = Load[x] : &:r2849_1, ~m? +# 2849| r2849_3(glval) = VariableAddress[y] : +# 2849| r2849_4(int) = Load[y] : &:r2849_3, ~m? +# 2849| r2849_5(bool) = CompareLT : r2849_2, r2849_4 +# 2849| v2849_6(void) = ConditionalBranch : r2849_5 +#-----| True -> Block 3 + +# 2851| Block 3 +# 2851| r2851_1(glval) = VariableAddress[x] : +# 2851| r2851_2(int) = Load[x] : &:r2851_1, ~m? +# 2851| r2851_3(int) = Constant[2] : +# 2851| r2851_4(bool) = CompareNE : r2851_2, r2851_3 +# 2851| v2851_5(void) = ConditionalBranch : r2851_4 +#-----| True -> Block 4 + +# 2853| Block 4 +# 2853| r2853_1(glval) = VariableAddress[u] : +# 2853| r2853_2(unsigned int) = Load[u] : &:r2853_1, ~m? +# 2853| r2853_3(glval) = VariableAddress[x] : +# 2853| r2853_4(int) = Load[x] : &:r2853_3, ~m? +# 2853| r2853_5(bool) = CompareLT : r2853_2, r2853_4 +# 2853| v2853_6(void) = ConditionalBranch : r2853_5 +#-----| True -> Block 5 + +# 2856| Block 5 +# 2856| r2856_1(glval) = VariableAddress[shadowed] : +# 2856| r2856_2(glval) = VariableAddress[x] : +# 2856| r2856_3(int) = Load[x] : &:r2856_2, ~m? +# 2856| mu2856_4(int) = Store[shadowed] : &:r2856_1, r2856_3 +# 2857| r2857_1(glval) = VariableAddress[shadowed] : +# 2857| r2857_2(int) = Load[shadowed] : &:r2857_1, ~m? +# 2857| r2857_3(int) = Constant[0] : +# 2857| r2857_4(bool) = CompareGT : r2857_2, r2857_3 +# 2857| v2857_5(void) = ConditionalBranch : r2857_4 +#-----| True -> Block 6 + +# 2859| Block 6 +# 2859| r2859_1(glval) = VariableAddress[x] : +# 2859| r2859_2(int) = Load[x] : &:r2859_1, ~m? +# 2859| r2859_3(int) = Constant[0] : +# 2859| r2859_4(bool) = CompareGT : r2859_2, r2859_3 +# 2859| v2859_5(void) = ConditionalBranch : r2859_4 +#-----| True -> Block 7 + +# 2860| Block 7 +# 2860| v2860_1(void) = NoOp : +# 2846| v2846_10(void) = ReturnVoid : +# 2846| v2846_11(void) = AliasedUse : ~m? +# 2846| v2846_12(void) = ExitFunction : + +# 2846| void test_assert_in_template(short, int, unsigned int) +# 2846| Block 0 +# 2846| v2846_1(void) = EnterFunction : +# 2846| mu2846_2(unknown) = AliasedDefinition : +# 2846| mu2846_3(unknown) = InitializeNonLocal : +# 2846| r2846_4(glval) = VariableAddress[x] : +# 2846| mu2846_5(short) = InitializeParameter[x] : &:r2846_4 +# 2846| r2846_6(glval) = VariableAddress[y] : +# 2846| mu2846_7(int) = InitializeParameter[y] : &:r2846_6 +# 2846| r2846_8(glval) = VariableAddress[u] : +# 2846| mu2846_9(unsigned int) = InitializeParameter[u] : &:r2846_8 +# 2847| r2847_1(glval) = VariableAddress[x] : +# 2847| r2847_2(short) = Load[x] : &:r2847_1, ~m? +# 2847| r2847_3(int) = Constant[0] : +# 2847| r2847_4(bool) = CompareGT : r2847_2, r2847_3 +# 2847| v2847_5(void) = ConditionalBranch : r2847_4 +#-----| True -> Block 1 + +# 2848| Block 1 +# 2848| r2848_1(int) = Constant[0] : +# 2848| r2848_2(glval) = VariableAddress[x] : +# 2848| r2848_3(short) = Load[x] : &:r2848_2, ~m? +# 2848| r2848_4(bool) = CompareLT : r2848_1, r2848_3 +# 2848| v2848_5(void) = ConditionalBranch : r2848_4 +#-----| True -> Block 2 + +# 2849| Block 2 +# 2849| r2849_1(glval) = VariableAddress[x] : +# 2849| r2849_2(short) = Load[x] : &:r2849_1, ~m? +# 2849| r2849_3(glval) = VariableAddress[y] : +# 2849| r2849_4(int) = Load[y] : &:r2849_3, ~m? +# 2849| r2849_5(bool) = CompareLT : r2849_2, r2849_4 +# 2849| v2849_6(void) = ConditionalBranch : r2849_5 +#-----| True -> Block 3 + +# 2851| Block 3 +# 2851| r2851_1(glval) = VariableAddress[x] : +# 2851| r2851_2(short) = Load[x] : &:r2851_1, ~m? +# 2851| r2851_3(int) = Constant[2] : +# 2851| r2851_4(bool) = CompareNE : r2851_2, r2851_3 +# 2851| v2851_5(void) = ConditionalBranch : r2851_4 +#-----| True -> Block 4 + +# 2853| Block 4 +# 2853| r2853_1(glval) = VariableAddress[u] : +# 2853| r2853_2(unsigned int) = Load[u] : &:r2853_1, ~m? +# 2853| r2853_3(glval) = VariableAddress[x] : +# 2853| r2853_4(short) = Load[x] : &:r2853_3, ~m? +# 2853| r2853_5(bool) = CompareLT : r2853_2, r2853_4 +# 2853| v2853_6(void) = ConditionalBranch : r2853_5 +#-----| True -> Block 5 + +# 2856| Block 5 +# 2856| r2856_1(glval) = VariableAddress[shadowed] : +# 2856| r2856_2(glval) = VariableAddress[x] : +# 2856| r2856_3(short) = Load[x] : &:r2856_2, ~m? +# 2856| r2856_4(int) = Convert : r2856_3 +# 2856| mu2856_5(int) = Store[shadowed] : &:r2856_1, r2856_4 +# 2857| r2857_1(glval) = VariableAddress[shadowed] : +# 2857| r2857_2(int) = Load[shadowed] : &:r2857_1, ~m? +# 2857| r2857_3(int) = Constant[0] : +# 2857| r2857_4(bool) = CompareGT : r2857_2, r2857_3 +# 2857| v2857_5(void) = ConditionalBranch : r2857_4 +#-----| True -> Block 6 + +# 2859| Block 6 +# 2859| r2859_1(glval) = VariableAddress[x] : +# 2859| r2859_2(short) = Load[x] : &:r2859_1, ~m? +# 2859| r2859_3(int) = Constant[0] : +# 2859| r2859_4(bool) = CompareGT : r2859_2, r2859_3 +# 2859| v2859_5(void) = ConditionalBranch : r2859_4 +#-----| True -> Block 7 + +# 2860| Block 7 +# 2860| v2860_1(void) = NoOp : +# 2846| v2846_10(void) = ReturnVoid : +# 2846| v2846_11(void) = AliasedUse : ~m? +# 2846| v2846_12(void) = ExitFunction : + +# 2865| void complex_assertions(int, bool, int) +# 2865| Block 0 +# 2865| v2865_1(void) = EnterFunction : +# 2865| mu2865_2(unknown) = AliasedDefinition : +# 2865| mu2865_3(unknown) = InitializeNonLocal : +# 2865| r2865_4(glval) = VariableAddress[x] : +# 2865| mu2865_5(int) = InitializeParameter[x] : &:r2865_4 +# 2865| r2865_6(glval) = VariableAddress[b] : +# 2865| mu2865_7(bool) = InitializeParameter[b] : &:r2865_6 +# 2865| r2865_8(glval) = VariableAddress[max] : +# 2865| mu2865_9(int) = InitializeParameter[max] : &:r2865_8 +# 2866| r2866_1(glval) = VariableAddress[y] : +# 2866| r2866_2(int) = Constant[0] : +# 2866| v2866_3(void) = Convert : r2866_2 +# 2866| r2866_4(glval) = VariableAddress[x] : +# 2866| r2866_5(int) = Load[x] : &:r2866_4, ~m? +# 2866| r2866_6(int) = CopyValue : r2866_5 +# 2866| mu2866_7(int) = Store[y] : &:r2866_1, r2866_6 +# 2867| r2867_1(glval) = VariableAddress[z] : +# 2867| r2867_2(glval) = VariableAddress[b] : +# 2867| r2867_3(bool) = Load[b] : &:r2867_2, ~m? +# 2867| v2867_4(void) = ConditionalBranch : r2867_3 +#-----| False -> Block 3 +#-----| True -> Block 2 + +# 2867| Block 1 +# 2867| r2867_5(glval) = VariableAddress[#temp2867:13] : +# 2867| r2867_6(int) = Load[#temp2867:13] : &:r2867_5, ~m? +# 2867| mu2867_7(int) = Store[z] : &:r2867_1, r2867_6 +# 2868| v2868_1(void) = NoOp : +# 2865| v2865_10(void) = ReturnVoid : +# 2865| v2865_11(void) = AliasedUse : ~m? +# 2865| v2865_12(void) = ExitFunction : + +# 2867| Block 2 +# 2867| r2867_8(int) = Constant[0] : +# 2867| r2867_9(glval) = VariableAddress[#temp2867:13] : +# 2867| mu2867_10(int) = Store[#temp2867:13] : &:r2867_9, r2867_8 +#-----| Goto -> Block 1 + +# 2867| Block 3 +# 2867| r2867_11(int) = Constant[1] : +# 2867| r2867_12(glval) = VariableAddress[#temp2867:13] : +# 2867| mu2867_13(int) = Store[#temp2867:13] : &:r2867_12, r2867_11 +#-----| Goto -> Block 1 + ir23.cpp: # 1| bool consteval_1() # 1| Block 0