diff options
-rw-r--r-- | AST.cpp | 6 | ||||
-rw-r--r-- | AST.h | 27 | ||||
-rw-r--r-- | Compiler.cpp | 5 | ||||
-rw-r--r-- | ExpressionCompiler.cpp | 7 | ||||
-rw-r--r-- | Parser.cpp | 11 | ||||
-rw-r--r-- | Parser.h | 1 | ||||
-rw-r--r-- | Types.h | 2 |
7 files changed, 42 insertions, 17 deletions
@@ -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() @@ -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 @@ -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() @@ -54,6 +54,7 @@ private: bool allowIndexed = false; bool allowEmptyName = false; bool allowInitialValue = false; + bool isDeclaredConst = false; }; ///@{ @@ -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 |