C++: fix duplicated UnreachedInstruction in raw IR

This commit is contained in:
Robert Marsh
2023-05-01 17:26:44 -04:00
parent 6dfc59874b
commit c6e0ee2695
14 changed files with 220 additions and 10 deletions

View File

@@ -410,6 +410,9 @@ predicate hasUnreachedInstruction(IRFunction func) {
exists(Call c |
c.getEnclosingFunction() = func.getFunction() and
any(Options opt).exits(c.getTarget())
) and
not exists(TranslatedUnreachableReturnStmt return |
return.getEnclosingFunction().getFunction() = func.getFunction()
)
}

View File

@@ -14437,6 +14437,31 @@ ir.cpp:
# 1903| Type = [VoidType] void
# 1903| ValueCategory = prvalue
# 1905| getStmt(1): [ReturnStmt] return ...
# 1907| [TopLevelFunction] int noreturnTest2(int)
# 1907| <params>:
# 1907| getParameter(0): [Parameter] x
# 1907| Type = [IntType] int
# 1907| getEntryPoint(): [BlockStmt] { ... }
# 1908| getStmt(0): [IfStmt] if (...) ...
# 1908| getCondition(): [LTExpr] ... < ...
# 1908| Type = [BoolType] bool
# 1908| ValueCategory = prvalue
# 1908| getLesserOperand(): [VariableAccess] x
# 1908| Type = [IntType] int
# 1908| ValueCategory = prvalue(load)
# 1908| getGreaterOperand(): [Literal] 10
# 1908| Type = [IntType] int
# 1908| Value = [Literal] 10
# 1908| ValueCategory = prvalue
# 1908| getThen(): [BlockStmt] { ... }
# 1909| getStmt(0): [ExprStmt] ExprStmt
# 1909| getExpr(): [FunctionCall] call to noreturnFunc
# 1909| Type = [VoidType] void
# 1909| ValueCategory = prvalue
# 1911| getStmt(1): [ReturnStmt] return ...
# 1911| getExpr(): [VariableAccess] x
# 1911| Type = [IntType] int
# 1911| ValueCategory = prvalue(load)
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| <params>:

View File

@@ -6,8 +6,6 @@ missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary
instructionWithoutSuccessor
| ir.cpp:1754:41:1754:42 | Chi: call to CopyConstructorTestVirtualClass | Instruction 'Chi: call to CopyConstructorTestVirtualClass' has no successors in function '$@'. | ir.cpp:1750:5:1750:34 | int implicit_copy_constructor_test(CopyConstructorTestNonVirtualClass const&, CopyConstructorTestVirtualClass const&) | int implicit_copy_constructor_test(CopyConstructorTestNonVirtualClass const&, CopyConstructorTestVirtualClass const&) |
| ir.cpp:1903:9:1903:20 | Chi: call to noreturnFunc | Instruction 'Chi: call to noreturnFunc' has no successors in function '$@'. | ir.cpp:1899:5:1899:16 | int noreturnTest(int) | int noreturnTest(int) |
ambiguousSuccessors
unexplainedLoop
unnecessaryPhiInstruction

View File

@@ -6,8 +6,6 @@ missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary
instructionWithoutSuccessor
| ir.cpp:1754:41:1754:42 | Chi: call to CopyConstructorTestVirtualClass | Instruction 'Chi: call to CopyConstructorTestVirtualClass' has no successors in function '$@'. | ir.cpp:1750:5:1750:34 | int implicit_copy_constructor_test(CopyConstructorTestNonVirtualClass const&, CopyConstructorTestVirtualClass const&) | int implicit_copy_constructor_test(CopyConstructorTestNonVirtualClass const&, CopyConstructorTestVirtualClass const&) |
| ir.cpp:1903:9:1903:20 | Chi: call to noreturnFunc | Instruction 'Chi: call to noreturnFunc' has no successors in function '$@'. | ir.cpp:1899:5:1899:16 | int noreturnTest(int) | int noreturnTest(int) |
ambiguousSuccessors
unexplainedLoop
unnecessaryPhiInstruction

View File

@@ -1904,4 +1904,11 @@ int noreturnTest(int x) {
}
}
int noreturnTest2(int x) {
if (x < 10) {
noreturnFunc();
}
return x;
}
// semmle-extractor-options: -std=c++17 --clang

View File

@@ -8802,6 +8802,25 @@
| ir.cpp:1903:9:1903:20 | ChiPartial | partial:m1903_3 |
| ir.cpp:1903:9:1903:20 | ChiTotal | total:m1899_4 |
| ir.cpp:1903:9:1903:20 | SideEffect | ~m1899_4 |
| ir.cpp:1907:5:1907:17 | Address | &:r1907_8 |
| ir.cpp:1907:5:1907:17 | ChiPartial | partial:m1907_3 |
| ir.cpp:1907:5:1907:17 | ChiTotal | total:m1907_2 |
| ir.cpp:1907:5:1907:17 | Load | m1911_4 |
| ir.cpp:1907:5:1907:17 | SideEffect | m1907_3 |
| ir.cpp:1907:23:1907:23 | Address | &:r1907_5 |
| ir.cpp:1908:9:1908:9 | Address | &:r1908_1 |
| ir.cpp:1908:9:1908:9 | Left | r1908_2 |
| ir.cpp:1908:9:1908:9 | Load | m1907_6 |
| ir.cpp:1908:9:1908:14 | Condition | r1908_4 |
| ir.cpp:1908:13:1908:14 | Right | r1908_3 |
| ir.cpp:1909:9:1909:20 | CallTarget | func:r1909_1 |
| ir.cpp:1909:9:1909:20 | ChiPartial | partial:m1909_3 |
| ir.cpp:1909:9:1909:20 | ChiTotal | total:m1907_4 |
| ir.cpp:1909:9:1909:20 | SideEffect | ~m1907_4 |
| ir.cpp:1911:5:1911:13 | Address | &:r1911_1 |
| ir.cpp:1911:12:1911:12 | Address | &:r1911_2 |
| ir.cpp:1911:12:1911:12 | Load | m1907_6 |
| ir.cpp:1911:12:1911:12 | StoreValue | r1911_3 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_5 |
| perf-regression.cpp:6:3:6:5 | Address | &:r6_7 |

View File

@@ -10136,6 +10136,37 @@ ir.cpp:
# 1903| mu1903_3(unknown) = ^CallSideEffect : ~m?
# 1905| v1905_1(void) = Unreached :
# 1907| int noreturnTest2(int)
# 1907| Block 0
# 1907| v1907_1(void) = EnterFunction :
# 1907| mu1907_2(unknown) = AliasedDefinition :
# 1907| mu1907_3(unknown) = InitializeNonLocal :
# 1907| r1907_4(glval<int>) = VariableAddress[x] :
# 1907| mu1907_5(int) = InitializeParameter[x] : &:r1907_4
# 1908| r1908_1(glval<int>) = VariableAddress[x] :
# 1908| r1908_2(int) = Load[x] : &:r1908_1, ~m?
# 1908| r1908_3(int) = Constant[10] :
# 1908| r1908_4(bool) = CompareLT : r1908_2, r1908_3
# 1908| v1908_5(void) = ConditionalBranch : r1908_4
#-----| False -> Block 2
#-----| True -> Block 1
# 1909| Block 1
# 1909| r1909_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
# 1909| v1909_2(void) = Call[noreturnFunc] : func:r1909_1
# 1909| mu1909_3(unknown) = ^CallSideEffect : ~m?
# 1907| v1907_6(void) = Unreached :
# 1911| Block 2
# 1911| r1911_1(glval<int>) = VariableAddress[#return] :
# 1911| r1911_2(glval<int>) = VariableAddress[x] :
# 1911| r1911_3(int) = Load[x] : &:r1911_2, ~m?
# 1911| mu1911_4(int) = Store[#return] : &:r1911_1, r1911_3
# 1907| r1907_7(glval<int>) = VariableAddress[#return] :
# 1907| v1907_8(void) = ReturnValue : &:r1907_7, ~m?
# 1907| v1907_9(void) = AliasedUse : ~m?
# 1907| v1907_10(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0

View File

@@ -6,7 +6,6 @@ missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary
instructionWithoutSuccessor
| ssa.cpp:427:9:427:20 | Chi: call to noreturnFunc | Instruction 'Chi: call to noreturnFunc' has no successors in function '$@'. | ssa.cpp:423:5:423:16 | int noreturnTest(int) | int noreturnTest(int) |
ambiguousSuccessors
unexplainedLoop
unnecessaryPhiInstruction

View File

@@ -6,7 +6,6 @@ missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary
instructionWithoutSuccessor
| ssa.cpp:427:9:427:20 | Chi: call to noreturnFunc | Instruction 'Chi: call to noreturnFunc' has no successors in function '$@'. | ssa.cpp:423:5:423:16 | int noreturnTest(int) | int noreturnTest(int) |
ambiguousSuccessors
unexplainedLoop
unnecessaryPhiInstruction

View File

@@ -2123,6 +2123,37 @@ ssa.cpp:
# 427| v427_2(void) = Call[noreturnFunc] : func:r427_1
# 427| m427_3(unknown) = ^CallSideEffect : ~m423_4
# 427| m427_4(unknown) = Chi : total:m423_4, partial:m427_3
# 423| v423_11(void) = Unreached :
# 423| Block 3
# 423| v423_11(void) = Unreached :
# 431| int noreturnTest2(int)
# 431| Block 0
# 431| v431_1(void) = EnterFunction :
# 431| m431_2(unknown) = AliasedDefinition :
# 431| m431_3(unknown) = InitializeNonLocal :
# 431| m431_4(unknown) = Chi : total:m431_2, partial:m431_3
# 431| r431_5(glval<int>) = VariableAddress[x] :
# 431| m431_6(int) = InitializeParameter[x] : &:r431_5
# 432| r432_1(glval<int>) = VariableAddress[x] :
# 432| r432_2(int) = Load[x] : &:r432_1, m431_6
# 432| r432_3(int) = Constant[10] :
# 432| r432_4(bool) = CompareLT : r432_2, r432_3
# 432| v432_5(void) = ConditionalBranch : r432_4
#-----| False -> Block 2
#-----| True -> Block 1
# 433| Block 1
# 433| r433_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
# 433| v433_2(void) = Call[noreturnFunc] : func:r433_1
# 433| m433_3(unknown) = ^CallSideEffect : ~m431_4
# 433| m433_4(unknown) = Chi : total:m431_4, partial:m433_3
# 431| v431_7(void) = Unreached :
# 435| Block 2
# 435| r435_1(glval<int>) = VariableAddress[#return] :
# 435| r435_2(glval<int>) = VariableAddress[x] :
# 435| r435_3(int) = Load[x] : &:r435_2, m431_6
# 435| m435_4(int) = Store[#return] : &:r435_1, r435_3
# 431| r431_8(glval<int>) = VariableAddress[#return] :
# 431| v431_9(void) = ReturnValue : &:r431_8, m435_4
# 431| v431_10(void) = AliasedUse : m431_3
# 431| v431_11(void) = ExitFunction :

View File

@@ -2112,6 +2112,37 @@ ssa.cpp:
# 427| v427_2(void) = Call[noreturnFunc] : func:r427_1
# 427| m427_3(unknown) = ^CallSideEffect : ~m423_4
# 427| m427_4(unknown) = Chi : total:m423_4, partial:m427_3
# 423| v423_11(void) = Unreached :
# 423| Block 3
# 423| v423_11(void) = Unreached :
# 431| int noreturnTest2(int)
# 431| Block 0
# 431| v431_1(void) = EnterFunction :
# 431| m431_2(unknown) = AliasedDefinition :
# 431| m431_3(unknown) = InitializeNonLocal :
# 431| m431_4(unknown) = Chi : total:m431_2, partial:m431_3
# 431| r431_5(glval<int>) = VariableAddress[x] :
# 431| m431_6(int) = InitializeParameter[x] : &:r431_5
# 432| r432_1(glval<int>) = VariableAddress[x] :
# 432| r432_2(int) = Load[x] : &:r432_1, m431_6
# 432| r432_3(int) = Constant[10] :
# 432| r432_4(bool) = CompareLT : r432_2, r432_3
# 432| v432_5(void) = ConditionalBranch : r432_4
#-----| False -> Block 2
#-----| True -> Block 1
# 433| Block 1
# 433| r433_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
# 433| v433_2(void) = Call[noreturnFunc] : func:r433_1
# 433| m433_3(unknown) = ^CallSideEffect : ~m431_4
# 433| m433_4(unknown) = Chi : total:m431_4, partial:m433_3
# 431| v431_7(void) = Unreached :
# 435| Block 2
# 435| r435_1(glval<int>) = VariableAddress[#return] :
# 435| r435_2(glval<int>) = VariableAddress[x] :
# 435| r435_3(int) = Load[x] : &:r435_2, m431_6
# 435| m435_4(int) = Store[#return] : &:r435_1, r435_3
# 431| r431_8(glval<int>) = VariableAddress[#return] :
# 431| v431_9(void) = ReturnValue : &:r431_8, m435_4
# 431| v431_10(void) = AliasedUse : m431_3
# 431| v431_11(void) = ExitFunction :

View File

@@ -427,3 +427,10 @@ int noreturnTest(int x) {
noreturnFunc();
}
}
int noreturnTest2(int x) {
if (x < 10) {
noreturnFunc();
}
return x;
}

View File

@@ -1971,3 +1971,34 @@ ssa.cpp:
# 427| v427_2(void) = Call[noreturnFunc] : func:r427_1
# 427| mu427_3(unknown) = ^CallSideEffect : ~m?
# 423| v423_10(void) = Unreached :
# 431| int noreturnTest2(int)
# 431| Block 0
# 431| v431_1(void) = EnterFunction :
# 431| mu431_2(unknown) = AliasedDefinition :
# 431| mu431_3(unknown) = InitializeNonLocal :
# 431| r431_4(glval<int>) = VariableAddress[x] :
# 431| m431_5(int) = InitializeParameter[x] : &:r431_4
# 432| r432_1(glval<int>) = VariableAddress[x] :
# 432| r432_2(int) = Load[x] : &:r432_1, m431_5
# 432| r432_3(int) = Constant[10] :
# 432| r432_4(bool) = CompareLT : r432_2, r432_3
# 432| v432_5(void) = ConditionalBranch : r432_4
#-----| False -> Block 2
#-----| True -> Block 1
# 433| Block 1
# 433| r433_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
# 433| v433_2(void) = Call[noreturnFunc] : func:r433_1
# 433| mu433_3(unknown) = ^CallSideEffect : ~m?
# 431| v431_6(void) = Unreached :
# 435| Block 2
# 435| r435_1(glval<int>) = VariableAddress[#return] :
# 435| r435_2(glval<int>) = VariableAddress[x] :
# 435| r435_3(int) = Load[x] : &:r435_2, m431_5
# 435| m435_4(int) = Store[#return] : &:r435_1, r435_3
# 431| r431_7(glval<int>) = VariableAddress[#return] :
# 431| v431_8(void) = ReturnValue : &:r431_7, m435_4
# 431| v431_9(void) = AliasedUse : ~m?
# 431| v431_10(void) = ExitFunction :

View File

@@ -1971,3 +1971,34 @@ ssa.cpp:
# 427| v427_2(void) = Call[noreturnFunc] : func:r427_1
# 427| mu427_3(unknown) = ^CallSideEffect : ~m?
# 423| v423_10(void) = Unreached :
# 431| int noreturnTest2(int)
# 431| Block 0
# 431| v431_1(void) = EnterFunction :
# 431| mu431_2(unknown) = AliasedDefinition :
# 431| mu431_3(unknown) = InitializeNonLocal :
# 431| r431_4(glval<int>) = VariableAddress[x] :
# 431| m431_5(int) = InitializeParameter[x] : &:r431_4
# 432| r432_1(glval<int>) = VariableAddress[x] :
# 432| r432_2(int) = Load[x] : &:r432_1, m431_5
# 432| r432_3(int) = Constant[10] :
# 432| r432_4(bool) = CompareLT : r432_2, r432_3
# 432| v432_5(void) = ConditionalBranch : r432_4
#-----| False -> Block 2
#-----| True -> Block 1
# 433| Block 1
# 433| r433_1(glval<unknown>) = FunctionAddress[noreturnFunc] :
# 433| v433_2(void) = Call[noreturnFunc] : func:r433_1
# 433| mu433_3(unknown) = ^CallSideEffect : ~m?
# 431| v431_6(void) = Unreached :
# 435| Block 2
# 435| r435_1(glval<int>) = VariableAddress[#return] :
# 435| r435_2(glval<int>) = VariableAddress[x] :
# 435| r435_3(int) = Load[x] : &:r435_2, m431_5
# 435| m435_4(int) = Store[#return] : &:r435_1, r435_3
# 431| r431_7(glval<int>) = VariableAddress[#return] :
# 431| v431_8(void) = ReturnValue : &:r431_7, m435_4
# 431| v431_9(void) = AliasedUse : ~m?
# 431| v431_10(void) = ExitFunction :