From 7b1b1a0a84e75da629d954a31950df8a2d7079a3 Mon Sep 17 00:00:00 2001 From: nishant-sachdeva Date: Tue, 30 Aug 2022 19:38:12 +0530 Subject: [PATCH] adding parser support for code keyword for data location --- docs/assembly.rst | 16 ++++++++-------- docs/grammar/SolidityLexer.g4 | 1 + docs/grammar/SolidityParser.g4 | 4 ++-- liblangutil/Token.h | 5 +++-- .../analysis/DeclarationTypeChecker.cpp | 4 ++++ libsolidity/analysis/SyntaxChecker.cpp | 8 ++++++++ libsolidity/analysis/SyntaxChecker.h | 2 ++ libsolidity/ast/AST.h | 2 +- libsolidity/ast/ASTJsonExporter.cpp | 2 ++ libsolidity/ast/TypeProvider.cpp | 13 +++++++++++++ libsolidity/ast/TypeProvider.h | 4 +++- libsolidity/ast/Types.cpp | 17 +++++++++++++++++ libsolidity/ast/Types.h | 2 +- libsolidity/codegen/ArrayUtils.cpp | 6 ++++++ libsolidity/codegen/CompilerUtils.cpp | 9 +++++++++ libsolidity/codegen/ExpressionCompiler.cpp | 6 ++++++ libsolidity/codegen/YulUtilFunctions.cpp | 3 +++ .../codegen/ir/IRGeneratorForStatements.cpp | 3 +++ libsolidity/parsing/Parser.cpp | 18 +++++++++++++----- libsolidity/parsing/Parser.h | 4 ++-- libyul/ObjectParser.cpp | 5 +---- .../semanticTests/tryCatch/panic.sol | 8 ++++---- .../various/code_length_contract_member.sol | 4 ++-- .../code_keyword_external_function_params.sol | 18 ++++++++++++++++++ .../code_keyword_function_params_interface.sol | 17 +++++++++++++++++ .../code_keyword_internal_function_params.sol | 18 ++++++++++++++++++ .../usage_as_bytes_variable.sol | 8 ++++++++ .../usage_as_function_param.sol | 10 ++++++++++ .../usage_as_int_variable.sol | 8 ++++++++ .../usage_as_string_varible.sol | 8 ++++++++ .../usage_as_struct_member.sol | 7 +++++++ .../yulSyntaxTests/objects/data_first.yul | 2 +- .../yulSyntaxTests/objects/empty_data.yul | 2 +- .../yulSyntaxTests/objects/empty_object.yul | 2 +- .../objects/empty_object_name.yul | 2 +- .../yulSyntaxTests/objects/subobject_first.yul | 2 +- 36 files changed, 213 insertions(+), 37 deletions(-) create mode 100644 test/libsolidity/syntaxTests/code/code_keyword_external_function_params.sol create mode 100644 test/libsolidity/syntaxTests/code/code_keyword_function_params_interface.sol create mode 100644 test/libsolidity/syntaxTests/code/code_keyword_internal_function_params.sol create mode 100644 test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_bytes_variable.sol create mode 100644 test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_function_param.sol create mode 100644 test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_int_variable.sol create mode 100644 test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_string_varible.sol create mode 100644 test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_struct_member.sol diff --git a/docs/assembly.rst b/docs/assembly.rst index b527ffbaf..6a3bc17dc 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -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) } } } diff --git a/docs/grammar/SolidityLexer.g4 b/docs/grammar/SolidityLexer.g4 index c47dc411c..36cd88bef 100644 --- a/docs/grammar/SolidityLexer.g4 +++ b/docs/grammar/SolidityLexer.g4 @@ -18,6 +18,7 @@ Bool: 'bool'; Break: 'break'; Bytes: 'bytes'; Calldata: 'calldata'; +Code: 'code'; Catch: 'catch'; Constant: 'constant'; Constructor: 'constructor'; diff --git a/docs/grammar/SolidityParser.g4 b/docs/grammar/SolidityParser.g4 index 92718b975..9ca2a65ff 100644 --- a/docs/grammar/SolidityParser.g4 +++ b/docs/grammar/SolidityParser.g4 @@ -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 diff --git a/liblangutil/Token.h b/liblangutil/Token.h index eb8015f4d..ea81705aa 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -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); diff --git a/libsolidity/analysis/DeclarationTypeChecker.cpp b/libsolidity/analysis/DeclarationTypeChecker.cpp index 54a7354e2..8330bc07d 100644 --- a/libsolidity/analysis/DeclarationTypeChecker.cpp +++ b/libsolidity/analysis/DeclarationTypeChecker.cpp @@ -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."); } diff --git a/libsolidity/analysis/SyntaxChecker.cpp b/libsolidity/analysis/SyntaxChecker.cpp index bdf138e20..bbf7d413f 100644 --- a/libsolidity/analysis/SyntaxChecker.cpp +++ b/libsolidity/analysis/SyntaxChecker.cpp @@ -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; +} diff --git a/libsolidity/analysis/SyntaxChecker.h b/libsolidity/analysis/SyntaxChecker.h index f221df09f..b63642f2f 100644 --- a/libsolidity/analysis/SyntaxChecker.h +++ b/libsolidity/analysis/SyntaxChecker.h @@ -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; diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index d6e41bb5f..a1b56179f 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -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) { diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index d308cd90c..68c424675 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -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 {}; diff --git a/libsolidity/ast/TypeProvider.cpp b/libsolidity/ast/TypeProvider.cpp index 91d1da4be..b46624ff8 100644 --- a/libsolidity/ast/TypeProvider.cpp +++ b/libsolidity/ast/TypeProvider.cpp @@ -34,6 +34,7 @@ InaccessibleDynamicType const TypeProvider::m_inaccessibleDynamic{}; unique_ptr TypeProvider::m_bytesStorage; unique_ptr TypeProvider::m_bytesMemory; unique_ptr TypeProvider::m_bytesCalldata; +unique_ptr TypeProvider::m_bytesCode; unique_ptr TypeProvider::m_stringStorage; unique_ptr 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(DataLocation::Code, false); + return m_bytesCode.get(); +} + ArrayType const* TypeProvider::stringStorage() { if (!m_stringStorage) diff --git a/libsolidity/ast/TypeProvider.h b/libsolidity/ast/TypeProvider.h index b089ff1ef..62ffc9f4e 100644 --- a/libsolidity/ast/TypeProvider.h +++ b/libsolidity/ast/TypeProvider.h @@ -57,7 +57,7 @@ public: static Type const* fromElementaryTypeName(ElementaryTypeNameToken const& _type, std::optional _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 m_bytesStorage; static std::unique_ptr m_bytesMemory; static std::unique_ptr m_bytesCalldata; + static std::unique_ptr m_bytesCode; static std::unique_ptr m_stringStorage; static std::unique_ptr m_stringMemory; diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index a1e447ca8..a0213d8f7 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -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> 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> 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, ""); } diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 553af6c7d..fc7b372ff 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -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 }; /** diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index 9b95463ba..752a11410 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -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: switch (location) { + case DataLocation::Code: + solUnimplemented("\"code\" as data location is not yet implemented"); + break; case DataLocation::Memory: // stack: if (!_arrayType.isByteArrayOrString()) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 32b1f1bba..16e98efdd 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -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; } diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 3ee824447..ab7fef8b5 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -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; } diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index b66189f05..61f2336e7 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -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(); }); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 679510cd6..17df7593b 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -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) diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index afa70609d..89994f7a0 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -812,6 +812,9 @@ ASTPointer 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 Parser::parseIdentifier() return nodeFactory.createNode(expectIdentifierToken()); } -ASTPointer Parser::parseIdentifierOrAddress() +ASTPointer Parser::parseIdentifierOrAddressOrCode() { RecursionGuard recursionGuard(*this); ASTNodeFactory nodeFactory(*this); nodeFactory.markEndPosition(); - return nodeFactory.createNode(expectIdentifierTokenOrAddress()); + return nodeFactory.createNode(expectIdentifierTokenOrAddressOrCode()); } ASTPointer Parser::parseUserDefinedTypeName() @@ -1905,7 +1908,7 @@ ASTPointer Parser::parseLeftHandSideExpression( advance(); nodeFactory.markEndPosition(); SourceLocation memberLocation = currentLocation(); - ASTPointer memberName = expectIdentifierTokenOrAddress(); + ASTPointer memberName = expectIdentifierTokenOrAddressOrCode(); expression = nodeFactory.createNode(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 Parser::expectIdentifierToken() return getLiteralAndAdvance(); } -ASTPointer Parser::expectIdentifierTokenOrAddress() +ASTPointer Parser::expectIdentifierTokenOrAddressOrCode() { ASTPointer result; if (m_scanner->currentToken() == Token::Address) @@ -2390,6 +2393,11 @@ ASTPointer Parser::expectIdentifierTokenOrAddress() result = make_shared("address"); advance(); } + else if (m_scanner->currentToken() == Token::Code) + { + result = make_shared("code"); + advance(); + } else { expectToken(Token::Identifier, false /* do not advance */); diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h index 7a9b41318..47da1fecd 100644 --- a/libsolidity/parsing/Parser.h +++ b/libsolidity/parsing/Parser.h @@ -115,7 +115,7 @@ private: ASTPointer parseUsingDirective(); ASTPointer parseModifierInvocation(); ASTPointer parseIdentifier(); - ASTPointer parseIdentifierOrAddress(); + ASTPointer parseIdentifierOrAddressOrCode(); ASTPointer parseUserDefinedTypeName(); ASTPointer parseIdentifierPath(); ASTPointer parseTypeNameSuffix(ASTPointer type, ASTNodeFactory& nodeFactory); @@ -214,7 +214,7 @@ private: ASTPointer expressionFromIndexAccessStructure(IndexAccessedPath const& _pathAndIndices); ASTPointer expectIdentifierToken(); - ASTPointer expectIdentifierTokenOrAddress(); + ASTPointer expectIdentifierTokenOrAddressOrCode(); ASTPointer getLiteralAndAdvance(); ///@} diff --git a/libyul/ObjectParser.cpp b/libyul/ObjectParser.cpp index 1a2d8b33a..5b118ab91 100644 --- a/libyul/ObjectParser.cpp +++ b/libyul/ObjectParser.cpp @@ -109,10 +109,7 @@ shared_ptr ObjectParser::parseObject(Object* _containingObject) shared_ptr ObjectParser::parseCode(optional _sourceNames) { - if (currentToken() != Token::Identifier || currentLiteral() != "code") - fatalParserError(4846_error, "Expected keyword \"code\"."); - advance(); - + expectToken(Token::Code); return parseBlock(std::move(_sourceNames)); } diff --git a/test/libsolidity/semanticTests/tryCatch/panic.sol b/test/libsolidity/semanticTests/tryCatch/panic.sol index eb7dd8c8b..185709836 100644 --- a/test/libsolidity/semanticTests/tryCatch/panic.sol +++ b/test/libsolidity/semanticTests/tryCatch/panic.sol @@ -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; } diff --git a/test/libsolidity/semanticTests/various/code_length_contract_member.sol b/test/libsolidity/semanticTests/various/code_length_contract_member.sol index 8486671ed..4db032e64 100644 --- a/test/libsolidity/semanticTests/various/code_length_contract_member.sol +++ b/test/libsolidity/semanticTests/various/code_length_contract_member.sol @@ -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); } } // ==== diff --git a/test/libsolidity/syntaxTests/code/code_keyword_external_function_params.sol b/test/libsolidity/syntaxTests/code/code_keyword_external_function_params.sol new file mode 100644 index 000000000..2ecfb5409 --- /dev/null +++ b/test/libsolidity/syntaxTests/code/code_keyword_external_function_params.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/code/code_keyword_function_params_interface.sol b/test/libsolidity/syntaxTests/code/code_keyword_function_params_interface.sol new file mode 100644 index 000000000..77f19252c --- /dev/null +++ b/test/libsolidity/syntaxTests/code/code_keyword_function_params_interface.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/code/code_keyword_internal_function_params.sol b/test/libsolidity/syntaxTests/code/code_keyword_internal_function_params.sol new file mode 100644 index 000000000..ba96c6e52 --- /dev/null +++ b/test/libsolidity/syntaxTests/code/code_keyword_internal_function_params.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_bytes_variable.sol b/test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_bytes_variable.sol new file mode 100644 index 000000000..d759322b4 --- /dev/null +++ b/test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_bytes_variable.sol @@ -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 ';' diff --git a/test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_function_param.sol b/test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_function_param.sol new file mode 100644 index 000000000..a5c82e865 --- /dev/null +++ b/test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_function_param.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_int_variable.sol b/test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_int_variable.sol new file mode 100644 index 000000000..b17c1e4ad --- /dev/null +++ b/test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_int_variable.sol @@ -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 ';' diff --git a/test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_string_varible.sol b/test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_string_varible.sol new file mode 100644 index 000000000..309e66b6d --- /dev/null +++ b/test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_string_varible.sol @@ -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 ';' diff --git a/test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_struct_member.sol b/test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_struct_member.sol new file mode 100644 index 000000000..0bd9a9286 --- /dev/null +++ b/test/libsolidity/syntaxTests/code/usage_as_identifier/usage_as_struct_member.sol @@ -0,0 +1,7 @@ +contract X { + struct codeInStruct { + string code; + } +} +// ---- +// ParserError 2314: (54-58): Expected identifier but got 'code' diff --git a/test/libyul/yulSyntaxTests/objects/data_first.yul b/test/libyul/yulSyntaxTests/objects/data_first.yul index 018674765..8b4cef1f9 100644 --- a/test/libyul/yulSyntaxTests/objects/data_first.yul +++ b/test/libyul/yulSyntaxTests/objects/data_first.yul @@ -3,4 +3,4 @@ object "A" { code {} } // ---- -// ParserError 4846: (15-19): Expected keyword "code". +// ParserError 2314: (15-19): Expected 'code' but got identifier diff --git a/test/libyul/yulSyntaxTests/objects/empty_data.yul b/test/libyul/yulSyntaxTests/objects/empty_data.yul index b2456a7ae..4365c41ef 100644 --- a/test/libyul/yulSyntaxTests/objects/empty_data.yul +++ b/test/libyul/yulSyntaxTests/objects/empty_data.yul @@ -2,4 +2,4 @@ object "A" { data "tmp" "" } // ---- -// ParserError 4846: (15-19): Expected keyword "code". +// ParserError 2314: (15-19): Expected 'code' but got identifier diff --git a/test/libyul/yulSyntaxTests/objects/empty_object.yul b/test/libyul/yulSyntaxTests/objects/empty_object.yul index cc9019e55..c83fb682e 100644 --- a/test/libyul/yulSyntaxTests/objects/empty_object.yul +++ b/test/libyul/yulSyntaxTests/objects/empty_object.yul @@ -1,4 +1,4 @@ object "A" { } // ---- -// ParserError 4846: (13-14): Expected keyword "code". +// ParserError 2314: (13-14): Expected 'code' but got '}' diff --git a/test/libyul/yulSyntaxTests/objects/empty_object_name.yul b/test/libyul/yulSyntaxTests/objects/empty_object_name.yul index 653bf4a0f..e8b39dfeb 100644 --- a/test/libyul/yulSyntaxTests/objects/empty_object_name.yul +++ b/test/libyul/yulSyntaxTests/objects/empty_object_name.yul @@ -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 '}' diff --git a/test/libyul/yulSyntaxTests/objects/subobject_first.yul b/test/libyul/yulSyntaxTests/objects/subobject_first.yul index 369e7180e..f426d93b7 100644 --- a/test/libyul/yulSyntaxTests/objects/subobject_first.yul +++ b/test/libyul/yulSyntaxTests/objects/subobject_first.yul @@ -6,4 +6,4 @@ object "A" { code {} } // ---- -// ParserError 4846: (15-21): Expected keyword "code". +// ParserError 2314: (15-21): Expected 'code' but got identifier