mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Respect "pragma stdlib" during name resolution.
This commit is contained in:
parent
2d490a0213
commit
dc992ae767
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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])
|
||||
|
@ -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;
|
||||
|
@ -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.");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user