[PATCH] Fix PR91606

Richard Biener rguenther@suse.de
Wed Oct 2 10:07:00 GMT 2019


A middle-end change exposed that the C++ FE handling of pointer-to-member
aggregates in cxx_get_alias_set isn't effective.  The following patch
makes it so by design by marking the structure members as not being
aliased (there can be no pointers like &x.__pfn or &x.__delta) thus
making them behave like fat pointers.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

OK for trunk and affected branches?

Thanks,
Richard.

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.

Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	(revision 276396)
+++ gcc/cp/decl.c	(working copy)
@@ -9554,10 +9554,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: gcc/testsuite/g++.dg/torture/pr91606.C
===================================================================
--- gcc/testsuite/g++.dg/torture/pr91606.C	(revision 0)
+++ gcc/testsuite/g++.dg/torture/pr91606.C	(working copy)
@@ -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);
+}



More information about the Gcc-patches mailing list