Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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 @@ -21,11 +21,11 @@
#define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H

#include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.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>

Expand All @@ -38,12 +38,6 @@ 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 @@ -59,9 +53,6 @@ class LifetimeSafetyReporter {
Confidence Confidence) {}
};

// 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,
Expand Down Expand Up @@ -106,7 +97,6 @@ class LifetimeSafetyAnalysis {
std::unique_ptr<LoanPropagationAnalysis> LoanPropagation;
};
} // namespace internal

} // namespace clang::lifetimes

#endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_H
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//===- LifetimeStats.h - Miscellaneous statistics related to lifetime safety
//analysis ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------------------------------===//
//
// This file declares the data structures and utility function for collection of
// staticstics related to Lifetimesafety analysis.
//
//===----------------------------------------------------------------------------------------------===//

#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_LIFETIMESTATS_H
#define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_LIFETIMESTATS_H

#include "llvm/ADT/StringMap.h"

namespace clang::lifetimes {
/// A structure to hold the statistics related to LifetimeAnalysis.
/// Currently it holds only the missing origin details.
struct LifetimeSafetyStats {
/// A map from `ExpressionClassName<QualType>` to their missing origin
/// counts.
llvm::StringMap<unsigned> MissingOriginCount;
};

// utility function to print missing origin stats.
void printStats(const LifetimeSafetyStats &Stats);
} // namespace clang::lifetimes

#endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_LIFETIMESTATS_H
28 changes: 2 additions & 26 deletions clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,11 @@

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

namespace clang::lifetimes {

struct LifetimeSafetyStats;
} // namespace clang::lifetimes

namespace clang::lifetimes::internal {

using OriginID = utils::ID<struct OriginTag>;
Expand Down Expand Up @@ -87,9 +81,7 @@ class OriginManager {

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

const llvm::DenseMap<const clang::Expr *, OriginID> &
getExprToOriginId() const;

/// Collects statistics about expressions that lack associated origins.
void collectMissingOrigins(Stmt *FunctionBody, LifetimeSafetyStats &LSStats);

private:
Expand All @@ -102,22 +94,6 @@ class OriginManager {
llvm::DenseMap<const clang::ValueDecl *, OriginID> DeclToOriginID;
llvm::DenseMap<const clang::Expr *, OriginID> ExprToOriginID;
};

/// An utility class to traverse the function body in the analysis
/// context and collect the count of expressions with missing origins.
class MissingOriginCollector
: public RecursiveASTVisitor<MissingOriginCollector> {
public:
MissingOriginCollector(const OriginManager &om,
llvm::StringMap<unsigned> &MissingOriginCount)
: OM(om), MissingOriginCount(MissingOriginCount) {}
bool VisitExpr(Expr *E);

private:
const OriginManager &OM;
llvm::StringMap<unsigned> &MissingOriginCount;
};

} // namespace clang::lifetimes::internal

#endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_ORIGINS_H
4 changes: 1 addition & 3 deletions clang/include/clang/Sema/AnalysisBasedWarnings.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,9 @@
#include "clang/AST/Decl.h"
#include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h"
#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.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
1 change: 1 addition & 0 deletions clang/lib/Analysis/LifetimeSafety/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ add_clang_library(clangAnalysisLifetimeSafety
LifetimeAnnotations.cpp
LifetimeSafety.cpp
LiveOrigins.cpp
LifetimeStats.cpp
Loans.cpp
LoanPropagation.cpp
Origins.cpp
Expand Down
22 changes: 4 additions & 18 deletions clang/lib/Analysis/LifetimeSafety/LifetimeSafety.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,16 @@
#include "clang/Analysis/Analyses/LifetimeSafety/Checker.h"
#include "clang/Analysis/Analyses/LifetimeSafety/Facts.h"
#include "clang/Analysis/Analyses/LifetimeSafety/FactsGenerator.h"
#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.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 "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 @@ -81,25 +80,12 @@ void collectLifetimeStats(AnalysisDeclContext &AC, OriginManager &OM,
}
} // 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,
LifetimeSafetyStats &Stats, bool CollectStats) {
std::unique_ptr<internal::LifetimeSafetyAnalysis> Analysis =
std::make_unique<internal::LifetimeSafetyAnalysis>(AC, Reporter);
Analysis->run();
internal::LifetimeSafetyAnalysis Analysis(AC, Reporter);
Analysis.run();
if (CollectStats)
collectLifetimeStats(AC, Analysis->getFactManager().getOriginMgr(), Stats);
collectLifetimeStats(AC, Analysis.getFactManager().getOriginMgr(), Stats);
}
} // namespace clang::lifetimes
30 changes: 30 additions & 0 deletions clang/lib/Analysis/LifetimeSafety/LifetimeStats.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//===- LifetimeStats.cpp - Miscellaneous statistics related to C++ Lifetime
//Safety analysis -*--------- C++-*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the data structures and utility function for collection of
// staticstics related to Lifetimesafety analysis.
//
//===----------------------------------------------------------------------===//

#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h"
#include "llvm/Support/raw_ostream.h"

namespace clang::lifetimes {
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";
}
} // namespace clang::lifetimes
75 changes: 37 additions & 38 deletions clang/lib/Analysis/LifetimeSafety/Origins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,50 @@

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

namespace clang::lifetimes::internal {

static bool isGslPointerType(QualType QT) {
if (const auto *RD = QT->getAsCXXRecordDecl()) {
// We need to check the template definition for specializations.
if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
return CTSD->getSpecializedTemplate()
->getTemplatedDecl()
->hasAttr<PointerAttr>();
return RD->hasAttr<PointerAttr>();
}
return false;
}

static bool isPointerType(QualType QT) {
namespace {
bool isPointerType(QualType QT) {
return QT->isPointerOrReferenceType() || isGslPointerType(QT);
}
// Check if a type has an origin.
static bool hasOrigin(const Expr *E) {
bool hasOrigin(const Expr *E) {
return E->isGLValue() || isPointerType(E->getType());
}
/// An utility class to traverse the function body in the analysis
/// context and collect the count of expressions with missing origins.
class MissingOriginCollector
: public RecursiveASTVisitor<MissingOriginCollector> {
public:
MissingOriginCollector(
const llvm::DenseMap<const clang::Expr *, OriginID> &ExprToOriginId,
llvm::StringMap<unsigned> &MissingOriginCount)
: ExprToOriginId(ExprToOriginId), MissingOriginCount(MissingOriginCount) {
}
bool VisitExpr(Expr *E) {
if (!hasOrigin(E))
return true;
// Check if we have an origin for this expression.
auto It = this->ExprToOriginId.find(E);
if (It == this->ExprToOriginId.end()) {
// No origin found: count this as missing origin.
std::string ExprStr = std::string(E->getStmtClassName()) +
" (Type: " + E->getType().getAsString() + ")";
MissingOriginCount[ExprStr]++;
}
return true;
}

private:
const llvm::DenseMap<const clang::Expr *, OriginID> &ExprToOriginId;
llvm::StringMap<unsigned> &MissingOriginCount;
};
} // namespace

void OriginManager::dump(OriginID OID, llvm::raw_ostream &OS) const {
OS << OID << " (";
Expand Down Expand Up @@ -63,7 +82,6 @@ OriginID OriginManager::get(const Expr &E) {
auto It = ExprToOriginID.find(&E);
if (It != ExprToOriginID.end())
return It->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 Expand Up @@ -113,33 +131,14 @@ OriginID OriginManager::getOrCreate(const ValueDecl &D) {
return NewID;
}

const llvm::DenseMap<const clang::Expr *, OriginID> &
OriginManager::getExprToOriginId() const {
return ExprToOriginID;
}

void OriginManager::collectMissingOrigins(Stmt *FunctionBody,
LifetimeSafetyStats &LSStats) {
if (!FunctionBody)
return;

MissingOriginCollector Collector(*this, LSStats.MissingOriginCount);
MissingOriginCollector Collector(this->ExprToOriginID,
LSStats.MissingOriginCount);
Collector.TraverseStmt(const_cast<Stmt *>(FunctionBody));
}

bool MissingOriginCollector::VisitExpr(Expr *E) {
if (!hasOrigin(E))
return true;
// Check if we have an origin for this expression
const auto &ExprToOriginId = OM.getExprToOriginId();
auto It = ExprToOriginId.find(E);
if (It == ExprToOriginId.end()) {
// No origin found - count this as missing
std::string ExprStr = std::string(E->getStmtClassName()) + "<" +
E->getType().getAsString() + ">";
MissingOriginCount[ExprStr]++;
}
return true;
}

} // namespace clang::lifetimes::internal
5 changes: 1 addition & 4 deletions clang/lib/Sema/AnalysisBasedWarnings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@
#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 @@ -49,7 +47,6 @@
#include "clang/Sema/SemaInternal.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/SmallVector.h"
Expand Down Expand Up @@ -3178,8 +3175,8 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
}

void clang::sema::AnalysisBasedWarnings::PrintStats() const {

llvm::errs() << "\n*** Analysis Based Warnings Stats:\n";

unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs;
unsigned AvgCFGBlocksPerFunction =
!NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt;
Expand Down