From 539599c198f2f5e445744221058af9d8a7f96a02 Mon Sep 17 00:00:00 2001
From: Mark Mitchell <mark@codesourcery.com>
Date: Thu, 12 Aug 2004 00:43:47 +0000
Subject: [PATCH] re PR c++/16853 (pointer-to-member initialization from
 incompatible one accepted)

	PR c++/16853
	* call.c (standard_conversion): Do not accept conversions between
	pointers to members if the class types are unrelated.

	PR c++/16618
	* parser.c (cp_parser_builtin_offsetof): Cast to "const volatile
	char &" instead of just "char &".

	PR c++/16870
	* pt.c (tsubst): Just return the unknown_type_node.

	PR c++/16853
	* g++.dg/init/ptrmem1.C: New test.

	PR c++/16618
	* g++.dg/parse/offsetof5.C: New test.

	PR c++/16870
	* g++.dg/template/overload3.C: New test.

From-SVN: r85840
---
 gcc/cp/ChangeLog                          | 13 +++++++++++++
 gcc/cp/call.c                             |  2 ++
 gcc/cp/parser.c                           |  7 ++++++-
 gcc/cp/pt.c                               |  1 +
 gcc/testsuite/ChangeLog                   | 11 +++++++++++
 gcc/testsuite/g++.dg/init/ptrmem1.C       |  7 +++++++
 gcc/testsuite/g++.dg/parse/offsetof5.C    | 13 +++++++++++++
 gcc/testsuite/g++.dg/template/overload3.C | 14 ++++++++++++++
 8 files changed, 67 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/init/ptrmem1.C
 create mode 100644 gcc/testsuite/g++.dg/parse/offsetof5.C
 create mode 100644 gcc/testsuite/g++.dg/template/overload3.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d15b6faff70b..3fba6273d48f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,16 @@
+2004-08-11  Mark Mitchell  <mark@codesourcery.com>
+
+	PR c++/16853
+	* call.c (standard_conversion): Do not accept conversions between
+	pointers to members if the class types are unrelated.
+
+	PR c++/16618
+	* parser.c (cp_parser_builtin_offsetof): Cast to "const volatile
+	char &" instead of just "char &".
+
+	PR c++/16870
+	* pt.c (tsubst): Just return the unknown_type_node.
+
 2004-08-11  Mark Mitchell  <mark@codesourcery.com>
 
 	PR c++/16964
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 194b3396db9c..23d65addbddf 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -716,6 +716,8 @@ standard_conversion (tree to, tree from, tree expr)
 					TYPE_PTRMEM_POINTED_TO_TYPE (from));
 	      conv = build_conv (ck_pmem, from, conv);
 	    }
+	  else if (!same_type_p (fbase, tbase))
+	    return NULL;
 	}
       else if (IS_AGGR_TYPE (TREE_TYPE (from))
 	       && IS_AGGR_TYPE (TREE_TYPE (to))
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 65872c8de5e8..a8854dcad2d7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -5859,7 +5859,12 @@ cp_parser_builtin_offsetof (cp_parser *parser)
      we're just mirroring the traditional macro implementation.  Better
      would be to do the lowering of the ADDR_EXPR to flat pointer arithmetic
      here rather than in build_x_unary_op.  */
-  expr = build_reinterpret_cast (build_reference_type (char_type_node), expr);
+  
+  expr = (build_reinterpret_cast 
+	  (build_reference_type (cp_build_qualified_type 
+				 (char_type_node, 
+				  TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)), 
+	   expr));
   expr = build_x_unary_op (ADDR_EXPR, expr);
   expr = build_reinterpret_cast (size_type_node, expr);
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 0574f44f1ad3..516488f0de2f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6706,6 +6706,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
       || t == integer_type_node
       || t == void_type_node
       || t == char_type_node
+      || t == unknown_type_node
       || TREE_CODE (t) == NAMESPACE_DECL)
     return t;
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9959a9d17094..a721a75a0937 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,14 @@
+2004-08-11  Mark Mitchell  <mark@codesourcery.com>
+
+	PR c++/16853
+	* g++.dg/init/ptrmem1.C: New test.
+
+	PR c++/16618
+	* g++.dg/parse/offsetof5.C: New test.
+
+	PR c++/16870
+	* g++.dg/template/overload3.C: New test.
+
 2004-08-11  Mark Mitchell  <mark@codesourcery.com>
 
 	PR c++/16964
diff --git a/gcc/testsuite/g++.dg/init/ptrmem1.C b/gcc/testsuite/g++.dg/init/ptrmem1.C
new file mode 100644
index 000000000000..6f1604fafa6f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/ptrmem1.C
@@ -0,0 +1,7 @@
+// PR c++/16853
+
+struct A {};
+struct B {};
+
+int B::* b;
+int A::* a = b; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/parse/offsetof5.C b/gcc/testsuite/g++.dg/parse/offsetof5.C
new file mode 100644
index 000000000000..553e33ded424
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/offsetof5.C
@@ -0,0 +1,13 @@
+// PR c++/16618
+
+#include <stddef.h>
+
+struct test
+{
+  const char a;
+};
+
+int main()
+{
+  offsetof(test,a);
+}
diff --git a/gcc/testsuite/g++.dg/template/overload3.C b/gcc/testsuite/g++.dg/template/overload3.C
new file mode 100644
index 000000000000..ec48fbb90707
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/overload3.C
@@ -0,0 +1,14 @@
+// PR c++/16870
+
+struct A
+{
+  int operator[](int) const;
+};
+
+template<int> A foo();
+
+A bar(A(*)());
+
+template<int> int baz() { return (bar(&foo<0>))[0]; }
+
+template int baz<0>();