[llvm-branch-commits] [clang] Fix lifetimebound for field access (#100197) (PR #100725)

2024-07-26 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 created 
https://github.com/llvm/llvm-project/pull/100725

Fixes: https://github.com/llvm/llvm-project/issues/81589

There is no way to switch this off without  `-Wno-dangling`.

>From f9e213895548bfaba21399cb337688e8f3839a3a Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Wed, 24 Jul 2024 15:58:52 +0200
Subject: [PATCH] Fix lifetimebound for field access (#100197)

Fixes: https://github.com/llvm/llvm-project/issues/81589

There is no way to switch this off without  `-Wno-dangling`.
---
 clang/docs/ReleaseNotes.rst   |  3 +++
 clang/lib/Sema/CheckExprLifetime.cpp  |  9 
 clang/test/SemaCXX/attr-lifetimebound.cpp | 26 +++
 3 files changed, 38 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 549da6812740f..71d615553c613 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -767,6 +767,9 @@ Improvements to Clang's diagnostics
 
 - Clang now diagnoses undefined behavior in constant expressions more 
consistently. This includes invalid shifts, and signed overflow in arithmetic.
 
+- Clang now diagnoses dangling references to fields of temporary objects. 
Fixes #GH81589.
+
+
 Improvements to Clang's time-trace
 --
 
diff --git a/clang/lib/Sema/CheckExprLifetime.cpp 
b/clang/lib/Sema/CheckExprLifetime.cpp
index 5c8ef564f30aa..112cf3d081822 100644
--- a/clang/lib/Sema/CheckExprLifetime.cpp
+++ b/clang/lib/Sema/CheckExprLifetime.cpp
@@ -7,6 +7,7 @@
 
//===--===//
 
 #include "CheckExprLifetime.h"
+#include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
 #include "clang/Basic/DiagnosticSema.h"
 #include "clang/Sema/Initialization.h"
@@ -548,6 +549,14 @@ static void 
visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path,
EnableLifetimeWarnings);
   }
 
+  if (auto *M = dyn_cast(Init)) {
+// Lifetime of a non-reference type field is same as base object.
+if (auto *F = dyn_cast(M->getMemberDecl());
+F && !F->getType()->isReferenceType())
+  visitLocalsRetainedByInitializer(Path, M->getBase(), Visit, true,
+   EnableLifetimeWarnings);
+  }
+
   if (isa(Init)) {
 if (EnableLifetimeWarnings)
   handleGslAnnotatedTypes(Path, Init, Visit);
diff --git a/clang/test/SemaCXX/attr-lifetimebound.cpp 
b/clang/test/SemaCXX/attr-lifetimebound.cpp
index 70bc545c07bd9..7db0a4d64d259 100644
--- a/clang/test/SemaCXX/attr-lifetimebound.cpp
+++ b/clang/test/SemaCXX/attr-lifetimebound.cpp
@@ -47,6 +47,31 @@ namespace usage_ok {
 q = A(); // expected-warning {{object backing the pointer q will be 
destroyed at the end of the full-expression}}
 r = A(1); // expected-warning {{object backing the pointer r will be 
destroyed at the end of the full-expression}}
   }
+
+  struct FieldCheck {
+struct Set {
+  int a;
+};
+struct Pair {
+  const int& a;
+  int b;
+  Set c;
+  int * d;
+};
+Pair p;  
+FieldCheck(const int& a): p(a){}
+Pair& getR() [[clang::lifetimebound]] { return p; }
+Pair* getP() [[clang::lifetimebound]] { return &p; }
+Pair* getNoLB() { return &p; }
+  };
+  void test_field_access() {
+int x = 0;
+const int& a = FieldCheck{x}.getR().a;
+const int& b = FieldCheck{x}.getP()->b;   // expected-warning {{temporary 
bound to local reference 'b' will be destroyed at the end of the 
full-expression}}
+const int& c = FieldCheck{x}.getP()->c.a; // expected-warning {{temporary 
bound to local reference 'c' will be destroyed at the end of the 
full-expression}}
+const int& d = FieldCheck{x}.getNoLB()->c.a;
+const int* e = FieldCheck{x}.getR().d;
+  }
 }
 
 # 1 "" 1 3
@@ -239,3 +264,4 @@ namespace move_forward_et_al_examples {
   S X;
   S *AddressOfOk = std::addressof(X);
 } // namespace move_forward_et_al_examples
+

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] Fix lifetimebound for field access (#100197) (PR #100725)

2024-07-26 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 milestoned 
https://github.com/llvm/llvm-project/pull/100725
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [codegen] Emit missing cleanups for stmt-expr and coro suspensions [take-2] (PR #85398)

2024-03-31 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/85398
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang-tools-extra] a4f3866 - [clangd] Remove "decision-forest-base" experimental flag.

2021-01-13 Thread Utkarsh Saxena via llvm-branch-commits

Author: Utkarsh Saxena
Date: 2021-01-13T17:54:38+01:00
New Revision: a4f386688239b06e09f28fd31f93bf761aa9c76f

URL: 
https://github.com/llvm/llvm-project/commit/a4f386688239b06e09f28fd31f93bf761aa9c76f
DIFF: 
https://github.com/llvm/llvm-project/commit/a4f386688239b06e09f28fd31f93bf761aa9c76f.diff

LOG: [clangd] Remove "decision-forest-base" experimental flag.

The value of this flag can only be fine tuned by using A/B testing on large
user base.
We do not expect individual users to use and fine tune this flag.

Differential Revision: https://reviews.llvm.org/D94513

Added: 


Modified: 
clang-tools-extra/clangd/tool/ClangdMain.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp 
b/clang-tools-extra/clangd/tool/ClangdMain.cpp
index d2c52cf61c53..9c75cafdb08e 100644
--- a/clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -194,14 +194,6 @@ opt 
RankingModel{
 Hidden,
 };
 
-opt DecisionForestBase{
-"decision-forest-base",
-cat(Features),
-desc("Base for exponentiating the prediction from DecisionForest."),
-init(CodeCompleteOptions().DecisionForestBase),
-Hidden,
-};
-
 // FIXME: also support "plain" style where signatures are always omitted.
 enum CompletionStyleFlag { Detailed, Bundled };
 opt CompletionStyle{
@@ -841,7 +833,6 @@ clangd accepts flags on the commandline, and in the 
CLANGD_FLAGS environment var
   Opts.CodeComplete.AllScopes = AllScopesCompletion;
   Opts.CodeComplete.RunParser = CodeCompletionParse;
   Opts.CodeComplete.RankingModel = RankingModel;
-  Opts.CodeComplete.DecisionForestBase = DecisionForestBase;
 
   RealThreadsafeFS TFS;
   std::vector> ProviderStack;



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang-tools-extra] 2f395b7 - [clangd] Make AST-based signals available to runWithPreamble.

2021-01-14 Thread Utkarsh Saxena via llvm-branch-commits

Author: Utkarsh Saxena
Date: 2021-01-14T18:34:50+01:00
New Revision: 2f395b7092bdac0e39bb4e2bb5e6b03e521a45dd

URL: 
https://github.com/llvm/llvm-project/commit/2f395b7092bdac0e39bb4e2bb5e6b03e521a45dd
DIFF: 
https://github.com/llvm/llvm-project/commit/2f395b7092bdac0e39bb4e2bb5e6b03e521a45dd.diff

LOG: [clangd] Make AST-based signals available to runWithPreamble.

Many useful signals can be derived from a valid AST which is regularly updated 
by
the ASTWorker. `runWithPreamble` does not have access to the ParsedAST
but it can be provided access to some signals derived from a (possibly
stale) AST.

Differential Revision: https://reviews.llvm.org/D94424

Added: 
clang-tools-extra/clangd/ASTSignals.cpp
clang-tools-extra/clangd/ASTSignals.h
clang-tools-extra/clangd/unittests/ASTSignalsTests.cpp

Modified: 
clang-tools-extra/clangd/CMakeLists.txt
clang-tools-extra/clangd/TUScheduler.cpp
clang-tools-extra/clangd/TUScheduler.h
clang-tools-extra/clangd/unittests/CMakeLists.txt
clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/ASTSignals.cpp 
b/clang-tools-extra/clangd/ASTSignals.cpp
new file mode 100644
index ..da849287bbf6
--- /dev/null
+++ b/clang-tools-extra/clangd/ASTSignals.cpp
@@ -0,0 +1,42 @@
+//===--- ASTSignals.cpp - LSP server -*- 
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
+//
+//===--===//
+
+#include "ASTSignals.h"
+#include "AST.h"
+#include "FindTarget.h"
+
+namespace clang {
+namespace clangd {
+ASTSignals ASTSignals::derive(const ParsedAST &AST) {
+  ASTSignals Signals;
+  const SourceManager &SM = AST.getSourceManager();
+  findExplicitReferences(AST.getASTContext(), [&](ReferenceLoc Ref) {
+for (const NamedDecl *ND : Ref.Targets) {
+  if (!isInsideMainFile(Ref.NameLoc, SM))
+continue;
+  SymbolID ID = getSymbolID(ND);
+  if (!ID)
+continue;
+  unsigned &SymbolCount = Signals.ReferencedSymbols[ID];
+  SymbolCount++;
+  // Process namespace only when we see the symbol for the first time.
+  if (SymbolCount != 1)
+continue;
+  if (const auto *NSD = dyn_cast(ND->getDeclContext())) {
+if (NSD->isAnonymousNamespace())
+  continue;
+std::string NS = printNamespaceScope(*NSD);
+if (!NS.empty())
+  Signals.RelatedNamespaces[NS]++;
+  }
+}
+  });
+  return Signals;
+}
+} // namespace clangd
+} // namespace clang

diff  --git a/clang-tools-extra/clangd/ASTSignals.h 
b/clang-tools-extra/clangd/ASTSignals.h
new file mode 100644
index ..bc70cd17310a
--- /dev/null
+++ b/clang-tools-extra/clangd/ASTSignals.h
@@ -0,0 +1,39 @@
+//===--- ASTSignals.h - LSP server ---*- 
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
+//
+//===--===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_ASTSIGNALS_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_ASTSIGNALS_H
+
+#include "ParsedAST.h"
+#include "index/SymbolID.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace clang {
+namespace clangd {
+
+/// Signals derived from a valid AST of a file.
+/// Provides information that can only be extracted from the AST to actions 
that
+/// can't access an AST. The signals are computed and updated asynchronously by
+/// the ASTWorker and thus they are always stale and also can be absent.
+/// Example usage: Information about the declarations used in a file affects
+/// code-completion ranking in that file.
+struct ASTSignals {
+  /// Number of occurrences of each symbol present in the file.
+  llvm::DenseMap ReferencedSymbols;
+  /// Namespaces whose symbols are used in the file, and the number of such
+  /// distinct symbols.
+  llvm::StringMap RelatedNamespaces;
+
+  static ASTSignals derive(const ParsedAST &AST);
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_ASTSIGNALS_H

diff  --git a/clang-tools-extra/clangd/CMakeLists.txt 
b/clang-tools-extra/clangd/CMakeLists.txt
index 9e62e0948027..1d12e7e2355d 100644
--- a/clang-tools-extra/clangd/CMakeLists.txt
+++ b/clang-tools-extra/clangd/CMakeLists.txt
@@ -46,6 +46,7 @@ include_directories(BEFORE 
"${CMAKE_CURRENT_BINARY_DIR}/../clang-tidy")
 
 add_clang_library(clangDaemon
   AST.cpp
+  ASTSignals.cpp
   ClangdLSPServer.cpp
   ClangdServer.cpp
   CodeComplete.cpp

diff  --git a/clang-tools-

[llvm-branch-commits] [clang-tools-extra] 8b09cf7 - [clangd] Trivial: Documentation fix in ASTSignals.

2021-01-14 Thread Utkarsh Saxena via llvm-branch-commits

Author: Utkarsh Saxena
Date: 2021-01-14T18:38:42+01:00
New Revision: 8b09cf7956d8abc722fa736874e4cea667a9d3cb

URL: 
https://github.com/llvm/llvm-project/commit/8b09cf7956d8abc722fa736874e4cea667a9d3cb
DIFF: 
https://github.com/llvm/llvm-project/commit/8b09cf7956d8abc722fa736874e4cea667a9d3cb.diff

LOG: [clangd] Trivial: Documentation fix in ASTSignals.

Added: 


Modified: 
clang-tools-extra/clangd/ASTSignals.cpp
clang-tools-extra/clangd/ASTSignals.h

Removed: 




diff  --git a/clang-tools-extra/clangd/ASTSignals.cpp 
b/clang-tools-extra/clangd/ASTSignals.cpp
index da849287bbf6..b8cc7f05927a 100644
--- a/clang-tools-extra/clangd/ASTSignals.cpp
+++ b/clang-tools-extra/clangd/ASTSignals.cpp
@@ -1,4 +1,4 @@
-//===--- ASTSignals.cpp - LSP server -*- 
C++-*-===//
+//===--- ASTSignals.cpp --*- 
C++-*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.

diff  --git a/clang-tools-extra/clangd/ASTSignals.h 
b/clang-tools-extra/clangd/ASTSignals.h
index bc70cd17310a..fd31be38ce8b 100644
--- a/clang-tools-extra/clangd/ASTSignals.h
+++ b/clang-tools-extra/clangd/ASTSignals.h
@@ -1,4 +1,4 @@
-//===--- ASTSignals.h - LSP server ---*- 
C++-*-===//
+//===--- ASTSignals.h *- 
C++-*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang-tools-extra] d5047d7 - [clangd] Update CC Ranking model with better sampling.

2021-01-15 Thread Utkarsh Saxena via llvm-branch-commits

Author: Utkarsh Saxena
Date: 2021-01-15T18:13:24+01:00
New Revision: d5047d762f391c94939d67fc84cae25b24125694

URL: 
https://github.com/llvm/llvm-project/commit/d5047d762f391c94939d67fc84cae25b24125694
DIFF: 
https://github.com/llvm/llvm-project/commit/d5047d762f391c94939d67fc84cae25b24125694.diff

LOG: [clangd] Update CC Ranking model with better sampling.

A better sampling strategy was used to generate the dataset for this
model.
New signals introduced in this model:
- NumNameInContext: Number of words in the context that matches the name
of the candidate.
- FractionNameInContext: Fraction of the words in context matching the
name of the candidate.

We remove the signal `IsForbidden` from the model and down rank
forbidden signals aggresively.

Differential Revision: https://reviews.llvm.org/D94697

Added: 


Modified: 
clang-tools-extra/clangd/Quality.cpp
clang-tools-extra/clangd/quality/model/features.json
clang-tools-extra/clangd/quality/model/forest.json

Removed: 



error:
 too big or took too long to generate


___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang-tools-extra] 0f9908a - [clangd] Use empty() instead of size()>0

2021-01-17 Thread Utkarsh Saxena via llvm-branch-commits

Author: Utkarsh Saxena
Date: 2021-01-17T15:13:01+01:00
New Revision: 0f9908a7c9c547f2675e00f88cc11ec02ca28e8d

URL: 
https://github.com/llvm/llvm-project/commit/0f9908a7c9c547f2675e00f88cc11ec02ca28e8d
DIFF: 
https://github.com/llvm/llvm-project/commit/0f9908a7c9c547f2675e00f88cc11ec02ca28e8d.diff

LOG: [clangd] Use empty() instead of size()>0

Added: 


Modified: 
clang-tools-extra/clangd/Quality.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/Quality.cpp 
b/clang-tools-extra/clangd/Quality.cpp
index 7b6a76584778..f076b44f5743 100644
--- a/clang-tools-extra/clangd/Quality.cpp
+++ b/clang-tools-extra/clangd/Quality.cpp
@@ -512,7 +512,7 @@ evaluateDecisionForest(const SymbolQualitySignals &Quality,
   E.setIsNameInContext(NumMatch > 0);
   E.setNumNameInContext(NumMatch);
   E.setFractionNameInContext(
-  Relevance.ContextWords && Relevance.ContextWords->size() > 0
+  Relevance.ContextWords && Relevance.ContextWords->empty()
   ? NumMatch * 1.0 / Relevance.ContextWords->size()
   : 0);
   E.setIsInBaseClass(Relevance.InBaseClass);



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang-tools-extra] 9abbc05 - [clangd] Use !empty() instead of size()>0

2021-01-17 Thread Utkarsh Saxena via llvm-branch-commits

Author: Utkarsh Saxena
Date: 2021-01-17T15:26:40+01:00
New Revision: 9abbc050974ff117b79e8e049c52c56db3f49aec

URL: 
https://github.com/llvm/llvm-project/commit/9abbc050974ff117b79e8e049c52c56db3f49aec
DIFF: 
https://github.com/llvm/llvm-project/commit/9abbc050974ff117b79e8e049c52c56db3f49aec.diff

LOG: [clangd] Use !empty() instead of size()>0

Added: 


Modified: 
clang-tools-extra/clangd/Quality.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/Quality.cpp 
b/clang-tools-extra/clangd/Quality.cpp
index f076b44f5743..27b959ecacb3 100644
--- a/clang-tools-extra/clangd/Quality.cpp
+++ b/clang-tools-extra/clangd/Quality.cpp
@@ -512,7 +512,7 @@ evaluateDecisionForest(const SymbolQualitySignals &Quality,
   E.setIsNameInContext(NumMatch > 0);
   E.setNumNameInContext(NumMatch);
   E.setFractionNameInContext(
-  Relevance.ContextWords && Relevance.ContextWords->empty()
+  Relevance.ContextWords && !Relevance.ContextWords->empty()
   ? NumMatch * 1.0 / Relevance.ContextWords->size()
   : 0);
   E.setIsInBaseClass(Relevance.InBaseClass);



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang-tools-extra] 275716d - [clangd] Derive new signals in CC from ASTSignals.

2021-01-18 Thread Utkarsh Saxena via llvm-branch-commits

Author: Utkarsh Saxena
Date: 2021-01-18T17:37:27+01:00
New Revision: 275716d6db79a6da3d5cee12139dd0c0abf8fd07

URL: 
https://github.com/llvm/llvm-project/commit/275716d6db79a6da3d5cee12139dd0c0abf8fd07
DIFF: 
https://github.com/llvm/llvm-project/commit/275716d6db79a6da3d5cee12139dd0c0abf8fd07.diff

LOG: [clangd] Derive new signals in CC from ASTSignals.

This patch only introduces new signals but does not use their value
in scoring a CC candidate. Usage of these signals in CC ranking in both
heiristics and ML model will be introduced in later patches.

Differential Revision: https://reviews.llvm.org/D94473

Added: 


Modified: 
clang-tools-extra/clangd/ClangdServer.cpp
clang-tools-extra/clangd/CodeComplete.cpp
clang-tools-extra/clangd/CodeComplete.h
clang-tools-extra/clangd/Quality.cpp
clang-tools-extra/clangd/Quality.h
clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/ClangdServer.cpp 
b/clang-tools-extra/clangd/ClangdServer.cpp
index 4f3a47dff05d..a76250fa168e 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -255,6 +255,7 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
 ParseInput.Opts.BuildRecoveryAST = BuildRecoveryAST;
 ParseInput.Opts.PreserveRecoveryASTType = PreserveRecoveryASTType;
 
+CodeCompleteOpts.MainFileSignals = IP->Signals;
 // FIXME(ibiryukov): even if Preamble is non-null, we may want to check
 // both the old and the new version in case only one of them matches.
 CodeCompleteResult Result = clangd::codeComplete(

diff  --git a/clang-tools-extra/clangd/CodeComplete.cpp 
b/clang-tools-extra/clangd/CodeComplete.cpp
index b3b40022fbb2..9cc18ae789d5 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -1685,6 +1685,7 @@ class CodeCompleteFlow {
 if (PreferredType)
   Relevance.HadContextType = true;
 Relevance.ContextWords = &ContextWords;
+Relevance.MainFileSignals = Opts.MainFileSignals;
 
 auto &First = Bundle.front();
 if (auto FuzzyScore = fuzzyScore(First))

diff  --git a/clang-tools-extra/clangd/CodeComplete.h 
b/clang-tools-extra/clangd/CodeComplete.h
index ddcbd487ecc6..debf71d4117c 100644
--- a/clang-tools-extra/clangd/CodeComplete.h
+++ b/clang-tools-extra/clangd/CodeComplete.h
@@ -15,6 +15,7 @@
 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CODECOMPLETE_H
 
+#include "ASTSignals.h"
 #include "Compiler.h"
 #include "Headers.h"
 #include "Protocol.h"
@@ -89,6 +90,7 @@ struct CodeCompleteOptions {
   /// clangd.
   const SymbolIndex *Index = nullptr;
 
+  const ASTSignals *MainFileSignals = nullptr;
   /// Include completions that require small corrections, e.g. change '.' to
   /// '->' on member access etc.
   bool IncludeFixIts = false;

diff  --git a/clang-tools-extra/clangd/Quality.cpp 
b/clang-tools-extra/clangd/Quality.cpp
index 27b959ecacb3..1c41b7c7661f 100644
--- a/clang-tools-extra/clangd/Quality.cpp
+++ b/clang-tools-extra/clangd/Quality.cpp
@@ -294,6 +294,38 @@ void SymbolRelevanceSignals::merge(const Symbol 
&IndexResult) {
   if (!(IndexResult.Flags & Symbol::VisibleOutsideFile)) {
 Scope = AccessibleScope::FileScope;
   }
+  if (MainFileSignals) {
+MainFileRefs =
+std::max(MainFileRefs,
+ MainFileSignals->ReferencedSymbols.lookup(IndexResult.ID));
+ScopeRefsInFile =
+std::max(ScopeRefsInFile,
+ MainFileSignals->RelatedNamespaces.lookup(IndexResult.Scope));
+  }
+}
+
+void SymbolRelevanceSignals::computeASTSignals(
+const CodeCompletionResult &SemaResult) {
+  if (!MainFileSignals)
+return;
+  if ((SemaResult.Kind != CodeCompletionResult::RK_Declaration) &&
+  (SemaResult.Kind != CodeCompletionResult::RK_Pattern))
+return;
+  if (const NamedDecl *ND = SemaResult.getDeclaration()) {
+auto ID = getSymbolID(ND);
+if (!ID)
+  return;
+MainFileRefs =
+std::max(MainFileRefs, MainFileSignals->ReferencedSymbols.lookup(ID));
+if (const auto *NSD = dyn_cast(ND->getDeclContext())) {
+  if (NSD->isAnonymousNamespace())
+return;
+  std::string Scope = printNamespaceScope(*NSD);
+  if (!Scope.empty())
+ScopeRefsInFile = std::max(
+ScopeRefsInFile, MainFileSignals->RelatedNamespaces.lookup(Scope));
+}
+  }
 }
 
 void SymbolRelevanceSignals::merge(const CodeCompletionResult &SemaCCResult) {
@@ -315,6 +347,7 @@ void SymbolRelevanceSignals::merge(const 
CodeCompletionResult &SemaCCResult) {
 InBaseClass |= SemaCCResult.InBaseClass;
   }
 
+  computeASTSignals(SemaCCResult);
   // Declarations are scoped, others (like macros) are assumed global.
   if (SemaCCResult.Declaration)
 Scope = std::min(Scope, computeScope(SemaCCResult.Declaration));

diff

[llvm-branch-commits] [clang-tools-extra] 8bf7116 - [clangd] Index local classes, virtual and overriding methods.

2021-01-19 Thread Utkarsh Saxena via llvm-branch-commits

Author: Utkarsh Saxena
Date: 2021-01-19T16:18:48+01:00
New Revision: 8bf7116d50bfe8cb881273798ff384ed965c05e9

URL: 
https://github.com/llvm/llvm-project/commit/8bf7116d50bfe8cb881273798ff384ed965c05e9
DIFF: 
https://github.com/llvm/llvm-project/commit/8bf7116d50bfe8cb881273798ff384ed965c05e9.diff

LOG: [clangd] Index local classes, virtual and overriding methods.

Previously we did not record local class declarations. Now with features like
findImplementation and typeHierarchy, we have a need to index such local
classes to accurately report subclasses and implementations of methods.

Performance testing results:
- No changes in indexing timing.
- No significant change in memory usage.
- **1%** increase in #relations.
- **0.17%** increase in #refs.
- **0.22%** increase #symbols.

**New index stats**
Time to index: **4:13 min**
memory usage **543MB**
number of symbols: **521.5K**
number of refs: **8679K**
number of relations: **49K**

**Base Index stats**
Time to index: **4:15 min**
memory usage **542MB**
number of symbols: **520K**
number of refs: **8664K**
number of relations: **48.5K**

Fixes: https://github.com/clangd/clangd/issues/644

Differential Revision: https://reviews.llvm.org/D94785

Added: 


Modified: 
clang-tools-extra/clangd/index/FileIndex.cpp
clang-tools-extra/clangd/index/IndexAction.cpp
clang-tools-extra/clangd/index/Serialization.cpp
clang-tools-extra/clangd/index/SymbolCollector.cpp
clang-tools-extra/clangd/index/SymbolCollector.h
clang-tools-extra/clangd/test/index-serialization/Inputs/sample.idx
clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
clang-tools-extra/clangd/unittests/XRefsTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/index/FileIndex.cpp 
b/clang-tools-extra/clangd/index/FileIndex.cpp
index 143e76863777..26084c288674 100644
--- a/clang-tools-extra/clangd/index/FileIndex.cpp
+++ b/clang-tools-extra/clangd/index/FileIndex.cpp
@@ -61,7 +61,8 @@ SlabTuple indexSymbols(ASTContext &AST, 
std::shared_ptr PP,
   // We only need declarations, because we don't count references.
   IndexOpts.SystemSymbolFilter =
   index::IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly;
-  IndexOpts.IndexFunctionLocals = false;
+  // We index function-local classes and its member functions only.
+  IndexOpts.IndexFunctionLocals = true;
   if (IsIndexMainAST) {
 // We only collect refs when indexing main AST.
 CollectorOpts.RefFilter = RefKind::All;

diff  --git a/clang-tools-extra/clangd/index/IndexAction.cpp 
b/clang-tools-extra/clangd/index/IndexAction.cpp
index aa65008b51c0..e5a48df90b4d 100644
--- a/clang-tools-extra/clangd/index/IndexAction.cpp
+++ b/clang-tools-extra/clangd/index/IndexAction.cpp
@@ -212,6 +212,8 @@ std::unique_ptr createStaticIndexingAction(
   index::IndexingOptions IndexOpts;
   IndexOpts.SystemSymbolFilter =
   index::IndexingOptions::SystemSymbolFilterKind::All;
+  // We index function-local classes and its member functions only.
+  IndexOpts.IndexFunctionLocals = true;
   Opts.CollectIncludePath = true;
   if (Opts.Origin == SymbolOrigin::Unknown)
 Opts.Origin = SymbolOrigin::Static;

diff  --git a/clang-tools-extra/clangd/index/Serialization.cpp 
b/clang-tools-extra/clangd/index/Serialization.cpp
index bba5eaa36754..ad1299aa1445 100644
--- a/clang-tools-extra/clangd/index/Serialization.cpp
+++ b/clang-tools-extra/clangd/index/Serialization.cpp
@@ -452,7 +452,7 @@ readCompileCommand(Reader CmdReader, 
llvm::ArrayRef Strings) {
 // The current versioning scheme is simple - non-current versions are rejected.
 // If you make a breaking change, bump this version number to invalidate stored
 // data. Later we may want to support some backward compatibility.
-constexpr static uint32_t Version = 15;
+constexpr static uint32_t Version = 16;
 
 llvm::Expected readRIFF(llvm::StringRef Data) {
   auto RIFF = riff::readFile(Data);

diff  --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp 
b/clang-tools-extra/clangd/index/SymbolCollector.cpp
index 20f2eacafb27..b1363c1f9cef 100644
--- a/clang-tools-extra/clangd/index/SymbolCollector.cpp
+++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp
@@ -223,6 +223,11 @@ bool SymbolCollector::shouldCollectSymbol(const NamedDecl 
&ND,
   if (!IsMainFileOnly && ND.isInAnonymousNamespace())
 return false;
 
+  // For function local symbols, index only classes and its member functions.
+  if (index::isFunctionLocalSymbol(&ND))
+return isa(ND) ||
+   (ND.isCXXInstanceMember() && ND.isFunctionOrFunctionTemplate());
+
   // We want most things but not "local" symbols such as symbols inside
   // FunctionDecl, BlockDecl, ObjCMethodDecl and OMPDeclareReductionDecl.
   // FIXME: Need a matcher for ExportDecl in order to include symbols declared

diff  --git a/clang-tools-extra/clangd/index/Symbo

[llvm-branch-commits] [clang-tools-extra] 17846ed - [clangd] Use ASTSignals in Heuristics CC Ranking.

2021-01-19 Thread Utkarsh Saxena via llvm-branch-commits

Author: Utkarsh Saxena
Date: 2021-01-19T19:48:42+01:00
New Revision: 17846ed5af4a83334ef7d07f0b4a9d525e6ec0db

URL: 
https://github.com/llvm/llvm-project/commit/17846ed5af4a83334ef7d07f0b4a9d525e6ec0db
DIFF: 
https://github.com/llvm/llvm-project/commit/17846ed5af4a83334ef7d07f0b4a9d525e6ec0db.diff

LOG: [clangd] Use ASTSignals in Heuristics CC Ranking.

Differential Revision: https://reviews.llvm.org/D94927

Added: 


Modified: 
clang-tools-extra/clangd/Quality.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/Quality.cpp 
b/clang-tools-extra/clangd/Quality.cpp
index 1c41b7c7661f..b49392bc7d04 100644
--- a/clang-tools-extra/clangd/Quality.cpp
+++ b/clang-tools-extra/clangd/Quality.cpp
@@ -474,6 +474,21 @@ float SymbolRelevanceSignals::evaluateHeuristics() const {
   if (NeedsFixIts)
 Score *= 0.5f;
 
+  // Use a sigmoid style boosting function similar to `References`, which flats
+  // out nicely for large values. This avoids a sharp gradient for heavily
+  // referenced symbols. Use smaller gradient for ScopeRefsInFile since ideally
+  // MainFileRefs <= ScopeRefsInFile.
+  if (MainFileRefs >= 2) {
+// E.g.: (2, 1.12), (9, 2.0), (48, 3.0).
+float S = std::pow(MainFileRefs, -0.11);
+Score *= 11.0 * (1 - S) / (1 + S) + 0.7;
+  }
+  if (ScopeRefsInFile >= 2) {
+// E.g.: (2, 1.04), (14, 2.0), (109, 3.0), (400, 3.6).
+float S = std::pow(ScopeRefsInFile, -0.10);
+Score *= 10.0 * (1 - S) / (1 + S) + 0.7;
+  }
+
   return Score;
 }
 



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang-tools-extra] 85c1c6a - [clangd] Add Random Forest runtime for code completion.

2020-09-18 Thread Utkarsh Saxena via llvm-branch-commits

Author: Utkarsh Saxena
Date: 2020-09-18T18:27:42+02:00
New Revision: 85c1c6a4ba4eebbd3f5cefb1512498b9f8a5bb7a

URL: 
https://github.com/llvm/llvm-project/commit/85c1c6a4ba4eebbd3f5cefb1512498b9f8a5bb7a
DIFF: 
https://github.com/llvm/llvm-project/commit/85c1c6a4ba4eebbd3f5cefb1512498b9f8a5bb7a.diff

LOG: [clangd] Add Random Forest runtime for code completion.

Summary:
[WIP]
- Proposes a json format for representing Random Forest model.
- Proposes a way to test the generated runtime using a test model.

TODO:
- Add generated source code snippet for easier review.
- Fix unused label warning.
- Figure out required using declarations for CATEGORICAL columns from 
Features.json.
- Necessary Google3 internal modifications for blaze before landing.
- Add documentation for format of the model.
- Document more.

Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, 
cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D83814

Added: 
clang-tools-extra/clangd/quality/CompletionModel.cmake
clang-tools-extra/clangd/quality/CompletionModelCodegen.py
clang-tools-extra/clangd/quality/README.md
clang-tools-extra/clangd/quality/model/features.json
clang-tools-extra/clangd/quality/model/forest.json
clang-tools-extra/clangd/unittests/DecisionForestTests.cpp

clang-tools-extra/clangd/unittests/decision_forest_model/CategoricalFeature.h
clang-tools-extra/clangd/unittests/decision_forest_model/features.json
clang-tools-extra/clangd/unittests/decision_forest_model/forest.json

Modified: 
clang-tools-extra/clangd/CMakeLists.txt
clang-tools-extra/clangd/unittests/CMakeLists.txt
clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/CMakeLists.txt 
b/clang-tools-extra/clangd/CMakeLists.txt
index 3a1a034ed17b..9d2ab5be222a 100644
--- a/clang-tools-extra/clangd/CMakeLists.txt
+++ b/clang-tools-extra/clangd/CMakeLists.txt
@@ -28,6 +28,9 @@ set(LLVM_LINK_COMPONENTS
   FrontendOpenMP
   Option
   )
+  
+include(${CMAKE_CURRENT_SOURCE_DIR}/quality/CompletionModel.cmake)
+gen_decision_forest(${CMAKE_CURRENT_SOURCE_DIR}/quality/model CompletionModel 
clang::clangd::Example)
 
 if(MSVC AND NOT CLANG_CL)
  set_source_files_properties(CompileCommands.cpp PROPERTIES COMPILE_FLAGS 
-wd4130) # disables C4130: logical operation on address of string constant
@@ -77,6 +80,7 @@ add_clang_library(clangDaemon
   TUScheduler.cpp
   URI.cpp
   XRefs.cpp
+  ${CMAKE_CURRENT_BINARY_DIR}/CompletionModel.cpp
 
   index/Background.cpp
   index/BackgroundIndexLoader.cpp
@@ -117,6 +121,11 @@ add_clang_library(clangDaemon
   omp_gen
   )
 
+# Include generated CompletionModel headers.
+target_include_directories(clangDaemon PUBLIC
+  $
+)
+
 clang_target_link_libraries(clangDaemon
   PRIVATE
   clangAST

diff  --git a/clang-tools-extra/clangd/quality/CompletionModel.cmake 
b/clang-tools-extra/clangd/quality/CompletionModel.cmake
new file mode 100644
index ..60c6d2aa8433
--- /dev/null
+++ b/clang-tools-extra/clangd/quality/CompletionModel.cmake
@@ -0,0 +1,37 @@
+# Run the Completion Model Codegenerator on the model present in the 
+# ${model} directory.
+# Produces a pair of files called ${filename}.h and  ${filename}.cpp in the 
+# ${CMAKE_CURRENT_BINARY_DIR}. The generated header
+# will define a C++ class called ${cpp_class} - which may be a
+# namespace-qualified class name.
+function(gen_decision_forest model filename cpp_class)
+  set(model_compiler 
${CMAKE_SOURCE_DIR}/../clang-tools-extra/clangd/quality/CompletionModelCodegen.py)
+  
+  set(output_dir ${CMAKE_CURRENT_BINARY_DIR})
+  set(header_file ${output_dir}/${filename}.h)
+  set(cpp_file ${output_dir}/${filename}.cpp)
+
+  add_custom_command(OUTPUT ${header_file} ${cpp_file}
+COMMAND "${Python3_EXECUTABLE}" ${model_compiler}
+  --model ${model}
+  --output_dir ${output_dir}
+  --filename ${filename}
+  --cpp_class ${cpp_class}
+COMMENT "Generating code completion model runtime..."
+DEPENDS ${model_compiler} ${model}/forest.json ${model}/features.json
+VERBATIM )
+
+  set_source_files_properties(${header_file} PROPERTIES
+GENERATED 1)
+  set_source_files_properties(${cpp_file} PROPERTIES
+GENERATED 1)
+
+  # Disable unused label warning for generated files.
+  if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+set_source_files_properties(${cpp_file} PROPERTIES
+  COMPILE_FLAGS /wd4102)
+  else()
+set_source_files_properties(${cpp_file} PROPERTIES
+  COMPILE_FLAGS -Wno-unused)
+  endif()
+endfunction()

diff  --git a/clang-tools-extra/clangd/quality/CompletionModelCodegen.py 
b/clang-tools-extra/clangd/quality/CompletionModelCodegen.py
new file mode 100644
index ..8f8234f6ebbc
--- /dev/null
+++ b/clang-tools-extra/clangd/quality/CompletionModelCodegen.py
@@ -0,0 +1,283 @@
+"""Code generator for Code Comp

[llvm-branch-commits] [clang-tools-extra] b31486a - [clangd] textDocument/implementation (LSP layer)

2020-11-23 Thread Utkarsh Saxena via llvm-branch-commits

Author: Utkarsh Saxena
Date: 2020-11-23T13:50:44+01:00
New Revision: b31486ad971774c859e3e031fc0d8d9b77e3b083

URL: 
https://github.com/llvm/llvm-project/commit/b31486ad971774c859e3e031fc0d8d9b77e3b083
DIFF: 
https://github.com/llvm/llvm-project/commit/b31486ad971774c859e3e031fc0d8d9b77e3b083.diff

LOG: [clangd] textDocument/implementation (LSP layer)

Differential Revision: https://reviews.llvm.org/D91721

Added: 
clang-tools-extra/clangd/test/implementations.test

Modified: 
clang-tools-extra/clangd/ClangdLSPServer.cpp
clang-tools-extra/clangd/ClangdLSPServer.h
clang-tools-extra/clangd/ClangdServer.cpp
clang-tools-extra/clangd/ClangdServer.h
clang-tools-extra/clangd/test/initialize-params.test

Removed: 




diff  --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp 
b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index e726271fe7cbe..335a6fc9ad94e 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -604,6 +604,7 @@ void ClangdLSPServer::onInitialize(const InitializeParams 
&Params,
  }},
 {"declarationProvider", true},
 {"definitionProvider", true},
+{"implementationProvider", true},
 {"documentHighlightProvider", true},
 {"documentLinkProvider",
  llvm::json::Object{
@@ -1291,6 +1292,22 @@ void ClangdLSPServer::onReference(const ReferenceParams 
&Params,
  });
 }
 
+void ClangdLSPServer::onGoToImplementation(
+const TextDocumentPositionParams &Params,
+Callback> Reply) {
+  Server->findImplementations(
+  Params.textDocument.uri.file(), Params.position,
+  [Reply = std::move(Reply)](
+  llvm::Expected> Overrides) mutable {
+if (!Overrides)
+  return Reply(Overrides.takeError());
+std::vector Impls;
+for (const LocatedSymbol &Sym : *Overrides)
+  Impls.push_back(Sym.PreferredDeclaration);
+return Reply(std::move(Impls));
+  });
+}
+
 void ClangdLSPServer::onSymbolInfo(const TextDocumentPositionParams &Params,
Callback> Reply) 
{
   Server->symbolInfo(Params.textDocument.uri.file(), Params.position,
@@ -1431,6 +1448,7 @@ ClangdLSPServer::ClangdLSPServer(class Transport &Transp,
   MsgHandler->bind("textDocument/signatureHelp", 
&ClangdLSPServer::onSignatureHelp);
   MsgHandler->bind("textDocument/definition", 
&ClangdLSPServer::onGoToDefinition);
   MsgHandler->bind("textDocument/declaration", 
&ClangdLSPServer::onGoToDeclaration);
+  MsgHandler->bind("textDocument/implementation", 
&ClangdLSPServer::onGoToImplementation);
   MsgHandler->bind("textDocument/references", &ClangdLSPServer::onReference);
   MsgHandler->bind("textDocument/switchSourceHeader", 
&ClangdLSPServer::onSwitchSourceHeader);
   MsgHandler->bind("textDocument/prepareRename", 
&ClangdLSPServer::onPrepareRename);

diff  --git a/clang-tools-extra/clangd/ClangdLSPServer.h 
b/clang-tools-extra/clangd/ClangdLSPServer.h
index b9200f6a2e1b8..4d568bc13d8bf 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.h
+++ b/clang-tools-extra/clangd/ClangdLSPServer.h
@@ -115,6 +115,8 @@ class ClangdLSPServer : private ClangdServer::Callbacks {
  Callback>);
   void onGoToDefinition(const TextDocumentPositionParams &,
 Callback>);
+  void onGoToImplementation(const TextDocumentPositionParams &,
+Callback>);
   void onReference(const ReferenceParams &, Callback>);
   void onSwitchSourceHeader(const TextDocumentIdentifier &,
 Callback>);

diff  --git a/clang-tools-extra/clangd/ClangdServer.cpp 
b/clang-tools-extra/clangd/ClangdServer.cpp
index b6f9fcfd23da8..889d2cbcf2807 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -718,6 +718,18 @@ void ClangdServer::foldingRanges(llvm::StringRef File,
TUScheduler::InvalidateOnUpdate);
 }
 
+void ClangdServer::findImplementations(
+PathRef File, Position Pos, Callback> CB) {
+  auto Action = [Pos, CB = std::move(CB),
+ this](llvm::Expected InpAST) mutable {
+if (!InpAST)
+  return CB(InpAST.takeError());
+CB(clangd::findImplementations(InpAST->AST, Pos, Index));
+  };
+
+  WorkScheduler.runWithAST("Implementations", File, std::move(Action));
+}
+
 void ClangdServer::findReferences(PathRef File, Position Pos, uint32_t Limit,
   Callback CB) {
   auto Action = [Pos, Limit, CB = std::move(CB),

diff  --git a/clang-tools-extra/clangd/ClangdServer.h 
b/clang-tools-extra/clangd/ClangdServer.h
index 0056f5072cca3..1ccb4c5899f81 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -253,6 +253,10 @@ class ClangdServer {
   /// Retrieve ranges that

[llvm-branch-commits] [clang-tools-extra] 4ce242a - [clangd] Find relations in Dex exploration tool.

2020-12-10 Thread Utkarsh Saxena via llvm-branch-commits

Author: Utkarsh Saxena
Date: 2020-12-10T16:54:03+01:00
New Revision: 4ce242a163c3b98385a5cb949a7e6b1e1ae7eb83

URL: 
https://github.com/llvm/llvm-project/commit/4ce242a163c3b98385a5cb949a7e6b1e1ae7eb83
DIFF: 
https://github.com/llvm/llvm-project/commit/4ce242a163c3b98385a5cb949a7e6b1e1ae7eb83.diff

LOG: [clangd] Find relations in Dex exploration tool.

Reviewed By: hokein

Differential Revision: https://reviews.llvm.org/D93029

Added: 


Modified: 
clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp

Removed: 




diff  --git a/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp 
b/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp
index d7da330e2ed0..49f16e72be92 100644
--- a/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp
+++ b/clang-tools-extra/clangd/index/dex/dexp/Dexp.cpp
@@ -11,6 +11,8 @@
 //
 
//===--===//
 
+#include "index/Index.h"
+#include "index/Relation.h"
 #include "index/Serialization.h"
 #include "index/dex/Dex.h"
 #include "index/remote/Client.h"
@@ -267,6 +269,43 @@ class Refs : public Command {
   }
 };
 
+class Relations : public Command {
+  llvm::cl::opt ID{
+  "id",
+  llvm::cl::Positional,
+  llvm::cl::desc("Symbol ID of the symbol being queried (hex)."),
+  };
+  llvm::cl::opt Relation{
+  "relation",
+  llvm::cl::desc("Relation kind for the predicate."),
+  values(clEnumValN(RelationKind::BaseOf, "base_of",
+"Find subclasses of a class."),
+ clEnumValN(RelationKind::OverriddenBy, "overridden_by",
+"Find methods that overrides a virtual method.")),
+  };
+
+  void run() override {
+if (ID.getNumOccurrences() == 0 || Relation.getNumOccurrences() == 0) {
+  llvm::errs()
+  << "Missing required argument: please provide id and -relation.\n";
+  return;
+}
+RelationsRequest Req;
+if (ID.getNumOccurrences()) {
+  auto SID = SymbolID::fromStr(ID);
+  if (!SID) {
+llvm::errs() << llvm::toString(SID.takeError()) << "\n";
+return;
+  }
+  Req.Subjects.insert(*SID);
+}
+Req.Predicate = Relation.getValue();
+Index->relations(Req, [](const SymbolID &SID, const Symbol &S) {
+  llvm::outs() << toYAML(S);
+});
+  }
+};
+
 class Export : public Command {
   llvm::cl::opt Format{
   "format",
@@ -326,6 +365,8 @@ struct {
 {"lookup", "Dump symbol details by ID or qualified name",
  std::make_unique},
 {"refs", "Find references by ID or qualified name", 
std::make_unique},
+{"relations", "Find relations by ID and relation kind",
+ std::make_unique},
 {"export", "Export index", std::make_unique},
 };
 



___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [Serialization] Code cleanups and polish 83233 (PR #83237)

2024-10-25 Thread Utkarsh Saxena via llvm-branch-commits

usx95 wrote:

> I tried to take a look at eigen and it looks like the declaration looks well 
> and I had no clue how that happens. A reproducer may be necessary here to 
> proceed. Thanks in advance.

I can reproduce using the following sources and invocations outlined in `run.sh`
https://github.com/usx95/llvm-project/commit/363d877bd317638b197f57c3591860e1688950d5

```sh
>  module-reproducer/run.sh

Building sensor_data.cc
Building tensor.cc
Building base.cc
In module 'sensor_data':
../../eigen/Eigen/src/Core/../plugins/CommonCwiseBinaryOps.inc:47:29: warning: 
inline function 'Eigen::operator*' is not defined [-Wundefined-inline]
   47 | EIGEN_MAKE_SCALAR_BINARY_OP(operator*, product)
  | ^
../../eigen/Eigen/src/Geometry/AngleAxis.h:221:35: note: used here
  221 |   Vector3 sin_axis = sin(m_angle) * m_axis;
  |   ^
1 warning generated.
```
This warning is a new breakage and does not happed without this change (ignore 
the linker failure).

https://github.com/llvm/llvm-project/pull/83237
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] release/20.x: [clang] Fix false positive regression for lifetime analysis warning. (#127460) (PR #127618)

2025-02-18 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 approved this pull request.


https://github.com/llvm/llvm-project/pull/127618
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Propagate loans using dataflow analysis (PR #147295)

2025-07-07 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/147295

>From dd2dd838f44ebeb6d45f75af2934159ee61b385b Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Sun, 6 Jul 2025 19:12:55 +
Subject: [PATCH] [LifetimeSafety] Propagate loans using dataflow analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 255 +-
 .../Sema/warn-lifetime-safety-dataflow.cpp| 186 +
 2 files changed, 440 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 2c2309de90e26..cdbab31ac7a9c 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -482,7 +482,247 @@ class FactGenerator : public 
ConstStmtVisitor {
 };
 
 // = //
-//  TODO: Run dataflow analysis to propagate loans, analyse and error 
reporting.
+//  The Dataflow Lattice
+// = //
+
+// Using LLVM's immutable collections is efficient for dataflow analysis
+// as it avoids deep copies during state transitions.
+// TODO(opt): Consider using a bitset to represent the set of loans.
+using LoanSet = llvm::ImmutableSet;
+using OriginLoanMap = llvm::ImmutableMap;
+
+/// An object to hold the factories for immutable collections, ensuring
+/// that all created states share the same underlying memory management.
+struct LifetimeFactory {
+  OriginLoanMap::Factory OriginMapFact;
+  LoanSet::Factory LoanSetFact;
+
+  LoanSet createLoanSet(LoanID LID) {
+return LoanSetFact.add(LoanSetFact.getEmptySet(), LID);
+  }
+};
+
+/// LifetimeLattice represents the state of our analysis at a given program
+/// point. It is an immutable object, and all operations produce a new
+/// instance rather than modifying the existing one.
+struct LifetimeLattice {
+  /// The map from an origin to the set of loans it contains.
+  /// TODO(opt): To reduce the lattice size, propagate origins of declarations,
+  /// not expressions, because expressions are not visible across blocks.
+  OriginLoanMap Origins = OriginLoanMap(nullptr);
+
+  explicit LifetimeLattice(const OriginLoanMap &S) : Origins(S) {}
+  LifetimeLattice() = default;
+
+  bool operator==(const LifetimeLattice &Other) const {
+return Origins == Other.Origins;
+  }
+  bool operator!=(const LifetimeLattice &Other) const {
+return !(*this == Other);
+  }
+
+  LoanSet getLoans(OriginID OID, LifetimeFactory &Factory) const {
+if (auto *Loans = Origins.lookup(OID))
+  return *Loans;
+return Factory.LoanSetFact.getEmptySet();
+  }
+
+  /// Computes the union of two lattices by performing a key-wise join of
+  /// their OriginLoanMaps.
+  // TODO(opt): This key-wise join is a performance bottleneck. A more
+  // efficient merge could be implemented using a Patricia Trie or HAMT
+  // instead of the current AVL-tree-based ImmutableMap.
+  LifetimeLattice join(const LifetimeLattice &Other,
+   LifetimeFactory &Factory) const {
+/// Merge the smaller map into the larger one ensuring we iterate over the
+/// smaller map.
+if (Origins.getHeight() < Other.Origins.getHeight())
+  return Other.join(*this, Factory);
+
+OriginLoanMap JoinedState = Origins;
+// For each origin in the other map, union its loan set with ours.
+for (const auto &Entry : Other.Origins) {
+  OriginID OID = Entry.first;
+  LoanSet OtherLoanSet = Entry.second;
+  JoinedState = Factory.OriginMapFact.add(
+  JoinedState, OID,
+  join(getLoans(OID, Factory), OtherLoanSet, Factory));
+}
+return LifetimeLattice(JoinedState);
+  }
+
+  LoanSet join(LoanSet a, LoanSet b, LifetimeFactory &Factory) const {
+/// Merge the smaller set into the larger one ensuring we iterate over the
+/// smaller set.
+if (a.getHeight() < b.getHeight())
+  std::swap(a, b);
+LoanSet Result = a;
+for (LoanID LID : b) {
+  /// TODO(opt): Profiling shows that this loop is a major performance
+  /// bottleneck. Investigate using a BitVector to represent the set of
+  /// loans for improved join performance.
+  Result = Factory.LoanSetFact.add(Result, LID);
+}
+return Result;
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "LifetimeLattice State:\n";
+if (Origins.isEmpty())
+  OS << "  \n";
+for (const auto &Entry : Origins) {
+  if (Entry.second.isEmpty())
+OS << "  Origin " << Entry.first << " contains no loans\n";
+  for (const LoanID &LID : Entry.second)
+OS << "  Origin " << Entry.first << " contains Loan " << LID << "\n";
+}
+  }
+};
+
+// = //
+//  The Transfer Function
+// = //
+class T

[llvm-branch-commits] [clang] [LifetimeSafety] Implement dataflow analysis for loan propagation (PR #147295)

2025-07-07 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/147295
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Propagate loans using dataflow analysis (PR #147295)

2025-07-07 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 created 
https://github.com/llvm/llvm-project/pull/147295

None

>From 2e4261b02b6230a8c79f01a673cc3030cfff3ea7 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Sun, 6 Jul 2025 19:12:55 +
Subject: [PATCH 1/6] [LifetimeSafety] Propagate loans using dataflow analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 255 +-
 .../Sema/warn-lifetime-safety-dataflow.cpp| 186 +
 2 files changed, 440 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 3fe30e36ebd0f..7870352f0287a 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -491,7 +491,247 @@ class FactGenerator : public 
ConstStmtVisitor {
 };
 
 // = //
-//  TODO: Run dataflow analysis to propagate loans, analyse and error 
reporting.
+//  The Dataflow Lattice
+// = //
+
+// Using LLVM's immutable collections is efficient for dataflow analysis
+// as it avoids deep copies during state transitions.
+// TODO(opt): Consider using a bitset to represent the set of loans.
+using LoanSet = llvm::ImmutableSet;
+using OriginLoanMap = llvm::ImmutableMap;
+
+/// An object to hold the factories for immutable collections, ensuring
+/// that all created states share the same underlying memory management.
+struct LifetimeFactory {
+  OriginLoanMap::Factory OriginMapFact;
+  LoanSet::Factory LoanSetFact;
+
+  LoanSet createLoanSet(LoanID LID) {
+return LoanSetFact.add(LoanSetFact.getEmptySet(), LID);
+  }
+};
+
+/// LifetimeLattice represents the state of our analysis at a given program
+/// point. It is an immutable object, and all operations produce a new
+/// instance rather than modifying the existing one.
+struct LifetimeLattice {
+  /// The map from an origin to the set of loans it contains.
+  /// TODO(opt): To reduce the lattice size, propagate origins of declarations,
+  /// not expressions, because expressions are not visible across blocks.
+  OriginLoanMap Origins = OriginLoanMap(nullptr);
+
+  explicit LifetimeLattice(const OriginLoanMap &S) : Origins(S) {}
+  LifetimeLattice() = default;
+
+  bool operator==(const LifetimeLattice &Other) const {
+return Origins == Other.Origins;
+  }
+  bool operator!=(const LifetimeLattice &Other) const {
+return !(*this == Other);
+  }
+
+  LoanSet getLoans(OriginID OID, LifetimeFactory &Factory) const {
+if (auto *Loans = Origins.lookup(OID))
+  return *Loans;
+return Factory.LoanSetFact.getEmptySet();
+  }
+
+  /// Computes the union of two lattices by performing a key-wise join of
+  /// their OriginLoanMaps.
+  // TODO(opt): This key-wise join is a performance bottleneck. A more
+  // efficient merge could be implemented using a Patricia Trie or HAMT
+  // instead of the current AVL-tree-based ImmutableMap.
+  LifetimeLattice join(const LifetimeLattice &Other,
+   LifetimeFactory &Factory) const {
+/// Merge the smaller map into the larger one ensuring we iterate over the
+/// smaller map.
+if (Origins.getHeight() < Other.Origins.getHeight())
+  return Other.join(*this, Factory);
+
+OriginLoanMap JoinedState = Origins;
+// For each origin in the other map, union its loan set with ours.
+for (const auto &Entry : Other.Origins) {
+  OriginID OID = Entry.first;
+  LoanSet OtherLoanSet = Entry.second;
+  JoinedState = Factory.OriginMapFact.add(
+  JoinedState, OID,
+  join(getLoans(OID, Factory), OtherLoanSet, Factory));
+}
+return LifetimeLattice(JoinedState);
+  }
+
+  LoanSet join(LoanSet a, LoanSet b, LifetimeFactory &Factory) const {
+/// Merge the smaller set into the larger one ensuring we iterate over the
+/// smaller set.
+if (a.getHeight() < b.getHeight())
+  std::swap(a, b);
+LoanSet Result = a;
+for (LoanID LID : b) {
+  /// TODO(opt): Profiling shows that this loop is a major performance
+  /// bottleneck. Investigate using a BitVector to represent the set of
+  /// loans for improved join performance.
+  Result = Factory.LoanSetFact.add(Result, LID);
+}
+return Result;
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "LifetimeLattice State:\n";
+if (Origins.isEmpty())
+  OS << "  \n";
+for (const auto &Entry : Origins) {
+  if (Entry.second.isEmpty())
+OS << "  Origin " << Entry.first << " contains no loans\n";
+  for (const LoanID &LID : Entry.second)
+OS << "  Origin " << Entry.first << " contains Loan " << LID << "\n";
+}
+  }
+};
+
+// = //
+//  The Transfer Function
+// = /

[llvm-branch-commits] [clang] [LifetimeSafety] Propagate loans using dataflow analysis (PR #147295)

2025-07-07 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/147295

>From 2e4261b02b6230a8c79f01a673cc3030cfff3ea7 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Sun, 6 Jul 2025 19:12:55 +
Subject: [PATCH 1/6] [LifetimeSafety] Propagate loans using dataflow analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 255 +-
 .../Sema/warn-lifetime-safety-dataflow.cpp| 186 +
 2 files changed, 440 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 3fe30e36ebd0f..7870352f0287a 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -491,7 +491,247 @@ class FactGenerator : public 
ConstStmtVisitor {
 };
 
 // = //
-//  TODO: Run dataflow analysis to propagate loans, analyse and error 
reporting.
+//  The Dataflow Lattice
+// = //
+
+// Using LLVM's immutable collections is efficient for dataflow analysis
+// as it avoids deep copies during state transitions.
+// TODO(opt): Consider using a bitset to represent the set of loans.
+using LoanSet = llvm::ImmutableSet;
+using OriginLoanMap = llvm::ImmutableMap;
+
+/// An object to hold the factories for immutable collections, ensuring
+/// that all created states share the same underlying memory management.
+struct LifetimeFactory {
+  OriginLoanMap::Factory OriginMapFact;
+  LoanSet::Factory LoanSetFact;
+
+  LoanSet createLoanSet(LoanID LID) {
+return LoanSetFact.add(LoanSetFact.getEmptySet(), LID);
+  }
+};
+
+/// LifetimeLattice represents the state of our analysis at a given program
+/// point. It is an immutable object, and all operations produce a new
+/// instance rather than modifying the existing one.
+struct LifetimeLattice {
+  /// The map from an origin to the set of loans it contains.
+  /// TODO(opt): To reduce the lattice size, propagate origins of declarations,
+  /// not expressions, because expressions are not visible across blocks.
+  OriginLoanMap Origins = OriginLoanMap(nullptr);
+
+  explicit LifetimeLattice(const OriginLoanMap &S) : Origins(S) {}
+  LifetimeLattice() = default;
+
+  bool operator==(const LifetimeLattice &Other) const {
+return Origins == Other.Origins;
+  }
+  bool operator!=(const LifetimeLattice &Other) const {
+return !(*this == Other);
+  }
+
+  LoanSet getLoans(OriginID OID, LifetimeFactory &Factory) const {
+if (auto *Loans = Origins.lookup(OID))
+  return *Loans;
+return Factory.LoanSetFact.getEmptySet();
+  }
+
+  /// Computes the union of two lattices by performing a key-wise join of
+  /// their OriginLoanMaps.
+  // TODO(opt): This key-wise join is a performance bottleneck. A more
+  // efficient merge could be implemented using a Patricia Trie or HAMT
+  // instead of the current AVL-tree-based ImmutableMap.
+  LifetimeLattice join(const LifetimeLattice &Other,
+   LifetimeFactory &Factory) const {
+/// Merge the smaller map into the larger one ensuring we iterate over the
+/// smaller map.
+if (Origins.getHeight() < Other.Origins.getHeight())
+  return Other.join(*this, Factory);
+
+OriginLoanMap JoinedState = Origins;
+// For each origin in the other map, union its loan set with ours.
+for (const auto &Entry : Other.Origins) {
+  OriginID OID = Entry.first;
+  LoanSet OtherLoanSet = Entry.second;
+  JoinedState = Factory.OriginMapFact.add(
+  JoinedState, OID,
+  join(getLoans(OID, Factory), OtherLoanSet, Factory));
+}
+return LifetimeLattice(JoinedState);
+  }
+
+  LoanSet join(LoanSet a, LoanSet b, LifetimeFactory &Factory) const {
+/// Merge the smaller set into the larger one ensuring we iterate over the
+/// smaller set.
+if (a.getHeight() < b.getHeight())
+  std::swap(a, b);
+LoanSet Result = a;
+for (LoanID LID : b) {
+  /// TODO(opt): Profiling shows that this loop is a major performance
+  /// bottleneck. Investigate using a BitVector to represent the set of
+  /// loans for improved join performance.
+  Result = Factory.LoanSetFact.add(Result, LID);
+}
+return Result;
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "LifetimeLattice State:\n";
+if (Origins.isEmpty())
+  OS << "  \n";
+for (const auto &Entry : Origins) {
+  if (Entry.second.isEmpty())
+OS << "  Origin " << Entry.first << " contains no loans\n";
+  for (const LoanID &LID : Entry.second)
+OS << "  Origin " << Entry.first << " contains Loan " << LID << "\n";
+}
+  }
+};
+
+// = //
+//  The Transfer Function
+// = //
+cla

[llvm-branch-commits] [clang] [LifetimeSafety] Implement dataflow analysis for loan propagation (PR #147295)

2025-07-07 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/147295

>From e870b040c4ef29b7ca2e50c1fc0ab5a2446f5cf6 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Sun, 6 Jul 2025 19:12:55 +
Subject: [PATCH] [LifetimeSafety] Propagate loans using dataflow analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 258 +-
 .../Sema/warn-lifetime-safety-dataflow.cpp| 186 +
 2 files changed, 443 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 2c2309de90e26..e881e592ef59f 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -13,7 +13,10 @@
 #include "clang/Analysis/Analyses/PostOrderCFGView.h"
 #include "clang/Analysis/AnalysisDeclContext.h"
 #include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/ImmutableSet.h"
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Debug.h"
@@ -482,7 +485,247 @@ class FactGenerator : public 
ConstStmtVisitor {
 };
 
 // = //
-//  TODO: Run dataflow analysis to propagate loans, analyse and error 
reporting.
+//  The Dataflow Lattice
+// = //
+
+// Using LLVM's immutable collections is efficient for dataflow analysis
+// as it avoids deep copies during state transitions.
+// TODO(opt): Consider using a bitset to represent the set of loans.
+using LoanSet = llvm::ImmutableSet;
+using OriginLoanMap = llvm::ImmutableMap;
+
+/// An object to hold the factories for immutable collections, ensuring
+/// that all created states share the same underlying memory management.
+struct LifetimeFactory {
+  OriginLoanMap::Factory OriginMapFact;
+  LoanSet::Factory LoanSetFact;
+
+  LoanSet createLoanSet(LoanID LID) {
+return LoanSetFact.add(LoanSetFact.getEmptySet(), LID);
+  }
+};
+
+/// LifetimeLattice represents the state of our analysis at a given program
+/// point. It is an immutable object, and all operations produce a new
+/// instance rather than modifying the existing one.
+struct LifetimeLattice {
+  /// The map from an origin to the set of loans it contains.
+  /// TODO(opt): To reduce the lattice size, propagate origins of declarations,
+  /// not expressions, because expressions are not visible across blocks.
+  OriginLoanMap Origins = OriginLoanMap(nullptr);
+
+  explicit LifetimeLattice(const OriginLoanMap &S) : Origins(S) {}
+  LifetimeLattice() = default;
+
+  bool operator==(const LifetimeLattice &Other) const {
+return Origins == Other.Origins;
+  }
+  bool operator!=(const LifetimeLattice &Other) const {
+return !(*this == Other);
+  }
+
+  LoanSet getLoans(OriginID OID, LifetimeFactory &Factory) const {
+if (auto *Loans = Origins.lookup(OID))
+  return *Loans;
+return Factory.LoanSetFact.getEmptySet();
+  }
+
+  /// Computes the union of two lattices by performing a key-wise join of
+  /// their OriginLoanMaps.
+  // TODO(opt): This key-wise join is a performance bottleneck. A more
+  // efficient merge could be implemented using a Patricia Trie or HAMT
+  // instead of the current AVL-tree-based ImmutableMap.
+  LifetimeLattice join(const LifetimeLattice &Other,
+   LifetimeFactory &Factory) const {
+/// Merge the smaller map into the larger one ensuring we iterate over the
+/// smaller map.
+if (Origins.getHeight() < Other.Origins.getHeight())
+  return Other.join(*this, Factory);
+
+OriginLoanMap JoinedState = Origins;
+// For each origin in the other map, union its loan set with ours.
+for (const auto &Entry : Other.Origins) {
+  OriginID OID = Entry.first;
+  LoanSet OtherLoanSet = Entry.second;
+  JoinedState = Factory.OriginMapFact.add(
+  JoinedState, OID,
+  join(getLoans(OID, Factory), OtherLoanSet, Factory));
+}
+return LifetimeLattice(JoinedState);
+  }
+
+  LoanSet join(LoanSet a, LoanSet b, LifetimeFactory &Factory) const {
+/// Merge the smaller set into the larger one ensuring we iterate over the
+/// smaller set.
+if (a.getHeight() < b.getHeight())
+  std::swap(a, b);
+LoanSet Result = a;
+for (LoanID LID : b) {
+  /// TODO(opt): Profiling shows that this loop is a major performance
+  /// bottleneck. Investigate using a BitVector to represent the set of
+  /// loans for improved join performance.
+  Result = Factory.LoanSetFact.add(Result, LID);
+}
+return Result;
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "LifetimeLattice State:\n";
+if (Origins.isEmpty())
+  OS << "  \n";
+for (const auto &Entry : Origins) {
+  if (Entry.second.isEmpty())
+OS

[llvm-branch-commits] [clang] [LifetimeSafety] Implement dataflow analysis for loan propagation (PR #147295)

2025-07-07 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/147295
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Implement dataflow analysis for loan propagation (PR #147295)

2025-07-07 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 ready_for_review 
https://github.com/llvm/llvm-project/pull/147295
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add script performance benchmarking (PR #147315)

2025-07-07 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/147315
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] Users/usx95/lifetime safety benchmarking (PR #147315)

2025-07-07 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/147315
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add script performance benchmarking (PR #147315)

2025-07-07 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/147315

>From 0fbfd74d23b6cd26ef0480f7b9061b2f4a745338 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 7 Jul 2025 15:13:00 +
Subject: [PATCH 1/2] [LifetimeSafety] Add script performance benchmarking

---
 clang/lib/Analysis/LifetimeSafety.cpp |   7 +-
 .../Analysis/lifetime_safety/benchmark.py | 215 ++
 2 files changed, 221 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/Analysis/lifetime_safety/benchmark.py

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index e881e592ef59f..1c83b5051bad1 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -151,7 +151,12 @@ class OriginManager {
 
   OriginID get(const ValueDecl &D) {
 auto It = DeclToOriginID.find(&D);
-assert(It != DeclToOriginID.end());
+// TODO: This should be an assert(It != ExprToOriginID.end()). The current
+// implementation falls back to getOrCreate to avoid crashing on
+// yet-unhandled pointer expressions, creating an empty origin for them.
+if (It == DeclToOriginID.end())
+  return getOrCreate(D);
+
 return It->second;
   }
 
diff --git a/clang/test/Analysis/lifetime_safety/benchmark.py 
b/clang/test/Analysis/lifetime_safety/benchmark.py
new file mode 100644
index 0..ddf32e192de17
--- /dev/null
+++ b/clang/test/Analysis/lifetime_safety/benchmark.py
@@ -0,0 +1,215 @@
+import sys
+import argparse
+import subprocess
+import tempfile
+import json
+import os
+from datetime import datetime
+import numpy as np
+from scipy.optimize import curve_fit
+from scipy.stats import t
+
+def generate_cpp_cycle_test(n: int) -> str:
+"""
+Generates a C++ code snippet with a specified number of pointers in a 
cycle.
+"""
+if n <= 0:
+return "// Number of variables must be positive."
+
+cpp_code = "struct MyObj { int id; ~MyObj() {} };\n\n"
+cpp_code += f"void long_cycle_{n}(bool condition) {{\n"
+for i in range(1, n + 1):
+cpp_code += f"  MyObj v{i}{{1}};\n"
+cpp_code += "\n"
+for i in range(1, n + 1):
+cpp_code += f"  MyObj* p{i} = &v{i};\n"
+
+cpp_code += "\n  while (condition) {\n"
+if n > 0:
+cpp_code += f"MyObj* temp = p1;\n"
+for i in range(1, n):
+cpp_code += f"p{i} = p{i+1};\n"
+cpp_code += f"p{n} = temp;\n"
+cpp_code += "  }\n}\n"
+cpp_code += f"\nint main() {{ long_cycle_{n}(false); return 0; }}\n"
+return cpp_code
+
+def generate_cpp_merge_test(n: int) -> str:
+"""
+Generates a C++ code snippet with N independent conditional assignments.
+"""
+if n <= 0:
+return "// Number of variables must be positive."
+
+cpp_code = "struct MyObj { int id; ~MyObj() {} };\n\n"
+cpp_code += f"void conditional_merges_{n}(bool condition) {{\n"
+decls = [f"v{i}" for i in range(1, n + 1)]
+cpp_code += f"  MyObj {', '.join(decls)};\n"
+ptr_decls = [f"*p{i} = nullptr" for i in range(1, n + 1)]
+cpp_code += f"  MyObj {', '.join(ptr_decls)};\n\n"
+
+for i in range(1, n + 1):
+cpp_code += f"  if(condition) {{ p{i} = &v{i}; }}\n"
+
+cpp_code += "}\n"
+cpp_code += f"\nint main() {{ conditional_merges_{n}(false); return 0; 
}}\n"
+return cpp_code
+
+def analyze_trace_file(trace_path: str) -> tuple[float, float]:
+"""
+Parses the -ftime-trace JSON output to find durations.
+
+Returns:
+A tuple of (lifetime_analysis_duration_us, total_clang_duration_us).
+"""
+lifetime_duration = 0.0
+total_duration = 0.0
+try:
+with open(trace_path, 'r') as f:
+trace_data = json.load(f)
+for event in trace_data.get('traceEvents', []):
+if event.get('name') == 'LifetimeAnalysis':
+lifetime_duration += float(event.get('dur', 0))
+if event.get('name') == 'ExecuteCompiler':
+total_duration += float(event.get('dur', 0))
+
+except (IOError, json.JSONDecodeError) as e:
+print(f"Error reading or parsing trace file {trace_path}: {e}", 
file=sys.stderr)
+return 0.0, 0.0
+return lifetime_duration, total_duration
+
+def power_law(n, c, k):
+"""Represents the power law function: y = c * n^k"""
+return c * np.power(n, k)
+
+def human_readable_time(ms: float) -> str:
+"""Converts milliseconds to a human-readable string (ms or s)."""
+if ms >= 1000:
+return f"{ms / 1000:.2f} s"
+return f"{ms:.2f} ms"
+
+def generate_markdown_report(results: dict) -> str:
+"""Generates a Markdown-formatted report from the benchmark results."""
+report = []
+timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S %Z")
+report.append(f"# Lifetime Analysis Performance Report")
+report.append(f"> Generated on: {timestamp}")
+report.append("\n---\n")
+
+for test_typ

[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-07 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/147315
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-08 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/147315

>From 014d81d9da31df3cf46bd8fc5f7cb470b3271b8e Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 7 Jul 2025 15:13:00 +
Subject: [PATCH] [LifetimeSafety] Add script performance benchmarking

---
 clang/lib/Analysis/LifetimeSafety.cpp |   7 +-
 .../Analysis/LifetimeSafety/CMakeLists.txt|  49 +++
 .../test/Analysis/LifetimeSafety/benchmark.py | 308 ++
 .../Analysis/LifetimeSafety/requirements.txt  |   2 +
 clang/test/CMakeLists.txt |   2 +
 5 files changed, 367 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/Analysis/LifetimeSafety/CMakeLists.txt
 create mode 100644 clang/test/Analysis/LifetimeSafety/benchmark.py
 create mode 100644 clang/test/Analysis/LifetimeSafety/requirements.txt

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index e881e592ef59f..1c83b5051bad1 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -151,7 +151,12 @@ class OriginManager {
 
   OriginID get(const ValueDecl &D) {
 auto It = DeclToOriginID.find(&D);
-assert(It != DeclToOriginID.end());
+// TODO: This should be an assert(It != ExprToOriginID.end()). The current
+// implementation falls back to getOrCreate to avoid crashing on
+// yet-unhandled pointer expressions, creating an empty origin for them.
+if (It == DeclToOriginID.end())
+  return getOrCreate(D);
+
 return It->second;
   }
 
diff --git a/clang/test/Analysis/LifetimeSafety/CMakeLists.txt 
b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
new file mode 100644
index 0..ce37a29655668
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
@@ -0,0 +1,49 @@
+# 
=
+# Lifetime Analysis Benchmarking Target
+# 
=
+# This target allows running performance benchmarks for the clang lifetime 
analysis
+# using a Python script (with managed dependencies).
+
+find_package(Python3 COMPONENTS Interpreter REQUIRED)
+
+# Define paths for the virtual environment and requirements file.
+set(LIFETIME_BENCHMARK_SCRIPT 
+  "${CMAKE_CURRENT_SOURCE_DIR}/benchmark.py")
+set(LIFETIME_BENCHMARK_VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/benchmark-venv")
+set(LIFETIME_BENCHMARK_REQUIREMENTS
+  "${CMAKE_CURRENT_SOURCE_DIR}/requirements.txt")
+set(LIFETIME_BENCHMARK_OUTPUT_DIR
+  "${CMAKE_CURRENT_BINARY_DIR}/benchmark_results")
+
+
+if(EXISTS ${LIFETIME_BENCHMARK_SCRIPT} AND EXISTS 
${LIFETIME_BENCHMARK_REQUIREMENTS})
+
+  # Set up the virtual environment and install packages
+  add_custom_command(
+OUTPUT ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+COMMAND ${Python3_EXECUTABLE} -m venv ${LIFETIME_BENCHMARK_VENV_DIR}
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python -m pip install -r 
${LIFETIME_BENCHMARK_REQUIREMENTS}
+DEPENDS ${LIFETIME_BENCHMARK_REQUIREMENTS}
+COMMENT "Creating Python virtual environment and installing dependencies 
for benchmark..."
+  )
+  add_custom_target(benchmark_venv_setup
+DEPENDS ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+  )
+
+  # Main benchmark target
+  add_custom_target(benchmark_lifetime_safety_analysis
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python 
${LIFETIME_BENCHMARK_SCRIPT}
+--clang-binary ${LLVM_BINARY_DIR}/bin/clang
+--output-dir ${LIFETIME_BENCHMARK_OUTPUT_DIR}
+
+DEPENDS clang benchmark_venv_setup
+
+# Display the output directly in the console.
+USES_TERMINAL
+
+COMMENT "Running Lifetime Analysis performance benchmarks..."
+  )
+
+  set_target_properties(benchmark_lifetime_safety_analysis 
+PROPERTIES FOLDER "Clang/Benchmarks")
+endif()
diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py 
b/clang/test/Analysis/LifetimeSafety/benchmark.py
new file mode 100644
index 0..10ffa6d7dc2be
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/benchmark.py
@@ -0,0 +1,308 @@
+import sys
+import argparse
+import subprocess
+import tempfile
+import json
+import os
+from datetime import datetime
+import numpy as np
+from scipy.optimize import curve_fit
+from scipy.stats import t
+
+
+def generate_cpp_cycle_test(n: int) -> str:
+"""
+Generates a C++ code snippet with a specified number of pointers in a 
cycle.
+Creates a while loop that rotates N pointers.
+This pattern tests the convergence speed of the dataflow analysis when
+reaching its fixed point.
+
+Example:
+struct MyObj { int id; ~MyObj() {} };
+
+void long_cycle_4(bool condition) {
+MyObj v1{1};
+MyObj v2{1};
+MyObj v3{1};
+MyObj v4{1};
+
+MyObj* p1 = &v1;
+MyObj* p2 = &v2;
+MyObj* p3 = &v3;
+MyObj* p4 = &v4;
+
+w

[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-08 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/147315
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-08 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/147315
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-08 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/147315
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-08 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/147315
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-08 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/147315
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Implement dataflow analysis for loan propagation (PR #147295)

2025-07-08 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/147295

>From 8cc690f5cae252e744dc7244dc701929a44a8799 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Sun, 6 Jul 2025 19:12:55 +
Subject: [PATCH] [LifetimeSafety] Propagate loans using dataflow analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 258 +-
 .../Sema/warn-lifetime-safety-dataflow.cpp| 186 +
 2 files changed, 443 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 366e73e803146..1c83b5051bad1 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -13,7 +13,10 @@
 #include "clang/Analysis/Analyses/PostOrderCFGView.h"
 #include "clang/Analysis/AnalysisDeclContext.h"
 #include "clang/Analysis/CFG.h"
+#include "clang/Analysis/FlowSensitive/DataflowWorklist.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/ImmutableSet.h"
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Debug.h"
@@ -487,7 +490,247 @@ class FactGenerator : public 
ConstStmtVisitor {
 };
 
 // = //
-//  TODO: Run dataflow analysis to propagate loans, analyse and error 
reporting.
+//  The Dataflow Lattice
+// = //
+
+// Using LLVM's immutable collections is efficient for dataflow analysis
+// as it avoids deep copies during state transitions.
+// TODO(opt): Consider using a bitset to represent the set of loans.
+using LoanSet = llvm::ImmutableSet;
+using OriginLoanMap = llvm::ImmutableMap;
+
+/// An object to hold the factories for immutable collections, ensuring
+/// that all created states share the same underlying memory management.
+struct LifetimeFactory {
+  OriginLoanMap::Factory OriginMapFact;
+  LoanSet::Factory LoanSetFact;
+
+  LoanSet createLoanSet(LoanID LID) {
+return LoanSetFact.add(LoanSetFact.getEmptySet(), LID);
+  }
+};
+
+/// LifetimeLattice represents the state of our analysis at a given program
+/// point. It is an immutable object, and all operations produce a new
+/// instance rather than modifying the existing one.
+struct LifetimeLattice {
+  /// The map from an origin to the set of loans it contains.
+  /// TODO(opt): To reduce the lattice size, propagate origins of declarations,
+  /// not expressions, because expressions are not visible across blocks.
+  OriginLoanMap Origins = OriginLoanMap(nullptr);
+
+  explicit LifetimeLattice(const OriginLoanMap &S) : Origins(S) {}
+  LifetimeLattice() = default;
+
+  bool operator==(const LifetimeLattice &Other) const {
+return Origins == Other.Origins;
+  }
+  bool operator!=(const LifetimeLattice &Other) const {
+return !(*this == Other);
+  }
+
+  LoanSet getLoans(OriginID OID, LifetimeFactory &Factory) const {
+if (auto *Loans = Origins.lookup(OID))
+  return *Loans;
+return Factory.LoanSetFact.getEmptySet();
+  }
+
+  /// Computes the union of two lattices by performing a key-wise join of
+  /// their OriginLoanMaps.
+  // TODO(opt): This key-wise join is a performance bottleneck. A more
+  // efficient merge could be implemented using a Patricia Trie or HAMT
+  // instead of the current AVL-tree-based ImmutableMap.
+  LifetimeLattice join(const LifetimeLattice &Other,
+   LifetimeFactory &Factory) const {
+/// Merge the smaller map into the larger one ensuring we iterate over the
+/// smaller map.
+if (Origins.getHeight() < Other.Origins.getHeight())
+  return Other.join(*this, Factory);
+
+OriginLoanMap JoinedState = Origins;
+// For each origin in the other map, union its loan set with ours.
+for (const auto &Entry : Other.Origins) {
+  OriginID OID = Entry.first;
+  LoanSet OtherLoanSet = Entry.second;
+  JoinedState = Factory.OriginMapFact.add(
+  JoinedState, OID,
+  join(getLoans(OID, Factory), OtherLoanSet, Factory));
+}
+return LifetimeLattice(JoinedState);
+  }
+
+  LoanSet join(LoanSet a, LoanSet b, LifetimeFactory &Factory) const {
+/// Merge the smaller set into the larger one ensuring we iterate over the
+/// smaller set.
+if (a.getHeight() < b.getHeight())
+  std::swap(a, b);
+LoanSet Result = a;
+for (LoanID LID : b) {
+  /// TODO(opt): Profiling shows that this loop is a major performance
+  /// bottleneck. Investigate using a BitVector to represent the set of
+  /// loans for improved join performance.
+  Result = Factory.LoanSetFact.add(Result, LID);
+}
+return Result;
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "LifetimeLattice State:\n";
+if (Origins.isEmpty())
+  OS << "  \n";
+for (const auto &Entry : Origins) {
+  if (Entry.second.isEmpty())
+OS

[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-08 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/147315

>From e8687c3d58a9da0874814846a1dbbaf173cdbf34 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 7 Jul 2025 15:13:00 +
Subject: [PATCH] [LifetimeSafety] Add script performance benchmarking

---
 .../Analysis/LifetimeSafety/CMakeLists.txt|  49 +++
 .../test/Analysis/LifetimeSafety/benchmark.py | 307 ++
 .../Analysis/LifetimeSafety/requirements.txt  |   2 +
 clang/test/CMakeLists.txt |   2 +
 4 files changed, 360 insertions(+)
 create mode 100644 clang/test/Analysis/LifetimeSafety/CMakeLists.txt
 create mode 100644 clang/test/Analysis/LifetimeSafety/benchmark.py
 create mode 100644 clang/test/Analysis/LifetimeSafety/requirements.txt

diff --git a/clang/test/Analysis/LifetimeSafety/CMakeLists.txt 
b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
new file mode 100644
index 0..ce37a29655668
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
@@ -0,0 +1,49 @@
+# 
=
+# Lifetime Analysis Benchmarking Target
+# 
=
+# This target allows running performance benchmarks for the clang lifetime 
analysis
+# using a Python script (with managed dependencies).
+
+find_package(Python3 COMPONENTS Interpreter REQUIRED)
+
+# Define paths for the virtual environment and requirements file.
+set(LIFETIME_BENCHMARK_SCRIPT 
+  "${CMAKE_CURRENT_SOURCE_DIR}/benchmark.py")
+set(LIFETIME_BENCHMARK_VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/benchmark-venv")
+set(LIFETIME_BENCHMARK_REQUIREMENTS
+  "${CMAKE_CURRENT_SOURCE_DIR}/requirements.txt")
+set(LIFETIME_BENCHMARK_OUTPUT_DIR
+  "${CMAKE_CURRENT_BINARY_DIR}/benchmark_results")
+
+
+if(EXISTS ${LIFETIME_BENCHMARK_SCRIPT} AND EXISTS 
${LIFETIME_BENCHMARK_REQUIREMENTS})
+
+  # Set up the virtual environment and install packages
+  add_custom_command(
+OUTPUT ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+COMMAND ${Python3_EXECUTABLE} -m venv ${LIFETIME_BENCHMARK_VENV_DIR}
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python -m pip install -r 
${LIFETIME_BENCHMARK_REQUIREMENTS}
+DEPENDS ${LIFETIME_BENCHMARK_REQUIREMENTS}
+COMMENT "Creating Python virtual environment and installing dependencies 
for benchmark..."
+  )
+  add_custom_target(benchmark_venv_setup
+DEPENDS ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+  )
+
+  # Main benchmark target
+  add_custom_target(benchmark_lifetime_safety_analysis
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python 
${LIFETIME_BENCHMARK_SCRIPT}
+--clang-binary ${LLVM_BINARY_DIR}/bin/clang
+--output-dir ${LIFETIME_BENCHMARK_OUTPUT_DIR}
+
+DEPENDS clang benchmark_venv_setup
+
+# Display the output directly in the console.
+USES_TERMINAL
+
+COMMENT "Running Lifetime Analysis performance benchmarks..."
+  )
+
+  set_target_properties(benchmark_lifetime_safety_analysis 
+PROPERTIES FOLDER "Clang/Benchmarks")
+endif()
diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py 
b/clang/test/Analysis/LifetimeSafety/benchmark.py
new file mode 100644
index 0..9d5f36c51b9ee
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/benchmark.py
@@ -0,0 +1,307 @@
+import sys
+import argparse
+import subprocess
+import tempfile
+import json
+import os
+from datetime import datetime
+import numpy as np
+from scipy.optimize import curve_fit
+from scipy.stats import t
+
+
+def generate_cpp_cycle_test(n: int) -> str:
+"""
+Generates a C++ code snippet with a specified number of pointers in a 
cycle.
+Creates a while loop that rotates N pointers.
+This pattern tests the convergence speed of the dataflow analysis when
+reaching its fixed point.
+
+Example:
+struct MyObj { int id; ~MyObj() {} };
+
+void long_cycle_4(bool condition) {
+MyObj v1{1};
+MyObj v2{1};
+MyObj v3{1};
+MyObj v4{1};
+
+MyObj* p1 = &v1;
+MyObj* p2 = &v2;
+MyObj* p3 = &v3;
+MyObj* p4 = &v4;
+
+while (condition) {
+MyObj* temp = p1;
+p1 = p2;
+p2 = p3;
+p3 = p4;
+p4 = temp;
+}
+}
+"""
+if n <= 0:
+return "// Number of variables must be positive."
+
+cpp_code = "struct MyObj { int id; ~MyObj() {} };\n\n"
+cpp_code += f"void long_cycle_{n}(bool condition) {{\n"
+for i in range(1, n + 1):
+cpp_code += f"  MyObj v{i}{{1}};\n"
+cpp_code += "\n"
+for i in range(1, n + 1):
+cpp_code += f"  MyObj* p{i} = &v{i};\n"
+
+cpp_code += "\n  while (condition) {\n"
+if n > 0:
+cpp_code += f"MyObj* temp = p1;\n"
+for i in range(1, n):
+cpp_code += f"p{i} = p{i+1};\n"
+cpp_code += f" 

[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-08 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 ready_for_review 
https://github.com/llvm/llvm-project/pull/147315
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-08 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/147315
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-08 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/147315
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-08 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/147315
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-08 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/147315

>From 1ebcbdfa5dae7a9970634e8316f4b8e344312a0e Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 7 Jul 2025 15:13:00 +
Subject: [PATCH] [LifetimeSafety] Add script performance benchmarking

---
 clang/lib/Analysis/LifetimeSafety.cpp |   7 +-
 .../Analysis/LifetimeSafety/CMakeLists.txt|  49 +++
 .../test/Analysis/LifetimeSafety/benchmark.py | 307 ++
 .../Analysis/LifetimeSafety/requirements.txt  |   2 +
 clang/test/CMakeLists.txt |   2 +
 5 files changed, 366 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/Analysis/LifetimeSafety/CMakeLists.txt
 create mode 100644 clang/test/Analysis/LifetimeSafety/benchmark.py
 create mode 100644 clang/test/Analysis/LifetimeSafety/requirements.txt

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index e881e592ef59f..1c83b5051bad1 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -151,7 +151,12 @@ class OriginManager {
 
   OriginID get(const ValueDecl &D) {
 auto It = DeclToOriginID.find(&D);
-assert(It != DeclToOriginID.end());
+// TODO: This should be an assert(It != ExprToOriginID.end()). The current
+// implementation falls back to getOrCreate to avoid crashing on
+// yet-unhandled pointer expressions, creating an empty origin for them.
+if (It == DeclToOriginID.end())
+  return getOrCreate(D);
+
 return It->second;
   }
 
diff --git a/clang/test/Analysis/LifetimeSafety/CMakeLists.txt 
b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
new file mode 100644
index 0..ce37a29655668
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
@@ -0,0 +1,49 @@
+# 
=
+# Lifetime Analysis Benchmarking Target
+# 
=
+# This target allows running performance benchmarks for the clang lifetime 
analysis
+# using a Python script (with managed dependencies).
+
+find_package(Python3 COMPONENTS Interpreter REQUIRED)
+
+# Define paths for the virtual environment and requirements file.
+set(LIFETIME_BENCHMARK_SCRIPT 
+  "${CMAKE_CURRENT_SOURCE_DIR}/benchmark.py")
+set(LIFETIME_BENCHMARK_VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/benchmark-venv")
+set(LIFETIME_BENCHMARK_REQUIREMENTS
+  "${CMAKE_CURRENT_SOURCE_DIR}/requirements.txt")
+set(LIFETIME_BENCHMARK_OUTPUT_DIR
+  "${CMAKE_CURRENT_BINARY_DIR}/benchmark_results")
+
+
+if(EXISTS ${LIFETIME_BENCHMARK_SCRIPT} AND EXISTS 
${LIFETIME_BENCHMARK_REQUIREMENTS})
+
+  # Set up the virtual environment and install packages
+  add_custom_command(
+OUTPUT ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+COMMAND ${Python3_EXECUTABLE} -m venv ${LIFETIME_BENCHMARK_VENV_DIR}
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python -m pip install -r 
${LIFETIME_BENCHMARK_REQUIREMENTS}
+DEPENDS ${LIFETIME_BENCHMARK_REQUIREMENTS}
+COMMENT "Creating Python virtual environment and installing dependencies 
for benchmark..."
+  )
+  add_custom_target(benchmark_venv_setup
+DEPENDS ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+  )
+
+  # Main benchmark target
+  add_custom_target(benchmark_lifetime_safety_analysis
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python 
${LIFETIME_BENCHMARK_SCRIPT}
+--clang-binary ${LLVM_BINARY_DIR}/bin/clang
+--output-dir ${LIFETIME_BENCHMARK_OUTPUT_DIR}
+
+DEPENDS clang benchmark_venv_setup
+
+# Display the output directly in the console.
+USES_TERMINAL
+
+COMMENT "Running Lifetime Analysis performance benchmarks..."
+  )
+
+  set_target_properties(benchmark_lifetime_safety_analysis 
+PROPERTIES FOLDER "Clang/Benchmarks")
+endif()
diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py 
b/clang/test/Analysis/LifetimeSafety/benchmark.py
new file mode 100644
index 0..9d5f36c51b9ee
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/benchmark.py
@@ -0,0 +1,307 @@
+import sys
+import argparse
+import subprocess
+import tempfile
+import json
+import os
+from datetime import datetime
+import numpy as np
+from scipy.optimize import curve_fit
+from scipy.stats import t
+
+
+def generate_cpp_cycle_test(n: int) -> str:
+"""
+Generates a C++ code snippet with a specified number of pointers in a 
cycle.
+Creates a while loop that rotates N pointers.
+This pattern tests the convergence speed of the dataflow analysis when
+reaching its fixed point.
+
+Example:
+struct MyObj { int id; ~MyObj() {} };
+
+void long_cycle_4(bool condition) {
+MyObj v1{1};
+MyObj v2{1};
+MyObj v3{1};
+MyObj v4{1};
+
+MyObj* p1 = &v1;
+MyObj* p2 = &v2;
+MyObj* p3 = &v3;
+MyObj* p4 = &v4;
+
+w

[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-08 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/147315
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-11 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/147315

>From 7d9009c2f22bf3f0980f7fd811be3185192490cf Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 7 Jul 2025 15:13:00 +
Subject: [PATCH] [LifetimeSafety] Add script performance benchmarking

---
 .../Analysis/LifetimeSafety/CMakeLists.txt|  49 +++
 .../test/Analysis/LifetimeSafety/benchmark.py | 307 ++
 .../Analysis/LifetimeSafety/requirements.txt  |   2 +
 clang/test/CMakeLists.txt |   2 +
 4 files changed, 360 insertions(+)
 create mode 100644 clang/test/Analysis/LifetimeSafety/CMakeLists.txt
 create mode 100644 clang/test/Analysis/LifetimeSafety/benchmark.py
 create mode 100644 clang/test/Analysis/LifetimeSafety/requirements.txt

diff --git a/clang/test/Analysis/LifetimeSafety/CMakeLists.txt 
b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
new file mode 100644
index 0..ce37a29655668
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
@@ -0,0 +1,49 @@
+# 
=
+# Lifetime Analysis Benchmarking Target
+# 
=
+# This target allows running performance benchmarks for the clang lifetime 
analysis
+# using a Python script (with managed dependencies).
+
+find_package(Python3 COMPONENTS Interpreter REQUIRED)
+
+# Define paths for the virtual environment and requirements file.
+set(LIFETIME_BENCHMARK_SCRIPT 
+  "${CMAKE_CURRENT_SOURCE_DIR}/benchmark.py")
+set(LIFETIME_BENCHMARK_VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/benchmark-venv")
+set(LIFETIME_BENCHMARK_REQUIREMENTS
+  "${CMAKE_CURRENT_SOURCE_DIR}/requirements.txt")
+set(LIFETIME_BENCHMARK_OUTPUT_DIR
+  "${CMAKE_CURRENT_BINARY_DIR}/benchmark_results")
+
+
+if(EXISTS ${LIFETIME_BENCHMARK_SCRIPT} AND EXISTS 
${LIFETIME_BENCHMARK_REQUIREMENTS})
+
+  # Set up the virtual environment and install packages
+  add_custom_command(
+OUTPUT ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+COMMAND ${Python3_EXECUTABLE} -m venv ${LIFETIME_BENCHMARK_VENV_DIR}
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python -m pip install -r 
${LIFETIME_BENCHMARK_REQUIREMENTS}
+DEPENDS ${LIFETIME_BENCHMARK_REQUIREMENTS}
+COMMENT "Creating Python virtual environment and installing dependencies 
for benchmark..."
+  )
+  add_custom_target(benchmark_venv_setup
+DEPENDS ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+  )
+
+  # Main benchmark target
+  add_custom_target(benchmark_lifetime_safety_analysis
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python 
${LIFETIME_BENCHMARK_SCRIPT}
+--clang-binary ${LLVM_BINARY_DIR}/bin/clang
+--output-dir ${LIFETIME_BENCHMARK_OUTPUT_DIR}
+
+DEPENDS clang benchmark_venv_setup
+
+# Display the output directly in the console.
+USES_TERMINAL
+
+COMMENT "Running Lifetime Analysis performance benchmarks..."
+  )
+
+  set_target_properties(benchmark_lifetime_safety_analysis 
+PROPERTIES FOLDER "Clang/Benchmarks")
+endif()
diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py 
b/clang/test/Analysis/LifetimeSafety/benchmark.py
new file mode 100644
index 0..9d5f36c51b9ee
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/benchmark.py
@@ -0,0 +1,307 @@
+import sys
+import argparse
+import subprocess
+import tempfile
+import json
+import os
+from datetime import datetime
+import numpy as np
+from scipy.optimize import curve_fit
+from scipy.stats import t
+
+
+def generate_cpp_cycle_test(n: int) -> str:
+"""
+Generates a C++ code snippet with a specified number of pointers in a 
cycle.
+Creates a while loop that rotates N pointers.
+This pattern tests the convergence speed of the dataflow analysis when
+reaching its fixed point.
+
+Example:
+struct MyObj { int id; ~MyObj() {} };
+
+void long_cycle_4(bool condition) {
+MyObj v1{1};
+MyObj v2{1};
+MyObj v3{1};
+MyObj v4{1};
+
+MyObj* p1 = &v1;
+MyObj* p2 = &v2;
+MyObj* p3 = &v3;
+MyObj* p4 = &v4;
+
+while (condition) {
+MyObj* temp = p1;
+p1 = p2;
+p2 = p3;
+p3 = p4;
+p4 = temp;
+}
+}
+"""
+if n <= 0:
+return "// Number of variables must be positive."
+
+cpp_code = "struct MyObj { int id; ~MyObj() {} };\n\n"
+cpp_code += f"void long_cycle_{n}(bool condition) {{\n"
+for i in range(1, n + 1):
+cpp_code += f"  MyObj v{i}{{1}};\n"
+cpp_code += "\n"
+for i in range(1, n + 1):
+cpp_code += f"  MyObj* p{i} = &v{i};\n"
+
+cpp_code += "\n  while (condition) {\n"
+if n > 0:
+cpp_code += f"MyObj* temp = p1;\n"
+for i in range(1, n):
+cpp_code += f"p{i} = p{i+1};\n"
+cpp_code += f" 

[llvm-branch-commits] [clang] [LifetimeSafety] Add expired loans analysis (PR #148222)

2025-07-11 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 created 
https://github.com/llvm/llvm-project/pull/148222

None

>From 14a9c8b50df11ce48ce15d0fbe29568b3e23b5a6 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Fri, 11 Jul 2025 11:11:47 +
Subject: [PATCH] [LifetimeSafety] Add expired loans analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 140 ++
 1 file changed, 140 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index e72192aa92c1a..88ec70d000d2c 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -735,6 +735,142 @@ class LifetimeDataflow {
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The lattice for tracking expired loans. It is a set of loan IDs.
+struct ExpiredLattice {
+  LoanSet Expired;
+
+  ExpiredLattice() = default;
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  /// Computes the union of two lattices.
+  ExpiredLattice join(const ExpiredLattice &Other,
+  LoanSet::Factory &Factory) const {
+LoanSet JoinedSet = Expired;
+for (LoanID LID : Other.Expired)
+  JoinedSet = Factory.add(JoinedSet, LID);
+return ExpiredLattice(JoinedSet);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+/// Transfer function for the expired loans analysis.
+class ExpiredLoansTransferer {
+  FactManager &AllFacts;
+  LoanSet::Factory &SetFactory;
+
+public:
+  explicit ExpiredLoansTransferer(FactManager &F, LoanSet::Factory &SF)
+  : AllFacts(F), SetFactory(SF) {}
+
+  /// Computes the exit state of a block by applying all its facts sequentially
+  /// to a given entry state.
+  ExpiredLattice transferBlock(const CFGBlock *Block,
+ExpiredLattice EntryState) {
+ExpiredLattice BlockState = EntryState;
+llvm::ArrayRef Facts = AllFacts.getFacts(Block);
+
+for (const Fact *F : Facts) {
+  BlockState = transferFact(BlockState, F);
+}
+return BlockState;
+  }
+
+private:
+  ExpiredLattice transferFact(ExpiredLattice In, const Fact *F) {
+if (const auto *EF = F->getAs())
+  return ExpiredLattice(SetFactory.add(In.Expired, EF->getLoanID()));
+
+if (const auto *IF = F->getAs())
+  return ExpiredLattice(SetFactory.remove(In.Expired, IF->getLoanID()));
+
+return In;
+  }
+};
+
+/// Dataflow analysis driver for tracking expired loans.
+class ExpiredLoansAnalysis {
+  const CFG &Cfg;
+  AnalysisDeclContext &AC;
+  LoanSet::Factory SetFactory;
+  ExpiredLoansTransferer Xfer;
+
+  llvm::DenseMap BlockEntryStates;
+  llvm::DenseMap BlockExitStates;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, FactManager &FS, AnalysisDeclContext &AC)
+  : Cfg(C), AC(AC), Xfer(FS, SetFactory) {}
+
+  void run() {
+llvm::TimeTraceScope TimeProfile("Expired Loans Analysis");
+ForwardDataflowWorklist Worklist(Cfg, AC);
+const CFGBlock *Entry = &Cfg.getEntry();
+BlockEntryStates[Entry] = ExpiredLattice(SetFactory.getEmptySet());
+Worklist.enqueueBlock(Entry);
+while (const CFGBlock *B = Worklist.dequeue()) {
+  ExpiredLattice EntryState = getEntryState(B);
+  ExpiredLattice ExitState = Xfer.transferBlock(B, EntryState);
+  BlockExitStates[B] = ExitState;
+
+  for (const CFGBlock *Successor : B->succs()) {
+auto SuccIt = BlockEntryStates.find(Successor);
+ExpiredLattice OldSuccEntryState = (SuccIt != BlockEntryStates.end())
+? SuccIt->second
+: ExpiredLattice{};
+ExpiredLattice NewSuccEntryState =
+OldSuccEntryState.join(ExitState, SetFactory);
+if (SuccIt == BlockEntryStates.end() ||
+NewSuccEntryState != OldSuccEntryState) {
+  BlockEntryStates[Successor] = NewSuccEntryState;
+  Worklist.enqueueBlock(Successor);
+}
+  }
+}
+  }
+
+  void dump() const {
+llvm::dbgs() << "==\n";
+llvm::dbgs() << "   Expired Loans Results:\n";
+llvm::dbgs() << "==\n";
+const CFGBlock &B = Cfg.getExit();
+getExitState(&B).dump(llvm::dbgs());
+  }
+
+  ExpiredLattice getEntryState(const CFGBlock *B) const {
+auto It = BlockEntryStates.find(B);
+if (It != BlockEntryStates.end()) {
+  return It->second;
+}
+return ExpiredLattice(SetFac

[llvm-branch-commits] [clang] [LifetimeSafety] Add expired loans analysis (PR #148222)

2025-07-11 Thread Utkarsh Saxena via llvm-branch-commits

usx95 wrote:

> [!WARNING]
> This pull request is not mergeable via GitHub because a downstack PR is 
> open. Once all requirements are satisfied, merge this PR as a stack  href="https://app.graphite.dev/github/pr/llvm/llvm-project/148222?utm_source=stack-comment-downstack-mergeability-warning";
>  >on Graphite.
> https://graphite.dev/docs/merge-pull-requests";>Learn more

* **#148222** https://app.graphite.dev/github/pr/llvm/llvm-project/148222?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> 👈 https://app.graphite.dev/github/pr/llvm/llvm-project/148222?utm_source=stack-comment-view-in-graphite";
 target="_blank">(View in Graphite)
* **#148065** https://app.graphite.dev/github/pr/llvm/llvm-project/148065?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>: 1 other dependent PR 
([#147315](https://github.com/llvm/llvm-project/pull/147315) https://app.graphite.dev/github/pr/llvm/llvm-project/147315?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>)
* `main`




This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn 
more about https://stacking.dev/?utm_source=stack-comment";>stacking.


https://github.com/llvm/llvm-project/pull/148222
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-10 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/147315

>From 7fcb14746ba080092560f18860534bb4d2d7adda Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 7 Jul 2025 15:13:00 +
Subject: [PATCH] [LifetimeSafety] Add script performance benchmarking

---
 .../Analysis/LifetimeSafety/CMakeLists.txt|  49 +++
 .../test/Analysis/LifetimeSafety/benchmark.py | 307 ++
 .../Analysis/LifetimeSafety/requirements.txt  |   2 +
 clang/test/CMakeLists.txt |   2 +
 4 files changed, 360 insertions(+)
 create mode 100644 clang/test/Analysis/LifetimeSafety/CMakeLists.txt
 create mode 100644 clang/test/Analysis/LifetimeSafety/benchmark.py
 create mode 100644 clang/test/Analysis/LifetimeSafety/requirements.txt

diff --git a/clang/test/Analysis/LifetimeSafety/CMakeLists.txt 
b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
new file mode 100644
index 0..ce37a29655668
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
@@ -0,0 +1,49 @@
+# 
=
+# Lifetime Analysis Benchmarking Target
+# 
=
+# This target allows running performance benchmarks for the clang lifetime 
analysis
+# using a Python script (with managed dependencies).
+
+find_package(Python3 COMPONENTS Interpreter REQUIRED)
+
+# Define paths for the virtual environment and requirements file.
+set(LIFETIME_BENCHMARK_SCRIPT 
+  "${CMAKE_CURRENT_SOURCE_DIR}/benchmark.py")
+set(LIFETIME_BENCHMARK_VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/benchmark-venv")
+set(LIFETIME_BENCHMARK_REQUIREMENTS
+  "${CMAKE_CURRENT_SOURCE_DIR}/requirements.txt")
+set(LIFETIME_BENCHMARK_OUTPUT_DIR
+  "${CMAKE_CURRENT_BINARY_DIR}/benchmark_results")
+
+
+if(EXISTS ${LIFETIME_BENCHMARK_SCRIPT} AND EXISTS 
${LIFETIME_BENCHMARK_REQUIREMENTS})
+
+  # Set up the virtual environment and install packages
+  add_custom_command(
+OUTPUT ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+COMMAND ${Python3_EXECUTABLE} -m venv ${LIFETIME_BENCHMARK_VENV_DIR}
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python -m pip install -r 
${LIFETIME_BENCHMARK_REQUIREMENTS}
+DEPENDS ${LIFETIME_BENCHMARK_REQUIREMENTS}
+COMMENT "Creating Python virtual environment and installing dependencies 
for benchmark..."
+  )
+  add_custom_target(benchmark_venv_setup
+DEPENDS ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+  )
+
+  # Main benchmark target
+  add_custom_target(benchmark_lifetime_safety_analysis
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python 
${LIFETIME_BENCHMARK_SCRIPT}
+--clang-binary ${LLVM_BINARY_DIR}/bin/clang
+--output-dir ${LIFETIME_BENCHMARK_OUTPUT_DIR}
+
+DEPENDS clang benchmark_venv_setup
+
+# Display the output directly in the console.
+USES_TERMINAL
+
+COMMENT "Running Lifetime Analysis performance benchmarks..."
+  )
+
+  set_target_properties(benchmark_lifetime_safety_analysis 
+PROPERTIES FOLDER "Clang/Benchmarks")
+endif()
diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py 
b/clang/test/Analysis/LifetimeSafety/benchmark.py
new file mode 100644
index 0..9d5f36c51b9ee
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/benchmark.py
@@ -0,0 +1,307 @@
+import sys
+import argparse
+import subprocess
+import tempfile
+import json
+import os
+from datetime import datetime
+import numpy as np
+from scipy.optimize import curve_fit
+from scipy.stats import t
+
+
+def generate_cpp_cycle_test(n: int) -> str:
+"""
+Generates a C++ code snippet with a specified number of pointers in a 
cycle.
+Creates a while loop that rotates N pointers.
+This pattern tests the convergence speed of the dataflow analysis when
+reaching its fixed point.
+
+Example:
+struct MyObj { int id; ~MyObj() {} };
+
+void long_cycle_4(bool condition) {
+MyObj v1{1};
+MyObj v2{1};
+MyObj v3{1};
+MyObj v4{1};
+
+MyObj* p1 = &v1;
+MyObj* p2 = &v2;
+MyObj* p3 = &v3;
+MyObj* p4 = &v4;
+
+while (condition) {
+MyObj* temp = p1;
+p1 = p2;
+p2 = p3;
+p3 = p4;
+p4 = temp;
+}
+}
+"""
+if n <= 0:
+return "// Number of variables must be positive."
+
+cpp_code = "struct MyObj { int id; ~MyObj() {} };\n\n"
+cpp_code += f"void long_cycle_{n}(bool condition) {{\n"
+for i in range(1, n + 1):
+cpp_code += f"  MyObj v{i}{{1}};\n"
+cpp_code += "\n"
+for i in range(1, n + 1):
+cpp_code += f"  MyObj* p{i} = &v{i};\n"
+
+cpp_code += "\n  while (condition) {\n"
+if n > 0:
+cpp_code += f"MyObj* temp = p1;\n"
+for i in range(1, n):
+cpp_code += f"p{i} = p{i+1};\n"
+cpp_code += f" 

[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-10 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/147315

>From 7fcb14746ba080092560f18860534bb4d2d7adda Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 7 Jul 2025 15:13:00 +
Subject: [PATCH] [LifetimeSafety] Add script performance benchmarking

---
 .../Analysis/LifetimeSafety/CMakeLists.txt|  49 +++
 .../test/Analysis/LifetimeSafety/benchmark.py | 307 ++
 .../Analysis/LifetimeSafety/requirements.txt  |   2 +
 clang/test/CMakeLists.txt |   2 +
 4 files changed, 360 insertions(+)
 create mode 100644 clang/test/Analysis/LifetimeSafety/CMakeLists.txt
 create mode 100644 clang/test/Analysis/LifetimeSafety/benchmark.py
 create mode 100644 clang/test/Analysis/LifetimeSafety/requirements.txt

diff --git a/clang/test/Analysis/LifetimeSafety/CMakeLists.txt 
b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
new file mode 100644
index 0..ce37a29655668
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
@@ -0,0 +1,49 @@
+# 
=
+# Lifetime Analysis Benchmarking Target
+# 
=
+# This target allows running performance benchmarks for the clang lifetime 
analysis
+# using a Python script (with managed dependencies).
+
+find_package(Python3 COMPONENTS Interpreter REQUIRED)
+
+# Define paths for the virtual environment and requirements file.
+set(LIFETIME_BENCHMARK_SCRIPT 
+  "${CMAKE_CURRENT_SOURCE_DIR}/benchmark.py")
+set(LIFETIME_BENCHMARK_VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/benchmark-venv")
+set(LIFETIME_BENCHMARK_REQUIREMENTS
+  "${CMAKE_CURRENT_SOURCE_DIR}/requirements.txt")
+set(LIFETIME_BENCHMARK_OUTPUT_DIR
+  "${CMAKE_CURRENT_BINARY_DIR}/benchmark_results")
+
+
+if(EXISTS ${LIFETIME_BENCHMARK_SCRIPT} AND EXISTS 
${LIFETIME_BENCHMARK_REQUIREMENTS})
+
+  # Set up the virtual environment and install packages
+  add_custom_command(
+OUTPUT ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+COMMAND ${Python3_EXECUTABLE} -m venv ${LIFETIME_BENCHMARK_VENV_DIR}
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python -m pip install -r 
${LIFETIME_BENCHMARK_REQUIREMENTS}
+DEPENDS ${LIFETIME_BENCHMARK_REQUIREMENTS}
+COMMENT "Creating Python virtual environment and installing dependencies 
for benchmark..."
+  )
+  add_custom_target(benchmark_venv_setup
+DEPENDS ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+  )
+
+  # Main benchmark target
+  add_custom_target(benchmark_lifetime_safety_analysis
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python 
${LIFETIME_BENCHMARK_SCRIPT}
+--clang-binary ${LLVM_BINARY_DIR}/bin/clang
+--output-dir ${LIFETIME_BENCHMARK_OUTPUT_DIR}
+
+DEPENDS clang benchmark_venv_setup
+
+# Display the output directly in the console.
+USES_TERMINAL
+
+COMMENT "Running Lifetime Analysis performance benchmarks..."
+  )
+
+  set_target_properties(benchmark_lifetime_safety_analysis 
+PROPERTIES FOLDER "Clang/Benchmarks")
+endif()
diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py 
b/clang/test/Analysis/LifetimeSafety/benchmark.py
new file mode 100644
index 0..9d5f36c51b9ee
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/benchmark.py
@@ -0,0 +1,307 @@
+import sys
+import argparse
+import subprocess
+import tempfile
+import json
+import os
+from datetime import datetime
+import numpy as np
+from scipy.optimize import curve_fit
+from scipy.stats import t
+
+
+def generate_cpp_cycle_test(n: int) -> str:
+"""
+Generates a C++ code snippet with a specified number of pointers in a 
cycle.
+Creates a while loop that rotates N pointers.
+This pattern tests the convergence speed of the dataflow analysis when
+reaching its fixed point.
+
+Example:
+struct MyObj { int id; ~MyObj() {} };
+
+void long_cycle_4(bool condition) {
+MyObj v1{1};
+MyObj v2{1};
+MyObj v3{1};
+MyObj v4{1};
+
+MyObj* p1 = &v1;
+MyObj* p2 = &v2;
+MyObj* p3 = &v3;
+MyObj* p4 = &v4;
+
+while (condition) {
+MyObj* temp = p1;
+p1 = p2;
+p2 = p3;
+p3 = p4;
+p4 = temp;
+}
+}
+"""
+if n <= 0:
+return "// Number of variables must be positive."
+
+cpp_code = "struct MyObj { int id; ~MyObj() {} };\n\n"
+cpp_code += f"void long_cycle_{n}(bool condition) {{\n"
+for i in range(1, n + 1):
+cpp_code += f"  MyObj v{i}{{1}};\n"
+cpp_code += "\n"
+for i in range(1, n + 1):
+cpp_code += f"  MyObj* p{i} = &v{i};\n"
+
+cpp_code += "\n  while (condition) {\n"
+if n > 0:
+cpp_code += f"MyObj* temp = p1;\n"
+for i in range(1, n):
+cpp_code += f"p{i} = p{i+1};\n"
+cpp_code += f" 

[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-10 Thread Utkarsh Saxena via llvm-branch-commits

usx95 wrote:

> [!WARNING]
> This pull request is not mergeable via GitHub because a downstack PR is 
> open. Once all requirements are satisfied, merge this PR as a stack  href="https://app.graphite.dev/github/pr/llvm/llvm-project/147315?utm_source=stack-comment-downstack-mergeability-warning";
>  >on Graphite.
> https://graphite.dev/docs/merge-pull-requests";>Learn more

* **#147315** https://app.graphite.dev/github/pr/llvm/llvm-project/147315?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/> 👈 https://app.graphite.dev/github/pr/llvm/llvm-project/147315?utm_source=stack-comment-view-in-graphite";
 target="_blank">(View in Graphite)
* **#147295** https://app.graphite.dev/github/pr/llvm/llvm-project/147295?utm_source=stack-comment-icon";
 target="_blank">https://static.graphite.dev/graphite-32x32-black.png"; alt="Graphite" 
width="10px" height="10px"/>
* `users/usx95/lifetime-safety-initial`




This stack of pull requests is managed by https://graphite.dev?utm-source=stack-comment";>Graphite. Learn 
more about https://stacking.dev/?utm_source=stack-comment";>stacking.


https://github.com/llvm/llvm-project/pull/147315
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Implement dataflow analysis for loan propagation (PR #147295)

2025-07-10 Thread Utkarsh Saxena via llvm-branch-commits

usx95 wrote:

Sorry about closing this. I have moved this to 
https://github.com/llvm/llvm-project/pull/148065

I accidentally deleted the base branch which permanently closes the PR :(

https://github.com/llvm/llvm-project/pull/147295
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From 8f6394b2ab6183fd06f6e216cbaa70b823809e5d Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From 12e5b9a2dc200a9d8e710ef509bb39021fc92de0 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 61 +++
 1 file changed, 61 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 0b4241cdf404c..300cc6ddd66af 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -769,6 +769,65 @@ class LoanPropagationAnalysis
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The dataflow lattice for tracking the set of expired loans.
+class ExpiredLattice {
+public:
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+/// The analysis that tracks which loans have expired.
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &Factory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LifetimeFactory &SF)
+  : DataflowAnalysis(C, AC, F), Factory(SF.LoanSetFactory) {}
+
+  using DataflowAnalysis::transfer;
+
+  const char *getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
+
+  /// Merges two lattices by taking the union of the expired loan sets.
+  Lattice join(Lattice L1, Lattice L2) const {
+return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(Factory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(Factory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO:
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -801,5 +860,7 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, Factory);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredAnalysis(Cfg, AC, FactMgr, Factory);
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From 3c30a13f6f796fd9483f7d6aeea28c12b8ad6d64 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From 9da8f3ab473378b2f5191c88b60a847e777ef4ec Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 61 +++
 1 file changed, 61 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 8be93bbba7131..e30e979bf1120 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -762,6 +762,64 @@ class LoanPropagationAnalysis
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The dataflow lattice for tracking the set of expired loans.
+struct ExpiredLattice {
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+/// The analysis that tracks which loans have expired.
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &Factory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LifetimeFactory &SF)
+  : DataflowAnalysis(C, AC, F), Factory(SF.LoanSetFactory) {}
+
+  using DataflowAnalysis::transfer;
+
+  StringRef getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
+
+  /// Merges two lattices by taking the union of the expired loan sets.
+  Lattice join(Lattice L1, Lattice L2) const {
+return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(Factory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(Factory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO:
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -794,5 +852,8 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, Factory);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredLoans(Cfg, AC, FactMgr, Factory);
+  ExpiredLoans.run();
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From 3c30a13f6f796fd9483f7d6aeea28c12b8ad6d64 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From 9da8f3ab473378b2f5191c88b60a847e777ef4ec Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 61 +++
 1 file changed, 61 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 8be93bbba7131..e30e979bf1120 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -762,6 +762,64 @@ class LoanPropagationAnalysis
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The dataflow lattice for tracking the set of expired loans.
+struct ExpiredLattice {
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+/// The analysis that tracks which loans have expired.
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &Factory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LifetimeFactory &SF)
+  : DataflowAnalysis(C, AC, F), Factory(SF.LoanSetFactory) {}
+
+  using DataflowAnalysis::transfer;
+
+  StringRef getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
+
+  /// Merges two lattices by taking the union of the expired loan sets.
+  Lattice join(Lattice L1, Lattice L2) const {
+return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(Factory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(Factory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO:
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -794,5 +852,8 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, Factory);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredLoans(Cfg, AC, FactMgr, Factory);
+  ExpiredLoans.run();
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From 542bc99c1f5fb5fc28a3374f61b2fa3d059d9d75 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From 4b70fcf7f20083a34a18bf0f84dfc29cce696db4 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 61 +++
 1 file changed, 61 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 9d1b662e3c589..5e54e8dadcfd0 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -763,6 +763,65 @@ class LoanPropagationAnalysis
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The dataflow lattice for tracking the set of expired loans.
+class ExpiredLattice {
+public:
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+/// The analysis that tracks which loans have expired.
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &Factory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LifetimeFactory &SF)
+  : DataflowAnalysis(C, AC, F), Factory(SF.LoanSetFactory) {}
+
+  using DataflowAnalysis::transfer;
+
+  const char *getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
+
+  /// Merges two lattices by taking the union of the expired loan sets.
+  Lattice join(Lattice L1, Lattice L2) const {
+return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(Factory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(Factory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO:
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -795,5 +854,7 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, Factory);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredAnalysis(Cfg, AC, FactMgr, Factory);
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From 542bc99c1f5fb5fc28a3374f61b2fa3d059d9d75 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From 4b70fcf7f20083a34a18bf0f84dfc29cce696db4 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 61 +++
 1 file changed, 61 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 9d1b662e3c589..5e54e8dadcfd0 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -763,6 +763,65 @@ class LoanPropagationAnalysis
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The dataflow lattice for tracking the set of expired loans.
+class ExpiredLattice {
+public:
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+/// The analysis that tracks which loans have expired.
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &Factory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LifetimeFactory &SF)
+  : DataflowAnalysis(C, AC, F), Factory(SF.LoanSetFactory) {}
+
+  using DataflowAnalysis::transfer;
+
+  const char *getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
+
+  /// Merges two lattices by taking the union of the expired loan sets.
+  Lattice join(Lattice L1, Lattice L2) const {
+return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(Factory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(Factory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO:
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -795,5 +854,7 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, Factory);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredAnalysis(Cfg, AC, FactMgr, Factory);
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From 3696b6b7a6167c63d0fd5cbef607e44129feb2e2 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From 3e064c102babd4abc403fa2ea4a41ce018f1352b Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 61 +++
 1 file changed, 61 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index a9c0ee08950b8..8995b5a8ecc90 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -761,6 +761,65 @@ class LoanPropagationAnalysis
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The dataflow lattice for tracking the set of expired loans.
+class ExpiredLattice {
+public:
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+/// The analysis that tracks which loans have expired.
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &Factory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LifetimeFactory &SF)
+  : DataflowAnalysis(C, AC, F), Factory(SF.LoanSetFactory) {}
+
+  using DataflowAnalysis::transfer;
+
+  const char *getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
+
+  /// Merges two lattices by taking the union of the expired loan sets.
+  Lattice join(Lattice L1, Lattice L2) const {
+return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(Factory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(Factory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO:
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -793,5 +852,7 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, Factory);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredAnalysis(Cfg, AC, FactMgr, Factory);
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From 3696b6b7a6167c63d0fd5cbef607e44129feb2e2 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From 3e064c102babd4abc403fa2ea4a41ce018f1352b Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 61 +++
 1 file changed, 61 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index a9c0ee08950b8..8995b5a8ecc90 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -761,6 +761,65 @@ class LoanPropagationAnalysis
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The dataflow lattice for tracking the set of expired loans.
+class ExpiredLattice {
+public:
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+/// The analysis that tracks which loans have expired.
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &Factory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LifetimeFactory &SF)
+  : DataflowAnalysis(C, AC, F), Factory(SF.LoanSetFactory) {}
+
+  using DataflowAnalysis::transfer;
+
+  const char *getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
+
+  /// Merges two lattices by taking the union of the expired loan sets.
+  Lattice join(Lattice L1, Lattice L2) const {
+return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(Factory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(Factory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO:
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -793,5 +852,7 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, Factory);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredAnalysis(Cfg, AC, FactMgr, Factory);
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/148712
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From 542bc99c1f5fb5fc28a3374f61b2fa3d059d9d75 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From 6ce317303d599371fc61529eb1d3e7a1624aa8fb Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 62 +++
 1 file changed, 62 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 9d1b662e3c589..52c6b18021d7a 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -763,6 +763,65 @@ class LoanPropagationAnalysis
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The dataflow lattice for tracking the set of expired loans.
+class ExpiredLattice {
+public:
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+/// The analysis that tracks which loans have expired.
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &Factory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LifetimeFactory &SF)
+  : DataflowAnalysis(C, AC, F), Factory(SF.LoanSetFactory) {}
+
+  using DataflowAnalysis::transfer;
+
+  const char *getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
+
+  /// Merges two lattices by taking the union of the expired loan sets.
+  Lattice join(Lattice L1, Lattice L2) const {
+return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(Factory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(Factory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO:
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -795,5 +854,8 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, Factory);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredLoans(Cfg, AC, FactMgr, Factory);
+  ExpiredLoans.run();
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-14 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/147315

>From 5fbfcd75b60d4db3a16e183f888aba1b72d87634 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 7 Jul 2025 15:13:00 +
Subject: [PATCH] [LifetimeSafety] Add script performance benchmarking

---
 .../Analysis/LifetimeSafety/CMakeLists.txt|  49 +++
 .../test/Analysis/LifetimeSafety/benchmark.py | 307 ++
 .../Analysis/LifetimeSafety/requirements.txt  |   2 +
 clang/test/CMakeLists.txt |   2 +
 4 files changed, 360 insertions(+)
 create mode 100644 clang/test/Analysis/LifetimeSafety/CMakeLists.txt
 create mode 100644 clang/test/Analysis/LifetimeSafety/benchmark.py
 create mode 100644 clang/test/Analysis/LifetimeSafety/requirements.txt

diff --git a/clang/test/Analysis/LifetimeSafety/CMakeLists.txt 
b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
new file mode 100644
index 0..ce37a29655668
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
@@ -0,0 +1,49 @@
+# 
=
+# Lifetime Analysis Benchmarking Target
+# 
=
+# This target allows running performance benchmarks for the clang lifetime 
analysis
+# using a Python script (with managed dependencies).
+
+find_package(Python3 COMPONENTS Interpreter REQUIRED)
+
+# Define paths for the virtual environment and requirements file.
+set(LIFETIME_BENCHMARK_SCRIPT 
+  "${CMAKE_CURRENT_SOURCE_DIR}/benchmark.py")
+set(LIFETIME_BENCHMARK_VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/benchmark-venv")
+set(LIFETIME_BENCHMARK_REQUIREMENTS
+  "${CMAKE_CURRENT_SOURCE_DIR}/requirements.txt")
+set(LIFETIME_BENCHMARK_OUTPUT_DIR
+  "${CMAKE_CURRENT_BINARY_DIR}/benchmark_results")
+
+
+if(EXISTS ${LIFETIME_BENCHMARK_SCRIPT} AND EXISTS 
${LIFETIME_BENCHMARK_REQUIREMENTS})
+
+  # Set up the virtual environment and install packages
+  add_custom_command(
+OUTPUT ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+COMMAND ${Python3_EXECUTABLE} -m venv ${LIFETIME_BENCHMARK_VENV_DIR}
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python -m pip install -r 
${LIFETIME_BENCHMARK_REQUIREMENTS}
+DEPENDS ${LIFETIME_BENCHMARK_REQUIREMENTS}
+COMMENT "Creating Python virtual environment and installing dependencies 
for benchmark..."
+  )
+  add_custom_target(benchmark_venv_setup
+DEPENDS ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+  )
+
+  # Main benchmark target
+  add_custom_target(benchmark_lifetime_safety_analysis
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python 
${LIFETIME_BENCHMARK_SCRIPT}
+--clang-binary ${LLVM_BINARY_DIR}/bin/clang
+--output-dir ${LIFETIME_BENCHMARK_OUTPUT_DIR}
+
+DEPENDS clang benchmark_venv_setup
+
+# Display the output directly in the console.
+USES_TERMINAL
+
+COMMENT "Running Lifetime Analysis performance benchmarks..."
+  )
+
+  set_target_properties(benchmark_lifetime_safety_analysis 
+PROPERTIES FOLDER "Clang/Benchmarks")
+endif()
diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py 
b/clang/test/Analysis/LifetimeSafety/benchmark.py
new file mode 100644
index 0..9d5f36c51b9ee
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/benchmark.py
@@ -0,0 +1,307 @@
+import sys
+import argparse
+import subprocess
+import tempfile
+import json
+import os
+from datetime import datetime
+import numpy as np
+from scipy.optimize import curve_fit
+from scipy.stats import t
+
+
+def generate_cpp_cycle_test(n: int) -> str:
+"""
+Generates a C++ code snippet with a specified number of pointers in a 
cycle.
+Creates a while loop that rotates N pointers.
+This pattern tests the convergence speed of the dataflow analysis when
+reaching its fixed point.
+
+Example:
+struct MyObj { int id; ~MyObj() {} };
+
+void long_cycle_4(bool condition) {
+MyObj v1{1};
+MyObj v2{1};
+MyObj v3{1};
+MyObj v4{1};
+
+MyObj* p1 = &v1;
+MyObj* p2 = &v2;
+MyObj* p3 = &v3;
+MyObj* p4 = &v4;
+
+while (condition) {
+MyObj* temp = p1;
+p1 = p2;
+p2 = p3;
+p3 = p4;
+p4 = temp;
+}
+}
+"""
+if n <= 0:
+return "// Number of variables must be positive."
+
+cpp_code = "struct MyObj { int id; ~MyObj() {} };\n\n"
+cpp_code += f"void long_cycle_{n}(bool condition) {{\n"
+for i in range(1, n + 1):
+cpp_code += f"  MyObj v{i}{{1}};\n"
+cpp_code += "\n"
+for i in range(1, n + 1):
+cpp_code += f"  MyObj* p{i} = &v{i};\n"
+
+cpp_code += "\n  while (condition) {\n"
+if n > 0:
+cpp_code += f"MyObj* temp = p1;\n"
+for i in range(1, n):
+cpp_code += f"p{i} = p{i+1};\n"
+cpp_code += f" 

[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-14 Thread Utkarsh Saxena via llvm-branch-commits

usx95 wrote:

### Merge activity

* **Jul 14, 6:16 PM UTC**: A user started a stack merge that includes this pull 
request via 
[Graphite](https://app.graphite.dev/github/pr/llvm/llvm-project/147315).


https://github.com/llvm/llvm-project/pull/147315
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add expired loans analysis (PR #148222)

2025-07-14 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148222

>From 19d033cb6aa4a84c78a9b37e25020f4e33e8976b Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 7 Jul 2025 15:13:00 +
Subject: [PATCH 1/3] [LifetimeSafety] Add script performance benchmarking

---
 .../Analysis/LifetimeSafety/CMakeLists.txt|  49 +++
 .../test/Analysis/LifetimeSafety/benchmark.py | 307 ++
 .../Analysis/LifetimeSafety/requirements.txt  |   2 +
 clang/test/CMakeLists.txt |   2 +
 4 files changed, 360 insertions(+)
 create mode 100644 clang/test/Analysis/LifetimeSafety/CMakeLists.txt
 create mode 100644 clang/test/Analysis/LifetimeSafety/benchmark.py
 create mode 100644 clang/test/Analysis/LifetimeSafety/requirements.txt

diff --git a/clang/test/Analysis/LifetimeSafety/CMakeLists.txt 
b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
new file mode 100644
index 0..ce37a29655668
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
@@ -0,0 +1,49 @@
+# 
=
+# Lifetime Analysis Benchmarking Target
+# 
=
+# This target allows running performance benchmarks for the clang lifetime 
analysis
+# using a Python script (with managed dependencies).
+
+find_package(Python3 COMPONENTS Interpreter REQUIRED)
+
+# Define paths for the virtual environment and requirements file.
+set(LIFETIME_BENCHMARK_SCRIPT 
+  "${CMAKE_CURRENT_SOURCE_DIR}/benchmark.py")
+set(LIFETIME_BENCHMARK_VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/benchmark-venv")
+set(LIFETIME_BENCHMARK_REQUIREMENTS
+  "${CMAKE_CURRENT_SOURCE_DIR}/requirements.txt")
+set(LIFETIME_BENCHMARK_OUTPUT_DIR
+  "${CMAKE_CURRENT_BINARY_DIR}/benchmark_results")
+
+
+if(EXISTS ${LIFETIME_BENCHMARK_SCRIPT} AND EXISTS 
${LIFETIME_BENCHMARK_REQUIREMENTS})
+
+  # Set up the virtual environment and install packages
+  add_custom_command(
+OUTPUT ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+COMMAND ${Python3_EXECUTABLE} -m venv ${LIFETIME_BENCHMARK_VENV_DIR}
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python -m pip install -r 
${LIFETIME_BENCHMARK_REQUIREMENTS}
+DEPENDS ${LIFETIME_BENCHMARK_REQUIREMENTS}
+COMMENT "Creating Python virtual environment and installing dependencies 
for benchmark..."
+  )
+  add_custom_target(benchmark_venv_setup
+DEPENDS ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+  )
+
+  # Main benchmark target
+  add_custom_target(benchmark_lifetime_safety_analysis
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python 
${LIFETIME_BENCHMARK_SCRIPT}
+--clang-binary ${LLVM_BINARY_DIR}/bin/clang
+--output-dir ${LIFETIME_BENCHMARK_OUTPUT_DIR}
+
+DEPENDS clang benchmark_venv_setup
+
+# Display the output directly in the console.
+USES_TERMINAL
+
+COMMENT "Running Lifetime Analysis performance benchmarks..."
+  )
+
+  set_target_properties(benchmark_lifetime_safety_analysis 
+PROPERTIES FOLDER "Clang/Benchmarks")
+endif()
diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py 
b/clang/test/Analysis/LifetimeSafety/benchmark.py
new file mode 100644
index 0..9d5f36c51b9ee
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/benchmark.py
@@ -0,0 +1,307 @@
+import sys
+import argparse
+import subprocess
+import tempfile
+import json
+import os
+from datetime import datetime
+import numpy as np
+from scipy.optimize import curve_fit
+from scipy.stats import t
+
+
+def generate_cpp_cycle_test(n: int) -> str:
+"""
+Generates a C++ code snippet with a specified number of pointers in a 
cycle.
+Creates a while loop that rotates N pointers.
+This pattern tests the convergence speed of the dataflow analysis when
+reaching its fixed point.
+
+Example:
+struct MyObj { int id; ~MyObj() {} };
+
+void long_cycle_4(bool condition) {
+MyObj v1{1};
+MyObj v2{1};
+MyObj v3{1};
+MyObj v4{1};
+
+MyObj* p1 = &v1;
+MyObj* p2 = &v2;
+MyObj* p3 = &v3;
+MyObj* p4 = &v4;
+
+while (condition) {
+MyObj* temp = p1;
+p1 = p2;
+p2 = p3;
+p3 = p4;
+p4 = temp;
+}
+}
+"""
+if n <= 0:
+return "// Number of variables must be positive."
+
+cpp_code = "struct MyObj { int id; ~MyObj() {} };\n\n"
+cpp_code += f"void long_cycle_{n}(bool condition) {{\n"
+for i in range(1, n + 1):
+cpp_code += f"  MyObj v{i}{{1}};\n"
+cpp_code += "\n"
+for i in range(1, n + 1):
+cpp_code += f"  MyObj* p{i} = &v{i};\n"
+
+cpp_code += "\n  while (condition) {\n"
+if n > 0:
+cpp_code += f"MyObj* temp = p1;\n"
+for i in range(1, n):
+cpp_code += f"p{i} = p{i+1};\n"
+cpp_code +=

[llvm-branch-commits] [clang] [LifetimeSafety] Add script for performance benchmarking (PR #147315)

2025-07-14 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/147315

>From 19d033cb6aa4a84c78a9b37e25020f4e33e8976b Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 7 Jul 2025 15:13:00 +
Subject: [PATCH] [LifetimeSafety] Add script performance benchmarking

---
 .../Analysis/LifetimeSafety/CMakeLists.txt|  49 +++
 .../test/Analysis/LifetimeSafety/benchmark.py | 307 ++
 .../Analysis/LifetimeSafety/requirements.txt  |   2 +
 clang/test/CMakeLists.txt |   2 +
 4 files changed, 360 insertions(+)
 create mode 100644 clang/test/Analysis/LifetimeSafety/CMakeLists.txt
 create mode 100644 clang/test/Analysis/LifetimeSafety/benchmark.py
 create mode 100644 clang/test/Analysis/LifetimeSafety/requirements.txt

diff --git a/clang/test/Analysis/LifetimeSafety/CMakeLists.txt 
b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
new file mode 100644
index 0..ce37a29655668
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/CMakeLists.txt
@@ -0,0 +1,49 @@
+# 
=
+# Lifetime Analysis Benchmarking Target
+# 
=
+# This target allows running performance benchmarks for the clang lifetime 
analysis
+# using a Python script (with managed dependencies).
+
+find_package(Python3 COMPONENTS Interpreter REQUIRED)
+
+# Define paths for the virtual environment and requirements file.
+set(LIFETIME_BENCHMARK_SCRIPT 
+  "${CMAKE_CURRENT_SOURCE_DIR}/benchmark.py")
+set(LIFETIME_BENCHMARK_VENV_DIR "${CMAKE_CURRENT_BINARY_DIR}/benchmark-venv")
+set(LIFETIME_BENCHMARK_REQUIREMENTS
+  "${CMAKE_CURRENT_SOURCE_DIR}/requirements.txt")
+set(LIFETIME_BENCHMARK_OUTPUT_DIR
+  "${CMAKE_CURRENT_BINARY_DIR}/benchmark_results")
+
+
+if(EXISTS ${LIFETIME_BENCHMARK_SCRIPT} AND EXISTS 
${LIFETIME_BENCHMARK_REQUIREMENTS})
+
+  # Set up the virtual environment and install packages
+  add_custom_command(
+OUTPUT ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+COMMAND ${Python3_EXECUTABLE} -m venv ${LIFETIME_BENCHMARK_VENV_DIR}
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python -m pip install -r 
${LIFETIME_BENCHMARK_REQUIREMENTS}
+DEPENDS ${LIFETIME_BENCHMARK_REQUIREMENTS}
+COMMENT "Creating Python virtual environment and installing dependencies 
for benchmark..."
+  )
+  add_custom_target(benchmark_venv_setup
+DEPENDS ${LIFETIME_BENCHMARK_VENV_DIR}/pyvenv.cfg
+  )
+
+  # Main benchmark target
+  add_custom_target(benchmark_lifetime_safety_analysis
+COMMAND ${LIFETIME_BENCHMARK_VENV_DIR}/bin/python 
${LIFETIME_BENCHMARK_SCRIPT}
+--clang-binary ${LLVM_BINARY_DIR}/bin/clang
+--output-dir ${LIFETIME_BENCHMARK_OUTPUT_DIR}
+
+DEPENDS clang benchmark_venv_setup
+
+# Display the output directly in the console.
+USES_TERMINAL
+
+COMMENT "Running Lifetime Analysis performance benchmarks..."
+  )
+
+  set_target_properties(benchmark_lifetime_safety_analysis 
+PROPERTIES FOLDER "Clang/Benchmarks")
+endif()
diff --git a/clang/test/Analysis/LifetimeSafety/benchmark.py 
b/clang/test/Analysis/LifetimeSafety/benchmark.py
new file mode 100644
index 0..9d5f36c51b9ee
--- /dev/null
+++ b/clang/test/Analysis/LifetimeSafety/benchmark.py
@@ -0,0 +1,307 @@
+import sys
+import argparse
+import subprocess
+import tempfile
+import json
+import os
+from datetime import datetime
+import numpy as np
+from scipy.optimize import curve_fit
+from scipy.stats import t
+
+
+def generate_cpp_cycle_test(n: int) -> str:
+"""
+Generates a C++ code snippet with a specified number of pointers in a 
cycle.
+Creates a while loop that rotates N pointers.
+This pattern tests the convergence speed of the dataflow analysis when
+reaching its fixed point.
+
+Example:
+struct MyObj { int id; ~MyObj() {} };
+
+void long_cycle_4(bool condition) {
+MyObj v1{1};
+MyObj v2{1};
+MyObj v3{1};
+MyObj v4{1};
+
+MyObj* p1 = &v1;
+MyObj* p2 = &v2;
+MyObj* p3 = &v3;
+MyObj* p4 = &v4;
+
+while (condition) {
+MyObj* temp = p1;
+p1 = p2;
+p2 = p3;
+p3 = p4;
+p4 = temp;
+}
+}
+"""
+if n <= 0:
+return "// Number of variables must be positive."
+
+cpp_code = "struct MyObj { int id; ~MyObj() {} };\n\n"
+cpp_code += f"void long_cycle_{n}(bool condition) {{\n"
+for i in range(1, n + 1):
+cpp_code += f"  MyObj v{i}{{1}};\n"
+cpp_code += "\n"
+for i in range(1, n + 1):
+cpp_code += f"  MyObj* p{i} = &v{i};\n"
+
+cpp_code += "\n  while (condition) {\n"
+if n > 0:
+cpp_code += f"MyObj* temp = p1;\n"
+for i in range(1, n):
+cpp_code += f"p{i} = p{i+1};\n"
+cpp_code += f" 

[llvm-branch-commits] [clang] [LifetimeSafety] Add expired loans analysis (PR #148222)

2025-07-14 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/148222
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add expired loans analysis (PR #148222)

2025-07-14 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148222

>From eb33d75e1ad1faf621f90d0b8f6ac3deab267084 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Fri, 11 Jul 2025 11:11:47 +
Subject: [PATCH 1/3] [LifetimeSafety] Add expired loans analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 140 ++
 1 file changed, 140 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 20f3285249ac2..a6de79cffb371 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -729,6 +729,142 @@ class LifetimeDataflow {
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The lattice for tracking expired loans. It is a set of loan IDs.
+struct ExpiredLattice {
+  LoanSet Expired;
+
+  ExpiredLattice() = default;
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  /// Computes the union of two lattices.
+  ExpiredLattice join(const ExpiredLattice &Other,
+  LoanSet::Factory &Factory) const {
+LoanSet JoinedSet = Expired;
+for (LoanID LID : Other.Expired)
+  JoinedSet = Factory.add(JoinedSet, LID);
+return ExpiredLattice(JoinedSet);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+/// Transfer function for the expired loans analysis.
+class ExpiredLoansTransferer {
+  FactManager &AllFacts;
+  LoanSet::Factory &SetFactory;
+
+public:
+  explicit ExpiredLoansTransferer(FactManager &F, LoanSet::Factory &SF)
+  : AllFacts(F), SetFactory(SF) {}
+
+  /// Computes the exit state of a block by applying all its facts sequentially
+  /// to a given entry state.
+  ExpiredLattice transferBlock(const CFGBlock *Block,
+ExpiredLattice EntryState) {
+ExpiredLattice BlockState = EntryState;
+llvm::ArrayRef Facts = AllFacts.getFacts(Block);
+
+for (const Fact *F : Facts) {
+  BlockState = transferFact(BlockState, F);
+}
+return BlockState;
+  }
+
+private:
+  ExpiredLattice transferFact(ExpiredLattice In, const Fact *F) {
+if (const auto *EF = F->getAs())
+  return ExpiredLattice(SetFactory.add(In.Expired, EF->getLoanID()));
+
+if (const auto *IF = F->getAs())
+  return ExpiredLattice(SetFactory.remove(In.Expired, IF->getLoanID()));
+
+return In;
+  }
+};
+
+/// Dataflow analysis driver for tracking expired loans.
+class ExpiredLoansAnalysis {
+  const CFG &Cfg;
+  AnalysisDeclContext &AC;
+  LoanSet::Factory SetFactory;
+  ExpiredLoansTransferer Xfer;
+
+  llvm::DenseMap BlockEntryStates;
+  llvm::DenseMap BlockExitStates;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, FactManager &FS, AnalysisDeclContext &AC)
+  : Cfg(C), AC(AC), Xfer(FS, SetFactory) {}
+
+  void run() {
+llvm::TimeTraceScope TimeProfile("Expired Loans Analysis");
+ForwardDataflowWorklist Worklist(Cfg, AC);
+const CFGBlock *Entry = &Cfg.getEntry();
+BlockEntryStates[Entry] = ExpiredLattice(SetFactory.getEmptySet());
+Worklist.enqueueBlock(Entry);
+while (const CFGBlock *B = Worklist.dequeue()) {
+  ExpiredLattice EntryState = getEntryState(B);
+  ExpiredLattice ExitState = Xfer.transferBlock(B, EntryState);
+  BlockExitStates[B] = ExitState;
+
+  for (const CFGBlock *Successor : B->succs()) {
+auto SuccIt = BlockEntryStates.find(Successor);
+ExpiredLattice OldSuccEntryState = (SuccIt != BlockEntryStates.end())
+? SuccIt->second
+: ExpiredLattice{};
+ExpiredLattice NewSuccEntryState =
+OldSuccEntryState.join(ExitState, SetFactory);
+if (SuccIt == BlockEntryStates.end() ||
+NewSuccEntryState != OldSuccEntryState) {
+  BlockEntryStates[Successor] = NewSuccEntryState;
+  Worklist.enqueueBlock(Successor);
+}
+  }
+}
+  }
+
+  void dump() const {
+llvm::dbgs() << "==\n";
+llvm::dbgs() << "   Expired Loans Results:\n";
+llvm::dbgs() << "==\n";
+const CFGBlock &B = Cfg.getExit();
+getExitState(&B).dump(llvm::dbgs());
+  }
+
+  ExpiredLattice getEntryState(const CFGBlock *B) const {
+auto It = BlockEntryStates.find(B);
+if (It != BlockEntryStates.end()) {
+  return It->second;
+}
+return ExpiredLattice(SetFacto

[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-14 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From 7c2838035392804a2cd9bda1d0751e3633d2a31f Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From ed73e3b1914a25c525bbb8f06fa0112cc4eb4bd0 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 62 +++
 1 file changed, 62 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index c1bd4e82f4327..1aba655a6ead1 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -746,6 +746,65 @@ class LoanPropagationAnalysis
 return Factory.LoanSetFact.getEmptySet();
   }
 };
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The lattice for tracking expired loans. It is a set of loan IDs.
+struct ExpiredLattice {
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &SetFactory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LoanSet::Factory &SF)
+  : DataflowAnalysis(C, AC, F), SetFactory(SF) {}
+
+  using DataflowAnalysis::transfer;
+
+  const char *getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(SetFactory.getEmptySet()); }
+
+  Lattice join(Lattice L1, Lattice L2) const {
+LoanSet JoinedSet = L1.Expired;
+for (LoanID LID : L2.Expired)
+  JoinedSet = SetFactory.add(JoinedSet, LID);
+return Lattice(JoinedSet);
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(SetFactory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(SetFactory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO: 
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -778,5 +837,8 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, LifetimeFact);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredAnalysis(Cfg, AC, FactMgr,
+   LifetimeFact.LoanSetFact);
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-14 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From 7c2838035392804a2cd9bda1d0751e3633d2a31f Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From ed73e3b1914a25c525bbb8f06fa0112cc4eb4bd0 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 62 +++
 1 file changed, 62 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index c1bd4e82f4327..1aba655a6ead1 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -746,6 +746,65 @@ class LoanPropagationAnalysis
 return Factory.LoanSetFact.getEmptySet();
   }
 };
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The lattice for tracking expired loans. It is a set of loan IDs.
+struct ExpiredLattice {
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &SetFactory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LoanSet::Factory &SF)
+  : DataflowAnalysis(C, AC, F), SetFactory(SF) {}
+
+  using DataflowAnalysis::transfer;
+
+  const char *getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(SetFactory.getEmptySet()); }
+
+  Lattice join(Lattice L1, Lattice L2) const {
+LoanSet JoinedSet = L1.Expired;
+for (LoanID LID : L2.Expired)
+  JoinedSet = SetFactory.add(JoinedSet, LID);
+return Lattice(JoinedSet);
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(SetFactory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(SetFactory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO: 
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -778,5 +837,8 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, LifetimeFact);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredAnalysis(Cfg, AC, FactMgr,
+   LifetimeFact.LoanSetFact);
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-14 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From a9cb32152b8ba94a6a93c7923cce1abac43c9022 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From a50b00e1b5394dacd635fd1da3aef83eb54348e5 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 62 +++
 1 file changed, 62 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 99bd7bc36faf5..1ac8f42318b8d 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -747,6 +747,65 @@ class LoanPropagationAnalysis
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The lattice for tracking expired loans. It is a set of loan IDs.
+struct ExpiredLattice {
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &SetFactory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LoanSet::Factory &SF)
+  : DataflowAnalysis(C, AC, F), SetFactory(SF) {}
+
+  using DataflowAnalysis::transfer;
+
+  const char *getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(SetFactory.getEmptySet()); }
+
+  Lattice join(Lattice L1, Lattice L2) const {
+LoanSet JoinedSet = L1.Expired;
+for (LoanID LID : L2.Expired)
+  JoinedSet = SetFactory.add(JoinedSet, LID);
+return Lattice(JoinedSet);
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(SetFactory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(SetFactory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO: 
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -779,5 +838,8 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, LifetimeFact);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredAnalysis(Cfg, AC, FactMgr,
+   LifetimeFact.LoanSetFact);
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-14 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From a9cb32152b8ba94a6a93c7923cce1abac43c9022 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From a50b00e1b5394dacd635fd1da3aef83eb54348e5 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 62 +++
 1 file changed, 62 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 99bd7bc36faf5..1ac8f42318b8d 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -747,6 +747,65 @@ class LoanPropagationAnalysis
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The lattice for tracking expired loans. It is a set of loan IDs.
+struct ExpiredLattice {
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &SetFactory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LoanSet::Factory &SF)
+  : DataflowAnalysis(C, AC, F), SetFactory(SF) {}
+
+  using DataflowAnalysis::transfer;
+
+  const char *getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(SetFactory.getEmptySet()); }
+
+  Lattice join(Lattice L1, Lattice L2) const {
+LoanSet JoinedSet = L1.Expired;
+for (LoanID LID : L2.Expired)
+  JoinedSet = SetFactory.add(JoinedSet, LID);
+return Lattice(JoinedSet);
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(SetFactory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(SetFactory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO: 
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -779,5 +838,8 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, LifetimeFact);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredAnalysis(Cfg, AC, FactMgr,
+   LifetimeFact.LoanSetFact);
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From 30deaddc558581426833360d74b302c1556f01ec Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From 04d61938d4e1334441538405f4f0698f8f6ae74e Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 61 +++
 1 file changed, 61 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 0e013ec23e776..add652d4ce601 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -767,6 +767,64 @@ class LoanPropagationAnalysis
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The dataflow lattice for tracking the set of expired loans.
+struct ExpiredLattice {
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+/// The analysis that tracks which loans have expired.
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &Factory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LifetimeFactory &SF)
+  : DataflowAnalysis(C, AC, F), Factory(SF.LoanSetFactory) {}
+
+  using DataflowAnalysis::transfer;
+
+  StringRef getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
+
+  /// Merges two lattices by taking the union of the expired loan sets.
+  Lattice join(Lattice L1, Lattice L2) const {
+return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(Factory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(Factory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO:
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -799,5 +857,8 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, Factory);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredLoans(Cfg, AC, FactMgr, Factory);
+  ExpiredLoans.run();
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From 30deaddc558581426833360d74b302c1556f01ec Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From 04d61938d4e1334441538405f4f0698f8f6ae74e Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 61 +++
 1 file changed, 61 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 0e013ec23e776..add652d4ce601 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -767,6 +767,64 @@ class LoanPropagationAnalysis
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The dataflow lattice for tracking the set of expired loans.
+struct ExpiredLattice {
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+/// The analysis that tracks which loans have expired.
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &Factory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LifetimeFactory &SF)
+  : DataflowAnalysis(C, AC, F), Factory(SF.LoanSetFactory) {}
+
+  using DataflowAnalysis::transfer;
+
+  StringRef getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
+
+  /// Merges two lattices by taking the union of the expired loan sets.
+  Lattice join(Lattice L1, Lattice L2) const {
+return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(Factory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(Factory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO:
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -799,5 +857,8 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, Factory);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredLoans(Cfg, AC, FactMgr, Factory);
+  ExpiredLoans.run();
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From 63fc65843dfd135d60bb45b1311a21d60338 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From 5f0991338d17813d9af276a0cea2d30875a9aa23 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 64 +++
 1 file changed, 64 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index f9a7093987896..217b02b416c1a 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -518,6 +518,8 @@ enum class Direction { Forward, Backward };
 /// analysis.
 /// \tparam LatticeType The dataflow lattice used by the analysis.
 /// \tparam Dir The direction of the analysis (Forward or Backward).
+/// TODO: Maybe use the dataflow framework! The framework might need changes
+/// to support the current comparison done at block-entry.
 template 
 class DataflowAnalysis {
 public:
@@ -775,6 +777,65 @@ class LoanPropagationAnalysis
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The dataflow lattice for tracking the set of expired loans.
+struct ExpiredLattice {
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+/// The analysis that tracks which loans have expired.
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &Factory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LifetimeFactory &SF)
+  : DataflowAnalysis(C, AC, F), Factory(SF.LoanSetFactory) {}
+
+  using Base::transfer;
+
+  StringRef getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
+
+  /// Merges two lattices by taking the union of the expired loan sets.
+  Lattice join(Lattice L1, Lattice L2) const {
+return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(Factory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(Factory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO:
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -807,5 +868,8 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, Factory);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredLoans(Cfg, AC, FactMgr, Factory);
+  ExpiredLoans.run();
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Support bidirectional dataflow analysis (PR #148967)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 ready_for_review 
https://github.com/llvm/llvm-project/pull/148967
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Support bidirectional dataflow analysis (PR #148967)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/148967
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 edited https://github.com/llvm/llvm-project/pull/148712
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Support bidirectional dataflow analysis (PR #148967)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148967

>From 7502ee577452c5c5d9bb4c9a8b24d6c4825cedd1 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Tue, 15 Jul 2025 21:24:11 +
Subject: [PATCH] add-backward-analysis-capability

---
 clang/lib/Analysis/LifetimeSafety.cpp | 108 ++
 1 file changed, 59 insertions(+), 49 deletions(-)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 0e013ec23e776..829da3ceb4c83 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -499,13 +499,16 @@ class FactGenerator : public 
ConstStmtVisitor {
 // = //
 // Generic Dataflow Analysis
 // = //
-/// A generic, policy-based driver for forward dataflow analyses. It combines
+
+enum class Direction { Forward, Backward };
+
+/// A generic, policy-based driver for dataflow analyses. It combines
 /// the dataflow runner and the transferer logic into a single class hierarchy.
 ///
 /// The derived class is expected to provide:
 /// - A `Lattice` type.
 /// - `StringRef getAnalysisName() const`
-/// - `Lattice getInitialState();` The initial state at the function entry.
+/// - `Lattice getInitialState();` The initial state of the analysis.
 /// - `Lattice join(Lattice, Lattice);` Merges states from multiple CFG paths.
 /// - `Lattice transfer(Lattice, const FactType&);` Defines how a single
 ///   lifetime-relevant `Fact` transforms the lattice state. Only overloads
@@ -514,18 +517,23 @@ class FactGenerator : public 
ConstStmtVisitor {
 /// \tparam Derived The CRTP derived class that implements the specific
 /// analysis.
 /// \tparam LatticeType The dataflow lattice used by the analysis.
+/// \tparam Dir The direction of the analysis (Forward or Backward).
 /// TODO: Maybe use the dataflow framework! The framework might need changes
 /// to support the current comparison done at block-entry.
-template  class DataflowAnalysis {
+template 
+class DataflowAnalysis {
 public:
   using Lattice = LatticeType;
+  using Base = DataflowAnalysis;
 
 private:
   const CFG &Cfg;
   AnalysisDeclContext &AC;
 
-  llvm::DenseMap BlockEntryStates;
-  llvm::DenseMap BlockExitStates;
+  llvm::DenseMap InStates;
+  llvm::DenseMap OutStates;
+
+  static constexpr bool isForward() { return Dir == Direction::Forward; }
 
 protected:
   FactManager &AllFacts;
@@ -539,75 +547,76 @@ template  class 
DataflowAnalysis {
 Derived &D = static_cast(*this);
 llvm::TimeTraceScope Time(D.getAnalysisName());
 
-ForwardDataflowWorklist Worklist(Cfg, AC);
-const CFGBlock *Entry = &Cfg.getEntry();
-BlockEntryStates[Entry] = D.getInitialState();
-Worklist.enqueueBlock(Entry);
-llvm::SmallBitVector Visited;
-Visited.resize(Cfg.getNumBlockIDs() + 1);
-
-while (const CFGBlock *B = Worklist.dequeue()) {
-  Lattice EntryState = getEntryState(B);
-  Lattice ExitState = transferBlock(B, EntryState);
-  BlockExitStates[B] = ExitState;
-  Visited.set(B->getBlockID());
+using Worklist =
+std::conditional_t;
+Worklist W(Cfg, AC);
+
+const CFGBlock *Start = isForward() ? &Cfg.getEntry() : &Cfg.getExit();
+InStates[Start] = D.getInitialState();
+W.enqueueBlock(Start);
 
-  for (const CFGBlock *Successor : B->succs()) {
-Lattice OldSuccEntryState = getEntryState(Successor);
-Lattice NewSuccEntryState = D.join(OldSuccEntryState, ExitState);
+llvm::SmallBitVector Visited(Cfg.getNumBlockIDs() + 1);
 
-// Enqueue the successor if its entry state has changed or if we have
+while (const CFGBlock *B = W.dequeue()) {
+  Lattice StateIn = getInState(B);
+  Lattice StateOut = transferBlock(B, StateIn);
+  OutStates[B] = StateOut;
+  Visited.set(B->getBlockID());
+  for (const CFGBlock *AdjacentB : isForward() ? B->succs() : B->preds()) {
+Lattice OldInState = getInState(AdjacentB);
+Lattice NewInState = D.join(OldInState, StateOut);
+// Enqueue the adjacent block if its in-state has changed or if we have
 // never visited it.
-if (!Visited.test(Successor->getBlockID()) ||
-NewSuccEntryState != OldSuccEntryState) {
-  BlockEntryStates[Successor] = NewSuccEntryState;
-  Worklist.enqueueBlock(Successor);
+if (!Visited.test(AdjacentB->getBlockID()) ||
+NewInState != OldInState) {
+  InStates[AdjacentB] = NewInState;
+  W.enqueueBlock(AdjacentB);
 }
   }
 }
   }
 
-  Lattice getEntryState(const CFGBlock *B) const {
-return BlockEntryStates.lookup(B);
-  }
+  Lattice getInState(const CFGBlock *B) const { return InStates.lookup(B); }
 
-  Lattice getExitState(const CFGBlock *B) const {
-return BlockExitStates.lookup(B);
-  }

[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From c8089978cbc691370b2537d7942325147fd7dc3f Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From aca68c29a969a33036db954f70a7d11521dbca6e Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 62 +++
 1 file changed, 62 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 829da3ceb4c83..217b02b416c1a 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -777,6 +777,65 @@ class LoanPropagationAnalysis
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The dataflow lattice for tracking the set of expired loans.
+struct ExpiredLattice {
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+/// The analysis that tracks which loans have expired.
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &Factory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LifetimeFactory &SF)
+  : DataflowAnalysis(C, AC, F), Factory(SF.LoanSetFactory) {}
+
+  using Base::transfer;
+
+  StringRef getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
+
+  /// Merges two lattices by taking the union of the expired loan sets.
+  Lattice join(Lattice L1, Lattice L2) const {
+return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(Factory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(Factory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO:
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -809,5 +868,8 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, Factory);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredLoans(Cfg, AC, FactMgr, Factory);
+  ExpiredLoans.run();
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [LifetimeSafety] Add loan expiry analysis (PR #148712)

2025-07-15 Thread Utkarsh Saxena via llvm-branch-commits

https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/148712

>From c8089978cbc691370b2537d7942325147fd7dc3f Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:32:35 +
Subject: [PATCH 1/2] users/usx95/lifetime-safety-add-loan-expiry


>From aca68c29a969a33036db954f70a7d11521dbca6e Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Mon, 14 Jul 2025 19:37:49 +
Subject: [PATCH 2/2] [LifetimeSafety] Add loan expiry analysis

---
 clang/lib/Analysis/LifetimeSafety.cpp | 62 +++
 1 file changed, 62 insertions(+)

diff --git a/clang/lib/Analysis/LifetimeSafety.cpp 
b/clang/lib/Analysis/LifetimeSafety.cpp
index 829da3ceb4c83..217b02b416c1a 100644
--- a/clang/lib/Analysis/LifetimeSafety.cpp
+++ b/clang/lib/Analysis/LifetimeSafety.cpp
@@ -777,6 +777,65 @@ class LoanPropagationAnalysis
   }
 };
 
+// = //
+// Expired Loans Analysis
+// = //
+
+/// The dataflow lattice for tracking the set of expired loans.
+struct ExpiredLattice {
+  LoanSet Expired;
+
+  ExpiredLattice() : Expired(nullptr) {};
+  explicit ExpiredLattice(LoanSet S) : Expired(S) {}
+
+  bool operator==(const ExpiredLattice &Other) const {
+return Expired == Other.Expired;
+  }
+  bool operator!=(const ExpiredLattice &Other) const {
+return !(*this == Other);
+  }
+
+  void dump(llvm::raw_ostream &OS) const {
+OS << "ExpiredLattice State:\n";
+if (Expired.isEmpty())
+  OS << "  \n";
+for (const LoanID &LID : Expired)
+  OS << "  Loan " << LID << " is expired\n";
+  }
+};
+
+/// The analysis that tracks which loans have expired.
+class ExpiredLoansAnalysis
+: public DataflowAnalysis {
+
+  LoanSet::Factory &Factory;
+
+public:
+  ExpiredLoansAnalysis(const CFG &C, AnalysisDeclContext &AC, FactManager &F,
+   LifetimeFactory &SF)
+  : DataflowAnalysis(C, AC, F), Factory(SF.LoanSetFactory) {}
+
+  using Base::transfer;
+
+  StringRef getAnalysisName() const { return "ExpiredLoans"; }
+
+  Lattice getInitialState() { return Lattice(Factory.getEmptySet()); }
+
+  /// Merges two lattices by taking the union of the expired loan sets.
+  Lattice join(Lattice L1, Lattice L2) const {
+return Lattice(utils::join(L1.Expired, L2.Expired, Factory));
+  }
+
+  Lattice transfer(Lattice In, const ExpireFact &F) {
+return Lattice(Factory.add(In.Expired, F.getLoanID()));
+  }
+
+  Lattice transfer(Lattice In, const IssueFact &F) {
+return Lattice(Factory.remove(In.Expired, F.getLoanID()));
+  }
+};
+
 // = //
 //  TODO:
 // - Modifying loan propagation to answer `LoanSet getLoans(Origin O, Point P)`
@@ -809,5 +868,8 @@ void runLifetimeSafetyAnalysis(const DeclContext &DC, const 
CFG &Cfg,
   LoanPropagationAnalysis LoanPropagation(Cfg, AC, FactMgr, Factory);
   LoanPropagation.run();
   DEBUG_WITH_TYPE("LifetimeLoanPropagation", LoanPropagation.dump());
+
+  ExpiredLoansAnalysis ExpiredLoans(Cfg, AC, FactMgr, Factory);
+  ExpiredLoans.run();
 }
 } // namespace clang

___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits