Skip to content

Commit 182bea4

Browse files
authored
Merge pull request #22580 from MathiasVP/fix-ir-consistency
C++: Fix IR for chained member access on temporaries
2 parents 4411b5e + fd9c8ca commit 182bea4

5 files changed

Lines changed: 86 additions & 7 deletions

File tree

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

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -430,14 +430,18 @@ private predicate mustTransformToGLValue(Expr expr) {
430430
}
431431

432432
/**
433-
* Holds if `expr` has an lvalue-to-rvalue conversion that should be ignored
434-
* when generating IR. This occurs for conversion from an lvalue of function type
435-
* to an rvalue of function pointer type. The conversion is represented in the
436-
* AST as an lvalue-to-rvalue conversion, but the IR represents both a function
433+
* Holds if `expr` has an explicit or implicit load that should be ignored
434+
* when generating IR. For example, this occurs for conversion from an lvalue of
435+
* function type to an rvalue of function pointer type. The conversion is represented
436+
* in the AST as an lvalue-to-rvalue conversion, but the IR represents both a function
437437
* lvalue and a function pointer prvalue the same.
438438
*/
439439
predicate ignoreLoad(Expr expr) {
440-
expr.hasLValueToRValueConversion() and
440+
(
441+
expr.hasLValueToRValueConversion()
442+
or
443+
isPRValueFieldAccessWithImplicitLoad(expr)
444+
) and
441445
(
442446
expr instanceof ThisExpr
443447
or
@@ -517,8 +521,11 @@ predicate hasTranslatedLoad(Expr expr) {
517521
predicate hasTranslatedSyntheticTemporaryObject(Expr expr) {
518522
not ignoreExpr(expr) and
519523
mustTransformToGLValue(expr) and
520-
// If it's a load, we'll just ignore the load in `ignoreLoad()`.
521-
not expr.hasLValueToRValueConversion()
524+
// If it's an explicit or implicit field load, reuse the existing address by
525+
// ignoring the load in `ignoreLoad` instead of materializing another
526+
// temporary.
527+
not expr.hasLValueToRValueConversion() and
528+
not isPRValueFieldAccessWithImplicitLoad(expr)
522529
}
523530

524531
Opcode comparisonOpcode(ComparisonOperation expr) {

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25804,6 +25804,30 @@ ir.cpp:
2580425804
# 2919| Conversion = [FloatingPointToIntegralConversion] floating point to integral conversion
2580525805
# 2919| Type = [IntType] int
2580625806
# 2919| ValueCategory = prvalue
25807+
# 2921| [CopyAssignmentOperator] PointerWrapper& PointerWrapper::operator=(PointerWrapper const&)
25808+
# 2921| <params>:
25809+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
25810+
#-----| Type = [LValueReferenceType] const PointerWrapper &
25811+
# 2921| [MoveAssignmentOperator] PointerWrapper& PointerWrapper::operator=(PointerWrapper&&)
25812+
# 2921| <params>:
25813+
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
25814+
#-----| Type = [RValueReferenceType] PointerWrapper &&
25815+
# 2925| [TopLevelFunction] PointerWrapper get_wrapper()
25816+
# 2925| <params>:
25817+
# 2927| [TopLevelFunction] void test()
25818+
# 2927| <params>:
25819+
# 2927| getEntryPoint(): [BlockStmt] { ... }
25820+
# 2928| getStmt(0): [ExprStmt] ExprStmt
25821+
# 2928| getExpr(): [ValueFieldAccess] x
25822+
# 2928| Type = [IntType] int
25823+
# 2928| ValueCategory = prvalue
25824+
# 2928| getQualifier(): [ValueFieldAccess] point
25825+
# 2928| Type = [Struct] Point
25826+
# 2928| ValueCategory = prvalue
25827+
# 2928| getQualifier(): [FunctionCall] call to get_wrapper
25828+
# 2928| Type = [Struct] PointerWrapper
25829+
# 2928| ValueCategory = prvalue
25830+
# 2929| getStmt(1): [ReturnStmt] return ...
2580725831
ir23.cpp:
2580825832
# 1| [TopLevelFunction] bool consteval_1()
2580925833
# 1| <params>:

‎cpp/ql/test/library-tests/ir/ir/aliased_ir.expected‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21772,6 +21772,26 @@ ir.cpp:
2177221772
# 2919| v2919_13(void) = AliasedUse : ~m2919_11
2177321773
# 2919| v2919_14(void) = ExitFunction :
2177421774

21775+
# 2927| void test()
21776+
# 2927| Block 0
21777+
# 2927| v2927_1(void) = EnterFunction :
21778+
# 2927| m2927_2(unknown) = AliasedDefinition :
21779+
# 2927| m2927_3(unknown) = InitializeNonLocal :
21780+
# 2927| m2927_4(unknown) = Chi : total:m2927_2, partial:m2927_3
21781+
# 2928| r2928_1(glval<unknown>) = FunctionAddress[get_wrapper] :
21782+
# 2928| r2928_2(PointerWrapper) = Call[get_wrapper] : func:r2928_1
21783+
# 2928| m2928_3(unknown) = ^CallSideEffect : ~m2927_4
21784+
# 2928| m2928_4(unknown) = Chi : total:m2927_4, partial:m2928_3
21785+
# 2928| r2928_5(glval<PointerWrapper>) = VariableAddress[#temp2928:3] :
21786+
# 2928| m2928_6(PointerWrapper) = Store[#temp2928:3] : &:r2928_5, r2928_2
21787+
# 2928| r2928_7(glval<Point>) = FieldAddress[point] : r2928_5
21788+
# 2928| r2928_8(glval<int>) = FieldAddress[x] : r2928_7
21789+
# 2928| r2928_9(int) = Load[?] : &:r2928_8, ~m2928_6
21790+
# 2929| v2929_1(void) = NoOp :
21791+
# 2927| v2927_5(void) = ReturnVoid :
21792+
# 2927| v2927_6(void) = AliasedUse : ~m2928_4
21793+
# 2927| v2927_7(void) = ExitFunction :
21794+
2177521795
ir23.cpp:
2177621796
# 1| bool consteval_1()
2177721797
# 1| Block 0

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2918,4 +2918,14 @@ T VariableTemplateFunc(T x) {
29182918

29192919
int VariableTemplateFuncUse = VariableTemplateFunc(2.3);
29202920

2921+
struct PointerWrapper {
2922+
Point point;
2923+
};
2924+
2925+
PointerWrapper get_wrapper();
2926+
2927+
void test() {
2928+
get_wrapper().point.x;
2929+
}
2930+
29212931
// semmle-extractor-options: -std=c++20 --clang

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19777,6 +19777,24 @@ ir.cpp:
1977719777
# 2919| v2919_11(void) = AliasedUse : ~m?
1977819778
# 2919| v2919_12(void) = ExitFunction :
1977919779

19780+
# 2927| void test()
19781+
# 2927| Block 0
19782+
# 2927| v2927_1(void) = EnterFunction :
19783+
# 2927| mu2927_2(unknown) = AliasedDefinition :
19784+
# 2927| mu2927_3(unknown) = InitializeNonLocal :
19785+
# 2928| r2928_1(glval<unknown>) = FunctionAddress[get_wrapper] :
19786+
# 2928| r2928_2(PointerWrapper) = Call[get_wrapper] : func:r2928_1
19787+
# 2928| mu2928_3(unknown) = ^CallSideEffect : ~m?
19788+
# 2928| r2928_4(glval<PointerWrapper>) = VariableAddress[#temp2928:3] :
19789+
# 2928| mu2928_5(PointerWrapper) = Store[#temp2928:3] : &:r2928_4, r2928_2
19790+
# 2928| r2928_6(glval<Point>) = FieldAddress[point] : r2928_4
19791+
# 2928| r2928_7(glval<int>) = FieldAddress[x] : r2928_6
19792+
# 2928| r2928_8(int) = Load[?] : &:r2928_7, ~m?
19793+
# 2929| v2929_1(void) = NoOp :
19794+
# 2927| v2927_4(void) = ReturnVoid :
19795+
# 2927| v2927_5(void) = AliasedUse : ~m?
19796+
# 2927| v2927_6(void) = ExitFunction :
19797+
1978019798
ir23.cpp:
1978119799
# 1| bool consteval_1()
1978219800
# 1| Block 0

0 commit comments

Comments
 (0)