mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #9971 from ethereum/fix-modifiers-using-exprimental-features-from-calling-module
Checking experimental pragmas in the right source unit when compiling modifiers and inherited functions
This commit is contained in:
commit
3724b98578
@ -9,6 +9,7 @@ Compiler Features:
|
|||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
* Code generator: Fix internal compiler error when referencing members via module name but not using the reference.
|
* Code generator: Fix internal compiler error when referencing members via module name but not using the reference.
|
||||||
|
* Code generator: Fix ``ABIEncoderV2`` pragma from the current module affecting inherited functions and applied modifiers.
|
||||||
* Type Checker: Fix internal compiler error caused by storage parameters with nested mappings in libraries.
|
* Type Checker: Fix internal compiler error caused by storage parameters with nested mappings in libraries.
|
||||||
* Name Resolver: Fix shadowing/same-name warnings for later declarations.
|
* Name Resolver: Fix shadowing/same-name warnings for later declarations.
|
||||||
|
|
||||||
|
@ -78,6 +78,7 @@ public:
|
|||||||
|
|
||||||
/// Update currently enabled set of experimental features.
|
/// Update currently enabled set of experimental features.
|
||||||
void setExperimentalFeatures(std::set<ExperimentalFeature> const& _features) { m_experimentalFeatures = _features; }
|
void setExperimentalFeatures(std::set<ExperimentalFeature> const& _features) { m_experimentalFeatures = _features; }
|
||||||
|
std::set<ExperimentalFeature> const& experimentalFeaturesActive() const { return m_experimentalFeatures; }
|
||||||
/// @returns true if the given feature is enabled.
|
/// @returns true if the given feature is enabled.
|
||||||
bool experimentalFeatureActive(ExperimentalFeature _feature) const { return m_experimentalFeatures.count(_feature); }
|
bool experimentalFeatureActive(ExperimentalFeature _feature) const { return m_experimentalFeatures.count(_feature); }
|
||||||
|
|
||||||
|
@ -1326,9 +1326,14 @@ void ContractCompiler::appendModifierOrFunctionCode()
|
|||||||
|
|
||||||
if (codeBlock)
|
if (codeBlock)
|
||||||
{
|
{
|
||||||
|
std::set<ExperimentalFeature> experimentalFeaturesOutside = m_context.experimentalFeaturesActive();
|
||||||
|
m_context.setExperimentalFeatures(codeBlock->sourceUnit().annotation().experimentalFeatures);
|
||||||
|
|
||||||
m_returnTags.emplace_back(m_context.newTag(), m_context.stackHeight());
|
m_returnTags.emplace_back(m_context.newTag(), m_context.stackHeight());
|
||||||
codeBlock->accept(*this);
|
codeBlock->accept(*this);
|
||||||
|
|
||||||
|
m_context.setExperimentalFeatures(experimentalFeaturesOutside);
|
||||||
|
|
||||||
solAssert(!m_returnTags.empty(), "");
|
solAssert(!m_returnTags.empty(), "");
|
||||||
m_context << m_returnTags.back().first;
|
m_context << m_returnTags.back().first;
|
||||||
m_returnTags.pop_back();
|
m_returnTags.pop_back();
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
==== Source: A ====
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
struct Data {
|
||||||
|
uint a;
|
||||||
|
uint[2] b;
|
||||||
|
uint c;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract A {
|
||||||
|
function get() public view returns (Data memory) {
|
||||||
|
return Data(5, [uint(66), 77], 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract B {
|
||||||
|
function foo(A _a) public returns (uint) {
|
||||||
|
return _a.get().b[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
==== Source: B ====
|
||||||
|
import "A";
|
||||||
|
|
||||||
|
contract C is B {
|
||||||
|
function test() public returns (uint) {
|
||||||
|
return foo(new A());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ====
|
||||||
|
// compileViaYul: also
|
||||||
|
// ----
|
||||||
|
// test() -> 77
|
@ -0,0 +1,38 @@
|
|||||||
|
==== Source: A ====
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
struct Data {
|
||||||
|
uint value;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract A {
|
||||||
|
function get() public view returns (Data memory) {
|
||||||
|
return Data(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract B {
|
||||||
|
uint x = 10;
|
||||||
|
uint y = 10;
|
||||||
|
|
||||||
|
modifier updateStorage() {
|
||||||
|
A a = new A();
|
||||||
|
x = a.get().value;
|
||||||
|
_;
|
||||||
|
y = a.get().value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
==== Source: B ====
|
||||||
|
import "A";
|
||||||
|
|
||||||
|
contract C is B {
|
||||||
|
function test()
|
||||||
|
public
|
||||||
|
updateStorage
|
||||||
|
returns (uint, uint)
|
||||||
|
{
|
||||||
|
return (x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// test() -> 5, 10
|
@ -0,0 +1,27 @@
|
|||||||
|
==== Source: A ====
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
struct Data {
|
||||||
|
bool flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract A {
|
||||||
|
function get() public view returns (Data memory) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract B {
|
||||||
|
modifier validate() {
|
||||||
|
A(0x00).get();
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
==== Source: B ====
|
||||||
|
import "A";
|
||||||
|
|
||||||
|
contract C is B {
|
||||||
|
function foo()
|
||||||
|
public
|
||||||
|
validate()
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,33 @@
|
|||||||
|
==== Source: A ====
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
struct Data {
|
||||||
|
bool flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract A {
|
||||||
|
function get() public view returns (Data memory) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract B {
|
||||||
|
constructor() validate {
|
||||||
|
A(0x00).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
modifier validate() {
|
||||||
|
A(0x00).get();
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
==== Source: B ====
|
||||||
|
import "A";
|
||||||
|
|
||||||
|
contract C is B {}
|
||||||
|
==== Source: C ====
|
||||||
|
import "B";
|
||||||
|
|
||||||
|
contract D is C {
|
||||||
|
constructor() validate B() validate C() validate {}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,25 @@
|
|||||||
|
==== Source: A ====
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
struct Data {
|
||||||
|
bool flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract A {
|
||||||
|
function get() public view returns (Data memory) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract B {
|
||||||
|
constructor() {
|
||||||
|
A(0x00).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
function foo() public view {
|
||||||
|
A(0x00).get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
==== Source: B ====
|
||||||
|
import "A";
|
||||||
|
|
||||||
|
contract C is B {}
|
||||||
|
// ----
|
@ -0,0 +1,21 @@
|
|||||||
|
==== Source: A ====
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
struct Item {
|
||||||
|
uint x;
|
||||||
|
}
|
||||||
|
|
||||||
|
library L {
|
||||||
|
event Ev(Item);
|
||||||
|
}
|
||||||
|
|
||||||
|
contract C {
|
||||||
|
function foo() public {
|
||||||
|
emit L.Ev(Item(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
==== Source: B ====
|
||||||
|
import "A";
|
||||||
|
|
||||||
|
contract D is C {}
|
||||||
|
// ----
|
@ -0,0 +1,29 @@
|
|||||||
|
==== Source: A ====
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
struct Data {
|
||||||
|
bool flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract A {
|
||||||
|
function get() public view returns (Data memory) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract B {
|
||||||
|
modifier validate() virtual {
|
||||||
|
A(0x00).get();
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
==== Source: B ====
|
||||||
|
import "A";
|
||||||
|
|
||||||
|
contract C is B {
|
||||||
|
function foo() public pure validate {}
|
||||||
|
|
||||||
|
modifier validate() override {
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
@ -0,0 +1,52 @@
|
|||||||
|
==== Source: C ====
|
||||||
|
import "X";
|
||||||
|
import "V1A";
|
||||||
|
import "V2A";
|
||||||
|
import "V1B";
|
||||||
|
|
||||||
|
contract C is V1A, V2A, V1B {
|
||||||
|
function foo()
|
||||||
|
public
|
||||||
|
modV1A
|
||||||
|
modV2A // There should be no error for modV2A (it uses ABIEncoderV2)
|
||||||
|
modV1B
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
==== Source: V1A ====
|
||||||
|
import "X";
|
||||||
|
|
||||||
|
contract V1A {
|
||||||
|
modifier modV1A() {
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
==== Source: V1B ====
|
||||||
|
import "X";
|
||||||
|
|
||||||
|
contract V1B {
|
||||||
|
modifier modV1B() {
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
==== Source: V2A ====
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
import "X";
|
||||||
|
|
||||||
|
contract V2A {
|
||||||
|
modifier modV2A() {
|
||||||
|
X(0x00).get();
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
==== Source: X ====
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
struct Data {
|
||||||
|
bool flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
contract X {
|
||||||
|
function get() public view returns (Data memory) {}
|
||||||
|
}
|
||||||
|
// ----
|
Loading…
Reference in New Issue
Block a user