Introduce abicoder pragma.

This commit is contained in:
chriseth 2020-10-22 19:19:14 +02:00
parent 22b31054b6
commit 834da7be90
20 changed files with 108 additions and 42 deletions

View File

@ -450,7 +450,7 @@ void ContractLevelChecker::checkLibraryRequirements(ContractDefinition const& _c
void ContractLevelChecker::checkBaseABICompatibility(ContractDefinition const& _contract) void ContractLevelChecker::checkBaseABICompatibility(ContractDefinition const& _contract)
{ {
if (_contract.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2)) if (*_contract.sourceUnit().annotation().useABICoderV2)
return; return;
if (_contract.isLibrary()) if (_contract.isLibrary())
@ -469,7 +469,7 @@ void ContractLevelChecker::checkBaseABICompatibility(ContractDefinition const& _
{ {
solAssert(func.second->hasDeclaration(), "Function has no declaration?!"); solAssert(func.second->hasDeclaration(), "Function has no declaration?!");
if (!func.second->declaration().sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2)) if (!*func.second->declaration().sourceUnit().annotation().useABICoderV2)
continue; continue;
auto const& currentLoc = func.second->declaration().location(); auto const& currentLoc = func.second->declaration().location();

View File

@ -73,6 +73,8 @@ void SyntaxChecker::endVisit(SourceUnit const& _sourceUnit)
// when reporting the warning, print the source name only // when reporting the warning, print the source name only
m_errorReporter.warning(3420_error, {-1, -1, _sourceUnit.location().source}, errorString); m_errorReporter.warning(3420_error, {-1, -1, _sourceUnit.location().source}, errorString);
} }
if (!m_sourceUnit->annotation().useABICoderV2.set())
m_sourceUnit->annotation().useABICoderV2 = false;
m_sourceUnit = nullptr; m_sourceUnit = nullptr;
} }
@ -113,9 +115,45 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
m_sourceUnit->annotation().experimentalFeatures.insert(feature); m_sourceUnit->annotation().experimentalFeatures.insert(feature);
if (!ExperimentalFeatureWithoutWarning.count(feature)) if (!ExperimentalFeatureWithoutWarning.count(feature))
m_errorReporter.warning(2264_error, _pragma.location(), "Experimental features are turned on. Do not use experimental features on live deployments."); m_errorReporter.warning(2264_error, _pragma.location(), "Experimental features are turned on. Do not use experimental features on live deployments.");
if (feature == ExperimentalFeature::ABIEncoderV2)
{
if (m_sourceUnit->annotation().useABICoderV2.set())
{
if (!*m_sourceUnit->annotation().useABICoderV2)
m_errorReporter.syntaxError(
8273_error,
_pragma.location(),
"ABI coder V1 has already been selected through \"pragma abicoder v1\"."
);
}
else
m_sourceUnit->annotation().useABICoderV2 = true;
}
} }
} }
} }
else if (_pragma.literals()[0] == "abicoder")
{
solAssert(m_sourceUnit, "");
if (
_pragma.literals().size() != 2 ||
!set<string>{"v1", "v2"}.count(_pragma.literals()[1])
)
m_errorReporter.syntaxError(
2745_error,
_pragma.location(),
"Expected either \"pragma abicoder v1\" or \"pragma abicoder v2\"."
);
else if (m_sourceUnit->annotation().useABICoderV2.set())
m_errorReporter.syntaxError(
3845_error,
_pragma.location(),
"ABI coder has already been selected for this source unit."
);
else
m_sourceUnit->annotation().useABICoderV2 = (_pragma.literals()[1] == "v2");
}
else if (_pragma.literals()[0] == "solidity") else if (_pragma.literals()[0] == "solidity")
{ {
vector<Token> tokens(_pragma.tokens().begin() + 1, _pragma.tokens().end()); vector<Token> tokens(_pragma.tokens().begin() + 1, _pragma.tokens().end());
@ -135,6 +173,7 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
} }
else else
m_errorReporter.syntaxError(4936_error, _pragma.location(), "Unknown pragma \"" + _pragma.literals()[0] + "\""); m_errorReporter.syntaxError(4936_error, _pragma.location(), "Unknown pragma \"" + _pragma.literals()[0] + "\"");
return true; return true;
} }

View File

@ -39,6 +39,7 @@ namespace solidity::frontend
* - issues deprecation warnings for unary '+' * - issues deprecation warnings for unary '+'
* - issues deprecation warning for throw * - issues deprecation warning for throw
* - whether the msize instruction is used and the Yul optimizer is enabled at the same time. * - whether the msize instruction is used and the Yul optimizer is enabled at the same time.
* - selection of the ABI coder through pragmas.
*/ */
class SyntaxChecker: private ASTConstVisitor class SyntaxChecker: private ASTConstVisitor
{ {

View File

@ -395,7 +395,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
m_errorReporter.typeError(4103_error, _var.location(), message); m_errorReporter.typeError(4103_error, _var.location(), message);
} }
else if ( else if (
!experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2) && !useABICoderV2() &&
!typeSupportedByOldABIEncoder(*type(_var), _function.libraryFunction()) !typeSupportedByOldABIEncoder(*type(_var), _function.libraryFunction())
) )
{ {
@ -567,7 +567,7 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
else if (_variable.visibility() >= Visibility::Public) else if (_variable.visibility() >= Visibility::Public)
{ {
FunctionType getter(_variable); FunctionType getter(_variable);
if (!experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2)) if (!useABICoderV2())
{ {
vector<string> unsupportedTypes; vector<string> unsupportedTypes;
for (auto const& param: getter.parameterTypes() + getter.returnParameterTypes()) for (auto const& param: getter.parameterTypes() + getter.returnParameterTypes())
@ -692,7 +692,7 @@ bool TypeChecker::visit(EventDefinition const& _eventDef)
if (!type(*var)->interfaceType(false)) if (!type(*var)->interfaceType(false))
m_errorReporter.typeError(3417_error, var->location(), "Internal or recursive type is not allowed as event parameter type."); m_errorReporter.typeError(3417_error, var->location(), "Internal or recursive type is not allowed as event parameter type.");
if ( if (
!experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2) && !useABICoderV2() &&
!typeSupportedByOldABIEncoder(*type(*var), false /* isLibrary */) !typeSupportedByOldABIEncoder(*type(*var), false /* isLibrary */)
) )
m_errorReporter.typeError( m_errorReporter.typeError(
@ -1897,7 +1897,7 @@ void TypeChecker::typeCheckABIEncodeFunctions(
bool const isPacked = _functionType->kind() == FunctionType::Kind::ABIEncodePacked; bool const isPacked = _functionType->kind() == FunctionType::Kind::ABIEncodePacked;
solAssert(_functionType->padArguments() != isPacked, "ABI function with unexpected padding"); solAssert(_functionType->padArguments() != isPacked, "ABI function with unexpected padding");
bool const abiEncoderV2 = experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2); bool const abiEncoderV2 = useABICoderV2();
// Check for named arguments // Check for named arguments
if (!_functionCall.names().empty()) if (!_functionCall.names().empty())
@ -2189,7 +2189,7 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
_functionType->kind() == FunctionType::Kind::Creation || _functionType->kind() == FunctionType::Kind::Creation ||
_functionType->kind() == FunctionType::Kind::Event; _functionType->kind() == FunctionType::Kind::Event;
if (callRequiresABIEncoding && !experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2)) if (callRequiresABIEncoding && !useABICoderV2())
{ {
solAssert(!isVariadic, ""); solAssert(!isVariadic, "");
solAssert(parameterTypes.size() == arguments.size(), ""); solAssert(parameterTypes.size() == arguments.size(), "");
@ -2337,7 +2337,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
{ {
returnTypes = typeCheckABIDecodeAndRetrieveReturnType( returnTypes = typeCheckABIDecodeAndRetrieveReturnType(
_functionCall, _functionCall,
experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2) useABICoderV2()
); );
break; break;
} }
@ -3384,10 +3384,11 @@ void TypeChecker::requireLValue(Expression const& _expression, bool _ordinaryAss
m_errorReporter.typeError(errorId, _expression.location(), description); m_errorReporter.typeError(errorId, _expression.location(), description);
} }
bool TypeChecker::experimentalFeatureActive(ExperimentalFeature _feature) const bool TypeChecker::useABICoderV2() const
{ {
solAssert(m_currentSourceUnit, ""); solAssert(m_currentSourceUnit, "");
if (m_currentContract) if (m_currentContract)
solAssert(m_currentSourceUnit == &m_currentContract->sourceUnit(), ""); solAssert(m_currentSourceUnit == &m_currentContract->sourceUnit(), "");
return m_currentSourceUnit->annotation().experimentalFeatures.count(_feature); return *m_currentSourceUnit->annotation().useABICoderV2;
} }

View File

@ -166,7 +166,7 @@ private:
/// Runs type checks on @a _expression to infer its type and then checks that it is an LValue. /// Runs type checks on @a _expression to infer its type and then checks that it is an LValue.
void requireLValue(Expression const& _expression, bool _ordinaryAssignment); void requireLValue(Expression const& _expression, bool _ordinaryAssignment);
bool experimentalFeatureActive(ExperimentalFeature _feature) const; bool useABICoderV2() const;
/// @returns the current scope that can have function or type definitions. /// @returns the current scope that can have function or type definitions.
/// This is either a contract or a source unit. /// This is either a contract or a source unit.

View File

@ -94,6 +94,7 @@ struct SourceUnitAnnotation: ASTAnnotation
SetOnce<std::map<ASTString, std::vector<Declaration const*>>> exportedSymbols; SetOnce<std::map<ASTString, std::vector<Declaration const*>>> exportedSymbols;
/// Experimental features. /// Experimental features.
std::set<ExperimentalFeature> experimentalFeatures; std::set<ExperimentalFeature> experimentalFeatures;
SetOnce<bool> useABICoderV2;
}; };
struct ScopableAnnotation struct ScopableAnnotation

View File

@ -1162,7 +1162,7 @@ void ArrayUtils::accessCallDataArrayElement(ArrayType const& _arrayType, bool _d
if ( if (
!_arrayType.isByteArray() && !_arrayType.isByteArray() &&
_arrayType.baseType()->storageBytes() < 32 && _arrayType.baseType()->storageBytes() < 32 &&
m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2) m_context.useABICoderV2()
) )
{ {
m_context << u256(32); m_context << u256(32);

View File

@ -76,11 +76,8 @@ public:
langutil::EVMVersion const& evmVersion() const { return m_evmVersion; } langutil::EVMVersion const& evmVersion() const { return m_evmVersion; }
/// Update currently enabled set of experimental features. void setUseABICoderV2(bool _value) { m_useABICoderV2 = _value; }
void setExperimentalFeatures(std::set<ExperimentalFeature> const& _features) { m_experimentalFeatures = _features; } bool useABICoderV2() const { return m_useABICoderV2; }
std::set<ExperimentalFeature> const& experimentalFeaturesActive() const { return m_experimentalFeatures; }
/// @returns true if the given feature is enabled.
bool experimentalFeatureActive(ExperimentalFeature _feature) const { return m_experimentalFeatures.count(_feature); }
void addStateVariable(VariableDeclaration const& _declaration, u256 const& _storageOffset, unsigned _byteOffset); void addStateVariable(VariableDeclaration const& _declaration, u256 const& _storageOffset, unsigned _byteOffset);
void addImmutable(VariableDeclaration const& _declaration); void addImmutable(VariableDeclaration const& _declaration);
@ -361,8 +358,7 @@ private:
/// Version of the EVM to compile against. /// Version of the EVM to compile against.
langutil::EVMVersion m_evmVersion; langutil::EVMVersion m_evmVersion;
RevertStrings const m_revertStrings; RevertStrings const m_revertStrings;
/// Activated experimental features. bool m_useABICoderV2 = false;
std::set<ExperimentalFeature> m_experimentalFeatures;
/// Other already compiled contracts to be used in contract creation calls. /// Other already compiled contracts to be used in contract creation calls.
std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> m_otherCompilers; std::map<ContractDefinition const*, std::shared_ptr<Compiler const>> m_otherCompilers;
/// Storage offsets of state variables /// Storage offsets of state variables

View File

@ -230,7 +230,7 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMemory) void CompilerUtils::abiDecode(TypePointers const& _typeParameters, bool _fromMemory)
{ {
/// Stack: <source_offset> <length> /// Stack: <source_offset> <length>
if (m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2)) if (m_context.useABICoderV2())
{ {
// Use the new Yul-based decoding function // Use the new Yul-based decoding function
auto stackHeightBefore = m_context.stackHeight(); auto stackHeightBefore = m_context.stackHeight();
@ -412,7 +412,7 @@ void CompilerUtils::encodeToMemory(
) )
{ {
// stack: <v1> <v2> ... <vn> <mem> // stack: <v1> <v2> ... <vn> <mem>
bool const encoderV2 = m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2); bool const encoderV2 = m_context.useABICoderV2();
TypePointers targetTypes = _targetTypes.empty() ? _givenTypes : _targetTypes; TypePointers targetTypes = _targetTypes.empty() ? _givenTypes : _targetTypes;
solAssert(targetTypes.size() == _givenTypes.size(), ""); solAssert(targetTypes.size() == _givenTypes.size(), "");
for (TypePointer& t: targetTypes) for (TypePointer& t: targetTypes)

View File

@ -126,7 +126,7 @@ void ContractCompiler::initializeContext(
map<ContractDefinition const*, shared_ptr<Compiler const>> const& _otherCompilers map<ContractDefinition const*, shared_ptr<Compiler const>> const& _otherCompilers
) )
{ {
m_context.setExperimentalFeatures(_contract.sourceUnit().annotation().experimentalFeatures); m_context.setUseABICoderV2(*_contract.sourceUnit().annotation().useABICoderV2);
m_context.setOtherCompilers(_otherCompilers); m_context.setOtherCompilers(_otherCompilers);
m_context.setMostDerivedContract(_contract); m_context.setMostDerivedContract(_contract);
if (m_runtimeCompiler) if (m_runtimeCompiler)
@ -1324,13 +1324,13 @@ void ContractCompiler::appendModifierOrFunctionCode()
if (codeBlock) if (codeBlock)
{ {
std::set<ExperimentalFeature> experimentalFeaturesOutside = m_context.experimentalFeaturesActive(); bool coderV2Outside = m_context.useABICoderV2();
m_context.setExperimentalFeatures(codeBlock->sourceUnit().annotation().experimentalFeatures); m_context.setUseABICoderV2(*codeBlock->sourceUnit().annotation().useABICoderV2);
m_returnTags.emplace_back(m_context.newTag(), m_context.stackHeight()); m_returnTags.emplace_back(m_context.newTag(), m_context.stackHeight());
codeBlock->accept(*this); codeBlock->accept(*this);
m_context.setExperimentalFeatures(experimentalFeaturesOutside); m_context.setUseABICoderV2(coderV2Outside);
solAssert(!m_returnTags.empty(), ""); solAssert(!m_returnTags.empty(), "");
m_context << m_returnTags.back().first; m_context << m_returnTags.back().first;

View File

@ -1682,7 +1682,7 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
{ {
solAssert(memberType->calldataEncodedSize() > 0, ""); solAssert(memberType->calldataEncodedSize() > 0, "");
solAssert(memberType->storageBytes() <= 32, ""); solAssert(memberType->storageBytes() <= 32, "");
if (memberType->storageBytes() < 32 && m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2)) if (memberType->storageBytes() < 32 && m_context.useABICoderV2())
{ {
m_context << u256(32); m_context << u256(32);
CompilerUtils(m_context).abiDecodeV2({memberType}, false); CompilerUtils(m_context).abiDecodeV2({memberType}, false);
@ -2490,7 +2490,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
// memory pointer), but kept references to the return data for // memory pointer), but kept references to the return data for
// (statically-sized) arrays // (statically-sized) arrays
bool needToUpdateFreeMemoryPtr = false; bool needToUpdateFreeMemoryPtr = false;
if (dynamicReturnSize || m_context.experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2)) if (dynamicReturnSize || m_context.useABICoderV2())
needToUpdateFreeMemoryPtr = true; needToUpdateFreeMemoryPtr = true;
else else
for (auto const& retType: returnTypes) for (auto const& retType: returnTypes)

View File

@ -34,6 +34,7 @@
#include <libsolidity/codegen/Compiler.h> #include <libsolidity/codegen/Compiler.h>
#include <libsolidity/ast/AST.h> #include <libsolidity/ast/AST.h>
#include <libsolidity/analysis/TypeChecker.h> #include <libsolidity/analysis/TypeChecker.h>
#include <libsolidity/analysis/SyntaxChecker.h>
#include <liblangutil/ErrorReporter.h> #include <liblangutil/ErrorReporter.h>
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
@ -61,6 +62,7 @@ evmasm::AssemblyItems compileContract(std::shared_ptr<CharStream> _sourceCode)
BOOST_CHECK(!!sourceUnit); BOOST_CHECK(!!sourceUnit);
Scoper::assignScopes(*sourceUnit); Scoper::assignScopes(*sourceUnit);
BOOST_REQUIRE(SyntaxChecker(errorReporter, false).checkSyntax(*sourceUnit));
GlobalContext globalContext; GlobalContext globalContext;
NameAndTypeResolver resolver(globalContext, solidity::test::CommonOptions::get().evmVersion(), errorReporter); NameAndTypeResolver resolver(globalContext, solidity::test::CommonOptions::get().evmVersion(), errorReporter);
DeclarationTypeChecker declarationTypeChecker(errorReporter, solidity::test::CommonOptions::get().evmVersion()); DeclarationTypeChecker declarationTypeChecker(errorReporter, solidity::test::CommonOptions::get().evmVersion());

View File

@ -27,6 +27,7 @@
#include <libsolidity/parsing/Parser.h> #include <libsolidity/parsing/Parser.h>
#include <libsolidity/analysis/NameAndTypeResolver.h> #include <libsolidity/analysis/NameAndTypeResolver.h>
#include <libsolidity/analysis/Scoper.h> #include <libsolidity/analysis/Scoper.h>
#include <libsolidity/analysis/SyntaxChecker.h>
#include <libsolidity/analysis/DeclarationTypeChecker.h> #include <libsolidity/analysis/DeclarationTypeChecker.h>
#include <libsolidity/codegen/CompilerContext.h> #include <libsolidity/codegen/CompilerContext.h>
#include <libsolidity/codegen/ExpressionCompiler.h> #include <libsolidity/codegen/ExpressionCompiler.h>
@ -93,18 +94,20 @@ Declaration const& resolveDeclaration(
} }
bytes compileFirstExpression( bytes compileFirstExpression(
const string& _sourceCode, string const& _sourceCode,
vector<vector<string>> _functions = {}, vector<vector<string>> _functions = {},
vector<vector<string>> _localVariables = {} vector<vector<string>> _localVariables = {}
) )
{ {
string sourceCode = "pragma solidity >=0.0; // SPDX-License-Identifier: GPL-3\n" + _sourceCode;
ASTPointer<SourceUnit> sourceUnit; ASTPointer<SourceUnit> sourceUnit;
try try
{ {
ErrorList errors; ErrorList errors;
ErrorReporter errorReporter(errors); ErrorReporter errorReporter(errors);
sourceUnit = Parser(errorReporter, solidity::test::CommonOptions::get().evmVersion()).parse( sourceUnit = Parser(errorReporter, solidity::test::CommonOptions::get().evmVersion()).parse(
make_shared<Scanner>(CharStream(_sourceCode, "")) make_shared<Scanner>(CharStream(sourceCode, ""))
); );
if (!sourceUnit) if (!sourceUnit)
return bytes(); return bytes();
@ -119,6 +122,7 @@ bytes compileFirstExpression(
ErrorReporter errorReporter(errors); ErrorReporter errorReporter(errors);
GlobalContext globalContext; GlobalContext globalContext;
Scoper::assignScopes(*sourceUnit); Scoper::assignScopes(*sourceUnit);
BOOST_REQUIRE(SyntaxChecker(errorReporter, false).checkSyntax(*sourceUnit));
NameAndTypeResolver resolver(globalContext, solidity::test::CommonOptions::get().evmVersion(), errorReporter); NameAndTypeResolver resolver(globalContext, solidity::test::CommonOptions::get().evmVersion(), errorReporter);
resolver.registerDeclarations(*sourceUnit); resolver.registerDeclarations(*sourceUnit);
BOOST_REQUIRE_MESSAGE(resolver.resolveNamesAndTypes(*sourceUnit), "Resolving names failed"); BOOST_REQUIRE_MESSAGE(resolver.resolveNamesAndTypes(*sourceUnit), "Resolving names failed");
@ -186,7 +190,7 @@ BOOST_AUTO_TEST_CASE(literal_false)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract test { contract test {
function f() { bool x = false; } function f() public { bool x = false; }
} }
)"; )";
bytes code = compileFirstExpression(sourceCode); bytes code = compileFirstExpression(sourceCode);
@ -199,7 +203,7 @@ BOOST_AUTO_TEST_CASE(int_literal)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract test { contract test {
function f() { uint x = 0x12345678901234567890; } function f() public { uint x = 0x12345678901234567890; }
} }
)"; )";
bytes code = compileFirstExpression(sourceCode); bytes code = compileFirstExpression(sourceCode);
@ -228,7 +232,7 @@ BOOST_AUTO_TEST_CASE(int_with_gwei_ether_subdenomination)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract test { contract test {
function test () { function f() public {
uint x = 1 gwei; uint x = 1 gwei;
} }
} }
@ -258,7 +262,7 @@ BOOST_AUTO_TEST_CASE(comparison)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract test { contract test {
function f() { bool x = (0x10aa < 0x11aa) != true; } function f() public { bool x = (0x10aa < 0x11aa) != true; }
} }
)"; )";
bytes code = compileFirstExpression(sourceCode); bytes code = compileFirstExpression(sourceCode);
@ -290,7 +294,7 @@ BOOST_AUTO_TEST_CASE(short_circuiting)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract test { contract test {
function f() { bool x = true != (4 <= 8 + 10 || 9 != 2); } function f() public { bool x = true != (4 <= 8 + 10 || 9 != 2); }
} }
)"; )";
bytes code = compileFirstExpression(sourceCode); bytes code = compileFirstExpression(sourceCode);
@ -321,7 +325,7 @@ BOOST_AUTO_TEST_CASE(arithmetic)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract test { contract test {
function f(uint y) { ((((((((y ^ 8) & 7) | 6) - 5) + 4) % 3) / 2) * 1); } function f(uint y) public { ((((((((y ^ 8) & 7) | 6) - 5) + 4) % 3) / 2) * 1); }
} }
)"; )";
bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}}); bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}});
@ -402,7 +406,7 @@ BOOST_AUTO_TEST_CASE(unary_operators)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract test { contract test {
function f(int y) { !(~- y == 2); } function f(int y) public { !(~- y == 2); }
} }
)"; )";
bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}}); bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}});
@ -492,7 +496,7 @@ BOOST_AUTO_TEST_CASE(assignment)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract test { contract test {
function f(uint a, uint b) { (a += b) * 2; } function f(uint a, uint b) public { (a += b) * 2; }
} }
)"; )";
bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "b"}}); bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "b"}});
@ -530,7 +534,7 @@ BOOST_AUTO_TEST_CASE(negative_literals_8bits)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract test { contract test {
function f() { int8 x = -0x80; } function f() public { int8 x = -0x80; }
} }
)"; )";
bytes code = compileFirstExpression(sourceCode); bytes code = compileFirstExpression(sourceCode);
@ -543,7 +547,7 @@ BOOST_AUTO_TEST_CASE(negative_literals_16bits)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract test { contract test {
function f() { int64 x = ~0xabc; } function f() public { int64 x = ~0xabc; }
} }
)"; )";
bytes code = compileFirstExpression(sourceCode); bytes code = compileFirstExpression(sourceCode);
@ -558,7 +562,7 @@ BOOST_AUTO_TEST_CASE(intermediately_overflowing_literals)
// have been applied // have been applied
char const* sourceCode = R"( char const* sourceCode = R"(
contract test { contract test {
function f() { uint8 x = (0x00ffffffffffffffffffffffffffffffffffffffff * 0xffffffffffffffffffffffffff01) & 0xbf; } function f() public { uint8 x = (0x00ffffffffffffffffffffffffffffffffffffffff * 0xffffffffffffffffffffffffff01) & 0xbf; }
} }
)"; )";
bytes code = compileFirstExpression(sourceCode); bytes code = compileFirstExpression(sourceCode);
@ -571,7 +575,7 @@ BOOST_AUTO_TEST_CASE(blockhash)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract test { contract test {
function f() { function f() public {
blockhash(3); blockhash(3);
} }
} }
@ -603,7 +607,7 @@ BOOST_AUTO_TEST_CASE(selfbalance)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract test { contract test {
function f() returns (uint) { function f() public returns (uint) {
return address(this).balance; return address(this).balance;
} }
} }

View File

@ -0,0 +1,4 @@
pragma experimental ABIEncoderV2;
pragma abicoder v1;
// ----
// SyntaxError 3845: (34-53): ABI coder has already been selected for this source unit.

View File

@ -0,0 +1,4 @@
pragma abicoder v1;
pragma experimental ABIEncoderV2;
// ----
// SyntaxError 8273: (20-53): ABI coder V1 has already been selected through "pragma abicoder v1".

View File

@ -0,0 +1,3 @@
pragma abicoder something;
// ----
// SyntaxError 2745: (0-26): Expected either "pragma abicoder v1" or "pragma abicoder v2".

View File

@ -0,0 +1,4 @@
pragma experimental ABIEncoderV2;
pragma abicoder v2;
// ----
// SyntaxError 3845: (34-53): ABI coder has already been selected for this source unit.

View File

@ -0,0 +1 @@
pragma abicoder v1;

View File

@ -0,0 +1,4 @@
pragma abicoder v1;
pragma abicoder v1;
// ----
// SyntaxError 3845: (20-39): ABI coder has already been selected for this source unit.

View File

@ -0,0 +1,2 @@
pragma abicoder v2;
pragma experimental ABIEncoderV2;