diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2018-08-02 17:33:11 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2018-08-02 17:33:11 +0000 | 
| commit | c7e70c433efc6953dc3888b9fbf9f3512d7da2b0 (patch) | |
| tree | 27425930fc0c91650a7f3527fcac8e0f92907b90 /include/clang/StaticAnalyzer | |
| parent | 486754660bb926339aefcf012a3f848592babb8b (diff) | |
Diffstat (limited to 'include/clang/StaticAnalyzer')
32 files changed, 292 insertions, 247 deletions
diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td index ab0e4af1361b..9e53460f6e93 100644 --- a/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -276,6 +276,10 @@ def ReturnUndefChecker : Checker<"UndefReturn">,  let ParentPackage = Cplusplus in { +def InnerPointerChecker : Checker<"InnerPointer">, +  HelpText<"Check for inner pointers of C++ containers used after re/deallocation">, +  DescFile<"InnerPointerChecker.cpp">; +  def NewDeleteChecker : Checker<"NewDelete">,    HelpText<"Check for double-free and use-after-free problems. Traces memory managed by new/delete.">,    DescFile<"MallocChecker.cpp">; @@ -305,10 +309,6 @@ def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">,             "destructor in their base class">,    DescFile<"DeleteWithNonVirtualDtorChecker.cpp">; -def InnerPointerChecker : Checker<"InnerPointer">, -  HelpText<"Check for inner pointers of C++ containers used after re/deallocation">, -  DescFile<"InnerPointerChecker.cpp">; -  def IteratorRangeChecker : Checker<"IteratorRange">,    HelpText<"Check for iterators used outside their valid ranges">,    DescFile<"IteratorChecker.cpp">; @@ -440,7 +440,7 @@ def MallocOverflowSecurityChecker : Checker<"MallocOverflow">,    DescFile<"MallocOverflowSecurityChecker.cpp">;  // Operating systems specific PROT_READ/PROT_WRITE values is not implemented, -// the defaults are correct for several common operating systems though,  +// the defaults are correct for several common operating systems though,  // but may need to be overridden via the related analyzer-config flags.  def MmapWriteExecChecker : Checker<"MmapWriteExec">,    HelpText<"Warn on mmap() calls that are both writable and executable">, diff --git a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h index e5e857e97029..f5a06394b187 100644 --- a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h +++ b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h @@ -136,7 +136,7 @@ public:      // by inlining the function      NoRetHard    }; -   +    /// Determines the object kind of a tracked object.    enum ObjKind {      /// Indicates that the tracked object is a CF object.  This is @@ -153,30 +153,30 @@ public:  private:    Kind K;    ObjKind O; -   +    RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {} -   +  public:    Kind getKind() const { return K; } -   +    ObjKind getObjKind() const { return O; } -   +    bool isOwned() const {      return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;    } -   +    bool notOwned() const {      return K == NotOwnedSymbol;    } -   +    bool operator==(const RetEffect &Other) const {      return K == Other.K && O == Other.O;    } -   +    static RetEffect MakeOwnedWhenTrackedReceiver() {      return RetEffect(OwnedWhenTrackedReceiver, ObjC);    } -   +    static RetEffect MakeOwned(ObjKind o) {      return RetEffect(OwnedSymbol, o);    } diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index 9d292cfddb0c..7586f7e0835b 100644 --- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -130,23 +130,23 @@ public:    /// Pair of checker name and enable/disable.    std::vector<std::pair<std::string, bool>> CheckersControlList; -   +    /// A key-value table of use-specified configuration values.    ConfigTable Config;    AnalysisStores AnalysisStoreOpt = RegionStoreModel;    AnalysisConstraints AnalysisConstraintsOpt = RangeConstraintsModel;    AnalysisDiagClients AnalysisDiagOpt = PD_HTML;    AnalysisPurgeMode AnalysisPurgeOpt = PurgeStmt; -   +    std::string AnalyzeSpecificFunction;    /// Store full compiler invocation for reproducible instructions in the    /// generated report.    std::string FullCompilerInvocation; -   +    /// The maximum number of times the analyzer visits a block.    unsigned maxBlockVisitOnPath; -   +    /// Disable all analyzer checks.    ///    /// This flag allows one to disable analyzer checks on the code processed by @@ -170,21 +170,21 @@ public:    /// precision until we have a better way to lazily evaluate such logic.  The    /// downside is that it eagerly bifurcates paths.    unsigned eagerlyAssumeBinOpBifurcation : 1; -   +    unsigned TrimGraph : 1;    unsigned visualizeExplodedGraphWithGraphViz : 1;    unsigned visualizeExplodedGraphWithUbiGraph : 1;    unsigned UnoptimizedCFG : 1;    unsigned PrintStats : 1; -   +    /// Do not re-analyze paths leading to exhausted nodes with a different    /// strategy. We get better code coverage when retry is enabled.    unsigned NoRetryExhausted : 1; -   +    /// The inlining stack depth limit.    // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).    unsigned InlineMaxStackDepth = 5; -   +    /// The mode of function selection used during inlining.    AnalysisInliningMode InliningMode = NoRedundancy; @@ -211,7 +211,7 @@ private:      UMK_Deep = 2    }; -  /// Controls the high-level analyzer mode, which influences the default  +  /// Controls the high-level analyzer mode, which influences the default    /// settings for some of the lower-level config options (such as IPAMode).    /// \sa getUserMode    UserModeKind UserMode = UMK_NotSet; @@ -221,7 +221,7 @@ private:    /// Controls which C++ member functions will be considered for inlining.    CXXInlineableMemberKind CXXMemberInliningMode; -   +    /// \sa includeImplicitDtorsInCFG    Optional<bool> IncludeImplicitDtorsInCFG; @@ -239,7 +239,7 @@ private:    /// \sa mayInlineCXXStandardLibrary    Optional<bool> InlineCXXStandardLibrary; -   +    /// \sa includeScopesInCFG    Optional<bool> IncludeScopesInCFG; @@ -722,9 +722,9 @@ public:    /// the option will be ignored.    bool shouldElideConstructors();  }; -   +  using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>; -   +  } // namespace clang  #endif // LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 111e1d1e8e20..9041f4c1afbd 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -74,7 +74,7 @@ using DiagnosticForConsumerMapTy =  /// This class provides an interface through which checkers can create  /// individual bug reports.  class BugReport : public llvm::ilist_node<BugReport> { -public:   +public:    class NodeResolver {      virtual void anchor(); @@ -102,7 +102,7 @@ protected:    PathDiagnosticLocation Location;    PathDiagnosticLocation UniqueingLocation;    const Decl *UniqueingDecl; -   +    const ExplodedNode *ErrorNode = nullptr;    SmallVector<SourceRange, 4> Ranges;    ExtraTextList ExtraText; @@ -220,12 +220,12 @@ public:    /// Disable all path pruning when generating a PathDiagnostic.    void disablePathPruning() { DoNotPrunePath = true; } -   +    void markInteresting(SymbolRef sym);    void markInteresting(const MemRegion *R);    void markInteresting(SVal V);    void markInteresting(const LocationContext *LC); -   +    bool isInteresting(SymbolRef sym);    bool isInteresting(const MemRegion *R);    bool isInteresting(SVal V); @@ -251,11 +251,11 @@ public:    void markInvalid(const void *Tag, const void *Data) {      Invalidations.insert(std::make_pair(Tag, Data));    } -   +    /// Return the canonical declaration, be it a method or class, where    /// this issue semantically occurred.    const Decl *getDeclWithIssue() const; -   +    /// Specifically set the Decl where an issue occurred.  This isn't necessary    /// for BugReports that cover a path as it will be automatically inferred.    void setDeclWithIssue(const Decl *declWithIssue) { @@ -290,7 +290,7 @@ public:    /// This allows for addition of meta data to the diagnostic.    /// -  /// Currently, only the HTMLDiagnosticClient knows how to display it.  +  /// Currently, only the HTMLDiagnosticClient knows how to display it.    void addExtraText(StringRef S) {      ExtraText.push_back(S);    } @@ -310,7 +310,7 @@ public:    PathDiagnosticLocation getUniqueingLocation() const {      return UniqueingLocation;    } -   +    /// Get the declaration containing the uniqueing location.    const Decl *getUniqueingDecl() const {      return UniqueingDecl; diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h index 92118b0fbee2..da019f83c214 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h @@ -246,7 +246,7 @@ public:                         BugReport &BR) override;  }; -/// When a region containing undefined value or '0' value is passed  +/// When a region containing undefined value or '0' value is passed  /// as an argument in a call, marks the call as interesting.  ///  /// As a result, BugReporter will not prune the path through the function even diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h index c723f31aec26..3c1f8f718a3b 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h @@ -52,7 +52,7 @@ public:      // FIXME: This is a workaround to ensure that the correct check name is used      // The check names are set after the constructors are run.      // In case the BugType object is initialized in the checker's ctor -    // the Check field will be empty. To circumvent this problem we use  +    // the Check field will be empty. To circumvent this problem we use      // CheckerBase whenever it is possible.      StringRef CheckName =          Checker ? Checker->getCheckName().getName() : Check.getName(); diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index b18d3c9b3031..b0bb12feba20 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -71,17 +71,17 @@ public:      PDFileEntry(llvm::FoldingSetNodeID &NodeID) : NodeID(NodeID) {}      using ConsumerFiles = std::vector<std::pair<StringRef, StringRef>>; -     +      /// A vector of <consumer,file> pairs.      ConsumerFiles files; -     +      /// A precomputed hash tag used for uniquing PDFileEntry objects.      const llvm::FoldingSetNodeID NodeID;      /// Used for profiling in the FoldingSet.      void Profile(llvm::FoldingSetNodeID &ID) { ID = NodeID; }    }; -   +    class FilesMade {      llvm::BumpPtrAllocator Alloc;      llvm::FoldingSet<PDFileEntry> Set; @@ -94,7 +94,7 @@ public:      void addDiagnostic(const PathDiagnostic &PD,                         StringRef ConsumerName,                         StringRef fileName); -     +      PDFileEntry::ConsumerFiles *getFiles(const PathDiagnostic &PD);    }; @@ -127,7 +127,7 @@ public:    virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }    virtual bool supportsLogicalOpControlFlow() const { return false; } -   +    /// Return true if the PathDiagnosticConsumer supports individual    /// PathDiagnostics that span multiple files.    virtual bool supportsCrossFileDiagnostics() const { return false; } @@ -322,12 +322,12 @@ public:    void flatten();    const SourceManager& getManager() const { assert(isValid()); return *SM; } -   +    void Profile(llvm::FoldingSetNodeID &ID) const;    void dump() const; -  /// Given an exploded node, retrieve the statement that should be used  +  /// Given an exploded node, retrieve the statement that should be used    /// for the diagnostic location.    static const Stmt *getStmt(const ExplodedNode *N); @@ -354,7 +354,7 @@ public:      Start.flatten();      End.flatten();    } -   +    void Profile(llvm::FoldingSetNodeID &ID) const {      Start.Profile(ID);      End.Profile(ID); @@ -378,7 +378,7 @@ private:    /// In the containing bug report, this piece is the last piece from    /// the main source file.    bool LastInMainSourceFile = false; -   +    /// A constant string that can be used to tag the PathDiagnosticPiece,    /// typically with the identification of the creator.  The actual pointer    /// value is meant to be an identifier; the string itself is useful for @@ -401,14 +401,14 @@ public:    /// Tag this PathDiagnosticPiece with the given C-string.    void setTag(const char *tag) { Tag = tag; } -   +    /// Return the opaque tag (if any) on the PathDiagnosticPiece.    const void *getTag() const { return Tag.data(); } -   +    /// Return the string representation of the tag.  This is useful    /// for debugging.    StringRef getTagStr() const { return Tag; } -   +    /// getDisplayHint - Return a hint indicating where the diagnostic should    ///  be displayed by the PathDiagnosticConsumer.    DisplayHint getDisplayHint() const { return Hint; } @@ -488,7 +488,7 @@ public:  /// Interface for classes constructing Stack hints.  /// -/// If a PathDiagnosticEvent occurs in a different frame than the final  +/// If a PathDiagnosticEvent occurs in a different frame than the final  /// diagnostic the hints can be used to summarize the effect of the call.  class StackHintGenerator {  public: @@ -563,12 +563,12 @@ public:    bool hasCallStackHint() { return (bool)CallStackHint; } -  /// Produce the hint for the given node. The node contains  +  /// Produce the hint for the given node. The node contains    /// information about the call for which the diagnostic can be generated.    std::string getCallStackMessage(const ExplodedNode *N) {      if (CallStackHint)        return CallStackHint->getMessage(N); -    return {};   +    return {};    }    void dump() const override; @@ -605,16 +605,16 @@ class PathDiagnosticCallPiece : public PathDiagnosticPiece {  public:    PathDiagnosticLocation callEnter;    PathDiagnosticLocation callEnterWithin; -  PathDiagnosticLocation callReturn;   +  PathDiagnosticLocation callReturn;    PathPieces path;    ~PathDiagnosticCallPiece() override;    const Decl *getCaller() const { return Caller; } -   +    const Decl *getCallee() const { return Callee; }    void setCallee(const CallEnter &CE, const SourceManager &SM); -   +    bool hasCallStackMessage() { return !CallStackMessage.empty(); }    void setCallStackMessage(StringRef st) { CallStackMessage = st; } @@ -725,7 +725,7 @@ public:    ~PathDiagnosticMacroPiece() override;    PathPieces subPieces; -   +    bool containsEvent() const;    void flattenLocations() override { @@ -779,7 +779,7 @@ class PathDiagnostic : public llvm::FoldingSetNode {    PathPieces pathImpl;    SmallVector<PathPieces *, 3> pathStack; -   +    /// Important bug uniqueing location.    /// The location info is useful to differentiate between bugs.    PathDiagnosticLocation UniqueingLoc; @@ -796,22 +796,22 @@ public:                   const Decl *DeclToUnique,                   std::unique_ptr<FilesToLineNumsMap> ExecutedLines);    ~PathDiagnostic(); -   +    const PathPieces &path; -  /// Return the path currently used by builders for constructing the  +  /// Return the path currently used by builders for constructing the    /// PathDiagnostic.    PathPieces &getActivePath() {      if (pathStack.empty())        return pathImpl;      return *pathStack.back();    } -   +    /// Return a mutable version of 'path'.    PathPieces &getMutablePieces() {      return pathImpl;    } -     +    /// Return the unrolled size of the path.    unsigned full_size(); @@ -898,7 +898,7 @@ public:    /// Two diagnostics with the same issue along different paths will generate    /// different profiles.    void FullProfile(llvm::FoldingSetNodeID &ID) const; -};   +};  } // namespace ento diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h index 45b7a61139ea..8484cfe4c956 100644 --- a/include/clang/StaticAnalyzer/Core/Checker.h +++ b/include/clang/StaticAnalyzer/Core/Checker.h @@ -63,7 +63,7 @@ public:  class EndOfTranslationUnit {    template <typename CHECKER>    static void _checkEndOfTranslationUnit(void *checker, -                                         const TranslationUnitDecl *TU,  +                                         const TranslationUnitDecl *TU,                                           AnalysisManager& mgr,                                           BugReporter &BR) {      ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR); @@ -331,7 +331,7 @@ public:  class RegionChanges {    template <typename CHECKER> -  static ProgramStateRef  +  static ProgramStateRef    _checkRegionChanges(void *checker,                        ProgramStateRef state,                        const InvalidatedSymbols *invalidated, @@ -370,7 +370,7 @@ class PointerEscape {                                                              Kind);      InvalidatedSymbols RegularEscape; -    for (InvalidatedSymbols::const_iterator I = Escaped.begin(),  +    for (InvalidatedSymbols::const_iterator I = Escaped.begin(),                                              E = Escaped.end(); I != E; ++I)        if (!ETraits->hasTrait(*I,                RegionAndSymbolInvalidationTraits::TK_PreserveContents) && @@ -410,7 +410,7 @@ class ConstPointerEscape {        return State;      InvalidatedSymbols ConstEscape; -    for (InvalidatedSymbols::const_iterator I = Escaped.begin(),  +    for (InvalidatedSymbols::const_iterator I = Escaped.begin(),                                              E = Escaped.end(); I != E; ++I)        if (ETraits->hasTrait(*I,                RegionAndSymbolInvalidationTraits::TK_PreserveContents) && @@ -436,7 +436,7 @@ public:    }  }; -   +  template <typename EVENT>  class Event {    template <typename CHECKER> @@ -504,7 +504,7 @@ public:  /// Dump checker name to stream.  raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker); -/// Tag that can use a checker name as a message provider  +/// Tag that can use a checker name as a message provider  /// (see SimpleProgramPointTag).  class CheckerProgramPointTag : public SimpleProgramPointTag {  public: diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index 33a794061a38..7c353326be46 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -86,7 +86,7 @@ enum PointerEscapeKind {    /// argument to a function.    PSK_IndirectEscapeOnCall, -  /// The reason for pointer escape is unknown. For example,  +  /// The reason for pointer escape is unknown. For example,    /// a region containing this pointer is invalidated.    PSK_EscapeOther  }; @@ -353,18 +353,18 @@ public:    ///    /// This notifies the checkers about pointer escape, which occurs whenever    /// the analyzer cannot track the symbol any more. For example, as a -  /// result of assigning a pointer into a global or when it's passed to a  +  /// result of assigning a pointer into a global or when it's passed to a    /// function call the analyzer cannot model. -  ///  +  ///    /// \param State The state at the point of escape.    /// \param Escaped The list of escaped symbols. -  /// \param Call The corresponding CallEvent, if the symbols escape as  +  /// \param Call The corresponding CallEvent, if the symbols escape as    ///        parameters to the given call.    /// \param Kind The reason of pointer escape. -  /// \param ITraits Information about invalidation for a particular  +  /// \param ITraits Information about invalidation for a particular    ///        region/symbol.    /// \returns Checkers can modify the state by returning a new one. -  ProgramStateRef  +  ProgramStateRef    runCheckersForPointerEscape(ProgramStateRef State,                                const InvalidatedSymbols &Escaped,                                const CallEvent *Call, @@ -381,7 +381,7 @@ public:    void runCheckersForEvalCall(ExplodedNodeSet &Dst,                                const ExplodedNodeSet &Src,                                const CallEvent &CE, ExprEngine &Eng); -   +    /// Run checkers for the entire Translation Unit.    void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,                                           AnalysisManager &mgr, @@ -419,21 +419,21 @@ public:  //===----------------------------------------------------------------------===//    using CheckStmtFunc = CheckerFn<void (const Stmt *, CheckerContext &)>; -   +    using CheckObjCMessageFunc =        CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>;    using CheckCallFunc =        CheckerFn<void (const CallEvent &, CheckerContext &)>; -   +    using CheckLocationFunc =        CheckerFn<void (const SVal &location, bool isLoad, const Stmt *S,                        CheckerContext &)>; -   +    using CheckBindFunc =        CheckerFn<void (const SVal &location, const SVal &val, const Stmt *S,                        CheckerContext &)>; -   +    using CheckEndAnalysisFunc =        CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>; @@ -441,18 +441,18 @@ public:    using CheckEndFunctionFunc =        CheckerFn<void (const ReturnStmt *, CheckerContext &)>; -   +    using CheckBranchConditionFunc =        CheckerFn<void (const Stmt *, CheckerContext &)>;    using CheckNewAllocatorFunc =        CheckerFn<void (const CXXNewExpr *, SVal, CheckerContext &)>; -   +    using CheckDeadSymbolsFunc =        CheckerFn<void (SymbolReaper &, CheckerContext &)>; -   +    using CheckLiveSymbolsFunc = CheckerFn<void (ProgramStateRef,SymbolReaper &)>; -   +    using CheckRegionChangesFunc =        CheckerFn<ProgramStateRef (ProgramStateRef,                                   const InvalidatedSymbols *symbols, @@ -460,17 +460,17 @@ public:                                   ArrayRef<const MemRegion *> Regions,                                   const LocationContext *LCtx,                                   const CallEvent *Call)>; -   +    using CheckPointerEscapeFunc =        CheckerFn<ProgramStateRef (ProgramStateRef,                                   const InvalidatedSymbols &Escaped,                                   const CallEvent *Call, PointerEscapeKind Kind,                                   RegionAndSymbolInvalidationTraits *ITraits)>; -   +    using EvalAssumeFunc =        CheckerFn<ProgramStateRef (ProgramStateRef, const SVal &cond,                                   bool assumption)>; -   +    using EvalCallFunc = CheckerFn<bool (const CallExpr *, CheckerContext &)>;    using CheckEndOfTranslationUnit = @@ -531,7 +531,7 @@ public:    template <typename EVENT>    void _registerListenerForEvent(CheckEventFunc checkfn) {      EventInfo &info = Events[getTag<EVENT>()]; -    info.Checkers.push_back(checkfn);     +    info.Checkers.push_back(checkfn);    }    template <typename EVENT> @@ -636,7 +636,7 @@ private:      EventInfo() = default;    }; -   +    using EventsTy = llvm::DenseMap<EventTag, EventInfo>;    EventsTy Events;  }; diff --git a/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h b/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h index e981871ae4e0..2d13bf34cd15 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h +++ b/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h @@ -28,7 +28,7 @@ class CheckerOptInfo {  public:    CheckerOptInfo(StringRef name, bool enable)      : Name(name), Enable(enable), Claimed(false) { } -   +    StringRef getName() const { return Name; }    bool isEnabled() const { return Enable; }    bool isDisabled() const { return !isEnabled(); } diff --git a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h index 912a601b61c4..d580dda73488 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h +++ b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h @@ -47,7 +47,7 @@  // The clang_registerCheckers function may add any number of checkers to the  // registry. If any checkers require additional initialization, use the three-  // argument form of CheckerRegistry::addChecker. -//  +//  // To load a checker plugin, specify the full path to the dynamic library as  // the argument to the -load option in the cc1 frontend. You can then enable  // your custom checker using the -analyzer-checker: diff --git a/include/clang/StaticAnalyzer/Core/IssueHash.h b/include/clang/StaticAnalyzer/Core/IssueHash.h index 8cb6631fae74..03997aae79ae 100644 --- a/include/clang/StaticAnalyzer/Core/IssueHash.h +++ b/include/clang/StaticAnalyzer/Core/IssueHash.h @@ -29,7 +29,7 @@ class LangOptions;  /// location. The bugtype and the name of the checker is also part of the hash.  /// The last component is the string representation of the enclosing declaration  /// of the associated location. -///  +///  /// In case a new hash is introduced, the old one should still be maintained for  /// a while. One should not introduce a new hash for every change, it is  /// possible to introduce experimental hashes that may change in the future. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h index 93edfcef2d5a..243795e720f6 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h @@ -88,7 +88,7 @@ public:    ///                       for 'unsigned char' (u8).    RangeTestResultKind testInRange(const llvm::APSInt &Val,                                    bool AllowMixedSign) const LLVM_READONLY; -   +    bool operator==(const APSIntType &Other) const {      return BitWidth == Other.BitWidth && IsUnsigned == Other.IsUnsigned;    } @@ -102,7 +102,7 @@ public:             std::tie(Other.BitWidth, Other.IsUnsigned);    }  }; -     +  } // end ento namespace  } // end clang namespace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index 02b335761e70..85369509efcd 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -45,12 +45,12 @@ class AnalysisManager : public BugReporterData {  public:    AnalyzerOptions &options; -   +    AnalysisManager(ASTContext &ctx,DiagnosticsEngine &diags,                    const LangOptions &lang,                    const PathDiagnosticConsumers &Consumers,                    StoreManagerCreator storemgr, -                  ConstraintManagerCreator constraintmgr,  +                  ConstraintManagerCreator constraintmgr,                    CheckerManager *checkerMgr,                    AnalyzerOptions &Options,                    CodeInjector* injector = nullptr); @@ -60,7 +60,7 @@ public:    void ClearContexts() {      AnaCtxMgr.clear();    } -   +    AnalysisDeclContextManager& getAnalysisDeclContextManager() {      return AnaCtxMgr;    } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index 0bbc6500d6ec..b72b158194c7 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -155,12 +155,12 @@ public:      return getValue(TargetType.convert(From));    } -   +    const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) {      APSIntType TargetType = getAPSIntType(T);      if (TargetType == APSIntType(From))        return From; -     +      return getValue(TargetType.convert(From));    } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h index b94dadff2342..5e831095abc7 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h @@ -35,7 +35,7 @@ class BlockCounter {  public:    BlockCounter() : Data(nullptr) {} -  unsigned getNumVisited(const StackFrameContext *CallSite,  +  unsigned getNumVisited(const StackFrameContext *CallSite,                           unsigned BlockID) const;    class Factory { @@ -45,7 +45,7 @@ public:      ~Factory();      BlockCounter GetEmptyCounter(); -    BlockCounter IncrementCount(BlockCounter BC,  +    BlockCounter IncrementCount(BlockCounter BC,                                    const StackFrameContext *CallSite,                                    unsigned BlockID);    }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index 9c667f912e9f..9078fb94d282 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -29,6 +29,7 @@  #include "clang/Basic/LLVM.h"  #include "clang/Basic/SourceLocation.h"  #include "clang/Basic/SourceManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"  #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"  #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"  #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" @@ -117,12 +118,12 @@ public:    }  }; -/// \class RuntimeDefinition  +/// \class RuntimeDefinition  /// Defines the runtime definition of the called function. -///  -/// Encapsulates the information we have about which Decl will be used  +/// +/// Encapsulates the information we have about which Decl will be used  /// when the call is executed on the given path. When dealing with dynamic -/// dispatch, the information is based on DynamicTypeInfo and might not be  +/// dispatch, the information is based on DynamicTypeInfo and might not be  /// precise.  class RuntimeDefinition {    /// The Declaration of the function which could be called at runtime. @@ -141,13 +142,13 @@ public:    RuntimeDefinition(const Decl *InD, const MemRegion *InR): D(InD), R(InR) {}    const Decl *getDecl() { return D; } -     -  /// Check if the definition we have is precise.  -  /// If not, it is possible that the call dispatches to another definition at  + +  /// Check if the definition we have is precise. +  /// If not, it is possible that the call dispatches to another definition at    /// execution time.    bool mayHaveOtherDefinitions() { return R != nullptr; } -   -  /// When other definitions are possible, returns the region whose runtime type  + +  /// When other definitions are possible, returns the region whose runtime type    /// determines the method definition.    const MemRegion *getDispatchRegion() { return R; }  }; @@ -404,6 +405,46 @@ public:    /// \p D must not be null.    static bool isVariadic(const Decl *D); +  /// Returns AnalysisDeclContext for the callee stack frame. +  /// Currently may fail; returns null on failure. +  AnalysisDeclContext *getCalleeAnalysisDeclContext() const; + +  /// Returns the callee stack frame. That stack frame will only be entered +  /// during analysis if the call is inlined, but it may still be useful +  /// in intermediate calculations even if the call isn't inlined. +  /// May fail; returns null on failure. +  const StackFrameContext *getCalleeStackFrame() const; + +  /// Returns memory location for a parameter variable within the callee stack +  /// frame. May fail; returns null on failure. +  const VarRegion *getParameterLocation(unsigned Index) const; + +  /// Returns true if on the current path, the argument was constructed by +  /// calling a C++ constructor over it. This is an internal detail of the +  /// analysis which doesn't necessarily represent the program semantics: +  /// if we are supposed to construct an argument directly, we may still +  /// not do that because we don't know how (i.e., construction context is +  /// unavailable in the CFG or not supported by the analyzer). +  bool isArgumentConstructedDirectly(unsigned Index) const { +    // This assumes that the object was not yet removed from the state. +    return ExprEngine::getObjectUnderConstruction( +        getState(), {getOriginExpr(), Index}, getCalleeStackFrame()).hasValue(); +  } + +  /// Some calls have parameter numbering mismatched from argument numbering. +  /// This function converts an argument index to the corresponding +  /// parameter index. Returns None is the argument doesn't correspond +  /// to any parameter variable. +  Optional<unsigned> getAdjustedParameterIndex(unsigned ArgumentIndex) const { +    if (dyn_cast_or_null<CXXOperatorCallExpr>(getOriginExpr()) && +        dyn_cast_or_null<CXXMethodDecl>(getDecl())) { +      // For member operator calls argument 0 on the expression corresponds +      // to implicit this-parameter on the declaration. +      return (ArgumentIndex > 0) ? Optional<unsigned>(ArgumentIndex - 1) : None; +    } +    return ArgumentIndex; +  } +    // Iterator access to formal parameters and their types.  private:    struct GetTypeFn { @@ -628,7 +669,7 @@ protected:        : AnyFunctionCall(D, St, LCtx) {}    CXXInstanceCall(const CXXInstanceCall &Other) = default; -  void getExtraInvalidatedValues(ValueList &Values,  +  void getExtraInvalidatedValues(ValueList &Values,           RegionAndSymbolInvalidationTraits *ETraits) const override;  public: diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index f3a0ca7b6608..ce2b711a4a1b 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -51,7 +51,7 @@ namespace ento {    /// be accessible from more than one translation unit.    #define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem) \      REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableSet<Elem>) -   +    /// Declares an immutable list of type \p NameTy, suitable for placement into    /// the ProgramState. This is implementing using llvm::ImmutableList.    /// @@ -83,7 +83,7 @@ public:    /// If we are post visiting a call, this flag will be set if the    /// call was inlined.  In all other cases it will be false.    const bool wasInlined; -   +    CheckerContext(NodeBuilder &builder,                   ExprEngine &eng,                   ExplodedNode *pred, @@ -110,7 +110,7 @@ public:    StoreManager &getStoreManager() {      return Eng.getStoreManager();    } -   +    /// Returns the previous node in the exploded graph, which includes    /// the state of the program before the checker ran. Note, checkers should    /// not retain the node in their state since the nodes might get invalidated. @@ -149,7 +149,7 @@ public:    BugReporter &getBugReporter() {      return Eng.getBugReporter();    } -   +    SourceManager &getSourceManager() {      return getBugReporter().getSourceManager();    } @@ -308,7 +308,7 @@ public:    static bool isCLibraryFunction(const FunctionDecl *FD,                                   StringRef Name = StringRef()); -  /// Depending on wither the location corresponds to a macro, return  +  /// Depending on wither the location corresponds to a macro, return    /// either the macro name or the token spelling.    ///    /// This could be useful when checkers' logic depends on whether a function diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 5755818cd971..17369a85bfa3 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -64,7 +64,7 @@ class CoreEngine {  public:    using BlocksExhausted =        std::vector<std::pair<BlockEdge, const ExplodedNode *>>; -   +    using BlocksAborted =        std::vector<std::pair<const CFGBlock *, const ExplodedNode *>>; @@ -87,7 +87,7 @@ private:    /// The locations where we stopped doing work because we visited a location    ///  too many times.    BlocksExhausted blocksExhausted; -   +    /// The locations where we stopped because the engine aborted analysis,    /// usually because it could not reason about something.    BlocksAborted blocksAborted; @@ -141,7 +141,7 @@ public:    /// Returns true if there is still simulation state on the worklist.    bool ExecuteWorkListWithInitialState(const LocationContext *L,                                         unsigned Steps, -                                       ProgramStateRef InitState,  +                                       ProgramStateRef InitState,                                         ExplodedNodeSet &Dst);    /// Dispatch the work list item based on the given location information. @@ -152,8 +152,8 @@ public:    // Functions for external checking of whether we have unfinished work    bool wasBlockAborted() const { return !blocksAborted.empty(); }    bool wasBlocksExhausted() const { return !blocksExhausted.empty(); } -  bool hasWorkRemaining() const { return wasBlocksExhausted() ||  -                                         WList->hasWork() ||  +  bool hasWorkRemaining() const { return wasBlocksExhausted() || +                                         WList->hasWork() ||                                           wasBlockAborted(); }    /// Inform the CoreEngine that a basic block was aborted because @@ -161,7 +161,7 @@ public:    void addAbortedBlock(const ExplodedNode *node, const CFGBlock *block) {      blocksAborted.push_back(std::make_pair(block, node));    } -   +    WorkList *getWorkList() const { return WList.get(); }    BlocksExhausted::const_iterator blocks_exhausted_begin() const { @@ -255,7 +255,7 @@ protected:    /// Allow subclasses to finalize results before result_begin() is executed.    virtual void finalizeResults() {} -   +    ExplodedNode *generateNodeImpl(const ProgramPoint &PP,                                   ProgramStateRef State,                                   ExplodedNode *Pred, @@ -474,7 +474,7 @@ class IndirectGotoNodeBuilder {    ExplodedNode *Pred;  public: -  IndirectGotoNodeBuilder(ExplodedNode *pred, const CFGBlock *src,  +  IndirectGotoNodeBuilder(ExplodedNode *pred, const CFGBlock *src,                      const Expr *e, const CFGBlock *dispatch, CoreEngine* eng)        : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {} @@ -508,7 +508,7 @@ public:    const Expr *getTarget() const { return E; }    ProgramStateRef getState() const { return Pred->State; } -   +    const LocationContext *getLocationContext() const {      return Pred->getLocationContext();    } @@ -562,7 +562,7 @@ public:    const Expr *getCondition() const { return Condition; }    ProgramStateRef getState() const { return Pred->State; } -   +    const LocationContext *getLocationContext() const {      return Pred->getLocationContext();    } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h index d49aa81bc958..77e35398077c 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h @@ -40,14 +40,14 @@ public:    const Stmt *getStmt() const { return first; }    const LocationContext *getLocationContext() const { return second; } -   +    /// Profile an EnvironmentEntry for inclusion in a FoldingSet.    static void Profile(llvm::FoldingSetNodeID &ID,                        const EnvironmentEntry &E) {      ID.AddPointer(E.getStmt());      ID.AddPointer(E.getLocationContext());    } -   +    void Profile(llvm::FoldingSetNodeID &ID) const {      Profile(ID, *this);    } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index c12198db6598..4e0c02e6d65b 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -87,7 +87,7 @@ class ExplodedNode : public llvm::FoldingSetNode {      // for the nodes in the group.      // This is not a PointerIntPair in order to keep the storage type opaque.      uintptr_t P; -     +    public:      NodeGroup(bool Flag = false) : P(Flag) {        assert(getFlag() == Flag); @@ -251,7 +251,7 @@ public:    };    static void SetAuditor(Auditor* A); -   +  private:    void replaceSuccessor(ExplodedNode *node) { Succs.replaceNode(node); }    void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); } @@ -286,18 +286,18 @@ protected:    /// NumNodes - The number of nodes in the graph.    unsigned NumNodes = 0; -   +    /// A list of recently allocated nodes that can potentially be recycled.    NodeVector ChangedNodes; -   +    /// A list of nodes that can be reused.    NodeVector FreeNodes; -   +    /// Determines how often nodes are reclaimed.    ///    /// If this is 0, nodes will never be reclaimed.    unsigned ReclaimNodeInterval = 0; -   +    /// Counter to determine when to reclaim nodes.    unsigned ReclaimCounter; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 25849e94c8ff..06a90fa847a6 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -69,7 +69,7 @@ namespace cross_tu {  class CrossTranslationUnitContext;  } // namespace cross_tu -   +  namespace ento {  class BasicValueFactory; @@ -117,7 +117,7 @@ private:    cross_tu::CrossTranslationUnitContext &CTU;    AnalysisManager &AMgr; -   +    AnalysisDeclContextManager &AnalysisDeclContexts;    CoreEngine Engine; @@ -136,11 +136,11 @@ private:    unsigned int currStmtIdx = 0;    const NodeBuilderContext *currBldrCtx = nullptr; -   +    /// Helper object to determine if an Objective-C message expression    /// implicitly never returns.    ObjCNoReturn ObjCNoRet; -   +    /// Whether or not GC is enabled in this analysis.    bool ObjCGCEnabled; @@ -173,7 +173,7 @@ public:    /// state of the function call. Returns true if there is still simulation    /// state on the worklist.    bool ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, -                                       ProgramStateRef InitState,  +                                       ProgramStateRef InitState,                                         ExplodedNodeSet &Dst) {      return Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);    } @@ -276,17 +276,17 @@ public:                         ExplodedNode *Pred, ExplodedNodeSet &Dst);    void ProcessMemberDtor(const CFGMemberDtor D,                           ExplodedNode *Pred, ExplodedNodeSet &Dst); -  void ProcessTemporaryDtor(const CFGTemporaryDtor D,  +  void ProcessTemporaryDtor(const CFGTemporaryDtor D,                              ExplodedNode *Pred, ExplodedNodeSet &Dst);    /// Called by CoreEngine when processing the entrance of a CFGBlock.    void processCFGBlockEntrance(const BlockEdge &L,                                 NodeBuilderWithSinks &nodeBuilder,                                 ExplodedNode *Pred) override; -  +    /// ProcessBranch - Called by CoreEngine.  Used to generate successor    ///  nodes by processing the 'effects' of a branch condition. -  void processBranch(const Stmt *Condition, const Stmt *Term,  +  void processBranch(const Stmt *Condition, const Stmt *Term,                       NodeBuilderContext& BuilderCtx,                       ExplodedNode *Pred,                       ExplodedNodeSet &Dst, @@ -354,7 +354,7 @@ public:    /// processRegionChanges - Called by ProgramStateManager whenever a change is made    ///  to the store. Used to update checkers that track region values. -  ProgramStateRef  +  ProgramStateRef    processRegionChanges(ProgramStateRef state,                         const InvalidatedSymbols *invalidated,                         ArrayRef<const MemRegion *> ExplicitRegions, @@ -410,15 +410,15 @@ public:                        ExplodedNodeSet &Dst);    /// VisitBlockExpr - Transfer function logic for BlockExprs. -  void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,  +  void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,                        ExplodedNodeSet &Dst);    /// VisitLambdaExpr - Transfer function logic for LambdaExprs. -  void VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,  +  void VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,                         ExplodedNodeSet &Dst);    /// VisitBinaryOperator - Transfer function logic for binary operators. -  void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode *Pred,  +  void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode *Pred,                             ExplodedNodeSet &Dst); @@ -431,21 +431,21 @@ public:                   ExplodedNodeSet &Dst);    /// VisitCompoundLiteralExpr - Transfer function logic for compound literals. -  void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,  +  void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,                                  ExplodedNode *Pred, ExplodedNodeSet &Dst);    /// Transfer function logic for DeclRefExprs and BlockDeclRefExprs.    void VisitCommonDeclRefExpr(const Expr *DR, const NamedDecl *D,                                ExplodedNode *Pred, ExplodedNodeSet &Dst); -   +    /// VisitDeclStmt - Transfer function logic for DeclStmts. -  void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,  +  void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,                       ExplodedNodeSet &Dst);    /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose -  void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R,  +  void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R,                          ExplodedNode *Pred, ExplodedNodeSet &Dst); -   +    void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred,                           ExplodedNodeSet &Dst); @@ -454,7 +454,7 @@ public:                          ExplodedNodeSet &Dst);    /// VisitMemberExpr - Transfer function for member expressions. -  void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,  +  void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,                         ExplodedNodeSet &Dst);    /// VisitAtomicExpr - Transfer function for builtin atomic expressions @@ -471,16 +471,16 @@ public:    /// VisitObjCForCollectionStmt - Transfer function logic for    ///  ObjCForCollectionStmt. -  void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,  +  void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,                                    ExplodedNode *Pred, ExplodedNodeSet &Dst);    void VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred,                          ExplodedNodeSet &Dst);    /// VisitReturnStmt - Transfer function logic for return statements. -  void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred,  +  void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred,                         ExplodedNodeSet &Dst); -   +    /// VisitOffsetOfExpr - Transfer function for offsetof.    void VisitOffsetOfExpr(const OffsetOfExpr *Ex, ExplodedNode *Pred,                           ExplodedNodeSet &Dst); @@ -490,7 +490,7 @@ public:                                       ExplodedNode *Pred, ExplodedNodeSet &Dst);    /// VisitUnaryOperator - Transfer function logic for unary operators. -  void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred,  +  void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred,                            ExplodedNodeSet &Dst);    /// Handle ++ and -- (both pre- and post-increment). @@ -505,7 +505,7 @@ public:    void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred,                           ExplodedNodeSet &Dst); -  void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,  +  void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,                          ExplodedNodeSet & Dst);    void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred, @@ -528,15 +528,15 @@ public:    /// Create a C++ temporary object for an rvalue.    void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, -                                ExplodedNode *Pred,  +                                ExplodedNode *Pred,                                  ExplodedNodeSet &Dst); -   +    /// evalEagerlyAssumeBinOpBifurcation - Given the nodes in 'Src', eagerly assume symbolic    ///  expressions of the form 'x != 0' and generate new nodes (stored in Dst)    ///  with those assumptions. -  void evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,  +  void evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,                           const Expr *Ex); -   +    static std::pair<const ProgramPointTag *, const ProgramPointTag *>      geteagerlyAssumeBinOpBifurcationTags(); @@ -580,7 +580,15 @@ public:                   SVal LHS, SVal RHS, QualType T) {      return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T);    } -   + +  /// By looking at a certain item that may be potentially part of an object's +  /// ConstructionContext, retrieve such object's location. A particular +  /// statement can be transparently passed as \p Item in most cases. +  static Optional<SVal> +  getObjectUnderConstruction(ProgramStateRef State, +                             const ConstructionContextItem &Item, +                             const LocationContext *LC); +  protected:    /// evalBind - Handle the semantics of binding a value to a specific location.    ///  This method is used by evalStore, VisitDeclStmt, and others. @@ -761,24 +769,17 @@ private:    /// This allows, among other things, to keep bindings to variable's fields    /// made within the constructor alive until its declaration actually    /// goes into scope. -  static ProgramStateRef addObjectUnderConstruction( -      ProgramStateRef State, -      llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P, -      const LocationContext *LC, SVal V); +  static ProgramStateRef +  addObjectUnderConstruction(ProgramStateRef State, +                             const ConstructionContextItem &Item, +                             const LocationContext *LC, SVal V);    /// Mark the object sa fully constructed, cleaning up the state trait    /// that tracks objects under construction. -  static ProgramStateRef finishObjectConstruction( -      ProgramStateRef State, -      llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P, -      const LocationContext *LC); - -  /// If the given statement corresponds to an object under construction, -  /// being part of its construciton context, retrieve that object's location. -  static Optional<SVal> getObjectUnderConstruction( -      ProgramStateRef State, -      llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P, -      const LocationContext *LC); +  static ProgramStateRef +  finishObjectConstruction(ProgramStateRef State, +                           const ConstructionContextItem &Item, +                           const LocationContext *LC);    /// If the given expression corresponds to a temporary that was used for    /// passing into an elidable copy/move constructor and that constructor diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index f3846eba6b96..3a93aae5a9bc 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -131,9 +131,9 @@ public:    bool hasGlobalsOrParametersStorage() const;    bool hasStackStorage() const; -   +    bool hasStackNonParametersStorage() const; -   +    bool hasStackParametersStorage() const;    /// Compute the offset within the top level memory object. @@ -253,7 +253,7 @@ class StaticGlobalSpaceRegion : public GlobalsSpaceRegion {    friend class MemRegionManager;    const CodeTextRegion *CR; -   +    StaticGlobalSpaceRegion(MemRegionManager *mgr, const CodeTextRegion *cr)        : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {      assert(cr); @@ -348,7 +348,7 @@ public:  class HeapSpaceRegion : public MemSpaceRegion {    friend class MemRegionManager; -   +    HeapSpaceRegion(MemRegionManager *mgr)        : MemSpaceRegion(mgr, HeapSpaceRegionKind) {} @@ -359,7 +359,7 @@ public:      return R->getKind() == HeapSpaceRegionKind;    }  }; -   +  class UnknownSpaceRegion : public MemSpaceRegion {    friend class MemRegionManager; @@ -613,7 +613,7 @@ public:      return R->getKind() == FunctionCodeRegionKind;    }  }; -   +  /// BlockCodeRegion - A region that represents code texts of blocks (closures).  ///  Blocks are represented with two kinds of regions.  BlockCodeRegions  ///  represent the "code", while BlockDataRegions represent instances of blocks, @@ -643,7 +643,7 @@ public:    QualType getLocationType() const override {      return locTy;    } -   +    const BlockDecl *getDecl() const {      return BD;    } @@ -658,7 +658,7 @@ public:      return R->getKind() == BlockCodeRegionKind;    }  }; -   +  /// BlockDataRegion - A region that represents a block instance.  ///  Blocks are represented with two kinds of regions.  BlockCodeRegions  ///  represent the "code", while BlockDataRegions represent instances of blocks, @@ -733,9 +733,9 @@ public:    /// Return the original region for a captured region, if    /// one exists.    const VarRegion *getOriginalRegion(const VarRegion *VR) const; -       +    referenced_vars_iterator referenced_vars_begin() const; -  referenced_vars_iterator referenced_vars_end() const;   +  referenced_vars_iterator referenced_vars_end() const;    void dumpToStream(raw_ostream &os) const override; @@ -824,7 +824,7 @@ public:      return R->getKind() == StringRegionKind;    }  }; -   +  /// The region associated with an ObjCStringLiteral.  class ObjCStringRegion : public TypedValueRegion {    friend class MemRegionManager; @@ -840,7 +840,7 @@ class ObjCStringRegion : public TypedValueRegion {    static void ProfileRegion(llvm::FoldingSetNodeID &ID,                              const ObjCStringLiteral *Str,                              const MemRegion *superRegion); -   +  public:    const ObjCStringLiteral *getObjCStringLiteral() const { return Str; } @@ -897,9 +897,9 @@ public:  class DeclRegion : public TypedValueRegion {  protected: -  const Decl *D; +  const ValueDecl *D; -  DeclRegion(const Decl *d, const MemRegion *sReg, Kind k) +  DeclRegion(const ValueDecl *d, const MemRegion *sReg, Kind k)        : TypedValueRegion(sReg, k), D(d) {      assert(classof(this));      assert(d); @@ -909,7 +909,7 @@ protected:                        const MemRegion* superRegion, Kind k);  public: -  const Decl *getDecl() const { return D; } +  const ValueDecl *getDecl() const { return D; }    void Profile(llvm::FoldingSetNodeID& ID) const override;    static bool classof(const MemRegion* R) { @@ -959,7 +959,7 @@ public:      return R->getKind() == VarRegionKind;    }  }; -   +  /// CXXThisRegion - Represents the region for the implicit 'this' parameter  ///  in a call to a C++ method.  This region doesn't represent the object  ///  referred to by 'this', but rather 'this' itself. @@ -1141,7 +1141,7 @@ public:    }  }; -// CXXBaseObjectRegion represents a base object within a C++ object. It is  +// CXXBaseObjectRegion represents a base object within a C++ object. It is  // identified by the base class declaration and the region of its parent object.  class CXXBaseObjectRegion : public TypedValueRegion {    friend class MemRegionManager; @@ -1197,7 +1197,7 @@ class MemRegionManager {    GlobalSystemSpaceRegion *SystemGlobals = nullptr;    GlobalImmutableSpaceRegion *ImmutableGlobals = nullptr; -  llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *>  +  llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *>      StackLocalsSpaceRegions;    llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *>      StackArgumentsSpaceRegions; @@ -1213,7 +1213,7 @@ public:    ~MemRegionManager();    ASTContext &getContext() { return C; } -   +    llvm::BumpPtrAllocator &getAllocator() { return A; }    /// getStackLocalsRegion - Retrieve the memory region associated with the @@ -1251,7 +1251,7 @@ public:    const CompoundLiteralRegion*    getCompoundLiteralRegion(const CompoundLiteralExpr *CL,                             const LocationContext *LC); -   +    /// getCXXThisRegion - Retrieve the [artificial] region associated with the    ///  parameter 'this'.    const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy, @@ -1320,7 +1320,7 @@ public:    /// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different    /// super region.    const CXXBaseObjectRegion * -  getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg,  +  getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg,                                    const SubRegion *superRegion) {      return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion,                                    baseReg->isVirtual()); @@ -1330,7 +1330,7 @@ public:    const BlockCodeRegion *getBlockCodeRegion(const BlockDecl *BD,                                              CanQualType locTy,                                              AnalysisDeclContext *AC); -   +    /// getBlockDataRegion - Get the memory region associated with an instance    ///  of a block.  Unlike many other MemRegions, the LocationContext*    ///  argument is allowed to be NULL for cases where we have no known @@ -1363,7 +1363,7 @@ private:    template <typename REG>    const REG* LazyAllocate(REG*& region); -   +    template <typename REG, typename ARG>    const REG* LazyAllocate(REG*& region, ARG a);  }; @@ -1408,7 +1408,7 @@ public:      /// should be invalidated.      TK_EntireMemSpace = 0x8 -    // Do not forget to extend StorageTypeForKinds if number of traits exceed  +    // Do not forget to extend StorageTypeForKinds if number of traits exceed      // the number of bits StorageTypeForKinds can store.    }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 17ab7379fdba..b86301a03470 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -36,6 +36,7 @@ class ASTContext;  namespace ento { +class AnalysisManager;  class CallEvent;  class CallEventManager; @@ -111,6 +112,8 @@ public:      return *stateMgr;    } +  AnalysisManager &getAnalysisManager() const; +    /// Return the ConstraintManager.    ConstraintManager &getConstraintManager() const; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index 31300d69f2ff..865014b22830 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -55,7 +55,7 @@ class SValBuilder {  protected:    ASTContext &Context; -   +    /// Manager of APSInt values.    BasicValueFactory BasicVals; @@ -69,7 +69,7 @@ protected:    /// The scalar type to use for array indices.    const QualType ArrayIndexTy; -   +    /// The width of the scalar type used for array indices.    const unsigned ArrayIndexWidth; @@ -137,7 +137,7 @@ public:    /// that represents the same value, but is hopefully easier to work with    /// than the original SVal.    virtual SVal simplifySVal(ProgramStateRef State, SVal Val) = 0; -   +    /// Constructs a symbolic expression for two non-location values.    SVal makeSymExprValNN(ProgramStateRef state, BinaryOperator::Opcode op,                        NonLoc lhs, NonLoc rhs, QualType resultTy); @@ -157,11 +157,11 @@ public:    const ASTContext &getContext() const { return Context; }    ProgramStateManager &getStateManager() { return StateMgr; } -   +    QualType getConditionType() const {      return Context.getLangOpts().CPlusPlus ? Context.BoolTy : Context.IntTy;    } -   +    QualType getArrayIndexType() const {      return ArrayIndexTy;    } @@ -237,7 +237,7 @@ public:    DefinedSVal getMemberPointer(const DeclaratorDecl *DD);    DefinedSVal getFunctionPointer(const FunctionDecl *func); -   +    DefinedSVal getBlockPointer(const BlockDecl *block, CanQualType locTy,                                const LocationContext *locContext,                                unsigned blockCount); @@ -252,7 +252,7 @@ public:      return nonloc::CompoundVal(BasicVals.getCompoundValData(type, vals));    } -  NonLoc makeLazyCompoundVal(const StoreRef &store,  +  NonLoc makeLazyCompoundVal(const StoreRef &store,                               const TypedValueRegion *region) {      return nonloc::LazyCompoundVal(          BasicVals.getLazyCompoundValData(store, region)); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 0fde63e9eb09..1b79bfc3f8cf 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -202,7 +202,7 @@ public:        return SymExpr::symbol_iterator();    } -  SymExpr::symbol_iterator symbol_end() const {  +  SymExpr::symbol_iterator symbol_end() const {      return SymExpr::symbol_end();    }  }; @@ -230,13 +230,13 @@ public:    // tautologically false.    bool isUndef() const = delete;    bool isValid() const = delete; -   +  protected:    DefinedOrUnknownSVal() = default;    explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)        : SVal(d, isLoc, ValKind) {}    explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr) : SVal(k, D) {} -   +  private:    friend class SVal; @@ -244,11 +244,11 @@ private:      return !V.isUndef();    }  }; -   +  class UnknownVal : public DefinedOrUnknownSVal {  public:    explicit UnknownVal() : DefinedOrUnknownSVal(UnknownValKind) {} -   +  private:    friend class SVal; @@ -325,7 +325,7 @@ public:    void dumpToStream(raw_ostream &Out) const;    static bool isLocType(QualType T) { -    return T->isAnyPointerType() || T->isBlockPointerType() ||  +    return T->isAnyPointerType() || T->isBlockPointerType() ||             T->isReferenceType() || T->isNullPtrType();    } @@ -664,7 +664,7 @@ private:    }  }; -} // namespace loc  +} // namespace loc  } // namespace ento diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index dc0644df8aab..fc072a380074 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -149,7 +149,7 @@ public:    // FIXME: This should soon be eliminated altogether; clients should deal with    // region extents directly. -  virtual DefinedOrUnknownSVal getSizeInElements(ProgramStateRef state,  +  virtual DefinedOrUnknownSVal getSizeInElements(ProgramStateRef state,                                                   const MemRegion *region,                                                   QualType EleTy) {      return UnknownVal(); @@ -176,8 +176,8 @@ public:    ///  - Successful cast (ex: derived is subclass of base).    ///  - Failed cast (ex: derived is definitely not a subclass of base).    ///    The distinction of this case from the next one is necessary to model -  ///    dynamic_cast.  -  ///  - We don't know (base is a symbolic region and we don't have  +  ///    dynamic_cast. +  ///  - We don't know (base is a symbolic region and we don't have    ///    enough info to determine if the cast will succeed at run time).    /// The function returns an SVal representing the derived class; it's    /// valid only if Failed flag is set to false. @@ -195,7 +195,7 @@ public:    virtual bool includedInBindings(Store store,                                    const MemRegion *region) const = 0; -   +    /// If the StoreManager supports it, increment the reference count of    /// the specified Store object.    virtual void incrementReferenceCount(Store store) {} @@ -221,7 +221,7 @@ public:    ///   globals should get invalidated.    /// \param[in,out] IS A set to fill with any symbols that are no longer    ///   accessible. Pass \c NULL if this information will not be used. -  /// \param[in] ITraits Information about invalidation for a particular  +  /// \param[in] ITraits Information about invalidation for a particular    ///   region/symbol.    /// \param[in,out] InvalidatedTopLevel A vector to fill with regions    ////  explicitly being invalidated. Pass \c NULL if this @@ -305,16 +305,16 @@ inline StoreRef::StoreRef(Store store, StoreManager & smgr)  inline StoreRef::StoreRef(const StoreRef &sr)      : store(sr.store), mgr(sr.mgr) -{  +{    if (store)      mgr.incrementReferenceCount(store);  } -   +  inline StoreRef::~StoreRef() {    if (store)      mgr.decrementReferenceCount(store);  } -   +  inline StoreRef &StoreRef::operator=(StoreRef const &newStore) {    assert(&newStore.mgr == &mgr);    if (store != newStore.store) { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h b/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h index c5b4e5036bdf..22259a239cf6 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h @@ -18,15 +18,15 @@  namespace clang {  namespace ento { -   +  class StoreManager; -   +  /// Store - This opaque type encapsulates an immutable mapping from  ///  locations to values.  At a high-level, it represents the symbolic  ///  memory model.  Different subclasses of StoreManager may choose  ///  different types to represent the locations and values.  using Store = const void *; -   +  class StoreRef {    Store store;    StoreManager &mgr; @@ -36,14 +36,14 @@ public:    StoreRef(const StoreRef &sr);    StoreRef &operator=(StoreRef const &newStore);    ~StoreRef(); -   +    bool operator==(const StoreRef &x) const {      assert(&mgr == &x.mgr);      return x.store == store;    }    bool operator!=(const StoreRef &x) const { return !operator==(x); } -   +    Store getStore() const { return store; }    const StoreManager &getStoreManager() const { return mgr; }  }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h index e574ffdd6a15..d6aa4feddff2 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -29,7 +29,7 @@ class CrossTranslationUnitContext;  }  namespace ento { -   +  struct NodeBuilderContext;  class AnalysisManager;  class ExplodedNodeSet; @@ -133,7 +133,7 @@ public:    /// processRegionChanges - Called by ProgramStateManager whenever a change is    /// made to the store. Used to update checkers that track region values. -  virtual ProgramStateRef  +  virtual ProgramStateRef    processRegionChanges(ProgramStateRef state,                         const InvalidatedSymbols *invalidated,                         ArrayRef<const MemRegion *> ExplicitRegions, @@ -142,7 +142,7 @@ public:                         const CallEvent *Call) = 0; -  inline ProgramStateRef  +  inline ProgramStateRef    processRegionChange(ProgramStateRef state,                        const MemRegion* MR,                        const LocationContext *LCtx) { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h index 52d78b6a3c82..0a75eeb3ea53 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h @@ -21,9 +21,9 @@ namespace ento {  namespace summMgr { -   +  /* Key kinds: -  +   - C functions   - C++ functions (name + parameter types)   - ObjC methods: @@ -34,21 +34,21 @@ namespace summMgr {   - C++ methods    - Class, function name + parameter types + const   */ -   +  class SummaryKey { -   +  };  } // end namespace clang::summMgr -   +  class SummaryManagerImpl { -   +  }; -   +  template <typename T>  class SummaryManager : SummaryManagerImpl { -   +  };  } // end GR namespace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index cc3ce72f9e56..074551962607 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -167,7 +167,7 @@ public:  ///  SubRegion::getExtent instead -- the value returned may not be a symbol.  class SymbolExtent : public SymbolData {    const SubRegion *R; -   +  public:    SymbolExtent(SymbolID sym, const SubRegion *r)        : SymbolData(SymbolExtentKind, sym), R(r) { @@ -300,7 +300,7 @@ public:    }  }; -/// Represents a symbolic expression involving a binary operator  +/// Represents a symbolic expression involving a binary operator  class BinarySymExpr : public SymExpr {    BinaryOperator::Opcode Op;    QualType T; @@ -558,7 +558,7 @@ class SymbolReaper {    SymbolSetTy TheDead;    RegionSetTy RegionRoots; -   +    const StackFrameContext *LCtx;    const Stmt *Loc;    SymbolManager& SymMgr; @@ -614,7 +614,7 @@ public:    bool hasDeadSymbols() const {      return !TheDead.empty();    } -   +    using region_iterator = RegionSetTy::const_iterator;    region_iterator region_begin() const { return RegionRoots.begin(); } @@ -627,10 +627,10 @@ public:    bool isDead(SymbolRef sym) const {      return TheDead.count(sym);    } -   +    void markLive(const MemRegion *region);    void markElementIndicesLive(const MemRegion *region); -   +    /// Set to the value of the symbolic store after    /// StoreManager::removeDeadBindings has been called.    void setReapedStore(StoreRef st) { reapedStore = st; } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h index 7df8f373b366..07edd35ff944 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h @@ -20,7 +20,7 @@  #include <cassert>  namespace clang { -   +  class CFGBlock;  namespace ento { @@ -47,13 +47,13 @@ public:    /// Returns the node associated with the worklist unit.    ExplodedNode *getNode() const { return node; } -   +    /// Returns the block counter map associated with the worklist unit.    BlockCounter getBlockCounter() const { return counter; }    /// Returns the CFGblock associated with the worklist unit.    const CFGBlock *getBlock() const { return block; } -   +    /// Return the index within the CFGBlock for the worklist unit.    unsigned getIndex() const { return blockIdx; }  };  | 
