Skip to content

Commit cc6422b

Browse files
authored
Merge pull request #15463 from ethereum/storageLocationsParserSupport
Parser support for explicit storage locations
2 parents 53ab29f + e844a8b commit cc6422b

File tree

78 files changed

+684
-16
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+684
-16
lines changed

Changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
### 0.8.29 (unreleased)
22

33
Language Features:
4+
* Introduce syntax for specifying contract storage layout base.
45

56

67
Compiler Features:

docs/grammar/SolidityLexer.g4

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Address: 'address';
1414
Anonymous: 'anonymous';
1515
As: 'as';
1616
Assembly: 'assembly' -> pushMode(AssemblyBlockMode);
17+
At: 'at'; // not a real keyword
1718
Bool: 'bool';
1819
Break: 'break';
1920
Bytes: 'bytes';
@@ -54,6 +55,7 @@ Indexed: 'indexed';
5455
Interface: 'interface';
5556
Internal: 'internal';
5657
Is: 'is';
58+
Layout: 'layout'; // not a real keyword
5759
Library: 'library';
5860
Mapping: 'mapping';
5961
Memory: 'memory';

docs/grammar/SolidityParser.g4

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,14 @@ symbolAliases: LBrace aliases+=importAliases (Comma aliases+=importAliases)* RBr
5252
/**
5353
* Top-level definition of a contract.
5454
*/
55-
contractDefinition:
55+
contractDefinition
56+
locals [boolean layoutSet=false, boolean inheritanceSet=false]
57+
:
5658
Abstract? Contract name=identifier
57-
inheritanceSpecifierList?
59+
(
60+
{!$layoutSet}? Layout At expression {$layoutSet = true;}
61+
| {!$inheritanceSet}? inheritanceSpecifierList {$inheritanceSet = true;}
62+
)*
5863
LBrace contractBodyElement* RBrace;
5964
/**
6065
* Top-level definition of an interface.
@@ -379,7 +384,7 @@ expression:
379384
expression LBrack index=expression? RBrack # IndexAccess
380385
| expression LBrack startIndex=expression? Colon endIndex=expression? RBrack # IndexRangeAccess
381386
| expression Period (identifier | Address) # MemberAccess
382-
| expression LBrace (namedArgument (Comma namedArgument)*)? RBrace # FunctionCallOptions
387+
| expression LBrace (namedArgument (Comma namedArgument)*) RBrace # FunctionCallOptions
383388
| expression callArgumentList # FunctionCall
384389
| Payable callArgumentList # PayableConversion
385390
| Type LParen typeName RParen # MetaType
@@ -420,7 +425,7 @@ inlineArrayExpression: LBrack (expression ( Comma expression)* ) RBrack;
420425
/**
421426
* Besides regular non-keyword Identifiers, some keywords like 'from' and 'error' can also be used as identifiers.
422427
*/
423-
identifier: Identifier | From | Error | Revert | Global | Transient;
428+
identifier: Identifier | From | Error | Revert | Global | Transient | Layout | At;
424429

425430
literal: stringLiteral | numberLiteral | booleanLiteral | hexStringLiteral | unicodeStringLiteral;
426431

liblangutil/ErrorReporter.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,17 @@ void ErrorReporter::parserError(ErrorId _error, SourceLocation const& _location,
190190
);
191191
}
192192

193+
void ErrorReporter::parserError(ErrorId _error, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, std::string const& _description)
194+
{
195+
error(
196+
_error,
197+
Error::Type::ParserError,
198+
_location,
199+
_secondaryLocation,
200+
_description
201+
);
202+
}
203+
193204
void ErrorReporter::fatalParserError(ErrorId _error, SourceLocation const& _location, std::string const& _description)
194205
{
195206
fatalError(

liblangutil/ErrorReporter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class ErrorReporter
8787
void fatalDeclarationError(ErrorId _error, SourceLocation const& _location, std::string const& _description);
8888

8989
void parserError(ErrorId _error, SourceLocation const& _location, std::string const& _description);
90+
void parserError(ErrorId _error, SourceLocation const& _location, SecondarySourceLocation const& _secondaryLocation, std::string const& _description);
9091

9192
void fatalParserError(ErrorId _error, SourceLocation const& _location, std::string const& _description);
9293

libsolidity/analysis/NameAndTypeResolver.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,10 @@ bool NameAndTypeResolver::resolveNamesAndTypesInternal(ASTNode& _node, bool _res
299299
if (!resolveNamesAndTypesInternal(*baseContract, true))
300300
success = false;
301301

302+
if (StorageLayoutSpecifier* storageLayoutSpecifier = contract->storageLayoutSpecifier())
303+
if (!resolveNamesAndTypesInternal(*storageLayoutSpecifier, true))
304+
success = false;
305+
302306
setScope(contract);
303307

304308
if (success)

libsolidity/analysis/TypeChecker.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
8686

8787
ASTNode::listAccept(_contract.baseContracts(), *this);
8888

89+
if (StorageLayoutSpecifier const* layoutSpecifier = _contract.storageLayoutSpecifier())
90+
layoutSpecifier->accept(*this);
91+
8992
for (auto const& n: _contract.subNodes())
9093
n->accept(*this);
9194

libsolidity/ast/AST.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,17 @@ std::multimap<std::string, FunctionDefinition const*> const& ContractDefinition:
371371
});
372372
}
373373

374+
StorageLayoutSpecifier::StorageLayoutSpecifier(
375+
int64_t _id,
376+
SourceLocation const& _location,
377+
ASTPointer<Expression> _baseSlotExpression
378+
):
379+
ASTNode(_id, _location),
380+
m_baseSlotExpression(_baseSlotExpression)
381+
{
382+
solAssert(m_baseSlotExpression);
383+
solAssert(_location.contains(m_baseSlotExpression->location()));
384+
}
374385

375386
TypeNameAnnotation& TypeName::annotation() const
376387
{

libsolidity/ast/AST.h

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -509,14 +509,16 @@ class ContractDefinition: public Declaration, public StructurallyDocumented, pub
509509
std::vector<ASTPointer<InheritanceSpecifier>> _baseContracts,
510510
std::vector<ASTPointer<ASTNode>> _subNodes,
511511
ContractKind _contractKind = ContractKind::Contract,
512-
bool _abstract = false
512+
bool _abstract = false,
513+
ASTPointer<StorageLayoutSpecifier> _storageLayoutSpecifier = nullptr
513514
):
514515
Declaration(_id, _location, _name, std::move(_nameLocation)),
515516
StructurallyDocumented(_documentation),
516517
m_baseContracts(std::move(_baseContracts)),
517518
m_subNodes(std::move(_subNodes)),
518519
m_contractKind(_contractKind),
519-
m_abstract(_abstract)
520+
m_abstract(_abstract),
521+
m_storageLayoutSpecifier(_storageLayoutSpecifier)
520522
{}
521523

522524
void accept(ASTVisitor& _visitor) override;
@@ -586,6 +588,9 @@ class ContractDefinition: public Declaration, public StructurallyDocumented, pub
586588

587589
bool abstract() const { return m_abstract; }
588590

591+
StorageLayoutSpecifier const* storageLayoutSpecifier() const { return m_storageLayoutSpecifier.get(); }
592+
StorageLayoutSpecifier* storageLayoutSpecifier() { return m_storageLayoutSpecifier.get(); }
593+
589594
ContractDefinition const* superContract(ContractDefinition const& _mostDerivedContract) const;
590595
/// @returns the next constructor in the inheritance hierarchy.
591596
FunctionDefinition const* nextConstructor(ContractDefinition const& _mostDerivedContract) const;
@@ -597,12 +602,30 @@ class ContractDefinition: public Declaration, public StructurallyDocumented, pub
597602
std::vector<ASTPointer<ASTNode>> m_subNodes;
598603
ContractKind m_contractKind;
599604
bool m_abstract{false};
605+
ASTPointer<StorageLayoutSpecifier> m_storageLayoutSpecifier;
600606

601607
util::LazyInit<std::vector<std::pair<util::FixedHash<4>, FunctionTypePointer>>> m_interfaceFunctionList[2];
602608
util::LazyInit<std::vector<EventDefinition const*>> m_interfaceEvents;
603609
util::LazyInit<std::multimap<std::string, FunctionDefinition const*>> m_definedFunctionsByName;
604610
};
605611

612+
613+
class StorageLayoutSpecifier : public ASTNode
614+
{
615+
public:
616+
StorageLayoutSpecifier(
617+
int64_t _id,
618+
SourceLocation const& _location,
619+
ASTPointer<Expression> _baseSlotExpression
620+
);
621+
void accept(ASTVisitor& _visitor) override;
622+
void accept(ASTConstVisitor& _visitor) const override;
623+
624+
Expression const& baseSlotExpression() const { solAssert(m_baseSlotExpression); return *m_baseSlotExpression; }
625+
private:
626+
ASTPointer<Expression> m_baseSlotExpression;
627+
};
628+
606629
/**
607630
* A sequence of identifiers separated by dots used outside the expression context. Inside the expression context, this is a sequence of Identifier and MemberAccess.
608631
*/

libsolidity/ast/ASTForward.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ class Identifier;
9898
class ElementaryTypeNameExpression;
9999
class Literal;
100100
class StructuredDocumentation;
101+
class StorageLayoutSpecifier;
101102

102103
/// Experimental Solidity nodes
103104
/// @{

0 commit comments

Comments
 (0)