aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2006-01-22 00:42:40 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2006-01-22 00:42:40 +0000
commit0e686aa6f7af3db2a7fc3a8f988d14d4e75282f4 (patch)
tree34bf7e47e301d282bde70b7e5eec5fcaa0d764a1
parent5826ba2218e090eeb05a7e60bd88305b1dd250a1 (diff)
downloadgcc-0e686aa6f7af3db2a7fc3a8f988d14d4e75282f4.zip
gcc-0e686aa6f7af3db2a7fc3a8f988d14d4e75282f4.tar.gz
gcc-0e686aa6f7af3db2a7fc3a8f988d14d4e75282f4.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog13
-rw-r--r--gcc/cp/class.c16
-rw-r--r--gcc/cp/decl.c29
-rw-r--r--gcc/cp/parser.c30
-rw-r--r--gcc/testsuite/ChangeLog11
-rw-r--r--gcc/testsuite/g++.dg/inherit/conv2.C22
-rw-r--r--gcc/testsuite/g++.dg/parse/dtor7.C4
-rw-r--r--gcc/testsuite/g++.dg/template/crash44.C7
8 files changed, 102 insertions, 30 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 42c69e8..ea7355b 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 bd89b55..6b075cb 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 ae0b7e8..3c98d49 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 148eb1d..4c09b2f 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 7c28e0e..07aa699 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 0000000..fd00838
--- /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 0000000..3525624
--- /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 0000000..d5596c1
--- /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" }