c++: Inform of CMI reads [PR 99166]

Message ID e54826d0-9b51-9ca0-ca98-0cf50a7e500e@acm.org
State New
Headers show
Series
  • c++: Inform of CMI reads [PR 99166]
Related show

Commit Message

Nathan Sidwell Feb. 19, 2021, 5:39 p.m.
When successfully reading a module CMI,	the user gets no indication of 
where that CMI was located.  I originally didn't consider this a problem 
-- the read was successful after all.  But it can make it difficult to 
interact with build systems, particularly when caching can be involved. 
Grovelling over internal dump files is not really useful to the user. 
Hence this option, which is similar to the -flang-info-include-translate 
variants, and allows the user to ask for all, or specific module read 
notification.

         gcc/c-family/
         * c.opt (flang-info-module-read, flang-info-module-read=): New.	
         gcc/
         * doc/invoke.texi (flang-info-module-read): Document.
         gcc/cp/
         * module.cc (note_cmis): New.
         (struct module_state): Add inform_read_p bit.
         (module_state::do_import): Inform of CMI location, if enabled.
         (init_modules):	Canonicalize note_cmis entries.
         (handle_module_option):	Handle -flang-info-module-read=FOO.
         gcc/testsuite/
         * g++.dg/modules/pr99166_a.X: New.
         * g++.dg/modules/pr99166_b.C: New.
         * g++.dg/modules/pr99166_c.C: New.
         * g++.dg/modules/pr99166_d.C: New.

-- 
Nathan Sidwell

Patch

diff --git c/gcc/c-family/c.opt w/gcc/c-family/c.opt
index b209d46d32b..3264c646ad3 100644
--- c/gcc/c-family/c.opt
+++ w/gcc/c-family/c.opt
@@ -1752,6 +1752,14 @@  flang-info-include-translate=
 C++ Joined RejectNegative MissingArgError(missing header name)
 Note a #include translation of a specific header.
 
+flang-info-module-read
+C++ Var(note_module_read_yes)
+Note Compiled Module Interface pathnames.
+
+flang-info-module-read=
+C++ Joined RejectNegative MissingArgError(missing module name)
+Note Compiled Module Interface pathname of a specific module or header-unit.
+
 fmax-include-depth=
 C ObjC C++ ObjC++ Joined RejectNegative UInteger
 fmax-include-depth=<number> Set the maximum depth of the nested #include.
diff --git c/gcc/cp/module.cc w/gcc/cp/module.cc
index e801c52069e..691381bf995 100644
--- c/gcc/cp/module.cc
+++ w/gcc/cp/module.cc
@@ -317,6 +317,9 @@  version2string (unsigned version, verstr_t &out)
 /* Include files to note translation for.  */
 static vec<const char *, va_heap, vl_embed> *note_includes;
 
+/* Modules to note CMI pathames.  */
+static vec<const char *, va_heap, vl_embed> *note_cmis;
+
 /* Traits to hash an arbitrary pointer.  Entries are not deletable,
    and removal is a noop (removal needed upon destruction).  */
 template <typename T>
@@ -3547,9 +3550,10 @@  class GTY((chain_next ("%h.parent"), for_user)) module_state {
 			   do it again  */
   bool call_init_p : 1; /* This module's global initializer needs
 			   calling.  */
+  bool inform_read_p : 1; /* Inform of a read.  */
   /* Record extensions emitted or permitted.  */
   unsigned extensions : SE_BITS;
-  /* 12 bits used, 4 bits remain  */
+  /* 13 bits used, 3 bits remain  */
 
  public:
   module_state (tree name, module_state *, bool);
@@ -3782,6 +3786,8 @@  module_state::module_state (tree name, module_state *parent, bool partition)
 
   partition_p = partition;
 
+  inform_read_p = false;
+
   extensions = 0;
   if (name && TREE_CODE (name) == STRING_CST)
     {
@@ -18634,6 +18640,8 @@  module_state::do_import (cpp_reader *reader, bool outermost)
     {
       const char *file = maybe_add_cmi_prefix (filename);
       dump () && dump ("CMI is %s", file);
+      if (note_module_read_yes || inform_read_p)
+	inform (loc, "reading CMI %qs", file);
       fd = open (file, O_RDONLY | O_CLOEXEC | O_BINARY);
       e = errno;
     }
@@ -19545,6 +19553,7 @@  init_modules (cpp_reader *reader)
   headers = BITMAP_GGC_ALLOC ();
 
   if (note_includes)
+    /* Canonicalize header names.  */
     for (unsigned ix = 0; ix != note_includes->length (); ix++)
       {
 	const char *hdr = (*note_includes)[ix];
@@ -19567,6 +19576,37 @@  init_modules (cpp_reader *reader)
 	(*note_includes)[ix] = path;
       }
 
+  if (note_cmis)
+    /* Canonicalize & mark module names.  */
+    for (unsigned ix = 0; ix != note_cmis->length (); ix++)
+      {
+	const char *name = (*note_cmis)[ix];
+	size_t len = strlen (name);
+
+	bool is_system = name[0] == '<';
+	bool is_user = name[0] == '"';
+	bool is_pathname = false;
+	if (!(is_system || is_user))
+	  for (unsigned ix = len; !is_pathname && ix--;)
+	    is_pathname = IS_DIR_SEPARATOR (name[ix]);
+	if (is_system || is_user || is_pathname)
+	  {
+	    if (len <= (is_pathname ? 0 : 2)
+		|| (!is_pathname && name[len-1] != (is_system ? '>' : '"')))
+	      {
+		error ("invalid header name %qs", name);
+		continue;
+	      }
+	    else
+	      name = canonicalize_header_name (is_pathname ? nullptr : reader,
+					       0, is_pathname, name, len);
+	  }
+	if (auto module = get_module (name))
+	  module->inform_read_p = 1;
+	else
+	  error ("invalid module name %qs", name);
+      }
+
   dump.push (NULL);
 
   /* Determine lazy handle bound.  */
@@ -19952,6 +19992,10 @@  handle_module_option (unsigned code, const char *str, int)
       vec_safe_push (note_includes, str);
       return true;
 
+    case OPT_flang_info_module_read_:
+      vec_safe_push (note_cmis, str);
+      return true;
+
     default:
       return false;
     }
diff --git c/gcc/doc/invoke.texi w/gcc/doc/invoke.texi
index c00514a6306..ea315f1be58 100644
--- c/gcc/doc/invoke.texi
+++ w/gcc/doc/invoke.texi
@@ -240,8 +240,9 @@  in the following sections.
 -fvisibility-inlines-hidden @gol
 -fvisibility-ms-compat @gol
 -fext-numeric-literals @gol
--flang-info-include-translate@r{[}=@var{name}@r{]} @gol
+-flang-info-include-translate@r{[}=@var{header}@r{]} @gol
 -flang-info-include-translate-not @gol
+-flang-info-module-read@r{[}=@var{module}@r{]} @gol
 -stdlib=@var{libstdc++,libc++} @gol
 -Wabi-tag  -Wcatch-value  -Wcatch-value=@var{n} @gol
 -Wno-class-conversion  -Wclass-memaccess @gol
@@ -3382,13 +3383,22 @@  is used when building the C++ library.)
 @itemx -flang-info-include-translate=@var{header}
 @opindex flang-info-include-translate
 @opindex flang-info-include-translate-not
-Diagnose include translation events.  The first will note accepted
+Inform of include translation events.  The first will note accepted
 include translations, the second will note declined include
 translations.  The @var{header} form will inform of include
 translations relating to that specific header.  If @var{header} is of
 the form @code{"user"} or @code{<system>} it will be resolved to a
 specific user or system header using the include path.
 
+@item -flang-info-module-read
+@itemx -flang-info-module-read=@var{module}
+@opindex flang-info-module-read
+Inform of Compiled Module Interface pathnames.  The first will note
+all read CMI pathnames.  The @var{module} form will not reading a
+specific module's CMI.  @var{module} may be a named module or a
+header-unit (the latter indicated by either being a pathname containing
+directory separators or enclosed in @code{<>} or @code{""}).
+
 @item -stdlib=@var{libstdc++,libc++}
 @opindex stdlib
 When G++ is configured to support this option, it allows specification of
@@ -33050,9 +33060,15 @@  textual.  With an argument, queries about include translation of a
 header files with that particular trailing pathname are noted.  You
 may repeat this form to cover several different header files.  This
 option may be helpful in determining whether include translation is
-happening---if it is working correctly, it'll behave as if it wasn't
+happening---if it is working correctly, it behaves as if it isn't
 there at all.
 
+The @option{-flang-info-module-read} option can be used to determine
+where the compiler is reading a CMI from.  Without the option, the
+compiler is silent when such a read is successful.  This option has an
+optional argument, which will restrict the notification to just the
+set of named modules or header units specified.
+
 The @option{-Winvalid-imported-macros} option causes all imported macros
 to be resolved at the end of compilation.  Without this, imported
 macros are only resolved when expanded or (re)defined.  This option
diff --git c/gcc/testsuite/g++.dg/modules/pr99166_a.X w/gcc/testsuite/g++.dg/modules/pr99166_a.X
new file mode 100644
index 00000000000..ad7ce7edf45
--- /dev/null
+++ w/gcc/testsuite/g++.dg/modules/pr99166_a.X
@@ -0,0 +1,6 @@ 
+// PR c++/99166, diagnostic
+// { dg-additional-options {-x c++-system-header iostream -fmodules-ts} }
+
+// { dg-prune-output {linker input file unused} }
+
+NO DO NOT COMPILE
diff --git c/gcc/testsuite/g++.dg/modules/pr99166_b.C w/gcc/testsuite/g++.dg/modules/pr99166_b.C
new file mode 100644
index 00000000000..64c5a8647ec
--- /dev/null
+++ w/gcc/testsuite/g++.dg/modules/pr99166_b.C
@@ -0,0 +1,7 @@ 
+// { dg-additional-options {-fmodules-ts -flang-info-module-read=<iostream>} }
+export module Foo;
+import <iostream>;
+
+export void frob ();
+
+// { dg-regexp {In module imported at [^\n]*pr99166_b.C:[0-9:]*\n[^\b]*iostream: note: reading CMI 'gcm.cache/[^[\n]*iostream.gcm'\n} }
diff --git c/gcc/testsuite/g++.dg/modules/pr99166_c.C w/gcc/testsuite/g++.dg/modules/pr99166_c.C
new file mode 100644
index 00000000000..d098f07279d
--- /dev/null
+++ w/gcc/testsuite/g++.dg/modules/pr99166_c.C
@@ -0,0 +1,4 @@ 
+// { dg-additional-options {-fmodules-ts -flang-info-module-read=Foo} }
+module Foo;
+
+// { dg-regexp {In module imported at [^\n]*pr99166_c.C:[0-9:]*\n[^\b]*Foo: note: reading CMI 'gcm.cache/Foo.gcm'\n} }
diff --git c/gcc/testsuite/g++.dg/modules/pr99166_d.C w/gcc/testsuite/g++.dg/modules/pr99166_d.C
new file mode 100644
index 00000000000..423053ec9ff
--- /dev/null
+++ w/gcc/testsuite/g++.dg/modules/pr99166_d.C
@@ -0,0 +1,6 @@ 
+// { dg-additional-options {-fmodules-ts -flang-info-module-read} }
+import Foo;
+
+// { dg-regexp {In module imported at [^\n]*pr99166_d.C:[0-9:]*\n[^\b]*Foo: note: reading CMI 'gcm.cache/Foo.gcm'\n} }
+
+// { dg-regexp {In module imported at [^\n]*pr99166_b.C:[0-9:]*,\nof module Foo, imported at [^\n]*pr99166_d.C:[0-9:]:\n[^\b]*iostream: note: reading CMI 'gcm.cache/[^[\n]*iostream.gcm'\n} }