From patchwork Fri Aug 19 23:11:52 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gab Charette X-Patchwork-Id: 110746 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 F0824B6F6F for ; Sat, 20 Aug 2011 09:12:20 +1000 (EST) Received: (qmail 9832 invoked by alias); 19 Aug 2011 23:12:18 -0000 Received: (qmail 9823 invoked by uid 22791); 19 Aug 2011 23:12:13 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RP_MATCHES_RCVD, SPF_HELO_PASS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.44.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 19 Aug 2011 23:11:56 +0000 Received: from hpaq13.eem.corp.google.com (hpaq13.eem.corp.google.com [172.25.149.13]) by smtp-out.google.com with ESMTP id p7JNBs8U018629; Fri, 19 Aug 2011 16:11:54 -0700 Received: from gchare.mtv.corp.google.com (gchare.mtv.corp.google.com [172.18.111.122]) by hpaq13.eem.corp.google.com with ESMTP id p7JNBqlE001389; Fri, 19 Aug 2011 16:11:52 -0700 Received: by gchare.mtv.corp.google.com (Postfix, from userid 138564) id 193EE1C1ECE; Fri, 19 Aug 2011 16:11:51 -0700 (PDT) To: reply@codereview.appspotmail.com, gcc-patches@gcc.gnu.org Subject: [pph] Add support for line table streaming with includes (issue4908051) Message-Id: <20110819231152.193EE1C1ECE@gchare.mtv.corp.google.com> Date: Fri, 19 Aug 2011 16:11:52 -0700 (PDT) From: gchare@google.com (Gabriel Charette) X-System-Of-Record: true 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 Applied requested changes. Tested on x64 with bootstrap and pph regression testing. Committing to pph branch, if any other changes are needed to this patch, I'm writting a clean up patch for the line_table implementation now and will add whatever else is needed to it. One thing I wasn't sure is how to handle headers with no .h extensions, will we ever pph any of those? I currently support them in this patch. Cheers, Gab 2011-08-19 Gabriel Charette gcc/cp/ChangeLog.pph * pph-streamer-in.c (pph_in_includes): Remove. (pph_in_linetable_marker): New. (pph_in_line_table_and_includes): Renamed from pph_in_and_merge_line_table. Now handles line_table and includes input in parallel. Now returns source_location corresponding to line 1 / col 0 of the header currently loaded as pph. (pph_read_file_1): Read line_table and includes before replaying tokens. Use location returned by pph_in_line_table_and_includes as forced token location for replayed tokens. * pph-streamer-out.c (pph_out_includes): Remove. (pph_out_linetable_marker): New. (pph_filename_eq_ignoring_path): New. (pph_get_next_include): New. (pph_out_line_table_and_includes): Renamed from pph_out_line_table. Now handles output of both the line_table and includes references in parallel. (pph_write_file): Write out line_table and includes before identifiers. * pph-streamer.h (enum pph_linetable_marker): New. * pph.c (pph_include_handler): Add hack to mimic line_table->highest_location behaviour in _cpp_stack_include used by the non-pph compiler. gcc/testsuite/ChangeLog.pph * g++.dg/pph/p4eabi1.cc: Remove asm xdiff. * g++.dg/pph/x4keyed.cc: Changed line info for expected failure. * g++.dg/pph/x7rtti.cc: Changed line info for expected failures. --- This patch is available for review at http://codereview.appspot.com/4908051 diff --git a/gcc/cp/pph-streamer-in.c b/gcc/cp/pph-streamer-in.c index 4666ace..9686edf 100644 --- a/gcc/cp/pph-streamer-in.c +++ b/gcc/cp/pph-streamer-in.c @@ -1281,27 +1281,6 @@ pph_in_symtab (pph_stream *stream) } -/* Read all the images included by STREAM. */ - -static void -pph_in_includes (pph_stream *stream) -{ - unsigned i, num; - - pph_reading_includes++; - - num = pph_in_uint (stream); - for (i = 0; i < num; i++) - { - const char *include_name = pph_in_string (stream); - pph_stream *include = pph_read_file (include_name); - pph_add_include (include, false); - } - - pph_reading_includes--; -} - - /* Read a linenum_type from STREAM. */ static inline linenum_type @@ -1320,6 +1299,20 @@ pph_in_source_location (pph_stream *stream) } +/* Read a line table marker from STREAM. */ + +static inline enum pph_linetable_marker +pph_in_linetable_marker (pph_stream *stream) +{ + enum pph_linetable_marker m = + (enum pph_linetable_marker) pph_in_uchar (stream); + gcc_assert (m == PPH_LINETABLE_ENTRY + || m == PPH_LINETABLE_REFERENCE + || m == PPH_LINETABLE_END); + return m; +} + + /* Read a line_map from STREAM into LM. */ static void @@ -1343,47 +1336,100 @@ pph_in_line_map (pph_stream *stream, struct line_map *lm) } -/* Read the line_table from STREAM and merge it in LINETAB. */ +/* Read the line_table from STREAM and merge it in LINETAB. At the same time + load includes in the order they were originally included by loading them at + the point they were referenced in the line_table. -static void -pph_in_and_merge_line_table (pph_stream *stream, struct line_maps *linetab) + Returns the source_location of line 1 / col 0 for this include. + + FIXME pph: The line_table is now identical to the non-pph line_table, the + only problem is that we load line_table entries twice for headers that are + re-included and are #ifdef guarded; thus shouldn't be replayed. This is + a known current issue, so I didn't bother working around it here for now. */ + +static source_location +pph_in_line_table_and_includes (pph_stream *stream, struct line_maps *linetab) { - unsigned int ix, pph_used, old_depth; + unsigned int old_depth; + bool first; + int includer_ix = -1; + unsigned int used_before = linetab->used; int entries_offset = linetab->used - PPH_NUM_IGNORED_LINE_TABLE_ENTRIES; + enum pph_linetable_marker next_lt_marker = pph_in_linetable_marker (stream); - pph_used = pph_in_uint (stream); + pph_reading_includes++; - for (ix = 0; ix < pph_used; ix++, linetab->used++) + for (first = true; next_lt_marker != PPH_LINETABLE_END; + next_lt_marker = pph_in_linetable_marker (stream)) { - struct line_map *lm; + if (next_lt_marker == PPH_LINETABLE_REFERENCE) + { + int old_loc_offset; + const char *include_name = pph_in_string (stream); + source_location prev_start_loc = pph_in_source_location (stream); + pph_stream *include; + + gcc_assert (!first); + + linetab->highest_location = (prev_start_loc - 1) + pph_loc_offset; + + old_loc_offset = pph_loc_offset; - linemap_ensure_extra_space_available (linetab); + include = pph_read_file (include_name); + pph_add_include (include, false); - lm = &linetab->maps[linetab->used]; + pph_loc_offset = old_loc_offset; + } + else + { + struct line_map *lm; - pph_in_line_map (stream, lm); + linemap_ensure_extra_space_available (linetab); - if (ix == 0) - { - pph_loc_offset = (linetab->highest_location + 1) - lm->start_location; + lm = &linetab->maps[linetab->used]; - /* When parsing the pph the header itself wasn't included by anything, - now it's included by the C file we are currently compiling. */ - gcc_assert(lm->included_from == -1); - lm->included_from = linetab->used - 1; - } + pph_in_line_map (stream, lm); - /* For the other entries in the pph's line_table which were included_from - another entry, reflect their included_from to the new position of the - entry which they were included from. */ - else if (lm->included_from != -1) - lm->included_from += entries_offset; + if (first) + { + first = false; + + pph_loc_offset = (linetab->highest_location + 1) + - lm->start_location; - gcc_assert (lm->included_from < (int) linetab->used); + includer_ix = linetab->used - 1; - lm->start_location += pph_loc_offset; + gcc_assert (lm->included_from == -1); + } + + gcc_assert (includer_ix != -1); + + /* When parsing the pph: the header itself wasn't included by + anything, now it's included by the file just before it in + the current include tree. */ + if (lm->included_from == -1) + lm->included_from = includer_ix; + /* For the other entries in the pph's line_table which were included + from another entry, reflect their included_from to the new position + of the entry which they were included from. */ + else + lm->included_from += entries_offset; + + gcc_assert (lm->included_from < (int) linetab->used); + + lm->start_location += pph_loc_offset; + + linetab->used++; + } } + pph_reading_includes--; + + { + unsigned int expected_in = pph_in_uint (stream); + gcc_assert (linetab->used - used_before == expected_in); + } + linetab->highest_location = pph_loc_offset + pph_in_uint (stream); linetab->highest_line = pph_loc_offset + pph_in_uint (stream); @@ -1399,6 +1445,8 @@ pph_in_and_merge_line_table (pph_stream *stream, struct line_maps *linetab) old_depth = linetab->depth++; linemap_add (linetab, LC_LEAVE, 0, NULL, 0); gcc_assert (linetab->depth == old_depth); + + return linetab->maps[used_before].start_location; } @@ -1419,8 +1467,10 @@ pph_read_file_1 (pph_stream *stream) if (flag_pph_debug >= 1) fprintf (pph_logfile, "PPH: Reading %s\n", stream->name); - /* Read all the images included by STREAM. */ - pph_in_includes (stream); + /* Read in STREAM's line table and merge it in the current line table. + At the same time, read in includes in the order they were originally + read. */ + cpp_token_replay_loc = pph_in_line_table_and_includes (stream, line_table); /* Read all the identifiers and pre-processor symbols in the global namespace. */ @@ -1433,16 +1483,12 @@ pph_read_file_1 (pph_stream *stream) bad_use->before_str, bad_use->after_str); /* Re-instantiate all the pre-processor symbols defined by STREAM. Force - their source_location to column 0 of the line the include occured on, - this avoids shifting all of the line_table's location as we would by adding - locations which wouldn't be there in the non-pph compile; thus working - towards an identical line_table in pph and non-pph. */ - cpp_token_replay_loc = linemap_position_for_column (line_table, 0); + their source_location to line 1 / column 0 of the file they were included + in. This avoids shifting all of the line_table's locations as we would by + adding locations which wouldn't be there in the non-pph compile; thus + working towards an identical line_table in pph and non-pph. */ cpp_lt_replay (parse_in, &idents_used, &cpp_token_replay_loc); - /* Read in STREAM's line table and merge it in the current line table. */ - pph_in_and_merge_line_table (stream, line_table); - /* Read the bindings from STREAM and merge them with the current bindings. */ pph_in_scope_chain (stream); diff --git a/gcc/cp/pph-streamer-out.c b/gcc/cp/pph-streamer-out.c index 1b84cc3..b563891 100644 --- a/gcc/cp/pph-streamer-out.c +++ b/gcc/cp/pph-streamer-out.c @@ -1142,21 +1142,6 @@ pph_out_symtab (pph_stream *stream) } -/* Emit the list of all the PPH files included by STREAM. */ - -static void -pph_out_includes (pph_stream *stream) -{ - unsigned i; - pph_stream *include; - - pph_out_uint (stream, VEC_length (pph_stream_ptr, - stream->encoder.w.includes)); - FOR_EACH_VEC_ELT (pph_stream_ptr, stream->encoder.w.includes, i, include) - pph_out_string (stream, include->name); -} - - /* Emit linenum_type LN to STREAM. */ static inline void @@ -1175,6 +1160,16 @@ pph_out_source_location (pph_stream *stream, source_location sl) } +/* Emit line table MARKER to STREAM. */ + +static inline void +pph_out_linetable_marker (pph_stream *stream, enum pph_linetable_marker marker) +{ + gcc_assert (marker == (enum pph_linetable_marker)(unsigned char) marker); + pph_out_uchar (stream, marker); +} + + /* Emit all information contained in LM to STREAM. */ static void @@ -1195,22 +1190,78 @@ pph_out_line_map (pph_stream *stream, struct line_map *lm) } -/* Emit the required line_map entry and some properties in LINETAB to STREAM, - ignoring builtin and command-line entries. */ +/* Compare filenames of a header and it's potentially corresponding pph file, + stripping the path passed in and the extension. Returns true if HEADER_PATH + and PPH_PATH end with the same filename. We expect HEADER_PATH to end in .h + and PPH_PATH to end in .pph. + + FIXME pph: We should not need to do this if we handled include paths + correctly, but for now the linemap holds full paths and the stream's includes + list only holds the include name. Also, the stream's includes hold pph + filenames where as the line_table as header filenames. */ + +static bool +pph_filename_eq_ignoring_path (const char *header_path, const char *pph_path) +{ + const char *header_name = lbasename (header_path); + const char *pph_name = lbasename (pph_path); + + const char *header_ext = strchr (header_name, '.'); + const char *pph_ext = strchr (pph_name, '.'); + + unsigned int name_length; + + if (header_ext != NULL) + { + name_length = header_ext - header_name; + gcc_assert (strcmp (header_ext, ".h") == 0); + } + else + /* Some headers do not have a .h suffix, but will still + have a .pph suffix after being pph'ed. */ + name_length = strlen (header_name); + + gcc_assert (strcmp (pph_ext, ".pph") == 0); + + /* Compare the filenames without their extension. */ + return pph_ext - pph_name == name_length + && strncmp (header_name, pph_name, name_length) == 0; +} + + +/* Return the *NEXT_INCLUDE_IX'th pph_stream in STREAM's list of includes. + Returns NULL if we have read all includes. */ + +static inline pph_stream * +pph_get_next_include (pph_stream *stream, unsigned int *next_incl_ix) +{ + if (*next_incl_ix < VEC_length (pph_stream_ptr, stream->encoder.w.includes)) + return VEC_index (pph_stream_ptr, stream->encoder.w.includes, + (*next_incl_ix)++); + else + return NULL; +} + + +/* Emit the required line_map entry (those directly related to this include) + and some properties in LINETAB to STREAM, ignoring builtin and command-line + entries. We will write references to our direct includes children and skip + their actual line_map entries (unless they are non-pph children in which case + we have to write out their line_map entries as well). We assume + stream->encoder.w.includes contains the pph headers included in the same + order they are seen in the line_table. */ static void -pph_out_line_table (pph_stream *stream, struct line_maps *linetab) +pph_out_line_table_and_includes (pph_stream *stream, struct line_maps *linetab) { - unsigned int ix; + unsigned int ix, next_incl_ix = 0; + pph_stream *current_include; /* Any #include should have been fully parsed and exited at this point. */ gcc_assert (linetab->depth == 0); - /* Only output used as the number of line_map entries we actually output. */ - pph_out_uint (stream, linetab->used - PPH_NUM_IGNORED_LINE_TABLE_ENTRIES); + current_include = pph_get_next_include (stream, &next_incl_ix); - /* Output all the non-ignored line_map entries. - Special casing the first one. */ for (ix = PPH_NUM_IGNORED_LINE_TABLE_ENTRIES; ix < linetab->used; ix++) { struct line_map *lm = &linetab->maps[ix]; @@ -1226,12 +1277,57 @@ pph_out_line_table (pph_stream *stream, struct line_maps *linetab) lm->reason = LC_ENTER; } - pph_out_line_map (stream, lm); - + /* If this is an entry from a pph header, only output reference. */ + if (current_include != NULL + && pph_filename_eq_ignoring_path (lm->to_file, current_include->name)) + { + int includer_level; + + gcc_assert (lm->reason == LC_ENTER); + gcc_assert (lm->included_from != -1); + + pph_out_linetable_marker (stream, PPH_LINETABLE_REFERENCE); + pph_out_string (stream, current_include->name); + + /* We also need to output the start_location to simulate the correct + highest_location on the way in. */ + pph_out_source_location (stream, lm->start_location); + + /* Potentially lm could be included from a header other then the main + one if a textual include includes a pph header (i.e. we can't + simply rely on going back to included_from == -1). */ + includer_level = INCLUDED_FROM (linetab, lm)->included_from; + + /* Skip all other linemap entries up to and including the LC_LEAVE + from the referenced header back to the one including it. */ + while (linetab->maps[++ix].included_from != includer_level) + /* We should always leave this loop before the end of the + current line_table entries. */ + gcc_assert (ix < linetab->used); + + current_include = pph_get_next_include (stream, &next_incl_ix); + } + else + { + pph_out_linetable_marker (stream, PPH_LINETABLE_ENTRY); + pph_out_line_map (stream, lm); + } + + /* Restore changes made to first entry above if needed. */ if (ix == PPH_NUM_IGNORED_LINE_TABLE_ENTRIES) - lm->reason = LC_RENAME; + lm->reason = LC_RENAME; } + pph_out_linetable_marker (stream, PPH_LINETABLE_END); + + /* Output the number of entries written to validate on input. */ + pph_out_uint (stream, linetab->used - PPH_NUM_IGNORED_LINE_TABLE_ENTRIES); + + /* Every pph header included should have been seen and skipped in the + line_table streaming above. */ + gcc_assert (next_incl_ix == VEC_length (pph_stream_ptr, + stream->encoder.w.includes)); + pph_out_source_location (stream, linetab->highest_location); pph_out_source_location (stream, linetab->highest_line); @@ -1248,18 +1344,14 @@ pph_write_file (pph_stream *stream) if (flag_pph_debug >= 1) fprintf (pph_logfile, "PPH: Writing %s\n", pph_out_file); - /* Emit the list of PPH files included by STREAM. These files will - be read and instantiated before any of the content in STREAM. */ - pph_out_includes (stream); + /* Emit the line table entries and references to our direct includes. */ + pph_out_line_table_and_includes (stream, line_table); /* Emit all the identifiers and pre-processor symbols in the global namespace. */ idents_used = cpp_lt_capture (parse_in); pph_out_identifiers (stream, &idents_used); - /* Emit the line table entries. */ - pph_out_line_table (stream, line_table); - /* Emit the bindings for the global namespace. */ pph_out_scope_chain (stream); if (flag_pph_dump_tree) diff --git a/gcc/cp/pph-streamer.h b/gcc/cp/pph-streamer.h index 7842f1f..4a1f9eb 100644 --- a/gcc/cp/pph-streamer.h +++ b/gcc/cp/pph-streamer.h @@ -63,6 +63,21 @@ enum pph_symtab_marker { PPH_SYMTAB_DECL }; +/* Line table markers. We only stream line table entries from the parent header + file, other entries are referred to by the name of the file which is then + loaded as an include at the correct point in time. */ +enum pph_linetable_marker { + + /* A regular line_map entry in the line_table. */ + PPH_LINETABLE_ENTRY = 0x01, + + /* A reference to another header to be loaded at this point. */ + PPH_LINETABLE_REFERENCE, + + /* Marks the end of the line_map entries. */ + PPH_LINETABLE_END +}; + /* Number of sections in a PPH file. FIXME, currently only one section is supported. To add more, it will also be necessary to handle section names in pph_get_section_data and pph_free_section_data. */ diff --git a/gcc/cp/pph.c b/gcc/cp/pph.c index 86aacbc..74f48fc 100644 --- a/gcc/cp/pph.c +++ b/gcc/cp/pph.c @@ -119,6 +119,10 @@ pph_include_handler (cpp_reader *reader, pph_file = query_pph_include_map (name); if (pph_file != NULL && !cpp_included_before (reader, name, input_location)) { + /* Hack. We do this to mimic what the non-pph compiler does in + _cpp_stack_include as our goal is to have identical line_tables. */ + line_table->highest_location--; + pph_read_file (pph_file); read_text_file_p = false; } diff --git a/gcc/testsuite/g++.dg/pph/p4eabi1.cc b/gcc/testsuite/g++.dg/pph/p4eabi1.cc index c7aa1b0..4bf19e6 100644 --- a/gcc/testsuite/g++.dg/pph/p4eabi1.cc +++ b/gcc/testsuite/g++.dg/pph/p4eabi1.cc @@ -1,5 +1,4 @@ // { dg-options "-w -fpermissive" } -// pph asm xdiff 48471 #include "p4eabi1.h" diff --git a/gcc/testsuite/g++.dg/pph/x4keyed.cc b/gcc/testsuite/g++.dg/pph/x4keyed.cc index ef88e7c..68b30c1 100644 --- a/gcc/testsuite/g++.dg/pph/x4keyed.cc +++ b/gcc/testsuite/g++.dg/pph/x4keyed.cc @@ -1,5 +1,5 @@ // { dg-xfail-if "BOGUS" { "*-*-*" } { "-fpph-map=pph.map" } } -// { dg-bogus "x0keyed2.h:11:1: error: redefinition of 'const char _ZTS5keyed ..'" "" { xfail *-*-* } 0 } +// { dg-bogus "x4keyed.cc:13:1: error: redefinition of 'const char _ZTS5keyed ..'" "" { xfail *-*-* } 0 } #include "x0keyed1.h" #include "x0keyed2.h" diff --git a/gcc/testsuite/g++.dg/pph/x7rtti.cc b/gcc/testsuite/g++.dg/pph/x7rtti.cc index 8a6c981..297ebe2 100644 --- a/gcc/testsuite/g++.dg/pph/x7rtti.cc +++ b/gcc/testsuite/g++.dg/pph/x7rtti.cc @@ -1,17 +1,17 @@ // { dg-xfail-if "BOGUS" { "*-*-*" } { "-fpph-map=pph.map" } } -// { dg-bogus "x5rtti1.h:13:0: warning: .__STDC_IEC_559_COMPLEX__. redefined .enabled by default." "" { xfail *-*-* } 0 } -// { dg-bogus "x5rtti1.h:13:0: warning: .__STDC_ISO_10646__. redefined .enabled by default." "" { xfail *-*-* } 0 } -// { dg-bogus "x5rtti1.h:13:0: warning: .__STDC_IEC_559__. redefined .enabled by default." "" { xfail *-*-* } 0 } -// { dg-bogus "x5rtti2.h:15:32: error: no match for .operator" "" { xfail *-*-* } 0 } -// { dg-bogus "x5rtti2.h:15:54: error: no match for .operator" "" { xfail *-*-* } 0 } -// { dg-bogus "x5rtti2.h:16:32: error: no match for .operator" "" { xfail *-*-* } 0 } -// { dg-bogus "x5rtti2.h:16:54: error: no match for .operator" "" { xfail *-*-* } 0 } -// { dg-bogus "x5rtti2.h:17:32: error: no match for .operator" "" { xfail *-*-* } 0 } -// { dg-bogus "x5rtti2.h:17:54: error: no match for .operator" "" { xfail *-*-* } 0 } -// { dg-bogus "x5rtti2.h:18:32: error: no match for .operator" "" { xfail *-*-* } 0 } -// { dg-bogus "x5rtti2.h:18:54: error: no match for .operator" "" { xfail *-*-* } 0 } -// { dg-bogus "x5rtti2.h:19:1: error: redefinition of .const char _ZTS15non_polymorphic ..." "" { xfail *-*-* } 0 } -// { dg-bogus "x5rtti2.h:19:1: error: redefinition of .const char _ZTS11polymorphic ..." "" { xfail *-*-* } 0 } +// { dg-bogus "x7rtti.cc:21:0: warning: .__STDC_IEC_559_COMPLEX__. redefined .enabled by default." "" { xfail *-*-* } 0 } +// { dg-bogus "x7rtti.cc:21:0: warning: .__STDC_ISO_10646__. redefined .enabled by default." "" { xfail *-*-* } 0 } +// { dg-bogus "x7rtti.cc:21:0: warning: .__STDC_IEC_559__. redefined .enabled by default." "" { xfail *-*-* } 0 } +// { dg-bogus "x7rtti.cc:24:32: error: no match for .operator" "" { xfail *-*-* } 0 } +// { dg-bogus "x7rtti.cc:24:54: error: no match for .operator" "" { xfail *-*-* } 0 } +// { dg-bogus "x7rtti.cc:25:32: error: no match for .operator" "" { xfail *-*-* } 0 } +// { dg-bogus "x7rtti.cc:25:54: error: no match for .operator" "" { xfail *-*-* } 0 } +// { dg-bogus "x7rtti.cc:26:32: error: no match for .operator" "" { xfail *-*-* } 0 } +// { dg-bogus "x7rtti.cc:26:54: error: no match for .operator" "" { xfail *-*-* } 0 } +// { dg-bogus "x7rtti.cc:27:32: error: no match for .operator" "" { xfail *-*-* } 0 } +// { dg-bogus "x7rtti.cc:27:54: error: no match for .operator" "" { xfail *-*-* } 0 } +// { dg-bogus "x7rtti.cc:28:1: error: redefinition of .const char _ZTS15non_polymorphic ..." "" { xfail *-*-* } 0 } +// { dg-bogus "x7rtti.cc:28:1: error: redefinition of .const char _ZTS11polymorphic ..." "" { xfail *-*-* } 0 } //FIXME We should make this a run test.