================
@@ -1737,22 +1733,95 @@ class BuildLockset : public 
ConstStmtVisitor<BuildLockset> {
   FactSet FSet;
   // The fact set for the function on exit.
   const FactSet &FunctionExitFSet;
-  LocalVariableMap::Context LVarCtx;
-  unsigned CtxIndex;
+
+  /// A `LocalVariableMap::Context` wrapper that groups a context 'Q' with its
+  /// immediate predecessor 'P' for a program point.  If the program point is
+  /// right after a Stmt 'S', 'P' is the pre-context of 'S' and 'Q' is the
+  /// post-context of 'S'.  Otherwise, 'P' == 'Q'.
+  ///
+  /// A DualLocalVarContext sets the global context for VarDefinition lookup to
+  /// the post-context 'Q',  once CREATED or UPDATED to the next program
+  /// point.  One can temporarily switch the global context to either 'P' or 
'Q'
+  /// using `switchToContextForScope`. The lifetime of the global context
+  /// switching is bound to the enclosing scope. The global context will be set
+  /// back to the prior state by the end of the scope.  This is done by the
+  /// returned ContextSwitchScope object.
+  ///
+  /// Note: The pre- and post-context of a Stmt are distinct only in Beta mode
+  /// (i.e., `Analyzer.Handler.issueBetaWarnings()`) because of the
+  /// out-parameter validation.  If not in Beta mode, the global context for
+  /// VarDefinition lookup is invisible, thus this wrapper has no impact on the
+  /// analysis.
+  class DualLocalVarContext {
+  public:
+    enum Point : char { Pre = 0, Post = 1 };
+
+    struct [[nodiscard]] ContextSwitchScope {
+      DualLocalVarContext &DC;
+      enum Point LastPoint;
+      ~ContextSwitchScope() { DC.switchContextTo(LastPoint); }
+    };
+
+    /// Temporarily switch context to \p P as long as the returned object 
lives.
+    [[nodiscard]] ContextSwitchScope switchToContextForScope(Point P) {
+      enum Point PriorPoint = CurrPoint;
+      switchContextTo(P);
+      return ContextSwitchScope{*this, PriorPoint};
+    }
+
+    /// Update the pre- and post-contexts to be associated with the next Stmt 
\p
+    /// S. Set the global context to the post-context of \p S upon returning.
+    ///
+    /// If \p S is null, the behavior is as if the Stmt is a no-op--the
+    /// post-context will shift to be the pre-context and the new post-context
+    /// is the same as the old one, resulting in identical pre- and
+    /// post-contexts.
+    void moveToNextContext(const Stmt *S) {
+      PrePost[Pre] = PrePost[Post];
+
+      const LocalVariableMap::Context &NewPostCtx =
+          S ? Analyzer.LocalVarMap.getNextContext(CtxIndex, S, *PrePost[Post])
+            : *PrePost[Pre];
+
+      PrePost[Post] = &NewPostCtx;
+      switchContextTo(Post);
+    }
+
+    /// Constructs a DualLocalVarContext for the entry program point, where 
pre-
+    /// and post-contexts are both equal to the \p EntryContext.
+    DualLocalVarContext(ThreadSafetyAnalyzer &Analyzer, unsigned EntryIdx,
+                        const LocalVariableMap::Context *EntryContext)
+        : Analyzer(Analyzer), PrePost{EntryContext, EntryContext},
+          CurrPoint(Post), CtxIndex(EntryIdx) {
+      assert(EntryContext);
+      switchContextTo(Post);
+    }
+
+  private:
+    ThreadSafetyAnalyzer &Analyzer;
+    // PrePost[0] points to the pre-context and
+    // PrePost[1] points to the post-context:
+    std::array<const LocalVariableMap::Context *, 2> PrePost;
+    enum Point CurrPoint;
----------------
melver wrote:

Just `Point CurrPoint` (C-style `enum Point...` redundant). Here and in other 
places.

https://github.com/llvm/llvm-project/pull/210219
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to