C++: Pull a bunch of language-dependent code that the IR depends on out into a separate module

This commit is contained in:
Dave Bartolomeo
2019-07-17 17:05:06 -07:00
parent e58df94672
commit 5d1d082a4f
41 changed files with 430 additions and 352 deletions

View File

@@ -1,4 +1,4 @@
private import cpp
private import internal.IRLanguageInternal
private newtype TIRConfiguration = MkIRConfiguration()
@@ -13,7 +13,7 @@ class IRConfiguration extends TIRConfiguration {
/**
* Holds if IR should be created for function `func`. By default, holds for all functions.
*/
predicate shouldCreateIRForFunction(Function func) {
predicate shouldCreateIRForFunction(Language::Function func) {
any()
}
}

View File

@@ -1,4 +1,4 @@
import cpp
private import semmle.code.cpp.ir.internal.IRLanguageInternal
private newtype TEdgeKind =
TGotoEdge() or // Single successor (including fall-through)
@@ -7,9 +7,7 @@ private newtype TEdgeKind =
TExceptionEdge() or // Thrown exception
TDefaultEdge() or // 'default' label of switch
TCaseEdge(string minValue, string maxValue) { // Case label of switch
exists(SwitchCase switchCase |
hasCaseEdge(switchCase, minValue, maxValue)
)
Language::hasCaseEdge(minValue, maxValue)
}
/**
@@ -122,20 +120,3 @@ class CaseEdge extends EdgeKind, TCaseEdge {
CaseEdge caseEdge(string minValue, string maxValue) {
result = TCaseEdge(minValue, maxValue)
}
private predicate hasCaseEdge(SwitchCase switchCase, string minValue,
string maxValue) {
minValue = switchCase.getExpr().getFullyConverted().getValue() and
if exists(switchCase.getEndExpr()) then
maxValue = switchCase.getEndExpr().getFullyConverted().getValue()
else
maxValue = minValue
}
EdgeKind getCaseEdge(SwitchCase switchCase) {
exists(CaseEdge edge |
result = edge and
hasCaseEdge(switchCase, edge.getMinValue(), edge.getMaxValue())
) or
(switchCase instanceof DefaultCase and result instanceof DefaultEdge)
}

View File

@@ -1,5 +1,3 @@
import cpp
private newtype TMemoryAccessKind =
TIndirectMemoryAccess() or
TIndirectMayMemoryAccess() or

View File

@@ -1,4 +1,3 @@
import cpp
private import semmle.code.cpp.ir.internal.TempVariableTag
class TempVariableTag extends TTempVariableTag {

View File

@@ -19,7 +19,7 @@ class IRBlockBase extends TIRBlock {
result = getFirstInstruction(this).toString()
}
final Location getLocation() {
final Language::Location getLocation() {
result = getFirstInstruction().getLocation()
}
@@ -67,7 +67,7 @@ class IRBlockBase extends TIRBlock {
result = getFirstInstruction(this).getEnclosingIRFunction()
}
final Function getEnclosingFunction() {
final Language::Function getEnclosingFunction() {
result = getFirstInstruction(this).getEnclosingFunction()
}
}

View File

@@ -1,9 +1,8 @@
private import internal.IRInternal
import Instruction
private import cpp
private newtype TIRFunction =
MkIRFunction(Function func) {
MkIRFunction(Language::Function func) {
Construction::functionHasIR(func)
}
@@ -11,7 +10,7 @@ private newtype TIRFunction =
* Represents the IR for a function.
*/
class IRFunction extends TIRFunction {
Function func;
Language::Function func;
IRFunction() {
this = MkIRFunction(func)
@@ -24,14 +23,14 @@ class IRFunction extends TIRFunction {
/**
* Gets the function whose IR is represented.
*/
final Function getFunction() {
final Language::Function getFunction() {
result = func
}
/**
* Gets the location of the function.
*/
final Location getLocation() {
final Language::Location getLocation() {
result = func.getLocation()
}

View File

@@ -1,12 +1,11 @@
private import internal.IRInternal
import IRFunction
private import cpp
import semmle.code.cpp.ir.implementation.TempVariableTag
private import semmle.code.cpp.ir.internal.IRUtilities
private import semmle.code.cpp.ir.internal.TempVariableTag
private import semmle.code.cpp.ir.internal.TIRVariable
IRUserVariable getIRUserVariable(Function func, Variable var) {
IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var) {
result.getVariable() = var and
result.getEnclosingFunction() = func
}
@@ -17,20 +16,20 @@ IRUserVariable getIRUserVariable(Function func, Variable var) {
* generated by the AST-to-IR translation (`IRTempVariable`).
*/
abstract class IRVariable extends TIRVariable {
Function func;
Language::Function func;
abstract string toString();
/**
* Gets the type of the variable.
*/
abstract Type getType();
abstract Language::Type getType();
/**
* Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation.
*/
abstract Locatable getAST();
abstract Language::AST getAST();
/**
* Gets an identifier string for the variable. This identifier is unique
@@ -41,7 +40,7 @@ abstract class IRVariable extends TIRVariable {
/**
* Gets the source location of this variable.
*/
final Location getLocation() {
final Language::Location getLocation() {
result = getAST().getLocation()
}
@@ -55,7 +54,7 @@ abstract class IRVariable extends TIRVariable {
/**
* Gets the function that references this variable.
*/
final Function getEnclosingFunction() {
final Language::Function getEnclosingFunction() {
result = func
}
}
@@ -63,29 +62,34 @@ abstract class IRVariable extends TIRVariable {
/**
* Represents a user-declared variable referenced by the IR for a function.
*/
abstract class IRUserVariable extends IRVariable {
Variable var;
class IRUserVariable extends IRVariable, TIRUserVariable {
Language::Variable var;
Language::Type type;
IRUserVariable() {
this = TIRUserVariable(var, type, func)
}
override final string toString() {
result = var.toString()
result = getVariable().toString()
}
override final Type getType() {
result = getVariableType(var)
}
override final Locatable getAST() {
override final Language::AST getAST() {
result = var
}
override final string getUniqueId() {
result = var.toString() + " " + var.getLocation().toString()
result = getVariable().toString() + " " + getVariable().getLocation().toString()
}
override final Language::Type getType() {
result = type
}
/**
* Gets the original user-declared variable.
*/
final Variable getVariable() {
Language::Variable getVariable() {
result = var
}
}
@@ -98,45 +102,49 @@ abstract class IRUserVariable extends IRVariable {
abstract class IRAutomaticVariable extends IRVariable {
}
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable,
TIRAutomaticUserVariable {
LocalScopeVariable localVar;
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
override Language::AutomaticVariable var;
IRAutomaticUserVariable() {
this = TIRAutomaticUserVariable(localVar, func) and
var = localVar
Language::isVariableAutomatic(var)
}
final LocalScopeVariable getLocalVariable() {
result = localVar
final override Language::AutomaticVariable getVariable() {
result = var
}
}
class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable {
class IRStaticUserVariable extends IRUserVariable {
override Language::StaticVariable var;
IRStaticUserVariable() {
this = TIRStaticUserVariable(var, func)
not Language::isVariableAutomatic(var)
}
final override Language::StaticVariable getVariable() {
result = var
}
}
IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) {
IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
result.getAST() = ast and
result.getTag() = tag
}
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
Locatable ast;
Language::AST ast;
TempVariableTag tag;
Type type;
Language::Type type;
IRTempVariable() {
this = TIRTempVariable(func, ast, tag, type)
}
override final Type getType() {
override final Language::Type getType() {
result = type
}
override final Locatable getAST() {
override final Language::AST getAST() {
result = ast
}

View File

@@ -3,11 +3,9 @@ import IRFunction
import IRBlock
import IRVariable
import Operand
private import cpp
import semmle.code.cpp.ir.implementation.EdgeKind
import semmle.code.cpp.ir.implementation.MemoryAccessKind
import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.Print
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.internal.OperandTag
@@ -60,7 +58,7 @@ module InstructionSanity {
message = "Instruction '" + instr.getOpcode().toString() + "' is missing an expected operand with tag '" +
tag.toString() + "' in function '$@'." and
func = instr.getEnclosingIRFunction() and
funcText = getIdentityString(func.getFunction())
funcText = Language::getIdentityString(func.getFunction())
)
}
@@ -101,10 +99,10 @@ module InstructionSanity {
}
query predicate missingOperandType(Operand operand, string message) {
exists(Function func |
exists(Language::Function func |
not exists(operand.getType()) and
func = operand.getUse().getEnclosingFunction() and
message = "Operand missing type in function '" + getIdentityString(func) + "'."
message = "Operand missing type in function '" + Language::getIdentityString(func) + "'."
)
}
@@ -135,14 +133,13 @@ module InstructionSanity {
* Holds if `instr` in `f` is part of a loop even though the AST of `f`
* contains no element that can cause loops.
*/
query predicate unexplainedLoop(Function f, Instruction instr) {
query predicate unexplainedLoop(Language::Function f, Instruction instr) {
exists(IRBlock block |
instr.getBlock() = block and
block.getEnclosingFunction() = f and
block.getASuccessor+() = block
) and
not exists(Loop l | l.getEnclosingFunction() = f) and
not exists(GotoStmt s | s.getEnclosingFunction() = f)
not Language::hasPotentialLoop(f)
}
/**
@@ -201,7 +198,7 @@ module InstructionSanity {
entry = f.getEntryBlock() and
entry.getASuccessor+() = block and
not forwardEdge+(entry, block) and
not exists(GotoStmt s | s.getEnclosingFunction() = f.getFunction())
not Language::hasGoto(f.getFunction())
)
}
@@ -209,7 +206,7 @@ module InstructionSanity {
* Holds if the number of back edges differs between the `Instruction` graph
* and the `IRBlock` graph.
*/
query predicate backEdgeCountMismatch(Function f, int fromInstr, int fromBlock) {
query predicate backEdgeCountMismatch(Language::Function f, int fromInstr, int fromBlock) {
fromInstr = count(Instruction i1, Instruction i2 |
i1.getEnclosingFunction() = f and i1.getBackEdgeSuccessor(_) = i2
) and
@@ -266,7 +263,7 @@ class Instruction extends Construction::TInstruction {
}
private string getResultPrefix() {
if getResultType() instanceof VoidType then
if getResultType() instanceof Language::VoidType then
result = "v"
else if hasMemoryResult() then
if isResultModeled() then
@@ -312,7 +309,7 @@ class Instruction extends Construction::TInstruction {
string getResultTypeString() {
exists(string valcat |
valcat = getValueCategoryString(getResultType().toString()) and
if (getResultType() instanceof UnknownType and
if (getResultType() instanceof Language::UnknownType and
not isGLValue() and
exists(getResultSize())) then (
result = valcat + "[" + getResultSize().toString() + "]"
@@ -379,7 +376,7 @@ class Instruction extends Construction::TInstruction {
/**
* Gets the function that contains this instruction.
*/
final Function getEnclosingFunction() {
final Language::Function getEnclosingFunction() {
result = getEnclosingIRFunction().getFunction()
}
@@ -393,28 +390,28 @@ class Instruction extends Construction::TInstruction {
/**
* Gets the AST that caused this instruction to be generated.
*/
final Locatable getAST() {
final Language::AST getAST() {
result = Construction::getInstructionAST(this)
}
/**
* Gets the location of the source code for this instruction.
*/
final Location getLocation() {
final Language::Location getLocation() {
result = getAST().getLocation()
}
/**
* Gets the `Expr` whose result is computed by this instruction, if any.
*/
final Expr getConvertedResultExpression() {
final Language::Expr getConvertedResultExpression() {
result = Construction::getInstructionConvertedResultExpression(this)
}
/**
* Gets the unconverted `Expr` whose result is computed by this instruction, if any.
*/
final Expr getUnconvertedResultExpression() {
final Language::Expr getUnconvertedResultExpression() {
result = Construction::getInstructionUnconvertedResultExpression(this)
}
@@ -425,7 +422,7 @@ class Instruction extends Construction::TInstruction {
* If `isGLValue()` holds, then the result type of this instruction should be
* thought of as "pointer to `getResultType()`".
*/
final Type getResultType() {
final Language::Type getResultType() {
Construction::instructionHasType(this, result, _)
}
@@ -461,11 +458,9 @@ class Instruction extends Construction::TInstruction {
final int getResultSize() {
if isGLValue() then (
// a glvalue is always pointer-sized.
exists(NullPointerType nullptr |
result = nullptr.getSize()
)
result = Language::getPointerSize()
)
else if getResultType() instanceof UnknownType then
else if getResultType() instanceof Language::UnknownType then
result = Construction::getInstructionResultSize(this)
else (
result = getResultType().getSize()
@@ -616,7 +611,7 @@ class VariableInstruction extends Instruction {
}
class FieldInstruction extends Instruction {
Field field;
Language::Field field;
FieldInstruction() {
field = Construction::getInstructionField(this)
@@ -626,13 +621,13 @@ class FieldInstruction extends Instruction {
result = field.toString()
}
final Field getField() {
final Language::Field getField() {
result = field
}
}
class FunctionInstruction extends Instruction {
Function funcSymbol;
Language::Function funcSymbol;
FunctionInstruction() {
funcSymbol = Construction::getInstructionFunction(this)
@@ -642,7 +637,7 @@ class FunctionInstruction extends Instruction {
result = funcSymbol.toString()
}
final Function getFunctionSymbol() {
final Language::Function getFunctionSymbol() {
result = funcSymbol
}
}
@@ -680,7 +675,7 @@ class InitializeParameterInstruction extends VariableInstruction {
getOpcode() instanceof Opcode::InitializeParameter
}
final Parameter getParameter() {
final Language::Parameter getParameter() {
result = var.(IRUserVariable).getVariable()
}
@@ -738,9 +733,9 @@ class UninitializedInstruction extends VariableInstruction {
}
/**
* Gets the `LocalVariable` that is uninitialized.
* Gets the variable that is uninitialized.
*/
final LocalVariable getLocalVariable() {
final Language::Variable getLocalVariable() {
result = var.(IRUserVariable).getVariable()
}
}
@@ -877,28 +872,28 @@ class ConstantInstruction extends ConstantValueInstruction {
class IntegerConstantInstruction extends ConstantInstruction {
IntegerConstantInstruction() {
getResultType() instanceof IntegralType
getResultType() instanceof Language::IntegralType
}
}
class FloatConstantInstruction extends ConstantInstruction {
FloatConstantInstruction() {
getResultType() instanceof FloatingPointType
getResultType() instanceof Language::FloatingPointType
}
}
class StringConstantInstruction extends Instruction {
StringLiteral value;
Language::StringLiteral value;
StringConstantInstruction() {
value = Construction::getInstructionStringLiteral(this)
}
override final string getImmediateString() {
result = value.getValueText().replaceAll("\n", " ").replaceAll("\r", "").replaceAll("\t", " ")
result = Language::getStringLiteralText(value)
}
final StringLiteral getValue() {
final Language::StringLiteral getValue() {
result = value
}
}
@@ -1086,8 +1081,8 @@ class ConvertInstruction extends UnaryInstruction {
* related by inheritance.
*/
class InheritanceConversionInstruction extends UnaryInstruction {
Class baseClass;
Class derivedClass;
Language::Class baseClass;
Language::Class derivedClass;
InheritanceConversionInstruction() {
Construction::getInstructionInheritance(this, baseClass, derivedClass)
@@ -1102,7 +1097,7 @@ class InheritanceConversionInstruction extends UnaryInstruction {
* the base and derived classes. This predicate does not hold if the
* conversion is to an indirect virtual base class.
*/
final ClassDerivation getDerivation() {
final Language::ClassDerivation getDerivation() {
result.getBaseClass() = baseClass and result.getDerivedClass() = derivedClass
}
@@ -1111,14 +1106,14 @@ class InheritanceConversionInstruction extends UnaryInstruction {
* base class of the derived class, or a virtual base class of the
* derived class.
*/
final Class getBaseClass() {
final Language::Class getBaseClass() {
result = baseClass
}
/**
* Gets the derived class of the conversion.
*/
final Class getDerivedClass() {
final Language::Class getDerivedClass() {
result = derivedClass
}
}
@@ -1349,7 +1344,7 @@ class CallInstruction extends Instruction {
/**
* Gets the `Function` that the call targets, if this is statically known.
*/
final Function getStaticCallTarget() {
final Language::Function getStaticCallTarget() {
result = getCallTarget().(FunctionInstruction).getFunctionSymbol()
}
@@ -1591,7 +1586,7 @@ class CatchInstruction extends Instruction {
* An instruction that catches an exception of a specific type.
*/
class CatchByTypeInstruction extends CatchInstruction {
Type exceptionType;
Language::Type exceptionType;
CatchByTypeInstruction() {
getOpcode() instanceof Opcode::CatchByType and
@@ -1605,7 +1600,7 @@ class CatchByTypeInstruction extends CatchInstruction {
/**
* Gets the type of exception to be caught.
*/
final Type getExceptionType() {
final Language::Type getExceptionType() {
result = exceptionType
}
}

View File

@@ -1,7 +1,6 @@
private import internal.IRInternal
import Instruction
import IRBlock
private import cpp
import semmle.code.cpp.ir.implementation.MemoryAccessKind
import semmle.code.cpp.ir.internal.Overlap
private import semmle.code.cpp.ir.internal.OperandTag
@@ -50,7 +49,7 @@ class Operand extends TOperand {
result = "Operand"
}
final Location getLocation() {
final Language::Location getLocation() {
result = getUse().getLocation()
}
@@ -166,7 +165,7 @@ class Operand extends TOperand {
* the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type.
*/
Type getType() {
Language::Type getType() {
result = getAnyDef().getResultType()
}
@@ -284,7 +283,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
class TypedOperand extends NonPhiMemoryOperand {
override TypedOperandTag tag;
override final Type getType() {
override final Language::Type getType() {
result = Construction::getInstructionOperandType(useInstr, tag)
}
}
@@ -447,7 +446,7 @@ class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override final int getSize() {
if getType() instanceof UnknownType then
if getType() instanceof Language::UnknownType then
result = Construction::getInstructionOperandSize(useInstr, tag)
else
result = getType().getSize()

View File

@@ -1,5 +1,5 @@
private import semmle.code.cpp.ir.internal.IRLanguageInternal
private import IR
private import cpp
import semmle.code.cpp.ir.IRConfiguration
private import semmle.code.cpp.Print
@@ -17,12 +17,12 @@ class PrintIRConfiguration extends TPrintIRConfiguration {
* Holds if the IR for `func` should be printed. By default, holds for all
* functions.
*/
predicate shouldPrintFunction(Function func) {
predicate shouldPrintFunction(Language::Function func) {
any()
}
}
private predicate shouldPrintFunction(Function func) {
private predicate shouldPrintFunction(Language::Function func) {
exists(PrintIRConfiguration config |
config.shouldPrintFunction(func)
)
@@ -32,7 +32,7 @@ private predicate shouldPrintFunction(Function func) {
* Override of `IRConfiguration` to only create IR for the functions that are to be dumped.
*/
private class FilteredIRConfiguration extends IRConfiguration {
override predicate shouldCreateIRForFunction(Function func) {
override predicate shouldCreateIRForFunction(Language::Function func) {
shouldPrintFunction(func)
}
}
@@ -69,7 +69,7 @@ abstract class PrintableIRNode extends TPrintableIRNode {
/**
* Gets the location to be emitted for the node.
*/
abstract Location getLocation();
abstract Language::Location getLocation();
/**
* Gets the label to be emitted for the node.
@@ -126,7 +126,7 @@ class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
result = irFunc.toString()
}
override Location getLocation() {
override Language::Location getLocation() {
result = irFunc.getLocation()
}
@@ -135,7 +135,7 @@ class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
}
override int getOrder() {
this = rank[result + 1](PrintableIRFunction orderedFunc, Location location |
this = rank[result + 1](PrintableIRFunction orderedFunc, Language::Location location |
location = orderedFunc.getIRFunction().getLocation() |
orderedFunc order by location.getFile().getAbsolutePath(), location.getStartLine(),
location.getStartColumn(), orderedFunc.getLabel()
@@ -165,7 +165,7 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
result = getLabel()
}
override Location getLocation() {
override Language::Location getLocation() {
result = block.getLocation()
}

View File

@@ -1,4 +1,4 @@
import cpp
private import cpp
import AliasAnalysis
import semmle.code.cpp.ir.internal.Overlap
private import semmle.code.cpp.Print

View File

@@ -1 +1,2 @@
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import SSAConstruction as Construction

View File

@@ -19,7 +19,7 @@ class IRBlockBase extends TIRBlock {
result = getFirstInstruction(this).toString()
}
final Location getLocation() {
final Language::Location getLocation() {
result = getFirstInstruction().getLocation()
}
@@ -67,7 +67,7 @@ class IRBlockBase extends TIRBlock {
result = getFirstInstruction(this).getEnclosingIRFunction()
}
final Function getEnclosingFunction() {
final Language::Function getEnclosingFunction() {
result = getFirstInstruction(this).getEnclosingFunction()
}
}

View File

@@ -1,9 +1,8 @@
private import internal.IRInternal
import Instruction
private import cpp
private newtype TIRFunction =
MkIRFunction(Function func) {
MkIRFunction(Language::Function func) {
Construction::functionHasIR(func)
}
@@ -11,7 +10,7 @@ private newtype TIRFunction =
* Represents the IR for a function.
*/
class IRFunction extends TIRFunction {
Function func;
Language::Function func;
IRFunction() {
this = MkIRFunction(func)
@@ -24,14 +23,14 @@ class IRFunction extends TIRFunction {
/**
* Gets the function whose IR is represented.
*/
final Function getFunction() {
final Language::Function getFunction() {
result = func
}
/**
* Gets the location of the function.
*/
final Location getLocation() {
final Language::Location getLocation() {
result = func.getLocation()
}

View File

@@ -1,12 +1,11 @@
private import internal.IRInternal
import IRFunction
private import cpp
import semmle.code.cpp.ir.implementation.TempVariableTag
private import semmle.code.cpp.ir.internal.IRUtilities
private import semmle.code.cpp.ir.internal.TempVariableTag
private import semmle.code.cpp.ir.internal.TIRVariable
IRUserVariable getIRUserVariable(Function func, Variable var) {
IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var) {
result.getVariable() = var and
result.getEnclosingFunction() = func
}
@@ -17,20 +16,20 @@ IRUserVariable getIRUserVariable(Function func, Variable var) {
* generated by the AST-to-IR translation (`IRTempVariable`).
*/
abstract class IRVariable extends TIRVariable {
Function func;
Language::Function func;
abstract string toString();
/**
* Gets the type of the variable.
*/
abstract Type getType();
abstract Language::Type getType();
/**
* Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation.
*/
abstract Locatable getAST();
abstract Language::AST getAST();
/**
* Gets an identifier string for the variable. This identifier is unique
@@ -41,7 +40,7 @@ abstract class IRVariable extends TIRVariable {
/**
* Gets the source location of this variable.
*/
final Location getLocation() {
final Language::Location getLocation() {
result = getAST().getLocation()
}
@@ -55,7 +54,7 @@ abstract class IRVariable extends TIRVariable {
/**
* Gets the function that references this variable.
*/
final Function getEnclosingFunction() {
final Language::Function getEnclosingFunction() {
result = func
}
}
@@ -63,29 +62,34 @@ abstract class IRVariable extends TIRVariable {
/**
* Represents a user-declared variable referenced by the IR for a function.
*/
abstract class IRUserVariable extends IRVariable {
Variable var;
class IRUserVariable extends IRVariable, TIRUserVariable {
Language::Variable var;
Language::Type type;
IRUserVariable() {
this = TIRUserVariable(var, type, func)
}
override final string toString() {
result = var.toString()
result = getVariable().toString()
}
override final Type getType() {
result = getVariableType(var)
}
override final Locatable getAST() {
override final Language::AST getAST() {
result = var
}
override final string getUniqueId() {
result = var.toString() + " " + var.getLocation().toString()
result = getVariable().toString() + " " + getVariable().getLocation().toString()
}
override final Language::Type getType() {
result = type
}
/**
* Gets the original user-declared variable.
*/
final Variable getVariable() {
Language::Variable getVariable() {
result = var
}
}
@@ -98,45 +102,49 @@ abstract class IRUserVariable extends IRVariable {
abstract class IRAutomaticVariable extends IRVariable {
}
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable,
TIRAutomaticUserVariable {
LocalScopeVariable localVar;
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
override Language::AutomaticVariable var;
IRAutomaticUserVariable() {
this = TIRAutomaticUserVariable(localVar, func) and
var = localVar
Language::isVariableAutomatic(var)
}
final LocalScopeVariable getLocalVariable() {
result = localVar
final override Language::AutomaticVariable getVariable() {
result = var
}
}
class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable {
class IRStaticUserVariable extends IRUserVariable {
override Language::StaticVariable var;
IRStaticUserVariable() {
this = TIRStaticUserVariable(var, func)
not Language::isVariableAutomatic(var)
}
final override Language::StaticVariable getVariable() {
result = var
}
}
IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) {
IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
result.getAST() = ast and
result.getTag() = tag
}
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
Locatable ast;
Language::AST ast;
TempVariableTag tag;
Type type;
Language::Type type;
IRTempVariable() {
this = TIRTempVariable(func, ast, tag, type)
}
override final Type getType() {
override final Language::Type getType() {
result = type
}
override final Locatable getAST() {
override final Language::AST getAST() {
result = ast
}

View File

@@ -3,11 +3,9 @@ import IRFunction
import IRBlock
import IRVariable
import Operand
private import cpp
import semmle.code.cpp.ir.implementation.EdgeKind
import semmle.code.cpp.ir.implementation.MemoryAccessKind
import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.Print
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.internal.OperandTag
@@ -60,7 +58,7 @@ module InstructionSanity {
message = "Instruction '" + instr.getOpcode().toString() + "' is missing an expected operand with tag '" +
tag.toString() + "' in function '$@'." and
func = instr.getEnclosingIRFunction() and
funcText = getIdentityString(func.getFunction())
funcText = Language::getIdentityString(func.getFunction())
)
}
@@ -101,10 +99,10 @@ module InstructionSanity {
}
query predicate missingOperandType(Operand operand, string message) {
exists(Function func |
exists(Language::Function func |
not exists(operand.getType()) and
func = operand.getUse().getEnclosingFunction() and
message = "Operand missing type in function '" + getIdentityString(func) + "'."
message = "Operand missing type in function '" + Language::getIdentityString(func) + "'."
)
}
@@ -135,14 +133,13 @@ module InstructionSanity {
* Holds if `instr` in `f` is part of a loop even though the AST of `f`
* contains no element that can cause loops.
*/
query predicate unexplainedLoop(Function f, Instruction instr) {
query predicate unexplainedLoop(Language::Function f, Instruction instr) {
exists(IRBlock block |
instr.getBlock() = block and
block.getEnclosingFunction() = f and
block.getASuccessor+() = block
) and
not exists(Loop l | l.getEnclosingFunction() = f) and
not exists(GotoStmt s | s.getEnclosingFunction() = f)
not Language::hasPotentialLoop(f)
}
/**
@@ -201,7 +198,7 @@ module InstructionSanity {
entry = f.getEntryBlock() and
entry.getASuccessor+() = block and
not forwardEdge+(entry, block) and
not exists(GotoStmt s | s.getEnclosingFunction() = f.getFunction())
not Language::hasGoto(f.getFunction())
)
}
@@ -209,7 +206,7 @@ module InstructionSanity {
* Holds if the number of back edges differs between the `Instruction` graph
* and the `IRBlock` graph.
*/
query predicate backEdgeCountMismatch(Function f, int fromInstr, int fromBlock) {
query predicate backEdgeCountMismatch(Language::Function f, int fromInstr, int fromBlock) {
fromInstr = count(Instruction i1, Instruction i2 |
i1.getEnclosingFunction() = f and i1.getBackEdgeSuccessor(_) = i2
) and
@@ -266,7 +263,7 @@ class Instruction extends Construction::TInstruction {
}
private string getResultPrefix() {
if getResultType() instanceof VoidType then
if getResultType() instanceof Language::VoidType then
result = "v"
else if hasMemoryResult() then
if isResultModeled() then
@@ -312,7 +309,7 @@ class Instruction extends Construction::TInstruction {
string getResultTypeString() {
exists(string valcat |
valcat = getValueCategoryString(getResultType().toString()) and
if (getResultType() instanceof UnknownType and
if (getResultType() instanceof Language::UnknownType and
not isGLValue() and
exists(getResultSize())) then (
result = valcat + "[" + getResultSize().toString() + "]"
@@ -379,7 +376,7 @@ class Instruction extends Construction::TInstruction {
/**
* Gets the function that contains this instruction.
*/
final Function getEnclosingFunction() {
final Language::Function getEnclosingFunction() {
result = getEnclosingIRFunction().getFunction()
}
@@ -393,28 +390,28 @@ class Instruction extends Construction::TInstruction {
/**
* Gets the AST that caused this instruction to be generated.
*/
final Locatable getAST() {
final Language::AST getAST() {
result = Construction::getInstructionAST(this)
}
/**
* Gets the location of the source code for this instruction.
*/
final Location getLocation() {
final Language::Location getLocation() {
result = getAST().getLocation()
}
/**
* Gets the `Expr` whose result is computed by this instruction, if any.
*/
final Expr getConvertedResultExpression() {
final Language::Expr getConvertedResultExpression() {
result = Construction::getInstructionConvertedResultExpression(this)
}
/**
* Gets the unconverted `Expr` whose result is computed by this instruction, if any.
*/
final Expr getUnconvertedResultExpression() {
final Language::Expr getUnconvertedResultExpression() {
result = Construction::getInstructionUnconvertedResultExpression(this)
}
@@ -425,7 +422,7 @@ class Instruction extends Construction::TInstruction {
* If `isGLValue()` holds, then the result type of this instruction should be
* thought of as "pointer to `getResultType()`".
*/
final Type getResultType() {
final Language::Type getResultType() {
Construction::instructionHasType(this, result, _)
}
@@ -461,11 +458,9 @@ class Instruction extends Construction::TInstruction {
final int getResultSize() {
if isGLValue() then (
// a glvalue is always pointer-sized.
exists(NullPointerType nullptr |
result = nullptr.getSize()
)
result = Language::getPointerSize()
)
else if getResultType() instanceof UnknownType then
else if getResultType() instanceof Language::UnknownType then
result = Construction::getInstructionResultSize(this)
else (
result = getResultType().getSize()
@@ -616,7 +611,7 @@ class VariableInstruction extends Instruction {
}
class FieldInstruction extends Instruction {
Field field;
Language::Field field;
FieldInstruction() {
field = Construction::getInstructionField(this)
@@ -626,13 +621,13 @@ class FieldInstruction extends Instruction {
result = field.toString()
}
final Field getField() {
final Language::Field getField() {
result = field
}
}
class FunctionInstruction extends Instruction {
Function funcSymbol;
Language::Function funcSymbol;
FunctionInstruction() {
funcSymbol = Construction::getInstructionFunction(this)
@@ -642,7 +637,7 @@ class FunctionInstruction extends Instruction {
result = funcSymbol.toString()
}
final Function getFunctionSymbol() {
final Language::Function getFunctionSymbol() {
result = funcSymbol
}
}
@@ -680,7 +675,7 @@ class InitializeParameterInstruction extends VariableInstruction {
getOpcode() instanceof Opcode::InitializeParameter
}
final Parameter getParameter() {
final Language::Parameter getParameter() {
result = var.(IRUserVariable).getVariable()
}
@@ -738,9 +733,9 @@ class UninitializedInstruction extends VariableInstruction {
}
/**
* Gets the `LocalVariable` that is uninitialized.
* Gets the variable that is uninitialized.
*/
final LocalVariable getLocalVariable() {
final Language::Variable getLocalVariable() {
result = var.(IRUserVariable).getVariable()
}
}
@@ -877,28 +872,28 @@ class ConstantInstruction extends ConstantValueInstruction {
class IntegerConstantInstruction extends ConstantInstruction {
IntegerConstantInstruction() {
getResultType() instanceof IntegralType
getResultType() instanceof Language::IntegralType
}
}
class FloatConstantInstruction extends ConstantInstruction {
FloatConstantInstruction() {
getResultType() instanceof FloatingPointType
getResultType() instanceof Language::FloatingPointType
}
}
class StringConstantInstruction extends Instruction {
StringLiteral value;
Language::StringLiteral value;
StringConstantInstruction() {
value = Construction::getInstructionStringLiteral(this)
}
override final string getImmediateString() {
result = value.getValueText().replaceAll("\n", " ").replaceAll("\r", "").replaceAll("\t", " ")
result = Language::getStringLiteralText(value)
}
final StringLiteral getValue() {
final Language::StringLiteral getValue() {
result = value
}
}
@@ -1086,8 +1081,8 @@ class ConvertInstruction extends UnaryInstruction {
* related by inheritance.
*/
class InheritanceConversionInstruction extends UnaryInstruction {
Class baseClass;
Class derivedClass;
Language::Class baseClass;
Language::Class derivedClass;
InheritanceConversionInstruction() {
Construction::getInstructionInheritance(this, baseClass, derivedClass)
@@ -1102,7 +1097,7 @@ class InheritanceConversionInstruction extends UnaryInstruction {
* the base and derived classes. This predicate does not hold if the
* conversion is to an indirect virtual base class.
*/
final ClassDerivation getDerivation() {
final Language::ClassDerivation getDerivation() {
result.getBaseClass() = baseClass and result.getDerivedClass() = derivedClass
}
@@ -1111,14 +1106,14 @@ class InheritanceConversionInstruction extends UnaryInstruction {
* base class of the derived class, or a virtual base class of the
* derived class.
*/
final Class getBaseClass() {
final Language::Class getBaseClass() {
result = baseClass
}
/**
* Gets the derived class of the conversion.
*/
final Class getDerivedClass() {
final Language::Class getDerivedClass() {
result = derivedClass
}
}
@@ -1349,7 +1344,7 @@ class CallInstruction extends Instruction {
/**
* Gets the `Function` that the call targets, if this is statically known.
*/
final Function getStaticCallTarget() {
final Language::Function getStaticCallTarget() {
result = getCallTarget().(FunctionInstruction).getFunctionSymbol()
}
@@ -1591,7 +1586,7 @@ class CatchInstruction extends Instruction {
* An instruction that catches an exception of a specific type.
*/
class CatchByTypeInstruction extends CatchInstruction {
Type exceptionType;
Language::Type exceptionType;
CatchByTypeInstruction() {
getOpcode() instanceof Opcode::CatchByType and
@@ -1605,7 +1600,7 @@ class CatchByTypeInstruction extends CatchInstruction {
/**
* Gets the type of exception to be caught.
*/
final Type getExceptionType() {
final Language::Type getExceptionType() {
result = exceptionType
}
}

View File

@@ -1,7 +1,6 @@
private import internal.IRInternal
import Instruction
import IRBlock
private import cpp
import semmle.code.cpp.ir.implementation.MemoryAccessKind
import semmle.code.cpp.ir.internal.Overlap
private import semmle.code.cpp.ir.internal.OperandTag
@@ -50,7 +49,7 @@ class Operand extends TOperand {
result = "Operand"
}
final Location getLocation() {
final Language::Location getLocation() {
result = getUse().getLocation()
}
@@ -166,7 +165,7 @@ class Operand extends TOperand {
* the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type.
*/
Type getType() {
Language::Type getType() {
result = getAnyDef().getResultType()
}
@@ -284,7 +283,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
class TypedOperand extends NonPhiMemoryOperand {
override TypedOperandTag tag;
override final Type getType() {
override final Language::Type getType() {
result = Construction::getInstructionOperandType(useInstr, tag)
}
}
@@ -447,7 +446,7 @@ class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override final int getSize() {
if getType() instanceof UnknownType then
if getType() instanceof Language::UnknownType then
result = Construction::getInstructionOperandSize(useInstr, tag)
else
result = getType().getSize()

View File

@@ -1,5 +1,5 @@
private import semmle.code.cpp.ir.internal.IRLanguageInternal
private import IR
private import cpp
import semmle.code.cpp.ir.IRConfiguration
private import semmle.code.cpp.Print
@@ -17,12 +17,12 @@ class PrintIRConfiguration extends TPrintIRConfiguration {
* Holds if the IR for `func` should be printed. By default, holds for all
* functions.
*/
predicate shouldPrintFunction(Function func) {
predicate shouldPrintFunction(Language::Function func) {
any()
}
}
private predicate shouldPrintFunction(Function func) {
private predicate shouldPrintFunction(Language::Function func) {
exists(PrintIRConfiguration config |
config.shouldPrintFunction(func)
)
@@ -32,7 +32,7 @@ private predicate shouldPrintFunction(Function func) {
* Override of `IRConfiguration` to only create IR for the functions that are to be dumped.
*/
private class FilteredIRConfiguration extends IRConfiguration {
override predicate shouldCreateIRForFunction(Function func) {
override predicate shouldCreateIRForFunction(Language::Function func) {
shouldPrintFunction(func)
}
}
@@ -69,7 +69,7 @@ abstract class PrintableIRNode extends TPrintableIRNode {
/**
* Gets the location to be emitted for the node.
*/
abstract Location getLocation();
abstract Language::Location getLocation();
/**
* Gets the label to be emitted for the node.
@@ -126,7 +126,7 @@ class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
result = irFunc.toString()
}
override Location getLocation() {
override Language::Location getLocation() {
result = irFunc.getLocation()
}
@@ -135,7 +135,7 @@ class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
}
override int getOrder() {
this = rank[result + 1](PrintableIRFunction orderedFunc, Location location |
this = rank[result + 1](PrintableIRFunction orderedFunc, Language::Location location |
location = orderedFunc.getIRFunction().getLocation() |
orderedFunc order by location.getFile().getAbsolutePath(), location.getStartLine(),
location.getStartColumn(), orderedFunc.getLabel()
@@ -165,7 +165,7 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
result = getLabel()
}
override Location getLocation() {
override Language::Location getLocation() {
result = block.getLocation()
}

View File

@@ -1,4 +1,4 @@
import cpp
private import cpp
import semmle.code.cpp.ir.implementation.raw.IR
private import semmle.code.cpp.ir.internal.OperandTag
private import semmle.code.cpp.ir.internal.TempVariableTag
@@ -28,6 +28,10 @@ cached private module Cached {
element.hasInstruction(_, tag, _, _)
}
cached predicate hasUserVariable(Function func, Variable var, Type type) {
getTranslatedFunction(func).hasUserVariable(var, type)
}
cached predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag,
Type type) {
exists(TranslatedElement element |

View File

@@ -1 +1,2 @@
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import IRConstruction as Construction

View File

@@ -1,4 +1,4 @@
import cpp
private import cpp
private predicate fieldIsInitialized(Field field) {
exists(ClassAggregateLiteral initList |

View File

@@ -1,4 +1,4 @@
import cpp
private import cpp
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.internal.OperandTag
private import semmle.code.cpp.models.interfaces.SideEffect

View File

@@ -1,4 +1,4 @@
import cpp
private import cpp
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.internal.OperandTag
private import InstructionTag

View File

@@ -1,4 +1,4 @@
import cpp
private import cpp
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.internal.IRUtilities
private import semmle.code.cpp.ir.internal.OperandTag

View File

@@ -1,5 +1,4 @@
import cpp
import cpp
private import cpp
import semmle.code.cpp.ir.implementation.raw.IR
private import semmle.code.cpp.ir.IRConfiguration
private import semmle.code.cpp.ir.implementation.Opcode

View File

@@ -1,4 +1,4 @@
import cpp
private import cpp
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.internal.OperandTag
private import semmle.code.cpp.ir.internal.TempVariableTag

View File

@@ -1,4 +1,4 @@
import cpp
private import cpp
import semmle.code.cpp.ir.implementation.raw.IR
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.internal.IRUtilities
@@ -310,6 +310,29 @@ class TranslatedFunction extends TranslatedElement,
)
}
/**
* Holds if this function defines or accesses variable `var` with type `type`. This includes all
* parameters and local variables, plus any global variables or static data members that are
* directly accessed by the function.
*/
final predicate hasUserVariable(Variable var, Type type) {
(
(
(
var instanceof GlobalOrNamespaceVariable or
var instanceof MemberVariable and not var instanceof Field
) and
exists(VariableAccess access |
access.getTarget() = var and
access.getEnclosingFunction() = func
)
) or
var.(LocalScopeVariable).getFunction() = func or
var.(Parameter).getCatchBlock().getEnclosingFunction() = func
) and
type = getVariableType(var)
}
private final Type getReturnType() {
result = func.getUnspecifiedType()
}

View File

@@ -1,4 +1,4 @@
import cpp
private import cpp
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.internal.OperandTag
private import InstructionTag

View File

@@ -1,6 +1,7 @@
import cpp
private import semmle.code.cpp.ir.internal.TempVariableTag
private import cpp
private import semmle.code.cpp.ir.internal.IRUtilities
private import semmle.code.cpp.ir.internal.OperandTag
private import semmle.code.cpp.ir.internal.TempVariableTag
private import InstructionTag
private import TranslatedCondition
private import TranslatedDeclarationEntry
@@ -760,6 +761,14 @@ class TranslatedJumpStmt extends TranslatedStmt {
}
}
private EdgeKind getCaseEdge(SwitchCase switchCase) {
exists(CaseEdge edge |
result = edge and
hasCaseEdge(switchCase, edge.getMinValue(), edge.getMaxValue())
) or
(switchCase instanceof DefaultCase and result instanceof DefaultEdge)
}
class TranslatedSwitchStmt extends TranslatedStmt {
override SwitchStmt stmt;

View File

@@ -19,7 +19,7 @@ class IRBlockBase extends TIRBlock {
result = getFirstInstruction(this).toString()
}
final Location getLocation() {
final Language::Location getLocation() {
result = getFirstInstruction().getLocation()
}
@@ -67,7 +67,7 @@ class IRBlockBase extends TIRBlock {
result = getFirstInstruction(this).getEnclosingIRFunction()
}
final Function getEnclosingFunction() {
final Language::Function getEnclosingFunction() {
result = getFirstInstruction(this).getEnclosingFunction()
}
}

View File

@@ -1,9 +1,8 @@
private import internal.IRInternal
import Instruction
private import cpp
private newtype TIRFunction =
MkIRFunction(Function func) {
MkIRFunction(Language::Function func) {
Construction::functionHasIR(func)
}
@@ -11,7 +10,7 @@ private newtype TIRFunction =
* Represents the IR for a function.
*/
class IRFunction extends TIRFunction {
Function func;
Language::Function func;
IRFunction() {
this = MkIRFunction(func)
@@ -24,14 +23,14 @@ class IRFunction extends TIRFunction {
/**
* Gets the function whose IR is represented.
*/
final Function getFunction() {
final Language::Function getFunction() {
result = func
}
/**
* Gets the location of the function.
*/
final Location getLocation() {
final Language::Location getLocation() {
result = func.getLocation()
}

View File

@@ -1,12 +1,11 @@
private import internal.IRInternal
import IRFunction
private import cpp
import semmle.code.cpp.ir.implementation.TempVariableTag
private import semmle.code.cpp.ir.internal.IRUtilities
private import semmle.code.cpp.ir.internal.TempVariableTag
private import semmle.code.cpp.ir.internal.TIRVariable
IRUserVariable getIRUserVariable(Function func, Variable var) {
IRUserVariable getIRUserVariable(Language::Function func, Language::Variable var) {
result.getVariable() = var and
result.getEnclosingFunction() = func
}
@@ -17,20 +16,20 @@ IRUserVariable getIRUserVariable(Function func, Variable var) {
* generated by the AST-to-IR translation (`IRTempVariable`).
*/
abstract class IRVariable extends TIRVariable {
Function func;
Language::Function func;
abstract string toString();
/**
* Gets the type of the variable.
*/
abstract Type getType();
abstract Language::Type getType();
/**
* Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation.
*/
abstract Locatable getAST();
abstract Language::AST getAST();
/**
* Gets an identifier string for the variable. This identifier is unique
@@ -41,7 +40,7 @@ abstract class IRVariable extends TIRVariable {
/**
* Gets the source location of this variable.
*/
final Location getLocation() {
final Language::Location getLocation() {
result = getAST().getLocation()
}
@@ -55,7 +54,7 @@ abstract class IRVariable extends TIRVariable {
/**
* Gets the function that references this variable.
*/
final Function getEnclosingFunction() {
final Language::Function getEnclosingFunction() {
result = func
}
}
@@ -63,29 +62,34 @@ abstract class IRVariable extends TIRVariable {
/**
* Represents a user-declared variable referenced by the IR for a function.
*/
abstract class IRUserVariable extends IRVariable {
Variable var;
class IRUserVariable extends IRVariable, TIRUserVariable {
Language::Variable var;
Language::Type type;
IRUserVariable() {
this = TIRUserVariable(var, type, func)
}
override final string toString() {
result = var.toString()
result = getVariable().toString()
}
override final Type getType() {
result = getVariableType(var)
}
override final Locatable getAST() {
override final Language::AST getAST() {
result = var
}
override final string getUniqueId() {
result = var.toString() + " " + var.getLocation().toString()
result = getVariable().toString() + " " + getVariable().getLocation().toString()
}
override final Language::Type getType() {
result = type
}
/**
* Gets the original user-declared variable.
*/
final Variable getVariable() {
Language::Variable getVariable() {
result = var
}
}
@@ -98,45 +102,49 @@ abstract class IRUserVariable extends IRVariable {
abstract class IRAutomaticVariable extends IRVariable {
}
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable,
TIRAutomaticUserVariable {
LocalScopeVariable localVar;
class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
override Language::AutomaticVariable var;
IRAutomaticUserVariable() {
this = TIRAutomaticUserVariable(localVar, func) and
var = localVar
Language::isVariableAutomatic(var)
}
final LocalScopeVariable getLocalVariable() {
result = localVar
final override Language::AutomaticVariable getVariable() {
result = var
}
}
class IRStaticUserVariable extends IRUserVariable, TIRStaticUserVariable {
class IRStaticUserVariable extends IRUserVariable {
override Language::StaticVariable var;
IRStaticUserVariable() {
this = TIRStaticUserVariable(var, func)
not Language::isVariableAutomatic(var)
}
final override Language::StaticVariable getVariable() {
result = var
}
}
IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) {
IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) {
result.getAST() = ast and
result.getTag() = tag
}
class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable {
Locatable ast;
Language::AST ast;
TempVariableTag tag;
Type type;
Language::Type type;
IRTempVariable() {
this = TIRTempVariable(func, ast, tag, type)
}
override final Type getType() {
override final Language::Type getType() {
result = type
}
override final Locatable getAST() {
override final Language::AST getAST() {
result = ast
}

View File

@@ -3,11 +3,9 @@ import IRFunction
import IRBlock
import IRVariable
import Operand
private import cpp
import semmle.code.cpp.ir.implementation.EdgeKind
import semmle.code.cpp.ir.implementation.MemoryAccessKind
import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.Print
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.internal.OperandTag
@@ -60,7 +58,7 @@ module InstructionSanity {
message = "Instruction '" + instr.getOpcode().toString() + "' is missing an expected operand with tag '" +
tag.toString() + "' in function '$@'." and
func = instr.getEnclosingIRFunction() and
funcText = getIdentityString(func.getFunction())
funcText = Language::getIdentityString(func.getFunction())
)
}
@@ -101,10 +99,10 @@ module InstructionSanity {
}
query predicate missingOperandType(Operand operand, string message) {
exists(Function func |
exists(Language::Function func |
not exists(operand.getType()) and
func = operand.getUse().getEnclosingFunction() and
message = "Operand missing type in function '" + getIdentityString(func) + "'."
message = "Operand missing type in function '" + Language::getIdentityString(func) + "'."
)
}
@@ -135,14 +133,13 @@ module InstructionSanity {
* Holds if `instr` in `f` is part of a loop even though the AST of `f`
* contains no element that can cause loops.
*/
query predicate unexplainedLoop(Function f, Instruction instr) {
query predicate unexplainedLoop(Language::Function f, Instruction instr) {
exists(IRBlock block |
instr.getBlock() = block and
block.getEnclosingFunction() = f and
block.getASuccessor+() = block
) and
not exists(Loop l | l.getEnclosingFunction() = f) and
not exists(GotoStmt s | s.getEnclosingFunction() = f)
not Language::hasPotentialLoop(f)
}
/**
@@ -201,7 +198,7 @@ module InstructionSanity {
entry = f.getEntryBlock() and
entry.getASuccessor+() = block and
not forwardEdge+(entry, block) and
not exists(GotoStmt s | s.getEnclosingFunction() = f.getFunction())
not Language::hasGoto(f.getFunction())
)
}
@@ -209,7 +206,7 @@ module InstructionSanity {
* Holds if the number of back edges differs between the `Instruction` graph
* and the `IRBlock` graph.
*/
query predicate backEdgeCountMismatch(Function f, int fromInstr, int fromBlock) {
query predicate backEdgeCountMismatch(Language::Function f, int fromInstr, int fromBlock) {
fromInstr = count(Instruction i1, Instruction i2 |
i1.getEnclosingFunction() = f and i1.getBackEdgeSuccessor(_) = i2
) and
@@ -266,7 +263,7 @@ class Instruction extends Construction::TInstruction {
}
private string getResultPrefix() {
if getResultType() instanceof VoidType then
if getResultType() instanceof Language::VoidType then
result = "v"
else if hasMemoryResult() then
if isResultModeled() then
@@ -312,7 +309,7 @@ class Instruction extends Construction::TInstruction {
string getResultTypeString() {
exists(string valcat |
valcat = getValueCategoryString(getResultType().toString()) and
if (getResultType() instanceof UnknownType and
if (getResultType() instanceof Language::UnknownType and
not isGLValue() and
exists(getResultSize())) then (
result = valcat + "[" + getResultSize().toString() + "]"
@@ -379,7 +376,7 @@ class Instruction extends Construction::TInstruction {
/**
* Gets the function that contains this instruction.
*/
final Function getEnclosingFunction() {
final Language::Function getEnclosingFunction() {
result = getEnclosingIRFunction().getFunction()
}
@@ -393,28 +390,28 @@ class Instruction extends Construction::TInstruction {
/**
* Gets the AST that caused this instruction to be generated.
*/
final Locatable getAST() {
final Language::AST getAST() {
result = Construction::getInstructionAST(this)
}
/**
* Gets the location of the source code for this instruction.
*/
final Location getLocation() {
final Language::Location getLocation() {
result = getAST().getLocation()
}
/**
* Gets the `Expr` whose result is computed by this instruction, if any.
*/
final Expr getConvertedResultExpression() {
final Language::Expr getConvertedResultExpression() {
result = Construction::getInstructionConvertedResultExpression(this)
}
/**
* Gets the unconverted `Expr` whose result is computed by this instruction, if any.
*/
final Expr getUnconvertedResultExpression() {
final Language::Expr getUnconvertedResultExpression() {
result = Construction::getInstructionUnconvertedResultExpression(this)
}
@@ -425,7 +422,7 @@ class Instruction extends Construction::TInstruction {
* If `isGLValue()` holds, then the result type of this instruction should be
* thought of as "pointer to `getResultType()`".
*/
final Type getResultType() {
final Language::Type getResultType() {
Construction::instructionHasType(this, result, _)
}
@@ -461,11 +458,9 @@ class Instruction extends Construction::TInstruction {
final int getResultSize() {
if isGLValue() then (
// a glvalue is always pointer-sized.
exists(NullPointerType nullptr |
result = nullptr.getSize()
)
result = Language::getPointerSize()
)
else if getResultType() instanceof UnknownType then
else if getResultType() instanceof Language::UnknownType then
result = Construction::getInstructionResultSize(this)
else (
result = getResultType().getSize()
@@ -616,7 +611,7 @@ class VariableInstruction extends Instruction {
}
class FieldInstruction extends Instruction {
Field field;
Language::Field field;
FieldInstruction() {
field = Construction::getInstructionField(this)
@@ -626,13 +621,13 @@ class FieldInstruction extends Instruction {
result = field.toString()
}
final Field getField() {
final Language::Field getField() {
result = field
}
}
class FunctionInstruction extends Instruction {
Function funcSymbol;
Language::Function funcSymbol;
FunctionInstruction() {
funcSymbol = Construction::getInstructionFunction(this)
@@ -642,7 +637,7 @@ class FunctionInstruction extends Instruction {
result = funcSymbol.toString()
}
final Function getFunctionSymbol() {
final Language::Function getFunctionSymbol() {
result = funcSymbol
}
}
@@ -680,7 +675,7 @@ class InitializeParameterInstruction extends VariableInstruction {
getOpcode() instanceof Opcode::InitializeParameter
}
final Parameter getParameter() {
final Language::Parameter getParameter() {
result = var.(IRUserVariable).getVariable()
}
@@ -738,9 +733,9 @@ class UninitializedInstruction extends VariableInstruction {
}
/**
* Gets the `LocalVariable` that is uninitialized.
* Gets the variable that is uninitialized.
*/
final LocalVariable getLocalVariable() {
final Language::Variable getLocalVariable() {
result = var.(IRUserVariable).getVariable()
}
}
@@ -877,28 +872,28 @@ class ConstantInstruction extends ConstantValueInstruction {
class IntegerConstantInstruction extends ConstantInstruction {
IntegerConstantInstruction() {
getResultType() instanceof IntegralType
getResultType() instanceof Language::IntegralType
}
}
class FloatConstantInstruction extends ConstantInstruction {
FloatConstantInstruction() {
getResultType() instanceof FloatingPointType
getResultType() instanceof Language::FloatingPointType
}
}
class StringConstantInstruction extends Instruction {
StringLiteral value;
Language::StringLiteral value;
StringConstantInstruction() {
value = Construction::getInstructionStringLiteral(this)
}
override final string getImmediateString() {
result = value.getValueText().replaceAll("\n", " ").replaceAll("\r", "").replaceAll("\t", " ")
result = Language::getStringLiteralText(value)
}
final StringLiteral getValue() {
final Language::StringLiteral getValue() {
result = value
}
}
@@ -1086,8 +1081,8 @@ class ConvertInstruction extends UnaryInstruction {
* related by inheritance.
*/
class InheritanceConversionInstruction extends UnaryInstruction {
Class baseClass;
Class derivedClass;
Language::Class baseClass;
Language::Class derivedClass;
InheritanceConversionInstruction() {
Construction::getInstructionInheritance(this, baseClass, derivedClass)
@@ -1102,7 +1097,7 @@ class InheritanceConversionInstruction extends UnaryInstruction {
* the base and derived classes. This predicate does not hold if the
* conversion is to an indirect virtual base class.
*/
final ClassDerivation getDerivation() {
final Language::ClassDerivation getDerivation() {
result.getBaseClass() = baseClass and result.getDerivedClass() = derivedClass
}
@@ -1111,14 +1106,14 @@ class InheritanceConversionInstruction extends UnaryInstruction {
* base class of the derived class, or a virtual base class of the
* derived class.
*/
final Class getBaseClass() {
final Language::Class getBaseClass() {
result = baseClass
}
/**
* Gets the derived class of the conversion.
*/
final Class getDerivedClass() {
final Language::Class getDerivedClass() {
result = derivedClass
}
}
@@ -1349,7 +1344,7 @@ class CallInstruction extends Instruction {
/**
* Gets the `Function` that the call targets, if this is statically known.
*/
final Function getStaticCallTarget() {
final Language::Function getStaticCallTarget() {
result = getCallTarget().(FunctionInstruction).getFunctionSymbol()
}
@@ -1591,7 +1586,7 @@ class CatchInstruction extends Instruction {
* An instruction that catches an exception of a specific type.
*/
class CatchByTypeInstruction extends CatchInstruction {
Type exceptionType;
Language::Type exceptionType;
CatchByTypeInstruction() {
getOpcode() instanceof Opcode::CatchByType and
@@ -1605,7 +1600,7 @@ class CatchByTypeInstruction extends CatchInstruction {
/**
* Gets the type of exception to be caught.
*/
final Type getExceptionType() {
final Language::Type getExceptionType() {
result = exceptionType
}
}

View File

@@ -1,7 +1,6 @@
private import internal.IRInternal
import Instruction
import IRBlock
private import cpp
import semmle.code.cpp.ir.implementation.MemoryAccessKind
import semmle.code.cpp.ir.internal.Overlap
private import semmle.code.cpp.ir.internal.OperandTag
@@ -50,7 +49,7 @@ class Operand extends TOperand {
result = "Operand"
}
final Location getLocation() {
final Language::Location getLocation() {
result = getUse().getLocation()
}
@@ -166,7 +165,7 @@ class Operand extends TOperand {
* the definition type, such as in the case of a partial read or a read from a pointer that
* has been cast to a different type.
*/
Type getType() {
Language::Type getType() {
result = getAnyDef().getResultType()
}
@@ -284,7 +283,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
class TypedOperand extends NonPhiMemoryOperand {
override TypedOperandTag tag;
override final Type getType() {
override final Language::Type getType() {
result = Construction::getInstructionOperandType(useInstr, tag)
}
}
@@ -447,7 +446,7 @@ class SideEffectOperand extends TypedOperand {
override SideEffectOperandTag tag;
override final int getSize() {
if getType() instanceof UnknownType then
if getType() instanceof Language::UnknownType then
result = Construction::getInstructionOperandSize(useInstr, tag)
else
result = getType().getSize()

View File

@@ -1,5 +1,5 @@
private import semmle.code.cpp.ir.internal.IRLanguageInternal
private import IR
private import cpp
import semmle.code.cpp.ir.IRConfiguration
private import semmle.code.cpp.Print
@@ -17,12 +17,12 @@ class PrintIRConfiguration extends TPrintIRConfiguration {
* Holds if the IR for `func` should be printed. By default, holds for all
* functions.
*/
predicate shouldPrintFunction(Function func) {
predicate shouldPrintFunction(Language::Function func) {
any()
}
}
private predicate shouldPrintFunction(Function func) {
private predicate shouldPrintFunction(Language::Function func) {
exists(PrintIRConfiguration config |
config.shouldPrintFunction(func)
)
@@ -32,7 +32,7 @@ private predicate shouldPrintFunction(Function func) {
* Override of `IRConfiguration` to only create IR for the functions that are to be dumped.
*/
private class FilteredIRConfiguration extends IRConfiguration {
override predicate shouldCreateIRForFunction(Function func) {
override predicate shouldCreateIRForFunction(Language::Function func) {
shouldPrintFunction(func)
}
}
@@ -69,7 +69,7 @@ abstract class PrintableIRNode extends TPrintableIRNode {
/**
* Gets the location to be emitted for the node.
*/
abstract Location getLocation();
abstract Language::Location getLocation();
/**
* Gets the label to be emitted for the node.
@@ -126,7 +126,7 @@ class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
result = irFunc.toString()
}
override Location getLocation() {
override Language::Location getLocation() {
result = irFunc.getLocation()
}
@@ -135,7 +135,7 @@ class PrintableIRFunction extends PrintableIRNode, TPrintableIRFunction {
}
override int getOrder() {
this = rank[result + 1](PrintableIRFunction orderedFunc, Location location |
this = rank[result + 1](PrintableIRFunction orderedFunc, Language::Location location |
location = orderedFunc.getIRFunction().getLocation() |
orderedFunc order by location.getFile().getAbsolutePath(), location.getStartLine(),
location.getStartColumn(), orderedFunc.getLabel()
@@ -165,7 +165,7 @@ class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
result = getLabel()
}
override Location getLocation() {
override Language::Location getLocation() {
result = block.getLocation()
}

View File

@@ -1 +1,2 @@
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
import SSAConstruction as Construction

View File

@@ -0,0 +1,75 @@
private import cpp as Cpp
private import semmle.code.cpp.Print as Print
private import IRUtilities
class Function = Cpp::Function;
class Location = Cpp::Location;
class AST = Cpp::Locatable;
class Type = Cpp::Type;
class UnknownType = Cpp::UnknownType;
class VoidType = Cpp::VoidType;
class IntegralType = Cpp::IntegralType;
class FloatingPointType = Cpp::FloatingPointType;
// REVIEW: May need to synthesize this for other languages. Or do we really need it at all?
class ClassDerivation = Cpp::ClassDerivation;
class StringLiteral = Cpp::StringLiteral;
class Variable = Cpp::Variable;
class AutomaticVariable = Cpp::LocalScopeVariable;
class StaticVariable = Cpp::Variable;
class Parameter = Cpp::Parameter;
class Field = Cpp::Field;
// TODO: Remove necessity for these.
class Expr = Cpp::Expr;
class Class = Cpp::Class; // Used for inheritance conversions
predicate getIdentityString = Print::getIdentityString/1;
predicate hasCaseEdge(string minValue, string maxValue) {
exists(Cpp::SwitchCase switchCase |
hasCaseEdge(switchCase, minValue, maxValue)
)
}
predicate hasPositionalArgIndex(int argIndex) {
exists(Cpp::FunctionCall call |
exists(call.getArgument(argIndex))
) or
exists(Cpp::BuiltInOperation op |
exists(op.getChild(argIndex))
)
}
predicate hasAsmOperandIndex(int operandIndex) {
exists(Cpp::AsmStmt asm |
exists(asm.getChild(operandIndex))
)
}
int getPointerSize() {
exists(Cpp::NullPointerType nullptr |
result = nullptr.getSize()
)
}
predicate isVariableAutomatic(Variable var) {
var instanceof Cpp::LocalScopeVariable and
not var.(Cpp::LocalScopeVariable).isStatic()
}
string getStringLiteralText(StringLiteral s) {
result = s.getValueText().replaceAll("\n", " ").replaceAll("\r", "").replaceAll("\t", " ")
}
predicate hasPotentialLoop(Function f) {
exists(Cpp::Loop l | l.getEnclosingFunction() = f) or
exists(Cpp::GotoStmt s | s.getEnclosingFunction() = f)
}
predicate hasGoto(Function f) {
exists(Cpp::GotoStmt s | s.getEnclosingFunction() = f)
}

View File

@@ -0,0 +1 @@
import IRCppLanguage as Language

View File

@@ -32,3 +32,11 @@ Type getVariableType(Variable v) {
)
)
}
predicate hasCaseEdge(SwitchCase switchCase, string minValue, string maxValue) {
minValue = switchCase.getExpr().getFullyConverted().getValue() and
if exists(switchCase.getEndExpr()) then
maxValue = switchCase.getEndExpr().getFullyConverted().getValue()
else
maxValue = minValue
}

View File

@@ -1,12 +1,4 @@
private import cpp
private int getMaxCallArgIndex() {
result = max(int argIndex |
exists(FunctionCall call |
exists(call.getArgument(argIndex))
)
)
}
private import IRLanguageInternal
private newtype TOperandTag =
TAddressOperand() or
@@ -22,17 +14,12 @@ private newtype TOperandTag =
TCallTargetOperand() or
TThisArgumentOperand() or
TPositionalArgumentOperand(int argIndex) {
argIndex in [0..getMaxCallArgIndex()] or
exists(BuiltInOperation op |
exists(op.getChild(argIndex))
)
Language::hasPositionalArgIndex(argIndex)
} or
TChiTotalOperand() or
TChiPartialOperand() or
TAsmOperand(int index) {
exists(AsmStmt asm |
exists(asm.getChild(index))
)
Language::hasAsmOperandIndex(index)
}
/**

View File

@@ -1,25 +1,13 @@
private import cpp
private import IRLanguageInternal
private import semmle.code.cpp.ir.implementation.TempVariableTag
private import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as Construction
newtype TIRVariable =
TIRAutomaticUserVariable(LocalScopeVariable var, Function func) {
Construction::functionHasIR(func) and
var.getFunction() = func or
var.(Parameter).getCatchBlock().getEnclosingFunction() = func
TIRUserVariable(Language::Variable var, Language::Type type,
Language::Function func) {
Construction::hasUserVariable(func, var, type)
} or
TIRStaticUserVariable(Variable var, Function func) {
Construction::functionHasIR(func) and
(
var instanceof GlobalOrNamespaceVariable or
var instanceof MemberVariable and not var instanceof Field
) and
exists(VariableAccess access |
access.getTarget() = var and
access.getEnclosingFunction() = func
)
} or
TIRTempVariable(Function func, Locatable ast, TempVariableTag tag, Type type) {
TIRTempVariable(Language::Function func, Language::AST ast, TempVariableTag tag,
Language::Type type) {
Construction::hasTempVariable(func, ast, tag, type)
}