Browse Source

Merge branch 'develop' into jsonrpc

cl-refactor
Marek Kotewicz 10 years ago
parent
commit
037364afa5
  1. 2
      alethzero/Transact.cpp
  2. 6
      libsolidity/AST.h
  3. 1
      libsolidity/CompilerContext.h
  4. 25
      libsolidity/ExpressionCompiler.cpp
  5. 2
      libsolidity/ExpressionCompiler.h
  6. 4
      libsolidity/Parser.cpp
  7. 4
      libsolidity/Token.h
  8. 32
      libsolidity/Types.cpp
  9. 8
      libsolidity/Types.h
  10. 4
      libsolidity/grammar.txt
  11. 2
      libweb3jsonrpc/WebThreeStubServerBase.cpp
  12. 2
      secp256k1/CMakeLists.txt
  13. 36
      test/SolidityEndToEndTest.cpp
  14. 12
      test/SolidityNameAndTypeResolution.cpp
  15. 6
      test/SolidityParser.cpp

2
alethzero/Transact.cpp

@ -169,9 +169,7 @@ void Transact::rejigData()
QString lll;
QString solidity;
if (src.find_first_not_of("1234567890abcdefABCDEF") == string::npos && src.size() % 2 == 0)
{
m_data = fromHex(src);
}
else if (sourceIsSolidity(src))
{
dev::solidity::CompilerStack compiler;

6
libsolidity/AST.h

@ -133,7 +133,7 @@ class Declaration: public ASTNode
{
public:
/// Visibility ordered from restricted to unrestricted.
enum class Visibility { Default, Private, Protected, Public, External };
enum class Visibility { Default, Private, Inheritable, Public, External };
Declaration(Location const& _location, ASTPointer<ASTString> const& _name,
Visibility _visibility = Visibility::Default):
@ -144,7 +144,7 @@ public:
Visibility getVisibility() const { return m_visibility == Visibility::Default ? getDefaultVisibility() : m_visibility; }
bool isPublic() const { return getVisibility() >= Visibility::Public; }
bool isVisibleInContract() const { return getVisibility() != Visibility::External; }
bool isVisibleInDerivedContracts() const { return isVisibleInContract() && getVisibility() >= Visibility::Protected; }
bool isVisibleInDerivedContracts() const { return isVisibleInContract() && getVisibility() >= Visibility::Inheritable; }
/// @returns the scope this declaration resides in. Can be nullptr if it is the global scope.
/// Available only after name and type resolution step.
@ -453,7 +453,7 @@ public:
bool isIndexed() const { return m_isIndexed; }
protected:
Visibility getDefaultVisibility() const override { return Visibility::Protected; }
Visibility getDefaultVisibility() const override { return Visibility::Inheritable; }
private:
ASTPointer<TypeName> m_typeName; ///< can be empty ("var")

1
libsolidity/CompilerContext.h

@ -48,6 +48,7 @@ public:
bytes const& getCompiledContract(ContractDefinition const& _contract) const;
void adjustStackOffset(int _adjustment) { m_asm.adjustDeposit(_adjustment); }
unsigned getStackHeight() { solAssert(m_asm.deposit() >= 0, ""); return unsigned(m_asm.deposit()); }
bool isMagicGlobal(Declaration const* _declaration) const { return m_magicGlobals.count(_declaration) != 0; }
bool isLocalVariable(Declaration const* _declaration) const;

25
libsolidity/ExpressionCompiler.cpp

@ -1119,9 +1119,13 @@ void ExpressionCompiler::LValue::storeValue(Type const& _sourceType, Location co
{
solAssert(_sourceType.getCategory() == m_dataType->getCategory(), "");
if (m_dataType->getCategory() == Type::Category::ByteArray)
{
CompilerUtils(*m_context).copyByteArrayToStorage(
dynamic_cast<ByteArrayType const&>(*m_dataType),
dynamic_cast<ByteArrayType const&>(_sourceType));
if (_move)
*m_context << eth::Instruction::POP;
}
else if (m_dataType->getCategory() == Type::Category::Struct)
{
// stack layout: source_ref target_ref
@ -1136,12 +1140,14 @@ void ExpressionCompiler::LValue::storeValue(Type const& _sourceType, Location co
*m_context << structType.getStorageOffsetOfMember(member.first)
<< eth::Instruction::DUP3 << eth::Instruction::DUP2
<< eth::Instruction::ADD;
// stack: source_ref target_ref member_offset source_member_ref
LValue rightHandSide(*m_context, LValueType::Storage, memberType);
rightHandSide.retrieveValue(_location, true);
// stack: source_ref target_ref offset source_value...
// stack: source_ref target_ref member_offset source_value...
*m_context << eth::dupInstruction(2 + memberType->getSizeOnStack())
<< eth::dupInstruction(2 + memberType->getSizeOnStack())
<< eth::Instruction::ADD;
// stack: source_ref target_ref member_offset source_value... target_member_ref
LValue memberLValue(*m_context, LValueType::Storage, memberType);
memberLValue.storeValue(*memberType, _location, true);
*m_context << eth::Instruction::POP;
@ -1189,6 +1195,23 @@ void ExpressionCompiler::LValue::setToZero(Location const& _location) const
case LValueType::Storage:
if (m_dataType->getCategory() == Type::Category::ByteArray)
CompilerUtils(*m_context).clearByteArray(dynamic_cast<ByteArrayType const&>(*m_dataType));
else if (m_dataType->getCategory() == Type::Category::Struct)
{
// stack layout: ref
auto const& structType = dynamic_cast<StructType const&>(*m_dataType);
for (auto const& member: structType.getMembers())
{
// zero each member that is not a mapping
TypePointer const& memberType = member.second;
if (memberType->getCategory() == Type::Category::Mapping)
continue;
*m_context << structType.getStorageOffsetOfMember(member.first)
<< eth::Instruction::DUP2 << eth::Instruction::ADD;
LValue memberValue(*m_context, LValueType::Storage, memberType);
memberValue.setToZero();
}
*m_context << eth::Instruction::POP;
}
else
{
if (m_size == 0)

2
libsolidity/ExpressionCompiler.h

@ -144,7 +144,7 @@ private:
void retrieveValue(Location const& _location, bool _remove = false) const;
/// Moves a value from the stack to the lvalue. Removes the value if @a _move is true.
/// @a _location is the source location of the expression that caused this operation.
/// Stack pre: [lvalue_ref] value
/// Stack pre: value [lvalue_ref]
/// Stack post if !_move: value_of(lvalue_ref)
void storeValue(Type const& _sourceType, Location const& _location = Location(), bool _move = false) const;
/// Stores zero in the lvalue.

4
libsolidity/Parser.cpp

@ -186,8 +186,8 @@ Declaration::Visibility Parser::parseVisibilitySpecifier(Token::Value _token)
Declaration::Visibility visibility(Declaration::Visibility::Default);
if (_token == Token::Public)
visibility = Declaration::Visibility::Public;
else if (_token == Token::Protected)
visibility = Declaration::Visibility::Protected;
else if (_token == Token::Inheritable)
visibility = Declaration::Visibility::Inheritable;
else if (_token == Token::Private)
visibility = Declaration::Visibility::Private;
else if (_token == Token::External)

4
libsolidity/Token.h

@ -162,7 +162,7 @@ namespace solidity
K(New, "new", 0) \
K(Public, "public", 0) \
K(Private, "private", 0) \
K(Protected, "protected", 0) \
K(Inheritable, "inheritable", 0) \
K(Return, "return", 0) \
K(Returns, "returns", 0) \
K(Struct, "struct", 0) \
@ -380,7 +380,7 @@ public:
static bool isCountOp(Value op) { return op == Inc || op == Dec; }
static bool isShiftOp(Value op) { return (SHL <= op) && (op <= SHR); }
static bool isVisibilitySpecifier(Value op) { return isVariableVisibilitySpecifier(op) || op == External; }
static bool isVariableVisibilitySpecifier(Value op) { return op == Public || op == Private || op == Protected; }
static bool isVariableVisibilitySpecifier(Value op) { return op == Public || op == Private || op == Inheritable; }
static bool isEtherSubdenomination(Value op) { return op == SubWei || op == SubSzabo || op == SubFinney || op == Token::SubEther; }
// Returns a string corresponding to the JS token string

32
libsolidity/Types.cpp

@ -573,19 +573,19 @@ MemberList const& ContractType::getMembers() const
if (!m_members)
{
// All address members and all interface functions
map<string, TypePointer> members(IntegerType::AddressMemberList.begin(),
IntegerType::AddressMemberList.end());
vector<pair<string, TypePointer>> members(IntegerType::AddressMemberList.begin(),
IntegerType::AddressMemberList.end());
if (m_super)
{
for (ContractDefinition const* base: m_contract.getLinearizedBaseContracts())
for (ASTPointer<FunctionDefinition> const& function: base->getDefinedFunctions())
if (!function->isConstructor() && !function->getName().empty() &&
if (!function->isConstructor() && !function->getName().empty()&&
function->isVisibleInDerivedContracts())
members.insert(make_pair(function->getName(), make_shared<FunctionType>(*function, true)));
members.push_back(make_pair(function->getName(), make_shared<FunctionType>(*function, true)));
}
else
for (auto const& it: m_contract.getInterfaceFunctions())
members[it.second->getDeclaration().getName()] = it.second;
members.push_back(make_pair(it.second->getDeclaration().getName(), it.second));
m_members.reset(new MemberList(members));
}
return *m_members;
@ -653,9 +653,9 @@ MemberList const& StructType::getMembers() const
// We need to lazy-initialize it because of recursive references.
if (!m_members)
{
map<string, TypePointer> members;
vector<pair<string, TypePointer>> members;
for (ASTPointer<VariableDeclaration> const& variable: m_struct.getMembers())
members[variable->getName()] = variable->getType();
members.push_back(make_pair(variable->getName(), variable->getType()));
m_members.reset(new MemberList(members));
}
return *m_members;
@ -857,15 +857,15 @@ MemberList const& FunctionType::getMembers() const
case Location::Bare:
if (!m_members)
{
map<string, TypePointer> members{
{"gas", make_shared<FunctionType>(parseElementaryTypeVector({"uint"}),
TypePointers{copyAndSetGasOrValue(true, false)},
Location::SetGas, false, m_gasSet, m_valueSet)},
vector<pair<string, TypePointer>> members{
{"value", make_shared<FunctionType>(parseElementaryTypeVector({"uint"}),
TypePointers{copyAndSetGasOrValue(false, true)},
Location::SetValue, false, m_gasSet, m_valueSet)}};
if (m_location == Location::Creation)
members.erase("gas");
if (m_location != Location::Creation)
members.push_back(make_pair("gas", make_shared<FunctionType>(
parseElementaryTypeVector({"uint"}),
TypePointers{copyAndSetGasOrValue(true, false)},
Location::SetGas, false, m_gasSet, m_valueSet)));
m_members.reset(new MemberList(members));
}
return *m_members;
@ -959,7 +959,7 @@ MemberList const& TypeType::getMembers() const
// We need to lazy-initialize it because of recursive references.
if (!m_members)
{
map<string, TypePointer> members;
vector<pair<string, TypePointer>> members;
if (m_actualType->getCategory() == Category::Contract && m_currentContract != nullptr)
{
ContractDefinition const& contract = dynamic_cast<ContractType const&>(*m_actualType).getContractDefinition();
@ -969,14 +969,14 @@ MemberList const& TypeType::getMembers() const
// functions. Note that this does not add inherited functions on purpose.
for (ASTPointer<FunctionDefinition> const& f: contract.getDefinedFunctions())
if (!f->isConstructor() && !f->getName().empty() && f->isVisibleInDerivedContracts())
members[f->getName()] = make_shared<FunctionType>(*f);
members.push_back(make_pair(f->getName(), make_shared<FunctionType>(*f)));
}
else if (m_actualType->getCategory() == Category::Enum)
{
EnumDefinition const& enumDef = dynamic_cast<EnumType const&>(*m_actualType).getEnumDefinition();
auto enumType = make_shared<EnumType>(enumDef);
for (ASTPointer<EnumValue> const& enumValue: enumDef.getMembers())
members.insert(make_pair(enumValue->getName(), enumType));
members.push_back(make_pair(enumValue->getName(), enumType));
}
m_members.reset(new MemberList(members));
}

8
libsolidity/Types.h

@ -50,14 +50,16 @@ using TypePointers = std::vector<TypePointer>;
class MemberList
{
public:
using MemberMap = std::map<std::string, TypePointer>;
using MemberMap = std::vector<std::pair<std::string, TypePointer>>;
MemberList() {}
explicit MemberList(MemberMap const& _members): m_memberTypes(_members) {}
TypePointer getMemberType(std::string const& _name) const
{
auto it = m_memberTypes.find(_name);
return it != m_memberTypes.end() ? it->second : TypePointer();
for (auto const& it: m_memberTypes)
if (it.first == _name)
return it.second;
return TypePointer();
}
MemberMap::const_iterator begin() const { return m_memberTypes.begin(); }

4
libsolidity/grammar.txt

@ -6,10 +6,10 @@ ContractPart = StateVariableDeclaration | StructDefinition | ModifierDefinition
InheritanceSpecifier = Identifier ( '(' Expression ( ',' Expression )* ')' )?
StructDefinition = 'struct' Identifier '{'
( VariableDeclaration (';' VariableDeclaration)* )? '}
StateVariableDeclaration = TypeName ( 'public' | 'protected' | 'private' )? Identifier ';'
StateVariableDeclaration = TypeName ( 'public' | 'inheritable' | 'private' )? Identifier ';'
ModifierDefinition = 'modifier' Identifier ParameterList? Block
FunctionDefinition = 'function' Identifier ParameterList
( Identifier | 'constant' | 'public' | 'protected' | 'private' )*
( Identifier | 'constant' | 'external' | 'public' | 'inheritable' | 'private' )*
( 'returns' ParameterList )? Block
EnumValue = Identifier

2
libweb3jsonrpc/WebThreeStubServerBase.cpp

@ -542,7 +542,7 @@ std::string WebThreeStubServerBase::eth_solidity(std::string const& _code)
int WebThreeStubServerBase::eth_number()
{
return client()->number() + 1;
return client()->number();
}
int WebThreeStubServerBase::eth_peerCount()

2
secp256k1/CMakeLists.txt

@ -31,7 +31,7 @@ else()
add_library(${EXECUTABLE} SHARED ${EXECUTABLE}.c)
endif()
# /TP - compile project as cpp project
set_target_properties(${EXECUTABLE} PROPERTIES COMPILE_FLAGS "/TP")
set_target_properties(${EXECUTABLE} PROPERTIES COMPILE_FLAGS "/TP /wd4244")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_NUM_BOOST -DUSE_FIELD_10X26 -DUSE_FIELD_INV_BUILTIN")
endif()

36
test/SolidityEndToEndTest.cpp

@ -2479,6 +2479,42 @@ BOOST_AUTO_TEST_CASE(struct_copy)
BOOST_CHECK(callContractFunction("retrieve(uint256)", 8) == encodeArgs(0, 0, 0, 0));
}
BOOST_AUTO_TEST_CASE(struct_containing_bytes_copy_and_delete)
{
char const* sourceCode = R"(
contract c {
struct Struct { uint a; bytes data; uint b; }
Struct data1;
Struct data2;
function set(uint _a, bytes _data, uint _b) external returns (bool) {
data1.a = _a;
data1.b = _b;
data1.data = _data;
return true;
}
function copy() returns (bool) {
data1 = data2;
return true;
}
function del() returns (bool) {
delete data1;
return true;
}
}
)";
compileAndRun(sourceCode);
string data = "123456789012345678901234567890123";
BOOST_CHECK(m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("set(uint256,bytes,uint256)", u256(data.length()), 12, data, 13) == encodeArgs(true));
BOOST_CHECK(!m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("copy()") == encodeArgs(true));
BOOST_CHECK(m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("set(uint256,bytes,uint256)", u256(data.length()), 12, data, 13) == encodeArgs(true));
BOOST_CHECK(!m_state.storage(m_contractAddress).empty());
BOOST_CHECK(callContractFunction("del()") == encodeArgs(true));
BOOST_CHECK(m_state.storage(m_contractAddress).empty());
}
BOOST_AUTO_TEST_CASE(struct_copy_via_local)
{
char const* sourceCode = R"(

12
test/SolidityNameAndTypeResolution.cpp

@ -470,7 +470,7 @@ BOOST_AUTO_TEST_CASE(illegal_override_indirect)
BOOST_AUTO_TEST_CASE(illegal_override_visibility)
{
char const* text = R"(
contract B { function f() protected {} }
contract B { function f() inheritable {} }
contract C is B { function f() public {} }
)";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
@ -706,7 +706,7 @@ BOOST_AUTO_TEST_CASE(private_state_variable)
" uint64(2);\n"
" }\n"
"uint256 private foo;\n"
"uint256 protected bar;\n"
"uint256 inheritable bar;\n"
"}\n";
ASTPointer<SourceUnit> source;
@ -717,7 +717,7 @@ BOOST_AUTO_TEST_CASE(private_state_variable)
function = retrieveFunctionBySignature(contract, "foo()");
BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a private variable should not exist");
function = retrieveFunctionBySignature(contract, "bar()");
BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a protected variable should not exist");
BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of an inheritable variable should not exist");
}
BOOST_AUTO_TEST_CASE(fallback_function)
@ -832,11 +832,11 @@ BOOST_AUTO_TEST_CASE(access_to_default_function_visibility)
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
}
BOOST_AUTO_TEST_CASE(access_to_protected_function)
BOOST_AUTO_TEST_CASE(access_to_inheritable_function)
{
char const* text = R"(
contract c {
function f() protected {}
function f() inheritable {}
}
contract d {
function g() { c(0).f(); }
@ -856,7 +856,7 @@ BOOST_AUTO_TEST_CASE(access_to_default_state_variable_visibility)
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(access_to_protected_state_variable)
BOOST_AUTO_TEST_CASE(access_to_inheritable_state_variable)
{
char const* text = R"(
contract c {

6
test/SolidityParser.cpp

@ -651,13 +651,13 @@ BOOST_AUTO_TEST_CASE(visibility_specifiers)
char const* text = R"(
contract c {
uint private a;
uint protected b;
uint inheritable b;
uint public c;
uint d;
function f() {}
function f_priv() private {}
function f_public() public {}
function f_protected() protected {}
function f_inheritable() inheritable {}
})";
BOOST_CHECK_NO_THROW(parseText(text));
}
@ -666,7 +666,7 @@ BOOST_AUTO_TEST_CASE(multiple_visibility_specifiers)
{
char const* text = R"(
contract c {
uint private protected a;
uint private inheritable a;
})";
BOOST_CHECK_THROW(parseText(text), ParserError);
}

Loading…
Cancel
Save