New Error object for CoverageMapping/createBinary

Hi all,

I saw that some methods that was returning ErrorOr<> object are now returning Expected<> object embedding Error object instead of std::error_code. I have some troubles understanding how to use the new Error class…

Until now, I was using this kind of code :

auto BinOrErr = llvm::object::createBinary(this->execPath);

if(auto EC = BinOrErr.getError())
{
errs() << "Error : " << EC.message() << “\n”;

return false;

}

And this one:

auto CoverageOrErr = llvm::coverage::CoverageMapping::load(this->execPath, this->profPath, arch);

if (auto EC = CoverageOrErr.getError())
{
errs() << "Error: Failed to load coverage: " << EC.message() << “\n”;
return false;
}

Since LLVM 3.9, load() and createBinary() return an Expected object. I managed to get the Error object using takeError() method (instead of the old getError()). But, since the Error object is not an std::error_code, I did not found a way to retrieve the message information… I tried to convert the Error object back to std::error_code using the function errorToErrorCode() like this:

auto CoverageOrErr = llvm::coverage::CoverageMapping::load(this->execPath, this->profPath, arch);

if (Error Err = CoverageOrErr.takeError())
{
errs() << "Error: Failed to load coverage: " << errorToErrorCode(Err).message() << “\n”;
return false;
}

But I cannot compile this code because of the copy constructor being marked as deleted.

error: use of deleted function ‘llvm::Error::Error(const llvm::Error&)’
/home/gagou/test/llvm/include/llvm/Support/Error.h:161:3: note: declared here
Error(const Error &Other) = delete;

I don’t know what I’m doing wrong, other files like SymbolizableObjectFile.cpp, ObjectFile.cpp IRObjectFile.cpp, etc seems to use the function errorToErrorCode() without any issue.

Does anyone know what is the best way to retrieve the message information from an Error object?

Thank you !

Regards,
Gael

Hi Gaël,

The copy constructor for the Error class has intentionally been marked as
deleted. My experience has been that this helps me write better error-handling
code, and ultimately makes debugging errors much easier. See Lang's excellent
write-up for more context:

    [RFC] Error handling in LLVM libraries
    http://lists.llvm.org/pipermail/llvm-dev/2016-February/095324.html

The "tl;dr" is that an Error is supposed to be unique, and has move-only
semantics.

Hi all,

I saw that some methods that was returning ErrorOr<> object are now returning Expected<> object embedding Error object instead of std::error_code. I have some troubles understanding how to use the new Error class...

Until now, I was using this kind of code :

auto BinOrErr = llvm::object::createBinary(this->execPath);

if(auto EC = BinOrErr.getError())
{
   errs() << "Error : " << EC.message() << "\n";
   return false;
}

This should now read:

    auto BinOrErr = llvm::object::createBinary(this->execPath);
    if (auto E = BinOrErr.takeError()) {
      errs() << "Error : " << llvm::toString(std::move(E)) << "\n";
      ...
    }

And this one:

auto CoverageOrErr = llvm::coverage::CoverageMapping::load(this->execPath, this->profPath, arch);

if (auto EC = CoverageOrErr.getError())
{
   errs() << "Error: Failed to load coverage: " << EC.message() << "\n";
   return false;
}

Since LLVM 3.9, load() and createBinary() return an Expected object. I managed to get the Error object using takeError() method (instead of the old getError()). But, since the Error object is not an std::error_code, I did not found a way to retrieve the message information... I tried to convert the Error object back to std::error_code using the function errorToErrorCode() like this:

auto CoverageOrErr = llvm::coverage::CoverageMapping::load(this->execPath, this->profPath, arch);

if (Error Err = CoverageOrErr.takeError())
{
   errs() << "Error: Failed to load coverage: " << errorToErrorCode(Err).message() << "\n";
   return false;
}

But I cannot compile this code because of the copy constructor being marked as deleted.

You need to give up ownership of "Err" before passing it into errorToErrorCode,
e.g:

    Error Err = ...;
    std::error_code EC = errorToErrorCode(std::move(Err));
    // The error pointed-to by Err has now been consumed ("destroyed").

Since you just want the error message, you could just write:

    Error Err = ...;
    errs() << toString(std::move(Err))

best,
vedant