This patch adds minimal type merging.  It unifies the existence of
types for a struct decl.  The method is to emit a merge key for the
type when we emit a merge key for the struct decl.

Test x4structover1.cc is now passing.

The next step is to merge struct definitions.  For that we have test
cases x*incomplete*, which progressively add more information to the
classes in different configurations of pph files.

Tested on x64.


Index: gcc/testsuite/ChangeLog.pph

2012-02-01   Lawrence Crowl  <cr...@google.com>

        * g++.dg/pph/x4structover1.cc: Mark fixed.
        * g++.dg/pph/a0incomplete2.hi: New.
        * g++.dg/pph/a0incomplete3.hi: New.
        * g++.dg/pph/a0incomplete4.cci: New.
        * g++.dg/pph/x0incomplete1.h: New.
        * g++.dg/pph/x0incomplete2.h: New.
        * g++.dg/pph/x0incomplete3.h: New.
        * g++.dg/pph/x1incomplete3.h: New.
        * g++.dg/pph/x1incomplete4.cc: New.
        * g++.dg/pph/x2incomplete4.cc: New.
        * g++.dg/pph/x3incomplete412.cc: New.
        * g++.dg/pph/x3incomplete413.cc: New.
        * g++.dg/pph/x4incomplete4123.cc: New.
        * g++.dg/pph/x4incomplete4321.cc: New.

Index: gcc/cp/ChangeLog.pph

2012-02-01   Lawrence Crowl  <cr...@google.com>

        * error.c (dump_function_decl):  Add protection against NULL.
        * pph-out.c (pph_out_merge_key_tree):  Write merge keys for struct
        types, as opposed to decls.
        * pph-in.c (pph_in_merge_tree_body):  Save chains in decls only.
        (pph_in_merge_key_tree): Read merge keys for struct types.  Split
        handling into two phases, cache insertion (which is before the trace
        front) and sub-tree reading.


Index: gcc/testsuite/g++.dg/pph/x1incomplete3.h
===================================================================
--- gcc/testsuite/g++.dg/pph/x1incomplete3.h    (revision 0)
+++ gcc/testsuite/g++.dg/pph/x1incomplete3.h    (revision 0)
@@ -0,0 +1,7 @@
+#ifndef X0INCOMPLETE3_H
+#define X0INCOMPLETE3_H
+
+#include "x0incomplete2.h"
+#include "a0incomplete3.hi"
+
+#endif
Index: gcc/testsuite/g++.dg/pph/x0incomplete2.h
===================================================================
--- gcc/testsuite/g++.dg/pph/x0incomplete2.h    (revision 0)
+++ gcc/testsuite/g++.dg/pph/x0incomplete2.h    (revision 0)
@@ -0,0 +1,6 @@
+#ifndef X0INCOMPLETE2_H
+#define X0INCOMPLETE2_H
+
+#include "a0incomplete2.hi"
+
+#endif
Index: gcc/testsuite/g++.dg/pph/x2incomplete4.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x2incomplete4.cc   (revision 0)
+++ gcc/testsuite/g++.dg/pph/x2incomplete4.cc   (revision 0)
@@ -0,0 +1,5 @@
+// { dg-xfail-if "ICE" { "*-*-*" } { "-fpph-map=pph.map" } }
+// { dg-bogus "internal compiler error: in import_export_decl, at cp/decl2.c" 
"" { xfail *-*-* } 0 }
+
+#include "x1incomplete3.h"
+#include "a0incomplete4.cci"
Index: gcc/testsuite/g++.dg/pph/x0incomplete3.h
===================================================================
--- gcc/testsuite/g++.dg/pph/x0incomplete3.h    (revision 0)
+++ gcc/testsuite/g++.dg/pph/x0incomplete3.h    (revision 0)
@@ -0,0 +1,7 @@
+#ifndef X0INCOMPLETE3_H
+#define X0INCOMPLETE3_H
+
+#include "a0incomplete2.hi"
+#include "a0incomplete3.hi"
+
+#endif
Index: gcc/testsuite/g++.dg/pph/x1incomplete4.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x1incomplete4.cc   (revision 0)
+++ gcc/testsuite/g++.dg/pph/x1incomplete4.cc   (revision 0)
@@ -0,0 +1,2 @@
+#include "x0incomplete3.h"
+#include "a0incomplete4.cci"
Index: gcc/testsuite/g++.dg/pph/a0incomplete4.cci
===================================================================
--- gcc/testsuite/g++.dg/pph/a0incomplete4.cci  (revision 0)
+++ gcc/testsuite/g++.dg/pph/a0incomplete4.cci  (revision 0)
@@ -0,0 +1,5 @@
+int query( copies arg )
+{
+    copies var( arg );
+    return var.value();
+}
Index: gcc/testsuite/g++.dg/pph/x4incomplete4123.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x4incomplete4123.cc        (revision 0)
+++ gcc/testsuite/g++.dg/pph/x4incomplete4123.cc        (revision 0)
@@ -0,0 +1,4 @@
+#include "x0incomplete1.h"
+#include "x0incomplete2.h"
+#include "x0incomplete3.h"
+#include "a0incomplete4.cci"
Index: gcc/testsuite/g++.dg/pph/x3incomplete412.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x3incomplete412.cc (revision 0)
+++ gcc/testsuite/g++.dg/pph/x3incomplete412.cc (revision 0)
@@ -0,0 +1,4 @@
+#include "x0incomplete1.h"
+#include "x0incomplete2.h"
+#include "a0incomplete3.hi"
+#include "a0incomplete4.cci"
Index: gcc/testsuite/g++.dg/pph/a0incomplete2.hi
===================================================================
--- gcc/testsuite/g++.dg/pph/a0incomplete2.hi   (revision 0)
+++ gcc/testsuite/g++.dg/pph/a0incomplete2.hi   (revision 0)
@@ -0,0 +1,12 @@
+#ifndef A0INCOMPLETE2_HI
+#define A0INCOMPLETE2_HI
+
+struct copies
+{
+    copies();
+    copies( const copies &arg );
+    int value();
+    int field;
+};
+
+#endif
Index: gcc/testsuite/g++.dg/pph/x4structover1.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x4structover1.cc   (revision 183821)
+++ gcc/testsuite/g++.dg/pph/x4structover1.cc   (working copy)
@@ -1,7 +1,3 @@
-// { dg-xfail-if "BOGUS TYPE MERGE" { "*-*-*" } { "-fpph-map=pph.map" } }
-// This test fails because even if we merge type decls,
-// we are not merging the corresponding types.
-
 #include "x0structover1.h"
 #include "x0structover2.h"
 
Index: gcc/testsuite/g++.dg/pph/x4incomplete4321.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x4incomplete4321.cc        (revision 0)
+++ gcc/testsuite/g++.dg/pph/x4incomplete4321.cc        (revision 0)
@@ -0,0 +1,7 @@
+// pph asm xdiff 64351
+// XFAIL missing constructors
+
+#include "x0incomplete3.h"
+#include "x0incomplete2.h"
+#include "x0incomplete1.h"
+#include "a0incomplete4.cci"
Index: gcc/testsuite/g++.dg/pph/x3incomplete413.cc
===================================================================
--- gcc/testsuite/g++.dg/pph/x3incomplete413.cc (revision 0)
+++ gcc/testsuite/g++.dg/pph/x3incomplete413.cc (revision 0)
@@ -0,0 +1,3 @@
+#include "x0incomplete1.h"
+#include "x0incomplete3.h"
+#include "a0incomplete4.cci"
Index: gcc/testsuite/g++.dg/pph/a0incomplete3.hi
===================================================================
--- gcc/testsuite/g++.dg/pph/a0incomplete3.hi   (revision 0)
+++ gcc/testsuite/g++.dg/pph/a0incomplete3.hi   (revision 0)
@@ -0,0 +1,21 @@
+#ifndef A0INCOMPLETE3_HI
+#define A0INCOMPLETE3_HI
+
+inline copies::copies()
+:
+   field( 0 )
+{
+}
+
+inline copies::copies( const copies &arg )
+:
+   field( arg.field + 1 )
+{
+}
+
+inline int copies::value()
+{
+    return field;
+}
+
+#endif
Index: gcc/testsuite/g++.dg/pph/x0incomplete1.h
===================================================================
--- gcc/testsuite/g++.dg/pph/x0incomplete1.h    (revision 0)
+++ gcc/testsuite/g++.dg/pph/x0incomplete1.h    (revision 0)
@@ -0,0 +1,6 @@
+#ifndef X0INCOMPLETE1_H
+#define X0INCOMPLETE1_H
+
+struct stuff;
+
+#endif
Index: gcc/cp/error.c
===================================================================
--- gcc/cp/error.c      (revision 183821)
+++ gcc/cp/error.c      (working copy)
@@ -1351,7 +1351,7 @@ static void
 dump_function_decl (tree t, int flags)
 {
   tree fntype;
-  tree parmtypes;
+  tree parmtypes, argtypes;
   tree cname = NULL_TREE;
   tree template_args = NULL_TREE;
   tree template_parms = NULL_TREE;
@@ -1393,7 +1393,12 @@ dump_function_decl (tree t, int flags)
     }
 
   fntype = TREE_TYPE (t);
-  parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);
+  gcc_assert (fntype)
+  argtypes = TYPE_ARG_TYPES (fntype);
+  if (argtypes)
+    parmtypes = skip_artificial_parms_for (t, argtypes);
+  else
+    parmtypes = NULL;
 
   if (DECL_CLASS_SCOPE_P (t))
     cname = DECL_CONTEXT (t);
Index: gcc/cp/pph-out.c
===================================================================
--- gcc/cp/pph-out.c    (revision 183821)
+++ gcc/cp/pph-out.c    (working copy)
@@ -2353,11 +2353,19 @@ pph_out_merge_key_tree (pph_stream *stre
       /* Write the merge name, used to lookup EXPR in the reader's context
         and merge if necessary.  */
       pph_out_merge_name (stream, expr);
+
+      if (TREE_CODE (expr) == TYPE_DECL)
+       {
+         bool is_implicit = DECL_IMPLICIT_TYPEDEF_P (expr);
+         tree type = TREE_TYPE (expr);
+         pph_out_bool (stream, is_implicit);
+         if (is_implicit)
+           pph_out_merge_key_tree (stream, type);
+       }
     }
   else
     {
       gcc_assert (TYPE_P (expr));
-      gcc_assert (false);
     }
 
   if (flag_pph_tracer)
Index: gcc/cp/pph-in.c
===================================================================
--- gcc/cp/pph-in.c     (revision 183821)
+++ gcc/cp/pph-in.c     (working copy)
@@ -2116,11 +2116,6 @@ pph_in_merge_tree_body (pph_stream *stre
   struct lto_input_block *ib = stream->encoder.r.ib;
   struct data_in *data_in = stream->encoder.r.data_in;
 
-  /* If we are reading a merge body, it means that EXPR is already in
-     some chain.  Given that EXPR may now be in a different location
-     in the chain, we need to make sure we do not lose it.  */
-  tree saved_expr_chain = TREE_CHAIN (expr);
-
   /* Read the language-independent parts of EXPR's body.  */
   streamer_read_tree_body (ib, data_in, expr);
 
@@ -2128,7 +2123,15 @@ pph_in_merge_tree_body (pph_stream *stre
   switch (TREE_CODE_CLASS (TREE_CODE (expr)))
     {
       case tcc_declaration:
+       {
+         /* If we are reading a merge body, it means that EXPR is already in
+            some chain.  Given that EXPR may now be in a different location
+            in the chain, we need to make sure we do not lose it.
+            FIXME pph: We should just not save TREE_CHAIN for merge bodies.  */
+         tree saved_expr_chain = TREE_CHAIN (expr);
        pph_in_merge_tcc_declaration (stream, expr);
+         TREE_CHAIN (expr) = saved_expr_chain;
+       }
        break;
 
       case tcc_type:
@@ -2140,10 +2143,6 @@ pph_in_merge_tree_body (pph_stream *stre
                     pph_tree_code_text (TREE_CODE (expr)));
        break;
     }
-
-  /* Restore TREE_CHAIN if necessary.  FIXME pph, we should just not
-     save TREE_CHAIN for merge bodies.  */
-  TREE_CHAIN (expr) = saved_expr_chain;
 }
 
 
@@ -2413,7 +2412,7 @@ pph_in_merge_key_tree (pph_stream *strea
   unsigned image_ix, ix;
   tree read_expr, expr;
   bool fully_read_p;
-  const char *name;
+  const char *name = "?";
 
   marker = pph_in_start_record (stream, &image_ix, &ix, PPH_any_tree);
   if (marker == PPH_RECORD_END)
@@ -2426,36 +2425,52 @@ pph_in_merge_key_tree (pph_stream *strea
      language-independent bitfields for the new tree.  */
   read_expr = pph_in_tree_header (stream, &fully_read_p);
   gcc_assert (!fully_read_p);
+  gcc_assert (chain);
 
   if (DECL_P (read_expr))
     {
-      gcc_assert (chain);
       name = pph_in_string (stream);
       /* If we are merging into an existing CHAIN.  Look for a match in
          CHAIN to READ_EXPR's header.  If we found a match, EXPR will be
          the existing tree that matches READ_EXPR. Otherwise, EXPR is the
          newly allocated READ_EXPR.  */
       expr = pph_merge_into_chain (read_expr, name, chain);
-      gcc_assert (expr != NULL);
-      pph_cache_insert_at (&stream->cache, expr, ix,
-                          pph_tree_code_to_tag (expr));
+    }
+  else
+    {
+      gcc_assert (TYPE_P (read_expr));
+      if (*chain)
+       expr = *chain;
+      else
+       expr = read_expr;
+    }
+  gcc_assert (expr != NULL);
+  pph_cache_insert_at (&stream->cache, expr, ix,
+                      pph_tree_code_to_tag (expr));
 
-      if (flag_pph_tracer)
-        pph_trace_tree (expr, name, pph_trace_front,
-                       expr == read_expr ? pph_trace_unmerged_key
-                                         : pph_trace_merged_key);
+  if (flag_pph_tracer)
+    pph_trace_tree (expr, name, pph_trace_front,
+                   expr == read_expr ? pph_trace_unmerged_key
+                                     : pph_trace_merged_key);
 
-      if (flag_pph_tracer)
-        pph_trace_tree (expr, name, pph_trace_back,
-                       expr == read_expr ? pph_trace_unmerged_key
-                                         : pph_trace_merged_key);
+  if (DECL_P (read_expr))
+    {
+      if (TREE_CODE (expr) == TYPE_DECL)
+       {
+         bool is_implicit = pph_in_bool (stream);
+         if (is_implicit)
+           pph_in_merge_key_tree (stream, &(TREE_TYPE (expr)));
+       }
     }
   else
     {
-      gcc_assert (TYPE_P (read_expr));
-      gcc_assert (false);
     }
 
+  if (flag_pph_tracer)
+    pph_trace_tree (expr, name, pph_trace_back,
+                   expr == read_expr ? pph_trace_unmerged_key
+                                     : pph_trace_merged_key);
+
   return expr;
 }
 

--
This patch is available for review at http://codereview.appspot.com/5620047

Reply via email to