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 d864e86aa040..da93976c4e26 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 @@ -97,7 +97,12 @@ newtype TInstructionTag = exists(Stmt s | exists(s.getImplicitDestructorCall(index))) } or CoAwaitBranchTag() or - BoolToIntConversionTag() + BoolToIntConversionTag() or + SizeofVlaDimensionTag(int index) { + index = -1 + or + exists(VlaDeclStmt v | exists(v.getVlaDimensionStmt(index))) + } class InstructionTag extends TInstructionTag { final string toString() { result = getInstructionTagId(this) } 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 e1314035437e..330362f55603 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 @@ -123,13 +123,16 @@ private predicate ignoreExprAndDescendants(Expr expr) { // or ignoreExprAndDescendants(getRealParent(expr)) // recursive case or - // va_start doesn't evaluate its argument, so we don't need to translate it. + // va_start does not evaluate its argument, so we do not need to translate it. exists(BuiltInVarArgsStart vaStartExpr | vaStartExpr.getLastNamedParameter().getFullyConverted() = expr ) or + // sizeof does not evaluate its argument, so we do not need to translate it. + exists(SizeofExprOperator sizeofExpr | sizeofExpr.getExprOperand().getFullyConverted() = expr) + or // The children of C11 _Generic expressions are just surface syntax. - exists(C11GenericExpr generic | generic.getAChild() = expr) + exists(C11GenericExpr generic | generic.getAChild().getFullyConverted() = expr) or // Do not translate implicit destructor calls for unnamed temporary variables that are // conditionally constructed (until we have a mechanism for calling these only when the diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index f749f8b7502c..463f13f1aee7 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -187,7 +187,7 @@ Variable getEnclosingVariable(Expr e) { } /** - * The IR translation of the "core" part of an expression. This is the part of + * The IR translation of the "core" part of an expression. This is the part of * the expression that produces the result value of the expression, before any * lvalue-to-rvalue conversion on the result. Every expression has a single * `TranslatedCoreExpr`. @@ -4094,6 +4094,103 @@ class TranslatedStmtExpr extends TranslatedNonConstantExpr { TranslatedStmt getStmt() { result = getTranslatedStmt(expr.getStmt()) } } +private VlaDeclStmt getVlaDeclStmt(Expr expr, int pointerDerefCount) { + expr.(VariableAccess).getTarget() = result.getVariable() and + pointerDerefCount = 0 + or + result = getVlaDeclStmt(expr.(PointerDereferenceExpr).getOperand(), pointerDerefCount - 1) +} + +class TranslatedSizeofExpr extends TranslatedNonConstantExpr { + override SizeofExprOperator expr; + VlaDeclStmt vlaDeclStmt; + int pointerDerefCount; + + TranslatedSizeofExpr() { + vlaDeclStmt = getVlaDeclStmt(expr.getExprOperand(), pointerDerefCount) and + pointerDerefCount < vlaDeclStmt.getNumberOfVlaDimensionStmts() + } + + final override Instruction getFirstInstruction(EdgeKind kind) { + result = this.getInstruction(SizeofVlaDimensionTag(-1)) and + kind instanceof GotoEdge + } + + override Instruction getALastInstructionInternal() { + result = + this.getInstruction(SizeofVlaDimensionTag(vlaDeclStmt.getNumberOfVlaDimensionStmts() - 1)) + } + + final override TranslatedElement getChildInternal(int id) { none() } + + final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { + opcode instanceof Opcode::Constant and + tag = SizeofVlaDimensionTag(-1) and + resultType = this.getResultType() + or + opcode instanceof Opcode::Mul and + exists(int n | pointerDerefCount <= n and n < vlaDeclStmt.getNumberOfVlaDimensionStmts() | + tag = SizeofVlaDimensionTag(n) + ) and + resultType = this.getResultType() + } + + final override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { + tag = SizeofVlaDimensionTag(-1) and + result = this.getInstruction(SizeofVlaDimensionTag(pointerDerefCount)) and + kind instanceof GotoEdge + or + exists(int n | pointerDerefCount <= n and n < vlaDeclStmt.getNumberOfVlaDimensionStmts() - 1 | + tag = SizeofVlaDimensionTag(n) and + result = this.getInstruction(SizeofVlaDimensionTag(n + 1)) + ) and + kind instanceof GotoEdge + or + tag = SizeofVlaDimensionTag(vlaDeclStmt.getNumberOfVlaDimensionStmts() - 1) and + result = this.getParent().getChildSuccessor(this, kind) + } + + override string getInstructionConstantValue(InstructionTag tag) { + tag = SizeofVlaDimensionTag(-1) and + result = + this.getBaseSize(vlaDeclStmt.getVariable().getType(), + vlaDeclStmt.getNumberOfVlaDimensionStmts() - 1).toString() + } + + private int getBaseSize(DerivedType type, int n) { + n = 0 and + result = type.getBaseType().getSize() + or + n = [1 .. vlaDeclStmt.getNumberOfVlaDimensionStmts() - 1] and + result = this.getBaseSize(type.getBaseType(), n - 1) + } + + override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { + exists(int n | pointerDerefCount <= n and n < vlaDeclStmt.getNumberOfVlaDimensionStmts() | + tag = SizeofVlaDimensionTag(n) and + ( + operandTag instanceof LeftOperandTag and + ( + n - 1 >= pointerDerefCount and + result = this.getInstruction(SizeofVlaDimensionTag(n - 1)) + or + n - 1 < pointerDerefCount and + result = this.getInstruction(SizeofVlaDimensionTag(-1)) + ) + or + operandTag instanceof RightOperandTag and + result = + getTranslatedExpr(vlaDeclStmt.getVlaDimensionStmt(n).getDimensionExpr()).getResult() + ) + ) + } + + final override Instruction getResult() { + result = + this.getInstruction(SizeofVlaDimensionTag(vlaDeclStmt.getNumberOfVlaDimensionStmts() - 1)) + } +} + class TranslatedErrorExpr extends TranslatedSingleInstructionExpr { override ErrorExpr expr; diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index c3085da03ab5..b03bd3266044 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -24581,6 +24581,186 @@ ir.cpp: # 2776| Value = [CStyleCast] 42 # 2776| ValueCategory = prvalue # 2777| getStmt(2): [ReturnStmt] return ... +# 2779| [TopLevelFunction] void vla_sizeof_test(int, size_t, char) +# 2779| : +# 2779| getParameter(0): [Parameter] len1 +# 2779| Type = [IntType] int +# 2779| getParameter(1): [Parameter] len2 +# 2779| Type = [CTypedefType,Size_t] size_t +# 2779| getParameter(2): [Parameter] len3 +# 2779| Type = [PlainCharType] char +# 2780| getEntryPoint(): [BlockStmt] { ... } +# 2781| getStmt(0): [DeclStmt] declaration +# 2781| getDeclarationEntry(0): [VariableDeclarationEntry] definition of tmp1 +# 2781| Type = [ArrayType] char[] +# 2781| getStmt(1): [VlaDimensionStmt] VLA dimension size +# 2781| getDimensionExpr(): [VariableAccess] len1 +# 2781| Type = [IntType] int +# 2781| ValueCategory = prvalue(load) +# 2781| getStmt(2): [VlaDeclStmt] VLA declaration +# 2782| getStmt(3): [DeclStmt] declaration +# 2782| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x +# 2782| Type = [CTypedefType,Size_t] size_t +# 2782| getVariable().getInitializer(): [Initializer] initializer for x +# 2782| getExpr(): [SizeofExprOperator] sizeof() +# 2782| Type = [LongType] unsigned long +# 2782| ValueCategory = prvalue +# 2782| getExprOperand(): [VariableAccess] tmp1 +# 2782| Type = [ArrayType] char[] +# 2782| ValueCategory = lvalue +# 2782| getExprOperand().getFullyConverted(): [ParenthesisExpr] (...) +# 2782| Type = [ArrayType] char[] +# 2782| ValueCategory = lvalue +# 2783| getStmt(4): [DeclStmt] declaration +# 2783| getDeclarationEntry(0): [VariableDeclarationEntry] definition of tmp2 +# 2783| Type = [ArrayType] int[][] +# 2783| getStmt(5): [VlaDimensionStmt] VLA dimension size +# 2783| getDimensionExpr(): [VariableAccess] len1 +# 2783| Type = [IntType] int +# 2783| ValueCategory = prvalue(load) +# 2783| getStmt(6): [VlaDimensionStmt] VLA dimension size +# 2783| getDimensionExpr(): [VariableAccess] len2 +# 2783| Type = [CTypedefType,Size_t] size_t +# 2783| ValueCategory = prvalue(load) +# 2783| getStmt(7): [VlaDeclStmt] VLA declaration +# 2784| getStmt(8): [DeclStmt] declaration +# 2784| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y +# 2784| Type = [CTypedefType,Size_t] size_t +# 2784| getVariable().getInitializer(): [Initializer] initializer for y +# 2784| getExpr(): [SizeofExprOperator] sizeof() +# 2784| Type = [LongType] unsigned long +# 2784| ValueCategory = prvalue +# 2784| getExprOperand(): [VariableAccess] tmp2 +# 2784| Type = [ArrayType] int[][] +# 2784| ValueCategory = lvalue +# 2784| getExprOperand().getFullyConverted(): [ParenthesisExpr] (...) +# 2784| Type = [ArrayType] int[][] +# 2784| ValueCategory = lvalue +# 2785| getStmt(9): [DeclStmt] declaration +# 2785| getDeclarationEntry(0): [VariableDeclarationEntry] definition of z +# 2785| Type = [CTypedefType,Size_t] size_t +# 2785| getVariable().getInitializer(): [Initializer] initializer for z +# 2785| getExpr(): [SizeofExprOperator] sizeof() +# 2785| Type = [LongType] unsigned long +# 2785| ValueCategory = prvalue +# 2785| getExprOperand(): [PointerDereferenceExpr] * ... +# 2785| Type = [ArrayType] int[] +# 2785| ValueCategory = lvalue +# 2785| getOperand(): [VariableAccess] tmp2 +# 2785| Type = [ArrayType] int[][] +# 2785| ValueCategory = lvalue +# 2785| getOperand().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion +# 2785| Type = [PointerType] int(*)[] +# 2785| ValueCategory = prvalue +# 2785| getExprOperand().getFullyConverted(): [ParenthesisExpr] (...) +# 2785| Type = [ArrayType] int[] +# 2785| ValueCategory = lvalue +# 2786| getStmt(10): [DeclStmt] declaration +# 2786| getDeclarationEntry(0): [VariableDeclarationEntry] definition of tmp3 +# 2786| Type = [ArrayType] int[][][] +# 2786| getStmt(11): [VlaDimensionStmt] VLA dimension size +# 2786| getDimensionExpr(): [VariableAccess] len1 +# 2786| Type = [IntType] int +# 2786| ValueCategory = prvalue(load) +# 2786| getStmt(12): [VlaDimensionStmt] VLA dimension size +# 2786| getDimensionExpr(): [VariableAccess] len2 +# 2786| Type = [CTypedefType,Size_t] size_t +# 2786| ValueCategory = prvalue(load) +# 2786| getStmt(13): [VlaDimensionStmt] VLA dimension size +# 2786| getDimensionExpr(): [VariableAccess] len3 +# 2786| Type = [PlainCharType] char +# 2786| ValueCategory = prvalue(load) +# 2786| getStmt(14): [VlaDeclStmt] VLA declaration +# 2787| getStmt(15): [DeclStmt] declaration +# 2787| getDeclarationEntry(0): [VariableDeclarationEntry] definition of w +# 2787| Type = [CTypedefType,Size_t] size_t +# 2787| getVariable().getInitializer(): [Initializer] initializer for w +# 2787| getExpr(): [SizeofExprOperator] sizeof() +# 2787| Type = [LongType] unsigned long +# 2787| ValueCategory = prvalue +# 2787| getExprOperand(): [VariableAccess] tmp3 +# 2787| Type = [ArrayType] int[][][] +# 2787| ValueCategory = lvalue +# 2787| getExprOperand().getFullyConverted(): [ParenthesisExpr] (...) +# 2787| Type = [ArrayType] int[][][] +# 2787| ValueCategory = lvalue +# 2788| getStmt(16): [DeclStmt] declaration +# 2788| getDeclarationEntry(0): [VariableDeclarationEntry] definition of v +# 2788| Type = [CTypedefType,Size_t] size_t +# 2788| getVariable().getInitializer(): [Initializer] initializer for v +# 2788| getExpr(): [SizeofExprOperator] sizeof() +# 2788| Type = [LongType] unsigned long +# 2788| ValueCategory = prvalue +# 2788| getExprOperand(): [PointerDereferenceExpr] * ... +# 2788| Type = [ArrayType] int[][] +# 2788| ValueCategory = lvalue +# 2788| getOperand(): [VariableAccess] tmp3 +# 2788| Type = [ArrayType] int[][][] +# 2788| ValueCategory = lvalue +# 2788| getOperand().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion +# 2788| Type = [PointerType] int(*)[][] +# 2788| ValueCategory = prvalue +# 2788| getExprOperand().getFullyConverted(): [ParenthesisExpr] (...) +# 2788| Type = [ArrayType] int[][] +# 2788| ValueCategory = lvalue +# 2789| getStmt(17): [DeclStmt] declaration +# 2789| getDeclarationEntry(0): [VariableDeclarationEntry] definition of u +# 2789| Type = [CTypedefType,Size_t] size_t +# 2789| getVariable().getInitializer(): [Initializer] initializer for u +# 2789| getExpr(): [SizeofExprOperator] sizeof() +# 2789| Type = [LongType] unsigned long +# 2789| ValueCategory = prvalue +# 2789| getExprOperand(): [PointerDereferenceExpr] * ... +# 2789| Type = [ArrayType] int[] +# 2789| ValueCategory = lvalue +# 2789| getOperand(): [PointerDereferenceExpr] * ... +# 2789| Type = [ArrayType] int[][] +# 2789| ValueCategory = lvalue +# 2789| getOperand(): [VariableAccess] tmp3 +# 2789| Type = [ArrayType] int[][][] +# 2789| ValueCategory = lvalue +# 2789| getOperand().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion +# 2789| Type = [PointerType] int(*)[][] +# 2789| ValueCategory = prvalue +# 2789| getOperand().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion +# 2789| Type = [PointerType] int(*)[] +# 2789| ValueCategory = prvalue +# 2789| getExprOperand().getFullyConverted(): [ParenthesisExpr] (...) +# 2789| Type = [ArrayType] int[] +# 2789| ValueCategory = lvalue +# 2790| getStmt(18): [DeclStmt] declaration +# 2790| getDeclarationEntry(0): [VariableDeclarationEntry] definition of t +# 2790| Type = [CTypedefType,Size_t] size_t +# 2790| getVariable().getInitializer(): [Initializer] initializer for t +# 2790| getExpr(): [SizeofExprOperator] sizeof() +# 2790| Type = [LongType] unsigned long +# 2790| Value = [SizeofExprOperator] 4 +# 2790| ValueCategory = prvalue +# 2790| getExprOperand(): [PointerDereferenceExpr] * ... +# 2790| Type = [IntType] int +# 2790| ValueCategory = lvalue +# 2790| getOperand(): [PointerDereferenceExpr] * ... +# 2790| Type = [ArrayType] int[] +# 2790| ValueCategory = lvalue +# 2790| getOperand(): [PointerDereferenceExpr] * ... +# 2790| Type = [ArrayType] int[][] +# 2790| ValueCategory = lvalue +# 2790| getOperand(): [VariableAccess] tmp3 +# 2790| Type = [ArrayType] int[][][] +# 2790| ValueCategory = lvalue +# 2790| getOperand().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion +# 2790| Type = [PointerType] int(*)[][] +# 2790| ValueCategory = prvalue +# 2790| getOperand().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion +# 2790| Type = [PointerType] int(*)[] +# 2790| ValueCategory = prvalue +# 2790| getOperand().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion +# 2790| Type = [IntPointerType] int * +# 2790| ValueCategory = prvalue +# 2790| getExprOperand().getFullyConverted(): [ParenthesisExpr] (...) +# 2790| Type = [IntType] int +# 2790| ValueCategory = lvalue +# 2791| getStmt(19): [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 d8babdb54e20..a9896a1b3d8d 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -20430,6 +20430,75 @@ ir.cpp: # 2774| v2774_6(void) = AliasedUse : ~m2776_6 # 2774| v2774_7(void) = ExitFunction : +# 2779| void vla_sizeof_test(int, size_t, char) +# 2779| Block 0 +# 2779| v2779_1(void) = EnterFunction : +# 2779| m2779_2(unknown) = AliasedDefinition : +# 2779| m2779_3(unknown) = InitializeNonLocal : +# 2779| m2779_4(unknown) = Chi : total:m2779_2, partial:m2779_3 +# 2779| r2779_5(glval) = VariableAddress[len1] : +# 2779| m2779_6(int) = InitializeParameter[len1] : &:r2779_5 +# 2779| r2779_7(glval) = VariableAddress[len2] : +# 2779| m2779_8(unsigned long) = InitializeParameter[len2] : &:r2779_7 +# 2779| r2779_9(glval) = VariableAddress[len3] : +# 2779| m2779_10(char) = InitializeParameter[len3] : &:r2779_9 +# 2781| r2781_1(glval) = VariableAddress[tmp1] : +# 2781| m2781_2(char[]) = Uninitialized[tmp1] : &:r2781_1 +# 2781| r2781_3(glval) = VariableAddress[len1] : +# 2781| r2781_4(int) = Load[len1] : &:r2781_3, m2779_6 +# 2781| v2781_5(void) = NoOp : +# 2782| r2782_1(glval) = VariableAddress[x] : +# 2782| r2782_2(unsigned long) = Constant[1] : +# 2782| r2782_3(unsigned long) = Mul : r2782_2, r2781_4 +# 2782| m2782_4(unsigned long) = Store[x] : &:r2782_1, r2782_3 +# 2783| r2783_1(glval) = VariableAddress[tmp2] : +# 2783| m2783_2(int[][]) = Uninitialized[tmp2] : &:r2783_1 +# 2783| r2783_3(glval) = VariableAddress[len1] : +# 2783| r2783_4(int) = Load[len1] : &:r2783_3, m2779_6 +# 2783| r2783_5(glval) = VariableAddress[len2] : +# 2783| r2783_6(unsigned long) = Load[len2] : &:r2783_5, m2779_8 +# 2783| v2783_7(void) = NoOp : +# 2784| r2784_1(glval) = VariableAddress[y] : +# 2784| r2784_2(unsigned long) = Constant[4] : +# 2784| r2784_3(unsigned long) = Mul : r2784_2, r2783_4 +# 2784| r2784_4(unsigned long) = Mul : r2784_3, r2783_6 +# 2784| m2784_5(unsigned long) = Store[y] : &:r2784_1, r2784_4 +# 2785| r2785_1(glval) = VariableAddress[z] : +# 2785| r2785_2(unsigned long) = Constant[4] : +# 2785| r2785_3(unsigned long) = Mul : r2785_2, r2783_6 +# 2785| m2785_4(unsigned long) = Store[z] : &:r2785_1, r2785_3 +# 2786| r2786_1(glval) = VariableAddress[tmp3] : +# 2786| m2786_2(int[][][]) = Uninitialized[tmp3] : &:r2786_1 +# 2786| r2786_3(glval) = VariableAddress[len1] : +# 2786| r2786_4(int) = Load[len1] : &:r2786_3, m2779_6 +# 2786| r2786_5(glval) = VariableAddress[len2] : +# 2786| r2786_6(unsigned long) = Load[len2] : &:r2786_5, m2779_8 +# 2786| r2786_7(glval) = VariableAddress[len3] : +# 2786| r2786_8(char) = Load[len3] : &:r2786_7, m2779_10 +# 2786| v2786_9(void) = NoOp : +# 2787| r2787_1(glval) = VariableAddress[w] : +# 2787| r2787_2(unsigned long) = Constant[4] : +# 2787| r2787_3(unsigned long) = Mul : r2787_2, r2786_4 +# 2787| r2787_4(unsigned long) = Mul : r2787_3, r2786_6 +# 2787| r2787_5(unsigned long) = Mul : r2787_4, r2786_8 +# 2787| m2787_6(unsigned long) = Store[w] : &:r2787_1, r2787_5 +# 2788| r2788_1(glval) = VariableAddress[v] : +# 2788| r2788_2(unsigned long) = Constant[4] : +# 2788| r2788_3(unsigned long) = Mul : r2788_2, r2786_6 +# 2788| r2788_4(unsigned long) = Mul : r2788_3, r2786_8 +# 2788| m2788_5(unsigned long) = Store[v] : &:r2788_1, r2788_4 +# 2789| r2789_1(glval) = VariableAddress[u] : +# 2789| r2789_2(unsigned long) = Constant[4] : +# 2789| r2789_3(unsigned long) = Mul : r2789_2, r2786_8 +# 2789| m2789_4(unsigned long) = Store[u] : &:r2789_1, r2789_3 +# 2790| r2790_1(glval) = VariableAddress[t] : +# 2790| r2790_2(unsigned long) = Constant[4] : +# 2790| m2790_3(unsigned long) = Store[t] : &:r2790_1, r2790_2 +# 2791| v2791_1(void) = NoOp : +# 2779| v2779_11(void) = ReturnVoid : +# 2779| v2779_12(void) = AliasedUse : m2779_3 +# 2779| v2779_13(void) = ExitFunction : + 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 66af788db12d..b4fb243ecdfc 100644 --- a/cpp/ql/test/library-tests/ir/ir/ir.cpp +++ b/cpp/ql/test/library-tests/ir/ir/ir.cpp @@ -2776,4 +2776,18 @@ void test_allocation_with_initializer() { long* p2 = new long(42); } +void vla_sizeof_test(int len1, size_t len2, char len3) +{ + char tmp1[len1]; + size_t x = sizeof(tmp1); + int tmp2[len1][len2]; + size_t y = sizeof(tmp2); + size_t z = sizeof(*tmp2); + int tmp3[len1][len2][len3]; + size_t w = sizeof(tmp3); + size_t v = sizeof(*tmp3); + size_t u = sizeof(**tmp3); + size_t t = sizeof(***tmp3); +} + // 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 a567c651ca24..5b696e8460f6 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -18577,6 +18577,74 @@ ir.cpp: # 2774| v2774_5(void) = AliasedUse : ~m? # 2774| v2774_6(void) = ExitFunction : +# 2779| void vla_sizeof_test(int, size_t, char) +# 2779| Block 0 +# 2779| v2779_1(void) = EnterFunction : +# 2779| mu2779_2(unknown) = AliasedDefinition : +# 2779| mu2779_3(unknown) = InitializeNonLocal : +# 2779| r2779_4(glval) = VariableAddress[len1] : +# 2779| mu2779_5(int) = InitializeParameter[len1] : &:r2779_4 +# 2779| r2779_6(glval) = VariableAddress[len2] : +# 2779| mu2779_7(unsigned long) = InitializeParameter[len2] : &:r2779_6 +# 2779| r2779_8(glval) = VariableAddress[len3] : +# 2779| mu2779_9(char) = InitializeParameter[len3] : &:r2779_8 +# 2781| r2781_1(glval) = VariableAddress[tmp1] : +# 2781| mu2781_2(char[]) = Uninitialized[tmp1] : &:r2781_1 +# 2781| r2781_3(glval) = VariableAddress[len1] : +# 2781| r2781_4(int) = Load[len1] : &:r2781_3, ~m? +# 2781| v2781_5(void) = NoOp : +# 2782| r2782_1(glval) = VariableAddress[x] : +# 2782| r2782_2(unsigned long) = Constant[1] : +# 2782| r2782_3(unsigned long) = Mul : r2782_2, r2781_4 +# 2782| mu2782_4(unsigned long) = Store[x] : &:r2782_1, r2782_3 +# 2783| r2783_1(glval) = VariableAddress[tmp2] : +# 2783| mu2783_2(int[][]) = Uninitialized[tmp2] : &:r2783_1 +# 2783| r2783_3(glval) = VariableAddress[len1] : +# 2783| r2783_4(int) = Load[len1] : &:r2783_3, ~m? +# 2783| r2783_5(glval) = VariableAddress[len2] : +# 2783| r2783_6(unsigned long) = Load[len2] : &:r2783_5, ~m? +# 2783| v2783_7(void) = NoOp : +# 2784| r2784_1(glval) = VariableAddress[y] : +# 2784| r2784_2(unsigned long) = Constant[4] : +# 2784| r2784_3(unsigned long) = Mul : r2784_2, r2783_4 +# 2784| r2784_4(unsigned long) = Mul : r2784_3, r2783_6 +# 2784| mu2784_5(unsigned long) = Store[y] : &:r2784_1, r2784_4 +# 2785| r2785_1(glval) = VariableAddress[z] : +# 2785| r2785_2(unsigned long) = Constant[4] : +# 2785| r2785_3(unsigned long) = Mul : r2785_2, r2783_6 +# 2785| mu2785_4(unsigned long) = Store[z] : &:r2785_1, r2785_3 +# 2786| r2786_1(glval) = VariableAddress[tmp3] : +# 2786| mu2786_2(int[][][]) = Uninitialized[tmp3] : &:r2786_1 +# 2786| r2786_3(glval) = VariableAddress[len1] : +# 2786| r2786_4(int) = Load[len1] : &:r2786_3, ~m? +# 2786| r2786_5(glval) = VariableAddress[len2] : +# 2786| r2786_6(unsigned long) = Load[len2] : &:r2786_5, ~m? +# 2786| r2786_7(glval) = VariableAddress[len3] : +# 2786| r2786_8(char) = Load[len3] : &:r2786_7, ~m? +# 2786| v2786_9(void) = NoOp : +# 2787| r2787_1(glval) = VariableAddress[w] : +# 2787| r2787_2(unsigned long) = Constant[4] : +# 2787| r2787_3(unsigned long) = Mul : r2787_2, r2786_4 +# 2787| r2787_4(unsigned long) = Mul : r2787_3, r2786_6 +# 2787| r2787_5(unsigned long) = Mul : r2787_4, r2786_8 +# 2787| mu2787_6(unsigned long) = Store[w] : &:r2787_1, r2787_5 +# 2788| r2788_1(glval) = VariableAddress[v] : +# 2788| r2788_2(unsigned long) = Constant[4] : +# 2788| r2788_3(unsigned long) = Mul : r2788_2, r2786_6 +# 2788| r2788_4(unsigned long) = Mul : r2788_3, r2786_8 +# 2788| mu2788_5(unsigned long) = Store[v] : &:r2788_1, r2788_4 +# 2789| r2789_1(glval) = VariableAddress[u] : +# 2789| r2789_2(unsigned long) = Constant[4] : +# 2789| r2789_3(unsigned long) = Mul : r2789_2, r2786_8 +# 2789| mu2789_4(unsigned long) = Store[u] : &:r2789_1, r2789_3 +# 2790| r2790_1(glval) = VariableAddress[t] : +# 2790| r2790_2(unsigned long) = Constant[4] : +# 2790| mu2790_3(unsigned long) = Store[t] : &:r2790_1, r2790_2 +# 2791| v2791_1(void) = NoOp : +# 2779| v2779_10(void) = ReturnVoid : +# 2779| v2779_11(void) = AliasedUse : ~m? +# 2779| v2779_12(void) = ExitFunction : + ir23.cpp: # 1| bool consteval_1() # 1| Block 0