aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md2
-rw-r--r--docs/solidity-by-example.rst12
-rw-r--r--libsolidity/analysis/ConstantEvaluator.cpp23
-rw-r--r--libsolidity/formal/SMTLib2Interface.cpp9
-rw-r--r--libsolidity/formal/SMTLib2Interface.h8
-rw-r--r--libsolidity/interface/SourceReferenceFormatter.cpp15
-rw-r--r--test/RPCSession.cpp19
-rw-r--r--test/RPCSession.h1
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp6
9 files changed, 75 insertions, 20 deletions
diff --git a/Changelog.md b/Changelog.md
index 68b9973f..45521f3e 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -2,6 +2,7 @@
Features:
* Syntax Checker: Turn the usage of ``callcode`` into an error as experimental 0.5.0 feature.
+ * Type Checker: More detailed errors for invalid array lengths (such as division by zero).
Bugfixes:
@@ -18,6 +19,7 @@ Features:
* Type Checker: Do not add members of ``address`` to contracts as experimental 0.5.0 feature.
* Type Checker: Force interface functions to be external as experimental 0.5.0 feature.
* Type Checker: Require ``storage`` or ``memory`` keyword for local variables as experimental 0.5.0 feature.
+ * Compiler Interface: Better formatted error message for long source snippets
Bugfixes:
* Code Generator: Allocate one byte per memory byte array element instead of 32.
diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst
index 139c8a42..59ab7962 100644
--- a/docs/solidity-by-example.rst
+++ b/docs/solidity-by-example.rst
@@ -221,8 +221,7 @@ activate themselves.
// absolute unix timestamps (seconds since 1970-01-01)
// or time periods in seconds.
address public beneficiary;
- uint public auctionStart;
- uint public biddingTime;
+ uint public auctionEnd;
// Current state of the auction.
address public highestBidder;
@@ -251,8 +250,7 @@ activate themselves.
address _beneficiary
) {
beneficiary = _beneficiary;
- auctionStart = now;
- biddingTime = _biddingTime;
+ auctionEnd = now + _biddingTime;
}
/// Bid on the auction with the value sent
@@ -268,7 +266,7 @@ activate themselves.
// Revert the call if the bidding
// period is over.
- require(now <= (auctionStart + biddingTime));
+ require(now <= auctionEnd);
// If the bid is not higher, send the
// money back.
@@ -322,7 +320,7 @@ activate themselves.
// external contracts.
// 1. Conditions
- require(now >= (auctionStart + biddingTime)); // auction did not yet end
+ require(now >= auctionEnd); // auction did not yet end
require(!ended); // this function has already been called
// 2. Effects
@@ -382,7 +380,6 @@ high or low invalid bids.
}
address public beneficiary;
- uint public auctionStart;
uint public biddingEnd;
uint public revealEnd;
bool public ended;
@@ -410,7 +407,6 @@ high or low invalid bids.
address _beneficiary
) {
beneficiary = _beneficiary;
- auctionStart = now;
biddingEnd = now + _biddingTime;
revealEnd = biddingEnd + _revealTime;
}
diff --git a/libsolidity/analysis/ConstantEvaluator.cpp b/libsolidity/analysis/ConstantEvaluator.cpp
index 6636ad97..bc3b7cf1 100644
--- a/libsolidity/analysis/ConstantEvaluator.cpp
+++ b/libsolidity/analysis/ConstantEvaluator.cpp
@@ -28,6 +28,7 @@ using namespace std;
using namespace dev;
using namespace dev::solidity;
+/// FIXME: this is pretty much a copy of TypeChecker::endVisit(BinaryOperation)
void ConstantEvaluator::endVisit(UnaryOperation const& _operation)
{
TypePointer const& subType = _operation.subExpression().annotation().type;
@@ -37,6 +38,7 @@ void ConstantEvaluator::endVisit(UnaryOperation const& _operation)
_operation.annotation().type = t;
}
+/// FIXME: this is pretty much a copy of TypeChecker::endVisit(BinaryOperation)
void ConstantEvaluator::endVisit(BinaryOperation const& _operation)
{
TypePointer const& leftType = _operation.leftExpression().annotation().type;
@@ -46,9 +48,24 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation)
if (!dynamic_cast<RationalNumberType const*>(rightType.get()))
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>();
- _operation.annotation().type = commonType;
+ if (!commonType)
+ {
+ m_errorReporter.typeError(
+ _operation.location(),
+ "Operator " +
+ string(Token::toString(_operation.getOperator())) +
+ " not compatible with types " +
+ leftType->toString() +
+ " and " +
+ rightType->toString()
+ );
+ commonType = leftType;
+ }
+ _operation.annotation().commonType = commonType;
+ _operation.annotation().type =
+ Token::isCompareOp(_operation.getOperator()) ?
+ make_shared<BoolType>() :
+ commonType;
}
void ConstantEvaluator::endVisit(Literal const& _literal)
diff --git a/libsolidity/formal/SMTLib2Interface.cpp b/libsolidity/formal/SMTLib2Interface.cpp
index cbd766fb..c627057a 100644
--- a/libsolidity/formal/SMTLib2Interface.cpp
+++ b/libsolidity/formal/SMTLib2Interface.cpp
@@ -64,6 +64,8 @@ void SMTLib2Interface::pop()
Expression SMTLib2Interface::newFunction(string _name, Sort _domain, Sort _codomain)
{
+ solAssert(!m_variables.count(_name), "");
+ m_variables[_name] = SMTVariableType::Function;
write(
"(declare-fun |" +
_name +
@@ -78,12 +80,16 @@ Expression SMTLib2Interface::newFunction(string _name, Sort _domain, Sort _codom
Expression SMTLib2Interface::newInteger(string _name)
{
+ solAssert(!m_variables.count(_name), "");
+ m_variables[_name] = SMTVariableType::Integer;
write("(declare-const |" + _name + "| Int)");
return SolverInterface::newInteger(move(_name));
}
Expression SMTLib2Interface::newBool(string _name)
{
+ solAssert(!m_variables.count(_name), "");
+ m_variables[_name] = SMTVariableType::Bool;
write("(declare-const |" + _name + "| Bool)");
return SolverInterface::newBool(std::move(_name));
}
@@ -145,7 +151,8 @@ string SMTLib2Interface::checkSatAndGetValuesCommand(vector<Expression> const& _
for (size_t i = 0; i < _expressionsToEvaluate.size(); i++)
{
auto const& e = _expressionsToEvaluate.at(i);
- // TODO they don't have to be ints...
+ solAssert(m_variables.count(e.name), "");
+ solAssert(m_variables[e.name] == SMTVariableType::Integer, "");
command += "(declare-const |EVALEXPR_" + to_string(i) + "| Int)\n";
command += "(assert (= |EVALEXPR_" + to_string(i) + "| " + toSExpr(e) + "))\n";
}
diff --git a/libsolidity/formal/SMTLib2Interface.h b/libsolidity/formal/SMTLib2Interface.h
index 63188acd..e827449f 100644
--- a/libsolidity/formal/SMTLib2Interface.h
+++ b/libsolidity/formal/SMTLib2Interface.h
@@ -68,6 +68,14 @@ private:
ReadCallback::Callback m_queryCallback;
std::vector<std::string> m_accumulatedOutput;
+
+ enum class SMTVariableType {
+ Function,
+ Integer,
+ Bool
+ };
+
+ std::map<std::string,SMTVariableType> m_variables;
};
}
diff --git a/libsolidity/interface/SourceReferenceFormatter.cpp b/libsolidity/interface/SourceReferenceFormatter.cpp
index 62d22999..aeafaf2d 100644
--- a/libsolidity/interface/SourceReferenceFormatter.cpp
+++ b/libsolidity/interface/SourceReferenceFormatter.cpp
@@ -49,6 +49,21 @@ void SourceReferenceFormatter::printSourceLocation(
if (startLine == endLine)
{
string line = scanner.lineAtPosition(_location->start);
+
+ int locationLength = endColumn - startColumn;
+ if (locationLength > 150)
+ {
+ line = line.substr(0, startColumn + 35) + " ... " + line.substr(endColumn - 35);
+ endColumn = startColumn + 75;
+ locationLength = 75;
+ }
+ if (line.length() > 150)
+ {
+ line = " ... " + line.substr(startColumn, locationLength) + " ... ";
+ startColumn = 5;
+ endColumn = startColumn + locationLength;
+ }
+
_stream << line << endl;
for_each(
line.cbegin(),
diff --git a/test/RPCSession.cpp b/test/RPCSession.cpp
index 634954a3..c06c3997 100644
--- a/test/RPCSession.cpp
+++ b/test/RPCSession.cpp
@@ -339,22 +339,25 @@ Json::Value RPCSession::rpcCall(string const& _methodName, vector<string> const&
return result["result"];
}
+string const& RPCSession::accountCreate()
+{
+ m_accounts.push_back(personal_newAccount(""));
+ personal_unlockAccount(m_accounts.back(), "", 100000);
+ return m_accounts.back();
+}
+
string const& RPCSession::accountCreateIfNotExists(size_t _id)
{
- if (_id >= m_accounts.size())
- {
- m_accounts.push_back(personal_newAccount(""));
- personal_unlockAccount(m_accounts.back(), "", 100000);
- }
+ while ((_id + 1) > m_accounts.size())
+ accountCreate();
return m_accounts[_id];
}
RPCSession::RPCSession(const string& _path):
m_ipcSocket(_path)
{
- string account = personal_newAccount("");
- personal_unlockAccount(account, "", 100000);
- m_accounts.push_back(account);
+ accountCreate();
+ // This will pre-fund the accounts create prior.
test_setChainParams(m_accounts);
}
diff --git a/test/RPCSession.h b/test/RPCSession.h
index eae6a09c..63f1dd21 100644
--- a/test/RPCSession.h
+++ b/test/RPCSession.h
@@ -121,6 +121,7 @@ public:
Json::Value rpcCall(std::string const& _methodName, std::vector<std::string> const& _args = std::vector<std::string>(), bool _canFail = false);
std::string const& account(size_t _id) const { return m_accounts.at(_id); }
+ std::string const& accountCreate();
std::string const& accountCreateIfNotExists(size_t _id);
private:
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index 9b5ea349..e5990e9b 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -7247,6 +7247,12 @@ BOOST_AUTO_TEST_CASE(array_length_invalid_expression)
}
)";
CHECK_ERROR(text, TypeError, "Invalid literal value.");
+ text = R"(
+ contract C {
+ uint[3/0] ids;
+ }
+ )";
+ CHECK_ERROR(text, TypeError, "Operator / not compatible with types int_const 3 and int_const 0");
}
BOOST_AUTO_TEST_CASE(no_address_members_on_contract)