NRVO is incompatible with the transformations made by an allocate
directive, this patch disables it for those variables.

Also adjusts a few tests that were modified to work around this bug.

gcc/cp/ChangeLog:

        * typeck.cc (can_do_nrvo_p): Return false for vars in an allocate
        directive.

gcc/testsuite/ChangeLog:

        * g++.dg/gomp/allocate-5.C: Remove workarounds, enable ilp32.
        * g++.dg/gomp/allocate-6.C: Likewise.
        * g++.dg/gomp/allocate-7.C: Likewise.
        * g++.dg/gomp/allocate-22.C: New test.

Signed-off-by: Waffl3x <[email protected]>
---
 gcc/cp/typeck.cc                        |  5 +++-
 gcc/testsuite/g++.dg/gomp/allocate-22.C | 31 +++++++++++++++++++++++++
 gcc/testsuite/g++.dg/gomp/allocate-5.C  |  3 +--
 gcc/testsuite/g++.dg/gomp/allocate-6.C  |  3 +--
 gcc/testsuite/g++.dg/gomp/allocate-7.C  |  8 ++++---
 5 files changed, 42 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/gomp/allocate-22.C

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index dcc35ae28a2..68a07229ece 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -11164,7 +11164,10 @@ can_do_nrvo_p (tree retval, tree functype)
          && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (retval)),
                          TYPE_MAIN_VARIANT (functype))
          /* And the returned value must be non-volatile.  */
-         && !TYPE_VOLATILE (TREE_TYPE (retval)));
+         && !TYPE_VOLATILE (TREE_TYPE (retval))
+         /* And the variable must not be used in an allocate directive.  */
+         && (!flag_openmp || !lookup_attribute ("omp allocate",
+                                                DECL_ATTRIBUTES (retval))));
 }
 
 /* True if we would like to perform NRVO, i.e. can_do_nrvo_p is true and we
diff --git a/gcc/testsuite/g++.dg/gomp/allocate-22.C 
b/gcc/testsuite/g++.dg/gomp/allocate-22.C
new file mode 100644
index 00000000000..821d9b2c610
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/allocate-22.C
@@ -0,0 +1,31 @@
+/* { dg-do compile { target c++14 } } */
+
+/* This used to ICE due to NRVO being attempted on 's', NRVO can not be
+   done on a variable used in an allocate directive.  */
+
+/* NRVO probably kicks in when sizeof(T) is greater than 16.  */
+struct S
+{
+  char _v[17];
+};
+
+S f0()
+{
+  S s;
+  #pragma omp allocate(s)
+  return s;
+}
+
+/* Also test with a VERY LARGE type just in case the above isn't big enough
+   to trigger NRVO in all cases.  */
+struct Big
+{
+  char _v[4096];
+};
+
+Big f1()
+{
+  Big b;
+  #pragma omp allocate(b)
+  return b;
+}
diff --git a/gcc/testsuite/g++.dg/gomp/allocate-5.C 
b/gcc/testsuite/g++.dg/gomp/allocate-5.C
index 724dd980138..f1085521fc5 100644
--- a/gcc/testsuite/g++.dg/gomp/allocate-5.C
+++ b/gcc/testsuite/g++.dg/gomp/allocate-5.C
@@ -1,5 +1,4 @@
 /* { dg-additional-options "-fdump-tree-gimple" } */
-/* { dg-skip-if "" { ilp32 } } */
 
 #include "allocate-allocator-handle.h"
 
@@ -55,7 +54,7 @@ struct S0 {
 };
 
 struct S1 {
-  int _v[2];
+  int _v[32];
   S1(int v) : _v() {
     int *end = _v + sizeof(_v) / sizeof(*_v);
     for (int *it = _v; it != end; ++it)
diff --git a/gcc/testsuite/g++.dg/gomp/allocate-6.C 
b/gcc/testsuite/g++.dg/gomp/allocate-6.C
index eb0c78a24db..d33b7d53097 100644
--- a/gcc/testsuite/g++.dg/gomp/allocate-6.C
+++ b/gcc/testsuite/g++.dg/gomp/allocate-6.C
@@ -1,5 +1,4 @@
 /* { dg-do compile { target c++11 } } */
-/* { dg-skip-if "" { ilp32 } } */
 /* { dg-additional-options "-fdump-tree-gimple" } */
 
 #include "allocate-allocator-handle.h"
@@ -23,7 +22,7 @@ struct S0 {
 };
 
 struct S1 {
-  int _v[2];
+  int _v[32];
   S1(int v) : _v() {
     int *end = _v + sizeof(_v) / sizeof(*_v);
     for (int *it = _v; it != end; ++it)
diff --git a/gcc/testsuite/g++.dg/gomp/allocate-7.C 
b/gcc/testsuite/g++.dg/gomp/allocate-7.C
index 01fc5b84014..16cc5843d1b 100644
--- a/gcc/testsuite/g++.dg/gomp/allocate-7.C
+++ b/gcc/testsuite/g++.dg/gomp/allocate-7.C
@@ -1,5 +1,4 @@
 /* { dg-do compile { target c++20 } } */
-/* { dg-skip-if "" { ilp32 } } */
 /* { dg-additional-options "-fdump-tree-gimple" } */
 
 #include "allocate-allocator-handle.h"
@@ -37,8 +36,11 @@ struct S0 {
 };
 
 struct S1 {
-  int _v[2];
-  S1(int v) : _v{v, v} {}
+  int _v[32];
+  S1(int v) : _v{v, v, v, v, v, v, v, v,
+                v, v, v, v, v, v, v, v,
+                v, v, v, v, v, v, v, v,
+                v, v, v, v, v, v, v, v} {}
   operator int() const { return 42; }
 };
 
-- 
2.54.0

Reply via email to