From 0e686aa6f7af3db2a7fc3a8f988d14d4e75282f4 Mon Sep 17 00:00:00 2001
From: Mark Mitchell <mark@codesourcery.com>
Date: Sun, 22 Jan 2006 00:42:40 +0000
Subject: [PATCH] re PR c++/25895 (wrong code with ?: and derived class
 pointers)

	PR c++/25895
	* class.c (build_base_path): Generate a NOP_EXPR instead of a
	COMPONENT_REF if the base and derived classes are at the same
	address.
	PR c++/25856
	* decl.c (begin_destructor_body): Robustify.
	PR c++/25858
	* parser.c (cp_parser_direct_declarator): Robustify.

	PR c++/25895
	* g++.dg/inherit/conv2.C: New test.
	PR c++/25856
	* g++.dg/parse/dtor7.C: New test.
	PR c++/25858
	* g++.dg/template/crash44.C: New test.

From-SVN: r110084
---
 gcc/cp/ChangeLog                        | 13 +++++++++++
 gcc/cp/class.c                          | 16 +++++++++----
 gcc/cp/decl.c                           | 29 ++++++++++++++----------
 gcc/cp/parser.c                         | 30 +++++++++++++------------
 gcc/testsuite/ChangeLog                 | 11 +++++++++
 gcc/testsuite/g++.dg/inherit/conv2.C    | 22 ++++++++++++++++++
 gcc/testsuite/g++.dg/parse/dtor7.C      |  4 ++++
 gcc/testsuite/g++.dg/template/crash44.C |  7 ++++++
 8 files changed, 102 insertions(+), 30 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/inherit/conv2.C
 create mode 100644 gcc/testsuite/g++.dg/parse/dtor7.C
 create mode 100644 gcc/testsuite/g++.dg/template/crash44.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 42c69e8d7b92..ea7355bcccec 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,16 @@
+2006-01-21  Mark Mitchell  <mark@codesourcery.com>
+
+	PR c++/25895
+	* class.c (build_base_path): Generate a NOP_EXPR instead of a
+	COMPONENT_REF if the base and derived classes are at the same
+	address.
+
+	PR c++/25856
+	* decl.c (begin_destructor_body): Robustify.
+
+	PR c++/25858 
+	* parser.c (cp_parser_direct_declarator): Robustify.
+	
 2006-01-20  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
 	* parser.c (cp_lexer_next_token_is_keyword): Simplify.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index bd89b558abda..6b075cbd0b72 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -289,13 +289,23 @@ build_base_path (enum tree_code code,
 
   offset = BINFO_OFFSET (binfo);
   fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
+  target_type = code == PLUS_EXPR ? BINFO_TYPE (binfo) : BINFO_TYPE (d_binfo);
 
   /* Do we need to look in the vtable for the real offset?  */
   virtual_access = (v_binfo && fixed_type_p <= 0);
 
   /* Do we need to check for a null pointer?  */
-  if (want_pointer && !nonnull && (virtual_access || !integer_zerop (offset)))
-    null_test = error_mark_node;
+  if (want_pointer && !nonnull)
+    {
+      /* If we know the conversion will not actually change the value
+	 of EXPR, then we can avoid testing the expression for NULL.
+	 We have to avoid generating a COMPONENT_REF for a base class
+	 field, because other parts of the compiler know that such
+	 expressions are always non-NULL.  */
+      if (!virtual_access && integer_zerop (offset))
+	return build_nop (build_pointer_type (target_type), expr);
+      null_test = error_mark_node;
+    }
 
   /* Protect against multiple evaluation if necessary.  */
   if (TREE_SIDE_EFFECTS (expr) && (null_test || virtual_access))
@@ -376,8 +386,6 @@ build_base_path (enum tree_code code,
 	offset = v_offset;
     }
 
-  target_type = code == PLUS_EXPR ? BINFO_TYPE (binfo) : BINFO_TYPE (d_binfo);
-
   target_type = cp_build_qualified_type
     (target_type, cp_type_quals (TREE_TYPE (TREE_TYPE (expr))));
   ptr_target_type = build_pointer_type (target_type);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index ae0b7e85c441..3c98d4918f23 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -10628,18 +10628,23 @@ begin_destructor_body (void)
 {
   tree compound_stmt;
 
-  compound_stmt = begin_compound_stmt (0);
-
-  /* Make all virtual function table pointers in non-virtual base
-     classes point to CURRENT_CLASS_TYPE's virtual function
-     tables.  */
-  initialize_vtbl_ptrs (current_class_ptr);
-
-  finish_compound_stmt (compound_stmt);
-
-  /* And insert cleanups for our bases and members so that they
-     will be properly destroyed if we throw.  */
-  push_base_cleanups ();
+  /* If the CURRENT_CLASS_TYPE is incomplete, we will have already
+     issued an error message.  We still want to try to process the
+     body of the function, but initialize_vtbl_ptrs will crash if
+     TYPE_BINFO is NULL.  */
+  if (COMPLETE_TYPE_P (current_class_type))
+    {
+      compound_stmt = begin_compound_stmt (0);
+      /* Make all virtual function table pointers in non-virtual base
+	 classes point to CURRENT_CLASS_TYPE's virtual function
+	 tables.  */
+      initialize_vtbl_ptrs (current_class_ptr);
+      finish_compound_stmt (compound_stmt);
+      
+      /* And insert cleanups for our bases and members so that they
+	 will be properly destroyed if we throw.  */
+      push_base_cleanups ();
+    }
 }
 
 /* At the end of every destructor we generate code to delete the object if
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 148eb1d14b3a..4c09b2fde9bf 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11479,22 +11479,24 @@ cp_parser_direct_declarator (cp_parser* parser,
 
 	      if (TREE_CODE (unqualified_name) == TYPE_DECL)
 		{
-		  if (qualifying_scope 
-		      && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (unqualified_name)))
+		  tree name_type = TREE_TYPE (unqualified_name);
+		  if (class_type && same_type_p (name_type, class_type))
 		    {
-		      error ("invalid use of constructor as a template");
-		      inform ("use %<%T::%D%> instead of %<%T::%T%> to name "
-			      "the constructor in a qualified name",
-			      class_type,
-			      DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
-			      class_type, class_type);
-		      declarator = cp_error_declarator;
-		      break;
+		      if (qualifying_scope
+			  && CLASSTYPE_USE_TEMPLATE (name_type))
+			{
+			  error ("invalid use of constructor as a template");
+			  inform ("use %<%T::%D%> instead of %<%T::%D%> to "
+				  "name the constructor in a qualified name",
+				  class_type,
+				  DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
+				  class_type, name_type);
+			  declarator = cp_error_declarator;
+			  break;
+			}
+		      else
+			unqualified_name = constructor_name (class_type);
 		    }
-		  else if (class_type
-			   && same_type_p (TREE_TYPE (unqualified_name),
-					   class_type))
-		    unqualified_name = constructor_name (class_type);
 		  else
 		    {
 		      /* We do not attempt to print the declarator
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7c28e0ee25b0..07aa699ca0c6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,14 @@
+2006-01-21  Mark Mitchell  <mark@codesourcery.com>
+
+	PR c++/25895
+	* g++.dg/inherit/conv2.C: New test.
+
+	PR c++/25856
+	* g++.dg/parse/dtor7.C: New test.
+
+	PR c++/25858
+	* g++.dg/template/crash44.C: New test.
+
 2005-01-21  Paul Thomas  <pault@gcc.gnu.org>
 
 	PR fortran/25124
diff --git a/gcc/testsuite/g++.dg/inherit/conv2.C b/gcc/testsuite/g++.dg/inherit/conv2.C
new file mode 100644
index 000000000000..fd0083825367
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/conv2.C
@@ -0,0 +1,22 @@
+// PR c++/25895
+// { dg-do run }
+
+class base {
+public:
+  base() {}
+private:
+  int val_;
+};
+
+class derived : public base {
+public:
+  derived() {}
+};
+
+static bool x = true ? (derived*)0 : (base*)0;
+
+int main ()
+{
+  if (x)
+    return 1;
+}
diff --git a/gcc/testsuite/g++.dg/parse/dtor7.C b/gcc/testsuite/g++.dg/parse/dtor7.C
new file mode 100644
index 000000000000..3525624e18d3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/dtor7.C
@@ -0,0 +1,4 @@
+// PR c++/25856
+
+struct A; // { dg-error "forward" } 
+A::~A() {} // { dg-error "undefined" }
diff --git a/gcc/testsuite/g++.dg/template/crash44.C b/gcc/testsuite/g++.dg/template/crash44.C
new file mode 100644
index 000000000000..d5596c19977a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/crash44.C
@@ -0,0 +1,7 @@
+// PR c++/25858
+
+namespace N {
+  template<int> struct A {};
+}
+
+struct B N::A<0> {}; // { dg-error "invalid" }
-- 
GitLab