llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-analysis

Author: Fangyi Zhou (fangyi-zhou)

<details>
<summary>Changes</summary>

Closes #<!-- -->57270.

This PR changes the `Stmt *` field in `SymbolConjured` with
`CFGBlock::ConstCFGElementRef`. The motivation is that, when conjuring a
symbol, there might not always be a statement available, causing
information to be lost for conjured symbols, whereas the CFGElementRef
can always be provided at the callsite.

Following the idea, this PR changes callsites of functions to create
conjured symbols, and replaces them with appropriate `CFGElementRef`s.

There is a caveat at loop widening, where the correct location is the
CFG terminator (which is not an element and does not have a ref). In
this case, the first element in the block is passed as a location.

Previous PR #<!-- -->128251, Reverted at #<!-- -->137304.


---

Patch is 124.28 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/137355.diff


38 Files Affected:

- (modified) clang/include/clang/Analysis/CFG.h (+9-1) 
- (modified) clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h 
(+10-1) 
- (modified) 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h (+2) 
- (modified) clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h 
(+1-1) 
- (modified) 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h (+2-1) 
- (modified) 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h (+8-7) 
- (modified) 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h (+10-27) 
- (modified) clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h 
(+4-4) 
- (modified) 
clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h (+49-22) 
- (modified) clang/lib/Analysis/CFG.cpp (+26-20) 
- (modified) clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp (+40-38) 
- (modified) clang/lib/StaticAnalyzer/Checkers/ContainerModeling.cpp (+29-26) 
- (modified) clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.cpp (+3-3) 
- (modified) clang/lib/StaticAnalyzer/Checkers/ErrnoModeling.h (+3-2) 
- (modified) clang/lib/StaticAnalyzer/Checkers/Iterator.cpp (+3-2) 
- (modified) clang/lib/StaticAnalyzer/Checkers/Iterator.h (+2-1) 
- (modified) clang/lib/StaticAnalyzer/Checkers/IteratorModeling.cpp (+51-42) 
- (modified) clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (+5-3) 
- (modified) clang/lib/StaticAnalyzer/Checkers/STLAlgorithmModeling.cpp 
(+14-12) 
- (modified) clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp (+14-12) 
- (modified) clang/lib/StaticAnalyzer/Checkers/StdLibraryFunctionsChecker.cpp 
(+1-1) 
- (modified) clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp (+22-21) 
- (modified) clang/lib/StaticAnalyzer/Core/CallEvent.cpp (+1-1) 
- (modified) clang/lib/StaticAnalyzer/Core/ExprEngine.cpp (+28-18) 
- (modified) clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp (+29-24) 
- (modified) clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp (+7-6) 
- (modified) clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp (+4-3) 
- (modified) clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp (+8-6) 
- (modified) clang/lib/StaticAnalyzer/Core/LoopWidening.cpp (+5-24) 
- (modified) clang/lib/StaticAnalyzer/Core/ProgramState.cpp (+4-4) 
- (modified) clang/lib/StaticAnalyzer/Core/RegionStore.cpp (+27-26) 
- (modified) clang/lib/StaticAnalyzer/Core/SValBuilder.cpp (+14-18) 
- (modified) clang/lib/StaticAnalyzer/Core/SymbolManager.cpp (+1-1) 
- (added) clang/test/Analysis/PR57270.cpp (+30) 
- (modified) clang/test/Analysis/container-modeling.cpp (+2-2) 
- (modified) clang/test/Analysis/dump_egraph.cpp (-1) 
- (modified) clang/test/Analysis/explain-svals.cpp (+6-6) 
- (modified) clang/test/Analysis/explain-svals.m (+2-2) 


``````````diff
diff --git a/clang/include/clang/Analysis/CFG.h 
b/clang/include/clang/Analysis/CFG.h
index a7ff38c786a8f..e70c70335e597 100644
--- a/clang/include/clang/Analysis/CFG.h
+++ b/clang/include/clang/Analysis/CFG.h
@@ -122,7 +122,8 @@ class CFGElement {
     return (Kind) x;
   }
 
-  void dumpToStream(llvm::raw_ostream &OS) const;
+  void dumpToStream(llvm::raw_ostream &OS,
+                    bool TerminateWithNewLine = true) const;
 
   void dump() const {
     dumpToStream(llvm::errs());
@@ -695,6 +696,11 @@ class CFGBlock {
     void dump() const {
       dumpToStream(llvm::errs());
     }
+
+    void Profile(llvm::FoldingSetNodeID &ID) const {
+      ID.AddPointer(Parent);
+      ID.AddInteger(Index);
+    }
   };
 
   template <bool IsReverse, bool IsConst> class ElementRefIterator {
@@ -1190,6 +1196,8 @@ class CFGBlock {
   }
 };
 
+using ConstCFGElementRef = CFGBlock::ConstCFGElementRef;
+
 /// CFGCallback defines methods that should be called when a logical
 /// operator error is found when building the CFG.
 class CFGCallback {
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h 
b/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
index 519d2d5b3676b..6c1025ecc7f4d 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
+++ b/clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
@@ -19,6 +19,7 @@
 #include "clang/AST/DeclCXX.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/raw_ostream.h"
 
 namespace clang {
 
@@ -29,6 +30,13 @@ class SValExplainer : public FullSValVisitor<SValExplainer, 
std::string> {
   ASTContext &ACtx;
   ProgramStateRef State;
 
+  std::string printCFGElementRef(ConstCFGElementRef Elem) {
+    std::string Str;
+    llvm::raw_string_ostream OS(Str);
+    Elem->dumpToStream(OS, /*TerminateWithNewLine=*/false);
+    return Str;
+  }
+
   std::string printStmt(const Stmt *S) {
     std::string Str;
     llvm::raw_string_ostream OS(Str);
@@ -114,7 +122,8 @@ class SValExplainer : public FullSValVisitor<SValExplainer, 
std::string> {
 
   std::string VisitSymbolConjured(const SymbolConjured *S) {
     return "symbol of type '" + S->getType().getAsString() +
-           "' conjured at statement '" + printStmt(S->getStmt()) + "'";
+           "' conjured at CFG element '" +
+           printCFGElementRef(S->getCFGElementRef()) + "'";
   }
 
   std::string VisitSymbolDerived(const SymbolDerived *S) {
diff --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
index bb33a6912bec7..63ca3efc6d228 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -151,6 +151,8 @@ class CheckerContext {
     return Pred->getSVal(S);
   }
 
+  ConstCFGElementRef getCFGElementRef() const { return Eng.getCFGElementRef(); 
}
+
   /// Returns true if the value of \p E is greater than or equal to \p
   /// Val under unsigned comparison.
   bool isGreaterOrEqual(const Expr *E, unsigned long long Val);
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
index 5f855251b3cde..285194148d3d3 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -226,7 +226,7 @@ class ExprEngine {
     return (*G.roots_begin())->getLocation().getLocationContext();
   }
 
-  CFGBlock::ConstCFGElementRef getCFGElementRef() const {
+  ConstCFGElementRef getCFGElementRef() const {
     const CFGBlock *blockPtr = currBldrCtx ? currBldrCtx->getBlock() : nullptr;
     return {blockPtr, currStmtIdx};
   }
diff --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
index e75228f92a8e5..50f2197b8a174 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
@@ -27,7 +27,8 @@ namespace ento {
 /// by the loop body in any iteration.
 ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
                                     const LocationContext *LCtx,
-                                    unsigned BlockCount, const Stmt *LoopStmt);
+                                    unsigned BlockCount,
+                                    ConstCFGElementRef Elem);
 
 } // end namespace ento
 } // end namespace clang
diff --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
index 4d66e086a2c2c..52714535e7907 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
@@ -313,7 +313,7 @@ class ProgramState : public llvm::FoldingSetNode {
   /// be triggered by this event.
   ///
   /// \param Regions the set of regions to be invalidated.
-  /// \param E the expression that caused the invalidation.
+  /// \param Elem The CFG Element that caused the invalidation.
   /// \param BlockCount The number of times the current basic block has been
   ///        visited.
   /// \param CausesPointerEscape the flag is set to true when the invalidation
@@ -325,16 +325,17 @@ class ProgramState : public llvm::FoldingSetNode {
   /// \param ITraits information about special handling for particular regions
   ///        or symbols.
   [[nodiscard]] ProgramStateRef
-  invalidateRegions(ArrayRef<const MemRegion *> Regions, const Stmt *S,
-                    unsigned BlockCount, const LocationContext *LCtx,
-                    bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
+  invalidateRegions(ArrayRef<const MemRegion *> Regions,
+                    ConstCFGElementRef Elem, unsigned BlockCount,
+                    const LocationContext *LCtx, bool CausesPointerEscape,
+                    InvalidatedSymbols *IS = nullptr,
                     const CallEvent *Call = nullptr,
                     RegionAndSymbolInvalidationTraits *ITraits = nullptr) 
const;
 
   [[nodiscard]] ProgramStateRef
-  invalidateRegions(ArrayRef<SVal> Values, const Stmt *S, unsigned BlockCount,
-                    const LocationContext *LCtx, bool CausesPointerEscape,
-                    InvalidatedSymbols *IS = nullptr,
+  invalidateRegions(ArrayRef<SVal> Values, ConstCFGElementRef Elem,
+                    unsigned BlockCount, const LocationContext *LCtx,
+                    bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
                     const CallEvent *Call = nullptr,
                     RegionAndSymbolInvalidationTraits *ITraits = nullptr) 
const;
 
diff --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
index 3f3e6bdb9ff3d..2911554de9d97 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -19,6 +19,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/Type.h"
+#include "clang/Analysis/CFG.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
@@ -171,19 +172,11 @@ class SValBuilder {
 
   // Forwarding methods to SymbolManager.
 
-  const SymbolConjured* conjureSymbol(const Stmt *stmt,
+  const SymbolConjured *conjureSymbol(ConstCFGElementRef Elem,
                                       const LocationContext *LCtx,
-                                      QualType type,
-                                      unsigned visitCount,
+                                      QualType type, unsigned visitCount,
                                       const void *symbolTag = nullptr) {
-    return SymMgr.conjureSymbol(stmt, LCtx, type, visitCount, symbolTag);
-  }
-
-  const SymbolConjured* conjureSymbol(const Expr *expr,
-                                      const LocationContext *LCtx,
-                                      unsigned visitCount,
-                                      const void *symbolTag = nullptr) {
-    return SymMgr.conjureSymbol(expr, LCtx, visitCount, symbolTag);
+    return SymMgr.conjureSymbol(Elem, LCtx, type, visitCount, symbolTag);
   }
 
   /// Construct an SVal representing '0' for the specified type.
@@ -199,16 +192,16 @@ class SValBuilder {
   /// preserve the relation between related(or even equivalent) expressions, so
   /// conjured symbols should be used sparingly.
   DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
-                                        const Expr *expr,
+                                        ConstCFGElementRef elem,
                                         const LocationContext *LCtx,
                                         unsigned count);
-  DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Stmt *S,
+  DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
+                                        ConstCFGElementRef elem,
                                         const LocationContext *LCtx,
                                         QualType type, unsigned count);
-  DefinedOrUnknownSVal conjureSymbolVal(const Stmt *stmt,
+  DefinedOrUnknownSVal conjureSymbolVal(ConstCFGElementRef elem,
                                         const LocationContext *LCtx,
-                                        QualType type,
-                                        unsigned visitCount);
+                                        QualType type, unsigned visitCount);
   DefinedOrUnknownSVal conjureSymbolVal(const CallEvent &call, QualType type,
                                         unsigned visitCount,
                                         const void *symbolTag = nullptr);
@@ -217,17 +210,7 @@ class SValBuilder {
                                         const void *symbolTag = nullptr);
 
   /// Conjure a symbol representing heap allocated memory region.
-  ///
-  /// Note, the expression should represent a location.
-  DefinedSVal getConjuredHeapSymbolVal(const Expr *E,
-                                       const LocationContext *LCtx,
-                                       unsigned Count);
-
-  /// Conjure a symbol representing heap allocated memory region.
-  ///
-  /// Note, now, the expression *doesn't* need to represent a location.
-  /// But the type need to!
-  DefinedSVal getConjuredHeapSymbolVal(const Expr *E,
+  DefinedSVal getConjuredHeapSymbolVal(ConstCFGElementRef elem,
                                        const LocationContext *LCtx,
                                        QualType type, unsigned Count);
 
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
index cf7623c7be409..29a53fcc9e28d 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
@@ -14,13 +14,13 @@
 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H
 
 #include "clang/AST/Type.h"
+#include "clang/Basic/LLVM.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
-#include "clang/Basic/LLVM.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallVector.h"
@@ -223,7 +223,7 @@ class StoreManager {
   ///
   /// \param[in] store The initial store.
   /// \param[in] Values The values to invalidate.
-  /// \param[in] S The current statement being evaluated. Used to conjure
+  /// \param[in] Elem The current CFG Element being evaluated. Used to conjure
   ///   symbols to mark the values of invalidated regions.
   /// \param[in] Count The current block count. Used to conjure
   ///   symbols to mark the values of invalidated regions.
@@ -241,8 +241,8 @@ class StoreManager {
   ///   even if they do not currently have bindings. Pass \c NULL if this
   ///   information will not be used.
   virtual StoreRef invalidateRegions(
-      Store store, ArrayRef<SVal> Values, const Stmt *S, unsigned Count,
-      const LocationContext *LCtx, const CallEvent *Call,
+      Store store, ArrayRef<SVal> Values, ConstCFGElementRef Elem,
+      unsigned Count, const LocationContext *LCtx, const CallEvent *Call,
       InvalidatedSymbols &IS, RegionAndSymbolInvalidationTraits &ITraits,
       InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) = 
0;
 
diff --git 
a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h 
b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
index cbbea1b56bb40..9e7c98fdded17 100644
--- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -80,29 +80,62 @@ class SymbolRegionValue : public SymbolData {
 /// A symbol representing the result of an expression in the case when we do
 /// not know anything about what the expression is.
 class SymbolConjured : public SymbolData {
-  const Stmt *S;
+  ConstCFGElementRef Elem;
   QualType T;
   unsigned Count;
   const LocationContext *LCtx;
   const void *SymbolTag;
 
   friend class SymExprAllocator;
-  SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx,
-                 QualType t, unsigned count, const void *symbolTag)
-      : SymbolData(SymbolConjuredKind, sym), S(s), T(t), Count(count),
+  SymbolConjured(SymbolID sym, ConstCFGElementRef elem,
+                 const LocationContext *lctx, QualType t, unsigned count,
+                 const void *symbolTag)
+      : SymbolData(SymbolConjuredKind, sym), Elem(elem), T(t), Count(count),
         LCtx(lctx), SymbolTag(symbolTag) {
-    // FIXME: 's' might be a nullptr if we're conducting invalidation
-    // that was caused by a destructor call on a temporary object,
-    // which has no statement associated with it.
-    // Due to this, we might be creating the same invalidation symbol for
-    // two different invalidation passes (for two different temporaries).
     assert(lctx);
     assert(isValidTypeForSymbol(t));
   }
 
 public:
-  /// It might return null.
-  const Stmt *getStmt() const { return S; }
+  ConstCFGElementRef getCFGElementRef() const { return Elem; }
+
+  // It might return null.
+  const Stmt *getStmt() const {
+    switch (Elem->getKind()) {
+    case CFGElement::Initializer:
+      return Elem->castAs<CFGInitializer>().getInitializer()->getInit();
+    case CFGElement::ScopeBegin:
+      return Elem->castAs<CFGScopeBegin>().getTriggerStmt();
+    case CFGElement::ScopeEnd:
+      return Elem->castAs<CFGScopeEnd>().getTriggerStmt();
+    case CFGElement::NewAllocator:
+      return Elem->castAs<CFGNewAllocator>().getAllocatorExpr();
+    case CFGElement::LifetimeEnds:
+      return Elem->castAs<CFGLifetimeEnds>().getTriggerStmt();
+    case CFGElement::LoopExit:
+      return Elem->castAs<CFGLoopExit>().getLoopStmt();
+    case CFGElement::Statement:
+      return Elem->castAs<CFGStmt>().getStmt();
+    case CFGElement::Constructor:
+      return Elem->castAs<CFGConstructor>().getStmt();
+    case CFGElement::CXXRecordTypedCall:
+      return Elem->castAs<CFGCXXRecordTypedCall>().getStmt();
+    case CFGElement::AutomaticObjectDtor:
+      return Elem->castAs<CFGAutomaticObjDtor>().getTriggerStmt();
+    case CFGElement::DeleteDtor:
+      return Elem->castAs<CFGDeleteDtor>().getDeleteExpr();
+    case CFGElement::BaseDtor:
+      return nullptr;
+    case CFGElement::MemberDtor:
+      return nullptr;
+    case CFGElement::TemporaryDtor:
+      return Elem->castAs<CFGTemporaryDtor>().getBindTemporaryExpr();
+    case CFGElement::CleanupFunction:
+      return nullptr;
+    }
+    return nullptr;
+  }
+
   unsigned getCount() const { return Count; }
   /// It might return null.
   const void *getTag() const { return SymbolTag; }
@@ -113,11 +146,11 @@ class SymbolConjured : public SymbolData {
 
   void dumpToStream(raw_ostream &os) const override;
 
-  static void Profile(llvm::FoldingSetNodeID &profile, const Stmt *S,
+  static void Profile(llvm::FoldingSetNodeID &profile, ConstCFGElementRef Elem,
                       const LocationContext *LCtx, QualType T, unsigned Count,
                       const void *SymbolTag) {
     profile.AddInteger((unsigned)SymbolConjuredKind);
-    profile.AddPointer(S);
+    profile.Add(Elem);
     profile.AddPointer(LCtx);
     profile.Add(T);
     profile.AddInteger(Count);
@@ -125,7 +158,7 @@ class SymbolConjured : public SymbolData {
   }
 
   void Profile(llvm::FoldingSetNodeID& profile) override {
-    Profile(profile, S, LCtx, T, Count, SymbolTag);
+    Profile(profile, Elem, LCtx, T, Count, SymbolTag);
   }
 
   // Implement isa<T> support.
@@ -533,18 +566,12 @@ class SymbolManager {
   template <typename SymExprT, typename... Args>
   const SymExprT *acquire(Args &&...args);
 
-  const SymbolConjured *conjureSymbol(const Stmt *E,
+  const SymbolConjured *conjureSymbol(ConstCFGElementRef Elem,
                                       const LocationContext *LCtx, QualType T,
                                       unsigned VisitCount,
                                       const void *SymbolTag = nullptr) {
-    return acquire<SymbolConjured>(E, LCtx, T, VisitCount, SymbolTag);
-  }
 
-  const SymbolConjured* conjureSymbol(const Expr *E,
-                                      const LocationContext *LCtx,
-                                      unsigned VisitCount,
-                                      const void *SymbolTag = nullptr) {
-    return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag);
+    return acquire<SymbolConjured>(Elem, LCtx, T, VisitCount, SymbolTag);
   }
 
   QualType getType(const SymExpr *SE) const {
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index d03a0a544b016..4b50b9248d21a 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -5803,16 +5803,17 @@ static void print_construction_context(raw_ostream &OS,
 }
 
 static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
-                       const CFGElement &E);
+                       const CFGElement &E, bool TerminateWithNewLine = true);
 
-void CFGElement::dumpToStream(llvm::raw_ostream &OS) const {
+void CFGElement::dumpToStream(llvm::raw_ostream &OS,
+                              bool TerminateWithNewLine) const {
   LangOptions LangOpts;
   StmtPrinterHelper Helper(nullptr, LangOpts);
-  print_elem(OS, Helper, *this);
+  print_elem(OS, Helper, *this, TerminateWithNewLine);
 }
 
 static void print_elem(raw_ostream &OS, StmtPrinterHelper &Helper,
-                       const CFGElement &E) {
+                       const CFGElement &E, bool TerminateWithNewLine) {
   switch (E.getKind()) {
   case CFGElement::Kind::Statement:
   case CFGElement::Kind::CXXRecordTypedCall:
@@ -5829,7 +5830,9 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper 
&Helper,
       if (Children.begin() != Children.end()) {
         OS << "({ ... ; ";
         Helper.handledStmt(*SE->getSubStmt()->body_rbegin(),OS);
-        OS << " })\n";
+        OS << " })";
+        if (TerminateWithNewLine)
+          OS << '\n';
         return;
       }
     }
@@ -5838,7 +5841,8 @@ static void print_elem(raw_ostream &OS, StmtPrinterHelper 
&Helper,
       if (B->getOpcode() == BO_Comma) {
         OS << "... , ";
         Helper.handledStmt(B->getRHS(),OS);
-        OS << '\n';
+        if (TerminateWithNewLine)
+          OS << '\n';
         return;
       }
     }
@@ -5866,15 +5870,14 @@ static void print_elem(raw_ostream &OS, 
StmtPrinterHelper &Helper,
     }
 
     // Expressions need a newline.
-    if (isa<Expr>(S))
+    if (isa<Expr>(S) && TerminateWithNewLine)
       OS << '\n';
 
-    break;
+    return;
   }
 
   case CFGElement::Kind::Initializer:
     print_in...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/137355
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to