mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #261 from chriseth/dataloc
Bugfix for explicit memory types in libraries.
This commit is contained in:
commit
e853eb22fa
@ -128,19 +128,21 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable)
|
|||||||
{
|
{
|
||||||
type = _variable.typeName()->annotation().type;
|
type = _variable.typeName()->annotation().type;
|
||||||
using Location = VariableDeclaration::Location;
|
using Location = VariableDeclaration::Location;
|
||||||
Location loc = _variable.referenceLocation();
|
Location varLoc = _variable.referenceLocation();
|
||||||
|
DataLocation typeLoc = DataLocation::Memory;
|
||||||
// References are forced to calldata for external function parameters (not return)
|
// References are forced to calldata for external function parameters (not return)
|
||||||
// and memory for parameters (also return) of publicly visible functions.
|
// and memory for parameters (also return) of publicly visible functions.
|
||||||
// They default to memory for function parameters and storage for local variables.
|
// They default to memory for function parameters and storage for local variables.
|
||||||
// As an exception, "storage" is allowed for library functions.
|
// As an exception, "storage" is allowed for library functions.
|
||||||
if (auto ref = dynamic_cast<ReferenceType const*>(type.get()))
|
if (auto ref = dynamic_cast<ReferenceType const*>(type.get()))
|
||||||
{
|
{
|
||||||
|
bool isPointer = true;
|
||||||
if (_variable.isExternalCallableParameter())
|
if (_variable.isExternalCallableParameter())
|
||||||
{
|
{
|
||||||
auto const& contract = dynamic_cast<ContractDefinition const&>(*_variable.scope()->scope());
|
auto const& contract = dynamic_cast<ContractDefinition const&>(*_variable.scope()->scope());
|
||||||
if (contract.isLibrary())
|
if (contract.isLibrary())
|
||||||
{
|
{
|
||||||
if (loc == Location::Memory)
|
if (varLoc == Location::Memory)
|
||||||
fatalTypeError(_variable.location(),
|
fatalTypeError(_variable.location(),
|
||||||
"Location has to be calldata or storage for external "
|
"Location has to be calldata or storage for external "
|
||||||
"library functions (remove the \"memory\" keyword)."
|
"library functions (remove the \"memory\" keyword)."
|
||||||
@ -149,50 +151,52 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// force location of external function parameters (not return) to calldata
|
// force location of external function parameters (not return) to calldata
|
||||||
if (loc != Location::Default)
|
if (varLoc != Location::Default)
|
||||||
fatalTypeError(_variable.location(),
|
fatalTypeError(_variable.location(),
|
||||||
"Location has to be calldata for external functions "
|
"Location has to be calldata for external functions "
|
||||||
"(remove the \"memory\" or \"storage\" keyword)."
|
"(remove the \"memory\" or \"storage\" keyword)."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (loc == Location::Default)
|
if (varLoc == Location::Default)
|
||||||
type = ref->copyForLocation(DataLocation::CallData, true);
|
typeLoc = DataLocation::CallData;
|
||||||
|
else
|
||||||
|
typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage;
|
||||||
}
|
}
|
||||||
else if (_variable.isCallableParameter() && _variable.scope()->isPublic())
|
else if (_variable.isCallableParameter() && _variable.scope()->isPublic())
|
||||||
{
|
{
|
||||||
auto const& contract = dynamic_cast<ContractDefinition const&>(*_variable.scope()->scope());
|
auto const& contract = dynamic_cast<ContractDefinition const&>(*_variable.scope()->scope());
|
||||||
// force locations of public or external function (return) parameters to memory
|
// force locations of public or external function (return) parameters to memory
|
||||||
if (loc == Location::Storage && !contract.isLibrary())
|
if (varLoc == Location::Storage && !contract.isLibrary())
|
||||||
fatalTypeError(_variable.location(),
|
fatalTypeError(_variable.location(),
|
||||||
"Location has to be memory for publicly visible functions "
|
"Location has to be memory for publicly visible functions "
|
||||||
"(remove the \"storage\" keyword)."
|
"(remove the \"storage\" keyword)."
|
||||||
);
|
);
|
||||||
if (loc == Location::Default || !contract.isLibrary())
|
if (varLoc == Location::Default || !contract.isLibrary())
|
||||||
type = ref->copyForLocation(DataLocation::Memory, true);
|
typeLoc = DataLocation::Memory;
|
||||||
|
else
|
||||||
|
typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (_variable.isConstant())
|
if (_variable.isConstant())
|
||||||
{
|
{
|
||||||
if (loc != Location::Default && loc != Location::Memory)
|
if (varLoc != Location::Default && varLoc != Location::Memory)
|
||||||
fatalTypeError(
|
fatalTypeError(
|
||||||
_variable.location(),
|
_variable.location(),
|
||||||
"Storage location has to be \"memory\" (or unspecified) for constants."
|
"Storage location has to be \"memory\" (or unspecified) for constants."
|
||||||
);
|
);
|
||||||
loc = Location::Memory;
|
typeLoc = DataLocation::Memory;
|
||||||
}
|
}
|
||||||
if (loc == Location::Default)
|
else if (varLoc == Location::Default)
|
||||||
loc = _variable.isCallableParameter() ? Location::Memory : Location::Storage;
|
typeLoc = _variable.isCallableParameter() ? DataLocation::Memory : DataLocation::Storage;
|
||||||
bool isPointer = !_variable.isStateVariable();
|
else
|
||||||
type = ref->copyForLocation(
|
typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage;
|
||||||
loc == Location::Memory ?
|
isPointer = !_variable.isStateVariable();
|
||||||
DataLocation::Memory :
|
|
||||||
DataLocation::Storage,
|
|
||||||
isPointer
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type = ref->copyForLocation(typeLoc, isPointer);
|
||||||
}
|
}
|
||||||
else if (loc != Location::Default && !ref)
|
else if (varLoc != Location::Default && !ref)
|
||||||
fatalTypeError(_variable.location(), "Storage location can only be given for array or struct types.");
|
fatalTypeError(_variable.location(), "Storage location can only be given for array or struct types.");
|
||||||
|
|
||||||
if (!type)
|
if (!type)
|
||||||
|
Loading…
Reference in New Issue
Block a user