aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity')
-rw-r--r--libsolidity/analysis/SyntaxChecker.cpp7
-rw-r--r--libsolidity/interface/GasEstimator.cpp9
-rw-r--r--libsolidity/parsing/Parser.cpp19
3 files changed, 30 insertions, 5 deletions
diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp
index 343b4ba8..f648e5b4 100644
--- a/libsolidity/analysis/SyntaxChecker.cpp
+++ b/libsolidity/analysis/SyntaxChecker.cpp
@@ -232,6 +232,13 @@ bool SyntaxChecker::visit(FunctionDefinition const& _function)
"Use \"constructor(...) { ... }\" instead."
);
}
+ if (!_function.isImplemented() && !_function.modifiers().empty())
+ {
+ if (v050)
+ m_errorReporter.syntaxError(_function.location(), "Functions without implementation cannot have modifiers.");
+ else
+ m_errorReporter.warning( _function.location(), "Modifiers of functions without implementation are ignored." );
+ }
return true;
}
diff --git a/libsolidity/interface/GasEstimator.cpp b/libsolidity/interface/GasEstimator.cpp
index 2139395f..a496cc21 100644
--- a/libsolidity/interface/GasEstimator.cpp
+++ b/libsolidity/interface/GasEstimator.cpp
@@ -136,12 +136,19 @@ GasEstimator::GasConsumption GasEstimator::functionalEstimation(
ExpressionClasses& classes = state->expressionClasses();
using Id = ExpressionClasses::Id;
using Ids = vector<Id>;
+ // div(calldataload(0), 1 << 224) equals to hashValue
Id hashValue = classes.find(u256(FixedHash<4>::Arith(FixedHash<4>(dev::keccak256(_signature)))));
Id calldata = classes.find(Instruction::CALLDATALOAD, Ids{classes.find(u256(0))});
classes.forceEqual(hashValue, Instruction::DIV, Ids{
calldata,
- classes.find(u256(1) << (8 * 28))
+ classes.find(u256(1) << 224)
});
+ // lt(calldatasize(), 4) equals to 0 (ignore the shortcut for fallback functions)
+ classes.forceEqual(
+ classes.find(u256(0)),
+ Instruction::LT,
+ Ids{classes.find(Instruction::CALLDATASIZE), classes.find(u256(4))}
+ );
}
PathGasMeter meter(_items, m_evmVersion);
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index 18ef740a..2d8ca7d3 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -365,12 +365,13 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(
Token::Value token = m_scanner->currentToken();
if (_allowModifiers && token == Token::Identifier)
{
- // This can either be a modifier (function declaration) or the name of the
- // variable (function type name plus variable).
- if (
+ // If the name is empty (and this is not a constructor),
+ // then this can either be a modifier (fallback function declaration)
+ // or the name of the state variable (function type name plus variable).
+ if ((result.name->empty() && !result.isConstructor) && (
m_scanner->peekNextToken() == Token::Semicolon ||
m_scanner->peekNextToken() == Token::Assign
- )
+ ))
// Variable declaration, break here.
break;
else
@@ -380,6 +381,14 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(
{
if (result.visibility != Declaration::Visibility::Default)
{
+ // There is the special case of a public state variable of function type.
+ // Detect this and return early.
+ if (
+ (result.visibility == Declaration::Visibility::External || result.visibility == Declaration::Visibility::Internal) &&
+ result.modifiers.empty() &&
+ (result.name->empty() && !result.isConstructor)
+ )
+ break;
parserError(string(
"Visibility already specified as \"" +
Declaration::visibilityToString(result.visibility) +
@@ -429,6 +438,7 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinitionOrFunctionTypeStateVariable(A
FunctionHeaderParserResult header = parseFunctionHeader(false, true, _contractName);
if (
+ header.isConstructor ||
!header.modifiers.empty() ||
!header.name->empty() ||
m_scanner->currentToken() == Token::Semicolon ||
@@ -794,6 +804,7 @@ ASTPointer<FunctionTypeName> Parser::parseFunctionType()
RecursionGuard recursionGuard(*this);
ASTNodeFactory nodeFactory(*this);
FunctionHeaderParserResult header = parseFunctionHeader(true, false);
+ solAssert(!header.isConstructor, "Tried to parse type as constructor.");
return nodeFactory.createNode<FunctionTypeName>(
header.parameters,
header.returnParameters,