Disable warning when a system header is a primary compilation file.
This change is necessary when creating a PPH file from a system
header.  The change adds and option -fprimary-system-header-okay and
implicitly sets it when a PPH output file is specified.  Added tests
x0sysheader.h and x1sysheader.cc.

Prepare for merging the lang_type in classes to support merging
types nested within classes.  The change adds some merging routines,
but only the bitsets are actually merged, and there is no effect
on existing tests.  Added tests x0neststruct1.h, x0neststruct2.h,
x4neststruct1.cc, and x4neststruct2.cc.  The latter test demonstrates
the problem with a failure.

Tested on x64.


Index: gcc/c-family/ChangeLog.pph

2012-03-09   Lawrence Crowl  <cr...@google.com>

        * c.opt (-fprimary-system-header-okay): New.
        * c-opts.c (c_common_handle_option): Add handling for
        -fprimary-system-header-okay.  Make PPH output imply this option.

Index: gcc/cp/ChangeLog.pph

2012-03-09   Lawrence Crowl  <cr...@google.com>

        * name-lookup.c (pph_out_binding_table): Correct comment.
        (pph_in_binding_table): Correct comment.
        * pph-out.c (pph_out_lang_type_class_bits): New.
        (pph_out_lang_type_class): Factor out the bitpack writing into
        pph_out_lang_type_class_bits.
        (pph_out_merge_key_lang_type_class): New.
        (pph_out_merge_key_lang_type): New.
        (pph_out_merge_key_tree): Also emit merge key for lang_type for classes.
        * pph-in.c (typedef merge_toc_entry): Generalize context.
        (pph_toc_lookup_add): New.
        (pph_merge_into_chain): Factor out TOC lookup and add to
        pph_toc_lookup_add.
        (pph_in_merge_lang_type_class_bits): New.
        (pph_in_lang_type_class): Factor out the bitpack reading into
        pph_in_merge_lang_type_class_bits.
        (pph_in_merge_key_lang_type_class): New.
        (pph_in_merge_key_lang_type): New.
        (pph_in_merge_key_tree_with_searcher): Also merge key for lang_type
        for classes.

Index: libcpp/ChangeLog.pph

2012-03-09   Lawrence Crowl  <cr...@google.com>

        * include/cpplib.h (struct cpp_options): Add option to supress warning
        about a system header as a primary file.
        * directives.c (do_pragma_system_header): Implement the effect of the
        above option.


Index: gcc/c-family/c.opt
===================================================================
--- gcc/c-family/c.opt  (revision 185111)
+++ gcc/c-family/c.opt  (working copy)
@@ -1017,6 +1017,10 @@ fpreprocessed
 C ObjC C++ ObjC++
 Treat the input file as already preprocessed
 
+fprimary-system-header-okay
+C ObjC C++ ObjC++
+Supress warning about compiling a primary system header file.
+
 ftrack-macro-expansion
 C ObjC C++ ObjC++ JoinedOrMissing RejectNegative UInteger
 ; converted into ftrack-macro-expansion=
Index: gcc/c-family/c-opts.c
===================================================================
--- gcc/c-family/c-opts.c       (revision 185111)
+++ gcc/c-family/c-opts.c       (working copy)
@@ -385,6 +385,7 @@ c_common_handle_option (size_t scode, co
 
     case OPT__output_pph_:
       pph_out_file = arg;
+      cpp_opts->primary_system_header_okay = true;
       break;
 
     case OPT_A:
@@ -803,6 +804,10 @@ c_common_handle_option (size_t scode, co
       add_pph_include_maps (arg);
       break;
 
+    case OPT_fprimary_system_header_okay:
+      cpp_opts->primary_system_header_okay = true;
+      break;
+
     case OPT_idirafter:
       add_path (xstrdup (arg), AFTER, 0, true);
       break;
Index: gcc/cp/pph-out.c
===================================================================
--- gcc/cp/pph-out.c    (revision 185112)
+++ gcc/cp/pph-out.c    (working copy)
@@ -1691,10 +1691,10 @@ pph_out_sorted_fields_type (pph_stream *
 }
 
 
-/* Write all the fields in lang_type_class instance LTC to STREAM.  */
+/* Write all the packed bits in lang_type_class instance LTC to STREAM.  */
 
 static void
-pph_out_lang_type_class (pph_stream *stream, struct lang_type_class *ltc)
+pph_out_lang_type_class_bits (pph_stream *stream, struct lang_type_class *ltc)
 {
   struct bitpack_d bp;
 
@@ -1745,7 +1745,15 @@ pph_out_lang_type_class (pph_stream *str
   bp_pack_value (&bp, ltc->has_complex_move_assign, 1);
   bp_pack_value (&bp, ltc->has_constexpr_ctor, 1);
   pph_out_bitpack (stream, &bp);
+}
+
 
+/* Write all the fields in lang_type_class instance LTC to STREAM.  */
+
+static void
+pph_out_lang_type_class (pph_stream *stream, struct lang_type_class *ltc)
+{
+  pph_out_lang_type_class_bits (stream, ltc);
   pph_out_tree (stream, ltc->primary_base);
   pph_out_tree_pair_vec (stream, ltc->vcall_indices);
   pph_out_tree (stream, ltc->vtables);
@@ -1774,6 +1782,16 @@ pph_out_lang_type_class (pph_stream *str
 }
 
 
+/* Write all the merge key fields in lang_type_class instance LTC to STREAM.  
*/
+
+static void
+pph_out_merge_key_lang_type_class (pph_stream *stream,
+                                  struct lang_type_class *ltc)
+{
+  pph_out_lang_type_class_bits (stream, ltc);
+}
+
+
 /* Write struct lang_type_ptrmem instance LTP to STREAM.  */
 
 static void
@@ -1806,6 +1824,24 @@ pph_out_lang_type (pph_stream *stream, t
 }
 
 
+/* Write the merge keys the lang-specific fields of TYPE to STREAM.  */
+
+static void
+pph_out_merge_key_lang_type (pph_stream *stream, struct lang_type *lt)
+{
+  enum pph_record_marker marker;
+  marker = pph_out_start_record (stream, lt, PPH_lang_type);
+  if (marker == PPH_RECORD_END)
+    return;
+
+  gcc_assert (marker == PPH_RECORD_START_NO_CACHE);
+
+  pph_out_lang_type_header (stream, &lt->u.h);
+  gcc_assert (lt->u.h.is_lang_type_class);
+  pph_out_merge_key_lang_type_class (stream, &lt->u.c);
+}
+
+
 /* Write machine_mode value MODE to STREAM.  */
 
 static void
@@ -2316,6 +2352,7 @@ pph_out_merge_key_tree (pph_stream *stre
          unsigned filter = PPHF_NO_XREFS | PPHF_NO_PREFS | PPHF_NO_BUILTINS;
          pph_out_merge_key_chain (stream, TYPE_FIELDS (expr), filter);
          pph_out_merge_key_chain (stream, TYPE_METHODS (expr), filter);
+         pph_out_merge_key_lang_type (stream, TYPE_LANG_SPECIFIC (expr));
        }
     }
 
Index: gcc/cp/name-lookup.c
===================================================================
--- gcc/cp/name-lookup.c        (revision 185111)
+++ gcc/cp/name-lookup.c        (working copy)
@@ -6042,7 +6042,7 @@ cp_emit_debug_info_for_using (tree t, tr
 }
 
 
-/* Write a binding_entry instance BT to STREAM.  */
+/* Write a binding table BT to STREAM.  */
 
 void
 pph_out_binding_table (pph_stream *stream, binding_table bt)
@@ -6065,7 +6065,7 @@ pph_out_binding_table (pph_stream *strea
 }
 
 
-/* Read and return a binding_entry instance BT from STREAM.  */
+/* Read and return a binding table BT from STREAM.  */
 
 binding_table
 pph_in_binding_table (pph_stream *stream)
Index: gcc/cp/pph-in.c
===================================================================
--- gcc/cp/pph-in.c     (revision 185112)
+++ gcc/cp/pph-in.c     (working copy)
@@ -895,7 +895,7 @@ typedef struct {
   tree expr;
 
   /* Context where this tree should be inserted into.  */
-  tree *context;
+  void *context;
 
   /* Name of the tree (from pph_merge_name).  */
   const char *name;
@@ -979,16 +979,18 @@ pph_prepend_to_chain (tree expr, tree *c
 }
 
 
-/* Merge the just-read header for tree EXPR with NAME onto the CHAIN.  */
+/* Lookup and possibly add an expr, name, and context tuple in the TOC.
+   Return the existing expr found.  If none was found, add an entry
+   and return the argument expr. */
 
 static tree
-pph_merge_into_chain (tree expr, const char *name, tree *chain)
+pph_toc_lookup_add (tree expr, const char *name, void *context)
 {
   merge_toc_entry key;
   tree found;
 
   key.expr = expr;
-  key.context = chain;
+  key.context = context;
   key.name = name;
   found = pph_toc_lookup (merge_toc, &key);
   if (!found)
@@ -996,17 +998,13 @@ pph_merge_into_chain (tree expr, const c
       pph_toc_add (merge_toc, &key);
 
       if (flag_pph_debug >= 3)
-        fprintf (pph_logfile, "PPH: %s NOT found on chain\n", name);
+        fprintf (pph_logfile, "PPH: %s %p NOT found in TOC\n", name, context);
 
-      /* Types (as opposed to type decls) are not on a chain.  */
-      if (chain)
-        return pph_prepend_to_chain (expr, chain);
-      else
-        return expr;
+      return expr;
     }
 
   if (flag_pph_debug >= 3)
-    fprintf (pph_logfile, "PPH: %s FOUND on chain\n", name);
+    fprintf (pph_logfile, "PPH: %s %p FOUND in TOC\n", name, context);
 
   gcc_assert (TREE_CODE (found) == TREE_CODE (expr));
 
@@ -1014,6 +1012,21 @@ pph_merge_into_chain (tree expr, const c
 }
 
 
+/* Merge the just-read header for tree EXPR with NAME onto the CHAIN.  */
+
+static tree
+pph_merge_into_chain (tree expr, const char *name, tree *chain)
+{
+  tree found = pph_toc_lookup_add (expr, name, (void*)chain);
+  if (found == expr)
+    {
+      gcc_assert (chain);
+      return pph_prepend_to_chain (expr, chain);
+    }
+  return found;
+}
+
+
 /****************************************************************** bindings */
 
 
@@ -1757,61 +1770,73 @@ pph_in_sorted_fields_type (pph_stream *s
 }
 
 
-/* Read all the fields in lang_type_class instance LTC to STREAM.  */
+/* Read and merge the bits in lang_type_class instance LTC to STREAM.  */
 
 static void
-pph_in_lang_type_class (pph_stream *stream, struct lang_type_class *ltc)
+pph_in_merge_lang_type_class_bits (pph_stream *stream,
+                                  struct lang_type_class *ltc)
 {
   struct bitpack_d bp;
-  enum pph_record_marker marker;
-  unsigned image_ix, ix;
 
   ltc->align = pph_in_uchar (stream);
 
   bp = pph_in_bitpack (stream);
-  ltc->has_mutable = bp_unpack_value (&bp, 1);
-  ltc->com_interface = bp_unpack_value (&bp, 1);
-  ltc->non_pod_class = bp_unpack_value (&bp, 1);
-  ltc->nearly_empty_p = bp_unpack_value (&bp, 1);
-  ltc->user_align = bp_unpack_value (&bp, 1);
-  ltc->has_copy_assign = bp_unpack_value (&bp, 1);
-  ltc->has_new = bp_unpack_value (&bp, 1);
-  ltc->has_array_new = bp_unpack_value (&bp, 1);
-  ltc->gets_delete = bp_unpack_value (&bp, 2);
-  ltc->interface_only = bp_unpack_value (&bp, 1);
-  ltc->interface_unknown = bp_unpack_value (&bp, 1);
-  ltc->contains_empty_class_p = bp_unpack_value (&bp, 1);
-  ltc->anon_aggr = bp_unpack_value (&bp, 1);
-  ltc->non_zero_init = bp_unpack_value (&bp, 1);
-  ltc->empty_p = bp_unpack_value (&bp, 1);
-  ltc->vec_new_uses_cookie = bp_unpack_value (&bp, 1);
-  ltc->declared_class = bp_unpack_value (&bp, 1);
-  ltc->diamond_shaped = bp_unpack_value (&bp, 1);
-  ltc->repeated_base = bp_unpack_value (&bp, 1);
-  ltc->being_defined = bp_unpack_value (&bp, 1);
-  ltc->java_interface = bp_unpack_value (&bp, 1);
-  ltc->debug_requested = bp_unpack_value (&bp, 1);
-  ltc->fields_readonly = bp_unpack_value (&bp, 1);
-  ltc->use_template = bp_unpack_value (&bp, 2);
-  ltc->ptrmemfunc_flag = bp_unpack_value (&bp, 1);
-  ltc->was_anonymous = bp_unpack_value (&bp, 1);
-  ltc->lazy_default_ctor = bp_unpack_value (&bp, 1);
-  ltc->lazy_copy_ctor = bp_unpack_value (&bp, 1);
-  ltc->lazy_copy_assign = bp_unpack_value (&bp, 1);
-  ltc->lazy_destructor = bp_unpack_value (&bp, 1);
-  ltc->has_const_copy_ctor = bp_unpack_value (&bp, 1);
-  ltc->has_complex_copy_ctor = bp_unpack_value (&bp, 1);
-  ltc->has_complex_copy_assign = bp_unpack_value (&bp, 1);
-  ltc->non_aggregate = bp_unpack_value (&bp, 1);
-  ltc->has_complex_dflt = bp_unpack_value (&bp, 1);
-  ltc->has_list_ctor = bp_unpack_value (&bp, 1);
-  ltc->non_std_layout = bp_unpack_value (&bp, 1);
-  ltc->is_literal = bp_unpack_value (&bp, 1);
-  ltc->lazy_move_ctor = bp_unpack_value (&bp, 1);
-  ltc->lazy_move_assign = bp_unpack_value (&bp, 1);
-  ltc->has_complex_move_ctor = bp_unpack_value (&bp, 1);
-  ltc->has_complex_move_assign = bp_unpack_value (&bp, 1);
-  ltc->has_constexpr_ctor = bp_unpack_value (&bp, 1);
+  ltc->has_mutable |= bp_unpack_value (&bp, 1);
+  ltc->com_interface |= bp_unpack_value (&bp, 1);
+  ltc->non_pod_class |= bp_unpack_value (&bp, 1);
+  ltc->nearly_empty_p |= bp_unpack_value (&bp, 1);
+  ltc->user_align |= bp_unpack_value (&bp, 1);
+  ltc->has_copy_assign |= bp_unpack_value (&bp, 1);
+  ltc->has_new |= bp_unpack_value (&bp, 1);
+  ltc->has_array_new |= bp_unpack_value (&bp, 1);
+  ltc->gets_delete |= bp_unpack_value (&bp, 2);
+  ltc->interface_only |= bp_unpack_value (&bp, 1);
+  ltc->interface_unknown |= bp_unpack_value (&bp, 1);
+  ltc->contains_empty_class_p |= bp_unpack_value (&bp, 1);
+  ltc->anon_aggr |= bp_unpack_value (&bp, 1);
+  ltc->non_zero_init |= bp_unpack_value (&bp, 1);
+  ltc->empty_p |= bp_unpack_value (&bp, 1);
+  ltc->vec_new_uses_cookie |= bp_unpack_value (&bp, 1);
+  ltc->declared_class |= bp_unpack_value (&bp, 1);
+  ltc->diamond_shaped |= bp_unpack_value (&bp, 1);
+  ltc->repeated_base |= bp_unpack_value (&bp, 1);
+  ltc->being_defined |= bp_unpack_value (&bp, 1);
+  ltc->java_interface |= bp_unpack_value (&bp, 1);
+  ltc->debug_requested |= bp_unpack_value (&bp, 1);
+  ltc->fields_readonly |= bp_unpack_value (&bp, 1);
+  ltc->use_template |= bp_unpack_value (&bp, 2);
+  ltc->ptrmemfunc_flag |= bp_unpack_value (&bp, 1);
+  ltc->was_anonymous |= bp_unpack_value (&bp, 1);
+  ltc->lazy_default_ctor |= bp_unpack_value (&bp, 1);
+  ltc->lazy_copy_ctor |= bp_unpack_value (&bp, 1);
+  ltc->lazy_copy_assign |= bp_unpack_value (&bp, 1);
+  ltc->lazy_destructor |= bp_unpack_value (&bp, 1);
+  ltc->has_const_copy_ctor |= bp_unpack_value (&bp, 1);
+  ltc->has_complex_copy_ctor |= bp_unpack_value (&bp, 1);
+  ltc->has_complex_copy_assign |= bp_unpack_value (&bp, 1);
+  ltc->non_aggregate |= bp_unpack_value (&bp, 1);
+  ltc->has_complex_dflt |= bp_unpack_value (&bp, 1);
+  ltc->has_list_ctor |= bp_unpack_value (&bp, 1);
+  ltc->non_std_layout |= bp_unpack_value (&bp, 1);
+  ltc->is_literal |= bp_unpack_value (&bp, 1);
+  ltc->lazy_move_ctor |= bp_unpack_value (&bp, 1);
+  ltc->lazy_move_assign |= bp_unpack_value (&bp, 1);
+  ltc->has_complex_move_ctor |= bp_unpack_value (&bp, 1);
+  ltc->has_complex_move_assign |= bp_unpack_value (&bp, 1);
+  ltc->has_constexpr_ctor |= bp_unpack_value (&bp, 1);
+}
+
+/* Read all the fields in lang_type_class instance LTC from STREAM.  */
+
+static void
+pph_in_lang_type_class (pph_stream *stream, struct lang_type_class *ltc)
+{
+  enum pph_record_marker marker;
+  unsigned image_ix, ix;
+
+  pph_in_merge_lang_type_class_bits (stream, ltc);
+  /* We are merging even for new classes,
+     because they have been allocated to zero.  */
 
   ltc->primary_base = pph_in_tree (stream);
   ltc->vcall_indices = pph_in_tree_pair_vec (stream);
@@ -1842,6 +1867,16 @@ pph_in_lang_type_class (pph_stream *stre
 }
 
 
+/* Merge all the fields in lang_type_class instance LTC from STREAM.  */
+
+static void
+pph_in_merge_key_lang_type_class (pph_stream *stream,
+                                 struct lang_type_class *ltc)
+{
+  pph_in_merge_lang_type_class_bits (stream, ltc);
+}
+
+
 /* Read all fields of struct lang_type_ptrmem instance LTP from STREAM.  */
 
 static void
@@ -1879,6 +1914,34 @@ pph_in_lang_type (pph_stream *stream)
 }
 
 
+/* Read merge keys in struct lang_type from STREAM.  */
+
+static void
+pph_in_merge_key_lang_type (pph_stream *stream, struct lang_type **lt_p)
+{
+  enum pph_record_marker marker;
+  unsigned image_ix, ix;
+  struct lang_type *lt = *lt_p;
+
+  marker = pph_in_start_record (stream, &image_ix, &ix, PPH_lang_type);
+  if (marker == PPH_RECORD_END)
+    return;
+
+  gcc_assert (marker == PPH_RECORD_START_NO_CACHE);
+
+  if (! lt)
+    {
+      /* There is no prior lang_type, hence no merging, so allocate it.  */
+      lt = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+      *lt_p = lt;
+    }
+
+  pph_in_lang_type_header (stream, &lt->u.h);
+  gcc_assert (lt->u.h.is_lang_type_class);
+  pph_in_merge_key_lang_type_class (stream, &lt->u.c);
+}
+
+
 /* Read from STREAM an enum machine_mode value.  */
 
 static enum machine_mode
@@ -2593,6 +2656,7 @@ pph_in_merge_key_tree_with_searcher (pph
        {
          pph_in_merge_key_chain (stream, &TYPE_FIELDS (expr));
          pph_in_merge_key_chain (stream, &TYPE_METHODS (expr));
+         pph_in_merge_key_lang_type (stream, &TYPE_LANG_SPECIFIC (expr));
        }
     }
 
Index: libcpp/directives.c
===================================================================
--- libcpp/directives.c (revision 185111)
+++ libcpp/directives.c (working copy)
@@ -1629,7 +1629,8 @@ do_pragma_poison (cpp_reader *pfile)
 static void
 do_pragma_system_header (cpp_reader *pfile)
 {
-  if (cpp_in_primary_file (pfile))
+  if (!CPP_OPTION (pfile, primary_system_header_okay)
+      && cpp_in_primary_file (pfile))
     cpp_error (pfile, CPP_DL_WARNING,
               "#pragma system_header ignored outside include file");
   else
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h     (revision 185111)
+++ libcpp/include/cpplib.h     (working copy)
@@ -444,6 +444,9 @@ struct cpp_options
   /* True to warn about precompiled header files we couldn't use.  */
   bool warn_invalid_pch;
 
+  /* False to warn about a primary file being a system header.  */
+  bool primary_system_header_okay;
+
   /* True if dependencies should be restored from a precompiled header.  */
   bool restore_pch_deps;
 

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

Reply via email to