aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity')
-rw-r--r--libsolidity/analysis/ControlFlowAnalyzer.cpp10
-rw-r--r--libsolidity/analysis/NameAndTypeResolver.cpp5
-rw-r--r--libsolidity/analysis/ReferencesResolver.cpp223
-rw-r--r--libsolidity/analysis/ReferencesResolver.h1
-rw-r--r--libsolidity/analysis/TypeChecker.cpp97
-rw-r--r--libsolidity/analysis/TypeChecker.h4
-rw-r--r--libsolidity/ast/AST.cpp14
-rw-r--r--libsolidity/ast/AST.h5
-rw-r--r--libsolidity/ast/ASTJsonConverter.cpp6
-rw-r--r--libsolidity/ast/ExperimentalFeatures.h3
-rw-r--r--libsolidity/ast/Types.cpp45
-rw-r--r--libsolidity/ast/Types.h8
-rw-r--r--libsolidity/codegen/ABIFunctions.cpp3
-rw-r--r--libsolidity/codegen/Compiler.cpp13
-rw-r--r--libsolidity/codegen/Compiler.h6
-rw-r--r--libsolidity/codegen/CompilerContext.cpp2
-rw-r--r--libsolidity/codegen/CompilerUtils.cpp12
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp44
-rw-r--r--libsolidity/codegen/ContractCompiler.h10
-rw-r--r--libsolidity/formal/SMTChecker.cpp10
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.cpp6
-rw-r--r--libsolidity/interface/CompilerStack.cpp48
-rw-r--r--libsolidity/interface/CompilerStack.h14
-rw-r--r--libsolidity/interface/StandardCompiler.cpp4
-rw-r--r--libsolidity/interface/StandardCompiler.h4
25 files changed, 250 insertions, 347 deletions
diff --git a/libsolidity/analysis/ControlFlowAnalyzer.cpp b/libsolidity/analysis/ControlFlowAnalyzer.cpp
index 6edf7986..483d08c8 100644
--- a/libsolidity/analysis/ControlFlowAnalyzer.cpp
+++ b/libsolidity/analysis/ControlFlowAnalyzer.cpp
@@ -144,12 +144,12 @@ void ControlFlowAnalyzer::checkUnassignedStorageReturnValues(
ssl.append("Problematic end of function:", _function.location());
}
- m_errorReporter.warning(
+ m_errorReporter.typeError(
returnVal->location(),
- "This variable is of storage pointer type and might be returned without assignment. "
- "This can cause storage corruption. Assign the variable (potentially from itself) "
- "to remove this warning.",
- ssl
+ ssl,
+ "This variable is of storage pointer type and might be returned without assignment and "
+ "could be used uninitialized. Assign the variable (potentially from itself) "
+ "to fix this error."
);
}
}
diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp
index 823378c7..c5c429ce 100644
--- a/libsolidity/analysis/NameAndTypeResolver.cpp
+++ b/libsolidity/analysis/NameAndTypeResolver.cpp
@@ -231,7 +231,7 @@ vector<Declaration const*> NameAndTypeResolver::cleanedDeclarations(
shared_ptr<FunctionType const> newFunctionType { d->functionType(false) };
if (!newFunctionType)
newFunctionType = d->functionType(true);
- return newFunctionType && functionType->hasEqualArgumentTypes(*newFunctionType);
+ return newFunctionType && functionType->hasEqualParameterTypes(*newFunctionType);
}
))
uniqueFunctions.push_back(declaration);
@@ -295,10 +295,7 @@ bool NameAndTypeResolver::resolveNamesAndTypesInternal(ASTNode& _node, bool _res
{
setScope(contract);
if (!resolveNamesAndTypes(*node, false))
- {
success = false;
- break;
- }
}
if (!success)
diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp
index a9a998b0..501521f5 100644
--- a/libsolidity/analysis/ReferencesResolver.cpp
+++ b/libsolidity/analysis/ReferencesResolver.cpp
@@ -47,7 +47,6 @@ bool ReferencesResolver::visit(Block const& _block)
{
if (!m_resolveInsideCode)
return false;
- m_experimental050Mode = _block.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050);
m_resolver.setScope(&_block);
return true;
}
@@ -64,7 +63,6 @@ bool ReferencesResolver::visit(ForStatement const& _for)
{
if (!m_resolveInsideCode)
return false;
- m_experimental050Mode = _for.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050);
m_resolver.setScope(&_for);
return true;
}
@@ -258,6 +256,11 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly)
string("_slot").size() :
string("_offset").size()
));
+ if (realName.empty())
+ {
+ declarationError(_identifier.location, "In variable names _slot and _offset can only be used as a suffix.");
+ return size_t(-1);
+ }
declarations = m_resolver.nameFromCurrentScope(realName);
}
if (declarations.size() != 1)
@@ -277,7 +280,7 @@ bool ReferencesResolver::visit(InlineAssembly const& _inlineAssembly)
// Will be re-generated later with correct information
// We use the latest EVM version because we will re-run it anyway.
assembly::AsmAnalysisInfo analysisInfo;
- boost::optional<Error::Type> errorTypeForLoose = m_experimental050Mode ? Error::Type::SyntaxError : Error::Type::Warning;
+ boost::optional<Error::Type> errorTypeForLoose = Error::Type::SyntaxError;
assembly::AsmAnalyzer(analysisInfo, errorsIgnored, EVMVersion(), errorTypeForLoose, assembly::AsmFlavour::Loose, resolver).analyze(_inlineAssembly.operations());
return false;
}
@@ -294,134 +297,138 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable)
if (_variable.annotation().type)
return;
+ if (!_variable.typeName())
+ {
+ // This can still happen in very unusual cases where a developer uses constructs, such as
+ // `var a;`, however, such code will have generated errors already.
+ // However, we cannot blindingly solAssert() for that here, as the TypeChecker (which is
+ // invoking ReferencesResolver) is generating it, so the error is most likely(!) generated
+ // after this step.
+ return;
+ }
+
TypePointer type;
- if (_variable.typeName())
+ type = _variable.typeName()->annotation().type;
+ using Location = VariableDeclaration::Location;
+ Location varLoc = _variable.referenceLocation();
+ DataLocation typeLoc = DataLocation::Memory;
+ // References are forced to calldata for external function parameters (not return)
+ // and memory for parameters (also return) of publicly visible functions.
+ // They default to memory for function parameters and storage for local variables.
+ // As an exception, "storage" is allowed for library functions.
+ if (auto ref = dynamic_cast<ReferenceType const*>(type.get()))
{
- type = _variable.typeName()->annotation().type;
- using Location = VariableDeclaration::Location;
- Location varLoc = _variable.referenceLocation();
- DataLocation typeLoc = DataLocation::Memory;
- // References are forced to calldata for external function parameters (not return)
- // and memory for parameters (also return) of publicly visible functions.
- // They default to memory for function parameters and storage for local variables.
- // As an exception, "storage" is allowed for library functions.
- if (auto ref = dynamic_cast<ReferenceType const*>(type.get()))
+ bool isPointer = true;
+ if (_variable.isExternalCallableParameter())
{
- bool isPointer = true;
- if (_variable.isExternalCallableParameter())
+ auto const& contract = dynamic_cast<ContractDefinition const&>(
+ *dynamic_cast<Declaration const&>(*_variable.scope()).scope()
+ );
+ if (contract.isLibrary())
{
- auto const& contract = dynamic_cast<ContractDefinition const&>(
- *dynamic_cast<Declaration const&>(*_variable.scope()).scope()
- );
- if (contract.isLibrary())
- {
- if (varLoc == Location::Memory)
- fatalTypeError(_variable.location(),
- "Location has to be calldata or storage for external "
- "library functions (remove the \"memory\" keyword)."
- );
- }
- else
- {
- // force location of external function parameters (not return) to calldata
- if (varLoc != Location::CallData && varLoc != Location::Default)
- fatalTypeError(_variable.location(),
- "Location has to be calldata for external functions "
- "(remove the \"memory\" or \"storage\" keyword)."
- );
- }
- if (varLoc == Location::Default)
- typeLoc = DataLocation::CallData;
- else
- typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage;
+ if (varLoc == Location::Memory)
+ fatalTypeError(_variable.location(),
+ "Location has to be calldata or storage for external "
+ "library functions (remove the \"memory\" keyword)."
+ );
}
- else if (_variable.isCallableParameter() && dynamic_cast<Declaration const&>(*_variable.scope()).isPublic())
+ else
{
- auto const& contract = dynamic_cast<ContractDefinition const&>(
- *dynamic_cast<Declaration const&>(*_variable.scope()).scope()
+ // force location of external function parameters (not return) to calldata
+ if (varLoc != Location::CallData && varLoc != Location::Default)
+ fatalTypeError(_variable.location(),
+ "Location has to be calldata for external functions "
+ "(remove the \"memory\" or \"storage\" keyword)."
+ );
+ }
+ if (varLoc == Location::Default)
+ typeLoc = DataLocation::CallData;
+ else
+ typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage;
+ }
+ else if (_variable.isCallableParameter() && dynamic_cast<Declaration const&>(*_variable.scope()).isPublic())
+ {
+ auto const& contract = dynamic_cast<ContractDefinition const&>(
+ *dynamic_cast<Declaration const&>(*_variable.scope()).scope()
+ );
+ // force locations of public or external function (return) parameters to memory
+ if (varLoc != Location::Memory && varLoc != Location::Default && !contract.isLibrary())
+ fatalTypeError(_variable.location(),
+ "Location has to be memory for publicly visible functions "
+ "(remove the \"storage\" or \"calldata\" keyword)."
);
- // force locations of public or external function (return) parameters to memory
- if (varLoc != Location::Memory && varLoc != Location::Default && !contract.isLibrary())
+ if (varLoc == Location::Default || !contract.isLibrary())
+ typeLoc = DataLocation::Memory;
+ else
+ {
+ if (varLoc == Location::CallData)
fatalTypeError(_variable.location(),
- "Location has to be memory for publicly visible functions "
- "(remove the \"storage\" or \"calldata\" keyword)."
+ "Location cannot be calldata for non-external functions "
+ "(remove the \"calldata\" keyword)."
);
- if (varLoc == Location::Default || !contract.isLibrary())
+ typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage;
+ }
+ }
+ else
+ {
+ if (_variable.isConstant())
+ {
+ if (varLoc != Location::Default && varLoc != Location::Memory)
+ fatalTypeError(
+ _variable.location(),
+ "Data location has to be \"memory\" (or unspecified) for constants."
+ );
+ typeLoc = DataLocation::Memory;
+ }
+ else if (varLoc == Location::Default)
+ {
+ if (_variable.isCallableParameter())
typeLoc = DataLocation::Memory;
else
{
- if (varLoc == Location::CallData)
- fatalTypeError(_variable.location(),
- "Location cannot be calldata for non-external functions "
- "(remove the \"calldata\" keyword)."
+ typeLoc = DataLocation::Storage;
+ if (_variable.isLocalVariable())
+ typeError(
+ _variable.location(),
+ "Data location must be specified as either \"memory\" or \"storage\"."
);
- typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage;
}
}
else
{
- if (_variable.isConstant())
+ switch (varLoc)
{
- if (varLoc != Location::Default && varLoc != Location::Memory)
- fatalTypeError(
- _variable.location(),
- "Data location has to be \"memory\" (or unspecified) for constants."
- );
+ case Location::Memory:
typeLoc = DataLocation::Memory;
+ break;
+ case Location::Storage:
+ typeLoc = DataLocation::Storage;
+ break;
+ case Location::CallData:
+ fatalTypeError(_variable.location(),
+ "Variable cannot be declared as \"calldata\" (remove the \"calldata\" keyword)."
+ );
+ break;
+ default:
+ solAssert(false, "Unknown data location");
}
- else if (varLoc == Location::Default)
- {
- if (_variable.isCallableParameter())
- typeLoc = DataLocation::Memory;
- else
- {
- typeLoc = DataLocation::Storage;
- if (_variable.isLocalVariable())
- typeError(
- _variable.location(),
- "Data location must be specified as either \"memory\" or \"storage\"."
- );
- }
- }
- else
- {
- switch (varLoc)
- {
- case Location::Memory:
- typeLoc = DataLocation::Memory;
- break;
- case Location::Storage:
- typeLoc = DataLocation::Storage;
- break;
- case Location::CallData:
- fatalTypeError(_variable.location(),
- "Variable cannot be declared as \"calldata\" (remove the \"calldata\" keyword)."
- );
- break;
- default:
- solAssert(false, "Unknown data location");
- }
- }
- isPointer = !_variable.isStateVariable();
}
- type = ref->copyForLocation(typeLoc, isPointer);
+ isPointer = !_variable.isStateVariable();
}
- else if (dynamic_cast<MappingType const*>(type.get()))
- {
- if (_variable.isLocalVariable() && varLoc != Location::Storage)
- typeError(
- _variable.location(),
- "Data location for mappings must be specified as \"storage\"."
- );
- }
- else if (varLoc != Location::Default && !ref)
- typeError(_variable.location(), "Data location can only be given for array or struct types.");
-
- _variable.annotation().type = type;
+ type = ref->copyForLocation(typeLoc, isPointer);
}
- else if (!_variable.canHaveAutoType())
- typeError(_variable.location(), "Explicit type needed.");
- // otherwise we have a "var"-declaration whose type is resolved by the first assignment
+ else if (dynamic_cast<MappingType const*>(type.get()))
+ {
+ if (_variable.isLocalVariable() && varLoc != Location::Storage)
+ typeError(
+ _variable.location(),
+ "Data location for mappings must be specified as \"storage\"."
+ );
+ }
+ else if (varLoc != Location::Default && !ref)
+ typeError(_variable.location(), "Data location can only be given for array or struct types.");
+
+ _variable.annotation().type = type;
}
void ReferencesResolver::typeError(SourceLocation const& _location, string const& _description)
diff --git a/libsolidity/analysis/ReferencesResolver.h b/libsolidity/analysis/ReferencesResolver.h
index 4e8f54b5..24ec4643 100644
--- a/libsolidity/analysis/ReferencesResolver.h
+++ b/libsolidity/analysis/ReferencesResolver.h
@@ -94,7 +94,6 @@ private:
std::vector<ParameterList const*> m_returnParameters;
bool const m_resolveInsideCode;
bool m_errorOccurred = false;
- bool m_experimental050Mode = false;
};
}
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 8c84e4dc..6882a14f 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -214,7 +214,7 @@ void TypeChecker::findDuplicateDefinitions(map<string, vector<T>> const& _defini
SecondarySourceLocation ssl;
for (size_t j = i + 1; j < overloads.size(); ++j)
- if (FunctionType(*overloads[i]).hasEqualArgumentTypes(FunctionType(*overloads[j])))
+ if (FunctionType(*overloads[i]).hasEqualParameterTypes(FunctionType(*overloads[j])))
{
ssl.append("Other declaration is here:", overloads[j]->location());
reported.insert(j);
@@ -252,7 +252,7 @@ void TypeChecker::checkContractAbstractFunctions(ContractDefinition const& _cont
FunctionTypePointer funType = make_shared<FunctionType>(*function);
auto it = find_if(overloads.begin(), overloads.end(), [&](FunTypeAndFlag const& _funAndFlag)
{
- return funType->hasEqualArgumentTypes(*_funAndFlag.first);
+ return funType->hasEqualParameterTypes(*_funAndFlag.first);
});
if (it == overloads.end())
overloads.push_back(make_pair(funType, function->isImplemented()));
@@ -404,7 +404,7 @@ void TypeChecker::checkFunctionOverride(FunctionDefinition const& function, Func
FunctionType functionType(function);
FunctionType superType(super);
- if (!functionType.hasEqualArgumentTypes(superType))
+ if (!functionType.hasEqualParameterTypes(superType))
return;
if (!function.annotation().superFunction)
@@ -475,7 +475,7 @@ void TypeChecker::checkContractExternalTypeClashes(ContractDefinition const& _co
for (auto const& it: externalDeclarations)
for (size_t i = 0; i < it.second.size(); ++i)
for (size_t j = i + 1; j < it.second.size(); ++j)
- if (!it.second[i].second->hasEqualArgumentTypes(*it.second[j].second))
+ if (!it.second[i].second->hasEqualParameterTypes(*it.second[j].second))
m_errorReporter.typeError(
it.second[j].first->location(),
"Function overload clash during conversion to external types for arguments."
@@ -498,7 +498,12 @@ void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment)
TupleType const& lhs = dynamic_cast<TupleType const&>(*type(_assignment.leftHandSide()));
TupleType const& rhs = dynamic_cast<TupleType const&>(*type(_assignment.rightHandSide()));
- bool fillRight = !lhs.components().empty() && (!lhs.components().back() || lhs.components().front());
+ if (lhs.components().size() != rhs.components().size())
+ {
+ solAssert(m_errorReporter.hasErrors(), "");
+ return;
+ }
+
size_t storageToStorageCopies = 0;
size_t toStorageCopies = 0;
for (size_t i = 0; i < lhs.components().size(); ++i)
@@ -506,10 +511,8 @@ void TypeChecker::checkDoubleStorageAssignment(Assignment const& _assignment)
ReferenceType const* ref = dynamic_cast<ReferenceType const*>(lhs.components()[i].get());
if (!ref || !ref->dataStoredIn(DataLocation::Storage) || ref->isPointer())
continue;
- size_t rhsPos = fillRight ? i : rhs.components().size() - (lhs.components().size() - i);
- solAssert(rhsPos < rhs.components().size(), "");
toStorageCopies++;
- if (rhs.components()[rhsPos]->dataStoredIn(DataLocation::Storage))
+ if (rhs.components()[i]->dataStoredIn(DataLocation::Storage))
storageToStorageCopies++;
}
if (storageToStorageCopies >= 1 && toStorageCopies >= 2)
@@ -751,13 +754,6 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
return false;
}
-bool TypeChecker::visit(EnumDefinition const& _enum)
-{
- if (m_scope->contractKind() == ContractDefinition::ContractKind::Interface)
- m_errorReporter.typeError(_enum.location(), "Enumerable cannot be declared in interfaces.");
- return false;
-}
-
void TypeChecker::visitManually(
ModifierInvocation const& _modifier,
vector<ContractDefinition const*> const& _bases
@@ -817,6 +813,7 @@ void TypeChecker::visitManually(
bool TypeChecker::visit(EventDefinition const& _eventDef)
{
+ solAssert(_eventDef.visibility() > Declaration::Visibility::Internal, "");
unsigned numIndexed = 0;
for (ASTPointer<VariableDeclaration> const& var: _eventDef.parameters())
{
@@ -826,6 +823,15 @@ bool TypeChecker::visit(EventDefinition const& _eventDef)
m_errorReporter.typeError(var->location(), "Type is required to live outside storage.");
if (!type(*var)->interfaceType(false))
m_errorReporter.typeError(var->location(), "Internal or recursive type is not allowed as event parameter type.");
+ if (
+ !_eventDef.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) &&
+ !typeSupportedByOldABIEncoder(*type(*var))
+ )
+ m_errorReporter.typeError(
+ var->location(),
+ "This type is only supported in the new experimental ABI encoder. "
+ "Use \"pragma experimental ABIEncoderV2;\" to enable the feature."
+ );
}
if (_eventDef.isAnonymous() && numIndexed > 4)
m_errorReporter.typeError(_eventDef.location(), "More than 4 indexed arguments for anonymous event.");
@@ -857,6 +863,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
return size_t(-1);
Declaration const* declaration = ref->second.declaration;
solAssert(!!declaration, "");
+ bool requiresStorage = ref->second.isSlot || ref->second.isOffset;
if (auto var = dynamic_cast<VariableDeclaration const*>(declaration))
{
if (var->isConstant())
@@ -864,7 +871,7 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
m_errorReporter.typeError(_identifier.location, "Constant variables not supported by inline assembly.");
return size_t(-1);
}
- else if (ref->second.isSlot || ref->second.isOffset)
+ else if (requiresStorage)
{
if (!var->isStateVariable() && !var->type()->dataStoredIn(DataLocation::Storage))
{
@@ -896,6 +903,11 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
return size_t(-1);
}
}
+ else if (requiresStorage)
+ {
+ m_errorReporter.typeError(_identifier.location, "The suffixes _offset and _slot can only be used on storage variables.");
+ return size_t(-1);
+ }
else if (_context == julia::IdentifierContext::LValue)
{
m_errorReporter.typeError(_identifier.location, "Only local variables can be assigned to in inline assembly.");
@@ -927,15 +939,11 @@ bool TypeChecker::visit(InlineAssembly const& _inlineAssembly)
};
solAssert(!_inlineAssembly.annotation().analysisInfo, "");
_inlineAssembly.annotation().analysisInfo = make_shared<assembly::AsmAnalysisInfo>();
- boost::optional<Error::Type> errorTypeForLoose =
- m_scope->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050) ?
- Error::Type::SyntaxError :
- Error::Type::Warning;
assembly::AsmAnalyzer analyzer(
*_inlineAssembly.annotation().analysisInfo,
m_errorReporter,
m_evmVersion,
- errorTypeForLoose,
+ Error::Type::SyntaxError,
assembly::AsmFlavour::Loose,
identifierAccess
);
@@ -974,9 +982,13 @@ bool TypeChecker::visit(ForStatement const& _forStatement)
void TypeChecker::endVisit(Return const& _return)
{
+ ParameterList const* params = _return.annotation().functionReturnParameters;
if (!_return.expression())
+ {
+ if (params && !params->parameters().empty())
+ m_errorReporter.typeError(_return.location(), "Return arguments required.");
return;
- ParameterList const* params = _return.annotation().functionReturnParameters;
+ }
if (!params)
{
m_errorReporter.typeError(_return.location(), "Return arguments not allowed.");
@@ -1038,7 +1050,10 @@ string createTupleDecl(vector<ASTPointer<VariableDeclaration>> const& _decls)
vector<string> components;
for (ASTPointer<VariableDeclaration> const& decl: _decls)
if (decl)
+ {
+ solAssert(decl->annotation().type, "");
components.emplace_back(decl->annotation().type->toString(false) + " " + decl->name());
+ }
else
components.emplace_back();
@@ -1056,6 +1071,9 @@ bool typeCanBeExpressed(vector<ASTPointer<VariableDeclaration>> const& decls)
if (!decl)
continue;
+ if (!decl->annotation().type)
+ return false;
+
if (auto functionType = dynamic_cast<FunctionType const*>(decl->annotation().type.get()))
if (
functionType->kind() != FunctionType::Kind::Internal &&
@@ -1318,11 +1336,41 @@ bool TypeChecker::visit(Conditional const& _conditional)
return false;
}
+void TypeChecker::checkExpressionAssignment(Type const& _type, Expression const& _expression)
+{
+ if (auto const* tupleExpression = dynamic_cast<TupleExpression const*>(&_expression))
+ {
+ auto const* tupleType = dynamic_cast<TupleType const*>(&_type);
+ auto const& types = tupleType ? tupleType->components() : vector<TypePointer> { _type.shared_from_this() };
+
+ solAssert(tupleExpression->components().size() == types.size(), "");
+ for (size_t i = 0; i < types.size(); i++)
+ if (types[i])
+ {
+ solAssert(!!tupleExpression->components()[i], "");
+ checkExpressionAssignment(*types[i], *tupleExpression->components()[i]);
+ }
+ }
+ else if (_type.category() == Type::Category::Mapping)
+ {
+ bool isLocalOrReturn = false;
+ if (auto const* identifier = dynamic_cast<Identifier const*>(&_expression))
+ if (auto const *variableDeclaration = dynamic_cast<VariableDeclaration const*>(identifier->annotation().referencedDeclaration))
+ if (variableDeclaration->isLocalOrReturn())
+ isLocalOrReturn = true;
+ if (!isLocalOrReturn)
+ m_errorReporter.typeError(_expression.location(), "Mappings cannot be assigned to.");
+ }
+}
+
bool TypeChecker::visit(Assignment const& _assignment)
{
requireLValue(_assignment.leftHandSide());
TypePointer t = type(_assignment.leftHandSide());
_assignment.annotation().type = t;
+
+ checkExpressionAssignment(*t, _assignment.leftHandSide());
+
if (TupleType const* tupleType = dynamic_cast<TupleType const*>(t.get()))
{
if (_assignment.assignmentOperator() != Token::Assign)
@@ -1339,11 +1387,6 @@ bool TypeChecker::visit(Assignment const& _assignment)
if (dynamic_cast<TupleType const*>(type(_assignment.rightHandSide()).get()))
checkDoubleStorageAssignment(_assignment);
}
- else if (t->category() == Type::Category::Mapping)
- {
- m_errorReporter.typeError(_assignment.location(), "Mappings cannot be assigned to.");
- _assignment.rightHandSide().accept(*this);
- }
else if (_assignment.assignmentOperator() == Token::Assign)
expectType(_assignment.rightHandSide(), *t);
else
diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h
index 8dc6b376..b696de85 100644
--- a/libsolidity/analysis/TypeChecker.h
+++ b/libsolidity/analysis/TypeChecker.h
@@ -87,13 +87,15 @@ private:
/// Checks (and warns) if a tuple assignment might cause unexpected overwrites in storage.
/// Should only be called if the left hand side is tuple-typed.
void checkDoubleStorageAssignment(Assignment const& _assignment);
+ // Checks whether the expression @arg _expression can be assigned from type @arg _type
+ // and reports an error, if not.
+ void checkExpressionAssignment(Type const& _type, Expression const& _expression);
virtual void endVisit(InheritanceSpecifier const& _inheritance) override;
virtual void endVisit(UsingForDirective const& _usingFor) override;
virtual bool visit(StructDefinition const& _struct) override;
virtual bool visit(FunctionDefinition const& _function) override;
virtual bool visit(VariableDeclaration const& _variable) override;
- virtual bool visit(EnumDefinition const& _enum) override;
/// We need to do this manually because we want to pass the bases of the current contract in
/// case this is a base constructor call.
void visitManually(ModifierInvocation const& _modifier, std::vector<ContractDefinition const*> const& _bases);
diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp
index 7719d080..23797d52 100644
--- a/libsolidity/ast/AST.cpp
+++ b/libsolidity/ast/AST.cpp
@@ -347,15 +347,6 @@ string FunctionDefinition::externalSignature() const
return FunctionType(*this).externalSignature();
}
-string FunctionDefinition::fullyQualifiedName() const
-{
- auto const* contract = dynamic_cast<ContractDefinition const*>(scope());
- solAssert(contract, "Enclosing scope of function definition was not set.");
-
- auto fname = name().empty() ? "<fallback>" : name();
- return sourceUnitName() + ":" + contract->name() + "." + fname;
-}
-
FunctionDefinitionAnnotation& FunctionDefinition::annotation() const
{
if (!m_annotation)
@@ -475,11 +466,6 @@ bool VariableDeclaration::isExternalCallableParameter() const
return false;
}
-bool VariableDeclaration::canHaveAutoType() const
-{
- return isLocalVariable() && !isCallableParameter();
-}
-
TypePointer VariableDeclaration::type() const
{
return annotation().type;
diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h
index 9ed3b9aa..69c6fa05 100644
--- a/libsolidity/ast/AST.h
+++ b/libsolidity/ast/AST.h
@@ -206,7 +206,6 @@ public:
bool isVisibleInDerivedContracts() const { return isVisibleInContract() && visibility() >= Visibility::Internal; }
bool isVisibleAsLibraryMember() const { return visibility() >= Visibility::Internal; }
- std::string fullyQualifiedName() const { return sourceUnitName() + ":" + name(); }
virtual bool isLValue() const { return false; }
virtual bool isPartOfExternalInterface() const { return false; }
@@ -406,6 +405,8 @@ public:
/// Returns the fallback function or nullptr if no fallback function was specified.
FunctionDefinition const* fallbackFunction() const;
+ std::string fullyQualifiedName() const { return sourceUnitName() + ":" + name(); }
+
virtual TypePointer type() const override;
virtual ContractDefinitionAnnotation& annotation() const override;
@@ -619,7 +620,6 @@ public:
std::vector<ASTPointer<ModifierInvocation>> const& modifiers() const { return m_functionModifiers; }
std::vector<ASTPointer<VariableDeclaration>> const& returnParameters() const { return m_returnParameters->parameters(); }
Block const& body() const { solAssert(m_body, ""); return *m_body; }
- std::string fullyQualifiedName() const;
virtual bool isVisibleInContract() const override
{
return Declaration::isVisibleInContract() && !isConstructor() && !isFallback();
@@ -696,7 +696,6 @@ public:
bool isExternalCallableParameter() const;
/// @returns true if the type of the variable does not need to be specified, i.e. it is declared
/// in the body of a function or modifier.
- bool canHaveAutoType() const;
bool isStateVariable() const { return m_isStateVariable; }
bool isIndexed() const { return m_isIndexed; }
bool isConstant() const { return m_isConstant; }
diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp
index 7c04741d..72b20b3b 100644
--- a/libsolidity/ast/ASTJsonConverter.cpp
+++ b/libsolidity/ast/ASTJsonConverter.cpp
@@ -325,9 +325,6 @@ bool ASTJsonConverter::visit(FunctionDefinition const& _node)
std::vector<pair<string, Json::Value>> attributes = {
make_pair("name", _node.name()),
make_pair("documentation", _node.documentation() ? Json::Value(*_node.documentation()) : Json::nullValue),
- // FIXME: remove with next breaking release
- make_pair(m_legacy ? "constant" : "isDeclaredConst", _node.stateMutability() <= StateMutability::View),
- make_pair("payable", _node.isPayable()),
make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
make_pair("superFunction", idOrNull(_node.annotation().superFunction)),
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
@@ -418,11 +415,8 @@ bool ASTJsonConverter::visit(UserDefinedTypeName const& _node)
bool ASTJsonConverter::visit(FunctionTypeName const& _node)
{
setJsonNode(_node, "FunctionTypeName", {
- make_pair("payable", _node.isPayable()),
make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
- // FIXME: remove with next breaking release
- make_pair(m_legacy ? "constant" : "isDeclaredConst", _node.stateMutability() <= StateMutability::View),
make_pair("parameterTypes", toJson(*_node.parameterTypeList())),
make_pair("returnParameterTypes", toJson(*_node.returnParameterTypeList())),
make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
diff --git a/libsolidity/ast/ExperimentalFeatures.h b/libsolidity/ast/ExperimentalFeatures.h
index c66a3659..54aad573 100644
--- a/libsolidity/ast/ExperimentalFeatures.h
+++ b/libsolidity/ast/ExperimentalFeatures.h
@@ -31,7 +31,6 @@ enum class ExperimentalFeature
{
ABIEncoderV2, // new ABI encoder that makes use of Yul
SMTChecker,
- V050, // v0.5.0 breaking changes
Test,
TestOnlyAnalysis
};
@@ -40,14 +39,12 @@ static const std::map<ExperimentalFeature, bool> ExperimentalFeatureOnlyAnalysis
{
{ ExperimentalFeature::SMTChecker, true },
{ ExperimentalFeature::TestOnlyAnalysis, true },
- { ExperimentalFeature::V050, true }
};
static const std::map<std::string, ExperimentalFeature> ExperimentalFeatureNames =
{
{ "ABIEncoderV2", ExperimentalFeature::ABIEncoderV2 },
{ "SMTChecker", ExperimentalFeature::SMTChecker },
- { "v0.5.0", ExperimentalFeature::V050 },
{ "__test", ExperimentalFeature::Test },
{ "__testOnlyAnalysis", ExperimentalFeature::TestOnlyAnalysis },
};
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 992d8fb6..349a59d4 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -169,15 +169,6 @@ pair<u256, unsigned> const* StorageOffsets::offset(size_t _index) const
return nullptr;
}
-MemberList& MemberList::operator=(MemberList&& _other)
-{
- solAssert(&_other != this, "");
-
- m_memberTypes = move(_other.m_memberTypes);
- m_storageOffsets = move(_other.m_storageOffsets);
- return *this;
-}
-
void MemberList::combine(MemberList const & _other)
{
m_memberTypes += _other.m_memberTypes;
@@ -263,6 +254,17 @@ string Type::escapeIdentifier(string const& _identifier)
return ret;
}
+string Type::identifier() const
+{
+ string ret = escapeIdentifier(richIdentifier());
+ solAssert(ret.find_first_of("0123456789") != 0, "Identifier cannot start with a number.");
+ solAssert(
+ ret.find_first_not_of("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMONPQRSTUVWXYZ_$") == string::npos,
+ "Identifier contains invalid characters."
+ );
+ return ret;
+}
+
TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type)
{
solAssert(Token::isElementaryTypeName(_type.token()),
@@ -1146,7 +1148,14 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ
string RationalNumberType::richIdentifier() const
{
- return "t_rational_" + m_value.numerator().str() + "_by_" + m_value.denominator().str();
+ // rational seemingly will put the sign always on the numerator,
+ // but let just make it deterministic here.
+ bigint numerator = abs(m_value.numerator());
+ bigint denominator = abs(m_value.denominator());
+ if (m_value < 0)
+ return "t_rational_minus_" + numerator.str() + "_by_" + denominator.str();
+ else
+ return "t_rational_" + numerator.str() + "_by_" + denominator.str();
}
bool RationalNumberType::operator==(Type const& _other) const
@@ -1871,7 +1880,7 @@ MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const* _con
continue;
auto memberType = dynamic_cast<FunctionType const*>(member.type.get());
solAssert(!!memberType, "Override changes type.");
- if (!memberType->hasEqualArgumentTypes(*functionType))
+ if (!memberType->hasEqualParameterTypes(*functionType))
continue;
functionWithEqualArgumentsFound = true;
break;
@@ -2295,16 +2304,14 @@ TypePointer TupleType::closestTemporaryType(TypePointer const& _targetType) cons
{
solAssert(!!_targetType, "");
TypePointers const& targetComponents = dynamic_cast<TupleType const&>(*_targetType).components();
- bool fillRight = !targetComponents.empty() && (!targetComponents.back() || targetComponents.front());
+ solAssert(components().size() == targetComponents.size(), "");
TypePointers tempComponents(targetComponents.size());
- for (size_t i = 0; i < min(targetComponents.size(), components().size()); ++i)
+ for (size_t i = 0; i < targetComponents.size(); ++i)
{
- size_t si = fillRight ? i : components().size() - i - 1;
- size_t ti = fillRight ? i : targetComponents.size() - i - 1;
- if (components()[si] && targetComponents[ti])
+ if (components()[i] && targetComponents[i])
{
- tempComponents[ti] = components()[si]->closestTemporaryType(targetComponents[ti]);
- solAssert(tempComponents[ti], "");
+ tempComponents[i] = components()[i]->closestTemporaryType(targetComponents[i]);
+ solAssert(tempComponents[i], "");
}
}
return make_shared<TupleType>(tempComponents);
@@ -2825,7 +2832,7 @@ bool FunctionType::canTakeArguments(TypePointers const& _argumentTypes, TypePoin
);
}
-bool FunctionType::hasEqualArgumentTypes(FunctionType const& _other) const
+bool FunctionType::hasEqualParameterTypes(FunctionType const& _other) const
{
if (m_parameterTypes.size() != _other.m_parameterTypes.size())
return false;
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index 12029a4e..1fa2b2f5 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -95,9 +95,7 @@ public:
using MemberMap = std::vector<Member>;
- MemberList() {}
explicit MemberList(MemberMap const& _members): m_memberTypes(_members) {}
- MemberList& operator=(MemberList&& _other);
void combine(MemberList const& _other);
TypePointer memberType(std::string const& _name) const
{
@@ -132,6 +130,8 @@ private:
mutable std::unique_ptr<StorageOffsets> m_storageOffsets;
};
+static_assert(std::is_nothrow_move_constructible<MemberList>::value, "MemberList should be noexcept move constructible");
+
/**
* Abstract base class that forms the root of the type hierarchy.
*/
@@ -172,7 +172,7 @@ public:
/// only if they have the same identifier.
/// The identifier should start with "t_".
/// Will not contain any character which would be invalid as an identifier.
- std::string identifier() const { return escapeIdentifier(richIdentifier()); }
+ std::string identifier() const;
/// More complex identifier strings use "parentheses", where $_ is interpreted as as
/// "opening parenthesis", _$ as "closing parenthesis", _$_ as "comma" and any $ that
@@ -1035,7 +1035,7 @@ public:
/// expression the function is called on.
bool canTakeArguments(TypePointers const& _arguments, TypePointer const& _selfType = TypePointer()) const;
/// @returns true if the types of parameters are equal (doesn't check return parameter types)
- bool hasEqualArgumentTypes(FunctionType const& _other) const;
+ bool hasEqualParameterTypes(FunctionType const& _other) const;
/// @returns true if the ABI is used for this call (only meaningful for external calls)
bool isBareCall() const;
diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp
index 1ce77d67..dda77958 100644
--- a/libsolidity/codegen/ABIFunctions.cpp
+++ b/libsolidity/codegen/ABIFunctions.cpp
@@ -228,7 +228,8 @@ string ABIFunctions::cleanupFunction(Type const& _type, bool _revertOnFailure)
if (type.numBytes() == 32)
templ("body", "cleaned := value");
else if (type.numBytes() == 0)
- templ("body", "cleaned := 0");
+ // This is disallowed in the type system.
+ solAssert(false, "");
else
{
size_t numBits = type.numBytes() * 8;
diff --git a/libsolidity/codegen/Compiler.cpp b/libsolidity/codegen/Compiler.cpp
index d3afada5..55f1d252 100644
--- a/libsolidity/codegen/Compiler.cpp
+++ b/libsolidity/codegen/Compiler.cpp
@@ -46,19 +46,6 @@ void Compiler::compileContract(
m_context.optimise(m_optimize, m_optimizeRuns);
}
-void Compiler::compileClone(
- ContractDefinition const& _contract,
- map<ContractDefinition const*, eth::Assembly const*> const& _contracts
-)
-{
- solAssert(!_contract.isLibrary(), "");
- ContractCompiler runtimeCompiler(nullptr, m_runtimeContext, m_optimize);
- ContractCompiler cloneCompiler(&runtimeCompiler, m_context, m_optimize);
- m_runtimeSub = cloneCompiler.compileClone(_contract, _contracts);
-
- m_context.optimise(m_optimize, m_optimizeRuns);
-}
-
eth::AssemblyItem Compiler::functionEntryLabel(FunctionDefinition const& _function) const
{
return m_runtimeContext.functionEntryLabelIfExists(_function);
diff --git a/libsolidity/codegen/Compiler.h b/libsolidity/codegen/Compiler.h
index f6865d75..4028ae63 100644
--- a/libsolidity/codegen/Compiler.h
+++ b/libsolidity/codegen/Compiler.h
@@ -50,12 +50,6 @@ public:
std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts,
bytes const& _metadata
);
- /// Compiles a contract that uses DELEGATECALL to call into a pre-deployed version of the given
- /// contract at runtime, but contains the full creation-time code.
- void compileClone(
- ContractDefinition const& _contract,
- std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts
- );
/// @returns Entire assembly.
eth::Assembly const& assembly() const { return m_context.assembly(); }
/// @returns The entire assembled object (with constructor).
diff --git a/libsolidity/codegen/CompilerContext.cpp b/libsolidity/codegen/CompilerContext.cpp
index 3b1b4ec0..71b615b8 100644
--- a/libsolidity/codegen/CompilerContext.cpp
+++ b/libsolidity/codegen/CompilerContext.cpp
@@ -411,7 +411,7 @@ FunctionDefinition const& CompilerContext::resolveVirtualFunction(
if (
function->name() == name &&
!function->isConstructor() &&
- FunctionType(*function).hasEqualArgumentTypes(functionType)
+ FunctionType(*function).hasEqualParameterTypes(functionType)
)
return *function;
solAssert(false, "Super function " + name + " not found.");
diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp
index bd3ec8f5..b30851fb 100644
--- a/libsolidity/codegen/CompilerUtils.cpp
+++ b/libsolidity/codegen/CompilerUtils.cpp
@@ -947,20 +947,12 @@ void CompilerUtils::convertType(
{
TupleType const& sourceTuple = dynamic_cast<TupleType const&>(_typeOnStack);
TupleType const& targetTuple = dynamic_cast<TupleType const&>(_targetType);
- // fillRight: remove excess values at right side, !fillRight: remove eccess values at left side
- bool fillRight = !targetTuple.components().empty() && (
- !targetTuple.components().back() ||
- targetTuple.components().front()
- );
+ solAssert(targetTuple.components().size() == sourceTuple.components().size(), "");
unsigned depth = sourceTuple.sizeOnStack();
for (size_t i = 0; i < sourceTuple.components().size(); ++i)
{
TypePointer sourceType = sourceTuple.components()[i];
- TypePointer targetType;
- if (fillRight && i < targetTuple.components().size())
- targetType = targetTuple.components()[i];
- else if (!fillRight && targetTuple.components().size() + i >= sourceTuple.components().size())
- targetType = targetTuple.components()[targetTuple.components().size() - (sourceTuple.components().size() - i)];
+ TypePointer targetType = targetTuple.components()[i];
if (!sourceType)
{
solAssert(!targetType, "");
diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp
index 2fffcf76..02274d60 100644
--- a/libsolidity/codegen/ContractCompiler.cpp
+++ b/libsolidity/codegen/ContractCompiler.cpp
@@ -94,27 +94,6 @@ size_t ContractCompiler::compileConstructor(
}
}
-size_t ContractCompiler::compileClone(
- ContractDefinition const& _contract,
- map<ContractDefinition const*, eth::Assembly const*> const& _contracts
-)
-{
- initializeContext(_contract, _contracts);
-
- appendInitAndConstructorCode(_contract);
-
- //@todo determine largest return size of all runtime functions
- auto runtimeSub = m_context.addSubroutine(cloneRuntime());
-
- // stack contains sub size
- m_context << Instruction::DUP1 << runtimeSub << u256(0) << Instruction::CODECOPY;
- m_context << u256(0) << Instruction::RETURN;
-
- appendMissingFunctions();
-
- return size_t(runtimeSub.data());
-}
-
void ContractCompiler::initializeContext(
ContractDefinition const& _contract,
map<ContractDefinition const*, eth::Assembly const*> const& _compiledContracts
@@ -980,29 +959,6 @@ void ContractCompiler::compileExpression(Expression const& _expression, TypePoin
CompilerUtils(m_context).convertType(*_expression.annotation().type, *_targetType);
}
-eth::AssemblyPointer ContractCompiler::cloneRuntime() const
-{
- eth::Assembly a;
- a << Instruction::CALLDATASIZE;
- a << u256(0) << Instruction::DUP1 << Instruction::CALLDATACOPY;
- //@todo adjust for larger return values, make this dynamic.
- a << u256(0x20) << u256(0) << Instruction::CALLDATASIZE;
- a << u256(0);
- // this is the address which has to be substituted by the linker.
- //@todo implement as special "marker" AssemblyItem.
- a << u256("0xcafecafecafecafecafecafecafecafecafecafe");
- a << u256(eth::GasCosts::callGas(m_context.evmVersion()) + 10) << Instruction::GAS << Instruction::SUB;
- a << Instruction::DELEGATECALL;
- //Propagate error condition (if DELEGATECALL pushes 0 on stack).
- a << Instruction::ISZERO;
- a << Instruction::ISZERO;
- eth::AssemblyItem afterTag = a.appendJumpI().tag();
- a << Instruction::INVALID << afterTag;
- //@todo adjust for larger return values, make this dynamic.
- a << u256(0x20) << u256(0) << Instruction::RETURN;
- return make_shared<eth::Assembly>(a);
-}
-
void ContractCompiler::popScopedVariables(ASTNode const* _node)
{
unsigned blockHeight = m_scopeStackHeight.at(m_modifierDepth).at(_node);
diff --git a/libsolidity/codegen/ContractCompiler.h b/libsolidity/codegen/ContractCompiler.h
index 8516ec2c..5fa650b1 100644
--- a/libsolidity/codegen/ContractCompiler.h
+++ b/libsolidity/codegen/ContractCompiler.h
@@ -56,13 +56,6 @@ public:
ContractDefinition const& _contract,
std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts
);
- /// Compiles a contract that uses DELEGATECALL to call into a pre-deployed version of the given
- /// contract at runtime, but contains the full creation-time code.
- /// @returns the identifier of the runtime sub-assembly.
- size_t compileClone(
- ContractDefinition const& _contract,
- std::map<ContractDefinition const*, eth::Assembly const*> const& _contracts
- );
private:
/// Registers the non-function objects inside the contract with the context and stores the basic
@@ -122,9 +115,6 @@ private:
void appendStackVariableInitialisation(VariableDeclaration const& _variable);
void compileExpression(Expression const& _expression, TypePointer const& _targetType = TypePointer());
- /// @returns the runtime assembly for clone contracts.
- eth::AssemblyPointer cloneRuntime() const;
-
/// Frees the variables of a certain scope (to be used when leaving).
void popScopedVariables(ASTNode const* _node);
diff --git a/libsolidity/formal/SMTChecker.cpp b/libsolidity/formal/SMTChecker.cpp
index 17b50a38..88c1e56a 100644
--- a/libsolidity/formal/SMTChecker.cpp
+++ b/libsolidity/formal/SMTChecker.cpp
@@ -375,8 +375,14 @@ void SMTChecker::endVisit(Identifier const& _identifier)
}
else if (SSAVariable::isSupportedType(_identifier.annotation().type->category()))
{
- VariableDeclaration const& decl = dynamic_cast<VariableDeclaration const&>(*(_identifier.annotation().referencedDeclaration));
- defineExpr(_identifier, currentValue(decl));
+ if (VariableDeclaration const* decl = dynamic_cast<VariableDeclaration const*>(_identifier.annotation().referencedDeclaration))
+ defineExpr(_identifier, currentValue(*decl));
+ else
+ // TODO: handle MagicVariableDeclaration here
+ m_errorReporter.warning(
+ _identifier.location(),
+ "Assertion checker does not yet support the type of this variable."
+ );
}
else if (FunctionType const* fun = dynamic_cast<FunctionType const*>(_identifier.annotation().type.get()))
{
diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp
index 011ca4dc..9a0110cf 100644
--- a/libsolidity/inlineasm/AsmAnalysis.cpp
+++ b/libsolidity/inlineasm/AsmAnalysis.cpp
@@ -57,7 +57,7 @@ bool AsmAnalyzer::operator()(Label const& _label)
solAssert(!_label.name.empty(), "");
checkLooseFeature(
_label.location,
- "The use of labels is deprecated. Please use \"if\", \"switch\", \"for\" or function calls instead."
+ "The use of labels is disallowed. Please use \"if\", \"switch\", \"for\" or function calls instead."
);
m_info.stackHeightInfo[&_label] = m_stackHeight;
warnOnInstructions(solidity::Instruction::JUMPDEST, _label.location);
@@ -68,7 +68,7 @@ bool AsmAnalyzer::operator()(assembly::Instruction const& _instruction)
{
checkLooseFeature(
_instruction.location,
- "The use of non-functional instructions is deprecated. Please use functional notation instead."
+ "The use of non-functional instructions is disallowed. Please use functional notation instead."
);
auto const& info = instructionInfo(_instruction.instruction);
m_stackHeight += info.ret - info.args;
@@ -201,7 +201,7 @@ bool AsmAnalyzer::operator()(assembly::StackAssignment const& _assignment)
{
checkLooseFeature(
_assignment.location,
- "The use of stack assignment is deprecated. Please use assignment in functional notation instead."
+ "The use of stack assignment is disallowed. Please use assignment in functional notation instead."
);
bool success = checkAssignment(_assignment.variableName, size_t(-1));
m_info.stackHeightInfo[&_assignment] = m_stackHeight;
diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp
index a7a3fe7a..836e30d2 100644
--- a/libsolidity/interface/CompilerStack.cpp
+++ b/libsolidity/interface/CompilerStack.cpp
@@ -329,7 +329,6 @@ void CompilerStack::link()
{
contract.second.object.link(m_libraries);
contract.second.runtimeObject.link(m_libraries);
- contract.second.cloneObject.link(m_libraries);
}
}
@@ -408,11 +407,6 @@ eth::LinkerObject const& CompilerStack::runtimeObject(string const& _contractNam
return contract(_contractName).runtimeObject;
}
-eth::LinkerObject const& CompilerStack::cloneObject(string const& _contractName) const
-{
- return contract(_contractName).cloneObject;
-}
-
/// FIXME: cache this string
string CompilerStack::assemblyString(string const& _contractName, StringMap _sourceCodes) const
{
@@ -583,7 +577,7 @@ StringMap CompilerStack::loadMissingSources(SourceUnit const& _ast, std::string
for (auto const& node: _ast.nodes())
if (ImportDirective const* import = dynamic_cast<ImportDirective*>(node.get()))
{
- string importPath = absolutePath(import->path(), _sourcePath);
+ string importPath = dev::absolutePath(import->path(), _sourcePath);
// The current value of `path` is the absolute path as seen from this source file.
// We first have to apply remappings before we can store the actual absolute path
// as seen globally.
@@ -626,8 +620,8 @@ string CompilerStack::applyRemapping(string const& _path, string const& _context
for (auto const& redir: m_remappings)
{
- string context = sanitizePath(redir.context);
- string prefix = sanitizePath(redir.prefix);
+ string context = dev::sanitizePath(redir.context);
+ string prefix = dev::sanitizePath(redir.prefix);
// Skip if current context is closer
if (context.length() < longestContext)
@@ -644,7 +638,7 @@ string CompilerStack::applyRemapping(string const& _path, string const& _context
longestContext = context.length();
longestPrefix = prefix.length();
- bestMatchTarget = sanitizePath(redir.target);
+ bestMatchTarget = dev::sanitizePath(redir.target);
}
string path = bestMatchTarget;
path.append(_path.begin() + longestPrefix, _path.end());
@@ -681,23 +675,6 @@ void CompilerStack::resolveImports()
swap(m_sourceOrder, sourceOrder);
}
-string CompilerStack::absolutePath(string const& _path, string const& _reference)
-{
- using path = boost::filesystem::path;
- path p(_path);
- // Anything that does not start with `.` is an absolute path.
- if (p.begin() == p.end() || (*p.begin() != "." && *p.begin() != ".."))
- return _path;
- path result(_reference);
- result.remove_filename();
- for (path::iterator it = p.begin(); it != p.end(); ++it)
- if (*it == "..")
- result = result.parent_path();
- else if (*it != ".")
- result /= *it;
- return result.generic_string();
-}
-
namespace
{
bool onlySafeExperimentalFeaturesActivated(set<ExperimentalFeature> const& features)
@@ -767,23 +744,6 @@ void CompilerStack::compileContract(
}
_compiledContracts[compiledContract.contract] = &compiler->assembly();
-
- try
- {
- if (!_contract.isLibrary())
- {
- Compiler cloneCompiler(m_evmVersion, m_optimize, m_optimizeRuns);
- cloneCompiler.compileClone(_contract, _compiledContracts);
- compiledContract.cloneObject = cloneCompiler.assembledObject();
- }
- }
- catch (eth::AssemblyException const&)
- {
- // In some cases (if the constructor requests a runtime function), it is not
- // possible to compile the clone.
-
- // TODO: Report error / warning
- }
}
string const CompilerStack::lastContractName() const
diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h
index 7b144660..2234a8c9 100644
--- a/libsolidity/interface/CompilerStack.h
+++ b/libsolidity/interface/CompilerStack.h
@@ -36,7 +36,6 @@
#include <json/json.h>
#include <boost/noncopyable.hpp>
-#include <boost/filesystem.hpp>
#include <ostream>
#include <string>
@@ -190,12 +189,6 @@ public:
/// @returns the runtime object for the contract.
eth::LinkerObject const& runtimeObject(std::string const& _contractName) const;
- /// @returns the bytecode of a contract that uses an already deployed contract via DELEGATECALL.
- /// The returned bytes will contain a sequence of 20 bytes of the format "XXX...XXX" which have to
- /// substituted by the actual address. Note that this sequence starts end ends in three X
- /// characters but can contain anything in between.
- eth::LinkerObject const& cloneObject(std::string const& _contractName) const;
-
/// @returns normal contract assembly items
eth::AssemblyItems const* assemblyItems(std::string const& _contractName) const;
@@ -258,7 +251,6 @@ private:
std::shared_ptr<Compiler> compiler;
eth::LinkerObject object; ///< Deployment object (includes the runtime sub-object).
eth::LinkerObject runtimeObject; ///< Runtime object.
- eth::LinkerObject cloneObject; ///< Clone object (deprecated).
std::string metadata; ///< The metadata json that will be hashed into the chain.
mutable std::unique_ptr<Json::Value const> abi;
mutable std::unique_ptr<Json::Value const> userDocumentation;
@@ -274,12 +266,6 @@ private:
std::string applyRemapping(std::string const& _path, std::string const& _context);
void resolveImports();
- /// @returns the absolute path corresponding to @a _path relative to @a _reference.
- static std::string absolutePath(std::string const& _path, std::string const& _reference);
-
- /// Helper function to return path converted strings.
- static std::string sanitizePath(std::string const& _path) { return boost::filesystem::path(_path).generic_string(); }
-
/// @returns true if the contract is requested to be compiled.
bool isRequestedContract(ContractDefinition const& _contract) const;
diff --git a/libsolidity/interface/StandardCompiler.cpp b/libsolidity/interface/StandardCompiler.cpp
index 8339780f..58b84163 100644
--- a/libsolidity/interface/StandardCompiler.cpp
+++ b/libsolidity/interface/StandardCompiler.cpp
@@ -567,7 +567,7 @@ Json::Value StandardCompiler::compileInternal(Json::Value const& _input)
return output;
}
-Json::Value StandardCompiler::compile(Json::Value const& _input)
+Json::Value StandardCompiler::compile(Json::Value const& _input) noexcept
{
try
{
@@ -591,7 +591,7 @@ Json::Value StandardCompiler::compile(Json::Value const& _input)
}
}
-string StandardCompiler::compile(string const& _input)
+string StandardCompiler::compile(string const& _input) noexcept
{
Json::Value input;
string errors;
diff --git a/libsolidity/interface/StandardCompiler.h b/libsolidity/interface/StandardCompiler.h
index 2772394a..fc9c3a59 100644
--- a/libsolidity/interface/StandardCompiler.h
+++ b/libsolidity/interface/StandardCompiler.h
@@ -47,10 +47,10 @@ public:
/// Sets all input parameters according to @a _input which conforms to the standardized input
/// format, performs compilation and returns a standardized output.
- Json::Value compile(Json::Value const& _input);
+ Json::Value compile(Json::Value const& _input) noexcept;
/// Parses input as JSON and peforms the above processing steps, returning a serialized JSON
/// output. Parsing errors are returned as regular errors.
- std::string compile(std::string const& _input);
+ std::string compile(std::string const& _input) noexcept;
private:
Json::Value compileInternal(Json::Value const& _input);