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 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 Initialize); StorageLocation &getOrCreateConstMethodReturnStorageLocation( const RecordStorageLocation &RecordLoc, const FunctionDecl *Callee, Environment &Env, llvm::function_ref Initialize); @@ -196,7 +200,8 @@ template StorageLocation & CachedConstAccessorsLattice::getOrCreateConstMethodReturnStorageLocation( const RecordStorageLocation &RecordLoc, const FunctionDecl *Callee, - Environment &Env, llvm::function_ref Initialize) { + Environment &Env, + llvm::function_ref Initialize) { assert(Callee != nullptr); QualType Type = Callee->getReturnType(); assert(!Type.isNull()); @@ -206,13 +211,24 @@ CachedConstAccessorsLattice::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 +StorageLocation & +CachedConstAccessorsLattice::getOrCreateConstMethodReturnStorageLocation( + const RecordStorageLocation &RecordLoc, const FunctionDecl *Callee, + Environment &Env, llvm::function_ref 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 void transferSmartPointerLikeCachedDeref( const CallExpr *DerefExpr, RecordStorageLocation *SmartPointerLoc, TransferState &State, - llvm::function_ref InitializeLoc); + llvm::function_ref InitializeLoc); +template +void transferSmartPointerLikeCachedDeref( + const CallExpr *DerefExpr, RecordStorageLocation *SmartPointerLoc, + TransferState &State, + llvm::function_ref InitializeLoc) { + transferSmartPointerLikeCachedDeref( + 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 void transferSmartPointerLikeCachedGet( const CallExpr *GetExpr, RecordStorageLocation *SmartPointerLoc, TransferState &State, - llvm::function_ref InitializeLoc); + llvm::function_ref InitializeLoc); +template +void transferSmartPointerLikeCachedGet( + const CallExpr *GetExpr, RecordStorageLocation *SmartPointerLoc, + TransferState &State, + llvm::function_ref InitializeLoc) { + transferSmartPointerLikeCachedGet( + GetExpr, SmartPointerLoc, State, + [InitializeLoc](QualType T, StorageLocation &Loc) { + InitializeLoc(Loc); + }); +} template void transferSmartPointerLikeCachedDeref( const CallExpr *DerefExpr, RecordStorageLocation *SmartPointerLoc, TransferState &State, - llvm::function_ref InitializeLoc) { + llvm::function_ref InitializeLoc) { if (State.Env.getStorageLocation(*DerefExpr) != nullptr) return; if (SmartPointerLoc == nullptr) @@ -145,7 +167,7 @@ template void transferSmartPointerLikeCachedGet( const CallExpr *GetExpr, RecordStorageLocation *SmartPointerLoc, TransferState &State, - llvm::function_ref InitializeLoc) { + llvm::function_ref 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