Merge pull request #347 from chriseth/libraryNameClashes

Detect library name clashes
This commit is contained in:
chriseth 2016-01-18 09:24:11 +01:00
commit 0099513cd4
4 changed files with 53 additions and 2 deletions

View File

@ -807,7 +807,6 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
);
auto contract = dynamic_cast<ContractDefinition const*>(funType->declaration().scope());
solAssert(contract && contract->isLibrary(), "");
//@TODO library name might not be unique
m_context.appendLibraryAddress(contract->name());
m_context << funType->externalIdentifier();
utils().moveIntoStack(funType->selfType()->sizeOnStack(), 2);
@ -1118,7 +1117,6 @@ void ExpressionCompiler::endVisit(Identifier const& _identifier)
else if (auto contract = dynamic_cast<ContractDefinition const*>(declaration))
{
if (contract->isLibrary())
//@todo name should be unique, change once we have module management
m_context.appendLibraryAddress(contract->name());
}
else if (dynamic_cast<EventDefinition const*>(declaration))

View File

@ -148,6 +148,9 @@ bool CompilerStack::parse()
m_contracts[contract->name()].contract = contract;
}
if (!checkLibraryNameClashes())
noErrors = false;
for (Source const* source: m_sourceOrder)
for (ASTPointer<ASTNode> const& node: source->ast->nodes())
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
@ -400,6 +403,37 @@ void CompilerStack::resolveImports()
swap(m_sourceOrder, sourceOrder);
}
bool CompilerStack::checkLibraryNameClashes()
{
bool clashFound = false;
map<string, SourceLocation> libraries;
for (Source const* source: m_sourceOrder)
for (ASTPointer<ASTNode> const& node: source->ast->nodes())
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
if (contract->isLibrary())
{
if (libraries.count(contract->name()))
{
auto err = make_shared<Error>(Error::Type::DeclarationError);
*err <<
errinfo_sourceLocation(contract->location()) <<
errinfo_comment(
"Library \"" + contract->name() + "\" declared twice "
"(will create ambiguities during linking)."
) <<
errinfo_secondarySourceLocation(SecondarySourceLocation().append(
"The other declaration is here:", libraries[contract->name()]
));
m_errors.push_back(err);
clashFound = true;
}
else
libraries[contract->name()] = contract->location();
}
return !clashFound;
}
string CompilerStack::absolutePath(string const& _path, string const& _reference) const
{
// Anything that does not start with `.` is an absolute path.

View File

@ -199,6 +199,9 @@ private:
};
void resolveImports();
/// Checks whether there are libraries with the same name, reports that as an error and
/// @returns false in this case.
bool checkLibraryNameClashes();
/// @returns the absolute path corresponding to @a _path relative to @a _reference.
std::string absolutePath(std::string const& _path, std::string const& _reference) const;
/// Compile a single contract and put the result in @a _compiledContracts.

View File

@ -101,6 +101,22 @@ BOOST_AUTO_TEST_CASE(simple_alias)
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(library_name_clash)
{
CompilerStack c;
c.addSource("a", "library A {}");
c.addSource("b", "library A {}");
BOOST_CHECK(!c.compile());
}
BOOST_AUTO_TEST_CASE(library_name_clash_with_contract)
{
CompilerStack c;
c.addSource("a", "contract A {}");
c.addSource("b", "library A {}");
BOOST_CHECK(c.compile());
}
BOOST_AUTO_TEST_CASE(complex_import)
{
CompilerStack c;