OSDN Git Service

cp:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 16 Mar 2003 14:36:43 +0000 (14:36 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 16 Mar 2003 14:36:43 +0000 (14:36 +0000)
PR c++/9629
* cp-tree.h (struct language_function): Add in_base_initializer.
(in_base_initializer): define it.
(expand_member_init): Remove INIT param.
* init.c (expand_member_init): Remove INIT param, return the member.
(emit_mem_initializers): Set in_base_initializer.
* class.c (build_base_path): Check in_base_initializer.
* parser.c (cp_parser_mem_initializer): Set in_base_initializer.
* pt.c (tsubst_initializer_list): Likewise.
testsuite:
PR c++/9629
* g++.dg/init/ctor2.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@64438 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/init.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/ctor2.C [new file with mode: 0644]

index 7cb5c9f..4a240a0 100644 (file)
@@ -1,3 +1,15 @@
+2003-03-16  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/9629
+       * cp-tree.h (struct language_function): Add in_base_initializer.
+       (in_base_initializer): define it.
+       (expand_member_init): Remove INIT param.
+       * init.c (expand_member_init): Remove INIT param, return the member.
+       (emit_mem_initializers): Set in_base_initializer.
+       * class.c (build_base_path): Check in_base_initializer.
+       * parser.c (cp_parser_mem_initializer): Set in_base_initializer.
+       * pt.c (tsubst_initializer_list): Likewise.
+
 2003-03-16   Gabriel Dos Reis <gdr@integrable-solutions.net>
 
        * decl.c (binding_for_name): Fix initialization thinko.
 
 2003-02-21  Nathan Sidwell  <nathan@codesourcery.com>
 
-       * search.c (bfs_walk_grow): Remove. Fold into ...
+       * search.c (grow_bfs_bases): Remove. Fold into ...
        (bfs_walk): ... here, fix fencepost error. Fix merge lossage
        in previous patch.
 
index 6b89bec..0df87ae 100644 (file)
@@ -302,8 +302,25 @@ build_base_path (enum tree_code code,
       /* Going via virtual base V_BINFO.  We need the static offset
          from V_BINFO to BINFO, and the dynamic offset from D_BINFO to
          V_BINFO.  That offset is an entry in D_BINFO's vtable.  */
-      tree v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
-                                       TREE_TYPE (TREE_TYPE (expr)));
+      tree v_offset;
+
+      if (fixed_type_p < 0 && in_base_initializer)
+       {
+         /* In a base member initializer, we cannot rely on
+            the vtable being set up. We have to use the vtt_parm.  */
+         tree derived = BINFO_INHERITANCE_CHAIN (v_binfo);
+         
+         v_offset = build (PLUS_EXPR, TREE_TYPE (current_vtt_parm),
+                           current_vtt_parm, BINFO_VPTR_INDEX (derived));
+         
+         v_offset = build1 (INDIRECT_REF,
+                            TREE_TYPE (TYPE_VFIELD (BINFO_TYPE (derived))),
+                            v_offset);
+         
+       }
+      else
+       v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
+                                    TREE_TYPE (TREE_TYPE (expr)));
       
       v_offset = build (PLUS_EXPR, TREE_TYPE (v_offset),
                        v_offset,  BINFO_VPTR_FIELD (v_binfo));
index 59699cd..587acbc 100644 (file)
@@ -866,6 +866,7 @@ struct language_function GTY(())
   int returns_null;
   int returns_abnormally;
   int in_function_try_handler;
+  int in_base_initializer;
   int x_expanding_p;
 
   struct named_label_use_list *x_named_label_uses;
@@ -936,6 +937,9 @@ struct language_function GTY(())
 
 #define doing_semantic_analysis_p() (!expanding_p)
 
+/* Non-zero if we are processing a base initializer.  Zero elsewhere.  */
+#define in_base_initializer cp_function_chain->in_base_initializer
+
 #define in_function_try_handler cp_function_chain->in_function_try_handler
 
 /* Expression always returned from function, or error_mark_node
@@ -3915,7 +3919,7 @@ extern void add_friend                          (tree, tree);
 extern tree do_friend                          (tree, tree, tree, tree, tree, enum overload_flags, tree, int);
 
 /* in init.c */
-extern tree expand_member_init                 (tree, tree);
+extern tree expand_member_init                 (tree);
 extern void emit_mem_initializers              (tree);
 extern tree build_aggr_init                    (tree, tree, int);
 extern tree build_init                         (tree, tree, int);
index 99812c6..d854283 100644 (file)
@@ -146,7 +146,7 @@ initialize_vtbl_ptrs (addr)
   list = build_tree_list (type, addr);
 
   /* Walk through the hierarchy, initializing the vptr in each base
-     class.  We do these in pre-order because can't find the virtual
+     class.  We do these in pre-order because we can't find the virtual
      bases for a class until we've initialized the vtbl for that
      class.  */
   dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs,
@@ -664,6 +664,8 @@ emit_mem_initializers (tree mem_inits)
      initializations should be performed.  */
   mem_inits = sort_mem_initializers (current_class_type, mem_inits);
 
+  in_base_initializer = 1;
+  
   /* Initialize base classes.  */
   while (mem_inits 
         && TREE_CODE (TREE_PURPOSE (mem_inits)) != FIELD_DECL)
@@ -704,10 +706,11 @@ emit_mem_initializers (tree mem_inits)
 
       mem_inits = TREE_CHAIN (mem_inits);
     }
+  in_base_initializer = 0;
 
   /* Initialize the vptrs.  */
   initialize_vtbl_ptrs (current_class_ptr);
-
+  
   /* Initialize the data members.  */
   while (mem_inits)
     {
@@ -951,16 +954,15 @@ member_init_ok_or_else (field, type, member_name)
 
 /* NAME is a FIELD_DECL, an IDENTIFIER_NODE which names a field, or it
    is a _TYPE node or TYPE_DECL which names a base for that type.
-   INIT is a parameter list for that field's or base's constructor.
-   Check the validity of NAME, and return a TREE_LIST of the base
-   _TYPE or FIELD_DECL and the INIT.  If NAME is invalid, return
+   Check the validity of NAME, and return either the base _TYPE, base
+   binfo, or the FIELD_DECL of the member.  If NAME is invalid, return
    NULL_TREE and issue a diagnostic.
 
    An old style unnamed direct single base construction is permitted,
    where NAME is NULL.  */
 
 tree
-expand_member_init (tree name, tree init)
+expand_member_init (tree name)
 {
   tree basetype;
   tree field;
@@ -997,14 +999,12 @@ expand_member_init (tree name, tree init)
   else
     basetype = NULL_TREE;
 
-  my_friendly_assert (init != NULL_TREE, 0);
-
   if (basetype)
     {
       tree binfo;
 
       if (current_template_parms)
-       return build_tree_list (basetype, init);
+       return basetype;
 
       binfo = lookup_base (current_class_type, basetype, 
                           ba_ignore, NULL);
@@ -1020,7 +1020,7 @@ expand_member_init (tree name, tree init)
                   name, current_class_type);
          return NULL_TREE;
        }
-      return build_tree_list (binfo, init);
+      return binfo;
     }
   else
     {
@@ -1030,7 +1030,7 @@ expand_member_init (tree name, tree init)
        field = name;
 
       if (member_init_ok_or_else (field, current_class_type, name))
-       return build_tree_list (field, init);
+       return field;
     }
 
   return NULL_TREE;
index 1c83227..f80c260 100644 (file)
@@ -7236,7 +7236,8 @@ cp_parser_mem_initializer (cp_parser* parser)
 {
   tree mem_initializer_id;
   tree expression_list;
-
+  tree member;
+  
   /* Find out what is being initialized.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
@@ -7245,6 +7246,10 @@ cp_parser_mem_initializer (cp_parser* parser)
     }
   else
     mem_initializer_id = cp_parser_mem_initializer_id (parser);
+  member = expand_member_init (mem_initializer_id);
+  if (member && !DECL_P (member))
+    in_base_initializer = 1;
+  
   /* Look for the opening `('.  */
   cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
   /* Parse the expression-list.  */
@@ -7256,8 +7261,9 @@ cp_parser_mem_initializer (cp_parser* parser)
   /* Look for the closing `)'.  */
   cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
 
-  return expand_member_init (mem_initializer_id,
-                            expression_list);
+  in_base_initializer = 0;
+  
+  return member ? build_tree_list (member, expression_list) : NULL_TREE;
 }
 
 /* Parse a mem-initializer-id.
index 410cd8f..87430b6 100644 (file)
@@ -11093,9 +11093,12 @@ tsubst_initializer_list (t, argvec)
 
       decl = tsubst_copy (TREE_PURPOSE (t), argvec, tf_error | tf_warning,
                          NULL_TREE);
+      decl = expand_member_init (decl);
+      if (decl && !DECL_P (decl))
+       in_base_initializer = 1;
+      
       init = tsubst_expr (TREE_VALUE (t), argvec, tf_error | tf_warning,
                          NULL_TREE);
-
       if (!init)
        ;
       else if (TREE_CODE (init) == TREE_LIST)
@@ -11104,9 +11107,11 @@ tsubst_initializer_list (t, argvec)
       else if (init != void_type_node)
        init = convert_from_reference (init);
 
-      init = expand_member_init (decl, init);
-      if (init)
+      in_base_initializer = 0;
+
+      if (decl)
        {
+         init = build_tree_list (decl, init);
          TREE_CHAIN (init) = inits;
          inits = init;
        }
index 92db48b..d4558f6 100644 (file)
@@ -1,3 +1,8 @@
+2003-03-16  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/9629
+       * g++.dg/init/ctor2.C: New test.
+
 2003-03-15  Roger Sayle  <roger@eyesopen.com>
 
        * g77.f-torture/compile/xformat.f: New test case.
diff --git a/gcc/testsuite/g++.dg/init/ctor2.C b/gcc/testsuite/g++.dg/init/ctor2.C
new file mode 100644 (file)
index 0000000..cf426f2
--- /dev/null
@@ -0,0 +1,34 @@
+// { dg-do run }
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 14 Mar 2003 <nathan@codesourcery.com>
+
+// PR 9629. The vtable is not set up until the base initializers have
+// run.
+
+struct A {
+  static A *a;
+  A ();
+};
+A *A::a;
+A::A () {a = this;}
+
+struct B {
+  static A *a;
+  B (A *);
+};
+A *B::a;
+B::B(A *a_) {a = a_;}
+
+struct C : virtual public A, public B {
+  C();
+};
+C::C () : B(this) {}
+
+struct D : virtual public C {};
+
+int main()
+{
+  new D();
+  return A::a != B::a;
+}