aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AST.cpp6
-rw-r--r--AST.h27
-rw-r--r--Compiler.cpp5
-rw-r--r--ExpressionCompiler.cpp7
-rw-r--r--Parser.cpp11
-rw-r--r--Parser.h1
-rw-r--r--Types.h2
7 files changed, 42 insertions, 17 deletions
diff --git a/AST.cpp b/AST.cpp
index 46c44995..b0560263 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -197,7 +197,7 @@ vector<pair<FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::getIn
}
for (ASTPointer<VariableDeclaration> const& v: contract->getStateVariables())
- if (v->isPublic() && functionsSeen.count(v->getName()) == 0)
+ if (v->isPublic() && functionsSeen.count(v->getName()) == 0 && !v->isConstant())
{
FunctionType ftype(*v);
functionsSeen.insert(v->getName());
@@ -322,8 +322,8 @@ string FunctionDefinition::getCanonicalSignature() const
bool VariableDeclaration::isLValue() const
{
- // External function parameters are Read-Only
- return !isExternalFunctionParameter();
+ // External function parameters and constant declared variables are Read-Only
+ return !isExternalFunctionParameter() && !m_isConstant;
}
void VariableDeclaration::checkTypeRequirements()
diff --git a/AST.h b/AST.h
index eab53153..e959ba24 100644
--- a/AST.h
+++ b/AST.h
@@ -440,13 +440,22 @@ private:
class VariableDeclaration: public Declaration
{
public:
- VariableDeclaration(SourceLocation const& _location, ASTPointer<TypeName> const& _type,
- ASTPointer<ASTString> const& _name, ASTPointer<Expression> _value,
- Visibility _visibility,
- bool _isStateVar = false, bool _isIndexed = false):
- Declaration(_location, _name, _visibility),
- m_typeName(_type), m_value(_value),
- m_isStateVariable(_isStateVar), m_isIndexed(_isIndexed) {}
+ VariableDeclaration(
+ SourceLocation const& _location,
+ ASTPointer<TypeName> const& _type,
+ ASTPointer<ASTString> const& _name,
+ ASTPointer<Expression> _value,
+ Visibility _visibility,
+ bool _isStateVar = false,
+ bool _isIndexed = false,
+ bool _isConstant = false):
+ Declaration(_location, _name, _visibility),
+ m_typeName(_type),
+ m_value(_value),
+ m_isStateVariable(_isStateVar),
+ m_isIndexed(_isIndexed),
+ m_isConstant(_isConstant){}
+
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
@@ -465,15 +474,17 @@ public:
bool isExternalFunctionParameter() const;
bool isStateVariable() const { return m_isStateVariable; }
bool isIndexed() const { return m_isIndexed; }
+ bool isConstant() const { return m_isConstant; }
protected:
Visibility getDefaultVisibility() const override { return Visibility::Internal; }
private:
ASTPointer<TypeName> m_typeName; ///< can be empty ("var")
- ASTPointer<Expression> m_value; ///< the assigned value, can be missing
+ ASTPointer<Expression> m_value; ///< the assigned value, can be missing
bool m_isStateVariable; ///< Whether or not this is a contract state variable
bool m_isIndexed; ///< Whether this is an indexed variable (used by events).
+ bool m_isConstant; ///< Whether the variable is a compile-time constant.
std::shared_ptr<Type const> m_type; ///< derived type, initially empty
};
diff --git a/Compiler.cpp b/Compiler.cpp
index b8ca03d3..0f4e89de 100644
--- a/Compiler.cpp
+++ b/Compiler.cpp
@@ -276,13 +276,14 @@ void Compiler::registerStateVariables(ContractDefinition const& _contract)
{
for (ContractDefinition const* contract: boost::adaptors::reverse(_contract.getLinearizedBaseContracts()))
for (ASTPointer<VariableDeclaration> const& variable: contract->getStateVariables())
- m_context.addStateVariable(*variable);
+ if (!variable->isConstant())
+ m_context.addStateVariable(*variable);
}
void Compiler::initializeStateVariables(ContractDefinition const& _contract)
{
for (ASTPointer<VariableDeclaration> const& variable: _contract.getStateVariables())
- if (variable->getValue())
+ if (variable->getValue() && !variable->isConstant())
ExpressionCompiler(m_context, m_optimize).appendStateVariableInitialization(*variable);
}
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp
index 331979c7..ce5f184b 100644
--- a/ExpressionCompiler.cpp
+++ b/ExpressionCompiler.cpp
@@ -855,8 +855,11 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
}
else if (FunctionDefinition const* functionDef = dynamic_cast<FunctionDefinition const*>(declaration))
m_context << m_context.getVirtualFunctionEntryLabel(*functionDef).pushTag();
- else if (dynamic_cast<VariableDeclaration const*>(declaration))
- setLValueFromDeclaration(*declaration, _identifier);
+ else if (auto variable = dynamic_cast<VariableDeclaration const*>(declaration))
+ {
+ if (!variable->isConstant())
+ setLValueFromDeclaration(*declaration, _identifier);
+ }
else if (dynamic_cast<ContractDefinition const*>(declaration))
{
// no-op
diff --git a/Parser.cpp b/Parser.cpp
index 44d11159..05c05f63 100644
--- a/Parser.cpp
+++ b/Parser.cpp
@@ -135,6 +135,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
}
while (m_scanner->getCurrentToken() == Token::Comma);
expectToken(Token::LBrace);
+ bool isDeclaredConst = false;
while (true)
{
Token::Value currentToken = m_scanner->getCurrentToken();
@@ -152,13 +153,21 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition()
VarDeclParserOptions options;
options.isStateVariable = true;
options.allowInitialValue = true;
+ options.isDeclaredConst = isDeclaredConst;
stateVariables.push_back(parseVariableDeclaration(options));
+ isDeclaredConst = false;
expectToken(Token::Semicolon);
}
else if (currentToken == Token::Modifier)
modifiers.push_back(parseModifierDefinition());
else if (currentToken == Token::Event)
events.push_back(parseEventDefinition());
+ else if (currentToken == Token::Const)
+ {
+ solAssert(Token::isElementaryTypeName(m_scanner->peekNextToken()), "");
+ isDeclaredConst = true;
+ m_scanner->next();
+ }
else
BOOST_THROW_EXCEPTION(createParserError("Function, variable, struct or modifier declaration expected."));
}
@@ -348,7 +357,7 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
}
return nodeFactory.createNode<VariableDeclaration>(type, identifier, value,
visibility, _options.isStateVariable,
- isIndexed);
+ isIndexed, _options.isDeclaredConst);
}
ASTPointer<ModifierDefinition> Parser::parseModifierDefinition()
diff --git a/Parser.h b/Parser.h
index cc0b2ca1..469e446f 100644
--- a/Parser.h
+++ b/Parser.h
@@ -54,6 +54,7 @@ private:
bool allowIndexed = false;
bool allowEmptyName = false;
bool allowInitialValue = false;
+ bool isDeclaredConst = false;
};
///@{
diff --git a/Types.h b/Types.h
index fd59a37a..853bd688 100644
--- a/Types.h
+++ b/Types.h
@@ -516,7 +516,7 @@ private:
std::vector<std::string> m_parameterNames;
std::vector<std::string> m_returnParameterNames;
Location const m_location;
- /// true iff the function takes an arbitrary number of arguments of arbitrary types
+ /// true if the function takes an arbitrary number of arguments of arbitrary types
bool const m_arbitraryParameters = false;
bool const m_gasSet = false; ///< true iff the gas value to be used is on the stack
bool const m_valueSet = false; ///< true iff the value to be sent is on the stack