Skip to content

Commit 2e2913b

Browse files
authored
Merge pull request #7839 from rdmarsh2/rdmarsh2/ir-initializer-inheritance-fix
C++: fix IR generation for constructor base inits when no constructor is present.
2 parents d08c0f7 + 55cbff7 commit 2e2913b

File tree

7 files changed

+182
-0
lines changed

7 files changed

+182
-0
lines changed

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,13 @@ newtype TTranslatedElement =
567567
} or
568568
// The initialization of a base class from within a constructor.
569569
TTranslatedConstructorBaseInit(ConstructorBaseInit init) { not ignoreExpr(init) } or
570+
// Workaround for a case where no base constructor is generated but a targetless base
571+
// constructor call is present.
572+
TTranslatedConstructorBareInit(ConstructorInit init) {
573+
not ignoreExpr(init) and
574+
not init instanceof ConstructorBaseInit and
575+
not init instanceof ConstructorFieldInit
576+
} or
570577
// The destruction of a base class from within a destructor.
571578
TTranslatedDestructorBaseDestruction(DestructorBaseDestruction destruction) {
572579
not ignoreExpr(destruction)

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,11 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
573573
baseInit = func.(Constructor).getInitializer(id) and
574574
result = getTranslatedConstructorBaseInit(baseInit)
575575
)
576+
or
577+
exists(ConstructorInit bareInit |
578+
bareInit = func.(Constructor).getInitializer(id) and
579+
result = getTranslatedConstructorBareInit(bareInit)
580+
)
576581
}
577582

578583
override Instruction getFirstInstruction() {

cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -917,3 +917,36 @@ class TranslatedDestructorBaseDestruction extends TranslatedBaseStructorCall,
917917

918918
final override string toString() { result = "destroy base: " + call.toString() }
919919
}
920+
921+
/**
922+
* A constructor base init call where no base constructor has been generated.
923+
*
924+
* Workaround for an extractor issue.
925+
*/
926+
class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstructorBareInit {
927+
ConstructorInit init;
928+
929+
TranslatedConstructorBareInit() { this = TTranslatedConstructorBareInit(init) }
930+
931+
override Locatable getAST() { result = init }
932+
933+
final override string toString() { result = "construct base (no constructor)" }
934+
935+
override Instruction getFirstInstruction() { result = getParent().getChildSuccessor(this) }
936+
937+
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
938+
none()
939+
}
940+
941+
override TranslatedElement getChild(int id) { none() }
942+
943+
override Function getFunction() { result = getParent().getFunction() }
944+
945+
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
946+
947+
override Instruction getChildSuccessor(TranslatedElement child) { none() }
948+
}
949+
950+
TranslatedConstructorBareInit getTranslatedConstructorBareInit(ConstructorInit init) {
951+
result.getAST() = init
952+
}

cpp/ql/test/library-tests/ir/ir/PrintAST.expected

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11332,6 +11332,64 @@ ir.cpp:
1133211332
# 1447| Type = [Struct] POD_Derived
1133311333
# 1447| ValueCategory = prvalue
1133411334
# 1448| getStmt(4): [ReturnStmt] return ...
11335+
# 1450| [CopyAssignmentOperator] Inheritance_Test_B& Inheritance_Test_B::operator=(Inheritance_Test_B const&)
11336+
# 1450| <params>:
11337+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
11338+
#-----| Type = [LValueReferenceType] const Inheritance_Test_B &
11339+
# 1450| [Constructor] void Inheritance_Test_B::Inheritance_Test_B()
11340+
# 1450| <params>:
11341+
# 1451| [Destructor] void Inheritance_Test_B::~Inheritance_Test_B()
11342+
# 1451| <params>:
11343+
# 1451| getEntryPoint(): [BlockStmt] { ... }
11344+
# 1451| getStmt(0): [ReturnStmt] return ...
11345+
# 1451| <destructions>:
11346+
# 1454| [CopyAssignmentOperator] Inheritance_Test_A& Inheritance_Test_A::operator=(Inheritance_Test_A const&)
11347+
# 1454| <params>:
11348+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
11349+
#-----| Type = [LValueReferenceType] const Inheritance_Test_A &
11350+
# 1454| [MoveAssignmentOperator] Inheritance_Test_A& Inheritance_Test_A::operator=(Inheritance_Test_A&&)
11351+
# 1454| <params>:
11352+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
11353+
#-----| Type = [RValueReferenceType] Inheritance_Test_A &&
11354+
# 1454| [CopyConstructor] void Inheritance_Test_A::Inheritance_Test_A(Inheritance_Test_A const&)
11355+
# 1454| <params>:
11356+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
11357+
#-----| Type = [LValueReferenceType] const Inheritance_Test_A &
11358+
# 1454| [MoveConstructor] void Inheritance_Test_A::Inheritance_Test_A(Inheritance_Test_A&&)
11359+
# 1454| <params>:
11360+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
11361+
#-----| Type = [RValueReferenceType] Inheritance_Test_A &&
11362+
# 1454| [Destructor] void Inheritance_Test_A::~Inheritance_Test_A()
11363+
# 1454| <params>:
11364+
# 1457| [Constructor] void Inheritance_Test_A::Inheritance_Test_A()
11365+
# 1457| <params>:
11366+
# 1457| <initializations>:
11367+
# 1457| getInitializer(0): (no string representation)
11368+
# 1457| Type = [Struct] Inheritance_Test_B
11369+
# 1457| ValueCategory = prvalue
11370+
# 1457| getInitializer(1): [ConstructorFieldInit] constructor init of field x
11371+
# 1457| Type = [IntType] int
11372+
# 1457| ValueCategory = prvalue
11373+
# 1457| getExpr(): [Literal] 42
11374+
# 1457| Type = [IntType] int
11375+
# 1457| Value = [Literal] 42
11376+
# 1457| ValueCategory = prvalue
11377+
# 1457| getEntryPoint(): [BlockStmt] { ... }
11378+
# 1458| getStmt(0): [ExprStmt] ExprStmt
11379+
# 1458| getExpr(): [AssignExpr] ... = ...
11380+
# 1458| Type = [IntType] int
11381+
# 1458| ValueCategory = lvalue
11382+
# 1458| getLValue(): [PointerFieldAccess] y
11383+
# 1458| Type = [IntType] int
11384+
# 1458| ValueCategory = lvalue
11385+
# 1458| getQualifier(): [ThisExpr] this
11386+
# 1458| Type = [PointerType] Inheritance_Test_A *
11387+
# 1458| ValueCategory = prvalue(load)
11388+
# 1458| getRValue(): [Literal] 3
11389+
# 1458| Type = [IntType] int
11390+
# 1458| Value = [Literal] 3
11391+
# 1458| ValueCategory = prvalue
11392+
# 1459| getStmt(1): [ReturnStmt] return ...
1133511393
perf-regression.cpp:
1133611394
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
1133711395
# 4| <params>:

cpp/ql/test/library-tests/ir/ir/ir.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1447,4 +1447,15 @@ void temporary_hierarchy() {
14471447
float f = (returnValue<POD_Derived>()).f();
14481448
}
14491449

1450+
struct Inheritance_Test_B {
1451+
~Inheritance_Test_B() {}
1452+
};
1453+
1454+
struct Inheritance_Test_A : public Inheritance_Test_B {
1455+
int x;
1456+
int y;
1457+
Inheritance_Test_A() : x(42) {
1458+
y = 3;
1459+
}
1460+
};
14501461
// semmle-extractor-options: -std=c++17 --clang

cpp/ql/test/library-tests/ir/ir/operand_locations.expected

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6626,6 +6626,36 @@
66266626
| ir.cpp:1447:44:1447:44 | ChiTotal | total:m1447_5 |
66276627
| ir.cpp:1447:44:1447:44 | SideEffect | ~m1447_5 |
66286628
| ir.cpp:1447:44:1447:44 | StoreValue | r1447_8 |
6629+
| ir.cpp:1451:3:1451:21 | Address | &:r1451_5 |
6630+
| ir.cpp:1451:3:1451:21 | Address | &:r1451_5 |
6631+
| ir.cpp:1451:3:1451:21 | Address | &:r1451_7 |
6632+
| ir.cpp:1451:3:1451:21 | Address | &:r1451_7 |
6633+
| ir.cpp:1451:3:1451:21 | ChiPartial | partial:m1451_3 |
6634+
| ir.cpp:1451:3:1451:21 | ChiTotal | total:m1451_2 |
6635+
| ir.cpp:1451:3:1451:21 | Load | m1451_6 |
6636+
| ir.cpp:1451:3:1451:21 | SideEffect | m1451_3 |
6637+
| ir.cpp:1451:3:1451:21 | SideEffect | m1451_8 |
6638+
| ir.cpp:1457:3:1457:20 | Address | &:r1457_5 |
6639+
| ir.cpp:1457:3:1457:20 | Address | &:r1457_5 |
6640+
| ir.cpp:1457:3:1457:20 | Address | &:r1457_7 |
6641+
| ir.cpp:1457:3:1457:20 | Address | &:r1457_7 |
6642+
| ir.cpp:1457:3:1457:20 | ChiPartial | partial:m1457_3 |
6643+
| ir.cpp:1457:3:1457:20 | ChiTotal | total:m1457_2 |
6644+
| ir.cpp:1457:3:1457:20 | Load | m1457_6 |
6645+
| ir.cpp:1457:3:1457:20 | SideEffect | m1457_3 |
6646+
| ir.cpp:1457:3:1457:20 | SideEffect | m1458_6 |
6647+
| ir.cpp:1457:3:1457:20 | Unary | m1457_6 |
6648+
| ir.cpp:1457:26:1457:30 | Address | &:r1457_9 |
6649+
| ir.cpp:1457:26:1457:30 | ChiPartial | partial:m1457_11 |
6650+
| ir.cpp:1457:26:1457:30 | ChiTotal | total:m1457_8 |
6651+
| ir.cpp:1457:26:1457:30 | StoreValue | r1457_10 |
6652+
| ir.cpp:1458:5:1458:5 | Address | &:r1458_2 |
6653+
| ir.cpp:1458:5:1458:5 | Address | &:r1458_4 |
6654+
| ir.cpp:1458:5:1458:5 | Load | m1457_6 |
6655+
| ir.cpp:1458:5:1458:5 | Unary | r1458_3 |
6656+
| ir.cpp:1458:5:1458:9 | ChiPartial | partial:m1458_5 |
6657+
| ir.cpp:1458:5:1458:9 | ChiTotal | total:m1457_12 |
6658+
| ir.cpp:1458:9:1458:9 | StoreValue | r1458_1 |
66296659
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
66306660
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
66316661
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |

cpp/ql/test/library-tests/ir/ir/raw_ir.expected

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7858,6 +7858,44 @@ ir.cpp:
78587858
# 1443| v1443_5(void) = AliasedUse : ~m?
78597859
# 1443| v1443_6(void) = ExitFunction :
78607860

7861+
# 1451| void Inheritance_Test_B::~Inheritance_Test_B()
7862+
# 1451| Block 0
7863+
# 1451| v1451_1(void) = EnterFunction :
7864+
# 1451| mu1451_2(unknown) = AliasedDefinition :
7865+
# 1451| mu1451_3(unknown) = InitializeNonLocal :
7866+
# 1451| r1451_4(glval<unknown>) = VariableAddress[#this] :
7867+
# 1451| mu1451_5(glval<Inheritance_Test_B>) = InitializeParameter[#this] : &:r1451_4
7868+
# 1451| r1451_6(glval<Inheritance_Test_B>) = Load[#this] : &:r1451_4, ~m?
7869+
# 1451| mu1451_7(Inheritance_Test_B) = InitializeIndirection[#this] : &:r1451_6
7870+
# 1451| v1451_8(void) = NoOp :
7871+
# 1451| v1451_9(void) = ReturnIndirection[#this] : &:r1451_6, ~m?
7872+
# 1451| v1451_10(void) = ReturnVoid :
7873+
# 1451| v1451_11(void) = AliasedUse : ~m?
7874+
# 1451| v1451_12(void) = ExitFunction :
7875+
7876+
# 1457| void Inheritance_Test_A::Inheritance_Test_A()
7877+
# 1457| Block 0
7878+
# 1457| v1457_1(void) = EnterFunction :
7879+
# 1457| mu1457_2(unknown) = AliasedDefinition :
7880+
# 1457| mu1457_3(unknown) = InitializeNonLocal :
7881+
# 1457| r1457_4(glval<unknown>) = VariableAddress[#this] :
7882+
# 1457| mu1457_5(glval<Inheritance_Test_A>) = InitializeParameter[#this] : &:r1457_4
7883+
# 1457| r1457_6(glval<Inheritance_Test_A>) = Load[#this] : &:r1457_4, ~m?
7884+
# 1457| mu1457_7(Inheritance_Test_A) = InitializeIndirection[#this] : &:r1457_6
7885+
# 1457| r1457_8(glval<int>) = FieldAddress[x] : mu1457_5
7886+
# 1457| r1457_9(int) = Constant[42] :
7887+
# 1457| mu1457_10(int) = Store[?] : &:r1457_8, r1457_9
7888+
# 1458| r1458_1(int) = Constant[3] :
7889+
# 1458| r1458_2(glval<unknown>) = VariableAddress[#this] :
7890+
# 1458| r1458_3(Inheritance_Test_A *) = Load[#this] : &:r1458_2, ~m?
7891+
# 1458| r1458_4(glval<int>) = FieldAddress[y] : r1458_3
7892+
# 1458| mu1458_5(int) = Store[?] : &:r1458_4, r1458_1
7893+
# 1459| v1459_1(void) = NoOp :
7894+
# 1457| v1457_11(void) = ReturnIndirection[#this] : &:r1457_6, ~m?
7895+
# 1457| v1457_12(void) = ReturnVoid :
7896+
# 1457| v1457_13(void) = AliasedUse : ~m?
7897+
# 1457| v1457_14(void) = ExitFunction :
7898+
78617899
perf-regression.cpp:
78627900
# 6| void Big::Big()
78637901
# 6| Block 0

0 commit comments

Comments
 (0)