diff options
Diffstat (limited to 'libsolidity')
82 files changed, 510 insertions, 242 deletions
diff --git a/libsolidity/CMakeLists.txt b/libsolidity/CMakeLists.txt index e67facb3..8c2ab347 100644 --- a/libsolidity/CMakeLists.txt +++ b/libsolidity/CMakeLists.txt @@ -1,58 +1,112 @@ # Until we have a clear separation, libyul has to be included here set(sources analysis/ConstantEvaluator.cpp + analysis/ConstantEvaluator.h analysis/ContractLevelChecker.cpp + analysis/ContractLevelChecker.h analysis/ControlFlowAnalyzer.cpp + analysis/ControlFlowAnalyzer.h analysis/ControlFlowBuilder.cpp + analysis/ControlFlowBuilder.h analysis/ControlFlowGraph.cpp + analysis/ControlFlowGraph.h analysis/DeclarationContainer.cpp + analysis/DeclarationContainer.h analysis/DocStringAnalyser.cpp + analysis/DocStringAnalyser.h analysis/GlobalContext.cpp + analysis/GlobalContext.h analysis/NameAndTypeResolver.cpp + analysis/NameAndTypeResolver.h analysis/PostTypeChecker.cpp + analysis/PostTypeChecker.h analysis/ReferencesResolver.cpp + analysis/ReferencesResolver.h analysis/SemVerHandler.cpp + analysis/SemVerHandler.h analysis/StaticAnalyzer.cpp + analysis/StaticAnalyzer.h analysis/SyntaxChecker.cpp + analysis/SyntaxChecker.h analysis/TypeChecker.cpp + analysis/TypeChecker.h analysis/ViewPureChecker.cpp + analysis/ViewPureChecker.h ast/AST.cpp + ast/AST.h + ast/AST_accept.h ast/ASTAnnotations.cpp + ast/ASTAnnotations.h + ast/ASTEnums.h + ast/ASTForward.h ast/ASTJsonConverter.cpp + ast/ASTJsonConverter.h ast/ASTPrinter.cpp + ast/ASTPrinter.h + ast/ASTVisitor.h + ast/ExperimentalFeatures.h ast/Types.cpp + ast/Types.h codegen/ABIFunctions.cpp + codegen/ABIFunctions.h codegen/ArrayUtils.cpp + codegen/ArrayUtils.h codegen/AsmCodeGen.cpp + codegen/AsmCodeGen.h codegen/Compiler.cpp + codegen/Compiler.h codegen/CompilerContext.cpp + codegen/CompilerContext.h codegen/CompilerUtils.cpp + codegen/CompilerUtils.h codegen/ContractCompiler.cpp + codegen/ContractCompiler.h codegen/ExpressionCompiler.cpp + codegen/ExpressionCompiler.h codegen/LValue.cpp + codegen/LValue.h formal/SMTChecker.cpp + formal/SMTChecker.h formal/SMTLib2Interface.cpp + formal/SMTLib2Interface.h formal/SMTPortfolio.cpp + formal/SMTPortfolio.h + formal/SolverInterface.h formal/SSAVariable.cpp + formal/SSAVariable.h formal/SymbolicTypes.cpp + formal/SymbolicTypes.h formal/SymbolicVariables.cpp + formal/SymbolicVariables.h formal/VariableUsage.cpp + formal/VariableUsage.h interface/ABI.cpp + interface/ABI.h interface/AssemblyStack.cpp + interface/AssemblyStack.h interface/CompilerStack.cpp + interface/CompilerStack.h interface/GasEstimator.cpp + interface/GasEstimator.h interface/Natspec.cpp + interface/Natspec.h + interface/ReadFile.h interface/StandardCompiler.cpp + interface/StandardCompiler.h interface/Version.cpp + interface/Version.h parsing/DocStringParser.cpp + parsing/DocStringParser.h parsing/Parser.cpp + parsing/Parser.h + parsing/Token.h ) find_package(Z3 QUIET) if (${Z3_FOUND}) add_definitions(-DHAVE_Z3) message("Z3 SMT solver found. This enables optional SMT checking with Z3.") - set(z3_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/formal/Z3Interface.cpp") + set(z3_SRCS formal/Z3Interface.cpp formal/Z3Interface.h) else() set(z3_SRCS) endif() @@ -61,7 +115,7 @@ find_package(CVC4 QUIET) if (${CVC4_FOUND}) add_definitions(-DHAVE_CVC4) message("CVC4 SMT solver found. This enables optional SMT checking with CVC4.") - set(cvc4_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/formal/CVC4Interface.cpp") + set(cvc4_SRCS formal/CVC4Interface.cpp formal/CVC4Interface.h) else() set(cvc4_SRCS) endif() diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp index 26d9584b..e637795a 100644 --- a/libsolidity/analysis/ConstantEvaluator.cpp +++ b/libsolidity/analysis/ConstantEvaluator.cpp @@ -21,6 +21,7 @@ */ #include <libsolidity/analysis/ConstantEvaluator.h> + #include <libsolidity/ast/AST.h> #include <liblangutil/ErrorReporter.h> diff --git a/libsolidity/analysis/ContractLevelChecker.cpp b/libsolidity/analysis/ContractLevelChecker.cpp index 526caff9..96b9611e 100644 --- a/libsolidity/analysis/ContractLevelChecker.cpp +++ b/libsolidity/analysis/ContractLevelChecker.cpp @@ -20,10 +20,9 @@ */ #include <libsolidity/analysis/ContractLevelChecker.h> -#include <libsolidity/ast/AST.h> +#include <libsolidity/ast/AST.h> #include <liblangutil/ErrorReporter.h> - #include <boost/range/adaptor/reversed.hpp> diff --git a/libsolidity/analysis/ContractLevelChecker.h b/libsolidity/analysis/ContractLevelChecker.h index 15cbf45d..d754687a 100644 --- a/libsolidity/analysis/ContractLevelChecker.h +++ b/libsolidity/analysis/ContractLevelChecker.h @@ -22,7 +22,6 @@ #pragma once #include <libsolidity/ast/ASTForward.h> - #include <map> namespace langutil diff --git a/libsolidity/analysis/ControlFlowAnalyzer.cpp b/libsolidity/analysis/ControlFlowAnalyzer.cpp index a7e1ed97..3adf6318 100644 --- a/libsolidity/analysis/ControlFlowAnalyzer.cpp +++ b/libsolidity/analysis/ControlFlowAnalyzer.cpp @@ -16,6 +16,7 @@ */ #include <libsolidity/analysis/ControlFlowAnalyzer.h> + #include <liblangutil/SourceLocation.h> #include <boost/range/algorithm/sort.hpp> diff --git a/libsolidity/analysis/ControlFlowAnalyzer.h b/libsolidity/analysis/ControlFlowAnalyzer.h index 859d826a..7761817a 100644 --- a/libsolidity/analysis/ControlFlowAnalyzer.h +++ b/libsolidity/analysis/ControlFlowAnalyzer.h @@ -18,7 +18,6 @@ #pragma once #include <libsolidity/analysis/ControlFlowGraph.h> - #include <set> namespace dev diff --git a/libsolidity/analysis/ControlFlowGraph.cpp b/libsolidity/analysis/ControlFlowGraph.cpp index a7cc9508..8960166a 100644 --- a/libsolidity/analysis/ControlFlowGraph.cpp +++ b/libsolidity/analysis/ControlFlowGraph.cpp @@ -16,10 +16,9 @@ */ #include <libsolidity/analysis/ControlFlowGraph.h> -#include <libsolidity/analysis/ControlFlowBuilder.h> +#include <libsolidity/analysis/ControlFlowBuilder.h> #include <boost/range/adaptor/reversed.hpp> - #include <algorithm> using namespace std; diff --git a/libsolidity/analysis/DeclarationContainer.cpp b/libsolidity/analysis/DeclarationContainer.cpp index cf12a49d..d0657898 100644 --- a/libsolidity/analysis/DeclarationContainer.cpp +++ b/libsolidity/analysis/DeclarationContainer.cpp @@ -21,6 +21,7 @@ */ #include <libsolidity/analysis/DeclarationContainer.h> + #include <libsolidity/ast/AST.h> #include <libsolidity/ast/Types.h> #include <libdevcore/StringUtils.h> diff --git a/libsolidity/analysis/DeclarationContainer.h b/libsolidity/analysis/DeclarationContainer.h index 9d7a17a3..e26f5891 100644 --- a/libsolidity/analysis/DeclarationContainer.h +++ b/libsolidity/analysis/DeclarationContainer.h @@ -22,11 +22,10 @@ #pragma once +#include <libsolidity/ast/ASTForward.h> +#include <boost/noncopyable.hpp> #include <map> #include <set> -#include <boost/noncopyable.hpp> - -#include <libsolidity/ast/ASTForward.h> namespace dev { diff --git a/libsolidity/analysis/DocStringAnalyser.cpp b/libsolidity/analysis/DocStringAnalyser.cpp index 69a7a43c..0878b550 100644 --- a/libsolidity/analysis/DocStringAnalyser.cpp +++ b/libsolidity/analysis/DocStringAnalyser.cpp @@ -22,9 +22,10 @@ */ #include <libsolidity/analysis/DocStringAnalyser.h> + #include <libsolidity/ast/AST.h> -#include <liblangutil/ErrorReporter.h> #include <libsolidity/parsing/DocStringParser.h> +#include <liblangutil/ErrorReporter.h> using namespace std; using namespace dev; diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp index cba2655c..cd5fe07d 100644 --- a/libsolidity/analysis/GlobalContext.cpp +++ b/libsolidity/analysis/GlobalContext.cpp @@ -21,10 +21,11 @@ * Container of the (implicit and explicit) global objects. */ -#include <memory> #include <libsolidity/analysis/GlobalContext.h> + #include <libsolidity/ast/AST.h> #include <libsolidity/ast/Types.h> +#include <memory> using namespace std; diff --git a/libsolidity/analysis/GlobalContext.h b/libsolidity/analysis/GlobalContext.h index 4ed08711..09611c41 100644 --- a/libsolidity/analysis/GlobalContext.h +++ b/libsolidity/analysis/GlobalContext.h @@ -22,12 +22,12 @@ #pragma once -#include <string> -#include <vector> +#include <libsolidity/ast/ASTForward.h> +#include <boost/noncopyable.hpp> #include <map> #include <memory> -#include <boost/noncopyable.hpp> -#include <libsolidity/ast/ASTForward.h> +#include <string> +#include <vector> namespace dev { diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp index 0528a200..95bc69fe 100644 --- a/libsolidity/analysis/NameAndTypeResolver.cpp +++ b/libsolidity/analysis/NameAndTypeResolver.cpp @@ -22,11 +22,10 @@ #include <libsolidity/analysis/NameAndTypeResolver.h> -#include <libsolidity/ast/AST.h> #include <libsolidity/analysis/TypeChecker.h> +#include <libsolidity/ast/AST.h> #include <liblangutil/ErrorReporter.h> #include <libdevcore/StringUtils.h> - #include <boost/algorithm/string.hpp> using namespace std; diff --git a/libsolidity/analysis/NameAndTypeResolver.h b/libsolidity/analysis/NameAndTypeResolver.h index 1b034ef4..89c53932 100644 --- a/libsolidity/analysis/NameAndTypeResolver.h +++ b/libsolidity/analysis/NameAndTypeResolver.h @@ -22,13 +22,15 @@ #pragma once -#include <map> -#include <list> -#include <boost/noncopyable.hpp> #include <libsolidity/analysis/DeclarationContainer.h> #include <libsolidity/analysis/ReferencesResolver.h> -#include <libsolidity/ast/ASTVisitor.h> #include <libsolidity/ast/ASTAnnotations.h> +#include <libsolidity/ast/ASTVisitor.h> + +#include <boost/noncopyable.hpp> + +#include <list> +#include <map> namespace langutil { diff --git a/libsolidity/analysis/PostTypeChecker.cpp b/libsolidity/analysis/PostTypeChecker.cpp index 27cbcd45..6a7e5c7e 100644 --- a/libsolidity/analysis/PostTypeChecker.cpp +++ b/libsolidity/analysis/PostTypeChecker.cpp @@ -16,15 +16,14 @@ */ #include <libsolidity/analysis/PostTypeChecker.h> -#include <libsolidity/ast/AST.h> + #include <libsolidity/analysis/SemVerHandler.h> -#include <liblangutil/ErrorReporter.h> +#include <libsolidity/ast/AST.h> #include <libsolidity/interface/Version.h> - +#include <liblangutil/ErrorReporter.h> #include <libdevcore/Algorithms.h> #include <boost/range/adaptor/map.hpp> - #include <memory> using namespace std; diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp index 76641c04..4e6d7f59 100644 --- a/libsolidity/analysis/ReferencesResolver.cpp +++ b/libsolidity/analysis/ReferencesResolver.cpp @@ -21,13 +21,15 @@ */ #include <libsolidity/analysis/ReferencesResolver.h> -#include <libsolidity/ast/AST.h> #include <libsolidity/analysis/NameAndTypeResolver.h> #include <libsolidity/analysis/ConstantEvaluator.h> +#include <libsolidity/ast/AST.h> + #include <libyul/AsmAnalysis.h> #include <libyul/AsmAnalysisInfo.h> #include <libyul/AsmData.h> #include <libyul/backends/evm/EVMDialect.h> + #include <liblangutil/ErrorReporter.h> #include <liblangutil/Exceptions.h> diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h index 32c0553f..b3de9458 100644 --- a/libsolidity/analysis/ReferencesResolver.h +++ b/libsolidity/analysis/ReferencesResolver.h @@ -22,12 +22,13 @@ #pragma once -#include <map> -#include <list> -#include <boost/noncopyable.hpp> #include <libsolidity/ast/ASTVisitor.h> #include <libsolidity/ast/ASTAnnotations.h> +#include <boost/noncopyable.hpp> +#include <list> +#include <map> + namespace langutil { class ErrorReporter; diff --git a/libsolidity/analysis/SemVerHandler.cpp b/libsolidity/analysis/SemVerHandler.cpp index 64fa17b3..7c6ba91f 100644 --- a/libsolidity/analysis/SemVerHandler.cpp +++ b/libsolidity/analysis/SemVerHandler.cpp @@ -21,6 +21,7 @@ */ #include <libsolidity/analysis/SemVerHandler.h> + #include <functional> using namespace std; diff --git a/libsolidity/analysis/StaticAnalyzer.cpp b/libsolidity/analysis/StaticAnalyzer.cpp index 4d0f3461..aaaa4f9f 100644 --- a/libsolidity/analysis/StaticAnalyzer.cpp +++ b/libsolidity/analysis/StaticAnalyzer.cpp @@ -21,6 +21,7 @@ */ #include <libsolidity/analysis/StaticAnalyzer.h> + #include <libsolidity/analysis/ConstantEvaluator.h> #include <libsolidity/ast/AST.h> #include <liblangutil/ErrorReporter.h> diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index a73d7e5c..066b5004 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -16,15 +16,18 @@ */ #include <libsolidity/analysis/SyntaxChecker.h> -#include <memory> + +#include <libsolidity/analysis/SemVerHandler.h> #include <libsolidity/ast/AST.h> #include <libsolidity/ast/ExperimentalFeatures.h> -#include <libsolidity/analysis/SemVerHandler.h> -#include <liblangutil/ErrorReporter.h> #include <libsolidity/interface/Version.h> -#include <boost/algorithm/cxx11/all_of.hpp> +#include <liblangutil/ErrorReporter.h> + +#include <boost/algorithm/cxx11/all_of.hpp> #include <boost/algorithm/string.hpp> + +#include <memory> #include <string> using namespace std; @@ -111,7 +114,7 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma) vector<string> literals(_pragma.literals().begin() + 1, _pragma.literals().end()); SemVerMatchExpressionParser parser(tokens, literals); auto matchExpression = parser.parse(); - SemVerVersion currentVersion{string(VersionString)}; + static SemVerVersion const currentVersion{string(VersionString)}; if (!matchExpression.matches(currentVersion)) m_errorReporter.syntaxError( _pragma.location(), diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 5bd96f8d..507a2c94 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -26,7 +26,6 @@ #include <libyul/AsmAnalysis.h> #include <libyul/AsmAnalysisInfo.h> #include <libyul/AsmData.h> - #include <libyul/backends/evm/EVMDialect.h> #include <liblangutil/ErrorReporter.h> @@ -35,8 +34,8 @@ #include <libdevcore/StringUtils.h> #include <boost/algorithm/cxx11/all_of.hpp> -#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/join.hpp> +#include <boost/algorithm/string/predicate.hpp> #include <memory> #include <vector> diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h index ebfcdadc..b60c571a 100644 --- a/libsolidity/analysis/TypeChecker.h +++ b/libsolidity/analysis/TypeChecker.h @@ -24,10 +24,10 @@ #include <liblangutil/EVMVersion.h> -#include <libsolidity/ast/Types.h> #include <libsolidity/ast/ASTAnnotations.h> #include <libsolidity/ast/ASTForward.h> #include <libsolidity/ast/ASTVisitor.h> +#include <libsolidity/ast/Types.h> namespace langutil { diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index bd3071b3..eb019481 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -16,14 +16,10 @@ */ #include <libsolidity/analysis/ViewPureChecker.h> - -#include <libevmasm/SemanticInformation.h> - #include <libsolidity/ast/ExperimentalFeatures.h> #include <libyul/AsmData.h> - #include <liblangutil/ErrorReporter.h> - +#include <libevmasm/SemanticInformation.h> #include <functional> using namespace std; diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 5779e4ad..f379d758 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -21,13 +21,12 @@ */ #include <libsolidity/ast/AST.h> + #include <libsolidity/ast/ASTVisitor.h> #include <libsolidity/ast/AST_accept.h> - #include <libdevcore/Keccak256.h> #include <boost/algorithm/string.hpp> - #include <algorithm> #include <functional> diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 2f418b09..9ac065ea 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -22,24 +22,22 @@ #pragma once - -#include <libsolidity/parsing/Token.h> #include <libsolidity/ast/ASTForward.h> #include <libsolidity/ast/Types.h> #include <libsolidity/ast/ASTAnnotations.h> #include <libsolidity/ast/ASTEnums.h> +#include <libsolidity/parsing/Token.h> #include <liblangutil/SourceLocation.h> #include <libevmasm/Instruction.h> - #include <libdevcore/FixedHash.h> -#include <json/json.h> #include <boost/noncopyable.hpp> +#include <json/json.h> +#include <memory> #include <string> #include <vector> -#include <memory> namespace yul { diff --git a/libsolidity/ast/ASTAnnotations.h b/libsolidity/ast/ASTAnnotations.h index e9cc905e..33893a4f 100644 --- a/libsolidity/ast/ASTAnnotations.h +++ b/libsolidity/ast/ASTAnnotations.h @@ -27,8 +27,8 @@ #include <map> #include <memory> -#include <vector> #include <set> +#include <vector> namespace yul { diff --git a/libsolidity/ast/ASTForward.h b/libsolidity/ast/ASTForward.h index 992fe4cd..f61acad9 100644 --- a/libsolidity/ast/ASTForward.h +++ b/libsolidity/ast/ASTForward.h @@ -22,8 +22,8 @@ #pragma once -#include <string> #include <memory> +#include <string> #include <vector> // Forward-declare all AST node types diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp index 1a2b3345..f8222598 100644 --- a/libsolidity/ast/ASTJsonConverter.cpp +++ b/libsolidity/ast/ASTJsonConverter.cpp @@ -20,11 +20,12 @@ */ #include <libsolidity/ast/ASTJsonConverter.h> -#include <boost/algorithm/string/join.hpp> -#include <libdevcore/UTF8.h> + #include <libsolidity/ast/AST.h> #include <libyul/AsmData.h> #include <libyul/AsmPrinter.h> +#include <libdevcore/UTF8.h> +#include <boost/algorithm/string/join.hpp> using namespace std; using namespace langutil; diff --git a/libsolidity/ast/ASTJsonConverter.h b/libsolidity/ast/ASTJsonConverter.h index ef0a217a..770e3d9d 100644 --- a/libsolidity/ast/ASTJsonConverter.h +++ b/libsolidity/ast/ASTJsonConverter.h @@ -22,12 +22,13 @@ #pragma once -#include <ostream> -#include <stack> +#include <libsolidity/ast/ASTAnnotations.h> #include <libsolidity/ast/ASTVisitor.h> #include <liblangutil/Exceptions.h> -#include <libsolidity/ast/ASTAnnotations.h> + #include <json/json.h> +#include <ostream> +#include <stack> namespace langutil { diff --git a/libsolidity/ast/ASTPrinter.cpp b/libsolidity/ast/ASTPrinter.cpp index cdc6ae7d..d8bafa2c 100644 --- a/libsolidity/ast/ASTPrinter.cpp +++ b/libsolidity/ast/ASTPrinter.cpp @@ -21,11 +21,10 @@ */ #include <libsolidity/ast/ASTPrinter.h> -#include <libsolidity/ast/AST.h> - -#include <json/json.h> +#include <libsolidity/ast/AST.h> #include <boost/algorithm/string/join.hpp> +#include <json/json.h> using namespace std; using namespace langutil; diff --git a/libsolidity/ast/ASTPrinter.h b/libsolidity/ast/ASTPrinter.h index de3bf8a2..d762af47 100644 --- a/libsolidity/ast/ASTPrinter.h +++ b/libsolidity/ast/ASTPrinter.h @@ -22,9 +22,9 @@ #pragma once -#include <ostream> #include <libsolidity/ast/ASTVisitor.h> #include <libsolidity/interface/GasEstimator.h> +#include <ostream> namespace dev { diff --git a/libsolidity/ast/ASTVisitor.h b/libsolidity/ast/ASTVisitor.h index 1a761032..8cb94e05 100644 --- a/libsolidity/ast/ASTVisitor.h +++ b/libsolidity/ast/ASTVisitor.h @@ -22,10 +22,10 @@ #pragma once -#include <string> +#include <libsolidity/ast/AST.h> #include <functional> +#include <string> #include <vector> -#include <libsolidity/ast/AST.h> namespace dev { diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index c35dde3c..cc978b4a 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -24,22 +24,22 @@ #include <libsolidity/ast/AST.h> -#include <libdevcore/CommonIO.h> +#include <libdevcore/Algorithms.h> #include <libdevcore/CommonData.h> +#include <libdevcore/CommonIO.h> #include <libdevcore/Keccak256.h> #include <libdevcore/UTF8.h> -#include <libdevcore/Algorithms.h> +#include <boost/algorithm/string.hpp> +#include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/join.hpp> -#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/predicate.hpp> -#include <boost/algorithm/string/classification.hpp> +#include <boost/algorithm/string/replace.hpp> #include <boost/algorithm/string/split.hpp> #include <boost/range/adaptor/reversed.hpp> -#include <boost/range/algorithm/copy.hpp> #include <boost/range/adaptor/sliced.hpp> #include <boost/range/adaptor/transformed.hpp> -#include <boost/algorithm/string.hpp> +#include <boost/range/algorithm/copy.hpp> #include <limits> diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 39157abe..ac1487b2 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -22,23 +22,23 @@ #pragma once -#include <liblangutil/Exceptions.h> -#include <libsolidity/ast/ASTForward.h> #include <libsolidity/ast/ASTEnums.h> +#include <libsolidity/ast/ASTForward.h> #include <libsolidity/parsing/Token.h> +#include <liblangutil/Exceptions.h> #include <libdevcore/Common.h> #include <libdevcore/CommonIO.h> #include <libdevcore/Result.h> +#include <boost/optional.hpp> #include <boost/noncopyable.hpp> #include <boost/rational.hpp> -#include <boost/optional.hpp> -#include <memory> -#include <string> #include <map> +#include <memory> #include <set> +#include <string> namespace dev { diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index 5000131c..c1ab03e3 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -24,7 +24,6 @@ #include <libsolidity/ast/AST.h> #include <libsolidity/codegen/CompilerUtils.h> - #include <libdevcore/Whiskers.h> #include <boost/algorithm/string/join.hpp> diff --git a/libsolidity/codegen/ABIFunctions.h b/libsolidity/codegen/ABIFunctions.h index d2132258..1e0cf7fa 100644 --- a/libsolidity/codegen/ABIFunctions.h +++ b/libsolidity/codegen/ABIFunctions.h @@ -22,14 +22,13 @@ #pragma once -#include <liblangutil/EVMVersion.h> - #include <libsolidity/ast/ASTForward.h> +#include <liblangutil/EVMVersion.h> -#include <vector> #include <functional> -#include <set> #include <map> +#include <set> +#include <vector> namespace dev { namespace solidity { diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index 4878f9f3..f9678f7c 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -21,13 +21,15 @@ */ #include <libsolidity/codegen/ArrayUtils.h> -#include <libevmasm/Instruction.h> + +#include <libsolidity/ast/Types.h> #include <libsolidity/codegen/CompilerContext.h> #include <libsolidity/codegen/CompilerUtils.h> -#include <libsolidity/ast/Types.h> -#include <liblangutil/Exceptions.h> #include <libsolidity/codegen/LValue.h> +#include <libevmasm/Instruction.h> +#include <liblangutil/Exceptions.h> + using namespace std; using namespace dev; using namespace langutil; diff --git a/libsolidity/codegen/AsmCodeGen.h b/libsolidity/codegen/AsmCodeGen.h index 303d32ee..516b0a36 100644 --- a/libsolidity/codegen/AsmCodeGen.h +++ b/libsolidity/codegen/AsmCodeGen.h @@ -22,9 +22,7 @@ #include <libyul/AsmAnalysis.h> #include <libyul/backends/evm/AbstractAssembly.h> - #include <liblangutil/SourceLocation.h> - #include <functional> namespace yul diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp index fe57cff6..a22e6e9d 100644 --- a/libsolidity/codegen/Compiler.cpp +++ b/libsolidity/codegen/Compiler.cpp @@ -21,8 +21,9 @@ */ #include <libsolidity/codegen/Compiler.h> -#include <libevmasm/Assembly.h> + #include <libsolidity/codegen/ContractCompiler.h> +#include <libevmasm/Assembly.h> using namespace std; using namespace dev; diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h index 48d9e9d6..784d7f8c 100644 --- a/libsolidity/codegen/Compiler.h +++ b/libsolidity/codegen/Compiler.h @@ -24,11 +24,9 @@ #include <libsolidity/codegen/CompilerContext.h> #include <liblangutil/EVMVersion.h> - #include <libevmasm/Assembly.h> - -#include <ostream> #include <functional> +#include <ostream> namespace dev { namespace solidity { diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp index 0b018e1e..be681b2e 100644 --- a/libsolidity/codegen/CompilerContext.cpp +++ b/libsolidity/codegen/CompilerContext.cpp @@ -21,19 +21,22 @@ */ #include <libsolidity/codegen/CompilerContext.h> -#include <libsolidity/codegen/CompilerUtils.h> + #include <libsolidity/ast/AST.h> -#include <libsolidity/codegen/Compiler.h> #include <libsolidity/codegen/AsmCodeGen.h> +#include <libsolidity/codegen/Compiler.h> +#include <libsolidity/codegen/CompilerUtils.h> #include <libsolidity/interface/Version.h> -#include <liblangutil/SourceReferenceFormatter.h> + #include <libyul/AsmParser.h> #include <libyul/AsmAnalysis.h> #include <libyul/AsmAnalysisInfo.h> -#include <libyul/YulString.h> #include <libyul/backends/evm/EVMDialect.h> +#include <libyul/YulString.h> + #include <liblangutil/ErrorReporter.h> #include <liblangutil/Scanner.h> +#include <liblangutil/SourceReferenceFormatter.h> #include <boost/algorithm/string/replace.hpp> diff --git a/libsolidity/codegen/CompilerContext.h b/libsolidity/codegen/CompilerContext.h index 02369813..dedcd95f 100644 --- a/libsolidity/codegen/CompilerContext.h +++ b/libsolidity/codegen/CompilerContext.h @@ -22,24 +22,21 @@ #pragma once -#include <libsolidity/codegen/ABIFunctions.h> - -#include <liblangutil/EVMVersion.h> - +#include <libsolidity/ast/ASTAnnotations.h> #include <libsolidity/ast/ASTForward.h> #include <libsolidity/ast/Types.h> -#include <libsolidity/ast/ASTAnnotations.h> +#include <libsolidity/codegen/ABIFunctions.h> -#include <libevmasm/Instruction.h> #include <libevmasm/Assembly.h> - +#include <libevmasm/Instruction.h> +#include <liblangutil/EVMVersion.h> #include <libdevcore/Common.h> +#include <functional> #include <ostream> #include <stack> #include <queue> #include <utility> -#include <functional> namespace dev { namespace solidity { diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 259f1620..bbc703c7 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -23,12 +23,10 @@ #include <libsolidity/codegen/CompilerUtils.h> #include <libsolidity/ast/AST.h> +#include <libsolidity/codegen/ABIFunctions.h> #include <libsolidity/codegen/ArrayUtils.h> #include <libsolidity/codegen/LValue.h> -#include <libsolidity/codegen/ABIFunctions.h> - #include <libevmasm/Instruction.h> - #include <libdevcore/Whiskers.h> using namespace std; diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index 5f7dce22..7e4f47ba 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -22,8 +22,8 @@ #pragma once -#include <libsolidity/codegen/CompilerContext.h> #include <libsolidity/ast/ASTForward.h> +#include <libsolidity/codegen/CompilerContext.h> namespace dev { namespace solidity { diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index 67876721..b051d260 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -20,19 +20,18 @@ * Solidity compiler. */ +#include <libsolidity/ast/AST.h> +#include <libsolidity/codegen/AsmCodeGen.h> +#include <libsolidity/codegen/CompilerUtils.h> #include <libsolidity/codegen/ContractCompiler.h> #include <libsolidity/codegen/ExpressionCompiler.h> -#include <libsolidity/codegen/CompilerUtils.h> -#include <libsolidity/codegen/AsmCodeGen.h> -#include <libsolidity/ast/AST.h> -#include <liblangutil/ErrorReporter.h> #include <libevmasm/Instruction.h> #include <libevmasm/Assembly.h> #include <libevmasm/GasMeter.h> +#include <liblangutil/ErrorReporter.h> #include <boost/range/adaptor/reversed.hpp> - #include <algorithm> using namespace std; @@ -332,6 +331,25 @@ void ContractCompiler::appendInternalSelector( } } +namespace +{ + +// Helper function to check if any function is payable +bool hasPayableFunctions(ContractDefinition const& _contract) +{ + FunctionDefinition const* fallback = _contract.fallbackFunction(); + if (fallback && fallback->isPayable()) + return true; + + for (auto const& it: _contract.interfaceFunctions()) + if (it.second->isPayable()) + return true; + + return false; +} + +} + void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contract) { map<FixedHash<4>, FunctionTypePointer> interfaceFunctions = _contract.interfaceFunctions(); @@ -343,6 +361,15 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac } FunctionDefinition const* fallback = _contract.fallbackFunction(); + solAssert(!_contract.isLibrary() || !fallback, "Libraries can't have fallback functions"); + + bool needToAddCallvalueCheck = true; + if (!hasPayableFunctions(_contract) && !interfaceFunctions.empty() && !_contract.isLibrary()) + { + appendCallValueCheck(); + needToAddCallvalueCheck = false; + } + eth::AssemblyItem notFound = m_context.newTag(); // directly jump to fallback if the data is too short to contain a function selector // also guards against short data @@ -351,23 +378,26 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac // retrieve the function signature hash from the calldata if (!interfaceFunctions.empty()) + { CompilerUtils(m_context).loadFromMemory(0, IntegerType(CompilerUtils::dataStartOffset * 8), true); - // stack now is: <can-call-non-view-functions>? <funhash> - vector<FixedHash<4>> sortedIDs; - for (auto const& it: interfaceFunctions) - { - callDataUnpackerEntryPoints.insert(std::make_pair(it.first, m_context.newTag())); - sortedIDs.emplace_back(it.first); + // stack now is: <can-call-non-view-functions>? <funhash> + vector<FixedHash<4>> sortedIDs; + for (auto const& it: interfaceFunctions) + { + callDataUnpackerEntryPoints.emplace(it.first, m_context.newTag()); + sortedIDs.emplace_back(it.first); + } + std::sort(sortedIDs.begin(), sortedIDs.end()); + appendInternalSelector(callDataUnpackerEntryPoints, sortedIDs, notFound, m_optimise_runs); } - std::sort(sortedIDs.begin(), sortedIDs.end()); - appendInternalSelector(callDataUnpackerEntryPoints, sortedIDs, notFound, m_optimise_runs); m_context << notFound; + if (fallback) { solAssert(!_contract.isLibrary(), ""); - if (!fallback->isPayable()) + if (!fallback->isPayable() && needToAddCallvalueCheck) appendCallValueCheck(); solAssert(fallback->isFallback(), ""); @@ -397,7 +427,7 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac m_context.setStackOffset(0); // We have to allow this for libraries, because value of the previous // call is still visible in the delegatecall. - if (!functionType->isPayable() && !_contract.isLibrary()) + if (!functionType->isPayable() && !_contract.isLibrary() && needToAddCallvalueCheck) appendCallValueCheck(); // Return tag is used to jump out of the function. diff --git a/libsolidity/codegen/ContractCompiler.h b/libsolidity/codegen/ContractCompiler.h index 266ace0b..40871f0d 100644 --- a/libsolidity/codegen/ContractCompiler.h +++ b/libsolidity/codegen/ContractCompiler.h @@ -22,11 +22,11 @@ #pragma once -#include <ostream> -#include <functional> #include <libsolidity/ast/ASTVisitor.h> #include <libsolidity/codegen/CompilerContext.h> #include <libevmasm/Assembly.h> +#include <functional> +#include <ostream> namespace dev { namespace solidity { diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 121585d9..46359f2b 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -20,21 +20,23 @@ * Solidity AST to EVM bytecode compiler for expressions. */ -#include <utility> -#include <numeric> -#include <boost/range/adaptor/reversed.hpp> -#include <boost/algorithm/string/replace.hpp> -#include <libdevcore/Common.h> -#include <libdevcore/Keccak256.h> -#include <libsolidity/ast/AST.h> #include <libsolidity/codegen/ExpressionCompiler.h> + +#include <libsolidity/ast/AST.h> #include <libsolidity/codegen/CompilerContext.h> #include <libsolidity/codegen/CompilerUtils.h> #include <libsolidity/codegen/LValue.h> -#include <libevmasm/GasMeter.h> +#include <libevmasm/GasMeter.h> +#include <libdevcore/Common.h> +#include <libdevcore/Keccak256.h> #include <libdevcore/Whiskers.h> +#include <boost/algorithm/string/replace.hpp> +#include <boost/range/adaptor/reversed.hpp> +#include <numeric> +#include <utility> + using namespace std; using namespace langutil; diff --git a/libsolidity/codegen/ExpressionCompiler.h b/libsolidity/codegen/ExpressionCompiler.h index e9345ece..4a6e43ff 100644 --- a/libsolidity/codegen/ExpressionCompiler.h +++ b/libsolidity/codegen/ExpressionCompiler.h @@ -23,14 +23,15 @@ #pragma once -#include <functional> -#include <memory> -#include <boost/noncopyable.hpp> -#include <libdevcore/Common.h> -#include <liblangutil/SourceLocation.h> #include <libsolidity/ast/ASTVisitor.h> #include <libsolidity/codegen/LValue.h> #include <liblangutil/Exceptions.h> +#include <liblangutil/SourceLocation.h> +#include <libdevcore/Common.h> + +#include <boost/noncopyable.hpp> +#include <functional> +#include <memory> namespace dev { namespace eth diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 6d71d36f..70dbee81 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -21,10 +21,11 @@ */ #include <libsolidity/codegen/LValue.h> -#include <libevmasm/Instruction.h> -#include <libsolidity/ast/Types.h> + #include <libsolidity/ast/AST.h> +#include <libsolidity/ast/Types.h> #include <libsolidity/codegen/CompilerUtils.h> +#include <libevmasm/Instruction.h> using namespace std; using namespace dev; diff --git a/libsolidity/codegen/LValue.h b/libsolidity/codegen/LValue.h index d854857b..3b44597f 100644 --- a/libsolidity/codegen/LValue.h +++ b/libsolidity/codegen/LValue.h @@ -22,10 +22,10 @@ #pragma once +#include <libsolidity/codegen/ArrayUtils.h> +#include <liblangutil/SourceLocation.h> #include <memory> #include <vector> -#include <liblangutil/SourceLocation.h> -#include <libsolidity/codegen/ArrayUtils.h> namespace dev { diff --git a/libsolidity/formal/CVC4Interface.cpp b/libsolidity/formal/CVC4Interface.cpp index de5e4430..e7c8f015 100644 --- a/libsolidity/formal/CVC4Interface.cpp +++ b/libsolidity/formal/CVC4Interface.cpp @@ -18,7 +18,6 @@ #include <libsolidity/formal/CVC4Interface.h> #include <liblangutil/Exceptions.h> - #include <libdevcore/CommonIO.h> using namespace std; diff --git a/libsolidity/formal/CVC4Interface.h b/libsolidity/formal/CVC4Interface.h index bbe23855..89792364 100644 --- a/libsolidity/formal/CVC4Interface.h +++ b/libsolidity/formal/CVC4Interface.h @@ -18,7 +18,6 @@ #pragma once #include <libsolidity/formal/SolverInterface.h> - #include <boost/noncopyable.hpp> #if defined(__GLIBC__) diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp index dc14f4c2..35c1e2f1 100644 --- a/libsolidity/formal/SMTChecker.cpp +++ b/libsolidity/formal/SMTChecker.cpp @@ -18,12 +18,10 @@ #include <libsolidity/formal/SMTChecker.h> #include <libsolidity/formal/SMTPortfolio.h> - #include <libsolidity/formal/VariableUsage.h> #include <libsolidity/formal/SymbolicTypes.h> #include <liblangutil/ErrorReporter.h> - #include <libdevcore/StringUtils.h> #include <boost/range/adaptor/map.hpp> @@ -60,8 +58,7 @@ void SMTChecker::analyze(SourceUnit const& _source, shared_ptr<Scanner> const& _ bool SMTChecker::visit(ContractDefinition const& _contract) { for (auto _var : _contract.stateVariables()) - if (_var->type()->isValueType()) - createVariable(*_var); + createVariable(*_var); return true; } @@ -94,9 +91,10 @@ bool SMTChecker::visit(FunctionDefinition const& _function) m_uninterpretedTerms.clear(); resetStateVariables(); initializeLocalVariables(_function); + m_loopExecutionHappened = false; + m_arrayAssignmentHappened = false; } - m_loopExecutionHappened = false; return true; } @@ -271,6 +269,11 @@ void SMTChecker::endVisit(Assignment const& _assignment) assignment(decl, _assignment.rightHandSide(), _assignment.location()); defineExpr(_assignment, expr(_assignment.rightHandSide())); } + else if (dynamic_cast<IndexAccess const*>(&_assignment.leftHandSide())) + { + arrayIndexAssignment(_assignment); + defineExpr(_assignment, expr(_assignment.rightHandSide())); + } else m_errorReporter.warning( _assignment.location(), @@ -459,6 +462,13 @@ void SMTChecker::visitGasLeft(FunctionCall const& _funCall) m_interface->addAssertion(symbolicVar->currentValue() <= symbolicVar->valueAtIndex(index - 1)); } +void SMTChecker::eraseArrayKnowledge() +{ + for (auto const& var: m_variables) + if (var.first->annotation().type->category() == Type::Category::Mapping) + newValue(*var.first); +} + void SMTChecker::inlineFunctionCall(FunctionCall const& _funCall) { FunctionDefinition const* _funDef = nullptr; @@ -532,7 +542,7 @@ void SMTChecker::abstractFunctionCall(FunctionCall const& _funCall) for (auto const& arg: _funCall.arguments()) smtArguments.push_back(expr(*arg)); defineExpr(_funCall, (*m_expressions.at(&_funCall.expression()))(smtArguments)); - m_uninterpretedTerms.push_back(&_funCall); + m_uninterpretedTerms.insert(&_funCall); setSymbolicUnknownValue(expr(_funCall), _funCall.annotation().type, *m_interface); } @@ -638,6 +648,74 @@ bool SMTChecker::visit(MemberAccess const& _memberAccess) return true; } +void SMTChecker::endVisit(IndexAccess const& _indexAccess) +{ + shared_ptr<SymbolicVariable> array; + if (auto const& id = dynamic_cast<Identifier const*>(&_indexAccess.baseExpression())) + { + auto const& varDecl = dynamic_cast<VariableDeclaration const&>(*id->annotation().referencedDeclaration); + solAssert(knownVariable(varDecl), ""); + array = m_variables[&varDecl]; + } + else if (auto const& innerAccess = dynamic_cast<IndexAccess const*>(&_indexAccess.baseExpression())) + { + solAssert(knownExpr(*innerAccess), ""); + array = m_expressions[innerAccess]; + } + else + { + m_errorReporter.warning( + _indexAccess.location(), + "Assertion checker does not yet implement this expression." + ); + return; + } + + solAssert(array, ""); + defineExpr(_indexAccess, smt::Expression::select( + array->currentValue(), + expr(*_indexAccess.indexExpression()) + )); + setSymbolicUnknownValue( + expr(_indexAccess), + _indexAccess.annotation().type, + *m_interface + ); + m_uninterpretedTerms.insert(&_indexAccess); +} + +void SMTChecker::arrayAssignment() +{ + m_arrayAssignmentHappened = true; + eraseArrayKnowledge(); +} + +void SMTChecker::arrayIndexAssignment(Assignment const& _assignment) +{ + auto const& indexAccess = dynamic_cast<IndexAccess const&>(_assignment.leftHandSide()); + if (auto const& id = dynamic_cast<Identifier const*>(&indexAccess.baseExpression())) + { + auto const& varDecl = dynamic_cast<VariableDeclaration const&>(*id->annotation().referencedDeclaration); + solAssert(knownVariable(varDecl), ""); + smt::Expression store = smt::Expression::store( + m_variables[&varDecl]->currentValue(), + expr(*indexAccess.indexExpression()), + expr(_assignment.rightHandSide()) + ); + m_interface->addAssertion(newValue(varDecl) == store); + } + else if (dynamic_cast<IndexAccess const*>(&indexAccess.baseExpression())) + m_errorReporter.warning( + indexAccess.location(), + "Assertion checker does not yet implement assignments to multi-dimensional mappings or arrays." + ); + else + m_errorReporter.warning( + _assignment.location(), + "Assertion checker does not yet implement this expression." + ); +} + void SMTChecker::defineGlobalVariable(string const& _name, Expression const& _expr, bool _increaseIndex) { if (!knownGlobalSymbol(_name)) @@ -803,6 +881,8 @@ void SMTChecker::assignment(VariableDeclaration const& _variable, smt::Expressio checkUnderOverflow(_value, *intType, _location); else if (dynamic_cast<AddressType const*>(type.get())) checkUnderOverflow(_value, IntegerType(160), _location); + else if (dynamic_cast<MappingType const*>(type.get())) + arrayAssignment(); m_interface->addAssertion(newValue(_variable) == _value); } @@ -847,12 +927,19 @@ void SMTChecker::checkCondition( } for (auto const& var: m_variables) { - expressionsToEvaluate.emplace_back(currentValue(*var.first)); - expressionNames.push_back(var.first->name()); + if (var.first->type()->isValueType()) + { + expressionsToEvaluate.emplace_back(currentValue(*var.first)); + expressionNames.push_back(var.first->name()); + } } for (auto const& var: m_globalContext) { - if (smtKind(var.second->type()->category()) != smt::Kind::Function) + auto const& type = var.second->type(); + if ( + type->isValueType() && + smtKind(type->category()) != smt::Kind::Function + ) { expressionsToEvaluate.emplace_back(var.second->currentValue()); expressionNames.push_back(var.first); @@ -860,8 +947,11 @@ void SMTChecker::checkCondition( } for (auto const& uf: m_uninterpretedTerms) { - expressionsToEvaluate.emplace_back(expr(*uf)); - expressionNames.push_back(m_scanner->sourceAt(uf->location())); + if (uf->annotation().type->isValueType()) + { + expressionsToEvaluate.emplace_back(expr(*uf)); + expressionNames.push_back(m_scanner->sourceAt(uf->location())); + } } } smt::CheckResult result; @@ -873,6 +963,12 @@ void SMTChecker::checkCondition( loopComment = "\nNote that some information is erased after the execution of loops.\n" "You can re-introduce information using require()."; + if (m_arrayAssignmentHappened) + loopComment += + "\nNote that array aliasing is not supported," + " therefore all mapping information is erased after" + " a mapping local variable/parameter is assigned.\n" + "You can re-introduce information using require()."; switch (result) { @@ -1006,7 +1102,11 @@ void SMTChecker::initializeFunctionCallParameters(FunctionDefinition const& _fun solAssert(funParams.size() == _callArgs.size(), ""); for (unsigned i = 0; i < funParams.size(); ++i) if (createVariable(*funParams[i])) + { m_interface->addAssertion(_callArgs[i] == newValue(*funParams[i])); + if (funParams[i]->annotation().type->category() == Type::Category::Mapping) + m_arrayAssignmentHappened = true; + } for (auto const& variable: _function.localVariables()) if (createVariable(*variable)) diff --git a/libsolidity/formal/SMTChecker.h b/libsolidity/formal/SMTChecker.h index 9f8c04ab..f14d2ac0 100644 --- a/libsolidity/formal/SMTChecker.h +++ b/libsolidity/formal/SMTChecker.h @@ -22,13 +22,11 @@ #include <libsolidity/formal/SymbolicVariables.h> #include <libsolidity/ast/ASTVisitor.h> - #include <libsolidity/interface/ReadFile.h> - #include <liblangutil/Scanner.h> -#include <unordered_map> #include <string> +#include <unordered_map> #include <vector> namespace langutil @@ -79,6 +77,7 @@ private: void endVisit(Literal const& _node) override; void endVisit(Return const& _node) override; bool visit(MemberAccess const& _node) override; + void endVisit(IndexAccess const& _node) override; void arithmeticOperation(BinaryOperation const& _op); void compareOperation(BinaryOperation const& _op); @@ -96,6 +95,14 @@ private: void defineGlobalVariable(std::string const& _name, Expression const& _expr, bool _increaseIndex = false); void defineGlobalFunction(std::string const& _name, Expression const& _expr); + /// Handles the side effects of assignment + /// to variable of some SMT array type + /// while aliasing is not supported. + void arrayAssignment(); + /// Handles assignment to SMT array index. + void arrayIndexAssignment(Assignment const& _assignment); + /// Erases information about SMT arrays. + void eraseArrayKnowledge(); /// Division expression in the given type. Requires special treatment because /// of rounding for signed division. @@ -203,14 +210,16 @@ private: std::shared_ptr<smt::SolverInterface> m_interface; std::shared_ptr<VariableUsage> m_variableUsage; bool m_loopExecutionHappened = false; + bool m_arrayAssignmentHappened = false; /// An Expression may have multiple smt::Expression due to /// repeated calls to the same function. std::unordered_map<Expression const*, std::shared_ptr<SymbolicVariable>> m_expressions; std::unordered_map<VariableDeclaration const*, std::shared_ptr<SymbolicVariable>> m_variables; std::unordered_map<std::string, std::shared_ptr<SymbolicVariable>> m_globalContext; /// Stores the instances of an Uninterpreted Function applied to arguments. + /// These may be direct application of UFs or Array index access. /// Used to retrieve models. - std::vector<Expression const*> m_uninterpretedTerms; + std::set<Expression const*> m_uninterpretedTerms; std::vector<smt::Expression> m_pathConditions; langutil::ErrorReporter& m_errorReporter; std::shared_ptr<langutil::Scanner> m_scanner; diff --git a/libsolidity/formal/SMTLib2Interface.cpp b/libsolidity/formal/SMTLib2Interface.cpp index 3cfa01b1..a23dbe55 100644 --- a/libsolidity/formal/SMTLib2Interface.cpp +++ b/libsolidity/formal/SMTLib2Interface.cpp @@ -17,22 +17,20 @@ #include <libsolidity/formal/SMTLib2Interface.h> -#include <liblangutil/Exceptions.h> #include <libsolidity/interface/ReadFile.h> - +#include <liblangutil/Exceptions.h> #include <libdevcore/Keccak256.h> -#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/join.hpp> +#include <boost/algorithm/string/predicate.hpp> #include <boost/filesystem/operations.hpp> -#include <cstdio> +#include <array> #include <fstream> #include <iostream> #include <memory> #include <stdexcept> #include <string> -#include <array> using namespace std; using namespace dev; diff --git a/libsolidity/formal/SMTLib2Interface.h b/libsolidity/formal/SMTLib2Interface.h index 55fc4096..d0bf4702 100644 --- a/libsolidity/formal/SMTLib2Interface.h +++ b/libsolidity/formal/SMTLib2Interface.h @@ -19,20 +19,17 @@ #include <libsolidity/formal/SolverInterface.h> -#include <liblangutil/Exceptions.h> #include <libsolidity/interface/ReadFile.h> - -#include <libdevcore/FixedHash.h> - +#include <liblangutil/Exceptions.h> #include <libdevcore/Common.h> +#include <libdevcore/FixedHash.h> #include <boost/noncopyable.hpp> - +#include <cstdio> #include <map> +#include <set> #include <string> #include <vector> -#include <cstdio> -#include <set> namespace dev { diff --git a/libsolidity/formal/SMTPortfolio.h b/libsolidity/formal/SMTPortfolio.h index 7f5ba37e..8c38bd2e 100644 --- a/libsolidity/formal/SMTPortfolio.h +++ b/libsolidity/formal/SMTPortfolio.h @@ -19,13 +19,10 @@ #include <libsolidity/formal/SolverInterface.h> - #include <libsolidity/interface/ReadFile.h> - #include <libdevcore/FixedHash.h> #include <boost/noncopyable.hpp> - #include <map> #include <vector> diff --git a/libsolidity/formal/SolverInterface.h b/libsolidity/formal/SolverInterface.h index 4a4b3fb1..6e0b17ac 100644 --- a/libsolidity/formal/SolverInterface.h +++ b/libsolidity/formal/SolverInterface.h @@ -17,18 +17,16 @@ #pragma once -#include <liblangutil/Exceptions.h> #include <libsolidity/interface/ReadFile.h> - +#include <liblangutil/Exceptions.h> #include <libdevcore/Common.h> #include <libdevcore/Exceptions.h> #include <boost/noncopyable.hpp> - +#include <cstdio> #include <map> #include <string> #include <vector> -#include <cstdio> namespace dev { @@ -80,6 +78,8 @@ struct FunctionSort: public Sort [&](SortPointer _a, SortPointer _b) { return *_a == *_b; } )) return false; + solAssert(codomain, ""); + solAssert(_otherFunction->codomain, ""); return *codomain == *_otherFunction->codomain; } @@ -99,6 +99,10 @@ struct ArraySort: public Sort return false; auto _otherArray = dynamic_cast<ArraySort const*>(&_other); solAssert(_otherArray, ""); + solAssert(_otherArray->domain, ""); + solAssert(_otherArray->range, ""); + solAssert(domain, ""); + solAssert(range, ""); return *domain == *_otherArray->domain && *range == *_otherArray->range; } @@ -161,8 +165,9 @@ public: static Expression select(Expression _array, Expression _index) { solAssert(_array.sort->kind == Kind::Array, ""); - auto const& arraySort = dynamic_cast<ArraySort const*>(_array.sort.get()); + std::shared_ptr<ArraySort> arraySort = std::dynamic_pointer_cast<ArraySort>(_array.sort); solAssert(arraySort, ""); + solAssert(_index.sort, ""); solAssert(*arraySort->domain == *_index.sort, ""); return Expression( "select", @@ -176,14 +181,16 @@ public: static Expression store(Expression _array, Expression _index, Expression _element) { solAssert(_array.sort->kind == Kind::Array, ""); - auto const& arraySort = dynamic_cast<ArraySort const*>(_array.sort.get()); + std::shared_ptr<ArraySort> arraySort = std::dynamic_pointer_cast<ArraySort>(_array.sort); solAssert(arraySort, ""); + solAssert(_index.sort, ""); + solAssert(_element.sort, ""); solAssert(*arraySort->domain == *_index.sort, ""); solAssert(*arraySort->range == *_element.sort, ""); return Expression( "store", std::vector<Expression>{std::move(_array), std::move(_index), std::move(_element)}, - _array.sort + arraySort ); } diff --git a/libsolidity/formal/SymbolicTypes.cpp b/libsolidity/formal/SymbolicTypes.cpp index 3cfaa271..269bff73 100644 --- a/libsolidity/formal/SymbolicTypes.cpp +++ b/libsolidity/formal/SymbolicTypes.cpp @@ -18,7 +18,6 @@ #include <libsolidity/formal/SymbolicTypes.h> #include <libsolidity/ast/Types.h> - #include <memory> using namespace std; @@ -52,13 +51,19 @@ smt::SortPointer dev::solidity::smtSort(Type const& _type) } case smt::Kind::Array: { - solUnimplementedAssert(false, "Invalid type"); + if (isMapping(_type.category())) + { + auto mapType = dynamic_cast<MappingType const*>(&_type); + solAssert(mapType, ""); + return make_shared<smt::ArraySort>(smtSort(*mapType->keyType()), smtSort(*mapType->valueType())); + } + // TODO Solidity array + return make_shared<smt::Sort>(smt::Kind::Int); } default: // Abstract case. return make_shared<smt::Sort>(smt::Kind::Int); } - solAssert(false, "Invalid type"); } vector<smt::SortPointer> dev::solidity::smtSort(vector<TypePointer> const& _types) @@ -77,6 +82,8 @@ smt::Kind dev::solidity::smtKind(Type::Category _category) return smt::Kind::Bool; else if (isFunction(_category)) return smt::Kind::Function; + else if (isMapping(_category)) + return smt::Kind::Array; // Abstract case. return smt::Kind::Int; } @@ -84,7 +91,8 @@ smt::Kind dev::solidity::smtKind(Type::Category _category) bool dev::solidity::isSupportedType(Type::Category _category) { return isNumber(_category) || - isBool(_category); + isBool(_category) || + isMapping(_category); } bool dev::solidity::isSupportedTypeDeclaration(Type::Category _category) @@ -130,6 +138,8 @@ pair<bool, shared_ptr<SymbolicVariable>> dev::solidity::newSymbolicVariable( else var = make_shared<SymbolicIntVariable>(type, _uniqueName, _solver); } + else if (isMapping(_type.category())) + var = make_shared<SymbolicMappingVariable>(type, _uniqueName, _solver); else solAssert(false, ""); return make_pair(abstract, var); @@ -183,6 +193,11 @@ bool dev::solidity::isFunction(Type::Category _category) return _category == Type::Category::Function; } +bool dev::solidity::isMapping(Type::Category _category) +{ + return _category == Type::Category::Mapping; +} + smt::Expression dev::solidity::minValue(IntegerType const& _type) { return smt::Expression(_type.minValue()); diff --git a/libsolidity/formal/SymbolicTypes.h b/libsolidity/formal/SymbolicTypes.h index 2c568f5b..35c7bb8d 100644 --- a/libsolidity/formal/SymbolicTypes.h +++ b/libsolidity/formal/SymbolicTypes.h @@ -19,7 +19,6 @@ #include <libsolidity/formal/SolverInterface.h> #include <libsolidity/formal/SymbolicVariables.h> - #include <libsolidity/ast/AST.h> #include <libsolidity/ast/Types.h> @@ -48,6 +47,7 @@ bool isAddress(Type::Category _category); bool isNumber(Type::Category _category); bool isBool(Type::Category _category); bool isFunction(Type::Category _category); +bool isMapping(Type::Category _category); /// Returns a new symbolic variable, according to _type. /// Also returns whether the type is abstract or not, diff --git a/libsolidity/formal/SymbolicVariables.cpp b/libsolidity/formal/SymbolicVariables.cpp index 997635af..c4fc81da 100644 --- a/libsolidity/formal/SymbolicVariables.cpp +++ b/libsolidity/formal/SymbolicVariables.cpp @@ -18,7 +18,6 @@ #include <libsolidity/formal/SymbolicVariables.h> #include <libsolidity/formal/SymbolicTypes.h> - #include <libsolidity/ast/AST.h> using namespace std; @@ -127,3 +126,13 @@ smt::Expression SymbolicFunctionVariable::operator()(vector<smt::Expression> _ar { return m_declaration(_arguments); } + +SymbolicMappingVariable::SymbolicMappingVariable( + TypePointer _type, + string const& _uniqueName, + smt::SolverInterface& _interface +): + SymbolicVariable(move(_type), _uniqueName, _interface) +{ + solAssert(isMapping(m_type->category()), ""); +} diff --git a/libsolidity/formal/SymbolicVariables.h b/libsolidity/formal/SymbolicVariables.h index 6754ee07..86abf4f1 100644 --- a/libsolidity/formal/SymbolicVariables.h +++ b/libsolidity/formal/SymbolicVariables.h @@ -17,12 +17,9 @@ #pragma once -#include <libsolidity/formal/SSAVariable.h> - #include <libsolidity/formal/SolverInterface.h> - +#include <libsolidity/formal/SSAVariable.h> #include <libsolidity/ast/Types.h> - #include <memory> namespace dev @@ -143,5 +140,18 @@ private: smt::Expression m_declaration; }; +/** + * Specialization of SymbolicVariable for Mapping + */ +class SymbolicMappingVariable: public SymbolicVariable +{ +public: + SymbolicMappingVariable( + TypePointer _type, + std::string const& _uniqueName, + smt::SolverInterface& _interface + ); +}; + } } diff --git a/libsolidity/formal/Z3Interface.cpp b/libsolidity/formal/Z3Interface.cpp index cb01dc61..4cbc3271 100644 --- a/libsolidity/formal/Z3Interface.cpp +++ b/libsolidity/formal/Z3Interface.cpp @@ -18,7 +18,6 @@ #include <libsolidity/formal/Z3Interface.h> #include <liblangutil/Exceptions.h> - #include <libdevcore/CommonIO.h> using namespace std; diff --git a/libsolidity/formal/Z3Interface.h b/libsolidity/formal/Z3Interface.h index 86e1badd..ee4d1551 100644 --- a/libsolidity/formal/Z3Interface.h +++ b/libsolidity/formal/Z3Interface.h @@ -18,9 +18,7 @@ #pragma once #include <libsolidity/formal/SolverInterface.h> - #include <boost/noncopyable.hpp> - #include <z3++.h> namespace dev diff --git a/libsolidity/interface/ABI.cpp b/libsolidity/interface/ABI.cpp index aefb34af..0d27109e 100644 --- a/libsolidity/interface/ABI.cpp +++ b/libsolidity/interface/ABI.cpp @@ -19,6 +19,7 @@ */ #include <libsolidity/interface/ABI.h> + #include <libsolidity/ast/AST.h> using namespace std; diff --git a/libsolidity/interface/ABI.h b/libsolidity/interface/ABI.h index db70729d..082f3900 100644 --- a/libsolidity/interface/ABI.h +++ b/libsolidity/interface/ABI.h @@ -20,9 +20,9 @@ #pragma once -#include <string> -#include <memory> #include <json/json.h> +#include <memory> +#include <string> namespace dev { diff --git a/libsolidity/interface/AssemblyStack.cpp b/libsolidity/interface/AssemblyStack.cpp index b97e00ae..69bceefc 100644 --- a/libsolidity/interface/AssemblyStack.cpp +++ b/libsolidity/interface/AssemblyStack.cpp @@ -23,20 +23,18 @@ #include <libsolidity/interface/AssemblyStack.h> #include <libsolidity/codegen/AsmCodeGen.h> - +#include <libevmasm/Assembly.h> #include <liblangutil/Scanner.h> -#include <libyul/AsmPrinter.h> -#include <libyul/AsmParser.h> + #include <libyul/AsmAnalysis.h> #include <libyul/AsmAnalysisInfo.h> -#include <libyul/backends/evm/EVMObjectCompiler.h> -#include <libyul/backends/evm/EVMCodeTransform.h> +#include <libyul/AsmParser.h> +#include <libyul/AsmPrinter.h> #include <libyul/backends/evm/EVMAssembly.h> +#include <libyul/backends/evm/EVMCodeTransform.h> #include <libyul/backends/evm/EVMDialect.h> +#include <libyul/backends/evm/EVMObjectCompiler.h> #include <libyul/ObjectParser.h> - -#include <libevmasm/Assembly.h> - #include <libyul/optimiser/Suite.h> using namespace std; diff --git a/libsolidity/interface/AssemblyStack.h b/libsolidity/interface/AssemblyStack.h index c8e3d35a..01db6b61 100644 --- a/libsolidity/interface/AssemblyStack.h +++ b/libsolidity/interface/AssemblyStack.h @@ -29,8 +29,8 @@ #include <libevmasm/LinkerObject.h> -#include <string> #include <memory> +#include <string> namespace langutil { diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 1e6e2330..625a665d 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -24,26 +24,27 @@ #include <libsolidity/interface/CompilerStack.h> -#include <libsolidity/interface/Version.h> -#include <libsolidity/analysis/SemVerHandler.h> -#include <libsolidity/ast/AST.h> -#include <libsolidity/parsing/Parser.h> -#include <libsolidity/analysis/ContractLevelChecker.h> #include <libsolidity/analysis/ControlFlowAnalyzer.h> #include <libsolidity/analysis/ControlFlowGraph.h> +#include <libsolidity/analysis/ContractLevelChecker.h> +#include <libsolidity/analysis/DocStringAnalyser.h> #include <libsolidity/analysis/GlobalContext.h> #include <libsolidity/analysis/NameAndTypeResolver.h> -#include <libsolidity/analysis/TypeChecker.h> -#include <libsolidity/analysis/DocStringAnalyser.h> -#include <libsolidity/analysis/StaticAnalyzer.h> #include <libsolidity/analysis/PostTypeChecker.h> +#include <libsolidity/analysis/SemVerHandler.h> +#include <libsolidity/analysis/StaticAnalyzer.h> #include <libsolidity/analysis/SyntaxChecker.h> +#include <libsolidity/analysis/TypeChecker.h> #include <libsolidity/analysis/ViewPureChecker.h> + +#include <libsolidity/ast/AST.h> #include <libsolidity/codegen/Compiler.h> #include <libsolidity/formal/SMTChecker.h> #include <libsolidity/interface/ABI.h> #include <libsolidity/interface/Natspec.h> #include <libsolidity/interface/GasEstimator.h> +#include <libsolidity/interface/Version.h> +#include <libsolidity/parsing/Parser.h> #include <libyul/YulString.h> diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 2c7add3b..74033170 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -34,15 +34,14 @@ #include <libdevcore/Common.h> #include <libdevcore/FixedHash.h> -#include <json/json.h> - #include <boost/noncopyable.hpp> +#include <json/json.h> +#include <functional> +#include <memory> #include <ostream> #include <string> -#include <memory> #include <vector> -#include <functional> namespace langutil { diff --git a/libsolidity/interface/GasEstimator.cpp b/libsolidity/interface/GasEstimator.cpp index de6b2ce5..8ffcf951 100644 --- a/libsolidity/interface/GasEstimator.cpp +++ b/libsolidity/interface/GasEstimator.cpp @@ -20,18 +20,21 @@ * Gas consumption estimator working alongside the AST. */ -#include "GasEstimator.h" -#include <map> -#include <functional> -#include <memory> -#include <libdevcore/Keccak256.h> -#include <libevmasm/ControlFlowGraph.h> -#include <libevmasm/KnownState.h> -#include <libevmasm/PathGasMeter.h> +#include <libsolidity/interface/GasEstimator.h> + #include <libsolidity/ast/AST.h> #include <libsolidity/ast/ASTVisitor.h> #include <libsolidity/codegen/CompilerUtils.h> +#include <libevmasm/ControlFlowGraph.h> +#include <libevmasm/KnownState.h> +#include <libevmasm/PathGasMeter.h> +#include <libdevcore/Keccak256.h> + +#include <functional> +#include <map> +#include <memory> + using namespace std; using namespace dev; using namespace dev::eth; diff --git a/libsolidity/interface/GasEstimator.h b/libsolidity/interface/GasEstimator.h index 214a3e58..f40cffeb 100644 --- a/libsolidity/interface/GasEstimator.h +++ b/libsolidity/interface/GasEstimator.h @@ -24,12 +24,12 @@ #include <liblangutil/EVMVersion.h> -#include <libevmasm/GasMeter.h> #include <libevmasm/Assembly.h> +#include <libevmasm/GasMeter.h> -#include <vector> -#include <map> #include <array> +#include <map> +#include <vector> namespace dev { diff --git a/libsolidity/interface/Natspec.cpp b/libsolidity/interface/Natspec.cpp index 11dde349..7a89abae 100644 --- a/libsolidity/interface/Natspec.cpp +++ b/libsolidity/interface/Natspec.cpp @@ -24,8 +24,9 @@ */ #include <libsolidity/interface/Natspec.h> -#include <boost/range/irange.hpp> + #include <libsolidity/ast/AST.h> +#include <boost/range/irange.hpp> using namespace std; using namespace dev; diff --git a/libsolidity/interface/Natspec.h b/libsolidity/interface/Natspec.h index 0be4dda2..fbaa6d4d 100644 --- a/libsolidity/interface/Natspec.h +++ b/libsolidity/interface/Natspec.h @@ -25,9 +25,9 @@ #pragma once -#include <string> -#include <memory> #include <json/json.h> +#include <memory> +#include <string> namespace dev { diff --git a/libsolidity/interface/ReadFile.h b/libsolidity/interface/ReadFile.h index 7068629d..3b3d747e 100644 --- a/libsolidity/interface/ReadFile.h +++ b/libsolidity/interface/ReadFile.h @@ -17,9 +17,9 @@ #pragma once -#include <string> -#include <functional> #include <boost/noncopyable.hpp> +#include <functional> +#include <string> namespace dev { diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp index 21d213e7..5be267e9 100644 --- a/libsolidity/interface/StandardCompiler.cpp +++ b/libsolidity/interface/StandardCompiler.cpp @@ -21,16 +21,16 @@ */ #include <libsolidity/interface/StandardCompiler.h> -#include <liblangutil/SourceReferenceFormatter.h> + #include <libsolidity/ast/ASTJsonConverter.h> +#include <liblangutil/SourceReferenceFormatter.h> #include <libevmasm/Instruction.h> #include <libdevcore/JSON.h> #include <libdevcore/Keccak256.h> -#include <algorithm> - #include <boost/algorithm/string.hpp> #include <boost/optional.hpp> +#include <algorithm> using namespace std; using namespace dev; diff --git a/libsolidity/interface/Version.cpp b/libsolidity/interface/Version.cpp index b785d557..efd46d40 100644 --- a/libsolidity/interface/Version.cpp +++ b/libsolidity/interface/Version.cpp @@ -21,11 +21,12 @@ */ #include <libsolidity/interface/Version.h> -#include <string> + +#include <liblangutil/Exceptions.h> #include <libdevcore/CommonData.h> #include <libdevcore/Common.h> -#include <liblangutil/Exceptions.h> #include <solidity/BuildInfo.h> +#include <string> using namespace dev; using namespace dev::solidity; diff --git a/libsolidity/interface/Version.h b/libsolidity/interface/Version.h index 24c3555d..38d63ec6 100644 --- a/libsolidity/interface/Version.h +++ b/libsolidity/interface/Version.h @@ -22,8 +22,8 @@ #pragma once -#include <string> #include <libdevcore/Common.h> +#include <string> namespace dev { diff --git a/libsolidity/parsing/DocStringParser.cpp b/libsolidity/parsing/DocStringParser.cpp index d8927fea..d1d45150 100644 --- a/libsolidity/parsing/DocStringParser.cpp +++ b/libsolidity/parsing/DocStringParser.cpp @@ -1,17 +1,33 @@ +/* + 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/parsing/DocStringParser.h> + #include <liblangutil/ErrorReporter.h> #include <liblangutil/Exceptions.h> -#include <boost/range/irange.hpp> #include <boost/range/algorithm.hpp> +#include <boost/range/irange.hpp> using namespace std; using namespace dev; using namespace langutil; using namespace dev::solidity; - namespace { diff --git a/libsolidity/parsing/DocStringParser.h b/libsolidity/parsing/DocStringParser.h index c83b416d..671a2f34 100644 --- a/libsolidity/parsing/DocStringParser.h +++ b/libsolidity/parsing/DocStringParser.h @@ -22,8 +22,8 @@ #pragma once -#include <string> #include <libsolidity/ast/ASTAnnotations.h> +#include <string> namespace langutil { diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 26f13f93..bcb28988 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -20,14 +20,17 @@ * Solidity parser. */ -#include <cctype> -#include <vector> #include <libsolidity/parsing/Parser.h> + +#include <libsolidity/analysis/SemVerHandler.h> +#include <libsolidity/interface/Version.h> #include <libyul/AsmParser.h> #include <libyul/backends/evm/EVMDialect.h> -#include <liblangutil/SourceLocation.h> #include <liblangutil/ErrorReporter.h> #include <liblangutil/Scanner.h> +#include <liblangutil/SourceLocation.h> +#include <cctype> +#include <vector> using namespace std; using namespace langutil; @@ -105,6 +108,20 @@ ASTPointer<SourceUnit> Parser::parse(shared_ptr<Scanner> const& _scanner) } } +void Parser::parsePragmaVersion(vector<Token> const& tokens, vector<string> const& literals) +{ + SemVerMatchExpressionParser parser(tokens, literals); + auto matchExpression = parser.parse(); + static SemVerVersion const currentVersion{string(VersionString)}; + // FIXME: only match for major version incompatibility + if (!matchExpression.matches(currentVersion)) + fatalParserError( + "Source file requires different compiler version (current compiler is " + + string(VersionString) + " - note that nightly builds are considered to be " + "strictly less than the released version" + ); +} + ASTPointer<PragmaDirective> Parser::parsePragmaDirective() { RecursionGuard recursionGuard(*this); @@ -133,6 +150,15 @@ ASTPointer<PragmaDirective> Parser::parsePragmaDirective() while (m_scanner->currentToken() != Token::Semicolon && m_scanner->currentToken() != Token::EOS); nodeFactory.markEndPosition(); expectToken(Token::Semicolon); + + if (literals.size() >= 2 && literals[0] == "solidity") + { + parsePragmaVersion( + vector<Token>(tokens.begin() + 1, tokens.end()), + vector<string>(literals.begin() + 1, literals.end()) + ); + } + return nodeFactory.createNode<PragmaDirective>(tokens, literals); } diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index 15852096..bf02c626 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -70,6 +70,7 @@ private: ///@{ ///@name Parsing functions for the AST nodes + void parsePragmaVersion(std::vector<Token> const& tokens, std::vector<std::string> const& literals); ASTPointer<PragmaDirective> parsePragmaDirective(); ASTPointer<ImportDirective> parseImportDirective(); ContractDefinition::ContractKind parseContractKind(); |