clang API Documentation

Consumed.h
Go to the documentation of this file.
00001 //===- Consumed.h ----------------------------------------------*- C++ --*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // A intra-procedural analysis for checking consumed properties.  This is based,
00011 // in part, on research on linear types.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H
00016 #define LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H
00017 
00018 #include "clang/AST/DeclCXX.h"
00019 #include "clang/AST/ExprCXX.h"
00020 #include "clang/AST/StmtCXX.h"
00021 #include "clang/Analysis/Analyses/PostOrderCFGView.h"
00022 #include "clang/Analysis/AnalysisContext.h"
00023 #include "clang/Basic/SourceLocation.h"
00024 
00025 namespace clang {
00026 namespace consumed {
00027   
00028   enum ConsumedState {
00029     // No state information for the given variable.
00030     CS_None,
00031     
00032     CS_Unknown,
00033     CS_Unconsumed,
00034     CS_Consumed
00035   };
00036   
00037   class ConsumedStmtVisitor;
00038   
00039   typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes;
00040   typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag;
00041   typedef std::list<DelayedDiag> DiagList;
00042 
00043   class ConsumedWarningsHandlerBase {
00044 
00045   public:
00046 
00047     virtual ~ConsumedWarningsHandlerBase();
00048 
00049     /// \brief Emit the warnings and notes left by the analysis.
00050     virtual void emitDiagnostics() {}
00051     
00052     /// \brief Warn that a variable's state doesn't match at the entry and exit
00053     /// of a loop.
00054     ///
00055     /// \param Loc -- The location of the end of the loop.
00056     ///
00057     /// \param VariableName -- The name of the variable that has a mismatched
00058     /// state.
00059     virtual void warnLoopStateMismatch(SourceLocation Loc,
00060                                        StringRef VariableName) {}
00061     
00062     /// \brief Warn about parameter typestate mismatches upon return.
00063     ///
00064     /// \param Loc -- The SourceLocation of the return statement.
00065     ///
00066     /// \param ExpectedState -- The state the return value was expected to be
00067     /// in.
00068     ///
00069     /// \param ObservedState -- The state the return value was observed to be
00070     /// in.
00071     virtual void warnParamReturnTypestateMismatch(SourceLocation Loc,
00072                                                   StringRef VariableName,
00073                                                   StringRef ExpectedState,
00074                                                   StringRef ObservedState) {};
00075     
00076     // FIXME: Add documentation.
00077     virtual void warnParamTypestateMismatch(SourceLocation LOC,
00078                                             StringRef ExpectedState,
00079                                             StringRef ObservedState) {}
00080     
00081     // FIXME: This can be removed when the attr propagation fix for templated
00082     //        classes lands.
00083     /// \brief Warn about return typestates set for unconsumable types.
00084     /// 
00085     /// \param Loc -- The location of the attributes.
00086     ///
00087     /// \param TypeName -- The name of the unconsumable type.
00088     virtual void warnReturnTypestateForUnconsumableType(SourceLocation Loc,
00089                                                         StringRef TypeName) {}
00090     
00091     /// \brief Warn about return typestate mismatches.
00092     ///
00093     /// \param Loc -- The SourceLocation of the return statement.
00094     ///
00095     /// \param ExpectedState -- The state the return value was expected to be
00096     /// in.
00097     ///
00098     /// \param ObservedState -- The state the return value was observed to be
00099     /// in.
00100     virtual void warnReturnTypestateMismatch(SourceLocation Loc,
00101                                              StringRef ExpectedState,
00102                                              StringRef ObservedState) {}
00103 
00104     /// \brief Warn about use-while-consumed errors.
00105     /// \param MethodName -- The name of the method that was incorrectly
00106     /// invoked.
00107     ///
00108     /// \param State -- The state the object was used in.
00109     ///
00110     /// \param Loc -- The SourceLocation of the method invocation.
00111     virtual void warnUseOfTempInInvalidState(StringRef MethodName,
00112                                              StringRef State,
00113                                              SourceLocation Loc) {}
00114 
00115     /// \brief Warn about use-while-consumed errors.
00116     /// \param MethodName -- The name of the method that was incorrectly
00117     /// invoked.
00118     ///
00119     /// \param State -- The state the object was used in.
00120     ///
00121     /// \param VariableName -- The name of the variable that holds the unique
00122     /// value.
00123     ///
00124     /// \param Loc -- The SourceLocation of the method invocation.
00125     virtual void warnUseInInvalidState(StringRef MethodName,
00126                                        StringRef VariableName,
00127                                        StringRef State,
00128                                        SourceLocation Loc) {}
00129   };
00130 
00131   class ConsumedStateMap {
00132     
00133     typedef llvm::DenseMap<const VarDecl *, ConsumedState> VarMapType;
00134     typedef llvm::DenseMap<const CXXBindTemporaryExpr *, ConsumedState>
00135             TmpMapType;
00136     
00137   protected:
00138     
00139     bool Reachable;
00140     const Stmt *From;
00141     VarMapType VarMap;
00142     TmpMapType TmpMap;
00143     
00144   public:
00145     ConsumedStateMap() : Reachable(true), From(nullptr) {}
00146     ConsumedStateMap(const ConsumedStateMap &Other)
00147       : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap),
00148         TmpMap() {}
00149     
00150     /// \brief Warn if any of the parameters being tracked are not in the state
00151     /// they were declared to be in upon return from a function.
00152     void checkParamsForReturnTypestate(SourceLocation BlameLoc,
00153       ConsumedWarningsHandlerBase &WarningsHandler) const;
00154     
00155     /// \brief Clear the TmpMap.
00156     void clearTemporaries();
00157     
00158     /// \brief Get the consumed state of a given variable.
00159     ConsumedState getState(const VarDecl *Var) const;
00160     
00161     /// \brief Get the consumed state of a given temporary value.
00162     ConsumedState getState(const CXXBindTemporaryExpr *Tmp) const;
00163     
00164     /// \brief Merge this state map with another map.
00165     void intersect(const ConsumedStateMap *Other);
00166     
00167     void intersectAtLoopHead(const CFGBlock *LoopHead, const CFGBlock *LoopBack,
00168       const ConsumedStateMap *LoopBackStates,
00169       ConsumedWarningsHandlerBase &WarningsHandler);
00170     
00171     /// \brief Return true if this block is reachable.
00172     bool isReachable() const { return Reachable; }
00173     
00174     /// \brief Mark the block as unreachable.
00175     void markUnreachable();
00176     
00177     /// \brief Set the source for a decision about the branching of states.
00178     /// \param Source -- The statement that was the origin of a branching
00179     /// decision.
00180     void setSource(const Stmt *Source) { this->From = Source; }
00181     
00182     /// \brief Set the consumed state of a given variable.
00183     void setState(const VarDecl *Var, ConsumedState State);
00184     
00185     /// \brief Set the consumed state of a given temporary value.
00186     void setState(const CXXBindTemporaryExpr *Tmp, ConsumedState State);
00187     
00188     /// \brief Remove the temporary value from our state map.
00189     void remove(const CXXBindTemporaryExpr *Tmp);
00190     
00191     /// \brief Tests to see if there is a mismatch in the states stored in two
00192     /// maps.
00193     ///
00194     /// \param Other -- The second map to compare against.
00195     bool operator!=(const ConsumedStateMap *Other) const;
00196   };
00197   
00198   class ConsumedBlockInfo {
00199     std::vector<ConsumedStateMap*> StateMapsArray;
00200     std::vector<unsigned int> VisitOrder;
00201     
00202   public:
00203     ConsumedBlockInfo() { }
00204     ~ConsumedBlockInfo() { llvm::DeleteContainerPointers(StateMapsArray); }
00205 
00206     ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph)
00207         : StateMapsArray(NumBlocks, nullptr), VisitOrder(NumBlocks, 0) {
00208       unsigned int VisitOrderCounter = 0;
00209       for (PostOrderCFGView::iterator BI = SortedGraph->begin(),
00210            BE = SortedGraph->end(); BI != BE; ++BI) {
00211         VisitOrder[(*BI)->getBlockID()] = VisitOrderCounter++;
00212       }
00213     }
00214     
00215     bool allBackEdgesVisited(const CFGBlock *CurrBlock,
00216                              const CFGBlock *TargetBlock);
00217     
00218     void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap,
00219                  bool &AlreadyOwned);
00220     void addInfo(const CFGBlock *Block, ConsumedStateMap *StateMap);
00221     
00222     ConsumedStateMap* borrowInfo(const CFGBlock *Block);
00223     
00224     void discardInfo(const CFGBlock *Block);
00225     
00226     ConsumedStateMap* getInfo(const CFGBlock *Block);
00227     
00228     bool isBackEdge(const CFGBlock *From, const CFGBlock *To);
00229     bool isBackEdgeTarget(const CFGBlock *Block);
00230   };
00231 
00232   /// A class that handles the analysis of uniqueness violations.
00233   class ConsumedAnalyzer {
00234     
00235     ConsumedBlockInfo BlockInfo;
00236     ConsumedStateMap *CurrStates;
00237     
00238     ConsumedState ExpectedReturnState;
00239     
00240     void determineExpectedReturnState(AnalysisDeclContext &AC,
00241                                       const FunctionDecl *D);
00242     bool hasConsumableAttributes(const CXXRecordDecl *RD);
00243     bool splitState(const CFGBlock *CurrBlock,
00244                     const ConsumedStmtVisitor &Visitor);
00245     
00246   public:
00247     
00248     ConsumedWarningsHandlerBase &WarningsHandler;
00249 
00250     ConsumedAnalyzer(ConsumedWarningsHandlerBase &WarningsHandler)
00251         : WarningsHandler(WarningsHandler) {}
00252 
00253     ConsumedState getExpectedReturnState() const { return ExpectedReturnState; }
00254     
00255     /// \brief Check a function's CFG for consumed violations.
00256     ///
00257     /// We traverse the blocks in the CFG, keeping track of the state of each
00258     /// value who's type has uniquness annotations.  If methods are invoked in
00259     /// the wrong state a warning is issued.  Each block in the CFG is traversed
00260     /// exactly once.
00261     void run(AnalysisDeclContext &AC);
00262   };
00263 }} // end namespace clang::consumed
00264 
00265 #endif