mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
C++: Pull a bunch of language-dependent code that the IR depends on out into a separate module
This commit is contained in:
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import cpp
|
||||
|
||||
private newtype TMemoryAccessKind =
|
||||
TIndirectMemoryAccess() or
|
||||
TIndirectMayMemoryAccess() or
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import cpp
|
||||
private import semmle.code.cpp.ir.internal.TempVariableTag
|
||||
|
||||
class TempVariableTag extends TTempVariableTag {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import cpp
|
||||
private import cpp
|
||||
import AliasAnalysis
|
||||
import semmle.code.cpp.ir.internal.Overlap
|
||||
private import semmle.code.cpp.Print
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
import SSAConstruction as Construction
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
import IRConstruction as Construction
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import cpp
|
||||
private import cpp
|
||||
|
||||
private predicate fieldIsInitialized(Field field) {
|
||||
exists(ClassAggregateLiteral initList |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
import SSAConstruction as Construction
|
||||
|
||||
75
cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll
Normal file
75
cpp/ql/src/semmle/code/cpp/ir/internal/IRCppLanguage.qll
Normal 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)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
import IRCppLanguage as Language
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user