File indexing completed on 2026-05-10 08:36:23
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H
0015 #define LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H
0016
0017 #include "clang/Analysis/Analyses/PostOrderCFGView.h"
0018 #include "clang/Analysis/CFG.h"
0019 #include "clang/Basic/LLVM.h"
0020 #include "clang/Basic/PartialDiagnostic.h"
0021 #include "clang/Basic/SourceLocation.h"
0022 #include "llvm/ADT/DenseMap.h"
0023 #include "llvm/ADT/SmallVector.h"
0024 #include "llvm/ADT/StringRef.h"
0025 #include <list>
0026 #include <memory>
0027 #include <utility>
0028 #include <vector>
0029
0030 namespace clang {
0031
0032 class AnalysisDeclContext;
0033 class CXXBindTemporaryExpr;
0034 class FunctionDecl;
0035 class PostOrderCFGView;
0036 class Stmt;
0037 class VarDecl;
0038
0039 namespace consumed {
0040
0041 class ConsumedStmtVisitor;
0042
0043 enum ConsumedState {
0044
0045 CS_None,
0046
0047 CS_Unknown,
0048 CS_Unconsumed,
0049 CS_Consumed
0050 };
0051
0052 using OptionalNotes = SmallVector<PartialDiagnosticAt, 1>;
0053 using DelayedDiag = std::pair<PartialDiagnosticAt, OptionalNotes>;
0054 using DiagList = std::list<DelayedDiag>;
0055
0056 class ConsumedWarningsHandlerBase {
0057 public:
0058 virtual ~ConsumedWarningsHandlerBase();
0059
0060
0061 virtual void emitDiagnostics() {}
0062
0063
0064
0065
0066
0067
0068
0069
0070 virtual void warnLoopStateMismatch(SourceLocation Loc,
0071 StringRef VariableName) {}
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 virtual void warnParamReturnTypestateMismatch(SourceLocation Loc,
0083 StringRef VariableName,
0084 StringRef ExpectedState,
0085 StringRef ObservedState) {}
0086
0087
0088 virtual void warnParamTypestateMismatch(SourceLocation LOC,
0089 StringRef ExpectedState,
0090 StringRef ObservedState) {}
0091
0092
0093
0094
0095
0096
0097
0098
0099 virtual void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
0100 StringRef TypeName) {}
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111 virtual void warnReturnTypestateMismatch(SourceLocation Loc,
0112 StringRef ExpectedState,
0113 StringRef ObservedState) {}
0114
0115
0116
0117
0118
0119
0120
0121
0122 virtual void warnUseOfTempInInvalidState(StringRef MethodName,
0123 StringRef State,
0124 SourceLocation Loc) {}
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136 virtual void warnUseInInvalidState(StringRef MethodName,
0137 StringRef VariableName,
0138 StringRef State,
0139 SourceLocation Loc) {}
0140 };
0141
0142 class ConsumedStateMap {
0143 using VarMapType = llvm::DenseMap<const VarDecl *, ConsumedState>;
0144 using TmpMapType =
0145 llvm::DenseMap<const CXXBindTemporaryExpr *, ConsumedState>;
0146
0147 protected:
0148 bool Reachable = true;
0149 const Stmt *From = nullptr;
0150 VarMapType VarMap;
0151 TmpMapType TmpMap;
0152
0153 public:
0154 ConsumedStateMap() = default;
0155 ConsumedStateMap(const ConsumedStateMap &Other)
0156 : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap) {}
0157
0158
0159
0160 ConsumedStateMap &operator=(const ConsumedStateMap &) = delete;
0161
0162
0163
0164 void checkParamsForReturnTypestate(SourceLocation BlameLoc,
0165 ConsumedWarningsHandlerBase &WarningsHandler) const;
0166
0167
0168 void clearTemporaries();
0169
0170
0171 ConsumedState getState(const VarDecl *Var) const;
0172
0173
0174 ConsumedState getState(const CXXBindTemporaryExpr *Tmp) const;
0175
0176
0177 void intersect(const ConsumedStateMap &Other);
0178
0179 void intersectAtLoopHead(const CFGBlock *LoopHead, const CFGBlock *LoopBack,
0180 const ConsumedStateMap *LoopBackStates,
0181 ConsumedWarningsHandlerBase &WarningsHandler);
0182
0183
0184 bool isReachable() const { return Reachable; }
0185
0186
0187 void markUnreachable();
0188
0189
0190
0191
0192 void setSource(const Stmt *Source) { this->From = Source; }
0193
0194
0195 void setState(const VarDecl *Var, ConsumedState State);
0196
0197
0198 void setState(const CXXBindTemporaryExpr *Tmp, ConsumedState State);
0199
0200
0201 void remove(const CXXBindTemporaryExpr *Tmp);
0202
0203
0204
0205
0206
0207 bool operator!=(const ConsumedStateMap *Other) const;
0208 };
0209
0210 class ConsumedBlockInfo {
0211 std::vector<std::unique_ptr<ConsumedStateMap>> StateMapsArray;
0212 std::vector<unsigned int> VisitOrder;
0213
0214 public:
0215 ConsumedBlockInfo() = default;
0216
0217 ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph)
0218 : StateMapsArray(NumBlocks), VisitOrder(NumBlocks, 0) {
0219 unsigned int VisitOrderCounter = 0;
0220 for (const auto BI : *SortedGraph)
0221 VisitOrder[BI->getBlockID()] = VisitOrderCounter++;
0222 }
0223
0224 bool allBackEdgesVisited(const CFGBlock *CurrBlock,
0225 const CFGBlock *TargetBlock);
0226
0227 void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap,
0228 std::unique_ptr<ConsumedStateMap> &OwnedStateMap);
0229 void addInfo(const CFGBlock *Block,
0230 std::unique_ptr<ConsumedStateMap> StateMap);
0231
0232 ConsumedStateMap* borrowInfo(const CFGBlock *Block);
0233
0234 void discardInfo(const CFGBlock *Block);
0235
0236 std::unique_ptr<ConsumedStateMap> getInfo(const CFGBlock *Block);
0237
0238 bool isBackEdge(const CFGBlock *From, const CFGBlock *To);
0239 bool isBackEdgeTarget(const CFGBlock *Block);
0240 };
0241
0242
0243 class ConsumedAnalyzer {
0244 ConsumedBlockInfo BlockInfo;
0245 std::unique_ptr<ConsumedStateMap> CurrStates;
0246
0247 ConsumedState ExpectedReturnState = CS_None;
0248
0249 void determineExpectedReturnState(AnalysisDeclContext &AC,
0250 const FunctionDecl *D);
0251 bool splitState(const CFGBlock *CurrBlock,
0252 const ConsumedStmtVisitor &Visitor);
0253
0254 public:
0255 ConsumedWarningsHandlerBase &WarningsHandler;
0256
0257 ConsumedAnalyzer(ConsumedWarningsHandlerBase &WarningsHandler)
0258 : WarningsHandler(WarningsHandler) {}
0259
0260 ConsumedState getExpectedReturnState() const { return ExpectedReturnState; }
0261
0262
0263
0264
0265
0266
0267
0268 void run(AnalysisDeclContext &AC);
0269 };
0270
0271 }
0272
0273 }
0274
0275 #endif