Merge remote-tracking branch 'origin/develop' into breaking

This commit is contained in:
chriseth
2021-10-06 12:00:17 +02:00
733 changed files with 18775 additions and 5313 deletions
@@ -27,6 +27,8 @@
#include <libsolidity/ast/TypeProvider.h>
#include <liblangutil/ErrorReporter.h>
#include <limits>
using namespace std;
using namespace solidity;
using namespace solidity::frontend;
@@ -71,7 +71,7 @@ bool ContractLevelChecker::check(SourceUnit const& _sourceUnit)
findDuplicateDefinitions(
filterDeclarations<EventDefinition>(*_sourceUnit.annotation().exportedSymbols)
);
if (!Error::containsOnlyWarnings(m_errorReporter.errors()))
if (Error::containsErrors(m_errorReporter.errors()))
noErrors = false;
for (ASTPointer<ASTNode> const& node: _sourceUnit.nodes())
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
@@ -97,7 +97,7 @@ bool ContractLevelChecker::check(ContractDefinition const& _contract)
checkPayableFallbackWithoutReceive(_contract);
checkStorageSize(_contract);
return Error::containsOnlyWarnings(m_errorReporter.errors());
return !Error::containsErrors(m_errorReporter.errors());
}
void ContractLevelChecker::checkDuplicateFunctions(ContractDefinition const& _contract)
+1 -1
View File
@@ -36,7 +36,7 @@ bool ControlFlowAnalyzer::run()
for (auto& [pair, flow]: m_cfg.allFunctionFlows())
analyze(*pair.function, pair.contract, *flow);
return Error::containsOnlyWarnings(m_errorReporter.errors());
return !Error::containsErrors(m_errorReporter.errors());
}
void ControlFlowAnalyzer::analyze(FunctionDefinition const& _function, ContractDefinition const* _contract, FunctionFlow const& _flow)
+11 -6
View File
@@ -409,7 +409,8 @@ bool ControlFlowBuilder::visit(InlineAssembly const& _inlineAssembly)
void ControlFlowBuilder::visit(yul::Statement const& _statement)
{
solAssert(m_currentNode && m_inlineAssembly, "");
m_currentNode->location = langutil::SourceLocation::smallestCovering(m_currentNode->location, locationOf(_statement));
solAssert(nativeLocationOf(_statement) == originLocationOf(_statement), "");
m_currentNode->location = langutil::SourceLocation::smallestCovering(m_currentNode->location, nativeLocationOf(_statement));
ASTWalker::visit(_statement);
}
@@ -496,14 +497,15 @@ void ControlFlowBuilder::operator()(yul::Identifier const& _identifier)
solAssert(m_currentNode && m_inlineAssembly, "");
auto const& externalReferences = m_inlineAssembly->annotation().externalReferences;
if (externalReferences.count(&_identifier))
{
if (auto const* declaration = dynamic_cast<VariableDeclaration const*>(externalReferences.at(&_identifier).declaration))
{
solAssert(nativeLocationOf(_identifier) == originLocationOf(_identifier), "");
m_currentNode->variableOccurrences.emplace_back(
*declaration,
VariableOccurrence::Kind::Access,
_identifier.debugData->location
nativeLocationOf(_identifier)
);
}
}
}
void ControlFlowBuilder::operator()(yul::Assignment const& _assignment)
@@ -514,11 +516,14 @@ void ControlFlowBuilder::operator()(yul::Assignment const& _assignment)
for (auto const& variable: _assignment.variableNames)
if (externalReferences.count(&variable))
if (auto const* declaration = dynamic_cast<VariableDeclaration const*>(externalReferences.at(&variable).declaration))
{
solAssert(nativeLocationOf(variable) == originLocationOf(variable), "");
m_currentNode->variableOccurrences.emplace_back(
*declaration,
VariableOccurrence::Kind::Assignment,
variable.debugData->location
nativeLocationOf(variable)
);
}
}
void ControlFlowBuilder::operator()(yul::FunctionCall const& _functionCall)
@@ -548,7 +553,7 @@ void ControlFlowBuilder::operator()(yul::FunctionDefinition const&)
void ControlFlowBuilder::operator()(yul::Leave const&)
{
// This has to be implemented, if we ever decide to visit functions.
solUnimplementedAssert(false, "");
solUnimplemented("");
}
bool ControlFlowBuilder::visit(VariableDeclaration const& _variableDeclaration)
+1 -1
View File
@@ -27,7 +27,7 @@ using namespace solidity::frontend;
bool CFG::constructFlow(ASTNode const& _astRoot)
{
_astRoot.accept(*this);
return Error::containsOnlyWarnings(m_errorReporter.errors());
return !Error::containsErrors(m_errorReporter.errors());
}
@@ -140,6 +140,30 @@ bool DeclarationTypeChecker::visit(StructDefinition const& _struct)
return false;
}
void DeclarationTypeChecker::endVisit(UserDefinedValueTypeDefinition const& _userDefined)
{
TypeName const* typeName = _userDefined.underlyingType();
solAssert(typeName, "");
if (!dynamic_cast<ElementaryTypeName const*>(typeName))
m_errorReporter.fatalTypeError(
8657_error,
typeName->location(),
"The underlying type for a user defined value type has to be an elementary value type."
);
Type const* type = typeName->annotation().type;
solAssert(type, "");
solAssert(!dynamic_cast<UserDefinedValueType const*>(type), "");
if (!type->isValueType())
m_errorReporter.typeError(
8129_error,
_userDefined.location(),
"The underlying type of the user defined value type \"" +
_userDefined.name() +
"\" is not a value type."
);
}
void DeclarationTypeChecker::endVisit(UserDefinedTypeName const& _typeName)
{
if (_typeName.annotation().type)
@@ -158,6 +182,8 @@ void DeclarationTypeChecker::endVisit(UserDefinedTypeName const& _typeName)
_typeName.annotation().type = TypeProvider::enumType(*enumDef);
else if (ContractDefinition const* contract = dynamic_cast<ContractDefinition const*>(declaration))
_typeName.annotation().type = TypeProvider::contract(*contract);
else if (auto userDefinedValueType = dynamic_cast<UserDefinedValueTypeDefinition const*>(declaration))
_typeName.annotation().type = TypeProvider::userDefinedValueType(*userDefinedValueType);
else
{
_typeName.annotation().type = TypeProvider::emptyTuple();
@@ -227,12 +253,13 @@ void DeclarationTypeChecker::endVisit(Mapping const& _mapping)
{
case Type::Category::Enum:
case Type::Category::Contract:
case Type::Category::UserDefinedValueType:
break;
default:
m_errorReporter.fatalTypeError(
7804_error,
typeName->location(),
"Only elementary types, contract types or enums are allowed as mapping keys."
"Only elementary types, user defined value types, contract types or enums are allowed as mapping keys."
);
break;
}
@@ -60,6 +60,7 @@ private:
void endVisit(VariableDeclaration const& _variable) override;
bool visit(EnumDefinition const& _enum) override;
bool visit(StructDefinition const& _struct) override;
void endVisit(UserDefinedValueTypeDefinition const& _userDefined) override;
bool visit(UsingForDirective const& _usingForDirective) override;
bool visit(InheritanceSpecifier const& _inheritanceSpecifier) override;
+2 -1
View File
@@ -34,6 +34,7 @@
#include <boost/algorithm/string.hpp>
#include <regex>
#include <string_view>
using namespace std;
using namespace solidity;
@@ -233,7 +234,7 @@ void DocStringTagParser::parseDocStrings(
for (auto const& [tagName, tagValue]: _annotation.docTags)
{
string static const customPrefix("custom:");
string_view static constexpr customPrefix("custom:");
if (tagName == "custom" || tagName == "custom:")
m_errorReporter.docstringParsingError(
6564_error,
+26 -22
View File
@@ -102,7 +102,12 @@ bool NameAndTypeResolver::performImports(SourceUnit& _sourceUnit, map<string, So
else
for (Declaration const* declaration: declarations)
if (!DeclarationRegistrationHelper::registerDeclaration(
target, *declaration, alias.alias.get(), &alias.location, false, m_errorReporter
target,
*declaration,
alias.alias ? alias.alias.get() : &alias.symbol->name(),
&alias.location,
false,
m_errorReporter
))
error = true;
}
@@ -607,13 +612,31 @@ bool DeclarationRegistrationHelper::visitNode(ASTNode& _node)
if (auto* declaration = dynamic_cast<Declaration*>(&_node))
registerDeclaration(*declaration);
if (auto* annotation = dynamic_cast<TypeDeclarationAnnotation*>(&_node.annotation()))
{
string canonicalName = dynamic_cast<Declaration const&>(_node).name();
solAssert(!canonicalName.empty(), "");
for (
ASTNode const* scope = m_currentScope;
scope != nullptr;
scope = m_scopes[scope]->enclosingNode()
)
if (auto decl = dynamic_cast<Declaration const*>(scope))
{
solAssert(!decl->name().empty(), "");
canonicalName = decl->name() + "." + canonicalName;
}
annotation->canonicalName = canonicalName;
}
if (dynamic_cast<ScopeOpener const*>(&_node))
enterNewSubScope(_node);
if (auto* variableScope = dynamic_cast<VariableScope*>(&_node))
m_currentFunction = variableScope;
if (auto* annotation = dynamic_cast<TypeDeclarationAnnotation*>(&_node.annotation()))
annotation->canonicalName = currentCanonicalName();
return true;
}
@@ -663,23 +686,4 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio
solAssert(_declaration.annotation().contract == m_currentContract, "");
}
string DeclarationRegistrationHelper::currentCanonicalName() const
{
string ret;
for (
ASTNode const* scope = m_currentScope;
scope != nullptr;
scope = m_scopes[scope]->enclosingNode()
)
{
if (auto decl = dynamic_cast<Declaration const*>(scope))
{
if (!ret.empty())
ret = "." + ret;
ret = decl->name() + ret;
}
}
return ret;
}
}
@@ -176,9 +176,6 @@ private:
static bool isOverloadedFunction(Declaration const& _declaration1, Declaration const& _declaration2);
/// @returns the canonical name of the current scope.
std::string currentCanonicalName() const;
std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& m_scopes;
ASTNode const* m_currentScope = nullptr;
VariableScope* m_currentFunction = nullptr;
+3 -2
View File
@@ -86,7 +86,8 @@ private:
int currentNode = static_cast<int>(numNodes++);
nodes[_function] = currentNode;
nodeInv[currentNode] = _function;
if (_function.overrides())
if (!_function.baseFunctions().empty())
for (auto const& baseFunction: _function.baseFunctions())
addEdge(currentNode, visit(baseFunction));
else
@@ -518,7 +519,7 @@ void OverrideChecker::checkOverride(OverrideProxy const& _overriding, OverridePr
"Override changes modifier signature."
);
if (!_overriding.overrides())
if (!_overriding.overrides() && !(_super.isFunction() && _super.contract().isInterface()))
overrideError(
_overriding,
_super,
+2 -2
View File
@@ -36,14 +36,14 @@ using namespace solidity::frontend;
bool PostTypeChecker::check(ASTNode const& _astRoot)
{
_astRoot.accept(*this);
return Error::containsOnlyWarnings(m_errorReporter.errors());
return !Error::containsErrors(m_errorReporter.errors());
}
bool PostTypeChecker::finalize()
{
for (auto& checker: m_checkers)
checker->finalize();
return Error::containsOnlyWarnings(m_errorReporter.errors());
return !Error::containsErrors(m_errorReporter.errors());
}
bool PostTypeChecker::visit(ContractDefinition const& _contractDefinition)
@@ -68,5 +68,5 @@ bool PostTypeContractLevelChecker::check(ContractDefinition const& _contract)
errorHashes[hash][signature] = error->location();
}
return Error::containsOnlyWarnings(m_errorReporter.errors());
return !Error::containsErrors(m_errorReporter.errors());
}
+19 -8
View File
@@ -201,9 +201,13 @@ bool ReferencesResolver::visit(Return const& _return)
void ReferencesResolver::operator()(yul::FunctionDefinition const& _function)
{
validateYulIdentifierName(_function.name, _function.debugData->location);
solAssert(nativeLocationOf(_function) == originLocationOf(_function), "");
validateYulIdentifierName(_function.name, nativeLocationOf(_function));
for (yul::TypedName const& varName: _function.parameters + _function.returnVariables)
validateYulIdentifierName(varName.name, varName.debugData->location);
{
solAssert(nativeLocationOf(varName) == originLocationOf(varName), "");
validateYulIdentifierName(varName.name, nativeLocationOf(varName));
}
bool wasInsideFunction = m_yulInsideFunction;
m_yulInsideFunction = true;
@@ -213,13 +217,17 @@ void ReferencesResolver::operator()(yul::FunctionDefinition const& _function)
void ReferencesResolver::operator()(yul::Identifier const& _identifier)
{
static set<string> suffixes{"slot", "offset", "length"};
solAssert(nativeLocationOf(_identifier) == originLocationOf(_identifier), "");
static set<string> suffixes{"slot", "offset", "length", "address", "selector"};
string suffix;
for (string const& s: suffixes)
if (boost::algorithm::ends_with(_identifier.name.str(), "." + s))
suffix = s;
// Could also use `pathFromCurrentScope`, split by '.'
// Could also use `pathFromCurrentScope`, split by '.'.
// If we do that, suffix should only be set for when it has a special
// meaning, not for normal identifierPaths.
auto declarations = m_resolver.nameFromCurrentScope(_identifier.name.str());
if (!suffix.empty())
{
@@ -238,7 +246,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
{
m_errorReporter.declarationError(
4718_error,
_identifier.debugData->location,
nativeLocationOf(_identifier),
"Multiple matching identifiers. Resolving overloaded identifiers is not supported."
);
return;
@@ -251,7 +259,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
)
m_errorReporter.declarationError(
9467_error,
_identifier.debugData->location,
nativeLocationOf(_identifier),
"Identifier not found. Use \".slot\" and \".offset\" to access storage variables."
);
return;
@@ -261,7 +269,7 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
{
m_errorReporter.declarationError(
6578_error,
_identifier.debugData->location,
nativeLocationOf(_identifier),
"Cannot access local Solidity variables from inside an inline assembly function."
);
return;
@@ -274,7 +282,10 @@ void ReferencesResolver::operator()(yul::Identifier const& _identifier)
void ReferencesResolver::operator()(yul::VariableDeclaration const& _varDecl)
{
for (auto const& identifier: _varDecl.variables)
validateYulIdentifierName(identifier.name, identifier.debugData->location);
{
solAssert(nativeLocationOf(identifier) == originLocationOf(identifier), "");
validateYulIdentifierName(identifier.name, nativeLocationOf(identifier));
}
if (_varDecl.value)
visit(*_varDecl.value);
+1 -1
View File
@@ -86,7 +86,7 @@ StaticAnalyzer::~StaticAnalyzer()
bool StaticAnalyzer::analyze(SourceUnit const& _sourceUnit)
{
_sourceUnit.accept(*this);
return Error::containsOnlyWarnings(m_errorReporter.errors());
return !Error::containsErrors(m_errorReporter.errors());
}
bool StaticAnalyzer::visit(ContractDefinition const& _contract)
+1 -1
View File
@@ -41,7 +41,7 @@ using namespace solidity::util;
bool SyntaxChecker::checkSyntax(ASTNode const& _astRoot)
{
_astRoot.accept(*this);
return Error::containsOnlyWarnings(m_errorReporter.errors());
return !Error::containsErrors(m_errorReporter.errors());
}
bool SyntaxChecker::visit(SourceUnit const& _sourceUnit)
+69 -35
View File
@@ -73,7 +73,7 @@ bool TypeChecker::checkTypeRequirements(SourceUnit const& _source)
m_currentSourceUnit = &_source;
_source.accept(*this);
m_currentSourceUnit = nullptr;
return Error::containsOnlyWarnings(m_errorReporter.errors());
return !Error::containsErrors(m_errorReporter.errors());
}
Type const* TypeChecker::type(Expression const& _expression) const
@@ -246,7 +246,10 @@ TypePointers TypeChecker::typeCheckMetaTypeFunctionAndRetrieveReturnType(Functio
Type::Category typeCategory = typeTypePtr->actualType()->category();
if (auto const* contractType = dynamic_cast<ContractType const*>(typeTypePtr->actualType()))
wrongType = contractType->isSuper();
else if (typeCategory != Type::Category::Integer)
else if (
typeCategory != Type::Category::Integer &&
typeCategory != Type::Category::Enum
)
wrongType = true;
}
else
@@ -257,7 +260,7 @@ TypePointers TypeChecker::typeCheckMetaTypeFunctionAndRetrieveReturnType(Functio
4259_error,
arguments.front()->location(),
"Invalid type for argument in the function call. "
"A contract type or an integer type is required, but " +
"An enum type, contract type or an integer type is required, but " +
type(*arguments.front())->toString(true) + " provided."
);
@@ -314,14 +317,22 @@ void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance)
void TypeChecker::endVisit(ModifierDefinition const& _modifier)
{
if (_modifier.virtualSemantics())
if (auto const* contractDef = dynamic_cast<ContractDefinition const*>(_modifier.scope()))
if (contractDef->isLibrary())
m_errorReporter.typeError(
3275_error,
_modifier.location(),
"Modifiers in a library cannot be virtual."
);
if (auto const* contractDef = dynamic_cast<ContractDefinition const*>(_modifier.scope()))
{
if (_modifier.virtualSemantics() && contractDef->isLibrary())
m_errorReporter.typeError(
3275_error,
_modifier.location(),
"Modifiers in a library cannot be virtual."
);
if (contractDef->isInterface())
m_errorReporter.typeError(
6408_error,
_modifier.location(),
"Modifiers cannot be defined or declared in interfaces."
);
}
if (!_modifier.isImplemented() && !_modifier.virtualSemantics())
m_errorReporter.typeError(8063_error, _modifier.location(), "Modifiers without implementation must be marked virtual.");
@@ -754,7 +765,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
solAssert(var->type(), "Expected variable type!");
if (var->immutable())
{
m_errorReporter.typeError(3773_error, _identifier.debugData->location, "Assembly access to immutable variables is not supported.");
m_errorReporter.typeError(3773_error, nativeLocationOf(_identifier), "Assembly access to immutable variables is not supported.");
return false;
}
if (var->isConstant())
@@ -763,7 +774,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
{
m_errorReporter.typeError(
3558_error,
_identifier.debugData->location,
nativeLocationOf(_identifier),
"Constant variable is circular."
);
return false;
@@ -773,24 +784,24 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
if (var && !var->value())
{
m_errorReporter.typeError(3224_error, _identifier.debugData->location, "Constant has no value.");
m_errorReporter.typeError(3224_error, nativeLocationOf(_identifier), "Constant has no value.");
return false;
}
else if (_context == yul::IdentifierContext::LValue)
{
m_errorReporter.typeError(6252_error, _identifier.debugData->location, "Constant variables cannot be assigned to.");
m_errorReporter.typeError(6252_error, nativeLocationOf(_identifier), "Constant variables cannot be assigned to.");
return false;
}
else if (!identifierInfo.suffix.empty())
else if (identifierInfo.suffix == "slot" || identifierInfo.suffix == "offset")
{
m_errorReporter.typeError(6617_error, _identifier.debugData->location, "The suffixes .offset and .slot can only be used on non-constant storage variables.");
m_errorReporter.typeError(6617_error, nativeLocationOf(_identifier), "The suffixes .offset and .slot can only be used on non-constant storage variables.");
return false;
}
else if (var && var->value() && !var->value()->annotation().type && !dynamic_cast<Literal const*>(var->value().get()))
{
m_errorReporter.typeError(
2249_error,
_identifier.debugData->location,
nativeLocationOf(_identifier),
"Constant variables with non-literal values cannot be forward referenced from inline assembly."
);
return false;
@@ -800,7 +811,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
type(*var->value())->category() != Type::Category::RationalNumber
))
{
m_errorReporter.typeError(7615_error, _identifier.debugData->location, "Only direct number constants and references to such constants are supported by inline assembly.");
m_errorReporter.typeError(7615_error, nativeLocationOf(_identifier), "Only direct number constants and references to such constants are supported by inline assembly.");
return false;
}
}
@@ -810,24 +821,24 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
if (!identifierInfo.suffix.empty())
{
string const& suffix = identifierInfo.suffix;
solAssert((set<string>{"offset", "slot", "length"}).count(suffix), "");
if (var->isStateVariable() || var->type()->dataStoredIn(DataLocation::Storage))
solAssert((set<string>{"offset", "slot", "length", "selector", "address"}).count(suffix), "");
if (!var->isConstant() && (var->isStateVariable() || var->type()->dataStoredIn(DataLocation::Storage)))
{
if (suffix != "slot" && suffix != "offset")
{
m_errorReporter.typeError(4656_error, _identifier.debugData->location, "State variables only support \".slot\" and \".offset\".");
m_errorReporter.typeError(4656_error, nativeLocationOf(_identifier), "State variables only support \".slot\" and \".offset\".");
return false;
}
else if (_context == yul::IdentifierContext::LValue)
{
if (var->isStateVariable())
{
m_errorReporter.typeError(4713_error, _identifier.debugData->location, "State variables cannot be assigned to - you have to use \"sstore()\".");
m_errorReporter.typeError(4713_error, nativeLocationOf(_identifier), "State variables cannot be assigned to - you have to use \"sstore()\".");
return false;
}
else if (suffix != "slot")
{
m_errorReporter.typeError(9739_error, _identifier.debugData->location, "Only .slot can be assigned to.");
m_errorReporter.typeError(9739_error, nativeLocationOf(_identifier), "Only .slot can be assigned to.");
return false;
}
}
@@ -839,13 +850,26 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
{
if (suffix != "offset" && suffix != "length")
{
m_errorReporter.typeError(1536_error, _identifier.debugData->location, "Calldata variables only support \".offset\" and \".length\".");
m_errorReporter.typeError(1536_error, nativeLocationOf(_identifier), "Calldata variables only support \".offset\" and \".length\".");
return false;
}
}
else if (auto const* fpType = dynamic_cast<FunctionTypePointer>(var->type()))
{
if (suffix != "selector" && suffix != "address")
{
m_errorReporter.typeError(9272_error, nativeLocationOf(_identifier), "Variables of type function pointer only support \".selector\" and \".address\".");
return false;
}
if (fpType->kind() != FunctionType::Kind::External)
{
m_errorReporter.typeError(8533_error, nativeLocationOf(_identifier), "Only Variables of type external function pointer support \".selector\" and \".address\".");
return false;
}
}
else
{
m_errorReporter.typeError(3622_error, _identifier.debugData->location, "The suffix \"." + suffix + "\" is not supported by this variable or type.");
m_errorReporter.typeError(3622_error, nativeLocationOf(_identifier), "The suffix \"." + suffix + "\" is not supported by this variable or type.");
return false;
}
}
@@ -853,14 +877,14 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
{
m_errorReporter.typeError(
1408_error,
_identifier.debugData->location,
nativeLocationOf(_identifier),
"Only local variables are supported. To access storage variables, use the \".slot\" and \".offset\" suffixes."
);
return false;
}
else if (var->type()->dataStoredIn(DataLocation::Storage))
{
m_errorReporter.typeError(9068_error, _identifier.debugData->location, "You have to use the \".slot\" or \".offset\" suffix to access storage reference variables.");
m_errorReporter.typeError(9068_error, nativeLocationOf(_identifier), "You have to use the \".slot\" or \".offset\" suffix to access storage reference variables.");
return false;
}
else if (var->type()->sizeOnStack() != 1)
@@ -869,18 +893,18 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
auto const* arrayType = dynamic_cast<ArrayType const*>(var->type());
arrayType && arrayType->isDynamicallySized() && arrayType->dataStoredIn(DataLocation::CallData)
)
m_errorReporter.typeError(1397_error, _identifier.debugData->location, "Call data elements cannot be accessed directly. Use \".offset\" and \".length\" to access the calldata offset and length of this array and then use \"calldatacopy\".");
m_errorReporter.typeError(1397_error, nativeLocationOf(_identifier), "Call data elements cannot be accessed directly. Use \".offset\" and \".length\" to access the calldata offset and length of this array and then use \"calldatacopy\".");
else
{
solAssert(!var->type()->dataStoredIn(DataLocation::CallData), "");
m_errorReporter.typeError(9857_error, _identifier.debugData->location, "Only types that use one stack slot are supported.");
m_errorReporter.typeError(9857_error, nativeLocationOf(_identifier), "Only types that use one stack slot are supported.");
}
return false;
}
}
else if (!identifierInfo.suffix.empty())
{
m_errorReporter.typeError(7944_error, _identifier.debugData->location, "The suffixes \".offset\", \".slot\" and \".length\" can only be used with variables.");
m_errorReporter.typeError(7944_error, nativeLocationOf(_identifier), "The suffixes \".offset\", \".slot\" and \".length\" can only be used with variables.");
return false;
}
else if (_context == yul::IdentifierContext::LValue)
@@ -888,7 +912,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
if (dynamic_cast<MagicVariableDeclaration const*>(declaration))
return false;
m_errorReporter.typeError(1990_error, _identifier.debugData->location, "Only local variables can be assigned to in inline assembly.");
m_errorReporter.typeError(1990_error, nativeLocationOf(_identifier), "Only local variables can be assigned to in inline assembly.");
return false;
}
@@ -897,7 +921,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
solAssert(!!declaration->type(), "Type of declaration required but not yet determined.");
if (dynamic_cast<FunctionDefinition const*>(declaration))
{
m_errorReporter.declarationError(2025_error, _identifier.debugData->location, "Access to functions is not allowed in inline assembly.");
m_errorReporter.declarationError(2025_error, nativeLocationOf(_identifier), "Access to functions is not allowed in inline assembly.");
return false;
}
else if (dynamic_cast<VariableDeclaration const*>(declaration))
@@ -907,7 +931,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
{
if (!contract->isLibrary())
{
m_errorReporter.typeError(4977_error, _identifier.debugData->location, "Expected a library.");
m_errorReporter.typeError(4977_error, nativeLocationOf(_identifier), "Expected a library.");
return false;
}
}
@@ -2470,6 +2494,13 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
returnTypes = functionType->returnParameterTypes();
break;
}
case FunctionType::Kind::Wrap:
case FunctionType::Kind::Unwrap:
{
typeCheckFunctionGeneralChecks(_functionCall, functionType);
returnTypes = functionType->returnParameterTypes();
break;
}
default:
{
typeCheckFunctionCall(_functionCall, functionType);
@@ -2907,7 +2938,10 @@ bool TypeChecker::visit(MemberAccess const& _memberAccess)
// TODO some members might be pure, but for example `address(0x123).balance` is not pure
// although every subexpression is, so leaving this limited for now.
if (auto tt = dynamic_cast<TypeType const*>(exprType))
if (tt->actualType()->category() == Type::Category::Enum)
if (
tt->actualType()->category() == Type::Category::Enum ||
tt->actualType()->category() == Type::Category::UserDefinedValueType
)
annotation.isPure = true;
if (
auto const* functionType = dynamic_cast<FunctionType const*>(exprType);
+1 -1
View File
@@ -69,7 +69,7 @@ public:
if (yul::EVMDialect const* dialect = dynamic_cast<decltype(dialect)>(&m_dialect))
if (yul::BuiltinFunctionForEVM const* fun = dialect->builtin(_funCall.functionName.name))
if (fun->instruction)
checkInstruction(_funCall.debugData->location, *fun->instruction);
checkInstruction(nativeLocationOf(_funCall), *fun->instruction);
for (auto const& arg: _funCall.arguments)
std::visit(*this, arg);