aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/analysis
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/analysis')
-rw-r--r--libsolidity/analysis/PostTypeChecker.cpp36
-rw-r--r--libsolidity/analysis/PostTypeChecker.h5
-rw-r--r--libsolidity/analysis/TypeChecker.cpp62
3 files changed, 61 insertions, 42 deletions
diff --git a/libsolidity/analysis/PostTypeChecker.cpp b/libsolidity/analysis/PostTypeChecker.cpp
index fbc72e52..19d0b708 100644
--- a/libsolidity/analysis/PostTypeChecker.cpp
+++ b/libsolidity/analysis/PostTypeChecker.cpp
@@ -21,6 +21,8 @@
#include <libsolidity/interface/ErrorReporter.h>
#include <libsolidity/interface/Version.h>
+#include <libdevcore/Algorithms.h>
+
#include <boost/range/adaptor/map.hpp>
#include <memory>
@@ -47,7 +49,7 @@ void PostTypeChecker::endVisit(ContractDefinition const&)
{
solAssert(!m_currentConstVariable, "");
for (auto declaration: m_constVariables)
- if (auto identifier = findCycle(declaration))
+ if (auto identifier = findCycle(*declaration))
m_errorReporter.typeError(
declaration->location(),
"The value of the constant " + declaration->name() +
@@ -87,20 +89,24 @@ bool PostTypeChecker::visit(Identifier const& _identifier)
return true;
}
-VariableDeclaration const* PostTypeChecker::findCycle(
- VariableDeclaration const* _startingFrom,
- set<VariableDeclaration const*> const& _seen
-)
+VariableDeclaration const* PostTypeChecker::findCycle(VariableDeclaration const& _startingFrom)
{
- if (_seen.count(_startingFrom))
- return _startingFrom;
- else if (m_constVariableDependencies.count(_startingFrom))
+ auto visitor = [&](VariableDeclaration const& _variable, CycleDetector<VariableDeclaration>& _cycleDetector)
{
- set<VariableDeclaration const*> seen(_seen);
- seen.insert(_startingFrom);
- for (auto v: m_constVariableDependencies[_startingFrom])
- if (findCycle(v, seen))
- return v;
- }
- return nullptr;
+ // Iterating through the dependencies needs to be deterministic and thus cannot
+ // depend on the memory layout.
+ // Because of that, we sort by AST node id.
+ vector<VariableDeclaration const*> dependencies(
+ m_constVariableDependencies[&_variable].begin(),
+ m_constVariableDependencies[&_variable].end()
+ );
+ sort(dependencies.begin(), dependencies.end(), [](VariableDeclaration const* _a, VariableDeclaration const* _b) -> bool
+ {
+ return _a->id() < _b->id();
+ });
+ for (auto v: dependencies)
+ if (_cycleDetector.run(*v))
+ return;
+ };
+ return CycleDetector<VariableDeclaration>(visitor).run(_startingFrom);
}
diff --git a/libsolidity/analysis/PostTypeChecker.h b/libsolidity/analysis/PostTypeChecker.h
index bafc1ae6..4f9dac6e 100644
--- a/libsolidity/analysis/PostTypeChecker.h
+++ b/libsolidity/analysis/PostTypeChecker.h
@@ -55,10 +55,7 @@ private:
virtual bool visit(Identifier const& _identifier) override;
- VariableDeclaration const* findCycle(
- VariableDeclaration const* _startingFrom,
- std::set<VariableDeclaration const*> const& _seen = std::set<VariableDeclaration const*>{}
- );
+ VariableDeclaration const* findCycle(VariableDeclaration const& _startingFrom);
ErrorReporter& m_errorReporter;
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 620dfca4..a252742d 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -320,7 +320,7 @@ void TypeChecker::checkContractAbstractConstructors(ContractDefinition const& _c
{
auto baseContract = dynamic_cast<ContractDefinition const*>(&dereference(base->name()));
solAssert(baseContract, "");
- if (!base->arguments().empty())
+ if (base->arguments() && !base->arguments()->empty())
argumentsNeeded.erase(baseContract);
}
}
@@ -506,30 +506,46 @@ void TypeChecker::endVisit(InheritanceSpecifier const& _inheritance)
// Interfaces do not have constructors, so there are zero parameters.
parameterTypes = ContractType(*base).newExpressionType()->parameterTypes();
- if (!arguments.empty() && parameterTypes.size() != arguments.size())
+ if (arguments)
{
- m_errorReporter.typeError(
- _inheritance.location(),
- "Wrong argument count for constructor call: " +
- toString(arguments.size()) +
- " arguments given but expected " +
- toString(parameterTypes.size()) +
- "."
- );
- return;
- }
+ bool v050 = m_scope->sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050);
- for (size_t i = 0; i < arguments.size(); ++i)
- if (!type(*arguments[i])->isImplicitlyConvertibleTo(*parameterTypes[i]))
- m_errorReporter.typeError(
- arguments[i]->location(),
- "Invalid type for argument in constructor call. "
- "Invalid implicit conversion from " +
- type(*arguments[i])->toString() +
- " to " +
- parameterTypes[i]->toString() +
- " requested."
- );
+ if (parameterTypes.size() != arguments->size())
+ {
+ if (arguments->size() == 0 && !v050)
+ m_errorReporter.warning(
+ _inheritance.location(),
+ "Wrong argument count for constructor call: " +
+ toString(arguments->size()) +
+ " arguments given but expected " +
+ toString(parameterTypes.size()) +
+ "."
+ );
+ else
+ {
+ m_errorReporter.typeError(
+ _inheritance.location(),
+ "Wrong argument count for constructor call: " +
+ toString(arguments->size()) +
+ " arguments given but expected " +
+ toString(parameterTypes.size()) +
+ "."
+ );
+ return;
+ }
+ }
+ for (size_t i = 0; i < arguments->size(); ++i)
+ if (!type(*(*arguments)[i])->isImplicitlyConvertibleTo(*parameterTypes[i]))
+ m_errorReporter.typeError(
+ (*arguments)[i]->location(),
+ "Invalid type for argument in constructor call. "
+ "Invalid implicit conversion from " +
+ type(*(*arguments)[i])->toString() +
+ " to " +
+ parameterTypes[i]->toString() +
+ " requested."
+ );
+ }
}
void TypeChecker::endVisit(UsingForDirective const& _usingFor)