diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 7df52ca23..f3c8ffa15 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -285,17 +285,17 @@ bool CompilerStack::analyze() // the special variables "this" and "super" must be set appropriately. for (Source const* source: m_sourceOrder) for (ASTPointer const& node: source->ast->nodes()) + { + if (!resolver.resolveNamesAndTypes(*node)) + return false; if (ContractDefinition* contract = dynamic_cast(node.get())) - { - - if (!resolver.resolveNamesAndTypes(*contract)) return false; // Note that we now reference contracts by their fully qualified names, and // thus contracts can only conflict if declared in the same source file. This // already causes a double-declaration error elsewhere, so we do not report // an error here and instead silently drop any additional contracts we find. if (m_contracts.find(contract->fullyQualifiedName()) == m_contracts.end()) m_contracts[contract->fullyQualifiedName()].contract = contract; - } + } // Next, we check inheritance, overrides, function collisions and other things at // contract or function level. diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index b358e4a94..7c42248f3 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -96,8 +96,11 @@ ASTPointer Parser::parse(shared_ptr const& _scanner) case Token::Library: nodes.push_back(parseContractDefinition()); break; + case Token::Struct: + nodes.push_back(parseStructDefinition()); + break; default: - fatalParserError(string("Expected pragma, import directive or contract/interface/library definition.")); + fatalParserError(string("Expected pragma, import directive or contract/interface/library/struct definition.")); } } solAssert(m_recursionDepth == 0, ""); diff --git a/test/libsolidity/semanticTests/structs/global.sol b/test/libsolidity/semanticTests/structs/global.sol new file mode 100644 index 000000000..18dbf87dd --- /dev/null +++ b/test/libsolidity/semanticTests/structs/global.sol @@ -0,0 +1,10 @@ +pragma experimental ABIEncoderV2; + +struct S { uint256 a; uint256 b; } +contract C { + function f(S calldata s) external pure returns (uint256, uint256) { + return (s.a, s.b); + } +} +// ---- +// f((uint256,uint256)): 42, 23 -> 42, 23 diff --git a/test/libsolidity/syntaxTests/structs/contract_global_struct_name_clash.sol b/test/libsolidity/syntaxTests/structs/contract_global_struct_name_clash.sol new file mode 100644 index 000000000..d8476f116 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/contract_global_struct_name_clash.sol @@ -0,0 +1,4 @@ +contract S {} +struct S { uint256 a; } +// ---- +// DeclarationError: (14-37): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/structs/global_struct.sol b/test/libsolidity/syntaxTests/structs/global_struct.sol new file mode 100644 index 000000000..219467eac --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/global_struct.sol @@ -0,0 +1,7 @@ +struct S { uint a; } +contract C { + function f() public pure { + S memory s = S(42); + s; + } +} \ No newline at end of file diff --git a/test/libsolidity/syntaxTests/structs/global_struct_contract_name_clash.sol b/test/libsolidity/syntaxTests/structs/global_struct_contract_name_clash.sol new file mode 100644 index 000000000..84ff22872 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/global_struct_contract_name_clash.sol @@ -0,0 +1,4 @@ +struct S { uint256 a; } +contract S {} +// ---- +// DeclarationError: (24-37): Identifier already declared. diff --git a/test/libsolidity/syntaxTests/structs/global_struct_shadowing.sol b/test/libsolidity/syntaxTests/structs/global_struct_shadowing.sol new file mode 100644 index 000000000..1a3e58443 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/global_struct_shadowing.sol @@ -0,0 +1,10 @@ +struct S { uint a; } +contract C { + struct S { address x; } + function f() public view { + S memory s = S(address(this)); + s; + } +} +// ---- +// Warning: (38-61): This declaration shadows an existing declaration. diff --git a/test/libsolidity/syntaxTests/structs/global_structs_name_clash.sol b/test/libsolidity/syntaxTests/structs/global_structs_name_clash.sol new file mode 100644 index 000000000..ce17f4c81 --- /dev/null +++ b/test/libsolidity/syntaxTests/structs/global_structs_name_clash.sol @@ -0,0 +1,4 @@ +struct S { uint256 a; } +struct S { uint256 a; } +// ---- +// DeclarationError: (24-47): Identifier already declared.