Respect "pragma stdlib" during name resolution.

This commit is contained in:
chriseth 2022-07-14 17:18:38 +02:00 committed by Nikola Matic
parent 2d490a0213
commit dc992ae767
5 changed files with 53 additions and 6 deletions

View File

@ -147,9 +147,18 @@ vector<Declaration const*> DeclarationContainer::resolveName(
ResolvingSettings _settings
) const
{
updateSettingsBasedOnStdlibPragma(_settings);
solAssert(!_name.empty(), "Attempt to resolve empty name.");
vector<Declaration const*> result;
if (!_settings.autoPopulateStdlib && m_stdlibIdentifiers && m_stdlibIdentifiers->count(_name))
{
solAssert(!m_enclosingContainer);
return result;
}
if (m_declarations.count(_name))
{
if (_settings.onlyVisibleAsUnqualifiedNames)
@ -211,7 +220,18 @@ void DeclarationContainer::populateHomonyms(back_insert_iterator<Homonyms> _it)
settings.recursive = true;
settings.alsoInvisible = true;
vector<Declaration const*> const& declarations = m_enclosingContainer->resolveName(name, std::move(settings));
if (!declarations.empty())
_it = make_pair(location, declarations);
}
}
void DeclarationContainer::updateSettingsBasedOnStdlibPragma(ResolvingSettings& _settings) const
{
if (auto const* sourceUnit = dynamic_cast<SourceUnit const*>(m_selfNode))
{
solAssert(sourceUnit->annotation().useStdlib.set());
if (*sourceUnit->annotation().useStdlib)
_settings.autoPopulateStdlib = false;
}
}

View File

@ -45,6 +45,9 @@ struct ResolvingSettings
/// if true, do not include declarations which can never actually be referenced using their
/// name alone (without being qualified with the name of scope in which they are declared).
bool onlyVisibleAsUnqualifiedNames = false;
/// If false, ignores symbols in the global scope that are part of the standard library
/// (this is set to false with "pragma stdlib").
bool autoPopulateStdlib = true;
};
@ -58,13 +61,18 @@ public:
using Homonyms = std::vector<std::pair<langutil::SourceLocation const*, std::vector<Declaration const*>>>;
DeclarationContainer() = default;
explicit DeclarationContainer(ASTNode const* _enclosingNode, DeclarationContainer* _enclosingContainer):
explicit DeclarationContainer(ASTNode const* _selfNode, ASTNode const* _enclosingNode, DeclarationContainer* _enclosingContainer):
m_selfNode(_selfNode),
m_enclosingNode(_enclosingNode),
m_enclosingContainer(_enclosingContainer)
{
if (_enclosingContainer)
_enclosingContainer->m_innerContainers.emplace_back(this);
}
void setStdlibIdentifiers(std::set<std::string> const& _stdlibIdentifiers)
{
m_stdlibIdentifiers = &_stdlibIdentifiers;
}
/// Registers the declaration in the scope unless its name is already declared or the name is empty.
/// @param _name the name to register, if nullptr the intrinsic name of @a _declaration is used.
/// @param _location alternative location, used to point at homonymous declarations.
@ -100,11 +108,16 @@ public:
void populateHomonyms(std::back_insert_iterator<Homonyms> _it) const;
private:
/// Disables autoPopulateStdlib in _settinsg if "pragma stdlib" is active in m_selfNode.
void updateSettingsBasedOnStdlibPragma(ResolvingSettings& _settings) const;
ASTNode const* m_selfNode = nullptr;
ASTNode const* m_enclosingNode = nullptr;
DeclarationContainer const* m_enclosingContainer = nullptr;
std::vector<DeclarationContainer const*> m_innerContainers;
std::map<ASTString, std::vector<Declaration const*>> m_declarations;
std::map<ASTString, std::vector<Declaration const*>> m_invisibleDeclarations;
std::set<std::string> const* m_stdlibIdentifiers = nullptr;
/// List of declarations (name and location) to check later for homonymity.
std::vector<std::pair<std::string, langutil::SourceLocation const*>> m_homonymCandidates;
};

View File

@ -125,6 +125,16 @@ vector<Declaration const*> GlobalContext::declarations() const
return declarations;
}
set<string> const& GlobalContext::stdlibIdentifiers()
{
set<string> static names{
"ecrecover",
"ripemd160",
"sha256"
};
return names;
}
MagicVariableDeclaration const* GlobalContext::currentThis() const
{
if (!m_thisPointer[m_currentContract])

View File

@ -28,6 +28,7 @@
#include <memory>
#include <string>
#include <vector>
#include <set>
namespace solidity::frontend
{
@ -55,6 +56,9 @@ public:
/// @returns a vector of all implicit global declarations excluding "this".
std::vector<Declaration const*> declarations() const;
/// @returns the set of identifiers that are not present in the global scope
/// when the "pragma stdlib" is active.
static std::set<std::string> const& stdlibIdentifiers();
private:
std::vector<std::shared_ptr<MagicVariableDeclaration const>> m_magicVariables;

View File

@ -47,9 +47,8 @@ NameAndTypeResolver::NameAndTypeResolver(
{
m_scopes[nullptr] = make_shared<DeclarationContainer>();
for (Declaration const* declaration: _globalContext.declarations())
{
solAssert(m_scopes[nullptr]->registerDeclaration(*declaration, false, false), "Unable to register global declaration.");
}
m_scopes[nullptr]->setStdlibIdentifiers(_globalContext.stdlibIdentifiers());
}
bool NameAndTypeResolver::registerDeclarations(SourceUnit& _sourceUnit, ASTNode const* _currentScope)
@ -573,7 +572,7 @@ bool DeclarationRegistrationHelper::visit(SourceUnit& _sourceUnit)
{
if (!m_scopes[&_sourceUnit])
// By importing, it is possible that the container already exists.
m_scopes[&_sourceUnit] = make_shared<DeclarationContainer>(m_currentScope, m_scopes[m_currentScope].get());
m_scopes[&_sourceUnit] = make_shared<DeclarationContainer>(&_sourceUnit, m_currentScope, m_scopes[m_currentScope].get());
return ASTVisitor::visit(_sourceUnit);
}
@ -587,7 +586,8 @@ bool DeclarationRegistrationHelper::visit(ImportDirective& _import)
SourceUnit const* importee = _import.annotation().sourceUnit;
solAssert(!!importee, "");
if (!m_scopes[importee])
m_scopes[importee] = make_shared<DeclarationContainer>(nullptr, m_scopes[nullptr].get());
m_scopes[importee] = make_shared<DeclarationContainer>(importee, nullptr, m_scopes[nullptr].get());
// TODO here, m_selfNode inside the contanier does not point to the key of m_scopes (_import) - is that a problem?
m_scopes[&_import] = m_scopes[importee];
ASTVisitor::visit(_import);
return false; // Do not recurse into child nodes (Identifier for symbolAliases)
@ -677,7 +677,7 @@ void DeclarationRegistrationHelper::enterNewSubScope(ASTNode& _subScope)
{
bool newlyAdded = m_scopes.emplace(
&_subScope,
make_shared<DeclarationContainer>(m_currentScope, m_scopes[m_currentScope].get())
make_shared<DeclarationContainer>(&_subScope, m_currentScope, m_scopes[m_currentScope].get())
).second;
solAssert(newlyAdded, "Unable to add new scope.");
}