diff options
-rw-r--r-- | libdevcore/Visitor.h | 128 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmScope.h | 27 | ||||
-rw-r--r-- | test/tools/fuzzer.cpp | 38 |
3 files changed, 157 insertions, 36 deletions
diff --git a/libdevcore/Visitor.h b/libdevcore/Visitor.h new file mode 100644 index 00000000..4030c928 --- /dev/null +++ b/libdevcore/Visitor.h @@ -0,0 +1,128 @@ +/* + 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/>. +*/ +/** + * Visitor templates. + */ + +#pragma once + +#include <functional> +#include <boost/variant/static_visitor.hpp> + +namespace dev +{ + +/// Generic visitor used as follows: +/// boost::apply_visitor(GenericVisitor<Class1, Class2>( +/// [](Class1& _c) { _c.f(); }, +/// [](Class2& _c) { _c.g(); } +/// ), variant); +/// This one does not have a fallback and will fail at +/// compile-time if you do not specify all variants. + +template <class...> +struct GenericVisitor{}; + +template <class Visitable, class... Others> +struct GenericVisitor<Visitable, Others...>: public GenericVisitor<Others...> +{ + using GenericVisitor<Others...>::operator (); + explicit GenericVisitor( + std::function<void(Visitable&)> _visitor, + std::function<void(Others&)>... _otherVisitors + ): + GenericVisitor<Others...>(std::move(_otherVisitors)...), + m_visitor(std::move(_visitor)) + {} + + void operator()(Visitable& _v) const { m_visitor(_v); } + + std::function<void(Visitable&)> m_visitor; +}; +template <> +struct GenericVisitor<>: public boost::static_visitor<> { + void operator()() const {} +}; + +/// Generic visitor with fallback: +/// boost::apply_visitor(GenericFallbackVisitor<Class1, Class2>( +/// [](Class1& _c) { _c.f(); }, +/// [](Class2& _c) { _c.g(); } +/// ), variant); +/// This one DOES have a fallback and will NOT fail at +/// compile-time if you do not specify all variants. + +template <class...> +struct GenericFallbackVisitor{}; + +template <class Visitable, class... Others> +struct GenericFallbackVisitor<Visitable, Others...>: public GenericFallbackVisitor<Others...> +{ + explicit GenericFallbackVisitor( + std::function<void(Visitable&)> _visitor, + std::function<void(Others&)>... _otherVisitors + ): + GenericFallbackVisitor<Others...>(std::move(_otherVisitors)...), + m_visitor(std::move(_visitor)) + {} + + using GenericFallbackVisitor<Others...>::operator (); + void operator()(Visitable& _v) const { m_visitor(_v); } + + std::function<void(Visitable&)> m_visitor; +}; +template <> +struct GenericFallbackVisitor<>: public boost::static_visitor<> { + template <class T> + void operator()(T&) const { } +}; + +/// Generic visitor with fallback that can return a value: +/// boost::apply_visitor(GenericFallbackReturnsVisitor<ReturnType, Class1, Class2>( +/// [](Class1& _c) { return _c.f(); }, +/// [](Class2& _c) { return _c.g(); } +/// ), variant); +/// This one DOES have a fallback and will NOT fail at +/// compile-time if you do not specify all variants. +/// The fallback {}-constructs the return value. + +template <class R, class...> +struct GenericFallbackReturnsVisitor{}; + +template <class R, class Visitable, class... Others> +struct GenericFallbackReturnsVisitor<R, Visitable, Others...>: public GenericFallbackReturnsVisitor<R, Others...> +{ + explicit GenericFallbackReturnsVisitor( + std::function<R(Visitable&)> _visitor, + std::function<R(Others&)>... _otherVisitors + ): + GenericFallbackReturnsVisitor<R, Others...>(std::move(_otherVisitors)...), + m_visitor(std::move(_visitor)) + {} + + using GenericFallbackReturnsVisitor<R, Others...>::operator (); + R operator()(Visitable& _v) const { return m_visitor(_v); } + + std::function<R(Visitable&)> m_visitor; +}; +template <class R> +struct GenericFallbackReturnsVisitor<R>: public boost::static_visitor<R> { + template <class T> + R operator()(T&) const { return {}; } +}; + +} diff --git a/libsolidity/inlineasm/AsmScope.h b/libsolidity/inlineasm/AsmScope.h index c8c63f8f..fc674e71 100644 --- a/libsolidity/inlineasm/AsmScope.h +++ b/libsolidity/inlineasm/AsmScope.h @@ -22,6 +22,8 @@ #include <libsolidity/interface/Exceptions.h> +#include <libdevcore/Visitor.h> + #include <boost/variant.hpp> #include <boost/optional.hpp> @@ -35,31 +37,6 @@ namespace solidity namespace assembly { -template <class...> -struct GenericVisitor{}; - -template <class Visitable, class... Others> -struct GenericVisitor<Visitable, Others...>: public GenericVisitor<Others...> -{ - using GenericVisitor<Others...>::operator (); - explicit GenericVisitor( - std::function<void(Visitable&)> _visitor, - std::function<void(Others&)>... _otherVisitors - ): - GenericVisitor<Others...>(_otherVisitors...), - m_visitor(_visitor) - {} - - void operator()(Visitable& _v) const { m_visitor(_v); } - - std::function<void(Visitable&)> m_visitor; -}; -template <> -struct GenericVisitor<>: public boost::static_visitor<> { - void operator()() const {} -}; - - struct Scope { using YulType = std::string; diff --git a/test/tools/fuzzer.cpp b/test/tools/fuzzer.cpp index f7b42b25..bb020f8c 100644 --- a/test/tools/fuzzer.cpp +++ b/test/tools/fuzzer.cpp @@ -28,6 +28,7 @@ #include <boost/program_options.hpp> #include <string> +#include <sstream> #include <iostream> using namespace std; @@ -48,15 +49,17 @@ string contains(string const& _haystack, vector<string> const& _needles) return ""; } -void testConstantOptimizer() +void testConstantOptimizer(string const& input) { if (!quiet) cout << "Testing constant optimizer" << endl; vector<u256> numbers; - while (!cin.eof()) + stringstream sin(input); + + while (!sin.eof()) { h256 data; - cin.read(reinterpret_cast<char*>(data.data()), 32); + sin.read(reinterpret_cast<char*>(data.data()), 32); numbers.push_back(u256(data)); } if (!quiet) @@ -108,20 +111,18 @@ void runCompiler(string input) } } -void testStandardCompiler() +void testStandardCompiler(string const& input) { if (!quiet) cout << "Testing compiler via JSON interface." << endl; - string input = readStandardInput(); runCompiler(input); } -void testCompiler(bool optimize) +void testCompiler(string const& input, bool optimize) { if (!quiet) cout << "Testing compiler " << (optimize ? "with" : "without") << " optimizer." << endl; - string input = readStandardInput(); Json::Value config = Json::objectValue; config["language"] = "Solidity"; @@ -168,15 +169,24 @@ Allowed options)", "Expects a binary string of up to 32 bytes on stdin." ) ( + "input-file", + po::value<string>(), + "input file" + ) + ( "without-optimizer", "Run without optimizations. Cannot be used together with standard-json." ); + // All positional options should be interpreted as input files + po::positional_options_description filesPositions; + filesPositions.add("input-file", 1); + po::variables_map arguments; try { po::command_line_parser cmdLineParser(argc, argv); - cmdLineParser.options(options); + cmdLineParser.options(options).positional(filesPositions); po::store(cmdLineParser.run(), arguments); } catch (po::error const& _exception) @@ -185,17 +195,23 @@ Allowed options)", return 1; } + string input; + if (arguments.count("input-file")) + input = readFileAsString(arguments["input-file"].as<string>()); + else + input = readStandardInput(); + if (arguments.count("quiet")) quiet = true; if (arguments.count("help")) cout << options; else if (arguments.count("const-opt")) - testConstantOptimizer(); + testConstantOptimizer(input); else if (arguments.count("standard-json")) - testStandardCompiler(); + testStandardCompiler(input); else - testCompiler(!arguments.count("without-optimizer")); + testCompiler(input, !arguments.count("without-optimizer")); return 0; } |