Merge pull request #8645 from ethereum/develop

Merge develop into release for 0.6.6.
This commit is contained in:
chriseth 2020-04-09 13:40:11 +02:00 committed by GitHub
commit 6c089d02b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
101 changed files with 995 additions and 275 deletions

View File

@ -10,7 +10,7 @@ include(EthPolicy)
eth_policy()
# project name and version should be set after cmake_policy CMP0048
set(PROJECT_VERSION "0.6.5")
set(PROJECT_VERSION "0.6.6")
# OSX target needed in order to support std::visit
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14")
project(solidity VERSION ${PROJECT_VERSION} LANGUAGES C CXX)

View File

@ -1,3 +1,16 @@
### 0.6.6 (2020-04-09)
Important Bugfixes:
* Fix tuple assignments with components occupying multiple stack slots and different stack size on left- and right-hand-side.
Bugfixes:
* AST export: Export `immutable` property in the field `mutability`.
* SMTChecker: Fix internal error in the CHC engine when calling inherited functions internally.
* Type Checker: Error when trying to encode functions with call options gas and value set.
### 0.6.5 (2020-04-06)
Important Bugfixes:

View File

@ -1,4 +1,12 @@
[
{
"name": "TupleAssignmentMultiStackSlotComponents",
"summary": "Tuple assignments with components that occupy several stack slots, i.e. nested tuples, pointers to external functions or references to dynamically sized calldata arrays, can result in invalid values.",
"description": "Tuple assignments did not correctly account for tuple components that occupy multiple stack slots in case the number of stack slots differs between left-hand-side and right-hand-side. This can either happen in the presence of nested tuples or if the right-hand-side contains external function pointers or references to dynamic calldata arrays, while the left-hand-side contains an omission.",
"introduced": "0.1.6",
"fixed": "0.6.6",
"severity": "very low"
},
{
"name": "MemoryArrayCreationOverflow",
"summary": "The creation of very large memory arrays can result in overlapping memory regions and thus memory corruption.",

View File

@ -111,6 +111,7 @@
},
"0.1.6": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -131,6 +132,7 @@
},
"0.1.7": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -151,6 +153,7 @@
},
"0.2.0": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
@ -172,6 +175,7 @@
},
"0.2.1": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
@ -193,6 +197,7 @@
},
"0.2.2": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
@ -214,6 +219,7 @@
},
"0.3.0": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -237,6 +243,7 @@
},
"0.3.1": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -259,6 +266,7 @@
},
"0.3.2": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -281,6 +289,7 @@
},
"0.3.3": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -302,6 +311,7 @@
},
"0.3.4": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -323,6 +333,7 @@
},
"0.3.5": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -344,6 +355,7 @@
},
"0.3.6": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -363,6 +375,7 @@
},
"0.4.0": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -382,6 +395,7 @@
},
"0.4.1": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -401,6 +415,7 @@
},
"0.4.10": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -418,6 +433,7 @@
},
"0.4.11": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -434,6 +450,7 @@
},
"0.4.12": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -449,6 +466,7 @@
},
"0.4.13": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -464,6 +482,7 @@
},
"0.4.14": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -478,6 +497,7 @@
},
"0.4.15": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -491,6 +511,7 @@
},
"0.4.16": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -506,6 +527,7 @@
},
"0.4.17": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -522,6 +544,7 @@
},
"0.4.18": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -537,6 +560,7 @@
},
"0.4.19": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -553,6 +577,7 @@
},
"0.4.2": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -571,6 +596,7 @@
},
"0.4.20": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -587,6 +613,7 @@
},
"0.4.21": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -603,6 +630,7 @@
},
"0.4.22": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -619,6 +647,7 @@
},
"0.4.23": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -634,6 +663,7 @@
},
"0.4.24": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -649,6 +679,7 @@
},
"0.4.25": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -662,6 +693,7 @@
},
"0.4.26": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -672,6 +704,7 @@
},
"0.4.3": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -689,6 +722,7 @@
},
"0.4.4": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -705,6 +739,7 @@
},
"0.4.5": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"UninitializedFunctionPointerInConstructor_0.4.x",
@ -723,6 +758,7 @@
},
"0.4.6": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"UninitializedFunctionPointerInConstructor_0.4.x",
@ -740,6 +776,7 @@
},
"0.4.7": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -757,6 +794,7 @@
},
"0.4.8": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -774,6 +812,7 @@
},
"0.4.9": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -791,6 +830,7 @@
},
"0.5.0": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -804,6 +844,7 @@
},
"0.5.1": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -817,6 +858,7 @@
},
"0.5.10": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"YulOptimizerRedundantAssignmentBreakContinue0.5",
@ -826,6 +868,7 @@
},
"0.5.11": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"YulOptimizerRedundantAssignmentBreakContinue0.5"
@ -834,6 +877,7 @@
},
"0.5.12": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"YulOptimizerRedundantAssignmentBreakContinue0.5"
@ -842,6 +886,7 @@
},
"0.5.13": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"YulOptimizerRedundantAssignmentBreakContinue0.5"
@ -850,6 +895,7 @@
},
"0.5.14": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"YulOptimizerRedundantAssignmentBreakContinue0.5",
@ -859,6 +905,7 @@
},
"0.5.15": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"YulOptimizerRedundantAssignmentBreakContinue0.5"
@ -867,6 +914,7 @@
},
"0.5.16": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden"
],
@ -874,12 +922,14 @@
},
"0.5.17": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow"
],
"released": "2020-03-17"
},
"0.5.2": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -893,6 +943,7 @@
},
"0.5.3": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -906,6 +957,7 @@
},
"0.5.4": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -919,6 +971,7 @@
},
"0.5.5": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"SignedArrayStorageCopy",
@ -934,6 +987,7 @@
},
"0.5.6": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers",
@ -949,6 +1003,7 @@
},
"0.5.7": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"ABIEncoderV2CalldataStructsWithStaticallySizedAndDynamicallyEncodedMembers",
@ -962,6 +1017,7 @@
},
"0.5.8": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"YulOptimizerRedundantAssignmentBreakContinue0.5",
@ -974,6 +1030,7 @@
},
"0.5.9": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"privateCanBeOverridden",
"YulOptimizerRedundantAssignmentBreakContinue0.5",
@ -985,6 +1042,7 @@
},
"0.6.0": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow",
"YulOptimizerRedundantAssignmentBreakContinue"
],
@ -992,30 +1050,40 @@
},
"0.6.1": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow"
],
"released": "2020-01-02"
},
"0.6.2": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow"
],
"released": "2020-01-27"
},
"0.6.3": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow"
],
"released": "2020-02-18"
},
"0.6.4": {
"bugs": [
"TupleAssignmentMultiStackSlotComponents",
"MemoryArrayCreationOverflow"
],
"released": "2020-03-10"
},
"0.6.5": {
"bugs": [],
"bugs": [
"TupleAssignmentMultiStackSlotComponents"
],
"released": "2020-04-06"
},
"0.6.6": {
"bugs": [],
"released": "2020-04-09"
}
}

View File

@ -433,7 +433,7 @@ The full contract
.. note::
The function ``splitSignature`` does not use all security
checks. A real implementation should use a more rigorously tested library,
such as openzepplin's `version <https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/ECRecovery.sol>`_ of this code.
such as openzepplin's `version <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/cryptography/ECDSA.sol>`_ of this code.
Verifying Payments
------------------

View File

@ -106,6 +106,8 @@ set(sources
formal/Sorts.h
formal/SSAVariable.cpp
formal/SSAVariable.h
formal/SymbolicState.cpp
formal/SymbolicState.h
formal/SymbolicTypes.cpp
formal/SymbolicTypes.h
formal/SymbolicVariables.cpp

View File

@ -54,11 +54,11 @@ public:
TypePointer evaluate(Expression const& _expr);
private:
virtual void endVisit(BinaryOperation const& _operation);
virtual void endVisit(UnaryOperation const& _operation);
virtual void endVisit(Literal const& _literal);
virtual void endVisit(Identifier const& _identifier);
virtual void endVisit(TupleExpression const& _tuple);
void endVisit(BinaryOperation const& _operation) override;
void endVisit(UnaryOperation const& _operation) override;
void endVisit(Literal const& _literal) override;
void endVisit(Identifier const& _identifier) override;
void endVisit(TupleExpression const& _tuple) override;
void setType(ASTNode const& _node, TypePointer const& _type);
TypePointer type(ASTNode const& _node);

View File

@ -50,7 +50,7 @@ class StaticAnalyzer: private ASTConstVisitor
public:
/// @param _errorReporter provides the error logging functionality.
explicit StaticAnalyzer(langutil::ErrorReporter& _errorReporter);
~StaticAnalyzer();
~StaticAnalyzer() override;
/// Performs static analysis on the given source unit and all of its sub-nodes.
/// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings

View File

@ -1430,41 +1430,37 @@ bool TypeChecker::visit(TupleExpression const& _tuple)
{
if (!components[i])
m_errorReporter.fatalTypeError(_tuple.location(), "Tuple component cannot be empty.");
else if (components[i])
{
components[i]->accept(*this);
types.push_back(type(*components[i]));
if (types[i]->category() == Type::Category::Tuple)
if (dynamic_cast<TupleType const&>(*types[i]).components().empty())
{
if (_tuple.isInlineArray())
m_errorReporter.fatalTypeError(components[i]->location(), "Array component cannot be empty.");
m_errorReporter.typeError(components[i]->location(), "Tuple component cannot be empty.");
}
components[i]->accept(*this);
types.push_back(type(*components[i]));
// Note: code generation will visit each of the expression even if they are not assigned from.
if (types[i]->category() == Type::Category::RationalNumber && components.size() > 1)
if (!dynamic_cast<RationalNumberType const&>(*types[i]).mobileType())
m_errorReporter.fatalTypeError(components[i]->location(), "Invalid rational number.");
if (_tuple.isInlineArray())
if (types[i]->category() == Type::Category::Tuple)
if (dynamic_cast<TupleType const&>(*types[i]).components().empty())
{
solAssert(!!types[i], "Inline array cannot have empty components");
if ((i == 0 || inlineArrayType) && !types[i]->mobileType())
m_errorReporter.fatalTypeError(components[i]->location(), "Invalid mobile type.");
if (i == 0)
inlineArrayType = types[i]->mobileType();
else if (inlineArrayType)
inlineArrayType = Type::commonType(inlineArrayType, types[i]);
if (_tuple.isInlineArray())
m_errorReporter.fatalTypeError(components[i]->location(), "Array component cannot be empty.");
m_errorReporter.typeError(components[i]->location(), "Tuple component cannot be empty.");
}
if (!components[i]->annotation().isPure)
isPure = false;
// Note: code generation will visit each of the expression even if they are not assigned from.
if (types[i]->category() == Type::Category::RationalNumber && components.size() > 1)
if (!dynamic_cast<RationalNumberType const&>(*types[i]).mobileType())
m_errorReporter.fatalTypeError(components[i]->location(), "Invalid rational number.");
if (_tuple.isInlineArray())
{
solAssert(!!types[i], "Inline array cannot have empty components");
if ((i == 0 || inlineArrayType) && !types[i]->mobileType())
m_errorReporter.fatalTypeError(components[i]->location(), "Invalid mobile type.");
if (i == 0)
inlineArrayType = types[i]->mobileType();
else if (inlineArrayType)
inlineArrayType = Type::commonType(inlineArrayType, types[i]);
}
else
types.push_back(TypePointer());
if (!components[i]->annotation().isPure)
isPure = false;
}
_tuple.annotation().isPure = isPure;
if (_tuple.isInlineArray())

View File

@ -217,6 +217,37 @@ ContractDefinitionAnnotation& ContractDefinition::annotation() const
return initAnnotation<ContractDefinitionAnnotation>();
}
ContractDefinition const* ContractDefinition::superContract(ContractDefinition const& _mostDerivedContract) const
{
auto const& hierarchy = _mostDerivedContract.annotation().linearizedBaseContracts;
auto it = find(hierarchy.begin(), hierarchy.end(), this);
solAssert(it != hierarchy.end(), "Base not found in inheritance hierarchy.");
++it;
if (it == hierarchy.end())
return nullptr;
else
{
solAssert(*it != this, "");
return *it;
}
}
FunctionDefinition const* ContractDefinition::nextConstructor(ContractDefinition const& _mostDerivedContract) const
{
ContractDefinition const* next = superContract(_mostDerivedContract);
if (next == nullptr)
return nullptr;
for (ContractDefinition const* c: _mostDerivedContract.annotation().linearizedBaseContracts)
if (c == next || next == nullptr)
{
if (c->constructor())
return c->constructor();
next = nullptr;
}
return nullptr;
}
TypeNameAnnotation& TypeName::annotation() const
{
return initAnnotation<TypeNameAnnotation>();

View File

@ -518,6 +518,10 @@ public:
bool abstract() const { return m_abstract; }
ContractDefinition const* superContract(ContractDefinition const& _mostDerivedContract) const;
/// @returns the next constructor in the inheritance hierarchy.
FunctionDefinition const* nextConstructor(ContractDefinition const& _mostDerivedContract) const;
private:
std::vector<ASTPointer<InheritanceSpecifier>> m_baseContracts;
std::vector<ASTPointer<ASTNode>> m_subNodes;
@ -850,7 +854,17 @@ class VariableDeclaration: public Declaration
{
public:
enum Location { Unspecified, Storage, Memory, CallData };
enum class Constantness { Mutable, Immutable, Constant };
enum class Mutability { Mutable, Immutable, Constant };
static std::string mutabilityToString(Mutability _mutability)
{
switch (_mutability)
{
case Mutability::Mutable: return "mutable";
case Mutability::Immutable: return "immutable";
case Mutability::Constant: return "constant";
}
return {};
}
VariableDeclaration(
int64_t _id,
@ -861,7 +875,7 @@ public:
Visibility _visibility,
bool _isStateVar = false,
bool _isIndexed = false,
Constantness _constantness = Constantness::Mutable,
Mutability _mutability = Mutability::Mutable,
ASTPointer<OverrideSpecifier> const& _overrides = nullptr,
Location _referenceLocation = Location::Unspecified
):
@ -870,7 +884,7 @@ public:
m_value(_value),
m_isStateVariable(_isStateVar),
m_isIndexed(_isIndexed),
m_constantness(_constantness),
m_mutability(_mutability),
m_overrides(_overrides),
m_location(_referenceLocation) {}
@ -914,8 +928,9 @@ public:
bool hasReferenceOrMappingType() const;
bool isStateVariable() const { return m_isStateVariable; }
bool isIndexed() const { return m_isIndexed; }
bool isConstant() const { return m_constantness == Constantness::Constant; }
bool immutable() const { return m_constantness == Constantness::Immutable; }
Mutability mutability() const { return m_mutability; }
bool isConstant() const { return m_mutability == Mutability::Constant; }
bool immutable() const { return m_mutability == Mutability::Immutable; }
ASTPointer<OverrideSpecifier> const& overrides() const { return m_overrides; }
Location referenceLocation() const { return m_location; }
/// @returns a set of allowed storage locations for the variable.
@ -943,7 +958,7 @@ private:
bool m_isStateVariable = false; ///< Whether or not this is a contract state variable
bool m_isIndexed = false; ///< Whether this is an indexed variable (used by events).
/// Whether the variable is "constant", "immutable" or non-marked (mutable).
Constantness m_constantness = Constantness::Mutable;
Mutability m_mutability = Mutability::Mutable;
ASTPointer<OverrideSpecifier> m_overrides; ///< Contains the override specifier node
Location m_location = Location::Unspecified; ///< Location of the variable if it is of reference type.
};

View File

@ -378,6 +378,7 @@ bool ASTJsonConverter::visit(VariableDeclaration const& _node)
make_pair("name", _node.name()),
make_pair("typeName", toJsonOrNull(_node.typeName())),
make_pair("constant", _node.isConstant()),
make_pair("mutability", VariableDeclaration::mutabilityToString(_node.mutability())),
make_pair("stateVariable", _node.isStateVariable()),
make_pair("storageLocation", location(_node.referenceLocation())),
make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json::nullValue),

View File

@ -411,11 +411,24 @@ ASTPointer<VariableDeclaration> ASTJsonImporter::createVariableDeclaration(Json:
{
astAssert(_node["name"].isString(), "Expected 'name' to be a string!");
VariableDeclaration::Constantness constantness{};
if (memberAsBool(_node, "constant"))
constantness = VariableDeclaration::Constantness::Constant;
VariableDeclaration::Mutability mutability{};
astAssert(member(_node, "mutability").isString(), "'mutability' expected to be string.");
string const mutabilityStr = member(_node, "mutability").asString();
if (mutabilityStr == "constant")
{
mutability = VariableDeclaration::Mutability::Constant;
astAssert(memberAsBool(_node, "constant"), "");
}
else
constantness = VariableDeclaration::Constantness::Mutable;
{
astAssert(!memberAsBool(_node, "constant"), "");
if (mutabilityStr == "mutable")
mutability = VariableDeclaration::Mutability::Mutable;
else if (mutabilityStr == "immutable")
mutability = VariableDeclaration::Mutability::Immutable;
else
astAssert(false, "");
}
return createASTNode<VariableDeclaration>(
_node,
@ -425,7 +438,7 @@ ASTPointer<VariableDeclaration> ASTJsonImporter::createVariableDeclaration(Json:
visibility(_node),
memberAsBool(_node, "stateVariable"),
_node.isMember("indexed") ? memberAsBool(_node, "indexed") : false,
constantness,
mutability,
_node["overrides"].isNull() ? nullptr : createOverrideSpecifier(member(_node, "overrides")),
location(_node)
);
@ -495,7 +508,7 @@ ASTPointer<UserDefinedTypeName> ASTJsonImporter::createUserDefinedTypeName(Json:
string nameString = member(_node, "name").asString();
boost::algorithm::split(strs, nameString, boost::is_any_of("."));
for (string s: strs)
namePath.push_back(ASTString(s));
namePath.emplace_back(s);
return createASTNode<UserDefinedTypeName>(
_node,
namePath

View File

@ -3112,6 +3112,8 @@ MemberList::MemberMap FunctionType::nativeMembers(ContractDefinition const* _sco
TypePointer FunctionType::encodingType() const
{
if (m_gasSet || m_valueSet)
return nullptr;
// Only external functions can be encoded, internal functions cannot leave code boundaries.
if (m_kind == Kind::External)
return this;

View File

@ -843,7 +843,7 @@ string ABIFunctions::abiEncodingFunctionStruct(
if (dynamicMember)
solAssert(dynamic, "");
members.push_back({});
members.emplace_back();
members.back()["preprocess"] = "";
switch (_from.location())
@ -1336,7 +1336,7 @@ string ABIFunctions::abiDecodingFunctionStruct(StructType const& _type, bool _fr
memberTempl("memoryOffset", toCompactHexWithPrefix(_type.memoryOffsetOfMember(member.name)));
memberTempl("abiDecode", abiDecodingFunction(*member.type, _fromMemory, false));
members.push_back({});
members.emplace_back();
members.back()["decode"] = memberTempl.render();
members.back()["memberName"] = member.name;
headPos += decodingType->calldataHeadSize();

View File

@ -269,29 +269,11 @@ evmasm::AssemblyItem CompilerContext::functionEntryLabelIfExists(Declaration con
FunctionDefinition const& CompilerContext::superFunction(FunctionDefinition const& _function, ContractDefinition const& _base)
{
solAssert(m_mostDerivedContract, "No most derived contract set.");
ContractDefinition const* super = superContract(_base);
ContractDefinition const* super = _base.superContract(mostDerivedContract());
solAssert(super, "Super contract not available.");
return _function.resolveVirtual(mostDerivedContract(), super);
}
FunctionDefinition const* CompilerContext::nextConstructor(ContractDefinition const& _contract) const
{
ContractDefinition const* next = superContract(_contract);
if (next == nullptr)
return nullptr;
for (ContractDefinition const* c: m_mostDerivedContract->annotation().linearizedBaseContracts)
if (next != nullptr && next != c)
continue;
else
{
next = nullptr;
if (c->constructor())
return c->constructor();
}
return nullptr;
}
ContractDefinition const& CompilerContext::mostDerivedContract() const
{
solAssert(m_mostDerivedContract, "Most derived contract not set.");
@ -536,21 +518,6 @@ LinkerObject const& CompilerContext::assembledObject() const
return object;
}
ContractDefinition const* CompilerContext::superContract(ContractDefinition const& _contract) const
{
auto const& hierarchy = mostDerivedContract().annotation().linearizedBaseContracts;
auto it = find(hierarchy.begin(), hierarchy.end(), &_contract);
solAssert(it != hierarchy.end(), "Base not found in inheritance hierarchy.");
++it;
if (it == hierarchy.end())
return nullptr;
else
{
solAssert(*it != &_contract, "");
return *it;
}
}
string CompilerContext::revertReasonIfDebug(string const& _message)
{
return YulUtilFunctions::revertReasonIfDebug(m_revertStrings, _message);

View File

@ -117,8 +117,6 @@ public:
/// @returns the function that overrides the given declaration from the most derived class just
/// above _base in the current inheritance hierarchy.
FunctionDefinition const& superFunction(FunctionDefinition const& _function, ContractDefinition const& _base);
/// @returns the next constructor in the inheritance hierarchy.
FunctionDefinition const* nextConstructor(ContractDefinition const& _contract) const;
/// Sets the contract currently being compiled - the most derived one.
void setMostDerivedContract(ContractDefinition const& _contract) { m_mostDerivedContract = &_contract; }
ContractDefinition const& mostDerivedContract() const;
@ -313,8 +311,6 @@ public:
RevertStrings revertStrings() const { return m_revertStrings; }
private:
/// @returns a pointer to the contract directly above the given contract.
ContractDefinition const* superContract(ContractDefinition const& _contract) const;
/// Updates source location set in the assembly.
void updateSourceLocation();

View File

@ -1108,12 +1108,12 @@ void CompilerUtils::convertType(
// Value shrank
for (unsigned j = targetSize; j < sourceSize; ++j)
{
moveToStackTop(depth - 1, 1);
moveToStackTop(depth + targetSize - sourceSize, 1);
m_context << Instruction::POP;
}
// Value grew
if (targetSize > sourceSize)
moveIntoStack(depth + targetSize - sourceSize - 1, targetSize - sourceSize);
moveIntoStack(depth - sourceSize, targetSize - sourceSize);
}
}
depth -= sourceSize;

View File

@ -159,7 +159,7 @@ void ContractCompiler::appendInitAndConstructorCode(ContractDefinition const& _c
if (FunctionDefinition const* constructor = _contract.constructor())
appendConstructor(*constructor);
else if (auto c = m_context.nextConstructor(_contract))
else if (auto c = _contract.nextConstructor(m_context.mostDerivedContract()))
appendBaseConstructor(*c);
else
appendCallValueCheck();
@ -596,7 +596,9 @@ bool ContractCompiler::visit(FunctionDefinition const& _function)
appendStackVariableInitialisation(*variable);
if (_function.isConstructor())
if (auto c = m_context.nextConstructor(dynamic_cast<ContractDefinition const&>(*_function.scope())))
if (auto c = dynamic_cast<ContractDefinition const&>(*_function.scope()).nextConstructor(
m_context.mostDerivedContract()
))
appendBaseConstructor(*c);
solAssert(m_returnTags.empty(), "");

View File

@ -352,7 +352,7 @@ string IRGenerator::dispatchRoutine(ContractDefinition const& _contract)
vector<map<string, string>> functions;
for (auto const& function: _contract.interfaceFunctions())
{
functions.push_back({});
functions.emplace_back();
map<string, string>& templ = functions.back();
templ["functionSelector"] = "0x" + function.first.hex();
FunctionTypePointer const& type = function.second;

View File

@ -18,6 +18,7 @@
#include <libsolidity/formal/BMC.h>
#include <libsolidity/formal/SMTPortfolio.h>
#include <libsolidity/formal/SymbolicState.h>
#include <libsolidity/formal/SymbolicTypes.h>
#include <boost/algorithm/string/replace.hpp>
@ -376,7 +377,7 @@ void BMC::endVisit(FunctionCall const& _funCall)
SMTEncoder::endVisit(_funCall);
auto value = _funCall.arguments().front();
solAssert(value, "");
smt::Expression thisBalance = m_context.balance();
smt::Expression thisBalance = m_context.state().balance();
addVerificationTarget(
VerificationTarget::Type::Balance,

View File

@ -961,7 +961,11 @@ smt::Expression CHC::predicate(FunctionCall const& _funCall)
for (auto const& var: function->returnParameters())
args.push_back(m_context.variable(*var)->currentValue());
return (*m_summaries.at(contract).at(function))(args);
if (contract->isLibrary())
return (*m_summaries.at(contract).at(function))(args);
solAssert(m_currentContract, "");
return (*m_summaries.at(m_currentContract).at(function))(args);
}
void CHC::addRule(smt::Expression const& _rule, string const& _ruleName)

View File

@ -25,13 +25,8 @@ using namespace solidity::util;
using namespace solidity::frontend::smt;
EncodingContext::EncodingContext():
m_thisAddress(make_unique<SymbolicAddressVariable>("this", *this))
m_state(*this)
{
auto sort = make_shared<ArraySort>(
SortProvider::intSort,
SortProvider::intSort
);
m_balances = make_unique<SymbolicVariable>(sort, "balances", *this);
}
void EncodingContext::reset()
@ -39,8 +34,7 @@ void EncodingContext::reset()
resetAllVariables();
m_expressions.clear();
m_globalContext.clear();
m_thisAddress->resetIndex();
m_balances->resetIndex();
m_state.reset();
m_assertions.clear();
}
@ -183,40 +177,6 @@ bool EncodingContext::knownGlobalSymbol(string const& _var) const
return m_globalContext.count(_var);
}
// Blockchain
Expression EncodingContext::thisAddress()
{
return m_thisAddress->currentValue();
}
Expression EncodingContext::balance()
{
return balance(m_thisAddress->currentValue());
}
Expression EncodingContext::balance(Expression _address)
{
return Expression::select(m_balances->currentValue(), move(_address));
}
void EncodingContext::transfer(Expression _from, Expression _to, Expression _value)
{
unsigned indexBefore = m_balances->index();
addBalance(_from, 0 - _value);
addBalance(_to, move(_value));
unsigned indexAfter = m_balances->index();
solAssert(indexAfter > indexBefore, "");
m_balances->increaseIndex();
/// Do not apply the transfer operation if _from == _to.
auto newBalances = Expression::ite(
move(_from) == move(_to),
m_balances->valueAtIndex(indexBefore),
m_balances->valueAtIndex(indexAfter)
);
addAssertion(m_balances->currentValue() == newBalances);
}
/// Solver.
Expression EncodingContext::assertions()
@ -232,7 +192,7 @@ void EncodingContext::pushSolver()
if (m_accumulateAssertions)
m_assertions.push_back(assertions());
else
m_assertions.push_back(smt::Expression(true));
m_assertions.emplace_back(true);
}
void EncodingContext::popSolver()
@ -248,16 +208,3 @@ void EncodingContext::addAssertion(Expression const& _expr)
else
m_assertions.back() = _expr && move(m_assertions.back());
}
/// Private helpers.
void EncodingContext::addBalance(Expression _address, Expression _value)
{
auto newBalances = Expression::store(
m_balances->currentValue(),
_address,
balance(_address) + move(_value)
);
m_balances->increaseIndex();
addAssertion(newBalances == m_balances->currentValue());
}

View File

@ -18,6 +18,7 @@
#pragma once
#include <libsolidity/formal/SolverInterface.h>
#include <libsolidity/formal/SymbolicState.h>
#include <libsolidity/formal/SymbolicVariables.h>
#include <unordered_map>
@ -121,18 +122,6 @@ public:
bool knownGlobalSymbol(std::string const& _var) const;
//@}
/// Blockchain.
//@{
/// Value of `this` address.
Expression thisAddress();
/// @returns the symbolic balance of address `this`.
Expression balance();
/// @returns the symbolic balance of an address.
Expression balance(Expression _address);
/// Transfer _value from _from to _to.
void transfer(Expression _from, Expression _to, Expression _value);
//@}
/// Solver.
//@{
/// @returns conjunction of all added assertions.
@ -148,10 +137,9 @@ public:
}
//@}
private:
/// Adds _value to _account's balance.
void addBalance(Expression _account, Expression _value);
SymbolicState& state() { return m_state; }
private:
/// Symbolic expressions.
//{@
/// Symbolic variables.
@ -164,11 +152,8 @@ private:
/// variables and functions.
std::unordered_map<std::string, std::shared_ptr<smt::SymbolicVariable>> m_globalContext;
/// Symbolic `this` address.
std::unique_ptr<SymbolicAddressVariable> m_thisAddress;
/// Symbolic balances.
std::unique_ptr<SymbolicVariable> m_balances;
/// Symbolic representation of the blockchain state.
SymbolicState m_state;
//@}
/// Solver related.

View File

@ -19,6 +19,7 @@
#include <libsolidity/ast/TypeProvider.h>
#include <libsolidity/formal/SMTPortfolio.h>
#include <libsolidity/formal/SymbolicState.h>
#include <libsolidity/formal/SymbolicTypes.h>
#include <boost/range/adaptors.hpp>
@ -619,10 +620,10 @@ void SMTEncoder::endVisit(FunctionCall const& _funCall)
auto const& value = args.front();
solAssert(value, "");
smt::Expression thisBalance = m_context.balance();
smt::Expression thisBalance = m_context.state().balance();
setSymbolicUnknownValue(thisBalance, TypeProvider::uint256(), m_context);
m_context.transfer(m_context.thisAddress(), expr(address), expr(*value));
m_context.state().transfer(m_context.state().thisAddress(), expr(address), expr(*value));
break;
}
default:
@ -711,7 +712,7 @@ void SMTEncoder::endVisit(Identifier const& _identifier)
defineGlobalVariable(_identifier.name(), _identifier);
else if (_identifier.name() == "this")
{
defineExpr(_identifier, m_context.thisAddress());
defineExpr(_identifier, m_context.state().thisAddress());
m_uninterpretedTerms.insert(&_identifier);
}
else
@ -858,7 +859,7 @@ bool SMTEncoder::visit(MemberAccess const& _memberAccess)
_memberAccess.expression().accept(*this);
if (_memberAccess.memberName() == "balance")
{
defineExpr(_memberAccess, m_context.balance(expr(_memberAccess.expression())));
defineExpr(_memberAccess, m_context.state().balance(expr(_memberAccess.expression())));
setSymbolicUnknownValue(*m_context.expression(_memberAccess), m_context);
m_uninterpretedTerms.insert(&_memberAccess);
return false;

View File

@ -0,0 +1,82 @@
/*
This file is part of solidity.
solidity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
solidity is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libsolidity/formal/SymbolicState.h>
#include <libsolidity/formal/EncodingContext.h>
using namespace std;
using namespace solidity::frontend::smt;
SymbolicState::SymbolicState(EncodingContext& _context):
m_context(_context)
{
}
void SymbolicState::reset()
{
m_thisAddress.resetIndex();
m_balances.resetIndex();
}
// Blockchain
Expression SymbolicState::thisAddress()
{
return m_thisAddress.currentValue();
}
Expression SymbolicState::balance()
{
return balance(m_thisAddress.currentValue());
}
Expression SymbolicState::balance(Expression _address)
{
return Expression::select(m_balances.currentValue(), move(_address));
}
void SymbolicState::transfer(Expression _from, Expression _to, Expression _value)
{
unsigned indexBefore = m_balances.index();
addBalance(_from, 0 - _value);
addBalance(_to, move(_value));
unsigned indexAfter = m_balances.index();
solAssert(indexAfter > indexBefore, "");
m_balances.increaseIndex();
/// Do not apply the transfer operation if _from == _to.
auto newBalances = Expression::ite(
move(_from) == move(_to),
m_balances.valueAtIndex(indexBefore),
m_balances.valueAtIndex(indexAfter)
);
m_context.addAssertion(m_balances.currentValue() == newBalances);
}
/// Private helpers.
void SymbolicState::addBalance(Expression _address, Expression _value)
{
auto newBalances = Expression::store(
m_balances.currentValue(),
_address,
balance(_address) + move(_value)
);
m_balances.increaseIndex();
m_context.addAssertion(newBalances == m_balances.currentValue());
}

View File

@ -0,0 +1,71 @@
/*
This file is part of solidity.
solidity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
solidity is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <libsolidity/formal/Sorts.h>
#include <libsolidity/formal/SolverInterface.h>
#include <libsolidity/formal/SymbolicVariables.h>
namespace solidity::frontend::smt
{
class EncodingContext;
/**
* Symbolic representation of the blockchain state.
*/
class SymbolicState
{
public:
SymbolicState(EncodingContext& _context);
void reset();
/// Blockchain.
//@{
/// Value of `this` address.
Expression thisAddress();
/// @returns the symbolic balance of address `this`.
Expression balance();
/// @returns the symbolic balance of an address.
Expression balance(Expression _address);
/// Transfer _value from _from to _to.
void transfer(Expression _from, Expression _to, Expression _value);
//@}
private:
/// Adds _value to _account's balance.
void addBalance(Expression _account, Expression _value);
EncodingContext& m_context;
/// Symbolic `this` address.
SymbolicAddressVariable m_thisAddress{
"this",
m_context
};
/// Symbolic balances.
SymbolicArrayVariable m_balances{
std::make_shared<ArraySort>(SortProvider::intSort, SortProvider::intSort),
"balances",
m_context
};
};
}

View File

@ -200,7 +200,7 @@ bool isArtifactRequested(Json::Value const& _outputSelection, string const& _fil
/// for Contract-level targets try both contract name and wildcard
vector<string> contracts{ _contract };
if (!_contract.empty())
contracts.push_back("*");
contracts.emplace_back("*");
for (auto const& contract: contracts)
if (
_outputSelection[file].isMember(contract) &&

View File

@ -695,7 +695,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
);
bool isIndexed = false;
VariableDeclaration::Constantness constantness = VariableDeclaration::Constantness::Mutable;
VariableDeclaration::Mutability mutability = VariableDeclaration::Mutability::Mutable;
ASTPointer<OverrideSpecifier> overrides = nullptr;
Visibility visibility(Visibility::Default);
VariableDeclaration::Location location = VariableDeclaration::Location::Unspecified;
@ -732,15 +732,15 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
isIndexed = true;
else if (token == Token::Constant || token == Token::Immutable)
{
if (constantness != VariableDeclaration::Constantness::Mutable)
if (mutability != VariableDeclaration::Mutability::Mutable)
parserError(
string("Constantness already set to ") +
(constantness == VariableDeclaration::Constantness::Constant ? "\"constant\"" : "\"immutable\"")
string("Mutability already set to ") +
(mutability == VariableDeclaration::Mutability::Constant ? "\"constant\"" : "\"immutable\"")
);
else if (token == Token::Constant)
constantness = VariableDeclaration::Constantness::Constant;
mutability = VariableDeclaration::Mutability::Constant;
else if (token == Token::Immutable)
constantness = VariableDeclaration::Constantness::Immutable;
mutability = VariableDeclaration::Mutability::Immutable;
}
else if (_options.allowLocationSpecifier && TokenTraits::isLocationSpecifier(token))
{
@ -800,7 +800,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
visibility,
_options.isStateVariable,
isIndexed,
constantness,
mutability,
overrides,
location
);

View File

@ -38,7 +38,7 @@
/// Operators need to stay in the global namespace.
/// Concatenate the contents of a container onto a vector
template <class T, class U> std::vector<T>& operator+=(std::vector<T>& _a, U const& _b)
template <class T, class U> std::vector<T>& operator+=(std::vector<T>& _a, U& _b)
{
for (auto const& i: _b)
_a.push_back(i);
@ -51,7 +51,7 @@ template <class T, class U> std::vector<T>& operator+=(std::vector<T>& _a, U&& _
return _a;
}
/// Concatenate the contents of a container onto a multiset
template <class U, class... T> std::multiset<T...>& operator+=(std::multiset<T...>& _a, U const& _b)
template <class U, class... T> std::multiset<T...>& operator+=(std::multiset<T...>& _a, U& _b)
{
_a.insert(_b.begin(), _b.end());
return _a;
@ -64,7 +64,7 @@ template <class U, class... T> std::multiset<T...>& operator+=(std::multiset<T..
return _a;
}
/// Concatenate the contents of a container onto a set
template <class U, class... T> std::set<T...>& operator+=(std::set<T...>& _a, U const& _b)
template <class U, class... T> std::set<T...>& operator+=(std::set<T...>& _a, U& _b)
{
_a.insert(_b.begin(), _b.end());
return _a;

View File

@ -38,7 +38,7 @@ class EVMAssembly: public AbstractAssembly
{
public:
explicit EVMAssembly(bool _evm15 = false): m_evm15(_evm15) { }
virtual ~EVMAssembly() = default;
~EVMAssembly() override = default;
/// Set a new source location valid starting from the next instruction.
void setSourceLocation(langutil::SourceLocation const& _location) override;

View File

@ -92,10 +92,10 @@ public:
{}
public:
void operator()(Identifier const& _identifier);
void operator()(FunctionDefinition const&);
void operator()(ForLoop const&);
void operator()(Block const& _block);
void operator()(Identifier const& _identifier) override;
void operator()(FunctionDefinition const&) override;
void operator()(ForLoop const&) override;
void operator()(Block const& _block) override;
private:
void increaseRefIfFound(YulString _variableName);

View File

@ -45,7 +45,7 @@ class NoOutputAssembly: public AbstractAssembly
{
public:
explicit NoOutputAssembly(bool _evm15 = false): m_evm15(_evm15) { }
virtual ~NoOutputAssembly() = default;
~NoOutputAssembly() override = default;
void setSourceLocation(langutil::SourceLocation const&) override {}
int stackHeight() const override { return m_stackHeight; }

View File

@ -104,7 +104,7 @@ void WordSizeTransform::operator()(Block& _block)
auto newLhs = generateU64IdentifierNames(varDecl.variables[0].name);
vector<Statement> ret;
for (int i = 0; i < 3; i++)
ret.push_back(VariableDeclaration{
ret.emplace_back(VariableDeclaration{
varDecl.location,
{TypedName{varDecl.location, newLhs[i], m_targetDialect.defaultType}},
make_unique<Expression>(Literal{
@ -114,7 +114,7 @@ void WordSizeTransform::operator()(Block& _block)
m_targetDialect.defaultType
})
});
ret.push_back(VariableDeclaration{
ret.emplace_back(VariableDeclaration{
varDecl.location,
{TypedName{varDecl.location, newLhs[3], m_targetDialect.defaultType}},
std::move(varDecl.value)
@ -135,8 +135,7 @@ void WordSizeTransform::operator()(Block& _block)
auto newLhs = generateU64IdentifierNames(varDecl.variables[0].name);
vector<Statement> ret;
for (int i = 0; i < 4; i++)
ret.push_back(
VariableDeclaration{
ret.emplace_back(VariableDeclaration{
varDecl.location,
{TypedName{varDecl.location, newLhs[i], m_targetDialect.defaultType}},
std::move(newRhs[i])
@ -165,7 +164,7 @@ void WordSizeTransform::operator()(Block& _block)
auto newLhs = generateU64IdentifierNames(assignment.variableNames[0].name);
vector<Statement> ret;
for (int i = 0; i < 3; i++)
ret.push_back(Assignment{
ret.emplace_back(Assignment{
assignment.location,
{Identifier{assignment.location, newLhs[i]}},
make_unique<Expression>(Literal{
@ -175,7 +174,7 @@ void WordSizeTransform::operator()(Block& _block)
m_targetDialect.defaultType
})
});
ret.push_back(Assignment{
ret.emplace_back(Assignment{
assignment.location,
{Identifier{assignment.location, newLhs[3]}},
std::move(assignment.value)
@ -196,8 +195,7 @@ void WordSizeTransform::operator()(Block& _block)
YulString lhsName = assignment.variableNames[0].name;
vector<Statement> ret;
for (int i = 0; i < 4; i++)
ret.push_back(
Assignment{
ret.emplace_back(Assignment{
assignment.location,
{Identifier{assignment.location, m_variableMapping.at(lhsName)[i]}},
std::move(newRhs[i])

View File

@ -65,7 +65,7 @@ public:
class ASTCopier: public ExpressionCopier, public StatementCopier
{
public:
virtual ~ASTCopier() = default;
~ASTCopier() override = default;
Expression operator()(Literal const& _literal) override;
Expression operator()(Identifier const& _identifier) override;
Expression operator()(FunctionCall const&) override;

View File

@ -46,7 +46,7 @@ public:
static void run(OptimiserStepContext&, Block& _ast);
using ASTModifier::operator();
virtual void visit(Expression& _expression);
void visit(Expression& _expression) override;
private:
explicit ExpressionSimplifier(Dialect const& _dialect): DataFlowAnalyzer(_dialect) {}

View File

@ -42,7 +42,7 @@ public:
static void run(OptimiserStepContext&, Block& _ast) { FunctionHoister{}(_ast); }
using ASTModifier::operator();
virtual void operator()(Block& _block);
void operator()(Block& _block) override;
private:
FunctionHoister() = default;

View File

@ -36,9 +36,9 @@ void NameCollector::operator()(VariableDeclaration const& _varDecl)
void NameCollector::operator ()(FunctionDefinition const& _funDef)
{
m_names.emplace(_funDef.name);
for (auto const arg: _funDef.parameters)
for (auto const& arg: _funDef.parameters)
m_names.emplace(arg.name);
for (auto const ret: _funDef.returnVariables)
for (auto const& ret: _funDef.returnVariables)
m_names.emplace(ret.name);
ASTWalker::operator ()(_funDef);
}

View File

@ -61,8 +61,8 @@ public:
{}
using ASTWalker::operator ();
virtual void operator()(Identifier const& _identifier);
virtual void operator()(FunctionCall const& _funCall);
void operator()(Identifier const& _identifier) override;
void operator()(FunctionCall const& _funCall) override;
static std::map<YulString, size_t> countReferences(Block const& _block, CountWhat _countWhat = VariablesAndFunctions);
static std::map<YulString, size_t> countReferences(FunctionDefinition const& _function, CountWhat _countWhat = VariablesAndFunctions);

View File

@ -104,7 +104,7 @@ public:
static bool containsMSize(Dialect const& _dialect, Block const& _ast);
using ASTWalker::operator();
void operator()(FunctionCall const& _funCall);
void operator()(FunctionCall const& _funCall) override;
private:
MSizeFinder(Dialect const& _dialect): m_dialect(_dialect) {}
@ -129,7 +129,7 @@ public:
}
using ASTWalker::operator();
void operator()(Leave const&) { m_leaveFound = true; }
void operator()(Leave const&) override { m_leaveFound = true; }
private:
LeaveFinder() = default;

View File

@ -50,12 +50,12 @@ public:
ASTWalker::operator()(_funDef);
auto& funType = functionTypes[_funDef.name];
for (auto const arg: _funDef.parameters)
for (auto const& arg: _funDef.parameters)
{
funType.parameters.emplace_back(arg.type);
variableTypes[arg.name] = arg.type;
}
for (auto const ret: _funDef.returnVariables)
for (auto const& ret: _funDef.returnVariables)
{
funType.returns.emplace_back(ret.type);
variableTypes[ret.name] = ret.type;

View File

@ -4,7 +4,7 @@
# first exporting a .sol file to JSON, then loading it into the compiler
# and exporting it again. The second JSON should be identical to the first
REPO_ROOT=$(realpath "$(dirname "$0")"/..)
REPO_ROOT=$(readlink -f "$(dirname "$0")"/..)
SOLIDITY_BUILD_DIR=${SOLIDITY_BUILD_DIR:-build}
SOLC=${REPO_ROOT}/${SOLIDITY_BUILD_DIR}/solc/solc
SPLITSOURCES=${REPO_ROOT}/scripts/splitSources.py

View File

@ -160,6 +160,7 @@ JSON AST:
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "",
"overrides": null,
"scope": 17,

View File

@ -31,6 +31,7 @@
"constant": false,
"functionSelector": "97682884",
"id": 4,
"mutability": "mutable",
"name": "m",
"nodeType": "VariableDeclaration",
"overrides": null,
@ -100,6 +101,7 @@
{
"constant": false,
"id": 12,
"mutability": "mutable",
"name": "a",
"nodeType": "VariableDeclaration",
"overrides": null,
@ -241,6 +243,7 @@
{
"constant": false,
"id": 22,
"mutability": "mutable",
"name": "c",
"nodeType": "VariableDeclaration",
"overrides": null,
@ -507,6 +510,7 @@
{
"constant": false,
"id": 6,
"mutability": "mutable",
"name": "arg",
"nodeType": "VariableDeclaration",
"overrides": null,
@ -547,6 +551,7 @@
{
"constant": false,
"id": 9,
"mutability": "mutable",
"name": "r",
"nodeType": "VariableDeclaration",
"overrides": null,

View File

@ -41,6 +41,7 @@
{
"constant": false,
"functionSelector": "97682884",
"mutability": "mutable",
"name": "m",
"overrides": null,
"scope": 39,
@ -118,6 +119,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "arg",
"overrides": null,
"scope": 38,
@ -157,6 +159,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "r",
"overrides": null,
"scope": 38,
@ -206,6 +209,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "a",
"overrides": null,
"scope": 37,
@ -359,6 +363,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "c",
"overrides": null,
"scope": 37,

View File

@ -30,6 +30,7 @@
{
"constant": false,
"id": 3,
"mutability": "mutable",
"name": "i",
"nodeType": "VariableDeclaration",
"overrides": null,

View File

@ -40,6 +40,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "i",
"overrides": null,
"scope": 4,

View File

@ -121,6 +121,7 @@
{
"constant": false,
"id": 3,
"mutability": "mutable",
"name": "x",
"nodeType": "VariableDeclaration",
"overrides": null,

View File

@ -77,6 +77,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "x",
"overrides": null,
"scope": 7,

View File

@ -35,6 +35,7 @@
{
"constant": false,
"id": 2,
"mutability": "mutable",
"name": "x",
"nodeType": "VariableDeclaration",
"overrides": null,
@ -72,6 +73,7 @@
{
"constant": false,
"id": 5,
"mutability": "mutable",
"name": "s",
"nodeType": "VariableDeclaration",
"overrides": null,

View File

@ -50,6 +50,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "x",
"overrides": null,
"scope": 3,
@ -85,6 +86,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "s",
"overrides": null,
"scope": 11,

View File

@ -45,6 +45,7 @@
{
"constant": false,
"id": 4,
"mutability": "mutable",
"name": "x",
"nodeType": "VariableDeclaration",
"overrides": null,

View File

@ -101,6 +101,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "x",
"overrides": null,
"scope": 7,

View File

@ -53,6 +53,7 @@
{
"constant": false,
"id": 6,
"mutability": "mutable",
"name": "x",
"nodeType": "VariableDeclaration",
"overrides": null,
@ -85,6 +86,7 @@
{
"constant": false,
"id": 3,
"mutability": "mutable",
"name": "",
"nodeType": "VariableDeclaration",
"overrides": null,
@ -139,6 +141,7 @@
{
"constant": false,
"id": 13,
"mutability": "mutable",
"name": "",
"nodeType": "VariableDeclaration",
"overrides": null,
@ -171,6 +174,7 @@
{
"constant": false,
"id": 10,
"mutability": "mutable",
"name": "",
"nodeType": "VariableDeclaration",
"overrides": null,

View File

@ -64,6 +64,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "x",
"overrides": null,
"scope": 16,
@ -104,6 +105,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "",
"overrides": null,
"scope": 5,
@ -157,6 +159,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "",
"overrides": null,
"scope": 16,
@ -197,6 +200,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "",
"overrides": null,
"scope": 12,

View File

@ -19,6 +19,7 @@
{
"constant": false,
"id": 2,
"mutability": "mutable",
"name": "a",
"nodeType": "VariableDeclaration",
"overrides": null,

View File

@ -26,6 +26,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "a",
"overrides": null,
"scope": 3,

View File

@ -45,6 +45,7 @@
{
"constant": false,
"id": 4,
"mutability": "mutable",
"name": "a",
"nodeType": "VariableDeclaration",
"overrides": null,

View File

@ -100,6 +100,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "a",
"overrides": null,
"scope": 9,

View File

@ -30,6 +30,7 @@
{
"constant": false,
"id": 3,
"mutability": "mutable",
"name": "a",
"nodeType": "VariableDeclaration",
"overrides": null,
@ -87,6 +88,7 @@
{
"constant": false,
"id": 10,
"mutability": "mutable",
"name": "b",
"nodeType": "VariableDeclaration",
"overrides": null,

View File

@ -40,6 +40,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "a",
"overrides": null,
"scope": 15,
@ -143,6 +144,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "b",
"overrides": null,
"scope": 13,

View File

@ -58,6 +58,7 @@
{
"constant": false,
"id": 8,
"mutability": "mutable",
"name": "a",
"nodeType": "VariableDeclaration",
"overrides": null,
@ -113,6 +114,7 @@
{
"constant": false,
"id": 12,
"mutability": "mutable",
"name": "b",
"nodeType": "VariableDeclaration",
"overrides": null,
@ -166,6 +168,7 @@
{
"constant": false,
"id": 16,
"mutability": "mutable",
"name": "c",
"nodeType": "VariableDeclaration",
"overrides": null,

View File

@ -80,6 +80,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "a",
"overrides": null,
"scope": 17,
@ -134,6 +135,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "b",
"overrides": null,
"scope": 17,
@ -186,6 +188,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "c",
"overrides": null,
"scope": 17,

View File

@ -56,6 +56,7 @@
{
"constant": false,
"id": 2,
"mutability": "mutable",
"name": "i",
"nodeType": "VariableDeclaration",
"overrides": null,

View File

@ -54,6 +54,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "i",
"overrides": null,
"scope": 6,

View File

@ -56,6 +56,7 @@
{
"constant": false,
"id": 2,
"mutability": "mutable",
"name": "i",
"nodeType": "VariableDeclaration",
"overrides": null,

View File

@ -54,6 +54,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "i",
"overrides": null,
"scope": 6,

View File

@ -0,0 +1,189 @@
{
"absolutePath": "a",
"exportedSymbols":
{
"C":
[
10
]
},
"id": 11,
"nodeType": "SourceUnit",
"nodes":
[
{
"abstract": false,
"baseContracts": [],
"contractDependencies": [],
"contractKind": "contract",
"documentation": null,
"fullyImplemented": true,
"id": 10,
"linearizedBaseContracts":
[
10
],
"name": "C",
"nodeType": "ContractDefinition",
"nodes":
[
{
"constant": false,
"functionSelector": "0dbe671f",
"id": 3,
"mutability": "immutable",
"name": "a",
"nodeType": "VariableDeclaration",
"overrides": null,
"scope": 10,
"src": "17:27:1",
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName":
{
"id": 1,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "17:4:1",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"value":
{
"argumentTypes": null,
"hexValue": "34",
"id": 2,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "43:1:1",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_4_by_1",
"typeString": "int_const 4"
},
"value": "4"
},
"visibility": "public"
},
{
"constant": true,
"functionSelector": "4df7e3d0",
"id": 6,
"mutability": "constant",
"name": "b",
"nodeType": "VariableDeclaration",
"overrides": null,
"scope": 10,
"src": "50:26:1",
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName":
{
"id": 4,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "50:4:1",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"value":
{
"argumentTypes": null,
"hexValue": "32",
"id": 5,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "75:1:1",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_2_by_1",
"typeString": "int_const 2"
},
"value": "2"
},
"visibility": "public"
},
{
"constant": false,
"functionSelector": "c3da42b8",
"id": 9,
"mutability": "mutable",
"name": "c",
"nodeType": "VariableDeclaration",
"overrides": null,
"scope": 10,
"src": "82:17:1",
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
},
"typeName":
{
"id": 7,
"name": "uint",
"nodeType": "ElementaryTypeName",
"src": "82:4:1",
"typeDescriptions":
{
"typeIdentifier": "t_uint256",
"typeString": "uint256"
}
},
"value":
{
"argumentTypes": null,
"hexValue": "33",
"id": 8,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "98:1:1",
"subdenomination": null,
"typeDescriptions":
{
"typeIdentifier": "t_rational_3_by_1",
"typeString": "int_const 3"
},
"value": "3"
},
"visibility": "public"
}
],
"scope": 11,
"src": "0:102:1"
}
],
"src": "0:103:1"
}

View File

@ -0,0 +1,8 @@
contract C
{
uint public immutable a = 4;
uint public constant b = 2;
uint public c = 3;
}
// ----

View File

@ -0,0 +1,195 @@
{
"attributes":
{
"absolutePath": "a",
"exportedSymbols":
{
"C":
[
10
]
}
},
"children":
[
{
"attributes":
{
"abstract": false,
"baseContracts":
[
null
],
"contractDependencies":
[
null
],
"contractKind": "contract",
"documentation": null,
"fullyImplemented": true,
"linearizedBaseContracts":
[
10
],
"name": "C",
"scope": 11
},
"children":
[
{
"attributes":
{
"constant": false,
"functionSelector": "0dbe671f",
"mutability": "immutable",
"name": "a",
"overrides": null,
"scope": 10,
"stateVariable": true,
"storageLocation": "default",
"type": "uint256",
"visibility": "public"
},
"children":
[
{
"attributes":
{
"name": "uint",
"type": "uint256"
},
"id": 1,
"name": "ElementaryTypeName",
"src": "17:4:1"
},
{
"attributes":
{
"argumentTypes": null,
"hexvalue": "34",
"isConstant": false,
"isLValue": false,
"isPure": true,
"lValueRequested": false,
"subdenomination": null,
"token": "number",
"type": "int_const 4",
"value": "4"
},
"id": 2,
"name": "Literal",
"src": "43:1:1"
}
],
"id": 3,
"name": "VariableDeclaration",
"src": "17:27:1"
},
{
"attributes":
{
"constant": true,
"functionSelector": "4df7e3d0",
"mutability": "constant",
"name": "b",
"overrides": null,
"scope": 10,
"stateVariable": true,
"storageLocation": "default",
"type": "uint256",
"visibility": "public"
},
"children":
[
{
"attributes":
{
"name": "uint",
"type": "uint256"
},
"id": 4,
"name": "ElementaryTypeName",
"src": "50:4:1"
},
{
"attributes":
{
"argumentTypes": null,
"hexvalue": "32",
"isConstant": false,
"isLValue": false,
"isPure": true,
"lValueRequested": false,
"subdenomination": null,
"token": "number",
"type": "int_const 2",
"value": "2"
},
"id": 5,
"name": "Literal",
"src": "75:1:1"
}
],
"id": 6,
"name": "VariableDeclaration",
"src": "50:26:1"
},
{
"attributes":
{
"constant": false,
"functionSelector": "c3da42b8",
"mutability": "mutable",
"name": "c",
"overrides": null,
"scope": 10,
"stateVariable": true,
"storageLocation": "default",
"type": "uint256",
"visibility": "public"
},
"children":
[
{
"attributes":
{
"name": "uint",
"type": "uint256"
},
"id": 7,
"name": "ElementaryTypeName",
"src": "82:4:1"
},
{
"attributes":
{
"argumentTypes": null,
"hexvalue": "33",
"isConstant": false,
"isLValue": false,
"isPure": true,
"lValueRequested": false,
"subdenomination": null,
"token": "number",
"type": "int_const 3",
"value": "3"
},
"id": 8,
"name": "Literal",
"src": "98:1:1"
}
],
"id": 9,
"name": "VariableDeclaration",
"src": "82:17:1"
}
],
"id": 10,
"name": "ContractDefinition",
"src": "0:102:1"
}
],
"id": 11,
"name": "SourceUnit",
"src": "0:103:1"
}

View File

@ -45,6 +45,7 @@
{
"constant": false,
"id": 3,
"mutability": "mutable",
"name": "x",
"nodeType": "VariableDeclaration",
"overrides": null,

View File

@ -100,6 +100,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "x",
"overrides": null,
"scope": 6,

View File

@ -45,6 +45,7 @@
{
"constant": false,
"id": 7,
"mutability": "mutable",
"name": "x",
"nodeType": "VariableDeclaration",
"overrides": null,

View File

@ -101,6 +101,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "x",
"overrides": null,
"scope": 9,

View File

@ -45,6 +45,7 @@
{
"constant": false,
"id": 8,
"mutability": "mutable",
"name": "rows",
"nodeType": "VariableDeclaration",
"overrides": null,

View File

@ -101,6 +101,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "rows",
"overrides": null,
"scope": 10,

View File

@ -45,6 +45,7 @@
{
"constant": false,
"id": 3,
"mutability": "mutable",
"name": "x",
"nodeType": "VariableDeclaration",
"overrides": null,

View File

@ -100,6 +100,7 @@
"attributes":
{
"constant": false,
"mutability": "mutable",
"name": "x",
"overrides": null,
"scope": 9,

View File

@ -34,14 +34,14 @@ namespace solidity::frontend::test
class SMTCheckerFramework: public AnalysisFramework
{
protected:
virtual std::pair<SourceUnit const*, ErrorList>
std::pair<SourceUnit const*, ErrorList>
parseAnalyseAndReturnError(
std::string const& _source,
bool _reportWarnings = false,
bool _insertVersionPragma = true,
bool _allowMultipleErrors = false,
bool _allowRecoveryErrors = false
)
) override
{
return AnalysisFramework::parseAnalyseAndReturnError(
"pragma experimental SMTChecker;\n" + _source,

View File

@ -46,7 +46,7 @@ public:
ExecutionFramework(_evmVersion), m_showMetadata(solidity::test::CommonOptions::get().showMetadata)
{}
virtual bytes const& compileAndRunWithoutCheck(
bytes const& compileAndRunWithoutCheck(
std::string const& _sourceCode,
u256 const& _value = 0,
std::string const& _contractName = "",

View File

@ -52,15 +52,15 @@ public:
FirstExpressionExtractor(ASTNode& _node): m_expression(nullptr) { _node.accept(*this); }
Expression* expression() const { return m_expression; }
private:
virtual bool visit(Assignment& _expression) override { return checkExpression(_expression); }
virtual bool visit(UnaryOperation& _expression) override { return checkExpression(_expression); }
virtual bool visit(BinaryOperation& _expression) override { return checkExpression(_expression); }
virtual bool visit(FunctionCall& _expression) override { return checkExpression(_expression); }
virtual bool visit(MemberAccess& _expression) override { return checkExpression(_expression); }
virtual bool visit(IndexAccess& _expression) override { return checkExpression(_expression); }
virtual bool visit(Identifier& _expression) override { return checkExpression(_expression); }
virtual bool visit(ElementaryTypeNameExpression& _expression) override { return checkExpression(_expression); }
virtual bool visit(Literal& _expression) override { return checkExpression(_expression); }
bool visit(Assignment& _expression) override { return checkExpression(_expression); }
bool visit(UnaryOperation& _expression) override { return checkExpression(_expression); }
bool visit(BinaryOperation& _expression) override { return checkExpression(_expression); }
bool visit(FunctionCall& _expression) override { return checkExpression(_expression); }
bool visit(MemberAccess& _expression) override { return checkExpression(_expression); }
bool visit(IndexAccess& _expression) override { return checkExpression(_expression); }
bool visit(Identifier& _expression) override { return checkExpression(_expression); }
bool visit(ElementaryTypeNameExpression& _expression) override { return checkExpression(_expression); }
bool visit(Literal& _expression) override { return checkExpression(_expression); }
bool checkExpression(Expression& _expression)
{
if (m_expression == nullptr)

View File

@ -672,7 +672,7 @@ BOOST_AUTO_TEST_CASE(inline_asm_end_location)
{
public:
bool visited = false;
virtual bool visit(InlineAssembly const& _inlineAsm)
bool visit(InlineAssembly const& _inlineAsm) override
{
auto loc = _inlineAsm.location();
auto asmStr = loc.source->source().substr(loc.start, loc.end - loc.start);

View File

@ -0,0 +1,17 @@
contract test {
function f3() public returns(int) {
int a = 3;
((, ), ) = ((7, 8), 9);
return a;
}
function f4() public returns(int) {
int a;
(a, ) = (4, (8, 16, 32));
return a;
}
}
// ====
// compileViaYul: false
// ----
// f3() -> 3
// f4() -> 4

View File

@ -0,0 +1,13 @@
contract C {
function f() public pure returns (uint, uint, uint) {
bytes memory a; bytes memory b; bytes memory c;
(a, (b, c)) = ("0", ("1", "2"));
return (uint8(a[0]), uint8(b[0]), uint8(c[0]));
}
}
// ====
// compileViaYul: also
// ----
// f() -> 0x30, 0x31, 0x32

View File

@ -0,0 +1,20 @@
pragma experimental SMTChecker;
contract C {
function c() public pure returns (uint) { return 42; }
}
contract B is C {
function b() public pure returns (uint) { return c(); }
}
contract A is B {
uint public x;
function a() public {
x = b();
assert(x < 40);
}
}
// ----
// Warning: (254-268): Assertion violation happens here

View File

@ -0,0 +1,24 @@
pragma experimental SMTChecker;
contract C {
uint y;
function c(uint _y) public returns (uint) {
y = _y;
return y;
}
}
contract B is C {
function b() public returns (uint) { return c(42); }
}
contract A is B {
uint public x;
function a() public {
x = b();
assert(x < 40);
}
}
// ----
// Warning: (274-288): Assertion violation happens here

View File

@ -3,5 +3,5 @@ contract C {
uint immutable constant x;
}
// ----
// ParserError: (32-41): Constantness already set to "immutable"
// ParserError: (64-72): Constantness already set to "immutable"
// ParserError: (32-41): Mutability already set to "immutable"
// ParserError: (64-72): Mutability already set to "immutable"

View File

@ -0,0 +1,11 @@
contract C {
function f() public payable {
abi.encode(this.f{value: 2});
abi.encode(this.f{gas: 2});
abi.encode(this.f{value: 2, gas: 1});
}
}
// ----
// TypeError: (60-76): This type cannot be encoded.
// TypeError: (92-106): This type cannot be encoded.
// TypeError: (122-146): This type cannot be encoded.

View File

@ -1,12 +1,11 @@
contract C {
function f() public pure {
bytes32 h = keccak256(abi.encodePacked(keccak256, f, this.f.gas, blockhash));
bytes32 h = keccak256(abi.encodePacked(keccak256, f, this.f{gas: 2}, blockhash));
h;
}
}
// ----
// Warning: (105-115): Using ".gas(...)" is deprecated. Use "{gas: ...}" instead.
// TypeError: (91-100): This type cannot be encoded.
// TypeError: (102-103): This type cannot be encoded.
// TypeError: (105-115): This type cannot be encoded.
// TypeError: (117-126): This type cannot be encoded.
// TypeError: (105-119): This type cannot be encoded.
// TypeError: (121-130): This type cannot be encoded.

View File

@ -76,13 +76,13 @@ BOOST_AUTO_TEST_CASE(test_alternatives_list)
{
vector<string> strings;
BOOST_CHECK_EQUAL(quotedAlternativesList(strings), "");
strings.push_back("a");
strings.emplace_back("a");
BOOST_CHECK_EQUAL(quotedAlternativesList(strings), "\"a\"");
strings.push_back("b");
strings.emplace_back("b");
BOOST_CHECK_EQUAL(quotedAlternativesList(strings), "\"a\" or \"b\"");
strings.push_back("c");
strings.emplace_back("c");
BOOST_CHECK_EQUAL(quotedAlternativesList(strings), "\"a\", \"b\" or \"c\"");
strings.push_back("d");
strings.emplace_back("d");
BOOST_CHECK_EQUAL(quotedAlternativesList(strings), "\"a\", \"b\", \"c\" or \"d\"");
}

View File

@ -47,15 +47,15 @@ string toString(SideEffects const& _sideEffects)
{
vector<string> ret;
if (_sideEffects.movable)
ret.push_back("movable");
ret.emplace_back("movable");
if (_sideEffects.sideEffectFree)
ret.push_back("sideEffectFree");
ret.emplace_back("sideEffectFree");
if (_sideEffects.sideEffectFreeIfNoMSize)
ret.push_back("sideEffectFreeIfNoMSize");
ret.emplace_back("sideEffectFreeIfNoMSize");
if (_sideEffects.invalidatesStorage)
ret.push_back("invalidatesStorage");
ret.emplace_back("invalidatesStorage");
if (_sideEffects.invalidatesMemory)
ret.push_back("invalidatesMemory");
ret.emplace_back("invalidatesMemory");
return joinHumanReadable(ret);
}
}

View File

@ -37,7 +37,7 @@ public:
return std::make_unique<SyntaxTest>(_config.filename, _config.evmVersion);
}
SyntaxTest(std::string const& _filename, langutil::EVMVersion _evmVersion);
virtual ~SyntaxTest() {}
~SyntaxTest() override {}
protected:
void parseAndAnalyze() override;

View File

@ -104,7 +104,7 @@ Allowed options)",
else if (arguments.count("input-files"))
inputs = arguments["input-files"].as<vector<string>>();
else
inputs.push_back("");
inputs.emplace_back("");
bool optimize = !arguments.count("without-optimizer");
int retResult = 0;

View File

@ -308,7 +308,7 @@ pair<
for (auto const& scope: m_scopes)
{
// Copy over all functions.
newScopes.push_back({});
newScopes.emplace_back();
for (auto const& [name, funDef]: scope)
if (funDef)
newScopes.back().emplace(name, funDef);

View File

@ -136,7 +136,7 @@ private:
/// Evaluates the expression and returns its value.
std::vector<u256> evaluateMulti(Expression const& _expression);
void openScope() { m_scopes.push_back({}); }
void openScope() { m_scopes.emplace_back(); }
/// Unregisters variables and functions.
void closeScope();

View File

@ -32,8 +32,7 @@ void ConstructorKeyword::endVisit(ContractDefinition const& _contract)
{
for (auto const* function: _contract.definedFunctions())
if (function->name() == _contract.name())
m_changes.push_back(
UpgradeChange{
m_changes.emplace_back(
UpgradeChange::Level::Safe,
function->location(),
SourceTransform::replaceFunctionName(
@ -41,18 +40,15 @@ void ConstructorKeyword::endVisit(ContractDefinition const& _contract)
function->name(),
"constructor"
)
}
);
}
void VisibilitySpecifier::endVisit(FunctionDefinition const& _function)
{
if (_function.noVisibilitySpecified())
m_changes.push_back(
UpgradeChange{
m_changes.emplace_back(
UpgradeChange::Level::Safe,
_function.location(),
SourceTransform::insertAfterRightParenthesis(_function.location(), "public")
}
);
}

View File

@ -37,7 +37,7 @@ public:
void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); }
private:
void endVisit(frontend::ContractDefinition const& _contract);
void endVisit(frontend::ContractDefinition const& _contract) override;
};
/**
@ -52,7 +52,7 @@ public:
void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); }
private:
void endVisit(frontend::FunctionDefinition const& _function);
void endVisit(frontend::FunctionDefinition const& _function) override;
};
}

View File

@ -106,12 +106,10 @@ void AbstractContract::endVisit(ContractDefinition const& _contract)
!_contract.abstract() &&
!_contract.isInterface()
)
m_changes.push_back(
UpgradeChange{
m_changes.emplace_back(
UpgradeChange::Level::Safe,
_contract.location(),
SourceTransform::insertBeforeKeyword(_contract.location(), "contract", "abstract")
}
);
}
@ -132,12 +130,10 @@ void OverridingFunction::endVisit(ContractDefinition const& _contract)
/// Add override with contract list, if needed.
if (!function->overrides() && expectedContracts.size() > 1)
m_changes.push_back(
UpgradeChange{
m_changes.emplace_back(
UpgradeChange::Level::Safe,
function->location(),
appendOverride(*function, expectedContracts)
}
);
for (auto [begin, end] = inheritedFunctions.equal_range(proxy); begin != end; begin++)
@ -151,12 +147,10 @@ void OverridingFunction::endVisit(ContractDefinition const& _contract)
/// If function does not specify override and no override with
/// contract list was added before.
if (!function->overrides() && expectedContracts.size() <= 1)
m_changes.push_back(
UpgradeChange{
m_changes.emplace_back(
UpgradeChange::Level::Safe,
function->location(),
appendOverride(*function, expectedContracts)
}
);
}
}
@ -181,12 +175,10 @@ void VirtualFunction::endVisit(ContractDefinition const& _contract)
function->visibility() > Visibility::Private
)
{
m_changes.push_back(
UpgradeChange{
m_changes.emplace_back(
UpgradeChange::Level::Safe,
function->location(),
appendVirtual(*function)
}
);
}
@ -198,12 +190,10 @@ void VirtualFunction::endVisit(ContractDefinition const& _contract)
!super.virtualSemantics()
)
{
m_changes.push_back(
UpgradeChange{
m_changes.emplace_back(
UpgradeChange::Level::Safe,
function->location(),
appendVirtual(*function)
}
);
}
}

View File

@ -35,7 +35,7 @@ public:
void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); }
private:
void endVisit(frontend::ContractDefinition const& _contract);
void endVisit(frontend::ContractDefinition const& _contract) override;
};
/**
@ -49,7 +49,7 @@ public:
void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); }
private:
void endVisit(frontend::ContractDefinition const& _contract);
void endVisit(frontend::ContractDefinition const& _contract) override;
};
/**
@ -63,7 +63,7 @@ public:
void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); }
private:
void endVisit(frontend::ContractDefinition const& _function);
void endVisit(frontend::ContractDefinition const& _function) override;
};
}

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