File indexing completed on 2026-05-10 08:36:24
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CACHED_CONST_ACCESSORS_LATTICE_H
0014 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE_CACHED_CONST_ACCESSORS_LATTICE_H
0015
0016 #include "clang/AST/Decl.h"
0017 #include "clang/AST/Expr.h"
0018 #include "clang/AST/Type.h"
0019 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
0020 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
0021 #include "clang/Analysis/FlowSensitive/StorageLocation.h"
0022 #include "clang/Analysis/FlowSensitive/Value.h"
0023 #include "llvm/ADT/DenseMap.h"
0024 #include "llvm/ADT/STLFunctionalExtras.h"
0025
0026 namespace clang {
0027 namespace dataflow {
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050 template <typename Base> class CachedConstAccessorsLattice : public Base {
0051 public:
0052 using Base::Base;
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062 Value *
0063 getOrCreateConstMethodReturnValue(const RecordStorageLocation &RecordLoc,
0064 const CallExpr *CE, Environment &Env);
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079 StorageLocation *getOrCreateConstMethodReturnStorageLocation(
0080 const RecordStorageLocation &RecordLoc, const CallExpr *CE,
0081 Environment &Env, llvm::function_ref<void(StorageLocation &)> Initialize);
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093 StorageLocation &getOrCreateConstMethodReturnStorageLocation(
0094 const RecordStorageLocation &RecordLoc, const FunctionDecl *Callee,
0095 Environment &Env, llvm::function_ref<void(StorageLocation &)> Initialize);
0096
0097 void clearConstMethodReturnValues(const RecordStorageLocation &RecordLoc) {
0098 ConstMethodReturnValues.erase(&RecordLoc);
0099 }
0100
0101 void clearConstMethodReturnStorageLocations(
0102 const RecordStorageLocation &RecordLoc) {
0103 ConstMethodReturnStorageLocations.erase(&RecordLoc);
0104 }
0105
0106 bool operator==(const CachedConstAccessorsLattice &Other) const {
0107 return Base::operator==(Other);
0108 }
0109
0110 LatticeJoinEffect join(const CachedConstAccessorsLattice &Other);
0111
0112 private:
0113
0114
0115 using ConstMethodReturnValuesType =
0116 llvm::SmallDenseMap<const RecordStorageLocation *,
0117 llvm::SmallDenseMap<const FunctionDecl *, Value *>>;
0118 ConstMethodReturnValuesType ConstMethodReturnValues;
0119
0120
0121
0122 using ConstMethodReturnStorageLocationsType = llvm::SmallDenseMap<
0123 const RecordStorageLocation *,
0124 llvm::SmallDenseMap<const FunctionDecl *, StorageLocation *>>;
0125 ConstMethodReturnStorageLocationsType ConstMethodReturnStorageLocations;
0126 };
0127
0128 namespace internal {
0129
0130 template <typename T>
0131 llvm::SmallDenseMap<const RecordStorageLocation *,
0132 llvm::SmallDenseMap<const FunctionDecl *, T *>>
0133 joinConstMethodMap(
0134 const llvm::SmallDenseMap<const RecordStorageLocation *,
0135 llvm::SmallDenseMap<const FunctionDecl *, T *>>
0136 &Map1,
0137 const llvm::SmallDenseMap<const RecordStorageLocation *,
0138 llvm::SmallDenseMap<const FunctionDecl *, T *>>
0139 &Map2,
0140 LatticeEffect &Effect) {
0141 llvm::SmallDenseMap<const RecordStorageLocation *,
0142 llvm::SmallDenseMap<const FunctionDecl *, T *>>
0143 Result;
0144 for (auto &[Loc, DeclToT] : Map1) {
0145 auto It = Map2.find(Loc);
0146 if (It == Map2.end()) {
0147 Effect = LatticeJoinEffect::Changed;
0148 continue;
0149 }
0150 const auto &OtherDeclToT = It->second;
0151 auto &JoinedDeclToT = Result[Loc];
0152 for (auto [Func, Var] : DeclToT) {
0153 T *OtherVar = OtherDeclToT.lookup(Func);
0154 if (OtherVar == nullptr || OtherVar != Var) {
0155 Effect = LatticeJoinEffect::Changed;
0156 continue;
0157 }
0158 JoinedDeclToT.insert({Func, Var});
0159 }
0160 }
0161 return Result;
0162 }
0163
0164 }
0165
0166 template <typename Base>
0167 LatticeEffect CachedConstAccessorsLattice<Base>::join(
0168 const CachedConstAccessorsLattice<Base> &Other) {
0169
0170 LatticeEffect Effect = Base::join(Other);
0171
0172
0173
0174
0175
0176 ConstMethodReturnValues =
0177 clang::dataflow::internal::joinConstMethodMap<dataflow::Value>(
0178 ConstMethodReturnValues, Other.ConstMethodReturnValues, Effect);
0179
0180 ConstMethodReturnStorageLocations =
0181 clang::dataflow::internal::joinConstMethodMap<dataflow::StorageLocation>(
0182 ConstMethodReturnStorageLocations,
0183 Other.ConstMethodReturnStorageLocations, Effect);
0184
0185 return Effect;
0186 }
0187
0188 template <typename Base>
0189 Value *CachedConstAccessorsLattice<Base>::getOrCreateConstMethodReturnValue(
0190 const RecordStorageLocation &RecordLoc, const CallExpr *CE,
0191 Environment &Env) {
0192 QualType Type = CE->getType();
0193 assert(!Type.isNull());
0194 assert(!Type->isReferenceType());
0195 assert(!Type->isRecordType());
0196
0197 auto &ObjMap = ConstMethodReturnValues[&RecordLoc];
0198 const FunctionDecl *DirectCallee = CE->getDirectCallee();
0199 if (DirectCallee == nullptr)
0200 return nullptr;
0201 auto it = ObjMap.find(DirectCallee);
0202 if (it != ObjMap.end())
0203 return it->second;
0204
0205 Value *Val = Env.createValue(Type);
0206 if (Val != nullptr)
0207 ObjMap.insert({DirectCallee, Val});
0208 return Val;
0209 }
0210
0211 template <typename Base>
0212 StorageLocation *
0213 CachedConstAccessorsLattice<Base>::getOrCreateConstMethodReturnStorageLocation(
0214 const RecordStorageLocation &RecordLoc, const CallExpr *CE,
0215 Environment &Env, llvm::function_ref<void(StorageLocation &)> Initialize) {
0216 assert(!CE->getType().isNull());
0217 assert(CE->isGLValue() || CE->getType()->isRecordType());
0218 auto &ObjMap = ConstMethodReturnStorageLocations[&RecordLoc];
0219 const FunctionDecl *DirectCallee = CE->getDirectCallee();
0220 if (DirectCallee == nullptr)
0221 return nullptr;
0222 auto it = ObjMap.find(DirectCallee);
0223 if (it != ObjMap.end())
0224 return it->second;
0225
0226 StorageLocation &Loc =
0227 Env.createStorageLocation(CE->getType().getNonReferenceType());
0228 Initialize(Loc);
0229
0230 ObjMap.insert({DirectCallee, &Loc});
0231 return &Loc;
0232 }
0233
0234 template <typename Base>
0235 StorageLocation &
0236 CachedConstAccessorsLattice<Base>::getOrCreateConstMethodReturnStorageLocation(
0237 const RecordStorageLocation &RecordLoc, const FunctionDecl *Callee,
0238 Environment &Env, llvm::function_ref<void(StorageLocation &)> Initialize) {
0239 assert(Callee != nullptr);
0240 QualType Type = Callee->getReturnType();
0241 assert(!Type.isNull());
0242 assert(Type->isReferenceType() || Type->isRecordType());
0243 auto &ObjMap = ConstMethodReturnStorageLocations[&RecordLoc];
0244 auto it = ObjMap.find(Callee);
0245 if (it != ObjMap.end())
0246 return *it->second;
0247
0248 StorageLocation &Loc = Env.createStorageLocation(Type.getNonReferenceType());
0249 Initialize(Loc);
0250
0251 ObjMap.insert({Callee, &Loc});
0252 return Loc;
0253 }
0254
0255 }
0256 }
0257
0258 #endif