diff options
author | chriseth <chris@ethereum.org> | 2019-01-18 07:16:06 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-01-18 07:16:06 +0800 |
commit | 2ec997e697e306dd54165aad365406ee88c534cb (patch) | |
tree | 5e943e23d38e332de3eedd33be11f2cf9df5fd69 /libsolidity/ast | |
parent | 0711873a2f13d7b0f27e268fcd0a7683665f339d (diff) | |
parent | 2a92403690a4998ab097503231ac39f854b9c76c (diff) | |
download | dexon-solidity-2ec997e697e306dd54165aad365406ee88c534cb.tar dexon-solidity-2ec997e697e306dd54165aad365406ee88c534cb.tar.gz dexon-solidity-2ec997e697e306dd54165aad365406ee88c534cb.tar.bz2 dexon-solidity-2ec997e697e306dd54165aad365406ee88c534cb.tar.lz dexon-solidity-2ec997e697e306dd54165aad365406ee88c534cb.tar.xz dexon-solidity-2ec997e697e306dd54165aad365406ee88c534cb.tar.zst dexon-solidity-2ec997e697e306dd54165aad365406ee88c534cb.zip |
Merge pull request #5775 from ethereum/codeAccess
Provide access to code of contract types.
Diffstat (limited to 'libsolidity/ast')
-rw-r--r-- | libsolidity/ast/AST.cpp | 5 | ||||
-rw-r--r-- | libsolidity/ast/AST.h | 4 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 50 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 19 |
4 files changed, 69 insertions, 9 deletions
diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index f379d758..4cf8b1e8 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -138,6 +138,11 @@ bool ContractDefinition::constructorIsPublic() const return !f || f->isPublic(); } +bool ContractDefinition::canBeDeployed() const +{ + return constructorIsPublic() && annotation().unimplementedFunctions.empty(); +} + FunctionDefinition const* ContractDefinition::fallbackFunction() const { for (ContractDefinition const* contract: annotation().linearizedBaseContracts) diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 9ac065ea..cd986050 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -408,6 +408,10 @@ public: FunctionDefinition const* constructor() const; /// @returns true iff the constructor of this contract is public (or non-existing). bool constructorIsPublic() const; + /// @returns true iff the contract can be deployed, i.e. is not abstract and has a + /// public constructor. + /// Should only be called after the type checker has run. + bool canBeDeployed() const; /// Returns the fallback function or nullptr if no fallback function was specified. FunctionDefinition const* fallbackFunction() const; diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index cc978b4a..081c7fb6 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -2626,6 +2626,7 @@ string FunctionType::richIdentifier() const case Kind::ABIEncodeWithSelector: id += "abiencodewithselector"; break; case Kind::ABIEncodeWithSignature: id += "abiencodewithsignature"; break; case Kind::ABIDecode: id += "abidecode"; break; + case Kind::MetaType: id += "metatype"; break; } id += "_" + stateMutabilityToString(m_stateMutability); id += identifierList(m_parameterTypes) + "returns" + identifierList(m_returnParameterTypes); @@ -3037,7 +3038,8 @@ bool FunctionType::isPure() const m_kind == Kind::ABIEncodePacked || m_kind == Kind::ABIEncodeWithSelector || m_kind == Kind::ABIEncodeWithSignature || - m_kind == Kind::ABIDecode; + m_kind == Kind::ABIDecode || + m_kind == Kind::MetaType; } TypePointers FunctionType::parseElementaryTypeVector(strings const& _types) @@ -3305,6 +3307,14 @@ string ModuleType::toString(bool) const return string("module \"") + m_sourceUnit.annotation().path + string("\""); } +shared_ptr<MagicType> MagicType::metaType(TypePointer _type) +{ + solAssert(_type && _type->category() == Type::Category::Contract, "Only contracts supported for now."); + auto t = make_shared<MagicType>(Kind::MetaType); + t->m_typeArgument = std::move(_type); + return t; +} + string MagicType::richIdentifier() const { switch (m_kind) @@ -3317,6 +3327,9 @@ string MagicType::richIdentifier() const return "t_magic_transaction"; case Kind::ABI: return "t_magic_abi"; + case Kind::MetaType: + solAssert(m_typeArgument, ""); + return "t_magic_meta_type_" + m_typeArgument->richIdentifier(); } return ""; } @@ -3403,12 +3416,27 @@ MemberList::MemberMap MagicType::nativeMembers(ContractDefinition const*) const StateMutability::Pure )} }); - default: - solAssert(false, "Unknown kind of magic."); + case Kind::MetaType: + { + solAssert( + m_typeArgument && m_typeArgument->category() == Type::Category::Contract, + "Only contracts supported for now" + ); + ContractDefinition const& contract = dynamic_cast<ContractType const&>(*m_typeArgument).contractDefinition(); + if (contract.canBeDeployed()) + return MemberList::MemberMap({ + {"creationCode", std::make_shared<ArrayType>(DataLocation::Memory)}, + {"runtimeCode", std::make_shared<ArrayType>(DataLocation::Memory)} + }); + else + return {}; + } } + solAssert(false, "Unknown kind of magic."); + return {}; } -string MagicType::toString(bool) const +string MagicType::toString(bool _short) const { switch (m_kind) { @@ -3420,7 +3448,17 @@ string MagicType::toString(bool) const return "tx"; case Kind::ABI: return "abi"; - default: - solAssert(false, "Unknown kind of magic."); + case Kind::MetaType: + solAssert(m_typeArgument, ""); + return "type(" + m_typeArgument->toString(_short) + ")"; } + solAssert(false, "Unknown kind of magic."); + return {}; +} + +TypePointer MagicType::typeArgument() const +{ + solAssert(m_kind == Kind::MetaType, ""); + solAssert(m_typeArgument, ""); + return m_typeArgument; } diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index bee00661..53109de1 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -989,6 +989,7 @@ public: ABIEncodeWithSignature, ABIDecode, GasLeft, ///< gasleft() + MetaType ///< type(...) }; Category category() const override { return Category::Function; } @@ -1299,16 +1300,23 @@ private: }; /** - * Special type for magic variables (block, msg, tx), similar to a struct but without any reference - * (it always references a global singleton by name). + * Special type for magic variables (block, msg, tx, type(...)), similar to a struct but without any reference. */ class MagicType: public Type { public: - enum class Kind { Block, Message, Transaction, ABI }; + enum class Kind { + Block, ///< "block" + Message, ///< "msg" + Transaction, ///< "tx" + ABI, ///< "abi" + MetaType ///< "type(...)" + }; Category category() const override { return Category::Magic; } explicit MagicType(Kind _kind): m_kind(_kind) {} + /// Factory function for meta type + static std::shared_ptr<MagicType> metaType(TypePointer _type); TypeResult binaryOperatorResult(Token, TypePointer const&) const override { @@ -1327,8 +1335,13 @@ public: Kind kind() const { return m_kind; } + TypePointer typeArgument() const; + private: Kind m_kind; + /// Contract type used for contract metadata magic. + TypePointer m_typeArgument; + }; /** |