tomasz-kaminski-sonarsource updated this revision to Diff 464677.
tomasz-kaminski-sonarsource added a comment.
Herald added subscribers: openmp-commits, zero9178, bzcheeseman, sdasgup3, 
wenzhicui, wrengr, cota, mravishankar, teijeong, rdzhabarov, tatianashp, 
msifontes, jurahul, Kayjukh, grosul1, Joonsoo, stephenneuendorffer, liufengdb, 
aartbik, mgester, arpith-jacob, nicolasvasilache, antiagainst, shauheen, 
rriddle, mehdi_amini, MaskRay.
Herald added a reviewer: nicolasvasilache.
Herald added projects: OpenMP, MLIR, lld-macho.
Herald added a reviewer: lld-macho.

Updated diff to be mergable.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D134947/new/

https://reviews.llvm.org/D134947

Files:
  clang/include/clang/Basic/DiagnosticDriverKinds.td
  clang/include/clang/Driver/Options.td
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
  clang/lib/Driver/Driver.cpp
  clang/lib/StaticAnalyzer/Core/RegionStore.cpp
  clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
  clang/test/Analysis/NewDeleteLeaks.cpp
  clang/test/Analysis/symbol-reaper-lambda.cpp
  clang/test/Analysis/trivial-copy-struct.cpp
  clang/test/Driver/cl-options.c
  lld/MachO/SymbolTable.cpp
  mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.td
  openmp/runtime/src/kmp_sched.cpp

Index: openmp/runtime/src/kmp_sched.cpp
===================================================================
--- openmp/runtime/src/kmp_sched.cpp
+++ openmp/runtime/src/kmp_sched.cpp
@@ -83,6 +83,9 @@
   KMP_PUSH_PARTITIONED_TIMER(OMP_loop_static);
   KMP_PUSH_PARTITIONED_TIMER(OMP_loop_static_scheduling);
 
+  // Clear monotonic/nonmonotonic bits (ignore it)
+  schedtype = SCHEDULE_WITHOUT_MODIFIERS(schedtype);
+
   typedef typename traits_t<T>::unsigned_t UT;
   typedef typename traits_t<T>::signed_t ST;
   /*  this all has to be changed back to TID and such.. */
Index: mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.td
===================================================================
--- mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.td
+++ mlir/include/mlir/Dialect/Linalg/TransformOps/LinalgTransformOps.td
@@ -705,14 +705,14 @@
       - the new scf.foreach_thread op,
       - the tiled op that implements TilingInterface.
 
-    ### Example using `num_threads`
+    #### Example using `num_threads`
 
     ```
     %0 = pdl_match @match_matmul in %arg1
     %3:2 = transform.structured.tile_to_foreach_thread_op %0 num_threads [10, 20]
     ```
 
-    ### Example using `tile_sizes`
+    #### Example using `tile_sizes`
 
     ```
     %0 = pdl_match @match_matmul in %arg1
Index: lld/MachO/SymbolTable.cpp
===================================================================
--- lld/MachO/SymbolTable.cpp
+++ lld/MachO/SymbolTable.cpp
@@ -392,53 +392,53 @@
   }
 }
 
-void macho::reportPendingUndefinedSymbols() {
-  for (const auto &undef : undefs) {
-    const UndefinedDiag &locations = undef.second;
-
-    std::string message = "undefined symbol";
-    if (config->archMultiple)
-      message += (" for arch " + getArchitectureName(config->arch())).str();
-    message += ": " + toString(*undef.first);
-
-    const size_t maxUndefinedReferences = 3;
-    size_t i = 0;
-    for (const std::string &loc : locations.otherReferences) {
-      if (i >= maxUndefinedReferences)
-        break;
-      message += "\n>>> referenced by " + loc;
-      ++i;
-    }
-
-    for (const UndefinedDiag::SectionAndOffset &loc :
-         locations.codeReferences) {
-      if (i >= maxUndefinedReferences)
-        break;
-      message += "\n>>> referenced by ";
-      std::string src = loc.isec->getSourceLocation(loc.offset);
-      if (!src.empty())
-        message += src + "\n>>>               ";
-      message += loc.isec->getLocation(loc.offset);
-      ++i;
-    }
+static void reportUndefinedSymbol(const Undefined &sym,
+                                  const UndefinedDiag &locations) {
+  std::string message = "undefined symbol";
+  if (config->archMultiple)
+    message += (" for arch " + getArchitectureName(config->arch())).str();
+  message += ": " + toString(sym);
+
+  const size_t maxUndefinedReferences = 3;
+  size_t i = 0;
+  for (const std::string &loc : locations.otherReferences) {
+    if (i >= maxUndefinedReferences)
+      break;
+    message += "\n>>> referenced by " + loc;
+    ++i;
+  }
 
-    size_t totalReferences =
-        locations.otherReferences.size() + locations.codeReferences.size();
-    if (totalReferences > i)
-      message +=
-          ("\n>>> referenced " + Twine(totalReferences - i) + " more times")
-              .str();
-
-    if (config->undefinedSymbolTreatment == UndefinedSymbolTreatment::error)
-      error(message);
-    else if (config->undefinedSymbolTreatment ==
-             UndefinedSymbolTreatment::warning)
-      warn(message);
-    else
-      assert(false &&
-             "diagnostics make sense for -undefined error|warning only");
+  for (const UndefinedDiag::SectionAndOffset &loc : locations.codeReferences) {
+    if (i >= maxUndefinedReferences)
+      break;
+    message += "\n>>> referenced by ";
+    std::string src = loc.isec->getSourceLocation(loc.offset);
+    if (!src.empty())
+      message += src + "\n>>>               ";
+    message += loc.isec->getLocation(loc.offset);
+    ++i;
   }
 
+  size_t totalReferences =
+      locations.otherReferences.size() + locations.codeReferences.size();
+  if (totalReferences > i)
+    message +=
+        ("\n>>> referenced " + Twine(totalReferences - i) + " more times")
+            .str();
+
+  if (config->undefinedSymbolTreatment == UndefinedSymbolTreatment::error)
+    error(message);
+  else if (config->undefinedSymbolTreatment ==
+           UndefinedSymbolTreatment::warning)
+    warn(message);
+  else
+    assert(false && "diagnostics make sense for -undefined error|warning only");
+}
+
+void macho::reportPendingUndefinedSymbols() {
+  for (const auto &undef : undefs)
+    reportUndefinedSymbol(*undef.first, undef.second);
+
   // This function is called multiple times during execution. Clear the printed
   // diagnostics to avoid printing the same things again the next time.
   undefs.clear();
Index: clang/test/Driver/cl-options.c
===================================================================
--- clang/test/Driver/cl-options.c
+++ clang/test/Driver/cl-options.c
@@ -782,4 +782,8 @@
 // EXTERNAL_W0: "-Wno-system-headers"
 // EXTERNAL_Wn: "-Wsystem-headers"
 
+// RUN: %clang_cl -vctoolsdir "" /arm64EC /c -### -- %s 2>&1 | FileCheck %s --check-prefix ARM64EC
+// ARM64EC: "-triple" "arm64ec-pc-windows-msvc19.20.0"
+// ARM64EC-NOT: /arm64EC has been overridden by specified target
+
 void f(void) { }
Index: clang/test/Analysis/trivial-copy-struct.cpp
===================================================================
--- clang/test/Analysis/trivial-copy-struct.cpp
+++ clang/test/Analysis/trivial-copy-struct.cpp
@@ -1,6 +1,7 @@
 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
 
 template <typename T> void clang_analyzer_dump(T);
+template <typename T> void clang_analyzer_value(T);
 void clang_analyzer_warnIfReached();
 
 struct Node { int* ptr; };
@@ -34,3 +35,67 @@
   (void)(n1->ptr);
   (void)(n2->ptr);
 }
+
+struct List {
+  List* next;
+  int value;
+  int padding;
+};
+
+void deadCode(List orig) {
+  List c = orig;
+  clang_analyzer_dump(c.value);
+  // expected-warning-re@-1 {{reg_${{[0-9]+}}<int orig.value>}}
+  if (c.value == 42)
+    return;
+  clang_analyzer_value(c.value);
+  // expected-warning@-1 {{32s:{ [-2147483648, 41], [43, 2147483647] }}}
+  // Before symbol was garbage collected too early, and we lost the constraints.
+  if (c.value != 42)
+    return;
+
+  clang_analyzer_warnIfReached(); // no-warning: Dead code.
+};
+
+void ptr1(List* n) {
+  List* n2 = new List(*n); // cctor
+  if (!n->next) {
+    if (n2->next) {
+      clang_analyzer_warnIfReached(); // unreachable
+    }
+  }
+  delete n2;
+}
+
+void ptr2(List* n) {
+  List* n2 = new List(); // ctor
+  *n2 = *n; // assignment
+  if (!n->next) {
+    if (n2->next) {
+      clang_analyzer_warnIfReached(); // unreachable
+    }
+  }
+  delete n2;
+}
+
+struct Wrapper {
+  List head;
+  int count;
+};
+
+void nestedLazyCompoundVal(List* n) {
+  Wrapper* w = 0;
+  {
+     Wrapper lw;
+     lw.head = *n;
+     w = new Wrapper(lw);
+  }
+  if (!n->next) {
+    if (w->head.next) {
+      // Unreachable, w->head is a copy of *n, therefore
+      // w->head.next and n->next are equal
+      clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
+    }
+  }
+  delete w;
+}
Index: clang/test/Analysis/symbol-reaper-lambda.cpp
===================================================================
--- /dev/null
+++ clang/test/Analysis/symbol-reaper-lambda.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
+// expected-no-diagnostics
+
+template <typename... Ts>
+void escape(Ts&...);
+struct Dummy {};
+
+int strange(Dummy param) {
+  Dummy local_pre_lambda;
+  int ref_captured = 0;
+
+  // LambdaExpr is modeled as lazyCompoundVal of tempRegion, that contains
+  // all captures. In this instance, this region contains a pointer/reference
+  // to ref_captured variable.
+  auto fn = [&] {
+    escape(param, local_pre_lambda);
+    return ref_captured; // no-warning: The value is not garbage.
+  };
+
+  int local_defined_after_lambda; // Unused, but necessary! Important that it's before the call.
+
+  // The ref_captured binding should not be pruned at this point, as it is still
+  // accessed via reference captured in operator() of fn.
+  return fn();
+}
+
Index: clang/test/Analysis/NewDeleteLeaks.cpp
===================================================================
--- clang/test/Analysis/NewDeleteLeaks.cpp
+++ clang/test/Analysis/NewDeleteLeaks.cpp
@@ -192,3 +192,29 @@
 // expected-note@-1 {{Potential leak of memory pointed to by 'v'}}
 
 } // namespace refkind_from_unoallocated_to_allocated
+
+// Check that memory leak is reported against a symbol if the last place it's
+// mentioned is a base region of a lazy compound value, as the program cannot
+// possibly free that memory.
+namespace symbol_reaper_lifetime {
+struct Nested {
+  int buf[2];
+};
+struct Wrapping {
+  Nested data;
+};
+
+Nested allocateWrappingAndReturnNested() {
+  // expected-note@+1 {{Memory is allocated}}
+  Wrapping const* p = new Wrapping();
+  // expected-warning@+2 {{Potential leak of memory pointed to by 'p'}}
+  // expected-note@+1    {{Potential leak of memory pointed to by 'p'}}
+  return p->data;
+}
+
+void caller() {
+  // expected-note@+1 {{Calling 'allocateWrappingAndReturnNested'}}
+  Nested n = allocateWrappingAndReturnNested();
+  (void)n;
+} // no-warning: No potential memory leak here, because that's been already reported.
+} // namespace symbol_reaper_lifetime
Index: clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -411,10 +411,14 @@
 }
 
 void SymbolReaper::markLive(const MemRegion *region) {
-  RegionRoots.insert(region->getBaseRegion());
+  LiveRegionRoots.insert(region->getBaseRegion());
   markElementIndicesLive(region);
 }
 
+void SymbolReaper::markLazilyCopied(const clang::ento::MemRegion *region) {
+  LazilyCopiedRegionRoots.insert(region->getBaseRegion());
+}
+
 void SymbolReaper::markElementIndicesLive(const MemRegion *region) {
   for (auto SR = dyn_cast<SubRegion>(region); SR;
        SR = dyn_cast<SubRegion>(SR->getSuperRegion())) {
@@ -437,8 +441,7 @@
   // is not used later in the path, we can diagnose a leak of a value within
   // that field earlier than, say, the variable that contains the field dies.
   MR = MR->getBaseRegion();
-
-  if (RegionRoots.count(MR))
+  if (LiveRegionRoots.count(MR))
     return true;
 
   if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
@@ -454,6 +457,15 @@
   return isa<AllocaRegion, CXXThisRegion, MemSpaceRegion, CodeTextRegion>(MR);
 }
 
+bool SymbolReaper::isLazilyCopiedRegion(const MemRegion *MR) const {
+  // TODO: See comment in isLiveRegion.
+  return LazilyCopiedRegionRoots.count(MR->getBaseRegion());
+}
+
+bool SymbolReaper::isReadableRegion(const MemRegion *MR) {
+  return isLiveRegion(MR) || isLazilyCopiedRegion(MR);
+}
+
 bool SymbolReaper::isLive(SymbolRef sym) {
   if (TheLiving.count(sym)) {
     markDependentsLive(sym);
@@ -464,7 +476,7 @@
 
   switch (sym->getKind()) {
   case SymExpr::SymbolRegionValueKind:
-    KnownLive = isLiveRegion(cast<SymbolRegionValue>(sym)->getRegion());
+    KnownLive = isReadableRegion(cast<SymbolRegionValue>(sym)->getRegion());
     break;
   case SymExpr::SymbolConjuredKind:
     KnownLive = false;
Index: clang/lib/StaticAnalyzer/Core/RegionStore.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -2838,6 +2838,10 @@
   // Is it a LazyCompoundVal?  All referenced regions are live as well.
   if (Optional<nonloc::LazyCompoundVal> LCS =
           V.getAs<nonloc::LazyCompoundVal>()) {
+    // TODO: Make regions referred to by `lazyCompoundVals` that are bound to
+    // subregions of the `LCS.getRegion()` also lazily copied.
+    if (const MemRegion *R = LCS->getRegion())
+      SymReaper.markLazilyCopied(R);
 
     const RegionStoreManager::SValListTy &Vals = RM.getInterestingValues(*LCS);
 
Index: clang/lib/Driver/Driver.cpp
===================================================================
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -1256,6 +1256,8 @@
     T.setVendor(llvm::Triple::PC);
     T.setEnvironment(llvm::Triple::MSVC);
     T.setObjectFormat(llvm::Triple::COFF);
+    if (Args.hasArg(options::OPT__SLASH_arm64EC))
+      T.setArch(llvm::Triple::aarch64, llvm::Triple::AArch64SubArch_arm64ec);
     TargetTriple = T.str();
   } else if (IsDXCMode()) {
     // Build TargetTriple from target_profile option for clang-dxc.
@@ -1380,6 +1382,14 @@
   const ToolChain &TC = getToolChain(
       *UArgs, computeTargetTriple(*this, TargetTriple, *UArgs));
 
+  // Report warning when arm64EC option is overridden by specified target
+  if ((TC.getTriple().getArch() != llvm::Triple::aarch64 ||
+       TC.getTriple().getSubArch() != llvm::Triple::AArch64SubArch_arm64ec) &&
+      UArgs->hasArg(options::OPT__SLASH_arm64EC)) {
+    getDiags().Report(clang::diag::warn_target_override_arm64ec)
+        << TC.getTriple().str();
+  }
+
   // The compilation takes ownership of Args.
   Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs,
                                    ContainsError);
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -582,7 +582,12 @@
   SymbolMapTy TheLiving;
   SymbolSetTy MetadataInUse;
 
-  RegionSetTy RegionRoots;
+  RegionSetTy LiveRegionRoots;
+  // The lazily copied regions are locations for which a program
+  // can access the value stored at that location, but not its address.
+  // These regions are constructed as a set of regions referred to by
+  // lazyCompoundVal.
+  RegionSetTy LazilyCopiedRegionRoots;
 
   const StackFrameContext *LCtx;
   const Stmt *Loc;
@@ -628,8 +633,8 @@
 
   using region_iterator = RegionSetTy::const_iterator;
 
-  region_iterator region_begin() const { return RegionRoots.begin(); }
-  region_iterator region_end() const { return RegionRoots.end(); }
+  region_iterator region_begin() const { return LiveRegionRoots.begin(); }
+  region_iterator region_end() const { return LiveRegionRoots.end(); }
 
   /// Returns whether or not a symbol has been confirmed dead.
   ///
@@ -640,6 +645,7 @@
   }
 
   void markLive(const MemRegion *region);
+  void markLazilyCopied(const MemRegion *region);
   void markElementIndicesLive(const MemRegion *region);
 
   /// Set to the value of the symbolic store after
@@ -647,6 +653,12 @@
   void setReapedStore(StoreRef st) { reapedStore = st; }
 
 private:
+  bool isLazilyCopiedRegion(const MemRegion *region) const;
+  // A readable region is a region that live or lazily copied.
+  // Any symbols that refer to values in regions are alive if the region
+  // is readable.
+  bool isReadableRegion(const MemRegion *region);
+
   /// Mark the symbols dependent on the input symbol as live.
   void markDependentsLive(SymbolRef sym);
 };
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -6695,6 +6695,8 @@
 def _SLASH_QIntel_jcc_erratum : CLFlag<"QIntel-jcc-erratum">,
   HelpText<"Align branches within 32-byte boundaries to mitigate the performance impact of the Intel JCC erratum.">,
   Alias<mbranches_within_32B_boundaries>;
+def _SLASH_arm64EC : CLFlag<"arm64EC">,
+  HelpText<"Set build target to arm64ec">;
 
 // Non-aliases:
 
Index: clang/include/clang/Basic/DiagnosticDriverKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -655,6 +655,10 @@
   "-fjmc works only for ELF; option ignored">,
   InGroup<OptionIgnored>;
 
+def warn_target_override_arm64ec : Warning<
+  "/arm64EC has been overridden by specified target: %0; option ignored">,
+  InGroup<OptionIgnored>;
+
 def err_drv_target_variant_invalid : Error<
   "unsupported '%0' value '%1'; use 'ios-macabi' instead">;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to