public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] libcpp: Diagnose #include after failed __has_include [PR80753]
@ 2023-06-13 16:29 Jakub Jelinek
  2023-06-15 11:48 ` Jason Merrill
  0 siblings, 1 reply; 2+ messages in thread
From: Jakub Jelinek @ 2023-06-13 16:29 UTC (permalink / raw)
  To: Joseph S. Myers, Marek Polacek, Jason Merrill; +Cc: gcc-patches

Hi!

As can be seen in the testcase, we don't diagnose #include/#include_next
of a non-existent header if __has_include/__has_include_next is done for
that header first.
The problem is that we normally error the first time some header is not
found, but in the _cpp_FFK_HAS_INCLUDE case obviously don't want to diagnose
it, just expand it to 0.  And libcpp caches both successful includes and
unsuccessful ones.

The following patch fixes that by remembering that we haven't diagnosed
error when using __has_include* on it, and diagnosing it when using the
cache entry in normal mode the first time.

I think _cpp_FFK_NORMAL is the only mode in which we normally diagnose
errors, for _cpp_FFK_PRE_INCLUDE that open_file_failed isn't reached
and for _cpp_FFK_FAKE neither.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk and
after a while for backports?

2023-06-13  Jakub Jelinek  <jakub@redhat.com>

	PR preprocessor/80753
libcpp/
	* files.cc (struct _cpp_file): Add deferred_error bitfield.
	(_cpp_find_file): When finding a file in cache with deferred_error
	set in _cpp_FFK_NORMAL mode, call open_file_failed and clear the flag.
	Set deferred_error in _cpp_FFK_HAS_INCLUDE mode if open_file_failed
	hasn't been called.
gcc/testsuite/
	* c-c++-common/missing-header-5.c: New test.

--- libcpp/files.cc.jj	2023-01-16 11:52:16.326730483 +0100
+++ libcpp/files.cc	2023-06-13 11:27:59.867465878 +0200
@@ -109,6 +109,10 @@ struct _cpp_file
   /* If this file is implicitly preincluded.  */
   bool implicit_preinclude : 1;
 
+  /* Set if a header wasn't found with __has_include or __has_include_next
+     and error should be emitted if it is included normally.  */
+  bool deferred_error : 1;
+
   /* > 0: Known C++ Module header unit, <0: known not.  ==0, unknown  */
   int header_unit : 2;
 };
@@ -523,7 +527,14 @@ _cpp_find_file (cpp_reader *pfile, const
   cpp_file_hash_entry *entry
     = search_cache ((struct cpp_file_hash_entry *) *hash_slot, start_dir);
   if (entry)
-    return entry->u.file;
+    {
+      if (entry->u.file->deferred_error && kind == _cpp_FFK_NORMAL)
+	{
+	  open_file_failed (pfile, entry->u.file, angle_brackets, loc);
+	  entry->u.file->deferred_error = false;
+	}
+      return entry->u.file;
+    }
 
   _cpp_file *file = make_cpp_file (start_dir, fname);
   file->implicit_preinclude
@@ -589,6 +600,8 @@ _cpp_find_file (cpp_reader *pfile, const
 
 	    if (kind != _cpp_FFK_HAS_INCLUDE)
 	      open_file_failed (pfile, file, angle_brackets, loc);
+	    else
+	      file->deferred_error = true;
 	    break;
 	  }
 
--- gcc/testsuite/c-c++-common/missing-header-5.c.jj	2023-06-13 11:29:49.345931030 +0200
+++ gcc/testsuite/c-c++-common/missing-header-5.c	2023-06-13 11:25:34.952497526 +0200
@@ -0,0 +1,15 @@
+/* PR preprocessor/80753 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+#if __has_include("nonexistent.h")
+# error
+#endif
+
+#include "nonexistent.h"
+
+/* { dg-message "nonexistent.h" "nonexistent.h" { target *-*-* } 0 } */
+/* { dg-message "terminated" "terminated" { target *-*-* } 0 } */
+
+/* This declaration should not receive any diagnostic.  */
+foo bar;

	Jakub


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] libcpp: Diagnose #include after failed __has_include [PR80753]
  2023-06-13 16:29 [PATCH] libcpp: Diagnose #include after failed __has_include [PR80753] Jakub Jelinek
@ 2023-06-15 11:48 ` Jason Merrill
  0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2023-06-15 11:48 UTC (permalink / raw)
  To: Jakub Jelinek, Joseph S. Myers, Marek Polacek; +Cc: gcc-patches

On 6/13/23 12:29, Jakub Jelinek wrote:
> Hi!
> 
> As can be seen in the testcase, we don't diagnose #include/#include_next
> of a non-existent header if __has_include/__has_include_next is done for
> that header first.
> The problem is that we normally error the first time some header is not
> found, but in the _cpp_FFK_HAS_INCLUDE case obviously don't want to diagnose
> it, just expand it to 0.  And libcpp caches both successful includes and
> unsuccessful ones.
> 
> The following patch fixes that by remembering that we haven't diagnosed
> error when using __has_include* on it, and diagnosing it when using the
> cache entry in normal mode the first time.
> 
> I think _cpp_FFK_NORMAL is the only mode in which we normally diagnose
> errors, for _cpp_FFK_PRE_INCLUDE that open_file_failed isn't reached
> and for _cpp_FFK_FAKE neither.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk and
> after a while for backports?

OK.

> 2023-06-13  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR preprocessor/80753
> libcpp/
> 	* files.cc (struct _cpp_file): Add deferred_error bitfield.
> 	(_cpp_find_file): When finding a file in cache with deferred_error
> 	set in _cpp_FFK_NORMAL mode, call open_file_failed and clear the flag.
> 	Set deferred_error in _cpp_FFK_HAS_INCLUDE mode if open_file_failed
> 	hasn't been called.
> gcc/testsuite/
> 	* c-c++-common/missing-header-5.c: New test.
> 
> --- libcpp/files.cc.jj	2023-01-16 11:52:16.326730483 +0100
> +++ libcpp/files.cc	2023-06-13 11:27:59.867465878 +0200
> @@ -109,6 +109,10 @@ struct _cpp_file
>     /* If this file is implicitly preincluded.  */
>     bool implicit_preinclude : 1;
>   
> +  /* Set if a header wasn't found with __has_include or __has_include_next
> +     and error should be emitted if it is included normally.  */
> +  bool deferred_error : 1;
> +
>     /* > 0: Known C++ Module header unit, <0: known not.  ==0, unknown  */
>     int header_unit : 2;
>   };
> @@ -523,7 +527,14 @@ _cpp_find_file (cpp_reader *pfile, const
>     cpp_file_hash_entry *entry
>       = search_cache ((struct cpp_file_hash_entry *) *hash_slot, start_dir);
>     if (entry)
> -    return entry->u.file;
> +    {
> +      if (entry->u.file->deferred_error && kind == _cpp_FFK_NORMAL)
> +	{
> +	  open_file_failed (pfile, entry->u.file, angle_brackets, loc);
> +	  entry->u.file->deferred_error = false;
> +	}
> +      return entry->u.file;
> +    }
>   
>     _cpp_file *file = make_cpp_file (start_dir, fname);
>     file->implicit_preinclude
> @@ -589,6 +600,8 @@ _cpp_find_file (cpp_reader *pfile, const
>   
>   	    if (kind != _cpp_FFK_HAS_INCLUDE)
>   	      open_file_failed (pfile, file, angle_brackets, loc);
> +	    else
> +	      file->deferred_error = true;
>   	    break;
>   	  }
>   
> --- gcc/testsuite/c-c++-common/missing-header-5.c.jj	2023-06-13 11:29:49.345931030 +0200
> +++ gcc/testsuite/c-c++-common/missing-header-5.c	2023-06-13 11:25:34.952497526 +0200
> @@ -0,0 +1,15 @@
> +/* PR preprocessor/80753 */
> +/* { dg-do compile } */
> +/* { dg-options "" } */
> +
> +#if __has_include("nonexistent.h")
> +# error
> +#endif
> +
> +#include "nonexistent.h"
> +
> +/* { dg-message "nonexistent.h" "nonexistent.h" { target *-*-* } 0 } */
> +/* { dg-message "terminated" "terminated" { target *-*-* } 0 } */
> +
> +/* This declaration should not receive any diagnostic.  */
> +foo bar;
> 
> 	Jakub
> 


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-06-15 11:48 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-13 16:29 [PATCH] libcpp: Diagnose #include after failed __has_include [PR80753] Jakub Jelinek
2023-06-15 11:48 ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).