From 5aabd90eff2069fa4f2c2d4c96b1b83a55eb7e8c Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 24 Mar 2026 13:06:52 +0100 Subject: [PATCH 01/16] C++: Add direct and default initialization subclasses for `ConstructorFieldInit` --- cpp/ql/lib/semmle/code/cpp/exprs/Call.qll | 29 ++++++- .../library-tests/ctorinits/ctors.expected | 18 ++-- .../library-tests/ir/ir/PrintAST.expected | 82 +++++++++---------- 3 files changed, 77 insertions(+), 52 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Call.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Call.qll index 4ef241e3d258..66a89490dd09 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Call.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Call.qll @@ -585,12 +585,15 @@ class ConstructorDelegationInit extends ConstructorBaseInit, @ctordelegatinginit /** * An initialization of a member variable performed as part of a - * constructor's explicit initializer list or implicit actions. + * constructor's initializer list or by default initialization. + * * In the example below, member variable `b` is being initialized by - * constructor parameter `a`: + * constructor parameter `a`, and `c` is initialized by default + * initialization: * ``` * struct S { * int b; + * int c = 3; * S(int a): b(a) {} * } s(2); * ``` @@ -616,6 +619,28 @@ class ConstructorFieldInit extends ConstructorInit, @ctorfieldinit { override predicate mayBeGloballyImpure() { this.getExpr().mayBeGloballyImpure() } } +/** + * An initialization of a member variable performed as part of a + * constructor's explicit initializer list. + */ +class ConstructorDirectFieldInit extends ConstructorFieldInit { + ConstructorDirectFieldInit() { exists(this.getChild(0)) } + + override string getAPrimaryQlClass() { result = "ConstructorDirectFieldInit" } +} + +/** + * An initialization of a member variable performed by default + * initialization. + */ +class ConstructorDefaultFieldInit extends ConstructorFieldInit { + ConstructorDefaultFieldInit() { + not exists(this.getChild(0)) and exists(this.getTarget().getInitializer()) + } + + override string getAPrimaryQlClass() { result = "ConstructorDefaultFieldInit" } +} + /** * A call to a destructor of a base class or field as part of a destructor's * compiler-generated actions. diff --git a/cpp/ql/test/library-tests/ctorinits/ctors.expected b/cpp/ql/test/library-tests/ctorinits/ctors.expected index 8a14ee6001ae..e8eba3385606 100644 --- a/cpp/ql/test/library-tests/ctorinits/ctors.expected +++ b/cpp/ql/test/library-tests/ctorinits/ctors.expected @@ -1,17 +1,17 @@ -| ctorinits.cpp:5:3:5:10 | NoisyInt | 0 | ConstructorFieldInit | ctorinits.cpp:5:29:5:42 | constructor init of field m_value | 1 | 0 | -| ctorinits.cpp:13:3:13:11 | NoisyPair | 0 | ConstructorFieldInit | ctorinits.cpp:14:7:14:16 | constructor init of field m_fst | 1 | 0 | -| ctorinits.cpp:13:3:13:11 | NoisyPair | 1 | ConstructorFieldInit | ctorinits.cpp:15:7:15:16 | constructor init of field m_snd | 1 | 0 | +| ctorinits.cpp:5:3:5:10 | NoisyInt | 0 | ConstructorDirectFieldInit | ctorinits.cpp:5:29:5:42 | constructor init of field m_value | 1 | 0 | +| ctorinits.cpp:13:3:13:11 | NoisyPair | 0 | ConstructorDirectFieldInit | ctorinits.cpp:14:7:14:16 | constructor init of field m_fst | 1 | 0 | +| ctorinits.cpp:13:3:13:11 | NoisyPair | 1 | ConstructorDirectFieldInit | ctorinits.cpp:15:7:15:16 | constructor init of field m_snd | 1 | 0 | | ctorinits.cpp:16:3:16:11 | NoisyPair | 0 | ConstructorDelegationInit | ctorinits.cpp:16:17:16:31 | call to NoisyPair | 2 | 2 | | ctorinits.cpp:21:8:21:8 | NoisyTriple | 0 | ConstructorDirectInit | ctorinits.cpp:21:8:21:8 | call to NoisyPair | 0 | 0 | -| ctorinits.cpp:21:8:21:8 | NoisyTriple | 1 | ConstructorFieldInit | ctorinits.cpp:21:8:21:8 | constructor init of field m_third | 1 | 0 | -| ctorinits.cpp:28:2:28:9 | ArrayInt | 0 | ConstructorFieldInit | ctorinits.cpp:28:13:28:13 | constructor init of field m_array | 1 | 0 | -| ctorinits.cpp:42:2:42:16 | ArrayMemberInit | 0 | ConstructorFieldInit | ctorinits.cpp:42:22:42:32 | constructor init of field xs | 1 | 4 | +| ctorinits.cpp:21:8:21:8 | NoisyTriple | 1 | ConstructorDirectFieldInit | ctorinits.cpp:21:8:21:8 | constructor init of field m_third | 1 | 0 | +| ctorinits.cpp:28:2:28:9 | ArrayInt | 0 | ConstructorDirectFieldInit | ctorinits.cpp:28:13:28:13 | constructor init of field m_array | 1 | 0 | +| ctorinits.cpp:42:2:42:16 | ArrayMemberInit | 0 | ConstructorDirectFieldInit | ctorinits.cpp:42:22:42:32 | constructor init of field xs | 1 | 4 | | ctorinits.cpp:65:3:65:15 | MultipleBases | 0 | ConstructorDirectInit | ctorinits.cpp:69:5:69:8 | call to A | 1 | 1 | | ctorinits.cpp:65:3:65:15 | MultipleBases | 1 | ConstructorDirectInit | ctorinits.cpp:67:5:67:8 | call to B | 1 | 1 | | ctorinits.cpp:65:3:65:15 | MultipleBases | 2 | ConstructorDirectInit | ctorinits.cpp:70:5:70:8 | call to C | 1 | 1 | -| ctorinits.cpp:65:3:65:15 | MultipleBases | 3 | ConstructorFieldInit | ctorinits.cpp:68:5:68:8 | constructor init of field x | 1 | 1 | -| ctorinits.cpp:65:3:65:15 | MultipleBases | 4 | ConstructorFieldInit | ctorinits.cpp:71:5:71:8 | constructor init of field y | 1 | 1 | -| ctorinits.cpp:65:3:65:15 | MultipleBases | 5 | ConstructorFieldInit | ctorinits.cpp:66:5:66:8 | constructor init of field z | 1 | 1 | +| ctorinits.cpp:65:3:65:15 | MultipleBases | 3 | ConstructorDirectFieldInit | ctorinits.cpp:68:5:68:8 | constructor init of field x | 1 | 1 | +| ctorinits.cpp:65:3:65:15 | MultipleBases | 4 | ConstructorDirectFieldInit | ctorinits.cpp:71:5:71:8 | constructor init of field y | 1 | 1 | +| ctorinits.cpp:65:3:65:15 | MultipleBases | 5 | ConstructorDirectFieldInit | ctorinits.cpp:66:5:66:8 | constructor init of field z | 1 | 1 | | ctorinits.cpp:81:8:81:8 | VD | 0 | ConstructorVirtualInit | ctorinits.cpp:81:8:81:8 | call to VB | 0 | 0 | | ctorinits.cpp:85:3:85:22 | VirtualAndNonVirtual | 0 | ConstructorVirtualInit | ctorinits.cpp:85:26:85:26 | call to VB | 0 | 0 | | ctorinits.cpp:85:3:85:22 | VirtualAndNonVirtual | 1 | ConstructorDirectInit | ctorinits.cpp:85:26:85:26 | call to VD | 0 | 0 | diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 45666a3b50b8..ec5db0c84006 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -277,7 +277,7 @@ bad_asts.cpp: #-----| getParameter(0): [Parameter] (unnamed parameter 0) #-----| Type = [LValueReferenceType] const Point & # 19| : -# 19| getInitializer(0): [ConstructorFieldInit] constructor init of field x +# 19| getInitializer(0): [ConstructorDirectFieldInit] constructor init of field x # 19| Type = [IntType] int # 19| ValueCategory = prvalue # 19| getExpr(): [ReferenceFieldAccess] x @@ -289,7 +289,7 @@ bad_asts.cpp: # 19| getQualifier().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) # 19| Type = [SpecifiedType] const Point # 19| ValueCategory = lvalue -# 19| getInitializer(1): [ConstructorFieldInit] constructor init of field y +# 19| getInitializer(1): [ConstructorDirectFieldInit] constructor init of field y # 19| Type = [IntType] int # 19| ValueCategory = prvalue # 19| getExpr(): [ReferenceFieldAccess] y @@ -8986,20 +8986,20 @@ ir.cpp: # 658| [Constructor] void C::C() # 658| : # 658| : -# 659| getInitializer(0): [ConstructorFieldInit] constructor init of field m_a +# 659| getInitializer(0): [ConstructorDirectFieldInit] constructor init of field m_a # 659| Type = [IntType] int # 659| ValueCategory = prvalue # 659| getExpr(): [Literal] 1 # 659| Type = [IntType] int # 659| Value = [Literal] 1 # 659| ValueCategory = prvalue -# 663| getInitializer(1): [ConstructorFieldInit] constructor init of field m_b +# 663| getInitializer(1): [ConstructorDirectFieldInit] constructor init of field m_b # 663| Type = [Struct] String # 663| ValueCategory = prvalue # 663| getExpr(): [ConstructorCall] call to String # 663| Type = [VoidType] void # 663| ValueCategory = prvalue -# 660| getInitializer(2): [ConstructorFieldInit] constructor init of field m_c +# 660| getInitializer(2): [ConstructorDirectFieldInit] constructor init of field m_c # 660| Type = [PlainCharType] char # 660| ValueCategory = prvalue # 660| getExpr(): [Literal] 3 @@ -9011,14 +9011,14 @@ ir.cpp: # 660| Type = [PlainCharType] char # 660| Value = [CStyleCast] 3 # 660| ValueCategory = prvalue -# 661| getInitializer(3): [ConstructorFieldInit] constructor init of field m_e +# 661| getInitializer(3): [ConstructorDirectFieldInit] constructor init of field m_e # 661| Type = [VoidPointerType] void * # 661| ValueCategory = prvalue # 661| getExpr(): [Literal] 0 # 661| Type = [VoidPointerType] void * # 661| Value = [Literal] 0 # 661| ValueCategory = prvalue -# 662| getInitializer(4): [ConstructorFieldInit] constructor init of field m_f +# 662| getInitializer(4): [ConstructorDirectFieldInit] constructor init of field m_f # 662| Type = [Struct] String # 662| ValueCategory = prvalue # 662| getExpr(): [ConstructorCall] call to String @@ -9474,7 +9474,7 @@ ir.cpp: #-----| getParameter(0): [Parameter] (unnamed parameter 0) #-----| Type = [LValueReferenceType] const Base & # 745| : -# 745| getInitializer(0): [ConstructorFieldInit] constructor init of field base_s +# 745| getInitializer(0): [ConstructorDirectFieldInit] constructor init of field base_s # 745| Type = [Struct] String # 745| ValueCategory = prvalue # 745| getExpr(): [ConstructorCall] call to String @@ -9485,7 +9485,7 @@ ir.cpp: # 748| [Constructor] void Base::Base() # 748| : # 748| : -# 748| getInitializer(0): [ConstructorFieldInit] constructor init of field base_s +# 748| getInitializer(0): [ConstructorDirectFieldInit] constructor init of field base_s # 748| Type = [Struct] String # 748| ValueCategory = prvalue # 748| getExpr(): [ConstructorCall] call to String @@ -9593,7 +9593,7 @@ ir.cpp: # 757| getInitializer(0): [ConstructorDirectInit] call to Base # 757| Type = [VoidType] void # 757| ValueCategory = prvalue -# 757| getInitializer(1): [ConstructorFieldInit] constructor init of field middle_s +# 757| getInitializer(1): [ConstructorDirectFieldInit] constructor init of field middle_s # 757| Type = [Struct] String # 757| ValueCategory = prvalue # 757| getExpr(): [ConstructorCall] call to String @@ -9704,7 +9704,7 @@ ir.cpp: # 766| getInitializer(0): [ConstructorDirectInit] call to Middle # 766| Type = [VoidType] void # 766| ValueCategory = prvalue -# 766| getInitializer(1): [ConstructorFieldInit] constructor init of field derived_s +# 766| getInitializer(1): [ConstructorDirectFieldInit] constructor init of field derived_s # 766| Type = [Struct] String # 766| ValueCategory = prvalue # 766| getExpr(): [ConstructorCall] call to String @@ -9743,7 +9743,7 @@ ir.cpp: # 775| getInitializer(0): [ConstructorVirtualInit] call to Base # 775| Type = [VoidType] void # 775| ValueCategory = prvalue -# 775| getInitializer(1): [ConstructorFieldInit] constructor init of field middlevb1_s +# 775| getInitializer(1): [ConstructorDirectFieldInit] constructor init of field middlevb1_s # 775| Type = [Struct] String # 775| ValueCategory = prvalue # 775| getExpr(): [ConstructorCall] call to String @@ -9782,7 +9782,7 @@ ir.cpp: # 784| getInitializer(0): [ConstructorVirtualInit] call to Base # 784| Type = [VoidType] void # 784| ValueCategory = prvalue -# 784| getInitializer(1): [ConstructorFieldInit] constructor init of field middlevb2_s +# 784| getInitializer(1): [ConstructorDirectFieldInit] constructor init of field middlevb2_s # 784| Type = [Struct] String # 784| ValueCategory = prvalue # 784| getExpr(): [ConstructorCall] call to String @@ -9827,7 +9827,7 @@ ir.cpp: # 793| getInitializer(2): [ConstructorDirectInit] call to MiddleVB2 # 793| Type = [VoidType] void # 793| ValueCategory = prvalue -# 793| getInitializer(3): [ConstructorFieldInit] constructor init of field derivedvb_s +# 793| getInitializer(3): [ConstructorDirectFieldInit] constructor init of field derivedvb_s # 793| Type = [Struct] String # 793| ValueCategory = prvalue # 793| getExpr(): [ConstructorCall] call to String @@ -15190,7 +15190,7 @@ ir.cpp: # 1508| getInitializer(0): [ConstructorInit] constructor init # 1508| Type = [Struct] Inheritance_Test_B # 1508| ValueCategory = prvalue -# 1508| getInitializer(1): [ConstructorFieldInit] constructor init of field x +# 1508| getInitializer(1): [ConstructorDirectFieldInit] constructor init of field x # 1508| Type = [IntType] int # 1508| ValueCategory = prvalue # 1508| getExpr(): [Literal] 42 @@ -15414,7 +15414,7 @@ ir.cpp: # 1533| [Constructor] void StructuredBindingDataMemberMemberStruct::StructuredBindingDataMemberMemberStruct() # 1533| : # 1533| : -# 1533| getInitializer(0): [ConstructorFieldInit] constructor init of field x +# 1533| getInitializer(0): [ConstructorDefaultFieldInit] constructor init of field x # 1533| Type = [IntType] int # 1533| ValueCategory = prvalue # 1533| getEntryPoint(): [BlockStmt] { ... } @@ -15434,25 +15434,25 @@ ir.cpp: # 1537| [Constructor] void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() # 1537| : # 1537| : -# 1537| getInitializer(0): [ConstructorFieldInit] constructor init of field i +# 1537| getInitializer(0): [ConstructorDefaultFieldInit] constructor init of field i # 1537| Type = [IntType] int # 1537| ValueCategory = prvalue -# 1537| getInitializer(1): [ConstructorFieldInit] constructor init of field d +# 1537| getInitializer(1): [ConstructorDefaultFieldInit] constructor init of field d # 1537| Type = [DoubleType] double # 1537| ValueCategory = prvalue -# 1537| getInitializer(2): [ConstructorFieldInit] constructor init of field r +# 1537| getInitializer(2): [ConstructorDefaultFieldInit] constructor init of field r # 1537| Type = [LValueReferenceType] int & # 1537| ValueCategory = prvalue -# 1537| getInitializer(3): [ConstructorFieldInit] constructor init of field p +# 1537| getInitializer(3): [ConstructorDefaultFieldInit] constructor init of field p # 1537| Type = [IntPointerType] int * # 1537| ValueCategory = prvalue -# 1537| getInitializer(4): [ConstructorFieldInit] constructor init of field xs +# 1537| getInitializer(4): [ConstructorDefaultFieldInit] constructor init of field xs # 1537| Type = [CTypedefType,NestedTypedefType] ArrayType # 1537| ValueCategory = prvalue -# 1537| getInitializer(5): [ConstructorFieldInit] constructor init of field r_alt +# 1537| getInitializer(5): [ConstructorDefaultFieldInit] constructor init of field r_alt # 1537| Type = [CTypedefType,NestedTypedefType] RefType # 1537| ValueCategory = prvalue -# 1537| getInitializer(6): [ConstructorFieldInit] constructor init of field m +# 1537| getInitializer(6): [ConstructorDirectFieldInit] constructor init of field m # 1537| Type = [Struct] StructuredBindingDataMemberMemberStruct # 1537| ValueCategory = prvalue # 1537| getExpr(): [ConstructorCall] call to StructuredBindingDataMemberMemberStruct @@ -15465,7 +15465,7 @@ ir.cpp: #-----| getParameter(0): [Parameter] (unnamed parameter 0) #-----| Type = [LValueReferenceType] const StructuredBindingDataMemberStruct & # 1537| : -# 1537| getInitializer(0): [ConstructorFieldInit] constructor init of field i +# 1537| getInitializer(0): [ConstructorDirectFieldInit] constructor init of field i # 1537| Type = [IntType] int # 1537| ValueCategory = prvalue # 1537| getExpr(): [ReferenceFieldAccess] i @@ -15477,7 +15477,7 @@ ir.cpp: # 1537| getQualifier().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) # 1537| Type = [SpecifiedType] const StructuredBindingDataMemberStruct # 1537| ValueCategory = lvalue -# 1537| getInitializer(1): [ConstructorFieldInit] constructor init of field d +# 1537| getInitializer(1): [ConstructorDirectFieldInit] constructor init of field d # 1537| Type = [DoubleType] double # 1537| ValueCategory = prvalue # 1537| getExpr(): [ReferenceFieldAccess] d @@ -15489,7 +15489,7 @@ ir.cpp: # 1537| getQualifier().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) # 1537| Type = [SpecifiedType] const StructuredBindingDataMemberStruct # 1537| ValueCategory = lvalue -# 1537| getInitializer(2): [ConstructorFieldInit] constructor init of field b +# 1537| getInitializer(2): [ConstructorDirectFieldInit] constructor init of field b # 1537| Type = [IntType] unsigned int # 1537| ValueCategory = prvalue # 1537| getExpr(): [ReferenceFieldAccess] b @@ -15501,7 +15501,7 @@ ir.cpp: # 1537| getQualifier().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) # 1537| Type = [SpecifiedType] const StructuredBindingDataMemberStruct # 1537| ValueCategory = lvalue -# 1537| getInitializer(3): [ConstructorFieldInit] constructor init of field r +# 1537| getInitializer(3): [ConstructorDirectFieldInit] constructor init of field r # 1537| Type = [LValueReferenceType] int & # 1537| ValueCategory = prvalue # 1537| getExpr(): [ReferenceFieldAccess] r @@ -15513,7 +15513,7 @@ ir.cpp: # 1537| getQualifier().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) # 1537| Type = [SpecifiedType] const StructuredBindingDataMemberStruct # 1537| ValueCategory = lvalue -# 1537| getInitializer(4): [ConstructorFieldInit] constructor init of field p +# 1537| getInitializer(4): [ConstructorDirectFieldInit] constructor init of field p # 1537| Type = [IntPointerType] int * # 1537| ValueCategory = prvalue # 1537| getExpr(): [ReferenceFieldAccess] p @@ -15525,7 +15525,7 @@ ir.cpp: # 1537| getQualifier().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) # 1537| Type = [SpecifiedType] const StructuredBindingDataMemberStruct # 1537| ValueCategory = lvalue -# 1537| getInitializer(5): [ConstructorFieldInit] constructor init of field xs +# 1537| getInitializer(5): [ConstructorDirectFieldInit] constructor init of field xs # 1537| Type = [CTypedefType,NestedTypedefType] ArrayType # 1537| ValueCategory = prvalue # 1537| getExpr(): [ReferenceFieldAccess] xs @@ -15537,7 +15537,7 @@ ir.cpp: # 1537| getQualifier().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) # 1537| Type = [SpecifiedType] const StructuredBindingDataMemberStruct # 1537| ValueCategory = lvalue -# 1537| getInitializer(6): [ConstructorFieldInit] constructor init of field r_alt +# 1537| getInitializer(6): [ConstructorDirectFieldInit] constructor init of field r_alt # 1537| Type = [CTypedefType,NestedTypedefType] RefType # 1537| ValueCategory = prvalue # 1537| getExpr(): [ReferenceFieldAccess] r_alt @@ -15549,7 +15549,7 @@ ir.cpp: # 1537| getQualifier().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) # 1537| Type = [SpecifiedType] const StructuredBindingDataMemberStruct # 1537| ValueCategory = lvalue -# 1537| getInitializer(7): [ConstructorFieldInit] constructor init of field m +# 1537| getInitializer(7): [ConstructorDirectFieldInit] constructor init of field m # 1537| Type = [Struct] StructuredBindingDataMemberMemberStruct # 1537| ValueCategory = prvalue # 1537| getExpr(): [ReferenceFieldAccess] m @@ -15918,13 +15918,13 @@ ir.cpp: # 1590| [Constructor] void StructuredBindingTupleRefGet::StructuredBindingTupleRefGet() # 1590| : # 1590| : -# 1590| getInitializer(0): [ConstructorFieldInit] constructor init of field i +# 1590| getInitializer(0): [ConstructorDefaultFieldInit] constructor init of field i # 1590| Type = [IntType] int # 1590| ValueCategory = prvalue -# 1590| getInitializer(1): [ConstructorFieldInit] constructor init of field d +# 1590| getInitializer(1): [ConstructorDefaultFieldInit] constructor init of field d # 1590| Type = [DoubleType] double # 1590| ValueCategory = prvalue -# 1590| getInitializer(2): [ConstructorFieldInit] constructor init of field r +# 1590| getInitializer(2): [ConstructorDefaultFieldInit] constructor init of field r # 1590| Type = [LValueReferenceType] int & # 1590| ValueCategory = prvalue # 1590| getEntryPoint(): [BlockStmt] { ... } @@ -15934,7 +15934,7 @@ ir.cpp: #-----| getParameter(0): [Parameter] (unnamed parameter 0) #-----| Type = [LValueReferenceType] const StructuredBindingTupleRefGet & # 1590| : -# 1590| getInitializer(0): [ConstructorFieldInit] constructor init of field i +# 1590| getInitializer(0): [ConstructorDirectFieldInit] constructor init of field i # 1590| Type = [IntType] int # 1590| ValueCategory = prvalue # 1590| getExpr(): [ReferenceFieldAccess] i @@ -15946,7 +15946,7 @@ ir.cpp: # 1590| getQualifier().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) # 1590| Type = [SpecifiedType] const StructuredBindingTupleRefGet # 1590| ValueCategory = lvalue -# 1590| getInitializer(1): [ConstructorFieldInit] constructor init of field d +# 1590| getInitializer(1): [ConstructorDirectFieldInit] constructor init of field d # 1590| Type = [DoubleType] double # 1590| ValueCategory = prvalue # 1590| getExpr(): [ReferenceFieldAccess] d @@ -15958,7 +15958,7 @@ ir.cpp: # 1590| getQualifier().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference) # 1590| Type = [SpecifiedType] const StructuredBindingTupleRefGet # 1590| ValueCategory = lvalue -# 1590| getInitializer(2): [ConstructorFieldInit] constructor init of field r +# 1590| getInitializer(2): [ConstructorDirectFieldInit] constructor init of field r # 1590| Type = [LValueReferenceType] int & # 1590| ValueCategory = prvalue # 1590| getExpr(): [ReferenceFieldAccess] r @@ -16327,10 +16327,10 @@ ir.cpp: # 1657| [Constructor] void StructuredBindingTupleNoRefGet::StructuredBindingTupleNoRefGet() # 1657| : # 1657| : -# 1657| getInitializer(0): [ConstructorFieldInit] constructor init of field i +# 1657| getInitializer(0): [ConstructorDefaultFieldInit] constructor init of field i # 1657| Type = [IntType] int # 1657| ValueCategory = prvalue -# 1657| getInitializer(1): [ConstructorFieldInit] constructor init of field r +# 1657| getInitializer(1): [ConstructorDefaultFieldInit] constructor init of field r # 1657| Type = [LValueReferenceType] int & # 1657| ValueCategory = prvalue # 1657| getEntryPoint(): [BlockStmt] { ... } @@ -19817,7 +19817,7 @@ ir.cpp: #-----| getParameter(0): [Parameter] (unnamed parameter 0) #-----| Type = [LValueReferenceType] const ClassWithDestructor & # 2188| : -# 2188| getInitializer(0): [ConstructorFieldInit] constructor init of field x +# 2188| getInitializer(0): [ConstructorDirectFieldInit] constructor init of field x # 2188| Type = [CharPointerType] char * # 2188| ValueCategory = prvalue # 2188| getExpr(): [ReferenceFieldAccess] x @@ -50386,7 +50386,7 @@ perf-regression.cpp: # 6| [Constructor] void Big::Big() # 6| : # 6| : -# 6| getInitializer(0): [ConstructorFieldInit] constructor init of field buffer +# 6| getInitializer(0): [ConstructorDirectFieldInit] constructor init of field buffer # 6| Type = [ArrayType] char[1073741824] # 6| ValueCategory = prvalue # 6| getExpr(): [ArrayAggregateLiteral] {...} From 07603a835a6a8b763907f25a2f19753442d156cf Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 24 Mar 2026 14:36:02 +0100 Subject: [PATCH 02/16] C++: Rename `CallOrAllocationExpr` to something more generic --- .../ir/implementation/raw/internal/SideEffects.qll | 12 ++++++------ .../raw/internal/TranslatedElement.qll | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll index 008637812573..b7b4be7f7877 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll @@ -130,13 +130,13 @@ private predicate hasDefaultSideEffect(Call call, ParameterIndex i, boolean buff } /** - * A `Call` or `NewOrNewArrayExpr` or `DeleteOrDeleteArrayExpr`. + * An expression that can have call side effects. * - * All kinds of expression invoke a function as part of their evaluation. This class provides a - * way to treat both kinds of function similarly, and to get the invoked `Function`. + * All kinds of expressions invoke a function as part of their evaluation. This class provides a + * way to treat those functions similarly, and to get the invoked `Function`. */ -class CallOrAllocationExpr extends Expr { - CallOrAllocationExpr() { +class ExprWithCallSizeEffects extends Expr { + ExprWithCallSizeEffects() { this instanceof Call or this instanceof NewOrNewArrayExpr @@ -158,7 +158,7 @@ class CallOrAllocationExpr extends Expr { * Returns the side effect opcode, if any, that represents any side effects not specifically modeled * by an argument side effect. */ -Opcode getCallSideEffectOpcode(CallOrAllocationExpr expr) { +Opcode getCallSideEffectOpcode(ExprWithCallSizeEffects expr) { not exists(expr.getTarget().(SideEffectFunction)) and result instanceof Opcode::CallSideEffect or exists(SideEffectFunction sideEffectFunction | 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 9829388ef177..93d7e9b02cfc 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 @@ -871,7 +871,7 @@ newtype TTranslatedElement = // The declaration/initialization part of a `ConditionDeclExpr` TTranslatedConditionDecl(ConditionDeclExpr expr) { not ignoreExpr(expr) } or // The side effects of a `Call` - TTranslatedCallSideEffects(CallOrAllocationExpr expr) { + TTranslatedCallSideEffects(ExprWithCallSizeEffects expr) { not ignoreExpr(expr) and not ignoreSideEffects(expr) } or From 59c27a2196873064d37bd56d8ea9bbbc3307c2ef Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 27 Feb 2026 14:38:46 +0100 Subject: [PATCH 03/16] C++: Add NSDMI tests --- .../library-tests/ir/ir/PrintAST.expected | 91 +++++++++++++++++++ .../library-tests/ir/ir/aliased_ir.expected | 60 ++++++++++++ cpp/ql/test/library-tests/ir/ir/ir.cpp | 15 +++ .../ir/ir/raw_consistency.expected | 3 + .../test/library-tests/ir/ir/raw_ir.expected | 87 ++++++++++++++++++ 5 files changed, 256 insertions(+) diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index ec5db0c84006..c9c1334a3913 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -25642,6 +25642,97 @@ ir.cpp: # 2884| Type = [VoidType] void # 2884| ValueCategory = prvalue # 2886| getStmt(6): [ReturnStmt] return ... +# 2889| [CopyAssignmentOperator] StructInit& StructInit::operator=(StructInit const&) +# 2889| : +#-----| getParameter(0): [Parameter] (unnamed parameter 0) +#-----| Type = [LValueReferenceType] const StructInit & +# 2889| [MoveAssignmentOperator] StructInit& StructInit::operator=(StructInit&&) +# 2889| : +#-----| getParameter(0): [Parameter] (unnamed parameter 0) +#-----| Type = [RValueReferenceType] StructInit && +# 2889| [CopyConstructor] void StructInit::StructInit(StructInit const&) +# 2889| : +#-----| getParameter(0): [Parameter] (unnamed parameter 0) +#-----| Type = [LValueReferenceType] const StructInit & +# 2889| [MoveConstructor] void StructInit::StructInit(StructInit&&) +# 2889| : +#-----| getParameter(0): [Parameter] (unnamed parameter 0) +#-----| Type = [RValueReferenceType] StructInit && +# 2897| [Constructor] void StructInit::StructInit(int) +# 2897| : +# 2897| getParameter(0): [Parameter] j +# 2897| Type = [IntType] int +# 2897| : +# 2897| getInitializer(0): [ConstructorDefaultFieldInit] constructor init of field i +# 2897| Type = [IntType] int +# 2897| ValueCategory = prvalue +# 2897| getInitializer(1): [ConstructorDirectFieldInit] constructor init of field j +# 2897| Type = [IntType] int +# 2897| ValueCategory = prvalue +# 2897| getExpr(): [VariableAccess] j +# 2897| Type = [IntType] int +# 2897| ValueCategory = prvalue(load) +# 2897| getInitializer(2): [ConstructorDefaultFieldInit] constructor init of field k +# 2897| Type = [IntType] int +# 2897| ValueCategory = prvalue +# 2897| getInitializer(3): [ConstructorDefaultFieldInit] constructor init of field l +# 2897| Type = [IntType] int +# 2897| ValueCategory = prvalue +# 2897| getInitializer(4): [ConstructorDefaultFieldInit] constructor init of field m +# 2897| Type = [IntType] int +# 2897| ValueCategory = prvalue +# 2897| getInitializer(5): [ConstructorDirectFieldInit] constructor init of field n +# 2897| Type = [IntType] int +# 2897| ValueCategory = prvalue +# 2897| getExpr(): [FunctionCall] call to get_val +# 2897| Type = [IntType] int +# 2897| ValueCategory = prvalue +# 2897| getQualifier(): [ThisExpr] this +# 2897| Type = [PointerType] StructInit * +# 2897| ValueCategory = prvalue(load) +# 2897| getEntryPoint(): [BlockStmt] { ... } +# 2897| getStmt(0): [ReturnStmt] return ... +# 2899| [Constructor] void StructInit::StructInit() +# 2899| : +# 2899| : +# 2899| getInitializer(0): [ConstructorDirectFieldInit] constructor init of field i +# 2899| Type = [IntType] int +# 2899| ValueCategory = prvalue +# 2899| getExpr(): [Literal] 41 +# 2899| Type = [IntType] int +# 2899| Value = [Literal] 41 +# 2899| ValueCategory = prvalue +# 2899| getInitializer(1): [ConstructorDefaultFieldInit] constructor init of field j +# 2899| Type = [IntType] int +# 2899| ValueCategory = prvalue +# 2899| getInitializer(2): [ConstructorDirectFieldInit] constructor init of field k +# 2899| Type = [IntType] int +# 2899| ValueCategory = prvalue +# 2899| getExpr(): [Literal] 41 +# 2899| Type = [IntType] int +# 2899| Value = [Literal] 41 +# 2899| ValueCategory = prvalue +# 2899| getInitializer(3): [ConstructorDefaultFieldInit] constructor init of field l +# 2899| Type = [IntType] int +# 2899| ValueCategory = prvalue +# 2899| getInitializer(4): [ConstructorDefaultFieldInit] constructor init of field m +# 2899| Type = [IntType] int +# 2899| ValueCategory = prvalue +# 2899| getInitializer(5): [ConstructorDefaultFieldInit] constructor init of field n +# 2899| Type = [IntType] int +# 2899| ValueCategory = prvalue +# 2899| getEntryPoint(): [BlockStmt] { ... } +# 2899| getStmt(0): [ReturnStmt] return ... +# 2901| [MemberFunction] int StructInit::get_val() +# 2901| : +# 2901| getEntryPoint(): [BlockStmt] { ... } +# 2901| getStmt(0): [ReturnStmt] return ... +# 2901| getExpr(): [ImplicitThisFieldAccess,PointerFieldAccess] k +# 2901| Type = [IntType] int +# 2901| ValueCategory = prvalue(load) +# 2901| getQualifier(): [ThisExpr] this +# 2901| Type = [PointerType] StructInit * +# 2901| ValueCategory = prvalue(load) 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 369cc9495a2b..5d2b92aed738 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -21066,6 +21066,66 @@ ir.cpp: # 2867| v2867_14(void) = ReturnVoid : #-----| Goto -> Block 1 +# 2897| void StructInit::StructInit(int) +# 2897| Block 0 +# 2897| v2897_1(void) = EnterFunction : +# 2897| m2897_2(unknown) = AliasedDefinition : +# 2897| m2897_3(unknown) = InitializeNonLocal : +# 2897| m2897_4(unknown) = Chi : total:m2897_2, partial:m2897_3 +# 2897| r2897_5(glval) = VariableAddress[#this] : +# 2897| m2897_6(glval) = InitializeParameter[#this] : &:r2897_5 +# 2897| r2897_7(glval) = Load[#this] : &:r2897_5, m2897_6 +# 2897| m2897_8(StructInit) = InitializeIndirection[#this] : &:r2897_7 +# 2897| r2897_9(glval) = VariableAddress[j] : +# 2897| m2897_10(int) = InitializeParameter[j] : &:r2897_9 +# 2897| v2897_11(void) = NoOp : +# 2897| v2897_12(void) = ReturnIndirection[#this] : &:r2897_7, m2897_8 +# 2897| v2897_13(void) = ReturnVoid : +# 2897| v2897_14(void) = AliasedUse : m2897_3 +# 2897| v2897_15(void) = ExitFunction : + +# 2899| void StructInit::StructInit() +# 2899| Block 0 +# 2899| v2899_1(void) = EnterFunction : +# 2899| m2899_2(unknown) = AliasedDefinition : +# 2899| m2899_3(unknown) = InitializeNonLocal : +# 2899| m2899_4(unknown) = Chi : total:m2899_2, partial:m2899_3 +# 2899| r2899_5(glval) = VariableAddress[#this] : +# 2899| m2899_6(glval) = InitializeParameter[#this] : &:r2899_5 +# 2899| r2899_7(glval) = Load[#this] : &:r2899_5, m2899_6 +# 2899| m2899_8(StructInit) = InitializeIndirection[#this] : &:r2899_7 +# 2899| r2899_9(glval) = FieldAddress[i] : r2899_7 +# 2899| r2899_10(int) = Constant[41] : +# 2899| m2899_11(int) = Store[?] : &:r2899_9, r2899_10 +# 2899| m2899_12(unknown) = Chi : total:m2899_8, partial:m2899_11 +# 2899| v2899_13(void) = NoOp : +# 2899| v2899_14(void) = ReturnIndirection[#this] : &:r2899_7, m2899_12 +# 2899| v2899_15(void) = ReturnVoid : +# 2899| v2899_16(void) = AliasedUse : m2899_3 +# 2899| v2899_17(void) = ExitFunction : + +# 2901| int StructInit::get_val() +# 2901| Block 0 +# 2901| v2901_1(void) = EnterFunction : +# 2901| m2901_2(unknown) = AliasedDefinition : +# 2901| m2901_3(unknown) = InitializeNonLocal : +# 2901| m2901_4(unknown) = Chi : total:m2901_2, partial:m2901_3 +# 2901| r2901_5(glval) = VariableAddress[#this] : +# 2901| m2901_6(glval) = InitializeParameter[#this] : &:r2901_5 +# 2901| r2901_7(glval) = Load[#this] : &:r2901_5, m2901_6 +# 2901| m2901_8(StructInit) = InitializeIndirection[#this] : &:r2901_7 +# 2901| r2901_9(glval) = VariableAddress[#return] : +# 2901| r2901_10(glval) = VariableAddress[#this] : +# 2901| r2901_11(StructInit *) = Load[#this] : &:r2901_10, m2901_6 +# 2901| r2901_12(glval) = FieldAddress[k] : r2901_11 +# 2901| r2901_13(int) = Load[?] : &:r2901_12, ~m2901_8 +# 2901| m2901_14(int) = Store[#return] : &:r2901_9, r2901_13 +# 2901| v2901_15(void) = ReturnIndirection[#this] : &:r2901_7, m2901_8 +# 2901| r2901_16(glval) = VariableAddress[#return] : +# 2901| v2901_17(void) = ReturnValue : &:r2901_16, m2901_14 +# 2901| v2901_18(void) = AliasedUse : m2901_3 +# 2901| v2901_19(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 41494ec00b3c..ddb1b41fdbce 100644 --- a/cpp/ql/test/library-tests/ir/ir/ir.cpp +++ b/cpp/ql/test/library-tests/ir/ir/ir.cpp @@ -2886,4 +2886,19 @@ namespace { } } +struct StructInit { + int i = 42; + int j = 42; + int k = 42; + int l = k; + int m = get_val(); + int n = 42; + + StructInit(int j) : j(j), n(get_val()) {} + + StructInit() : i(41), k(41) {} + + int get_val() { return k; } +}; + // semmle-extractor-options: -std=c++20 --clang 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 de43ad9631aa..230d0805cd2d 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected @@ -21,6 +21,9 @@ lostReachability backEdgeCountMismatch useNotDominatedByDefinition | ir.cpp:1537:8:1537:8 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:1537:8:1537:8 | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | +| ir.cpp:2897:5:2897:14 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:2897:5:2897:14 | void StructInit::StructInit(int) | void StructInit::StructInit(int) | +| ir.cpp:2897:5:2897:14 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:2897:5:2897:14 | void StructInit::StructInit(int) | void StructInit::StructInit(int) | +| ir.cpp:2899:5:2899:14 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:2899:5:2899:14 | void StructInit::StructInit() | void StructInit::StructInit() | 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 03278f9aa728..8d61ec6789b8 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -19200,6 +19200,93 @@ ir.cpp: # 2867| v2867_13(void) = ReturnVoid : #-----| Goto -> Block 1 +# 2897| void StructInit::StructInit(int) +# 2897| Block 0 +# 2897| v2897_1(void) = EnterFunction : +# 2897| mu2897_2(unknown) = AliasedDefinition : +# 2897| mu2897_3(unknown) = InitializeNonLocal : +# 2897| r2897_4(glval) = VariableAddress[#this] : +# 2897| mu2897_5(glval) = InitializeParameter[#this] : &:r2897_4 +# 2897| r2897_6(glval) = Load[#this] : &:r2897_4, ~m? +# 2897| mu2897_7(StructInit) = InitializeIndirection[#this] : &:r2897_6 +# 2897| r2897_8(glval) = VariableAddress[j] : +# 2897| mu2897_9(int) = InitializeParameter[j] : &:r2897_8 +#-----| Goto -> Block 3 + +# 2897| Block 1 +# 2897| r2897_10(glval) = FieldAddress[j] : r2897_6 +# 2897| r2897_11(glval) = VariableAddress[j] : +# 2897| r2897_12(int) = Load[j] : &:r2897_11, ~m? +# 2897| mu2897_13(int) = Store[?] : &:r2897_10, r2897_12 +#-----| Goto -> Block 3 + +# 2897| Block 2 +# 2897| r2897_14(glval) = FieldAddress[n] : r2897_6 +# 2897| r2897_15(glval) = VariableAddress[#this] : +# 2897| r2897_16(StructInit *) = Load[#this] : &:r2897_15, ~m? +# 2897| r2897_17(glval) = FunctionAddress[get_val] : +# 2897| r2897_18(int) = Call[get_val] : func:r2897_17, this:r2897_16 +# 2897| mu2897_19(unknown) = ^CallSideEffect : ~m? +# 2897| v2897_20(void) = ^IndirectReadSideEffect[-1] : &:r2897_16, ~m? +# 2897| mu2897_21(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2897_16 +# 2897| mu2897_22(int) = Store[?] : &:r2897_14, r2897_18 +#-----| Goto -> Block 3 + +# 2897| Block 3 +# 2897| v2897_23(void) = NoOp : +# 2897| v2897_24(void) = ReturnIndirection[#this] : &:r2897_6, ~m? +# 2897| v2897_25(void) = ReturnVoid : +# 2897| v2897_26(void) = AliasedUse : ~m? +# 2897| v2897_27(void) = ExitFunction : + +# 2899| void StructInit::StructInit() +# 2899| Block 0 +# 2899| v2899_1(void) = EnterFunction : +# 2899| mu2899_2(unknown) = AliasedDefinition : +# 2899| mu2899_3(unknown) = InitializeNonLocal : +# 2899| r2899_4(glval) = VariableAddress[#this] : +# 2899| mu2899_5(glval) = InitializeParameter[#this] : &:r2899_4 +# 2899| r2899_6(glval) = Load[#this] : &:r2899_4, ~m? +# 2899| mu2899_7(StructInit) = InitializeIndirection[#this] : &:r2899_6 +# 2899| r2899_8(glval) = FieldAddress[i] : r2899_6 +# 2899| r2899_9(int) = Constant[41] : +# 2899| mu2899_10(int) = Store[?] : &:r2899_8, r2899_9 +#-----| Goto -> Block 2 + +# 2899| Block 1 +# 2899| r2899_11(glval) = FieldAddress[k] : r2899_6 +# 2899| r2899_12(int) = Constant[41] : +# 2899| mu2899_13(int) = Store[?] : &:r2899_11, r2899_12 +#-----| Goto -> Block 2 + +# 2899| Block 2 +# 2899| v2899_14(void) = NoOp : +# 2899| v2899_15(void) = ReturnIndirection[#this] : &:r2899_6, ~m? +# 2899| v2899_16(void) = ReturnVoid : +# 2899| v2899_17(void) = AliasedUse : ~m? +# 2899| v2899_18(void) = ExitFunction : + +# 2901| int StructInit::get_val() +# 2901| Block 0 +# 2901| v2901_1(void) = EnterFunction : +# 2901| mu2901_2(unknown) = AliasedDefinition : +# 2901| mu2901_3(unknown) = InitializeNonLocal : +# 2901| r2901_4(glval) = VariableAddress[#this] : +# 2901| mu2901_5(glval) = InitializeParameter[#this] : &:r2901_4 +# 2901| r2901_6(glval) = Load[#this] : &:r2901_4, ~m? +# 2901| mu2901_7(StructInit) = InitializeIndirection[#this] : &:r2901_6 +# 2901| r2901_8(glval) = VariableAddress[#return] : +# 2901| r2901_9(glval) = VariableAddress[#this] : +# 2901| r2901_10(StructInit *) = Load[#this] : &:r2901_9, ~m? +# 2901| r2901_11(glval) = FieldAddress[k] : r2901_10 +# 2901| r2901_12(int) = Load[?] : &:r2901_11, ~m? +# 2901| mu2901_13(int) = Store[#return] : &:r2901_8, r2901_12 +# 2901| v2901_14(void) = ReturnIndirection[#this] : &:r2901_6, ~m? +# 2901| r2901_15(glval) = VariableAddress[#return] : +# 2901| v2901_16(void) = ReturnValue : &:r2901_15, ~m? +# 2901| v2901_17(void) = AliasedUse : ~m? +# 2901| v2901_18(void) = ExitFunction : + ir23.cpp: # 1| bool consteval_1() # 1| Block 0 From 68039ecd687f3cf45910e8e10dbb6f61cf62a532 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 3 Mar 2026 16:33:27 +0100 Subject: [PATCH 04/16] C++: Add NSDMI dataflow test --- .../dataflow-consistency.expected | 2 ++ .../dataflow-tests/test-source-sink.expected | 2 ++ .../dataflow/dataflow-tests/test.cpp | 18 +++++++++++++++++- 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected index ff41f299f9c2..4e145427a362 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-consistency.expected @@ -10,11 +10,13 @@ uniqueEnclosingCallable | test.cpp:1158:18:1158:42 | ... , ... | Node should have one enclosing callable but has 0. | | test.cpp:1158:23:1158:31 | recursion | Node should have one enclosing callable but has 0. | | test.cpp:1158:35:1158:40 | call to source | Node should have one enclosing callable but has 0. | +| test.cpp:1318:13:1318:18 | call to source | Node should have one enclosing callable but has 0. | uniqueCallEnclosingCallable | test.cpp:864:47:864:54 | call to source | Call should have one enclosing callable but has 0. | | test.cpp:872:46:872:51 | call to source | Call should have one enclosing callable but has 0. | | test.cpp:1158:18:1158:21 | call to sink | Call should have one enclosing callable but has 0. | | test.cpp:1158:35:1158:40 | call to source | Call should have one enclosing callable but has 0. | +| test.cpp:1318:13:1318:18 | call to source | Call should have one enclosing callable but has 0. | uniqueType uniqueNodeLocation missingLocation diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-source-sink.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-source-sink.expected index 03a106208a5b..420bd110e1f7 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-source-sink.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-source-sink.expected @@ -170,6 +170,7 @@ astFlow | test.cpp:1308:7:1308:12 | call to source | test.cpp:1309:14:1309:16 | ... ++ | | test.cpp:1312:7:1312:12 | call to source | test.cpp:1313:8:1313:24 | ... ? ... : ... | | test.cpp:1312:7:1312:12 | call to source | test.cpp:1314:8:1314:8 | x | +| test.cpp:1329:11:1329:16 | call to source | test.cpp:1330:10:1330:10 | i | | true_upon_entry.cpp:17:11:17:16 | call to source | true_upon_entry.cpp:21:8:21:8 | x | | true_upon_entry.cpp:27:9:27:14 | call to source | true_upon_entry.cpp:29:8:29:8 | x | | true_upon_entry.cpp:33:11:33:16 | call to source | true_upon_entry.cpp:39:8:39:8 | x | @@ -390,6 +391,7 @@ irFlow | test.cpp:1308:7:1308:12 | call to source | test.cpp:1309:8:1309:16 | ... ++ | | test.cpp:1312:7:1312:12 | call to source | test.cpp:1313:8:1313:24 | ... ? ... : ... | | test.cpp:1312:7:1312:12 | call to source | test.cpp:1314:8:1314:8 | x | +| test.cpp:1329:11:1329:16 | call to source | test.cpp:1330:10:1330:10 | i | | true_upon_entry.cpp:9:11:9:16 | call to source | true_upon_entry.cpp:13:8:13:8 | x | | true_upon_entry.cpp:17:11:17:16 | call to source | true_upon_entry.cpp:21:8:21:8 | x | | true_upon_entry.cpp:27:9:27:14 | call to source | true_upon_entry.cpp:29:8:29:8 | x | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp index e1c3ef98fb74..ca240eb7b2b3 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp @@ -1312,4 +1312,20 @@ void crement_test2(bool b, int y) { x = source(); sink(b ? (long)x++ : 0); // $ ir ast sink(x); // $ ir ast -} \ No newline at end of file +} + +struct nsdmi { + int i = source(); + + nsdmi() {} + + nsdmi(int i) : i(i) {} +}; + +void nsdmi_test() { + nsdmi x; + sink(x.i); // $ MISSING: ir ast + + nsdmi y(source()); + sink(y.i); // $ ir ast +} From 09f930f4e86d64f5b65455682d4d8e8ecac9a828 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 27 Feb 2026 16:42:31 +0100 Subject: [PATCH 05/16] C++: Generate initialization function for each NSDMI --- .../raw/internal/IRConstruction.qll | 5 + .../raw/internal/TranslatedCondition.qll | 3 +- .../internal/TranslatedDeclarationEntry.qll | 1 + .../raw/internal/TranslatedElement.qll | 7 +- .../raw/internal/TranslatedExpr.qll | 53 ++++- .../raw/internal/TranslatedInitialization.qll | 8 +- .../TranslatedNonStaticDataMember.qll | 217 ++++++++++++++++++ 7 files changed, 288 insertions(+), 6 deletions(-) create mode 100644 cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedNonStaticDataMember.qll diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll index 9e9a47a5b4f1..7a667fcc0178 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll @@ -15,6 +15,7 @@ private import TranslatedCall private import TranslatedStmt private import TranslatedFunction private import TranslatedGlobalVar +private import TranslatedNonStaticDataMember private import TranslatedInitialization TranslatedElement getInstructionTranslatedElement(Instruction instruction) { @@ -45,6 +46,8 @@ module Raw { or not var.isFromUninstantiatedTemplate(_) and var instanceof StaticInitializedStaticLocalVariable + or + var instanceof Field ) and var.hasInitializer() and ( @@ -64,6 +67,8 @@ module Raw { getTranslatedFunction(decl).hasUserVariable(var, type) or getTranslatedVarInit(decl).hasUserVariable(var, type) + or + getTranslatedFieldInit(decl).hasUserVariable(var, type) } cached diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll index ff8867db696b..be8bff5b05cc 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCondition.qll @@ -36,7 +36,8 @@ abstract class TranslatedCondition extends TranslatedElement { final override Declaration getFunction() { result = getEnclosingFunction(expr) or result = getEnclosingVariable(expr).(GlobalOrNamespaceVariable) or - result = getEnclosingVariable(expr).(StaticInitializedStaticLocalVariable) + result = getEnclosingVariable(expr).(StaticInitializedStaticLocalVariable) or + result = getEnclosingVariable(expr).(Field) } final Type getResultType() { result = expr.getUnspecifiedType() } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll index c0fe9cd2207d..b10bba90536c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll @@ -36,6 +36,7 @@ abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslated or not entry.getDeclaration() instanceof StaticInitializedStaticLocalVariable and not entry.getDeclaration() instanceof GlobalOrNamespaceVariable and + not entry.getDeclaration() instanceof Field and result = stmt.getEnclosingFunction() ) } 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 93d7e9b02cfc..c30cc4bbc5c5 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 @@ -918,7 +918,10 @@ newtype TTranslatedElement = } or // The side effect that initializes newly-allocated memory. TTranslatedAllocationSideEffect(AllocationExpr expr) { not ignoreSideEffects(expr) } or - TTranslatedStaticStorageDurationVarInit(Variable var) { Raw::varHasIRFunc(var) } or + TTranslatedStaticStorageDurationVarInit(Variable var) { + Raw::varHasIRFunc(var) and not var instanceof Field + } or + TTranslatedNonStaticDataMemberVarInit(Field var) { Raw::varHasIRFunc(var) } or TTranslatedAssertionOperand(MacroInvocation mi, int index) { hasAssertionOperand(mi, index) } /** @@ -1297,5 +1300,7 @@ abstract class TranslatedRootElement extends TranslatedElement { this instanceof TTranslatedFunction or this instanceof TTranslatedStaticStorageDurationVarInit + or + this instanceof TTranslatedNonStaticDataMemberVarInit } } 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 2f7ffa636da3..712f140e5b8e 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 @@ -14,6 +14,7 @@ private import TranslatedFunction private import TranslatedInitialization private import TranslatedStmt private import TranslatedGlobalVar +private import TranslatedNonStaticDataMember private import IRConstruction import TranslatedCall @@ -138,6 +139,8 @@ abstract class TranslatedExpr extends TranslatedElement { result = getTranslatedFunction(getEnclosingFunction(expr)) or result = getTranslatedVarInit(getEnclosingVariable(expr)) + or + result = getTranslatedFieldInit(getEnclosingVariable(expr)) } } @@ -153,7 +156,10 @@ Declaration getEnclosingDeclaration0(Expr e) { i.getExpr().getFullyConverted() = e and v = i.getDeclaration() | - if v instanceof StaticInitializedStaticLocalVariable or v instanceof GlobalOrNamespaceVariable + if + v instanceof StaticInitializedStaticLocalVariable or + v instanceof GlobalOrNamespaceVariable or + v instanceof Field then result = v else result = e.getEnclosingDeclaration() ) @@ -173,7 +179,10 @@ Variable getEnclosingVariable0(Expr e) { i.getExpr().getFullyConverted() = e and v = i.getDeclaration() | - if v instanceof StaticInitializedStaticLocalVariable or v instanceof GlobalOrNamespaceVariable + if + v instanceof StaticInitializedStaticLocalVariable or + v instanceof GlobalOrNamespaceVariable or + v instanceof Field then result = v else result = e.getEnclosingVariable() ) @@ -826,6 +835,46 @@ class TranslatedPostfixCrementOperation extends TranslatedCrementOperation { override Instruction getResult() { result = this.getLoadedOperand().getResult() } } +class TranslatedParamAccessForType extends TranslatedNonConstantExpr { + override ParamAccessForType expr; + + TranslatedParamAccessForType() { + // Currently only needed for this parameter accesses. + expr.isThisAccess() + } + + final override Instruction getFirstInstruction(EdgeKind kind) { + result = this.getInstruction(OnlyInstructionTag()) and + kind instanceof GotoEdge + } + + override Instruction getALastInstructionInternal() { + result = this.getInstruction(OnlyInstructionTag()) + } + + final override TranslatedElement getChildInternal(int id) { none() } + + override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { + tag = OnlyInstructionTag() and + result = this.getParent().getChildSuccessor(this, kind) + } + + override Instruction getResult() { result = this.getInstruction(OnlyInstructionTag()) } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { + tag = OnlyInstructionTag() and + opcode instanceof Opcode::CopyValue and + resultType = getTypeForPRValue(expr.getType()) + } + + override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { + tag = OnlyInstructionTag() and + operandTag instanceof UnaryOperandTag and + result = + this.getEnclosingFunction().(TranslatedNonStaticDataMemberVarInit).getLoadThisInstruction() + } +} + /** * IR translation of an array access expression (e.g. `a[i]`). The array being accessed will either * be a prvalue of pointer type (possibly due to an implicit array-to-pointer conversion), or a diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll index b280dd7bc700..581b0886f7f0 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -148,7 +148,8 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn final override Declaration getFunction() { result = getEnclosingFunction(expr) or result = getEnclosingVariable(expr).(GlobalOrNamespaceVariable) or - result = getEnclosingVariable(expr).(StaticInitializedStaticLocalVariable) + result = getEnclosingVariable(expr).(StaticInitializedStaticLocalVariable) or + result = getEnclosingVariable(expr).(Field) } final override Locatable getAst() { result = expr } @@ -528,7 +529,8 @@ abstract class TranslatedFieldInitialization extends TranslatedElement { final override Declaration getFunction() { result = getEnclosingFunction(ast) or result = getEnclosingVariable(ast).(GlobalOrNamespaceVariable) or - result = getEnclosingVariable(ast).(StaticInitializedStaticLocalVariable) + result = getEnclosingVariable(ast).(StaticInitializedStaticLocalVariable) or + result = getEnclosingVariable(ast).(Field) } final override Instruction getFirstInstruction(EdgeKind kind) { @@ -701,6 +703,8 @@ abstract class TranslatedElementInitialization extends TranslatedElement { result = getEnclosingVariable(initList).(GlobalOrNamespaceVariable) or result = getEnclosingVariable(initList).(StaticInitializedStaticLocalVariable) + or + result = getEnclosingVariable(initList).(Field) } final override Instruction getFirstInstruction(EdgeKind kind) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedNonStaticDataMember.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedNonStaticDataMember.qll new file mode 100644 index 000000000000..ff06ff3198ed --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedNonStaticDataMember.qll @@ -0,0 +1,217 @@ +import semmle.code.cpp.ir.implementation.raw.internal.TranslatedElement +private import TranslatedExpr +private import cpp +private import semmle.code.cpp.ir.implementation.internal.OperandTag +private import semmle.code.cpp.ir.internal.TempVariableTag +private import semmle.code.cpp.ir.internal.CppType +private import TranslatedInitialization +private import InstructionTag +private import semmle.code.cpp.ir.internal.IRUtilities + +class TranslatedNonStaticDataMemberVarInit extends TranslatedRootElement, + TTranslatedNonStaticDataMemberVarInit, InitializationContext +{ + Field field; + Class cls; + + TranslatedNonStaticDataMemberVarInit() { + this = TTranslatedNonStaticDataMemberVarInit(field) and + cls.getAMember() = field + } + + override string toString() { result = cls.toString() + "::" + field.toString() } + + final override Field getAst() { result = field } + + final override Declaration getFunction() { result = field } + + override Instruction getFirstInstruction(EdgeKind kind) { + result = this.getInstruction(EnterFunctionTag()) and + kind instanceof GotoEdge + } + + override Instruction getALastInstructionInternal() { + result = this.getInstruction(ExitFunctionTag()) + } + + override TranslatedElement getChild(int n) { + n = 1 and + result = getTranslatedInitialization(field.getInitializer().getExpr().getFullyConverted()) + } + + override predicate hasInstruction(Opcode op, InstructionTag tag, CppType type) { + op instanceof Opcode::EnterFunction and + tag = EnterFunctionTag() and + type = getVoidType() + or + op instanceof Opcode::AliasedDefinition and + tag = AliasedDefinitionTag() and + type = getUnknownType() + or + op instanceof Opcode::InitializeNonLocal and + tag = InitializeNonLocalTag() and + type = getUnknownType() + or + tag = ThisAddressTag() and + op instanceof Opcode::VariableAddress and + type = getTypeForGLValue(any(UnknownType t)) + or + tag = InitializerStoreTag() and + op instanceof Opcode::InitializeParameter and + type = this.getThisType() + or + tag = ThisLoadTag() and + op instanceof Opcode::Load and + type = this.getThisType() + or + tag = InitializerIndirectStoreTag() and + op instanceof Opcode::InitializeIndirection and + type = getTypeForPRValue(cls) + or + op instanceof Opcode::FieldAddress and + tag = InitializerFieldAddressTag() and + type = getTypeForGLValue(field.getType()) + or + op instanceof Opcode::ReturnVoid and + tag = ReturnTag() and + type = getVoidType() + or + op instanceof Opcode::AliasedUse and + tag = AliasedUseTag() and + type = getVoidType() + or + op instanceof Opcode::ExitFunction and + tag = ExitFunctionTag() and + type = getVoidType() + } + + override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { + kind instanceof GotoEdge and + ( + tag = EnterFunctionTag() and + result = this.getInstruction(AliasedDefinitionTag()) + or + tag = AliasedDefinitionTag() and + result = this.getInstruction(InitializeNonLocalTag()) + or + tag = InitializeNonLocalTag() and + result = this.getInstruction(ThisAddressTag()) + or + tag = ThisAddressTag() and + result = this.getInstruction(InitializerStoreTag()) + or + tag = InitializerStoreTag() and + result = this.getInstruction(ThisLoadTag()) + or + tag = ThisLoadTag() and + result = this.getInstruction(InitializerIndirectStoreTag()) + or + tag = InitializerIndirectStoreTag() and + result = this.getInstruction(InitializerFieldAddressTag()) + ) + or + tag = InitializerFieldAddressTag() and + result = this.getChild(1).getFirstInstruction(kind) + or + kind instanceof GotoEdge and + ( + tag = ReturnTag() and + result = this.getInstruction(AliasedUseTag()) + or + tag = AliasedUseTag() and + result = this.getInstruction(ExitFunctionTag()) + ) + } + + override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { + child = this.getChild(1) and + result = this.getInstruction(ReturnTag()) and + kind instanceof GotoEdge + } + + final override CppType getInstructionMemoryOperandType( + InstructionTag tag, TypedOperandTag operandTag + ) { + tag = AliasedUseTag() and + operandTag instanceof SideEffectOperandTag and + result = getUnknownType() + } + + override IRVariable getInstructionVariable(InstructionTag tag) { + ( + tag = ThisAddressTag() or + tag = InitializerStoreTag() or + tag = InitializerIndirectStoreTag() + ) and + result = getIRTempVariable(field, ThisTempVar()) + } + + override Field getInstructionField(InstructionTag tag) { + tag = InitializerFieldAddressTag() and + result = field + } + + override predicate hasTempVariable(TempVariableTag tag, CppType type) { + tag = ThisTempVar() and + type = this.getThisType() + } + + /** + * Holds if this variable defines or accesses variable `var` with type `type`. This includes all + * parameters and local variables, plus any global variables or static data members that are + * directly accessed by the function. + */ + final predicate hasUserVariable(Variable varUsed, CppType type) { + ( + ( + varUsed instanceof GlobalOrNamespaceVariable + or + varUsed instanceof StaticLocalVariable + or + varUsed instanceof MemberVariable and not varUsed instanceof Field + ) and + exists(VariableAccess access | + access.getTarget() = varUsed and + getEnclosingVariable(access) = field + ) + or + field = varUsed + or + varUsed.(LocalScopeVariable).getEnclosingElement*() = field + or + varUsed.(Parameter).getCatchBlock().getEnclosingElement*() = field + ) and + type = getTypeForPRValue(getVariableType(varUsed)) + } + + override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { + ( + tag = InitializerStoreTag() + or + tag = ThisLoadTag() + ) and + operandTag instanceof AddressOperandTag and + result = this.getInstruction(ThisAddressTag()) + or + ( + tag = InitializerIndirectStoreTag() and + operandTag instanceof AddressOperandTag + or + tag = InitializerFieldAddressTag() and + operandTag instanceof UnaryOperandTag + ) and + result = this.getInstruction(ThisLoadTag()) + } + + override Instruction getTargetAddress() { + result = this.getInstruction(InitializerFieldAddressTag()) + } + + override Type getTargetType() { result = field.getUnspecifiedType() } + + final Instruction getLoadThisInstruction() { result = this.getInstruction(ThisLoadTag()) } + + private CppType getThisType() { result = getTypeForGLValue(cls) } +} + +TranslatedNonStaticDataMemberVarInit getTranslatedFieldInit(Field field) { result.getAst() = field } From 9e60e1217f8e274f90ba3aae6b9130cf69a3f452 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 27 Feb 2026 16:43:11 +0100 Subject: [PATCH 06/16] C++: Update expected test results --- .../test/library-tests/ir/ir/PrintConfig.qll | 2 + .../library-tests/ir/ir/aliased_ir.expected | 355 ++++++++++++++++++ .../test/library-tests/ir/ir/raw_ir.expected | 311 +++++++++++++++ 3 files changed, 668 insertions(+) diff --git a/cpp/ql/test/library-tests/ir/ir/PrintConfig.qll b/cpp/ql/test/library-tests/ir/ir/PrintConfig.qll index aa23cf423add..6e98d23bcf47 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintConfig.qll +++ b/cpp/ql/test/library-tests/ir/ir/PrintConfig.qll @@ -20,5 +20,7 @@ predicate shouldDumpDeclaration(Declaration decl) { decl.(GlobalOrNamespaceVariable).hasInitializer() or decl.(StaticLocalVariable).hasInitializer() + or + decl.(Field).hasInitializer() ) } 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 5d2b92aed738..40a424f7f9a4 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -12375,6 +12375,24 @@ ir.cpp: # 1533| v1533_12(void) = AliasedUse : m1533_3 # 1533| v1533_13(void) = ExitFunction : +# 1534| int StructuredBindingDataMemberMemberStruct::x +# 1534| Block 0 +# 1534| v1534_1(void) = EnterFunction : +# 1534| m1534_2(unknown) = AliasedDefinition : +# 1534| m1534_3(unknown) = InitializeNonLocal : +# 1534| m1534_4(unknown) = Chi : total:m1534_2, partial:m1534_3 +# 1534| r1534_5(glval) = VariableAddress[#this] : +# 1534| m1534_6(glval) = InitializeParameter[#this] : &:r1534_5 +# 1534| r1534_7(glval) = Load[#this] : &:r1534_5, m1534_6 +# 1534| m1534_8(StructuredBindingDataMemberMemberStruct) = InitializeIndirection[#this] : &:r1534_7 +# 1534| r1534_9(glval) = FieldAddress[x] : r1534_7 +# 1534| r1534_10(int) = Constant[5] : +# 1534| m1534_11(int) = Store[?] : &:r1534_9, r1534_10 +# 1534| m1534_12(unknown) = Chi : total:m1534_8, partial:m1534_11 +# 1534| v1534_13(void) = ReturnVoid : +# 1534| v1534_14(void) = AliasedUse : m1534_3 +# 1534| v1534_15(void) = ExitFunction : + # 1537| void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() # 1537| Block 0 # 1537| v1537_1(void) = EnterFunction : @@ -12476,6 +12494,130 @@ ir.cpp: # 1537| v1537_76(void) = AliasedUse : m1537_3 # 1537| v1537_77(void) = ExitFunction : +# 1540| int StructuredBindingDataMemberStruct::i +# 1540| Block 0 +# 1540| v1540_1(void) = EnterFunction : +# 1540| m1540_2(unknown) = AliasedDefinition : +# 1540| m1540_3(unknown) = InitializeNonLocal : +# 1540| m1540_4(unknown) = Chi : total:m1540_2, partial:m1540_3 +# 1540| r1540_5(glval) = VariableAddress[#this] : +# 1540| m1540_6(glval) = InitializeParameter[#this] : &:r1540_5 +# 1540| r1540_7(glval) = Load[#this] : &:r1540_5, m1540_6 +# 1540| m1540_8(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1540_7 +# 1540| r1540_9(glval) = FieldAddress[i] : r1540_7 +# 1540| r1540_10(int) = Constant[1] : +# 1540| m1540_11(int) = Store[?] : &:r1540_9, r1540_10 +# 1540| m1540_12(unknown) = Chi : total:m1540_8, partial:m1540_11 +# 1540| v1540_13(void) = ReturnVoid : +# 1540| v1540_14(void) = AliasedUse : m1540_3 +# 1540| v1540_15(void) = ExitFunction : + +# 1541| double StructuredBindingDataMemberStruct::d +# 1541| Block 0 +# 1541| v1541_1(void) = EnterFunction : +# 1541| m1541_2(unknown) = AliasedDefinition : +# 1541| m1541_3(unknown) = InitializeNonLocal : +# 1541| m1541_4(unknown) = Chi : total:m1541_2, partial:m1541_3 +# 1541| r1541_5(glval) = VariableAddress[#this] : +# 1541| m1541_6(glval) = InitializeParameter[#this] : &:r1541_5 +# 1541| r1541_7(glval) = Load[#this] : &:r1541_5, m1541_6 +# 1541| m1541_8(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1541_7 +# 1541| r1541_9(glval) = FieldAddress[d] : r1541_7 +# 1541| r1541_10(double) = Constant[2.0] : +# 1541| m1541_11(double) = Store[?] : &:r1541_9, r1541_10 +# 1541| m1541_12(unknown) = Chi : total:m1541_8, partial:m1541_11 +# 1541| v1541_13(void) = ReturnVoid : +# 1541| v1541_14(void) = AliasedUse : m1541_3 +# 1541| v1541_15(void) = ExitFunction : + +# 1543| int& StructuredBindingDataMemberStruct::r +# 1543| Block 0 +# 1543| v1543_1(void) = EnterFunction : +# 1543| m1543_2(unknown) = AliasedDefinition : +# 1543| m1543_3(unknown) = InitializeNonLocal : +# 1543| m1543_4(unknown) = Chi : total:m1543_2, partial:m1543_3 +# 1543| r1543_5(glval) = VariableAddress[#this] : +# 1543| m1543_6(glval) = InitializeParameter[#this] : &:r1543_5 +# 1543| r1543_7(glval) = Load[#this] : &:r1543_5, m1543_6 +# 1543| m1543_8(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1543_7 +# 1543| m1543_9(unknown) = Chi : total:m1543_4, partial:m1543_8 +# 1543| r1543_10(glval) = FieldAddress[r] : r1543_7 +# 1543| r1543_11(StructuredBindingDataMemberStruct *) = CopyValue : r1543_7 +# 1543| r1543_12(glval) = FieldAddress[i] : r1543_11 +#-----| r0_1(int &) = CopyValue : r1543_12 +#-----| m0_2(int &) = Store[?] : &:r1543_10, r0_1 +#-----| m0_3(unknown) = Chi : total:m1543_9, partial:m0_2 +# 1543| v1543_13(void) = ReturnVoid : +# 1543| v1543_14(void) = AliasedUse : ~m0_3 +# 1543| v1543_15(void) = ExitFunction : + +# 1544| int* StructuredBindingDataMemberStruct::p +# 1544| Block 0 +# 1544| v1544_1(void) = EnterFunction : +# 1544| m1544_2(unknown) = AliasedDefinition : +# 1544| m1544_3(unknown) = InitializeNonLocal : +# 1544| m1544_4(unknown) = Chi : total:m1544_2, partial:m1544_3 +# 1544| r1544_5(glval) = VariableAddress[#this] : +# 1544| m1544_6(glval) = InitializeParameter[#this] : &:r1544_5 +# 1544| r1544_7(glval) = Load[#this] : &:r1544_5, m1544_6 +# 1544| m1544_8(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1544_7 +# 1544| m1544_9(unknown) = Chi : total:m1544_4, partial:m1544_8 +# 1544| r1544_10(glval) = FieldAddress[p] : r1544_7 +# 1544| r1544_11(StructuredBindingDataMemberStruct *) = CopyValue : r1544_7 +# 1544| r1544_12(glval) = FieldAddress[i] : r1544_11 +# 1544| r1544_13(int *) = CopyValue : r1544_12 +# 1544| m1544_14(int *) = Store[?] : &:r1544_10, r1544_13 +# 1544| m1544_15(unknown) = Chi : total:m1544_9, partial:m1544_14 +# 1544| v1544_16(void) = ReturnVoid : +# 1544| v1544_17(void) = AliasedUse : ~m1544_15 +# 1544| v1544_18(void) = ExitFunction : + +# 1545| StructuredBindingDataMemberStruct::ArrayType StructuredBindingDataMemberStruct::xs +# 1545| Block 0 +# 1545| v1545_1(void) = EnterFunction : +# 1545| m1545_2(unknown) = AliasedDefinition : +# 1545| m1545_3(unknown) = InitializeNonLocal : +# 1545| m1545_4(unknown) = Chi : total:m1545_2, partial:m1545_3 +# 1545| r1545_5(glval) = VariableAddress[#this] : +# 1545| m1545_6(glval) = InitializeParameter[#this] : &:r1545_5 +# 1545| r1545_7(glval) = Load[#this] : &:r1545_5, m1545_6 +# 1545| m1545_8(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1545_7 +# 1545| r1545_9(glval) = FieldAddress[xs] : r1545_7 +# 1545| r1545_10(int) = Constant[0] : +# 1545| r1545_11(glval) = PointerAdd[4] : r1545_9, r1545_10 +# 1545| r1545_12(int) = Constant[1] : +# 1545| m1545_13(int) = Store[?] : &:r1545_11, r1545_12 +# 1545| m1545_14(unknown) = Chi : total:m1545_8, partial:m1545_13 +# 1545| r1545_15(int) = Constant[1] : +# 1545| r1545_16(glval) = PointerAdd[4] : r1545_9, r1545_15 +# 1545| r1545_17(int) = Constant[2] : +# 1545| m1545_18(int) = Store[?] : &:r1545_16, r1545_17 +# 1545| m1545_19(unknown) = Chi : total:m1545_14, partial:m1545_18 +# 1545| v1545_20(void) = ReturnVoid : +# 1545| v1545_21(void) = AliasedUse : m1545_3 +# 1545| v1545_22(void) = ExitFunction : + +# 1546| StructuredBindingDataMemberStruct::RefType StructuredBindingDataMemberStruct::r_alt +# 1546| Block 0 +# 1546| v1546_1(void) = EnterFunction : +# 1546| m1546_2(unknown) = AliasedDefinition : +# 1546| m1546_3(unknown) = InitializeNonLocal : +# 1546| m1546_4(unknown) = Chi : total:m1546_2, partial:m1546_3 +# 1546| r1546_5(glval) = VariableAddress[#this] : +# 1546| m1546_6(glval) = InitializeParameter[#this] : &:r1546_5 +# 1546| r1546_7(glval) = Load[#this] : &:r1546_5, m1546_6 +# 1546| m1546_8(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1546_7 +# 1546| m1546_9(unknown) = Chi : total:m1546_4, partial:m1546_8 +# 1546| r1546_10(glval) = FieldAddress[r_alt] : r1546_7 +# 1546| r1546_11(StructuredBindingDataMemberStruct *) = CopyValue : r1546_7 +# 1546| r1546_12(glval) = FieldAddress[i] : r1546_11 +#-----| r0_1(int &) = CopyValue : r1546_12 +#-----| m0_2(int &) = Store[?] : &:r1546_10, r0_1 +#-----| m0_3(unknown) = Chi : total:m1546_9, partial:m0_2 +# 1546| v1546_13(void) = ReturnVoid : +# 1546| v1546_14(void) = AliasedUse : ~m0_3 +# 1546| v1546_15(void) = ExitFunction : + # 1550| void data_member_structured_binding() # 1550| Block 0 # 1550| v1550_1(void) = EnterFunction : @@ -12711,6 +12853,63 @@ ir.cpp: # 1590| v1590_36(void) = AliasedUse : m1590_3 # 1590| v1590_37(void) = ExitFunction : +# 1591| int StructuredBindingTupleRefGet::i +# 1591| Block 0 +# 1591| v1591_1(void) = EnterFunction : +# 1591| m1591_2(unknown) = AliasedDefinition : +# 1591| m1591_3(unknown) = InitializeNonLocal : +# 1591| m1591_4(unknown) = Chi : total:m1591_2, partial:m1591_3 +# 1591| r1591_5(glval) = VariableAddress[#this] : +# 1591| m1591_6(glval) = InitializeParameter[#this] : &:r1591_5 +# 1591| r1591_7(glval) = Load[#this] : &:r1591_5, m1591_6 +# 1591| m1591_8(StructuredBindingTupleRefGet) = InitializeIndirection[#this] : &:r1591_7 +# 1591| r1591_9(glval) = FieldAddress[i] : r1591_7 +# 1591| r1591_10(int) = Constant[1] : +# 1591| m1591_11(int) = Store[?] : &:r1591_9, r1591_10 +# 1591| m1591_12(unknown) = Chi : total:m1591_8, partial:m1591_11 +# 1591| v1591_13(void) = ReturnVoid : +# 1591| v1591_14(void) = AliasedUse : m1591_3 +# 1591| v1591_15(void) = ExitFunction : + +# 1592| double StructuredBindingTupleRefGet::d +# 1592| Block 0 +# 1592| v1592_1(void) = EnterFunction : +# 1592| m1592_2(unknown) = AliasedDefinition : +# 1592| m1592_3(unknown) = InitializeNonLocal : +# 1592| m1592_4(unknown) = Chi : total:m1592_2, partial:m1592_3 +# 1592| r1592_5(glval) = VariableAddress[#this] : +# 1592| m1592_6(glval) = InitializeParameter[#this] : &:r1592_5 +# 1592| r1592_7(glval) = Load[#this] : &:r1592_5, m1592_6 +# 1592| m1592_8(StructuredBindingTupleRefGet) = InitializeIndirection[#this] : &:r1592_7 +# 1592| r1592_9(glval) = FieldAddress[d] : r1592_7 +# 1592| r1592_10(double) = Constant[2.200000000000000178] : +# 1592| m1592_11(double) = Store[?] : &:r1592_9, r1592_10 +# 1592| m1592_12(unknown) = Chi : total:m1592_8, partial:m1592_11 +# 1592| v1592_13(void) = ReturnVoid : +# 1592| v1592_14(void) = AliasedUse : m1592_3 +# 1592| v1592_15(void) = ExitFunction : + +# 1593| int& StructuredBindingTupleRefGet::r +# 1593| Block 0 +# 1593| v1593_1(void) = EnterFunction : +# 1593| m1593_2(unknown) = AliasedDefinition : +# 1593| m1593_3(unknown) = InitializeNonLocal : +# 1593| m1593_4(unknown) = Chi : total:m1593_2, partial:m1593_3 +# 1593| r1593_5(glval) = VariableAddress[#this] : +# 1593| m1593_6(glval) = InitializeParameter[#this] : &:r1593_5 +# 1593| r1593_7(glval) = Load[#this] : &:r1593_5, m1593_6 +# 1593| m1593_8(StructuredBindingTupleRefGet) = InitializeIndirection[#this] : &:r1593_7 +# 1593| m1593_9(unknown) = Chi : total:m1593_4, partial:m1593_8 +# 1593| r1593_10(glval) = FieldAddress[r] : r1593_7 +# 1593| r1593_11(StructuredBindingTupleRefGet *) = CopyValue : r1593_7 +# 1593| r1593_12(glval) = FieldAddress[i] : r1593_11 +#-----| r0_1(int &) = CopyValue : r1593_12 +#-----| m0_2(int &) = Store[?] : &:r1593_10, r0_1 +#-----| m0_3(unknown) = Chi : total:m1593_9, partial:m0_2 +# 1593| v1593_13(void) = ReturnVoid : +# 1593| v1593_14(void) = AliasedUse : ~m0_3 +# 1593| v1593_15(void) = ExitFunction : + # 1618| std::tuple_element::type& StructuredBindingTupleRefGet::get() # 1618| Block 0 # 1618| v1618_1(void) = EnterFunction : @@ -12962,6 +13161,45 @@ ir.cpp: # 1657| v1657_12(void) = AliasedUse : m1657_3 # 1657| v1657_13(void) = ExitFunction : +# 1658| int StructuredBindingTupleNoRefGet::i +# 1658| Block 0 +# 1658| v1658_1(void) = EnterFunction : +# 1658| m1658_2(unknown) = AliasedDefinition : +# 1658| m1658_3(unknown) = InitializeNonLocal : +# 1658| m1658_4(unknown) = Chi : total:m1658_2, partial:m1658_3 +# 1658| r1658_5(glval) = VariableAddress[#this] : +# 1658| m1658_6(glval) = InitializeParameter[#this] : &:r1658_5 +# 1658| r1658_7(glval) = Load[#this] : &:r1658_5, m1658_6 +# 1658| m1658_8(StructuredBindingTupleNoRefGet) = InitializeIndirection[#this] : &:r1658_7 +# 1658| r1658_9(glval) = FieldAddress[i] : r1658_7 +# 1658| r1658_10(int) = Constant[1] : +# 1658| m1658_11(int) = Store[?] : &:r1658_9, r1658_10 +# 1658| m1658_12(unknown) = Chi : total:m1658_8, partial:m1658_11 +# 1658| v1658_13(void) = ReturnVoid : +# 1658| v1658_14(void) = AliasedUse : m1658_3 +# 1658| v1658_15(void) = ExitFunction : + +# 1659| int& StructuredBindingTupleNoRefGet::r +# 1659| Block 0 +# 1659| v1659_1(void) = EnterFunction : +# 1659| m1659_2(unknown) = AliasedDefinition : +# 1659| m1659_3(unknown) = InitializeNonLocal : +# 1659| m1659_4(unknown) = Chi : total:m1659_2, partial:m1659_3 +# 1659| r1659_5(glval) = VariableAddress[#this] : +# 1659| m1659_6(glval) = InitializeParameter[#this] : &:r1659_5 +# 1659| r1659_7(glval) = Load[#this] : &:r1659_5, m1659_6 +# 1659| m1659_8(StructuredBindingTupleNoRefGet) = InitializeIndirection[#this] : &:r1659_7 +# 1659| m1659_9(unknown) = Chi : total:m1659_4, partial:m1659_8 +# 1659| r1659_10(glval) = FieldAddress[r] : r1659_7 +# 1659| r1659_11(StructuredBindingTupleNoRefGet *) = CopyValue : r1659_7 +# 1659| r1659_12(glval) = FieldAddress[i] : r1659_11 +#-----| r0_1(int &) = CopyValue : r1659_12 +#-----| m0_2(int &) = Store[?] : &:r1659_10, r0_1 +#-----| m0_3(unknown) = Chi : total:m1659_9, partial:m0_2 +# 1659| v1659_13(void) = ReturnVoid : +# 1659| v1659_14(void) = AliasedUse : ~m0_3 +# 1659| v1659_15(void) = ExitFunction : + # 1684| std::tuple_element::type StructuredBindingTupleNoRefGet::get() # 1684| Block 0 # 1684| v1684_1(void) = EnterFunction : @@ -21066,6 +21304,123 @@ ir.cpp: # 2867| v2867_14(void) = ReturnVoid : #-----| Goto -> Block 1 +# 2890| int StructInit::i +# 2890| Block 0 +# 2890| v2890_1(void) = EnterFunction : +# 2890| m2890_2(unknown) = AliasedDefinition : +# 2890| m2890_3(unknown) = InitializeNonLocal : +# 2890| m2890_4(unknown) = Chi : total:m2890_2, partial:m2890_3 +# 2890| r2890_5(glval) = VariableAddress[#this] : +# 2890| m2890_6(glval) = InitializeParameter[#this] : &:r2890_5 +# 2890| r2890_7(glval) = Load[#this] : &:r2890_5, m2890_6 +# 2890| m2890_8(StructInit) = InitializeIndirection[#this] : &:r2890_7 +# 2890| r2890_9(glval) = FieldAddress[i] : r2890_7 +# 2890| r2890_10(int) = Constant[42] : +# 2890| m2890_11(int) = Store[?] : &:r2890_9, r2890_10 +# 2890| m2890_12(unknown) = Chi : total:m2890_8, partial:m2890_11 +# 2890| v2890_13(void) = ReturnVoid : +# 2890| v2890_14(void) = AliasedUse : m2890_3 +# 2890| v2890_15(void) = ExitFunction : + +# 2891| int StructInit::j +# 2891| Block 0 +# 2891| v2891_1(void) = EnterFunction : +# 2891| m2891_2(unknown) = AliasedDefinition : +# 2891| m2891_3(unknown) = InitializeNonLocal : +# 2891| m2891_4(unknown) = Chi : total:m2891_2, partial:m2891_3 +# 2891| r2891_5(glval) = VariableAddress[#this] : +# 2891| m2891_6(glval) = InitializeParameter[#this] : &:r2891_5 +# 2891| r2891_7(glval) = Load[#this] : &:r2891_5, m2891_6 +# 2891| m2891_8(StructInit) = InitializeIndirection[#this] : &:r2891_7 +# 2891| r2891_9(glval) = FieldAddress[j] : r2891_7 +# 2891| r2891_10(int) = Constant[42] : +# 2891| m2891_11(int) = Store[?] : &:r2891_9, r2891_10 +# 2891| m2891_12(unknown) = Chi : total:m2891_8, partial:m2891_11 +# 2891| v2891_13(void) = ReturnVoid : +# 2891| v2891_14(void) = AliasedUse : m2891_3 +# 2891| v2891_15(void) = ExitFunction : + +# 2892| int StructInit::k +# 2892| Block 0 +# 2892| v2892_1(void) = EnterFunction : +# 2892| m2892_2(unknown) = AliasedDefinition : +# 2892| m2892_3(unknown) = InitializeNonLocal : +# 2892| m2892_4(unknown) = Chi : total:m2892_2, partial:m2892_3 +# 2892| r2892_5(glval) = VariableAddress[#this] : +# 2892| m2892_6(glval) = InitializeParameter[#this] : &:r2892_5 +# 2892| r2892_7(glval) = Load[#this] : &:r2892_5, m2892_6 +# 2892| m2892_8(StructInit) = InitializeIndirection[#this] : &:r2892_7 +# 2892| r2892_9(glval) = FieldAddress[k] : r2892_7 +# 2892| r2892_10(int) = Constant[42] : +# 2892| m2892_11(int) = Store[?] : &:r2892_9, r2892_10 +# 2892| m2892_12(unknown) = Chi : total:m2892_8, partial:m2892_11 +# 2892| v2892_13(void) = ReturnVoid : +# 2892| v2892_14(void) = AliasedUse : m2892_3 +# 2892| v2892_15(void) = ExitFunction : + +# 2893| int StructInit::l +# 2893| Block 0 +# 2893| v2893_1(void) = EnterFunction : +# 2893| m2893_2(unknown) = AliasedDefinition : +# 2893| m2893_3(unknown) = InitializeNonLocal : +# 2893| m2893_4(unknown) = Chi : total:m2893_2, partial:m2893_3 +# 2893| r2893_5(glval) = VariableAddress[#this] : +# 2893| m2893_6(glval) = InitializeParameter[#this] : &:r2893_5 +# 2893| r2893_7(glval) = Load[#this] : &:r2893_5, m2893_6 +# 2893| m2893_8(StructInit) = InitializeIndirection[#this] : &:r2893_7 +# 2893| r2893_9(glval) = FieldAddress[l] : r2893_7 +# 2893| r2893_10(StructInit *) = CopyValue : r2893_7 +# 2893| r2893_11(glval) = FieldAddress[k] : r2893_10 +# 2893| r2893_12(int) = Load[?] : &:r2893_11, ~m2893_8 +# 2893| m2893_13(int) = Store[?] : &:r2893_9, r2893_12 +# 2893| m2893_14(unknown) = Chi : total:m2893_8, partial:m2893_13 +# 2893| v2893_15(void) = ReturnVoid : +# 2893| v2893_16(void) = AliasedUse : m2893_3 +# 2893| v2893_17(void) = ExitFunction : + +# 2894| int StructInit::m +# 2894| Block 0 +# 2894| v2894_1(void) = EnterFunction : +# 2894| m2894_2(unknown) = AliasedDefinition : +# 2894| m2894_3(unknown) = InitializeNonLocal : +# 2894| m2894_4(unknown) = Chi : total:m2894_2, partial:m2894_3 +# 2894| r2894_5(glval) = VariableAddress[#this] : +# 2894| m2894_6(glval) = InitializeParameter[#this] : &:r2894_5 +# 2894| r2894_7(glval) = Load[#this] : &:r2894_5, m2894_6 +# 2894| m2894_8(StructInit) = InitializeIndirection[#this] : &:r2894_7 +# 2894| r2894_9(glval) = FieldAddress[m] : r2894_7 +# 2894| r2894_10(StructInit *) = CopyValue : r2894_7 +# 2894| r2894_11(glval) = FunctionAddress[get_val] : +# 2894| r2894_12(int) = Call[get_val] : func:r2894_11, this:r2894_10 +# 2894| m2894_13(unknown) = ^CallSideEffect : ~m2894_4 +# 2894| m2894_14(unknown) = Chi : total:m2894_4, partial:m2894_13 +# 2894| v2894_15(void) = ^IndirectReadSideEffect[-1] : &:r2894_10, ~m2894_8 +# 2894| m2894_16(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2894_10 +# 2894| m2894_17(unknown) = Chi : total:m2894_8, partial:m2894_16 +# 2894| m2894_18(int) = Store[?] : &:r2894_9, r2894_12 +# 2894| m2894_19(unknown) = Chi : total:m2894_17, partial:m2894_18 +# 2894| v2894_20(void) = ReturnVoid : +# 2894| v2894_21(void) = AliasedUse : ~m2894_14 +# 2894| v2894_22(void) = ExitFunction : + +# 2895| int StructInit::n +# 2895| Block 0 +# 2895| v2895_1(void) = EnterFunction : +# 2895| m2895_2(unknown) = AliasedDefinition : +# 2895| m2895_3(unknown) = InitializeNonLocal : +# 2895| m2895_4(unknown) = Chi : total:m2895_2, partial:m2895_3 +# 2895| r2895_5(glval) = VariableAddress[#this] : +# 2895| m2895_6(glval) = InitializeParameter[#this] : &:r2895_5 +# 2895| r2895_7(glval) = Load[#this] : &:r2895_5, m2895_6 +# 2895| m2895_8(StructInit) = InitializeIndirection[#this] : &:r2895_7 +# 2895| r2895_9(glval) = FieldAddress[n] : r2895_7 +# 2895| r2895_10(int) = Constant[42] : +# 2895| m2895_11(int) = Store[?] : &:r2895_9, r2895_10 +# 2895| m2895_12(unknown) = Chi : total:m2895_8, partial:m2895_11 +# 2895| v2895_13(void) = ReturnVoid : +# 2895| v2895_14(void) = AliasedUse : m2895_3 +# 2895| v2895_15(void) = ExitFunction : + # 2897| void StructInit::StructInit(int) # 2897| Block 0 # 2897| v2897_1(void) = EnterFunction : 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 8d61ec6789b8..16649e72d084 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -11352,6 +11352,22 @@ ir.cpp: # 1533| v1533_11(void) = AliasedUse : ~m? # 1533| v1533_12(void) = ExitFunction : +# 1534| int StructuredBindingDataMemberMemberStruct::x +# 1534| Block 0 +# 1534| v1534_1(void) = EnterFunction : +# 1534| mu1534_2(unknown) = AliasedDefinition : +# 1534| mu1534_3(unknown) = InitializeNonLocal : +# 1534| r1534_4(glval) = VariableAddress[#this] : +# 1534| mu1534_5(glval) = InitializeParameter[#this] : &:r1534_4 +# 1534| r1534_6(glval) = Load[#this] : &:r1534_4, ~m? +# 1534| mu1534_7(StructuredBindingDataMemberMemberStruct) = InitializeIndirection[#this] : &:r1534_6 +# 1534| r1534_8(glval) = FieldAddress[x] : r1534_6 +# 1534| r1534_9(int) = Constant[5] : +# 1534| mu1534_10(int) = Store[?] : &:r1534_8, r1534_9 +# 1534| v1534_11(void) = ReturnVoid : +# 1534| v1534_12(void) = AliasedUse : ~m? +# 1534| v1534_13(void) = ExitFunction : + # 1537| void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() # 1537| Block 0 # 1537| v1537_1(void) = EnterFunction : @@ -11454,6 +11470,114 @@ ir.cpp: # 1537| v1537_67(void) = AliasedUse : ~m? # 1537| v1537_68(void) = ExitFunction : +# 1540| int StructuredBindingDataMemberStruct::i +# 1540| Block 0 +# 1540| v1540_1(void) = EnterFunction : +# 1540| mu1540_2(unknown) = AliasedDefinition : +# 1540| mu1540_3(unknown) = InitializeNonLocal : +# 1540| r1540_4(glval) = VariableAddress[#this] : +# 1540| mu1540_5(glval) = InitializeParameter[#this] : &:r1540_4 +# 1540| r1540_6(glval) = Load[#this] : &:r1540_4, ~m? +# 1540| mu1540_7(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1540_6 +# 1540| r1540_8(glval) = FieldAddress[i] : r1540_6 +# 1540| r1540_9(int) = Constant[1] : +# 1540| mu1540_10(int) = Store[?] : &:r1540_8, r1540_9 +# 1540| v1540_11(void) = ReturnVoid : +# 1540| v1540_12(void) = AliasedUse : ~m? +# 1540| v1540_13(void) = ExitFunction : + +# 1541| double StructuredBindingDataMemberStruct::d +# 1541| Block 0 +# 1541| v1541_1(void) = EnterFunction : +# 1541| mu1541_2(unknown) = AliasedDefinition : +# 1541| mu1541_3(unknown) = InitializeNonLocal : +# 1541| r1541_4(glval) = VariableAddress[#this] : +# 1541| mu1541_5(glval) = InitializeParameter[#this] : &:r1541_4 +# 1541| r1541_6(glval) = Load[#this] : &:r1541_4, ~m? +# 1541| mu1541_7(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1541_6 +# 1541| r1541_8(glval) = FieldAddress[d] : r1541_6 +# 1541| r1541_9(double) = Constant[2.0] : +# 1541| mu1541_10(double) = Store[?] : &:r1541_8, r1541_9 +# 1541| v1541_11(void) = ReturnVoid : +# 1541| v1541_12(void) = AliasedUse : ~m? +# 1541| v1541_13(void) = ExitFunction : + +# 1543| int& StructuredBindingDataMemberStruct::r +# 1543| Block 0 +# 1543| v1543_1(void) = EnterFunction : +# 1543| mu1543_2(unknown) = AliasedDefinition : +# 1543| mu1543_3(unknown) = InitializeNonLocal : +# 1543| r1543_4(glval) = VariableAddress[#this] : +# 1543| mu1543_5(glval) = InitializeParameter[#this] : &:r1543_4 +# 1543| r1543_6(glval) = Load[#this] : &:r1543_4, ~m? +# 1543| mu1543_7(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1543_6 +# 1543| r1543_8(glval) = FieldAddress[r] : r1543_6 +# 1543| r1543_9(StructuredBindingDataMemberStruct *) = CopyValue : r1543_6 +# 1543| r1543_10(glval) = FieldAddress[i] : r1543_9 +#-----| r0_1(int &) = CopyValue : r1543_10 +#-----| mu0_2(int &) = Store[?] : &:r1543_8, r0_1 +# 1543| v1543_11(void) = ReturnVoid : +# 1543| v1543_12(void) = AliasedUse : ~m? +# 1543| v1543_13(void) = ExitFunction : + +# 1544| int* StructuredBindingDataMemberStruct::p +# 1544| Block 0 +# 1544| v1544_1(void) = EnterFunction : +# 1544| mu1544_2(unknown) = AliasedDefinition : +# 1544| mu1544_3(unknown) = InitializeNonLocal : +# 1544| r1544_4(glval) = VariableAddress[#this] : +# 1544| mu1544_5(glval) = InitializeParameter[#this] : &:r1544_4 +# 1544| r1544_6(glval) = Load[#this] : &:r1544_4, ~m? +# 1544| mu1544_7(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1544_6 +# 1544| r1544_8(glval) = FieldAddress[p] : r1544_6 +# 1544| r1544_9(StructuredBindingDataMemberStruct *) = CopyValue : r1544_6 +# 1544| r1544_10(glval) = FieldAddress[i] : r1544_9 +# 1544| r1544_11(int *) = CopyValue : r1544_10 +# 1544| mu1544_12(int *) = Store[?] : &:r1544_8, r1544_11 +# 1544| v1544_13(void) = ReturnVoid : +# 1544| v1544_14(void) = AliasedUse : ~m? +# 1544| v1544_15(void) = ExitFunction : + +# 1545| StructuredBindingDataMemberStruct::ArrayType StructuredBindingDataMemberStruct::xs +# 1545| Block 0 +# 1545| v1545_1(void) = EnterFunction : +# 1545| mu1545_2(unknown) = AliasedDefinition : +# 1545| mu1545_3(unknown) = InitializeNonLocal : +# 1545| r1545_4(glval) = VariableAddress[#this] : +# 1545| mu1545_5(glval) = InitializeParameter[#this] : &:r1545_4 +# 1545| r1545_6(glval) = Load[#this] : &:r1545_4, ~m? +# 1545| mu1545_7(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1545_6 +# 1545| r1545_8(glval) = FieldAddress[xs] : r1545_6 +# 1545| r1545_9(int) = Constant[0] : +# 1545| r1545_10(glval) = PointerAdd[4] : r1545_8, r1545_9 +# 1545| r1545_11(int) = Constant[1] : +# 1545| mu1545_12(int) = Store[?] : &:r1545_10, r1545_11 +# 1545| r1545_13(int) = Constant[1] : +# 1545| r1545_14(glval) = PointerAdd[4] : r1545_8, r1545_13 +# 1545| r1545_15(int) = Constant[2] : +# 1545| mu1545_16(int) = Store[?] : &:r1545_14, r1545_15 +# 1545| v1545_17(void) = ReturnVoid : +# 1545| v1545_18(void) = AliasedUse : ~m? +# 1545| v1545_19(void) = ExitFunction : + +# 1546| StructuredBindingDataMemberStruct::RefType StructuredBindingDataMemberStruct::r_alt +# 1546| Block 0 +# 1546| v1546_1(void) = EnterFunction : +# 1546| mu1546_2(unknown) = AliasedDefinition : +# 1546| mu1546_3(unknown) = InitializeNonLocal : +# 1546| r1546_4(glval) = VariableAddress[#this] : +# 1546| mu1546_5(glval) = InitializeParameter[#this] : &:r1546_4 +# 1546| r1546_6(glval) = Load[#this] : &:r1546_4, ~m? +# 1546| mu1546_7(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1546_6 +# 1546| r1546_8(glval) = FieldAddress[r_alt] : r1546_6 +# 1546| r1546_9(StructuredBindingDataMemberStruct *) = CopyValue : r1546_6 +# 1546| r1546_10(glval) = FieldAddress[i] : r1546_9 +#-----| r0_1(int &) = CopyValue : r1546_10 +#-----| mu0_2(int &) = Store[?] : &:r1546_8, r0_1 +# 1546| v1546_11(void) = ReturnVoid : +# 1546| v1546_12(void) = AliasedUse : ~m? +# 1546| v1546_13(void) = ExitFunction : + # 1550| void data_member_structured_binding() # 1550| Block 0 # 1550| v1550_1(void) = EnterFunction : @@ -11675,6 +11799,56 @@ ir.cpp: # 1590| v1590_32(void) = AliasedUse : ~m? # 1590| v1590_33(void) = ExitFunction : +# 1591| int StructuredBindingTupleRefGet::i +# 1591| Block 0 +# 1591| v1591_1(void) = EnterFunction : +# 1591| mu1591_2(unknown) = AliasedDefinition : +# 1591| mu1591_3(unknown) = InitializeNonLocal : +# 1591| r1591_4(glval) = VariableAddress[#this] : +# 1591| mu1591_5(glval) = InitializeParameter[#this] : &:r1591_4 +# 1591| r1591_6(glval) = Load[#this] : &:r1591_4, ~m? +# 1591| mu1591_7(StructuredBindingTupleRefGet) = InitializeIndirection[#this] : &:r1591_6 +# 1591| r1591_8(glval) = FieldAddress[i] : r1591_6 +# 1591| r1591_9(int) = Constant[1] : +# 1591| mu1591_10(int) = Store[?] : &:r1591_8, r1591_9 +# 1591| v1591_11(void) = ReturnVoid : +# 1591| v1591_12(void) = AliasedUse : ~m? +# 1591| v1591_13(void) = ExitFunction : + +# 1592| double StructuredBindingTupleRefGet::d +# 1592| Block 0 +# 1592| v1592_1(void) = EnterFunction : +# 1592| mu1592_2(unknown) = AliasedDefinition : +# 1592| mu1592_3(unknown) = InitializeNonLocal : +# 1592| r1592_4(glval) = VariableAddress[#this] : +# 1592| mu1592_5(glval) = InitializeParameter[#this] : &:r1592_4 +# 1592| r1592_6(glval) = Load[#this] : &:r1592_4, ~m? +# 1592| mu1592_7(StructuredBindingTupleRefGet) = InitializeIndirection[#this] : &:r1592_6 +# 1592| r1592_8(glval) = FieldAddress[d] : r1592_6 +# 1592| r1592_9(double) = Constant[2.200000000000000178] : +# 1592| mu1592_10(double) = Store[?] : &:r1592_8, r1592_9 +# 1592| v1592_11(void) = ReturnVoid : +# 1592| v1592_12(void) = AliasedUse : ~m? +# 1592| v1592_13(void) = ExitFunction : + +# 1593| int& StructuredBindingTupleRefGet::r +# 1593| Block 0 +# 1593| v1593_1(void) = EnterFunction : +# 1593| mu1593_2(unknown) = AliasedDefinition : +# 1593| mu1593_3(unknown) = InitializeNonLocal : +# 1593| r1593_4(glval) = VariableAddress[#this] : +# 1593| mu1593_5(glval) = InitializeParameter[#this] : &:r1593_4 +# 1593| r1593_6(glval) = Load[#this] : &:r1593_4, ~m? +# 1593| mu1593_7(StructuredBindingTupleRefGet) = InitializeIndirection[#this] : &:r1593_6 +# 1593| r1593_8(glval) = FieldAddress[r] : r1593_6 +# 1593| r1593_9(StructuredBindingTupleRefGet *) = CopyValue : r1593_6 +# 1593| r1593_10(glval) = FieldAddress[i] : r1593_9 +#-----| r0_1(int &) = CopyValue : r1593_10 +#-----| mu0_2(int &) = Store[?] : &:r1593_8, r0_1 +# 1593| v1593_11(void) = ReturnVoid : +# 1593| v1593_12(void) = AliasedUse : ~m? +# 1593| v1593_13(void) = ExitFunction : + # 1618| std::tuple_element::type& StructuredBindingTupleRefGet::get() # 1618| Block 0 # 1618| v1618_1(void) = EnterFunction : @@ -11903,6 +12077,40 @@ ir.cpp: # 1657| v1657_11(void) = AliasedUse : ~m? # 1657| v1657_12(void) = ExitFunction : +# 1658| int StructuredBindingTupleNoRefGet::i +# 1658| Block 0 +# 1658| v1658_1(void) = EnterFunction : +# 1658| mu1658_2(unknown) = AliasedDefinition : +# 1658| mu1658_3(unknown) = InitializeNonLocal : +# 1658| r1658_4(glval) = VariableAddress[#this] : +# 1658| mu1658_5(glval) = InitializeParameter[#this] : &:r1658_4 +# 1658| r1658_6(glval) = Load[#this] : &:r1658_4, ~m? +# 1658| mu1658_7(StructuredBindingTupleNoRefGet) = InitializeIndirection[#this] : &:r1658_6 +# 1658| r1658_8(glval) = FieldAddress[i] : r1658_6 +# 1658| r1658_9(int) = Constant[1] : +# 1658| mu1658_10(int) = Store[?] : &:r1658_8, r1658_9 +# 1658| v1658_11(void) = ReturnVoid : +# 1658| v1658_12(void) = AliasedUse : ~m? +# 1658| v1658_13(void) = ExitFunction : + +# 1659| int& StructuredBindingTupleNoRefGet::r +# 1659| Block 0 +# 1659| v1659_1(void) = EnterFunction : +# 1659| mu1659_2(unknown) = AliasedDefinition : +# 1659| mu1659_3(unknown) = InitializeNonLocal : +# 1659| r1659_4(glval) = VariableAddress[#this] : +# 1659| mu1659_5(glval) = InitializeParameter[#this] : &:r1659_4 +# 1659| r1659_6(glval) = Load[#this] : &:r1659_4, ~m? +# 1659| mu1659_7(StructuredBindingTupleNoRefGet) = InitializeIndirection[#this] : &:r1659_6 +# 1659| r1659_8(glval) = FieldAddress[r] : r1659_6 +# 1659| r1659_9(StructuredBindingTupleNoRefGet *) = CopyValue : r1659_6 +# 1659| r1659_10(glval) = FieldAddress[i] : r1659_9 +#-----| r0_1(int &) = CopyValue : r1659_10 +#-----| mu0_2(int &) = Store[?] : &:r1659_8, r0_1 +# 1659| v1659_11(void) = ReturnVoid : +# 1659| v1659_12(void) = AliasedUse : ~m? +# 1659| v1659_13(void) = ExitFunction : + # 1684| std::tuple_element::type StructuredBindingTupleNoRefGet::get() # 1684| Block 0 # 1684| v1684_1(void) = EnterFunction : @@ -19200,6 +19408,109 @@ ir.cpp: # 2867| v2867_13(void) = ReturnVoid : #-----| Goto -> Block 1 +# 2890| int StructInit::i +# 2890| Block 0 +# 2890| v2890_1(void) = EnterFunction : +# 2890| mu2890_2(unknown) = AliasedDefinition : +# 2890| mu2890_3(unknown) = InitializeNonLocal : +# 2890| r2890_4(glval) = VariableAddress[#this] : +# 2890| mu2890_5(glval) = InitializeParameter[#this] : &:r2890_4 +# 2890| r2890_6(glval) = Load[#this] : &:r2890_4, ~m? +# 2890| mu2890_7(StructInit) = InitializeIndirection[#this] : &:r2890_6 +# 2890| r2890_8(glval) = FieldAddress[i] : r2890_6 +# 2890| r2890_9(int) = Constant[42] : +# 2890| mu2890_10(int) = Store[?] : &:r2890_8, r2890_9 +# 2890| v2890_11(void) = ReturnVoid : +# 2890| v2890_12(void) = AliasedUse : ~m? +# 2890| v2890_13(void) = ExitFunction : + +# 2891| int StructInit::j +# 2891| Block 0 +# 2891| v2891_1(void) = EnterFunction : +# 2891| mu2891_2(unknown) = AliasedDefinition : +# 2891| mu2891_3(unknown) = InitializeNonLocal : +# 2891| r2891_4(glval) = VariableAddress[#this] : +# 2891| mu2891_5(glval) = InitializeParameter[#this] : &:r2891_4 +# 2891| r2891_6(glval) = Load[#this] : &:r2891_4, ~m? +# 2891| mu2891_7(StructInit) = InitializeIndirection[#this] : &:r2891_6 +# 2891| r2891_8(glval) = FieldAddress[j] : r2891_6 +# 2891| r2891_9(int) = Constant[42] : +# 2891| mu2891_10(int) = Store[?] : &:r2891_8, r2891_9 +# 2891| v2891_11(void) = ReturnVoid : +# 2891| v2891_12(void) = AliasedUse : ~m? +# 2891| v2891_13(void) = ExitFunction : + +# 2892| int StructInit::k +# 2892| Block 0 +# 2892| v2892_1(void) = EnterFunction : +# 2892| mu2892_2(unknown) = AliasedDefinition : +# 2892| mu2892_3(unknown) = InitializeNonLocal : +# 2892| r2892_4(glval) = VariableAddress[#this] : +# 2892| mu2892_5(glval) = InitializeParameter[#this] : &:r2892_4 +# 2892| r2892_6(glval) = Load[#this] : &:r2892_4, ~m? +# 2892| mu2892_7(StructInit) = InitializeIndirection[#this] : &:r2892_6 +# 2892| r2892_8(glval) = FieldAddress[k] : r2892_6 +# 2892| r2892_9(int) = Constant[42] : +# 2892| mu2892_10(int) = Store[?] : &:r2892_8, r2892_9 +# 2892| v2892_11(void) = ReturnVoid : +# 2892| v2892_12(void) = AliasedUse : ~m? +# 2892| v2892_13(void) = ExitFunction : + +# 2893| int StructInit::l +# 2893| Block 0 +# 2893| v2893_1(void) = EnterFunction : +# 2893| mu2893_2(unknown) = AliasedDefinition : +# 2893| mu2893_3(unknown) = InitializeNonLocal : +# 2893| r2893_4(glval) = VariableAddress[#this] : +# 2893| mu2893_5(glval) = InitializeParameter[#this] : &:r2893_4 +# 2893| r2893_6(glval) = Load[#this] : &:r2893_4, ~m? +# 2893| mu2893_7(StructInit) = InitializeIndirection[#this] : &:r2893_6 +# 2893| r2893_8(glval) = FieldAddress[l] : r2893_6 +# 2893| r2893_9(StructInit *) = CopyValue : r2893_6 +# 2893| r2893_10(glval) = FieldAddress[k] : r2893_9 +# 2893| r2893_11(int) = Load[?] : &:r2893_10, ~m? +# 2893| mu2893_12(int) = Store[?] : &:r2893_8, r2893_11 +# 2893| v2893_13(void) = ReturnVoid : +# 2893| v2893_14(void) = AliasedUse : ~m? +# 2893| v2893_15(void) = ExitFunction : + +# 2894| int StructInit::m +# 2894| Block 0 +# 2894| v2894_1(void) = EnterFunction : +# 2894| mu2894_2(unknown) = AliasedDefinition : +# 2894| mu2894_3(unknown) = InitializeNonLocal : +# 2894| r2894_4(glval) = VariableAddress[#this] : +# 2894| mu2894_5(glval) = InitializeParameter[#this] : &:r2894_4 +# 2894| r2894_6(glval) = Load[#this] : &:r2894_4, ~m? +# 2894| mu2894_7(StructInit) = InitializeIndirection[#this] : &:r2894_6 +# 2894| r2894_8(glval) = FieldAddress[m] : r2894_6 +# 2894| r2894_9(StructInit *) = CopyValue : r2894_6 +# 2894| r2894_10(glval) = FunctionAddress[get_val] : +# 2894| r2894_11(int) = Call[get_val] : func:r2894_10, this:r2894_9 +# 2894| mu2894_12(unknown) = ^CallSideEffect : ~m? +# 2894| v2894_13(void) = ^IndirectReadSideEffect[-1] : &:r2894_9, ~m? +# 2894| mu2894_14(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2894_9 +# 2894| mu2894_15(int) = Store[?] : &:r2894_8, r2894_11 +# 2894| v2894_16(void) = ReturnVoid : +# 2894| v2894_17(void) = AliasedUse : ~m? +# 2894| v2894_18(void) = ExitFunction : + +# 2895| int StructInit::n +# 2895| Block 0 +# 2895| v2895_1(void) = EnterFunction : +# 2895| mu2895_2(unknown) = AliasedDefinition : +# 2895| mu2895_3(unknown) = InitializeNonLocal : +# 2895| r2895_4(glval) = VariableAddress[#this] : +# 2895| mu2895_5(glval) = InitializeParameter[#this] : &:r2895_4 +# 2895| r2895_6(glval) = Load[#this] : &:r2895_4, ~m? +# 2895| mu2895_7(StructInit) = InitializeIndirection[#this] : &:r2895_6 +# 2895| r2895_8(glval) = FieldAddress[n] : r2895_6 +# 2895| r2895_9(int) = Constant[42] : +# 2895| mu2895_10(int) = Store[?] : &:r2895_8, r2895_9 +# 2895| v2895_11(void) = ReturnVoid : +# 2895| v2895_12(void) = AliasedUse : ~m? +# 2895| v2895_13(void) = ExitFunction : + # 2897| void StructInit::StructInit(int) # 2897| Block 0 # 2897| v2897_1(void) = EnterFunction : From b91a52a050c521842951ecbb42ede17f48945aa6 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Mon, 2 Mar 2026 15:59:34 +0100 Subject: [PATCH 07/16] C++: Allow `getInstructionFunction` to yield a declaration --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll | 6 +++++- .../semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll | 5 +++-- .../code/cpp/ir/implementation/aliased_ssa/Instruction.qll | 6 +++--- .../semmle/code/cpp/ir/implementation/raw/Instruction.qll | 6 +++--- .../cpp/ir/implementation/raw/internal/IRConstruction.qll | 2 +- .../cpp/ir/implementation/raw/internal/TranslatedCall.qll | 2 +- .../ir/implementation/raw/internal/TranslatedElement.qll | 2 +- .../cpp/ir/implementation/raw/internal/TranslatedExpr.qll | 6 +++--- .../cpp/ir/implementation/unaliased_ssa/Instruction.qll | 6 +++--- 9 files changed, 23 insertions(+), 18 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll index 1895726ecb41..afec2384b233 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowNodes.qll @@ -878,7 +878,11 @@ module Public { /** Gets the parameter through which this value is assigned. */ Parameter getParameter() { - result = this.getCallInstruction().getStaticCallTarget().getParameter(this.getArgumentIndex()) + result = + this.getCallInstruction() + .getStaticCallTarget() + .(Function) + .getParameter(this.getArgumentIndex()) } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll index 45a6755356b5..4d109c0716d5 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaImplCommon.qll @@ -175,7 +175,8 @@ private class PointerWrapperTypeIndirection extends Indirection instanceof Point override predicate isAdditionalDereference(Instruction deref, Operand address) { exists(CallInstruction call | operandForFullyConvertedCall(getAUse(deref), call) and - this = call.getStaticCallTarget().getClassAndName(["operator*", "operator->", "get"]) and + this = + call.getStaticCallTarget().(Function).getClassAndName(["operator*", "operator->", "get"]) and address = call.getThisArgumentOperand() ) } @@ -194,7 +195,7 @@ private module IteratorIndirections { override predicate isAdditionalWrite(Node0Impl value, Operand address, boolean certain) { exists(CallInstruction call | call.getArgumentOperand(0) = value.asOperand() | - this = call.getStaticCallTarget().getClassAndName("operator=") and + this = call.getStaticCallTarget().(Function).getClassAndName("operator=") and address = call.getThisArgumentOperand() and certain = false ) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 8d3e960c3f87..b7dcd4d8f754 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -495,7 +495,7 @@ class FieldInstruction extends Instruction { * `FunctionAddress` instruction. */ class FunctionInstruction extends Instruction { - Language::Function funcSymbol; + Language::Declaration funcSymbol; FunctionInstruction() { funcSymbol = Raw::getInstructionFunction(this) } @@ -504,7 +504,7 @@ class FunctionInstruction extends Instruction { /** * Gets the function that this instruction references. */ - final Language::Function getFunctionSymbol() { result = funcSymbol } + final Language::Declaration getFunctionSymbol() { result = funcSymbol } } /** @@ -1678,7 +1678,7 @@ class CallInstruction extends Instruction { /** * Gets the `Function` that the call targets, if this is statically known. */ - final Language::Function getStaticCallTarget() { + final Language::Declaration getStaticCallTarget() { result = this.getCallTarget().(FunctionAddressInstruction).getFunctionSymbol() } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 8d3e960c3f87..b7dcd4d8f754 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -495,7 +495,7 @@ class FieldInstruction extends Instruction { * `FunctionAddress` instruction. */ class FunctionInstruction extends Instruction { - Language::Function funcSymbol; + Language::Declaration funcSymbol; FunctionInstruction() { funcSymbol = Raw::getInstructionFunction(this) } @@ -504,7 +504,7 @@ class FunctionInstruction extends Instruction { /** * Gets the function that this instruction references. */ - final Language::Function getFunctionSymbol() { result = funcSymbol } + final Language::Declaration getFunctionSymbol() { result = funcSymbol } } /** @@ -1678,7 +1678,7 @@ class CallInstruction extends Instruction { /** * Gets the `Function` that the call targets, if this is statically known. */ - final Language::Function getStaticCallTarget() { + final Language::Declaration getStaticCallTarget() { result = this.getCallTarget().(FunctionAddressInstruction).getFunctionSymbol() } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll index 7a667fcc0178..f3d88908cd6e 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll @@ -115,7 +115,7 @@ module Raw { } cached - Function getInstructionFunction(Instruction instruction) { + Declaration getInstructionFunction(Instruction instruction) { result = getInstructionTranslatedElement(instruction) .getInstructionFunction(getInstructionTag(instruction)) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 1a5c65d364de..f3d084883a71 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -348,7 +348,7 @@ class TranslatedExprCall extends TranslatedCallExpr { class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall { override FunctionCall expr; - override Function getInstructionFunction(InstructionTag tag) { + override Declaration getInstructionFunction(InstructionTag tag) { tag = CallTargetTag() and result = expr.getTarget() } 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 c30cc4bbc5c5..117c92e3fe5e 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 @@ -1182,7 +1182,7 @@ abstract class TranslatedElement extends TTranslatedElement { * If the instruction specified by `tag` is a `FunctionInstruction`, gets the * `Function` for that instruction. */ - Function getInstructionFunction(InstructionTag tag) { none() } + Declaration getInstructionFunction(InstructionTag tag) { none() } /** * If the instruction specified by `tag` is a `VariableInstruction`, gets 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 712f140e5b8e..9a437b905381 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 @@ -1264,7 +1264,7 @@ class TranslatedFunctionAccess extends TranslatedNonConstantExpr { resultType = this.getResultType() } - override Function getInstructionFunction(InstructionTag tag) { + override Declaration getInstructionFunction(InstructionTag tag) { tag = OnlyInstructionTag() and result = expr.getTarget() } @@ -2547,7 +2547,7 @@ class TranslatedAllocatorCall extends TTranslatedAllocatorCall, TranslatedDirect any() } - override Function getInstructionFunction(InstructionTag tag) { + override Declaration getInstructionFunction(InstructionTag tag) { tag = CallTargetTag() and result = expr.getAllocator() } @@ -2630,7 +2630,7 @@ class TranslatedDeleteOrDeleteArrayExpr extends TranslatedNonConstantExpr, Trans result = this.getFirstArgumentOrCallInstruction(kind) } - override Function getInstructionFunction(InstructionTag tag) { + override Declaration getInstructionFunction(InstructionTag tag) { tag = CallTargetTag() and result = expr.getDeallocator() } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 8d3e960c3f87..b7dcd4d8f754 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -495,7 +495,7 @@ class FieldInstruction extends Instruction { * `FunctionAddress` instruction. */ class FunctionInstruction extends Instruction { - Language::Function funcSymbol; + Language::Declaration funcSymbol; FunctionInstruction() { funcSymbol = Raw::getInstructionFunction(this) } @@ -504,7 +504,7 @@ class FunctionInstruction extends Instruction { /** * Gets the function that this instruction references. */ - final Language::Function getFunctionSymbol() { result = funcSymbol } + final Language::Declaration getFunctionSymbol() { result = funcSymbol } } /** @@ -1678,7 +1678,7 @@ class CallInstruction extends Instruction { /** * Gets the `Function` that the call targets, if this is statically known. */ - final Language::Function getStaticCallTarget() { + final Language::Declaration getStaticCallTarget() { result = this.getCallTarget().(FunctionAddressInstruction).getFunctionSymbol() } From e986d8922aefb2c3c6afb98a2ebdccab002b309d Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 3 Mar 2026 11:20:17 +0100 Subject: [PATCH 08/16] C++: Call functions for NSDMI initialization Currently missing: side-effect information for the functions --- .../raw/internal/TranslatedElement.qll | 10 +- .../raw/internal/TranslatedInitialization.qll | 88 +++++- .../library-tests/ir/ir/aliased_ir.expected | 279 +++++++++++------- .../ir/ir/raw_consistency.expected | 4 - .../test/library-tests/ir/ir/raw_ir.expected | 195 ++++++------ 5 files changed, 369 insertions(+), 207 deletions(-) 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 117c92e3fe5e..66ad2ae26793 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 @@ -767,7 +767,7 @@ newtype TTranslatedElement = expr = initList.getFieldExpr(field, position).getFullyConverted() ) or - exists(ConstructorFieldInit init | + exists(ConstructorDirectFieldInit init | not ignoreExpr(init) and ast = init and field = init.getTarget() and @@ -775,6 +775,14 @@ newtype TTranslatedElement = position = -1 ) } or + // The initialization of a field via a default member initializer. + TTranslatedDefaultFieldInitialization(Expr ast, Field field) { + exists(ConstructorDefaultFieldInit init | + not ignoreExpr(init) and + ast = init and + field = init.getTarget() + ) + } or // The value initialization of a field due to an omitted member of an // initializer list. TTranslatedFieldValueInitialization(Expr ast, Field field) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll index 581b0886f7f0..f5d092ca44ae 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -533,10 +533,7 @@ abstract class TranslatedFieldInitialization extends TranslatedElement { result = getEnclosingVariable(ast).(Field) } - final override Instruction getFirstInstruction(EdgeKind kind) { - result = this.getInstruction(this.getFieldAddressTag()) and - kind instanceof GotoEdge - } + final Field getField() { result = field } /** * Gets the zero-based index describing the order in which this field is to be @@ -544,6 +541,20 @@ abstract class TranslatedFieldInitialization extends TranslatedElement { */ final int getOrder() { result = field.getInitializationOrder() } + /** Gets the position in the initializer list, or `-1` if the initialization is implicit. */ + int getPosition() { result = -1 } +} + +/** + * Represents the IR translation of the initialization of a field from an + * element of an initializer list where default initialization is not used. + */ +abstract class TranslatedNonDefaultFieldInitialization extends TranslatedFieldInitialization { + final override Instruction getFirstInstruction(EdgeKind kind) { + result = this.getInstruction(this.getFieldAddressTag()) and + kind instanceof GotoEdge + } + override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { tag = this.getFieldAddressTag() and opcode instanceof Opcode::FieldAddress and @@ -561,18 +572,13 @@ abstract class TranslatedFieldInitialization extends TranslatedElement { } final InstructionTag getFieldAddressTag() { result = InitializerFieldAddressTag() } - - final Field getField() { result = field } - - /** Gets the position in the initializer list, or `-1` if the initialization is implicit. */ - int getPosition() { result = -1 } } /** * Represents the IR translation of the initialization of a field from an * explicit element in an initializer list. */ -class TranslatedExplicitFieldInitialization extends TranslatedFieldInitialization, +class TranslatedExplicitFieldInitialization extends TranslatedNonDefaultFieldInitialization, InitializationContext, TTranslatedExplicitFieldInitialization { Expr expr; @@ -612,6 +618,61 @@ class TranslatedExplicitFieldInitialization extends TranslatedFieldInitializatio override int getPosition() { result = position } } +/** + * Represents the IR translation of the initialization of a field from an + * element of an initializer list where default initialization is used. + */ +class TranslatedDefaultFieldInitialization extends TranslatedFieldInitialization, + TTranslatedDefaultFieldInitialization +{ + TranslatedDefaultFieldInitialization() { + this = TTranslatedDefaultFieldInitialization(ast, field) + } + + final override Instruction getFirstInstruction(EdgeKind kind) { + result = this.getInstruction(CallTargetTag()) and + kind instanceof GotoEdge + } + + override Instruction getALastInstructionInternal() { result = this.getInstruction(CallTag()) } + + override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { + tag = CallTargetTag() and + result = this.getInstruction(CallTag()) + or + tag = CallTag() and + result = this.getParent().getChildSuccessor(this, kind) + } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { + tag = CallTargetTag() and + opcode instanceof Opcode::FunctionAddress and + resultType = getFunctionGLValueType() + or + tag = CallTag() and + opcode instanceof Opcode::Call and + resultType = getVoidType() + } + + override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { + tag = CallTag() and + ( + operandTag instanceof CallTargetOperandTag and + result = this.getInstruction(CallTargetTag()) + or + operandTag instanceof ThisArgumentOperandTag and + result = getTranslatedFunction(this.getFunction()).getLoadThisInstruction() + ) + } + + override Declaration getInstructionFunction(InstructionTag tag) { + tag = CallTargetTag() and + result = field + } + + override TranslatedElement getChild(int id) { none() } +} + private string getZeroValue(Type type) { if type instanceof FloatingPointType then result = "0.0" else result = "0" } @@ -620,7 +681,7 @@ private string getZeroValue(Type type) { * Represents the IR translation of the initialization of a field without a * corresponding element in the initializer list. */ -class TranslatedFieldValueInitialization extends TranslatedFieldInitialization, +class TranslatedFieldValueInitialization extends TranslatedNonDefaultFieldInitialization, TTranslatedFieldValueInitialization { TranslatedFieldValueInitialization() { this = TTranslatedFieldValueInitialization(ast, field) } @@ -630,7 +691,7 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization, } override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) { - TranslatedFieldInitialization.super.hasInstruction(opcode, tag, resultType) + TranslatedNonDefaultFieldInitialization.super.hasInstruction(opcode, tag, resultType) or tag = this.getFieldDefaultValueTag() and opcode instanceof Opcode::Constant and @@ -661,7 +722,8 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization, } override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { - result = TranslatedFieldInitialization.super.getInstructionRegisterOperand(tag, operandTag) + result = + TranslatedNonDefaultFieldInitialization.super.getInstructionRegisterOperand(tag, operandTag) or tag = this.getFieldDefaultValueStoreTag() and ( 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 40a424f7f9a4..20e254f066e3 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -12369,11 +12369,14 @@ ir.cpp: # 1533| m1533_6(glval) = InitializeParameter[#this] : &:r1533_5 # 1533| r1533_7(glval) = Load[#this] : &:r1533_5, m1533_6 # 1533| m1533_8(StructuredBindingDataMemberMemberStruct) = InitializeIndirection[#this] : &:r1533_7 -# 1533| v1533_9(void) = NoOp : -# 1533| v1533_10(void) = ReturnIndirection[#this] : &:r1533_7, m1533_8 -# 1533| v1533_11(void) = ReturnVoid : -# 1533| v1533_12(void) = AliasedUse : m1533_3 -# 1533| v1533_13(void) = ExitFunction : +# 1533| m1533_9(unknown) = Chi : total:m1533_4, partial:m1533_8 +# 1533| r1533_10(glval) = FunctionAddress[x] : +# 1533| v1533_11(void) = Call[x] : func:r1533_10, this:r1533_7 +# 1533| v1533_12(void) = NoOp : +# 1533| v1533_13(void) = ReturnIndirection[#this] : &:r1533_7, m1533_8 +# 1533| v1533_14(void) = ReturnVoid : +# 1533| v1533_15(void) = AliasedUse : ~m1533_9 +# 1533| v1533_16(void) = ExitFunction : # 1534| int StructuredBindingDataMemberMemberStruct::x # 1534| Block 0 @@ -12395,19 +12398,39 @@ ir.cpp: # 1537| void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() # 1537| Block 0 -# 1537| v1537_1(void) = EnterFunction : -# 1537| m1537_2(unknown) = AliasedDefinition : -# 1537| m1537_3(unknown) = InitializeNonLocal : -# 1537| m1537_4(unknown) = Chi : total:m1537_2, partial:m1537_3 -# 1537| r1537_5(glval) = VariableAddress[#this] : -# 1537| m1537_6(glval) = InitializeParameter[#this] : &:r1537_5 -# 1537| r1537_7(glval) = Load[#this] : &:r1537_5, m1537_6 -# 1537| m1537_8(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1537_7 -# 1537| v1537_9(void) = NoOp : -# 1537| v1537_10(void) = ReturnIndirection[#this] : &:r1537_7, m1537_8 -# 1537| v1537_11(void) = ReturnVoid : -# 1537| v1537_12(void) = AliasedUse : m1537_3 -# 1537| v1537_13(void) = ExitFunction : +# 1537| v1537_1(void) = EnterFunction : +# 1537| m1537_2(unknown) = AliasedDefinition : +# 1537| m1537_3(unknown) = InitializeNonLocal : +# 1537| m1537_4(unknown) = Chi : total:m1537_2, partial:m1537_3 +# 1537| r1537_5(glval) = VariableAddress[#this] : +# 1537| m1537_6(glval) = InitializeParameter[#this] : &:r1537_5 +# 1537| r1537_7(glval) = Load[#this] : &:r1537_5, m1537_6 +# 1537| m1537_8(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1537_7 +# 1537| m1537_9(unknown) = Chi : total:m1537_4, partial:m1537_8 +# 1537| r1537_10(glval) = FunctionAddress[i] : +# 1537| v1537_11(void) = Call[i] : func:r1537_10, this:r1537_7 +# 1537| r1537_12(glval) = FunctionAddress[d] : +# 1537| v1537_13(void) = Call[d] : func:r1537_12, this:r1537_7 +# 1537| r1537_14(glval) = FunctionAddress[r] : +# 1537| v1537_15(void) = Call[r] : func:r1537_14, this:r1537_7 +# 1537| r1537_16(glval) = FunctionAddress[p] : +# 1537| v1537_17(void) = Call[p] : func:r1537_16, this:r1537_7 +# 1537| r1537_18(glval) = FunctionAddress[xs] : +# 1537| v1537_19(void) = Call[xs] : func:r1537_18, this:r1537_7 +# 1537| r1537_20(glval) = FunctionAddress[r_alt] : +# 1537| v1537_21(void) = Call[r_alt] : func:r1537_20, this:r1537_7 +# 1537| r1537_22(glval) = FieldAddress[m] : r1537_7 +# 1537| r1537_23(glval) = FunctionAddress[StructuredBindingDataMemberMemberStruct] : +# 1537| v1537_24(void) = Call[StructuredBindingDataMemberMemberStruct] : func:r1537_23, this:r1537_22 +# 1537| m1537_25(unknown) = ^CallSideEffect : ~m1537_9 +# 1537| m1537_26(unknown) = Chi : total:m1537_9, partial:m1537_25 +# 1537| m1537_27(StructuredBindingDataMemberMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_22 +# 1537| m1537_28(unknown) = Chi : total:m1537_26, partial:m1537_27 +# 1537| v1537_29(void) = NoOp : +# 1537| v1537_30(void) = ReturnIndirection[#this] : &:r1537_7, ~m1537_28 +# 1537| v1537_31(void) = ReturnVoid : +# 1537| v1537_32(void) = AliasedUse : ~m1537_28 +# 1537| v1537_33(void) = ExitFunction : # 1537| void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct(StructuredBindingDataMemberStruct const&) # 1537| Block 0 @@ -12626,15 +12649,16 @@ ir.cpp: # 1550| m1550_4(unknown) = Chi : total:m1550_2, partial:m1550_3 # 1551| r1551_1(glval) = VariableAddress[s] : # 1551| m1551_2(StructuredBindingDataMemberStruct) = Uninitialized[s] : &:r1551_1 -# 1551| r1551_3(glval) = FunctionAddress[StructuredBindingDataMemberStruct] : -# 1551| v1551_4(void) = Call[StructuredBindingDataMemberStruct] : func:r1551_3, this:r1551_1 -# 1551| m1551_5(unknown) = ^CallSideEffect : ~m1550_4 -# 1551| m1551_6(unknown) = Chi : total:m1550_4, partial:m1551_5 -# 1551| m1551_7(StructuredBindingDataMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1551_1 -# 1551| m1551_8(StructuredBindingDataMemberStruct) = Chi : total:m1551_2, partial:m1551_7 +# 1551| m1551_3(unknown) = Chi : total:m1550_4, partial:m1551_2 +# 1551| r1551_4(glval) = FunctionAddress[StructuredBindingDataMemberStruct] : +# 1551| v1551_5(void) = Call[StructuredBindingDataMemberStruct] : func:r1551_4, this:r1551_1 +# 1551| m1551_6(unknown) = ^CallSideEffect : ~m1551_3 +# 1551| m1551_7(unknown) = Chi : total:m1551_3, partial:m1551_6 +# 1551| m1551_8(StructuredBindingDataMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1551_1 +# 1551| m1551_9(unknown) = Chi : total:m1551_7, partial:m1551_8 # 1554| r1554_1(glval) = VariableAddress[(unnamed local variable)] : # 1554| r1554_2(glval) = VariableAddress[s] : -# 1554| r1554_3(StructuredBindingDataMemberStruct) = Load[s] : &:r1554_2, m1551_8 +# 1554| r1554_3(StructuredBindingDataMemberStruct) = Load[s] : &:r1554_2, ~m1551_9 # 1554| m1554_4(StructuredBindingDataMemberStruct) = Store[(unnamed local variable)] : &:r1554_1, r1554_3 # 1554| r1554_5(glval) = VariableAddress[i] : # 1554| r1554_6(glval) = VariableAddress[(unnamed local variable)] : @@ -12691,7 +12715,7 @@ ir.cpp: # 1558| r1558_2(glval) = VariableAddress[r] : # 1558| r1558_3(int &) = Load[r] : &:r1558_2, m1554_22 # 1558| m1558_4(int) = Store[?] : &:r1558_3, r1558_1 -# 1558| m1558_5(unknown) = Chi : total:m1551_6, partial:m1558_4 +# 1558| m1558_5(unknown) = Chi : total:m1551_9, partial:m1558_4 # 1559| r1559_1(int) = Constant[6] : # 1559| r1559_2(glval) = VariableAddress[p] : # 1559| r1559_3(int *&) = Load[p] : &:r1559_2, m1554_26 @@ -12716,7 +12740,7 @@ ir.cpp: # 1562| m1562_5(int) = Store[w] : &:r1562_1, r1562_4 # 1566| r1566_1(glval) = VariableAddress[unnamed_local_variable] : # 1566| r1566_2(glval) = VariableAddress[s] : -# 1566| r1566_3(StructuredBindingDataMemberStruct) = Load[s] : &:r1566_2, m1551_8 +# 1566| r1566_3(StructuredBindingDataMemberStruct) = Load[s] : &:r1566_2, ~m1559_7 # 1566| m1566_4(StructuredBindingDataMemberStruct) = Store[unnamed_local_variable] : &:r1566_1, r1566_3 # 1567| r1567_1(glval) = VariableAddress[i] : # 1567| r1567_2(glval) = VariableAddress[unnamed_local_variable] : @@ -12802,11 +12826,18 @@ ir.cpp: # 1590| m1590_6(glval) = InitializeParameter[#this] : &:r1590_5 # 1590| r1590_7(glval) = Load[#this] : &:r1590_5, m1590_6 # 1590| m1590_8(StructuredBindingTupleRefGet) = InitializeIndirection[#this] : &:r1590_7 -# 1590| v1590_9(void) = NoOp : -# 1590| v1590_10(void) = ReturnIndirection[#this] : &:r1590_7, m1590_8 -# 1590| v1590_11(void) = ReturnVoid : -# 1590| v1590_12(void) = AliasedUse : m1590_3 -# 1590| v1590_13(void) = ExitFunction : +# 1590| m1590_9(unknown) = Chi : total:m1590_4, partial:m1590_8 +# 1590| r1590_10(glval) = FunctionAddress[i] : +# 1590| v1590_11(void) = Call[i] : func:r1590_10, this:r1590_7 +# 1590| r1590_12(glval) = FunctionAddress[d] : +# 1590| v1590_13(void) = Call[d] : func:r1590_12, this:r1590_7 +# 1590| r1590_14(glval) = FunctionAddress[r] : +# 1590| v1590_15(void) = Call[r] : func:r1590_14, this:r1590_7 +# 1590| v1590_16(void) = NoOp : +# 1590| v1590_17(void) = ReturnIndirection[#this] : &:r1590_7, m1590_8 +# 1590| v1590_18(void) = ReturnVoid : +# 1590| v1590_19(void) = AliasedUse : ~m1590_9 +# 1590| v1590_20(void) = ExitFunction : # 1590| void StructuredBindingTupleRefGet::StructuredBindingTupleRefGet(StructuredBindingTupleRefGet const&) # 1590| Block 0 @@ -12986,22 +13017,23 @@ ir.cpp: # 1630| m1630_4(unknown) = Chi : total:m1630_2, partial:m1630_3 # 1631| r1631_1(glval) = VariableAddress[t] : # 1631| m1631_2(StructuredBindingTupleRefGet) = Uninitialized[t] : &:r1631_1 -# 1631| r1631_3(glval) = FunctionAddress[StructuredBindingTupleRefGet] : -# 1631| v1631_4(void) = Call[StructuredBindingTupleRefGet] : func:r1631_3, this:r1631_1 -# 1631| m1631_5(unknown) = ^CallSideEffect : ~m1630_4 -# 1631| m1631_6(unknown) = Chi : total:m1630_4, partial:m1631_5 -# 1631| m1631_7(StructuredBindingTupleRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1631_1 -# 1631| m1631_8(StructuredBindingTupleRefGet) = Chi : total:m1631_2, partial:m1631_7 +# 1631| m1631_3(unknown) = Chi : total:m1630_4, partial:m1631_2 +# 1631| r1631_4(glval) = FunctionAddress[StructuredBindingTupleRefGet] : +# 1631| v1631_5(void) = Call[StructuredBindingTupleRefGet] : func:r1631_4, this:r1631_1 +# 1631| m1631_6(unknown) = ^CallSideEffect : ~m1631_3 +# 1631| m1631_7(unknown) = Chi : total:m1631_3, partial:m1631_6 +# 1631| m1631_8(StructuredBindingTupleRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1631_1 +# 1631| m1631_9(unknown) = Chi : total:m1631_7, partial:m1631_8 # 1634| r1634_1(glval) = VariableAddress[(unnamed local variable)] : # 1634| r1634_2(glval) = VariableAddress[t] : -# 1634| r1634_3(StructuredBindingTupleRefGet) = Load[t] : &:r1634_2, m1631_8 +# 1634| r1634_3(StructuredBindingTupleRefGet) = Load[t] : &:r1634_2, ~m1631_9 # 1634| m1634_4(StructuredBindingTupleRefGet) = Store[(unnamed local variable)] : &:r1634_1, r1634_3 # 1634| r1634_5(glval) = VariableAddress[i] : # 1634| r1634_6(glval) = VariableAddress[(unnamed local variable)] : # 1634| r1634_7(glval) = FunctionAddress[get] : # 1634| r1634_8(int &) = Call[get] : func:r1634_7, this:r1634_6 -# 1634| m1634_9(unknown) = ^CallSideEffect : ~m1631_6 -# 1634| m1634_10(unknown) = Chi : total:m1631_6, partial:m1634_9 +# 1634| m1634_9(unknown) = ^CallSideEffect : ~m1631_9 +# 1634| m1634_10(unknown) = Chi : total:m1631_9, partial:m1634_9 # 1634| v1634_11(void) = ^IndirectReadSideEffect[-1] : &:r1634_6, m1634_4 # 1634| m1634_12(StructuredBindingTupleRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1634_6 # 1634| m1634_13(StructuredBindingTupleRefGet) = Chi : total:m1634_4, partial:m1634_12 @@ -13068,7 +13100,7 @@ ir.cpp: # 1640| m1640_5(int) = Store[w] : &:r1640_1, r1640_4 # 1644| r1644_1(glval) = VariableAddress[unnamed_local_variable] : # 1644| r1644_2(glval) = VariableAddress[t] : -# 1644| r1644_3(StructuredBindingTupleRefGet) = Load[t] : &:r1644_2, m1631_8 +# 1644| r1644_3(StructuredBindingTupleRefGet) = Load[t] : &:r1644_2, ~m1638_6 # 1644| m1644_4(StructuredBindingTupleRefGet) = Store[unnamed_local_variable] : &:r1644_1, r1644_3 # 1645| r1645_1(glval) = VariableAddress[i] : # 1645| r1645_2(glval) = VariableAddress[unnamed_local_variable] : @@ -13155,11 +13187,16 @@ ir.cpp: # 1657| m1657_6(glval) = InitializeParameter[#this] : &:r1657_5 # 1657| r1657_7(glval) = Load[#this] : &:r1657_5, m1657_6 # 1657| m1657_8(StructuredBindingTupleNoRefGet) = InitializeIndirection[#this] : &:r1657_7 -# 1657| v1657_9(void) = NoOp : -# 1657| v1657_10(void) = ReturnIndirection[#this] : &:r1657_7, m1657_8 -# 1657| v1657_11(void) = ReturnVoid : -# 1657| v1657_12(void) = AliasedUse : m1657_3 -# 1657| v1657_13(void) = ExitFunction : +# 1657| m1657_9(unknown) = Chi : total:m1657_4, partial:m1657_8 +# 1657| r1657_10(glval) = FunctionAddress[i] : +# 1657| v1657_11(void) = Call[i] : func:r1657_10, this:r1657_7 +# 1657| r1657_12(glval) = FunctionAddress[r] : +# 1657| v1657_13(void) = Call[r] : func:r1657_12, this:r1657_7 +# 1657| v1657_14(void) = NoOp : +# 1657| v1657_15(void) = ReturnIndirection[#this] : &:r1657_7, m1657_8 +# 1657| v1657_16(void) = ReturnVoid : +# 1657| v1657_17(void) = AliasedUse : ~m1657_9 +# 1657| v1657_18(void) = ExitFunction : # 1658| int StructuredBindingTupleNoRefGet::i # 1658| Block 0 @@ -13276,12 +13313,13 @@ ir.cpp: # 1696| m1696_4(unknown) = Chi : total:m1696_2, partial:m1696_3 # 1697| r1697_1(glval) = VariableAddress[t] : # 1697| m1697_2(StructuredBindingTupleNoRefGet) = Uninitialized[t] : &:r1697_1 -# 1697| r1697_3(glval) = FunctionAddress[StructuredBindingTupleNoRefGet] : -# 1697| v1697_4(void) = Call[StructuredBindingTupleNoRefGet] : func:r1697_3, this:r1697_1 -# 1697| m1697_5(unknown) = ^CallSideEffect : ~m1696_4 -# 1697| m1697_6(unknown) = Chi : total:m1696_4, partial:m1697_5 -# 1697| m1697_7(StructuredBindingTupleNoRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1697_1 -# 1697| m1697_8(StructuredBindingTupleNoRefGet) = Chi : total:m1697_2, partial:m1697_7 +# 1697| m1697_3(unknown) = Chi : total:m1696_4, partial:m1697_2 +# 1697| r1697_4(glval) = FunctionAddress[StructuredBindingTupleNoRefGet] : +# 1697| v1697_5(void) = Call[StructuredBindingTupleNoRefGet] : func:r1697_4, this:r1697_1 +# 1697| m1697_6(unknown) = ^CallSideEffect : ~m1697_3 +# 1697| m1697_7(unknown) = Chi : total:m1697_3, partial:m1697_6 +# 1697| m1697_8(StructuredBindingTupleNoRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1697_1 +# 1697| m1697_9(unknown) = Chi : total:m1697_7, partial:m1697_8 # 1700| r1700_1(glval) = VariableAddress[(unnamed local variable)] : # 1700| r1700_2(glval) = VariableAddress[t] : # 1700| r1700_3(StructuredBindingTupleNoRefGet &) = CopyValue : r1700_2 @@ -13293,11 +13331,11 @@ ir.cpp: # 1700| r1700_9(glval) = CopyValue : r1700_8 # 1700| r1700_10(glval) = FunctionAddress[get] : # 1700| r1700_11(int) = Call[get] : func:r1700_10, this:r1700_9 -# 1700| m1700_12(unknown) = ^CallSideEffect : ~m1697_6 -# 1700| m1700_13(unknown) = Chi : total:m1697_6, partial:m1700_12 -# 1700| v1700_14(void) = ^IndirectReadSideEffect[-1] : &:r1700_9, m1697_8 +# 1700| m1700_12(unknown) = ^CallSideEffect : ~m1697_9 +# 1700| m1700_13(unknown) = Chi : total:m1697_9, partial:m1700_12 +# 1700| v1700_14(void) = ^IndirectReadSideEffect[-1] : &:r1700_9, ~m1700_13 # 1700| m1700_15(StructuredBindingTupleNoRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1700_9 -# 1700| m1700_16(StructuredBindingTupleNoRefGet) = Chi : total:m1697_8, partial:m1700_15 +# 1700| m1700_16(unknown) = Chi : total:m1700_13, partial:m1700_15 # 1700| m1700_17(int) = Store[#temp1700:16] : &:r1700_6, r1700_11 # 1700| r1700_18(int &) = CopyValue : r1700_6 # 1700| m1700_19(int &&) = Store[i] : &:r1700_5, r1700_18 @@ -13307,11 +13345,11 @@ ir.cpp: # 1700| r1700_23(glval) = CopyValue : r1700_22 # 1700| r1700_24(glval) = FunctionAddress[get] : # 1700| r1700_25(int &) = Call[get] : func:r1700_24, this:r1700_23 -# 1700| m1700_26(unknown) = ^CallSideEffect : ~m1700_13 -# 1700| m1700_27(unknown) = Chi : total:m1700_13, partial:m1700_26 -# 1700| v1700_28(void) = ^IndirectReadSideEffect[-1] : &:r1700_23, m1700_16 +# 1700| m1700_26(unknown) = ^CallSideEffect : ~m1700_16 +# 1700| m1700_27(unknown) = Chi : total:m1700_16, partial:m1700_26 +# 1700| v1700_28(void) = ^IndirectReadSideEffect[-1] : &:r1700_23, ~m1700_27 # 1700| m1700_29(StructuredBindingTupleNoRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1700_23 -# 1700| m1700_30(StructuredBindingTupleNoRefGet) = Chi : total:m1700_16, partial:m1700_29 +# 1700| m1700_30(unknown) = Chi : total:m1700_27, partial:m1700_29 # 1700| r1700_31(glval) = CopyValue : r1700_25 # 1700| r1700_32(int &) = CopyValue : r1700_31 # 1700| m1700_33(int &) = Store[r] : &:r1700_20, r1700_32 @@ -13321,11 +13359,11 @@ ir.cpp: # 1700| r1700_37(glval) = CopyValue : r1700_36 # 1700| r1700_38(glval) = FunctionAddress[get] : # 1700| r1700_39(int &&) = Call[get] : func:r1700_38, this:r1700_37 -# 1700| m1700_40(unknown) = ^CallSideEffect : ~m1700_27 -# 1700| m1700_41(unknown) = Chi : total:m1700_27, partial:m1700_40 -# 1700| v1700_42(void) = ^IndirectReadSideEffect[-1] : &:r1700_37, m1700_30 +# 1700| m1700_40(unknown) = ^CallSideEffect : ~m1700_30 +# 1700| m1700_41(unknown) = Chi : total:m1700_30, partial:m1700_40 +# 1700| v1700_42(void) = ^IndirectReadSideEffect[-1] : &:r1700_37, ~m1700_41 # 1700| m1700_43(StructuredBindingTupleNoRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1700_37 -# 1700| m1700_44(StructuredBindingTupleNoRefGet) = Chi : total:m1700_30, partial:m1700_43 +# 1700| m1700_44(unknown) = Chi : total:m1700_41, partial:m1700_43 # 1700| r1700_45(glval) = CopyValue : r1700_39 # 1700| r1700_46(int &) = CopyValue : r1700_45 # 1700| m1700_47(int &&) = Store[rv] : &:r1700_34, r1700_46 @@ -13350,7 +13388,7 @@ ir.cpp: # 1704| r1704_3(int &) = Load[r] : &:r1704_2, m1700_33 # 1704| r1704_4(glval) = CopyValue : r1704_3 # 1704| m1704_5(int) = Store[?] : &:r1704_4, r1704_1 -# 1704| m1704_6(unknown) = Chi : total:m1700_41, partial:m1704_5 +# 1704| m1704_6(unknown) = Chi : total:m1700_44, partial:m1704_5 # 1705| r1705_1(glval) = VariableAddress[rr] : # 1705| r1705_2(glval) = VariableAddress[r] : # 1705| r1705_3(int &) = Load[r] : &:r1705_2, m1700_33 @@ -13375,9 +13413,9 @@ ir.cpp: # 1711| r1711_7(int) = Call[get] : func:r1711_6, this:r1711_5 # 1711| m1711_8(unknown) = ^CallSideEffect : ~m1704_6 # 1711| m1711_9(unknown) = Chi : total:m1704_6, partial:m1711_8 -# 1711| v1711_10(void) = ^IndirectReadSideEffect[-1] : &:r1711_5, m1700_44 +# 1711| v1711_10(void) = ^IndirectReadSideEffect[-1] : &:r1711_5, ~m1711_9 # 1711| m1711_11(StructuredBindingTupleNoRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1711_5 -# 1711| m1711_12(StructuredBindingTupleNoRefGet) = Chi : total:m1700_44, partial:m1711_11 +# 1711| m1711_12(unknown) = Chi : total:m1711_9, partial:m1711_11 # 1711| m1711_13(int) = Store[#temp1711:20] : &:r1711_2, r1711_7 # 1711| r1711_14(int &) = CopyValue : r1711_2 # 1711| m1711_15(int &&) = Store[i] : &:r1711_1, r1711_14 @@ -13387,11 +13425,11 @@ ir.cpp: # 1712| r1712_4(glval) = CopyValue : r1712_3 # 1712| r1712_5(glval) = FunctionAddress[get] : # 1712| r1712_6(int &) = Call[get] : func:r1712_5, this:r1712_4 -# 1712| m1712_7(unknown) = ^CallSideEffect : ~m1711_9 -# 1712| m1712_8(unknown) = Chi : total:m1711_9, partial:m1712_7 -# 1712| v1712_9(void) = ^IndirectReadSideEffect[-1] : &:r1712_4, m1711_12 +# 1712| m1712_7(unknown) = ^CallSideEffect : ~m1711_12 +# 1712| m1712_8(unknown) = Chi : total:m1711_12, partial:m1712_7 +# 1712| v1712_9(void) = ^IndirectReadSideEffect[-1] : &:r1712_4, ~m1712_8 # 1712| m1712_10(StructuredBindingTupleNoRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1712_4 -# 1712| m1712_11(StructuredBindingTupleNoRefGet) = Chi : total:m1711_12, partial:m1712_10 +# 1712| m1712_11(unknown) = Chi : total:m1712_8, partial:m1712_10 # 1712| r1712_12(glval) = CopyValue : r1712_6 # 1712| r1712_13(int &) = CopyValue : r1712_12 # 1712| m1712_14(int &) = Store[r] : &:r1712_1, r1712_13 @@ -13401,11 +13439,11 @@ ir.cpp: # 1713| r1713_4(glval) = CopyValue : r1713_3 # 1713| r1713_5(glval) = FunctionAddress[get] : # 1713| r1713_6(int &&) = Call[get] : func:r1713_5, this:r1713_4 -# 1713| m1713_7(unknown) = ^CallSideEffect : ~m1712_8 -# 1713| m1713_8(unknown) = Chi : total:m1712_8, partial:m1713_7 -# 1713| v1713_9(void) = ^IndirectReadSideEffect[-1] : &:r1713_4, m1712_11 +# 1713| m1713_7(unknown) = ^CallSideEffect : ~m1712_11 +# 1713| m1713_8(unknown) = Chi : total:m1712_11, partial:m1713_7 +# 1713| v1713_9(void) = ^IndirectReadSideEffect[-1] : &:r1713_4, ~m1713_8 # 1713| m1713_10(StructuredBindingTupleNoRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1713_4 -# 1713| m1713_11(StructuredBindingTupleNoRefGet) = Chi : total:m1712_11, partial:m1713_10 +# 1713| m1713_11(unknown) = Chi : total:m1713_8, partial:m1713_10 # 1713| r1713_12(glval) = CopyValue : r1713_6 # 1713| r1713_13(int &) = CopyValue : r1713_12 # 1713| m1713_14(int &&) = Store[rv] : &:r1713_1, r1713_13 @@ -13430,7 +13468,7 @@ ir.cpp: # 1717| r1717_3(int &) = Load[r] : &:r1717_2, m1712_14 # 1717| r1717_4(glval) = CopyValue : r1717_3 # 1717| m1717_5(int) = Store[?] : &:r1717_4, r1717_1 -# 1717| m1717_6(unknown) = Chi : total:m1713_8, partial:m1717_5 +# 1717| m1717_6(unknown) = Chi : total:m1713_11, partial:m1717_5 # 1718| r1718_1(glval) = VariableAddress[rr] : # 1718| r1718_2(glval) = VariableAddress[r] : # 1718| r1718_3(int &) = Load[r] : &:r1718_2, m1712_14 @@ -21423,21 +21461,47 @@ ir.cpp: # 2897| void StructInit::StructInit(int) # 2897| Block 0 -# 2897| v2897_1(void) = EnterFunction : -# 2897| m2897_2(unknown) = AliasedDefinition : -# 2897| m2897_3(unknown) = InitializeNonLocal : -# 2897| m2897_4(unknown) = Chi : total:m2897_2, partial:m2897_3 -# 2897| r2897_5(glval) = VariableAddress[#this] : -# 2897| m2897_6(glval) = InitializeParameter[#this] : &:r2897_5 -# 2897| r2897_7(glval) = Load[#this] : &:r2897_5, m2897_6 -# 2897| m2897_8(StructInit) = InitializeIndirection[#this] : &:r2897_7 -# 2897| r2897_9(glval) = VariableAddress[j] : -# 2897| m2897_10(int) = InitializeParameter[j] : &:r2897_9 -# 2897| v2897_11(void) = NoOp : -# 2897| v2897_12(void) = ReturnIndirection[#this] : &:r2897_7, m2897_8 -# 2897| v2897_13(void) = ReturnVoid : -# 2897| v2897_14(void) = AliasedUse : m2897_3 -# 2897| v2897_15(void) = ExitFunction : +# 2897| v2897_1(void) = EnterFunction : +# 2897| m2897_2(unknown) = AliasedDefinition : +# 2897| m2897_3(unknown) = InitializeNonLocal : +# 2897| m2897_4(unknown) = Chi : total:m2897_2, partial:m2897_3 +# 2897| r2897_5(glval) = VariableAddress[#this] : +# 2897| m2897_6(glval) = InitializeParameter[#this] : &:r2897_5 +# 2897| r2897_7(glval) = Load[#this] : &:r2897_5, m2897_6 +# 2897| m2897_8(StructInit) = InitializeIndirection[#this] : &:r2897_7 +# 2897| m2897_9(unknown) = Chi : total:m2897_4, partial:m2897_8 +# 2897| r2897_10(glval) = VariableAddress[j] : +# 2897| m2897_11(int) = InitializeParameter[j] : &:r2897_10 +# 2897| r2897_12(glval) = FunctionAddress[i] : +# 2897| v2897_13(void) = Call[i] : func:r2897_12, this:r2897_7 +# 2897| r2897_14(glval) = FieldAddress[j] : r2897_7 +# 2897| r2897_15(glval) = VariableAddress[j] : +# 2897| r2897_16(int) = Load[j] : &:r2897_15, m2897_11 +# 2897| m2897_17(int) = Store[?] : &:r2897_14, r2897_16 +# 2897| m2897_18(unknown) = Chi : total:m2897_9, partial:m2897_17 +# 2897| r2897_19(glval) = FunctionAddress[k] : +# 2897| v2897_20(void) = Call[k] : func:r2897_19, this:r2897_7 +# 2897| r2897_21(glval) = FunctionAddress[l] : +# 2897| v2897_22(void) = Call[l] : func:r2897_21, this:r2897_7 +# 2897| r2897_23(glval) = FunctionAddress[m] : +# 2897| v2897_24(void) = Call[m] : func:r2897_23, this:r2897_7 +# 2897| r2897_25(glval) = FieldAddress[n] : r2897_7 +# 2897| r2897_26(glval) = VariableAddress[#this] : +# 2897| r2897_27(StructInit *) = Load[#this] : &:r2897_26, m2897_6 +# 2897| r2897_28(glval) = FunctionAddress[get_val] : +# 2897| r2897_29(int) = Call[get_val] : func:r2897_28, this:r2897_27 +# 2897| m2897_30(unknown) = ^CallSideEffect : ~m2897_18 +# 2897| m2897_31(unknown) = Chi : total:m2897_18, partial:m2897_30 +# 2897| v2897_32(void) = ^IndirectReadSideEffect[-1] : &:r2897_27, ~m2897_31 +# 2897| m2897_33(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2897_27 +# 2897| m2897_34(unknown) = Chi : total:m2897_31, partial:m2897_33 +# 2897| m2897_35(int) = Store[?] : &:r2897_25, r2897_29 +# 2897| m2897_36(unknown) = Chi : total:m2897_34, partial:m2897_35 +# 2897| v2897_37(void) = NoOp : +# 2897| v2897_38(void) = ReturnIndirection[#this] : &:r2897_7, ~m2897_36 +# 2897| v2897_39(void) = ReturnVoid : +# 2897| v2897_40(void) = AliasedUse : ~m2897_36 +# 2897| v2897_41(void) = ExitFunction : # 2899| void StructInit::StructInit() # 2899| Block 0 @@ -21449,15 +21513,28 @@ ir.cpp: # 2899| m2899_6(glval) = InitializeParameter[#this] : &:r2899_5 # 2899| r2899_7(glval) = Load[#this] : &:r2899_5, m2899_6 # 2899| m2899_8(StructInit) = InitializeIndirection[#this] : &:r2899_7 -# 2899| r2899_9(glval) = FieldAddress[i] : r2899_7 -# 2899| r2899_10(int) = Constant[41] : -# 2899| m2899_11(int) = Store[?] : &:r2899_9, r2899_10 -# 2899| m2899_12(unknown) = Chi : total:m2899_8, partial:m2899_11 -# 2899| v2899_13(void) = NoOp : -# 2899| v2899_14(void) = ReturnIndirection[#this] : &:r2899_7, m2899_12 -# 2899| v2899_15(void) = ReturnVoid : -# 2899| v2899_16(void) = AliasedUse : m2899_3 -# 2899| v2899_17(void) = ExitFunction : +# 2899| m2899_9(unknown) = Chi : total:m2899_4, partial:m2899_8 +# 2899| r2899_10(glval) = FieldAddress[i] : r2899_7 +# 2899| r2899_11(int) = Constant[41] : +# 2899| m2899_12(int) = Store[?] : &:r2899_10, r2899_11 +# 2899| m2899_13(unknown) = Chi : total:m2899_9, partial:m2899_12 +# 2899| r2899_14(glval) = FunctionAddress[j] : +# 2899| v2899_15(void) = Call[j] : func:r2899_14, this:r2899_7 +# 2899| r2899_16(glval) = FieldAddress[k] : r2899_7 +# 2899| r2899_17(int) = Constant[41] : +# 2899| m2899_18(int) = Store[?] : &:r2899_16, r2899_17 +# 2899| m2899_19(unknown) = Chi : total:m2899_13, partial:m2899_18 +# 2899| r2899_20(glval) = FunctionAddress[l] : +# 2899| v2899_21(void) = Call[l] : func:r2899_20, this:r2899_7 +# 2899| r2899_22(glval) = FunctionAddress[m] : +# 2899| v2899_23(void) = Call[m] : func:r2899_22, this:r2899_7 +# 2899| r2899_24(glval) = FunctionAddress[n] : +# 2899| v2899_25(void) = Call[n] : func:r2899_24, this:r2899_7 +# 2899| v2899_26(void) = NoOp : +# 2899| v2899_27(void) = ReturnIndirection[#this] : &:r2899_7, ~m2899_19 +# 2899| v2899_28(void) = ReturnVoid : +# 2899| v2899_29(void) = AliasedUse : ~m2899_19 +# 2899| v2899_30(void) = ExitFunction : # 2901| int StructInit::get_val() # 2901| Block 0 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 230d0805cd2d..f1b75895c3e7 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected @@ -20,10 +20,6 @@ multipleIRTypes lostReachability backEdgeCountMismatch useNotDominatedByDefinition -| ir.cpp:1537:8:1537:8 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:1537:8:1537:8 | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() | -| ir.cpp:2897:5:2897:14 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:2897:5:2897:14 | void StructInit::StructInit(int) | void StructInit::StructInit(int) | -| ir.cpp:2897:5:2897:14 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:2897:5:2897:14 | void StructInit::StructInit(int) | void StructInit::StructInit(int) | -| ir.cpp:2899:5:2899:14 | Unary | Operand 'Unary' is not dominated by its definition in function '$@'. | ir.cpp:2899:5:2899:14 | void StructInit::StructInit() | void StructInit::StructInit() | 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 16649e72d084..acb250ed58bb 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -11346,11 +11346,13 @@ ir.cpp: # 1533| mu1533_5(glval) = InitializeParameter[#this] : &:r1533_4 # 1533| r1533_6(glval) = Load[#this] : &:r1533_4, ~m? # 1533| mu1533_7(StructuredBindingDataMemberMemberStruct) = InitializeIndirection[#this] : &:r1533_6 -# 1533| v1533_8(void) = NoOp : -# 1533| v1533_9(void) = ReturnIndirection[#this] : &:r1533_6, ~m? -# 1533| v1533_10(void) = ReturnVoid : -# 1533| v1533_11(void) = AliasedUse : ~m? -# 1533| v1533_12(void) = ExitFunction : +# 1533| r1533_8(glval) = FunctionAddress[x] : +# 1533| v1533_9(void) = Call[x] : func:r1533_8, this:r1533_6 +# 1533| v1533_10(void) = NoOp : +# 1533| v1533_11(void) = ReturnIndirection[#this] : &:r1533_6, ~m? +# 1533| v1533_12(void) = ReturnVoid : +# 1533| v1533_13(void) = AliasedUse : ~m? +# 1533| v1533_14(void) = ExitFunction : # 1534| int StructuredBindingDataMemberMemberStruct::x # 1534| Block 0 @@ -11370,29 +11372,35 @@ ir.cpp: # 1537| void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct() # 1537| Block 0 -# 1537| v1537_1(void) = EnterFunction : -# 1537| mu1537_2(unknown) = AliasedDefinition : -# 1537| mu1537_3(unknown) = InitializeNonLocal : -# 1537| r1537_4(glval) = VariableAddress[#this] : -# 1537| mu1537_5(glval) = InitializeParameter[#this] : &:r1537_4 -# 1537| r1537_6(glval) = Load[#this] : &:r1537_4, ~m? -# 1537| mu1537_7(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1537_6 -#-----| Goto -> Block 2 - -# 1537| Block 1 -# 1537| r1537_8(glval) = FieldAddress[m] : r1537_6 -# 1537| r1537_9(glval) = FunctionAddress[StructuredBindingDataMemberMemberStruct] : -# 1537| v1537_10(void) = Call[StructuredBindingDataMemberMemberStruct] : func:r1537_9, this:r1537_8 -# 1537| mu1537_11(unknown) = ^CallSideEffect : ~m? -# 1537| mu1537_12(StructuredBindingDataMemberMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_8 -#-----| Goto -> Block 2 - -# 1537| Block 2 -# 1537| v1537_13(void) = NoOp : -# 1537| v1537_14(void) = ReturnIndirection[#this] : &:r1537_6, ~m? -# 1537| v1537_15(void) = ReturnVoid : -# 1537| v1537_16(void) = AliasedUse : ~m? -# 1537| v1537_17(void) = ExitFunction : +# 1537| v1537_1(void) = EnterFunction : +# 1537| mu1537_2(unknown) = AliasedDefinition : +# 1537| mu1537_3(unknown) = InitializeNonLocal : +# 1537| r1537_4(glval) = VariableAddress[#this] : +# 1537| mu1537_5(glval) = InitializeParameter[#this] : &:r1537_4 +# 1537| r1537_6(glval) = Load[#this] : &:r1537_4, ~m? +# 1537| mu1537_7(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1537_6 +# 1537| r1537_8(glval) = FunctionAddress[i] : +# 1537| v1537_9(void) = Call[i] : func:r1537_8, this:r1537_6 +# 1537| r1537_10(glval) = FunctionAddress[d] : +# 1537| v1537_11(void) = Call[d] : func:r1537_10, this:r1537_6 +# 1537| r1537_12(glval) = FunctionAddress[r] : +# 1537| v1537_13(void) = Call[r] : func:r1537_12, this:r1537_6 +# 1537| r1537_14(glval) = FunctionAddress[p] : +# 1537| v1537_15(void) = Call[p] : func:r1537_14, this:r1537_6 +# 1537| r1537_16(glval) = FunctionAddress[xs] : +# 1537| v1537_17(void) = Call[xs] : func:r1537_16, this:r1537_6 +# 1537| r1537_18(glval) = FunctionAddress[r_alt] : +# 1537| v1537_19(void) = Call[r_alt] : func:r1537_18, this:r1537_6 +# 1537| r1537_20(glval) = FieldAddress[m] : r1537_6 +# 1537| r1537_21(glval) = FunctionAddress[StructuredBindingDataMemberMemberStruct] : +# 1537| v1537_22(void) = Call[StructuredBindingDataMemberMemberStruct] : func:r1537_21, this:r1537_20 +# 1537| mu1537_23(unknown) = ^CallSideEffect : ~m? +# 1537| mu1537_24(StructuredBindingDataMemberMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_20 +# 1537| v1537_25(void) = NoOp : +# 1537| v1537_26(void) = ReturnIndirection[#this] : &:r1537_6, ~m? +# 1537| v1537_27(void) = ReturnVoid : +# 1537| v1537_28(void) = AliasedUse : ~m? +# 1537| v1537_29(void) = ExitFunction : # 1537| void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct(StructuredBindingDataMemberStruct const&) # 1537| Block 0 @@ -11752,11 +11760,17 @@ ir.cpp: # 1590| mu1590_5(glval) = InitializeParameter[#this] : &:r1590_4 # 1590| r1590_6(glval) = Load[#this] : &:r1590_4, ~m? # 1590| mu1590_7(StructuredBindingTupleRefGet) = InitializeIndirection[#this] : &:r1590_6 -# 1590| v1590_8(void) = NoOp : -# 1590| v1590_9(void) = ReturnIndirection[#this] : &:r1590_6, ~m? -# 1590| v1590_10(void) = ReturnVoid : -# 1590| v1590_11(void) = AliasedUse : ~m? -# 1590| v1590_12(void) = ExitFunction : +# 1590| r1590_8(glval) = FunctionAddress[i] : +# 1590| v1590_9(void) = Call[i] : func:r1590_8, this:r1590_6 +# 1590| r1590_10(glval) = FunctionAddress[d] : +# 1590| v1590_11(void) = Call[d] : func:r1590_10, this:r1590_6 +# 1590| r1590_12(glval) = FunctionAddress[r] : +# 1590| v1590_13(void) = Call[r] : func:r1590_12, this:r1590_6 +# 1590| v1590_14(void) = NoOp : +# 1590| v1590_15(void) = ReturnIndirection[#this] : &:r1590_6, ~m? +# 1590| v1590_16(void) = ReturnVoid : +# 1590| v1590_17(void) = AliasedUse : ~m? +# 1590| v1590_18(void) = ExitFunction : # 1590| void StructuredBindingTupleRefGet::StructuredBindingTupleRefGet(StructuredBindingTupleRefGet const&) # 1590| Block 0 @@ -12071,11 +12085,15 @@ ir.cpp: # 1657| mu1657_5(glval) = InitializeParameter[#this] : &:r1657_4 # 1657| r1657_6(glval) = Load[#this] : &:r1657_4, ~m? # 1657| mu1657_7(StructuredBindingTupleNoRefGet) = InitializeIndirection[#this] : &:r1657_6 -# 1657| v1657_8(void) = NoOp : -# 1657| v1657_9(void) = ReturnIndirection[#this] : &:r1657_6, ~m? -# 1657| v1657_10(void) = ReturnVoid : -# 1657| v1657_11(void) = AliasedUse : ~m? -# 1657| v1657_12(void) = ExitFunction : +# 1657| r1657_8(glval) = FunctionAddress[i] : +# 1657| v1657_9(void) = Call[i] : func:r1657_8, this:r1657_6 +# 1657| r1657_10(glval) = FunctionAddress[r] : +# 1657| v1657_11(void) = Call[r] : func:r1657_10, this:r1657_6 +# 1657| v1657_12(void) = NoOp : +# 1657| v1657_13(void) = ReturnIndirection[#this] : &:r1657_6, ~m? +# 1657| v1657_14(void) = ReturnVoid : +# 1657| v1657_15(void) = AliasedUse : ~m? +# 1657| v1657_16(void) = ExitFunction : # 1658| int StructuredBindingTupleNoRefGet::i # 1658| Block 0 @@ -19513,42 +19531,41 @@ ir.cpp: # 2897| void StructInit::StructInit(int) # 2897| Block 0 -# 2897| v2897_1(void) = EnterFunction : -# 2897| mu2897_2(unknown) = AliasedDefinition : -# 2897| mu2897_3(unknown) = InitializeNonLocal : -# 2897| r2897_4(glval) = VariableAddress[#this] : -# 2897| mu2897_5(glval) = InitializeParameter[#this] : &:r2897_4 -# 2897| r2897_6(glval) = Load[#this] : &:r2897_4, ~m? -# 2897| mu2897_7(StructInit) = InitializeIndirection[#this] : &:r2897_6 -# 2897| r2897_8(glval) = VariableAddress[j] : -# 2897| mu2897_9(int) = InitializeParameter[j] : &:r2897_8 -#-----| Goto -> Block 3 - -# 2897| Block 1 -# 2897| r2897_10(glval) = FieldAddress[j] : r2897_6 -# 2897| r2897_11(glval) = VariableAddress[j] : -# 2897| r2897_12(int) = Load[j] : &:r2897_11, ~m? -# 2897| mu2897_13(int) = Store[?] : &:r2897_10, r2897_12 -#-----| Goto -> Block 3 - -# 2897| Block 2 -# 2897| r2897_14(glval) = FieldAddress[n] : r2897_6 -# 2897| r2897_15(glval) = VariableAddress[#this] : -# 2897| r2897_16(StructInit *) = Load[#this] : &:r2897_15, ~m? -# 2897| r2897_17(glval) = FunctionAddress[get_val] : -# 2897| r2897_18(int) = Call[get_val] : func:r2897_17, this:r2897_16 -# 2897| mu2897_19(unknown) = ^CallSideEffect : ~m? -# 2897| v2897_20(void) = ^IndirectReadSideEffect[-1] : &:r2897_16, ~m? -# 2897| mu2897_21(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2897_16 -# 2897| mu2897_22(int) = Store[?] : &:r2897_14, r2897_18 -#-----| Goto -> Block 3 - -# 2897| Block 3 -# 2897| v2897_23(void) = NoOp : -# 2897| v2897_24(void) = ReturnIndirection[#this] : &:r2897_6, ~m? -# 2897| v2897_25(void) = ReturnVoid : -# 2897| v2897_26(void) = AliasedUse : ~m? -# 2897| v2897_27(void) = ExitFunction : +# 2897| v2897_1(void) = EnterFunction : +# 2897| mu2897_2(unknown) = AliasedDefinition : +# 2897| mu2897_3(unknown) = InitializeNonLocal : +# 2897| r2897_4(glval) = VariableAddress[#this] : +# 2897| mu2897_5(glval) = InitializeParameter[#this] : &:r2897_4 +# 2897| r2897_6(glval) = Load[#this] : &:r2897_4, ~m? +# 2897| mu2897_7(StructInit) = InitializeIndirection[#this] : &:r2897_6 +# 2897| r2897_8(glval) = VariableAddress[j] : +# 2897| mu2897_9(int) = InitializeParameter[j] : &:r2897_8 +# 2897| r2897_10(glval) = FunctionAddress[i] : +# 2897| v2897_11(void) = Call[i] : func:r2897_10, this:r2897_6 +# 2897| r2897_12(glval) = FieldAddress[j] : r2897_6 +# 2897| r2897_13(glval) = VariableAddress[j] : +# 2897| r2897_14(int) = Load[j] : &:r2897_13, ~m? +# 2897| mu2897_15(int) = Store[?] : &:r2897_12, r2897_14 +# 2897| r2897_16(glval) = FunctionAddress[k] : +# 2897| v2897_17(void) = Call[k] : func:r2897_16, this:r2897_6 +# 2897| r2897_18(glval) = FunctionAddress[l] : +# 2897| v2897_19(void) = Call[l] : func:r2897_18, this:r2897_6 +# 2897| r2897_20(glval) = FunctionAddress[m] : +# 2897| v2897_21(void) = Call[m] : func:r2897_20, this:r2897_6 +# 2897| r2897_22(glval) = FieldAddress[n] : r2897_6 +# 2897| r2897_23(glval) = VariableAddress[#this] : +# 2897| r2897_24(StructInit *) = Load[#this] : &:r2897_23, ~m? +# 2897| r2897_25(glval) = FunctionAddress[get_val] : +# 2897| r2897_26(int) = Call[get_val] : func:r2897_25, this:r2897_24 +# 2897| mu2897_27(unknown) = ^CallSideEffect : ~m? +# 2897| v2897_28(void) = ^IndirectReadSideEffect[-1] : &:r2897_24, ~m? +# 2897| mu2897_29(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2897_24 +# 2897| mu2897_30(int) = Store[?] : &:r2897_22, r2897_26 +# 2897| v2897_31(void) = NoOp : +# 2897| v2897_32(void) = ReturnIndirection[#this] : &:r2897_6, ~m? +# 2897| v2897_33(void) = ReturnVoid : +# 2897| v2897_34(void) = AliasedUse : ~m? +# 2897| v2897_35(void) = ExitFunction : # 2899| void StructInit::StructInit() # 2899| Block 0 @@ -19562,20 +19579,22 @@ ir.cpp: # 2899| r2899_8(glval) = FieldAddress[i] : r2899_6 # 2899| r2899_9(int) = Constant[41] : # 2899| mu2899_10(int) = Store[?] : &:r2899_8, r2899_9 -#-----| Goto -> Block 2 - -# 2899| Block 1 -# 2899| r2899_11(glval) = FieldAddress[k] : r2899_6 -# 2899| r2899_12(int) = Constant[41] : -# 2899| mu2899_13(int) = Store[?] : &:r2899_11, r2899_12 -#-----| Goto -> Block 2 - -# 2899| Block 2 -# 2899| v2899_14(void) = NoOp : -# 2899| v2899_15(void) = ReturnIndirection[#this] : &:r2899_6, ~m? -# 2899| v2899_16(void) = ReturnVoid : -# 2899| v2899_17(void) = AliasedUse : ~m? -# 2899| v2899_18(void) = ExitFunction : +# 2899| r2899_11(glval) = FunctionAddress[j] : +# 2899| v2899_12(void) = Call[j] : func:r2899_11, this:r2899_6 +# 2899| r2899_13(glval) = FieldAddress[k] : r2899_6 +# 2899| r2899_14(int) = Constant[41] : +# 2899| mu2899_15(int) = Store[?] : &:r2899_13, r2899_14 +# 2899| r2899_16(glval) = FunctionAddress[l] : +# 2899| v2899_17(void) = Call[l] : func:r2899_16, this:r2899_6 +# 2899| r2899_18(glval) = FunctionAddress[m] : +# 2899| v2899_19(void) = Call[m] : func:r2899_18, this:r2899_6 +# 2899| r2899_20(glval) = FunctionAddress[n] : +# 2899| v2899_21(void) = Call[n] : func:r2899_20, this:r2899_6 +# 2899| v2899_22(void) = NoOp : +# 2899| v2899_23(void) = ReturnIndirection[#this] : &:r2899_6, ~m? +# 2899| v2899_24(void) = ReturnVoid : +# 2899| v2899_25(void) = AliasedUse : ~m? +# 2899| v2899_26(void) = ExitFunction : # 2901| int StructInit::get_val() # 2901| Block 0 From 22eda4ef0aa46f86967634ba4bf48e9a20cb3f06 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Fri, 20 Mar 2026 17:44:14 +0100 Subject: [PATCH 09/16] C++: Add call side effects for default field initializations to the IR --- .../raw/internal/SideEffects.qll | 23 ++++++-- .../raw/internal/TranslatedCall.qll | 52 +++++++++++++------ .../raw/internal/TranslatedElement.qll | 11 ++-- .../raw/internal/TranslatedInitialization.qll | 15 +++++- 4 files changed, 77 insertions(+), 24 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll index b7b4be7f7877..0ce1f898c0d1 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll @@ -133,7 +133,7 @@ private predicate hasDefaultSideEffect(Call call, ParameterIndex i, boolean buff * An expression that can have call side effects. * * All kinds of expressions invoke a function as part of their evaluation. This class provides a - * way to treat those functions similarly, and to get the invoked `Function`. + * way to treat those expressions similarly, and to get the invoked `Declaration`. */ class ExprWithCallSizeEffects extends Expr { ExprWithCallSizeEffects() { @@ -142,15 +142,19 @@ class ExprWithCallSizeEffects extends Expr { this instanceof NewOrNewArrayExpr or this instanceof DeleteOrDeleteArrayExpr + or + this instanceof ConstructorDefaultFieldInit } - /** Gets the `Function` invoked by this expression, if known. */ - final Function getTarget() { + /** Gets the `Declaration` invoked by this expression, if known. */ + final Declaration getTarget() { result = this.(Call).getTarget() or result = this.(NewOrNewArrayExpr).getAllocator() or result = this.(DeleteOrDeleteArrayExpr).getDeallocator() + or + result = this.(ConstructorDefaultFieldInit).getTarget() } } @@ -175,7 +179,7 @@ Opcode getCallSideEffectOpcode(ExprWithCallSizeEffects expr) { /** * Returns a side effect opcode for parameter index `i` of the specified call. * - * This predicate will return at most two results: one read side effect, and one write side effect. + * This predicate will yield at most two results: one read side effect, and one write side effect. */ Opcode getASideEffectOpcode(Call call, ParameterIndex i) { exists(boolean buffer | @@ -228,3 +232,14 @@ Opcode getASideEffectOpcode(Call call, ParameterIndex i) { ) ) } + +/** + * Returns a side effect opcode for a default field initialization. + * + * This predicate will yield two results: one read side effect, and one write side effect. + */ +Opcode getDefaultFieldInitSideEffectOpcode() { + result instanceof Opcode::IndirectReadSideEffect + or + result instanceof Opcode::IndirectMayWriteSideEffect +} diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index f3d084883a71..572ce5f2858a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -10,6 +10,7 @@ private import SideEffects private import TranslatedElement private import TranslatedExpr private import TranslatedFunction +private import TranslatedInitialization private import DefaultOptions as DefaultOptions /** @@ -429,6 +430,9 @@ class TranslatedCallSideEffects extends TranslatedSideEffects, TTranslatedCallSi or expr instanceof DeleteOrDeleteArrayExpr and result = getTranslatedDeleteOrDeleteArray(expr).getInstruction(CallTag()) + or + expr instanceof ConstructorDefaultFieldInit and + result = getTranslatedConstructorFieldInitialization(expr).getInstruction(CallTag()) } } @@ -504,11 +508,25 @@ abstract class TranslatedSideEffect extends TranslatedElement { abstract predicate sideEffectInstruction(Opcode opcode, CppType type); } +private class CallOrDefaultFieldInit extends Expr { + CallOrDefaultFieldInit() { + this instanceof Call + or + this instanceof ConstructorDefaultFieldInit + } + + Declaration getTarget() { + result = this.(Call).getTarget() + or + result = this.(ConstructorDefaultFieldInit).getTarget() + } +} + /** * The IR translation of a single argument side effect for a call. */ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect { - Call call; + CallOrDefaultFieldInit callOrInit; int index; SideEffectOpcode sideEffectOpcode; @@ -524,7 +542,7 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect { result = "(read side effect for " + this.getArgString() + ")" } - override Call getPrimaryExpr() { result = call } + override Expr getPrimaryExpr() { result = callOrInit } override predicate sortOrder(int group, int indexInGroup) { indexInGroup = index and @@ -586,9 +604,10 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect { tag instanceof OnlyInstructionTag and operandTag instanceof BufferSizeOperandTag and result = - getTranslatedExpr(call.getArgument(call.getTarget() - .(SideEffectFunction) - .getParameterSizeIndex(index)).getFullyConverted()).getResult() + getTranslatedExpr(callOrInit + .(Call) + .getArgument(callOrInit.getTarget().(SideEffectFunction).getParameterSizeIndex(index)) + .getFullyConverted()).getResult() } /** Holds if this side effect is a write side effect, rather than a read side effect. */ @@ -616,7 +635,7 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect, Expr arg; TranslatedArgumentExprSideEffect() { - this = TTranslatedArgumentExprSideEffect(call, arg, index, sideEffectOpcode) + this = TTranslatedArgumentExprSideEffect(callOrInit, arg, index, sideEffectOpcode) } final override Locatable getAst() { result = arg } @@ -640,28 +659,31 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect, * The IR translation of an argument side effect for `*this` on a call, where there is no `Expr` * object that represents the `this` argument. * - * The applies only to constructor calls, as the AST has exploit qualifier `Expr`s for all other - * calls to non-static member functions. + * The applies to constructor calls and default field initializations, as the AST has explicit + * qualifier `Expr`s for all other calls to non-static member functions. */ -class TranslatedStructorQualifierSideEffect extends TranslatedArgumentSideEffect, - TTranslatedStructorQualifierSideEffect +class TranslatedImplicitThisQualifierSideEffect extends TranslatedArgumentSideEffect, + TTranslatedImplicitThisQualifierSideEffect { - TranslatedStructorQualifierSideEffect() { - this = TTranslatedStructorQualifierSideEffect(call, sideEffectOpcode) and + TranslatedImplicitThisQualifierSideEffect() { + this = TTranslatedImplicitThisQualifierSideEffect(callOrInit, sideEffectOpcode) and index = -1 } - final override Locatable getAst() { result = call } + final override Locatable getAst() { result = callOrInit } - final override Type getIndirectionType() { result = call.getTarget().getDeclaringType() } + final override Type getIndirectionType() { result = callOrInit.getTarget().getDeclaringType() } final override string getArgString() { result = "this" } final override Instruction getArgInstruction() { exists(TranslatedStructorCall structorCall | - structorCall.getExpr() = call and + structorCall.getExpr() = callOrInit and result = structorCall.getQualifierResult() ) + or + callOrInit instanceof ConstructorDefaultFieldInit and + result = getTranslatedFunction(callOrInit.getEnclosingFunction()).getLoadThisInstruction() } } 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 66ad2ae26793..2f86a3f476bc 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 @@ -918,11 +918,16 @@ newtype TTranslatedElement = } or // Constructor calls lack a qualifier (`this`) expression, so we need to handle the side effects // on `*this` without an `Expr`. - TTranslatedStructorQualifierSideEffect(Call call, SideEffectOpcode opcode) { + TTranslatedImplicitThisQualifierSideEffect(ExprWithCallSizeEffects call, SideEffectOpcode opcode) { not ignoreExpr(call) and not ignoreSideEffects(call) and - call instanceof ConstructorCall and - opcode = getASideEffectOpcode(call, -1) + ( + call instanceof ConstructorCall and + opcode = getASideEffectOpcode(call, -1) + or + call instanceof ConstructorFieldInit and + opcode = getDefaultFieldInitSideEffectOpcode() + ) } or // The side effect that initializes newly-allocated memory. TTranslatedAllocationSideEffect(AllocationExpr expr) { not ignoreSideEffects(expr) } or diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll index f5d092ca44ae..614d9dd58990 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -634,13 +634,22 @@ class TranslatedDefaultFieldInitialization extends TranslatedFieldInitialization kind instanceof GotoEdge } - override Instruction getALastInstructionInternal() { result = this.getInstruction(CallTag()) } + override Instruction getALastInstructionInternal() { + result = this.getSideEffects().getALastInstruction() + } + + override TranslatedElement getLastChild() { result = this.getSideEffects() } override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { tag = CallTargetTag() and result = this.getInstruction(CallTag()) or tag = CallTag() and + result = this.getSideEffects().getFirstInstruction(kind) + } + + override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { + child = this.getSideEffects() and result = this.getParent().getChildSuccessor(this, kind) } @@ -670,7 +679,9 @@ class TranslatedDefaultFieldInitialization extends TranslatedFieldInitialization result = field } - override TranslatedElement getChild(int id) { none() } + override TranslatedElement getChild(int id) { id = 0 and result = this.getSideEffects() } + + final TranslatedSideEffects getSideEffects() { result.getExpr() = ast } } private string getZeroValue(Type type) { From f3fc80a080287553789191712179cff0b7072d36 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 24 Mar 2026 10:57:10 +0100 Subject: [PATCH 10/16] C++: Update expected test results --- .../library-tests/ir/ir/aliased_ir.expected | 368 +++++++++++------- .../test/library-tests/ir/ir/raw_ir.expected | 296 ++++++++------ 2 files changed, 412 insertions(+), 252 deletions(-) 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 20e254f066e3..e6fc2db62f10 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ir.expected @@ -12361,22 +12361,27 @@ ir.cpp: # 1533| void StructuredBindingDataMemberMemberStruct::StructuredBindingDataMemberMemberStruct() # 1533| Block 0 -# 1533| v1533_1(void) = EnterFunction : -# 1533| m1533_2(unknown) = AliasedDefinition : -# 1533| m1533_3(unknown) = InitializeNonLocal : -# 1533| m1533_4(unknown) = Chi : total:m1533_2, partial:m1533_3 -# 1533| r1533_5(glval) = VariableAddress[#this] : -# 1533| m1533_6(glval) = InitializeParameter[#this] : &:r1533_5 -# 1533| r1533_7(glval) = Load[#this] : &:r1533_5, m1533_6 -# 1533| m1533_8(StructuredBindingDataMemberMemberStruct) = InitializeIndirection[#this] : &:r1533_7 -# 1533| m1533_9(unknown) = Chi : total:m1533_4, partial:m1533_8 -# 1533| r1533_10(glval) = FunctionAddress[x] : -# 1533| v1533_11(void) = Call[x] : func:r1533_10, this:r1533_7 -# 1533| v1533_12(void) = NoOp : -# 1533| v1533_13(void) = ReturnIndirection[#this] : &:r1533_7, m1533_8 -# 1533| v1533_14(void) = ReturnVoid : -# 1533| v1533_15(void) = AliasedUse : ~m1533_9 -# 1533| v1533_16(void) = ExitFunction : +# 1533| v1533_1(void) = EnterFunction : +# 1533| m1533_2(unknown) = AliasedDefinition : +# 1533| m1533_3(unknown) = InitializeNonLocal : +# 1533| m1533_4(unknown) = Chi : total:m1533_2, partial:m1533_3 +# 1533| r1533_5(glval) = VariableAddress[#this] : +# 1533| m1533_6(glval) = InitializeParameter[#this] : &:r1533_5 +# 1533| r1533_7(glval) = Load[#this] : &:r1533_5, m1533_6 +# 1533| m1533_8(StructuredBindingDataMemberMemberStruct) = InitializeIndirection[#this] : &:r1533_7 +# 1533| m1533_9(unknown) = Chi : total:m1533_4, partial:m1533_8 +# 1533| r1533_10(glval) = FunctionAddress[x] : +# 1533| v1533_11(void) = Call[x] : func:r1533_10, this:r1533_7 +# 1533| m1533_12(unknown) = ^CallSideEffect : ~m1533_9 +# 1533| m1533_13(unknown) = Chi : total:m1533_9, partial:m1533_12 +# 1533| v1533_14(void) = ^IndirectReadSideEffect[-1] : &:r1533_7, ~m1533_13 +# 1533| m1533_15(StructuredBindingDataMemberMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1533_7 +# 1533| m1533_16(unknown) = Chi : total:m1533_13, partial:m1533_15 +# 1533| v1533_17(void) = NoOp : +# 1533| v1533_18(void) = ReturnIndirection[#this] : &:r1533_7, ~m1533_16 +# 1533| v1533_19(void) = ReturnVoid : +# 1533| v1533_20(void) = AliasedUse : ~m1533_16 +# 1533| v1533_21(void) = ExitFunction : # 1534| int StructuredBindingDataMemberMemberStruct::x # 1534| Block 0 @@ -12409,28 +12414,58 @@ ir.cpp: # 1537| m1537_9(unknown) = Chi : total:m1537_4, partial:m1537_8 # 1537| r1537_10(glval) = FunctionAddress[i] : # 1537| v1537_11(void) = Call[i] : func:r1537_10, this:r1537_7 -# 1537| r1537_12(glval) = FunctionAddress[d] : -# 1537| v1537_13(void) = Call[d] : func:r1537_12, this:r1537_7 -# 1537| r1537_14(glval) = FunctionAddress[r] : -# 1537| v1537_15(void) = Call[r] : func:r1537_14, this:r1537_7 -# 1537| r1537_16(glval) = FunctionAddress[p] : -# 1537| v1537_17(void) = Call[p] : func:r1537_16, this:r1537_7 -# 1537| r1537_18(glval) = FunctionAddress[xs] : -# 1537| v1537_19(void) = Call[xs] : func:r1537_18, this:r1537_7 -# 1537| r1537_20(glval) = FunctionAddress[r_alt] : -# 1537| v1537_21(void) = Call[r_alt] : func:r1537_20, this:r1537_7 -# 1537| r1537_22(glval) = FieldAddress[m] : r1537_7 -# 1537| r1537_23(glval) = FunctionAddress[StructuredBindingDataMemberMemberStruct] : -# 1537| v1537_24(void) = Call[StructuredBindingDataMemberMemberStruct] : func:r1537_23, this:r1537_22 -# 1537| m1537_25(unknown) = ^CallSideEffect : ~m1537_9 -# 1537| m1537_26(unknown) = Chi : total:m1537_9, partial:m1537_25 -# 1537| m1537_27(StructuredBindingDataMemberMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_22 -# 1537| m1537_28(unknown) = Chi : total:m1537_26, partial:m1537_27 -# 1537| v1537_29(void) = NoOp : -# 1537| v1537_30(void) = ReturnIndirection[#this] : &:r1537_7, ~m1537_28 -# 1537| v1537_31(void) = ReturnVoid : -# 1537| v1537_32(void) = AliasedUse : ~m1537_28 -# 1537| v1537_33(void) = ExitFunction : +# 1537| m1537_12(unknown) = ^CallSideEffect : ~m1537_9 +# 1537| m1537_13(unknown) = Chi : total:m1537_9, partial:m1537_12 +# 1537| v1537_14(void) = ^IndirectReadSideEffect[-1] : &:r1537_7, ~m1537_13 +# 1537| m1537_15(StructuredBindingDataMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_7 +# 1537| m1537_16(unknown) = Chi : total:m1537_13, partial:m1537_15 +# 1537| r1537_17(glval) = FunctionAddress[d] : +# 1537| v1537_18(void) = Call[d] : func:r1537_17, this:r1537_7 +# 1537| m1537_19(unknown) = ^CallSideEffect : ~m1537_16 +# 1537| m1537_20(unknown) = Chi : total:m1537_16, partial:m1537_19 +# 1537| v1537_21(void) = ^IndirectReadSideEffect[-1] : &:r1537_7, ~m1537_20 +# 1537| m1537_22(StructuredBindingDataMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_7 +# 1537| m1537_23(unknown) = Chi : total:m1537_20, partial:m1537_22 +# 1537| r1537_24(glval) = FunctionAddress[r] : +# 1537| v1537_25(void) = Call[r] : func:r1537_24, this:r1537_7 +# 1537| m1537_26(unknown) = ^CallSideEffect : ~m1537_23 +# 1537| m1537_27(unknown) = Chi : total:m1537_23, partial:m1537_26 +# 1537| v1537_28(void) = ^IndirectReadSideEffect[-1] : &:r1537_7, ~m1537_27 +# 1537| m1537_29(StructuredBindingDataMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_7 +# 1537| m1537_30(unknown) = Chi : total:m1537_27, partial:m1537_29 +# 1537| r1537_31(glval) = FunctionAddress[p] : +# 1537| v1537_32(void) = Call[p] : func:r1537_31, this:r1537_7 +# 1537| m1537_33(unknown) = ^CallSideEffect : ~m1537_30 +# 1537| m1537_34(unknown) = Chi : total:m1537_30, partial:m1537_33 +# 1537| v1537_35(void) = ^IndirectReadSideEffect[-1] : &:r1537_7, ~m1537_34 +# 1537| m1537_36(StructuredBindingDataMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_7 +# 1537| m1537_37(unknown) = Chi : total:m1537_34, partial:m1537_36 +# 1537| r1537_38(glval) = FunctionAddress[xs] : +# 1537| v1537_39(void) = Call[xs] : func:r1537_38, this:r1537_7 +# 1537| m1537_40(unknown) = ^CallSideEffect : ~m1537_37 +# 1537| m1537_41(unknown) = Chi : total:m1537_37, partial:m1537_40 +# 1537| v1537_42(void) = ^IndirectReadSideEffect[-1] : &:r1537_7, ~m1537_41 +# 1537| m1537_43(StructuredBindingDataMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_7 +# 1537| m1537_44(unknown) = Chi : total:m1537_41, partial:m1537_43 +# 1537| r1537_45(glval) = FunctionAddress[r_alt] : +# 1537| v1537_46(void) = Call[r_alt] : func:r1537_45, this:r1537_7 +# 1537| m1537_47(unknown) = ^CallSideEffect : ~m1537_44 +# 1537| m1537_48(unknown) = Chi : total:m1537_44, partial:m1537_47 +# 1537| v1537_49(void) = ^IndirectReadSideEffect[-1] : &:r1537_7, ~m1537_48 +# 1537| m1537_50(StructuredBindingDataMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_7 +# 1537| m1537_51(unknown) = Chi : total:m1537_48, partial:m1537_50 +# 1537| r1537_52(glval) = FieldAddress[m] : r1537_7 +# 1537| r1537_53(glval) = FunctionAddress[StructuredBindingDataMemberMemberStruct] : +# 1537| v1537_54(void) = Call[StructuredBindingDataMemberMemberStruct] : func:r1537_53, this:r1537_52 +# 1537| m1537_55(unknown) = ^CallSideEffect : ~m1537_51 +# 1537| m1537_56(unknown) = Chi : total:m1537_51, partial:m1537_55 +# 1537| m1537_57(StructuredBindingDataMemberMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_52 +# 1537| m1537_58(unknown) = Chi : total:m1537_56, partial:m1537_57 +# 1537| v1537_59(void) = NoOp : +# 1537| v1537_60(void) = ReturnIndirection[#this] : &:r1537_7, ~m1537_58 +# 1537| v1537_61(void) = ReturnVoid : +# 1537| v1537_62(void) = AliasedUse : ~m1537_58 +# 1537| v1537_63(void) = ExitFunction : # 1537| void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct(StructuredBindingDataMemberStruct const&) # 1537| Block 0 @@ -12818,26 +12853,41 @@ ir.cpp: # 1590| void StructuredBindingTupleRefGet::StructuredBindingTupleRefGet() # 1590| Block 0 -# 1590| v1590_1(void) = EnterFunction : -# 1590| m1590_2(unknown) = AliasedDefinition : -# 1590| m1590_3(unknown) = InitializeNonLocal : -# 1590| m1590_4(unknown) = Chi : total:m1590_2, partial:m1590_3 -# 1590| r1590_5(glval) = VariableAddress[#this] : -# 1590| m1590_6(glval) = InitializeParameter[#this] : &:r1590_5 -# 1590| r1590_7(glval) = Load[#this] : &:r1590_5, m1590_6 -# 1590| m1590_8(StructuredBindingTupleRefGet) = InitializeIndirection[#this] : &:r1590_7 -# 1590| m1590_9(unknown) = Chi : total:m1590_4, partial:m1590_8 -# 1590| r1590_10(glval) = FunctionAddress[i] : -# 1590| v1590_11(void) = Call[i] : func:r1590_10, this:r1590_7 -# 1590| r1590_12(glval) = FunctionAddress[d] : -# 1590| v1590_13(void) = Call[d] : func:r1590_12, this:r1590_7 -# 1590| r1590_14(glval) = FunctionAddress[r] : -# 1590| v1590_15(void) = Call[r] : func:r1590_14, this:r1590_7 -# 1590| v1590_16(void) = NoOp : -# 1590| v1590_17(void) = ReturnIndirection[#this] : &:r1590_7, m1590_8 -# 1590| v1590_18(void) = ReturnVoid : -# 1590| v1590_19(void) = AliasedUse : ~m1590_9 -# 1590| v1590_20(void) = ExitFunction : +# 1590| v1590_1(void) = EnterFunction : +# 1590| m1590_2(unknown) = AliasedDefinition : +# 1590| m1590_3(unknown) = InitializeNonLocal : +# 1590| m1590_4(unknown) = Chi : total:m1590_2, partial:m1590_3 +# 1590| r1590_5(glval) = VariableAddress[#this] : +# 1590| m1590_6(glval) = InitializeParameter[#this] : &:r1590_5 +# 1590| r1590_7(glval) = Load[#this] : &:r1590_5, m1590_6 +# 1590| m1590_8(StructuredBindingTupleRefGet) = InitializeIndirection[#this] : &:r1590_7 +# 1590| m1590_9(unknown) = Chi : total:m1590_4, partial:m1590_8 +# 1590| r1590_10(glval) = FunctionAddress[i] : +# 1590| v1590_11(void) = Call[i] : func:r1590_10, this:r1590_7 +# 1590| m1590_12(unknown) = ^CallSideEffect : ~m1590_9 +# 1590| m1590_13(unknown) = Chi : total:m1590_9, partial:m1590_12 +# 1590| v1590_14(void) = ^IndirectReadSideEffect[-1] : &:r1590_7, ~m1590_13 +# 1590| m1590_15(StructuredBindingTupleRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1590_7 +# 1590| m1590_16(unknown) = Chi : total:m1590_13, partial:m1590_15 +# 1590| r1590_17(glval) = FunctionAddress[d] : +# 1590| v1590_18(void) = Call[d] : func:r1590_17, this:r1590_7 +# 1590| m1590_19(unknown) = ^CallSideEffect : ~m1590_16 +# 1590| m1590_20(unknown) = Chi : total:m1590_16, partial:m1590_19 +# 1590| v1590_21(void) = ^IndirectReadSideEffect[-1] : &:r1590_7, ~m1590_20 +# 1590| m1590_22(StructuredBindingTupleRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1590_7 +# 1590| m1590_23(unknown) = Chi : total:m1590_20, partial:m1590_22 +# 1590| r1590_24(glval) = FunctionAddress[r] : +# 1590| v1590_25(void) = Call[r] : func:r1590_24, this:r1590_7 +# 1590| m1590_26(unknown) = ^CallSideEffect : ~m1590_23 +# 1590| m1590_27(unknown) = Chi : total:m1590_23, partial:m1590_26 +# 1590| v1590_28(void) = ^IndirectReadSideEffect[-1] : &:r1590_7, ~m1590_27 +# 1590| m1590_29(StructuredBindingTupleRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1590_7 +# 1590| m1590_30(unknown) = Chi : total:m1590_27, partial:m1590_29 +# 1590| v1590_31(void) = NoOp : +# 1590| v1590_32(void) = ReturnIndirection[#this] : &:r1590_7, ~m1590_30 +# 1590| v1590_33(void) = ReturnVoid : +# 1590| v1590_34(void) = AliasedUse : ~m1590_30 +# 1590| v1590_35(void) = ExitFunction : # 1590| void StructuredBindingTupleRefGet::StructuredBindingTupleRefGet(StructuredBindingTupleRefGet const&) # 1590| Block 0 @@ -13179,24 +13229,34 @@ ir.cpp: # 1657| void StructuredBindingTupleNoRefGet::StructuredBindingTupleNoRefGet() # 1657| Block 0 -# 1657| v1657_1(void) = EnterFunction : -# 1657| m1657_2(unknown) = AliasedDefinition : -# 1657| m1657_3(unknown) = InitializeNonLocal : -# 1657| m1657_4(unknown) = Chi : total:m1657_2, partial:m1657_3 -# 1657| r1657_5(glval) = VariableAddress[#this] : -# 1657| m1657_6(glval) = InitializeParameter[#this] : &:r1657_5 -# 1657| r1657_7(glval) = Load[#this] : &:r1657_5, m1657_6 -# 1657| m1657_8(StructuredBindingTupleNoRefGet) = InitializeIndirection[#this] : &:r1657_7 -# 1657| m1657_9(unknown) = Chi : total:m1657_4, partial:m1657_8 -# 1657| r1657_10(glval) = FunctionAddress[i] : -# 1657| v1657_11(void) = Call[i] : func:r1657_10, this:r1657_7 -# 1657| r1657_12(glval) = FunctionAddress[r] : -# 1657| v1657_13(void) = Call[r] : func:r1657_12, this:r1657_7 -# 1657| v1657_14(void) = NoOp : -# 1657| v1657_15(void) = ReturnIndirection[#this] : &:r1657_7, m1657_8 -# 1657| v1657_16(void) = ReturnVoid : -# 1657| v1657_17(void) = AliasedUse : ~m1657_9 -# 1657| v1657_18(void) = ExitFunction : +# 1657| v1657_1(void) = EnterFunction : +# 1657| m1657_2(unknown) = AliasedDefinition : +# 1657| m1657_3(unknown) = InitializeNonLocal : +# 1657| m1657_4(unknown) = Chi : total:m1657_2, partial:m1657_3 +# 1657| r1657_5(glval) = VariableAddress[#this] : +# 1657| m1657_6(glval) = InitializeParameter[#this] : &:r1657_5 +# 1657| r1657_7(glval) = Load[#this] : &:r1657_5, m1657_6 +# 1657| m1657_8(StructuredBindingTupleNoRefGet) = InitializeIndirection[#this] : &:r1657_7 +# 1657| m1657_9(unknown) = Chi : total:m1657_4, partial:m1657_8 +# 1657| r1657_10(glval) = FunctionAddress[i] : +# 1657| v1657_11(void) = Call[i] : func:r1657_10, this:r1657_7 +# 1657| m1657_12(unknown) = ^CallSideEffect : ~m1657_9 +# 1657| m1657_13(unknown) = Chi : total:m1657_9, partial:m1657_12 +# 1657| v1657_14(void) = ^IndirectReadSideEffect[-1] : &:r1657_7, ~m1657_13 +# 1657| m1657_15(StructuredBindingTupleNoRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1657_7 +# 1657| m1657_16(unknown) = Chi : total:m1657_13, partial:m1657_15 +# 1657| r1657_17(glval) = FunctionAddress[r] : +# 1657| v1657_18(void) = Call[r] : func:r1657_17, this:r1657_7 +# 1657| m1657_19(unknown) = ^CallSideEffect : ~m1657_16 +# 1657| m1657_20(unknown) = Chi : total:m1657_16, partial:m1657_19 +# 1657| v1657_21(void) = ^IndirectReadSideEffect[-1] : &:r1657_7, ~m1657_20 +# 1657| m1657_22(StructuredBindingTupleNoRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1657_7 +# 1657| m1657_23(unknown) = Chi : total:m1657_20, partial:m1657_22 +# 1657| v1657_24(void) = NoOp : +# 1657| v1657_25(void) = ReturnIndirection[#this] : &:r1657_7, ~m1657_23 +# 1657| v1657_26(void) = ReturnVoid : +# 1657| v1657_27(void) = AliasedUse : ~m1657_23 +# 1657| v1657_28(void) = ExitFunction : # 1658| int StructuredBindingTupleNoRefGet::i # 1658| Block 0 @@ -21474,67 +21534,107 @@ ir.cpp: # 2897| m2897_11(int) = InitializeParameter[j] : &:r2897_10 # 2897| r2897_12(glval) = FunctionAddress[i] : # 2897| v2897_13(void) = Call[i] : func:r2897_12, this:r2897_7 -# 2897| r2897_14(glval) = FieldAddress[j] : r2897_7 -# 2897| r2897_15(glval) = VariableAddress[j] : -# 2897| r2897_16(int) = Load[j] : &:r2897_15, m2897_11 -# 2897| m2897_17(int) = Store[?] : &:r2897_14, r2897_16 -# 2897| m2897_18(unknown) = Chi : total:m2897_9, partial:m2897_17 -# 2897| r2897_19(glval) = FunctionAddress[k] : -# 2897| v2897_20(void) = Call[k] : func:r2897_19, this:r2897_7 -# 2897| r2897_21(glval) = FunctionAddress[l] : -# 2897| v2897_22(void) = Call[l] : func:r2897_21, this:r2897_7 -# 2897| r2897_23(glval) = FunctionAddress[m] : -# 2897| v2897_24(void) = Call[m] : func:r2897_23, this:r2897_7 -# 2897| r2897_25(glval) = FieldAddress[n] : r2897_7 -# 2897| r2897_26(glval) = VariableAddress[#this] : -# 2897| r2897_27(StructInit *) = Load[#this] : &:r2897_26, m2897_6 -# 2897| r2897_28(glval) = FunctionAddress[get_val] : -# 2897| r2897_29(int) = Call[get_val] : func:r2897_28, this:r2897_27 -# 2897| m2897_30(unknown) = ^CallSideEffect : ~m2897_18 -# 2897| m2897_31(unknown) = Chi : total:m2897_18, partial:m2897_30 -# 2897| v2897_32(void) = ^IndirectReadSideEffect[-1] : &:r2897_27, ~m2897_31 -# 2897| m2897_33(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2897_27 -# 2897| m2897_34(unknown) = Chi : total:m2897_31, partial:m2897_33 -# 2897| m2897_35(int) = Store[?] : &:r2897_25, r2897_29 -# 2897| m2897_36(unknown) = Chi : total:m2897_34, partial:m2897_35 -# 2897| v2897_37(void) = NoOp : -# 2897| v2897_38(void) = ReturnIndirection[#this] : &:r2897_7, ~m2897_36 -# 2897| v2897_39(void) = ReturnVoid : -# 2897| v2897_40(void) = AliasedUse : ~m2897_36 -# 2897| v2897_41(void) = ExitFunction : +# 2897| m2897_14(unknown) = ^CallSideEffect : ~m2897_9 +# 2897| m2897_15(unknown) = Chi : total:m2897_9, partial:m2897_14 +# 2897| v2897_16(void) = ^IndirectReadSideEffect[-1] : &:r2897_7, ~m2897_15 +# 2897| m2897_17(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2897_7 +# 2897| m2897_18(unknown) = Chi : total:m2897_15, partial:m2897_17 +# 2897| r2897_19(glval) = FieldAddress[j] : r2897_7 +# 2897| r2897_20(glval) = VariableAddress[j] : +# 2897| r2897_21(int) = Load[j] : &:r2897_20, m2897_11 +# 2897| m2897_22(int) = Store[?] : &:r2897_19, r2897_21 +# 2897| m2897_23(unknown) = Chi : total:m2897_18, partial:m2897_22 +# 2897| r2897_24(glval) = FunctionAddress[k] : +# 2897| v2897_25(void) = Call[k] : func:r2897_24, this:r2897_7 +# 2897| m2897_26(unknown) = ^CallSideEffect : ~m2897_23 +# 2897| m2897_27(unknown) = Chi : total:m2897_23, partial:m2897_26 +# 2897| v2897_28(void) = ^IndirectReadSideEffect[-1] : &:r2897_7, ~m2897_27 +# 2897| m2897_29(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2897_7 +# 2897| m2897_30(unknown) = Chi : total:m2897_27, partial:m2897_29 +# 2897| r2897_31(glval) = FunctionAddress[l] : +# 2897| v2897_32(void) = Call[l] : func:r2897_31, this:r2897_7 +# 2897| m2897_33(unknown) = ^CallSideEffect : ~m2897_30 +# 2897| m2897_34(unknown) = Chi : total:m2897_30, partial:m2897_33 +# 2897| v2897_35(void) = ^IndirectReadSideEffect[-1] : &:r2897_7, ~m2897_34 +# 2897| m2897_36(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2897_7 +# 2897| m2897_37(unknown) = Chi : total:m2897_34, partial:m2897_36 +# 2897| r2897_38(glval) = FunctionAddress[m] : +# 2897| v2897_39(void) = Call[m] : func:r2897_38, this:r2897_7 +# 2897| m2897_40(unknown) = ^CallSideEffect : ~m2897_37 +# 2897| m2897_41(unknown) = Chi : total:m2897_37, partial:m2897_40 +# 2897| v2897_42(void) = ^IndirectReadSideEffect[-1] : &:r2897_7, ~m2897_41 +# 2897| m2897_43(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2897_7 +# 2897| m2897_44(unknown) = Chi : total:m2897_41, partial:m2897_43 +# 2897| r2897_45(glval) = FieldAddress[n] : r2897_7 +# 2897| r2897_46(glval) = VariableAddress[#this] : +# 2897| r2897_47(StructInit *) = Load[#this] : &:r2897_46, m2897_6 +# 2897| r2897_48(glval) = FunctionAddress[get_val] : +# 2897| r2897_49(int) = Call[get_val] : func:r2897_48, this:r2897_47 +# 2897| m2897_50(unknown) = ^CallSideEffect : ~m2897_44 +# 2897| m2897_51(unknown) = Chi : total:m2897_44, partial:m2897_50 +# 2897| v2897_52(void) = ^IndirectReadSideEffect[-1] : &:r2897_47, ~m2897_51 +# 2897| m2897_53(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2897_47 +# 2897| m2897_54(unknown) = Chi : total:m2897_51, partial:m2897_53 +# 2897| m2897_55(int) = Store[?] : &:r2897_45, r2897_49 +# 2897| m2897_56(unknown) = Chi : total:m2897_54, partial:m2897_55 +# 2897| v2897_57(void) = NoOp : +# 2897| v2897_58(void) = ReturnIndirection[#this] : &:r2897_7, ~m2897_56 +# 2897| v2897_59(void) = ReturnVoid : +# 2897| v2897_60(void) = AliasedUse : ~m2897_56 +# 2897| v2897_61(void) = ExitFunction : # 2899| void StructInit::StructInit() # 2899| Block 0 -# 2899| v2899_1(void) = EnterFunction : -# 2899| m2899_2(unknown) = AliasedDefinition : -# 2899| m2899_3(unknown) = InitializeNonLocal : -# 2899| m2899_4(unknown) = Chi : total:m2899_2, partial:m2899_3 -# 2899| r2899_5(glval) = VariableAddress[#this] : -# 2899| m2899_6(glval) = InitializeParameter[#this] : &:r2899_5 -# 2899| r2899_7(glval) = Load[#this] : &:r2899_5, m2899_6 -# 2899| m2899_8(StructInit) = InitializeIndirection[#this] : &:r2899_7 -# 2899| m2899_9(unknown) = Chi : total:m2899_4, partial:m2899_8 -# 2899| r2899_10(glval) = FieldAddress[i] : r2899_7 -# 2899| r2899_11(int) = Constant[41] : -# 2899| m2899_12(int) = Store[?] : &:r2899_10, r2899_11 -# 2899| m2899_13(unknown) = Chi : total:m2899_9, partial:m2899_12 -# 2899| r2899_14(glval) = FunctionAddress[j] : -# 2899| v2899_15(void) = Call[j] : func:r2899_14, this:r2899_7 -# 2899| r2899_16(glval) = FieldAddress[k] : r2899_7 -# 2899| r2899_17(int) = Constant[41] : -# 2899| m2899_18(int) = Store[?] : &:r2899_16, r2899_17 -# 2899| m2899_19(unknown) = Chi : total:m2899_13, partial:m2899_18 -# 2899| r2899_20(glval) = FunctionAddress[l] : -# 2899| v2899_21(void) = Call[l] : func:r2899_20, this:r2899_7 -# 2899| r2899_22(glval) = FunctionAddress[m] : -# 2899| v2899_23(void) = Call[m] : func:r2899_22, this:r2899_7 -# 2899| r2899_24(glval) = FunctionAddress[n] : -# 2899| v2899_25(void) = Call[n] : func:r2899_24, this:r2899_7 -# 2899| v2899_26(void) = NoOp : -# 2899| v2899_27(void) = ReturnIndirection[#this] : &:r2899_7, ~m2899_19 -# 2899| v2899_28(void) = ReturnVoid : -# 2899| v2899_29(void) = AliasedUse : ~m2899_19 -# 2899| v2899_30(void) = ExitFunction : +# 2899| v2899_1(void) = EnterFunction : +# 2899| m2899_2(unknown) = AliasedDefinition : +# 2899| m2899_3(unknown) = InitializeNonLocal : +# 2899| m2899_4(unknown) = Chi : total:m2899_2, partial:m2899_3 +# 2899| r2899_5(glval) = VariableAddress[#this] : +# 2899| m2899_6(glval) = InitializeParameter[#this] : &:r2899_5 +# 2899| r2899_7(glval) = Load[#this] : &:r2899_5, m2899_6 +# 2899| m2899_8(StructInit) = InitializeIndirection[#this] : &:r2899_7 +# 2899| m2899_9(unknown) = Chi : total:m2899_4, partial:m2899_8 +# 2899| r2899_10(glval) = FieldAddress[i] : r2899_7 +# 2899| r2899_11(int) = Constant[41] : +# 2899| m2899_12(int) = Store[?] : &:r2899_10, r2899_11 +# 2899| m2899_13(unknown) = Chi : total:m2899_9, partial:m2899_12 +# 2899| r2899_14(glval) = FunctionAddress[j] : +# 2899| v2899_15(void) = Call[j] : func:r2899_14, this:r2899_7 +# 2899| m2899_16(unknown) = ^CallSideEffect : ~m2899_13 +# 2899| m2899_17(unknown) = Chi : total:m2899_13, partial:m2899_16 +# 2899| v2899_18(void) = ^IndirectReadSideEffect[-1] : &:r2899_7, ~m2899_17 +# 2899| m2899_19(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2899_7 +# 2899| m2899_20(unknown) = Chi : total:m2899_17, partial:m2899_19 +# 2899| r2899_21(glval) = FieldAddress[k] : r2899_7 +# 2899| r2899_22(int) = Constant[41] : +# 2899| m2899_23(int) = Store[?] : &:r2899_21, r2899_22 +# 2899| m2899_24(unknown) = Chi : total:m2899_20, partial:m2899_23 +# 2899| r2899_25(glval) = FunctionAddress[l] : +# 2899| v2899_26(void) = Call[l] : func:r2899_25, this:r2899_7 +# 2899| m2899_27(unknown) = ^CallSideEffect : ~m2899_24 +# 2899| m2899_28(unknown) = Chi : total:m2899_24, partial:m2899_27 +# 2899| v2899_29(void) = ^IndirectReadSideEffect[-1] : &:r2899_7, ~m2899_28 +# 2899| m2899_30(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2899_7 +# 2899| m2899_31(unknown) = Chi : total:m2899_28, partial:m2899_30 +# 2899| r2899_32(glval) = FunctionAddress[m] : +# 2899| v2899_33(void) = Call[m] : func:r2899_32, this:r2899_7 +# 2899| m2899_34(unknown) = ^CallSideEffect : ~m2899_31 +# 2899| m2899_35(unknown) = Chi : total:m2899_31, partial:m2899_34 +# 2899| v2899_36(void) = ^IndirectReadSideEffect[-1] : &:r2899_7, ~m2899_35 +# 2899| m2899_37(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2899_7 +# 2899| m2899_38(unknown) = Chi : total:m2899_35, partial:m2899_37 +# 2899| r2899_39(glval) = FunctionAddress[n] : +# 2899| v2899_40(void) = Call[n] : func:r2899_39, this:r2899_7 +# 2899| m2899_41(unknown) = ^CallSideEffect : ~m2899_38 +# 2899| m2899_42(unknown) = Chi : total:m2899_38, partial:m2899_41 +# 2899| v2899_43(void) = ^IndirectReadSideEffect[-1] : &:r2899_7, ~m2899_42 +# 2899| m2899_44(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2899_7 +# 2899| m2899_45(unknown) = Chi : total:m2899_42, partial:m2899_44 +# 2899| v2899_46(void) = NoOp : +# 2899| v2899_47(void) = ReturnIndirection[#this] : &:r2899_7, ~m2899_45 +# 2899| v2899_48(void) = ReturnVoid : +# 2899| v2899_49(void) = AliasedUse : ~m2899_45 +# 2899| v2899_50(void) = ExitFunction : # 2901| int StructInit::get_val() # 2901| Block 0 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 acb250ed58bb..06655517dbbc 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -11339,20 +11339,23 @@ ir.cpp: # 1533| void StructuredBindingDataMemberMemberStruct::StructuredBindingDataMemberMemberStruct() # 1533| Block 0 -# 1533| v1533_1(void) = EnterFunction : -# 1533| mu1533_2(unknown) = AliasedDefinition : -# 1533| mu1533_3(unknown) = InitializeNonLocal : -# 1533| r1533_4(glval) = VariableAddress[#this] : -# 1533| mu1533_5(glval) = InitializeParameter[#this] : &:r1533_4 -# 1533| r1533_6(glval) = Load[#this] : &:r1533_4, ~m? -# 1533| mu1533_7(StructuredBindingDataMemberMemberStruct) = InitializeIndirection[#this] : &:r1533_6 -# 1533| r1533_8(glval) = FunctionAddress[x] : -# 1533| v1533_9(void) = Call[x] : func:r1533_8, this:r1533_6 -# 1533| v1533_10(void) = NoOp : -# 1533| v1533_11(void) = ReturnIndirection[#this] : &:r1533_6, ~m? -# 1533| v1533_12(void) = ReturnVoid : -# 1533| v1533_13(void) = AliasedUse : ~m? -# 1533| v1533_14(void) = ExitFunction : +# 1533| v1533_1(void) = EnterFunction : +# 1533| mu1533_2(unknown) = AliasedDefinition : +# 1533| mu1533_3(unknown) = InitializeNonLocal : +# 1533| r1533_4(glval) = VariableAddress[#this] : +# 1533| mu1533_5(glval) = InitializeParameter[#this] : &:r1533_4 +# 1533| r1533_6(glval) = Load[#this] : &:r1533_4, ~m? +# 1533| mu1533_7(StructuredBindingDataMemberMemberStruct) = InitializeIndirection[#this] : &:r1533_6 +# 1533| r1533_8(glval) = FunctionAddress[x] : +# 1533| v1533_9(void) = Call[x] : func:r1533_8, this:r1533_6 +# 1533| mu1533_10(unknown) = ^CallSideEffect : ~m? +# 1533| v1533_11(void) = ^IndirectReadSideEffect[-1] : &:r1533_6, ~m? +# 1533| mu1533_12(StructuredBindingDataMemberMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1533_6 +# 1533| v1533_13(void) = NoOp : +# 1533| v1533_14(void) = ReturnIndirection[#this] : &:r1533_6, ~m? +# 1533| v1533_15(void) = ReturnVoid : +# 1533| v1533_16(void) = AliasedUse : ~m? +# 1533| v1533_17(void) = ExitFunction : # 1534| int StructuredBindingDataMemberMemberStruct::x # 1534| Block 0 @@ -11381,26 +11384,44 @@ ir.cpp: # 1537| mu1537_7(StructuredBindingDataMemberStruct) = InitializeIndirection[#this] : &:r1537_6 # 1537| r1537_8(glval) = FunctionAddress[i] : # 1537| v1537_9(void) = Call[i] : func:r1537_8, this:r1537_6 -# 1537| r1537_10(glval) = FunctionAddress[d] : -# 1537| v1537_11(void) = Call[d] : func:r1537_10, this:r1537_6 -# 1537| r1537_12(glval) = FunctionAddress[r] : -# 1537| v1537_13(void) = Call[r] : func:r1537_12, this:r1537_6 -# 1537| r1537_14(glval) = FunctionAddress[p] : -# 1537| v1537_15(void) = Call[p] : func:r1537_14, this:r1537_6 -# 1537| r1537_16(glval) = FunctionAddress[xs] : -# 1537| v1537_17(void) = Call[xs] : func:r1537_16, this:r1537_6 -# 1537| r1537_18(glval) = FunctionAddress[r_alt] : -# 1537| v1537_19(void) = Call[r_alt] : func:r1537_18, this:r1537_6 -# 1537| r1537_20(glval) = FieldAddress[m] : r1537_6 -# 1537| r1537_21(glval) = FunctionAddress[StructuredBindingDataMemberMemberStruct] : -# 1537| v1537_22(void) = Call[StructuredBindingDataMemberMemberStruct] : func:r1537_21, this:r1537_20 -# 1537| mu1537_23(unknown) = ^CallSideEffect : ~m? -# 1537| mu1537_24(StructuredBindingDataMemberMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_20 -# 1537| v1537_25(void) = NoOp : -# 1537| v1537_26(void) = ReturnIndirection[#this] : &:r1537_6, ~m? -# 1537| v1537_27(void) = ReturnVoid : -# 1537| v1537_28(void) = AliasedUse : ~m? -# 1537| v1537_29(void) = ExitFunction : +# 1537| mu1537_10(unknown) = ^CallSideEffect : ~m? +# 1537| v1537_11(void) = ^IndirectReadSideEffect[-1] : &:r1537_6, ~m? +# 1537| mu1537_12(StructuredBindingDataMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_6 +# 1537| r1537_13(glval) = FunctionAddress[d] : +# 1537| v1537_14(void) = Call[d] : func:r1537_13, this:r1537_6 +# 1537| mu1537_15(unknown) = ^CallSideEffect : ~m? +# 1537| v1537_16(void) = ^IndirectReadSideEffect[-1] : &:r1537_6, ~m? +# 1537| mu1537_17(StructuredBindingDataMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_6 +# 1537| r1537_18(glval) = FunctionAddress[r] : +# 1537| v1537_19(void) = Call[r] : func:r1537_18, this:r1537_6 +# 1537| mu1537_20(unknown) = ^CallSideEffect : ~m? +# 1537| v1537_21(void) = ^IndirectReadSideEffect[-1] : &:r1537_6, ~m? +# 1537| mu1537_22(StructuredBindingDataMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_6 +# 1537| r1537_23(glval) = FunctionAddress[p] : +# 1537| v1537_24(void) = Call[p] : func:r1537_23, this:r1537_6 +# 1537| mu1537_25(unknown) = ^CallSideEffect : ~m? +# 1537| v1537_26(void) = ^IndirectReadSideEffect[-1] : &:r1537_6, ~m? +# 1537| mu1537_27(StructuredBindingDataMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_6 +# 1537| r1537_28(glval) = FunctionAddress[xs] : +# 1537| v1537_29(void) = Call[xs] : func:r1537_28, this:r1537_6 +# 1537| mu1537_30(unknown) = ^CallSideEffect : ~m? +# 1537| v1537_31(void) = ^IndirectReadSideEffect[-1] : &:r1537_6, ~m? +# 1537| mu1537_32(StructuredBindingDataMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_6 +# 1537| r1537_33(glval) = FunctionAddress[r_alt] : +# 1537| v1537_34(void) = Call[r_alt] : func:r1537_33, this:r1537_6 +# 1537| mu1537_35(unknown) = ^CallSideEffect : ~m? +# 1537| v1537_36(void) = ^IndirectReadSideEffect[-1] : &:r1537_6, ~m? +# 1537| mu1537_37(StructuredBindingDataMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_6 +# 1537| r1537_38(glval) = FieldAddress[m] : r1537_6 +# 1537| r1537_39(glval) = FunctionAddress[StructuredBindingDataMemberMemberStruct] : +# 1537| v1537_40(void) = Call[StructuredBindingDataMemberMemberStruct] : func:r1537_39, this:r1537_38 +# 1537| mu1537_41(unknown) = ^CallSideEffect : ~m? +# 1537| mu1537_42(StructuredBindingDataMemberMemberStruct) = ^IndirectMayWriteSideEffect[-1] : &:r1537_38 +# 1537| v1537_43(void) = NoOp : +# 1537| v1537_44(void) = ReturnIndirection[#this] : &:r1537_6, ~m? +# 1537| v1537_45(void) = ReturnVoid : +# 1537| v1537_46(void) = AliasedUse : ~m? +# 1537| v1537_47(void) = ExitFunction : # 1537| void StructuredBindingDataMemberStruct::StructuredBindingDataMemberStruct(StructuredBindingDataMemberStruct const&) # 1537| Block 0 @@ -11753,24 +11774,33 @@ ir.cpp: # 1590| void StructuredBindingTupleRefGet::StructuredBindingTupleRefGet() # 1590| Block 0 -# 1590| v1590_1(void) = EnterFunction : -# 1590| mu1590_2(unknown) = AliasedDefinition : -# 1590| mu1590_3(unknown) = InitializeNonLocal : -# 1590| r1590_4(glval) = VariableAddress[#this] : -# 1590| mu1590_5(glval) = InitializeParameter[#this] : &:r1590_4 -# 1590| r1590_6(glval) = Load[#this] : &:r1590_4, ~m? -# 1590| mu1590_7(StructuredBindingTupleRefGet) = InitializeIndirection[#this] : &:r1590_6 -# 1590| r1590_8(glval) = FunctionAddress[i] : -# 1590| v1590_9(void) = Call[i] : func:r1590_8, this:r1590_6 -# 1590| r1590_10(glval) = FunctionAddress[d] : -# 1590| v1590_11(void) = Call[d] : func:r1590_10, this:r1590_6 -# 1590| r1590_12(glval) = FunctionAddress[r] : -# 1590| v1590_13(void) = Call[r] : func:r1590_12, this:r1590_6 -# 1590| v1590_14(void) = NoOp : -# 1590| v1590_15(void) = ReturnIndirection[#this] : &:r1590_6, ~m? -# 1590| v1590_16(void) = ReturnVoid : -# 1590| v1590_17(void) = AliasedUse : ~m? -# 1590| v1590_18(void) = ExitFunction : +# 1590| v1590_1(void) = EnterFunction : +# 1590| mu1590_2(unknown) = AliasedDefinition : +# 1590| mu1590_3(unknown) = InitializeNonLocal : +# 1590| r1590_4(glval) = VariableAddress[#this] : +# 1590| mu1590_5(glval) = InitializeParameter[#this] : &:r1590_4 +# 1590| r1590_6(glval) = Load[#this] : &:r1590_4, ~m? +# 1590| mu1590_7(StructuredBindingTupleRefGet) = InitializeIndirection[#this] : &:r1590_6 +# 1590| r1590_8(glval) = FunctionAddress[i] : +# 1590| v1590_9(void) = Call[i] : func:r1590_8, this:r1590_6 +# 1590| mu1590_10(unknown) = ^CallSideEffect : ~m? +# 1590| v1590_11(void) = ^IndirectReadSideEffect[-1] : &:r1590_6, ~m? +# 1590| mu1590_12(StructuredBindingTupleRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1590_6 +# 1590| r1590_13(glval) = FunctionAddress[d] : +# 1590| v1590_14(void) = Call[d] : func:r1590_13, this:r1590_6 +# 1590| mu1590_15(unknown) = ^CallSideEffect : ~m? +# 1590| v1590_16(void) = ^IndirectReadSideEffect[-1] : &:r1590_6, ~m? +# 1590| mu1590_17(StructuredBindingTupleRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1590_6 +# 1590| r1590_18(glval) = FunctionAddress[r] : +# 1590| v1590_19(void) = Call[r] : func:r1590_18, this:r1590_6 +# 1590| mu1590_20(unknown) = ^CallSideEffect : ~m? +# 1590| v1590_21(void) = ^IndirectReadSideEffect[-1] : &:r1590_6, ~m? +# 1590| mu1590_22(StructuredBindingTupleRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1590_6 +# 1590| v1590_23(void) = NoOp : +# 1590| v1590_24(void) = ReturnIndirection[#this] : &:r1590_6, ~m? +# 1590| v1590_25(void) = ReturnVoid : +# 1590| v1590_26(void) = AliasedUse : ~m? +# 1590| v1590_27(void) = ExitFunction : # 1590| void StructuredBindingTupleRefGet::StructuredBindingTupleRefGet(StructuredBindingTupleRefGet const&) # 1590| Block 0 @@ -12078,22 +12108,28 @@ ir.cpp: # 1657| void StructuredBindingTupleNoRefGet::StructuredBindingTupleNoRefGet() # 1657| Block 0 -# 1657| v1657_1(void) = EnterFunction : -# 1657| mu1657_2(unknown) = AliasedDefinition : -# 1657| mu1657_3(unknown) = InitializeNonLocal : -# 1657| r1657_4(glval) = VariableAddress[#this] : -# 1657| mu1657_5(glval) = InitializeParameter[#this] : &:r1657_4 -# 1657| r1657_6(glval) = Load[#this] : &:r1657_4, ~m? -# 1657| mu1657_7(StructuredBindingTupleNoRefGet) = InitializeIndirection[#this] : &:r1657_6 -# 1657| r1657_8(glval) = FunctionAddress[i] : -# 1657| v1657_9(void) = Call[i] : func:r1657_8, this:r1657_6 -# 1657| r1657_10(glval) = FunctionAddress[r] : -# 1657| v1657_11(void) = Call[r] : func:r1657_10, this:r1657_6 -# 1657| v1657_12(void) = NoOp : -# 1657| v1657_13(void) = ReturnIndirection[#this] : &:r1657_6, ~m? -# 1657| v1657_14(void) = ReturnVoid : -# 1657| v1657_15(void) = AliasedUse : ~m? -# 1657| v1657_16(void) = ExitFunction : +# 1657| v1657_1(void) = EnterFunction : +# 1657| mu1657_2(unknown) = AliasedDefinition : +# 1657| mu1657_3(unknown) = InitializeNonLocal : +# 1657| r1657_4(glval) = VariableAddress[#this] : +# 1657| mu1657_5(glval) = InitializeParameter[#this] : &:r1657_4 +# 1657| r1657_6(glval) = Load[#this] : &:r1657_4, ~m? +# 1657| mu1657_7(StructuredBindingTupleNoRefGet) = InitializeIndirection[#this] : &:r1657_6 +# 1657| r1657_8(glval) = FunctionAddress[i] : +# 1657| v1657_9(void) = Call[i] : func:r1657_8, this:r1657_6 +# 1657| mu1657_10(unknown) = ^CallSideEffect : ~m? +# 1657| v1657_11(void) = ^IndirectReadSideEffect[-1] : &:r1657_6, ~m? +# 1657| mu1657_12(StructuredBindingTupleNoRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1657_6 +# 1657| r1657_13(glval) = FunctionAddress[r] : +# 1657| v1657_14(void) = Call[r] : func:r1657_13, this:r1657_6 +# 1657| mu1657_15(unknown) = ^CallSideEffect : ~m? +# 1657| v1657_16(void) = ^IndirectReadSideEffect[-1] : &:r1657_6, ~m? +# 1657| mu1657_17(StructuredBindingTupleNoRefGet) = ^IndirectMayWriteSideEffect[-1] : &:r1657_6 +# 1657| v1657_18(void) = NoOp : +# 1657| v1657_19(void) = ReturnIndirection[#this] : &:r1657_6, ~m? +# 1657| v1657_20(void) = ReturnVoid : +# 1657| v1657_21(void) = AliasedUse : ~m? +# 1657| v1657_22(void) = ExitFunction : # 1658| int StructuredBindingTupleNoRefGet::i # 1658| Block 0 @@ -19542,59 +19578,83 @@ ir.cpp: # 2897| mu2897_9(int) = InitializeParameter[j] : &:r2897_8 # 2897| r2897_10(glval) = FunctionAddress[i] : # 2897| v2897_11(void) = Call[i] : func:r2897_10, this:r2897_6 -# 2897| r2897_12(glval) = FieldAddress[j] : r2897_6 -# 2897| r2897_13(glval) = VariableAddress[j] : -# 2897| r2897_14(int) = Load[j] : &:r2897_13, ~m? -# 2897| mu2897_15(int) = Store[?] : &:r2897_12, r2897_14 -# 2897| r2897_16(glval) = FunctionAddress[k] : -# 2897| v2897_17(void) = Call[k] : func:r2897_16, this:r2897_6 -# 2897| r2897_18(glval) = FunctionAddress[l] : -# 2897| v2897_19(void) = Call[l] : func:r2897_18, this:r2897_6 -# 2897| r2897_20(glval) = FunctionAddress[m] : -# 2897| v2897_21(void) = Call[m] : func:r2897_20, this:r2897_6 -# 2897| r2897_22(glval) = FieldAddress[n] : r2897_6 -# 2897| r2897_23(glval) = VariableAddress[#this] : -# 2897| r2897_24(StructInit *) = Load[#this] : &:r2897_23, ~m? -# 2897| r2897_25(glval) = FunctionAddress[get_val] : -# 2897| r2897_26(int) = Call[get_val] : func:r2897_25, this:r2897_24 -# 2897| mu2897_27(unknown) = ^CallSideEffect : ~m? -# 2897| v2897_28(void) = ^IndirectReadSideEffect[-1] : &:r2897_24, ~m? -# 2897| mu2897_29(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2897_24 -# 2897| mu2897_30(int) = Store[?] : &:r2897_22, r2897_26 -# 2897| v2897_31(void) = NoOp : -# 2897| v2897_32(void) = ReturnIndirection[#this] : &:r2897_6, ~m? -# 2897| v2897_33(void) = ReturnVoid : -# 2897| v2897_34(void) = AliasedUse : ~m? -# 2897| v2897_35(void) = ExitFunction : +# 2897| mu2897_12(unknown) = ^CallSideEffect : ~m? +# 2897| v2897_13(void) = ^IndirectReadSideEffect[-1] : &:r2897_6, ~m? +# 2897| mu2897_14(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2897_6 +# 2897| r2897_15(glval) = FieldAddress[j] : r2897_6 +# 2897| r2897_16(glval) = VariableAddress[j] : +# 2897| r2897_17(int) = Load[j] : &:r2897_16, ~m? +# 2897| mu2897_18(int) = Store[?] : &:r2897_15, r2897_17 +# 2897| r2897_19(glval) = FunctionAddress[k] : +# 2897| v2897_20(void) = Call[k] : func:r2897_19, this:r2897_6 +# 2897| mu2897_21(unknown) = ^CallSideEffect : ~m? +# 2897| v2897_22(void) = ^IndirectReadSideEffect[-1] : &:r2897_6, ~m? +# 2897| mu2897_23(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2897_6 +# 2897| r2897_24(glval) = FunctionAddress[l] : +# 2897| v2897_25(void) = Call[l] : func:r2897_24, this:r2897_6 +# 2897| mu2897_26(unknown) = ^CallSideEffect : ~m? +# 2897| v2897_27(void) = ^IndirectReadSideEffect[-1] : &:r2897_6, ~m? +# 2897| mu2897_28(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2897_6 +# 2897| r2897_29(glval) = FunctionAddress[m] : +# 2897| v2897_30(void) = Call[m] : func:r2897_29, this:r2897_6 +# 2897| mu2897_31(unknown) = ^CallSideEffect : ~m? +# 2897| v2897_32(void) = ^IndirectReadSideEffect[-1] : &:r2897_6, ~m? +# 2897| mu2897_33(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2897_6 +# 2897| r2897_34(glval) = FieldAddress[n] : r2897_6 +# 2897| r2897_35(glval) = VariableAddress[#this] : +# 2897| r2897_36(StructInit *) = Load[#this] : &:r2897_35, ~m? +# 2897| r2897_37(glval) = FunctionAddress[get_val] : +# 2897| r2897_38(int) = Call[get_val] : func:r2897_37, this:r2897_36 +# 2897| mu2897_39(unknown) = ^CallSideEffect : ~m? +# 2897| v2897_40(void) = ^IndirectReadSideEffect[-1] : &:r2897_36, ~m? +# 2897| mu2897_41(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2897_36 +# 2897| mu2897_42(int) = Store[?] : &:r2897_34, r2897_38 +# 2897| v2897_43(void) = NoOp : +# 2897| v2897_44(void) = ReturnIndirection[#this] : &:r2897_6, ~m? +# 2897| v2897_45(void) = ReturnVoid : +# 2897| v2897_46(void) = AliasedUse : ~m? +# 2897| v2897_47(void) = ExitFunction : # 2899| void StructInit::StructInit() # 2899| Block 0 -# 2899| v2899_1(void) = EnterFunction : -# 2899| mu2899_2(unknown) = AliasedDefinition : -# 2899| mu2899_3(unknown) = InitializeNonLocal : -# 2899| r2899_4(glval) = VariableAddress[#this] : -# 2899| mu2899_5(glval) = InitializeParameter[#this] : &:r2899_4 -# 2899| r2899_6(glval) = Load[#this] : &:r2899_4, ~m? -# 2899| mu2899_7(StructInit) = InitializeIndirection[#this] : &:r2899_6 -# 2899| r2899_8(glval) = FieldAddress[i] : r2899_6 -# 2899| r2899_9(int) = Constant[41] : -# 2899| mu2899_10(int) = Store[?] : &:r2899_8, r2899_9 -# 2899| r2899_11(glval) = FunctionAddress[j] : -# 2899| v2899_12(void) = Call[j] : func:r2899_11, this:r2899_6 -# 2899| r2899_13(glval) = FieldAddress[k] : r2899_6 -# 2899| r2899_14(int) = Constant[41] : -# 2899| mu2899_15(int) = Store[?] : &:r2899_13, r2899_14 -# 2899| r2899_16(glval) = FunctionAddress[l] : -# 2899| v2899_17(void) = Call[l] : func:r2899_16, this:r2899_6 -# 2899| r2899_18(glval) = FunctionAddress[m] : -# 2899| v2899_19(void) = Call[m] : func:r2899_18, this:r2899_6 -# 2899| r2899_20(glval) = FunctionAddress[n] : -# 2899| v2899_21(void) = Call[n] : func:r2899_20, this:r2899_6 -# 2899| v2899_22(void) = NoOp : -# 2899| v2899_23(void) = ReturnIndirection[#this] : &:r2899_6, ~m? -# 2899| v2899_24(void) = ReturnVoid : -# 2899| v2899_25(void) = AliasedUse : ~m? -# 2899| v2899_26(void) = ExitFunction : +# 2899| v2899_1(void) = EnterFunction : +# 2899| mu2899_2(unknown) = AliasedDefinition : +# 2899| mu2899_3(unknown) = InitializeNonLocal : +# 2899| r2899_4(glval) = VariableAddress[#this] : +# 2899| mu2899_5(glval) = InitializeParameter[#this] : &:r2899_4 +# 2899| r2899_6(glval) = Load[#this] : &:r2899_4, ~m? +# 2899| mu2899_7(StructInit) = InitializeIndirection[#this] : &:r2899_6 +# 2899| r2899_8(glval) = FieldAddress[i] : r2899_6 +# 2899| r2899_9(int) = Constant[41] : +# 2899| mu2899_10(int) = Store[?] : &:r2899_8, r2899_9 +# 2899| r2899_11(glval) = FunctionAddress[j] : +# 2899| v2899_12(void) = Call[j] : func:r2899_11, this:r2899_6 +# 2899| mu2899_13(unknown) = ^CallSideEffect : ~m? +# 2899| v2899_14(void) = ^IndirectReadSideEffect[-1] : &:r2899_6, ~m? +# 2899| mu2899_15(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2899_6 +# 2899| r2899_16(glval) = FieldAddress[k] : r2899_6 +# 2899| r2899_17(int) = Constant[41] : +# 2899| mu2899_18(int) = Store[?] : &:r2899_16, r2899_17 +# 2899| r2899_19(glval) = FunctionAddress[l] : +# 2899| v2899_20(void) = Call[l] : func:r2899_19, this:r2899_6 +# 2899| mu2899_21(unknown) = ^CallSideEffect : ~m? +# 2899| v2899_22(void) = ^IndirectReadSideEffect[-1] : &:r2899_6, ~m? +# 2899| mu2899_23(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2899_6 +# 2899| r2899_24(glval) = FunctionAddress[m] : +# 2899| v2899_25(void) = Call[m] : func:r2899_24, this:r2899_6 +# 2899| mu2899_26(unknown) = ^CallSideEffect : ~m? +# 2899| v2899_27(void) = ^IndirectReadSideEffect[-1] : &:r2899_6, ~m? +# 2899| mu2899_28(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2899_6 +# 2899| r2899_29(glval) = FunctionAddress[n] : +# 2899| v2899_30(void) = Call[n] : func:r2899_29, this:r2899_6 +# 2899| mu2899_31(unknown) = ^CallSideEffect : ~m? +# 2899| v2899_32(void) = ^IndirectReadSideEffect[-1] : &:r2899_6, ~m? +# 2899| mu2899_33(StructInit) = ^IndirectMayWriteSideEffect[-1] : &:r2899_6 +# 2899| v2899_34(void) = NoOp : +# 2899| v2899_35(void) = ReturnIndirection[#this] : &:r2899_6, ~m? +# 2899| v2899_36(void) = ReturnVoid : +# 2899| v2899_37(void) = AliasedUse : ~m? +# 2899| v2899_38(void) = ExitFunction : # 2901| int StructInit::get_val() # 2901| Block 0 From b554d7dd166f85952e72267f7d2785015378a12a Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 24 Mar 2026 11:04:46 +0100 Subject: [PATCH 11/16] C++: Fix QL-for-QL warnings --- .../raw/internal/TranslatedInitialization.qll | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll index 614d9dd58990..10c033131225 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -515,8 +515,8 @@ TranslatedFieldInitialization getTranslatedConstructorFieldInitialization(Constr } /** - * Represents the IR translation of the initialization of a field from an - * element of an initializer list. + * The IR translation of the initialization of a field from an element of + * an initializer list. */ abstract class TranslatedFieldInitialization extends TranslatedElement { Expr ast; @@ -546,8 +546,8 @@ abstract class TranslatedFieldInitialization extends TranslatedElement { } /** - * Represents the IR translation of the initialization of a field from an - * element of an initializer list where default initialization is not used. + * The IR translation of the initialization of a field from an element of an initializer + * list where default initialization is not used. */ abstract class TranslatedNonDefaultFieldInitialization extends TranslatedFieldInitialization { final override Instruction getFirstInstruction(EdgeKind kind) { @@ -575,8 +575,8 @@ abstract class TranslatedNonDefaultFieldInitialization extends TranslatedFieldIn } /** - * Represents the IR translation of the initialization of a field from an - * explicit element in an initializer list. + * The IR translation of the initialization of a field from an explicit element in + * an initializer list. */ class TranslatedExplicitFieldInitialization extends TranslatedNonDefaultFieldInitialization, InitializationContext, TTranslatedExplicitFieldInitialization @@ -619,8 +619,8 @@ class TranslatedExplicitFieldInitialization extends TranslatedNonDefaultFieldIni } /** - * Represents the IR translation of the initialization of a field from an - * element of an initializer list where default initialization is used. + * The IR translation of the initialization of a field from an element of an initializer + * list where default initialization is used. */ class TranslatedDefaultFieldInitialization extends TranslatedFieldInitialization, TTranslatedDefaultFieldInitialization @@ -689,8 +689,8 @@ private string getZeroValue(Type type) { } /** - * Represents the IR translation of the initialization of a field without a - * corresponding element in the initializer list. + * The IR translation of the initialization of a field without a corresponding + * element in the initializer list. */ class TranslatedFieldValueInitialization extends TranslatedNonDefaultFieldInitialization, TTranslatedFieldValueInitialization @@ -758,8 +758,8 @@ class TranslatedFieldValueInitialization extends TranslatedNonDefaultFieldInitia } /** - * Represents the IR translation of the initialization of an array element from - * an element of an initializer list. + * The IR translation of the initialization of an array element from an element + * of an initializer list. */ abstract class TranslatedElementInitialization extends TranslatedElement { ArrayOrVectorAggregateLiteral initList; @@ -836,8 +836,8 @@ abstract class TranslatedElementInitialization extends TranslatedElement { } /** - * Represents the IR translation of the initialization of an array element from - * an explicit element in an initializer list. + * The IR translation of the initialization of an array element from an explicit + * element in an initializer list. */ class TranslatedExplicitElementInitialization extends TranslatedElementInitialization, TTranslatedExplicitElementInitialization, InitializationContext @@ -885,8 +885,8 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ } /** - * Represents the IR translation of the initialization of a range of array - * elements without corresponding elements in the initializer list. + * The IR translation of the initialization of a range of array elements without + * corresponding elements in the initializer list. */ class TranslatedElementValueInitialization extends TranslatedElementInitialization, TTranslatedElementValueInitialization From 4a637cbe0a0457c52d9db7698e3065151b9d187a Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 24 Mar 2026 15:34:34 +0100 Subject: [PATCH 12/16] C++: Accept dataflow test changes These need to be looked at, but because data flow through default field initialization is currently not working, let's postpone this as part of that work. --- .../dataflow/dataflow-tests/type-bugs.expected | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.expected index 87ebdc9e83a3..f68f9cf30811 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/type-bugs.expected @@ -36,6 +36,18 @@ irTypeBugs | ../../../include/iterator.h:31:16:31:25 | ../../../include/iterator.h:31:16:31:25 | ../../../include/iterator.h:31:16:31:25 | [summary] read: Argument[this].Element[*] in operator-> | | ../../../include/iterator.h:31:16:31:25 | ../../../include/iterator.h:31:16:31:25 | ../../../include/iterator.h:31:16:31:25 | [summary] to write: ReturnValue[**] in operator-> | | ../../../include/iterator.h:31:16:31:25 | ../../../include/iterator.h:31:16:31:25 | ../../../include/iterator.h:31:16:31:25 | [summary] to write: ReturnValue[*] in operator-> | +| ../../../include/iterator.h:50:14:50:22 | ../../../include/iterator.h:50:14:50:22 | ../../../include/iterator.h:50:14:50:22 | container | +| ../../../include/iterator.h:50:14:50:22 | ../../../include/iterator.h:50:14:50:22 | ../../../include/iterator.h:50:14:50:22 | container | +| ../../../include/iterator.h:50:14:50:22 | ../../../include/iterator.h:50:14:50:22 | ../../../include/iterator.h:50:14:50:22 | container | +| ../../../include/iterator.h:75:14:75:22 | ../../../include/iterator.h:75:14:75:22 | ../../../include/iterator.h:75:14:75:22 | container | +| ../../../include/iterator.h:75:14:75:22 | ../../../include/iterator.h:75:14:75:22 | ../../../include/iterator.h:75:14:75:22 | container | +| ../../../include/iterator.h:75:14:75:22 | ../../../include/iterator.h:75:14:75:22 | ../../../include/iterator.h:75:14:75:22 | container | +| test.cpp:356:7:356:11 | test.cpp:356:7:356:11 | test.cpp:356:7:356:11 | field | +| test.cpp:356:7:356:11 | test.cpp:356:7:356:11 | test.cpp:356:7:356:11 | field | +| test.cpp:356:7:356:11 | test.cpp:356:7:356:11 | test.cpp:356:7:356:11 | field | +| test.cpp:1318:9:1318:9 | test.cpp:1318:9:1318:9 | test.cpp:1318:9:1318:9 | i | +| test.cpp:1318:9:1318:9 | test.cpp:1318:9:1318:9 | test.cpp:1318:9:1318:9 | i | +| test.cpp:1318:9:1318:9 | test.cpp:1318:9:1318:9 | test.cpp:1318:9:1318:9 | i | incorrectBaseType | clang.cpp:22:8:22:20 | *& ... | Expected 'Node.getType()' to be int, but it was int * | | clang.cpp:23:17:23:29 | *& ... | Expected 'Node.getType()' to be int, but it was int * | From 0f44d6a7800678c916aab68b1738d010b389f580 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 24 Mar 2026 15:39:09 +0100 Subject: [PATCH 13/16] C++: Add change note --- cpp/ql/lib/change-notes/2026-03-24-field-init.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 cpp/ql/lib/change-notes/2026-03-24-field-init.md diff --git a/cpp/ql/lib/change-notes/2026-03-24-field-init.md b/cpp/ql/lib/change-notes/2026-03-24-field-init.md new file mode 100644 index 000000000000..0318d31aef58 --- /dev/null +++ b/cpp/ql/lib/change-notes/2026-03-24-field-init.md @@ -0,0 +1,5 @@ +--- +category: feature +--- +* Added a class `ConstructorDirectFieldInit` to represent field initializations that occur in member initialization lists. +* Added a class `ConstructorDefaultFieldInit` to represent default field initializations. From 49c5cc05acf8c1fde4cf45055a65a27faa1ae04f Mon Sep 17 00:00:00 2001 From: Jeroen Ketema <93738568+jketema@users.noreply.github.com> Date: Tue, 24 Mar 2026 16:09:33 +0100 Subject: [PATCH 14/16] Update cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../code/cpp/ir/implementation/raw/internal/TranslatedCall.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 572ce5f2858a..bd012d4b9b4a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -659,7 +659,7 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect, * The IR translation of an argument side effect for `*this` on a call, where there is no `Expr` * object that represents the `this` argument. * - * The applies to constructor calls and default field initializations, as the AST has explicit + * This applies to constructor calls and default field initializations, as the AST has explicit * qualifier `Expr`s for all other calls to non-static member functions. */ class TranslatedImplicitThisQualifierSideEffect extends TranslatedArgumentSideEffect, From db7c61969db301262f1bacc562ce3479146ef02f Mon Sep 17 00:00:00 2001 From: Jeroen Ketema <93738568+jketema@users.noreply.github.com> Date: Tue, 24 Mar 2026 16:11:10 +0100 Subject: [PATCH 15/16] Update cpp/ql/lib/change-notes/2026-03-24-field-init.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- cpp/ql/lib/change-notes/2026-03-24-field-init.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/lib/change-notes/2026-03-24-field-init.md b/cpp/ql/lib/change-notes/2026-03-24-field-init.md index 0318d31aef58..c11329a3d9f0 100644 --- a/cpp/ql/lib/change-notes/2026-03-24-field-init.md +++ b/cpp/ql/lib/change-notes/2026-03-24-field-init.md @@ -1,5 +1,5 @@ --- category: feature --- -* Added a class `ConstructorDirectFieldInit` to represent field initializations that occur in member initialization lists. +* Added a class `ConstructorDirectFieldInit` to represent field initializations that occur in member initializer lists. * Added a class `ConstructorDefaultFieldInit` to represent default field initializations. From dad517ff5e637f4b14cfc86797bd2de8348f492e Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Tue, 24 Mar 2026 16:16:14 +0100 Subject: [PATCH 16/16] C++: Fix typo --- .../code/cpp/ir/implementation/raw/internal/SideEffects.qll | 6 +++--- .../ir/implementation/raw/internal/TranslatedElement.qll | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll index 0ce1f898c0d1..c6214bf5e4f7 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll @@ -135,8 +135,8 @@ private predicate hasDefaultSideEffect(Call call, ParameterIndex i, boolean buff * All kinds of expressions invoke a function as part of their evaluation. This class provides a * way to treat those expressions similarly, and to get the invoked `Declaration`. */ -class ExprWithCallSizeEffects extends Expr { - ExprWithCallSizeEffects() { +class ExprWithCallSideEffects extends Expr { + ExprWithCallSideEffects() { this instanceof Call or this instanceof NewOrNewArrayExpr @@ -162,7 +162,7 @@ class ExprWithCallSizeEffects extends Expr { * Returns the side effect opcode, if any, that represents any side effects not specifically modeled * by an argument side effect. */ -Opcode getCallSideEffectOpcode(ExprWithCallSizeEffects expr) { +Opcode getCallSideEffectOpcode(ExprWithCallSideEffects expr) { not exists(expr.getTarget().(SideEffectFunction)) and result instanceof Opcode::CallSideEffect or exists(SideEffectFunction sideEffectFunction | 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 2f86a3f476bc..58456476f6a2 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 @@ -879,7 +879,7 @@ newtype TTranslatedElement = // The declaration/initialization part of a `ConditionDeclExpr` TTranslatedConditionDecl(ConditionDeclExpr expr) { not ignoreExpr(expr) } or // The side effects of a `Call` - TTranslatedCallSideEffects(ExprWithCallSizeEffects expr) { + TTranslatedCallSideEffects(ExprWithCallSideEffects expr) { not ignoreExpr(expr) and not ignoreSideEffects(expr) } or @@ -918,7 +918,7 @@ newtype TTranslatedElement = } or // Constructor calls lack a qualifier (`this`) expression, so we need to handle the side effects // on `*this` without an `Expr`. - TTranslatedImplicitThisQualifierSideEffect(ExprWithCallSizeEffects call, SideEffectOpcode opcode) { + TTranslatedImplicitThisQualifierSideEffect(ExprWithCallSideEffects call, SideEffectOpcode opcode) { not ignoreExpr(call) and not ignoreSideEffects(call) and (