[clang][SSAF] Allow no Data for summary analysis (#211342)

Extractors might not always add summaries for all the TUs. If they don't
add any summaries to the TU result, then loading this summary for a
summary analysis would cause a failure.

This patch handles the situation gracefully by accepting such cases.

Split from: #209354

---------

Co-authored-by: Ziqing Luo <ziqing_luo@apple.com>
This commit is contained in:
Balázs Benics 2026-07-23 09:13:59 +01:00 committed by GitHub
parent beca2e90e6
commit 64b593c237
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 33 additions and 37 deletions

View file

@ -102,30 +102,16 @@ AnalysisDriver::toposort(llvm::ArrayRef<AnalysisName> Roots) {
llvm::Error AnalysisDriver::executeSummaryAnalysis(SummaryAnalysisBase &Summary,
WPASuite &Suite) const {
SummaryName SN = Summary.getSummaryName();
auto DataIt = LU->Data.find(SN);
if (DataIt == LU->Data.end()) {
return ErrorBuilder::create(std::errc::invalid_argument,
"no data for analysis '{0}' in LUSummary",
Summary.getAnalysisName())
.build();
}
if (auto Err = Summary.initialize()) {
if (auto Err = Summary.initialize())
return Err;
}
for (auto &[Id, EntitySummary] : DataIt->second) {
if (auto Err = Summary.add(Id, *EntitySummary)) {
return Err;
}
auto DataIt = LU->Data.find(Summary.getSummaryName());
if (DataIt != LU->Data.end()) {
for (auto &[Id, EntitySummary] : DataIt->second)
if (auto Err = Summary.add(Id, *EntitySummary))
return Err;
}
if (auto Err = Summary.finalize()) {
return Err;
}
return llvm::Error::success();
return Summary.finalize();
}
llvm::Error AnalysisDriver::executeDerivedAnalysis(DerivedAnalysisBase &Derived,

View file

@ -15,13 +15,13 @@
// UNKNOWN: no analysis registered for 'AnalysisName(NoSuchAnalysis)'
// ============================================================================
// Error: valid analysis name but LUSummary lacks entity data for it
// Success: Analyses might not add summaries in every run.
// Valid analysis name but LUSummary lacks entity data for it is not an error.
// ============================================================================
// RUN: not %clang-ssaf-analyzer-with-plugin %S/Inputs/lu-tags-only.json \
// RUN: %clang-ssaf-analyzer-with-plugin %S/Inputs/lu-tags-only.json \
// RUN: -o %t/missing-data.json -a PairsAnalysisResult 2>&1 \
// RUN: | FileCheck %s --check-prefix=MISSING-DATA
// MISSING-DATA: no data for analysis 'AnalysisName(PairsAnalysisResult)' in LUSummary
// RUN: | count 0
// ============================================================================
// Success: run TagsAnalysisResult only (single analysis)

View file

@ -468,15 +468,20 @@ TEST_F(AnalysisDriverTest, RunByName) {
"no result for 'AnalysisName(Analysis2)' in WPASuite"));
}
// run(names) — error when a requested name has no data in LUSummary.
TEST_F(AnalysisDriverTest, RunByNameErrorMissingData) {
// run(names) — a requested name with no data in the LUSummary yields an empty
// (but initialized and finalized) result rather than an error.
TEST_F(AnalysisDriverTest, RunByNameEmptyWhenMissingData) {
auto LU = makeLUSummary();
AnalysisDriver Driver(std::move(LU));
EXPECT_THAT_EXPECTED(
Driver.run({AnalysisName("Analysis1")}),
llvm::FailedWithMessage(
"no data for analysis 'AnalysisName(Analysis1)' in LUSummary"));
auto WPAOrErr = Driver.run({AnalysisName("Analysis1")});
ASSERT_THAT_EXPECTED(WPAOrErr, llvm::Succeeded());
auto R1OrErr = WPAOrErr->get<Analysis1Result>();
ASSERT_THAT_EXPECTED(R1OrErr, llvm::Succeeded());
EXPECT_TRUE(R1OrErr->Entries.empty());
EXPECT_TRUE(R1OrErr->WasInitialized);
EXPECT_TRUE(R1OrErr->WasFinalized);
}
// run(names) — error when a requested name has no registered analysis.
@ -522,15 +527,20 @@ TEST_F(AnalysisDriverTest, RunByType) {
"no result for 'AnalysisName(Analysis2)' in WPASuite"));
}
// run<ResultTs...>() — error when a requested type has no data in LUSummary.
TEST_F(AnalysisDriverTest, RunByTypeErrorMissingData) {
// run<ResultTs...>() — a requested type with no data in the LUSummary yields an
// empty (but initialized and finalized) result rather than an error.
TEST_F(AnalysisDriverTest, RunByTypeEmptyWhenMissingData) {
auto LU = makeLUSummary();
AnalysisDriver Driver(std::move(LU));
EXPECT_THAT_EXPECTED(
Driver.run<Analysis1Result>(),
llvm::FailedWithMessage(
"no data for analysis 'AnalysisName(Analysis1)' in LUSummary"));
auto WPAOrErr = Driver.run<Analysis1Result>();
ASSERT_THAT_EXPECTED(WPAOrErr, llvm::Succeeded());
auto R1OrErr = WPAOrErr->get<Analysis1Result>();
ASSERT_THAT_EXPECTED(R1OrErr, llvm::Succeeded());
EXPECT_TRUE(R1OrErr->Entries.empty());
EXPECT_TRUE(R1OrErr->WasInitialized);
EXPECT_TRUE(R1OrErr->WasFinalized);
}
// contains() — present entries return true; absent entries return false.