Merge pull request #7267 from ethereum/globalStruct

Allow global struct definitions.
This commit is contained in:
chriseth 2019-09-02 15:07:12 +02:00 committed by GitHub
commit ac5498bb88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 455 additions and 5 deletions

View File

@ -5,6 +5,7 @@ Breaking changes:
Language Features:
* Allow global enums and structs.
Compiler Features:

View File

@ -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<ASTNode> const& node: source->ast->nodes())
{
if (!resolver.resolveNamesAndTypes(*node))
return false;
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(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.

View File

@ -96,8 +96,14 @@ ASTPointer<SourceUnit> Parser::parse(shared_ptr<Scanner> const& _scanner)
case Token::Library:
nodes.push_back(parseContractDefinition());
break;
case Token::Struct:
nodes.push_back(parseStructDefinition());
break;
case Token::Enum:
nodes.push_back(parseEnumDefinition());
break;
default:
fatalParserError(string("Expected pragma, import directive or contract/interface/library definition."));
fatalParserError(string("Expected pragma, import directive or contract/interface/library/struct/enum definition."));
}
}
solAssert(m_recursionDepth == 0, "");

View File

@ -0,0 +1,58 @@
pragma experimental ABIEncoderV2;
struct S { uint a; }
contract C {
function f(S calldata s) external view {}
function g(S memory s) public view {}
}
// ----
// :C
// [
// {
// "constant": true,
// "inputs":
// [
// {
// "components":
// [
// {
// "internalType": "uint256",
// "name": "a",
// "type": "uint256"
// }
// ],
// "internalType": "struct S",
// "name": "s",
// "type": "tuple"
// }
// ],
// "name": "g",
// "outputs": [],
// "payable": false,
// "stateMutability": "view",
// "type": "function"
// },
// {
// "constant": true,
// "inputs":
// [
// {
// "components":
// [
// {
// "internalType": "uint256",
// "name": "a",
// "type": "uint256"
// }
// ],
// "internalType": "struct S",
// "name": "s",
// "type": "tuple"
// }
// ],
// "name": "f",
// "outputs": [],
// "payable": false,
// "stateMutability": "view",
// "type": "function"
// }
// ]

View File

@ -0,0 +1,32 @@
{
"absolutePath" : "a",
"exportedSymbols" :
{
"E" :
[
2
]
},
"id" : 3,
"nodeType" : "SourceUnit",
"nodes" :
[
{
"canonicalName" : "E",
"id" : 2,
"members" :
[
{
"id" : 1,
"name" : "A",
"nodeType" : "EnumValue",
"src" : "9:1:1"
}
],
"name" : "E",
"nodeType" : "EnumDefinition",
"src" : "0:12:1"
}
],
"src" : "0:13:1"
}

View File

@ -0,0 +1,3 @@
enum E { A }
// ----

View File

@ -0,0 +1,41 @@
{
"attributes" :
{
"absolutePath" : "a",
"exportedSymbols" :
{
"E" :
[
2
]
}
},
"children" :
[
{
"attributes" :
{
"canonicalName" : "E",
"name" : "E"
},
"children" :
[
{
"attributes" :
{
"name" : "A"
},
"id" : 1,
"name" : "EnumValue",
"src" : "9:1:1"
}
],
"id" : 2,
"name" : "EnumDefinition",
"src" : "0:12:1"
}
],
"id" : 3,
"name" : "SourceUnit",
"src" : "0:13:1"
}

View File

@ -0,0 +1,58 @@
{
"absolutePath" : "a",
"exportedSymbols" :
{
"S" :
[
3
]
},
"id" : 4,
"nodeType" : "SourceUnit",
"nodes" :
[
{
"canonicalName" : "S",
"id" : 3,
"members" :
[
{
"constant" : false,
"id" : 2,
"name" : "a",
"nodeType" : "VariableDeclaration",
"overrides" : null,
"scope" : 3,
"src" : "11:9:1",
"stateVariable" : false,
"storageLocation" : "default",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
},
"typeName" :
{
"id" : 1,
"name" : "uint256",
"nodeType" : "ElementaryTypeName",
"src" : "11:7:1",
"typeDescriptions" :
{
"typeIdentifier" : "t_uint256",
"typeString" : "uint256"
}
},
"value" : null,
"visibility" : "internal"
}
],
"name" : "S",
"nodeType" : "StructDefinition",
"scope" : 4,
"src" : "0:23:1",
"visibility" : "public"
}
],
"src" : "0:24:1"
}

View File

@ -0,0 +1,3 @@
struct S { uint256 a; }
// ----

View File

@ -0,0 +1,64 @@
{
"attributes" :
{
"absolutePath" : "a",
"exportedSymbols" :
{
"S" :
[
3
]
}
},
"children" :
[
{
"attributes" :
{
"canonicalName" : "S",
"name" : "S",
"scope" : 4,
"visibility" : "public"
},
"children" :
[
{
"attributes" :
{
"constant" : false,
"name" : "a",
"overrides" : null,
"scope" : 3,
"stateVariable" : false,
"storageLocation" : "default",
"type" : "uint256",
"value" : null,
"visibility" : "internal"
},
"children" :
[
{
"attributes" :
{
"name" : "uint256",
"type" : "uint256"
},
"id" : 1,
"name" : "ElementaryTypeName",
"src" : "11:7:1"
}
],
"id" : 2,
"name" : "VariableDeclaration",
"src" : "11:9:1"
}
],
"id" : 3,
"name" : "StructDefinition",
"src" : "0:23:1"
}
],
"id" : 4,
"name" : "SourceUnit",
"src" : "0:24:1"
}

View File

@ -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

View File

@ -0,0 +1,7 @@
enum E { A }
contract C {
function f() public pure {
E e = E.A;
e;
}
}

View File

@ -0,0 +1,4 @@
enum E { A }
contract E {}
// ----
// DeclarationError: (13-26): Identifier already declared.

View File

@ -0,0 +1,4 @@
enum E { A }
enum E { A }
// ----
// DeclarationError: (13-25): Identifier already declared.

View File

@ -0,0 +1,10 @@
enum E { A }
contract C {
enum E { A }
function f() public pure {
E e = E.A;
e;
}
}
// ----
// Warning: (30-42): This declaration shadows an existing declaration.

View File

@ -0,0 +1,7 @@
==== Source: a ====
contract A {}
==== Source: b ====
import "a";
struct A { uint256 a; }
// ----
// DeclarationError: (b:12-35): Identifier already declared.

View File

@ -0,0 +1,7 @@
==== Source: a ====
contract A {}
==== Source: b ====
import "a" as A;
struct A { uint256 a; }
// ----
// DeclarationError: (b:17-40): Identifier already declared.

View File

@ -0,0 +1,7 @@
==== Source: a ====
contract A {}
==== Source: b ====
import {A as b} from "a";
struct b { uint256 a; }
// ----
// DeclarationError: (b:26-49): Identifier already declared.

View File

@ -0,0 +1,7 @@
==== Source: a ====
contract A {}
==== Source: b ====
import {A} from "a";
struct A { uint256 a; }
// ----
// DeclarationError: (b:21-44): Identifier already declared.

View File

@ -0,0 +1,5 @@
==== Source: a ====
contract A {}
==== Source: b ====
import {A} from "a";
struct B { uint256 a; }

View File

@ -0,0 +1,7 @@
==== Source: a ====
enum E { A }
==== Source: b ====
import "a";
enum E { A }
// ----
// DeclarationError: (b:12-24): Identifier already declared.

View File

@ -0,0 +1,7 @@
==== Source: a ====
enum E { A }
==== Source: b ====
import "a";
contract E { }
// ----
// DeclarationError: (b:12-26): Identifier already declared.

View File

@ -0,0 +1,7 @@
==== Source: a ====
enum E { A }
==== Source: b ====
import "a";
struct E { uint256 a; }
// ----
// DeclarationError: (b:12-35): Identifier already declared.

View File

@ -0,0 +1,7 @@
==== Source: a ====
struct A { uint256 a; }
==== Source: b ====
import "a";
struct A { uint256 a; }
// ----
// DeclarationError: (b:12-35): Identifier already declared.

View File

@ -0,0 +1,7 @@
==== Source: a ====
struct A { uint256 a; }
==== Source: b ====
import "a" as A;
struct A { uint256 a; }
// ----
// DeclarationError: (b:17-40): Identifier already declared.

View File

@ -0,0 +1,7 @@
==== Source: a ====
struct A { uint256 a; }
==== Source: b ====
import {A as b} from "a";
struct b { uint256 a; }
// ----
// DeclarationError: (b:26-49): Identifier already declared.

View File

@ -0,0 +1,7 @@
==== Source: a ====
struct A { uint256 a; }
==== Source: b ====
import {A} from "a";
struct A { uint256 a; }
// ----
// DeclarationError: (b:21-44): Identifier already declared.

View File

@ -0,0 +1,5 @@
==== Source: a ====
struct A { uint256 a; }
==== Source: b ====
import {A} from "a";
struct B { uint256 a; }

View File

@ -0,0 +1,7 @@
==== Source: a ====
struct A { uint256 a; }
==== Source: b ====
import "a";
contract A {}
// ----
// DeclarationError: (b:12-25): Identifier already declared.

View File

@ -0,0 +1,7 @@
==== Source: a ====
struct A { uint256 a; }
==== Source: b ====
import "a" as A;
contract A {}
// ----
// DeclarationError: (b:17-30): Identifier already declared.

View File

@ -0,0 +1,7 @@
==== Source: a ====
struct A { uint256 a; }
==== Source: b ====
import {A as b} from "a";
contract b {}
// ----
// DeclarationError: (b:26-39): Identifier already declared.

View File

@ -0,0 +1,7 @@
==== Source: a ====
struct A { uint256 a; }
==== Source: b ====
import {A} from "a";
contract A {}
// ----
// DeclarationError: (b:21-34): Identifier already declared.

View File

@ -0,0 +1,5 @@
==== Source: a ====
struct A { uint256 a; }
==== Source: b ====
import {A} from "a";
contract B {}

View File

@ -0,0 +1,4 @@
contract S {}
struct S { uint256 a; }
// ----
// DeclarationError: (14-37): Identifier already declared.

View File

@ -0,0 +1,7 @@
struct S { uint a; }
contract C {
function f() public pure {
S memory s = S(42);
s;
}
}

View File

@ -0,0 +1,4 @@
struct S { uint256 a; }
contract S {}
// ----
// DeclarationError: (24-37): Identifier already declared.

View File

@ -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.

View File

@ -0,0 +1,4 @@
struct S { uint256 a; }
struct S { uint256 a; }
// ----
// DeclarationError: (24-47): Identifier already declared.