[analyzer][ctu] Reland "Avoid parsing invocation list again and again..

..during on-demand parsing of CTU"

During CTU, the *on-demand parsing* will read and parse the invocation
list to know how to compile the file being imported. However, it seems
that the invocation list will be parsed again if a previous parsing
has failed.
Then, parse again and fail again. This patch tries to overcome the
problem by storing the error code during the first parsing, and
re-create the stored error during the later parsings.

Reland without test.

Reviewed By: steakhal

Patch By: OikawaKirie!

Differential Revision: https://reviews.llvm.org/D101763
This commit is contained in:
Ella Ma 2021-05-25 09:42:16 +02:00 committed by Balazs Benics
parent ff30436dc5
commit d59b4acf80
2 changed files with 19 additions and 5 deletions

View File

@ -38,6 +38,7 @@ class TranslationUnitDecl;
namespace cross_tu {
enum class index_error_code {
success = 0,
unspecified = 1,
missing_index_file,
invalid_index_format,
@ -253,6 +254,7 @@ private:
/// In case of on-demand parsing, the invocations for parsing the source
/// files is stored.
llvm::Optional<InvocationListTy> InvocationList;
index_error_code PreviousParsingResult = index_error_code::success;
};
/// Maintain number of AST loads and check for reaching the load limit.

View File

@ -92,6 +92,10 @@ public:
std::string message(int Condition) const override {
switch (static_cast<index_error_code>(Condition)) {
case index_error_code::success:
// There should not be a success error. Jump to unreachable directly.
// Add this case to make the compiler stop complaining.
break;
case index_error_code::unspecified:
return "An unknown error has occurred.";
case index_error_code::missing_index_file:
@ -667,12 +671,15 @@ llvm::Error CrossTranslationUnitContext::ASTLoader::lazyInitInvocationList() {
/// Lazily initialize the invocation list member used for on-demand parsing.
if (InvocationList)
return llvm::Error::success();
if (index_error_code::success != PreviousParsingResult)
return llvm::make_error<IndexError>(PreviousParsingResult);
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileContent =
llvm::MemoryBuffer::getFile(InvocationListFilePath);
if (!FileContent)
return llvm::make_error<IndexError>(
index_error_code::invocation_list_file_not_found);
if (!FileContent) {
PreviousParsingResult = index_error_code::invocation_list_file_not_found;
return llvm::make_error<IndexError>(PreviousParsingResult);
}
std::unique_ptr<llvm::MemoryBuffer> ContentBuffer = std::move(*FileContent);
assert(ContentBuffer && "If no error was produced after loading, the pointer "
"should not be nullptr.");
@ -680,8 +687,13 @@ llvm::Error CrossTranslationUnitContext::ASTLoader::lazyInitInvocationList() {
llvm::Expected<InvocationListTy> ExpectedInvocationList =
parseInvocationList(ContentBuffer->getBuffer(), PathStyle);
if (!ExpectedInvocationList)
return ExpectedInvocationList.takeError();
// Handle the error to store the code for next call to this function.
if (!ExpectedInvocationList) {
llvm::handleAllErrors(
ExpectedInvocationList.takeError(),
[&](const IndexError &E) { PreviousParsingResult = E.getCode(); });
return llvm::make_error<IndexError>(PreviousParsingResult);
}
InvocationList = *ExpectedInvocationList;