-
Notifications
You must be signed in to change notification settings - Fork 15.7k
[LifetimeSafety] Add missing origins stats for lifetime analysis #166568
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 17 commits
fd8693c
3ff81d6
984582f
499d3b0
f274e84
8341778
56b2dd9
0081a95
0ca0f58
a30fa2e
8264809
6f123ed
06f232e
ea1eca9
f0d444c
cf92f90
f0dab14
e03a850
2f68912
0bf4b2f
27a4b26
afe33b2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| //===- LifetimeStats.h - Lifetime Safety Statistics --------------*- 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 | ||
| // statistics related to Lifetime Safety analysis. | ||
| // | ||
| //===------------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_LIFETIMESTATS_H | ||
| #define LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_LIFETIMESTATS_H | ||
|
|
||
| #include "clang/AST/TypeBase.h" | ||
| #include "llvm/ADT/DenseMap.h" | ||
| #include "llvm/ADT/StringMap.h" | ||
|
|
||
| namespace clang::lifetimes { | ||
| /// A structure to hold the statistics related to LifetimeAnalysis. | ||
| /// These are accumulated across all analyzed functions and printed | ||
| /// when -print-stats is enabled. | ||
| struct LifetimeSafetyStats { | ||
| /// A map from `StmtClassName` to their missing origin counts. | ||
| llvm::StringMap<unsigned> ExprStmtClassToMissingOriginCount; | ||
| /// A map from `QualType` to their missing origin counts. | ||
| llvm::DenseMap<const clang::Type *, unsigned> ExprTypeToMissingOriginCount; | ||
| }; | ||
|
|
||
| /// Utility function to print missing origin stats. | ||
| void printStats(const LifetimeSafetyStats &Stats); | ||
| } // namespace clang::lifetimes | ||
|
|
||
| #endif // LLVM_CLANG_ANALYSIS_ANALYSES_LIFETIMESAFETY_LIFETIMESTATS_H | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| //===- LifetimeStats.cpp - Lifetime Safety Statistics -*------------ 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 "clang/AST/TypeBase.h" | ||
| #include "llvm/Support/raw_ostream.h" | ||
|
|
||
| namespace clang::lifetimes { | ||
| void printStats(const LifetimeSafetyStats &Stats) { | ||
| llvm::errs() << "\n*** LifetimeSafety Missing Origin per QualType: " | ||
| "(QualType : count) :\n\n"; | ||
| unsigned TotalMissingOrigins = 0; | ||
| for (const auto &[ExprType, MissingOriginCount] : Stats.ExprTypeToMissingOriginCount) { | ||
| QualType QT = QualType(ExprType, 0); | ||
| llvm::errs() << QT.getAsString() << " : " << MissingOriginCount << '\n'; | ||
| TotalMissingOrigins += MissingOriginCount; | ||
| } | ||
| llvm::errs() << "\n\n*** LifetimeSafety Missing Origin per StmtClassName: " | ||
| "(StmtClassName : count) :\n\n"; | ||
| for (const auto &[ExprStmtClassName, MissingOriginCount] : Stats.ExprStmtClassToMissingOriginCount) { | ||
| llvm::errs() << ExprStmtClassName << " : " << MissingOriginCount << '\n'; | ||
| } | ||
| llvm::errs() << "\nTotal missing origins: " << TotalMissingOrigins << "\n"; | ||
| llvm::errs() << "\n****************************************\n"; | ||
| } | ||
| } // namespace clang::lifetimes |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,10 @@ | |
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "clang/Analysis/Analyses/LifetimeSafety/Origins.h" | ||
| #include "clang/AST/Expr.h" | ||
| #include "clang/AST/RecursiveASTVisitor.h" | ||
| #include "clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h" | ||
| #include "llvm/ADT/StringMap.h" | ||
| #include "clang/AST/ASTContext.h" | ||
| #include "clang/AST/Attr.h" | ||
| #include "clang/AST/DeclCXX.h" | ||
|
|
@@ -15,6 +19,34 @@ | |
| #include "clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h" | ||
|
|
||
| namespace clang::lifetimes::internal { | ||
| namespace { | ||
| /// A 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, | ||
| LifetimeSafetyStats &LSStats) | ||
| : ExprToOriginId(ExprToOriginId), LSStats(LSStats) {} | ||
| bool VisitExpr(Expr *E) { | ||
| if (!hasOrigin(E)) | ||
| return true; | ||
| // Check if we have an origin for this expression. | ||
| if (!ExprToOriginId.contains(E)) { | ||
| // No origin found: count this as missing origin. | ||
| LSStats.ExprTypeToMissingOriginCount[E->getType().getTypePtr()]++; | ||
| LSStats.ExprStmtClassToMissingOriginCount[std::string( | ||
| E->getStmtClassName())]++; | ||
| } | ||
| return true; | ||
| } | ||
|
|
||
| private: | ||
| const llvm::DenseMap<const clang::Expr *, OriginID> &ExprToOriginId; | ||
| LifetimeSafetyStats &LSStats; | ||
| }; | ||
| } // namespace | ||
|
|
||
| bool hasOrigins(QualType QT) { | ||
| return QT->isPointerOrReferenceType() || isGslPointerType(QT); | ||
|
|
@@ -157,4 +189,20 @@ const Origin &OriginManager::getOrigin(OriginID ID) const { | |
| return AllOrigins[ID.Value]; | ||
| } | ||
|
|
||
| OriginID OriginManager::getOrCreate(const ValueDecl &D) { | ||
|
||
| auto It = DeclToOriginID.find(&D); | ||
| if (It != DeclToOriginID.end()) | ||
| return It->second; | ||
| OriginID NewID = getNextOriginID(); | ||
| addOrigin(NewID, D); | ||
| DeclToOriginID[&D] = NewID; | ||
| return NewID; | ||
| } | ||
|
|
||
| void OriginManager::collectMissingOrigins(Stmt &FunctionBody, | ||
| LifetimeSafetyStats &LSStats) { | ||
| MissingOriginCollector Collector(this->ExprToOriginID, LSStats); | ||
| Collector.TraverseStmt(const_cast<Stmt *>(&FunctionBody)); | ||
| } | ||
|
|
||
| } // namespace clang::lifetimes::internal | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| // RUN: %clang_cc1 -print-stats -fexperimental-lifetime-safety -Wexperimental-lifetime-safety %s 2>&1 | FileCheck %s | ||
|
|
||
|
|
||
| // CHECK: *** LifetimeSafety Missing Origin per QualType: (QualType : count) : | ||
| // CHECK: *** LifetimeSafety Missing Origin per StmtClassName: (StmtClassName : count) : |
Uh oh!
There was an error while loading. Please reload this page.