MCPcopy Create free account
hub / github.com/argotorg/solidity / checkDoubleStorageAssignment

Method checkDoubleStorageAssignment

libsolidity/analysis/StaticAnalyzer.cpp:373–468  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

371}
372
373void StaticAnalyzer::checkDoubleStorageAssignment(Assignment const& _assignment)
374{
375 size_t storageToStorageCopies = 0;
376 size_t toStorageCopies = 0;
377 size_t storageByteArrayPushes = 0;
378 size_t storageByteAccesses = 0;
379 auto count = [&](TupleExpression const& _lhs, TupleType const& _rhs, auto _recurse) -> void {
380 TupleType const& lhsType = dynamic_cast<TupleType const&>(*type(_lhs));
381 TupleExpression const* lhsResolved = dynamic_cast<TupleExpression const*>(resolveOuterUnaryTuples(&_lhs));
382
383 solAssert(lhsResolved && lhsResolved->components().size() == lhsType.components().size());
384 if (lhsType.components().size() != _rhs.components().size())
385 {
386 solAssert(m_errorReporter.hasErrors(), "");
387 return;
388 }
389
390 for (auto&& [index, componentType]: lhsType.components() | ranges::views::enumerate)
391 {
392 if (ReferenceType const* ref = dynamic_cast<ReferenceType const*>(componentType))
393 {
394 if (ref->dataStoredIn(DataLocation::Storage) && !ref->isPointer())
395 {
396 toStorageCopies++;
397 if (_rhs.components()[index]->dataStoredIn(DataLocation::Storage))
398 storageToStorageCopies++;
399 }
400 }
401 else if (FixedBytesType const* bytesType = dynamic_cast<FixedBytesType const*>(componentType))
402 {
403 if (bytesType->numBytes() == 1)
404 {
405 if (FunctionCall const* lhsCall = dynamic_cast<FunctionCall const*>(resolveOuterUnaryTuples(lhsResolved->components().at(index).get())))
406 {
407 FunctionType const& callType = dynamic_cast<FunctionType const&>(*type(lhsCall->expression()));
408 if (callType.kind() == FunctionType::Kind::ArrayPush)
409 {
410 ArrayType const& arrayType = dynamic_cast<ArrayType const&>(*callType.selfType());
411 if (arrayType.isByteArray() && arrayType.dataStoredIn(DataLocation::Storage))
412 {
413 ++storageByteAccesses;
414 ++storageByteArrayPushes;
415 }
416 }
417 }
418 else if (IndexAccess const* indexAccess = dynamic_cast<IndexAccess const*>(resolveOuterUnaryTuples(lhsResolved->components().at(index).get())))
419 {
420 if (ArrayType const* arrayType = dynamic_cast<ArrayType const*>(type(indexAccess->baseExpression())))
421 if (arrayType->isByteArray() && arrayType->dataStoredIn(DataLocation::Storage))
422 ++storageByteAccesses;
423 }
424 }
425 }
426 else if (dynamic_cast<TupleType const*>(componentType))
427 if (auto const* lhsNested = dynamic_cast<TupleExpression const*>(lhsResolved->components().at(index).get()))
428 if (auto const* rhsNestedType = dynamic_cast<TupleType const*>(_rhs.components().at(index)))
429 _recurse(
430 *lhsNested,

Callers

nothing calls this directly

Calls 15

typeFunction · 0.85
resolveOuterUnaryTuplesFunction · 0.85
countFunction · 0.85
isPointerMethod · 0.80
numBytesMethod · 0.80
atMethod · 0.80
selfTypeMethod · 0.80
isByteArrayMethod · 0.80
sizeMethod · 0.45
hasErrorsMethod · 0.45
dataStoredInMethod · 0.45
getMethod · 0.45

Tested by

no test coverage detected