From 66aa69e2add2b8641a652768b0eac30f00427145 Mon Sep 17 00:00:00 2001
From: Sunil Dora <sunilkumar.dora@windriver.com>
Date: Wed, 11 Dec 2024 09:48:16 -0800
Subject: [PATCH] gcc: Fix c++: tweak for Wrange-loop-construct

This commit updates the warning to use a check for "trivially constructible" instead of
"trivially copyable." The original check was incorrect, as "trivially copyable" only applies
to types that can be copied trivially, whereas "trivially constructible" is the correct check
for types that can be trivially default-constructed.

This change ensures the warning is more accurate and aligns with the proper type traits.

LLVM accepted a similar fix:
https://github.com/llvm/llvm-project/issues/47355

PR c++/116731 [https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116731]

Upstream-Status: Backport [https://gcc.gnu.org/g:179dc0f0fe01012675c1b430591b9891ce96c26e]

Signed-off-by: Marek Polacek <polacek@redhat.com>
Signed-off-by: Sunil Dora <sunilkumar.dora@windriver.com>
---
 gcc/cp/parser.cc                              |  7 ++-
 .../g++.dg/warn/Wrange-loop-construct3.C      | 57 +++++++++++++++++++
 2 files changed, 61 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/Wrange-loop-construct3.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 4e67da6ff..5dd94357d 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -13854,11 +13854,12 @@ warn_for_range_copy (tree decl, tree expr)
   else if (!CP_TYPE_CONST_P (type))
     return;
 
-  /* Since small trivially copyable types are cheap to copy, we suppress the
-     warning for them.  64B is a common size of a cache line.  */
+  /* Since small trivially constructible types are cheap to construct, we
+     suppress the warning for them.  64B is a common size of a cache line.  */
+  tree list = build_tree_list (NULL_TREE, TREE_TYPE (expr));
   if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST
       || (tree_to_uhwi (TYPE_SIZE_UNIT (type)) <= 64
-	  && trivially_copyable_p (type)))
+	  && is_trivially_xible (INIT_EXPR, type, list)))
     return;
 
   /* If we can initialize a reference directly, suggest that to avoid the
diff --git a/gcc/testsuite/g++.dg/warn/Wrange-loop-construct3.C b/gcc/testsuite/g++.dg/warn/Wrange-loop-construct3.C
new file mode 100644
index 000000000..3d9d0c908
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wrange-loop-construct3.C
@@ -0,0 +1,57 @@
+// PR c++/116731
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wrange-loop-construct" }
+
+void
+f0 ()
+{
+  struct S {
+    char a[64];
+    S& operator=(const S&) { return *this; };
+  };
+
+  S arr[8];
+  for (const auto r : arr)
+    (void) r;
+}
+
+void
+f1 ()
+{
+  struct S {
+    char a[65];
+    S& operator=(const S&) { return *this; };
+  };
+
+  S arr[8];
+  for (const auto r : arr) // { dg-warning "creates a copy" }
+    (void) r;
+}
+
+void
+f2 ()
+{
+  struct S {
+    char a[64];
+    S& operator=(const S&) { return *this; };
+    ~S() { }
+  };
+
+  S arr[8];
+  for (const auto r : arr) // { dg-warning "creates a copy" }
+    (void) r;
+}
+
+void
+f3 ()
+{
+  struct S {
+    char a[65];
+    S& operator=(const S&) { return *this; };
+    ~S() { }
+  };
+
+  S arr[8];
+  for (const auto r : arr) // { dg-warning "creates a copy" }
+    (void) r;
+}
-- 
2.43.0

