aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian <c@ethdev.com>2015-02-14 08:22:44 +0800
committerChristian <c@ethdev.com>2015-02-17 02:25:24 +0800
commitf7ba85e0ecb6f690d62bcf66e0f0525f2ed97337 (patch)
treebbd2b50913748f78b311b6cbea27bb6ba5ec9c9e
parent3e29ec2cb2075fc6734a0f350503c393fbeeb3d6 (diff)
downloaddexon-solidity-f7ba85e0ecb6f690d62bcf66e0f0525f2ed97337.tar
dexon-solidity-f7ba85e0ecb6f690d62bcf66e0f0525f2ed97337.tar.gz
dexon-solidity-f7ba85e0ecb6f690d62bcf66e0f0525f2ed97337.tar.bz2
dexon-solidity-f7ba85e0ecb6f690d62bcf66e0f0525f2ed97337.tar.lz
dexon-solidity-f7ba85e0ecb6f690d62bcf66e0f0525f2ed97337.tar.xz
dexon-solidity-f7ba85e0ecb6f690d62bcf66e0f0525f2ed97337.tar.zst
dexon-solidity-f7ba85e0ecb6f690d62bcf66e0f0525f2ed97337.zip
No write access to parameters of external functions.
-rw-r--r--AST.cpp28
-rw-r--r--AST.h16
-rw-r--r--ASTJsonConverter.cpp17
-rw-r--r--Compiler.cpp23
4 files changed, 50 insertions, 34 deletions
diff --git a/AST.cpp b/AST.cpp
index 0dbad433..0fafd2d1 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -288,12 +288,23 @@ string FunctionDefinition::getCanonicalSignature() const
return FunctionType(*this).getCanonicalSignature(getName());
}
-Declaration::LValueType VariableDeclaration::getLValueType() const
+bool VariableDeclaration::isLValue() const
{
- if (dynamic_cast<FunctionDefinition const*>(getScope()) || dynamic_cast<ModifierDefinition const*>(getScope()))
- return Declaration::LValueType::Local;
- else
- return Declaration::LValueType::Storage;
+ if (auto const* function = dynamic_cast<FunctionDefinition const*>(getScope()))
+ if (function->getVisibility() == Declaration::Visibility::External && isFunctionParameter())
+ return false;
+ return true;
+}
+
+bool VariableDeclaration::isFunctionParameter() const
+{
+ auto const* function = dynamic_cast<FunctionDefinition const*>(getScope());
+ if (!function)
+ return false;
+ for (auto const& variable: function->getParameters())
+ if (variable.get() == this)
+ return true;
+ return false;
}
TypePointer ModifierDefinition::getType(ContractDefinition const*) const
@@ -586,8 +597,7 @@ void MemberAccess::checkTypeRequirements()
if (!m_type)
BOOST_THROW_EXCEPTION(createTypeError("Member \"" + *m_memberName + "\" not found or not "
"visible in " + type.toString()));
- //@todo later, this will not always be STORAGE
- m_lvalue = type.getCategory() == Type::Category::Struct ? Declaration::LValueType::Storage : Declaration::LValueType::None;
+ m_isLValue = (type.getCategory() == Type::Category::Struct);
}
void IndexAccess::checkTypeRequirements()
@@ -599,14 +609,14 @@ void IndexAccess::checkTypeRequirements()
MappingType const& type = dynamic_cast<MappingType const&>(*m_base->getType());
m_index->expectType(*type.getKeyType());
m_type = type.getValueType();
- m_lvalue = Declaration::LValueType::Storage;
+ m_isLValue = true;
}
void Identifier::checkTypeRequirements()
{
solAssert(m_referencedDeclaration, "Identifier not resolved.");
- m_lvalue = m_referencedDeclaration->getLValueType();
+ m_isLValue = m_referencedDeclaration->isLValue();
m_type = m_referencedDeclaration->getType(m_currentContract);
if (!m_type)
BOOST_THROW_EXCEPTION(createTypeError("Declaration referenced before type could be determined."));
diff --git a/AST.h b/AST.h
index c40e24d1..af45934f 100644
--- a/AST.h
+++ b/AST.h
@@ -132,7 +132,6 @@ private:
class Declaration: public ASTNode
{
public:
- enum class LValueType { None, Local, Storage };
/// Visibility ordered from restricted to unrestricted.
enum class Visibility { Default, Private, Protected, Public, External };
@@ -156,8 +155,7 @@ public:
/// The current contract has to be given since this context can change the type, especially of
/// contract types.
virtual TypePointer getType(ContractDefinition const* m_currentContract = nullptr) const = 0;
- /// @returns the lvalue type of expressions referencing this declaration
- virtual LValueType getLValueType() const { return LValueType::None; }
+ virtual bool isLValue() const { return false; }
protected:
virtual Visibility getDefaultVisibility() const { return Visibility::Public; }
@@ -448,8 +446,9 @@ public:
TypePointer getType(ContractDefinition const* = nullptr) const { return m_type; }
void setType(std::shared_ptr<Type const> const& _type) { m_type = _type; }
- virtual LValueType getLValueType() const override;
+ virtual bool isLValue() const override;
bool isLocalVariable() const { return !!dynamic_cast<FunctionDefinition const*>(getScope()); }
+ bool isFunctionParameter() const;
bool isStateVariable() const { return m_isStateVariable; }
bool isIndexed() const { return m_isIndexed; }
@@ -887,8 +886,7 @@ public:
virtual void checkTypeRequirements() = 0;
std::shared_ptr<Type const> const& getType() const { return m_type; }
- bool isLValue() const { return m_lvalue != Declaration::LValueType::None; }
- bool isLocalLValue() const { return m_lvalue == Declaration::LValueType::Local; }
+ bool isLValue() const { return m_isLValue; }
/// Helper function, infer the type via @ref checkTypeRequirements and then check that it
/// is implicitly convertible to @a _expectedType. If not, throw exception.
@@ -903,9 +901,9 @@ public:
protected:
//! Inferred type of the expression, only filled after a call to checkTypeRequirements().
std::shared_ptr<Type const> m_type;
- //! If this expression is an lvalue (i.e. something that can be assigned to) and is stored
- //! locally or in storage. This is set during calls to @a checkTypeRequirements()
- Declaration::LValueType m_lvalue = Declaration::LValueType::None;
+ //! If this expression is an lvalue (i.e. something that can be assigned to).
+ //! This is set during calls to @a checkTypeRequirements()
+ bool m_isLValue = false;
//! Whether the outer expression requested the address (true) or the value (false) of this expression.
bool m_lvalueRequested = false;
};
diff --git a/ASTJsonConverter.cpp b/ASTJsonConverter.cpp
index a216a59a..04feafe2 100644
--- a/ASTJsonConverter.cpp
+++ b/ASTJsonConverter.cpp
@@ -118,11 +118,7 @@ bool ASTJsonConverter::visit(FunctionDefinition const& _node)
bool ASTJsonConverter::visit(VariableDeclaration const& _node)
{
- bool isLocalVariable = (_node.getLValueType() == VariableDeclaration::LValueType::Local);
- addJsonNode("VariableDeclaration",
- { make_pair("name", _node.getName()),
- make_pair("local", boost::lexical_cast<std::string>(isLocalVariable))},
- true);
+ addJsonNode("VariableDeclaration", { make_pair("name", _node.getName()) }, true);
return true;
}
@@ -216,11 +212,12 @@ bool ASTJsonConverter::visit(ExpressionStatement const&)
bool ASTJsonConverter::visit(Expression const& _node)
{
- addJsonNode("Expression",
- { make_pair("type", getType(_node)),
- make_pair("lvalue", boost::lexical_cast<std::string>(_node.isLValue())),
- make_pair("local_lvalue", boost::lexical_cast<std::string>(_node.isLocalLValue())) },
- true);
+ addJsonNode(
+ "Expression",
+ { make_pair("type", getType(_node)),
+ make_pair("lvalue", boost::lexical_cast<std::string>(_node.isLValue())) },
+ true
+ );
return true;
}
diff --git a/Compiler.cpp b/Compiler.cpp
index dad79bb0..4dbcbbfe 100644
--- a/Compiler.cpp
+++ b/Compiler.cpp
@@ -255,12 +255,22 @@ bool Compiler::visit(FunctionDefinition const& _function)
// stack upon entry: [return address] [arg0] [arg1] ... [argn]
// reserve additional slots: [retarg0] ... [retargm] [localvar0] ... [localvarp]
- unsigned parametersSize = CompilerUtils::getSizeOnStack(_function.getParameters());
- m_context.adjustStackOffset(parametersSize);
- for (ASTPointer<VariableDeclaration const> const& variable: _function.getParameters())
+ if (_function.getVisibility() != Declaration::Visibility::External)
{
- m_context.addVariable(*variable, parametersSize);
- parametersSize -= variable->getType()->getSizeOnStack();
+ unsigned parametersSize = CompilerUtils::getSizeOnStack(_function.getParameters());
+ m_context.adjustStackOffset(parametersSize);
+ for (ASTPointer<VariableDeclaration const> const& variable: _function.getParameters())
+ {
+ m_context.addVariable(*variable, parametersSize);
+ parametersSize -= variable->getType()->getSizeOnStack();
+ }
+ }
+ else
+ {
+ unsigned calldataPos = CompilerUtils::dataStartOffset;
+ // calldatapos is _always_ dynamic.
+ for (ASTPointer<VariableDeclaration const> const& variable: _function.getParameters())
+ m_context.addCalldataVariable(*variable, calldataPos);
}
for (ASTPointer<VariableDeclaration const> const& variable: _function.getReturnParameters())
m_context.addAndInitializeVariable(*variable);
@@ -277,7 +287,8 @@ bool Compiler::visit(FunctionDefinition const& _function)
// Note that the fact that the return arguments are of increasing index is vital for this
// algorithm to work.
- unsigned const c_argumentsSize = CompilerUtils::getSizeOnStack(_function.getParameters());
+ unsigned const c_argumentsSize = (_function.getVisibility() == Declaration::Visibility::External
+ ? 0 : CompilerUtils::getSizeOnStack(_function.getParameters()));
unsigned const c_returnValuesSize = CompilerUtils::getSizeOnStack(_function.getReturnParameters());
unsigned const c_localVariablesSize = CompilerUtils::getSizeOnStack(_function.getLocalVariables());