Merge pull request #7278 from ethereum/develop

Merge develop into develop_060
This commit is contained in:
Mathias L. Baumann 2019-08-26 10:26:48 +02:00 committed by GitHub
commit 502bf01be2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
66 changed files with 985 additions and 493 deletions

View File

@ -47,7 +47,7 @@ usual ``//`` and ``/* */`` comments. There is one exception: Identifiers in inli
these curly braces, you can use the following (see the later sections for more details):
- literals, i.e. ``0x123``, ``42`` or ``"abc"`` (strings up to 32 characters)
- opcodes in functional style, e.g. ``add(1, mlod(0))``
- opcodes in functional style, e.g. ``add(1, mload(0))``
- variable declarations, e.g. ``let x := 7``, ``let x := add(y, 3)`` or ``let x`` (initial value of empty (0) is assigned)
- identifiers (assembly-local variables and externals if used as inline assembly), e.g. ``add(3, x)``, ``sstore(x_slot, 2)``
- assignments, e.g. ``x := add(y, 3)``

View File

@ -124,7 +124,7 @@ Encoding of the Metadata Hash in the Bytecode
=============================================
Because we might support other ways to retrieve the metadata file in the future,
the mapping ``{"bzzr0": <Swarm hash>, "solc": <compiler version>}`` is stored
the mapping ``{"bzzr1": <Swarm hash>, "solc": <compiler version>}`` is stored
`CBOR <https://tools.ietf.org/html/rfc7049>`_-encoded. Since the mapping might
contain more keys (see below) and the beginning of that
encoding is not easy to find, its length is added in a two-byte big-endian
@ -132,7 +132,7 @@ encoding. The current version of the Solidity compiler usually adds the followin
to the end of the deployed bytecode::
0xa2
0x65 'b' 'z' 'z' 'r' '0' 0x58 0x20 <32 bytes swarm hash>
0x65 'b' 'z' 'z' 'r' '1' 0x58 0x20 <32 bytes swarm hash>
0x64 's' 'o' 'l' 'c' 0x43 <3 byte version encoding>
0x00 0x32
@ -150,9 +150,9 @@ will instead use a complete version string including commit hash and build date.
are used, the mapping will also contain ``"experimental": true``.
.. note::
The compiler currently uses the "swarm version 0" hash of the metadata,
The compiler currently uses the "swarm version 1" hash of the metadata,
but this might change in the future, so do not rely on this sequence
to start with ``0xa2 0x65 'b' 'z' 'z' 'r' '0'``. We might also
to start with ``0xa2 0x65 'b' 'z' 'z' 'r' '1'``. We might also
add additional data to this CBOR structure, so the
best option is to use a proper CBOR parser.

View File

@ -27,6 +27,9 @@
#include <libdevcore/UTF8.h>
#include <boost/algorithm/string/join.hpp>
#include <vector>
#include <algorithm>
using namespace std;
using namespace langutil;
@ -259,7 +262,7 @@ bool ASTJsonConverter::visit(ContractDefinition const& _node)
make_pair("fullyImplemented", _node.annotation().unimplementedFunctions.empty()),
make_pair("linearizedBaseContracts", getContainerIds(_node.annotation().linearizedBaseContracts)),
make_pair("baseContracts", toJson(_node.baseContracts())),
make_pair("contractDependencies", getContainerIds(_node.annotation().contractDependencies)),
make_pair("contractDependencies", getContainerIds(_node.annotation().contractDependencies, true)),
make_pair("nodes", toJson(_node.subNodes())),
make_pair("scope", idOrNull(_node.scope()))
});

View File

@ -29,6 +29,8 @@
#include <json/json.h>
#include <ostream>
#include <stack>
#include <vector>
#include <algorithm>
namespace langutil
{
@ -148,15 +150,23 @@ private:
return _node.id();
}
template<class Container>
static Json::Value getContainerIds(Container const& container)
static Json::Value getContainerIds(Container const& _container, bool _order = false)
{
Json::Value tmp(Json::arrayValue);
for (auto const& element: container)
std::vector<int> tmp;
for (auto const& element: _container)
{
solAssert(element, "");
tmp.append(nodeId(*element));
tmp.push_back(nodeId(*element));
}
return tmp;
if (_order)
std::sort(tmp.begin(), tmp.end());
Json::Value json(Json::arrayValue);
for (int val: tmp)
json.append(val);
return json;
}
static Json::Value typePointerToJson(TypePointer _tp, bool _short = false);
static Json::Value typePointerToJson(boost::optional<FuncCallArguments> const& _tps);

View File

@ -26,7 +26,7 @@ parts:
source: .
source-type: git
plugin: cmake
build-packages: [build-essential, libboost-all-dev, libcvc4-dev]
build-packages: [build-essential, libboost-all-dev]
stage-packages: [libicu60]
override-build: |
if git describe --exact-match --tags 2> /dev/null
@ -34,7 +34,7 @@ parts:
echo -n > ../src/prerelease.txt
fi
snapcraftctl build
after: [z3]
after: [z3, cvc4]
z3:
source: https://github.com/Z3Prover/z3.git
source-tag: z3-4.8.4
@ -47,3 +47,16 @@ parts:
cd build
make -j -l $(grep -c "^processor" /proc/cpuinfo)
make install DESTDIR=$SNAPCRAFT_PART_INSTALL
cvc4:
source: https://github.com/CVC4/CVC4.git
source-tag: "1.7"
plugin: nil
build-packages: [python, cmake, openjdk-11-jre, libgmp-dev]
override-build: |
./contrib/get-antlr-3.4
./configure.sh --prefix=$SNAPCRAFT_STAGE/usr
cd build
make -j -l $(grep -c "^processor" /proc/cpuinfo)
make install
mkdir -p $SNAPCRAFT_PART_INSTALL/usr/lib/
cp $SNAPCRAFT_STAGE/usr/lib/libcvc4.so.6 $SNAPCRAFT_PART_INSTALL/usr/lib/

View File

@ -62,11 +62,15 @@ bool TestCase::validateSettings(langutil::EVMVersion)
return true;
}
pair<string, size_t> TestCase::parseSourceAndSettingsWithLineNumbers(istream& _stream)
pair<map<string, string>, size_t> TestCase::parseSourcesAndSettingsWithLineNumbers(istream& _stream)
{
string source;
map<string, string> sources;
string currentSourceName;
string currentSource;
string line;
size_t lineNumber = 1;
static string const sourceDelimiterStart("==== Source:");
static string const sourceDelimiterEnd("====");
static string const comment("// ");
static string const settingsDelimiter("// ====");
static string const delimiter("// ----");
@ -80,7 +84,22 @@ pair<string, size_t> TestCase::parseSourceAndSettingsWithLineNumbers(istream& _s
else if (boost::algorithm::starts_with(line, settingsDelimiter))
sourcePart = false;
else if (sourcePart)
source += line + "\n";
{
if (boost::algorithm::starts_with(line, sourceDelimiterStart) && boost::algorithm::ends_with(line, sourceDelimiterEnd))
{
if (!(currentSourceName.empty() && currentSource.empty()))
sources[currentSourceName] = std::move(currentSource);
currentSource = {};
currentSourceName = boost::trim_copy(line.substr(
sourceDelimiterStart.size(),
line.size() - sourceDelimiterEnd.size() - sourceDelimiterStart.size()
));
if (sources.count(currentSourceName))
throw runtime_error("Multiple definitions of test source \"" + currentSourceName + "\".");
}
else
currentSource += line + "\n";
}
else if (boost::algorithm::starts_with(line, comment))
{
size_t colon = line.find(':');
@ -95,12 +114,26 @@ pair<string, size_t> TestCase::parseSourceAndSettingsWithLineNumbers(istream& _s
else
throw runtime_error(string("Expected \"//\" or \"// ---\" to terminate settings and source."));
}
return make_pair(source, lineNumber);
sources[currentSourceName] = currentSource;
return {sources, lineNumber};
}
map<string, string> TestCase::parseSourcesAndSettings(istream& _stream)
{
return get<0>(parseSourcesAndSettingsWithLineNumbers(_stream));
}
pair<string, size_t> TestCase::parseSourceAndSettingsWithLineNumbers(istream& _stream)
{
auto [sourceMap, lineOffset] = parseSourcesAndSettingsWithLineNumbers(_stream);
if (sourceMap.size() != 1)
BOOST_THROW_EXCEPTION(runtime_error("Expected single source definition, but got multiple sources."));
return {std::move(sourceMap.begin()->second), lineOffset};
}
string TestCase::parseSourceAndSettings(istream& _stream)
{
return get<0>(parseSourceAndSettingsWithLineNumbers(_stream));
return parseSourceAndSettingsWithLineNumbers(_stream).first;
}
string TestCase::parseSimpleExpectations(std::istream& _file)

View File

@ -80,6 +80,8 @@ public:
virtual bool validateSettings(langutil::EVMVersion /*_evmVersion*/);
protected:
std::pair<std::map<std::string, std::string>, std::size_t> parseSourcesAndSettingsWithLineNumbers(std::istream& _file);
std::map<std::string, std::string> parseSourcesAndSettings(std::istream& _file);
std::pair<std::string, std::size_t> parseSourceAndSettingsWithLineNumbers(std::istream& _file);
std::string parseSourceAndSettings(std::istream& _file);
static void expect(std::string::iterator& _it, std::string::iterator _end, std::string::value_type _c);

View File

@ -0,0 +1,233 @@
{
"absolutePath" : "a",
"exportedSymbols" :
{
"A" :
[
1
],
"B" :
[
4
],
"C" :
[
7
],
"D" :
[
10
],
"E" :
[
13
]
},
"id" : 14,
"nodeType" : "SourceUnit",
"nodes" :
[
{
"baseContracts" : [],
"contractDependencies" : [],
"contractKind" : "contract",
"documentation" : null,
"fullyImplemented" : true,
"id" : 1,
"linearizedBaseContracts" :
[
1
],
"name" : "A",
"nodeType" : "ContractDefinition",
"nodes" : [],
"scope" : 14,
"src" : "0:14:1"
},
{
"baseContracts" :
[
{
"arguments" : null,
"baseName" :
{
"contractScope" : null,
"id" : 2,
"name" : "A",
"nodeType" : "UserDefinedTypeName",
"referencedDeclaration" : 1,
"src" : "29:1:1",
"typeDescriptions" :
{
"typeIdentifier" : "t_contract$_A_$1",
"typeString" : "contract A"
}
},
"id" : 3,
"nodeType" : "InheritanceSpecifier",
"src" : "29:1:1"
}
],
"contractDependencies" :
[
1
],
"contractKind" : "contract",
"documentation" : null,
"fullyImplemented" : true,
"id" : 4,
"linearizedBaseContracts" :
[
4,
1
],
"name" : "B",
"nodeType" : "ContractDefinition",
"nodes" : [],
"scope" : 14,
"src" : "15:19:1"
},
{
"baseContracts" :
[
{
"arguments" : null,
"baseName" :
{
"contractScope" : null,
"id" : 5,
"name" : "B",
"nodeType" : "UserDefinedTypeName",
"referencedDeclaration" : 4,
"src" : "49:1:1",
"typeDescriptions" :
{
"typeIdentifier" : "t_contract$_B_$4",
"typeString" : "contract B"
}
},
"id" : 6,
"nodeType" : "InheritanceSpecifier",
"src" : "49:1:1"
}
],
"contractDependencies" :
[
1,
4
],
"contractKind" : "contract",
"documentation" : null,
"fullyImplemented" : true,
"id" : 7,
"linearizedBaseContracts" :
[
7,
4,
1
],
"name" : "C",
"nodeType" : "ContractDefinition",
"nodes" : [],
"scope" : 14,
"src" : "35:19:1"
},
{
"baseContracts" :
[
{
"arguments" : null,
"baseName" :
{
"contractScope" : null,
"id" : 8,
"name" : "C",
"nodeType" : "UserDefinedTypeName",
"referencedDeclaration" : 7,
"src" : "69:1:1",
"typeDescriptions" :
{
"typeIdentifier" : "t_contract$_C_$7",
"typeString" : "contract C"
}
},
"id" : 9,
"nodeType" : "InheritanceSpecifier",
"src" : "69:1:1"
}
],
"contractDependencies" :
[
1,
4,
7
],
"contractKind" : "contract",
"documentation" : null,
"fullyImplemented" : true,
"id" : 10,
"linearizedBaseContracts" :
[
10,
7,
4,
1
],
"name" : "D",
"nodeType" : "ContractDefinition",
"nodes" : [],
"scope" : 14,
"src" : "55:19:1"
},
{
"baseContracts" :
[
{
"arguments" : null,
"baseName" :
{
"contractScope" : null,
"id" : 11,
"name" : "D",
"nodeType" : "UserDefinedTypeName",
"referencedDeclaration" : 10,
"src" : "89:1:1",
"typeDescriptions" :
{
"typeIdentifier" : "t_contract$_D_$10",
"typeString" : "contract D"
}
},
"id" : 12,
"nodeType" : "InheritanceSpecifier",
"src" : "89:1:1"
}
],
"contractDependencies" :
[
1,
4,
7,
10
],
"contractKind" : "contract",
"documentation" : null,
"fullyImplemented" : true,
"id" : 13,
"linearizedBaseContracts" :
[
13,
10,
7,
4,
1
],
"name" : "E",
"nodeType" : "ContractDefinition",
"nodes" : [],
"scope" : 14,
"src" : "75:19:1"
}
],
"src" : "0:95:1"
}

View File

@ -0,0 +1,7 @@
contract A { }
contract B is A { }
contract C is B { }
contract D is C { }
contract E is D { }
// ----

View File

@ -0,0 +1,288 @@
{
"attributes" :
{
"absolutePath" : "a",
"exportedSymbols" :
{
"A" :
[
1
],
"B" :
[
4
],
"C" :
[
7
],
"D" :
[
10
],
"E" :
[
13
]
}
},
"children" :
[
{
"attributes" :
{
"baseContracts" :
[
null
],
"contractDependencies" :
[
null
],
"contractKind" : "contract",
"documentation" : null,
"fullyImplemented" : true,
"linearizedBaseContracts" :
[
1
],
"name" : "A",
"nodes" :
[
null
],
"scope" : 14
},
"id" : 1,
"name" : "ContractDefinition",
"src" : "0:14:1"
},
{
"attributes" :
{
"contractDependencies" :
[
1
],
"contractKind" : "contract",
"documentation" : null,
"fullyImplemented" : true,
"linearizedBaseContracts" :
[
4,
1
],
"name" : "B",
"nodes" :
[
null
],
"scope" : 14
},
"children" :
[
{
"attributes" :
{
"arguments" : null
},
"children" :
[
{
"attributes" :
{
"contractScope" : null,
"name" : "A",
"referencedDeclaration" : 1,
"type" : "contract A"
},
"id" : 2,
"name" : "UserDefinedTypeName",
"src" : "29:1:1"
}
],
"id" : 3,
"name" : "InheritanceSpecifier",
"src" : "29:1:1"
}
],
"id" : 4,
"name" : "ContractDefinition",
"src" : "15:19:1"
},
{
"attributes" :
{
"contractDependencies" :
[
1,
4
],
"contractKind" : "contract",
"documentation" : null,
"fullyImplemented" : true,
"linearizedBaseContracts" :
[
7,
4,
1
],
"name" : "C",
"nodes" :
[
null
],
"scope" : 14
},
"children" :
[
{
"attributes" :
{
"arguments" : null
},
"children" :
[
{
"attributes" :
{
"contractScope" : null,
"name" : "B",
"referencedDeclaration" : 4,
"type" : "contract B"
},
"id" : 5,
"name" : "UserDefinedTypeName",
"src" : "49:1:1"
}
],
"id" : 6,
"name" : "InheritanceSpecifier",
"src" : "49:1:1"
}
],
"id" : 7,
"name" : "ContractDefinition",
"src" : "35:19:1"
},
{
"attributes" :
{
"contractDependencies" :
[
1,
4,
7
],
"contractKind" : "contract",
"documentation" : null,
"fullyImplemented" : true,
"linearizedBaseContracts" :
[
10,
7,
4,
1
],
"name" : "D",
"nodes" :
[
null
],
"scope" : 14
},
"children" :
[
{
"attributes" :
{
"arguments" : null
},
"children" :
[
{
"attributes" :
{
"contractScope" : null,
"name" : "C",
"referencedDeclaration" : 7,
"type" : "contract C"
},
"id" : 8,
"name" : "UserDefinedTypeName",
"src" : "69:1:1"
}
],
"id" : 9,
"name" : "InheritanceSpecifier",
"src" : "69:1:1"
}
],
"id" : 10,
"name" : "ContractDefinition",
"src" : "55:19:1"
},
{
"attributes" :
{
"contractDependencies" :
[
1,
4,
7,
10
],
"contractKind" : "contract",
"documentation" : null,
"fullyImplemented" : true,
"linearizedBaseContracts" :
[
13,
10,
7,
4,
1
],
"name" : "E",
"nodes" :
[
null
],
"scope" : 14
},
"children" :
[
{
"attributes" :
{
"arguments" : null
},
"children" :
[
{
"attributes" :
{
"contractScope" : null,
"name" : "D",
"referencedDeclaration" : 10,
"type" : "contract D"
},
"id" : 11,
"name" : "UserDefinedTypeName",
"src" : "89:1:1"
}
],
"id" : 12,
"name" : "InheritanceSpecifier",
"src" : "89:1:1"
}
],
"id" : 13,
"name" : "ContractDefinition",
"src" : "75:19:1"
}
],
"id" : 14,
"name" : "SourceUnit",
"src" : "0:95:1"
}

View File

@ -1 +1,3 @@
contract C1 {} contract C2 is C1 {}
// ----

View File

@ -41,183 +41,6 @@ namespace test
BOOST_AUTO_TEST_SUITE(SolidityImports)
BOOST_AUTO_TEST_CASE(smoke_test)
{
CompilerStack c;
c.setSources({{"a", "contract C {} pragma solidity >=0.0;"}});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(regular_import)
{
CompilerStack c;
c.setSources({
{"a", "contract C {} pragma solidity >=0.0;"},
{"b", "import \"a\"; contract D is C {} pragma solidity >=0.0;"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(import_does_not_clutter_importee)
{
CompilerStack c;
c.setSources({
{"a", "contract C { D d; } pragma solidity >=0.0;"},
{"b", "import \"a\"; contract D is C {} pragma solidity >=0.0;"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(!c.compile());
}
BOOST_AUTO_TEST_CASE(import_is_transitive)
{
CompilerStack c;
c.setSources({
{"a", "contract C { } pragma solidity >=0.0;"},
{"b", "import \"a\"; pragma solidity >=0.0;"},
{"c", "import \"b\"; contract D is C {} pragma solidity >=0.0;"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(circular_import)
{
CompilerStack c;
c.setSources({
{"a", "import \"b\"; contract C { D d; } pragma solidity >=0.0;"},
{"b", "import \"a\"; contract D { C c; } pragma solidity >=0.0;"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(relative_import)
{
CompilerStack c;
c.setSources({
{"a", "import \"./dir/b\"; contract A is B {} pragma solidity >=0.0;"},
{"dir/b", "contract B {} pragma solidity >=0.0;"},
{"dir/c", "import \"../a\"; contract C is A {} pragma solidity >=0.0;"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(relative_import_multiplex)
{
CompilerStack c;
c.setSources({
{"a", "contract A {} pragma solidity >=0.0;"},
{"dir/a/b/c", "import \"../../.././a\"; contract B is A {} pragma solidity >=0.0;"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(simple_alias)
{
CompilerStack c;
c.setSources({
{"a", "contract A {} pragma solidity >=0.0;"},
{"dir/a/b/c", "import \"../../.././a\" as x; contract B is x.A { function() external { x.A r = x.A(20); } } pragma solidity >=0.0;"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(library_name_clash)
{
CompilerStack c;
c.setSources({
{"a", "library A {} pragma solidity >=0.0;"},
{"b", "library A {} pragma solidity >=0.0;"},
{"c", "import {A} from \"./a\"; import {A} from \"./b\";"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(!c.compile());
}
BOOST_AUTO_TEST_CASE(library_name_clash_with_contract)
{
CompilerStack c;
c.setSources({
{"a", "contract A {} pragma solidity >=0.0;"},
{"b", "library A {} pragma solidity >=0.0;"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(complex_import)
{
CompilerStack c;
c.setSources({
{"a", "contract A {} contract B {} contract C { struct S { uint a; } } pragma solidity >=0.0;"},
{"b", "import \"a\" as x; import {B as b, C as c, C} from \"a\"; "
"contract D is b { function f(c.S memory var1, x.C.S memory var2, C.S memory var3) internal {} } pragma solidity >=0.0;"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(name_clash_in_import_1)
{
CompilerStack c;
c.setSources({
{"a", "contract A {} pragma solidity >=0.0;"},
{"b", "import \"a\"; contract A {} pragma solidity >=0.0;"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(!c.compile());
}
BOOST_AUTO_TEST_CASE(name_clash_in_import_2)
{
CompilerStack c;
c.setSources({
{"a", "contract A {} pragma solidity >=0.0;"},
{"b", "import \"a\" as A; contract A {} pragma solidity >=0.0;"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(!c.compile());
}
BOOST_AUTO_TEST_CASE(name_clash_in_import_3)
{
CompilerStack c;
c.setSources({
{"a", "contract A {} pragma solidity >=0.0;"},
{"b", "import {A as b} from \"a\"; contract b {} pragma solidity >=0.0;"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(!c.compile());
}
BOOST_AUTO_TEST_CASE(name_clash_in_import_4)
{
CompilerStack c;
c.setSources({
{"a", "contract A {} pragma solidity >=0.0;"},
{"b", "import {A} from \"a\"; contract A {} pragma solidity >=0.0;"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(!c.compile());
}
BOOST_AUTO_TEST_CASE(name_clash_in_import_5)
{
CompilerStack c;
c.setSources({
{"a", "contract A {} pragma solidity >=0.0;"},
{"b", "import {A} from \"a\"; contract B {} pragma solidity >=0.0;"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(remappings)
{
CompilerStack c;
@ -246,17 +69,6 @@ BOOST_AUTO_TEST_CASE(context_dependent_remappings)
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(filename_with_period)
{
CompilerStack c;
c.setSources({
{"a/a.sol", "import \".b.sol\"; contract A is B {} pragma solidity >=0.0;"},
{"a/.b.sol", "contract B {} pragma solidity >=0.0;"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(!c.compile());
}
BOOST_AUTO_TEST_CASE(context_dependent_remappings_ensure_default_and_module_preserved)
{
CompilerStack c;
@ -303,245 +115,6 @@ BOOST_AUTO_TEST_CASE(context_dependent_remappings_order_independent_2)
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(shadowing_via_import)
{
CompilerStack c;
c.setSources({
{"a", "library A {} pragma solidity >=0.0;"},
{"b", "library A {} pragma solidity >=0.0;"},
{"c", "import {A} from \"./a\"; import {A} from \"./b\";"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(!c.compile());
}
BOOST_AUTO_TEST_CASE(shadowing_builtins_with_imports)
{
CompilerStack c;
c.setSources({
{"B.sol", "contract X {} pragma solidity >=0.0;"},
{"b", R"(
pragma solidity >=0.0;
import * as msg from "B.sol";
contract C {
})"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile());
size_t errorCount = 0;
for (auto const& e: c.errors())
{
string const* msg = e->comment();
BOOST_REQUIRE(msg);
if (msg->find("pre-release") != string::npos)
continue;
BOOST_CHECK(
msg->find("shadows a builtin symbol") != string::npos
);
errorCount++;
}
BOOST_CHECK_EQUAL(errorCount, 1);
}
BOOST_AUTO_TEST_CASE(shadowing_builtins_with_multiple_imports)
{
CompilerStack c;
c.setSources({
{"B.sol", "contract msg {} contract block{} pragma solidity >=0.0;"},
{"b", R"(
pragma solidity >=0.0;
import {msg, block} from "B.sol";
contract C {
})"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile());
auto numErrors = c.errors().size();
// Sometimes we get the prerelease warning, sometimes not.
BOOST_CHECK(4 <= numErrors && numErrors <= 5);
for (auto const& e: c.errors())
{
string const* msg = e->comment();
BOOST_REQUIRE(msg);
BOOST_CHECK(
msg->find("pre-release") != string::npos ||
msg->find("shadows a builtin symbol") != string::npos
);
}
}
BOOST_AUTO_TEST_CASE(shadowing_builtins_with_alias)
{
CompilerStack c;
c.setSources({
{"B.sol", "contract C {} pragma solidity >=0.0;"},
{"b", R"(
pragma solidity >=0.0;
import {C as msg} from "B.sol";)"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile());
auto numErrors = c.errors().size();
// Sometimes we get the prerelease warning, sometimes not.
BOOST_CHECK(1 <= numErrors && numErrors <= 2);
for (auto const& e: c.errors())
{
string const* msg = e->comment();
BOOST_REQUIRE(msg);
BOOST_CHECK(
msg->find("pre-release") != string::npos ||
msg->find("shadows a builtin symbol") != string::npos
);
}
}
BOOST_AUTO_TEST_CASE(inheritance_abi_encoder_mismatch_1)
{
CompilerStack c;
c.setSources({
{"A.sol", R"(
pragma solidity >=0.0;
pragma experimental ABIEncoderV2;
contract A
{
struct S { uint a; }
S public s;
function f(S memory _s) returns (S memory,S memory) { }
}
)"},
{"B.sol", R"(
pragma solidity >=0.0;
pragma experimental ABIEncoderV2;
import "./A.sol";
contract B is A { }
)"},
{"C.sol", R"(
pragma solidity >=0.0;
import "./B.sol";
contract C is B { }
)"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(!c.compile());
int typeErrors = 0;
// Sometimes we get the prerelease warning, sometimes not.
for (auto const& e: c.errors())
{
if (e->type() != langutil::Error::Type::TypeError)
continue;
typeErrors++;
string const* msg = e->comment();
BOOST_REQUIRE(msg);
BOOST_CHECK_EQUAL(*msg, std::string("Contract \"C\" does not use the new experimental ABI encoder but wants to inherit from a contract which uses types that require it. Use \"pragma experimental ABIEncoderV2;\" for the inheriting contract as well to enable the feature."));
}
BOOST_CHECK_EQUAL(typeErrors, 1);
}
BOOST_AUTO_TEST_CASE(inheritance_abi_encoder_mismatch_2)
{
CompilerStack c;
c.setSources({
{"A.sol", R"(
pragma solidity >=0.0;
pragma experimental ABIEncoderV2;
contract A
{
struct S { uint a; }
S public s;
function f(S memory _s) returns (S memory,S memory) { }
}
)"},
{"B.sol", R"(
pragma solidity >=0.0;
import "./A.sol";
contract B is A { }
)"},
{"C.sol", R"(
pragma solidity >=0.0;
import "./B.sol";
contract C is B { }
)"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(!c.compile());
int typeErrors = 0;
// Sometimes we get the prerelease warning, sometimes not.
for (auto const& e: c.errors())
{
if (e->type() != langutil::Error::Type::TypeError)
continue;
typeErrors++;
string const* msg = e->comment();
BOOST_REQUIRE(msg);
BOOST_CHECK_EQUAL(*msg, std::string("Contract \"B\" does not use the new experimental ABI encoder but wants to inherit from a contract which uses types that require it. Use \"pragma experimental ABIEncoderV2;\" for the inheriting contract as well to enable the feature."));
}
BOOST_CHECK_EQUAL(typeErrors, 1);
}
BOOST_AUTO_TEST_CASE(inheritance_abi_encoder_match)
{
CompilerStack c;
c.setSources({
{"A.sol", R"(
pragma solidity >=0.0;
pragma experimental ABIEncoderV2;
contract A
{
struct S { uint a; }
S public s;
function f(S memory _s) public returns (S memory,S memory) { }
}
)"},
{"B.sol", R"(
pragma solidity >=0.0;
pragma experimental ABIEncoderV2;
import "./A.sol";
contract B is A { }
)"},
{"C.sol", R"(
pragma solidity >=0.0;
pragma experimental ABIEncoderV2;
import "./B.sol";
contract C is B { }
)"}
});
c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile());
int typeErrors = 0;
// Sometimes we get the prerelease warning, sometimes not.
for (auto const& e: c.errors())
{
if (e->type() != langutil::Error::Type::TypeError)
continue;
typeErrors++;
}
BOOST_CHECK_EQUAL(typeErrors, 0);
}
BOOST_AUTO_TEST_SUITE_END()
}

View File

@ -116,13 +116,15 @@ BOOST_AUTO_TEST_CASE(division)
if (a == 0) {
return 0;
}
// TODO remove when SMTChecker sees that this code is the `else` of the `return`.
require(a != 0);
uint256 c = a * b;
require(c / a == b);
return c;
}
}
)";
CHECK_WARNING(text, "Division by zero");
CHECK_SUCCESS_OR_WARNING(text, "might happen");
text = R"(
contract C {
function div(uint256 a, uint256 b) internal pure returns (uint256) {

View File

@ -108,6 +108,9 @@ TestCase::TestResult SMTCheckerTest::run(ostream& _stream, string const& _linePr
BOOST_THROW_EXCEPTION(runtime_error("Error must have a SourceLocation with start and end."));
int start = location["start"].asInt();
int end = location["end"].asInt();
std::string sourceName;
if (location.isMember("source") && location["source"].isString())
sourceName = location["source"].asString();
if (start >= static_cast<int>(versionPragma.size()))
start -= versionPragma.size();
if (end >= static_cast<int>(versionPragma.size()))
@ -115,6 +118,7 @@ TestCase::TestResult SMTCheckerTest::run(ostream& _stream, string const& _linePr
m_errorList.emplace_back(SyntaxTestError{
error["type"].asString(),
error["message"].asString(),
sourceName,
start,
end
});
@ -141,13 +145,20 @@ vector<string> SMTCheckerTest::hashesFromJson(Json::Value const& _jsonObj, strin
Json::Value SMTCheckerTest::buildJson(string const& _extra)
{
string language = "\"language\": \"Solidity\"";
string sourceName = "\"A\"";
string sourceContent = "\"" + _extra + m_source + "\"";
string sourceObj = "{ \"content\": " + sourceContent + "}";
string sources = " \"sources\": { " + sourceName + ": " + sourceObj + "}";
string sources = " \"sources\": { ";
bool first = true;
for (auto [sourceName, sourceContent]: m_sources)
{
string sourceObj = "{ \"content\": \"" + _extra + sourceContent + "\"}";
if (!first)
sources += ", ";
sources += "\"" + sourceName + "\": " + sourceObj;
first = false;
}
sources += "}";
string input = "{" + language + ", " + sources + "}";
Json::Value source;
if (!jsonParse(input, source))
BOOST_THROW_EXCEPTION(runtime_error("Could not build JSON from string."));
BOOST_THROW_EXCEPTION(runtime_error("Could not build JSON from string: " + input));
return source;
}

View File

@ -59,7 +59,8 @@ SyntaxTest::SyntaxTest(string const& _filename, langutil::EVMVersion _evmVersion
BOOST_THROW_EXCEPTION(runtime_error("Cannot open test contract: \"" + _filename + "\"."));
file.exceptions(ios::badbit);
m_source = parseSourceAndSettings(file);
m_sources = parseSourcesAndSettings(file);
if (m_settings.count("optimize-yul"))
{
m_optimiseYul = true;
@ -74,7 +75,10 @@ TestCase::TestResult SyntaxTest::run(ostream& _stream, string const& _linePrefix
{
string const versionPragma = "pragma solidity >=0.0;\n";
compiler().reset();
compiler().setSources({{"", versionPragma + m_source}});
auto sourcesWithPragma = m_sources;
for (auto& source: sourcesWithPragma)
source.second = versionPragma + source.second;
compiler().setSources(sourcesWithPragma);
compiler().setEVMVersion(m_evmVersion);
compiler().setParserErrorRecovery(m_parserErrorRecovery);
compiler().setOptimiserSettings(
@ -83,11 +87,27 @@ TestCase::TestResult SyntaxTest::run(ostream& _stream, string const& _linePrefix
OptimiserSettings::minimal()
);
if (compiler().parse())
compiler().analyze();
if (compiler().analyze())
try
{
if (!compiler().compile())
BOOST_THROW_EXCEPTION(runtime_error("Compilation failed even though analysis was successful."));
}
catch (UnimplementedFeatureError const& _e)
{
m_errorList.emplace_back(SyntaxTestError{
"UnimplementedFeatureError",
errorMessage(_e),
"",
-1,
-1
});
}
for (auto const& currentError: filterErrors(compiler().errors(), true))
{
int locationStart = -1, locationEnd = -1;
string sourceName;
if (auto location = boost::get_error_info<errinfo_sourceLocation>(*currentError))
{
// ignore the version pragma inserted by the testing tool when calculating locations.
@ -95,10 +115,13 @@ TestCase::TestResult SyntaxTest::run(ostream& _stream, string const& _linePrefix
locationStart = location->start - versionPragma.size();
if (location->end >= static_cast<int>(versionPragma.size()))
locationEnd = location->end - versionPragma.size();
if (location->source)
sourceName = location->source->name();
}
m_errorList.emplace_back(SyntaxTestError{
currentError->typeName(),
errorMessage(*currentError),
sourceName,
locationStart,
locationEnd
});
@ -123,51 +146,65 @@ bool SyntaxTest::printExpectationAndError(ostream& _stream, string const& _lineP
void SyntaxTest::printSource(ostream& _stream, string const& _linePrefix, bool _formatted) const
{
if (m_sources.empty())
return;
bool outputSourceNames = true;
if (m_sources.size() == 1 && m_sources.begin()->first.empty())
outputSourceNames = false;
if (_formatted)
{
if (m_source.empty())
return;
vector<char const*> sourceFormatting(m_source.length(), formatting::RESET);
for (auto const& error: m_errorList)
if (error.locationStart >= 0 && error.locationEnd >= 0)
{
assert(static_cast<size_t>(error.locationStart) <= m_source.length());
assert(static_cast<size_t>(error.locationEnd) <= m_source.length());
bool isWarning = error.type == "Warning";
for (int i = error.locationStart; i < error.locationEnd; i++)
if (isWarning)
{
if (sourceFormatting[i] == formatting::RESET)
sourceFormatting[i] = formatting::ORANGE_BACKGROUND_256;
}
else
sourceFormatting[i] = formatting::RED_BACKGROUND;
}
_stream << _linePrefix << sourceFormatting.front() << m_source.front();
for (size_t i = 1; i < m_source.length(); i++)
for (auto const& [name, source]: m_sources)
{
if (sourceFormatting[i] != sourceFormatting[i - 1])
_stream << sourceFormatting[i];
if (m_source[i] != '\n')
_stream << m_source[i];
else
if (outputSourceNames)
_stream << _linePrefix << formatting::CYAN << "==== Source: " << name << " ====" << formatting::RESET << endl;
vector<char const*> sourceFormatting(source.length(), formatting::RESET);
for (auto const& error: m_errorList)
if (error.sourceName == name && error.locationStart >= 0 && error.locationEnd >= 0)
{
assert(static_cast<size_t>(error.locationStart) <= source.length());
assert(static_cast<size_t>(error.locationEnd) <= source.length());
bool isWarning = error.type == "Warning";
for (int i = error.locationStart; i < error.locationEnd; i++)
if (isWarning)
{
if (sourceFormatting[i] == formatting::RESET)
sourceFormatting[i] = formatting::ORANGE_BACKGROUND_256;
}
else
sourceFormatting[i] = formatting::RED_BACKGROUND;
}
_stream << _linePrefix << sourceFormatting.front() << source.front();
for (size_t i = 1; i < source.length(); i++)
{
_stream << formatting::RESET << endl;
if (i + 1 < m_source.length())
_stream << _linePrefix << sourceFormatting[i];
if (sourceFormatting[i] != sourceFormatting[i - 1])
_stream << sourceFormatting[i];
if (source[i] != '\n')
_stream << source[i];
else
{
_stream << formatting::RESET << endl;
if (i + 1 < source.length())
_stream << _linePrefix << sourceFormatting[i];
}
}
_stream << formatting::RESET;
}
_stream << formatting::RESET;
}
else
{
stringstream stream(m_source);
string line;
while (getline(stream, line))
_stream << _linePrefix << line << endl;
}
for (auto const& [name, source]: m_sources)
{
if (outputSourceNames)
_stream << _linePrefix << "==== Source: " + name << " ====" << endl;
stringstream stream(source);
string line;
while (getline(stream, line))
_stream << _linePrefix << line << endl;
}
}
void SyntaxTest::printErrorList(
@ -187,9 +224,11 @@ void SyntaxTest::printErrorList(
_stream << _linePrefix;
_stream << error.type << ": ";
}
if (error.locationStart >= 0 || error.locationEnd >= 0)
if (!error.sourceName.empty() || error.locationStart >= 0 || error.locationEnd >= 0)
{
_stream << "(";
if (!error.sourceName.empty())
_stream << error.sourceName << ":";
if (error.locationStart >= 0)
_stream << error.locationStart;
_stream << "-";
@ -234,10 +273,19 @@ vector<SyntaxTestError> SyntaxTest::parseExpectations(istream& _stream)
int locationStart = -1;
int locationEnd = -1;
std::string sourceName;
if (it != line.end() && *it == '(')
{
++it;
if (it != line.end() && !isdigit(*it))
{
auto sourceNameStart = it;
while (it != line.end() && *it != ':')
++it;
sourceName = std::string(sourceNameStart, it);
expect(it, line.end(), ':');
}
locationStart = parseUnsignedInteger(it, line.end());
expect(it, line.end(), '-');
locationEnd = parseUnsignedInteger(it, line.end());
@ -251,6 +299,7 @@ vector<SyntaxTestError> SyntaxTest::parseExpectations(istream& _stream)
expectations.emplace_back(SyntaxTestError{
move(errorType),
move(errorMessage),
move(sourceName),
locationStart,
locationEnd
});

View File

@ -38,12 +38,14 @@ struct SyntaxTestError
{
std::string type;
std::string message;
std::string sourceName;
int locationStart;
int locationEnd;
bool operator==(SyntaxTestError const& _rhs) const
{
return type == _rhs.type &&
message == _rhs.message &&
sourceName == _rhs.sourceName &&
locationStart == _rhs.locationStart &&
locationEnd == _rhs.locationEnd;
}
@ -85,7 +87,7 @@ protected:
static std::vector<SyntaxTestError> parseExpectations(std::istream& _stream);
std::string m_source;
std::map<std::string, std::string> m_sources;
std::vector<SyntaxTestError> m_expectations;
std::vector<SyntaxTestError> m_errorList;
bool m_optimiseYul = false;

View File

@ -1,3 +1,4 @@
==== Source: A ====
pragma experimental SMTChecker;
contract C

View File

@ -1,3 +1,4 @@
==== Source: A ====
pragma experimental SMTChecker;
contract C

View File

@ -4,3 +4,5 @@ contract C {
fixed a3 = 0 / 0.123;
fixed a4 = 0 / -0.123;
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.

View File

@ -0,0 +1,4 @@
==== Source: a ====
import "b"; contract C { D d; }
==== Source: b ====
import "a"; contract D { C c; }

View File

@ -0,0 +1,5 @@
==== Source: a ====
contract A {} contract B {} contract C { struct S { uint a; } }
==== Source: b ====
import "a" as x; import {B as b, C as c, C} from "a";
contract D is b { function f(c.S memory var1, x.C.S memory var2, C.S memory var3) internal {} }

View File

@ -0,0 +1,6 @@
==== Source: a/.b.sol ====
contract B {}
==== Source: a/a.sol ====
import ".b.sol"; contract A is B {}
// ----
// ParserError: (a/a.sol:0-16): Source ".b.sol" not found: File not supplied initially.

View File

@ -0,0 +1,6 @@
==== Source: a ====
contract C { D d; }
==== Source: b ====
import "a"; contract D is C {}
// ----
// DeclarationError: (a:13-14): Identifier not found or not unique.

View File

@ -0,0 +1,7 @@
==== Source: a ====
contract C { }
==== Source: b ====
import "a";
==== Source: c ====
import "b";
contract D is C {}

View File

@ -0,0 +1,23 @@
==== Source: A.sol ====
pragma experimental ABIEncoderV2;
contract A
{
struct S { uint a; }
S public s;
function f(S memory _s) public returns (S memory,S memory) { }
}
==== Source: B.sol ====
pragma experimental ABIEncoderV2;
import "./A.sol";
contract B is A { }
==== Source: C.sol ====
pragma experimental ABIEncoderV2;
import "./B.sol";
contract C is B { }
// ----
// Warning: (A.sol:0-33): Experimental features are turned on. Do not use experimental features on live deployments.
// Warning: (B.sol:0-33): Experimental features are turned on. Do not use experimental features on live deployments.
// Warning: (C.sol:0-33): Experimental features are turned on. Do not use experimental features on live deployments.

View File

@ -0,0 +1,21 @@
==== Source: A.sol ====
pragma experimental ABIEncoderV2;
contract A
{
struct S { uint a; }
S public s;
function f(S memory _s) public returns (S memory,S memory) { }
}
==== Source: B.sol ====
pragma experimental ABIEncoderV2;
import "./A.sol";
contract B is A { }
==== Source: C.sol ====
import "./B.sol";
contract C is B { }
// ----
// Warning: (A.sol:0-33): Experimental features are turned on. Do not use experimental features on live deployments.
// Warning: (B.sol:0-33): Experimental features are turned on. Do not use experimental features on live deployments.
// TypeError: (C.sol:18-37): Contract "C" does not use the new experimental ABI encoder but wants to inherit from a contract which uses types that require it. Use "pragma experimental ABIEncoderV2;" for the inheriting contract as well to enable the feature.

View File

@ -0,0 +1,18 @@
==== Source: A.sol ====
pragma experimental ABIEncoderV2;
contract A
{
struct S { uint a; }
S public s;
function f(S memory _s) public returns (S memory,S memory) { }
}
==== Source: B.sol ====
import "./A.sol";
contract B is A { }
==== Source: C.sol ====
import "./B.sol";
contract C is B { }
// ----
// Warning: (A.sol:0-33): Experimental features are turned on. Do not use experimental features on live deployments.
// TypeError: (B.sol:18-37): Contract "B" does not use the new experimental ABI encoder but wants to inherit from a contract which uses types that require it. Use "pragma experimental ABIEncoderV2;" for the inheriting contract as well to enable the feature.

View File

@ -0,0 +1,8 @@
==== Source: a ====
library A {}
==== Source: b ====
library A {}
==== Source: c ====
import {A} from "./a"; import {A} from "./b";
// ----
// DeclarationError: (c:23-45): Identifier already declared.

View File

@ -0,0 +1,4 @@
==== Source: a ====
contract A {}
==== Source: b ====
library A {}

View File

@ -0,0 +1,6 @@
==== Source: a ====
contract A {}
==== Source: b ====
import "a"; contract A {}
// ----
// DeclarationError: (b:12-25): Identifier already declared.

View File

@ -0,0 +1,6 @@
==== Source: a ====
contract A {}
==== Source: b ====
import "a" as A; contract A {}
// ----
// DeclarationError: (b:17-30): Identifier already declared.

View File

@ -0,0 +1,6 @@
==== Source: a ====
contract A {}
==== Source: b ====
import {A as b} from "a"; contract b {}
// ----
// DeclarationError: (b:26-39): Identifier already declared.

View File

@ -0,0 +1,6 @@
==== Source: a ====
contract A {}
==== Source: b ====
import {A} from "a"; contract A {}
// ----
// DeclarationError: (b:21-34): Identifier already declared.

View File

@ -0,0 +1,4 @@
==== Source: a ====
contract A {}
==== Source: b ====
import {A} from "a"; contract B {}

View File

@ -0,0 +1,4 @@
==== Source: a ====
contract C {}
==== Source: b ====
import "a"; contract D is C {}

View File

@ -0,0 +1,6 @@
==== Source: a ====
import "./dir/b"; contract A is B {}
==== Source: dir/b ====
contract B {}
==== Source: dir/c ====
import "../a"; contract C is A {}

View File

@ -0,0 +1,4 @@
==== Source: a ====
contract A {}
==== Source: dir/a/b/c ====
import "../../.././a"; contract B is A {}

View File

@ -0,0 +1,6 @@
==== Source: B.sol ====
contract C {}
==== Source: b ====
import {C as msg} from "B.sol";
// ----
// Warning: (B.sol:0-13): This declaration shadows a builtin symbol.

View File

@ -0,0 +1,8 @@
==== Source: B.sol ====
contract X {}
==== Source: b ====
import * as msg from "B.sol";
contract C {
}
// ----
// Warning: (b:0-29): This declaration shadows a builtin symbol.

View File

@ -0,0 +1,11 @@
==== Source: B.sol ====
contract msg {} contract block{}
==== Source: b ====
import {msg, block} from "B.sol";
contract C {
}
// ----
// Warning: (B.sol:0-15): This declaration shadows a builtin symbol.
// Warning: (B.sol:16-32): This declaration shadows a builtin symbol.
// Warning: (B.sol:0-15): This declaration shadows a builtin symbol.
// Warning: (B.sol:16-32): This declaration shadows a builtin symbol.

View File

@ -0,0 +1,8 @@
==== Source: a ====
library A {}
==== Source: b ====
library A {}
==== Source: c ====
import {A} from "./a"; import {A} from "./b";
// ----
// DeclarationError: (c:23-45): Identifier already declared.

View File

@ -0,0 +1,4 @@
==== Source: a ====
contract A {}
==== Source: dir/a/b/c ====
import "../../.././a" as x; contract B is x.A { function() external { x.A r = x.A(20); r; } }

View File

@ -0,0 +1,2 @@
==== Source: a ====
contract C {}

View File

@ -4,5 +4,6 @@ contract test {
}
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.
// Warning: (50-67): Unused local variable.
// Warning: (20-119): Function state mutability can be restricted to pure

View File

@ -4,5 +4,6 @@ contract test {
}
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.
// Warning: (50-73): Unused local variable.
// Warning: (20-118): Function state mutability can be restricted to pure

View File

@ -0,0 +1,10 @@
==== Source: A ====
contract A {
function g() public { x; }
}
==== Source: B ====
contract B {
function f() public { }
}
// ----
// DeclarationError: (A:36-37): Undeclared identifier.

View File

@ -0,0 +1,12 @@
==== Source: A ====
contract A {
function g(uint256 x) public view returns(uint256) { return x; }
}
==== Source: B ====
import "A";
contract B is A {
function f(uint256 x) public view returns(uint256) { return x; }
}
// ----
// Warning: (A:14-78): Function state mutability can be restricted to pure
// Warning: (B:31-95): Function state mutability can be restricted to pure

View File

@ -0,0 +1,5 @@
==== Source: a ====
import "b";
contract C {}
// ----
// ParserError: (a:0-11): Source "b" not found: File not supplied initially.

View File

@ -0,0 +1,10 @@
==== Source: A ====
contract A {
function g(uint256 x) public view returns(uint256) { return x; }
}
==== Source: B ====
contract B is A {
function f(uint256 x) public view returns(uint256) { return x; }
}
// ----
// DeclarationError: (B:14-15): Identifier not found or not unique.

View File

@ -0,0 +1,7 @@
==== Source: SourceName ====
contract A {
uint256 x;
function f() public pure { x = 42; }
}
// ----
// TypeError: (SourceName:53-54): Function declared as pure, but this expression (potentially) modifies the state and thus requires non-payable (the default) or payable.

View File

@ -0,0 +1,11 @@
==== Source: A ====
contract A {
function g(uint256 x) public view returns(uint256) { return x; }
}
==== Source: B ====
contract B {
function f(uint256 x) public view returns(uint256) { return x; }
}
// ----
// Warning: (A:14-78): Function state mutability can be restricted to pure
// Warning: (B:14-78): Function state mutability can be restricted to pure

View File

@ -8,4 +8,5 @@ contract test {
}
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.
// Warning: (20-147): Function state mutability can be restricted to pure

View File

@ -6,4 +6,5 @@ contract test {
}
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.
// Warning: (20-104): Function state mutability can be restricted to pure

View File

@ -6,4 +6,5 @@ contract test {
}
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.
// Warning: (20-108): Function state mutability can be restricted to pure

View File

@ -5,3 +5,5 @@ contract test {
a; b;
}
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.

View File

@ -7,3 +7,5 @@ contract A {
a; b; c; d;
}
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.

View File

@ -5,4 +5,5 @@ contract test {
}
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.
// Warning: (20-104): Function state mutability can be restricted to pure

View File

@ -6,4 +6,5 @@ contract test {
}
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.
// Warning: (20-182): Function state mutability can be restricted to pure

View File

@ -4,3 +4,5 @@ contract test {
fixedString[0.5] = "Half";
}
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.

View File

@ -5,3 +5,5 @@ contract test {
}
myStruct a = myStruct(3.125, 3);
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.

View File

@ -11,5 +11,6 @@ contract test {
}
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.
// Warning: (238-252): This declaration shadows an existing declaration.
// Warning: (20-339): Function state mutability can be restricted to pure

View File

@ -4,5 +4,6 @@ contract test {
}
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.
// Warning: (50-58): Unused local variable.
// Warning: (20-89): Function state mutability can be restricted to pure

View File

@ -6,6 +6,7 @@ contract A {
}
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.
// Warning: (52-60): Unused function parameter. Remove or comment out the variable name to silence this warning.
// Warning: (62-74): Unused function parameter. Remove or comment out the variable name to silence this warning.
// Warning: (93-104): Unused local variable.

View File

@ -7,3 +7,4 @@ contract C {
}
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.

View File

@ -6,3 +6,5 @@ contract test {
a; b; c;
}
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.

View File

@ -13,3 +13,4 @@ contract C {
}
}
// ----
// UnimplementedFeatureError: Not yet implemented - FixedPointType.