Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@
#include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
#include "clang/Analysis/Analyses/LifetimeSafety/LiveOrigins.h"
#include "clang/Analysis/Analyses/LifetimeSafety/LoanPropagation.h"
#include "clang/Analysis/Analyses/LifetimeSafety/Origins.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/raw_ostream.h"
#include <string>

namespace clang::lifetimes {

Expand All @@ -34,6 +38,12 @@ enum class Confidence : uint8_t {
Definite // Reported as a definite error (-Wlifetime-safety-permissive)
};

/// A structure to hold the statistics related to LifetimeAnalysis.
/// Curently it holds only the missing origin details.
struct LifetimeSafetyStats {
llvm::StringMap<unsigned> MissingOriginCount;
};

class LifetimeSafetyReporter {
public:
LifetimeSafetyReporter() = default;
Expand All @@ -44,10 +54,6 @@ class LifetimeSafetyReporter {
Confidence Confidence) {}
};

/// The main entry point for the analysis.
void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
LifetimeSafetyReporter *Reporter);

namespace internal {
/// An object to hold the factories for immutable collections, ensuring
/// that all created states share the same underlying memory management.
Expand All @@ -60,6 +66,7 @@ struct LifetimeFactory {
/// Running the lifetime safety analysis and querying its results. It
/// encapsulates the various dataflow analyses.
class LifetimeSafetyAnalysis {

public:
LifetimeSafetyAnalysis(AnalysisDeclContext &AC,
LifetimeSafetyReporter *Reporter);
Expand All @@ -82,6 +89,15 @@ class LifetimeSafetyAnalysis {
std::unique_ptr<LoanPropagationAnalysis> LoanPropagation;
};
} // namespace internal

// utility function to print missing origin stats.
void PrintStats(const LifetimeSafetyStats &Stats);

/// The main entry point for the analysis.
void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
LifetimeSafetyReporter *Reporter,
LifetimeSafetyStats &Stats, bool CollectStats);

} // namespace clang::lifetimes

#endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@

#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/TypeBase.h"
#include "clang/Analysis/Analyses/LifetimeSafety/Utils.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/raw_ostream.h"

namespace clang::lifetimes::internal {

Expand Down Expand Up @@ -78,6 +81,8 @@ class OriginManager {

void dump(OriginID OID, llvm::raw_ostream &OS) const;

const llvm::StringMap<unsigned> getMissingOrigins() const;

private:
OriginID getNextOriginID() { return NextOriginID++; }

Expand All @@ -87,6 +92,7 @@ class OriginManager {
llvm::SmallVector<Origin> AllOrigins;
llvm::DenseMap<const clang::ValueDecl *, OriginID> DeclToOriginID;
llvm::DenseMap<const clang::Expr *, OriginID> ExprToOriginID;
llvm::StringMap<unsigned> ExprTypeToMissingOriginCount;
};
} // namespace clang::lifetimes::internal

Expand Down
7 changes: 7 additions & 0 deletions clang/include/clang/Sema/AnalysisBasedWarnings.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@
#define LLVM_CLANG_SEMA_ANALYSISBASEDWARNINGS_H

#include "clang/AST/Decl.h"
#include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h"
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Sema/ScopeInfo.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringMap.h"
#include <memory>

namespace clang {
Expand Down Expand Up @@ -101,6 +105,9 @@ class AnalysisBasedWarnings {
/// a single function.
unsigned MaxUninitAnalysisBlockVisitsPerFunction;

/// Map from expressions missing origin in OriginManager to their counts.
clang::lifetimes::LifetimeSafetyStats LSStats;

/// @}

public:
Expand Down
26 changes: 23 additions & 3 deletions clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CFG.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/Support/raw_ostream.h"
#include <memory>

namespace clang::lifetimes {
Expand Down Expand Up @@ -70,9 +72,27 @@ void LifetimeSafetyAnalysis::run() {
}
} // namespace internal

void PrintStats(const LifetimeSafetyStats &Stats) {
llvm::errs() << "\n*** LifetimeSafety Missing Origin Stats "
"(expression_type : count) :\n\n";
unsigned totalMissingOrigins = 0;
for (const auto &[expr, count] : Stats.MissingOriginCount) {
llvm::errs() << expr << " : " << count << '\n';
totalMissingOrigins += count;
}
llvm::errs() << "Total missing origins: " << totalMissingOrigins << "\n";
llvm::errs() << "\n****************************************\n";
}

void runLifetimeSafetyAnalysis(AnalysisDeclContext &AC,
LifetimeSafetyReporter *Reporter) {
internal::LifetimeSafetyAnalysis Analysis(AC, Reporter);
Analysis.run();
LifetimeSafetyReporter *Reporter,
LifetimeSafetyStats &Stats, bool CollectStats) {
std::unique_ptr<internal::LifetimeSafetyAnalysis> Analysis =
std::make_unique<internal::LifetimeSafetyAnalysis>(AC, Reporter);
Analysis->run();
for (const auto &[expr, count] :
Analysis->getFactManager().getOriginMgr().getMissingOrigins()) {
Stats.MissingOriginCount[expr] += count;
}
}
} // namespace clang::lifetimes
18 changes: 18 additions & 0 deletions clang/lib/Analysis/LifetimeSafety/Origins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
//===----------------------------------------------------------------------===//

#include "clang/Analysis/Analyses/LifetimeSafety/Origins.h"
#include "clang/AST/Expr.h"
#include "clang/AST/TypeBase.h"
#include "llvm/ADT/StringMap.h"

namespace clang::lifetimes::internal {

Expand All @@ -22,6 +25,10 @@ void OriginManager::dump(OriginID OID, llvm::raw_ostream &OS) const {
OS << ")";
}

const llvm::StringMap<unsigned> OriginManager::getMissingOrigins() const {
return ExprTypeToMissingOriginCount;
}

Origin &OriginManager::addOrigin(OriginID ID, const clang::ValueDecl &D) {
AllOrigins.emplace_back(ID, &D);
return AllOrigins.back();
Expand All @@ -39,6 +46,17 @@ OriginID OriginManager::get(const Expr &E) {
auto It = ExprToOriginID.find(&E);
if (It != ExprToOriginID.end())
return It->second;

// if the expression has no specific origin, increment the missing origin
// counter.
std::string ExprStr(E.getStmtClassName());
ExprStr = ExprStr + "<" + E.getType().getAsString() + ">";
auto CountIt = ExprTypeToMissingOriginCount.find(ExprStr);
if (CountIt == ExprTypeToMissingOriginCount.end()) {
ExprTypeToMissingOriginCount[ExprStr] = 1;
} else {
CountIt->second++;
}
// If the expression itself has no specific origin, and it's a reference
// to a declaration, its origin is that of the declaration it refers to.
// For pointer types, where we don't pre-emptively create an origin for the
Expand Down
10 changes: 8 additions & 2 deletions clang/lib/Sema/AnalysisBasedWarnings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
#include "clang/Analysis/Analyses/CalledOnceCheck.h"
#include "clang/Analysis/Analyses/Consumed.h"
#include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h"
#include "clang/Analysis/Analyses/LifetimeSafety/Origins.h"
#include "clang/Analysis/Analyses/ReachableCode.h"
#include "clang/Analysis/Analyses/ThreadSafety.h"
#include "clang/Analysis/Analyses/UninitializedValues.h"
Expand All @@ -52,7 +54,9 @@
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <deque>
#include <iterator>
Expand Down Expand Up @@ -3092,7 +3096,8 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
if (EnableLifetimeSafetyAnalysis && S.getLangOpts().CPlusPlus) {
if (AC.getCFG()) {
lifetimes::LifetimeSafetyReporterImpl LifetimeSafetyReporter(S);
lifetimes::runLifetimeSafetyAnalysis(AC, &LifetimeSafetyReporter);
lifetimes::runLifetimeSafetyAnalysis(AC, &LifetimeSafetyReporter, LSStats,
S.CollectStats);
}
}
// Check for violations of "called once" parameter properties.
Expand Down Expand Up @@ -3159,8 +3164,9 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
}

void clang::sema::AnalysisBasedWarnings::PrintStats() const {
llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";

clang::lifetimes::PrintStats(LSStats);
llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";
unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
unsigned AvgCFGBlocksPerFunction =
!NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
Expand Down