]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: fix spurious -Wrange-loop-construct warning [PR125697] master trunk
authorMarek Polacek <polacek@redhat.com>
Wed, 10 Jun 2026 20:43:18 +0000 (16:43 -0400)
committerMarek Polacek <polacek@redhat.com>
Mon, 22 Jun 2026 19:34:14 +0000 (15:34 -0400)
Here we issue a bogus -Wrange-loop-construct warning because the
is_trivially_xible check uses `const pair<int>` which makes it seem
like `pair<T>::pair(const pair<_U1> &&)` would actually be used,
which is non-trivial, while the loop would actually use a trivial
copy.  Fixed by using `const pair<int> &` for the is_trivially_xible
check.

PR c++/125697

gcc/cp/ChangeLog:

* cp-tree.h (trivially_copy_constructible_p): Declare.
* parser.cc (warn_for_range_copy): Use it.
* reflect.cc (eval_is_trivially_copy_constructible_type): Use it.
* tree.cc (trivially_copy_constructible_p): New.

gcc/ChangeLog:

* doc/invoke.texi: Clarify -Wrange-loop-construct description.

gcc/testsuite/ChangeLog:

* g++.dg/warn/Wrange-loop-construct4.C: New test.

Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/cp-tree.h
gcc/cp/parser.cc
gcc/cp/reflect.cc
gcc/cp/tree.cc
gcc/doc/invoke.texi
gcc/testsuite/g++.dg/warn/Wrange-loop-construct4.C [new file with mode: 0644]

index 6df271d5e3596bda3ff768da3e858476cb240acb..132139f9d52025416e7872ca45369cdc78eee133 100644 (file)
@@ -8749,6 +8749,7 @@ extern bool std_layout_type_p                     (const_tree);
 extern bool trivial_type_p                     (const_tree);
 extern bool implicit_lifetime_type_p           (tree);
 extern bool trivially_copyable_p               (const_tree);
+extern bool trivially_copy_constructible_p     (tree);
 extern bool has_trivial_abi_attribute          (tree);
 extern void validate_trivial_abi_attribute     (tree);
 extern bool type_has_unique_obj_representations (const_tree, bool = false);
index 38b5bd3e1ce4fd8ac88425d00317702822cc407f..1ce591666fe39444dec1e4a180eca80e6130e864 100644 (file)
@@ -16015,11 +16015,9 @@ warn_for_range_copy (tree decl, tree expr)
 
   /* 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 vec = make_tree_vec (1);
-  TREE_VEC_ELT (vec, 0) = TREE_TYPE (expr);
   if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST
       || (tree_to_uhwi (TYPE_SIZE_UNIT (type)) <= 64
-         && is_trivially_xible (INIT_EXPR, type, vec)))
+         && trivially_copy_constructible_p (type)))
     return;
 
   /* If we can initialize a reference directly, suggest that to avoid the
index f15be65c2466c26a14d189bd82ea6197167f9e2c..bf1c41772d34ee8956adaa5b6808abe188eb297e 100644 (file)
@@ -4661,10 +4661,7 @@ eval_is_trivially_default_constructible_type (tree type)
 static tree
 eval_is_trivially_copy_constructible_type (tree type)
 {
-  tree arg = make_tree_vec (1);
-  TREE_VEC_ELT (arg, 0)
-    = build_stub_type (type, cp_type_quals (type) | TYPE_QUAL_CONST, false);
-  if (is_trivially_xible (INIT_EXPR, type, arg))
+  if (trivially_copy_constructible_p (type))
     return boolean_true_node;
   else
     return boolean_false_node;
index a99f5e19c0d88cf5f3b3b4cdde5fd74bfbc9ddc9..d9a0583b8b834920a820cad62fbffecee7631bcd 100644 (file)
@@ -4909,6 +4909,17 @@ trivial_type_p (const_tree t)
     return scalarish_type_p (t);
 }
 
+/* Returns true iff type T is a trivially copy constructible type.  */
+
+bool
+trivially_copy_constructible_p (tree t)
+{
+  tree arg = make_tree_vec (1);
+  TREE_VEC_ELT (arg, 0)
+    = build_stub_type (t, cp_type_quals (t) | TYPE_QUAL_CONST, false);
+  return is_trivially_xible (INIT_EXPR, t, arg);
+}
+
 /* Returns 1 iff type T is an implicit-lifetime type, as defined in
    [basic.types.general] and [class.prop].  */
 
index 76fae1da0bb38dfbc55e999907391451a25884be..06399e3b903cc42e41bb4f3baaf1c972927984dd 100644 (file)
@@ -4517,8 +4517,8 @@ void fn () @{
 @}
 @end smallexample
 
-It does not warn when the type being copied is a trivially-copyable type whose
-size is less than 64 bytes.
+It does not warn when the type being copied is a trivially copy constructible
+type whose size is less than 64 bytes.
 
 This warning also warns when a loop variable in a range-based for-loop is
 initialized with a value of a different type resulting in a copy.  For example:
diff --git a/gcc/testsuite/g++.dg/warn/Wrange-loop-construct4.C b/gcc/testsuite/g++.dg/warn/Wrange-loop-construct4.C
new file mode 100644 (file)
index 0000000..2d79278
--- /dev/null
@@ -0,0 +1,47 @@
+// PR c++/125697
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wrange-loop-construct" }
+
+template <typename> struct pair {
+  int first;
+  int second;
+  template <typename _U1> pair(const pair<_U1> &&);
+};
+void
+foo (const pair<int> (&arr)[1])
+{
+  for (const auto x : arr)  // { dg-bogus "creates a copy" }
+    (void) x;
+}
+static_assert(__is_trivially_copyable(pair<int>));
+static_assert(!__is_trivially_constructible(pair<int>));
+
+template <typename> struct pairbig {
+  int first;
+  int second;
+  char arr[64];
+  template <typename _U1> pairbig(const pairbig<_U1> &&);
+};
+void
+bar (const pairbig<int> (&arr)[1])
+{
+  for (const auto x : arr)  // { dg-warning "creates a copy" }
+    (void) x;
+}
+static_assert(__is_trivially_copyable(pairbig<int>));
+static_assert(!__is_trivially_constructible(pairbig<int>));
+
+template <typename> struct pairnontriv {
+  int first;
+  int second;
+  pairnontriv(const pairnontriv &);
+  template <typename _U1> pairnontriv(const pairnontriv<_U1> &&);
+};
+void
+baz (const pairnontriv<int> (&arr)[1])
+{
+  for (const auto x : arr)  // { dg-warning "creates a copy" }
+    (void) x;
+}
+static_assert(!__is_trivially_copyable(pairnontriv<int>));
+static_assert(!__is_trivially_constructible(pairnontriv<int>));