Merge pull request #9038 from ethereum/develop

Merge develop into breaking.
This commit is contained in:
chriseth
2020-05-27 15:24:27 +02:00
committed by GitHub
116 changed files with 1424 additions and 582 deletions
+14 -13
View File
@@ -338,8 +338,14 @@ TypePointer FunctionDefinition::type() const
TypePointer FunctionDefinition::typeViaContractName() const
{
if (annotation().contract->isLibrary())
return FunctionType(*this).asCallableFunction(true);
return TypeProvider::function(*this, FunctionType::Kind::Declaration);
{
if (isPublic())
return FunctionType(*this).asExternallyCallableFunction(true);
else
return TypeProvider::function(*this, FunctionType::Kind::Internal);
}
else
return TypeProvider::function(*this, FunctionType::Kind::Declaration);
}
string FunctionDefinition::externalSignature() const
@@ -369,7 +375,7 @@ FunctionDefinition const& FunctionDefinition::resolveVirtual(
solAssert(!dynamic_cast<ContractDefinition const&>(*scope()).isLibrary(), "");
FunctionType const* functionType = TypeProvider::function(*this)->asCallableFunction(false);
FunctionType const* functionType = TypeProvider::function(*this)->asExternallyCallableFunction(false);
for (ContractDefinition const* c: _mostDerivedContract.annotation().linearizedBaseContracts)
{
@@ -380,7 +386,7 @@ FunctionDefinition const& FunctionDefinition::resolveVirtual(
if (
function->name() == name() &&
!function->isConstructor() &&
FunctionType(*function).asCallableFunction(false)->hasEqualParameterTypes(*functionType)
FunctionType(*function).asExternallyCallableFunction(false)->hasEqualParameterTypes(*functionType)
)
return *function;
}
@@ -616,18 +622,14 @@ set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() c
if (!hasReferenceOrMappingType() || isStateVariable() || isEventParameter())
return set<Location>{ Location::Unspecified };
else if (isExternalCallableParameter())
{
set<Location> locations{ Location::CallData };
if (isLibraryFunctionParameter())
locations.insert(Location::Storage);
return locations;
}
else if (isCallableOrCatchParameter())
{
set<Location> locations{ Location::Memory };
if (isInternalCallableParameter() || isLibraryFunctionParameter() || isTryCatchParameter())
locations.insert(Location::Storage);
if (!isTryCatchParameter())
locations.insert(Location::CallData);
return locations;
}
else if (isLocalVariable())
@@ -642,8 +644,7 @@ set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() c
case Type::Category::Mapping:
return set<Location>{ Location::Storage };
default:
// TODO: add Location::Calldata once implemented for local variables.
return set<Location>{ Location::Memory, Location::Storage };
return set<Location>{ Location::Memory, Location::Storage, Location::CallData };
}
};
return dataLocations(typeName()->annotation().type, dataLocations);
+20 -6
View File
@@ -349,14 +349,17 @@ TypePointer Type::fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool) c
MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition const& _scope)
{
// Normalise data location of type.
TypePointer type = TypeProvider::withLocationIfReference(DataLocation::Storage, &_type);
DataLocation typeLocation = DataLocation::Storage;
if (auto refType = dynamic_cast<ReferenceType const*>(&_type))
typeLocation = refType->location();
set<Declaration const*> seenFunctions;
MemberList::MemberMap members;
for (ContractDefinition const* contract: _scope.annotation().linearizedBaseContracts)
for (UsingForDirective const* ufd: contract->usingForDirectives())
{
if (ufd->typeName() && *type != *TypeProvider::withLocationIfReference(
DataLocation::Storage,
if (ufd->typeName() && _type != *TypeProvider::withLocationIfReference(
typeLocation,
ufd->typeName()->annotation().type
))
continue;
@@ -370,7 +373,7 @@ MemberList::MemberMap Type::boundFunctions(Type const& _type, ContractDefinition
seenFunctions.insert(function);
if (function->parameters().empty())
continue;
FunctionTypePointer fun = FunctionType(*function, FunctionType::Kind::External).asCallableFunction(true, true);
FunctionTypePointer fun = FunctionType(*function, FunctionType::Kind::External).asExternallyCallableFunction(true, true);
if (_type.isImplicitlyConvertibleTo(*fun->selfType()))
members.emplace_back(function->name(), fun, function);
}
@@ -2058,7 +2061,7 @@ MemberList::MemberMap ContractType::nativeMembers(ContractDefinition const* _con
for (auto const& it: m_contract.interfaceFunctions())
members.emplace_back(
it.second->declaration().name(),
it.second->asCallableFunction(m_contract.isLibrary()),
it.second->asExternallyCallableFunction(m_contract.isLibrary()),
&it.second->declaration()
);
}
@@ -3026,6 +3029,17 @@ unsigned FunctionType::storageBytes() const
solAssert(false, "Storage size of non-storable function type requested.");
}
bool FunctionType::nameable() const
{
return
(m_kind == Kind::Internal || m_kind == Kind::External) &&
!m_bound &&
!m_arbitraryParameters &&
!m_gasSet &&
!m_valueSet &&
!m_saltSet;
}
vector<tuple<string, TypePointer>> FunctionType::makeStackItems() const
{
vector<tuple<string, TypePointer>> slots;
@@ -3427,7 +3441,7 @@ TypePointer FunctionType::copyAndSetCallOptions(bool _setGas, bool _setValue, bo
);
}
FunctionTypePointer FunctionType::asCallableFunction(bool _inLibrary, bool _bound) const
FunctionTypePointer FunctionType::asExternallyCallableFunction(bool _inLibrary, bool _bound) const
{
if (_bound)
solAssert(!m_parameterTypes.empty(), "");
+17 -2
View File
@@ -263,6 +263,10 @@ public:
/// Returns true if the type can be stored as a value (as opposed to a reference) on the stack,
/// i.e. it behaves differently in lvalue context and in value context.
virtual bool isValueType() const { return false; }
/// @returns true if this type can be used for variables. It returns false for
/// types like magic types, literals and function types with a kind that is not
/// internal or external.
virtual bool nameable() const { return false; }
/// @returns a list of named and typed stack items that determine the layout of this type on the stack.
/// A stack item either has an empty name and type ``nullptr`` referring to a single stack slot, or
/// has a non-empty name and a valid type referring to the stack layout of that type.
@@ -402,6 +406,7 @@ public:
unsigned storageBytes() const override { return 160 / 8; }
bool leftAligned() const override { return false; }
bool isValueType() const override { return true; }
bool nameable() const override { return true; }
MemberList::MemberMap nativeMembers(ContractDefinition const*) const override;
@@ -446,6 +451,7 @@ public:
unsigned storageBytes() const override { return m_bits / 8; }
bool leftAligned() const override { return false; }
bool isValueType() const override { return true; }
bool nameable() const override { return true; }
std::string toString(bool _short) const override;
@@ -492,6 +498,7 @@ public:
unsigned storageBytes() const override { return m_totalBits / 8; }
bool leftAligned() const override { return false; }
bool isValueType() const override { return true; }
bool nameable() const override { return true; }
std::string toString(bool _short) const override;
@@ -639,6 +646,7 @@ public:
unsigned storageBytes() const override { return m_bytes; }
bool leftAligned() const override { return true; }
bool isValueType() const override { return true; }
bool nameable() const override { return true; }
std::string toString(bool) const override { return "bytes" + util::toString(m_bytes); }
MemberList::MemberMap nativeMembers(ContractDefinition const*) const override;
@@ -666,6 +674,7 @@ public:
unsigned storageBytes() const override { return 1; }
bool leftAligned() const override { return false; }
bool isValueType() const override { return true; }
bool nameable() const override { return true; }
std::string toString(bool) const override { return "bool"; }
u256 literalValue(Literal const* _literal) const override;
@@ -773,6 +782,7 @@ public:
bool isDynamicallyEncoded() const override;
u256 storageSize() const override;
bool canLiveOutsideStorage() const override { return m_baseType->canLiveOutsideStorage(); }
bool nameable() const override { return true; }
std::string toString(bool _short) const override;
std::string canonicalName() const override;
std::string signatureInExternalFunction(bool _structsByName) const override;
@@ -875,6 +885,7 @@ public:
bool leftAligned() const override { solAssert(!isSuper(), ""); return false; }
bool canLiveOutsideStorage() const override { return !isSuper(); }
bool isValueType() const override { return !isSuper(); }
bool nameable() const override { return !isSuper(); }
std::string toString(bool _short) const override;
std::string canonicalName() const override;
@@ -935,6 +946,7 @@ public:
u256 memoryDataSize() const override;
u256 storageSize() const override;
bool canLiveOutsideStorage() const override { return true; }
bool nameable() const override { return true; }
std::string toString(bool _short) const override;
MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override;
@@ -997,6 +1009,7 @@ public:
std::string toString(bool _short) const override;
std::string canonicalName() const override;
bool isValueType() const override { return true; }
bool nameable() const override { return true; }
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
TypePointer encodingType() const override;
@@ -1202,6 +1215,7 @@ public:
bool leftAligned() const override;
unsigned storageBytes() const override;
bool isValueType() const override { return true; }
bool nameable() const override;
bool canLiveOutsideStorage() const override { return m_kind == Kind::Internal || m_kind == Kind::External; }
bool hasSimpleZeroValueInMemory() const override { return false; }
MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override;
@@ -1290,11 +1304,11 @@ public:
/// @returns a copy of this function type where the location of reference types is changed
/// from CallData to Memory. This is the type that would be used when the function is
/// called, as opposed to the parameter types that are available inside the function body.
/// called externally, as opposed to the parameter types that are available inside the function body.
/// Also supports variants to be used for library or bound calls.
/// @param _inLibrary if true, uses DelegateCall as location.
/// @param _bound if true, the function type is set to be bound.
FunctionTypePointer asCallableFunction(bool _inLibrary, bool _bound = false) const;
FunctionTypePointer asExternallyCallableFunction(bool _inLibrary, bool _bound = false) const;
protected:
std::vector<std::tuple<std::string, TypePointer>> makeStackItems() const override;
@@ -1339,6 +1353,7 @@ public:
bool dataStoredIn(DataLocation _location) const override { return _location == DataLocation::Storage; }
/// Cannot be stored in memory, but just in case.
bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); }
bool nameable() const override { return true; }
Type const* keyType() const { return m_keyType; }
Type const* valueType() const { return m_valueType; }