Skip to content

Conversation

fmayer
Copy link
Contributor

@fmayer fmayer commented Oct 17, 2025

This makes it easier to write the initialization function, because the
callee does not have to find out the type again.

Created using spr 1.3.7
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:dataflow Clang Dataflow Analysis framework - https://clang.llvm.org/docs/DataFlowAnalysisIntro.html clang:analysis labels Oct 17, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 17, 2025

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-analysis

Author: Florian Mayer (fmayer)

Changes

This makes it easier to write the initialization function, because the
callee does not have to find out the type again.


Full diff: https://github.com/llvm/llvm-project/pull/164030.diff

3 Files Affected:

  • (modified) clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h (+18-2)
  • (modified) clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h (+26-4)
  • (modified) clang/unittests/Analysis/FlowSensitive/CachedConstAccessorsLatticeTest.cpp (+18)
diff --git a/clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h b/clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h
index 6496771ad037e..4e316aaf09bdb 100644
--- a/clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h
+++ b/clang/include/clang/Analysis/FlowSensitive/CachedConstAccessorsLattice.h
@@ -73,6 +73,10 @@ template <typename Base> class CachedConstAccessorsLattice : public Base {
   ///
   ///  - `Callee` should return a location (return type is a reference type or a
   ///     record type).
+  StorageLocation &getOrCreateConstMethodReturnStorageLocation(
+      const RecordStorageLocation &RecordLoc, const FunctionDecl *Callee,
+      Environment &Env,
+      llvm::function_ref<void(QualType, StorageLocation &)> Initialize);
   StorageLocation &getOrCreateConstMethodReturnStorageLocation(
       const RecordStorageLocation &RecordLoc, const FunctionDecl *Callee,
       Environment &Env, llvm::function_ref<void(StorageLocation &)> Initialize);
@@ -196,7 +200,8 @@ template <typename Base>
 StorageLocation &
 CachedConstAccessorsLattice<Base>::getOrCreateConstMethodReturnStorageLocation(
     const RecordStorageLocation &RecordLoc, const FunctionDecl *Callee,
-    Environment &Env, llvm::function_ref<void(StorageLocation &)> Initialize) {
+    Environment &Env,
+    llvm::function_ref<void(QualType, StorageLocation &)> Initialize) {
   assert(Callee != nullptr);
   QualType Type = Callee->getReturnType();
   assert(!Type.isNull());
@@ -206,13 +211,24 @@ CachedConstAccessorsLattice<Base>::getOrCreateConstMethodReturnStorageLocation(
   if (it != ObjMap.end())
     return *it->second;
 
+  auto T = Type.getNonReferenceType();
   StorageLocation &Loc = Env.createStorageLocation(Type.getNonReferenceType());
-  Initialize(Loc);
+  Initialize(T, Loc);
 
   ObjMap.insert({Callee, &Loc});
   return Loc;
 }
 
+template <typename Base>
+StorageLocation &
+CachedConstAccessorsLattice<Base>::getOrCreateConstMethodReturnStorageLocation(
+    const RecordStorageLocation &RecordLoc, const FunctionDecl *Callee,
+    Environment &Env, llvm::function_ref<void(StorageLocation &)> Initialize) {
+  return getOrCreateConstMethodReturnStorageLocation(
+      RecordLoc, Callee, Env,
+      [Initialize](QualType T, StorageLocation &Loc) { Initialize(Loc); });
+}
+
 } // namespace dataflow
 } // namespace clang
 
diff --git a/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h b/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h
index e55b83aa845d4..b5bdff2df8ed6 100644
--- a/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h
+++ b/clang/include/clang/Analysis/FlowSensitive/SmartPointerAccessorCaching.h
@@ -91,7 +91,18 @@ template <typename LatticeT>
 void transferSmartPointerLikeCachedDeref(
     const CallExpr *DerefExpr, RecordStorageLocation *SmartPointerLoc,
     TransferState<LatticeT> &State,
-    llvm::function_ref<void(StorageLocation &)> InitializeLoc);
+    llvm::function_ref<void(QualType, StorageLocation &)> InitializeLoc);
+template <typename LatticeT>
+void transferSmartPointerLikeCachedDeref(
+    const CallExpr *DerefExpr, RecordStorageLocation *SmartPointerLoc,
+    TransferState<LatticeT> &State,
+    llvm::function_ref<void(StorageLocation &)> InitializeLoc) {
+  transferSmartPointerLikeCachedDeref<LatticeT>(
+      DerefExpr, SmartPointerLoc, State,
+      [InitializeLoc](QualType T, StorageLocation &Loc) {
+        InitializeLoc(Loc);
+      });
+}
 
 /// A transfer function for `operator->` (and `get`) calls that can be cached.
 /// Runs the `InitializeLoc` callback to initialize any new StorageLocations.
@@ -103,13 +114,24 @@ template <typename LatticeT>
 void transferSmartPointerLikeCachedGet(
     const CallExpr *GetExpr, RecordStorageLocation *SmartPointerLoc,
     TransferState<LatticeT> &State,
-    llvm::function_ref<void(StorageLocation &)> InitializeLoc);
+    llvm::function_ref<void(QualType, StorageLocation &)> InitializeLoc);
+template <typename LatticeT>
+void transferSmartPointerLikeCachedGet(
+    const CallExpr *GetExpr, RecordStorageLocation *SmartPointerLoc,
+    TransferState<LatticeT> &State,
+    llvm::function_ref<void(StorageLocation &)> InitializeLoc) {
+  transferSmartPointerLikeCachedGet<LatticeT>(
+      GetExpr, SmartPointerLoc, State,
+      [InitializeLoc](QualType T, StorageLocation &Loc) {
+        InitializeLoc(Loc);
+      });
+}
 
 template <typename LatticeT>
 void transferSmartPointerLikeCachedDeref(
     const CallExpr *DerefExpr, RecordStorageLocation *SmartPointerLoc,
     TransferState<LatticeT> &State,
-    llvm::function_ref<void(StorageLocation &)> InitializeLoc) {
+    llvm::function_ref<void(QualType, StorageLocation &)> InitializeLoc) {
   if (State.Env.getStorageLocation(*DerefExpr) != nullptr)
     return;
   if (SmartPointerLoc == nullptr)
@@ -145,7 +167,7 @@ template <typename LatticeT>
 void transferSmartPointerLikeCachedGet(
     const CallExpr *GetExpr, RecordStorageLocation *SmartPointerLoc,
     TransferState<LatticeT> &State,
-    llvm::function_ref<void(StorageLocation &)> InitializeLoc) {
+    llvm::function_ref<void(QualType, StorageLocation &)> InitializeLoc) {
   if (SmartPointerLoc == nullptr)
     return;
 
diff --git a/clang/unittests/Analysis/FlowSensitive/CachedConstAccessorsLatticeTest.cpp b/clang/unittests/Analysis/FlowSensitive/CachedConstAccessorsLatticeTest.cpp
index 67b471e328b5e..5a195ed6cfc32 100644
--- a/clang/unittests/Analysis/FlowSensitive/CachedConstAccessorsLatticeTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/CachedConstAccessorsLatticeTest.cpp
@@ -307,5 +307,23 @@ TEST_F(CachedConstAccessorsLatticeTest, ProducesNewValueAfterJoinDistinct) {
   EXPECT_NE(ValAfterJoin2, Val3);
 }
 
+TEST_F(CachedConstAccessorsLatticeTest, TypePassed) {
+  CommonTestInputs Inputs;
+  auto *CE = Inputs.CallRef;
+  RecordStorageLocation Loc(Inputs.SType, RecordStorageLocation::FieldToLoc(),
+                            {});
+
+  LatticeT Lattice;
+
+  const FunctionDecl *Callee = CE->getDirectCallee();
+  auto RetType = Callee->getReturnType().getNonReferenceType();
+  auto CheckedInit = [RetType](QualType T, StorageLocation &) {
+    ASSERT_EQ(T, RetType);
+  };
+  ASSERT_NE(Callee, nullptr);
+  Lattice.getOrCreateConstMethodReturnStorageLocation(Loc, Callee, Env,
+                                                      CheckedInit);
+}
+
 } // namespace
 } // namespace clang::dataflow

@fmayer fmayer requested a review from jvoung October 17, 2025 23:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:analysis clang:dataflow Clang Dataflow Analysis framework - https://clang.llvm.org/docs/DataFlowAnalysisIntro.html clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants