mirror of
https://github.com/github/codeql.git
synced 2026-05-02 20:25:13 +02:00
Merge branch 'master' of github.com:Semmle/ql into rdmarsh/cpp/ir-constructor-side-effects
This commit is contained in:
@@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable {
|
||||
|
||||
abstract string toString();
|
||||
|
||||
/**
|
||||
* Holds if this variable's value cannot be changed within a function. Currently used for string
|
||||
* literals, but could also apply to `const` global and static variables.
|
||||
*/
|
||||
predicate isReadOnly() { none() }
|
||||
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
@@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable {
|
||||
final override Language::StaticVariable getVariable() { result = var }
|
||||
}
|
||||
|
||||
abstract class IRGeneratedVariable extends IRVariable {
|
||||
Language::AST ast;
|
||||
Language::LanguageType type;
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
|
||||
override string toString() { result = getBaseString() + getLocationString() }
|
||||
|
||||
override string getUniqueId() { none() }
|
||||
|
||||
final string getLocationString() {
|
||||
result = ast.getLocation().getStartLine().toString() + ":" +
|
||||
ast.getLocation().getStartColumn().toString()
|
||||
}
|
||||
|
||||
string getBaseString() { none() }
|
||||
}
|
||||
|
||||
IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
|
||||
result.getAST() = ast and
|
||||
result.getTag() = tag
|
||||
}
|
||||
|
||||
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
|
||||
Language::AST ast;
|
||||
class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
|
||||
TempVariableTag tag;
|
||||
Language::LanguageType type;
|
||||
|
||||
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "Temp: " + Construction::getTempVariableUniqueId(this)
|
||||
}
|
||||
|
||||
final TempVariableTag getTag() { result = tag }
|
||||
|
||||
override string toString() {
|
||||
result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" +
|
||||
ast.getLocation().getStartColumn().toString()
|
||||
}
|
||||
|
||||
string getBaseString() { result = "#temp" }
|
||||
override string getBaseString() { result = "#temp" }
|
||||
}
|
||||
|
||||
class IRReturnVariable extends IRTempVariable {
|
||||
@@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable {
|
||||
|
||||
override string getBaseString() { result = "#throw" }
|
||||
}
|
||||
|
||||
class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
Language::StringLiteral literal;
|
||||
|
||||
IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) }
|
||||
|
||||
final override predicate isReadOnly() { any() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
}
|
||||
|
||||
override string getBaseString() { result = "#string" }
|
||||
|
||||
final Language::StringLiteral getLiteral() { result = literal }
|
||||
}
|
||||
|
||||
@@ -818,14 +818,12 @@ class FloatConstantInstruction extends ConstantInstruction {
|
||||
FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType }
|
||||
}
|
||||
|
||||
class StringConstantInstruction extends Instruction {
|
||||
Language::StringLiteral value;
|
||||
class StringConstantInstruction extends VariableInstruction {
|
||||
override IRStringLiteral var;
|
||||
|
||||
StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) }
|
||||
final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) }
|
||||
|
||||
final override string getImmediateString() { result = Language::getStringLiteralText(value) }
|
||||
|
||||
final Language::StringLiteral getValue() { result = value }
|
||||
final Language::StringLiteral getValue() { result = var.getLiteral() }
|
||||
}
|
||||
|
||||
class BinaryInstruction extends Instruction {
|
||||
|
||||
@@ -308,6 +308,10 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset)
|
||||
instr.(VariableAddressInstruction).getIRVariable() = var and
|
||||
bitOffset = 0
|
||||
or
|
||||
// A string literal is just a special read-only global variable.
|
||||
instr.(StringConstantInstruction).getIRVariable() = var and
|
||||
bitOffset = 0
|
||||
or
|
||||
exists(Operand operand, IntValue originalBitOffset, IntValue propagatedBitOffset |
|
||||
operand = instr.getAnOperand() and
|
||||
// If an operand is propagated, then the result points to the same variable,
|
||||
|
||||
@@ -210,17 +210,21 @@ Overlap getOverlap(MemoryLocation def, MemoryLocation use) {
|
||||
def instanceof UnknownVirtualVariable and
|
||||
result instanceof MustTotallyOverlap
|
||||
or
|
||||
// An UnknownMemoryLocation may partially overlap any Location within the same virtual variable.
|
||||
// An UnknownMemoryLocation may partially overlap any Location within the same virtual variable,
|
||||
// unless the location is read-only.
|
||||
def.getVirtualVariable() = use.getVirtualVariable() and
|
||||
def instanceof UnknownMemoryLocation and
|
||||
result instanceof MayPartiallyOverlap
|
||||
result instanceof MayPartiallyOverlap and
|
||||
not use.(VariableMemoryLocation).getVariable().isReadOnly()
|
||||
or
|
||||
// An UnknownNonLocalMemoryLocation may partially overlap any location within the same virtual
|
||||
// variable, except a local variable.
|
||||
// variable, except a local variable or read-only variable.
|
||||
def.getVirtualVariable() = use.getVirtualVariable() and
|
||||
def instanceof UnknownNonLocalMemoryLocation and
|
||||
result instanceof MayPartiallyOverlap and
|
||||
not use.(VariableMemoryLocation).getVariable() instanceof IRAutomaticVariable
|
||||
not exists(IRVariable var | var = use.(VariableMemoryLocation).getVariable() |
|
||||
var instanceof IRAutomaticVariable or var.isReadOnly()
|
||||
)
|
||||
or
|
||||
exists(VariableMemoryLocation defVariableLocation |
|
||||
defVariableLocation = def and
|
||||
|
||||
@@ -341,11 +341,6 @@ private module Cached {
|
||||
result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue()
|
||||
}
|
||||
|
||||
cached
|
||||
Language::StringLiteral getInstructionStringLiteral(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue()
|
||||
}
|
||||
|
||||
cached
|
||||
Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) {
|
||||
result = getOldInstruction(instruction)
|
||||
|
||||
@@ -9,4 +9,10 @@ newtype TIRVariable =
|
||||
Language::Function func, Language::AST ast, TempVariableTag tag, Language::LanguageType type
|
||||
) {
|
||||
Construction::hasTempVariable(func, ast, tag, type)
|
||||
} or
|
||||
TIRStringLiteral(
|
||||
Language::Function func, Language::AST ast, Language::LanguageType type,
|
||||
Language::StringLiteral literal
|
||||
) {
|
||||
Construction::hasStringLiteral(func, ast, type, literal)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable {
|
||||
|
||||
abstract string toString();
|
||||
|
||||
/**
|
||||
* Holds if this variable's value cannot be changed within a function. Currently used for string
|
||||
* literals, but could also apply to `const` global and static variables.
|
||||
*/
|
||||
predicate isReadOnly() { none() }
|
||||
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
@@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable {
|
||||
final override Language::StaticVariable getVariable() { result = var }
|
||||
}
|
||||
|
||||
abstract class IRGeneratedVariable extends IRVariable {
|
||||
Language::AST ast;
|
||||
Language::LanguageType type;
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
|
||||
override string toString() { result = getBaseString() + getLocationString() }
|
||||
|
||||
override string getUniqueId() { none() }
|
||||
|
||||
final string getLocationString() {
|
||||
result = ast.getLocation().getStartLine().toString() + ":" +
|
||||
ast.getLocation().getStartColumn().toString()
|
||||
}
|
||||
|
||||
string getBaseString() { none() }
|
||||
}
|
||||
|
||||
IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
|
||||
result.getAST() = ast and
|
||||
result.getTag() = tag
|
||||
}
|
||||
|
||||
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
|
||||
Language::AST ast;
|
||||
class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
|
||||
TempVariableTag tag;
|
||||
Language::LanguageType type;
|
||||
|
||||
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "Temp: " + Construction::getTempVariableUniqueId(this)
|
||||
}
|
||||
|
||||
final TempVariableTag getTag() { result = tag }
|
||||
|
||||
override string toString() {
|
||||
result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" +
|
||||
ast.getLocation().getStartColumn().toString()
|
||||
}
|
||||
|
||||
string getBaseString() { result = "#temp" }
|
||||
override string getBaseString() { result = "#temp" }
|
||||
}
|
||||
|
||||
class IRReturnVariable extends IRTempVariable {
|
||||
@@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable {
|
||||
|
||||
override string getBaseString() { result = "#throw" }
|
||||
}
|
||||
|
||||
class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
Language::StringLiteral literal;
|
||||
|
||||
IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) }
|
||||
|
||||
final override predicate isReadOnly() { any() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
}
|
||||
|
||||
override string getBaseString() { result = "#string" }
|
||||
|
||||
final Language::StringLiteral getLiteral() { result = literal }
|
||||
}
|
||||
|
||||
@@ -818,14 +818,12 @@ class FloatConstantInstruction extends ConstantInstruction {
|
||||
FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType }
|
||||
}
|
||||
|
||||
class StringConstantInstruction extends Instruction {
|
||||
Language::StringLiteral value;
|
||||
class StringConstantInstruction extends VariableInstruction {
|
||||
override IRStringLiteral var;
|
||||
|
||||
StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) }
|
||||
final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) }
|
||||
|
||||
final override string getImmediateString() { result = Language::getStringLiteralText(value) }
|
||||
|
||||
final Language::StringLiteral getValue() { result = value }
|
||||
final Language::StringLiteral getValue() { result = var.getLiteral() }
|
||||
}
|
||||
|
||||
class BinaryInstruction extends Instruction {
|
||||
|
||||
@@ -44,6 +44,13 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasStringLiteral(Function func, Locatable ast, CppType type, StringLiteral literal) {
|
||||
literal = ast and
|
||||
literal.getEnclosingFunction() = func and
|
||||
getTypeForPRValue(literal.getType()) = type
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasModeledMemoryResult(Instruction instruction) { none() }
|
||||
|
||||
@@ -234,8 +241,14 @@ private module Cached {
|
||||
|
||||
cached
|
||||
IRVariable getInstructionVariable(Instruction instruction) {
|
||||
result = getInstructionTranslatedElement(instruction)
|
||||
.getInstructionVariable(getInstructionTag(instruction))
|
||||
exists(TranslatedElement element, InstructionTag tag |
|
||||
element = getInstructionTranslatedElement(instruction) and
|
||||
tag = getInstructionTag(instruction) and
|
||||
(
|
||||
result = element.getInstructionVariable(tag) or
|
||||
result.(IRStringLiteral).getAST() = element.getInstructionStringLiteral(tag)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -266,12 +279,6 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
StringLiteral getInstructionStringLiteral(Instruction instruction) {
|
||||
result = getInstructionTranslatedElement(instruction)
|
||||
.getInstructionStringLiteral(getInstructionTag(instruction))
|
||||
}
|
||||
|
||||
cached
|
||||
BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) {
|
||||
result = getInstructionTranslatedElement(instruction)
|
||||
|
||||
@@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable {
|
||||
|
||||
abstract string toString();
|
||||
|
||||
/**
|
||||
* Holds if this variable's value cannot be changed within a function. Currently used for string
|
||||
* literals, but could also apply to `const` global and static variables.
|
||||
*/
|
||||
predicate isReadOnly() { none() }
|
||||
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
@@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable {
|
||||
final override Language::StaticVariable getVariable() { result = var }
|
||||
}
|
||||
|
||||
abstract class IRGeneratedVariable extends IRVariable {
|
||||
Language::AST ast;
|
||||
Language::LanguageType type;
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
|
||||
override string toString() { result = getBaseString() + getLocationString() }
|
||||
|
||||
override string getUniqueId() { none() }
|
||||
|
||||
final string getLocationString() {
|
||||
result = ast.getLocation().getStartLine().toString() + ":" +
|
||||
ast.getLocation().getStartColumn().toString()
|
||||
}
|
||||
|
||||
string getBaseString() { none() }
|
||||
}
|
||||
|
||||
IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
|
||||
result.getAST() = ast and
|
||||
result.getTag() = tag
|
||||
}
|
||||
|
||||
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
|
||||
Language::AST ast;
|
||||
class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
|
||||
TempVariableTag tag;
|
||||
Language::LanguageType type;
|
||||
|
||||
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "Temp: " + Construction::getTempVariableUniqueId(this)
|
||||
}
|
||||
|
||||
final TempVariableTag getTag() { result = tag }
|
||||
|
||||
override string toString() {
|
||||
result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" +
|
||||
ast.getLocation().getStartColumn().toString()
|
||||
}
|
||||
|
||||
string getBaseString() { result = "#temp" }
|
||||
override string getBaseString() { result = "#temp" }
|
||||
}
|
||||
|
||||
class IRReturnVariable extends IRTempVariable {
|
||||
@@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable {
|
||||
|
||||
override string getBaseString() { result = "#throw" }
|
||||
}
|
||||
|
||||
class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
Language::StringLiteral literal;
|
||||
|
||||
IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) }
|
||||
|
||||
final override predicate isReadOnly() { any() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
}
|
||||
|
||||
override string getBaseString() { result = "#string" }
|
||||
|
||||
final Language::StringLiteral getLiteral() { result = literal }
|
||||
}
|
||||
|
||||
@@ -818,14 +818,12 @@ class FloatConstantInstruction extends ConstantInstruction {
|
||||
FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType }
|
||||
}
|
||||
|
||||
class StringConstantInstruction extends Instruction {
|
||||
Language::StringLiteral value;
|
||||
class StringConstantInstruction extends VariableInstruction {
|
||||
override IRStringLiteral var;
|
||||
|
||||
StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) }
|
||||
final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) }
|
||||
|
||||
final override string getImmediateString() { result = Language::getStringLiteralText(value) }
|
||||
|
||||
final Language::StringLiteral getValue() { result = value }
|
||||
final Language::StringLiteral getValue() { result = var.getLiteral() }
|
||||
}
|
||||
|
||||
class BinaryInstruction extends Instruction {
|
||||
|
||||
@@ -308,6 +308,10 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset)
|
||||
instr.(VariableAddressInstruction).getIRVariable() = var and
|
||||
bitOffset = 0
|
||||
or
|
||||
// A string literal is just a special read-only global variable.
|
||||
instr.(StringConstantInstruction).getIRVariable() = var and
|
||||
bitOffset = 0
|
||||
or
|
||||
exists(Operand operand, IntValue originalBitOffset, IntValue propagatedBitOffset |
|
||||
operand = instr.getAnOperand() and
|
||||
// If an operand is propagated, then the result points to the same variable,
|
||||
|
||||
@@ -341,11 +341,6 @@ private module Cached {
|
||||
result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue()
|
||||
}
|
||||
|
||||
cached
|
||||
Language::StringLiteral getInstructionStringLiteral(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue()
|
||||
}
|
||||
|
||||
cached
|
||||
Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) {
|
||||
result = getOldInstruction(instruction)
|
||||
|
||||
@@ -952,81 +952,107 @@ ssa.cpp:
|
||||
# 213| v0_69(void) = AliasedUse : ~m0_1
|
||||
# 213| v0_70(void) = ExitFunction :
|
||||
|
||||
# 226| void Constructible::Constructible(int)
|
||||
# 226| char StringLiteralAliasing()
|
||||
# 226| Block 0
|
||||
# 226| v0_0(void) = EnterFunction :
|
||||
# 226| m0_1(unknown) = AliasedDefinition :
|
||||
# 226| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 226| r0_3(glval<Constructible>) = InitializeThis :
|
||||
# 226| r0_4(glval<int>) = VariableAddress[x] :
|
||||
# 226| m0_5(int) = InitializeParameter[x] : &:r0_4
|
||||
# 226| v0_6(void) = NoOp :
|
||||
# 226| v0_7(void) = ReturnVoid :
|
||||
# 226| v0_8(void) = UnmodeledUse : mu*
|
||||
# 226| v0_9(void) = AliasedUse : ~m0_1
|
||||
# 226| v0_10(void) = ExitFunction :
|
||||
# 226| v0_0(void) = EnterFunction :
|
||||
# 226| m0_1(unknown) = AliasedDefinition :
|
||||
# 226| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 227| r0_3(glval<unknown>) = FunctionAddress[ExternalFunc] :
|
||||
# 227| v0_4(void) = Call : func:r0_3
|
||||
# 227| m0_5(unknown) = ^CallSideEffect : ~m0_1
|
||||
# 227| m0_6(unknown) = Chi : total:m0_1, partial:m0_5
|
||||
# 229| r0_7(glval<char *>) = VariableAddress[s] :
|
||||
# 229| r0_8(glval<char[8]>) = StringConstant["Literal"] :
|
||||
# 229| r0_9(char *) = Convert : r0_8
|
||||
# 229| m0_10(char *) = Store : &:r0_7, r0_9
|
||||
# 230| r0_11(glval<char>) = VariableAddress[#return] :
|
||||
# 230| r0_12(glval<char *>) = VariableAddress[s] :
|
||||
# 230| r0_13(char *) = Load : &:r0_12, m0_10
|
||||
# 230| r0_14(int) = Constant[2] :
|
||||
# 230| r0_15(glval<char>) = PointerAdd[1] : r0_13, r0_14
|
||||
# 230| r0_16(char) = Load : &:r0_15, ~m0_1
|
||||
# 230| m0_17(char) = Store : &:r0_11, r0_16
|
||||
# 226| r0_18(glval<char>) = VariableAddress[#return] :
|
||||
# 226| v0_19(void) = ReturnValue : &:r0_18, m0_17
|
||||
# 226| v0_20(void) = UnmodeledUse : mu*
|
||||
# 226| v0_21(void) = AliasedUse : ~m0_6
|
||||
# 226| v0_22(void) = ExitFunction :
|
||||
|
||||
# 227| void Constructible::g()
|
||||
# 227| Block 0
|
||||
# 227| v0_0(void) = EnterFunction :
|
||||
# 227| m0_1(unknown) = AliasedDefinition :
|
||||
# 227| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 227| r0_3(glval<Constructible>) = InitializeThis :
|
||||
# 227| v0_4(void) = NoOp :
|
||||
# 227| v0_5(void) = ReturnVoid :
|
||||
# 227| v0_6(void) = UnmodeledUse : mu*
|
||||
# 227| v0_7(void) = AliasedUse : ~m0_1
|
||||
# 227| v0_8(void) = ExitFunction :
|
||||
# 235| void Constructible::Constructible(int)
|
||||
# 235| Block 0
|
||||
# 235| v0_0(void) = EnterFunction :
|
||||
# 235| m0_1(unknown) = AliasedDefinition :
|
||||
# 235| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 235| r0_3(glval<Constructible>) = InitializeThis :
|
||||
# 235| r0_4(glval<int>) = VariableAddress[x] :
|
||||
# 235| m0_5(int) = InitializeParameter[x] : &:r0_4
|
||||
# 235| v0_6(void) = NoOp :
|
||||
# 235| v0_7(void) = ReturnVoid :
|
||||
# 235| v0_8(void) = UnmodeledUse : mu*
|
||||
# 235| v0_9(void) = AliasedUse : ~m0_1
|
||||
# 235| v0_10(void) = ExitFunction :
|
||||
|
||||
# 230| void ExplicitConstructorCalls()
|
||||
# 230| Block 0
|
||||
# 230| v0_0(void) = EnterFunction :
|
||||
# 230| m0_1(unknown) = AliasedDefinition :
|
||||
# 230| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 231| r0_3(glval<Constructible>) = VariableAddress[c] :
|
||||
# 231| m0_4(Constructible) = Uninitialized[c] : &:r0_3
|
||||
# 231| r0_5(glval<unknown>) = FunctionAddress[Constructible] :
|
||||
# 231| r0_6(int) = Constant[1] :
|
||||
# 231| v0_7(void) = Call : func:r0_5, this:r0_3, 0:r0_6
|
||||
# 231| m0_8(unknown) = ^CallSideEffect : ~m0_1
|
||||
# 231| m0_9(unknown) = Chi : total:m0_1, partial:m0_8
|
||||
# 231| m0_10(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_3
|
||||
# 231| m0_11(Constructible) = Chi : total:m0_4, partial:m0_10
|
||||
# 232| r0_12(glval<Constructible>) = VariableAddress[c] :
|
||||
# 232| r0_13(glval<unknown>) = FunctionAddress[g] :
|
||||
# 232| v0_14(void) = Call : func:r0_13, this:r0_12
|
||||
# 232| m0_15(unknown) = ^CallSideEffect : ~m0_9
|
||||
# 232| m0_16(unknown) = Chi : total:m0_9, partial:m0_15
|
||||
# 232| v0_17(void) = ^BufferReadSideEffect[-1] : &:r0_12, ~m0_11
|
||||
# 232| m0_18(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_12
|
||||
# 232| m0_19(Constructible) = Chi : total:m0_11, partial:m0_18
|
||||
# 233| r0_20(glval<Constructible>) = VariableAddress[c] :
|
||||
# 233| r0_21(glval<unknown>) = FunctionAddress[g] :
|
||||
# 233| v0_22(void) = Call : func:r0_21, this:r0_20
|
||||
# 233| m0_23(unknown) = ^CallSideEffect : ~m0_16
|
||||
# 233| m0_24(unknown) = Chi : total:m0_16, partial:m0_23
|
||||
# 233| v0_25(void) = ^BufferReadSideEffect[-1] : &:r0_20, ~m0_19
|
||||
# 233| m0_26(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_20
|
||||
# 233| m0_27(Constructible) = Chi : total:m0_19, partial:m0_26
|
||||
# 234| r0_28(glval<Constructible>) = VariableAddress[c2] :
|
||||
# 234| m0_29(Constructible) = Uninitialized[c2] : &:r0_28
|
||||
# 234| r0_30(glval<unknown>) = FunctionAddress[Constructible] :
|
||||
# 234| r0_31(int) = Constant[2] :
|
||||
# 234| v0_32(void) = Call : func:r0_30, this:r0_28, 0:r0_31
|
||||
# 234| m0_33(unknown) = ^CallSideEffect : ~m0_24
|
||||
# 234| m0_34(unknown) = Chi : total:m0_24, partial:m0_33
|
||||
# 234| m0_35(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_28
|
||||
# 234| m0_36(Constructible) = Chi : total:m0_29, partial:m0_35
|
||||
# 235| r0_37(glval<Constructible>) = VariableAddress[c2] :
|
||||
# 235| r0_38(glval<unknown>) = FunctionAddress[g] :
|
||||
# 235| v0_39(void) = Call : func:r0_38, this:r0_37
|
||||
# 235| m0_40(unknown) = ^CallSideEffect : ~m0_34
|
||||
# 235| m0_41(unknown) = Chi : total:m0_34, partial:m0_40
|
||||
# 235| v0_42(void) = ^BufferReadSideEffect[-1] : &:r0_37, ~m0_36
|
||||
# 235| m0_43(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_37
|
||||
# 235| m0_44(Constructible) = Chi : total:m0_36, partial:m0_43
|
||||
# 236| v0_45(void) = NoOp :
|
||||
# 230| v0_46(void) = ReturnVoid :
|
||||
# 230| v0_47(void) = UnmodeledUse : mu*
|
||||
# 230| v0_48(void) = AliasedUse : ~m0_41
|
||||
# 230| v0_49(void) = ExitFunction :
|
||||
# 236| void Constructible::g()
|
||||
# 236| Block 0
|
||||
# 236| v0_0(void) = EnterFunction :
|
||||
# 236| m0_1(unknown) = AliasedDefinition :
|
||||
# 236| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 236| r0_3(glval<Constructible>) = InitializeThis :
|
||||
# 236| v0_4(void) = NoOp :
|
||||
# 236| v0_5(void) = ReturnVoid :
|
||||
# 236| v0_6(void) = UnmodeledUse : mu*
|
||||
# 236| v0_7(void) = AliasedUse : ~m0_1
|
||||
# 236| v0_8(void) = ExitFunction :
|
||||
|
||||
# 239| void ExplicitConstructorCalls()
|
||||
# 239| Block 0
|
||||
# 239| v0_0(void) = EnterFunction :
|
||||
# 239| m0_1(unknown) = AliasedDefinition :
|
||||
# 239| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 240| r0_3(glval<Constructible>) = VariableAddress[c] :
|
||||
# 240| m0_4(Constructible) = Uninitialized[c] : &:r0_3
|
||||
# 240| r0_5(glval<unknown>) = FunctionAddress[Constructible] :
|
||||
# 240| r0_6(int) = Constant[1] :
|
||||
# 240| v0_7(void) = Call : func:r0_5, this:r0_3, 0:r0_6
|
||||
# 240| m0_8(unknown) = ^CallSideEffect : ~m0_1
|
||||
# 240| m0_9(unknown) = Chi : total:m0_1, partial:m0_8
|
||||
# 240| m0_10(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_3
|
||||
# 240| m0_11(Constructible) = Chi : total:m0_4, partial:m0_10
|
||||
# 241| r0_12(glval<Constructible>) = VariableAddress[c] :
|
||||
# 241| r0_13(glval<unknown>) = FunctionAddress[g] :
|
||||
# 241| v0_14(void) = Call : func:r0_13, this:r0_12
|
||||
# 241| m0_15(unknown) = ^CallSideEffect : ~m0_9
|
||||
# 241| m0_16(unknown) = Chi : total:m0_9, partial:m0_15
|
||||
# 241| v0_17(void) = ^BufferReadSideEffect[-1] : &:r0_12, ~m0_11
|
||||
# 241| m0_18(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_12
|
||||
# 241| m0_19(Constructible) = Chi : total:m0_11, partial:m0_18
|
||||
# 242| r0_20(glval<Constructible>) = VariableAddress[c] :
|
||||
# 242| r0_21(glval<unknown>) = FunctionAddress[g] :
|
||||
# 242| v0_22(void) = Call : func:r0_21, this:r0_20
|
||||
# 242| m0_23(unknown) = ^CallSideEffect : ~m0_16
|
||||
# 242| m0_24(unknown) = Chi : total:m0_16, partial:m0_23
|
||||
# 242| v0_25(void) = ^BufferReadSideEffect[-1] : &:r0_20, ~m0_19
|
||||
# 242| m0_26(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_20
|
||||
# 242| m0_27(Constructible) = Chi : total:m0_19, partial:m0_26
|
||||
# 243| r0_28(glval<Constructible>) = VariableAddress[c2] :
|
||||
# 243| m0_29(Constructible) = Uninitialized[c2] : &:r0_28
|
||||
# 243| r0_30(glval<unknown>) = FunctionAddress[Constructible] :
|
||||
# 243| r0_31(int) = Constant[2] :
|
||||
# 243| v0_32(void) = Call : func:r0_30, this:r0_28, 0:r0_31
|
||||
# 243| m0_33(unknown) = ^CallSideEffect : ~m0_24
|
||||
# 243| m0_34(unknown) = Chi : total:m0_24, partial:m0_33
|
||||
# 243| m0_35(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_28
|
||||
# 243| m0_36(Constructible) = Chi : total:m0_29, partial:m0_35
|
||||
# 244| r0_37(glval<Constructible>) = VariableAddress[c2] :
|
||||
# 244| r0_38(glval<unknown>) = FunctionAddress[g] :
|
||||
# 244| v0_39(void) = Call : func:r0_38, this:r0_37
|
||||
# 244| m0_40(unknown) = ^CallSideEffect : ~m0_34
|
||||
# 244| m0_41(unknown) = Chi : total:m0_34, partial:m0_40
|
||||
# 244| v0_42(void) = ^BufferReadSideEffect[-1] : &:r0_37, ~m0_36
|
||||
# 244| m0_43(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_37
|
||||
# 244| m0_44(Constructible) = Chi : total:m0_36, partial:m0_43
|
||||
# 245| v0_45(void) = NoOp :
|
||||
# 239| v0_46(void) = ReturnVoid :
|
||||
# 239| v0_47(void) = UnmodeledUse : mu*
|
||||
# 239| v0_48(void) = AliasedUse : ~m0_41
|
||||
# 239| v0_49(void) = ExitFunction :
|
||||
|
||||
@@ -221,6 +221,15 @@ void InitArray() {
|
||||
char f[3] = { 0 };
|
||||
}
|
||||
|
||||
extern void ExternalFunc();
|
||||
|
||||
char StringLiteralAliasing() {
|
||||
ExternalFunc();
|
||||
|
||||
const char* s = "Literal";
|
||||
return s[2]; // Should be defined by `AliasedDefinition`, not `Chi` or `CallSideEffect`.
|
||||
}
|
||||
|
||||
class Constructible {
|
||||
public:
|
||||
Constructible(int x) {};
|
||||
|
||||
@@ -908,71 +908,96 @@ ssa.cpp:
|
||||
# 213| v0_61(void) = AliasedUse : ~mu0_2
|
||||
# 213| v0_62(void) = ExitFunction :
|
||||
|
||||
# 226| void Constructible::Constructible(int)
|
||||
# 226| char StringLiteralAliasing()
|
||||
# 226| Block 0
|
||||
# 226| v0_0(void) = EnterFunction :
|
||||
# 226| mu0_1(unknown) = AliasedDefinition :
|
||||
# 226| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 226| r0_3(glval<Constructible>) = InitializeThis :
|
||||
# 226| r0_4(glval<int>) = VariableAddress[x] :
|
||||
# 226| m0_5(int) = InitializeParameter[x] : &:r0_4
|
||||
# 226| v0_6(void) = NoOp :
|
||||
# 226| v0_7(void) = ReturnVoid :
|
||||
# 226| v0_8(void) = UnmodeledUse : mu*
|
||||
# 226| v0_9(void) = AliasedUse : ~mu0_2
|
||||
# 226| v0_10(void) = ExitFunction :
|
||||
# 226| v0_0(void) = EnterFunction :
|
||||
# 226| mu0_1(unknown) = AliasedDefinition :
|
||||
# 226| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 227| r0_3(glval<unknown>) = FunctionAddress[ExternalFunc] :
|
||||
# 227| v0_4(void) = Call : func:r0_3
|
||||
# 227| mu0_5(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 229| r0_6(glval<char *>) = VariableAddress[s] :
|
||||
# 229| r0_7(glval<char[8]>) = StringConstant["Literal"] :
|
||||
# 229| r0_8(char *) = Convert : r0_7
|
||||
# 229| m0_9(char *) = Store : &:r0_6, r0_8
|
||||
# 230| r0_10(glval<char>) = VariableAddress[#return] :
|
||||
# 230| r0_11(glval<char *>) = VariableAddress[s] :
|
||||
# 230| r0_12(char *) = Load : &:r0_11, m0_9
|
||||
# 230| r0_13(int) = Constant[2] :
|
||||
# 230| r0_14(glval<char>) = PointerAdd[1] : r0_12, r0_13
|
||||
# 230| r0_15(char) = Load : &:r0_14, ~mu0_2
|
||||
# 230| m0_16(char) = Store : &:r0_10, r0_15
|
||||
# 226| r0_17(glval<char>) = VariableAddress[#return] :
|
||||
# 226| v0_18(void) = ReturnValue : &:r0_17, m0_16
|
||||
# 226| v0_19(void) = UnmodeledUse : mu*
|
||||
# 226| v0_20(void) = AliasedUse : ~mu0_2
|
||||
# 226| v0_21(void) = ExitFunction :
|
||||
|
||||
# 227| void Constructible::g()
|
||||
# 227| Block 0
|
||||
# 227| v0_0(void) = EnterFunction :
|
||||
# 227| mu0_1(unknown) = AliasedDefinition :
|
||||
# 227| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 227| r0_3(glval<Constructible>) = InitializeThis :
|
||||
# 227| v0_4(void) = NoOp :
|
||||
# 227| v0_5(void) = ReturnVoid :
|
||||
# 227| v0_6(void) = UnmodeledUse : mu*
|
||||
# 227| v0_7(void) = AliasedUse : ~mu0_2
|
||||
# 227| v0_8(void) = ExitFunction :
|
||||
# 235| void Constructible::Constructible(int)
|
||||
# 235| Block 0
|
||||
# 235| v0_0(void) = EnterFunction :
|
||||
# 235| mu0_1(unknown) = AliasedDefinition :
|
||||
# 235| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 235| r0_3(glval<Constructible>) = InitializeThis :
|
||||
# 235| r0_4(glval<int>) = VariableAddress[x] :
|
||||
# 235| m0_5(int) = InitializeParameter[x] : &:r0_4
|
||||
# 235| v0_6(void) = NoOp :
|
||||
# 235| v0_7(void) = ReturnVoid :
|
||||
# 235| v0_8(void) = UnmodeledUse : mu*
|
||||
# 235| v0_9(void) = AliasedUse : ~mu0_2
|
||||
# 235| v0_10(void) = ExitFunction :
|
||||
|
||||
# 230| void ExplicitConstructorCalls()
|
||||
# 230| Block 0
|
||||
# 230| v0_0(void) = EnterFunction :
|
||||
# 230| mu0_1(unknown) = AliasedDefinition :
|
||||
# 230| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 231| r0_3(glval<Constructible>) = VariableAddress[c] :
|
||||
# 231| mu0_4(Constructible) = Uninitialized[c] : &:r0_3
|
||||
# 231| r0_5(glval<unknown>) = FunctionAddress[Constructible] :
|
||||
# 231| r0_6(int) = Constant[1] :
|
||||
# 231| v0_7(void) = Call : func:r0_5, this:r0_3, 0:r0_6
|
||||
# 231| mu0_8(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 231| mu0_9(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_3
|
||||
# 232| r0_10(glval<Constructible>) = VariableAddress[c] :
|
||||
# 232| r0_11(glval<unknown>) = FunctionAddress[g] :
|
||||
# 232| v0_12(void) = Call : func:r0_11, this:r0_10
|
||||
# 232| mu0_13(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 232| v0_14(void) = ^BufferReadSideEffect[-1] : &:r0_10, ~mu0_2
|
||||
# 232| mu0_15(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_10
|
||||
# 233| r0_16(glval<Constructible>) = VariableAddress[c] :
|
||||
# 233| r0_17(glval<unknown>) = FunctionAddress[g] :
|
||||
# 233| v0_18(void) = Call : func:r0_17, this:r0_16
|
||||
# 233| mu0_19(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 233| v0_20(void) = ^BufferReadSideEffect[-1] : &:r0_16, ~mu0_2
|
||||
# 233| mu0_21(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_16
|
||||
# 234| r0_22(glval<Constructible>) = VariableAddress[c2] :
|
||||
# 234| mu0_23(Constructible) = Uninitialized[c2] : &:r0_22
|
||||
# 234| r0_24(glval<unknown>) = FunctionAddress[Constructible] :
|
||||
# 234| r0_25(int) = Constant[2] :
|
||||
# 234| v0_26(void) = Call : func:r0_24, this:r0_22, 0:r0_25
|
||||
# 234| mu0_27(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 234| mu0_28(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_22
|
||||
# 235| r0_29(glval<Constructible>) = VariableAddress[c2] :
|
||||
# 235| r0_30(glval<unknown>) = FunctionAddress[g] :
|
||||
# 235| v0_31(void) = Call : func:r0_30, this:r0_29
|
||||
# 235| mu0_32(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 235| v0_33(void) = ^BufferReadSideEffect[-1] : &:r0_29, ~mu0_2
|
||||
# 235| mu0_34(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_29
|
||||
# 236| v0_35(void) = NoOp :
|
||||
# 230| v0_36(void) = ReturnVoid :
|
||||
# 230| v0_37(void) = UnmodeledUse : mu*
|
||||
# 230| v0_38(void) = AliasedUse : ~mu0_2
|
||||
# 230| v0_39(void) = ExitFunction :
|
||||
# 236| void Constructible::g()
|
||||
# 236| Block 0
|
||||
# 236| v0_0(void) = EnterFunction :
|
||||
# 236| mu0_1(unknown) = AliasedDefinition :
|
||||
# 236| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 236| r0_3(glval<Constructible>) = InitializeThis :
|
||||
# 236| v0_4(void) = NoOp :
|
||||
# 236| v0_5(void) = ReturnVoid :
|
||||
# 236| v0_6(void) = UnmodeledUse : mu*
|
||||
# 236| v0_7(void) = AliasedUse : ~mu0_2
|
||||
# 236| v0_8(void) = ExitFunction :
|
||||
|
||||
# 239| void ExplicitConstructorCalls()
|
||||
# 239| Block 0
|
||||
# 239| v0_0(void) = EnterFunction :
|
||||
# 239| mu0_1(unknown) = AliasedDefinition :
|
||||
# 239| mu0_2(unknown) = UnmodeledDefinition :
|
||||
# 240| r0_3(glval<Constructible>) = VariableAddress[c] :
|
||||
# 240| mu0_4(Constructible) = Uninitialized[c] : &:r0_3
|
||||
# 240| r0_5(glval<unknown>) = FunctionAddress[Constructible] :
|
||||
# 240| r0_6(int) = Constant[1] :
|
||||
# 240| v0_7(void) = Call : func:r0_5, this:r0_3, 0:r0_6
|
||||
# 240| mu0_8(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 240| mu0_9(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_3
|
||||
# 241| r0_10(glval<Constructible>) = VariableAddress[c] :
|
||||
# 241| r0_11(glval<unknown>) = FunctionAddress[g] :
|
||||
# 241| v0_12(void) = Call : func:r0_11, this:r0_10
|
||||
# 241| mu0_13(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 241| v0_14(void) = ^BufferReadSideEffect[-1] : &:r0_10, ~mu0_2
|
||||
# 241| mu0_15(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_10
|
||||
# 242| r0_16(glval<Constructible>) = VariableAddress[c] :
|
||||
# 242| r0_17(glval<unknown>) = FunctionAddress[g] :
|
||||
# 242| v0_18(void) = Call : func:r0_17, this:r0_16
|
||||
# 242| mu0_19(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 242| v0_20(void) = ^BufferReadSideEffect[-1] : &:r0_16, ~mu0_2
|
||||
# 242| mu0_21(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_16
|
||||
# 243| r0_22(glval<Constructible>) = VariableAddress[c2] :
|
||||
# 243| mu0_23(Constructible) = Uninitialized[c2] : &:r0_22
|
||||
# 243| r0_24(glval<unknown>) = FunctionAddress[Constructible] :
|
||||
# 243| r0_25(int) = Constant[2] :
|
||||
# 243| v0_26(void) = Call : func:r0_24, this:r0_22, 0:r0_25
|
||||
# 243| mu0_27(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 243| mu0_28(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_22
|
||||
# 244| r0_29(glval<Constructible>) = VariableAddress[c2] :
|
||||
# 244| r0_30(glval<unknown>) = FunctionAddress[g] :
|
||||
# 244| v0_31(void) = Call : func:r0_30, this:r0_29
|
||||
# 244| mu0_32(unknown) = ^CallSideEffect : ~mu0_2
|
||||
# 244| v0_33(void) = ^BufferReadSideEffect[-1] : &:r0_29, ~mu0_2
|
||||
# 244| mu0_34(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_29
|
||||
# 245| v0_35(void) = NoOp :
|
||||
# 239| v0_36(void) = ReturnVoid :
|
||||
# 239| v0_37(void) = UnmodeledUse : mu*
|
||||
# 239| v0_38(void) = AliasedUse : ~mu0_2
|
||||
# 239| v0_39(void) = ExitFunction :
|
||||
|
||||
@@ -9,4 +9,10 @@ newtype TIRVariable =
|
||||
Language::Function func, Language::AST ast, TempVariableTag tag, Language::LanguageType type
|
||||
) {
|
||||
Construction::hasTempVariable(func, ast, tag, type)
|
||||
} or
|
||||
TIRStringLiteral(
|
||||
Language::Function func, Language::AST ast, Language::LanguageType type,
|
||||
Language::StringLiteral literal
|
||||
) {
|
||||
Construction::hasStringLiteral(func, ast, type, literal)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable {
|
||||
|
||||
abstract string toString();
|
||||
|
||||
/**
|
||||
* Holds if this variable's value cannot be changed within a function. Currently used for string
|
||||
* literals, but could also apply to `const` global and static variables.
|
||||
*/
|
||||
predicate isReadOnly() { none() }
|
||||
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
@@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable {
|
||||
final override Language::StaticVariable getVariable() { result = var }
|
||||
}
|
||||
|
||||
abstract class IRGeneratedVariable extends IRVariable {
|
||||
Language::AST ast;
|
||||
Language::LanguageType type;
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
|
||||
override string toString() { result = getBaseString() + getLocationString() }
|
||||
|
||||
override string getUniqueId() { none() }
|
||||
|
||||
final string getLocationString() {
|
||||
result = ast.getLocation().getStartLine().toString() + ":" +
|
||||
ast.getLocation().getStartColumn().toString()
|
||||
}
|
||||
|
||||
string getBaseString() { none() }
|
||||
}
|
||||
|
||||
IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
|
||||
result.getAST() = ast and
|
||||
result.getTag() = tag
|
||||
}
|
||||
|
||||
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
|
||||
Language::AST ast;
|
||||
class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
|
||||
TempVariableTag tag;
|
||||
Language::LanguageType type;
|
||||
|
||||
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "Temp: " + Construction::getTempVariableUniqueId(this)
|
||||
}
|
||||
|
||||
final TempVariableTag getTag() { result = tag }
|
||||
|
||||
override string toString() {
|
||||
result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" +
|
||||
ast.getLocation().getStartColumn().toString()
|
||||
}
|
||||
|
||||
string getBaseString() { result = "#temp" }
|
||||
override string getBaseString() { result = "#temp" }
|
||||
}
|
||||
|
||||
class IRReturnVariable extends IRTempVariable {
|
||||
@@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable {
|
||||
|
||||
override string getBaseString() { result = "#throw" }
|
||||
}
|
||||
|
||||
class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
Language::StringLiteral literal;
|
||||
|
||||
IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) }
|
||||
|
||||
final override predicate isReadOnly() { any() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
}
|
||||
|
||||
override string getBaseString() { result = "#string" }
|
||||
|
||||
final Language::StringLiteral getLiteral() { result = literal }
|
||||
}
|
||||
|
||||
@@ -818,14 +818,12 @@ class FloatConstantInstruction extends ConstantInstruction {
|
||||
FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType }
|
||||
}
|
||||
|
||||
class StringConstantInstruction extends Instruction {
|
||||
Language::StringLiteral value;
|
||||
class StringConstantInstruction extends VariableInstruction {
|
||||
override IRStringLiteral var;
|
||||
|
||||
StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) }
|
||||
final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) }
|
||||
|
||||
final override string getImmediateString() { result = Language::getStringLiteralText(value) }
|
||||
|
||||
final Language::StringLiteral getValue() { result = value }
|
||||
final Language::StringLiteral getValue() { result = var.getLiteral() }
|
||||
}
|
||||
|
||||
class BinaryInstruction extends Instruction {
|
||||
|
||||
@@ -52,6 +52,15 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasStringLiteral(
|
||||
Callable callable, Language::AST ast, CSharpType type, StringLiteral literal
|
||||
) {
|
||||
literal = ast and
|
||||
literal.getEnclosingCallable() = callable and
|
||||
getTypeForPRValue(literal.getType()) = type
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasModeledMemoryResult(Instruction instruction) { none() }
|
||||
|
||||
@@ -232,8 +241,14 @@ private module Cached {
|
||||
|
||||
cached
|
||||
IRVariable getInstructionVariable(Instruction instruction) {
|
||||
result = getInstructionTranslatedElement(instruction)
|
||||
.getInstructionVariable(getInstructionTag(instruction))
|
||||
exists(TranslatedElement element, InstructionTag tag |
|
||||
element = getInstructionTranslatedElement(instruction) and
|
||||
tag = getInstructionTag(instruction) and
|
||||
(
|
||||
result = element.getInstructionVariable(tag) or
|
||||
result.(IRStringLiteral).getAST() = element.getInstructionStringLiteral(tag)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -265,12 +280,6 @@ private module Cached {
|
||||
.getInstructionConstantValue(getInstructionTag(instruction))
|
||||
}
|
||||
|
||||
cached
|
||||
StringLiteral getInstructionStringLiteral(Instruction instruction) {
|
||||
result = getInstructionTranslatedElement(instruction)
|
||||
.getInstructionStringLiteral(getInstructionTag(instruction))
|
||||
}
|
||||
|
||||
cached
|
||||
CSharpType getInstructionExceptionType(Instruction instruction) {
|
||||
result = getInstructionTranslatedElement(instruction)
|
||||
|
||||
@@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable {
|
||||
|
||||
abstract string toString();
|
||||
|
||||
/**
|
||||
* Holds if this variable's value cannot be changed within a function. Currently used for string
|
||||
* literals, but could also apply to `const` global and static variables.
|
||||
*/
|
||||
predicate isReadOnly() { none() }
|
||||
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
@@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable {
|
||||
final override Language::StaticVariable getVariable() { result = var }
|
||||
}
|
||||
|
||||
abstract class IRGeneratedVariable extends IRVariable {
|
||||
Language::AST ast;
|
||||
Language::LanguageType type;
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
|
||||
override string toString() { result = getBaseString() + getLocationString() }
|
||||
|
||||
override string getUniqueId() { none() }
|
||||
|
||||
final string getLocationString() {
|
||||
result = ast.getLocation().getStartLine().toString() + ":" +
|
||||
ast.getLocation().getStartColumn().toString()
|
||||
}
|
||||
|
||||
string getBaseString() { none() }
|
||||
}
|
||||
|
||||
IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
|
||||
result.getAST() = ast and
|
||||
result.getTag() = tag
|
||||
}
|
||||
|
||||
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
|
||||
Language::AST ast;
|
||||
class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
|
||||
TempVariableTag tag;
|
||||
Language::LanguageType type;
|
||||
|
||||
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "Temp: " + Construction::getTempVariableUniqueId(this)
|
||||
}
|
||||
|
||||
final TempVariableTag getTag() { result = tag }
|
||||
|
||||
override string toString() {
|
||||
result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" +
|
||||
ast.getLocation().getStartColumn().toString()
|
||||
}
|
||||
|
||||
string getBaseString() { result = "#temp" }
|
||||
override string getBaseString() { result = "#temp" }
|
||||
}
|
||||
|
||||
class IRReturnVariable extends IRTempVariable {
|
||||
@@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable {
|
||||
|
||||
override string getBaseString() { result = "#throw" }
|
||||
}
|
||||
|
||||
class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
Language::StringLiteral literal;
|
||||
|
||||
IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) }
|
||||
|
||||
final override predicate isReadOnly() { any() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
}
|
||||
|
||||
override string getBaseString() { result = "#string" }
|
||||
|
||||
final Language::StringLiteral getLiteral() { result = literal }
|
||||
}
|
||||
|
||||
@@ -818,14 +818,12 @@ class FloatConstantInstruction extends ConstantInstruction {
|
||||
FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType }
|
||||
}
|
||||
|
||||
class StringConstantInstruction extends Instruction {
|
||||
Language::StringLiteral value;
|
||||
class StringConstantInstruction extends VariableInstruction {
|
||||
override IRStringLiteral var;
|
||||
|
||||
StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) }
|
||||
final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) }
|
||||
|
||||
final override string getImmediateString() { result = Language::getStringLiteralText(value) }
|
||||
|
||||
final Language::StringLiteral getValue() { result = value }
|
||||
final Language::StringLiteral getValue() { result = var.getLiteral() }
|
||||
}
|
||||
|
||||
class BinaryInstruction extends Instruction {
|
||||
|
||||
@@ -341,11 +341,6 @@ private module Cached {
|
||||
result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue()
|
||||
}
|
||||
|
||||
cached
|
||||
Language::StringLiteral getInstructionStringLiteral(Instruction instruction) {
|
||||
result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue()
|
||||
}
|
||||
|
||||
cached
|
||||
Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) {
|
||||
result = getOldInstruction(instruction)
|
||||
|
||||
Reference in New Issue
Block a user