C++/C#: Make escape analysis unsound by default

When building SSA, we'll be assuming that stack variables do not escape, at least until we improve our alias analysis. I've added a new `IREscapeAnalysisConfiguration` class to allow the query to control this, and a new `UseSoundEscapeAnalysis.qll` module that can be imported to switch to the sound escape analysis. I've cloned the existing IR and SSA tests to have both sound and unsound versions. There were relatively few diffs in the IR dump tests, and the sanity tests still give the same results after one change described below.

Assuming that stack variables do not escape exposed an existing bug where we do not emit an `Uninitialized` instruction for the temporary variables used by `return` statements and `throw` expressions, even if the initializer is a constructor call or array initializer. I've refactored the code for handling elements that initialize a variable to share a common base class. I added a test case for returning an object initialized by constructor call, and ensured that the IR diffs for the existing `throw` test cases are correct.
This commit is contained in:
Dave Bartolomeo
2020-01-22 00:15:30 -07:00
parent 80997a3323
commit 9d35ff73c4
53 changed files with 14654 additions and 171 deletions

View File

@@ -1,3 +1,7 @@
/**
* Module used to configure the IR generation process.
*/
private import internal.IRConfigurationInternal
private newtype TIRConfiguration = MkIRConfiguration()
@@ -13,3 +17,18 @@ class IRConfiguration extends TIRConfiguration {
*/
predicate shouldCreateIRForFunction(Language::Function func) { any() }
}
private newtype TIREscapeAnalysisConfiguration = MkIREscapeAnalysisConfiguration()
/**
* The query can extend this class to control what escape analysis is used when generating SSA.
*/
class IREscapeAnalysisConfiguration extends TIREscapeAnalysisConfiguration {
string toString() { result = "IREscapeAnalysisConfiguration" }
/**
* Holds if the escape analysis done by SSA construction should be sound. By default, the SSA is
* built assuming that no variable's address ever escapes.
*/
predicate useSoundEscapeAnalysis() { none() }
}

View File

@@ -0,0 +1,9 @@
import IRConfiguration
/**
* Overrides the default IR configuration to use sound escape analysis, instead of assuming that
* variable addresses never escape.
*/
class SoundEscapeAnalysisConfiguration extends IREscapeAnalysisConfiguration {
override predicate useSoundEscapeAnalysis() { any() }
}

View File

@@ -2,6 +2,7 @@ private import AliasAnalysisInternal
private import cpp
private import InputIR
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
private import semmle.code.cpp.ir.implementation.IRConfiguration
private import semmle.code.cpp.models.interfaces.Alias
private class IntValue = Ints::IntValue;
@@ -277,9 +278,16 @@ private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) {
* analysis.
*/
predicate variableAddressEscapes(IRVariable var) {
automaticVariableAddressEscapes(var.(IRAutomaticVariable))
exists(IREscapeAnalysisConfiguration config |
config.useSoundEscapeAnalysis() and
(
automaticVariableAddressEscapes(var.(IRAutomaticVariable))
)
)
or
// All variables with static storage duration have their address escape.
// All variables with static storage duration have their address escape, even when escape analysis
// is allowed to be unsound. Otherwise, we won't have a definition for any non-escaped global
// variable. Normally, we rely on `AliasedDefinition` to handle that.
not var instanceof IRAutomaticVariable
}

View File

@@ -107,7 +107,7 @@ class PropertyProvider extends IRPropertyProvider {
exists(
MemoryLocation useLocation, IRBlock predBlock, IRBlock defBlock, int defIndex, Overlap overlap
|
hasPhiOperandDefinition(_, useLocation, block, predBlock, defBlock, defIndex, overlap) and
hasPhiOperandDefinition(_, useLocation, block, predBlock, defBlock, defIndex) and
key = "PhiUse[" + useLocation.toString() + " from " + predBlock.getDisplayIndex().toString() +
"]" and
result = defBlock.getDisplayIndex().toString() + "_" + defIndex + " (" + overlap.toString() +

View File

@@ -43,93 +43,34 @@ abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslated
* Represents the IR translation of the declaration of a local variable,
* including its initialization, if any.
*/
abstract class TranslatedVariableDeclaration extends TranslatedElement, InitializationContext {
abstract class TranslatedLocalVariableDeclaration extends TranslatedVariableInitialization {
/**
* Gets the local variable being declared.
*/
abstract LocalVariable getVariable();
override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
final override Type getTargetType() { result = getVariableType(getVariable()) }
override Instruction getFirstInstruction() {
result = getInstruction(InitializerVariableAddressTag())
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = InitializerVariableAddressTag() and
opcode instanceof Opcode::VariableAddress and
resultType = getTypeForGLValue(getVariableType(getVariable()))
or
hasUninitializedInstruction() and
tag = InitializerStoreTag() and
opcode instanceof Opcode::Uninitialized and
resultType = getTypeForPRValue(getVariableType(getVariable()))
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
(
tag = InitializerVariableAddressTag() and
kind instanceof GotoEdge and
if hasUninitializedInstruction()
then result = getInstruction(InitializerStoreTag())
else result = getInitialization().getFirstInstruction()
)
or
hasUninitializedInstruction() and
kind instanceof GotoEdge and
tag = InitializerStoreTag() and
(
result = getInitialization().getFirstInstruction()
or
not exists(getInitialization()) and result = getParent().getChildSuccessor(this)
)
}
override Instruction getChildSuccessor(TranslatedElement child) {
child = getInitialization() and result = getParent().getChildSuccessor(this)
}
override IRVariable getInstructionVariable(InstructionTag tag) {
(
tag = InitializerVariableAddressTag()
or
hasUninitializedInstruction() and tag = InitializerStoreTag()
) and
result = getIRUserVariable(getFunction(), getVariable())
}
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
hasUninitializedInstruction() and
tag = InitializerStoreTag() and
operandTag instanceof AddressOperandTag and
result = getInstruction(InitializerVariableAddressTag())
}
override Instruction getTargetAddress() {
result = getInstruction(InitializerVariableAddressTag())
}
override Type getTargetType() { result = getVariableType(getVariable()) }
private TranslatedInitialization getInitialization() {
final override TranslatedInitialization getInitialization() {
result = getTranslatedInitialization(getVariable()
.getInitializer()
.getExpr()
.getFullyConverted())
}
private predicate hasUninitializedInstruction() {
not exists(getInitialization()) or
getInitialization() instanceof TranslatedListInitialization or
getInitialization() instanceof TranslatedConstructorInitialization or
getInitialization().(TranslatedStringLiteralInitialization).zeroInitRange(_, _)
final override Instruction getInitializationSuccessor() {
result = getParent().getChildSuccessor(this)
}
final override IRVariable getIRVariable() {
result = getIRUserVariable(getFunction(), getVariable())
}
}
/**
* Represents the IR translation of a local variable declaration within a declaration statement.
*/
class TranslatedVariableDeclarationEntry extends TranslatedVariableDeclaration,
class TranslatedVariableDeclarationEntry extends TranslatedLocalVariableDeclaration,
TranslatedDeclarationEntry {
LocalVariable var;
@@ -151,7 +92,7 @@ TranslatedRangeBasedForVariableDeclaration getTranslatedRangeBasedForVariableDec
/**
* Represents the IR translation of a compiler-generated variable in a range-based `for` loop.
*/
class TranslatedRangeBasedForVariableDeclaration extends TranslatedVariableDeclaration,
class TranslatedRangeBasedForVariableDeclaration extends TranslatedLocalVariableDeclaration,
TTranslatedRangeBasedForVariableDeclaration {
RangeBasedForStmt forStmt;
LocalVariable var;
@@ -181,7 +122,7 @@ TranslatedConditionDecl getTranslatedConditionDecl(ConditionDeclExpr expr) {
* }
* ```
*/
class TranslatedConditionDecl extends TranslatedVariableDeclaration, TTranslatedConditionDecl {
class TranslatedConditionDecl extends TranslatedLocalVariableDeclaration, TTranslatedConditionDecl {
ConditionDeclExpr conditionDeclExpr;
TranslatedConditionDecl() { this = TTranslatedConditionDecl(conditionDeclExpr) }

View File

@@ -1932,47 +1932,33 @@ abstract class TranslatedThrowExpr extends TranslatedNonConstantExpr {
* IR translation of a `throw` expression with an argument
* (e.g. `throw std::bad_alloc()`).
*/
class TranslatedThrowValueExpr extends TranslatedThrowExpr, InitializationContext {
class TranslatedThrowValueExpr extends TranslatedThrowExpr, TranslatedVariableInitialization {
TranslatedThrowValueExpr() { not expr instanceof ReThrowExpr }
override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
override Instruction getFirstInstruction() {
result = getInstruction(InitializerVariableAddressTag())
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
TranslatedThrowExpr.super.hasInstruction(opcode, tag, resultType)
or
tag = InitializerVariableAddressTag() and
opcode instanceof Opcode::VariableAddress and
resultType = getTypeForGLValue(getExceptionType())
TranslatedVariableInitialization.super.hasInstruction(opcode, tag, resultType)
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
result = TranslatedThrowExpr.super.getInstructionSuccessor(tag, kind)
or
tag = InitializerVariableAddressTag() and
result = getInitialization().getFirstInstruction() and
kind instanceof GotoEdge
result = TranslatedVariableInitialization.super.getInstructionSuccessor(tag, kind)
}
override Instruction getChildSuccessor(TranslatedElement child) {
child = getInitialization() and
final override Instruction getInitializationSuccessor() {
result = getInstruction(ThrowTag())
}
override IRVariable getInstructionVariable(InstructionTag tag) {
tag = InitializerVariableAddressTag() and
result = getIRTempVariable(expr, ThrowTempVar())
}
final override predicate hasTempVariable(TempVariableTag tag, CppType type) {
tag = ThrowTempVar() and
type = getTypeForPRValue(getExceptionType())
}
final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
result = TranslatedVariableInitialization.super.getInstructionOperand(tag, operandTag)
or
tag = ThrowTag() and
(
operandTag instanceof AddressOperandTag and
@@ -1989,16 +1975,16 @@ class TranslatedThrowValueExpr extends TranslatedThrowExpr, InitializationContex
result = getTypeForPRValue(getExceptionType())
}
override Instruction getTargetAddress() {
result = getInstruction(InitializerVariableAddressTag())
}
override Type getTargetType() { result = getExceptionType() }
TranslatedInitialization getInitialization() {
final override TranslatedInitialization getInitialization() {
result = getTranslatedInitialization(expr.getExpr().getFullyConverted())
}
final override IRVariable getIRVariable() {
result = getIRTempVariable(expr, ThrowTempVar())
}
final override Opcode getThrowOpcode() { result instanceof Opcode::ThrowValue }
private Type getExceptionType() { result = expr.getType() }

View File

@@ -30,6 +30,98 @@ abstract class InitializationContext extends TranslatedElement {
abstract Type getTargetType();
}
/**
* Base class for any element that initializes a stack variable. Examples include local variable
* declarations, `return` statements, and `throw` expressions.
*/
abstract class TranslatedVariableInitialization extends TranslatedElement, InitializationContext {
final override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
final override Instruction getFirstInstruction() {
result = getInstruction(InitializerVariableAddressTag())
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = InitializerVariableAddressTag() and
opcode instanceof Opcode::VariableAddress and
resultType = getTypeForGLValue(getTargetType())
or
hasUninitializedInstruction() and
tag = InitializerStoreTag() and
opcode instanceof Opcode::Uninitialized and
resultType = getTypeForPRValue(getTargetType())
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
(
tag = InitializerVariableAddressTag() and
kind instanceof GotoEdge and
if hasUninitializedInstruction()
then result = getInstruction(InitializerStoreTag())
else result = getInitialization().getFirstInstruction()
)
or
hasUninitializedInstruction() and
kind instanceof GotoEdge and
tag = InitializerStoreTag() and
(
result = getInitialization().getFirstInstruction()
or
not exists(getInitialization()) and result = getInitializationSuccessor()
)
}
final override Instruction getChildSuccessor(TranslatedElement child) {
child = getInitialization() and result = getInitializationSuccessor()
}
override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) {
hasUninitializedInstruction() and
tag = InitializerStoreTag() and
operandTag instanceof AddressOperandTag and
result = getInstruction(InitializerVariableAddressTag())
}
final override IRVariable getInstructionVariable(InstructionTag tag) {
(
tag = InitializerVariableAddressTag()
or
hasUninitializedInstruction() and tag = InitializerStoreTag()
) and
result = getIRVariable()
}
final override Instruction getTargetAddress() {
result = getInstruction(InitializerVariableAddressTag())
}
/**
* Get the initialization for the variable.
*/
abstract TranslatedInitialization getInitialization();
/**
* Get the `IRVariable` to be initialized. This may be an `IRTempVariable`.
*/
abstract IRVariable getIRVariable();
/**
* Gets the `Instruction` to be executed immediately after the initialization.
*/
abstract Instruction getInitializationSuccessor();
/**
* Holds if this initialization requires an `Uninitialized` instruction to be emitted before
* evaluating the initializer.
*/
final predicate hasUninitializedInstruction() {
not exists(getInitialization()) or
getInitialization() instanceof TranslatedListInitialization or
getInitialization() instanceof TranslatedConstructorInitialization or
getInitialization().(TranslatedStringLiteralInitialization).zeroInitRange(_, _)
}
}
/**
* Represents the IR translation of any initialization, whether from an
* initializer list or from a direct initializer.

View File

@@ -130,46 +130,22 @@ abstract class TranslatedReturnStmt extends TranslatedStmt {
}
}
class TranslatedReturnValueStmt extends TranslatedReturnStmt, InitializationContext {
class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariableInitialization {
TranslatedReturnValueStmt() { stmt.hasExpr() }
override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
override Instruction getFirstInstruction() {
result = getInstruction(InitializerVariableAddressTag())
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = InitializerVariableAddressTag() and
opcode instanceof Opcode::VariableAddress and
resultType = getTypeForGLValue(getEnclosingFunction().getReturnType())
}
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
tag = InitializerVariableAddressTag() and
result = getInitialization().getFirstInstruction() and
kind instanceof GotoEdge
}
override Instruction getChildSuccessor(TranslatedElement child) {
child = getInitialization() and
final override Instruction getInitializationSuccessor() {
result = getEnclosingFunction().getReturnSuccessorInstruction()
}
override IRVariable getInstructionVariable(InstructionTag tag) {
tag = InitializerVariableAddressTag() and
result = getEnclosingFunction().getReturnVariable()
}
final override Type getTargetType() { result = getEnclosingFunction().getReturnType() }
override Instruction getTargetAddress() {
result = getInstruction(InitializerVariableAddressTag())
}
override Type getTargetType() { result = getEnclosingFunction().getReturnType() }
TranslatedInitialization getInitialization() {
final override TranslatedInitialization getInitialization() {
result = getTranslatedInitialization(stmt.getExpr().getFullyConverted())
}
final override IRVariable getIRVariable() {
result = getEnclosingFunction().getReturnVariable()
}
}
class TranslatedReturnVoidStmt extends TranslatedReturnStmt {

View File

@@ -2,6 +2,7 @@ private import AliasAnalysisInternal
private import cpp
private import InputIR
private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
private import semmle.code.cpp.ir.implementation.IRConfiguration
private import semmle.code.cpp.models.interfaces.Alias
private class IntValue = Ints::IntValue;
@@ -277,9 +278,16 @@ private predicate automaticVariableAddressEscapes(IRAutomaticVariable var) {
* analysis.
*/
predicate variableAddressEscapes(IRVariable var) {
automaticVariableAddressEscapes(var.(IRAutomaticVariable))
exists(IREscapeAnalysisConfiguration config |
config.useSoundEscapeAnalysis() and
(
automaticVariableAddressEscapes(var.(IRAutomaticVariable))
)
)
or
// All variables with static storage duration have their address escape.
// All variables with static storage duration have their address escape, even when escape analysis
// is allowed to be unsound. Otherwise, we won't have a definition for any non-escaped global
// variable. Normally, we rely on `AliasedDefinition` to handle that.
not var instanceof IRAutomaticVariable
}

View File

@@ -107,7 +107,7 @@ class PropertyProvider extends IRPropertyProvider {
exists(
MemoryLocation useLocation, IRBlock predBlock, IRBlock defBlock, int defIndex, Overlap overlap
|
hasPhiOperandDefinition(_, useLocation, block, predBlock, defBlock, defIndex, overlap) and
hasPhiOperandDefinition(_, useLocation, block, predBlock, defBlock, defIndex) and
key = "PhiUse[" + useLocation.toString() + " from " + predBlock.getDisplayIndex().toString() +
"]" and
result = defBlock.getDisplayIndex().toString() + "_" + defIndex + " (" + overlap.toString() +

View File

@@ -1,6 +1,7 @@
import default
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.AliasAnalysis
import semmle.code.cpp.ir.implementation.raw.IR
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis
predicate shouldEscape(IRAutomaticUserVariable var) {
exists(string name |

View File

@@ -1,6 +1,7 @@
import default
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.AliasAnalysis
import semmle.code.cpp.ir.implementation.unaliased_ssa.IR
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis
predicate shouldEscape(IRAutomaticUserVariable var) {
exists(string name |

View File

@@ -8056,6 +8056,20 @@ ir.cpp:
# 1166| 0: [VariableAccess] y
# 1166| Type = [IntType] int
# 1166| ValueCategory = prvalue(load)
# 1169| [TopLevelFunction] String ReturnObjectImpl()
# 1169| params:
# 1169| body: [Block] { ... }
# 1170| 0: [ReturnStmt] return ...
# 1170| 0: [ConstructorCall] call to String
# 1170| Type = [Struct] String
# 1170| ValueCategory = prvalue
# 1170| 0: [ArrayToPointerConversion] array to pointer conversion
# 1170| Type = [PointerType] const char *
# 1170| ValueCategory = prvalue
# 1170| expr: foo
# 1170| Type = [ArrayType] const char[4]
# 1170| Value = [StringLiteral] "foo"
# 1170| ValueCategory = lvalue
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| params:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.ql

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.IRSanity
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -0,0 +1,26 @@
missingOperand
| ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
| ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
unexpectedOperand
duplicateOperand
missingPhiOperand
missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary
instructionWithoutSuccessor
ambiguousSuccessors
unexplainedLoop
unnecessaryPhiInstruction
operandAcrossFunctions
instructionWithoutUniqueBlock
containsLoopOfForwardEdges
lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSASanity
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -0,0 +1,2 @@
multipleOperandMemoryLocations
missingVirtualVariableForMemoryLocation

View File

@@ -1166,4 +1166,8 @@ int ModeledCallTarget(int x) {
return y;
}
String ReturnObjectImpl() {
return String("foo");
}
// semmle-extractor-options: -std=c++17 --clang

View File

@@ -3371,15 +3371,16 @@ ir.cpp:
# 731| Block 7
# 731| r731_11(glval<String>) = VariableAddress[#throw731:19] :
# 731| r731_12(glval<unknown>) = FunctionAddress[String] :
# 731| r731_13(glval<char[14]>) = StringConstant["String object"] :
# 731| r731_14(char *) = Convert : r731_13
# 731| v731_15(void) = Call : func:r731_12, this:r731_11, 0:r731_14
# 731| mu731_16(unknown) = ^CallSideEffect : ~mu724_3
# 731| mu731_17(String) = ^IndirectMayWriteSideEffect[-1] : &:r731_11
# 731| v731_18(void) = ^BufferReadSideEffect[0] : &:r731_14, ~mu724_3
# 731| mu731_19(unknown) = ^BufferMayWriteSideEffect[0] : &:r731_14
# 731| v731_20(void) = ThrowValue : &:r731_11, ~mu724_3
# 731| mu731_12(String) = Uninitialized[#throw731:19] : &:r731_11
# 731| r731_13(glval<unknown>) = FunctionAddress[String] :
# 731| r731_14(glval<char[14]>) = StringConstant["String object"] :
# 731| r731_15(char *) = Convert : r731_14
# 731| v731_16(void) = Call : func:r731_13, this:r731_11, 0:r731_15
# 731| mu731_17(unknown) = ^CallSideEffect : ~mu724_3
# 731| mu731_18(String) = ^IndirectMayWriteSideEffect[-1] : &:r731_11
# 731| v731_19(void) = ^BufferReadSideEffect[0] : &:r731_15, ~mu724_3
# 731| mu731_20(unknown) = ^BufferMayWriteSideEffect[0] : &:r731_15
# 731| v731_21(void) = ThrowValue : &:r731_11, ~mu724_3
#-----| Exception -> Block 9
# 733| Block 8
@@ -3399,15 +3400,16 @@ ir.cpp:
# 735| r735_4(char *) = Load : &:r735_2, ~mu735_3
# 735| mu735_5(unknown) = InitializeIndirection[s] : &:r735_4
# 736| r736_1(glval<String>) = VariableAddress[#throw736:5] :
# 736| r736_2(glval<unknown>) = FunctionAddress[String] :
# 736| r736_3(glval<char *>) = VariableAddress[s] :
# 736| r736_4(char *) = Load : &:r736_3, ~mu724_3
# 736| v736_5(void) = Call : func:r736_2, this:r736_1, 0:r736_4
# 736| mu736_6(unknown) = ^CallSideEffect : ~mu724_3
# 736| mu736_7(String) = ^IndirectMayWriteSideEffect[-1] : &:r736_1
# 736| v736_8(void) = ^BufferReadSideEffect[0] : &:r736_4, ~mu724_3
# 736| mu736_9(unknown) = ^BufferMayWriteSideEffect[0] : &:r736_4
# 736| v736_10(void) = ThrowValue : &:r736_1, ~mu724_3
# 736| mu736_2(String) = Uninitialized[#throw736:5] : &:r736_1
# 736| r736_3(glval<unknown>) = FunctionAddress[String] :
# 736| r736_4(glval<char *>) = VariableAddress[s] :
# 736| r736_5(char *) = Load : &:r736_4, ~mu724_3
# 736| v736_6(void) = Call : func:r736_3, this:r736_1, 0:r736_5
# 736| mu736_7(unknown) = ^CallSideEffect : ~mu724_3
# 736| mu736_8(String) = ^IndirectMayWriteSideEffect[-1] : &:r736_1
# 736| v736_9(void) = ^BufferReadSideEffect[0] : &:r736_5, ~mu724_3
# 736| mu736_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r736_5
# 736| v736_11(void) = ThrowValue : &:r736_1, ~mu724_3
#-----| Exception -> Block 2
# 738| Block 11
@@ -5728,15 +5730,16 @@ ir.cpp:
# 1140| Block 7
# 1140| r1140_11(glval<String>) = VariableAddress[#throw1140:19] :
# 1140| r1140_12(glval<unknown>) = FunctionAddress[String] :
# 1140| r1140_13(glval<char[14]>) = StringConstant["String object"] :
# 1140| r1140_14(char *) = Convert : r1140_13
# 1140| v1140_15(void) = Call : func:r1140_12, this:r1140_11, 0:r1140_14
# 1140| mu1140_16(unknown) = ^CallSideEffect : ~mu1133_3
# 1140| mu1140_17(String) = ^IndirectMayWriteSideEffect[-1] : &:r1140_11
# 1140| v1140_18(void) = ^BufferReadSideEffect[0] : &:r1140_14, ~mu1133_3
# 1140| mu1140_19(unknown) = ^BufferMayWriteSideEffect[0] : &:r1140_14
# 1140| v1140_20(void) = ThrowValue : &:r1140_11, ~mu1133_3
# 1140| mu1140_12(String) = Uninitialized[#throw1140:19] : &:r1140_11
# 1140| r1140_13(glval<unknown>) = FunctionAddress[String] :
# 1140| r1140_14(glval<char[14]>) = StringConstant["String object"] :
# 1140| r1140_15(char *) = Convert : r1140_14
# 1140| v1140_16(void) = Call : func:r1140_13, this:r1140_11, 0:r1140_15
# 1140| mu1140_17(unknown) = ^CallSideEffect : ~mu1133_3
# 1140| mu1140_18(String) = ^IndirectMayWriteSideEffect[-1] : &:r1140_11
# 1140| v1140_19(void) = ^BufferReadSideEffect[0] : &:r1140_15, ~mu1133_3
# 1140| mu1140_20(unknown) = ^BufferMayWriteSideEffect[0] : &:r1140_15
# 1140| v1140_21(void) = ThrowValue : &:r1140_11, ~mu1133_3
#-----| Exception -> Block 9
# 1142| Block 8
@@ -5756,15 +5759,16 @@ ir.cpp:
# 1144| r1144_4(char *) = Load : &:r1144_2, ~mu1144_3
# 1144| mu1144_5(unknown) = InitializeIndirection[s] : &:r1144_4
# 1145| r1145_1(glval<String>) = VariableAddress[#throw1145:5] :
# 1145| r1145_2(glval<unknown>) = FunctionAddress[String] :
# 1145| r1145_3(glval<char *>) = VariableAddress[s] :
# 1145| r1145_4(char *) = Load : &:r1145_3, ~mu1133_3
# 1145| v1145_5(void) = Call : func:r1145_2, this:r1145_1, 0:r1145_4
# 1145| mu1145_6(unknown) = ^CallSideEffect : ~mu1133_3
# 1145| mu1145_7(String) = ^IndirectMayWriteSideEffect[-1] : &:r1145_1
# 1145| v1145_8(void) = ^BufferReadSideEffect[0] : &:r1145_4, ~mu1133_3
# 1145| mu1145_9(unknown) = ^BufferMayWriteSideEffect[0] : &:r1145_4
# 1145| v1145_10(void) = ThrowValue : &:r1145_1, ~mu1133_3
# 1145| mu1145_2(String) = Uninitialized[#throw1145:5] : &:r1145_1
# 1145| r1145_3(glval<unknown>) = FunctionAddress[String] :
# 1145| r1145_4(glval<char *>) = VariableAddress[s] :
# 1145| r1145_5(char *) = Load : &:r1145_4, ~mu1133_3
# 1145| v1145_6(void) = Call : func:r1145_3, this:r1145_1, 0:r1145_5
# 1145| mu1145_7(unknown) = ^CallSideEffect : ~mu1133_3
# 1145| mu1145_8(String) = ^IndirectMayWriteSideEffect[-1] : &:r1145_1
# 1145| v1145_9(void) = ^BufferReadSideEffect[0] : &:r1145_5, ~mu1133_3
# 1145| mu1145_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r1145_5
# 1145| v1145_11(void) = ThrowValue : &:r1145_1, ~mu1133_3
#-----| Exception -> Block 2
# 1147| Block 11
@@ -5878,6 +5882,27 @@ ir.cpp:
# 1163| v1163_9(void) = AliasedUse : ~mu1163_3
# 1163| v1163_10(void) = ExitFunction :
# 1169| String ReturnObjectImpl()
# 1169| Block 0
# 1169| v1169_1(void) = EnterFunction :
# 1169| mu1169_2(unknown) = AliasedDefinition :
# 1169| mu1169_3(unknown) = UnmodeledDefinition :
# 1170| r1170_1(glval<String>) = VariableAddress[#return] :
# 1170| mu1170_2(String) = Uninitialized[#return] : &:r1170_1
# 1170| r1170_3(glval<unknown>) = FunctionAddress[String] :
# 1170| r1170_4(glval<char[4]>) = StringConstant["foo"] :
# 1170| r1170_5(char *) = Convert : r1170_4
# 1170| r1170_6(String) = Call : func:r1170_3, this:r1170_1, 0:r1170_5
# 1170| mu1170_7(unknown) = ^CallSideEffect : ~mu1169_3
# 1170| mu1170_8(String) = ^IndirectMayWriteSideEffect[-1] : &:r1170_1
# 1170| v1170_9(void) = ^BufferReadSideEffect[0] : &:r1170_5, ~mu1169_3
# 1170| mu1170_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r1170_5
# 1169| r1169_4(glval<String>) = VariableAddress[#return] :
# 1169| v1169_5(void) = ReturnValue : &:r1169_4, ~mu1169_3
# 1169| v1169_6(void) = UnmodeledUse : mu*
# 1169| v1169_7(void) = AliasedUse : ~mu1169_3
# 1169| v1169_8(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.unaliased_ssa.IRSanity
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -0,0 +1,26 @@
missingOperand
| ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
| ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() |
unexpectedOperand
duplicateOperand
missingPhiOperand
missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary
instructionWithoutSuccessor
ambiguousSuccessors
unexplainedLoop
unnecessaryPhiInstruction
operandAcrossFunctions
instructionWithoutUniqueBlock
containsLoopOfForwardEdges
lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSASanity
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -0,0 +1,2 @@
multipleOperandMemoryLocations
missingVirtualVariableForMemoryLocation

View File

@@ -0,0 +1,6 @@
/**
* @kind graph
*/
import semmle.code.cpp.ir.implementation.aliased_ssa.PrintIR
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.IRSanity
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -0,0 +1,22 @@
missingOperand
unexpectedOperand
duplicateOperand
missingPhiOperand
missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary
instructionWithoutSuccessor
ambiguousSuccessors
unexplainedLoop
unnecessaryPhiInstruction
operandAcrossFunctions
instructionWithoutUniqueBlock
containsLoopOfForwardEdges
lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSASanity
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -0,0 +1,2 @@
multipleOperandMemoryLocations
missingVirtualVariableForMemoryLocation

View File

@@ -0,0 +1,6 @@
/**
* @kind graph
*/
import semmle.code.cpp.ir.implementation.unaliased_ssa.PrintIR
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.ql

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.unaliased_ssa.IRSanity
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -0,0 +1,22 @@
missingOperand
unexpectedOperand
duplicateOperand
missingPhiOperand
missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary
instructionWithoutSuccessor
ambiguousSuccessors
unexplainedLoop
unnecessaryPhiInstruction
operandAcrossFunctions
instructionWithoutUniqueBlock
containsLoopOfForwardEdges
lostReachability
backEdgeCountMismatch
useNotDominatedByDefinition
missingCanonicalLanguageType
multipleCanonicalLanguageTypes
missingIRType
multipleIRTypes
missingCppType

View File

@@ -0,0 +1,2 @@
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSASanity
import semmle.code.cpp.ir.implementation.UseSoundEscapeAnalysis

View File

@@ -0,0 +1,2 @@
multipleOperandMemoryLocations
missingVirtualVariableForMemoryLocation