Merge pull request #2268 from dave-bartolomeo/dbartol/StringLiteralAlias

C++/C#: Treat string literals like read-only global variables for alias purposes
This commit is contained in:
Robert Marsh
2019-11-08 12:43:57 -08:00
committed by GitHub
23 changed files with 361 additions and 131 deletions

View File

@@ -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 }
}

View File

@@ -808,14 +808,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 {

View File

@@ -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,

View File

@@ -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

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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 }
}

View File

@@ -808,14 +808,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 {

View File

@@ -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)

View File

@@ -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 }
}

View File

@@ -808,14 +808,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 {

View File

@@ -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,

View File

@@ -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)

View File

@@ -951,3 +951,29 @@ ssa.cpp:
# 213| v0_68(void) = UnmodeledUse : mu*
# 213| v0_69(void) = AliasedUse : ~m0_1
# 213| v0_70(void) = ExitFunction :
# 226| char StringLiteralAliasing()
# 226| Block 0
# 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 :

View File

@@ -219,4 +219,13 @@ void InitArray() {
char d[2] = { 0 };
char e[2] = { 0, 1 };
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`.
}

View File

@@ -907,3 +907,28 @@ ssa.cpp:
# 213| v0_60(void) = UnmodeledUse : mu*
# 213| v0_61(void) = AliasedUse : ~mu0_2
# 213| v0_62(void) = ExitFunction :
# 226| char StringLiteralAliasing()
# 226| Block 0
# 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 :

View File

@@ -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)
}

View File

@@ -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 }
}

View File

@@ -808,14 +808,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 {

View File

@@ -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)

View File

@@ -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 }
}

View File

@@ -808,14 +808,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 {

View File

@@ -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)