mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
adding parser support for code keyword for data location
This commit is contained in:
parent
095363eff7
commit
7b1b1a0a84
@ -45,19 +45,19 @@ Solidity language without a compiler change.
|
||||
pragma solidity >=0.4.16 <0.9.0;
|
||||
|
||||
library GetCode {
|
||||
function at(address addr) public view returns (bytes memory code) {
|
||||
function at(address addr) public view returns (bytes memory codeObject) {
|
||||
assembly {
|
||||
// retrieve the size of the code, this needs assembly
|
||||
// retrieve the size of the codeObject, this needs assembly
|
||||
let size := extcodesize(addr)
|
||||
// allocate output byte array - this could also be done without assembly
|
||||
// by using code = new bytes(size)
|
||||
code := mload(0x40)
|
||||
// by using codeObject = new bytes(size)
|
||||
codeObject := mload(0x40)
|
||||
// new "memory end" including padding
|
||||
mstore(0x40, add(code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
|
||||
mstore(0x40, add(codeObject, and(add(add(size, 0x20), 0x1f), not(0x1f))))
|
||||
// store length in memory
|
||||
mstore(code, size)
|
||||
// actually retrieve the code, this needs assembly
|
||||
extcodecopy(addr, add(code, 0x20), 0, size)
|
||||
mstore(codeObject, size)
|
||||
// actually retrieve the codeObject, this needs assembly
|
||||
extcodecopy(addr, add(codeObject, 0x20), 0, size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ Bool: 'bool';
|
||||
Break: 'break';
|
||||
Bytes: 'bytes';
|
||||
Calldata: 'calldata';
|
||||
Code: 'code';
|
||||
Catch: 'catch';
|
||||
Constant: 'constant';
|
||||
Constructor: 'constructor';
|
||||
|
@ -336,7 +336,7 @@ locals [boolean visibilitySet = false, boolean mutabilitySet = false]
|
||||
* The declaration of a single variable.
|
||||
*/
|
||||
variableDeclaration: type=typeName location=dataLocation? name=identifier;
|
||||
dataLocation: Memory | Storage | Calldata;
|
||||
dataLocation: Memory | Storage | Calldata | Code;
|
||||
|
||||
/**
|
||||
* Complex expression.
|
||||
@ -348,7 +348,7 @@ dataLocation: Memory | Storage | Calldata;
|
||||
expression:
|
||||
expression LBrack index=expression? RBrack # IndexAccess
|
||||
| expression LBrack start=expression? Colon end=expression? RBrack # IndexRangeAccess
|
||||
| expression Period (identifier | Address) # MemberAccess
|
||||
| expression Period (identifier | Address | Code) # MemberAccess
|
||||
| expression LBrace (namedArgument (Comma namedArgument)*)? RBrace # FunctionCallOptions
|
||||
| expression callArgumentList # FunctionCall
|
||||
| Payable callArgumentList # PayableConversion
|
||||
|
@ -185,6 +185,7 @@ namespace solidity::langutil
|
||||
K(Returns, "returns", 0) \
|
||||
K(Storage, "storage", 0) \
|
||||
K(CallData, "calldata", 0) \
|
||||
K(Code, "code", 0) \
|
||||
K(Struct, "struct", 0) \
|
||||
K(Throw, "throw", 0) \
|
||||
K(Try, "try", 0) \
|
||||
@ -307,7 +308,7 @@ namespace TokenTraits
|
||||
constexpr bool isShiftOp(Token op) { return (Token::SHL <= op) && (op <= Token::SHR); }
|
||||
constexpr bool isVariableVisibilitySpecifier(Token op) { return op == Token::Public || op == Token::Private || op == Token::Internal; }
|
||||
constexpr bool isVisibilitySpecifier(Token op) { return isVariableVisibilitySpecifier(op) || op == Token::External; }
|
||||
constexpr bool isLocationSpecifier(Token op) { return op == Token::Memory || op == Token::Storage || op == Token::CallData; }
|
||||
constexpr bool isLocationSpecifier(Token op) { return op == Token::Memory || op == Token::Storage || op == Token::CallData || op == Token::Code; }
|
||||
|
||||
constexpr bool isStateMutabilitySpecifier(Token op)
|
||||
{
|
||||
@ -322,7 +323,7 @@ namespace TokenTraits
|
||||
{
|
||||
return tok == Token::Function || tok == Token::Let || tok == Token::If || tok == Token::Switch || tok == Token::Case ||
|
||||
tok == Token::Default || tok == Token::For || tok == Token::Break || tok == Token::Continue || tok == Token::Leave ||
|
||||
tok == Token::TrueLiteral || tok == Token::FalseLiteral || tok == Token::HexStringLiteral || tok == Token::Hex;
|
||||
tok == Token::TrueLiteral || tok == Token::FalseLiteral || tok == Token::HexStringLiteral || tok == Token::Hex || tok == Token::Code;
|
||||
}
|
||||
|
||||
bool isYulKeyword(std::string const& _literal);
|
||||
|
@ -364,6 +364,7 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
|
||||
case Location::Memory: return "\"memory\"";
|
||||
case Location::Storage: return "\"storage\"";
|
||||
case Location::CallData: return "\"calldata\"";
|
||||
case Location::Code: return "\"code\"";
|
||||
case Location::Unspecified: return "none";
|
||||
}
|
||||
return {};
|
||||
@ -433,6 +434,9 @@ void DeclarationTypeChecker::endVisit(VariableDeclaration const& _variable)
|
||||
case Location::CallData:
|
||||
typeLoc = DataLocation::CallData;
|
||||
break;
|
||||
case Location::Code:
|
||||
typeLoc = DataLocation::Code;
|
||||
break;
|
||||
case Location::Unspecified:
|
||||
solAssert(!_variable.hasReferenceOrMappingType(), "Data location not properly set.");
|
||||
}
|
||||
|
@ -496,3 +496,11 @@ bool SyntaxChecker::visit(StructDefinition const& _struct)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SyntaxChecker::visit(VariableDeclaration const& _node)
|
||||
{
|
||||
if (_node.referenceLocation() == VariableDeclaration::Location::Code)
|
||||
m_errorReporter.syntaxError(2397_error, _node.location(), "Usage of \"code\" as a data location is not yet supported.");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -97,6 +97,8 @@ private:
|
||||
bool visit(StructDefinition const& _struct) override;
|
||||
bool visit(Literal const& _literal) override;
|
||||
|
||||
bool visit(VariableDeclaration const& _node) override;
|
||||
|
||||
langutil::ErrorReporter& m_errorReporter;
|
||||
|
||||
bool m_useYulOptimizer = false;
|
||||
|
@ -1007,7 +1007,7 @@ private:
|
||||
class VariableDeclaration: public Declaration, public StructurallyDocumented
|
||||
{
|
||||
public:
|
||||
enum Location { Unspecified, Storage, Memory, CallData };
|
||||
enum Location { Unspecified, Storage, Memory, CallData, Code};
|
||||
enum class Mutability { Mutable, Immutable, Constant };
|
||||
static std::string mutabilityToString(Mutability _mutability)
|
||||
{
|
||||
|
@ -1006,6 +1006,8 @@ string ASTJsonExporter::location(VariableDeclaration::Location _location)
|
||||
return "memory";
|
||||
case VariableDeclaration::Location::CallData:
|
||||
return "calldata";
|
||||
case VariableDeclaration::Location::Code:
|
||||
return "code";
|
||||
}
|
||||
// To make the compiler happy
|
||||
return {};
|
||||
|
@ -34,6 +34,7 @@ InaccessibleDynamicType const TypeProvider::m_inaccessibleDynamic{};
|
||||
unique_ptr<ArrayType> TypeProvider::m_bytesStorage;
|
||||
unique_ptr<ArrayType> TypeProvider::m_bytesMemory;
|
||||
unique_ptr<ArrayType> TypeProvider::m_bytesCalldata;
|
||||
unique_ptr<ArrayType> TypeProvider::m_bytesCode;
|
||||
unique_ptr<ArrayType> TypeProvider::m_stringStorage;
|
||||
unique_ptr<ArrayType> TypeProvider::m_stringMemory;
|
||||
|
||||
@ -181,6 +182,7 @@ void TypeProvider::reset()
|
||||
clearCache(m_bytesStorage);
|
||||
clearCache(m_bytesMemory);
|
||||
clearCache(m_bytesCalldata);
|
||||
clearCache(m_bytesCode);
|
||||
clearCache(m_stringStorage);
|
||||
clearCache(m_stringMemory);
|
||||
clearCache(m_emptyTuple);
|
||||
@ -281,6 +283,8 @@ Type const* TypeProvider::fromElementaryTypeName(string const& _name)
|
||||
location = DataLocation::CallData;
|
||||
else if (nameParts[1] == "memory")
|
||||
location = DataLocation::Memory;
|
||||
else if (nameParts[1] == "code")
|
||||
location = DataLocation::Code;
|
||||
else
|
||||
solAssert(false, "Unknown data location: " + nameParts[1]);
|
||||
}
|
||||
@ -325,6 +329,15 @@ ArrayType const* TypeProvider::bytesCalldata()
|
||||
return m_bytesCalldata.get();
|
||||
}
|
||||
|
||||
ArrayType const* TypeProvider::bytesCode()
|
||||
{
|
||||
solUnimplemented("\"code\" as data location not yet implemented.");
|
||||
// TODO :: Remove this Assert when implementing DataLocation::Code
|
||||
if (!m_bytesCode)
|
||||
m_bytesCode = make_unique<ArrayType>(DataLocation::Code, false);
|
||||
return m_bytesCode.get();
|
||||
}
|
||||
|
||||
ArrayType const* TypeProvider::stringStorage()
|
||||
{
|
||||
if (!m_stringStorage)
|
||||
|
@ -57,7 +57,7 @@ public:
|
||||
static Type const* fromElementaryTypeName(ElementaryTypeNameToken const& _type, std::optional<StateMutability> _stateMutability = {});
|
||||
|
||||
/// Converts a given elementary type name with optional data location
|
||||
/// suffix " storage", " calldata" or " memory" to a type pointer. If suffix not given, defaults to " storage".
|
||||
/// suffix " storage", " calldata", "code" or " memory" to a type pointer. If suffix not given, defaults to " storage".
|
||||
static Type const* fromElementaryTypeName(std::string const& _name);
|
||||
|
||||
/// @returns boolean type.
|
||||
@ -69,6 +69,7 @@ public:
|
||||
static ArrayType const* bytesStorage();
|
||||
static ArrayType const* bytesMemory();
|
||||
static ArrayType const* bytesCalldata();
|
||||
static ArrayType const* bytesCode();
|
||||
static ArrayType const* stringStorage();
|
||||
static ArrayType const* stringMemory();
|
||||
|
||||
@ -217,6 +218,7 @@ private:
|
||||
static std::unique_ptr<ArrayType> m_bytesStorage;
|
||||
static std::unique_ptr<ArrayType> m_bytesMemory;
|
||||
static std::unique_ptr<ArrayType> m_bytesCalldata;
|
||||
static std::unique_ptr<ArrayType> m_bytesCode;
|
||||
static std::unique_ptr<ArrayType> m_stringStorage;
|
||||
static std::unique_ptr<ArrayType> m_stringMemory;
|
||||
|
||||
|
@ -1505,6 +1505,9 @@ TypeResult ReferenceType::unaryOperatorResult(Token _operator) const
|
||||
return TypeProvider::emptyTuple();
|
||||
case DataLocation::Storage:
|
||||
return isPointer() ? nullptr : TypeProvider::emptyTuple();
|
||||
case DataLocation::Code:
|
||||
solUnimplemented("\"code\" as data location is not yet implemented");
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@ -1532,6 +1535,8 @@ string ReferenceType::stringForReferencePart() const
|
||||
return "calldata";
|
||||
case DataLocation::Memory:
|
||||
return "memory";
|
||||
case DataLocation::Code:
|
||||
return "code";
|
||||
}
|
||||
solAssert(false, "");
|
||||
return "";
|
||||
@ -1551,6 +1556,9 @@ string ReferenceType::identifierLocationSuffix() const
|
||||
case DataLocation::CallData:
|
||||
id += "_calldata";
|
||||
break;
|
||||
case DataLocation::Code:
|
||||
id += "_code";
|
||||
break;
|
||||
}
|
||||
if (isPointer())
|
||||
id += "_ptr";
|
||||
@ -1709,6 +1717,9 @@ BoolResult ArrayType::validForLocation(DataLocation _loc) const
|
||||
if (storageSizeUpperBound() >= bigint(1) << 256)
|
||||
return BoolResult::err("Type too large for storage.");
|
||||
break;
|
||||
case DataLocation::Code:
|
||||
solUnimplemented("\"code\" as a data location is not yet implemented");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1789,6 +1800,9 @@ vector<tuple<string, Type const*>> ArrayType::makeStackItems() const
|
||||
case DataLocation::Storage:
|
||||
// byte offset inside storage value is omitted
|
||||
return {std::make_tuple("slot", TypeProvider::uint256())};
|
||||
case DataLocation::Code:
|
||||
solUnimplemented("\"code\" as a data location is not yet implemented");
|
||||
break;
|
||||
}
|
||||
solAssert(false, "");
|
||||
}
|
||||
@ -2529,6 +2543,9 @@ vector<tuple<string, Type const*>> StructType::makeStackItems() const
|
||||
return {std::make_tuple("mpos", TypeProvider::uint256())};
|
||||
case DataLocation::Storage:
|
||||
return {std::make_tuple("slot", TypeProvider::uint256())};
|
||||
case DataLocation::Code:
|
||||
solUnimplemented("\"code\" as a data location is not yet implemented");
|
||||
break;
|
||||
}
|
||||
solAssert(false, "");
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ inline rational makeRational(bigint const& _numerator, bigint const& _denominato
|
||||
return rational(_numerator, _denominator);
|
||||
}
|
||||
|
||||
enum class DataLocation { Storage, CallData, Memory };
|
||||
enum class DataLocation { Storage, CallData, Memory, Code };
|
||||
|
||||
|
||||
/**
|
||||
|
@ -1022,6 +1022,9 @@ void ArrayUtils::retrieveLength(ArrayType const& _arrayType, unsigned _stackDept
|
||||
if (_arrayType.isByteArrayOrString())
|
||||
m_context.callYulFunction(m_context.utilFunctions().extractByteArrayLengthFunction(), 1, 1);
|
||||
break;
|
||||
case DataLocation::Code:
|
||||
solUnimplemented("\"code\" as data location is not yet implemented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1048,6 +1051,9 @@ void ArrayUtils::accessIndex(ArrayType const& _arrayType, bool _doBoundsCheck, b
|
||||
// stack: <base_ref> <index>
|
||||
switch (location)
|
||||
{
|
||||
case DataLocation::Code:
|
||||
solUnimplemented("\"code\" as data location is not yet implemented");
|
||||
break;
|
||||
case DataLocation::Memory:
|
||||
// stack: <base_ref> <index>
|
||||
if (!_arrayType.isByteArrayOrString())
|
||||
|
@ -1111,6 +1111,9 @@ void CompilerUtils::convertType(
|
||||
"Invalid conversion to calldata type."
|
||||
);
|
||||
break;
|
||||
case DataLocation::Code:
|
||||
solUnimplemented("\"code\" as data location is not yet implemented");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1231,12 +1234,18 @@ void CompilerUtils::convertType(
|
||||
case DataLocation::Memory:
|
||||
// nothing to do
|
||||
break;
|
||||
case DataLocation::Code:
|
||||
solUnimplemented("\"code\" as data location is not yet implemented");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DataLocation::CallData:
|
||||
solAssert(_typeOnStack == _targetType);
|
||||
// nothing to do
|
||||
break;
|
||||
case DataLocation::Code:
|
||||
solUnimplemented("\"code\" as data location is not yet implemented");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1978,6 +1978,9 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess)
|
||||
case DataLocation::Memory:
|
||||
m_context << Instruction::MLOAD;
|
||||
break;
|
||||
case DataLocation::Code:
|
||||
solUnimplemented("\"code\" as data location is not yet implemented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (member == "push" || member == "pop")
|
||||
@ -2124,6 +2127,9 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
||||
case DataLocation::CallData:
|
||||
ArrayUtils(m_context).accessCallDataArrayElement(arrayType);
|
||||
break;
|
||||
case DataLocation::Code:
|
||||
solUnimplemented("\"code\" as data location is not yet implemented");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -2467,6 +2467,9 @@ string YulUtilFunctions::nextArrayElementFunction(ArrayType const& _type)
|
||||
templ("advance", toCompactHexWithPrefix(size));
|
||||
break;
|
||||
}
|
||||
case DataLocation::Code:
|
||||
solUnimplemented("\"code\" as data location is not yet implemented");
|
||||
break;
|
||||
}
|
||||
return templ.render();
|
||||
});
|
||||
|
@ -2282,6 +2282,9 @@ void IRGeneratorForStatements::endVisit(IndexAccess const& _indexAccess)
|
||||
define(_indexAccess) << indexAccessFunctionCall << "\n";
|
||||
break;
|
||||
}
|
||||
case DataLocation::Code:
|
||||
solUnimplemented("\"code\" as data location is not yet implemented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (baseType.category() == Type::Category::FixedBytes)
|
||||
|
@ -812,6 +812,9 @@ ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(
|
||||
case Token::CallData:
|
||||
location = VariableDeclaration::Location::CallData;
|
||||
break;
|
||||
case Token::Code:
|
||||
location = VariableDeclaration::Location::Code;
|
||||
break;
|
||||
default:
|
||||
solAssert(false, "Unknown data location.");
|
||||
}
|
||||
@ -1025,12 +1028,12 @@ ASTPointer<Identifier> Parser::parseIdentifier()
|
||||
return nodeFactory.createNode<Identifier>(expectIdentifierToken());
|
||||
}
|
||||
|
||||
ASTPointer<Identifier> Parser::parseIdentifierOrAddress()
|
||||
ASTPointer<Identifier> Parser::parseIdentifierOrAddressOrCode()
|
||||
{
|
||||
RecursionGuard recursionGuard(*this);
|
||||
ASTNodeFactory nodeFactory(*this);
|
||||
nodeFactory.markEndPosition();
|
||||
return nodeFactory.createNode<Identifier>(expectIdentifierTokenOrAddress());
|
||||
return nodeFactory.createNode<Identifier>(expectIdentifierTokenOrAddressOrCode());
|
||||
}
|
||||
|
||||
ASTPointer<UserDefinedTypeName> Parser::parseUserDefinedTypeName()
|
||||
@ -1905,7 +1908,7 @@ ASTPointer<Expression> Parser::parseLeftHandSideExpression(
|
||||
advance();
|
||||
nodeFactory.markEndPosition();
|
||||
SourceLocation memberLocation = currentLocation();
|
||||
ASTPointer<ASTString> memberName = expectIdentifierTokenOrAddress();
|
||||
ASTPointer<ASTString> memberName = expectIdentifierTokenOrAddressOrCode();
|
||||
expression = nodeFactory.createNode<MemberAccess>(expression, std::move(memberName), std::move(memberLocation));
|
||||
break;
|
||||
}
|
||||
@ -2252,7 +2255,7 @@ Parser::IndexAccessedPath Parser::parseIndexAccessedPath()
|
||||
while (m_scanner->currentToken() == Token::Period)
|
||||
{
|
||||
advance();
|
||||
iap.path.push_back(parseIdentifierOrAddress());
|
||||
iap.path.push_back(parseIdentifierOrAddressOrCode());
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -2382,7 +2385,7 @@ ASTPointer<ASTString> Parser::expectIdentifierToken()
|
||||
return getLiteralAndAdvance();
|
||||
}
|
||||
|
||||
ASTPointer<ASTString> Parser::expectIdentifierTokenOrAddress()
|
||||
ASTPointer<ASTString> Parser::expectIdentifierTokenOrAddressOrCode()
|
||||
{
|
||||
ASTPointer<ASTString> result;
|
||||
if (m_scanner->currentToken() == Token::Address)
|
||||
@ -2390,6 +2393,11 @@ ASTPointer<ASTString> Parser::expectIdentifierTokenOrAddress()
|
||||
result = make_shared<ASTString>("address");
|
||||
advance();
|
||||
}
|
||||
else if (m_scanner->currentToken() == Token::Code)
|
||||
{
|
||||
result = make_shared<ASTString>("code");
|
||||
advance();
|
||||
}
|
||||
else
|
||||
{
|
||||
expectToken(Token::Identifier, false /* do not advance */);
|
||||
|
@ -115,7 +115,7 @@ private:
|
||||
ASTPointer<UsingForDirective> parseUsingDirective();
|
||||
ASTPointer<ModifierInvocation> parseModifierInvocation();
|
||||
ASTPointer<Identifier> parseIdentifier();
|
||||
ASTPointer<Identifier> parseIdentifierOrAddress();
|
||||
ASTPointer<Identifier> parseIdentifierOrAddressOrCode();
|
||||
ASTPointer<UserDefinedTypeName> parseUserDefinedTypeName();
|
||||
ASTPointer<IdentifierPath> parseIdentifierPath();
|
||||
ASTPointer<TypeName> parseTypeNameSuffix(ASTPointer<TypeName> type, ASTNodeFactory& nodeFactory);
|
||||
@ -214,7 +214,7 @@ private:
|
||||
ASTPointer<Expression> expressionFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices);
|
||||
|
||||
ASTPointer<ASTString> expectIdentifierToken();
|
||||
ASTPointer<ASTString> expectIdentifierTokenOrAddress();
|
||||
ASTPointer<ASTString> expectIdentifierTokenOrAddressOrCode();
|
||||
ASTPointer<ASTString> getLiteralAndAdvance();
|
||||
///@}
|
||||
|
||||
|
@ -109,10 +109,7 @@ shared_ptr<Object> ObjectParser::parseObject(Object* _containingObject)
|
||||
|
||||
shared_ptr<Block> ObjectParser::parseCode(optional<SourceNameMap> _sourceNames)
|
||||
{
|
||||
if (currentToken() != Token::Identifier || currentLiteral() != "code")
|
||||
fatalParserError(4846_error, "Expected keyword \"code\".");
|
||||
advance();
|
||||
|
||||
expectToken(Token::Code);
|
||||
return parseBlock(std::move(_sourceNames));
|
||||
}
|
||||
|
||||
|
@ -3,18 +3,18 @@ contract C {
|
||||
require(b, "failure");
|
||||
return x - y;
|
||||
}
|
||||
function onlyPanic(bool b, uint x, uint y) public returns (uint r, uint code) {
|
||||
function onlyPanic(bool b, uint x, uint y) public returns (uint r, uint codeObject) {
|
||||
try this.uf(b, x, y) returns (uint b) {
|
||||
r = b;
|
||||
} catch Panic(uint c) {
|
||||
code = c;
|
||||
codeObject = c;
|
||||
}
|
||||
}
|
||||
function panicAndError(bool b, uint x, uint y) public returns (uint r, uint code, string memory msg_) {
|
||||
function panicAndError(bool b, uint x, uint y) public returns (uint r, uint codeObject, string memory msg_) {
|
||||
try this.uf(b, x, y) returns (uint b) {
|
||||
r = b;
|
||||
} catch Panic(uint c) {
|
||||
code = c;
|
||||
codeObject = c;
|
||||
} catch Error(string memory _errmsg) {
|
||||
msg_ = _errmsg;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Test to see if type.code.length does extcodesize(type) only when type is an address.
|
||||
struct S {
|
||||
bytes32 code;
|
||||
bytes32 codeObject;
|
||||
bytes32 another;
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ contract C {
|
||||
S s;
|
||||
|
||||
function f() public returns (uint, uint, bool) {
|
||||
return (s.code.length, s.another.length, address(this).code.length > 50);
|
||||
return (s.codeObject.length, s.another.length, address(this).code.length > 50);
|
||||
}
|
||||
}
|
||||
// ====
|
||||
|
@ -0,0 +1,18 @@
|
||||
contract X {
|
||||
function bar(string code input) external pure {
|
||||
string code test = input;
|
||||
}
|
||||
function g(string code) external {}
|
||||
function i(string code str) external {
|
||||
this.g(str);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// SyntaxError 2397: (30-47): Usage of "code" as a data location is not yet supported.
|
||||
// SyntaxError 2397: (73-89): Usage of "code" as a data location is not yet supported.
|
||||
// SyntaxError 2397: (120-131): Usage of "code" as a data location is not yet supported.
|
||||
// SyntaxError 2397: (160-175): Usage of "code" as a data location is not yet supported.
|
||||
// TypeError 6651: (30-47): Data location must be "memory" or "calldata" for parameter in external function, but "code" was given.
|
||||
// TypeError 6651: (73-89): Data location must be "storage", "memory" or "calldata" for variable, but "code" was given.
|
||||
// TypeError 6651: (120-131): Data location must be "memory" or "calldata" for parameter in external function, but "code" was given.
|
||||
// TypeError 6651: (160-175): Data location must be "memory" or "calldata" for parameter in external function, but "code" was given.
|
@ -0,0 +1,17 @@
|
||||
interface testInterface {
|
||||
function C(function (string code) external) external;
|
||||
function D(string code) external;
|
||||
}
|
||||
|
||||
contract testContract {
|
||||
function k(string code str) external pure {
|
||||
abi.encodeCall(testInterface.D, (str));
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// SyntaxError 2397: (51-62): Usage of "code" as a data location is not yet supported.
|
||||
// SyntaxError 2397: (99-110): Usage of "code" as a data location is not yet supported.
|
||||
// SyntaxError 2397: (164-179): Usage of "code" as a data location is not yet supported.
|
||||
// TypeError 6651: (51-62): Data location must be "memory" or "calldata" for parameter in function, but "code" was given.
|
||||
// TypeError 6651: (99-110): Data location must be "memory" or "calldata" for parameter in external function, but "code" was given.
|
||||
// TypeError 6651: (164-179): Data location must be "memory" or "calldata" for parameter in external function, but "code" was given.
|
@ -0,0 +1,18 @@
|
||||
contract X {
|
||||
function foo(string code input) internal pure {
|
||||
string code test = input;
|
||||
}
|
||||
function g(string code) internal {}
|
||||
function i(string code str) internal {
|
||||
g(str);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// SyntaxError 2397: (30-47): Usage of "code" as a data location is not yet supported.
|
||||
// SyntaxError 2397: (73-89): Usage of "code" as a data location is not yet supported.
|
||||
// SyntaxError 2397: (120-131): Usage of "code" as a data location is not yet supported.
|
||||
// SyntaxError 2397: (160-175): Usage of "code" as a data location is not yet supported.
|
||||
// TypeError 6651: (30-47): Data location must be "storage", "memory" or "calldata" for parameter in function, but "code" was given.
|
||||
// TypeError 6651: (73-89): Data location must be "storage", "memory" or "calldata" for variable, but "code" was given.
|
||||
// TypeError 6651: (120-131): Data location must be "storage", "memory" or "calldata" for parameter in function, but "code" was given.
|
||||
// TypeError 6651: (160-175): Data location must be "storage", "memory" or "calldata" for parameter in function, but "code" was given.
|
@ -0,0 +1,8 @@
|
||||
contract X {
|
||||
function codeAsBytes() external {
|
||||
bytes32 calldata code;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// ParserError 3548: (76-80): Location already specified.
|
||||
// ParserError 2314: (80-81): Expected identifier but got ';'
|
@ -0,0 +1,10 @@
|
||||
contract X {
|
||||
function g(string calldata str) external {}
|
||||
|
||||
function foo(string calldata code) external {
|
||||
this.g(code);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// ParserError 3548: (95-99): Location already specified.
|
||||
// ParserError 6933: (127-131): Expected primary expression.
|
@ -0,0 +1,8 @@
|
||||
contract X {
|
||||
function codeAsString() external {
|
||||
uint32 calldata code;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// ParserError 3548: (76-80): Location already specified.
|
||||
// ParserError 2314: (80-81): Expected identifier but got ';'
|
@ -0,0 +1,8 @@
|
||||
contract X {
|
||||
function codeAsInt() external {
|
||||
string calldata code;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// ParserError 3548: (73-77): Location already specified.
|
||||
// ParserError 2314: (77-78): Expected identifier but got ';'
|
@ -0,0 +1,7 @@
|
||||
contract X {
|
||||
struct codeInStruct {
|
||||
string code;
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// ParserError 2314: (54-58): Expected identifier but got 'code'
|
@ -3,4 +3,4 @@ object "A" {
|
||||
code {}
|
||||
}
|
||||
// ----
|
||||
// ParserError 4846: (15-19): Expected keyword "code".
|
||||
// ParserError 2314: (15-19): Expected 'code' but got identifier
|
||||
|
@ -2,4 +2,4 @@ object "A" {
|
||||
data "tmp" ""
|
||||
}
|
||||
// ----
|
||||
// ParserError 4846: (15-19): Expected keyword "code".
|
||||
// ParserError 2314: (15-19): Expected 'code' but got identifier
|
||||
|
@ -1,4 +1,4 @@
|
||||
object "A" {
|
||||
}
|
||||
// ----
|
||||
// ParserError 4846: (13-14): Expected keyword "code".
|
||||
// ParserError 2314: (13-14): Expected 'code' but got '}'
|
||||
|
@ -2,4 +2,4 @@ object "" {
|
||||
}
|
||||
// ----
|
||||
// ParserError 3287: (7-9): Object name cannot be empty.
|
||||
// ParserError 4846: (12-13): Expected keyword "code".
|
||||
// ParserError 2314: (12-13): Expected 'code' but got '}'
|
||||
|
@ -6,4 +6,4 @@ object "A" {
|
||||
code {}
|
||||
}
|
||||
// ----
|
||||
// ParserError 4846: (15-21): Expected keyword "code".
|
||||
// ParserError 2314: (15-21): Expected 'code' but got identifier
|
||||
|
Loading…
Reference in New Issue
Block a user