If a declaration shadows several others, group them together

This commit is contained in:
a3d4 2020-10-08 03:59:06 +02:00
parent f29ebc0847
commit 90c8c32d86
6 changed files with 56 additions and 36 deletions

View File

@ -191,6 +191,9 @@ void DeclarationContainer::populateHomonyms(back_insert_iterator<Homonyms> _it)
innerContainer->populateHomonyms(_it);
for (auto [name, location]: m_homonymCandidates)
for (auto const* declaration: m_enclosingContainer->resolveName(name, true, true))
_it = make_pair(location, declaration);
{
vector<Declaration const*> const& declarations = m_enclosingContainer->resolveName(name, true, true);
if (!declarations.empty())
_it = make_pair(location, declarations);
}
}

View File

@ -27,8 +27,6 @@
#include <liblangutil/Exceptions.h>
#include <liblangutil/SourceLocation.h>
#include <boost/noncopyable.hpp>
#include <map>
#include <set>
namespace solidity::frontend
{
@ -40,7 +38,7 @@ namespace solidity::frontend
class DeclarationContainer
{
public:
using Homonyms = std::vector<std::pair<langutil::SourceLocation const*, Declaration const*>>;
using Homonyms = std::vector<std::pair<langutil::SourceLocation const*, std::vector<Declaration const*>>>;
explicit DeclarationContainer(
ASTNode const* _enclosingNode = nullptr,

View File

@ -229,41 +229,44 @@ void NameAndTypeResolver::warnHomonymDeclarations() const
DeclarationContainer::Homonyms homonyms;
m_scopes.at(nullptr)->populateHomonyms(back_inserter(homonyms));
unordered_set<SourceLocation const*> noMoreMagic;
for (auto [innerLocation, outerDeclaration]: homonyms)
for (auto [innerLocation, outerDeclarations]: homonyms)
{
solAssert(innerLocation && outerDeclaration, "");
solAssert(innerLocation && !outerDeclarations.empty(), "");
if (dynamic_cast<MagicVariableDeclaration const*>(outerDeclaration))
bool magicShadowed = false;
SecondarySourceLocation homonymousLocations;
SecondarySourceLocation shadowedLocations;
for (Declaration const* outerDeclaration: outerDeclarations)
{
// avoids duplecated warnings
// (some magic variables ("revert", "require") appear in different flavors under the same name)
if (noMoreMagic.insert(innerLocation).second)
m_errorReporter.warning(
2319_error,
*innerLocation,
"This declaration shadows a builtin symbol."
);
}
else
{
SourceLocation const& outerLocation = outerDeclaration->location();
if (!outerDeclaration->isVisibleInContract())
m_errorReporter.warning(
8760_error,
*innerLocation,
"This declaration has the same name as another declaration.",
SecondarySourceLocation().append("The other declaration is here:", outerLocation)
);
solAssert(outerDeclaration, "");
if (dynamic_cast<MagicVariableDeclaration const*>(outerDeclaration))
magicShadowed = true;
else if (!outerDeclaration->isVisibleInContract())
homonymousLocations.append("The other declaration is here:", outerDeclaration->location());
else
m_errorReporter.warning(
2519_error,
*innerLocation,
"This declaration shadows an existing declaration.",
SecondarySourceLocation().append("The shadowed declaration is here:", outerLocation)
);
shadowedLocations.append("The shadowed declaration is here:", outerDeclaration->location());
}
if (magicShadowed)
m_errorReporter.warning(
2319_error,
*innerLocation,
"This declaration shadows a builtin symbol."
);
if (!homonymousLocations.infos.empty())
m_errorReporter.warning(
8760_error,
*innerLocation,
"This declaration has the same name as another declaration.",
homonymousLocations
);
if (!shadowedLocations.infos.empty())
m_errorReporter.warning(
2519_error,
*innerLocation,
"This declaration shadows an existing declaration.",
shadowedLocations
);
}
}

View File

@ -16,5 +16,4 @@ contract D is C {
// ----
// Warning 2519: (s1.sol:65-134): This declaration shadows an existing declaration.
// Warning 2519: (s2.sol:85-155): This declaration shadows an existing declaration.
// Warning 2519: (s2.sol:85-155): This declaration shadows an existing declaration.
// DeclarationError 1686: (s2.sol:17-64): Function with same name and parameter types defined twice.

View File

@ -0,0 +1,7 @@
contract test {
function e() external { }
function f() public pure { uint e; e = 0; }
function e(int) external { }
}
// ----
// Warning 8760: (77-83): This declaration has the same name as another declaration.

View File

@ -0,0 +1,10 @@
function e() {}
contract test {
function f() pure public { uint e; uint g; uint h; e = g = h = 0; }
function g() pure public {}
}
function h() {}
// ----
// Warning 2519: (63-69): This declaration shadows an existing declaration.
// Warning 2519: (71-77): This declaration shadows an existing declaration.
// Warning 2519: (79-85): This declaration shadows an existing declaration.