From patchwork Sat Mar 10 01:29:48 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lawrence Crowl X-Patchwork-Id: 145789 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id B716BB6EF3 for ; Sat, 10 Mar 2012 12:30:15 +1100 (EST) Comment: DKIM? See http://www.dkim.org DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=gcc.gnu.org; s=default; x=1331947816; h=Comment: DomainKey-Signature:Received:Received:Received:Received:Received: Received:Received:Received:Received:To:Subject:Message-Id:Date: From:Mailing-List:Precedence:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:Sender:Delivered-To; bh=ek86eBV iKXpqcdz23W4oYun/0N4=; b=RiDJdAMQ/TTIO461lMDIVYi/DSrsZhpKiibld62 oJ1A5UKagkOoXF+NtWVJVFYiO0u9ayZd0vqnzv/Uve1CDbOTJsMsbwf1pGJ2mqHp vA5qcNhBWopXk5IIvegBEgvEW37rY9bqvPb/sM4Ok1qNj6wzNmstqCTazAEeflTs x6b8= Comment: DomainKeys? See http://antispam.yahoo.com/domainkeys DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=default; d=gcc.gnu.org; h=Received:Received:X-SWARE-Spam-Status:X-Spam-Check-By:Received:Received:X-Google-DKIM-Signature:Received:Received:Received:Received:Received:To:Subject:Message-Id:Date:From:X-Gm-Message-State:X-IsSubscribed:Mailing-List:Precedence:List-Id:List-Unsubscribe:List-Archive:List-Post:List-Help:Sender:Delivered-To; b=a+H4yMgt45CGKp7VB3ClXytovUDIbWlktoYkhG10MwKaRA3Zys3oT0v/0ZjQvb +VeNtqF6u3yyZY83VMadRFG4k0Z1mB4LzNDzhxGL+kwwlr7xRmxTDbiNtp0ANn2+ s3m+LYnqNJSBageSUye87vR11JM9F6HH2gak0GR/zaURA=; Received: (qmail 11330 invoked by alias); 10 Mar 2012 01:30:10 -0000 Received: (qmail 11307 invoked by uid 22791); 10 Mar 2012 01:30:06 -0000 X-SWARE-Spam-Status: No, hits=-2.4 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RCVD_IN_DNSWL_LOW, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail-bk0-f73.google.com (HELO mail-bk0-f73.google.com) (209.85.214.73) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 10 Mar 2012 01:29:51 +0000 Received: by bkcjg15 with SMTP id jg15so70137bkc.2 for ; Fri, 09 Mar 2012 17:29:50 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=to:subject:message-id:date:from:x-gm-message-state; bh=7DajgJbq5ibQlFsnDnRTII9FTkFImvqGjYJBwJ3LyJk=; b=M0dqD/KXYeoj4A61c3F00J3Onq08q7EkFUjlCZ0UNGVnlIfRl+LZ77vFiKPy5cNGmi uaonVBSIcWazvy7fUqKpy3VstB+PRbMRDz6WYtUUr0nG18JFAYvVN0OcXUaUdmr1GLIk o6MgcAKSkkszYamL+JpIlYmV8PcC043HHrbBqlylZVjaCmwGs5Nb9M3bKeyYoXQBn6OC ooxtdXeeFnsHvB5QhvgP76YD0cz/UNgZ7z/YZt+AgIaSmg0qtM8GHT/kinrbI4CqPe/X HRD3/gAvs9mY3g6csVrIEjjC62WekpTd+JelTU0ZwGAKdcBXCpI2K8vJ5G6+X64Psezf B0hQ== Received: by 10.14.186.9 with SMTP id v9mr1240583eem.5.1331342990025; Fri, 09 Mar 2012 17:29:50 -0800 (PST) Received: by 10.14.186.9 with SMTP id v9mr1240571eem.5.1331342989913; Fri, 09 Mar 2012 17:29:49 -0800 (PST) Received: from hpza10.eem.corp.google.com ([74.125.121.33]) by gmr-mx.google.com with ESMTPS id y56si4665983eea.1.2012.03.09.17.29.49 (version=TLSv1/SSLv3 cipher=AES128-SHA); Fri, 09 Mar 2012 17:29:49 -0800 (PST) Received: from jade.mtv.corp.google.com (jade.mtv.corp.google.com [172.18.110.116]) by hpza10.eem.corp.google.com (Postfix) with ESMTP id 690512000AA; Fri, 9 Mar 2012 17:29:49 -0800 (PST) Received: by jade.mtv.corp.google.com (Postfix, from userid 21482) id AE30D2226C8; Fri, 9 Mar 2012 17:29:48 -0800 (PST) To: reply@codereview.appspotmail.com, dnovillo@google.com, gcc-patches@gcc.gnu.org Subject: [pph] System Headers. Nested Types. (issue5797052) Message-Id: <20120310012948.AE30D2226C8@jade.mtv.corp.google.com> Date: Fri, 9 Mar 2012 17:29:48 -0800 (PST) From: crowl@google.com (Lawrence Crowl) X-Gm-Message-State: ALoCoQne1SDXi1QW+xXCTVrEQWyAtclN1QeXuaySsJBTctV5IeodetgwTwwCdOFYD+EayM+u0QK8UmDikL0Mus9pBcsekvurlF3GFevwLXYnqT4CkvVffCZB2cdLhd5zo9X9+jaN9O/gHmi2MxEW7OsqI7tar7nDVC+9VhGPdni8MOTuv+028ok= X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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. --- This patch is available for review at http://codereview.appspot.com/5797052 Index: gcc/c-family/ChangeLog.pph 2012-03-09 Lawrence Crowl * 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 * 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 * 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, <->u.h); + gcc_assert (lt->u.h.is_lang_type_class); + pph_out_merge_key_lang_type_class (stream, <->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, <->u.h); + gcc_assert (lt->u.h.is_lang_type_class); + pph_in_merge_key_lang_type_class (stream, <->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;