diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll index 14399078231..55a59cc9588 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll @@ -49,6 +49,9 @@ class Expr extends StmtParent, @expr { /** Gets the enclosing variable of this expression, if any. */ Variable getEnclosingVariable() { result = exprEnclosingElement(this) } + /** Gets the enclosing variable or function of this expression. */ + Declaration getEnclosingDeclaration() { result = exprEnclosingElement(this) } + /** Gets a child of this expression. */ Expr getAChild() { exists(int n | result = this.getChild(n)) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 4171f5a5227..2bfded52441 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -100,7 +100,7 @@ class Node extends TIRDataFlowNode { Declaration getEnclosingCallable() { none() } // overridden in subclasses /** Gets the function to which this node belongs, if any. */ - Function getFunction() { none() } // overridden in subclasses + Declaration getFunction() { none() } // overridden in subclasses /** Gets the type of this node. */ IRType getType() { none() } // overridden in subclasses @@ -196,7 +196,7 @@ class InstructionNode extends Node, TInstructionNode { override Declaration getEnclosingCallable() { result = this.getFunction() } - override Function getFunction() { result = instr.getEnclosingFunction() } + override Declaration getFunction() { result = instr.getEnclosingFunction() } override IRType getType() { result = instr.getResultIRType() } @@ -222,7 +222,7 @@ class OperandNode extends Node, TOperandNode { override Declaration getEnclosingCallable() { result = this.getFunction() } - override Function getFunction() { result = op.getUse().getEnclosingFunction() } + override Declaration getFunction() { result = op.getUse().getEnclosingFunction() } override IRType getType() { result = op.getIRType() } @@ -274,7 +274,7 @@ class StoreNodeInstr extends StoreNode, TStoreNodeInstr { /** Gets the underlying instruction. */ Instruction getInstruction() { result = instr } - override Function getFunction() { result = this.getInstruction().getEnclosingFunction() } + override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() } override IRType getType() { result = this.getInstruction().getResultIRType() } @@ -328,7 +328,7 @@ class StoreNodeOperand extends StoreNode, TStoreNodeOperand { /** Gets the underlying operand. */ Operand getOperand() { result = operand } - override Function getFunction() { result = operand.getDef().getEnclosingFunction() } + override Declaration getFunction() { result = operand.getDef().getEnclosingFunction() } override IRType getType() { result = operand.getIRType() } @@ -384,7 +384,7 @@ class ReadNode extends Node, TReadNode { override Declaration getEnclosingCallable() { result = this.getFunction() } - override Function getFunction() { result = this.getInstruction().getEnclosingFunction() } + override Declaration getFunction() { result = this.getInstruction().getEnclosingFunction() } override IRType getType() { result = this.getInstruction().getResultIRType() } @@ -436,7 +436,7 @@ class SsaPhiNode extends Node, TSsaPhiNode { override Declaration getEnclosingCallable() { result = this.getFunction() } - override Function getFunction() { result = phi.getBasicBlock().getEnclosingFunction() } + override Declaration getFunction() { result = phi.getBasicBlock().getEnclosingFunction() } override IRType getType() { result instanceof IRVoidType } @@ -673,7 +673,7 @@ class VariableNode extends Node, TVariableNode { /** Gets the variable corresponding to this node. */ Variable getVariable() { result = v } - override Function getFunction() { none() } + override Declaration getFunction() { none() } override Declaration getEnclosingCallable() { // When flow crosses from one _enclosing callable_ to another, the diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/IRConfiguration.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/IRConfiguration.qll index 37ac2fccdd9..90cdb9e0f5f 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/IRConfiguration.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/IRConfiguration.qll @@ -16,7 +16,7 @@ class IRConfiguration extends TIRConfiguration { /** * Holds if IR should be created for function `func`. By default, holds for all functions. */ - predicate shouldCreateIRForFunction(Language::Function func) { any() } + predicate shouldCreateIRForFunction(Language::Declaration func) { any() } /** * Holds if the strings used as part of an IR dump should be generated for function `func`. @@ -25,7 +25,7 @@ class IRConfiguration extends TIRConfiguration { * of debug strings for IR that will not be dumped. We still generate the actual IR for these * functions, however, to preserve the results of any interprocedural analysis. */ - predicate shouldEvaluateDebugStringsForFunction(Language::Function func) { any() } + predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) { any() } } private newtype TIREscapeAnalysisConfiguration = MkIREscapeAnalysisConfiguration() diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll index bac7634cbd0..78008a6c69b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll @@ -97,7 +97,7 @@ class IRBlockBase extends TIRBlock { /** * Gets the `Function` that contains this block. */ - final Language::Function getEnclosingFunction() { + final Language::Declaration getEnclosingFunction() { result = getFirstInstruction(this).getEnclosingFunction() } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRConsistency.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRConsistency.qll index 31983d34247..45b44b14a3c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRConsistency.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRConsistency.qll @@ -524,4 +524,23 @@ module InstructionConsistency { "' has a `this` argument operand that is not an address, in function '$@'." and irFunc = getInstructionIRFunction(instr, irFuncText) } + + query predicate nonUniqueIRVariable( + Instruction instr, string message, OptionalIRFunction irFunc, string irFuncText + ) { + exists(VariableInstruction vi, IRVariable v1, IRVariable v2 | + instr = vi and vi.getIRVariable() = v1 and vi.getIRVariable() = v2 and v1 != v2 + ) and + message = + "Variable instruction '" + instr.toString() + + "' has multiple associated variables, in function '$@'." and + irFunc = getInstructionIRFunction(instr, irFuncText) + or + instr.getOpcode() instanceof Opcode::VariableAddress and + not instr instanceof VariableInstruction and + message = + "Variable address instruction '" + instr.toString() + + "' has no associated variable, in function '$@'." and + irFunc = getInstructionIRFunction(instr, irFuncText) + } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll index ca4708857a7..c92082d767d 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll @@ -18,7 +18,7 @@ private import Imports::IRType * by the AST-to-IR translation (`IRTempVariable`). */ class IRVariable extends TIRVariable { - Language::Function func; + Language::Declaration func; IRVariable() { this = TIRUserVariable(_, _, func) or @@ -79,7 +79,7 @@ class IRVariable extends TIRVariable { /** * Gets the function that references this variable. */ - final Language::Function getEnclosingFunction() { result = func } + final Language::Declaration getEnclosingFunction() { result = func } } /** @@ -246,7 +246,7 @@ class IREllipsisVariable extends IRTempVariable, IRParameter { final override string toString() { result = "#ellipsis" } - final override int getIndex() { result = func.getNumberOfParameters() } + final override int getIndex() { result = func.(Language::Function).getNumberOfParameters() } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index e5a908bbf9a..8e863ddf635 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -194,7 +194,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets the function that contains this instruction. */ - final Language::Function getEnclosingFunction() { + final Language::Declaration getEnclosingFunction() { result = this.getEnclosingIRFunction().getFunction() } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll index 59dadee7154..53cdc75512b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll @@ -26,20 +26,20 @@ class PrintIRConfiguration extends TPrintIRConfiguration { * Holds if the IR for `func` should be printed. By default, holds for all * functions. */ - predicate shouldPrintFunction(Language::Function func) { any() } + predicate shouldPrintFunction(Language::Declaration decl) { any() } } /** * Override of `IRConfiguration` to only evaluate debug strings for the functions that are to be dumped. */ private class FilteredIRConfiguration extends IRConfiguration { - override predicate shouldEvaluateDebugStringsForFunction(Language::Function func) { + override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) { shouldPrintFunction(func) } } -private predicate shouldPrintFunction(Language::Function func) { - exists(PrintIRConfiguration config | config.shouldPrintFunction(func)) +private predicate shouldPrintFunction(Language::Declaration decl) { + exists(PrintIRConfiguration config | config.shouldPrintFunction(decl)) } private string getAdditionalInstructionProperty(Instruction instr, string key) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/IRFunctionBase.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/IRFunctionBase.qll index 60895ce3d26..576b4f9adf1 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/IRFunctionBase.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/IRFunctionBase.qll @@ -5,23 +5,28 @@ private import IRFunctionBaseInternal private newtype TIRFunction = - MkIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) } + TFunctionIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) } or + TVarInitIRFunction(Language::GlobalVariable var) { IRConstruction::Raw::varHasIRFunc(var) } /** * The IR for a function. This base class contains only the predicates that are the same between all * phases of the IR. Each instantiation of `IRFunction` extends this class. */ class IRFunctionBase extends TIRFunction { - Language::Function func; + Language::Declaration decl; - IRFunctionBase() { this = MkIRFunction(func) } + IRFunctionBase() { + this = TFunctionIRFunction(decl) + or + this = TVarInitIRFunction(decl) + } /** Gets a textual representation of this element. */ - final string toString() { result = "IR: " + func.toString() } + final string toString() { result = "IR: " + decl.toString() } /** Gets the function whose IR is represented. */ - final Language::Function getFunction() { result = func } + final Language::Declaration getFunction() { result = decl } /** Gets the location of the function. */ - final Language::Location getLocation() { result = func.getLocation() } + final Language::Location getLocation() { result = decl.getLocation() } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll index 12a0c6e7898..fe72263249f 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll @@ -2,21 +2,21 @@ private import TIRVariableInternal private import Imports::TempVariableTag newtype TIRVariable = - TIRUserVariable(Language::Variable var, Language::LanguageType type, Language::Function func) { + TIRUserVariable(Language::Variable var, Language::LanguageType type, Language::Declaration func) { Construction::hasUserVariable(func, var, type) } or TIRTempVariable( - Language::Function func, Language::AST ast, TempVariableTag tag, Language::LanguageType type + Language::Declaration func, Language::AST ast, TempVariableTag tag, Language::LanguageType type ) { Construction::hasTempVariable(func, ast, tag, type) } or TIRDynamicInitializationFlag( - Language::Function func, Language::Variable var, Language::LanguageType type + Language::Declaration func, Language::Variable var, Language::LanguageType type ) { Construction::hasDynamicInitializationFlag(func, var, type) } or TIRStringLiteral( - Language::Function func, Language::AST ast, Language::LanguageType type, + Language::Declaration func, Language::AST ast, Language::LanguageType type, Language::StringLiteral literal ) { Construction::hasStringLiteral(func, ast, type, literal) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRBlock.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRBlock.qll index bac7634cbd0..78008a6c69b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRBlock.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRBlock.qll @@ -97,7 +97,7 @@ class IRBlockBase extends TIRBlock { /** * Gets the `Function` that contains this block. */ - final Language::Function getEnclosingFunction() { + final Language::Declaration getEnclosingFunction() { result = getFirstInstruction(this).getEnclosingFunction() } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRConsistency.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRConsistency.qll index 31983d34247..45b44b14a3c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRConsistency.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRConsistency.qll @@ -524,4 +524,23 @@ module InstructionConsistency { "' has a `this` argument operand that is not an address, in function '$@'." and irFunc = getInstructionIRFunction(instr, irFuncText) } + + query predicate nonUniqueIRVariable( + Instruction instr, string message, OptionalIRFunction irFunc, string irFuncText + ) { + exists(VariableInstruction vi, IRVariable v1, IRVariable v2 | + instr = vi and vi.getIRVariable() = v1 and vi.getIRVariable() = v2 and v1 != v2 + ) and + message = + "Variable instruction '" + instr.toString() + + "' has multiple associated variables, in function '$@'." and + irFunc = getInstructionIRFunction(instr, irFuncText) + or + instr.getOpcode() instanceof Opcode::VariableAddress and + not instr instanceof VariableInstruction and + message = + "Variable address instruction '" + instr.toString() + + "' has no associated variable, in function '$@'." and + irFunc = getInstructionIRFunction(instr, irFuncText) + } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRVariable.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRVariable.qll index ca4708857a7..c92082d767d 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRVariable.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRVariable.qll @@ -18,7 +18,7 @@ private import Imports::IRType * by the AST-to-IR translation (`IRTempVariable`). */ class IRVariable extends TIRVariable { - Language::Function func; + Language::Declaration func; IRVariable() { this = TIRUserVariable(_, _, func) or @@ -79,7 +79,7 @@ class IRVariable extends TIRVariable { /** * Gets the function that references this variable. */ - final Language::Function getEnclosingFunction() { result = func } + final Language::Declaration getEnclosingFunction() { result = func } } /** @@ -246,7 +246,7 @@ class IREllipsisVariable extends IRTempVariable, IRParameter { final override string toString() { result = "#ellipsis" } - final override int getIndex() { result = func.getNumberOfParameters() } + final override int getIndex() { result = func.(Language::Function).getNumberOfParameters() } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll index e5a908bbf9a..8e863ddf635 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -194,7 +194,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets the function that contains this instruction. */ - final Language::Function getEnclosingFunction() { + final Language::Declaration getEnclosingFunction() { result = this.getEnclosingIRFunction().getFunction() } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll index 59dadee7154..53cdc75512b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/PrintIR.qll @@ -26,20 +26,20 @@ class PrintIRConfiguration extends TPrintIRConfiguration { * Holds if the IR for `func` should be printed. By default, holds for all * functions. */ - predicate shouldPrintFunction(Language::Function func) { any() } + predicate shouldPrintFunction(Language::Declaration decl) { any() } } /** * Override of `IRConfiguration` to only evaluate debug strings for the functions that are to be dumped. */ private class FilteredIRConfiguration extends IRConfiguration { - override predicate shouldEvaluateDebugStringsForFunction(Language::Function func) { + override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) { shouldPrintFunction(func) } } -private predicate shouldPrintFunction(Language::Function func) { - exists(PrintIRConfiguration config | config.shouldPrintFunction(func)) +private predicate shouldPrintFunction(Language::Declaration decl) { + exists(PrintIRConfiguration config | config.shouldPrintFunction(decl)) } private string getAdditionalInstructionProperty(Instruction instr, string key) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll index 94bfc53875f..44e9ecbfe5e 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll @@ -13,6 +13,7 @@ private import TranslatedElement private import TranslatedExpr private import TranslatedStmt private import TranslatedFunction +private import TranslatedGlobalVar TranslatedElement getInstructionTranslatedElement(Instruction instruction) { instruction = TRawInstruction(result, _) @@ -35,29 +36,41 @@ module Raw { cached predicate functionHasIR(Function func) { exists(getTranslatedFunction(func)) } + cached + predicate varHasIRFunc(GlobalOrNamespaceVariable var) { + var.hasInitializer() and + ( + not var.getType().isDeeplyConst() + or + var.getInitializer().getExpr() instanceof StringLiteral + ) + } + cached predicate hasInstruction(TranslatedElement element, InstructionTag tag) { element.hasInstruction(_, tag, _) } cached - predicate hasUserVariable(Function func, Variable var, CppType type) { - getTranslatedFunction(func).hasUserVariable(var, type) + predicate hasUserVariable(Declaration decl, Variable var, CppType type) { + getTranslatedFunction(decl).hasUserVariable(var, type) + or + getTranslatedVarInit(decl).hasUserVariable(var, type) } cached - predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, CppType type) { + predicate hasTempVariable(Declaration decl, Locatable ast, TempVariableTag tag, CppType type) { exists(TranslatedElement element | element.getAst() = ast and - func = element.getFunction() and + decl = element.getFunction() and element.hasTempVariable(tag, type) ) } cached - predicate hasStringLiteral(Function func, Locatable ast, CppType type, StringLiteral literal) { + predicate hasStringLiteral(Declaration decl, Locatable ast, CppType type, StringLiteral literal) { literal = ast and - literal.getEnclosingFunction() = func and + literal.getEnclosingDeclaration() = decl and getTypeForPRValue(literal.getType()) = type } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 66c601736af..f8960cd205d 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -180,7 +180,7 @@ abstract class TranslatedSideEffects extends TranslatedElement { /** DEPRECATED: Alias for getAst */ deprecated override Locatable getAST() { result = getAst() } - final override Function getFunction() { result = getExpr().getEnclosingFunction() } + final override Declaration getFunction() { result = getExpr().getEnclosingDeclaration() } final override TranslatedElement getChild(int i) { result = @@ -375,7 +375,7 @@ abstract class TranslatedSideEffect extends TranslatedElement { kind instanceof GotoEdge } - final override Function getFunction() { result = getParent().getFunction() } + final override Declaration getFunction() { result = getParent().getFunction() } final override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) { tag = OnlyInstructionTag() and @@ -436,13 +436,6 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect { result = index } - /** - * Gets the `TranslatedFunction` containing this expression. - */ - final TranslatedFunction getEnclosingFunction() { - result = getTranslatedFunction(call.getEnclosingFunction()) - } - final override predicate sideEffectInstruction(Opcode opcode, CppType type) { opcode = sideEffectOpcode and ( diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index d11d718e215..103b5424197 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -25,9 +25,9 @@ private Element getRealParent(Expr expr) { result.(Destructor).getADestruction() = expr } -IRUserVariable getIRUserVariable(Function func, Variable var) { +IRUserVariable getIRUserVariable(Declaration decl, Variable var) { result.getVariable() = var and - result.getEnclosingFunction() = func + result.getEnclosingFunction() = decl } IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) { @@ -67,7 +67,8 @@ private predicate ignoreExprAndDescendants(Expr expr) { exists(Initializer init, StaticStorageDurationVariable var | init = var.getInitializer() and not var.hasDynamicInitialization() and - expr = init.getExpr().getFullyConverted() + expr = init.getExpr().getFullyConverted() and + not var instanceof GlobalOrNamespaceVariable ) or // Ignore descendants of `__assume` expressions, since we translated these to `NoOp`. @@ -117,7 +118,8 @@ private predicate ignoreExprOnly(Expr expr) { // should not be translated. exists(NewOrNewArrayExpr new | expr = new.getAllocatorCall().getArgument(0)) or - not translateFunction(expr.getEnclosingFunction()) + not translateFunction(expr.getEnclosingFunction()) and + not Raw::varHasIRFunc(expr.getEnclosingVariable()) or // We do not yet translate destructors properly, so for now we ignore the // destructor call. We do, however, translate the expression being @@ -662,7 +664,8 @@ newtype TTranslatedElement = opcode = getASideEffectOpcode(call, -1) } or // The side effect that initializes newly-allocated memory. - TTranslatedAllocationSideEffect(AllocationExpr expr) { not ignoreSideEffects(expr) } + TTranslatedAllocationSideEffect(AllocationExpr expr) { not ignoreSideEffects(expr) } or + TTranslatedGlobalOrNamespaceVarInit(GlobalOrNamespaceVariable var) { Raw::varHasIRFunc(var) } /** * Gets the index of the first explicitly initialized element in `initList` @@ -792,7 +795,7 @@ abstract class TranslatedElement extends TTranslatedElement { /** * Gets the `Function` that contains this element. */ - abstract Function getFunction(); + abstract Declaration getFunction(); /** * Gets the successor instruction of the instruction that was generated by @@ -942,3 +945,14 @@ abstract class TranslatedElement extends TTranslatedElement { */ final TranslatedElement getParent() { result.getAChild() = this } } + +/** + * Represents the IR translation of a root element, either a function or a global variable. + */ +abstract class TranslatedRootElement extends TranslatedElement { + TranslatedRootElement() { + this instanceof TTranslatedFunction + or + this instanceof TTranslatedGlobalOrNamespaceVarInit + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index c81b7c5943a..f91486833ff 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -12,6 +12,7 @@ private import TranslatedElement private import TranslatedFunction private import TranslatedInitialization private import TranslatedStmt +private import TranslatedGlobalVar import TranslatedCall /** @@ -78,7 +79,7 @@ abstract class TranslatedExpr extends TranslatedElement { /** DEPRECATED: Alias for getAst */ deprecated override Locatable getAST() { result = this.getAst() } - final override Function getFunction() { result = expr.getEnclosingFunction() } + final override Declaration getFunction() { result = expr.getEnclosingDeclaration() } /** * Gets the expression from which this `TranslatedExpr` is generated. @@ -88,8 +89,10 @@ abstract class TranslatedExpr extends TranslatedElement { /** * Gets the `TranslatedFunction` containing this expression. */ - final TranslatedFunction getEnclosingFunction() { + final TranslatedRootElement getEnclosingFunction() { result = getTranslatedFunction(expr.getEnclosingFunction()) + or + result = getTranslatedVarInit(expr.getEnclosingVariable()) } } @@ -787,7 +790,7 @@ class TranslatedThisExpr extends TranslatedNonConstantExpr { override IRVariable getInstructionVariable(InstructionTag tag) { tag = ThisAddressTag() and - result = this.getEnclosingFunction().getThisVariable() + result = this.getEnclosingFunction().(TranslatedFunction).getThisVariable() } } @@ -838,7 +841,7 @@ class TranslatedNonFieldVariableAccess extends TranslatedVariableAccess { override IRVariable getInstructionVariable(InstructionTag tag) { tag = OnlyInstructionTag() and - result = getIRUserVariable(expr.getEnclosingFunction(), expr.getTarget()) + result = getIRUserVariable(expr.getEnclosingDeclaration(), expr.getTarget()) } } @@ -2522,7 +2525,7 @@ class TranslatedVarArgsStart extends TranslatedNonConstantExpr { final override IRVariable getInstructionVariable(InstructionTag tag) { tag = VarArgsStartEllipsisAddressTag() and - result = this.getEnclosingFunction().getEllipsisVariable() + result = this.getEnclosingFunction().(TranslatedFunction).getEllipsisVariable() } final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll index 0f781cb2244..b4746ae58de 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll @@ -58,7 +58,7 @@ predicate hasReturnValue(Function func) { not func.getUnspecifiedType() instance * Represents the IR translation of a function. This is the root elements for * all other elements associated with this function. */ -class TranslatedFunction extends TranslatedElement, TTranslatedFunction { +class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction { Function func; TranslatedFunction() { this = TTranslatedFunction(func) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedGlobalVar.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedGlobalVar.qll new file mode 100644 index 00000000000..31174d8ba5f --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedGlobalVar.qll @@ -0,0 +1,132 @@ +import semmle.code.cpp.ir.implementation.raw.internal.TranslatedElement +private import cpp +private import semmle.code.cpp.ir.implementation.IRType +private import semmle.code.cpp.ir.implementation.Opcode +private import semmle.code.cpp.ir.implementation.internal.OperandTag +private import semmle.code.cpp.ir.internal.CppType +private import TranslatedInitialization +private import InstructionTag +private import semmle.code.cpp.ir.internal.IRUtilities + +class TranslatedGlobalOrNamespaceVarInit extends TranslatedRootElement, + TTranslatedGlobalOrNamespaceVarInit, InitializationContext { + GlobalOrNamespaceVariable var; + + TranslatedGlobalOrNamespaceVarInit() { this = TTranslatedGlobalOrNamespaceVarInit(var) } + + override string toString() { result = var.toString() } + + final override GlobalOrNamespaceVariable getAst() { result = var } + + final override Declaration getFunction() { result = var } + + final Location getLocation() { result = var.getLocation() } + + override Instruction getFirstInstruction() { result = this.getInstruction(EnterFunctionTag()) } + + override TranslatedElement getChild(int n) { + n = 1 and + result = getTranslatedInitialization(var.getInitializer().getExpr().getFullyConverted()) + } + + override predicate hasInstruction(Opcode op, InstructionTag tag, CppType type) { + op instanceof Opcode::EnterFunction and + tag = EnterFunctionTag() and + type = getVoidType() + or + op instanceof Opcode::AliasedDefinition and + tag = AliasedDefinitionTag() and + type = getUnknownType() + or + op instanceof Opcode::VariableAddress and + tag = InitializerVariableAddressTag() and + type = getTypeForGLValue(var.getType()) + or + op instanceof Opcode::ReturnVoid and + tag = ReturnTag() and + type = getVoidType() + or + op instanceof Opcode::AliasedUse and + tag = AliasedUseTag() and + type = getVoidType() + or + op instanceof Opcode::ExitFunction and + tag = ExitFunctionTag() and + type = getVoidType() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + kind instanceof GotoEdge and + ( + tag = EnterFunctionTag() and + result = this.getInstruction(AliasedDefinitionTag()) + or + tag = AliasedDefinitionTag() and + result = this.getInstruction(InitializerVariableAddressTag()) + or + tag = InitializerVariableAddressTag() and + result = getChild(1).getFirstInstruction() + or + tag = ReturnTag() and + result = this.getInstruction(AliasedUseTag()) + or + tag = AliasedUseTag() and + result = this.getInstruction(ExitFunctionTag()) + ) + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = this.getChild(1) and + result = this.getInstruction(ReturnTag()) + } + + final override CppType getInstructionMemoryOperandType( + InstructionTag tag, TypedOperandTag operandTag + ) { + tag = AliasedUseTag() and + operandTag instanceof SideEffectOperandTag and + result = getUnknownType() + } + + override IRUserVariable getInstructionVariable(InstructionTag tag) { + tag = InitializerVariableAddressTag() and + result.getVariable() = var and + result.getEnclosingFunction() = var + } + + override Instruction getTargetAddress() { + result = this.getInstruction(InitializerVariableAddressTag()) + } + + override Type getTargetType() { result = var.getUnspecifiedType() } + + /** + * Holds if this variable 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 varUsed, CppType type) { + ( + ( + varUsed instanceof GlobalOrNamespaceVariable + or + varUsed instanceof MemberVariable and not varUsed instanceof Field + ) and + exists(VariableAccess access | + access.getTarget() = varUsed and + access.getEnclosingVariable() = var + ) + or + var = varUsed + or + varUsed.(LocalScopeVariable).getEnclosingElement*() = var + or + varUsed.(Parameter).getCatchBlock().getEnclosingElement*() = var + ) and + type = getTypeForPRValue(getVariableType(varUsed)) + } +} + +TranslatedGlobalOrNamespaceVarInit getTranslatedVarInit(GlobalOrNamespaceVariable var) { + result.getAst() = var +} diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll index 1a9d7ad9d70..b800405a73b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -137,7 +137,10 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn final override string toString() { result = "init: " + expr.toString() } - final override Function getFunction() { result = expr.getEnclosingFunction() } + final override Declaration getFunction() { + result = expr.getEnclosingFunction() or + result = expr.getEnclosingVariable().(GlobalOrNamespaceVariable) + } final override Locatable getAst() { result = expr } @@ -486,7 +489,10 @@ abstract class TranslatedFieldInitialization extends TranslatedElement { /** DEPRECATED: Alias for getAst */ deprecated override Locatable getAST() { result = getAst() } - final override Function getFunction() { result = ast.getEnclosingFunction() } + final override Declaration getFunction() { + result = ast.getEnclosingFunction() or + result = ast.getEnclosingVariable().(GlobalOrNamespaceVariable) + } final override Instruction getFirstInstruction() { result = getInstruction(getFieldAddressTag()) } @@ -633,7 +639,11 @@ abstract class TranslatedElementInitialization extends TranslatedElement { /** DEPRECATED: Alias for getAst */ deprecated override Locatable getAST() { result = getAst() } - final override Function getFunction() { result = initList.getEnclosingFunction() } + final override Declaration getFunction() { + result = initList.getEnclosingFunction() + or + result = initList.getEnclosingVariable().(GlobalOrNamespaceVariable) + } final override Instruction getFirstInstruction() { result = getInstruction(getElementIndexTag()) } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll index bac7634cbd0..78008a6c69b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll @@ -97,7 +97,7 @@ class IRBlockBase extends TIRBlock { /** * Gets the `Function` that contains this block. */ - final Language::Function getEnclosingFunction() { + final Language::Declaration getEnclosingFunction() { result = getFirstInstruction(this).getEnclosingFunction() } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRConsistency.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRConsistency.qll index 31983d34247..45b44b14a3c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRConsistency.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRConsistency.qll @@ -524,4 +524,23 @@ module InstructionConsistency { "' has a `this` argument operand that is not an address, in function '$@'." and irFunc = getInstructionIRFunction(instr, irFuncText) } + + query predicate nonUniqueIRVariable( + Instruction instr, string message, OptionalIRFunction irFunc, string irFuncText + ) { + exists(VariableInstruction vi, IRVariable v1, IRVariable v2 | + instr = vi and vi.getIRVariable() = v1 and vi.getIRVariable() = v2 and v1 != v2 + ) and + message = + "Variable instruction '" + instr.toString() + + "' has multiple associated variables, in function '$@'." and + irFunc = getInstructionIRFunction(instr, irFuncText) + or + instr.getOpcode() instanceof Opcode::VariableAddress and + not instr instanceof VariableInstruction and + message = + "Variable address instruction '" + instr.toString() + + "' has no associated variable, in function '$@'." and + irFunc = getInstructionIRFunction(instr, irFuncText) + } } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll index ca4708857a7..c92082d767d 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll @@ -18,7 +18,7 @@ private import Imports::IRType * by the AST-to-IR translation (`IRTempVariable`). */ class IRVariable extends TIRVariable { - Language::Function func; + Language::Declaration func; IRVariable() { this = TIRUserVariable(_, _, func) or @@ -79,7 +79,7 @@ class IRVariable extends TIRVariable { /** * Gets the function that references this variable. */ - final Language::Function getEnclosingFunction() { result = func } + final Language::Declaration getEnclosingFunction() { result = func } } /** @@ -246,7 +246,7 @@ class IREllipsisVariable extends IRTempVariable, IRParameter { final override string toString() { result = "#ellipsis" } - final override int getIndex() { result = func.getNumberOfParameters() } + final override int getIndex() { result = func.(Language::Function).getNumberOfParameters() } } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index e5a908bbf9a..8e863ddf635 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -194,7 +194,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets the function that contains this instruction. */ - final Language::Function getEnclosingFunction() { + final Language::Declaration getEnclosingFunction() { result = this.getEnclosingIRFunction().getFunction() } diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll index 59dadee7154..53cdc75512b 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll @@ -26,20 +26,20 @@ class PrintIRConfiguration extends TPrintIRConfiguration { * Holds if the IR for `func` should be printed. By default, holds for all * functions. */ - predicate shouldPrintFunction(Language::Function func) { any() } + predicate shouldPrintFunction(Language::Declaration decl) { any() } } /** * Override of `IRConfiguration` to only evaluate debug strings for the functions that are to be dumped. */ private class FilteredIRConfiguration extends IRConfiguration { - override predicate shouldEvaluateDebugStringsForFunction(Language::Function func) { + override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) { shouldPrintFunction(func) } } -private predicate shouldPrintFunction(Language::Function func) { - exists(PrintIRConfiguration config | config.shouldPrintFunction(func)) +private predicate shouldPrintFunction(Language::Declaration decl) { + exists(PrintIRConfiguration config | config.shouldPrintFunction(decl)) } private string getAdditionalInstructionProperty(Instruction instr, string key) { diff --git a/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguage.qll b/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguage.qll index f047d6c4753..46e3e6dec1c 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguage.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/internal/IRCppLanguage.qll @@ -50,12 +50,16 @@ class AutomaticVariable = Cpp::StackVariable; class StaticVariable = Cpp::Variable; +class GlobalVariable = Cpp::GlobalOrNamespaceVariable; + class Parameter = Cpp::Parameter; class Field = Cpp::Field; class BuiltInOperation = Cpp::BuiltInOperation; +class Declaration = Cpp::Declaration; + // TODO: Remove necessity for these. class Expr = Cpp::Expr; diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected index 6b3e01b0e77..1c802f3eeec 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected @@ -199,7 +199,9 @@ postWithInFlow | example.c:28:22:28:25 | & ... [post update] | PostUpdateNode should not be the target of local flow. | | example.c:28:23:28:25 | pos [post update] | PostUpdateNode should not be the target of local flow. | | globals.cpp:5:9:5:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| globals.cpp:9:5:9:19 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | globals.cpp:13:5:13:19 | flowTestGlobal1 [post update] | PostUpdateNode should not be the target of local flow. | +| globals.cpp:16:12:16:26 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | globals.cpp:23:5:23:19 | flowTestGlobal2 [post update] | PostUpdateNode should not be the target of local flow. | | lambdas.cpp:8:6:8:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | lambdas.cpp:9:6:9:6 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | diff --git a/cpp/ql/test/library-tests/ir/ir/PrintConfig.qll b/cpp/ql/test/library-tests/ir/ir/PrintConfig.qll index ccf243386fe..a9167597691 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintConfig.qll +++ b/cpp/ql/test/library-tests/ir/ir/PrintConfig.qll @@ -12,4 +12,11 @@ predicate locationIsInStandardHeaders(Location loc) { * * This predicate excludes functions defined in standard headers. */ -predicate shouldDumpFunction(Function func) { not locationIsInStandardHeaders(func.getLocation()) } +predicate shouldDumpFunction(Declaration decl) { + not locationIsInStandardHeaders(decl.getLocation()) and + ( + not decl instanceof Variable + or + decl.(GlobalOrNamespaceVariable).hasInitializer() + ) +} diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected index 31e5b01229c..79887fffc1f 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency.expected @@ -23,6 +23,7 @@ invalidOverlap nonUniqueEnclosingIRFunction fieldAddressOnNonPointer thisArgumentIsNonPointer +nonUniqueIRVariable missingCanonicalLanguageType multipleCanonicalLanguageTypes missingIRType diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected index 31e5b01229c..79887fffc1f 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_consistency_unsound.expected @@ -23,6 +23,7 @@ invalidOverlap nonUniqueEnclosingIRFunction fieldAddressOnNonPointer thisArgumentIsNonPointer +nonUniqueIRVariable missingCanonicalLanguageType multipleCanonicalLanguageTypes missingIRType diff --git a/cpp/ql/test/library-tests/ir/ir/ir.cpp b/cpp/ql/test/library-tests/ir/ir/ir.cpp index e85c5f1b505..4c49d95d453 100644 --- a/cpp/ql/test/library-tests/ir/ir/ir.cpp +++ b/cpp/ql/test/library-tests/ir/ir/ir.cpp @@ -1816,4 +1816,18 @@ void switch_initialization(int x) { } } +int global_1; + +int global_2 = 1; + +const int global_3 = 2; + +constructor_only global_4(1); + +constructor_only global_5 = constructor_only(2); + +char *global_string = "global string"; + +int global_6 = global_2; + // semmle-extractor-options: -std=c++17 --clang diff --git a/cpp/ql/test/library-tests/ir/ir/operand_locations.expected b/cpp/ql/test/library-tests/ir/ir/operand_locations.expected index 4b531d9c690..3510d24b7c7 100644 --- a/cpp/ql/test/library-tests/ir/ir/operand_locations.expected +++ b/cpp/ql/test/library-tests/ir/ir/operand_locations.expected @@ -4743,6 +4743,14 @@ | ir.cpp:1034:6:1034:20 | ChiTotal | total:m1034_2 | | ir.cpp:1034:6:1034:20 | SideEffect | m1034_3 | | ir.cpp:1035:15:1035:15 | Address | &:r1035_1 | +| ir.cpp:1038:6:1038:8 | Address | &:r1038_3 | +| ir.cpp:1038:6:1038:8 | SideEffect | ~m1038_8 | +| ir.cpp:1038:12:1038:18 | Address | &:r1038_4 | +| ir.cpp:1038:12:1038:18 | Address | &:r1038_4 | +| ir.cpp:1038:12:1038:18 | ChiPartial | partial:m1038_7 | +| ir.cpp:1038:12:1038:18 | ChiTotal | total:m1038_2 | +| ir.cpp:1038:12:1038:18 | Load | m1038_5 | +| ir.cpp:1038:12:1038:18 | StoreValue | r1038_6 | | ir.cpp:1038:14:1038:14 | Address | &:r1038_5 | | ir.cpp:1038:14:1038:14 | Address | &:r1038_5 | | ir.cpp:1038:14:1038:14 | Address | &:r1038_5 | @@ -8457,6 +8465,45 @@ | ir.cpp:1815:14:1815:15 | Address | &:r1815_1 | | ir.cpp:1815:14:1815:15 | Load | m1813_4 | | ir.cpp:1815:14:1815:15 | Right | r1815_2 | +| ir.cpp:1821:5:1821:12 | Address | &:r1821_3 | +| ir.cpp:1821:5:1821:12 | SideEffect | ~m1821_6 | +| ir.cpp:1821:16:1821:16 | ChiPartial | partial:m1821_5 | +| ir.cpp:1821:16:1821:16 | ChiTotal | total:m1821_2 | +| ir.cpp:1821:16:1821:16 | StoreValue | r1821_4 | +| ir.cpp:1825:18:1825:25 | Address | &:r1825_3 | +| ir.cpp:1825:18:1825:25 | Arg(this) | this:r1825_3 | +| ir.cpp:1825:18:1825:25 | SideEffect | ~m1825_10 | +| ir.cpp:1825:27:1825:27 | Arg(0) | 0:r1825_5 | +| ir.cpp:1825:27:1825:28 | CallTarget | func:r1825_4 | +| ir.cpp:1825:27:1825:28 | ChiPartial | partial:m1825_7 | +| ir.cpp:1825:27:1825:28 | ChiPartial | partial:m1825_9 | +| ir.cpp:1825:27:1825:28 | ChiTotal | total:m1825_2 | +| ir.cpp:1825:27:1825:28 | ChiTotal | total:m1825_8 | +| ir.cpp:1825:27:1825:28 | SideEffect | ~m1825_2 | +| ir.cpp:1827:18:1827:25 | Address | &:r1827_3 | +| ir.cpp:1827:18:1827:25 | Arg(this) | this:r1827_3 | +| ir.cpp:1827:18:1827:25 | SideEffect | ~m1827_10 | +| ir.cpp:1827:28:1827:47 | CallTarget | func:r1827_4 | +| ir.cpp:1827:28:1827:47 | ChiPartial | partial:m1827_7 | +| ir.cpp:1827:28:1827:47 | ChiPartial | partial:m1827_9 | +| ir.cpp:1827:28:1827:47 | ChiTotal | total:m1827_2 | +| ir.cpp:1827:28:1827:47 | ChiTotal | total:m1827_8 | +| ir.cpp:1827:28:1827:47 | SideEffect | ~m1827_2 | +| ir.cpp:1827:46:1827:46 | Arg(0) | 0:r1827_5 | +| ir.cpp:1829:7:1829:19 | Address | &:r1829_3 | +| ir.cpp:1829:7:1829:19 | SideEffect | ~m1829_8 | +| ir.cpp:1829:23:1829:37 | ChiPartial | partial:m1829_7 | +| ir.cpp:1829:23:1829:37 | ChiTotal | total:m1829_2 | +| ir.cpp:1829:23:1829:37 | StoreValue | r1829_6 | +| ir.cpp:1829:23:1829:37 | Unary | r1829_4 | +| ir.cpp:1829:23:1829:37 | Unary | r1829_5 | +| ir.cpp:1831:5:1831:12 | Address | &:r1831_3 | +| ir.cpp:1831:5:1831:12 | SideEffect | ~m1831_7 | +| ir.cpp:1831:16:1831:23 | Address | &:r1831_4 | +| ir.cpp:1831:16:1831:23 | ChiPartial | partial:m1831_6 | +| ir.cpp:1831:16:1831:23 | ChiTotal | total:m1831_2 | +| ir.cpp:1831:16:1831:23 | Load | ~m1831_2 | +| ir.cpp:1831:16:1831:23 | StoreValue | r1831_5 | | perf-regression.cpp:6:3:6:5 | Address | &:r6_5 | | perf-regression.cpp:6:3:6:5 | Address | &:r6_5 | | perf-regression.cpp:6:3:6:5 | Address | &:r6_7 | @@ -8700,6 +8747,34 @@ | smart_ptr.cpp:47:43:47:63 | SideEffect | ~m47_16 | | smart_ptr.cpp:47:43:47:63 | Unary | r47_5 | | smart_ptr.cpp:47:43:47:63 | Unary | r47_6 | +| struct_init.cpp:9:13:9:25 | Left | r9_3 | +| struct_init.cpp:9:13:9:25 | Left | r9_3 | +| struct_init.cpp:9:13:9:25 | SideEffect | ~m11_10 | +| struct_init.cpp:9:31:12:1 | Right | r9_4 | +| struct_init.cpp:9:31:12:1 | Right | r9_6 | +| struct_init.cpp:9:31:12:1 | Unary | r9_5 | +| struct_init.cpp:9:31:12:1 | Unary | r9_5 | +| struct_init.cpp:9:31:12:1 | Unary | r9_7 | +| struct_init.cpp:9:31:12:1 | Unary | r9_7 | +| struct_init.cpp:10:5:10:21 | Address | &:r10_1 | +| struct_init.cpp:10:5:10:21 | Address | &:r10_6 | +| struct_init.cpp:10:7:10:9 | ChiPartial | partial:m10_4 | +| struct_init.cpp:10:7:10:9 | ChiTotal | total:m9_2 | +| struct_init.cpp:10:7:10:9 | StoreValue | r10_3 | +| struct_init.cpp:10:7:10:9 | Unary | r10_2 | +| struct_init.cpp:10:12:10:19 | ChiPartial | partial:m10_8 | +| struct_init.cpp:10:12:10:19 | ChiTotal | total:m10_5 | +| struct_init.cpp:10:12:10:19 | StoreValue | r10_7 | +| struct_init.cpp:11:5:11:22 | Address | &:r11_1 | +| struct_init.cpp:11:5:11:22 | Address | &:r11_6 | +| struct_init.cpp:11:7:11:9 | ChiPartial | partial:m11_4 | +| struct_init.cpp:11:7:11:9 | ChiTotal | total:m10_9 | +| struct_init.cpp:11:7:11:9 | StoreValue | r11_3 | +| struct_init.cpp:11:7:11:9 | Unary | r11_2 | +| struct_init.cpp:11:12:11:20 | ChiPartial | partial:m11_9 | +| struct_init.cpp:11:12:11:20 | ChiTotal | total:m11_5 | +| struct_init.cpp:11:12:11:20 | StoreValue | r11_8 | +| struct_init.cpp:11:13:11:20 | Unary | r11_7 | | struct_init.cpp:16:6:16:20 | ChiPartial | partial:m16_3 | | struct_init.cpp:16:6:16:20 | ChiTotal | total:m16_2 | | struct_init.cpp:16:6:16:20 | SideEffect | ~m17_5 | diff --git a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected index 9575759051e..cc50472385b 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_consistency.expected @@ -27,6 +27,7 @@ invalidOverlap nonUniqueEnclosingIRFunction fieldAddressOnNonPointer thisArgumentIsNonPointer +nonUniqueIRVariable missingCanonicalLanguageType multipleCanonicalLanguageTypes missingIRType diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 17c59485eb9..8f67435f3c1 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -5650,6 +5650,19 @@ ir.cpp: # 1034| v1034_5(void) = AliasedUse : ~m? # 1034| v1034_6(void) = ExitFunction : +# 1038| (lambda [] type at line 1038, col. 12) lam +# 1038| Block 0 +# 1038| v1038_1(void) = EnterFunction : +# 1038| mu1038_2(unknown) = AliasedDefinition : +# 1038| r1038_3(glval) = VariableAddress[lam] : +# 1038| r1038_4(glval) = VariableAddress[#temp1038:12] : +# 1038| mu1038_5(decltype([...](...){...})) = Uninitialized[#temp1038:12] : &:r1038_4 +# 1038| r1038_6(decltype([...](...){...})) = Load[#temp1038:12] : &:r1038_4, ~m? +# 1038| mu1038_7(decltype([...](...){...})) = Store[lam] : &:r1038_3, r1038_6 +# 1038| v1038_8(void) = ReturnVoid : +# 1038| v1038_9(void) = AliasedUse : ~m? +# 1038| v1038_10(void) = ExitFunction : + # 1038| void (lambda [] type at line 1038, col. 12)::operator()() const # 1038| Block 0 # 1038| v1038_1(void) = EnterFunction : @@ -9720,6 +9733,70 @@ ir.cpp: # 1785| v1785_7(void) = AliasedUse : ~m? # 1785| v1785_8(void) = ExitFunction : +# 1821| int global_2 +# 1821| Block 0 +# 1821| v1821_1(void) = EnterFunction : +# 1821| mu1821_2(unknown) = AliasedDefinition : +# 1821| r1821_3(glval) = VariableAddress[global_2] : +# 1821| r1821_4(int) = Constant[1] : +# 1821| mu1821_5(int) = Store[global_2] : &:r1821_3, r1821_4 +# 1821| v1821_6(void) = ReturnVoid : +# 1821| v1821_7(void) = AliasedUse : ~m? +# 1821| v1821_8(void) = ExitFunction : + +# 1825| constructor_only global_4 +# 1825| Block 0 +# 1825| v1825_1(void) = EnterFunction : +# 1825| mu1825_2(unknown) = AliasedDefinition : +# 1825| r1825_3(glval) = VariableAddress[global_4] : +# 1825| r1825_4(glval) = FunctionAddress[constructor_only] : +# 1825| r1825_5(int) = Constant[1] : +# 1825| v1825_6(void) = Call[constructor_only] : func:r1825_4, this:r1825_3, 0:r1825_5 +# 1825| mu1825_7(unknown) = ^CallSideEffect : ~m? +# 1825| mu1825_8(constructor_only) = ^IndirectMayWriteSideEffect[-1] : &:r1825_3 +# 1825| v1825_9(void) = ReturnVoid : +# 1825| v1825_10(void) = AliasedUse : ~m? +# 1825| v1825_11(void) = ExitFunction : + +# 1827| constructor_only global_5 +# 1827| Block 0 +# 1827| v1827_1(void) = EnterFunction : +# 1827| mu1827_2(unknown) = AliasedDefinition : +# 1827| r1827_3(glval) = VariableAddress[global_5] : +# 1827| r1827_4(glval) = FunctionAddress[constructor_only] : +# 1827| r1827_5(int) = Constant[2] : +# 1827| v1827_6(void) = Call[constructor_only] : func:r1827_4, this:r1827_3, 0:r1827_5 +# 1827| mu1827_7(unknown) = ^CallSideEffect : ~m? +# 1827| mu1827_8(constructor_only) = ^IndirectMayWriteSideEffect[-1] : &:r1827_3 +# 1827| v1827_9(void) = ReturnVoid : +# 1827| v1827_10(void) = AliasedUse : ~m? +# 1827| v1827_11(void) = ExitFunction : + +# 1829| char* global_string +# 1829| Block 0 +# 1829| v1829_1(void) = EnterFunction : +# 1829| mu1829_2(unknown) = AliasedDefinition : +# 1829| r1829_3(glval) = VariableAddress[global_string] : +# 1829| r1829_4(glval) = StringConstant["global string"] : +# 1829| r1829_5(char *) = Convert : r1829_4 +# 1829| r1829_6(char *) = Convert : r1829_5 +# 1829| mu1829_7(char *) = Store[global_string] : &:r1829_3, r1829_6 +# 1829| v1829_8(void) = ReturnVoid : +# 1829| v1829_9(void) = AliasedUse : ~m? +# 1829| v1829_10(void) = ExitFunction : + +# 1831| int global_6 +# 1831| Block 0 +# 1831| v1831_1(void) = EnterFunction : +# 1831| mu1831_2(unknown) = AliasedDefinition : +# 1831| r1831_3(glval) = VariableAddress[global_6] : +# 1831| r1831_4(glval) = VariableAddress[global_2] : +# 1831| r1831_5(int) = Load[global_2] : &:r1831_4, ~m? +# 1831| mu1831_6(int) = Store[global_6] : &:r1831_3, r1831_5 +# 1831| v1831_7(void) = ReturnVoid : +# 1831| v1831_8(void) = AliasedUse : ~m? +# 1831| v1831_9(void) = ExitFunction : + perf-regression.cpp: # 6| void Big::Big() # 6| Block 0 @@ -9941,6 +10018,34 @@ smart_ptr.cpp: # 28| v28_6(void) = ExitFunction : struct_init.cpp: +# 9| Info infos_in_file[] +# 9| Block 0 +# 9| v9_1(void) = EnterFunction : +# 9| mu9_2(unknown) = AliasedDefinition : +# 9| r9_3(glval) = VariableAddress[infos_in_file] : +# 9| r9_4(int) = Constant[0] : +# 9| r9_5(glval) = PointerAdd[16] : r9_3, r9_4 +# 10| r10_1(glval) = FieldAddress[name] : r9_5 +# 10| r10_2(glval) = StringConstant["1"] : +# 10| r10_3(char *) = Convert : r10_2 +# 10| mu10_4(char *) = Store[?] : &:r10_1, r10_3 +# 10| r10_5(glval<..(*)(..)>) = FieldAddress[handler] : r9_5 +# 10| r10_6(..(*)(..)) = FunctionAddress[handler1] : +# 10| mu10_7(..(*)(..)) = Store[?] : &:r10_5, r10_6 +# 9| r9_6(int) = Constant[1] : +# 9| r9_7(glval) = PointerAdd[16] : r9_3, r9_6 +# 11| r11_1(glval) = FieldAddress[name] : r9_7 +# 11| r11_2(glval) = StringConstant["3"] : +# 11| r11_3(char *) = Convert : r11_2 +# 11| mu11_4(char *) = Store[?] : &:r11_1, r11_3 +# 11| r11_5(glval<..(*)(..)>) = FieldAddress[handler] : r9_7 +# 11| r11_6(glval<..()(..)>) = FunctionAddress[handler2] : +# 11| r11_7(..(*)(..)) = CopyValue : r11_6 +# 11| mu11_8(..(*)(..)) = Store[?] : &:r11_5, r11_7 +# 9| v9_8(void) = ReturnVoid : +# 9| v9_9(void) = AliasedUse : ~m? +# 9| v9_10(void) = ExitFunction : + # 16| void let_info_escape(Info*) # 16| Block 0 # 16| v16_1(void) = EnterFunction : diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.ql b/cpp/ql/test/library-tests/ir/ir/raw_ir.ql index a0ebe4d2bdd..ae37a4a932b 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.ql +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.ql @@ -7,5 +7,5 @@ private import semmle.code.cpp.ir.implementation.raw.PrintIR private import PrintConfig private class PrintConfig extends PrintIRConfiguration { - override predicate shouldPrintFunction(Function func) { shouldDumpFunction(func) } + override predicate shouldPrintFunction(Declaration decl) { shouldDumpFunction(decl) } } diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency.expected index 31e5b01229c..79887fffc1f 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency.expected @@ -23,6 +23,7 @@ invalidOverlap nonUniqueEnclosingIRFunction fieldAddressOnNonPointer thisArgumentIsNonPointer +nonUniqueIRVariable missingCanonicalLanguageType multipleCanonicalLanguageTypes missingIRType diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency_unsound.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency_unsound.expected index 31e5b01229c..79887fffc1f 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_consistency_unsound.expected @@ -23,6 +23,7 @@ invalidOverlap nonUniqueEnclosingIRFunction fieldAddressOnNonPointer thisArgumentIsNonPointer +nonUniqueIRVariable missingCanonicalLanguageType multipleCanonicalLanguageTypes missingIRType diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_consistency.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_consistency.expected index 31e5b01229c..79887fffc1f 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_consistency.expected @@ -23,6 +23,7 @@ invalidOverlap nonUniqueEnclosingIRFunction fieldAddressOnNonPointer thisArgumentIsNonPointer +nonUniqueIRVariable missingCanonicalLanguageType multipleCanonicalLanguageTypes missingIRType diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_consistency_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_consistency_unsound.expected index 31e5b01229c..79887fffc1f 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_consistency_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_consistency_unsound.expected @@ -23,6 +23,7 @@ invalidOverlap nonUniqueEnclosingIRFunction fieldAddressOnNonPointer thisArgumentIsNonPointer +nonUniqueIRVariable missingCanonicalLanguageType multipleCanonicalLanguageTypes missingIRType diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_consistency.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_consistency.expected index 31e5b01229c..79887fffc1f 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_consistency.expected @@ -23,6 +23,7 @@ invalidOverlap nonUniqueEnclosingIRFunction fieldAddressOnNonPointer thisArgumentIsNonPointer +nonUniqueIRVariable missingCanonicalLanguageType multipleCanonicalLanguageTypes missingIRType diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_consistency_unsound.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_consistency_unsound.expected index 31e5b01229c..79887fffc1f 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_consistency_unsound.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_consistency_unsound.expected @@ -23,6 +23,7 @@ invalidOverlap nonUniqueEnclosingIRFunction fieldAddressOnNonPointer thisArgumentIsNonPointer +nonUniqueIRVariable missingCanonicalLanguageType multipleCanonicalLanguageTypes missingIRType diff --git a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_consistency.expected index fcfef712b56..665d30605ee 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_consistency.expected @@ -98,6 +98,9 @@ thisArgumentIsNonPointer | pmcallexpr.cpp:8:2:8:15 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | | pointer_to_member.cpp:23:5:23:54 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) | | pointer_to_member.cpp:24:5:24:49 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) | +nonUniqueIRVariable +| misc.c:178:22:178:40 | VariableAddress: __PRETTY_FUNCTION__ | Variable address instruction 'VariableAddress: __PRETTY_FUNCTION__' has no associated variable, in function '$@'. | misc.c:177:6:177:14 | void magicvars() | void magicvars() | +| misc.c:179:27:179:34 | VariableAddress: __func__ | Variable address instruction 'VariableAddress: __func__' has no associated variable, in function '$@'. | misc.c:177:6:177:14 | void magicvars() | void magicvars() | missingCanonicalLanguageType multipleCanonicalLanguageTypes missingIRType diff --git a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected index e37a676565c..044257ed952 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected @@ -1622,6 +1622,7 @@ postWithInFlow | cpp11.cpp:28:21:28:34 | temporary object [post update] | PostUpdateNode should not be the target of local flow. | | cpp11.cpp:29:7:29:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | cpp11.cpp:31:5:31:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| cpp11.cpp:36:5:36:14 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | cpp11.cpp:56:14:56:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | cpp11.cpp:56:14:56:15 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | cpp11.cpp:60:15:60:16 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | @@ -2230,6 +2231,8 @@ postWithInFlow | ltrbinopexpr.c:37:5:37:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | ltrbinopexpr.c:39:5:39:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | ltrbinopexpr.c:40:5:40:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| misc.c:10:5:10:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| misc.c:11:5:11:13 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | misc.c:18:5:18:5 | i [post update] | PostUpdateNode should not be the target of local flow. | | misc.c:19:5:19:5 | i [post update] | PostUpdateNode should not be the target of local flow. | | misc.c:20:7:20:7 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | @@ -2289,6 +2292,7 @@ postWithInFlow | misc.c:200:24:200:27 | args [post update] | PostUpdateNode should not be the target of local flow. | | misc.c:200:24:200:27 | array to pointer conversion [post update] | PostUpdateNode should not be the target of local flow. | | misc.c:208:1:208:3 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | +| misc.c:210:5:210:20 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | misc.c:216:3:216:26 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | | misc.c:220:3:220:5 | * ... [post update] | PostUpdateNode should not be the target of local flow. | | misc.c:220:4:220:5 | VariableAddress [post update] | PostUpdateNode should not be the target of local flow. | diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected index 4a4bea025a8..69f6429c080 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_consistency.expected @@ -148,6 +148,9 @@ thisArgumentIsNonPointer | pmcallexpr.cpp:8:2:8:15 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | | pointer_to_member.cpp:23:5:23:54 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) | | pointer_to_member.cpp:24:5:24:49 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) | +nonUniqueIRVariable +| misc.c:178:22:178:40 | VariableAddress: __PRETTY_FUNCTION__ | Variable address instruction 'VariableAddress: __PRETTY_FUNCTION__' has no associated variable, in function '$@'. | misc.c:177:6:177:14 | void magicvars() | void magicvars() | +| misc.c:179:27:179:34 | VariableAddress: __func__ | Variable address instruction 'VariableAddress: __func__' has no associated variable, in function '$@'. | misc.c:177:6:177:14 | void magicvars() | void magicvars() | missingCanonicalLanguageType multipleCanonicalLanguageTypes missingIRType diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_consistency.expected b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_consistency.expected index 56e9f2e881a..83e97d12a7d 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_consistency.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_consistency.expected @@ -98,6 +98,9 @@ thisArgumentIsNonPointer | pmcallexpr.cpp:8:2:8:15 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | array_delete.cpp:5:6:5:6 | void f() | void f() | | pointer_to_member.cpp:23:5:23:54 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) | | pointer_to_member.cpp:24:5:24:49 | Call: call to expression | Call instruction 'Call: call to expression' has a `this` argument operand that is not an address, in function '$@'. | pointer_to_member.cpp:14:5:14:9 | int usePM(int PM::*) | int usePM(int PM::*) | +nonUniqueIRVariable +| misc.c:178:22:178:40 | VariableAddress: __PRETTY_FUNCTION__ | Variable address instruction 'VariableAddress: __PRETTY_FUNCTION__' has no associated variable, in function '$@'. | misc.c:177:6:177:14 | void magicvars() | void magicvars() | +| misc.c:179:27:179:34 | VariableAddress: __func__ | Variable address instruction 'VariableAddress: __func__' has no associated variable, in function '$@'. | misc.c:177:6:177:14 | void magicvars() | void magicvars() | missingCanonicalLanguageType multipleCanonicalLanguageTypes missingIRType diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/diff_ir_expr.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/diff_ir_expr.expected index 7322e9723ec..b838a13d5af 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/diff_ir_expr.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/diff_ir_expr.expected @@ -1,18 +1,15 @@ | test.cpp:5:3:5:13 | ... = ... | test.cpp:5:3:5:13 | ... = ... | AST only | | test.cpp:6:3:6:13 | ... = ... | test.cpp:6:3:6:13 | ... = ... | AST only | | test.cpp:7:3:7:7 | ... = ... | test.cpp:7:3:7:7 | ... = ... | AST only | -| test.cpp:10:16:10:16 | 1 | test.cpp:10:16:10:16 | 1 | AST only | | test.cpp:16:3:16:24 | ... = ... | test.cpp:16:3:16:24 | ... = ... | AST only | | test.cpp:17:3:17:24 | ... = ... | test.cpp:17:3:17:24 | ... = ... | AST only | | test.cpp:18:3:18:7 | ... = ... | test.cpp:18:3:18:7 | ... = ... | AST only | -| test.cpp:21:16:21:16 | 2 | test.cpp:21:16:21:16 | 2 | AST only | | test.cpp:29:3:29:3 | x | test.cpp:31:3:31:3 | x | IR only | | test.cpp:29:3:29:24 | ... = ... | test.cpp:29:3:29:24 | ... = ... | AST only | | test.cpp:30:3:30:17 | call to change_global02 | test.cpp:30:3:30:17 | call to change_global02 | AST only | | test.cpp:31:3:31:3 | x | test.cpp:29:3:29:3 | x | IR only | | test.cpp:31:3:31:24 | ... = ... | test.cpp:31:3:31:24 | ... = ... | AST only | | test.cpp:32:3:32:7 | ... = ... | test.cpp:32:3:32:7 | ... = ... | AST only | -| test.cpp:35:16:35:16 | 3 | test.cpp:35:16:35:16 | 3 | AST only | | test.cpp:43:3:43:3 | x | test.cpp:45:3:45:3 | x | IR only | | test.cpp:43:3:43:24 | ... = ... | test.cpp:43:3:43:24 | ... = ... | AST only | | test.cpp:43:7:43:24 | ... + ... | test.cpp:45:7:45:24 | ... + ... | IR only | diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected index 24dc1c1ab44..88e365023a1 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -69,6 +69,23 @@ test.cpp: # 1| v1_10(void) = AliasedUse : m1_3 # 1| v1_11(void) = ExitFunction : +# 10| int global01 +# 10| Block 0 +# 10| v10_1(void) = EnterFunction : +# 10| m10_2(unknown) = AliasedDefinition : +# 10| valnum = unique +# 10| r10_3(glval) = VariableAddress[global01] : +# 10| valnum = unique +# 10| r10_4(int) = Constant[1] : +# 10| valnum = m10_5, r10_4 +# 10| m10_5(int) = Store[global01] : &:r10_3, r10_4 +# 10| valnum = m10_5, r10_4 +# 10| m10_6(unknown) = Chi : total:m10_2, partial:m10_5 +# 10| valnum = unique +# 10| v10_7(void) = ReturnVoid : +# 10| v10_8(void) = AliasedUse : ~m10_6 +# 10| v10_9(void) = ExitFunction : + # 12| void test01(int, int) # 12| Block 0 # 12| v12_1(void) = EnterFunction : @@ -151,6 +168,23 @@ test.cpp: # 12| v12_10(void) = AliasedUse : m12_3 # 12| v12_11(void) = ExitFunction : +# 21| int global02 +# 21| Block 0 +# 21| v21_1(void) = EnterFunction : +# 21| m21_2(unknown) = AliasedDefinition : +# 21| valnum = unique +# 21| r21_3(glval) = VariableAddress[global02] : +# 21| valnum = unique +# 21| r21_4(int) = Constant[2] : +# 21| valnum = m21_5, r21_4 +# 21| m21_5(int) = Store[global02] : &:r21_3, r21_4 +# 21| valnum = m21_5, r21_4 +# 21| m21_6(unknown) = Chi : total:m21_2, partial:m21_5 +# 21| valnum = unique +# 21| v21_7(void) = ReturnVoid : +# 21| v21_8(void) = AliasedUse : ~m21_6 +# 21| v21_9(void) = ExitFunction : + # 25| void test02(int, int) # 25| Block 0 # 25| v25_1(void) = EnterFunction : @@ -240,6 +274,23 @@ test.cpp: # 25| v25_10(void) = AliasedUse : ~m30_4 # 25| v25_11(void) = ExitFunction : +# 35| int global03 +# 35| Block 0 +# 35| v35_1(void) = EnterFunction : +# 35| m35_2(unknown) = AliasedDefinition : +# 35| valnum = unique +# 35| r35_3(glval) = VariableAddress[global03] : +# 35| valnum = unique +# 35| r35_4(int) = Constant[3] : +# 35| valnum = m35_5, r35_4 +# 35| m35_5(int) = Store[global03] : &:r35_3, r35_4 +# 35| valnum = m35_5, r35_4 +# 35| m35_6(unknown) = Chi : total:m35_2, partial:m35_5 +# 35| valnum = unique +# 35| v35_7(void) = ReturnVoid : +# 35| v35_8(void) = AliasedUse : ~m35_6 +# 35| v35_9(void) = ExitFunction : + # 39| void test03(int, int, int*) # 39| Block 0 # 39| v39_1(void) = EnterFunction : diff --git a/csharp/ql/src/experimental/ir/implementation/IRConfiguration.qll b/csharp/ql/src/experimental/ir/implementation/IRConfiguration.qll index 37ac2fccdd9..90cdb9e0f5f 100644 --- a/csharp/ql/src/experimental/ir/implementation/IRConfiguration.qll +++ b/csharp/ql/src/experimental/ir/implementation/IRConfiguration.qll @@ -16,7 +16,7 @@ class IRConfiguration extends TIRConfiguration { /** * Holds if IR should be created for function `func`. By default, holds for all functions. */ - predicate shouldCreateIRForFunction(Language::Function func) { any() } + predicate shouldCreateIRForFunction(Language::Declaration func) { any() } /** * Holds if the strings used as part of an IR dump should be generated for function `func`. @@ -25,7 +25,7 @@ class IRConfiguration extends TIRConfiguration { * of debug strings for IR that will not be dumped. We still generate the actual IR for these * functions, however, to preserve the results of any interprocedural analysis. */ - predicate shouldEvaluateDebugStringsForFunction(Language::Function func) { any() } + predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) { any() } } private newtype TIREscapeAnalysisConfiguration = MkIREscapeAnalysisConfiguration() diff --git a/csharp/ql/src/experimental/ir/implementation/internal/IRFunctionBase.qll b/csharp/ql/src/experimental/ir/implementation/internal/IRFunctionBase.qll index 60895ce3d26..576b4f9adf1 100644 --- a/csharp/ql/src/experimental/ir/implementation/internal/IRFunctionBase.qll +++ b/csharp/ql/src/experimental/ir/implementation/internal/IRFunctionBase.qll @@ -5,23 +5,28 @@ private import IRFunctionBaseInternal private newtype TIRFunction = - MkIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) } + TFunctionIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) } or + TVarInitIRFunction(Language::GlobalVariable var) { IRConstruction::Raw::varHasIRFunc(var) } /** * The IR for a function. This base class contains only the predicates that are the same between all * phases of the IR. Each instantiation of `IRFunction` extends this class. */ class IRFunctionBase extends TIRFunction { - Language::Function func; + Language::Declaration decl; - IRFunctionBase() { this = MkIRFunction(func) } + IRFunctionBase() { + this = TFunctionIRFunction(decl) + or + this = TVarInitIRFunction(decl) + } /** Gets a textual representation of this element. */ - final string toString() { result = "IR: " + func.toString() } + final string toString() { result = "IR: " + decl.toString() } /** Gets the function whose IR is represented. */ - final Language::Function getFunction() { result = func } + final Language::Declaration getFunction() { result = decl } /** Gets the location of the function. */ - final Language::Location getLocation() { result = func.getLocation() } + final Language::Location getLocation() { result = decl.getLocation() } } diff --git a/csharp/ql/src/experimental/ir/implementation/internal/TIRVariable.qll b/csharp/ql/src/experimental/ir/implementation/internal/TIRVariable.qll index 12a0c6e7898..fe72263249f 100644 --- a/csharp/ql/src/experimental/ir/implementation/internal/TIRVariable.qll +++ b/csharp/ql/src/experimental/ir/implementation/internal/TIRVariable.qll @@ -2,21 +2,21 @@ private import TIRVariableInternal private import Imports::TempVariableTag newtype TIRVariable = - TIRUserVariable(Language::Variable var, Language::LanguageType type, Language::Function func) { + TIRUserVariable(Language::Variable var, Language::LanguageType type, Language::Declaration func) { Construction::hasUserVariable(func, var, type) } or TIRTempVariable( - Language::Function func, Language::AST ast, TempVariableTag tag, Language::LanguageType type + Language::Declaration func, Language::AST ast, TempVariableTag tag, Language::LanguageType type ) { Construction::hasTempVariable(func, ast, tag, type) } or TIRDynamicInitializationFlag( - Language::Function func, Language::Variable var, Language::LanguageType type + Language::Declaration func, Language::Variable var, Language::LanguageType type ) { Construction::hasDynamicInitializationFlag(func, var, type) } or TIRStringLiteral( - Language::Function func, Language::AST ast, Language::LanguageType type, + Language::Declaration func, Language::AST ast, Language::LanguageType type, Language::StringLiteral literal ) { Construction::hasStringLiteral(func, ast, type, literal) diff --git a/csharp/ql/src/experimental/ir/implementation/raw/IRBlock.qll b/csharp/ql/src/experimental/ir/implementation/raw/IRBlock.qll index bac7634cbd0..78008a6c69b 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/IRBlock.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/IRBlock.qll @@ -97,7 +97,7 @@ class IRBlockBase extends TIRBlock { /** * Gets the `Function` that contains this block. */ - final Language::Function getEnclosingFunction() { + final Language::Declaration getEnclosingFunction() { result = getFirstInstruction(this).getEnclosingFunction() } } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/IRConsistency.qll b/csharp/ql/src/experimental/ir/implementation/raw/IRConsistency.qll index 31983d34247..45b44b14a3c 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/IRConsistency.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/IRConsistency.qll @@ -524,4 +524,23 @@ module InstructionConsistency { "' has a `this` argument operand that is not an address, in function '$@'." and irFunc = getInstructionIRFunction(instr, irFuncText) } + + query predicate nonUniqueIRVariable( + Instruction instr, string message, OptionalIRFunction irFunc, string irFuncText + ) { + exists(VariableInstruction vi, IRVariable v1, IRVariable v2 | + instr = vi and vi.getIRVariable() = v1 and vi.getIRVariable() = v2 and v1 != v2 + ) and + message = + "Variable instruction '" + instr.toString() + + "' has multiple associated variables, in function '$@'." and + irFunc = getInstructionIRFunction(instr, irFuncText) + or + instr.getOpcode() instanceof Opcode::VariableAddress and + not instr instanceof VariableInstruction and + message = + "Variable address instruction '" + instr.toString() + + "' has no associated variable, in function '$@'." and + irFunc = getInstructionIRFunction(instr, irFuncText) + } } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/IRVariable.qll b/csharp/ql/src/experimental/ir/implementation/raw/IRVariable.qll index ca4708857a7..c92082d767d 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/IRVariable.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/IRVariable.qll @@ -18,7 +18,7 @@ private import Imports::IRType * by the AST-to-IR translation (`IRTempVariable`). */ class IRVariable extends TIRVariable { - Language::Function func; + Language::Declaration func; IRVariable() { this = TIRUserVariable(_, _, func) or @@ -79,7 +79,7 @@ class IRVariable extends TIRVariable { /** * Gets the function that references this variable. */ - final Language::Function getEnclosingFunction() { result = func } + final Language::Declaration getEnclosingFunction() { result = func } } /** @@ -246,7 +246,7 @@ class IREllipsisVariable extends IRTempVariable, IRParameter { final override string toString() { result = "#ellipsis" } - final override int getIndex() { result = func.getNumberOfParameters() } + final override int getIndex() { result = func.(Language::Function).getNumberOfParameters() } } /** diff --git a/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll b/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll index e5a908bbf9a..8e863ddf635 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/Instruction.qll @@ -194,7 +194,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets the function that contains this instruction. */ - final Language::Function getEnclosingFunction() { + final Language::Declaration getEnclosingFunction() { result = this.getEnclosingIRFunction().getFunction() } diff --git a/csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll b/csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll index 59dadee7154..53cdc75512b 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/PrintIR.qll @@ -26,20 +26,20 @@ class PrintIRConfiguration extends TPrintIRConfiguration { * Holds if the IR for `func` should be printed. By default, holds for all * functions. */ - predicate shouldPrintFunction(Language::Function func) { any() } + predicate shouldPrintFunction(Language::Declaration decl) { any() } } /** * Override of `IRConfiguration` to only evaluate debug strings for the functions that are to be dumped. */ private class FilteredIRConfiguration extends IRConfiguration { - override predicate shouldEvaluateDebugStringsForFunction(Language::Function func) { + override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) { shouldPrintFunction(func) } } -private predicate shouldPrintFunction(Language::Function func) { - exists(PrintIRConfiguration config | config.shouldPrintFunction(func)) +private predicate shouldPrintFunction(Language::Declaration decl) { + exists(PrintIRConfiguration config | config.shouldPrintFunction(decl)) } private string getAdditionalInstructionProperty(Instruction instr, string key) { diff --git a/csharp/ql/src/experimental/ir/implementation/raw/internal/IRConstruction.qll b/csharp/ql/src/experimental/ir/implementation/raw/internal/IRConstruction.qll index db6bd5c24e5..80002ffc020 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/internal/IRConstruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/internal/IRConstruction.qll @@ -46,6 +46,9 @@ module Raw { cached predicate functionHasIR(Callable callable) { exists(getTranslatedFunction(callable)) } + cached + predicate varHasIRFunc(Field field) { none() } + cached predicate hasInstruction(TranslatedElement element, InstructionTag tag) { element.hasInstruction(_, tag, _) diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRBlock.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRBlock.qll index bac7634cbd0..78008a6c69b 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRBlock.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRBlock.qll @@ -97,7 +97,7 @@ class IRBlockBase extends TIRBlock { /** * Gets the `Function` that contains this block. */ - final Language::Function getEnclosingFunction() { + final Language::Declaration getEnclosingFunction() { result = getFirstInstruction(this).getEnclosingFunction() } } diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRConsistency.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRConsistency.qll index 31983d34247..45b44b14a3c 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRConsistency.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRConsistency.qll @@ -524,4 +524,23 @@ module InstructionConsistency { "' has a `this` argument operand that is not an address, in function '$@'." and irFunc = getInstructionIRFunction(instr, irFuncText) } + + query predicate nonUniqueIRVariable( + Instruction instr, string message, OptionalIRFunction irFunc, string irFuncText + ) { + exists(VariableInstruction vi, IRVariable v1, IRVariable v2 | + instr = vi and vi.getIRVariable() = v1 and vi.getIRVariable() = v2 and v1 != v2 + ) and + message = + "Variable instruction '" + instr.toString() + + "' has multiple associated variables, in function '$@'." and + irFunc = getInstructionIRFunction(instr, irFuncText) + or + instr.getOpcode() instanceof Opcode::VariableAddress and + not instr instanceof VariableInstruction and + message = + "Variable address instruction '" + instr.toString() + + "' has no associated variable, in function '$@'." and + irFunc = getInstructionIRFunction(instr, irFuncText) + } } diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRVariable.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRVariable.qll index ca4708857a7..c92082d767d 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRVariable.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/IRVariable.qll @@ -18,7 +18,7 @@ private import Imports::IRType * by the AST-to-IR translation (`IRTempVariable`). */ class IRVariable extends TIRVariable { - Language::Function func; + Language::Declaration func; IRVariable() { this = TIRUserVariable(_, _, func) or @@ -79,7 +79,7 @@ class IRVariable extends TIRVariable { /** * Gets the function that references this variable. */ - final Language::Function getEnclosingFunction() { result = func } + final Language::Declaration getEnclosingFunction() { result = func } } /** @@ -246,7 +246,7 @@ class IREllipsisVariable extends IRTempVariable, IRParameter { final override string toString() { result = "#ellipsis" } - final override int getIndex() { result = func.getNumberOfParameters() } + final override int getIndex() { result = func.(Language::Function).getNumberOfParameters() } } /** diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll index e5a908bbf9a..8e863ddf635 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/Instruction.qll @@ -194,7 +194,7 @@ class Instruction extends Construction::TStageInstruction { /** * Gets the function that contains this instruction. */ - final Language::Function getEnclosingFunction() { + final Language::Declaration getEnclosingFunction() { result = this.getEnclosingIRFunction().getFunction() } diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll index 59dadee7154..53cdc75512b 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/PrintIR.qll @@ -26,20 +26,20 @@ class PrintIRConfiguration extends TPrintIRConfiguration { * Holds if the IR for `func` should be printed. By default, holds for all * functions. */ - predicate shouldPrintFunction(Language::Function func) { any() } + predicate shouldPrintFunction(Language::Declaration decl) { any() } } /** * Override of `IRConfiguration` to only evaluate debug strings for the functions that are to be dumped. */ private class FilteredIRConfiguration extends IRConfiguration { - override predicate shouldEvaluateDebugStringsForFunction(Language::Function func) { + override predicate shouldEvaluateDebugStringsForFunction(Language::Declaration func) { shouldPrintFunction(func) } } -private predicate shouldPrintFunction(Language::Function func) { - exists(PrintIRConfiguration config | config.shouldPrintFunction(func)) +private predicate shouldPrintFunction(Language::Declaration decl) { + exists(PrintIRConfiguration config | config.shouldPrintFunction(decl)) } private string getAdditionalInstructionProperty(Instruction instr, string key) { diff --git a/csharp/ql/src/experimental/ir/internal/IRCSharpLanguage.qll b/csharp/ql/src/experimental/ir/internal/IRCSharpLanguage.qll index 88c27315c2f..11fbe784ca0 100644 --- a/csharp/ql/src/experimental/ir/internal/IRCSharpLanguage.qll +++ b/csharp/ql/src/experimental/ir/internal/IRCSharpLanguage.qll @@ -8,6 +8,12 @@ class OpaqueTypeTag = CSharp::ValueOrRefType; class Function = CSharp::Callable; +class GlobalVariable extends CSharp::Field { + GlobalVariable() { this.isStatic() } +} + +class Declaration = CSharp::Declaration; + class Location = CSharp::Location; class UnknownLocation = CSharp::EmptyLocation; diff --git a/csharp/ql/test/experimental/ir/ir/raw_ir_consistency.expected b/csharp/ql/test/experimental/ir/ir/raw_ir_consistency.expected index 7231134d5e2..05ab9037c87 100644 --- a/csharp/ql/test/experimental/ir/ir/raw_ir_consistency.expected +++ b/csharp/ql/test/experimental/ir/ir/raw_ir_consistency.expected @@ -28,6 +28,7 @@ fieldAddressOnNonPointer thisArgumentIsNonPointer | inoutref.cs:32:22:32:35 | Call: object creation of type MyStruct | Call instruction 'Call: object creation of type MyStruct' has a `this` argument operand that is not an address, in function '$@'. | inoutref.cs:29:17:29:20 | System.Void InOutRef.Main() | System.Void InOutRef.Main() | | pointers.cs:27:22:27:35 | Call: object creation of type MyStruct | Call instruction 'Call: object creation of type MyStruct' has a `this` argument operand that is not an address, in function '$@'. | pointers.cs:25:17:25:20 | System.Void Pointers.Main() | System.Void Pointers.Main() | +nonUniqueIRVariable missingCanonicalLanguageType multipleCanonicalLanguageTypes missingIRType diff --git a/csharp/ql/test/experimental/ir/ir/unaliased_ssa_consistency.expected b/csharp/ql/test/experimental/ir/ir/unaliased_ssa_consistency.expected index 7231134d5e2..05ab9037c87 100644 --- a/csharp/ql/test/experimental/ir/ir/unaliased_ssa_consistency.expected +++ b/csharp/ql/test/experimental/ir/ir/unaliased_ssa_consistency.expected @@ -28,6 +28,7 @@ fieldAddressOnNonPointer thisArgumentIsNonPointer | inoutref.cs:32:22:32:35 | Call: object creation of type MyStruct | Call instruction 'Call: object creation of type MyStruct' has a `this` argument operand that is not an address, in function '$@'. | inoutref.cs:29:17:29:20 | System.Void InOutRef.Main() | System.Void InOutRef.Main() | | pointers.cs:27:22:27:35 | Call: object creation of type MyStruct | Call instruction 'Call: object creation of type MyStruct' has a `this` argument operand that is not an address, in function '$@'. | pointers.cs:25:17:25:20 | System.Void Pointers.Main() | System.Void Pointers.Main() | +nonUniqueIRVariable missingCanonicalLanguageType multipleCanonicalLanguageTypes missingIRType