Skip to content

Commit e853eb2

Browse files
committed
Merge pull request #261 from chriseth/dataloc
Bugfix for explicit memory types in libraries.
2 parents 8cbe99f + 7e3bf83 commit e853eb2

1 file changed

Lines changed: 24 additions & 20 deletions

File tree

libsolidity/analysis/ReferencesResolver.cpp

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -128,19 +128,21 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable)
128128
{
129129
type = _variable.typeName()->annotation().type;
130130
using Location = VariableDeclaration::Location;
131-
Location loc = _variable.referenceLocation();
131+
Location varLoc = _variable.referenceLocation();
132+
DataLocation typeLoc = DataLocation::Memory;
132133
// References are forced to calldata for external function parameters (not return)
133134
// and memory for parameters (also return) of publicly visible functions.
134135
// They default to memory for function parameters and storage for local variables.
135136
// As an exception, "storage" is allowed for library functions.
136137
if (auto ref = dynamic_cast<ReferenceType const*>(type.get()))
137138
{
139+
bool isPointer = true;
138140
if (_variable.isExternalCallableParameter())
139141
{
140142
auto const& contract = dynamic_cast<ContractDefinition const&>(*_variable.scope()->scope());
141143
if (contract.isLibrary())
142144
{
143-
if (loc == Location::Memory)
145+
if (varLoc == Location::Memory)
144146
fatalTypeError(_variable.location(),
145147
"Location has to be calldata or storage for external "
146148
"library functions (remove the \"memory\" keyword)."
@@ -149,50 +151,52 @@ void ReferencesResolver::endVisit(VariableDeclaration const& _variable)
149151
else
150152
{
151153
// force location of external function parameters (not return) to calldata
152-
if (loc != Location::Default)
154+
if (varLoc != Location::Default)
153155
fatalTypeError(_variable.location(),
154156
"Location has to be calldata for external functions "
155157
"(remove the \"memory\" or \"storage\" keyword)."
156158
);
157159
}
158-
if (loc == Location::Default)
159-
type = ref->copyForLocation(DataLocation::CallData, true);
160+
if (varLoc == Location::Default)
161+
typeLoc = DataLocation::CallData;
162+
else
163+
typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage;
160164
}
161165
else if (_variable.isCallableParameter() && _variable.scope()->isPublic())
162166
{
163167
auto const& contract = dynamic_cast<ContractDefinition const&>(*_variable.scope()->scope());
164168
// force locations of public or external function (return) parameters to memory
165-
if (loc == Location::Storage && !contract.isLibrary())
169+
if (varLoc == Location::Storage && !contract.isLibrary())
166170
fatalTypeError(_variable.location(),
167171
"Location has to be memory for publicly visible functions "
168172
"(remove the \"storage\" keyword)."
169173
);
170-
if (loc == Location::Default || !contract.isLibrary())
171-
type = ref->copyForLocation(DataLocation::Memory, true);
174+
if (varLoc == Location::Default || !contract.isLibrary())
175+
typeLoc = DataLocation::Memory;
176+
else
177+
typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage;
172178
}
173179
else
174180
{
175181
if (_variable.isConstant())
176182
{
177-
if (loc != Location::Default && loc != Location::Memory)
183+
if (varLoc != Location::Default && varLoc != Location::Memory)
178184
fatalTypeError(
179185
_variable.location(),
180186
"Storage location has to be \"memory\" (or unspecified) for constants."
181187
);
182-
loc = Location::Memory;
188+
typeLoc = DataLocation::Memory;
183189
}
184-
if (loc == Location::Default)
185-
loc = _variable.isCallableParameter() ? Location::Memory : Location::Storage;
186-
bool isPointer = !_variable.isStateVariable();
187-
type = ref->copyForLocation(
188-
loc == Location::Memory ?
189-
DataLocation::Memory :
190-
DataLocation::Storage,
191-
isPointer
192-
);
190+
else if (varLoc == Location::Default)
191+
typeLoc = _variable.isCallableParameter() ? DataLocation::Memory : DataLocation::Storage;
192+
else
193+
typeLoc = varLoc == Location::Memory ? DataLocation::Memory : DataLocation::Storage;
194+
isPointer = !_variable.isStateVariable();
193195
}
196+
197+
type = ref->copyForLocation(typeLoc, isPointer);
194198
}
195-
else if (loc != Location::Default && !ref)
199+
else if (varLoc != Location::Default && !ref)
196200
fatalTypeError(_variable.location(), "Storage location can only be given for array or struct types.");
197201

198202
if (!type)

0 commit comments

Comments
 (0)