re PR c++/91606 (Optimization leads to invalid code)
authorRichard Biener <rguenther@suse.de>
Wed, 2 Oct 2019 10:54:10 +0000 (10:54 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Wed, 2 Oct 2019 10:54:10 +0000 (10:54 +0000)
2019-10-02  Richard Biener  <rguenther@suse.de>

PR c++/91606
* decl.c (build_ptrmemfunc_type): Mark pointer-to-member
fat pointer structure members as DECL_NONADDRESSABLE_P.

* g++.dg/torture/pr91606.C: New testcase.

From-SVN: r276448

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr91606.C [new file with mode: 0644]

index a1e520a..bac74fe 100644 (file)
@@ -1,3 +1,9 @@
+2019-10-02  Richard Biener  <rguenther@suse.de>
+
+       PR c++/91606
+       * decl.c (build_ptrmemfunc_type): Mark pointer-to-member
+       fat pointer structure members as DECL_NONADDRESSABLE_P.
+
 2019-09-28  Marek Polacek  <polacek@redhat.com>
 
        PR c++/91889 - follow-up fix for DR 2352.
index 67c4521..c96294f 100644 (file)
@@ -9665,10 +9665,12 @@ build_ptrmemfunc_type (tree type)
   TYPE_PTRMEMFUNC_FLAG (t) = 1;
 
   field = build_decl (input_location, FIELD_DECL, pfn_identifier, type);
+  DECL_NONADDRESSABLE_P (field) = 1;
   fields = field;
 
   field = build_decl (input_location, FIELD_DECL, delta_identifier, 
                      delta_type_node);
+  DECL_NONADDRESSABLE_P (field) = 1;
   DECL_CHAIN (field) = fields;
   fields = field;
 
index a5a1cf3..3fbed65 100644 (file)
@@ -1,3 +1,8 @@
+2019-10-02  Richard Biener  <rguenther@suse.de>
+
+       PR c++/91606
+       * g++.dg/torture/pr91606.C: New testcase.
+
 2019-10-02  Tobias Burnus  <tobias@codesourcery.com>
 
        * gfortran.dg/goacc/asyncwait-1.f95: Handle new error message.
diff --git a/gcc/testsuite/g++.dg/torture/pr91606.C b/gcc/testsuite/g++.dg/torture/pr91606.C
new file mode 100644 (file)
index 0000000..37a05a5
--- /dev/null
@@ -0,0 +1,109 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fstrict-aliasing" } */
+
+#include <cstdlib>
+#include <array>
+#include <type_traits>
+
+template <typename T1, typename T2>
+struct variant
+{
+  constexpr variant(T1 arg)
+      : f1(arg),
+      index(0)
+  {}
+
+  constexpr variant(T2 arg)
+      : f2(arg),
+      index(1)
+  {}
+
+  union
+    {
+      T1 f1;
+      T2 f2;
+    };
+  std::size_t index = 0;
+};
+
+template <typename T1, typename T2>
+constexpr const T1* get_if(const variant<T1, T2>* v)
+{
+  if (v->index != 0)
+    {
+      return nullptr;
+    }
+  return &v->f1;
+}
+
+template <typename T2, typename T1>
+constexpr const T2* get_if(const variant<T1, T2>* v)
+{
+  if (v->index != 1)
+    {
+      return nullptr;
+    }
+  return &v->f2;
+}
+
+template <typename T, size_t N>
+struct my_array
+{
+  constexpr const T* begin() const
+    {
+      return data;
+    }
+
+  constexpr const T* end() const
+    {
+      return data + N;
+    }
+
+  T data[N];
+};
+
+template <typename ...Ts>
+constexpr auto get_array_of_variants(Ts ...ptrs)
+{
+  return std::array<variant<std::decay_t<Ts>...>, sizeof...(Ts)>{ ptrs... };
+}
+
+template <typename T>
+constexpr auto get_member_functions();
+
+template <typename Member, typename Class>
+constexpr int getFuncId(Member (Class::*memFuncPtr))
+{
+  int idx = 0u;
+  for (auto &anyFunc : get_member_functions<Class>())
+    {
+      if (auto *specificFunc = get_if<Member (Class::*)>(&anyFunc))
+       {
+         if (*specificFunc == memFuncPtr)
+           {
+             return idx;
+           }
+       }
+      ++idx;
+    }
+  std::abort();
+}
+
+struct MyStruct
+{
+  void fun1(int /*a*/) {}
+
+  int fun2(char /*b*/, short /*c*/, bool /*d*/) { return 0; }
+
+};
+
+template <>
+constexpr auto get_member_functions<MyStruct>()
+{
+  return get_array_of_variants(&MyStruct::fun1, &MyStruct::fun2);
+}
+
+int main()
+{
+  return getFuncId(&MyStruct::fun1);
+}