Patch: fix PR c++/17577

Tom Tromey tromey@redhat.com
Sun Nov 11 08:46:00 GMT 2007


This patch fixes PR c++/17577.

Since the change to lex all at once, it hasn't been possible to detect
whether `#pragma implementation' is seen too late.  With mapped
locations, it is now possible, by comparing the location of the pragma
with the location of the included header.

Bootstrapped and regtested on x86 FC-6.  Ok?

Tom

:ADDPATCH c++:

gcc/cp/ChangeLog:
2007-11-10  Tom Tromey  <tromey@redhat.com>

	PR c++/17577:
	* lex.c (handle_pragma_implementation): Use cpp_included_before.

gcc/testsuite/ChangeLog:
2007-11-10  Tom Tromey  <tromey@redhat.com>

	PR c++/17577:
	* g++.dg/ext/pr17577.h: New file.
	* g++.dg/ext/pr17577.C: New file.

libcpp/ChangeLog:
2007-11-10  Tom Tromey  <tromey@redhat.com>

	PR c++/17557:
	* include/cpplib.h (cpp_included_before): Declare.
	* files.c (struct file_hash_entry) <location>: New field.
	(_cpp_find_file): Initialize new field.
	(make_cpp_dir): Likewise.
	(cpp_included_before): New function.

Index: gcc/cp/lex.c
===================================================================
--- gcc/cp/lex.c	(revision 130049)
+++ gcc/cp/lex.c	(working copy)
@@ -572,14 +572,14 @@
   else
     {
       filename = ggc_strdup (TREE_STRING_POINTER (fname));
-#if 0
+#ifdef USE_MAPPED_LOCATION
       /* We currently cannot give this diagnostic, as we reach this point
 	 only after cpplib has scanned the entire translation unit, so
 	 cpp_included always returns true.  A plausible fix is to compare
 	 the current source-location cookie with the first source-location
 	 cookie (if any) of the filename, but this requires completing the
 	 --enable-mapped-location project first.  See PR 17577.  */
-      if (cpp_included (parse_in, filename))
+      if (cpp_included_before (parse_in, filename, input_location))
 	warning (0, "#pragma implementation for %qs appears after "
 		 "file is included", filename);
 #endif
Index: gcc/testsuite/g++.dg/ext/pr17577.h
===================================================================
--- gcc/testsuite/g++.dg/ext/pr17577.h	(revision 0)
+++ gcc/testsuite/g++.dg/ext/pr17577.h	(revision 0)
@@ -0,0 +1,2 @@
+// Test for PR c++/17577.
+#pragma interface
Index: gcc/testsuite/g++.dg/ext/pr17577.C
===================================================================
--- gcc/testsuite/g++.dg/ext/pr17577.C	(revision 0)
+++ gcc/testsuite/g++.dg/ext/pr17577.C	(revision 0)
@@ -0,0 +1,6 @@
+// Test for PR c++/17577.
+
+/* { dg-do compile } */
+
+#include "pr17577.h"
+#pragma implementation "pr17577.h" /* { dg-warning "appears after file" } */
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h	(revision 130049)
+++ libcpp/include/cpplib.h	(working copy)
@@ -853,6 +853,7 @@
 
 /* In cppfiles.c */
 extern bool cpp_included (cpp_reader *, const char *);
+extern bool cpp_included_before (cpp_reader *, const char *, source_location);
 extern void cpp_make_system_header (cpp_reader *, int, int);
 extern bool cpp_push_include (cpp_reader *, const char *);
 extern void cpp_change_file (cpp_reader *, enum lc_reason, const char *);
Index: libcpp/files.c
===================================================================
--- libcpp/files.c	(revision 130049)
+++ libcpp/files.c	(working copy)
@@ -142,6 +142,7 @@
 {
   struct file_hash_entry *next;
   cpp_dir *start_dir;
+  source_location location;
   union
   {
     _cpp_file *file;
@@ -521,6 +522,7 @@
   entry = new_file_hash_entry (pfile);
   entry->next = *hash_slot;
   entry->start_dir = start_dir;
+  entry->location = pfile->line_table->highest_location;
   entry->u.file = file;
   *hash_slot = entry;
 
@@ -533,6 +535,7 @@
       entry = new_file_hash_entry (pfile);
       entry->next = *hash_slot;
       entry->start_dir = pfile->bracket_include;
+      entry->location = pfile->line_table->highest_location;
       entry->u.file = file;
       *hash_slot = entry;
     }
@@ -543,6 +546,7 @@
       entry = new_file_hash_entry (pfile);
       entry->next = *hash_slot;
       entry->start_dir = pfile->quote_include;
+      entry->location = pfile->line_table->highest_location;
       entry->u.file = file;
       *hash_slot = entry;
     }
@@ -993,6 +997,7 @@
   entry = new_file_hash_entry (pfile);
   entry->next = *hash_slot;
   entry->start_dir = NULL;
+  entry->location = pfile->line_table->highest_location;
   entry->u.dir = dir;
   *hash_slot = entry;
 
@@ -1036,6 +1041,25 @@
   return entry != NULL;
 }
 
+/* Returns TRUE if a file FNAME has ever been successfully opened
+   before LOCATION.  This routine is not intended to correctly handle
+   filenames aliased by links or redundant . or .. traversals etc.  */
+bool
+cpp_included_before (cpp_reader *pfile, const char *fname,
+		     source_location location)
+{
+  struct file_hash_entry *entry;
+
+  entry = (struct file_hash_entry *)
+     htab_find_with_hash (pfile->file_hash, fname, htab_hash_string (fname));
+
+  while (entry && (entry->start_dir == NULL || entry->u.file->err_no
+		   || entry->location > location))
+    entry = entry->next;
+
+  return entry != NULL;
+}
+
 /* Calculate the hash value of a file hash entry P.  */
 
 static hashval_t



More information about the Gcc-patches mailing list