Merge remote-tracking branch 'origin/develop' into breaking

This commit is contained in:
chriseth 2020-06-15 17:11:41 +02:00
commit 8155ad2187
132 changed files with 1083 additions and 417 deletions

View File

@ -110,7 +110,7 @@ matrix:
before_install:
- nvm install 8
- nvm use 8
- docker pull ethereum/solidity-buildpack-deps:emsdk-1.39.15-1
- docker pull ethereum/solidity-buildpack-deps:emsdk-1.39.15-2
env:
- SOLC_EMSCRIPTEN=On
- SOLC_INSTALL_DEPS_TRAVIS=Off

View File

@ -20,18 +20,38 @@ Bugfixes:
* NatSpec: Constructors and functions have consistent userdoc output.
### 0.6.10 (unreleased)
### 0.6.11 (unreleased)
Language Features:
Compiler Features:
* NatSpec: Add fields "kind" and "version" to the JSON output.
Bugfixes:
### 0.6.10 (2020-06-11)
Important Bugfixes:
* Fixed a bug related to internal library functions with ``calldata`` parameters called via ``using for``.
Compiler Features:
* Commandline Interface: Re-group help screen.
* Output compilation error codes in standard-json and when using ``--error-codes``.
* Yul: Raise warning for switch statements that only have a default and no other cases.
Bugfixes:
* SMTChecker: Fix internal error when encoding tuples of tuples.
* SMTChecker: Fix aliasing soundness after pushing to an array pointer.
* Type system: Fix internal compiler error on calling externally a function that returns variables with calldata location.
* Type system: Fix bug where a bound function was not found if ``using for`` is applied to explicit reference types.
### 0.6.9 (2020-06-04)

View File

@ -1,4 +1,12 @@
[
{
"name": "UsingForCalldata",
"summary": "Function calls to internal library functions with calldata parameters called via ``using for`` can result in invalid data being read.",
"description": "Function calls to internal library functions using the ``using for`` mechanism copied all calldata parameters to memory first and passed them on like that, regardless of whether it was an internal or an external call. Due to that, the called function would receive a memory pointer that is interpreted as a calldata pointer. Since dynamically sized arrays are passed using two stack slots for calldata, but only one for memory, this can lead to stack corruption. An affected library call will consider the JUMPDEST to which it is supposed to return as part of its arguments and will instead jump out to whatever was on the stack before the call.",
"introduced": "0.6.9",
"fixed": "0.6.10",
"severity": "very low"
},
{
"name": "MissingEscapingInFormatting",
"summary": "String literals containing double backslash characters passed directly to external or encoding function calls can lead to a different string being used when ABIEncoderV2 is enabled.",

View File

@ -1105,6 +1105,10 @@
],
"released": "2020-01-02"
},
"0.6.10": {
"bugs": [],
"released": "2020-06-11"
},
"0.6.2": {
"bugs": [
"MissingEscapingInFormatting",
@ -1165,7 +1169,9 @@
"released": "2020-05-14"
},
"0.6.9": {
"bugs": [],
"bugs": [
"UsingForCalldata"
],
"released": "2020-06-04"
}
}

View File

@ -430,7 +430,13 @@ Array slices are useful to ABI-decode secondary data passed in function paramete
/// Forward call to "setOwner(address)" that is implemented by client
/// after doing basic validation on the address argument.
function forward(bytes calldata _payload) external {
bytes4 sig = abi.decode(_payload[:4], (bytes4));
// Since ABI decoding requires padded data, we cannot
// use abi.decode(_payload[:4], (bytes4)).
bytes4 sig =
_payload[0] |
(bytes4(_payload[1]) >> 8) |
(bytes4(_payload[2]) >> 16) |
(bytes4(_payload[3]) >> 24);
if (sig == bytes4(keccak256("setOwner(address)"))) {
address owner = abi.decode(_payload[4:], (address));
require(owner != address(0), "Address of owner cannot be zero.");

View File

@ -374,8 +374,10 @@ Output Description
"component": "general",
// Mandatory ("error" or "warning")
"severity": "error",
// Optional: unique code for the cause of the error
"errorCode": "3141",
// Mandatory
"message": "Invalid keyword"
"message": "Invalid keyword",
// Optional: the message formatted with source location
"formattedMessage": "sourceFile.sol:100: Invalid keyword"
}

View File

@ -59,7 +59,7 @@ void AssemblyItem::setPushTagSubIdAndTag(size_t _subId, size_t _tag)
setData(data);
}
unsigned AssemblyItem::bytesRequired(unsigned _addressLength) const
size_t AssemblyItem::bytesRequired(size_t _addressLength) const
{
switch (m_type)
{
@ -69,7 +69,7 @@ unsigned AssemblyItem::bytesRequired(unsigned _addressLength) const
case PushString:
return 1 + 32;
case Push:
return 1 + max<unsigned>(1, util::bytesRequired(data()));
return 1 + max<size_t>(1, util::bytesRequired(data()));
case PushSubSize:
case PushProgramSize:
return 1 + 4; // worst case: a 16MB program

View File

@ -133,7 +133,7 @@ public:
/// @returns an upper bound for the number of bytes required by this item, assuming that
/// the value of a jump tag takes @a _addressLength bytes.
unsigned bytesRequired(unsigned _addressLength) const;
size_t bytesRequired(size_t _addressLength) const;
size_t arguments() const;
size_t returnValues() const;
size_t deposit() const { return returnValues() - arguments(); }

View File

@ -107,7 +107,7 @@ tuple<int, int> CharStream::translatePositionToLineColumn(int _position) const
using size_type = string::size_type;
using diff_type = string::difference_type;
size_type searchPosition = min<size_type>(m_source.size(), size_type(_position));
int lineNumber = count(m_source.begin(), m_source.begin() + diff_type(searchPosition), '\n');
int lineNumber = static_cast<int>(count(m_source.begin(), m_source.begin() + diff_type(searchPosition), '\n'));
size_type lineStart;
if (searchPosition == 0)
lineStart = 0;

View File

@ -179,7 +179,7 @@ bool Scanner::scanHexByte(char& o_scannedByte)
rollback(i);
return false;
}
x = x * 16 + d;
x = static_cast<char>(x * 16 + d);
advance();
}
o_scannedByte = x;
@ -197,7 +197,7 @@ std::optional<unsigned> Scanner::scanUnicode()
rollback(i);
return {};
}
x = x * 16 + static_cast<size_t>(d);
x = x * 16 + static_cast<unsigned>(d);
advance();
}
return x;

View File

@ -38,7 +38,15 @@ SourceReferenceExtractor::Message SourceReferenceExtractor::extract(util::Except
for (auto const& info: secondaryLocation->infos)
secondary.emplace_back(extract(&info.second, info.first));
return Message{std::move(primary), _category, std::move(secondary)};
return Message{std::move(primary), _category, std::move(secondary), nullopt};
}
SourceReferenceExtractor::Message SourceReferenceExtractor::extract(Error const& _error)
{
string category = (_error.type() == Error::Type::Warning) ? "Warning" : "Error";
Message message = extract(_error, category);
message.errorId = _error.errorId();
return message;
}
SourceReference SourceReferenceExtractor::extract(SourceLocation const* _location, std::string message)

View File

@ -16,16 +16,14 @@
*/
#pragma once
#include <liblangutil/Exceptions.h>
#include <iosfwd>
#include <optional>
#include <string>
#include <tuple>
#include <vector>
namespace solidity::util
{
struct Exception;
}
namespace solidity::langutil
{
@ -58,8 +56,6 @@ struct SourceReference
}
};
struct SourceLocation;
namespace SourceReferenceExtractor
{
struct Message
@ -67,9 +63,11 @@ namespace SourceReferenceExtractor
SourceReference primary;
std::string category; // "Error", "Warning", ...
std::vector<SourceReference> secondary;
std::optional<ErrorId> errorId;
};
Message extract(util::Exception const& _exception, std::string _category);
Message extract(Error const& _error);
SourceReference extract(SourceLocation const* _location, std::string message = "");
}

View File

@ -80,10 +80,7 @@ void SourceReferenceFormatter::printExceptionInformation(util::Exception const&
void SourceReferenceFormatter::printErrorInformation(Error const& _error)
{
printExceptionInformation(
_error,
(_error.type() == Error::Type::Warning) ? "Warning" : "Error"
);
printExceptionInformation(SourceReferenceExtractor::extract(_error));
}
void SourceReferenceFormatter::printExceptionInformation(SourceReferenceExtractor::Message const& _msg)

View File

@ -151,6 +151,8 @@ void SourceReferenceFormatterHuman::printExceptionInformation(SourceReferenceExt
{
// exception header line
errorColored() << _msg.category;
if (m_withErrorIds && _msg.errorId.has_value())
errorColored() << " (" << _msg.errorId.value().error << ")";
messageColored() << ": " << _msg.primary.message << '\n';
printSourceLocation(_msg.primary);

View File

@ -29,22 +29,14 @@
#include <sstream>
#include <functional>
namespace solidity::util
{
struct Exception; // forward
}
namespace solidity::langutil
{
struct SourceLocation;
struct SourceReference;
class SourceReferenceFormatterHuman: public SourceReferenceFormatter
{
public:
SourceReferenceFormatterHuman(std::ostream& _stream, bool colored):
SourceReferenceFormatter{_stream}, m_colored{colored}
SourceReferenceFormatterHuman(std::ostream& _stream, bool _colored, bool _withErrorIds):
SourceReferenceFormatter{_stream}, m_colored{_colored}, m_withErrorIds(_withErrorIds)
{}
void printSourceLocation(SourceReference const& _ref) override;
@ -54,12 +46,13 @@ public:
static std::string formatExceptionInformation(
util::Exception const& _exception,
std::string const& _name,
bool colored = false
bool _colored = false,
bool _withErrorIds = false
)
{
std::ostringstream errorOutput;
SourceReferenceFormatterHuman formatter(errorOutput, colored);
SourceReferenceFormatterHuman formatter(errorOutput, _colored, _withErrorIds);
formatter.printExceptionInformation(_exception, _name);
return errorOutput.str();
}
@ -75,6 +68,7 @@ private:
private:
bool m_colored;
bool m_withErrorIds;
};
}

View File

@ -68,7 +68,7 @@ struct OverrideGraph
std::map<OverrideProxy, int> nodes;
std::map<int, OverrideProxy> nodeInv;
std::map<int, std::set<int>> edges;
int numNodes = 2;
size_t numNodes = 2;
void addEdge(int _a, int _b)
{
edges[_a].insert(_b);
@ -82,7 +82,7 @@ private:
auto it = nodes.find(_function);
if (it != nodes.end())
return it->second;
int currentNode = numNodes++;
int currentNode = static_cast<int>(numNodes++);
nodes[_function] = currentNode;
nodeInv[currentNode] = _function;
if (_function.overrides())
@ -116,21 +116,24 @@ private:
std::vector<int> m_parent = std::vector<int>(m_graph.numNodes, -1);
std::set<OverrideProxy> m_cutVertices{};
void run(int _u = 0, int _depth = 0)
void run(size_t _u = 0, size_t _depth = 0)
{
m_visited.at(_u) = true;
m_depths.at(_u) = m_low.at(_u) = _depth;
for (int v: m_graph.edges.at(_u))
if (!m_visited.at(v))
m_depths.at(_u) = m_low.at(_u) = static_cast<int>(_depth);
for (int const v: m_graph.edges.at(static_cast<int>(_u)))
{
m_parent[v] = _u;
run(v, _depth + 1);
if (m_low[v] >= m_depths[_u] && m_parent[_u] != -1)
m_cutVertices.insert(m_graph.nodeInv.at(_u));
m_low[_u] = min(m_low[_u], m_low[v]);
auto const vInd = static_cast<size_t>(v);
if (!m_visited.at(vInd))
{
m_parent[vInd] = static_cast<int>(_u);
run(vInd, _depth + 1);
if (m_low[vInd] >= m_depths[_u] && m_parent[_u] != -1)
m_cutVertices.insert(m_graph.nodeInv.at(static_cast<int>(_u)));
m_low[_u] = min(m_low[_u], m_low[vInd]);
}
else if (v != m_parent[_u])
m_low[_u] = min(m_low[_u], m_depths[v]);
m_low[_u] = min(m_low[_u], m_depths[vInd]);
}
}
};
@ -213,7 +216,7 @@ bool OverrideProxy::CompareBySignature::operator()(OverrideProxy const& _a, Over
size_t OverrideProxy::id() const
{
return std::visit(GenericVisitor{
[&](auto const* _item) -> size_t { return _item->id(); }
[&](auto const* _item) -> size_t { return static_cast<size_t>(_item->id()); }
}, m_item);
}

View File

@ -668,7 +668,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
{
auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier);
if (ref == _inlineAssembly.annotation().externalReferences.end())
return size_t(-1);
return numeric_limits<size_t>::max();
Declaration const* declaration = ref->second.declaration;
solAssert(!!declaration, "");
bool requiresStorage = ref->second.isSlot || ref->second.isOffset;
@ -678,7 +678,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
if (var->immutable())
{
m_errorReporter.typeError(3773_error, _identifier.location, "Assembly access to immutable variables is not supported.");
return size_t(-1);
return numeric_limits<size_t>::max();
}
if (var->isConstant())
{
@ -687,17 +687,17 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
if (var && !var->value())
{
m_errorReporter.typeError(3224_error, _identifier.location, "Constant has no value.");
return size_t(-1);
return numeric_limits<size_t>::max();
}
else if (_context == yul::IdentifierContext::LValue)
{
m_errorReporter.typeError(6252_error, _identifier.location, "Constant variables cannot be assigned to.");
return size_t(-1);
return numeric_limits<size_t>::max();
}
else if (requiresStorage)
{
m_errorReporter.typeError(6617_error, _identifier.location, "The suffixes _offset and _slot can only be used on non-constant storage variables.");
return size_t(-1);
return numeric_limits<size_t>::max();
}
else if (var && var->value() && !var->value()->annotation().type && !dynamic_cast<Literal const*>(var->value().get()))
{
@ -725,19 +725,19 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
if (!var->isStateVariable() && !var->type()->dataStoredIn(DataLocation::Storage))
{
m_errorReporter.typeError(3622_error, _identifier.location, "The suffixes _offset and _slot can only be used on storage variables.");
return size_t(-1);
return numeric_limits<size_t>::max();
}
else if (_context == yul::IdentifierContext::LValue)
{
if (var->isStateVariable())
{
m_errorReporter.typeError(4713_error, _identifier.location, "State variables cannot be assigned to - you have to use \"sstore()\".");
return size_t(-1);
return numeric_limits<size_t>::max();
}
else if (ref->second.isOffset)
{
m_errorReporter.typeError(9739_error, _identifier.location, "Only _slot can be assigned to.");
return size_t(-1);
return numeric_limits<size_t>::max();
}
else
solAssert(ref->second.isSlot, "");
@ -746,12 +746,12 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
else if (!var->isConstant() && var->isStateVariable())
{
m_errorReporter.typeError(1408_error, _identifier.location, "Only local variables are supported. To access storage variables, use the _slot and _offset suffixes.");
return size_t(-1);
return numeric_limits<size_t>::max();
}
else if (var->type()->dataStoredIn(DataLocation::Storage))
{
m_errorReporter.typeError(9068_error, _identifier.location, "You have to use the _slot or _offset suffix to access storage reference variables.");
return size_t(-1);
return numeric_limits<size_t>::max();
}
else if (var->type()->sizeOnStack() != 1)
{
@ -759,21 +759,21 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
m_errorReporter.typeError(2370_error, _identifier.location, "Call data elements cannot be accessed directly. Copy to a local variable first or use \"calldataload\" or \"calldatacopy\" with manually determined offsets and sizes.");
else
m_errorReporter.typeError(9857_error, _identifier.location, "Only types that use one stack slot are supported.");
return size_t(-1);
return numeric_limits<size_t>::max();
}
}
else if (requiresStorage)
{
m_errorReporter.typeError(7944_error, _identifier.location, "The suffixes _offset and _slot can only be used on storage variables.");
return size_t(-1);
return numeric_limits<size_t>::max();
}
else if (_context == yul::IdentifierContext::LValue)
{
if (dynamic_cast<MagicVariableDeclaration const*>(declaration))
return size_t(-1);
return numeric_limits<size_t>::max();
m_errorReporter.typeError(1990_error, _identifier.location, "Only local variables can be assigned to in inline assembly.");
return size_t(-1);
return numeric_limits<size_t>::max();
}
if (_context == yul::IdentifierContext::RValue)
@ -782,7 +782,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
if (dynamic_cast<FunctionDefinition const*>(declaration))
{
m_errorReporter.declarationError(2025_error, _identifier.location, "Access to functions is not allowed in inline assembly.");
return size_t(-1);
return numeric_limits<size_t>::max();
}
else if (dynamic_cast<VariableDeclaration const*>(declaration))
{
@ -792,11 +792,11 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
if (!contract->isLibrary())
{
m_errorReporter.typeError(4977_error, _identifier.location, "Expected a library.");
return size_t(-1);
return numeric_limits<size_t>::max();
}
}
else
return size_t(-1);
return numeric_limits<size_t>::max();
}
ref->second.valueSize = 1;
return size_t(1);

View File

@ -38,7 +38,7 @@ using namespace solidity;
using namespace solidity::frontend;
ASTNode::ASTNode(int64_t _id, SourceLocation _location):
m_id(_id),
m_id(static_cast<size_t>(_id)),
m_location(std::move(_location))
{
}

View File

@ -88,7 +88,7 @@ public:
virtual ~ASTNode() {}
/// @returns an identifier of this AST node that is unique for a single compilation run.
int64_t id() const { return m_id; }
int64_t id() const { return int64_t(m_id); }
virtual void accept(ASTVisitor& _visitor) = 0;
virtual void accept(ASTConstVisitor& _visitor) const = 0;

View File

@ -37,6 +37,7 @@
#include <utility>
#include <vector>
#include <algorithm>
#include <limits>
using namespace std;
using namespace solidity::langutil;
@ -134,7 +135,7 @@ size_t ASTJsonConverter::sourceIndexFromLocation(SourceLocation const& _location
if (_location.source && m_sourceIndices.count(_location.source->name()))
return m_sourceIndices.at(_location.source->name());
else
return size_t(-1);
return numeric_limits<size_t>::max();
}
string ASTJsonConverter::sourceLocationToString(SourceLocation const& _location) const

View File

@ -92,7 +92,7 @@ SourceLocation const ASTJsonImporter::createSourceLocation(Json::Value const& _n
{
astAssert(member(_node, "src").isString(), "'src' must be a string");
return solidity::langutil::parseSourceLocation(_node["src"].asString(), m_currentSourceName, int(m_sourceLocations.size()));
return solidity::langutil::parseSourceLocation(_node["src"].asString(), m_currentSourceName, m_sourceLocations.size());
}
template<class T>

View File

@ -113,14 +113,22 @@ public:
/// @returns a copy of @a _type having the same location as this (and is not a pointer type)
/// if _type is a reference type and an unmodified copy of _type otherwise.
/// This function is mostly useful to modify inner types appropriately.
static Type const* withLocationIfReference(DataLocation _location, Type const* _type)
static Type const* withLocationIfReference(DataLocation _location, Type const* _type, bool _isPointer = false)
{
if (auto refType = dynamic_cast<ReferenceType const*>(_type))
return withLocation(refType, _location, false);
return withLocation(refType, _location, _isPointer);
return _type;
}
static bool isReferenceWithLocation(Type const* _type, DataLocation _location)
{
if (auto const* refType = dynamic_cast<ReferenceType const*>(_type))
if (refType->location() == _location)
return true;
return false;
}
/// @returns the internally-facing or externally-facing type of a function or the type of a function declaration.
static FunctionType const* function(FunctionDefinition const& _function, FunctionType::Kind _kind = FunctionType::Kind::Declaration);

View File

@ -356,10 +356,18 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition
for (ContractDefinition const* contract: _scope.annotation().linearizedBaseContracts)
for (UsingForDirective const* ufd: contract->usingForDirectives())
{
if (ufd->typeName() && _type != *TypeProvider::withLocationIfReference(
// Convert both types to pointers for comparison to see if the `using for`
// directive applies.
// Further down, we check more detailed for each function if `_type` is
// convertible to the function parameter type.
if (ufd->typeName() &&
*TypeProvider::withLocationIfReference(typeLocation, &_type, true) !=
*TypeProvider::withLocationIfReference(
typeLocation,
ufd->typeName()->annotation().type
))
ufd->typeName()->annotation().type,
true
)
)
continue;
auto const& library = dynamic_cast<ContractDefinition const&>(
*ufd->libraryName().annotation().referencedDeclaration
@ -371,7 +379,8 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition
seenFunctions.insert(function);
if (function->parameters().empty())
continue;
FunctionTypePointer fun = FunctionType(*function, FunctionType::Kind::External).asExternallyCallableFunction(true, true);
FunctionTypePointer fun =
dynamic_cast<FunctionType const&>(*function->typeViaContractName()).asBoundFunction();
if (_type.isImplicitlyConvertibleTo(*fun->selfType()))
members.emplace_back(function->name(), fun, function);
}
@ -773,7 +782,7 @@ tuple<bool, rational> RationalNumberType::parseRational(string const& _value)
denominator = bigint(string(fractionalBegin, _value.end()));
denominator /= boost::multiprecision::pow(
bigint(10),
distance(radixPoint + 1, _value.end())
static_cast<size_t>(distance(radixPoint + 1, _value.end()))
);
numerator = bigint(string(_value.begin(), radixPoint));
value = numerator + denominator;
@ -1093,7 +1102,7 @@ TypeResult RationalNumberType::binaryOperatorResult(Token _operator, Type const*
if (_base == 1)
return 1;
else if (_base == -1)
return 1 - 2 * int(_exponent & 1);
return 1 - 2 * static_cast<int>(_exponent & 1);
else
return boost::multiprecision::pow(_base, _exponent);
};
@ -1199,7 +1208,7 @@ string RationalNumberType::bigintToReadableString(bigint const& _num)
string str = _num.str();
if (str.size() > 32)
{
int omitted = str.size() - 8;
size_t omitted = str.size() - 8;
str = str.substr(0, 4) + "...(" + to_string(omitted) + " digits omitted)..." + str.substr(str.size() - 4, 4);
}
return str;
@ -1229,7 +1238,7 @@ u256 RationalNumberType::literalValue(Literal const*) const
{
auto fixed = fixedPointType();
solAssert(fixed, "Rational number cannot be represented as fixed point type.");
int fractionalDigits = fixed->fractionalDigits();
unsigned fractionalDigits = fixed->fractionalDigits();
shiftedValue = m_value.numerator() * boost::multiprecision::pow(bigint(10), fractionalDigits) / m_value.denominator();
}
@ -1319,7 +1328,7 @@ StringLiteralType::StringLiteralType(string _value):
BoolResult StringLiteralType::isImplicitlyConvertibleTo(Type const& _convertTo) const
{
if (auto fixedBytes = dynamic_cast<FixedBytesType const*>(&_convertTo))
return size_t(fixedBytes->numBytes()) >= m_value.size();
return static_cast<size_t>(fixedBytes->numBytes()) >= m_value.size();
else if (auto arrayType = dynamic_cast<ArrayType const*>(&_convertTo))
return
arrayType->isByteArray() &&
@ -2485,6 +2494,21 @@ set<string> StructType::membersMissingInMemory() const
return missing;
}
vector<tuple<string, TypePointer>> StructType::makeStackItems() const
{
switch (m_location)
{
case DataLocation::CallData:
return {std::make_tuple("offset", TypeProvider::uint256())};
case DataLocation::Memory:
return {std::make_tuple("mpos", TypeProvider::uint256())};
case DataLocation::Storage:
return {std::make_tuple("slot", TypeProvider::uint256())};
}
solAssert(false, "");
}
TypePointer EnumType::encodingType() const
{
return TypeProvider::uint(8 * storageBytes());
@ -3466,34 +3490,61 @@ TypePointer FunctionType::copyAndSetCallOptions(bool _setGas, bool _setValue, bo
);
}
FunctionTypePointer FunctionType::asExternallyCallableFunction(bool _inLibrary, bool _bound) const
FunctionTypePointer FunctionType::asBoundFunction() const
{
if (_bound)
solAssert(!m_parameterTypes.empty(), "");
FunctionDefinition const* fun = dynamic_cast<FunctionDefinition const*>(m_declaration);
solAssert(fun && fun->libraryFunction(), "");
solAssert(!m_gasSet, "");
solAssert(!m_valueSet, "");
solAssert(!m_saltSet, "");
return TypeProvider::function(
m_parameterTypes,
m_returnParameterTypes,
m_parameterNames,
m_returnParameterNames,
m_kind,
m_arbitraryParameters,
m_stateMutability,
m_declaration,
m_gasSet,
m_valueSet,
m_saltSet,
true
);
}
FunctionTypePointer FunctionType::asExternallyCallableFunction(bool _inLibrary) const
{
TypePointers parameterTypes;
for (auto const& t: m_parameterTypes)
{
auto refType = dynamic_cast<ReferenceType const*>(t);
if (refType && refType->location() == DataLocation::CallData)
parameterTypes.push_back(TypeProvider::withLocation(refType, DataLocation::Memory, true));
if (TypeProvider::isReferenceWithLocation(t, DataLocation::CallData))
parameterTypes.push_back(
TypeProvider::withLocationIfReference(DataLocation::Memory, t, true)
);
else
parameterTypes.push_back(t);
}
TypePointers returnParameterTypes;
for (auto const& returnParamType: m_returnParameterTypes)
if (TypeProvider::isReferenceWithLocation(returnParamType, DataLocation::CallData))
returnParameterTypes.push_back(
TypeProvider::withLocationIfReference(DataLocation::Memory, returnParamType, true)
);
else
returnParameterTypes.push_back(returnParamType);
Kind kind = m_kind;
if (_inLibrary)
{
solAssert(!!m_declaration, "Declaration has to be available.");
if (!m_declaration->isPublic())
kind = Kind::Internal; // will be inlined
else
solAssert(m_declaration->isPublic(), "");
kind = Kind::DelegateCall;
}
return TypeProvider::function(
parameterTypes,
m_returnParameterTypes,
returnParameterTypes,
m_parameterNames,
m_returnParameterNames,
kind,
@ -3503,7 +3554,7 @@ FunctionTypePointer FunctionType::asExternallyCallableFunction(bool _inLibrary,
m_gasSet,
m_valueSet,
m_saltSet,
_bound
m_bound
);
}

View File

@ -980,6 +980,8 @@ public:
void clearCache() const override;
protected:
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override;
private:
StructDefinition const& m_struct;
// Caches for interfaceType(bool)
@ -1302,13 +1304,16 @@ public:
/// of the parameters to false.
TypePointer copyAndSetCallOptions(bool _setGas, bool _setValue, bool _setSalt) const;
/// @returns a copy of this function type with the `bound` flag set to true.
/// Should only be called on library functions.
FunctionTypePointer asBoundFunction() const;
/// @returns a copy of this function type where the location of reference types is changed
/// from CallData to Memory. This is the type that would be used when the function is
/// called externally, as opposed to the parameter types that are available inside the function body.
/// Also supports variants to be used for library or bound calls.
/// @param _inLibrary if true, uses DelegateCall as location.
/// @param _bound if true, the function type is set to be bound.
FunctionTypePointer asExternallyCallableFunction(bool _inLibrary, bool _bound = false) const;
FunctionTypePointer asExternallyCallableFunction(bool _inLibrary) const;
protected:
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override;

View File

@ -725,7 +725,7 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray(
size_t itemsPerSlot = 32 / storageBytes;
solAssert(itemsPerSlot > 0, "");
// The number of elements we need to handle manually after the loop.
size_t spill = size_t(_from.length() % itemsPerSlot);
size_t spill = static_cast<size_t>(_from.length() % itemsPerSlot);
Whiskers templ(
R"(
// <readableTypeNameFrom> -> <readableTypeNameTo>

View File

@ -56,7 +56,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
bool directCopy = sourceIsStorage && sourceBaseType->isValueType() && *sourceBaseType == *targetBaseType;
bool haveByteOffsetSource = !directCopy && sourceIsStorage && sourceBaseType->storageBytes() <= 16;
bool haveByteOffsetTarget = !directCopy && targetBaseType->storageBytes() <= 16;
unsigned byteOffsetSize = (haveByteOffsetSource ? 1 : 0) + (haveByteOffsetTarget ? 1 : 0);
unsigned byteOffsetSize = (haveByteOffsetSource ? 1u : 0u) + (haveByteOffsetTarget ? 1u : 0u);
// stack: source_ref [source_length] target_ref
// store target_ref

View File

@ -133,7 +133,7 @@ void CompilerContext::callLowLevelFunction(
*this << lowLevelFunctionTag(_name, _inArgs, _outArgs, _generator);
appendJump(evmasm::AssemblyItem::JumpType::IntoFunction);
adjustStackOffset(int(_outArgs) - 1 - _inArgs);
adjustStackOffset(static_cast<int>(_outArgs) - 1 - static_cast<int>(_inArgs));
*this << retTag.tag();
}
@ -147,7 +147,7 @@ void CompilerContext::callYulFunction(
auto const retTag = pushNewTag();
CompilerUtils(*this).moveIntoStack(_inArgs);
appendJumpTo(namedTag(_name));
adjustStackOffset(int(_outArgs) - 1 - _inArgs);
adjustStackOffset(static_cast<int>(_outArgs) - 1 - static_cast<int>(_inArgs));
*this << retTag.tag();
}
@ -181,7 +181,7 @@ void CompilerContext::appendMissingLowLevelFunctions()
tie(name, inArgs, outArgs, generator) = m_lowLevelFunctionGenerationQueue.front();
m_lowLevelFunctionGenerationQueue.pop();
setStackOffset(inArgs + 1);
setStackOffset(static_cast<int>(inArgs) + 1);
*this << m_lowLevelFunctions.at(name).tag();
generator(*this);
CompilerUtils(*this).moveToStackTop(outArgs);
@ -298,12 +298,12 @@ unsigned CompilerContext::baseStackOffsetOfVariable(Declaration const& _declarat
unsigned CompilerContext::baseToCurrentStackOffset(unsigned _baseOffset) const
{
return m_asm->deposit() - _baseOffset - 1;
return static_cast<unsigned>(m_asm->deposit()) - _baseOffset - 1;
}
unsigned CompilerContext::currentToBaseStackOffset(unsigned _offset) const
{
return m_asm->deposit() - _offset - 1;
return static_cast<unsigned>(m_asm->deposit()) - _offset - 1;
}
pair<u256, unsigned> CompilerContext::storageLocationOfVariable(Declaration const& _declaration) const
@ -371,7 +371,7 @@ void CompilerContext::appendInlineAssembly(
OptimiserSettings const& _optimiserSettings
)
{
int startStackHeight = stackHeight();
unsigned startStackHeight = stackHeight();
set<yul::YulString> externallyUsedIdentifiers;
for (auto const& fun: _externallyUsedFunctions)
@ -387,9 +387,9 @@ void CompilerContext::appendInlineAssembly(
) -> size_t
{
if (_insideFunction)
return size_t(-1);
return numeric_limits<size_t>::max();
auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name.str());
return it == _localVariables.end() ? size_t(-1) : 1;
return it == _localVariables.end() ? numeric_limits<size_t>::max() : 1;
};
identifierAccess.generateCode = [&](
yul::Identifier const& _identifier,
@ -399,8 +399,8 @@ void CompilerContext::appendInlineAssembly(
{
auto it = std::find(_localVariables.begin(), _localVariables.end(), _identifier.name.str());
solAssert(it != _localVariables.end(), "");
int stackDepth = _localVariables.end() - it;
int stackDiff = _assembly.stackHeight() - startStackHeight + stackDepth;
auto stackDepth = static_cast<size_t>(distance(it, _localVariables.end()));
size_t stackDiff = static_cast<size_t>(_assembly.stackHeight()) - startStackHeight + stackDepth;
if (_context == yul::IdentifierContext::LValue)
stackDiff -= 1;
if (stackDiff < 1 || stackDiff > 16)

View File

@ -377,7 +377,7 @@ private:
/// The runtime context if in Creation mode, this is used for generating tags that would be stored into the storage and then used at runtime.
CompilerContext *m_runtimeContext;
/// The index of the runtime subroutine.
size_t m_runtimeSub = -1;
size_t m_runtimeSub = std::numeric_limits<size_t>::max();
/// An index of low-level function labels by name.
std::map<std::string, evmasm::AssemblyItem> m_lowLevelFunctions;
/// Collector for yul functions.

View File

@ -1351,7 +1351,7 @@ void CompilerUtils::popAndJump(unsigned _toHeight, evmasm::AssemblyItem const& _
unsigned amount = m_context.stackHeight() - _toHeight;
popStackSlots(amount);
m_context.appendJumpTo(_jumpTo);
m_context.adjustStackOffset(amount);
m_context.adjustStackOffset(static_cast<int>(amount));
}
unsigned CompilerUtils::sizeOnStack(vector<Type const*> const& _variableTypes)
@ -1436,7 +1436,7 @@ unsigned CompilerUtils::loadFromMemoryHelper(Type const& _type, bool _fromCallda
{
bool leftAligned = _type.category() == Type::Category::FixedBytes;
// add leading or trailing zeros by dividing/multiplying depending on alignment
int shiftFactor = (32 - numBytes) * 8;
unsigned shiftFactor = (32 - numBytes) * 8;
rightShiftNumberOnStack(shiftFactor);
if (leftAligned)
{

View File

@ -185,7 +185,7 @@ size_t ContractCompiler::packIntoContractCreator(ContractDefinition const& _cont
CompilerContext::LocationSetter locationSetter(m_context, _contract);
m_context << deployRoutine;
solAssert(m_context.runtimeSub() != size_t(-1), "Runtime sub not registered");
solAssert(m_context.runtimeSub() != numeric_limits<size_t>::max(), "Runtime sub not registered");
ContractType contractType(_contract);
auto const& immutables = contractType.immutableVariables();
@ -221,7 +221,7 @@ size_t ContractCompiler::deployLibrary(ContractDefinition const& _contract)
CompilerContext::LocationSetter locationSetter(m_context, _contract);
solAssert(m_context.runtimeSub() != size_t(-1), "Runtime sub not registered");
solAssert(m_context.runtimeSub() != numeric_limits<size_t>::max(), "Runtime sub not registered");
m_context.pushSubroutineSize(m_context.runtimeSub());
m_context.pushSubroutineOffset(m_context.runtimeSub());
// This code replaces the address added by appendDeployTimeAddress().
@ -349,11 +349,11 @@ void ContractCompiler::appendInternalSelector(
m_context << dupInstruction(1) << u256(FixedHash<4>::Arith(pivot)) << Instruction::GT;
evmasm::AssemblyItem lessTag{m_context.appendConditionalJump()};
// Here, we have funid >= pivot
vector<FixedHash<4>> larger{_ids.begin() + pivotIndex, _ids.end()};
vector<FixedHash<4>> larger{_ids.begin() + static_cast<ptrdiff_t>(pivotIndex), _ids.end()};
appendInternalSelector(_entryPoints, larger, _notFoundTag, _runs);
m_context << lessTag;
// Here, we have funid < pivot
vector<FixedHash<4>> smaller{_ids.begin(), _ids.begin() + pivotIndex};
vector<FixedHash<4>> smaller{_ids.begin(), _ids.begin() + static_cast<ptrdiff_t>(pivotIndex)};
appendInternalSelector(_entryPoints, smaller, _notFoundTag, _runs);
}
else
@ -512,8 +512,8 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
m_context << returnTag;
// Return tag and input parameters get consumed.
m_context.adjustStackOffset(
CompilerUtils(m_context).sizeOnStack(functionType->returnParameterTypes()) -
CompilerUtils(m_context).sizeOnStack(functionType->parameterTypes()) -
static_cast<int>(CompilerUtils::sizeOnStack(functionType->returnParameterTypes())) -
static_cast<int>(CompilerUtils::sizeOnStack(functionType->parameterTypes())) -
1
);
// Consumes the return parameters.
@ -589,7 +589,7 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
unsigned parametersSize = CompilerUtils::sizeOnStack(_function.parameters());
if (!_function.isConstructor())
// adding 1 for return address.
m_context.adjustStackOffset(parametersSize + 1);
m_context.adjustStackOffset(static_cast<int>(parametersSize) + 1);
for (ASTPointer<VariableDeclaration> const& variable: _function.parameters())
{
m_context.addVariable(*variable, parametersSize);
@ -609,7 +609,7 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
m_breakTags.clear();
m_continueTags.clear();
m_currentFunction = &_function;
m_modifierDepth = -1;
m_modifierDepth = numeric_limits<unsigned>::max();
m_scopeStackHeight.clear();
m_context.setModifierDepth(0);
@ -627,10 +627,10 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
unsigned const c_returnValuesSize = CompilerUtils::sizeOnStack(_function.returnParameters());
vector<int> stackLayout;
stackLayout.push_back(c_returnValuesSize); // target of return address
stackLayout.push_back(static_cast<int>(c_returnValuesSize)); // target of return address
stackLayout += vector<int>(c_argumentsSize, -1); // discard all arguments
for (unsigned i = 0; i < c_returnValuesSize; ++i)
stackLayout.push_back(i);
for (size_t i = 0; i < c_returnValuesSize; ++i)
stackLayout.push_back(static_cast<int>(i));
if (stackLayout.size() > 17)
BOOST_THROW_EXCEPTION(
@ -638,7 +638,7 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
errinfo_sourceLocation(_function.location()) <<
errinfo_comment("Stack too deep, try removing local variables.")
);
while (stackLayout.back() != int(stackLayout.size() - 1))
while (stackLayout.back() != static_cast<int>(stackLayout.size() - 1))
if (stackLayout.back() < 0)
{
m_context << Instruction::POP;
@ -646,11 +646,11 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
}
else
{
m_context << swapInstruction(stackLayout.size() - stackLayout.back() - 1);
swap(stackLayout[stackLayout.back()], stackLayout.back());
m_context << swapInstruction(stackLayout.size() - static_cast<size_t>(stackLayout.back()) - 1);
swap(stackLayout[static_cast<size_t>(stackLayout.back())], stackLayout.back());
}
for (int i = 0; i < int(stackLayout.size()); ++i)
if (stackLayout[i] != i)
for (size_t i = 0; i < stackLayout.size(); ++i)
if (stackLayout[i] != static_cast<int>(i))
solAssert(false, "Invalid stack layout on cleanup.");
for (ASTPointer<VariableDeclaration> const& variable: _function.parameters() + _function.returnParameters())
@ -677,7 +677,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
{
auto ref = _inlineAssembly.annotation().externalReferences.find(&_identifier);
if (ref == _inlineAssembly.annotation().externalReferences.end())
return size_t(-1);
return numeric_limits<size_t>::max();
return ref->second.valueSize;
};
identifierAccess.generateCode = [&](yul::Identifier const& _identifier, yul::IdentifierContext _context, yul::AbstractAssembly& _assembly)
@ -696,7 +696,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
functionDef = &functionDef->resolveVirtual(m_context.mostDerivedContract());
auto functionEntryLabel = m_context.functionEntryLabel(*functionDef).pushTag();
solAssert(functionEntryLabel.data() <= std::numeric_limits<size_t>::max(), "");
_assembly.appendLabelReference(size_t(functionEntryLabel.data()));
_assembly.appendLabelReference(static_cast<size_t>(functionEntryLabel.data()));
// If there is a runtime context, we have to merge both labels into the same
// stack slot in case we store it in storage.
if (CompilerContext* rtc = m_context.runtimeContext())
@ -705,7 +705,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
_assembly.appendInstruction(Instruction::MUL);
auto runtimeEntryLabel = rtc->functionEntryLabel(*functionDef).toSubAssemblyTag(m_context.runtimeSub());
solAssert(runtimeEntryLabel.data() <= std::numeric_limits<size_t>::max(), "");
_assembly.appendLabelReference(size_t(runtimeEntryLabel.data()));
_assembly.appendLabelReference(static_cast<size_t>(runtimeEntryLabel.data()));
_assembly.appendInstruction(Instruction::OR);
}
}
@ -772,7 +772,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
}
else if (m_context.isLocalVariable(decl))
{
int stackDiff = _assembly.stackHeight() - m_context.baseStackOffsetOfVariable(*variable);
unsigned stackDiff = static_cast<unsigned>(_assembly.stackHeight()) - m_context.baseStackOffsetOfVariable(*variable);
if (ref->second.isSlot || ref->second.isOffset)
{
solAssert(variable->type()->dataStoredIn(DataLocation::Storage), "");
@ -816,7 +816,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
}
else
solAssert(false, "Invalid declaration type.");
solAssert(_assembly.stackHeight() - depositBefore == int(ref->second.valueSize), "");
solAssert(_assembly.stackHeight() - depositBefore == static_cast<int>(ref->second.valueSize), "");
}
else
{
@ -828,7 +828,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
"Can only assign to stack variables in inline assembly."
);
solAssert(variable->type()->sizeOnStack() == 1, "");
int stackDiff = _assembly.stackHeight() - m_context.baseStackOffsetOfVariable(*variable) - 1;
unsigned stackDiff = static_cast<unsigned>(_assembly.stackHeight()) - m_context.baseStackOffsetOfVariable(*variable) - 1;
if (stackDiff > 16 || stackDiff < 1)
BOOST_THROW_EXCEPTION(
CompilerError() <<
@ -875,7 +875,7 @@ bool ContractCompiler::visit(InlineAssembly const& _inlineAssembly)
false,
m_optimiserSettings.optimizeStackAllocation
);
m_context.setStackOffset(startStackHeight);
m_context.setStackOffset(static_cast<int>(startStackHeight));
return false;
}
@ -914,7 +914,7 @@ bool ContractCompiler::visit(TryStatement const& _tryStatement)
solAssert(params[i] && exprTypes[i] && *params[i]->annotation().type == *exprTypes[i], "");
}
else
CompilerUtils(m_context).popStackSlots(returnSize);
CompilerUtils(m_context).popStackSlots(static_cast<size_t>(returnSize));
_tryStatement.clauses().front()->accept(*this);
}
@ -937,7 +937,7 @@ void ContractCompiler::handleCatch(vector<ASTPointer<TryCatchClause>> const& _ca
else
solAssert(false, "");
solAssert(_catchClauses.size() == size_t(1 + (structured ? 1 : 0) + (fallback ? 1 : 0)), "");
solAssert(_catchClauses.size() == 1ul + (structured ? 1 : 0) + (fallback ? 1 : 0), "");
evmasm::AssemblyItem endTag = m_context.newTag();
evmasm::AssemblyItem fallbackTag = m_context.newTag();

View File

@ -100,7 +100,7 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
if (_varDecl.immutable())
solAssert(paramTypes.empty(), "");
m_context.adjustStackOffset(1 + CompilerUtils::sizeOnStack(paramTypes));
m_context.adjustStackOffset(static_cast<int>(1 + CompilerUtils::sizeOnStack(paramTypes)));
if (!_varDecl.immutable())
{
@ -242,7 +242,7 @@ bool ExpressionCompiler::visit(Conditional const& _condition)
acceptAndConvert(_condition.falseExpression(), *_condition.annotation().type);
evmasm::AssemblyItem endTag = m_context.appendJumpToNew();
m_context << trueTag;
int offset = _condition.annotation().type->sizeOnStack();
int offset = static_cast<int>(_condition.annotation().type->sizeOnStack());
m_context.adjustStackOffset(-offset);
acceptAndConvert(_condition.trueExpression(), *_condition.annotation().type);
m_context << endTag;
@ -619,7 +619,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
unsigned returnParametersSize = CompilerUtils::sizeOnStack(function.returnParameterTypes());
// callee adds return parameters, but removes arguments and return label
m_context.adjustStackOffset(returnParametersSize - parameterSize - 1);
m_context.adjustStackOffset(static_cast<int>(returnParametersSize - parameterSize) - 1);
break;
}
case FunctionType::Kind::BareCall:
@ -705,7 +705,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
acceptAndConvert(*arguments.front(), *TypeProvider::uint256(), true);
// Note that function is not the original function, but the ".gas" function.
// Its values of gasSet and valueSet is equal to the original function's though.
unsigned stackDepth = (function.gasSet() ? 1 : 0) + (function.valueSet() ? 1 : 0);
unsigned stackDepth = (function.gasSet() ? 1u : 0u) + (function.valueSet() ? 1u : 0u);
if (stackDepth > 0)
m_context << swapInstruction(stackDepth);
if (function.gasSet())
@ -814,7 +814,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
case FunctionType::Kind::Log3:
case FunctionType::Kind::Log4:
{
unsigned logNumber = int(function.kind()) - int(FunctionType::Kind::Log0);
unsigned logNumber = static_cast<unsigned>(function.kind()) - static_cast<unsigned>(FunctionType::Kind::Log0);
for (unsigned arg = logNumber; arg > 0; --arg)
acceptAndConvert(*arguments[arg], *function.parameterTypes()[arg], true);
arguments.front()->accept(*this);
@ -1088,7 +1088,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
{
utils().revertWithStringData(*arguments.at(1)->annotation().type);
// Here, the argument is consumed, but in the other branch, it is still there.
m_context.adjustStackOffset(arguments.at(1)->annotation().type->sizeOnStack());
m_context.adjustStackOffset(static_cast<int>(arguments.at(1)->annotation().type->sizeOnStack()));
}
else
m_context.appendRevert();
@ -1271,9 +1271,9 @@ bool ExpressionCompiler::visit(FunctionCallOptions const& _functionCallOptions)
acceptAndConvert(*_functionCallOptions.options()[i], *requiredType);
solAssert(!contains(presentOptions, newOption), "");
size_t insertPos = presentOptions.end() - lower_bound(presentOptions.begin(), presentOptions.end(), newOption);
ptrdiff_t insertPos = presentOptions.end() - lower_bound(presentOptions.begin(), presentOptions.end(), newOption);
utils().moveIntoStack(insertPos, 1);
utils().moveIntoStack(static_cast<size_t>(insertPos), 1);
presentOptions.insert(presentOptions.end() - insertPos, newOption);
}
@ -2190,7 +2190,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
// contract address
unsigned selfSize = _functionType.bound() ? _functionType.selfType()->sizeOnStack() : 0;
unsigned gasValueSize = (_functionType.gasSet() ? 1 : 0) + (_functionType.valueSet() ? 1 : 0);
unsigned gasValueSize = (_functionType.gasSet() ? 1u : 0u) + (_functionType.valueSet() ? 1u : 0u);
unsigned contractStackPos = m_context.currentToBaseStackOffset(1 + gasValueSize + selfSize + (_functionType.isBareCall() ? 0 : 1));
unsigned gasStackPos = m_context.currentToBaseStackOffset(gasValueSize);
unsigned valueStackPos = m_context.currentToBaseStackOffset(1);
@ -2361,7 +2361,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
m_context << Instruction::CALL;
unsigned remainsSize =
2 + // contract address, input_memory_end
2u + // contract address, input_memory_end
(_functionType.valueSet() ? 1 : 0) +
(_functionType.gasSet() ? 1 : 0) +
(!_functionType.isBareCall() ? 1 : 0);

View File

@ -1652,8 +1652,7 @@ string YulUtilFunctions::allocateAndInitializeMemoryStructFunction(StructType co
return m_functionCollector.createFunction(functionName, [&]() {
Whiskers templ(R"(
function <functionName>() -> memPtr {
let allocSize := <allocSize>()
memPtr := <alloc>(allocSize)
memPtr := <alloc>(<allocSize>)
let offset := memPtr
<#member>
mstore(offset, <zeroValue>())

View File

@ -636,7 +636,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
});
solAssert(it != callArgumentNames.cend(), "");
arguments.push_back(callArguments[std::distance(callArgumentNames.begin(), it)]);
arguments.push_back(callArguments[static_cast<size_t>(std::distance(callArgumentNames.begin(), it))]);
}
auto memberAccess = dynamic_cast<MemberAccess const*>(&_functionCall.expression());
@ -1092,7 +1092,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
case FunctionType::Kind::Log3:
case FunctionType::Kind::Log4:
{
unsigned logNumber = int(functionType->kind()) - int(FunctionType::Kind::Log0);
unsigned logNumber = static_cast<unsigned>(functionType->kind()) - static_cast<unsigned>(FunctionType::Kind::Log0);
solAssert(arguments.size() == logNumber + 1, "");
ABIFunctions abi(m_context.evmVersion(), m_context.revertStrings(), m_context.functionCollector());
string indexedArgs;
@ -1477,7 +1477,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
pair<u256, unsigned> const& offsets = structType.storageOffsetsOfMember(member);
string slot = m_context.newYulVariable();
m_code << "let " << slot << " := " <<
("add(" + expression.name() + ", " + offsets.first.str() + ")\n");
("add(" + expression.part("slot").name() + ", " + offsets.first.str() + ")\n");
setLValue(_memberAccess, IRLValue{
type(_memberAccess),
IRLValue::Storage{slot, offsets.second}
@ -1497,7 +1497,25 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
}
case DataLocation::CallData:
{
solUnimplementedAssert(false, "");
string baseRef = expression.part("offset").name();
string offset = m_context.newYulVariable();
m_code << "let " << offset << " := " << "add(" << baseRef << ", " << to_string(structType.calldataOffsetOfMember(member)) << ")\n";
if (_memberAccess.annotation().type->isDynamicallyEncoded())
define(_memberAccess) <<
m_utils.accessCalldataTailFunction(*_memberAccess.annotation().type) <<
"(" <<
baseRef <<
", " <<
offset <<
")" <<
std::endl;
else
define(_memberAccess) <<
m_utils.readFromCalldata(*_memberAccess.annotation().type) <<
"(" <<
offset <<
")" <<
std::endl;
break;
}
default:

View File

@ -104,7 +104,7 @@ void CHC::analyze(SourceUnit const& _source)
for (auto const* assertion: assertions)
{
createErrorBlock();
connectBlocks(target.value, error(), target.constraints && (target.errorId == assertion->id()));
connectBlocks(target.value, error(), target.constraints && (target.errorId == static_cast<size_t>(assertion->id())));
auto [result, model] = query(error(), assertion->location());
// This should be fine but it's a bug in the old compiler
(void)model;
@ -116,7 +116,7 @@ void CHC::analyze(SourceUnit const& _source)
{
solAssert(dynamic_cast<FunctionCall const*>(scope), "");
createErrorBlock();
connectBlocks(target.value, error(), target.constraints && (target.errorId == scope->id()));
connectBlocks(target.value, error(), target.constraints && (target.errorId == static_cast<size_t>(scope->id())));
auto [result, model] = query(error(), scope->location());
// This should be fine but it's a bug in the old compiler
(void)model;
@ -533,7 +533,9 @@ void CHC::visitAssert(FunctionCall const& _funCall)
connectBlocks(
m_currentBlock,
m_currentFunction->isConstructor() ? summary(*m_currentContract) : summary(*m_currentFunction),
currentPathConditions() && !m_context.expression(*args.front())->currentValue() && (m_error.currentValue() == _funCall.id())
currentPathConditions() && !m_context.expression(*args.front())->currentValue() && (
m_error.currentValue() == static_cast<size_t>(_funCall.id())
)
);
m_context.addAssertion(m_error.currentValue() == previousError);
@ -601,7 +603,7 @@ void CHC::makeArrayPopVerificationTarget(FunctionCall const& _arrayPop)
connectBlocks(
m_currentBlock,
m_currentFunction->isConstructor() ? summary(*m_currentContract) : summary(*m_currentFunction),
currentPathConditions() && symbArray->length() <= 0 && m_error.currentValue() == _arrayPop.id()
currentPathConditions() && symbArray->length() <= 0 && m_error.currentValue() == static_cast<size_t>(_arrayPop.id())
);
m_context.addAssertion(m_error.currentValue() == previousError);
@ -891,13 +893,13 @@ vector<smtutil::Expression> CHC::initialStateVariables()
return stateVariablesAtIndex(0);
}
vector<smtutil::Expression> CHC::stateVariablesAtIndex(int _index)
vector<smtutil::Expression> CHC::stateVariablesAtIndex(unsigned _index)
{
solAssert(m_currentContract, "");
return applyMap(m_stateVariables, [&](auto _var) { return valueAtIndex(*_var, _index); });
}
vector<smtutil::Expression> CHC::stateVariablesAtIndex(int _index, ContractDefinition const& _contract)
vector<smtutil::Expression> CHC::stateVariablesAtIndex(unsigned _index, ContractDefinition const& _contract)
{
return applyMap(
stateVariablesIncludingInheritedAndPrivate(_contract),

View File

@ -149,8 +149,8 @@ private:
/// @returns the symbolic values of the state variables at the beginning
/// of the current transaction.
std::vector<smtutil::Expression> initialStateVariables();
std::vector<smtutil::Expression> stateVariablesAtIndex(int _index);
std::vector<smtutil::Expression> stateVariablesAtIndex(int _index, ContractDefinition const& _contract);
std::vector<smtutil::Expression> stateVariablesAtIndex(unsigned _index);
std::vector<smtutil::Expression> stateVariablesAtIndex(unsigned _index, ContractDefinition const& _contract);
/// @returns the current symbolic values of the current state variables.
std::vector<smtutil::Expression> currentStateVariables();

View File

@ -32,12 +32,23 @@ EncodingContext::EncodingContext():
void EncodingContext::reset()
{
resetAllVariables();
resetSlackId();
m_expressions.clear();
m_globalContext.clear();
m_state.reset();
m_assertions.clear();
}
void EncodingContext::resetSlackId()
{
m_nextSlackId = 0;
}
unsigned EncodingContext::newSlackId()
{
return m_nextSlackId++;
}
void EncodingContext::clear()
{
m_variables.clear();

View File

@ -40,6 +40,10 @@ public:
/// alive because of state variables and inlined function calls.
/// To be used in the beginning of a root function visit.
void reset();
/// Resets the fresh id for slack variables.
void resetSlackId();
/// Returns the current fresh slack id and increments it.
unsigned newSlackId();
/// Clears the entire context, erasing everything.
/// To be used before a model checking engine starts.
void clear();
@ -168,6 +172,9 @@ private:
/// Whether to conjoin assertions in the assertion stack.
bool m_accumulateAssertions = true;
//@}
/// Fresh ids for slack variables to be created deterministically.
unsigned m_nextSlackId = 0;
};
}

View File

@ -154,15 +154,16 @@ void SMTEncoder::visitFunctionOrModifier()
++m_modifierDepthStack.back();
FunctionDefinition const& function = dynamic_cast<FunctionDefinition const&>(*m_callStack.back().first);
if (m_modifierDepthStack.back() == int(function.modifiers().size()))
if (m_modifierDepthStack.back() == static_cast<int>(function.modifiers().size()))
{
if (function.isImplemented())
function.body().accept(*this);
}
else
{
solAssert(m_modifierDepthStack.back() < int(function.modifiers().size()), "");
ASTPointer<ModifierInvocation> const& modifierInvocation = function.modifiers()[m_modifierDepthStack.back()];
solAssert(m_modifierDepthStack.back() < static_cast<int>(function.modifiers().size()), "");
ASTPointer<ModifierInvocation> const& modifierInvocation =
function.modifiers()[static_cast<size_t>(m_modifierDepthStack.back())];
solAssert(modifierInvocation, "");
auto refDecl = modifierInvocation->name()->annotation().referencedDeclaration;
if (dynamic_cast<ContractDefinition const*>(refDecl))
@ -1203,7 +1204,7 @@ pair<smtutil::Expression, smtutil::Expression> SMTEncoder::arithmeticOperation(
smtutil::Expression const& _left,
smtutil::Expression const& _right,
TypePointer const& _commonType,
Expression const&
Expression const& _operation
)
{
static set<Token> validOperators{
@ -1226,39 +1227,66 @@ pair<smtutil::Expression, smtutil::Expression> SMTEncoder::arithmeticOperation(
else
intType = TypeProvider::uint256();
smtutil::Expression valueNoMod(
_op == Token::Add ? _left + _right :
_op == Token::Sub ? _left - _right :
_op == Token::Div ? division(_left, _right, *intType) :
_op == Token::Mul ? _left * _right :
/*_op == Token::Mod*/ _left % _right
);
auto valueUnbounded = [&]() -> smtutil::Expression {
switch (_op)
{
case Token::Add: return _left + _right;
case Token::Sub: return _left - _right;
case Token::Mul: return _left * _right;
case Token::Div: return division(_left, _right, *intType);
case Token::Mod: return _left % _right;
default: solAssert(false, "");
}
}();
if (_op == Token::Div || _op == Token::Mod)
{
m_context.addAssertion(_right != 0);
// mod and unsigned division never underflow/overflow
if (_op == Token::Mod || !intType->isSigned())
return {valueUnbounded, valueUnbounded};
// The only case where division overflows is
// - type is signed
// - LHS is type.min
// - RHS is -1
// the result is then -(type.min), which wraps back to type.min
smtutil::Expression maxLeft = _left == smt::minValue(*intType);
smtutil::Expression minusOneRight = _right == -1;
smtutil::Expression wrap = smtutil::Expression::ite(maxLeft && minusOneRight, smt::minValue(*intType), valueUnbounded);
return {wrap, valueUnbounded};
}
auto symbMin = smt::minValue(*intType);
auto symbMax = smt::maxValue(*intType);
smtutil::Expression intValueRange = (0 - symbMin) + symbMax + 1;
string suffix = to_string(_operation.id()) + "_" + to_string(m_context.newSlackId());
smt::SymbolicIntVariable k(intType, intType, "k_" + suffix, m_context);
smt::SymbolicIntVariable m(intType, intType, "m_" + suffix, m_context);
// To wrap around valueUnbounded in case of overflow or underflow, we replace it with a k, given:
// 1. k + m * intValueRange = valueUnbounded
// 2. k is in range of the desired integer type
auto wrap = k.currentValue();
m_context.addAssertion(valueUnbounded == (k.currentValue() + intValueRange * m.currentValue()));
m_context.addAssertion(k.currentValue() >= symbMin);
m_context.addAssertion(k.currentValue() <= symbMax);
// TODO this could be refined:
// for unsigned types it's enough to check only the upper bound.
auto value = smtutil::Expression::ite(
valueNoMod > symbMax,
valueNoMod % intValueRange,
valueUnbounded > symbMax,
wrap,
smtutil::Expression::ite(
valueNoMod < symbMin,
valueNoMod % intValueRange,
valueNoMod
valueUnbounded < symbMin,
wrap,
valueUnbounded
)
);
if (intType->isSigned())
value = smtutil::Expression::ite(
value > symbMax,
value - intValueRange,
value
);
return {value, valueNoMod};
return {value, valueUnbounded};
}
void SMTEncoder::compareOperation(BinaryOperation const& _op)
@ -1679,8 +1707,8 @@ void SMTEncoder::mergeVariables(set<VariableDeclaration const*> const& _variable
for (auto const* decl: sortedVars)
{
solAssert(_indicesEndTrue.count(decl) && _indicesEndFalse.count(decl), "");
int trueIndex = _indicesEndTrue.at(decl);
int falseIndex = _indicesEndFalse.at(decl);
auto trueIndex = static_cast<unsigned>(_indicesEndTrue.at(decl));
auto falseIndex = static_cast<unsigned>(_indicesEndFalse.at(decl));
solAssert(trueIndex != falseIndex, "");
m_context.addAssertion(m_context.newValue(*decl) == smtutil::Expression::ite(
_condition,
@ -1696,7 +1724,7 @@ smtutil::Expression SMTEncoder::currentValue(VariableDeclaration const& _decl)
return m_context.variable(_decl)->currentValue();
}
smtutil::Expression SMTEncoder::valueAtIndex(VariableDeclaration const& _decl, int _index)
smtutil::Expression SMTEncoder::valueAtIndex(VariableDeclaration const& _decl, unsigned _index)
{
solAssert(m_context.knownVariable(_decl), "");
return m_context.variable(_decl)->valueAtIndex(_index);
@ -1819,7 +1847,7 @@ SMTEncoder::VariableIndices SMTEncoder::copyVariableIndices()
void SMTEncoder::resetVariableIndices(VariableIndices const& _indices)
{
for (auto const& var: _indices)
m_context.variable(*var.first)->setIndex(var.second);
m_context.variable(*var.first)->setIndex(static_cast<unsigned>(var.second));
}
void SMTEncoder::clearIndices(ContractDefinition const* _contract, FunctionDefinition const* _function)

View File

@ -201,7 +201,7 @@ protected:
smtutil::Expression currentValue(VariableDeclaration const& _decl);
/// @returns an expression denoting the value of the variable declared in @a _decl
/// at the given index. Does not ensure that this index exists.
smtutil::Expression valueAtIndex(VariableDeclaration const& _decl, int _index);
smtutil::Expression valueAtIndex(VariableDeclaration const& _decl, unsigned _index);
/// Returns the expression corresponding to the AST node.
/// If _targetType is not null apply conversion.
/// Throws if the expression does not exist.

View File

@ -66,12 +66,12 @@ string SymbolicVariable::currentName() const
return uniqueSymbol(m_ssa->index());
}
smtutil::Expression SymbolicVariable::valueAtIndex(int _index) const
smtutil::Expression SymbolicVariable::valueAtIndex(unsigned _index) const
{
return m_context.newVariable(uniqueSymbol(_index), m_sort);
}
string SymbolicVariable::nameAtIndex(int _index) const
string SymbolicVariable::nameAtIndex(unsigned _index) const
{
return uniqueSymbol(_index);
}
@ -170,12 +170,12 @@ smtutil::Expression SymbolicFunctionVariable::currentFunctionValue() const
return m_declaration;
}
smtutil::Expression SymbolicFunctionVariable::valueAtIndex(int _index) const
smtutil::Expression SymbolicFunctionVariable::valueAtIndex(unsigned _index) const
{
return m_abstract.valueAtIndex(_index);
}
smtutil::Expression SymbolicFunctionVariable::functionValueAtIndex(int _index) const
smtutil::Expression SymbolicFunctionVariable::functionValueAtIndex(unsigned _index) const
{
return SymbolicVariable::valueAtIndex(_index);
}
@ -304,7 +304,7 @@ smtutil::Expression SymbolicArrayVariable::currentValue(frontend::TypePointer co
return m_pair.currentValue();
}
smtutil::Expression SymbolicArrayVariable::valueAtIndex(int _index) const
smtutil::Expression SymbolicArrayVariable::valueAtIndex(unsigned _index) const
{
return m_pair.valueAtIndex(_index);
}

View File

@ -54,8 +54,8 @@ public:
virtual smtutil::Expression currentValue(frontend::TypePointer const& _targetType = TypePointer{}) const;
std::string currentName() const;
virtual smtutil::Expression valueAtIndex(int _index) const;
virtual std::string nameAtIndex(int _index) const;
virtual smtutil::Expression valueAtIndex(unsigned _index) const;
virtual std::string nameAtIndex(unsigned _index) const;
virtual smtutil::Expression resetIndex();
virtual smtutil::Expression setIndex(unsigned _index);
virtual smtutil::Expression increaseIndex();
@ -165,10 +165,10 @@ public:
// Explicit request the function declaration.
smtutil::Expression currentFunctionValue() const;
smtutil::Expression valueAtIndex(int _index) const override;
smtutil::Expression valueAtIndex(unsigned _index) const override;
// Explicit request the function declaration.
smtutil::Expression functionValueAtIndex(int _index) const;
smtutil::Expression functionValueAtIndex(unsigned _index) const;
smtutil::Expression resetIndex() override;
smtutil::Expression setIndex(unsigned _index) override;
@ -251,7 +251,7 @@ public:
SymbolicArrayVariable(SymbolicArrayVariable&&) = default;
smtutil::Expression currentValue(frontend::TypePointer const& _targetType = TypePointer{}) const override;
smtutil::Expression valueAtIndex(int _index) const override;
smtutil::Expression valueAtIndex(unsigned _index) const override;
smtutil::Expression resetIndex() override { SymbolicVariable::resetIndex(); return m_pair.resetIndex(); }
smtutil::Expression setIndex(unsigned _index) override { SymbolicVariable::setIndex(_index); return m_pair.setIndex(_index); }
smtutil::Expression increaseIndex() override { SymbolicVariable::increaseIndex(); return m_pair.increaseIndex(); }

View File

@ -982,7 +982,7 @@ string CompilerStack::applyRemapping(string const& _path, string const& _context
bestMatchTarget = util::sanitizePath(redir.target);
}
string path = bestMatchTarget;
path.append(_path.begin() + longestPrefix, _path.end());
path.append(_path.begin() + static_cast<string::difference_type>(longestPrefix), _path.end());
return path;
}

View File

@ -54,8 +54,8 @@ GasEstimator::ASTGasConsumptionSelfAccumulated GasEstimator::structuralEstimatio
{
solAssert(!!block.startState, "");
GasMeter meter(block.startState->copy(), m_evmVersion);
auto const end = _items.begin() + block.end;
for (auto iter = _items.begin() + block.begin; iter != end; ++iter)
auto const end = _items.begin() + static_cast<ptrdiff_t>(block.end);
for (auto iter = _items.begin() + static_cast<ptrdiff_t>(block.begin); iter != end; ++iter)
particularCosts[iter->location()] += meter.estimateMax(*iter);
}

View File

@ -37,6 +37,9 @@ Json::Value Natspec::userDocumentation(ContractDefinition const& _contractDef)
Json::Value doc;
Json::Value methods(Json::objectValue);
doc["version"] = Json::Value(c_natspecVersion);
doc["kind"] = Json::Value("user");
auto constructorDefinition(_contractDef.constructor());
if (constructorDefinition)
{
@ -91,6 +94,9 @@ Json::Value Natspec::devDocumentation(ContractDefinition const& _contractDef)
Json::Value doc;
Json::Value methods(Json::objectValue);
doc["version"] = Json::Value(c_natspecVersion);
doc["kind"] = Json::Value("dev");
auto author = extractDoc(_contractDef.annotation().docTags, "author");
if (!author.empty())
doc["author"] = author;

View File

@ -40,6 +40,8 @@ struct DocTag;
class Natspec
{
public:
static unsigned int constexpr c_natspecVersion = 1;
/// Get the User documentation of the contract
/// @param _contractDef The contract definition
/// @return A JSON representation of the contract's user documentation

View File

@ -111,7 +111,8 @@ Json::Value formatErrorWithException(
bool const& _warning,
string const& _type,
string const& _component,
string const& _message
string const& _message,
optional<ErrorId> _errorId = nullopt
)
{
string message;
@ -122,7 +123,7 @@ Json::Value formatErrorWithException(
else
message = _message;
return formatError(
Json::Value error = formatError(
_warning,
_type,
_component,
@ -131,6 +132,11 @@ Json::Value formatErrorWithException(
formatSourceLocation(boost::get_error_info<errinfo_sourceLocation>(_exception)),
formatSecondarySourceLocation(boost::get_error_info<errinfo_secondarySourceLocation>(_exception))
);
if (_errorId)
error["errorCode"] = to_string(_errorId.value().error);
return error;
}
map<string, set<string>> requestedContractNames(Json::Value const& _outputSelection)
@ -857,7 +863,8 @@ Json::Value StandardCompiler::compileSolidity(StandardCompiler::InputsAndSetting
err.type() == Error::Type::Warning,
err.typeName(),
"general",
""
"",
err.errorId()
));
}
}

View File

@ -50,7 +50,7 @@ Json::Value StorageLayout::generate(VariableDeclaration const& _var, u256 const&
TypePointer varType = _var.type();
varEntry["label"] = _var.name();
varEntry["astId"] = int(_var.id());
varEntry["astId"] = static_cast<int>(_var.id());
varEntry["contract"] = m_contract->fullyQualifiedName();
varEntry["slot"] = _slot.str();
varEntry["offset"] = _offset;

View File

@ -106,7 +106,7 @@ bytes solidity::util::fromHex(std::string const& _s, WhenError _throw)
{
int h = fromHex(_s[s++], _throw);
if (h != -1)
ret.push_back(h);
ret.push_back(static_cast<uint8_t>(h));
else
return bytes();
}
@ -115,7 +115,7 @@ bytes solidity::util::fromHex(std::string const& _s, WhenError _throw)
int h = fromHex(_s[i], _throw);
int l = fromHex(_s[i + 1], _throw);
if (h != -1 && l != -1)
ret.push_back((uint8_t)(h * 16 + l));
ret.push_back(static_cast<uint8_t>(h * 16 + l));
else
return bytes();
}
@ -148,14 +148,14 @@ string solidity::util::getChecksummedAddress(string const& _addr)
h256 hash = keccak256(boost::algorithm::to_lower_copy(s, std::locale::classic()));
string ret = "0x";
for (size_t i = 0; i < 40; ++i)
for (unsigned i = 0; i < 40; ++i)
{
char addressCharacter = s[i];
unsigned nibble = (unsigned(hash[i / 2]) >> (4 * (1 - (i % 2)))) & 0xf;
uint8_t nibble = hash[i / 2u] >> (4u * (1u - (i % 2u))) & 0xf;
if (nibble >= 8)
ret += toupper(addressCharacter);
ret += static_cast<char>(toupper(addressCharacter));
else
ret += tolower(addressCharacter);
ret += static_cast<char>(tolower(addressCharacter));
}
return ret;
}

View File

@ -64,10 +64,44 @@ public:
FixedHash(Arith const& _arith) { toBigEndian(_arith, m_data); }
/// Explicitly construct, copying from a byte array.
explicit FixedHash(bytes const& _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min<unsigned>(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } }
explicit FixedHash(bytes const& _array, ConstructFromHashType _sizeMismatchBehavior = FailIfDifferent)
{
if (_array.size() == N)
memcpy(m_data.data(), _array.data(), _array.size());
else
{
m_data.fill(0);
if (_sizeMismatchBehavior != FailIfDifferent)
{
auto bytesToCopy = std::min<size_t>(_array.size(), N);
for (size_t i = 0; i < bytesToCopy; ++i)
if (_sizeMismatchBehavior == AlignRight)
m_data[N - 1 - i] = _array[_array.size() - 1 - i];
else
m_data[i] = _array[i];
}
}
}
/// Explicitly construct, copying from a byte array.
explicit FixedHash(bytesConstRef _b, ConstructFromHashType _t = FailIfDifferent) { if (_b.size() == N) memcpy(m_data.data(), _b.data(), std::min<unsigned>(_b.size(), N)); else { m_data.fill(0); if (_t != FailIfDifferent) { auto c = std::min<unsigned>(_b.size(), N); for (unsigned i = 0; i < c; ++i) m_data[_t == AlignRight ? N - 1 - i : i] = _b[_t == AlignRight ? _b.size() - 1 - i : i]; } } }
explicit FixedHash(bytesConstRef _b, ConstructFromHashType _t = FailIfDifferent)
{
if (_b.size() == N)
memcpy(m_data.data(), _b.data(), std::min<size_t>(_b.size(), N));
else
{
m_data.fill(0);
if (_t != FailIfDifferent)
{
auto c = std::min<size_t>(_b.size(), N);
for (size_t i = 0; i < c; ++i)
if (_t == AlignRight)
m_data[N - 1 - i] = _b[_b.size() - 1 - i];
else
m_data[i] = _b[i];
}
}
}
/// Explicitly construct, copying from a string.
explicit FixedHash(std::string const& _s, ConstructFromStringType _t = FromHex, ConstructFromHashType _ht = FailIfDifferent): FixedHash(_t == FromHex ? fromHex(_s, WhenError::Throw) : solidity::util::asBytes(_s), _ht) {}

View File

@ -69,25 +69,25 @@ static uint64_t const RC[24] = \
#define REPEAT6(e) e e e e e e
#define REPEAT24(e) REPEAT6(e e e e)
#define REPEAT5(e) e e e e e
#define FOR5(v, s, e) \
#define FOR5(type, v, s, e) \
v = 0; \
REPEAT5(e; v += s;)
REPEAT5(e; v = static_cast<type>(v + s);)
/*** Keccak-f[1600] ***/
static inline void keccakf(void* state) {
uint64_t* a = (uint64_t*)state;
auto* a = static_cast<uint64_t*>(state);
uint64_t b[5] = {0};
for (int i = 0; i < 24; i++)
{
uint8_t x, y;
// Theta
FOR5(x, 1,
FOR5(uint8_t, x, 1,
b[x] = 0;
FOR5(y, 5,
FOR5(uint8_t, y, 5,
b[x] ^= a[x + y]; ))
FOR5(x, 1,
FOR5(y, 5,
FOR5(uint8_t, x, 1,
FOR5(uint8_t, y, 5,
a[y + x] ^= b[(x + 4) % 5] ^ rol(b[(x + 1) % 5], 1); ))
// Rho and pi
uint64_t t = a[1];
@ -97,11 +97,12 @@ static inline void keccakf(void* state) {
t = b[0];
x++; )
// Chi
FOR5(y,
FOR5(uint8_t,
y,
5,
FOR5(x, 1,
FOR5(uint8_t, x, 1,
b[x] = a[y + x];)
FOR5(x, 1,
FOR5(uint8_t, x, 1,
a[y + x] = b[x] ^ ((~b[(x + 1) % 5]) & b[(x + 2) % 5]); ))
// Iota
a[0] ^= RC[i];

View File

@ -137,7 +137,7 @@ vector<YulString> AsmAnalyzer::operator()(Identifier const& _identifier)
{
bool insideFunction = m_currentScope->insideFunction();
size_t stackSize = m_resolver(_identifier, yul::IdentifierContext::RValue, insideFunction);
if (stackSize != size_t(-1))
if (stackSize != numeric_limits<size_t>::max())
{
found = true;
yulAssert(stackSize == 1, "Invalid stack size of external reference.");
@ -479,7 +479,7 @@ void AsmAnalyzer::checkAssignment(Identifier const& _variable, YulString _valueT
{
bool insideFunction = m_currentScope->insideFunction();
size_t variableSize = m_resolver(_variable, yul::IdentifierContext::LValue, insideFunction);
if (variableSize != size_t(-1))
if (variableSize != numeric_limits<size_t>::max())
{
found = true;
variableType = &m_dialect.defaultType;

View File

@ -45,7 +45,7 @@ string solidity::yul::reindent(string const& _code)
auto const static countBraces = [](string const& _s) noexcept -> int
{
auto const i = _s.find("//");
auto const e = i == _s.npos ? end(_s) : next(begin(_s), i);
auto const e = i == _s.npos ? end(_s) : next(begin(_s), static_cast<ptrdiff_t>(i));
auto const opening = count_if(begin(_s), e, [](auto ch) { return ch == '{' || ch == '('; });
auto const closing = count_if(begin(_s), e, [](auto ch) { return ch == '}' || ch == ')'; });
return opening - closing;

View File

@ -71,10 +71,10 @@ public:
{
// FNV hash - can be replaced by a better one, e.g. xxhash64
std::uint64_t hash = emptyHash();
for (auto c: v)
for (char c: v)
{
hash *= 1099511628211u;
hash ^= c;
hash ^= static_cast<uint64_t>(c);
}
return hash;

View File

@ -143,14 +143,14 @@ pair<shared_ptr<AbstractAssembly>, AbstractAssembly::SubID> EthAssemblyAdapter::
{
shared_ptr<evmasm::Assembly> assembly{make_shared<evmasm::Assembly>()};
auto sub = m_assembly.newSub(assembly);
return {make_shared<EthAssemblyAdapter>(*assembly), size_t(sub.data())};
return {make_shared<EthAssemblyAdapter>(*assembly), static_cast<size_t>(sub.data())};
}
void EthAssemblyAdapter::appendDataOffset(AbstractAssembly::SubID _sub)
{
auto it = m_dataHashBySubId.find(_sub);
if (it == m_dataHashBySubId.end())
m_assembly.pushSubroutineOffset(size_t(_sub));
m_assembly.pushSubroutineOffset(_sub);
else
m_assembly << evmasm::AssemblyItem(evmasm::PushData, it->second);
}
@ -159,7 +159,7 @@ void EthAssemblyAdapter::appendDataSize(AbstractAssembly::SubID _sub)
{
auto it = m_dataHashBySubId.find(_sub);
if (it == m_dataHashBySubId.end())
m_assembly.pushSubroutineSize(size_t(_sub));
m_assembly.pushSubroutineSize(static_cast<size_t>(_sub));
else
m_assembly << u256(m_assembly.data(h256(it->second)).size());
}

View File

@ -74,7 +74,7 @@ void EVMAssembly::appendLabelReference(LabelID _labelId)
EVMAssembly::LabelID EVMAssembly::newLabelId()
{
m_labelPositions[m_nextLabelId] = size_t(-1);
m_labelPositions[m_nextLabelId] = numeric_limits<size_t>::max();
return m_nextLabelId++;
}
@ -165,7 +165,7 @@ evmasm::LinkerObject EVMAssembly::finalize()
size_t referencePos = ref.first;
yulAssert(m_labelPositions.count(ref.second), "");
size_t labelPos = m_labelPositions.at(ref.second);
yulAssert(labelPos != size_t(-1), "Undefined but allocated label used.");
yulAssert(labelPos != numeric_limits<size_t>::max(), "Undefined but allocated label used.");
updateReference(referencePos, labelReferenceSize, u256(labelPos));
}
@ -177,7 +177,7 @@ evmasm::LinkerObject EVMAssembly::finalize()
void EVMAssembly::setLabelToCurrentPosition(LabelID _labelId)
{
yulAssert(m_labelPositions.count(_labelId), "Label not found.");
yulAssert(m_labelPositions[_labelId] == size_t(-1), "Label already set.");
yulAssert(m_labelPositions[_labelId] == numeric_limits<size_t>::max(), "Label already set.");
m_labelPositions[_labelId] = m_bytecode.size();
}

View File

@ -175,28 +175,29 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl)
{
yulAssert(m_scope, "");
int const numVariables = _varDecl.variables.size();
int heightAtStart = m_assembly.stackHeight();
size_t const numVariables = _varDecl.variables.size();
auto heightAtStart = static_cast<size_t>(m_assembly.stackHeight());
if (_varDecl.value)
{
std::visit(*this, *_varDecl.value);
expectDeposit(numVariables, heightAtStart);
expectDeposit(static_cast<int>(numVariables), static_cast<int>(heightAtStart));
}
else
{
m_assembly.setSourceLocation(_varDecl.location);
int variablesLeft = numVariables;
size_t variablesLeft = numVariables;
while (variablesLeft--)
m_assembly.appendConstant(u256(0));
}
m_assembly.setSourceLocation(_varDecl.location);
bool atTopOfStack = true;
for (int varIndex = numVariables - 1; varIndex >= 0; --varIndex)
for (size_t varIndex = 0; varIndex < numVariables; ++varIndex)
{
YulString varName = _varDecl.variables[varIndex].name;
size_t varIndexReverse = numVariables - 1 - varIndex;
YulString varName = _varDecl.variables[varIndexReverse].name;
auto& var = std::get<Scope::Variable>(m_scope->identifiers.at(varName));
m_context->variableStackHeights[&var] = heightAtStart + varIndex;
m_context->variableStackHeights[&var] = heightAtStart + varIndexReverse;
if (!m_allowStackOpt)
continue;
@ -214,10 +215,10 @@ void CodeTransform::operator()(VariableDeclaration const& _varDecl)
atTopOfStack = false;
else
{
int slot = *m_unusedStackSlots.begin();
auto slot = static_cast<size_t>(*m_unusedStackSlots.begin());
m_unusedStackSlots.erase(m_unusedStackSlots.begin());
m_context->variableStackHeights[&var] = slot;
if (int heightDiff = variableHeightDiff(var, varName, true))
if (size_t heightDiff = variableHeightDiff(var, varName, true))
m_assembly.appendInstruction(evmasm::swapInstruction(heightDiff - 1));
m_assembly.appendInstruction(evmasm::Instruction::POP);
}
@ -240,7 +241,7 @@ void CodeTransform::operator()(Assignment const& _assignment)
{
int height = m_assembly.stackHeight();
std::visit(*this, *_assignment.value);
expectDeposit(_assignment.variableNames.size(), height);
expectDeposit(static_cast<int>(_assignment.variableNames.size()), height);
m_assembly.setSourceLocation(_assignment.location);
generateMultiAssignment(_assignment.variableNames);
@ -263,7 +264,7 @@ void CodeTransform::operator()(FunctionCall const& _call)
else
{
m_assembly.setSourceLocation(_call.location);
EVMAssembly::LabelID returnLabel(-1); // only used for evm 1.0
EVMAssembly::LabelID returnLabel(numeric_limits<EVMAssembly::LabelID>::max()); // only used for evm 1.0
if (!m_evm15)
{
returnLabel = m_assembly.newLabelId();
@ -281,10 +282,17 @@ void CodeTransform::operator()(FunctionCall const& _call)
visitExpression(arg);
m_assembly.setSourceLocation(_call.location);
if (m_evm15)
m_assembly.appendJumpsub(functionEntryID(_call.functionName.name, *function), function->arguments.size(), function->returns.size());
m_assembly.appendJumpsub(
functionEntryID(_call.functionName.name, *function),
static_cast<int>(function->arguments.size()),
static_cast<int>(function->returns.size())
);
else
{
m_assembly.appendJumpTo(functionEntryID(_call.functionName.name, *function), function->returns.size() - function->arguments.size() - 1);
m_assembly.appendJumpTo(
functionEntryID(_call.functionName.name, *function),
static_cast<int>(function->returns.size() - function->arguments.size()) - 1
);
m_assembly.appendLabel(returnLabel);
}
}
@ -300,7 +308,7 @@ void CodeTransform::operator()(Identifier const& _identifier)
{
// TODO: opportunity for optimization: Do not DUP if this is the last reference
// to the top most element of the stack
if (int heightDiff = variableHeightDiff(_var, _identifier.name, false))
if (size_t heightDiff = variableHeightDiff(_var, _identifier.name, false))
m_assembly.appendInstruction(evmasm::dupInstruction(heightDiff));
else
// Store something to balance the stack
@ -407,7 +415,7 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
int const stackHeightBefore = m_assembly.stackHeight();
if (m_evm15)
m_assembly.appendBeginsub(functionEntryID(_function.name, function), _function.parameters.size());
m_assembly.appendBeginsub(functionEntryID(_function.name, function), static_cast<int>(_function.parameters.size()));
else
m_assembly.appendLabel(functionEntryID(_function.name, function));
@ -465,15 +473,15 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
// modified parallel to the actual stack.
vector<int> stackLayout;
if (!m_evm15)
stackLayout.push_back(_function.returnVariables.size()); // Move return label to the top
stackLayout.push_back(static_cast<int>(_function.returnVariables.size())); // Move return label to the top
stackLayout += vector<int>(_function.parameters.size(), -1); // discard all arguments
for (size_t i = 0; i < _function.returnVariables.size(); ++i)
stackLayout.push_back(i); // Move return values down, but keep order.
stackLayout.push_back(static_cast<int>(i)); // Move return values down, but keep order.
if (stackLayout.size() > 17)
{
StackTooDeepError error(_function.name, YulString{}, stackLayout.size() - 17);
StackTooDeepError error(_function.name, YulString{}, static_cast<int>(stackLayout.size()) - 17);
error << errinfo_comment(
"The function " +
_function.name.str() +
@ -481,11 +489,11 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
to_string(stackLayout.size() - 17) +
" parameters or return variables too many to fit the stack size."
);
stackError(std::move(error), m_assembly.stackHeight() - _function.parameters.size());
stackError(std::move(error), m_assembly.stackHeight() - static_cast<int>(_function.parameters.size()));
}
else
{
while (!stackLayout.empty() && stackLayout.back() != int(stackLayout.size() - 1))
while (!stackLayout.empty() && stackLayout.back() != static_cast<int>(stackLayout.size() - 1))
if (stackLayout.back() < 0)
{
m_assembly.appendInstruction(evmasm::Instruction::POP);
@ -493,17 +501,17 @@ void CodeTransform::operator()(FunctionDefinition const& _function)
}
else
{
m_assembly.appendInstruction(evmasm::swapInstruction(stackLayout.size() - stackLayout.back() - 1));
swap(stackLayout[stackLayout.back()], stackLayout.back());
m_assembly.appendInstruction(evmasm::swapInstruction(stackLayout.size() - static_cast<size_t>(stackLayout.back()) - 1));
swap(stackLayout[static_cast<size_t>(stackLayout.back())], stackLayout.back());
}
for (int i = 0; size_t(i) < stackLayout.size(); ++i)
yulAssert(i == stackLayout[i], "Error reshuffling stack.");
for (size_t i = 0; i < stackLayout.size(); ++i)
yulAssert(i == static_cast<size_t>(stackLayout[i]), "Error reshuffling stack.");
}
}
if (m_evm15)
m_assembly.appendReturnsub(_function.returnVariables.size(), stackHeightBefore);
m_assembly.appendReturnsub(static_cast<int>(_function.returnVariables.size()), stackHeightBefore);
else
m_assembly.appendJump(stackHeightBefore - _function.returnVariables.size());
m_assembly.appendJump(stackHeightBefore - static_cast<int>(_function.returnVariables.size()));
m_assembly.setStackHeight(stackHeightBefore);
}
@ -683,7 +691,7 @@ void CodeTransform::generateAssignment(Identifier const& _variableName)
if (auto var = m_scope->lookup(_variableName.name))
{
Scope::Variable const& _var = std::get<Scope::Variable>(*var);
if (int heightDiff = variableHeightDiff(_var, _variableName.name, true))
if (size_t heightDiff = variableHeightDiff(_var, _variableName.name, true))
m_assembly.appendInstruction(evmasm::swapInstruction(heightDiff - 1));
m_assembly.appendInstruction(evmasm::Instruction::POP);
decreaseReference(_variableName.name, _var);
@ -698,12 +706,12 @@ void CodeTransform::generateAssignment(Identifier const& _variableName)
}
}
int CodeTransform::variableHeightDiff(Scope::Variable const& _var, YulString _varName, bool _forSwap)
size_t CodeTransform::variableHeightDiff(Scope::Variable const& _var, YulString _varName, bool _forSwap)
{
yulAssert(m_context->variableStackHeights.count(&_var), "");
int heightDiff = m_assembly.stackHeight() - m_context->variableStackHeights[&_var];
size_t heightDiff = static_cast<size_t>(m_assembly.stackHeight()) - m_context->variableStackHeights[&_var];
yulAssert(heightDiff > (_forSwap ? 1 : 0), "Negative stack difference for variable.");
int limit = _forSwap ? 17 : 16;
size_t limit = _forSwap ? 17 : 16;
if (heightDiff > limit)
{
m_stackErrors.emplace_back(_varName, heightDiff - limit);
@ -723,4 +731,3 @@ void CodeTransform::expectDeposit(int _deposit, int _oldHeight) const
{
yulAssert(m_assembly.stackHeight() == _oldHeight + _deposit, "Invalid stack deposit.");
}

View File

@ -54,7 +54,7 @@ struct StackTooDeepError: virtual YulException
struct CodeTransformContext
{
std::map<Scope::Function const*, AbstractAssembly::LabelID> functionEntryIDs;
std::map<Scope::Variable const*, int> variableStackHeights;
std::map<Scope::Variable const*, size_t> variableStackHeights;
std::map<Scope::Variable const*, unsigned> variableReferences;
struct JumpInfo
@ -200,7 +200,7 @@ private:
/// Determines the stack height difference to the given variables. Throws
/// if it is not yet in scope or the height difference is too large. Returns
/// the (positive) stack height difference otherwise.
int variableHeightDiff(Scope::Variable const& _var, YulString _name, bool _forSwap);
size_t variableHeightDiff(Scope::Variable const& _var, YulString _name, bool _forSwap);
void expectDeposit(int _deposit, int _oldHeight) const;

View File

@ -63,8 +63,8 @@ pair<YulString, BuiltinFunctionForEVM> createEVMFunction(
evmasm::InstructionInfo info = evmasm::instructionInfo(_instruction);
BuiltinFunctionForEVM f;
f.name = YulString{_name};
f.parameters.resize(info.args);
f.returns.resize(info.ret);
f.parameters.resize(static_cast<size_t>(info.args));
f.returns.resize(static_cast<size_t>(info.ret));
f.sideEffects = EVMDialect::sideEffectsOfInstruction(_instruction);
f.controlFlowSideEffects.terminates = evmasm::SemanticInformation::terminatesControlFlow(_instruction);
f.controlFlowSideEffects.reverts = evmasm::SemanticInformation::reverts(_instruction);

View File

@ -91,7 +91,11 @@ void GasMeterVisitor::operator()(Literal const& _lit)
m_runGas += evmasm::GasMeter::runGas(evmasm::Instruction::PUSH1);
m_dataGas +=
singleByteDataGas() +
size_t(evmasm::GasMeter::dataGas(toCompactBigEndian(valueOfLiteral(_lit), 1), m_isCreation, m_dialect.evmVersion()));
static_cast<size_t>(evmasm::GasMeter::dataGas(
toCompactBigEndian(valueOfLiteral(_lit), 1),
m_isCreation,
m_dialect.evmVersion()
));
}
void GasMeterVisitor::operator()(Identifier const&)

View File

@ -22,9 +22,11 @@
#include <libyul/Exceptions.h>
#include <libsolutil/CommonData.h>
#include <libsolutil/Visitor.h>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/adaptor/map.hpp>
#include <boost/range/adaptor/transformed.hpp>
using namespace std;
using namespace solidity;
@ -82,6 +84,16 @@ bytes toBytes(ValueType _vt)
return toBytes(uint8_t(_vt));
}
ValueType toValueType(wasm::Type _type)
{
if (_type == wasm::Type::i32)
return ValueType::I32;
else if (_type == wasm::Type::i64)
return ValueType::I64;
else
yulAssert(false, "Invalid wasm variable type");
}
enum class Export: uint8_t
{
Function = 0x0,
@ -131,6 +143,16 @@ bytes toBytes(Opcode _o)
return toBytes(uint8_t(_o));
}
Opcode constOpcodeFor(ValueType _type)
{
if (_type == ValueType::I32)
return Opcode::I32Const;
else if (_type == ValueType::I64)
return Opcode::I64Const;
else
yulAssert(false, "Values of this type cannot be used with const opcode");
}
static map<string, uint8_t> const builtins = {
{"i32.load", 0x28},
{"i64.load", 0x29},
@ -249,6 +271,34 @@ bytes makeSection(Section _section, bytes _data)
return toBytes(_section) + prefixSize(move(_data));
}
/// This is a kind of run-length-encoding of local types.
vector<pair<size_t, ValueType>> groupLocalVariables(vector<VariableDeclaration> _localVariables)
{
vector<pair<size_t, ValueType>> localEntries;
size_t entrySize = 0;
ValueType entryType = ValueType::I32; // Any type would work here
for (VariableDeclaration const& localVariable: _localVariables)
{
ValueType variableType = toValueType(localVariable.type);
if (variableType != entryType)
{
if (entrySize > 0)
localEntries.emplace_back(entrySize, entryType);
entryType = variableType;
entrySize = 0;
}
++entrySize;
}
if (entrySize > 0)
localEntries.emplace_back(entrySize, entryType);
return localEntries;
}
}
bytes BinaryTransform::run(Module const& _module)
@ -297,7 +347,10 @@ bytes BinaryTransform::run(Module const& _module)
bytes BinaryTransform::operator()(Literal const& _literal)
{
return toBytes(Opcode::I64Const) + lebEncodeSigned(_literal.value);
return std::visit(GenericVisitor{
[&](uint32_t _value) -> bytes { return toBytes(Opcode::I32Const) + lebEncodeSigned(static_cast<int32_t>(_value)); },
[&](uint64_t _value) -> bytes { return toBytes(Opcode::I64Const) + lebEncodeSigned(static_cast<int64_t>(_value)); },
}, _literal.value);
}
bytes BinaryTransform::operator()(StringLiteral const&)
@ -323,12 +376,12 @@ bytes BinaryTransform::operator()(BuiltinCall const& _call)
if (_call.functionName == "dataoffset")
{
string name = get<StringLiteral>(_call.arguments.at(0)).value;
return toBytes(Opcode::I64Const) + lebEncodeSigned(m_subModulePosAndSize.at(name).first);
return toBytes(Opcode::I64Const) + lebEncodeSigned(static_cast<int64_t>(m_subModulePosAndSize.at(name).first));
}
else if (_call.functionName == "datasize")
{
string name = get<StringLiteral>(_call.arguments.at(0)).value;
return toBytes(Opcode::I64Const) + lebEncodeSigned(m_subModulePosAndSize.at(name).second);
return toBytes(Opcode::I64Const) + lebEncodeSigned(static_cast<int64_t>(m_subModulePosAndSize.at(name).second));
}
bytes args = visit(_call.arguments);
@ -443,21 +496,18 @@ bytes BinaryTransform::operator()(FunctionDefinition const& _function)
{
bytes ret;
// This is a kind of run-length-encoding of local types. Has to be adapted once
// we have locals of different types.
if (_function.locals.size() == 0)
ret += lebEncode(0); // number of locals groups
else
vector<pair<size_t, ValueType>> localEntries = groupLocalVariables(_function.locals);
ret += lebEncode(localEntries.size());
for (pair<size_t, ValueType> const& entry: localEntries)
{
ret += lebEncode(1); // number of locals groups
ret += lebEncode(_function.locals.size());
ret += toBytes(ValueType::I64);
ret += lebEncode(entry.first);
ret += toBytes(entry.second);
}
m_locals.clear();
size_t varIdx = 0;
for (size_t i = 0; i < _function.parameterNames.size(); ++i)
m_locals[_function.parameterNames[i]] = varIdx++;
for (size_t i = 0; i < _function.parameters.size(); ++i)
m_locals[_function.parameters[i].name] = varIdx++;
for (size_t i = 0; i < _function.locals.size(); ++i)
m_locals[_function.locals[i].variableName] = varIdx++;
@ -475,38 +525,39 @@ BinaryTransform::Type BinaryTransform::typeOf(FunctionImport const& _import)
{
return {
encodeTypes(_import.paramTypes),
encodeTypes(_import.returnType ? vector<string>(1, *_import.returnType) : vector<string>())
encodeTypes(_import.returnType ? vector<wasm::Type>(1, *_import.returnType) : vector<wasm::Type>())
};
}
BinaryTransform::Type BinaryTransform::typeOf(FunctionDefinition const& _funDef)
{
return {
encodeTypes(vector<string>(_funDef.parameterNames.size(), "i64")),
encodeTypes(vector<string>(_funDef.returns ? 1 : 0, "i64"))
encodeTypes(_funDef.parameters),
encodeTypes(_funDef.returnType ? vector<wasm::Type>(1, *_funDef.returnType) : vector<wasm::Type>())
};
}
uint8_t BinaryTransform::encodeType(string const& _typeName)
uint8_t BinaryTransform::encodeType(wasm::Type _type)
{
if (_typeName == "i32")
return uint8_t(ValueType::I32);
else if (_typeName == "i64")
return uint8_t(ValueType::I64);
else
yulAssert(false, "");
return 0;
return uint8_t(toValueType(_type));
}
vector<uint8_t> BinaryTransform::encodeTypes(vector<string> const& _typeNames)
vector<uint8_t> BinaryTransform::encodeTypes(vector<wasm::Type> const& _types)
{
vector<uint8_t> result;
for (auto const& t: _typeNames)
for (wasm::Type t: _types)
result.emplace_back(encodeType(t));
return result;
}
vector<uint8_t> BinaryTransform::encodeTypes(wasm::TypedNameList const& _typedNameList)
{
vector<uint8_t> result;
for (TypedName const& typedName: _typedNameList)
result.emplace_back(encodeType(typedName.type));
return result;
}
map<BinaryTransform::Type, vector<string>> BinaryTransform::typeToFunctionMap(
vector<wasm::FunctionImport> const& _imports,
vector<wasm::FunctionDefinition> const& _functions
@ -612,13 +663,16 @@ bytes BinaryTransform::memorySection()
bytes BinaryTransform::globalSection(vector<wasm::GlobalVariableDeclaration> const& _globals)
{
bytes result = lebEncode(_globals.size());
for (size_t i = 0; i < _globals.size(); ++i)
for (wasm::GlobalVariableDeclaration const& global: _globals)
{
ValueType globalType = toValueType(global.type);
result +=
toBytes(ValueType::I64) +
toBytes(globalType) +
lebEncode(static_cast<uint8_t>(Mutability::Var)) +
toBytes(Opcode::I64Const) +
toBytes(constOpcodeFor(globalType)) +
lebEncodeSigned(0) +
toBytes(Opcode::End);
}
return makeSection(Section::GLOBAL, move(result));
}

View File

@ -71,8 +71,9 @@ private:
static Type typeOf(wasm::FunctionImport const& _import);
static Type typeOf(wasm::FunctionDefinition const& _funDef);
static uint8_t encodeType(std::string const& _typeName);
static std::vector<uint8_t> encodeTypes(std::vector<std::string> const& _typeNames);
static uint8_t encodeType(wasm::Type _type);
static std::vector<uint8_t> encodeTypes(std::vector<wasm::Type> const& _types);
static std::vector<uint8_t> encodeTypes(wasm::TypedNameList const& _typedNameList);
static std::map<Type, std::vector<std::string>> typeToFunctionMap(
std::vector<wasm::FunctionImport> const& _imports,

View File

@ -20,7 +20,10 @@
#include <libyul/backends/wasm/TextTransform.h>
#include <libyul/Exceptions.h>
#include <libsolutil/StringUtils.h>
#include <libsolutil/Visitor.h>
#include <boost/algorithm/string/join.hpp>
#include <boost/algorithm/string/replace.hpp>
@ -44,9 +47,9 @@ string TextTransform::run(wasm::Module const& _module)
{
ret += " (import \"" + imp.module + "\" \"" + imp.externalName + "\" (func $" + imp.internalName;
if (!imp.paramTypes.empty())
ret += " (param" + joinHumanReadablePrefixed(imp.paramTypes, " ", " ") + ")";
ret += " (param" + joinHumanReadablePrefixed(imp.paramTypes | boost::adaptors::transformed(encodeType), " ", " ") + ")";
if (imp.returnType)
ret += " (result " + *imp.returnType + ")";
ret += " (result " + encodeType(*imp.returnType) + ")";
ret += "))\n";
}
@ -56,7 +59,7 @@ string TextTransform::run(wasm::Module const& _module)
ret += " (export \"main\" (func $main))\n";
for (auto const& g: _module.globals)
ret += " (global $" + g.variableName + " (mut i64) (i64.const 0))\n";
ret += " (global $" + g.variableName + " (mut " + encodeType(g.type) + ") (" + encodeType(g.type) + ".const 0))\n";
ret += "\n";
for (auto const& f: _module.functions)
ret += transform(f) + "\n";
@ -65,7 +68,10 @@ string TextTransform::run(wasm::Module const& _module)
string TextTransform::operator()(wasm::Literal const& _literal)
{
return "(i64.const " + to_string(_literal.value) + ")";
return std::visit(GenericVisitor{
[&](uint32_t _value) -> string { return "(i32.const " + to_string(_value) + ")"; },
[&](uint64_t _value) -> string { return "(i64.const " + to_string(_value) + ")"; },
}, _literal.value);
}
string TextTransform::operator()(wasm::StringLiteral const& _literal)
@ -162,12 +168,12 @@ string TextTransform::indented(string const& _in)
string TextTransform::transform(wasm::FunctionDefinition const& _function)
{
string ret = "(func $" + _function.name + "\n";
for (auto const& param: _function.parameterNames)
ret += " (param $" + param + " i64)\n";
if (_function.returns)
ret += " (result i64)\n";
for (auto const& param: _function.parameters)
ret += " (param $" + param.name + " " + encodeType(param.type) + ")\n";
if (_function.returnType.has_value())
ret += " (result " + encodeType(_function.returnType.value()) + ")\n";
for (auto const& local: _function.locals)
ret += " (local $" + local.variableName + " i64)\n";
ret += " (local $" + local.variableName + " " + encodeType(local.type) + ")\n";
ret += indented(joinTransformed(_function.body, '\n'));
if (ret.back() != '\n')
ret += '\n';
@ -193,3 +199,13 @@ string TextTransform::joinTransformed(vector<wasm::Expression> const& _expressio
}
return ret;
}
string TextTransform::encodeType(wasm::Type _type)
{
if (_type == wasm::Type::i32)
return "i32";
else if (_type == wasm::Type::i64)
return "i64";
else
yulAssert(false, "Invalid wasm type");
}

View File

@ -63,6 +63,8 @@ private:
std::vector<wasm::Expression> const& _expressions,
char _separator = ' '
);
static std::string encodeType(wasm::Type _type);
};
}

View File

@ -30,6 +30,15 @@
namespace solidity::yul::wasm
{
enum class Type
{
i32,
i64,
};
struct TypedName { std::string name; Type type; };
using TypedNameList = std::vector<TypedName>;
struct Literal;
struct StringLiteral;
struct LocalVariable;
@ -50,7 +59,7 @@ using Expression = std::variant<
Block, If, Loop, Branch, BranchIf, Return
>;
struct Literal { uint64_t value; };
struct Literal { std::variant<uint32_t, uint64_t> value; };
struct StringLiteral { std::string value; };
struct LocalVariable { std::string name; };
struct GlobalVariable { std::string name; };
@ -70,21 +79,21 @@ struct Branch { Label label; };
struct Return {};
struct BranchIf { Label label; std::unique_ptr<Expression> condition; };
struct VariableDeclaration { std::string variableName; };
struct GlobalVariableDeclaration { std::string variableName; };
struct VariableDeclaration { std::string variableName; Type type; };
struct GlobalVariableDeclaration { std::string variableName; Type type; };
struct FunctionImport {
std::string module;
std::string externalName;
std::string internalName;
std::vector<std::string> paramTypes;
std::optional<std::string> returnType;
std::vector<Type> paramTypes;
std::optional<Type> returnType;
};
struct FunctionDefinition
{
std::string name;
std::vector<std::string> parameterNames;
bool returns;
std::vector<TypedName> parameters;
std::optional<Type> returnType;
std::vector<VariableDeclaration> locals;
std::vector<Expression> body;
};

View File

@ -88,7 +88,7 @@ wasm::Expression WasmCodeTransform::operator()(VariableDeclaration const& _varDe
for (auto const& var: _varDecl.variables)
{
variableNames.emplace_back(var.name.str());
m_localVariables.emplace_back(wasm::VariableDeclaration{variableNames.back()});
m_localVariables.emplace_back(wasm::VariableDeclaration{variableNames.back(), wasm::Type::i64});
}
if (_varDecl.value)
@ -127,10 +127,10 @@ wasm::Expression WasmCodeTransform::operator()(FunctionCall const& _call)
builtin->name.str().substr(4),
builtin->name.str(),
{},
builtin->returns.empty() ? nullopt : make_optional<string>(builtin->returns.front().str())
builtin->returns.empty() ? nullopt : make_optional<wasm::Type>(translatedType(builtin->returns.front()))
};
for (auto const& param: builtin->parameters)
imp.paramTypes.emplace_back(param.str());
imp.paramTypes.emplace_back(translatedType(param));
m_functionsToImport[builtin->name] = std::move(imp);
}
typeConversionNeeded = true;
@ -184,7 +184,7 @@ wasm::Expression WasmCodeTransform::operator()(Literal const& _literal)
{
u256 value = valueOfLiteral(_literal);
yulAssert(value <= numeric_limits<uint64_t>::max(), "Literal too large: " + value.str());
return wasm::Literal{uint64_t(value)};
return wasm::Literal{static_cast<uint64_t>(value)};
}
wasm::Expression WasmCodeTransform::operator()(If const& _if)
@ -193,7 +193,7 @@ wasm::Expression WasmCodeTransform::operator()(If const& _if)
vector<wasm::Expression> args;
args.emplace_back(visitReturnByValue(*_if.condition));
args.emplace_back(wasm::Literal{0});
args.emplace_back(wasm::Literal{static_cast<uint64_t>(0)});
return wasm::If{
make_unique<wasm::Expression>(wasm::BuiltinCall{"i64.ne", std::move(args)}),
visit(_if.body.statements),
@ -205,7 +205,7 @@ wasm::Expression WasmCodeTransform::operator()(Switch const& _switch)
{
wasm::Block block;
string condition = m_nameDispenser.newName("condition"_yulstring).str();
m_localVariables.emplace_back(wasm::VariableDeclaration{condition});
m_localVariables.emplace_back(wasm::VariableDeclaration{condition, wasm::Type::i64});
block.statements.emplace_back(wasm::LocalAssignment{condition, visit(*_switch.expression)});
vector<wasm::Expression>* currentBlock = &block.statements;
@ -325,10 +325,11 @@ wasm::FunctionDefinition WasmCodeTransform::translateFunction(yul::FunctionDefin
wasm::FunctionDefinition fun;
fun.name = _fun.name.str();
for (auto const& param: _fun.parameters)
fun.parameterNames.emplace_back(param.name.str());
fun.parameters.push_back({param.name.str(), wasm::Type::i64});
for (auto const& retParam: _fun.returnVariables)
fun.locals.emplace_back(wasm::VariableDeclaration{retParam.name.str()});
fun.returns = !_fun.returnVariables.empty();
fun.locals.emplace_back(wasm::VariableDeclaration{retParam.name.str(), wasm::Type::i64});
if (!_fun.returnVariables.empty())
fun.returnType = wasm::Type::i64;
yulAssert(m_localVariables.empty(), "");
yulAssert(m_functionBodyLabel.empty(), "");
@ -361,14 +362,14 @@ wasm::Expression WasmCodeTransform::injectTypeConversionIfNeeded(wasm::FunctionC
{
wasm::FunctionImport const& import = m_functionsToImport.at(YulString{_call.functionName});
for (size_t i = 0; i < _call.arguments.size(); ++i)
if (import.paramTypes.at(i) == "i32")
if (import.paramTypes.at(i) == wasm::Type::i32)
_call.arguments[i] = wasm::BuiltinCall{"i32.wrap_i64", make_vector<wasm::Expression>(std::move(_call.arguments[i]))};
else
yulAssert(import.paramTypes.at(i) == "i64", "Unknown type " + import.paramTypes.at(i));
yulAssert(import.paramTypes.at(i) == wasm::Type::i64, "Invalid Wasm type");
if (import.returnType && *import.returnType != "i64")
if (import.returnType && *import.returnType != wasm::Type::i64)
{
yulAssert(*import.returnType == "i32", "Invalid type " + *import.returnType);
yulAssert(*import.returnType == wasm::Type::i32, "Invalid Wasm type");
return wasm::BuiltinCall{"i64.extend_i32_u", make_vector<wasm::Expression>(std::move(_call))};
}
return {std::move(_call)};
@ -400,6 +401,17 @@ void WasmCodeTransform::allocateGlobals(size_t _amount)
{
while (m_globalVariables.size() < _amount)
m_globalVariables.emplace_back(wasm::GlobalVariableDeclaration{
m_nameDispenser.newName("global_"_yulstring).str()
m_nameDispenser.newName("global_"_yulstring).str(),
wasm::Type::i64
});
}
wasm::Type WasmCodeTransform::translatedType(yul::Type _yulType)
{
if (_yulType == "i32"_yulstring)
return wasm::Type::i32;
else if (_yulType == "i64"_yulstring)
return wasm::Type::i64;
else
yulAssert(false, "This Yul type does not have a corresponding type in Wasm.");
}

View File

@ -89,6 +89,8 @@ private:
/// Makes sure that there are at least @a _amount global variables.
void allocateGlobals(size_t _amount);
static wasm::Type translatedType(yul::Type _yulType);
Dialect const& m_dialect;
NameDispenser m_nameDispenser;

View File

@ -112,7 +112,7 @@ void WordSizeTransform::operator()(Block& _block)
yulAssert(varDecl.variables.size() == 1, "");
auto newLhs = generateU64IdentifierNames(varDecl.variables[0].name);
vector<Statement> ret;
for (int i = 0; i < 3; i++)
for (size_t i = 0; i < 3; i++)
ret.emplace_back(VariableDeclaration{
varDecl.location,
{TypedName{varDecl.location, newLhs[i], m_targetDialect.defaultType}},
@ -143,7 +143,7 @@ void WordSizeTransform::operator()(Block& _block)
auto newRhs = expandValue(*varDecl.value);
auto newLhs = generateU64IdentifierNames(varDecl.variables[0].name);
vector<Statement> ret;
for (int i = 0; i < 4; i++)
for (size_t i = 0; i < 4; i++)
ret.emplace_back(VariableDeclaration{
varDecl.location,
{TypedName{varDecl.location, newLhs[i], m_targetDialect.defaultType}},
@ -172,7 +172,7 @@ void WordSizeTransform::operator()(Block& _block)
yulAssert(assignment.variableNames.size() == 1, "");
auto newLhs = generateU64IdentifierNames(assignment.variableNames[0].name);
vector<Statement> ret;
for (int i = 0; i < 3; i++)
for (size_t i = 0; i < 3; i++)
ret.emplace_back(Assignment{
assignment.location,
{Identifier{assignment.location, newLhs[i]}},
@ -203,7 +203,7 @@ void WordSizeTransform::operator()(Block& _block)
auto newRhs = expandValue(*assignment.value);
YulString lhsName = assignment.variableNames[0].name;
vector<Statement> ret;
for (int i = 0; i < 4; i++)
for (size_t i = 0; i < 4; i++)
ret.emplace_back(Assignment{
assignment.location,
{Identifier{assignment.location, m_variableMapping.at(lhsName)[i]}},
@ -382,7 +382,7 @@ std::vector<Statement> WordSizeTransform::handleSwitch(Switch& _switch)
array<YulString, 4> WordSizeTransform::generateU64IdentifierNames(YulString const& _s)
{
yulAssert(m_variableMapping.find(_s) == m_variableMapping.end(), "");
for (int i = 0; i < 4; i++)
for (size_t i = 0; i < 4; i++)
m_variableMapping[_s][i] = m_nameDispenser.newName(YulString{_s.str() + "_" + to_string(i)});
return m_variableMapping[_s];
}
@ -392,19 +392,20 @@ array<unique_ptr<Expression>, 4> WordSizeTransform::expandValue(Expression const
array<unique_ptr<Expression>, 4> ret;
if (holds_alternative<Identifier>(_e))
{
Identifier const& id = std::get<Identifier>(_e);
for (int i = 0; i < 4; i++)
auto const& id = std::get<Identifier>(_e);
for (size_t i = 0; i < 4; i++)
ret[i] = make_unique<Expression>(Identifier{id.location, m_variableMapping.at(id.name)[i]});
}
else if (holds_alternative<Literal>(_e))
{
Literal const& lit = std::get<Literal>(_e);
auto const& lit = std::get<Literal>(_e);
u256 val = valueOfLiteral(lit);
for (int i = 3; i >= 0; i--)
for (size_t exprIndex = 0; exprIndex < 4; ++exprIndex)
{
size_t exprIndexReverse = 3 - exprIndex;
u256 currentVal = val & std::numeric_limits<uint64_t>::max();
val >>= 64;
ret[i] = make_unique<Expression>(
ret[exprIndexReverse] = make_unique<Expression>(
Literal{
lit.location,
LiteralKind::Number,
@ -426,4 +427,3 @@ vector<Expression> WordSizeTransform::expandValueToVector(Expression const& _e)
ret.emplace_back(std::move(*val));
return ret;
}

View File

@ -51,10 +51,10 @@ void DeadCodeEliminator::operator()(Block& _block)
tie(controlFlowChange, index) = TerminationFinder{m_dialect}.firstUnconditionalControlFlowChange(_block.statements);
// Erase everything after the terminating statement that is not a function definition.
if (controlFlowChange != TerminationFinder::ControlFlow::FlowOut && index != size_t(-1))
if (controlFlowChange != TerminationFinder::ControlFlow::FlowOut && index != std::numeric_limits<size_t>::max())
_block.statements.erase(
remove_if(
_block.statements.begin() + index + 1,
_block.statements.begin() + static_cast<ptrdiff_t>(index) + 1,
_block.statements.end(),
[] (Statement const& _s) { return !holds_alternative<yul::FunctionDefinition>(_s); }
),
@ -63,4 +63,3 @@ void DeadCodeEliminator::operator()(Block& _block)
ASTModifier::operator()(_block);
}

View File

@ -119,7 +119,7 @@ void ExpressionJoiner::decrementLatestStatementPointer()
void ExpressionJoiner::resetLatestStatementPointer()
{
m_currentBlock = nullptr;
m_latestStatementInBlock = size_t(-1);
m_latestStatementInBlock = numeric_limits<size_t>::max();
}
Statement* ExpressionJoiner::latestStatement()

View File

@ -180,7 +180,7 @@ pair<TerminationFinder::ControlFlow, size_t> TerminationFinder::firstUncondition
if (controlFlow != ControlFlow::FlowOut)
return {controlFlow, i};
}
return {ControlFlow::FlowOut, size_t(-1)};
return {ControlFlow::FlowOut, numeric_limits<size_t>::max()};
}
TerminationFinder::ControlFlow TerminationFinder::controlFlowKind(Statement const& _statement)

View File

@ -178,14 +178,14 @@ bool StackCompressor::run(
eliminateVariables(
_dialect,
std::get<Block>(_object.code->statements.at(0)),
stackSurplus.at({}),
static_cast<size_t>(stackSurplus.at({})),
allowMSizeOptimzation
);
}
for (size_t i = 1; i < _object.code->statements.size(); ++i)
{
FunctionDefinition& fun = std::get<FunctionDefinition>(_object.code->statements[i]);
auto& fun = std::get<FunctionDefinition>(_object.code->statements[i]);
if (!stackSurplus.count(fun.name))
continue;
@ -193,7 +193,7 @@ bool StackCompressor::run(
eliminateVariables(
_dialect,
fun,
stackSurplus.at(fun.name),
static_cast<size_t>(stackSurplus.at(fun.name)),
allowMSizeOptimzation
);
}

View File

@ -34,5 +34,5 @@ else
BUILD_DIR="$1"
fi
docker run -v $(pwd):/root/project -w /root/project ethereum/solidity-buildpack-deps:emsdk-1.39.15-1 \
docker run -v $(pwd):/root/project -w /root/project ethereum/solidity-buildpack-deps:emsdk-1.39.15-2 \
./scripts/travis-emscripten/build_emscripten.sh $BUILD_DIR

View File

@ -177,6 +177,7 @@ static string const g_strVersion = "version";
static string const g_strIgnoreMissingFiles = "ignore-missing";
static string const g_strColor = "color";
static string const g_strNoColor = "no-color";
static string const g_strErrorIds = "error-codes";
static string const g_strOldReporter = "old-reporter";
static string const g_argAbi = g_strAbi;
@ -222,6 +223,7 @@ static string const g_stdinFileName = g_stdinFileNameStr;
static string const g_argIgnoreMissingFiles = g_strIgnoreMissingFiles;
static string const g_argColor = g_strColor;
static string const g_argNoColor = g_strNoColor;
static string const g_argErrorIds = g_strErrorIds;
static string const g_argOldReporter = g_strOldReporter;
/// Possible arguments to for --combined-json
@ -878,6 +880,10 @@ General Information)").c_str(),
g_argNoColor.c_str(),
"Explicitly disable colored output, disabling terminal auto-detection."
)
(
g_argErrorIds.c_str(),
"Output error codes."
)
(
g_argOldReporter.c_str(),
"Enables old diagnostics reporter (legacy option, will be removed)."
@ -991,6 +997,8 @@ General Information)").c_str(),
m_coloredOutput = !m_args.count(g_argNoColor) && (isatty(STDERR_FILENO) || m_args.count(g_argColor));
m_withErrorIds = m_args.count(g_argErrorIds);
if (m_args.count(g_argHelp) || (isatty(fileno(stdin)) && _argc == 1))
{
sout() << desc;
@ -1296,7 +1304,7 @@ bool CommandLineInterface::processInput()
if (m_args.count(g_argOldReporter))
formatter = make_unique<SourceReferenceFormatter>(serr(false));
else
formatter = make_unique<SourceReferenceFormatterHuman>(serr(false), m_coloredOutput);
formatter = make_unique<SourceReferenceFormatterHuman>(serr(false), m_coloredOutput, m_withErrorIds);
try
{
@ -1735,7 +1743,7 @@ bool CommandLineInterface::assemble(
if (m_args.count(g_argOldReporter))
formatter = make_unique<SourceReferenceFormatter>(serr(false));
else
formatter = make_unique<SourceReferenceFormatterHuman>(serr(false), m_coloredOutput);
formatter = make_unique<SourceReferenceFormatterHuman>(serr(false), m_coloredOutput, m_withErrorIds);
for (auto const& error: stack.errors())
{

View File

@ -131,6 +131,8 @@ private:
CompilerStack::MetadataHash m_metadataHash = CompilerStack::MetadataHash::IPFS;
/// Whether or not to colorize diagnostics output.
bool m_coloredOutput = true;
/// Whether or not to output error IDs.
bool m_withErrorIds = false;
};
}

View File

@ -121,6 +121,7 @@ function test_solc_behaviour()
rm "$stdout_path.bak"
else
sed -i.bak -e '/^Warning: This is a pre-release compiler version, please do not use it in production./d' "$stderr_path"
sed -i.bak -e '/^Warning (3805): This is a pre-release compiler version, please do not use it in production./d' "$stderr_path"
sed -i.bak -e 's/\(^[ ]*auxdata: \)0x[0-9a-f]*$/\1AUXDATA REMOVED/' "$stdout_path"
sed -i.bak -e 's/ Consider adding "pragma .*$//' "$stderr_path"
# Remove trailing empty lines. Needs a line break to make OSX sed happy.

View File

@ -0,0 +1 @@
--error-codes

View File

@ -0,0 +1,26 @@
Error (4937): No visibility specified. Did you intend to add "public"?
--> error_codes/input.sol:4:5:
|
4 | function f() {
| ^ (Relevant source part starts here and spans across multiple lines).
Warning (3420): Source file does not specify required compiler version!
--> error_codes/input.sol
Error (4247): Expression has to be an lvalue.
--> error_codes/input.sol:5:9:
|
5 | 2=0;
| ^
Error (7407): Type int_const 0 is not implicitly convertible to expected type int_const 2.
--> error_codes/input.sol:5:11:
|
5 | 2=0;
| ^
Error (2614): Indexed expression has to be a type, mapping or array (is literal_string "")
--> error_codes/input.sol:6:9:
|
6 | ""[2];
| ^^

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,8 @@
// SPDX-License-Identifier: GPL-3.0
contract C {
function f() {
2=0;
""[2];
}
}

View File

@ -1,6 +1,6 @@
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}},"b.sol":{"A1":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}},"b.sol":{"A1":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"},{"component":"general","errorCode":"3420","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","errorCode":"2018","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }
^------------------------------------------^
","message":"Function state mutability can be restricted to pure","severity":"warning","sourceLocation":{"end":93,"file":"b.sol","start":49},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}

View File

@ -1,6 +1,6 @@
{"contracts":{"a.sol":{"A2":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
{"contracts":{"a.sol":{"A2":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"},{"component":"general","errorCode":"3420","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","errorCode":"2018","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }
^------------------------------------------^
","message":"Function state mutability can be restricted to pure","severity":"warning","sourceLocation":{"end":93,"file":"b.sol","start":49},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}

View File

@ -1,6 +1,6 @@
{"errors":[{"component":"general","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
{"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"},{"component":"general","errorCode":"3420","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","errorCode":"2018","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }
^------------------------------------------^
","message":"Function state mutability can be restricted to pure","severity":"warning","sourceLocation":{"end":93,"file":"b.sol","start":49},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}

View File

@ -1,6 +1,6 @@
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}},"A2":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}},"b.sol":{"A1":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}},"B2":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}},"A2":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}},"b.sol":{"A1":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}},"B2":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"},{"component":"general","errorCode":"3420","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","errorCode":"2018","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }
^------------------------------------------^
","message":"Function state mutability can be restricted to pure","severity":"warning","sourceLocation":{"end":93,"file":"b.sol","start":49},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}

View File

@ -1,2 +1,2 @@
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}

View File

@ -1,5 +1,5 @@
{"contracts":{"b.sol":{"B2":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
{"contracts":{"b.sol":{"B2":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"b.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"b.sol","start":-1},"type":"Warning"},{"component":"general","errorCode":"2018","formattedMessage":"b.sol:2:15: Warning: Function state mutability can be restricted to pure
contract A1 { function b(uint x) public { assert(x > 0); } } contract B2 { function b(uint x) public pure { assert(x > 0); } }
^------------------------------------------^
","message":"Function state mutability can be restricted to pure","severity":"warning","sourceLocation":{"end":93,"file":"b.sol","start":49},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}

View File

@ -1,2 +1,2 @@
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}},"A2":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
{"contracts":{"a.sol":{"A1":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}},"A2":{"evm":{"bytecode":{"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"sourceMap removed"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"}],"sources":{"a.sol":{"id":0},"b.sol":{"id":1}}}

View File

@ -1,7 +1,7 @@
{"errors":[{"component":"general","formattedMessage":"A:2:58: ParserError: Expected type name
{"errors":[{"component":"general","errorCode":"3546","formattedMessage":"A:2:58: ParserError: Expected type name
pragma solidity >=0.0; contract Errort6 { using foo for ; /* missing type name */ }
^
","message":"Expected type name","severity":"error","sourceLocation":{"end":94,"file":"A","start":93},"type":"ParserError"},{"component":"general","formattedMessage":"A:2:84: Warning: Recovered in ContractDefinition at '}'.
","message":"Expected type name","severity":"error","sourceLocation":{"end":94,"file":"A","start":93},"type":"ParserError"},{"component":"general","errorCode":"3796","formattedMessage":"A:2:84: Warning: Recovered in ContractDefinition at '}'.
pragma solidity >=0.0; contract Errort6 { using foo for ; /* missing type name */ }
^
","message":"Recovered in ContractDefinition at '}'.","severity":"warning","sourceLocation":{"end":120,"file":"A","start":119},"type":"Warning"}],"sources":{"A":{"ast":{"absolutePath":"A","exportedSymbols":{"Errort6":[3]},"id":4,"license":"GPL-3.0","nodeType":"SourceUnit","nodes":[{"id":1,"literals":["solidity",">=","0.0"],"nodeType":"PragmaDirective","src":"36:22:0"},{"abstract":false,"baseContracts":[],"contractDependencies":[],"contractKind":"contract","documentation":null,"fullyImplemented":true,"id":3,"linearizedBaseContracts":[3],"name":"Errort6","nodeType":"ContractDefinition","nodes":[],"scope":4,"src":"59:35:0"}],"src":"36:84:0"},"id":0}}}

View File

@ -1,4 +1,4 @@
{"errors":[{"component":"general","formattedMessage":":2:24: DeclarationError: Declaration \"A\" not found in \"\" (referenced as \".\").
{"errors":[{"component":"general","errorCode":"2904","formattedMessage":":2:24: DeclarationError: Declaration \"A\" not found in \"\" (referenced as \".\").
pragma solidity >=0.0; import {A} from \".\";
^------------------^
","message":"Declaration \"A\" not found in \"\" (referenced as \".\").","severity":"error","type":"DeclarationError"}],"sources":{}}

View File

@ -1,2 +1,2 @@
{"contracts":{"a.sol":{"A":{"evm":{"deployedBytecode":{"immutableReferences":{"3":[{"length":32,"start":77}]},"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"36:96:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;108:7;126:1;119:8;;74:56;:::o"}}}}},"errors":[{"component":"general","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
{"contracts":{"a.sol":{"A":{"evm":{"deployedBytecode":{"immutableReferences":{"3":[{"length":32,"start":77}]},"linkReferences":{},"object":"bytecode removed","opcodes":"opcodes removed","sourceMap":"36:96:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;108:7;126:1;119:8;;74:56;:::o"}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"a.sol: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"a.sol","start":-1},"type":"Warning"}],"sources":{"a.sol":{"id":0}}}

View File

@ -1,4 +1,4 @@
{"errors":[{"component":"general","formattedMessage":"A:2:112: DeclarationError: Base constructor arguments given twice.
{"errors":[{"component":"general","errorCode":"3364","formattedMessage":"A:2:112: DeclarationError: Base constructor arguments given twice.
pragma solidity >=0.0; contract A { constructor(uint) public {} } contract B is A(2) { } contract C is A(3) {} contract D is B, C {}
^-------------------^
A:2:81: First constructor call is here:

View File

@ -1,2 +1,2 @@
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[{"astId":3,"contract":"fileA:A","label":"s1","offset":0,"slot":"0","type":"t_bytes_storage"},{"astId":5,"contract":"fileA:A","label":"s2","offset":0,"slot":"1","type":"t_bytes_storage"}],"types":{"t_bytes_storage":{"encoding":"bytes","label":"bytes","numberOfBytes":"32"}}}}}},"errors":[{"component":"general","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[{"astId":3,"contract":"fileA:A","label":"s1","offset":0,"slot":"0","type":"t_bytes_storage"},{"astId":5,"contract":"fileA:A","label":"s2","offset":0,"slot":"1","type":"t_bytes_storage"}],"types":{"t_bytes_storage":{"encoding":"bytes","label":"bytes","numberOfBytes":"32"}}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"fileA","start":-1},"type":"Warning"}],"sources":{"fileA":{"id":0}}}

View File

@ -1,2 +1,2 @@
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[{"astId":3,"contract":"fileA:A","label":"array1","offset":0,"slot":"0","type":"t_array(t_uint256)dyn_storage"},{"astId":6,"contract":"fileA:A","label":"array2","offset":0,"slot":"1","type":"t_array(t_bool)dyn_storage"}],"types":{"t_array(t_bool)dyn_storage":{"base":"t_bool","encoding":"dynamic_array","label":"bool[]","numberOfBytes":"32"},"t_array(t_uint256)dyn_storage":{"base":"t_uint256","encoding":"dynamic_array","label":"uint256[]","numberOfBytes":"32"},"t_bool":{"encoding":"inplace","label":"bool","numberOfBytes":"1"},"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}}}}},"errors":[{"component":"general","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[{"astId":3,"contract":"fileA:A","label":"array1","offset":0,"slot":"0","type":"t_array(t_uint256)dyn_storage"},{"astId":6,"contract":"fileA:A","label":"array2","offset":0,"slot":"1","type":"t_array(t_bool)dyn_storage"}],"types":{"t_array(t_bool)dyn_storage":{"base":"t_bool","encoding":"dynamic_array","label":"bool[]","numberOfBytes":"32"},"t_array(t_uint256)dyn_storage":{"base":"t_uint256","encoding":"dynamic_array","label":"uint256[]","numberOfBytes":"32"},"t_bool":{"encoding":"inplace","label":"bool","numberOfBytes":"1"},"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"fileA","start":-1},"type":"Warning"}],"sources":{"fileA":{"id":0}}}

View File

@ -1,2 +1,2 @@
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[{"astId":14,"contract":"fileA:A","label":"x","offset":0,"slot":"0","type":"t_uint256"},{"astId":16,"contract":"fileA:A","label":"y","offset":0,"slot":"1","type":"t_uint256"},{"astId":18,"contract":"fileA:A","label":"s","offset":0,"slot":"2","type":"t_struct(S)12_storage"},{"astId":20,"contract":"fileA:A","label":"addr","offset":0,"slot":"6","type":"t_address"},{"astId":26,"contract":"fileA:A","label":"map","offset":0,"slot":"7","type":"t_mapping(t_uint256,t_mapping(t_address,t_bool))"},{"astId":29,"contract":"fileA:A","label":"array","offset":0,"slot":"8","type":"t_array(t_uint256)dyn_storage"},{"astId":31,"contract":"fileA:A","label":"s1","offset":0,"slot":"9","type":"t_string_storage"},{"astId":33,"contract":"fileA:A","label":"b1","offset":0,"slot":"10","type":"t_bytes_storage"}],"types":{"t_address":{"encoding":"inplace","label":"address","numberOfBytes":"20"},"t_array(t_uint256)2_storage":{"base":"t_uint256","encoding":"inplace","label":"uint256[2]","numberOfBytes":"64"},"t_array(t_uint256)dyn_storage":{"base":"t_uint256","encoding":"dynamic_array","label":"uint256[]","numberOfBytes":"32"},"t_bool":{"encoding":"inplace","label":"bool","numberOfBytes":"1"},"t_bytes_storage":{"encoding":"bytes","label":"bytes","numberOfBytes":"32"},"t_mapping(t_address,t_bool)":{"encoding":"mapping","key":"t_address","label":"mapping(address => bool)","numberOfBytes":"32","value":"t_bool"},"t_mapping(t_uint256,t_mapping(t_address,t_bool))":{"encoding":"mapping","key":"t_uint256","label":"mapping(uint256 => mapping(address => bool))","numberOfBytes":"32","value":"t_mapping(t_address,t_bool)"},"t_string_storage":{"encoding":"bytes","label":"string","numberOfBytes":"32"},"t_struct(S)12_storage":{"encoding":"inplace","label":"struct A.S","members":[{"astId":2,"contract":"fileA:A","label":"a","offset":0,"slot":"0","type":"t_uint128"},{"astId":4,"contract":"fileA:A","label":"b","offset":16,"slot":"0","type":"t_uint128"},{"astId":8,"contract":"fileA:A","label":"staticArray","offset":0,"slot":"1","type":"t_array(t_uint256)2_storage"},{"astId":11,"contract":"fileA:A","label":"dynArray","offset":0,"slot":"3","type":"t_array(t_uint256)dyn_storage"}],"numberOfBytes":"128"},"t_uint128":{"encoding":"inplace","label":"uint128","numberOfBytes":"16"},"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}}}}},"errors":[{"component":"general","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[{"astId":14,"contract":"fileA:A","label":"x","offset":0,"slot":"0","type":"t_uint256"},{"astId":16,"contract":"fileA:A","label":"y","offset":0,"slot":"1","type":"t_uint256"},{"astId":18,"contract":"fileA:A","label":"s","offset":0,"slot":"2","type":"t_struct(S)12_storage"},{"astId":20,"contract":"fileA:A","label":"addr","offset":0,"slot":"6","type":"t_address"},{"astId":26,"contract":"fileA:A","label":"map","offset":0,"slot":"7","type":"t_mapping(t_uint256,t_mapping(t_address,t_bool))"},{"astId":29,"contract":"fileA:A","label":"array","offset":0,"slot":"8","type":"t_array(t_uint256)dyn_storage"},{"astId":31,"contract":"fileA:A","label":"s1","offset":0,"slot":"9","type":"t_string_storage"},{"astId":33,"contract":"fileA:A","label":"b1","offset":0,"slot":"10","type":"t_bytes_storage"}],"types":{"t_address":{"encoding":"inplace","label":"address","numberOfBytes":"20"},"t_array(t_uint256)2_storage":{"base":"t_uint256","encoding":"inplace","label":"uint256[2]","numberOfBytes":"64"},"t_array(t_uint256)dyn_storage":{"base":"t_uint256","encoding":"dynamic_array","label":"uint256[]","numberOfBytes":"32"},"t_bool":{"encoding":"inplace","label":"bool","numberOfBytes":"1"},"t_bytes_storage":{"encoding":"bytes","label":"bytes","numberOfBytes":"32"},"t_mapping(t_address,t_bool)":{"encoding":"mapping","key":"t_address","label":"mapping(address => bool)","numberOfBytes":"32","value":"t_bool"},"t_mapping(t_uint256,t_mapping(t_address,t_bool))":{"encoding":"mapping","key":"t_uint256","label":"mapping(uint256 => mapping(address => bool))","numberOfBytes":"32","value":"t_mapping(t_address,t_bool)"},"t_string_storage":{"encoding":"bytes","label":"string","numberOfBytes":"32"},"t_struct(S)12_storage":{"encoding":"inplace","label":"struct A.S","members":[{"astId":2,"contract":"fileA:A","label":"a","offset":0,"slot":"0","type":"t_uint128"},{"astId":4,"contract":"fileA:A","label":"b","offset":16,"slot":"0","type":"t_uint128"},{"astId":8,"contract":"fileA:A","label":"staticArray","offset":0,"slot":"1","type":"t_array(t_uint256)2_storage"},{"astId":11,"contract":"fileA:A","label":"dynArray","offset":0,"slot":"3","type":"t_array(t_uint256)dyn_storage"}],"numberOfBytes":"128"},"t_uint128":{"encoding":"inplace","label":"uint128","numberOfBytes":"16"},"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"fileA","start":-1},"type":"Warning"}],"sources":{"fileA":{"id":0}}}

View File

@ -1,2 +1,2 @@
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[{"astId":2,"contract":"fileA:A","label":"x","offset":0,"slot":"0","type":"t_uint256"},{"astId":4,"contract":"fileA:A","label":"y","offset":0,"slot":"1","type":"t_uint256"},{"astId":10,"contract":"fileA:A","label":"map","offset":0,"slot":"2","type":"t_mapping(t_uint256,t_mapping(t_address,t_bool))"}],"types":{"t_address":{"encoding":"inplace","label":"address","numberOfBytes":"20"},"t_bool":{"encoding":"inplace","label":"bool","numberOfBytes":"1"},"t_mapping(t_address,t_bool)":{"encoding":"mapping","key":"t_address","label":"mapping(address => bool)","numberOfBytes":"32","value":"t_bool"},"t_mapping(t_uint256,t_mapping(t_address,t_bool))":{"encoding":"mapping","key":"t_uint256","label":"mapping(uint256 => mapping(address => bool))","numberOfBytes":"32","value":"t_mapping(t_address,t_bool)"},"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}}}}},"errors":[{"component":"general","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[{"astId":2,"contract":"fileA:A","label":"x","offset":0,"slot":"0","type":"t_uint256"},{"astId":4,"contract":"fileA:A","label":"y","offset":0,"slot":"1","type":"t_uint256"},{"astId":10,"contract":"fileA:A","label":"map","offset":0,"slot":"2","type":"t_mapping(t_uint256,t_mapping(t_address,t_bool))"}],"types":{"t_address":{"encoding":"inplace","label":"address","numberOfBytes":"20"},"t_bool":{"encoding":"inplace","label":"bool","numberOfBytes":"1"},"t_mapping(t_address,t_bool)":{"encoding":"mapping","key":"t_address","label":"mapping(address => bool)","numberOfBytes":"32","value":"t_bool"},"t_mapping(t_uint256,t_mapping(t_address,t_bool))":{"encoding":"mapping","key":"t_uint256","label":"mapping(uint256 => mapping(address => bool))","numberOfBytes":"32","value":"t_mapping(t_address,t_bool)"},"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"fileA","start":-1},"type":"Warning"}],"sources":{"fileA":{"id":0}}}

View File

@ -1,2 +1,2 @@
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[],"types":null}}}},"errors":[{"component":"general","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[],"types":null}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"fileA","start":-1},"type":"Warning"}],"sources":{"fileA":{"id":0}}}

View File

@ -1,2 +1,2 @@
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[],"types":null}}}},"errors":[{"component":"general","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[],"types":null}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"fileA","start":-1},"type":"Warning"}],"sources":{"fileA":{"id":0},"fileB":{"id":1}}}

View File

@ -1,2 +1,2 @@
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[{"astId":3,"contract":"fileA:A","label":"s1","offset":0,"slot":"0","type":"t_string_storage"},{"astId":5,"contract":"fileA:A","label":"s2","offset":0,"slot":"1","type":"t_string_storage"}],"types":{"t_string_storage":{"encoding":"bytes","label":"string","numberOfBytes":"32"}}}}}},"errors":[{"component":"general","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[{"astId":3,"contract":"fileA:A","label":"s1","offset":0,"slot":"0","type":"t_string_storage"},{"astId":5,"contract":"fileA:A","label":"s2","offset":0,"slot":"1","type":"t_string_storage"}],"types":{"t_string_storage":{"encoding":"bytes","label":"string","numberOfBytes":"32"}}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"fileA","start":-1},"type":"Warning"}],"sources":{"fileA":{"id":0}}}

View File

@ -1,2 +1,2 @@
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[{"astId":14,"contract":"fileA:A","label":"x","offset":0,"slot":"0","type":"t_uint256"},{"astId":16,"contract":"fileA:A","label":"y","offset":0,"slot":"1","type":"t_uint256"},{"astId":18,"contract":"fileA:A","label":"s","offset":0,"slot":"2","type":"t_struct(S)12_storage"},{"astId":20,"contract":"fileA:A","label":"addr","offset":0,"slot":"7","type":"t_address"}],"types":{"t_address":{"encoding":"inplace","label":"address","numberOfBytes":"20"},"t_array(t_uint256)2_storage":{"base":"t_uint256","encoding":"inplace","label":"uint256[2]","numberOfBytes":"64"},"t_array(t_uint256)dyn_storage":{"base":"t_uint256","encoding":"dynamic_array","label":"uint256[]","numberOfBytes":"32"},"t_struct(S)12_storage":{"encoding":"inplace","label":"struct A.S","members":[{"astId":2,"contract":"fileA:A","label":"a","offset":0,"slot":"0","type":"t_uint256"},{"astId":4,"contract":"fileA:A","label":"b","offset":0,"slot":"1","type":"t_uint256"},{"astId":8,"contract":"fileA:A","label":"staticArray","offset":0,"slot":"2","type":"t_array(t_uint256)2_storage"},{"astId":11,"contract":"fileA:A","label":"dynArray","offset":0,"slot":"4","type":"t_array(t_uint256)dyn_storage"}],"numberOfBytes":"160"},"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}}}}},"errors":[{"component":"general","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[{"astId":14,"contract":"fileA:A","label":"x","offset":0,"slot":"0","type":"t_uint256"},{"astId":16,"contract":"fileA:A","label":"y","offset":0,"slot":"1","type":"t_uint256"},{"astId":18,"contract":"fileA:A","label":"s","offset":0,"slot":"2","type":"t_struct(S)12_storage"},{"astId":20,"contract":"fileA:A","label":"addr","offset":0,"slot":"7","type":"t_address"}],"types":{"t_address":{"encoding":"inplace","label":"address","numberOfBytes":"20"},"t_array(t_uint256)2_storage":{"base":"t_uint256","encoding":"inplace","label":"uint256[2]","numberOfBytes":"64"},"t_array(t_uint256)dyn_storage":{"base":"t_uint256","encoding":"dynamic_array","label":"uint256[]","numberOfBytes":"32"},"t_struct(S)12_storage":{"encoding":"inplace","label":"struct A.S","members":[{"astId":2,"contract":"fileA:A","label":"a","offset":0,"slot":"0","type":"t_uint256"},{"astId":4,"contract":"fileA:A","label":"b","offset":0,"slot":"1","type":"t_uint256"},{"astId":8,"contract":"fileA:A","label":"staticArray","offset":0,"slot":"2","type":"t_array(t_uint256)2_storage"},{"astId":11,"contract":"fileA:A","label":"dynArray","offset":0,"slot":"4","type":"t_array(t_uint256)dyn_storage"}],"numberOfBytes":"160"},"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"fileA","start":-1},"type":"Warning"}],"sources":{"fileA":{"id":0}}}

View File

@ -1,2 +1,2 @@
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[{"astId":14,"contract":"fileA:A","label":"x","offset":0,"slot":"0","type":"t_uint256"},{"astId":16,"contract":"fileA:A","label":"y","offset":0,"slot":"1","type":"t_uint256"},{"astId":18,"contract":"fileA:A","label":"s","offset":0,"slot":"2","type":"t_struct(S)12_storage"},{"astId":20,"contract":"fileA:A","label":"addr","offset":0,"slot":"6","type":"t_address"}],"types":{"t_address":{"encoding":"inplace","label":"address","numberOfBytes":"20"},"t_array(t_uint256)2_storage":{"base":"t_uint256","encoding":"inplace","label":"uint256[2]","numberOfBytes":"64"},"t_array(t_uint256)dyn_storage":{"base":"t_uint256","encoding":"dynamic_array","label":"uint256[]","numberOfBytes":"32"},"t_struct(S)12_storage":{"encoding":"inplace","label":"struct A.S","members":[{"astId":2,"contract":"fileA:A","label":"a","offset":0,"slot":"0","type":"t_uint128"},{"astId":4,"contract":"fileA:A","label":"b","offset":16,"slot":"0","type":"t_uint128"},{"astId":8,"contract":"fileA:A","label":"staticArray","offset":0,"slot":"1","type":"t_array(t_uint256)2_storage"},{"astId":11,"contract":"fileA:A","label":"dynArray","offset":0,"slot":"3","type":"t_array(t_uint256)dyn_storage"}],"numberOfBytes":"128"},"t_uint128":{"encoding":"inplace","label":"uint128","numberOfBytes":"16"},"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}}}}},"errors":[{"component":"general","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[{"astId":14,"contract":"fileA:A","label":"x","offset":0,"slot":"0","type":"t_uint256"},{"astId":16,"contract":"fileA:A","label":"y","offset":0,"slot":"1","type":"t_uint256"},{"astId":18,"contract":"fileA:A","label":"s","offset":0,"slot":"2","type":"t_struct(S)12_storage"},{"astId":20,"contract":"fileA:A","label":"addr","offset":0,"slot":"6","type":"t_address"}],"types":{"t_address":{"encoding":"inplace","label":"address","numberOfBytes":"20"},"t_array(t_uint256)2_storage":{"base":"t_uint256","encoding":"inplace","label":"uint256[2]","numberOfBytes":"64"},"t_array(t_uint256)dyn_storage":{"base":"t_uint256","encoding":"dynamic_array","label":"uint256[]","numberOfBytes":"32"},"t_struct(S)12_storage":{"encoding":"inplace","label":"struct A.S","members":[{"astId":2,"contract":"fileA:A","label":"a","offset":0,"slot":"0","type":"t_uint128"},{"astId":4,"contract":"fileA:A","label":"b","offset":16,"slot":"0","type":"t_uint128"},{"astId":8,"contract":"fileA:A","label":"staticArray","offset":0,"slot":"1","type":"t_array(t_uint256)2_storage"},{"astId":11,"contract":"fileA:A","label":"dynArray","offset":0,"slot":"3","type":"t_array(t_uint256)dyn_storage"}],"numberOfBytes":"128"},"t_uint128":{"encoding":"inplace","label":"uint128","numberOfBytes":"16"},"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"fileA","start":-1},"type":"Warning"}],"sources":{"fileA":{"id":0}}}

View File

@ -1,2 +1,2 @@
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[{"astId":2,"contract":"fileA:A","label":"x","offset":0,"slot":"0","type":"t_uint256"},{"astId":4,"contract":"fileA:A","label":"y","offset":0,"slot":"1","type":"t_uint256"},{"astId":6,"contract":"fileA:A","label":"addr","offset":0,"slot":"2","type":"t_address"},{"astId":10,"contract":"fileA:A","label":"array","offset":0,"slot":"3","type":"t_array(t_uint256)2_storage"}],"types":{"t_address":{"encoding":"inplace","label":"address","numberOfBytes":"20"},"t_array(t_uint256)2_storage":{"base":"t_uint256","encoding":"inplace","label":"uint256[2]","numberOfBytes":"64"},"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}}}}},"errors":[{"component":"general","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
{"contracts":{"fileA":{"A":{"storageLayout":{"storage":[{"astId":2,"contract":"fileA:A","label":"x","offset":0,"slot":"0","type":"t_uint256"},{"astId":4,"contract":"fileA:A","label":"y","offset":0,"slot":"1","type":"t_uint256"},{"astId":6,"contract":"fileA:A","label":"addr","offset":0,"slot":"2","type":"t_address"},{"astId":10,"contract":"fileA:A","label":"array","offset":0,"slot":"3","type":"t_array(t_uint256)2_storage"}],"types":{"t_address":{"encoding":"inplace","label":"address","numberOfBytes":"20"},"t_array(t_uint256)2_storage":{"base":"t_uint256","encoding":"inplace","label":"uint256[2]","numberOfBytes":"64"},"t_uint256":{"encoding":"inplace","label":"uint256","numberOfBytes":"32"}}}}}},"errors":[{"component":"general","errorCode":"3420","formattedMessage":"fileA: Warning: Source file does not specify required compiler version!
","message":"Source file does not specify required compiler version!","severity":"warning","sourceLocation":{"end":-1,"file":"fileA","start":-1},"type":"Warning"}],"sources":{"fileA":{"id":0}}}

Some files were not shown because too many files have changed in this diff Show More