in Sources/SolToBoogie/ProcedureTranslator.cs [1085:1205]
private void GenerateConstructorWithBaseCalls(FunctionDefinition ctor, List<BoogieVariable> inParams)
{
VeriSolAssert(ctor.IsConstructor, $"{ctor.Name} is not a constructor");
ContractDefinition contract = context.GetContractByFunction(ctor);
string procName = contract.Name + "_" + contract.Name;
// no output params for constructor
List<BoogieVariable> outParams = new List<BoogieVariable>();
List<BoogieAttribute> attributes = new List<BoogieAttribute>()
{
new BoogieAttribute("constructor"),
new BoogieAttribute("public"),
};
if (context.TranslateFlags.GenerateInlineAttributes)
{
attributes.Add(new BoogieAttribute("inline", 1));
};
BoogieProcedure procedure = new BoogieProcedure(procName, inParams, outParams, attributes);
context.Program.AddDeclaration(procedure);
// skip if it in ignored set
if (context.IsMethodInIgnoredSet(ctor, currentContract))
{
Console.WriteLine($"Warning!: Ignoring constructor {ctor.Name} in contract {currentContract.Name} specified using /ignoreMethod:");
}
else
{
// no local variables for constructor
List<BoogieVariable> localVars = new List<BoogieVariable>();
BoogieStmtList ctorBody = new BoogieStmtList();
List<int> baseContractIds = new List<int>(contract.LinearizedBaseContracts);
baseContractIds.Reverse();
// Print function argument values to corral.txt for counterexample:
PrintArguments(ctor, inParams, ctorBody);
//Note that the current derived contract appears as a baseContractId
foreach (int id in baseContractIds)
{
ContractDefinition baseContract = context.GetASTNodeById(id) as ContractDefinition;
VeriSolAssert(baseContract != null);
// since we are not translating any statements, currentStmtList remains null
currentStmtList = new BoogieStmtList();
string callee = TransUtils.GetCanonicalConstructorName(baseContract);
if (baseContract.Name == contract.Name)
{
// for current contract, call the body that does not have the base calls
// for base contracts, call the wrapper constructor
callee += "_NoBaseCtor";
}
List<BoogieExpr> inputs = new List<BoogieExpr>();
List<BoogieIdentifierExpr> outputs = new List<BoogieIdentifierExpr>();
InheritanceSpecifier inheritanceSpecifier = GetInheritanceSpecifieWithArgsOfBase(contract, baseContract);
ModifierInvocation modifierInvocation = GetModifierInvocationOfBase(ctor, baseContract);
if (inheritanceSpecifier != null)
{
inputs.Add(new BoogieIdentifierExpr("this"));
inputs.Add(new BoogieIdentifierExpr("msgsender_MSG"));
inputs.Add(new BoogieIdentifierExpr("msgvalue_MSG"));
foreach (Expression argument in inheritanceSpecifier.Arguments)
{
inputs.Add(TranslateExpr(argument));
}
}
else if (modifierInvocation != null)
{
inputs.Add(new BoogieIdentifierExpr("this"));
inputs.Add(new BoogieIdentifierExpr("msgsender_MSG"));
inputs.Add(new BoogieIdentifierExpr("msgvalue_MSG"));
foreach (Expression argument in modifierInvocation.Arguments)
{
inputs.Add(TranslateExpr(argument));
}
}
else // no argument for this base constructor
{
if (baseContract.Name == contract.Name)
{
// only do this for the derived contract
foreach (BoogieVariable param in inParams)
{
inputs.Add(new BoogieIdentifierExpr(param.TypedIdent.Name));
}
}
else
{
// Do we call the constructor or assume that it is invoked in teh base contract?
// Do we call the constructor or assume that it is invoked in teh base contract?
// since it needs argument, we cannot invoke it here (Issue #101)
var baseCtr = context.IsConstructorDefined(baseContract) ? context.GetConstructorByContract(baseContract) : null;
if (baseCtr != null && baseCtr.Parameters.Length() > 0)
{
continue;
}
else if (!currentContract.BaseContracts.Any(x => x.BaseName.Name.Equals(baseContract.Name)))
{
Console.WriteLine($"Warning!!: Invoking base constructor { callee} that is not explicitly called in the inheritance/modifier list specified in { ctor.Name}...");
}
inputs.Add(new BoogieIdentifierExpr("this"));
inputs.Add(new BoogieIdentifierExpr("msgsender_MSG"));
inputs.Add(new BoogieIdentifierExpr("msgvalue_MSG"));
}
}
BoogieCallCmd callCmd = new BoogieCallCmd(callee, inputs, outputs);
ctorBody.AppendStmtList(currentStmtList);
ctorBody.AddStatement(callCmd);
currentStmtList = null;
}
localVars.AddRange(boogieToLocalVarsMap[currentBoogieProc]);
BoogieImplementation implementation = new BoogieImplementation(procName, inParams, outParams, localVars, ctorBody);
context.Program.AddDeclaration(implementation);
}
}