mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #11124 from ethereum/extend-callgraph
Add creationCode/runtimeCode contract creation detection to call graph
This commit is contained in:
commit
54cea090bf
@ -165,6 +165,18 @@ bool FunctionCallGraphBuilder::visit(Identifier const& _identifier)
|
||||
|
||||
bool FunctionCallGraphBuilder::visit(MemberAccess const& _memberAccess)
|
||||
{
|
||||
TypePointer exprType = _memberAccess.expression().annotation().type;
|
||||
ASTString const& memberName = _memberAccess.memberName();
|
||||
|
||||
if (auto magicType = dynamic_cast<MagicType const*>(exprType))
|
||||
if (magicType->kind() == MagicType::Kind::MetaType && (
|
||||
memberName == "creationCode" || memberName == "runtimeCode"
|
||||
))
|
||||
{
|
||||
ContractType const& accessedContractType = dynamic_cast<ContractType const&>(*magicType->typeArgument());
|
||||
m_graph.bytecodeDependency.emplace(&accessedContractType.contractDefinition(), &_memberAccess);
|
||||
}
|
||||
|
||||
auto functionType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type);
|
||||
auto functionDef = dynamic_cast<FunctionDefinition const*>(_memberAccess.annotation().referencedDeclaration);
|
||||
if (!functionType || !functionDef || functionType->kind() != FunctionType::Kind::Internal)
|
||||
@ -173,7 +185,7 @@ bool FunctionCallGraphBuilder::visit(MemberAccess const& _memberAccess)
|
||||
// Super functions
|
||||
if (*_memberAccess.annotation().requiredLookup == VirtualLookup::Super)
|
||||
{
|
||||
if (auto const* typeType = dynamic_cast<TypeType const*>(_memberAccess.expression().annotation().type))
|
||||
if (auto const* typeType = dynamic_cast<TypeType const*>(exprType))
|
||||
if (auto const contractType = dynamic_cast<ContractType const*>(typeType->actualType()))
|
||||
{
|
||||
solAssert(contractType->isSuper(), "");
|
||||
@ -187,7 +199,6 @@ bool FunctionCallGraphBuilder::visit(MemberAccess const& _memberAccess)
|
||||
solAssert(*_memberAccess.annotation().requiredLookup == VirtualLookup::Static, "");
|
||||
|
||||
functionReferenced(*functionDef, _memberAccess.annotation().calledDirectly);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -212,7 +223,7 @@ bool FunctionCallGraphBuilder::visit(ModifierInvocation const& _modifierInvocati
|
||||
bool FunctionCallGraphBuilder::visit(NewExpression const& _newExpression)
|
||||
{
|
||||
if (ContractType const* contractType = dynamic_cast<ContractType const*>(_newExpression.typeName().annotation().type))
|
||||
m_graph.createdContracts.emplace(&contractType->contractDefinition());
|
||||
m_graph.bytecodeDependency.emplace(&contractType->contractDefinition(), &_newExpression);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -61,8 +61,9 @@ struct CallGraph
|
||||
/// any calls.
|
||||
std::map<Node, std::set<Node, CompareByID>, CompareByID> edges;
|
||||
|
||||
/// Contracts that may get created with `new` by functions present in the graph.
|
||||
std::set<ContractDefinition const*, ASTNode::CompareByID> createdContracts;
|
||||
/// Contracts that need to be compiled before this one can be compiled.
|
||||
/// The value is the ast node that created the dependency.
|
||||
std::map<ContractDefinition const*, ASTNode const*, ASTNode::CompareByID> bytecodeDependency;
|
||||
|
||||
/// Events that may get emitted by functions present in the graph.
|
||||
std::set<EventDefinition const*, ASTNode::CompareByID> emittedEvents;
|
||||
|
@ -159,8 +159,8 @@ void checkCallGraphExpectations(
|
||||
CallGraph const& callGraph = *_callGraphs.at(contractName);
|
||||
|
||||
edges[contractName] = edgeNames(callGraph.edges);
|
||||
if (!callGraph.createdContracts.empty())
|
||||
createdContractSets[contractName] = callGraph.createdContracts | views::transform(getContractName) | to<set<string>>();
|
||||
if (!callGraph.bytecodeDependency.empty())
|
||||
createdContractSets[contractName] = callGraph.bytecodeDependency | views::keys | views::transform(getContractName) | to<set<string>>();
|
||||
if (!callGraph.emittedEvents.empty())
|
||||
emittedEventSets[contractName] = callGraph.emittedEvents | views::transform(eventToString) | to<set<string>>();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user