C++: IR translation for non-runtime-initialized static local variables.

This commit is contained in:
Mathias Vorreiter Pedersen
2023-04-18 19:19:59 +01:00
parent 4bf03e7962
commit d14ee931e1
10 changed files with 50 additions and 28 deletions

View File

@@ -6,7 +6,7 @@ private import IRFunctionBaseInternal
private newtype TIRFunction = private newtype TIRFunction =
TFunctionIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) } or TFunctionIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) } or
TVarInitIRFunction(Language::GlobalVariable var) { IRConstruction::Raw::varHasIRFunc(var) } TVarInitIRFunction(Language::Variable var) { IRConstruction::Raw::varHasIRFunc(var) }
/** /**
* The IR for a function. This base class contains only the predicates that are the same between all * The IR for a function. This base class contains only the predicates that are the same between all

View File

@@ -37,7 +37,13 @@ module Raw {
predicate functionHasIR(Function func) { exists(getTranslatedFunction(func)) } predicate functionHasIR(Function func) { exists(getTranslatedFunction(func)) }
cached cached
predicate varHasIRFunc(GlobalOrNamespaceVariable var) { predicate varHasIRFunc(Variable var) {
(
var instanceof GlobalOrNamespaceVariable
or
not var.isFromUninstantiatedTemplate(_) and
var instanceof StaticInitializedStaticLocalVariable
) and
var.hasInitializer() and var.hasInitializer() and
( (
not var.getType().isDeeplyConst() not var.getType().isDeeplyConst()
@@ -75,9 +81,10 @@ module Raw {
} }
cached cached
predicate hasDynamicInitializationFlag(Function func, StaticLocalVariable var, CppType type) { predicate hasDynamicInitializationFlag(
Function func, RuntimeInitializedStaticLocalVariable var, CppType type
) {
var.getFunction() = func and var.getFunction() = func and
var.hasDynamicInitialization() and
type = getBoolType() type = getBoolType()
} }

View File

@@ -62,15 +62,6 @@ private predicate ignoreExprAndDescendants(Expr expr) {
// constant value. // constant value.
isIRConstant(getRealParent(expr)) isIRConstant(getRealParent(expr))
or or
// Only translate the initializer of a static local if it uses run-time data.
// Otherwise the initializer does not run in function scope.
exists(Initializer init, StaticStorageDurationVariable var |
init = var.getInitializer() and
not var.hasDynamicInitialization() and
expr = init.getExpr().getFullyConverted() and
not var instanceof GlobalOrNamespaceVariable
)
or
// Ignore descendants of `__assume` expressions, since we translated these to `NoOp`. // Ignore descendants of `__assume` expressions, since we translated these to `NoOp`.
getRealParent(expr) instanceof AssumeExpr getRealParent(expr) instanceof AssumeExpr
or or
@@ -438,6 +429,17 @@ predicate hasTranslatedSyntheticTemporaryObject(Expr expr) {
not expr.hasLValueToRValueConversion() not expr.hasLValueToRValueConversion()
} }
class StaticInitializedStaticLocalVariable extends StaticLocalVariable {
StaticInitializedStaticLocalVariable() {
this.hasInitializer() and
not this.hasDynamicInitialization()
}
}
class RuntimeInitializedStaticLocalVariable extends StaticLocalVariable {
RuntimeInitializedStaticLocalVariable() { this.hasDynamicInitialization() }
}
/** /**
* Holds if the specified `DeclarationEntry` needs an IR translation. An IR translation is only * Holds if the specified `DeclarationEntry` needs an IR translation. An IR translation is only
* necessary for automatic local variables, or for static local variables with dynamic * necessary for automatic local variables, or for static local variables with dynamic
@@ -453,7 +455,7 @@ private predicate translateDeclarationEntry(IRDeclarationEntry entry) {
not var.isStatic() not var.isStatic()
or or
// Ignore static variables unless they have a dynamic initializer. // Ignore static variables unless they have a dynamic initializer.
var.(StaticLocalVariable).hasDynamicInitialization() var instanceof RuntimeInitializedStaticLocalVariable
) )
) )
} }
@@ -755,7 +757,7 @@ newtype TTranslatedElement =
} or } or
// The side effect that initializes newly-allocated memory. // The side effect that initializes newly-allocated memory.
TTranslatedAllocationSideEffect(AllocationExpr expr) { not ignoreSideEffects(expr) } or TTranslatedAllocationSideEffect(AllocationExpr expr) { not ignoreSideEffects(expr) } or
TTranslatedGlobalOrNamespaceVarInit(GlobalOrNamespaceVariable var) { Raw::varHasIRFunc(var) } TTranslatedStaticStorageDurationVarInit(Variable var) { Raw::varHasIRFunc(var) }
/** /**
* Gets the index of the first explicitly initialized element in `initList` * Gets the index of the first explicitly initialized element in `initList`
@@ -1043,6 +1045,6 @@ abstract class TranslatedRootElement extends TranslatedElement {
TranslatedRootElement() { TranslatedRootElement() {
this instanceof TTranslatedFunction this instanceof TTranslatedFunction
or or
this instanceof TTranslatedGlobalOrNamespaceVarInit this instanceof TTranslatedStaticStorageDurationVarInit
} }
} }

View File

@@ -322,6 +322,8 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
( (
var instanceof GlobalOrNamespaceVariable var instanceof GlobalOrNamespaceVariable
or or
var instanceof StaticLocalVariable
or
var instanceof MemberVariable and not var instanceof Field var instanceof MemberVariable and not var instanceof Field
) and ) and
exists(VariableAccess access | exists(VariableAccess access |

View File

@@ -8,16 +8,16 @@ private import TranslatedInitialization
private import InstructionTag private import InstructionTag
private import semmle.code.cpp.ir.internal.IRUtilities private import semmle.code.cpp.ir.internal.IRUtilities
class TranslatedGlobalOrNamespaceVarInit extends TranslatedRootElement, class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
TTranslatedGlobalOrNamespaceVarInit, InitializationContext TTranslatedStaticStorageDurationVarInit, InitializationContext
{ {
GlobalOrNamespaceVariable var; Variable var;
TranslatedGlobalOrNamespaceVarInit() { this = TTranslatedGlobalOrNamespaceVarInit(var) } TranslatedStaticStorageDurationVarInit() { this = TTranslatedStaticStorageDurationVarInit(var) }
override string toString() { result = var.toString() } override string toString() { result = var.toString() }
final override GlobalOrNamespaceVariable getAst() { result = var } final override Variable getAst() { result = var }
final override Declaration getFunction() { result = var } final override Declaration getFunction() { result = var }
@@ -111,6 +111,8 @@ class TranslatedGlobalOrNamespaceVarInit extends TranslatedRootElement,
( (
varUsed instanceof GlobalOrNamespaceVariable varUsed instanceof GlobalOrNamespaceVariable
or or
varUsed instanceof StaticLocalVariable
or
varUsed instanceof MemberVariable and not varUsed instanceof Field varUsed instanceof MemberVariable and not varUsed instanceof Field
) and ) and
exists(VariableAccess access | exists(VariableAccess access |
@@ -128,6 +130,4 @@ class TranslatedGlobalOrNamespaceVarInit extends TranslatedRootElement,
} }
} }
TranslatedGlobalOrNamespaceVarInit getTranslatedVarInit(GlobalOrNamespaceVariable var) { TranslatedStaticStorageDurationVarInit getTranslatedVarInit(Variable var) { result.getAst() = var }
result.getAst() = var
}

View File

@@ -139,7 +139,8 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
final override Declaration getFunction() { final override Declaration getFunction() {
result = expr.getEnclosingFunction() or result = expr.getEnclosingFunction() or
result = expr.getEnclosingVariable().(GlobalOrNamespaceVariable) result = expr.getEnclosingVariable().(GlobalOrNamespaceVariable) or
result = expr.getEnclosingVariable().(StaticInitializedStaticLocalVariable)
} }
final override Locatable getAst() { result = expr } final override Locatable getAst() { result = expr }
@@ -654,6 +655,8 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
result = initList.getEnclosingFunction() result = initList.getEnclosingFunction()
or or
result = initList.getEnclosingVariable().(GlobalOrNamespaceVariable) result = initList.getEnclosingVariable().(GlobalOrNamespaceVariable)
or
result = initList.getEnclosingVariable().(StaticInitializedStaticLocalVariable)
} }
final override Instruction getFirstInstruction() { result = getInstruction(getElementIndexTag()) } final override Instruction getFirstInstruction() { result = getInstruction(getElementIndexTag()) }

View File

@@ -47,7 +47,7 @@ class Variable = Cpp::Variable;
class AutomaticVariable = Cpp::StackVariable; class AutomaticVariable = Cpp::StackVariable;
class StaticVariable = Cpp::Variable; class StaticVariable = Cpp::StaticStorageDurationVariable;
class GlobalVariable = Cpp::GlobalOrNamespaceVariable; class GlobalVariable = Cpp::GlobalOrNamespaceVariable;

View File

@@ -1,3 +1,9 @@
private import cpp
private import semmle.code.cpp.Print as Print private import semmle.code.cpp.Print as Print
predicate getIdentityString = Print::getIdentityString/1; string getIdentityString(Declaration decl) {
if decl instanceof StaticLocalVariable
then
exists(StaticLocalVariable v | v = decl | result = v.getType().toString() + " " + v.getName())
else result = Print::getIdentityString(decl)
}

View File

@@ -18,5 +18,7 @@ predicate shouldDumpFunction(Declaration decl) {
decl instanceof Function decl instanceof Function
or or
decl.(GlobalOrNamespaceVariable).hasInitializer() decl.(GlobalOrNamespaceVariable).hasInitializer()
or
decl.(StaticLocalVariable).hasInitializer()
) )
} }

View File

@@ -6,7 +6,7 @@ private import IRFunctionBaseInternal
private newtype TIRFunction = private newtype TIRFunction =
TFunctionIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) } or TFunctionIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) } or
TVarInitIRFunction(Language::GlobalVariable var) { IRConstruction::Raw::varHasIRFunc(var) } TVarInitIRFunction(Language::Variable var) { IRConstruction::Raw::varHasIRFunc(var) }
/** /**
* The IR for a function. This base class contains only the predicates that are the same between all * The IR for a function. This base class contains only the predicates that are the same between all