Skip to content

Commit 60dce06

Browse files
committed
merge 0.8.5 eth solidity
1 parent e77e9e4 commit 60dce06

18 files changed

+708
-17
lines changed

cmake/EthCompilerSettings.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ elseif (DEFINED MSVC)
162162

163163
add_compile_options(/MP) # enable parallel compilation
164164
add_compile_options(/EHsc) # specify Exception Handling Model in msvc
165-
add_compile_options(/WX) # enable warnings-as-errors
165+
add_compile_options(/WX-) # enable warnings-as-errors
166166
add_compile_options(/wd4068) # disable unknown pragma warning (4068)
167167
add_compile_options(/wd4996) # disable unsafe function warning (4996)
168168
add_compile_options(/wd4503) # disable decorated name length exceeded, name was truncated (4503)

libevmasm/ConstantOptimiser.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,8 @@ unsigned ConstantOptimisationMethod::optimiseConstants(
6363
AssemblyItems replacement;
6464
if (copyGas < literalGas && copyGas < computeGas)
6565
{
66-
replacement = copy.execute(_assembly);
67-
optimisations++;
66+
/*replacement = copy.execute(_assembly);
67+
optimisations++;*/
6868
}
6969
else if (computeGas < literalGas && computeGas <= copyGas)
7070
{

libevmasm/GasMeter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ GasMeter::GasConsumption GasMeter::estimateMax(AssemblyItem const& _item, bool _
8181
break;
8282
case Instruction::RETURN:
8383
case Instruction::REVERT:
84+
case Instruction::REVERTDIY:
8485
gas = runGas(_item.instruction());
8586
gas += memoryGas(0, -1);
8687
break;

libevmasm/Instruction.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,39 @@ std::map<std::string, Instruction> const solidity::evmasm::c_instructions =
166166
{ "LOG3", Instruction::LOG3 },
167167
{ "LOG4", Instruction::LOG4 },
168168
{ "CREATE", Instruction::CREATE },
169+
170+
/* Begin SQL instruction */
171+
{ "CREATETABLE", Instruction::CREATETABLE},
172+
{ "EXDROPTABLE", Instruction::EXDROPTABLE},
173+
{ "EXRENAMETABLE", Instruction::EXRENAMETABLE},
174+
{ "EXINSERTSQL", Instruction::EXINSERTSQL},
175+
{ "EXDELETESQL", Instruction::EXDELETESQL},
176+
{ "EXUPDATESQL", Instruction::EXUPDATESQL},
177+
{ "EXSELECTSQL", Instruction::EXSELECTSQL},
178+
{ "EXTRANSBEGIN", Instruction::EXTRANSBEGIN},
179+
{ "EXTRANSCOMMIT", Instruction::EXTRANSCOMMIT},
180+
{ "EXGRANTSQL", Instruction::EXGRANTSQL},
181+
{ "EXGETROWSIZE", Instruction::EXGETROWSIZE},
182+
{ "EXGETCOLSIZE", Instruction::EXGETCOLSIZE},
183+
{ "EXGETVALUEBYKEY", Instruction::EXGETVALUEBYKEY},
184+
{ "EXGETVALUEBYINDEX", Instruction::EXGETVALUEBYINDEX},
185+
{ "EXEXITFUNC", Instruction::EXEXITFUNC},
186+
{ "EXGETLENBYKEY", Instruction::EXGETLENBYKEY},
187+
{ "EXGETLENBYINDEX", Instruction::EXGETLENBYINDEX},
188+
/* End SQL instruction */
189+
190+
/* Begin Token instruction */
191+
{ "EXACCOUNTSET", Instruction::EXACCOUNTSET },
192+
{ "EXTRANSFERRATESET", Instruction::EXTRANSFERRATESET },
193+
{ "EXTRANSFERRANGESET", Instruction::EXTRANSFERRANGESET },
194+
{ "EXTRUSTSET", Instruction::EXTRUSTSET },
195+
{ "EXTRUSTLIMIT", Instruction::EXTRUSTLIMIT },
196+
{ "EXGATEWAYBALANCE", Instruction::EXGATEWAYBALANCE },
197+
{ "EXPAY", Instruction::EXPAY },
198+
/* End Token instructtion */
199+
200+
{ "REVERTDIY", Instruction::REVERTDIY},
201+
169202
{ "CALL", Instruction::CALL },
170203
{ "CALLCODE", Instruction::CALLCODE },
171204
{ "STATICCALL", Instruction::STATICCALL },
@@ -312,6 +345,31 @@ static std::map<Instruction, InstructionInfo> const c_instructionInfo =
312345
{ Instruction::LOG3, { "LOG3", 0, 5, 0, true, Tier::Special } },
313346
{ Instruction::LOG4, { "LOG4", 0, 6, 0, true, Tier::Special } },
314347
{ Instruction::CREATE, { "CREATE", 0, 3, 1, true, Tier::Special } },
348+
{ Instruction::CREATETABLE, { "CREATETABLE", 0, 5, 1, true, Tier::Zero} },
349+
{ Instruction::EXDROPTABLE, { "EXDROPTABLE", 0, 3, 1, true, Tier::Zero} },
350+
{ Instruction::EXRENAMETABLE, { "EXRENAMETABLE", 0, 5, 1, true, Tier::Zero} },
351+
{ Instruction::EXINSERTSQL, { "EXINSERTSQL", 0, 5, 1, true, Tier::Zero} },
352+
{ Instruction::EXDELETESQL, { "EXDELETESQL", 0, 5, 1, true, Tier::Zero} },
353+
{ Instruction::EXUPDATESQL, { "EXUPDATESQL", 0, 7, 1, true, Tier::Zero} },
354+
{ Instruction::EXSELECTSQL, { "EXSELECTSQL", 0, 5, 1, true, Tier::Zero} },
355+
{ Instruction::EXGRANTSQL, { "EXGRANTSQL", 0, 6, 1, true, Tier::Zero} },
356+
{ Instruction::EXTRANSBEGIN,{ "EXTRANSBEGIN", 0, 0, 0, true, Tier::Zero} },
357+
{ Instruction::EXTRANSCOMMIT, { "EXTRANSCOMMIT", 0, 0, 1, true, Tier::Zero} },
358+
{ Instruction::EXGETROWSIZE, { "EXGETROWSIZE", 0, 1, 1, true, Tier::Zero} },
359+
{ Instruction::EXGETCOLSIZE, { "EXGETCOLSIZE", 0, 1, 1, true, Tier::Zero} },
360+
{ Instruction::EXGETVALUEBYKEY, { "EXGETVALUEBYKEY", 0, 6, 1, true, Tier::Zero} },
361+
{ Instruction::EXGETVALUEBYINDEX, { "EXGETVALUEBYINDEX", 0, 5, 1, true, Tier::Zero} },
362+
{ Instruction::EXEXITFUNC, { "EXEXITFUNC", 0, 0, 0, true, Tier::Zero} },
363+
{ Instruction::EXGETLENBYKEY, { "EXGETLENBYKEY", 0, 4, 1, true, Tier::Zero} },
364+
{ Instruction::EXGETLENBYINDEX, { "EXGETLENBYINDEX",0, 3, 1, true, Tier::Zero} },
365+
{ Instruction::EXACCOUNTSET, { "EXACCOUNTSET", 0, 3, 1, true, Tier::Zero } },
366+
{ Instruction::EXTRANSFERRATESET,{ "EXTRANSFERRATESET", 0, 3, 1, true, Tier::Zero } },
367+
{ Instruction::EXTRANSFERRANGESET,{ "EXTRANSFERRANGESET", 0, 5, 1, true, Tier::Zero } },
368+
{ Instruction::EXTRUSTSET,{ "EXTRUSTSET", 0, 6, 1, true, Tier::Zero } },
369+
{ Instruction::EXTRUSTLIMIT,{ "EXTRUSTLIMIT", 0, 4, 1, true, Tier::Zero } },
370+
{ Instruction::EXGATEWAYBALANCE,{ "EXGATEWAYBALANCE", 0, 4, 1, true, Tier::Zero } },
371+
{ Instruction::EXPAY,{ "EXPAY", 0, 7, 1, true, Tier::Zero } },
372+
{ Instruction::REVERTDIY, { "REVERTDIY", 0, 2, 0, true, Tier::Zero } },
315373
{ Instruction::CALL, { "CALL", 0, 7, 1, true, Tier::Special } },
316374
{ Instruction::CALLCODE, { "CALLCODE", 0, 7, 1, true, Tier::Special } },
317375
{ Instruction::RETURN, { "RETURN", 0, 2, 0, true, Tier::Zero } },

libevmasm/Instruction.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,35 @@ enum class Instruction: uint8_t
175175
LOG3, ///< Makes a log entry; 3 topics.
176176
LOG4, ///< Makes a log entry; 4 topics.
177177

178+
CREATETABLE = 0xc0, // self-extention intructions
179+
EXDROPTABLE,
180+
EXRENAMETABLE,
181+
EXINSERTSQL,
182+
EXDELETESQL,
183+
EXUPDATESQL,
184+
EXSELECTSQL,
185+
EXGRANTSQL,
186+
EXTRANSBEGIN,
187+
EXTRANSCOMMIT,
188+
EXGETROWSIZE,
189+
EXGETCOLSIZE,
190+
EXGETVALUEBYKEY,
191+
EXGETVALUEBYINDEX,
192+
EXEXITFUNC,
193+
EXGETLENBYKEY,
194+
EXGETLENBYINDEX = 0xd0,
195+
196+
EXACCOUNTSET,
197+
EXTRANSFERRATESET,
198+
EXTRANSFERRANGESET,
199+
EXTRUSTSET,
200+
EXTRUSTLIMIT,
201+
EXGATEWAYBALANCE,
202+
EXPAY,
203+
204+
REVERTDIY,
205+
/** NOTE: maximum value is 0xef */
206+
178207
CREATE = 0xf0, ///< create a new account with associated code
179208
CALL, ///< message-call into an account
180209
CALLCODE, ///< message-call with another account's code only

libevmasm/PeepholeOptimiser.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,8 @@ struct UnreachableCode
349349
it[0] != Instruction::STOP &&
350350
it[0] != Instruction::INVALID &&
351351
it[0] != Instruction::SELFDESTRUCT &&
352-
it[0] != Instruction::REVERT
352+
it[0] != Instruction::REVERT &&
353+
it[0] != Instruction::REVERTDIY
353354
)
354355
return false;
355356

libevmasm/SemanticInformation.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ bool SemanticInformation::terminatesControlFlow(Instruction _instruction)
145145
case Instruction::STOP:
146146
case Instruction::INVALID:
147147
case Instruction::REVERT:
148+
case Instruction::REVERTDIY:
148149
return true;
149150
default:
150151
return false;

libsolidity/analysis/GlobalContext.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,15 @@ inline vector<shared_ptr<MagicVariableDeclaration const>> constructMagicVariable
8787
magicVarDecl("require", TypeProvider::function(strings{"bool", "string memory"}, strings{}, FunctionType::Kind::Require, false, StateMutability::Pure)),
8888
magicVarDecl("revert", TypeProvider::function(strings(), strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)),
8989
magicVarDecl("revert", TypeProvider::function(strings{"string memory"}, strings(), FunctionType::Kind::Revert, false, StateMutability::Pure)),
90+
magicVarDecl("revertdiy", TypeProvider::function(strings(), strings(), FunctionType::Kind::RevertDIY, false, StateMutability::Pure)),
91+
magicVarDecl("revertdiy", TypeProvider::function(strings{ "string memory" }, strings(), FunctionType::Kind::RevertDIY, false, StateMutability::Pure)),
9092
magicVarDecl("ripemd160", TypeProvider::function(strings{"bytes memory"}, strings{"bytes20"}, FunctionType::Kind::RIPEMD160, false, StateMutability::Pure)),
9193
magicVarDecl("selfdestruct", TypeProvider::function(strings{"address payable"}, strings{}, FunctionType::Kind::Selfdestruct)),
9294
magicVarDecl("sha256", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::SHA256, false, StateMutability::Pure)),
9395
magicVarDecl("sha3", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, false, StateMutability::Pure)),
9496
magicVarDecl("suicide", TypeProvider::function(strings{"address payable"}, strings{}, FunctionType::Kind::Selfdestruct)),
9597
magicVarDecl("tx", TypeProvider::magic(MagicType::Kind::Transaction)),
98+
magicVarDecl("db", TypeProvider::magic(MagicType::Kind::Database)),
9699
// Accepts a MagicType that can be any contract type or an Integer type and returns a
97100
// MagicType. The TypeChecker handles the correctness of the input and output types.
98101
magicVarDecl("type", TypeProvider::function(

libsolidity/ast/Types.cpp

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,22 @@ MemberList::MemberMap AddressType::nativeMembers(ASTNode const*) const
474474
{"call", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCall, false, StateMutability::Payable)},
475475
{"callcode", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareCallCode, false, StateMutability::Payable)},
476476
{"delegatecall", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareDelegateCall, false, StateMutability::NonPayable)},
477-
{"staticcall", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareStaticCall, false, StateMutability::View)}
477+
{"staticcall", TypeProvider::function(strings{"bytes memory"}, strings{"bool", "bytes memory"}, FunctionType::Kind::BareStaticCall, false, StateMutability::View)},
478+
{"create", TypeProvider::function(strings{"string memory", "string memory"}, strings(), FunctionType::Kind::CreateSQL)},
479+
{"drop", TypeProvider::function(strings{"string memory"}, strings(), FunctionType::Kind::DropSQL)},
480+
{"rename", TypeProvider::function(strings{"string memory", "string memory"}, strings(), FunctionType::Kind::RenameSQL)},
481+
{"insert", TypeProvider::function(strings{"string memory", "string memory"}, strings(), FunctionType::Kind::InsertSQL)},
482+
{"deletex", TypeProvider::function(strings{"string memory", "string memory"}, strings(), FunctionType::Kind::DeleteSQL)},
483+
{"update", TypeProvider::function(strings{"string memory", "string memory", "string memory"}, strings(), FunctionType::Kind::UpdateSQL)},
484+
{"get", TypeProvider::function(strings{"string memory", "string memory"}, strings{"uint256"}, FunctionType::Kind::GetSQL, false, StateMutability::View)},
485+
{"grant", TypeProvider::function(strings{"address", "string memory", "string memory"}, strings(), FunctionType::Kind::GrantSQL)},
486+
{ "accountSet", TypeProvider::function(strings{"uint32", "bool"}, strings(), FunctionType::Kind::AccountSet) },
487+
{ "setTransferRate", TypeProvider::function(strings{ "string memory"}, strings(), FunctionType::Kind::SetTransferRate) },
488+
{ "setTransferRange", TypeProvider::function(strings{ "string memory", "string memory" }, strings(), FunctionType::Kind::SetTransferRange) },
489+
{ "trustSet", TypeProvider::function(strings{ "string memory", "string memory", "address" }, strings(), FunctionType::Kind::TrustSet) },
490+
{ "trustLimit", TypeProvider::function(strings{ "string memory", "address" }, strings{ "int" }, FunctionType::Kind::TrustLimit, false, StateMutability::View) },
491+
{ "gatewayBalance", TypeProvider::function(strings{ "string memory", "address" }, strings{ "int" }, FunctionType::Kind::GateWayBalance, false, StateMutability::View) },
492+
{ "pay", TypeProvider::function(strings{ "address", "string memory", "string memory", "address" }, strings(), FunctionType::Kind::Pay) }
478493
};
479494
if (m_stateMutability == StateMutability::Payable)
480495
{
@@ -2878,8 +2893,10 @@ string FunctionType::richIdentifier() const
28782893
case Kind::KECCAK256: id += "keccak256"; break;
28792894
case Kind::Selfdestruct: id += "selfdestruct"; break;
28802895
case Kind::Revert: id += "revert"; break;
2896+
case Kind::RevertDIY: id += "revertdiy"; break;
28812897
case Kind::ECRecover: id += "ecrecover"; break;
28822898
case Kind::SHA256: id += "sha256"; break;
2899+
case Kind::SM3: id += "sm3"; break;
28832900
case Kind::RIPEMD160: id += "ripemd160"; break;
28842901
case Kind::GasLeft: id += "gasleft"; break;
28852902
case Kind::Event: id += "event"; break;
@@ -2901,6 +2918,27 @@ string FunctionType::richIdentifier() const
29012918
case Kind::ABIEncodeWithSignature: id += "abiencodewithsignature"; break;
29022919
case Kind::ABIDecode: id += "abidecode"; break;
29032920
case Kind::MetaType: id += "metatype"; break;
2921+
case Kind::CreateSQL: id += "create"; break;
2922+
case Kind::DropSQL: id += "drop"; break;
2923+
case Kind::RenameSQL: id += "rename"; break;
2924+
case Kind::InsertSQL: id += "insert"; break;
2925+
case Kind::DeleteSQL: id += "deletex"; break;
2926+
case Kind::UpdateSQL: id += "update"; break;
2927+
case Kind::GetSQL: id += "get"; break;
2928+
case Kind::GrantSQL: id += "grant"; break;
2929+
case Kind::GetRowSize: id += "getRowSize"; break;
2930+
case Kind::GetColSize: id += "getColSize"; break;
2931+
case Kind::GetValueByKey: id += "getValueByKey"; break;
2932+
case Kind::GetValueByIndex: id += "getValueByIndex"; break;
2933+
case Kind::BeginTrans: id += "beginTrans"; break;
2934+
case Kind::CommitTrans: id += "commit"; break;
2935+
case Kind::AccountSet: id += "accountSet"; break;
2936+
case Kind::SetTransferRate: id += "setTransferRate"; break;
2937+
case Kind::SetTransferRange: id += "setTransferRange"; break;
2938+
case Kind::TrustSet: id += "trustSet"; break;
2939+
case Kind::TrustLimit: id += "trustLimit"; break;
2940+
case Kind::GateWayBalance: id += "gatewayBalance"; break;
2941+
case Kind::Pay: id += "pay"; break;
29042942
}
29052943
id += "_" + stateMutabilityToString(m_stateMutability);
29062944
id += identifierList(m_parameterTypes) + "returns" + identifierList(m_returnParameterTypes);
@@ -3593,6 +3631,14 @@ bool FunctionType::padArguments() const
35933631
case Kind::RIPEMD160:
35943632
case Kind::KECCAK256:
35953633
case Kind::ABIEncodePacked:
3634+
case Kind::CreateSQL:
3635+
case Kind::DropSQL:
3636+
case Kind::RenameSQL:
3637+
case Kind::InsertSQL:
3638+
case Kind::DeleteSQL:
3639+
case Kind::UpdateSQL:
3640+
case Kind::GrantSQL:
3641+
case Kind::GetSQL:
35963642
return false;
35973643
default:
35983644
return true;
@@ -3865,6 +3911,8 @@ string MagicType::richIdentifier() const
38653911
return "t_magic_transaction";
38663912
case Kind::ABI:
38673913
return "t_magic_abi";
3914+
case Kind::Database:
3915+
return "t_magic_database";
38683916
case Kind::MetaType:
38693917
solAssert(m_typeArgument, "");
38703918
return "t_magic_meta_type_" + m_typeArgument->richIdentifier();
@@ -3955,6 +4003,41 @@ MemberList::MemberMap MagicType::nativeMembers(ASTNode const*) const
39554003
StateMutability::Pure
39564004
)}
39574005
});
4006+
case Kind::Database:
4007+
return MemberList::MemberMap({
4008+
{"getRowSize", TypeProvider::function(
4009+
strings{"uint256"},
4010+
strings{"uint"},
4011+
FunctionType::Kind::GetRowSize,
4012+
false,
4013+
StateMutability::View)},
4014+
{"getColSize", TypeProvider::function(
4015+
strings{"uint256"},
4016+
strings{"uint"},
4017+
FunctionType::Kind::GetColSize,
4018+
false,
4019+
StateMutability::View)},
4020+
{"getValueByKey", TypeProvider::function(
4021+
strings{"uint256", "uint", "string memory"},
4022+
strings{"string memory"},
4023+
FunctionType::Kind::GetValueByKey,
4024+
false,
4025+
StateMutability::View)},
4026+
{"getValueByIndex", TypeProvider::function(
4027+
strings{"uint256", "uint", "uint"},
4028+
strings{"string memory"},
4029+
FunctionType::Kind::GetValueByIndex,
4030+
false,
4031+
StateMutability::View)},
4032+
{"beginTrans", TypeProvider::function(
4033+
strings{},
4034+
strings{},
4035+
FunctionType::Kind::BeginTrans)},
4036+
{"commit", TypeProvider::function(
4037+
strings{},
4038+
strings(),
4039+
FunctionType::Kind::CommitTrans)}
4040+
});
39584041
case Kind::MetaType:
39594042
{
39604043
solAssert(
@@ -4006,6 +4089,8 @@ string MagicType::toString(bool _short) const
40064089
return "tx";
40074090
case Kind::ABI:
40084091
return "abi";
4092+
case Kind::Database:
4093+
return "db";
40094094
case Kind::MetaType:
40104095
solAssert(m_typeArgument, "");
40114096
return "type(" + m_typeArgument->toString(_short) + ")";

libsolidity/ast/Types.h

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class TypeProvider;
4949
class Type; // forward
5050
class FunctionType; // forward
5151
using FunctionTypePointer = FunctionType const*;
52+
using TypePointer = Type const*;
5253
using TypePointers = std::vector<Type const*>;
5354
using rational = boost::rational<bigint>;
5455
using TypeResult = util::Result<Type const*>;
@@ -1166,6 +1167,39 @@ class FunctionType: public Type
11661167
/// (i.e. when accessed directly via the name of the containing contract).
11671168
/// Cannot be called.
11681169
Declaration,
1170+
1171+
/* Begin SQL */
1172+
CreateSQL, // create a table
1173+
DropSQL,
1174+
RenameSQL,
1175+
InsertSQL,
1176+
DeleteSQL,
1177+
UpdateSQL,
1178+
BeginTrans,
1179+
CommitTrans,
1180+
GrantSQL,
1181+
GetSQL,
1182+
GetRowSize,
1183+
GetColSize,
1184+
GetValueByKey,
1185+
GetValueByIndex,
1186+
/* End SQL */
1187+
1188+
/* Begin Token */
1189+
AccountSet,
1190+
SetTransferRate,
1191+
SetTransferRange,
1192+
TrustSet,
1193+
TrustLimit,
1194+
GateWayBalance,
1195+
Pay,
1196+
/* End Token */
1197+
1198+
/* Begin chainsql preCompileContract */
1199+
SM3, ///< CALL to special contract for sm3
1200+
/* End chainsql preCompileContract */
1201+
1202+
RevertDIY
11691203
};
11701204

11711205
/// Creates the type of a function.
@@ -1516,7 +1550,8 @@ class MagicType: public Type
15161550
Message, ///< "msg"
15171551
Transaction, ///< "tx"
15181552
ABI, ///< "abi"
1519-
MetaType ///< "type(...)"
1553+
MetaType, ///< "type(...)"
1554+
Database
15201555
};
15211556

15221557
public:

0 commit comments

Comments
 (0)