Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:23

0001 //===- Consumed.h -----------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // A intra-procedural analysis for checking consumed properties.  This is based,
0010 // in part, on research on linear types.
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     // No state information for the given variable.
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     /// Emit the warnings and notes left by the analysis.
0061     virtual void emitDiagnostics() {}
0062 
0063     /// Warn that a variable's state doesn't match at the entry and exit
0064     /// of a loop.
0065     ///
0066     /// \param Loc -- The location of the end of the loop.
0067     ///
0068     /// \param VariableName -- The name of the variable that has a mismatched
0069     /// state.
0070     virtual void warnLoopStateMismatch(SourceLocation Loc,
0071                                        StringRef VariableName) {}
0072 
0073     /// Warn about parameter typestate mismatches upon return.
0074     ///
0075     /// \param Loc -- The SourceLocation of the return statement.
0076     ///
0077     /// \param ExpectedState -- The state the return value was expected to be
0078     /// in.
0079     ///
0080     /// \param ObservedState -- The state the return value was observed to be
0081     /// in.
0082     virtual void warnParamReturnTypestateMismatch(SourceLocation Loc,
0083                                                   StringRef VariableName,
0084                                                   StringRef ExpectedState,
0085                                                   StringRef ObservedState) {}
0086 
0087     // FIXME: Add documentation.
0088     virtual void warnParamTypestateMismatch(SourceLocation LOC,
0089                                             StringRef ExpectedState,
0090                                             StringRef ObservedState) {}
0091 
0092     // FIXME: This can be removed when the attr propagation fix for templated
0093     //        classes lands.
0094     /// Warn about return typestates set for unconsumable types.
0095     ///
0096     /// \param Loc -- The location of the attributes.
0097     ///
0098     /// \param TypeName -- The name of the unconsumable type.
0099     virtual void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
0100                                                         StringRef TypeName) {}
0101 
0102     /// Warn about return typestate mismatches.
0103     ///
0104     /// \param Loc -- The SourceLocation of the return statement.
0105     ///
0106     /// \param ExpectedState -- The state the return value was expected to be
0107     /// in.
0108     ///
0109     /// \param ObservedState -- The state the return value was observed to be
0110     /// in.
0111     virtual void warnReturnTypestateMismatch(SourceLocation Loc,
0112                                              StringRef ExpectedState,
0113                                              StringRef ObservedState) {}
0114 
0115     /// Warn about use-while-consumed errors.
0116     /// \param MethodName -- The name of the method that was incorrectly
0117     /// invoked.
0118     ///
0119     /// \param State -- The state the object was used in.
0120     ///
0121     /// \param Loc -- The SourceLocation of the method invocation.
0122     virtual void warnUseOfTempInInvalidState(StringRef MethodName,
0123                                              StringRef State,
0124                                              SourceLocation Loc) {}
0125 
0126     /// Warn about use-while-consumed errors.
0127     /// \param MethodName -- The name of the method that was incorrectly
0128     /// invoked.
0129     ///
0130     /// \param State -- The state the object was used in.
0131     ///
0132     /// \param VariableName -- The name of the variable that holds the unique
0133     /// value.
0134     ///
0135     /// \param Loc -- The SourceLocation of the method invocation.
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     // The copy assignment operator is defined as deleted pending further
0159     // motivation.
0160     ConsumedStateMap &operator=(const ConsumedStateMap &) = delete;
0161 
0162     /// Warn if any of the parameters being tracked are not in the state
0163     /// they were declared to be in upon return from a function.
0164     void checkParamsForReturnTypestate(SourceLocation BlameLoc,
0165       ConsumedWarningsHandlerBase &WarningsHandler) const;
0166 
0167     /// Clear the TmpMap.
0168     void clearTemporaries();
0169 
0170     /// Get the consumed state of a given variable.
0171     ConsumedState getState(const VarDecl *Var) const;
0172 
0173     /// Get the consumed state of a given temporary value.
0174     ConsumedState getState(const CXXBindTemporaryExpr *Tmp) const;
0175 
0176     /// Merge this state map with another map.
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     /// Return true if this block is reachable.
0184     bool isReachable() const { return Reachable; }
0185 
0186     /// Mark the block as unreachable.
0187     void markUnreachable();
0188 
0189     /// Set the source for a decision about the branching of states.
0190     /// \param Source -- The statement that was the origin of a branching
0191     /// decision.
0192     void setSource(const Stmt *Source) { this->From = Source; }
0193 
0194     /// Set the consumed state of a given variable.
0195     void setState(const VarDecl *Var, ConsumedState State);
0196 
0197     /// Set the consumed state of a given temporary value.
0198     void setState(const CXXBindTemporaryExpr *Tmp, ConsumedState State);
0199 
0200     /// Remove the temporary value from our state map.
0201     void remove(const CXXBindTemporaryExpr *Tmp);
0202 
0203     /// Tests to see if there is a mismatch in the states stored in two
0204     /// maps.
0205     ///
0206     /// \param Other -- The second map to compare against.
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   /// A class that handles the analysis of uniqueness violations.
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     /// Check a function's CFG for consumed violations.
0263     ///
0264     /// We traverse the blocks in the CFG, keeping track of the state of each
0265     /// value who's type has uniqueness annotations.  If methods are invoked in
0266     /// the wrong state a warning is issued.  Each block in the CFG is traversed
0267     /// exactly once.
0268     void run(AnalysisDeclContext &AC);
0269   };
0270 
0271 } // namespace consumed
0272 
0273 } // namespace clang
0274 
0275 #endif // LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H