Skip to content

Commit 31cc995

Browse files
committed
Handle struct members, enum members etc. in a special way during name resolution
1 parent 4312277 commit 31cc995

File tree

5 files changed

+43
-27
lines changed

5 files changed

+43
-27
lines changed

libsolidity/analysis/DeclarationContainer.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,7 @@ bool DeclarationContainer::registerDeclaration(
121121
if (conflictingDeclaration(_declaration, _name))
122122
return false;
123123

124-
// Do not warn about shadowing for structs and enums because their members are
125-
// not accessible without prefixes. Also do not warn about event parameters
126-
// because they do not participate in any proper scope.
127-
FunctionDefinition const* functionDefinitionScope = dynamic_cast<FunctionDefinition const*>(_declaration.scope());
128-
bool special = (_declaration.scope() && (_declaration.isStructMember() || _declaration.isEnumValue() || _declaration.isEventParameter())) ||
129-
(functionDefinitionScope && !functionDefinitionScope->hasBody()); // parameter of a function without body
130-
if (m_enclosingContainer && !special)
124+
if (m_enclosingContainer && _declaration.isNameSelfSufficient())
131125
m_homonymCandidates.emplace_back(*_name, _location ? _location : &_declaration.location());
132126
}
133127

@@ -146,14 +140,28 @@ bool DeclarationContainer::registerDeclaration(
146140
return registerDeclaration(_declaration, nullptr, nullptr, _invisible, _update);
147141
}
148142

149-
vector<Declaration const*> DeclarationContainer::resolveName(ASTString const& _name, bool _recursive, bool _alsoInvisible) const
143+
vector<Declaration const*> DeclarationContainer::resolveName(
144+
ASTString const& _name,
145+
bool _recursive,
146+
bool _alsoInvisible,
147+
bool _onlySelfSufficientNames
148+
) const
150149
{
151150
solAssert(!_name.empty(), "Attempt to resolve empty name.");
152151
vector<Declaration const*> result;
152+
153+
auto filter = [&result, &_onlySelfSufficientNames](vector<Declaration const*> _declarations) {
154+
_onlySelfSufficientNames ?
155+
copy_if(_declarations.cbegin(), _declarations.cend(), back_inserter(result), [](auto& _declaration) {
156+
return _declaration->isNameSelfSufficient();
157+
}) :
158+
copy(_declarations.cbegin(), _declarations.cend(), back_inserter(result));
159+
};
160+
153161
if (m_declarations.count(_name))
154-
result = m_declarations.at(_name);
162+
filter(m_declarations.at(_name));
155163
if (_alsoInvisible && m_invisibleDeclarations.count(_name))
156-
result += m_invisibleDeclarations.at(_name);
164+
filter(m_invisibleDeclarations.at(_name));
157165
if (result.empty() && _recursive && m_enclosingContainer)
158166
result = m_enclosingContainer->resolveName(_name, true, _alsoInvisible);
159167
return result;

libsolidity/analysis/DeclarationContainer.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,12 @@ class DeclarationContainer
5656
bool registerDeclaration(Declaration const& _declaration, ASTString const* _name, langutil::SourceLocation const* _location, bool _invisible, bool _update);
5757
bool registerDeclaration(Declaration const& _declaration, bool _invisible, bool _update);
5858

59-
std::vector<Declaration const*> resolveName(ASTString const& _name, bool _recursive = false, bool _alsoInvisible = false) const;
59+
std::vector<Declaration const*> resolveName(
60+
ASTString const& _name,
61+
bool _recursive = false,
62+
bool _alsoInvisible = false,
63+
bool _onlySelfSufficientNames = false
64+
) const;
6065
ASTNode const* enclosingNode() const { return m_enclosingNode; }
6166
DeclarationContainer const* enclosingContainer() const { return m_enclosingContainer; }
6267
ASTNode const* currentNode() const { return m_currentNode; }

libsolidity/analysis/NameAndTypeResolver.cpp

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -190,22 +190,7 @@ vector<Declaration const*> NameAndTypeResolver::nameFromCurrentScope(ASTString c
190190
Declaration const* NameAndTypeResolver::pathFromCurrentScope(vector<ASTString> const& _path) const
191191
{
192192
solAssert(!_path.empty(), "");
193-
vector<Declaration const*> candidates;
194-
195-
bool isStructScope = dynamic_cast<StructDefinition const*>(m_currentScope->currentNode());
196-
if (isStructScope && _path.size() == 1)
197-
{
198-
// For cases like
199-
// enum E {a}; struct S {E E;}
200-
// the resolved name would be the struct member name, if we start from the current scope.
201-
// So we start from the enclosing scope instead.
202-
// It should be OK because there is no way to use unqualified access to struct members.
203-
DeclarationContainer const* enclosingContainer = m_currentScope->enclosingContainer();
204-
solAssert(enclosingContainer, "");
205-
candidates = enclosingContainer->resolveName(_path.front(), true);
206-
}
207-
else
208-
candidates = m_currentScope->resolveName(_path.front(), true);
193+
vector<Declaration const*> candidates = m_currentScope->resolveName(_path.front(), true, false, true);
209194

210195
for (size_t i = 1; i < _path.size() && candidates.size() == 1; i++)
211196
{

libsolidity/ast/AST.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,18 @@ bool Declaration::isEventParameter() const
498498
return dynamic_cast<EventDefinition const*>(scope());
499499
}
500500

501+
bool Declaration::isNameSelfSufficient() const
502+
{
503+
if (!scope())
504+
return true;
505+
if (isStructMember() || isEnumValue() || isEventParameter())
506+
return false;
507+
if (auto functionDefinition = dynamic_cast<FunctionDefinition const*>(scope()))
508+
if (!functionDefinition->hasBody())
509+
return false; // parameter of a function without body
510+
return true;
511+
}
512+
501513
DeclarationAnnotation& Declaration::annotation() const
502514
{
503515
return initAnnotation<DeclarationAnnotation>();

libsolidity/ast/AST.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,12 @@ class Declaration: public ASTNode, public Scopable
268268
/// @returns true if this is a declaration of a parameter of an event.
269269
bool isEventParameter() const;
270270

271+
/// @returns true if the name can be used as is.
272+
/// Usually the name alone can be used to refer to the corresponding entity.
273+
/// But, for example, struct member names or enum member names require a prefix.
274+
/// Another example is event parameter names, which do not participate in any proper scope.
275+
bool isNameSelfSufficient() const;
276+
271277
/// @returns the type of expressions referencing this declaration.
272278
/// This can only be called once types of variable declarations have already been resolved.
273279
virtual TypePointer type() const = 0;

0 commit comments

Comments
 (0)