Skip to content

Commit 7282ad9

Browse files
authored
Merge pull request github#5854 from dbartol/dbartol/smart-pointers/side-effects
C++: Generate side effect instructions for smart pointer indirections
2 parents da14647 + 773e5f2 commit 7282ad9

File tree

20 files changed

+397
-10
lines changed

20 files changed

+397
-10
lines changed

config/identical-files.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,10 @@
250250
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll",
251251
"csharp/ql/src/experimental/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll"
252252
],
253+
"SSA PrintAliasAnalysis": [
254+
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/PrintAliasAnalysis.qll",
255+
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/PrintAliasAnalysis.qll"
256+
],
253257
"C++ SSA AliasAnalysisImports": [
254258
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysisImports.qll",
255259
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysisImports.qll"

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,3 +416,46 @@ predicate addressOperandAllocationAndOffset(
416416
)
417417
)
418418
}
419+
420+
/**
421+
* Predicates used only for printing annotated IR dumps. These should not be used in production
422+
* queries.
423+
*/
424+
module Print {
425+
string getOperandProperty(Operand operand, string key) {
426+
key = "alloc" and
427+
result =
428+
strictconcat(Configuration::Allocation allocation, IntValue bitOffset |
429+
addressOperandAllocationAndOffset(operand, allocation, bitOffset)
430+
|
431+
allocation.toString() + Ints::getBitOffsetString(bitOffset), ", "
432+
)
433+
or
434+
key = "prop" and
435+
result =
436+
strictconcat(Instruction destInstr, IntValue bitOffset, string value |
437+
operandIsPropagatedIncludingByCall(operand, bitOffset, destInstr) and
438+
if destInstr = operand.getUse()
439+
then value = "@" + Ints::getBitOffsetString(bitOffset) + "->result"
440+
else value = "@" + Ints::getBitOffsetString(bitOffset) + "->" + destInstr.getResultId()
441+
|
442+
value, ", "
443+
)
444+
}
445+
446+
string getInstructionProperty(Instruction instr, string key) {
447+
key = "prop" and
448+
result =
449+
strictconcat(IntValue bitOffset, Operand sourceOperand, string value |
450+
operandIsPropagatedIncludingByCall(sourceOperand, bitOffset, instr) and
451+
if instr = sourceOperand.getUse()
452+
then value = sourceOperand.getDumpId() + Ints::getBitOffsetString(bitOffset) + "->@"
453+
else
454+
value =
455+
sourceOperand.getUse().getResultId() + "." + sourceOperand.getDumpId() +
456+
Ints::getBitOffsetString(bitOffset) + "->@"
457+
|
458+
value, ", "
459+
)
460+
}
461+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Include this module to annotate IR dumps with information computed by `AliasAnalysis.qll`.
3+
*/
4+
5+
private import AliasAnalysisInternal
6+
private import InputIR
7+
private import AliasAnalysisImports
8+
private import AliasAnalysis
9+
private import semmle.code.cpp.ir.internal.IntegerConstant
10+
11+
private class AliasPropertyProvider extends IRPropertyProvider {
12+
override string getOperandProperty(Operand operand, string key) {
13+
result = Print::getOperandProperty(operand, key)
14+
}
15+
16+
override string getInstructionProperty(Instruction instr, string key) {
17+
result = Print::getInstructionProperty(instr, key)
18+
}
19+
}

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,10 @@ module SSAConsistency {
10731073
locationCount > 1 and
10741074
func = operand.getEnclosingIRFunction() and
10751075
funcText = Language::getIdentityString(func.getFunction()) and
1076-
message = "Operand has " + locationCount.toString() + " memory accesses in function '$@'."
1076+
message =
1077+
operand.getUse().toString() + " " + "Operand has " + locationCount.toString() +
1078+
" memory accesses in function '$@': " +
1079+
strictconcat(Alias::getOperandMemoryLocation(operand).toString(), ", ")
10771080
)
10781081
}
10791082

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/SideEffects.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
private import cpp
99
private import semmle.code.cpp.ir.implementation.Opcode
10+
private import semmle.code.cpp.models.interfaces.PointerWrapper
1011
private import semmle.code.cpp.models.interfaces.SideEffect
1112

1213
/**
@@ -39,7 +40,8 @@ private predicate hasDefaultSideEffect(Call call, ParameterIndex i, boolean buff
3940
exists(Type t | t = expr.getUnspecifiedType() |
4041
t instanceof ArrayType or
4142
t instanceof PointerType or
42-
t instanceof ReferenceType
43+
t instanceof ReferenceType or
44+
t instanceof PointerWrapper
4345
) and
4446
(
4547
isWrite = true and

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,3 +416,46 @@ predicate addressOperandAllocationAndOffset(
416416
)
417417
)
418418
}
419+
420+
/**
421+
* Predicates used only for printing annotated IR dumps. These should not be used in production
422+
* queries.
423+
*/
424+
module Print {
425+
string getOperandProperty(Operand operand, string key) {
426+
key = "alloc" and
427+
result =
428+
strictconcat(Configuration::Allocation allocation, IntValue bitOffset |
429+
addressOperandAllocationAndOffset(operand, allocation, bitOffset)
430+
|
431+
allocation.toString() + Ints::getBitOffsetString(bitOffset), ", "
432+
)
433+
or
434+
key = "prop" and
435+
result =
436+
strictconcat(Instruction destInstr, IntValue bitOffset, string value |
437+
operandIsPropagatedIncludingByCall(operand, bitOffset, destInstr) and
438+
if destInstr = operand.getUse()
439+
then value = "@" + Ints::getBitOffsetString(bitOffset) + "->result"
440+
else value = "@" + Ints::getBitOffsetString(bitOffset) + "->" + destInstr.getResultId()
441+
|
442+
value, ", "
443+
)
444+
}
445+
446+
string getInstructionProperty(Instruction instr, string key) {
447+
key = "prop" and
448+
result =
449+
strictconcat(IntValue bitOffset, Operand sourceOperand, string value |
450+
operandIsPropagatedIncludingByCall(sourceOperand, bitOffset, instr) and
451+
if instr = sourceOperand.getUse()
452+
then value = sourceOperand.getDumpId() + Ints::getBitOffsetString(bitOffset) + "->@"
453+
else
454+
value =
455+
sourceOperand.getUse().getResultId() + "." + sourceOperand.getDumpId() +
456+
Ints::getBitOffsetString(bitOffset) + "->@"
457+
|
458+
value, ", "
459+
)
460+
}
461+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Include this module to annotate IR dumps with information computed by `AliasAnalysis.qll`.
3+
*/
4+
5+
private import AliasAnalysisInternal
6+
private import InputIR
7+
private import AliasAnalysisImports
8+
private import AliasAnalysis
9+
private import semmle.code.cpp.ir.internal.IntegerConstant
10+
11+
private class AliasPropertyProvider extends IRPropertyProvider {
12+
override string getOperandProperty(Operand operand, string key) {
13+
result = Print::getOperandProperty(operand, key)
14+
}
15+
16+
override string getInstructionProperty(Instruction instr, string key) {
17+
result = Print::getInstructionProperty(instr, key)
18+
}
19+
}

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,10 @@ module SSAConsistency {
10731073
locationCount > 1 and
10741074
func = operand.getEnclosingIRFunction() and
10751075
funcText = Language::getIdentityString(func.getFunction()) and
1076-
message = "Operand has " + locationCount.toString() + " memory accesses in function '$@'."
1076+
message =
1077+
operand.getUse().toString() + " " + "Operand has " + locationCount.toString() +
1078+
" memory accesses in function '$@': " +
1079+
strictconcat(Alias::getOperandMemoryLocation(operand).toString(), ", ")
10771080
)
10781081
}
10791082

cpp/ql/src/semmle/code/cpp/models/implementations/SmartPointer.qll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,11 @@ private class SmartPtrSetterFunction extends MemberFunction, AliasFunction, Side
157157
// parameter.
158158
result.isParameter(1)
159159
else result.isParameterDeref(0)
160+
or
161+
// One of the functions that takes ownership of a raw pointer.
162+
param0.getUnspecifiedType() instanceof PointerType and
163+
result.isParameter(0)
160164
)
161-
or
162-
// One of the functions that takes ownership of a raw pointer.
163-
param0.getUnspecifiedType() instanceof PointerType and
164-
result.isParameter(0)
165165
)
166166
}
167167
}

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

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11365,6 +11365,86 @@ perf-regression.cpp:
1136511365
# 12| Type = [IntType] int
1136611366
# 12| Value = [Literal] 0
1136711367
# 12| ValueCategory = prvalue
11368+
smart_ptr.cpp:
11369+
# 8| [TopLevelFunction] void unique_ptr_arg(std::unique_ptr<int, std::default_delete<int>>)
11370+
# 8| <params>:
11371+
# 8| getParameter(0): [Parameter] up
11372+
# 8| Type = [ClassTemplateInstantiation] unique_ptr<int, default_delete<int>>
11373+
# 10| [TopLevelFunction] void call_unique_ptr_arg(int*)
11374+
# 10| <params>:
11375+
# 10| getParameter(0): [Parameter] p
11376+
# 10| Type = [IntPointerType] int *
11377+
# 10| getEntryPoint(): [BlockStmt] { ... }
11378+
# 11| getStmt(0): [DeclStmt] declaration
11379+
# 11| getDeclarationEntry(0): [VariableDeclarationEntry] definition of up
11380+
# 11| Type = [ClassTemplateInstantiation] unique_ptr<int, default_delete<int>>
11381+
# 11| getVariable().getInitializer(): [Initializer] initializer for up
11382+
# 11| getExpr(): [ConstructorCall] call to unique_ptr
11383+
# 11| Type = [VoidType] void
11384+
# 11| ValueCategory = prvalue
11385+
# 11| getArgument(0): [VariableAccess] p
11386+
# 11| Type = [IntPointerType] int *
11387+
# 11| ValueCategory = prvalue(load)
11388+
# 12| getStmt(1): [ExprStmt] ExprStmt
11389+
# 12| getExpr(): [FunctionCall] call to unique_ptr_arg
11390+
# 12| Type = [VoidType] void
11391+
# 12| ValueCategory = prvalue
11392+
# 12| getArgument(0): [FunctionCall] call to move
11393+
# 12| Type = [RValueReferenceType] type &&
11394+
# 12| ValueCategory = prvalue
11395+
# 12| getArgument(0): [VariableAccess] up
11396+
# 12| Type = [ClassTemplateInstantiation] unique_ptr<int, default_delete<int>>
11397+
# 12| ValueCategory = lvalue
11398+
# 12| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
11399+
# 12| Type = [LValueReferenceType] unique_ptr<int, default_delete<int>> &
11400+
# 12| ValueCategory = prvalue
11401+
# 12| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
11402+
# 12| Type = [ClassTemplateInstantiation] unique_ptr<int, default_delete<int>>
11403+
# 12| ValueCategory = lvalue
11404+
# 12| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
11405+
# 12| Type = [CTypedefType,NestedTypedefType] type
11406+
# 12| ValueCategory = prvalue(load)
11407+
# 13| getStmt(2): [ReturnStmt] return ...
11408+
# 15| [TopLevelFunction] void shared_ptr_arg(std::shared_ptr<float>)
11409+
# 15| <params>:
11410+
# 15| getParameter(0): [Parameter] sp
11411+
# 15| Type = [ClassTemplateInstantiation] shared_ptr<float>
11412+
# 17| [TopLevelFunction] void call_shared_ptr_arg(float*)
11413+
# 17| <params>:
11414+
# 17| getParameter(0): [Parameter] p
11415+
# 17| Type = [PointerType] float *
11416+
# 17| getEntryPoint(): [BlockStmt] { ... }
11417+
# 18| getStmt(0): [DeclStmt] declaration
11418+
# 18| getDeclarationEntry(0): [VariableDeclarationEntry] definition of sp
11419+
# 18| Type = [ClassTemplateInstantiation] shared_ptr<float>
11420+
# 18| getVariable().getInitializer(): [Initializer] initializer for sp
11421+
# 18| getExpr(): [ConstructorCall] call to shared_ptr
11422+
# 18| Type = [VoidType] void
11423+
# 18| ValueCategory = prvalue
11424+
# 18| getArgument(0): [VariableAccess] p
11425+
# 18| Type = [PointerType] float *
11426+
# 18| ValueCategory = prvalue(load)
11427+
# 19| getStmt(1): [ExprStmt] ExprStmt
11428+
# 19| getExpr(): [FunctionCall] call to shared_ptr_arg
11429+
# 19| Type = [VoidType] void
11430+
# 19| ValueCategory = prvalue
11431+
# 19| getArgument(0): [ConstructorCall] call to shared_ptr
11432+
# 19| Type = [VoidType] void
11433+
# 19| ValueCategory = prvalue
11434+
# 19| getArgument(0): [VariableAccess] sp
11435+
# 19| Type = [ClassTemplateInstantiation] shared_ptr<float>
11436+
# 19| ValueCategory = lvalue
11437+
# 19| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
11438+
# 19| Type = [LValueReferenceType] const shared_ptr<float> &
11439+
# 19| ValueCategory = prvalue
11440+
# 19| getExpr(): [CStyleCast] (const shared_ptr<float>)...
11441+
# 19| Conversion = [GlvalueConversion] glvalue conversion
11442+
# 19| Type = [SpecifiedType] const shared_ptr<float>
11443+
# 19| ValueCategory = lvalue
11444+
# 19| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
11445+
# 19| Type = [ClassTemplateInstantiation] shared_ptr<float>
11446+
# 19| ValueCategory = lvalue
11447+
# 20| getStmt(2): [ReturnStmt] return ...
1136811448
struct_init.cpp:
1136911449
# 1| [TopLevelFunction] int handler1(void*)
1137011450
# 1| <params>:

0 commit comments

Comments
 (0)