diff options
-rw-r--r-- | libsolidity/codegen/ExpressionCompiler.cpp | 2 | ||||
-rw-r--r-- | libsolidity/interface/CompilerStack.cpp | 33 | ||||
-rw-r--r-- | libsolidity/interface/CompilerStack.h | 3 |
3 files changed, 36 insertions, 2 deletions
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index f0dab41a..040217da 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -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)) diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index a6f6f224..9a7d6982 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -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,36 @@ 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); + } + 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. diff --git a/libsolidity/interface/CompilerStack.h b/libsolidity/interface/CompilerStack.h index 3e6dc456..6cf19db4 100644 --- a/libsolidity/interface/CompilerStack.h +++ b/libsolidity/interface/CompilerStack.h @@ -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. |