mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Introduce abicoder pragma.
This commit is contained in:
@@ -450,7 +450,7 @@ void ContractLevelChecker::checkLibraryRequirements(ContractDefinition const& _c
|
||||
|
||||
void ContractLevelChecker::checkBaseABICompatibility(ContractDefinition const& _contract)
|
||||
{
|
||||
if (_contract.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2))
|
||||
if (*_contract.sourceUnit().annotation().useABICoderV2)
|
||||
return;
|
||||
|
||||
if (_contract.isLibrary())
|
||||
@@ -469,7 +469,7 @@ void ContractLevelChecker::checkBaseABICompatibility(ContractDefinition const& _
|
||||
{
|
||||
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;
|
||||
|
||||
auto const& currentLoc = func.second->declaration().location();
|
||||
|
||||
@@ -73,6 +73,8 @@ void SyntaxChecker::endVisit(SourceUnit const& _sourceUnit)
|
||||
// when reporting the warning, print the source name only
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -113,9 +115,45 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
|
||||
m_sourceUnit->annotation().experimentalFeatures.insert(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.");
|
||||
|
||||
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")
|
||||
{
|
||||
vector<Token> tokens(_pragma.tokens().begin() + 1, _pragma.tokens().end());
|
||||
@@ -135,6 +173,7 @@ bool SyntaxChecker::visit(PragmaDirective const& _pragma)
|
||||
}
|
||||
else
|
||||
m_errorReporter.syntaxError(4936_error, _pragma.location(), "Unknown pragma \"" + _pragma.literals()[0] + "\"");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace solidity::frontend
|
||||
* - issues deprecation warnings for unary '+'
|
||||
* - issues deprecation warning for throw
|
||||
* - 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
|
||||
{
|
||||
|
||||
@@ -395,7 +395,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
|
||||
m_errorReporter.typeError(4103_error, _var.location(), message);
|
||||
}
|
||||
else if (
|
||||
!experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2) &&
|
||||
!useABICoderV2() &&
|
||||
!typeSupportedByOldABIEncoder(*type(_var), _function.libraryFunction())
|
||||
)
|
||||
{
|
||||
@@ -567,7 +567,7 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
|
||||
else if (_variable.visibility() >= Visibility::Public)
|
||||
{
|
||||
FunctionType getter(_variable);
|
||||
if (!experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2))
|
||||
if (!useABICoderV2())
|
||||
{
|
||||
vector<string> unsupportedTypes;
|
||||
for (auto const& param: getter.parameterTypes() + getter.returnParameterTypes())
|
||||
@@ -692,7 +692,7 @@ bool TypeChecker::visit(EventDefinition const& _eventDef)
|
||||
if (!type(*var)->interfaceType(false))
|
||||
m_errorReporter.typeError(3417_error, var->location(), "Internal or recursive type is not allowed as event parameter type.");
|
||||
if (
|
||||
!experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2) &&
|
||||
!useABICoderV2() &&
|
||||
!typeSupportedByOldABIEncoder(*type(*var), false /* isLibrary */)
|
||||
)
|
||||
m_errorReporter.typeError(
|
||||
@@ -1897,7 +1897,7 @@ void TypeChecker::typeCheckABIEncodeFunctions(
|
||||
bool const isPacked = _functionType->kind() == FunctionType::Kind::ABIEncodePacked;
|
||||
solAssert(_functionType->padArguments() != isPacked, "ABI function with unexpected padding");
|
||||
|
||||
bool const abiEncoderV2 = experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2);
|
||||
bool const abiEncoderV2 = useABICoderV2();
|
||||
|
||||
// Check for named arguments
|
||||
if (!_functionCall.names().empty())
|
||||
@@ -2189,7 +2189,7 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
|
||||
_functionType->kind() == FunctionType::Kind::Creation ||
|
||||
_functionType->kind() == FunctionType::Kind::Event;
|
||||
|
||||
if (callRequiresABIEncoding && !experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2))
|
||||
if (callRequiresABIEncoding && !useABICoderV2())
|
||||
{
|
||||
solAssert(!isVariadic, "");
|
||||
solAssert(parameterTypes.size() == arguments.size(), "");
|
||||
@@ -2337,7 +2337,7 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
|
||||
{
|
||||
returnTypes = typeCheckABIDecodeAndRetrieveReturnType(
|
||||
_functionCall,
|
||||
experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2)
|
||||
useABICoderV2()
|
||||
);
|
||||
break;
|
||||
}
|
||||
@@ -3384,10 +3384,11 @@ void TypeChecker::requireLValue(Expression const& _expression, bool _ordinaryAss
|
||||
m_errorReporter.typeError(errorId, _expression.location(), description);
|
||||
}
|
||||
|
||||
bool TypeChecker::experimentalFeatureActive(ExperimentalFeature _feature) const
|
||||
bool TypeChecker::useABICoderV2() const
|
||||
{
|
||||
solAssert(m_currentSourceUnit, "");
|
||||
if (m_currentContract)
|
||||
solAssert(m_currentSourceUnit == &m_currentContract->sourceUnit(), "");
|
||||
return m_currentSourceUnit->annotation().experimentalFeatures.count(_feature);
|
||||
return *m_currentSourceUnit->annotation().useABICoderV2;
|
||||
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ private:
|
||||
/// 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);
|
||||
|
||||
bool experimentalFeatureActive(ExperimentalFeature _feature) const;
|
||||
bool useABICoderV2() const;
|
||||
|
||||
/// @returns the current scope that can have function or type definitions.
|
||||
/// This is either a contract or a source unit.
|
||||
|
||||
Reference in New Issue
Block a user