aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/analysis
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/analysis')
-rw-r--r--libsolidity/analysis/ConstantEvaluator.cpp10
-rw-r--r--libsolidity/analysis/ConstantEvaluator.h8
-rw-r--r--libsolidity/analysis/NameAndTypeResolver.cpp6
-rw-r--r--libsolidity/analysis/ReferencesResolver.cpp25
-rw-r--r--libsolidity/analysis/SyntaxChecker.cpp9
-rw-r--r--libsolidity/analysis/TypeChecker.cpp59
-rw-r--r--libsolidity/analysis/TypeChecker.h4
7 files changed, 92 insertions, 29 deletions
diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp
index 7057eab7..6636ad97 100644
--- a/libsolidity/analysis/ConstantEvaluator.cpp
+++ b/libsolidity/analysis/ConstantEvaluator.cpp
@@ -22,17 +22,17 @@
#include <libsolidity/analysis/ConstantEvaluator.h>
#include <libsolidity/ast/AST.h>
+#include <libsolidity/interface/ErrorReporter.h>
using namespace std;
using namespace dev;
using namespace dev::solidity;
-
void ConstantEvaluator::endVisit(UnaryOperation const& _operation)
{
TypePointer const& subType = _operation.subExpression().annotation().type;
if (!dynamic_cast<RationalNumberType const*>(subType.get()))
- BOOST_THROW_EXCEPTION(_operation.subExpression().createTypeError("Invalid constant expression."));
+ m_errorReporter.fatalTypeError(_operation.subExpression().location(), "Invalid constant expression.");
TypePointer t = subType->unaryOperatorResult(_operation.getOperator());
_operation.annotation().type = t;
}
@@ -42,9 +42,9 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation)
TypePointer const& leftType = _operation.leftExpression().annotation().type;
TypePointer const& rightType = _operation.rightExpression().annotation().type;
if (!dynamic_cast<RationalNumberType const*>(leftType.get()))
- BOOST_THROW_EXCEPTION(_operation.leftExpression().createTypeError("Invalid constant expression."));
+ m_errorReporter.fatalTypeError(_operation.leftExpression().location(), "Invalid constant expression.");
if (!dynamic_cast<RationalNumberType const*>(rightType.get()))
- BOOST_THROW_EXCEPTION(_operation.rightExpression().createTypeError("Invalid constant expression."));
+ m_errorReporter.fatalTypeError(_operation.rightExpression().location(), "Invalid constant expression.");
TypePointer commonType = leftType->binaryOperatorResult(_operation.getOperator(), rightType);
if (Token::isCompareOp(_operation.getOperator()))
commonType = make_shared<BoolType>();
@@ -55,5 +55,5 @@ void ConstantEvaluator::endVisit(Literal const& _literal)
{
_literal.annotation().type = Type::forLiteral(_literal);
if (!_literal.annotation().type)
- BOOST_THROW_EXCEPTION(_literal.createTypeError("Invalid literal value."));
+ m_errorReporter.fatalTypeError(_literal.location(), "Invalid literal value.");
}
diff --git a/libsolidity/analysis/ConstantEvaluator.h b/libsolidity/analysis/ConstantEvaluator.h
index 9ec04ebe..90bceb5d 100644
--- a/libsolidity/analysis/ConstantEvaluator.h
+++ b/libsolidity/analysis/ConstantEvaluator.h
@@ -29,6 +29,7 @@ namespace dev
namespace solidity
{
+class ErrorReporter;
class TypeChecker;
/**
@@ -37,13 +38,18 @@ class TypeChecker;
class ConstantEvaluator: private ASTConstVisitor
{
public:
- ConstantEvaluator(Expression const& _expr) { _expr.accept(*this); }
+ ConstantEvaluator(Expression const& _expr, ErrorReporter& _errorReporter):
+ m_errorReporter(_errorReporter)
+ {
+ _expr.accept(*this);
+ }
private:
virtual void endVisit(BinaryOperation const& _operation);
virtual void endVisit(UnaryOperation const& _operation);
virtual void endVisit(Literal const& _literal);
+ ErrorReporter& m_errorReporter;
};
}
diff --git a/libsolidity/analysis/NameAndTypeResolver.cpp b/libsolidity/analysis/NameAndTypeResolver.cpp
index 523e7176..5d010693 100644
--- a/libsolidity/analysis/NameAndTypeResolver.cpp
+++ b/libsolidity/analysis/NameAndTypeResolver.cpp
@@ -647,10 +647,12 @@ void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaratio
bool warnAboutShadowing = true;
// Do not warn about shadowing for structs and enums because their members are
- // not accessible without prefixes.
+ // not accessible without prefixes. Also do not warn about event parameters
+ // because they don't participate in any proper scope.
if (
dynamic_cast<StructDefinition const*>(m_currentScope) ||
- dynamic_cast<EnumDefinition const*>(m_currentScope)
+ dynamic_cast<EnumDefinition const*>(m_currentScope) ||
+ dynamic_cast<EventDefinition const*>(m_currentScope)
)
warnAboutShadowing = false;
// Do not warn about the constructor shadowing the contract.
diff --git a/libsolidity/analysis/ReferencesResolver.cpp b/libsolidity/analysis/ReferencesResolver.cpp
index 8f07d43a..f22c95cc 100644
--- a/libsolidity/analysis/ReferencesResolver.cpp
+++ b/libsolidity/analysis/ReferencesResolver.cpp
@@ -147,10 +147,12 @@ void ReferencesResolver::endVisit(ArrayTypeName const& _typeName)
if (Expression const* length = _typeName.length())
{
if (!length->annotation().type)
- ConstantEvaluator e(*length);
+ ConstantEvaluator e(*length, m_errorReporter);
auto const* lengthType = dynamic_cast<RationalNumberType const*>(length->annotation().type.get());
- if (!lengthType || lengthType->isFractional())
+ if (!lengthType || !lengthType->mobileType())
fatalTypeError(length->location(), "Invalid array length, expected integer literal.");
+ else if (lengthType->isFractional())
+ fatalTypeError(length->location(), "Array with fractional length specified.");
else if (lengthType->isNegative())
fatalTypeError(length->location(), "Array with negative length specified.");
else
@@ -296,11 +298,19 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable)
{
typeLoc = DataLocation::Storage;
if (_variable.isLocalVariable())
- m_errorReporter.warning(
- _variable.location(),
- "Variable is declared as a storage pointer. "
- "Use an explicit \"storage\" keyword to silence this warning."
- );
+ {
+ if (_variable.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050))
+ typeError(
+ _variable.location(),
+ "Storage location must be specified as either \"memory\" or \"storage\"."
+ );
+ else
+ m_errorReporter.warning(
+ _variable.location(),
+ "Variable is declared as a storage pointer. "
+ "Use an explicit \"storage\" keyword to silence this warning."
+ );
+ }
}
}
else
@@ -347,4 +357,3 @@ void ReferencesResolver::fatalDeclarationError(SourceLocation const& _location,
m_errorOccurred = true;
m_errorReporter.fatalDeclarationError(_location, _description);
}
-
diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp
index 187eb26f..0ca4b86c 100644
--- a/libsolidity/analysis/SyntaxChecker.cpp
+++ b/libsolidity/analysis/SyntaxChecker.cpp
@@ -182,8 +182,15 @@ bool SyntaxChecker::visit(Throw const& _throwStatement)
bool SyntaxChecker::visit(UnaryOperation const& _operation)
{
+ bool const v050 = m_sourceUnit->annotation().experimentalFeatures.count(ExperimentalFeature::V050);
+
if (_operation.getOperator() == Token::Add)
- m_errorReporter.warning(_operation.location(), "Use of unary + is deprecated.");
+ {
+ if (v050)
+ m_errorReporter.syntaxError(_operation.location(), "Use of unary + is deprecated.");
+ else
+ m_errorReporter.warning(_operation.location(), "Use of unary + is deprecated.");
+ }
return true;
}
diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp
index 43930125..c2fba565 100644
--- a/libsolidity/analysis/TypeChecker.cpp
+++ b/libsolidity/analysis/TypeChecker.cpp
@@ -75,6 +75,7 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
ASTNode::listAccept(_contract.baseContracts(), *this);
checkContractDuplicateFunctions(_contract);
+ checkContractDuplicateEvents(_contract);
checkContractIllegalOverrides(_contract);
checkContractAbstractFunctions(_contract);
checkContractAbstractConstructors(_contract);
@@ -183,9 +184,27 @@ void TypeChecker::checkContractDuplicateFunctions(ContractDefinition const& _con
msg
);
}
- for (auto const& it: functions)
+
+ findDuplicateDefinitions(functions, "Function with same name and arguments defined twice.");
+}
+
+void TypeChecker::checkContractDuplicateEvents(ContractDefinition const& _contract)
+{
+ /// Checks that two events with the same name defined in this contract have different
+ /// argument types
+ map<string, vector<EventDefinition const*>> events;
+ for (EventDefinition const* event: _contract.events())
+ events[event->name()].push_back(event);
+
+ findDuplicateDefinitions(events, "Event with same name and arguments defined twice.");
+}
+
+template <class T>
+void TypeChecker::findDuplicateDefinitions(map<string, vector<T>> const& _definitions, string _message)
+{
+ for (auto const& it: _definitions)
{
- vector<FunctionDefinition const*> const& overloads = it.second;
+ vector<T> const& overloads = it.second;
set<size_t> reported;
for (size_t i = 0; i < overloads.size() && !reported.count(i); ++i)
{
@@ -200,18 +219,17 @@ void TypeChecker::checkContractDuplicateFunctions(ContractDefinition const& _con
if (ssl.infos.size() > 0)
{
- string msg = "Function with same name and arguments defined twice.";
size_t occurrences = ssl.infos.size();
if (occurrences > 32)
{
ssl.infos.resize(32);
- msg += " Truncated from " + boost::lexical_cast<string>(occurrences) + " to the first 32 occurrences.";
+ _message += " Truncated from " + boost::lexical_cast<string>(occurrences) + " to the first 32 occurrences.";
}
m_errorReporter.declarationError(
overloads[i]->location(),
ssl,
- msg
+ _message
);
}
}
@@ -577,8 +595,16 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
{
if (_function.isImplemented())
m_errorReporter.typeError(_function.location(), "Functions in interfaces cannot have an implementation.");
- if (_function.visibility() < FunctionDefinition::Visibility::Public)
- m_errorReporter.typeError(_function.location(), "Functions in interfaces cannot be internal or private.");
+ if (_function.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050))
+ {
+ if (_function.visibility() != FunctionDefinition::Visibility::External)
+ m_errorReporter.typeError(_function.location(), "Functions in interfaces must be declared external.");
+ }
+ else
+ {
+ if (_function.visibility() < FunctionDefinition::Visibility::Public)
+ m_errorReporter.typeError(_function.location(), "Functions in interfaces cannot be internal or private.");
+ }
if (_function.isConstructor())
m_errorReporter.typeError(_function.location(), "Constructor cannot be defined in interfaces.");
}
@@ -627,14 +653,23 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
if (!allowed)
m_errorReporter.typeError(_variable.location(), "Constants of non-value type not yet implemented.");
}
+
if (!_variable.value())
m_errorReporter.typeError(_variable.location(), "Uninitialized \"constant\" variable.");
else if (!_variable.value()->annotation().isPure)
- m_errorReporter.warning(
- _variable.value()->location(),
- "Initial value for constant variable has to be compile-time constant. "
- "This will fail to compile with the next breaking version change."
- );
+ {
+ if (_variable.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::V050))
+ m_errorReporter.typeError(
+ _variable.value()->location(),
+ "Initial value for constant variable has to be compile-time constant."
+ );
+ else
+ m_errorReporter.warning(
+ _variable.value()->location(),
+ "Initial value for constant variable has to be compile-time constant. "
+ "This will fail to compile with the next breaking version change."
+ );
+ }
}
if (!_variable.isStateVariable())
{
diff --git a/libsolidity/analysis/TypeChecker.h b/libsolidity/analysis/TypeChecker.h
index 0c6f54d3..abe6dac1 100644
--- a/libsolidity/analysis/TypeChecker.h
+++ b/libsolidity/analysis/TypeChecker.h
@@ -61,6 +61,7 @@ private:
/// Checks that two functions defined in this contract with the same name have different
/// arguments and that there is at most one constructor.
void checkContractDuplicateFunctions(ContractDefinition const& _contract);
+ void checkContractDuplicateEvents(ContractDefinition const& _contract);
void checkContractIllegalOverrides(ContractDefinition const& _contract);
/// Reports a type error with an appropiate message if overriden function signature differs.
/// Also stores the direct super function in the AST annotations.
@@ -108,6 +109,9 @@ private:
virtual void endVisit(ElementaryTypeNameExpression const& _expr) override;
virtual void endVisit(Literal const& _literal) override;
+ template <class T>
+ void findDuplicateDefinitions(std::map<std::string, std::vector<T>> const& _definitions, std::string _message);
+
bool contractDependenciesAreCyclic(
ContractDefinition const& _contract,
std::set<ContractDefinition const*> const& _seenContracts = std::set<ContractDefinition const*>()