Re: [PATCH] c++/modules: Fix ICE when writing nontrivial variable initializers

2024-01-06 Thread Nathan Sidwell

ok

On 1/2/24 17:43, Nathaniel Shead wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

The attached testcase Patrick found in PR c++/112899 ICEs because it is
attempting to write a variable initializer that is no longer in the
static_aggregates map.

The issue is that, for non-header modules, the loop in
c_parse_final_cleanups prunes the static_aggregates list, which means
that by the time we get to emitting module information those
initialisers have been lost.

However, we don't actually need to write non-trivial initialisers for
non-header modules, because they've already been emitted as part of the
module TU itself.  Instead let's just only write the initializers from
header modules (which skipped writing them in c_parse_final_cleanups).

gcc/cp/ChangeLog:

* module.cc (trees_out::write_var_def): Only write initializers
in header modules.

gcc/testsuite/ChangeLog:

* g++.dg/modules/init-5_a.C: New test.
* g++.dg/modules/init-5_b.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/module.cc|  3 ++-
  gcc/testsuite/g++.dg/modules/init-5_a.C |  9 +
  gcc/testsuite/g++.dg/modules/init-5_b.C | 10 ++
  3 files changed, 21 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/init-5_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/init-5_b.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 14818131a70..82b61a2c2ad 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -11707,7 +11707,8 @@ trees_out::write_var_def (tree decl)
  {
tree dyn_init = NULL_TREE;
  
-  if (DECL_NONTRIVIALLY_INITIALIZED_P (decl))

+  /* We only need to write initializers in header modules.  */
+  if (header_module_p () && DECL_NONTRIVIALLY_INITIALIZED_P (decl))
{
  dyn_init = value_member (decl,
   CP_DECL_THREAD_LOCAL_P (decl)
diff --git a/gcc/testsuite/g++.dg/modules/init-5_a.C 
b/gcc/testsuite/g++.dg/modules/init-5_a.C
new file mode 100644
index 000..466b120b5a0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/init-5_a.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi M }
+
+export module M;
+
+export struct A {
+  static int f() { return -1; }
+  static inline int x = f();
+};
diff --git a/gcc/testsuite/g++.dg/modules/init-5_b.C 
b/gcc/testsuite/g++.dg/modules/init-5_b.C
new file mode 100644
index 000..40973cc6936
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/init-5_b.C
@@ -0,0 +1,10 @@
+// { dg-module-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+import M;
+
+int main() {
+  const int& x = A::x;
+  if (x != -1)
+    __builtin_abort();
+}


--
Nathan Sidwell



Re: [PATCH] c++/modules: Prevent overwriting arguments for duplicates [PR112588]

2024-01-06 Thread Nathan Sidwell
I;m not sure about this, there was clearly a reason I did it the way it is, but 
perhaps that reasoning became obsolete -- something about an existing 
declaration and reading in a definition maybe?


nathan

On 11/22/23 06:33, Nathaniel Shead wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu. I don't have write
access.

-- >8 --

When merging duplicate instantiations of function templates, currently
read_function_def overwrites the arguments with that of the existing
duplicate. This is problematic, however, since this means that the
PARM_DECLs in the body of the function definition no longer match with
the PARM_DECLs in the argument list, which causes issues when it comes
to generating RTL.

There doesn't seem to be any reason to do this replacement, so this
patch removes that logic.

PR c++/112588

gcc/cp/ChangeLog:

* module.cc (trees_in::read_function_def): Don't overwrite
arguments.

gcc/testsuite/ChangeLog:

* g++.dg/modules/merge-16.h: New test.
* g++.dg/modules/merge-16_a.C: New test.
* g++.dg/modules/merge-16_b.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/module.cc  |  2 --
  gcc/testsuite/g++.dg/modules/merge-16.h   | 10 ++
  gcc/testsuite/g++.dg/modules/merge-16_a.C |  7 +++
  gcc/testsuite/g++.dg/modules/merge-16_b.C |  5 +
  4 files changed, 22 insertions(+), 2 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/merge-16.h
  create mode 100644 gcc/testsuite/g++.dg/modules/merge-16_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/merge-16_b.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 4f5b6e2747a..2520ab659cc 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -11665,8 +11665,6 @@ trees_in::read_function_def (tree decl, tree 
maybe_template)
DECL_RESULT (decl) = result;
DECL_INITIAL (decl) = initial;
DECL_SAVED_TREE (decl) = saved;
-  if (maybe_dup)
-   DECL_ARGUMENTS (decl) = DECL_ARGUMENTS (maybe_dup);
  
if (context)

SET_DECL_FRIEND_CONTEXT (decl, context);
diff --git a/gcc/testsuite/g++.dg/modules/merge-16.h 
b/gcc/testsuite/g++.dg/modules/merge-16.h
new file mode 100644
index 000..fdb38551103
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-16.h
@@ -0,0 +1,10 @@
+// PR c++/112588
+
+void f(int*);
+
+template 
+struct S {
+  void g(int n) { f(); }
+};
+
+template struct S;
diff --git a/gcc/testsuite/g++.dg/modules/merge-16_a.C 
b/gcc/testsuite/g++.dg/modules/merge-16_a.C
new file mode 100644
index 000..c243224c875
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-16_a.C
@@ -0,0 +1,7 @@
+// PR c++/112588
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi merge16 }
+
+module;
+#include "merge-16.h"
+export module merge16;
diff --git a/gcc/testsuite/g++.dg/modules/merge-16_b.C 
b/gcc/testsuite/g++.dg/modules/merge-16_b.C
new file mode 100644
index 000..8c7b1f0511f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/merge-16_b.C
@@ -0,0 +1,5 @@
+// PR c++/112588
+// { dg-additional-options "-fmodules-ts" }
+
+#include "merge-16.h"
+import merge16;


--
Nathan Sidwell



Re: [PATCH] c++/modules: more checks for exporting names with using-declarations

2024-01-06 Thread Nathan Sidwell
auto_diagnostic_group d;
- error ("%q#D does not have external linkage", new_fn);
- inform (DECL_SOURCE_LOCATION (new_fn),
- "%q#D declared here", new_fn);
- exporting = false;
-   }
-   }
+   exporting = check_can_export_using_decl (new_fn);
  
  	  /* [namespace.udecl]
  
@@ -4938,20 +4966,26 @@ do_nonmember_using_decl (name_lookup , bool fn_scope_p,

failed = true;
  }
else if (insert_p)
-// FIXME:what if we're newly exporting lookup.value
-value = lookup.value;
+{
+  value = lookup.value;
+  if (revealing_p && module_exporting_p ())
+   check_can_export_using_decl (value);
+}

/* Now the type binding.  */

if (lookup.type && lookup.type != type)
  {
-  // FIXME: What if we're exporting lookup.type?
if (type && !decls_match (lookup.type, type))
{
  diagnose_name_conflict (lookup.type, type);
  failed = true;
}
else if (insert_p)
-   type = lookup.type;
+   {
+ type = lookup.type;
+ if (revealing_p && module_exporting_p ())
+   check_can_export_using_decl (type);
+   }
  }
  
if (insert_p)

diff --git a/gcc/testsuite/g++.dg/modules/using-10.C 
b/gcc/testsuite/g++.dg/modules/using-10.C
new file mode 100644
index 000..5735353ee21
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-10.C
@@ -0,0 +1,71 @@
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi !bad }
+
+export module bad;
+
+// internal linkage
+namespace s {
+  namespace {
+struct a1 {};  // { dg-message "declared here with internal linkage" }
+
+template 
+struct b1;  // { dg-message "declared here with internal linkage" }
+
+int x1;  // { dg-message "declared here with internal linkage" }
+
+template 
+T y1;  // { dg-message "declared here with internal linkage" }
+
+void f1();  // { dg-message "declared here with internal linkage" }
+
+template 
+void g1();  // { dg-message "declared here with internal linkage" }
+  }
+}
+
+// module linkage
+namespace m {
+  struct a2 {};  // { dg-message "declared here with module linkage" }
+
+  template 
+  struct b2;  // { dg-message "declared here with module linkage" }
+
+  int x2;  // { dg-message "declared here with module linkage" }
+
+  template 
+  T y2;  // { dg-message "declared here with module linkage" }
+
+  void f2();  // { dg-message "declared here with module linkage" }
+
+  template 
+  void g2();  // { dg-message "declared here with module linkage" }
+}
+
+export using s::a1;  // { dg-error "does not have external linkage" }
+export using s::b1;  // { dg-error "does not have external linkage" }
+export using s::x1;  // { dg-error "does not have external linkage" }
+export using s::y1;  // { dg-error "does not have external linkage" }
+export using s::f1;  // { dg-error "does not have external linkage" }
+export using s::g1;  // { dg-error "does not have external linkage" }
+
+export using m::a2;  // { dg-error "does not have external linkage" }
+export using m::b2;  // { dg-error "does not have external linkage" }
+export using m::x2;  // { dg-error "does not have external linkage" }
+export using m::y2;  // { dg-error "does not have external linkage" }
+export using m::f2;  // { dg-error "does not have external linkage" }
+export using m::g2;  // { dg-error "does not have external linkage" }
+
+namespace t {
+  using a = int;  // { dg-message "declared here with no linkage" }
+
+  template 
+  using b = int;  // { dg-message "declared here with no linkage" }
+
+  typedef int c;  // { dg-message "declared here with no linkage" }
+}
+
+export using t::a;  // { dg-error "does not have external linkage" }
+export using t::b;  // { dg-error "does not have external linkage" }
+export using t::c;  // { dg-error "does not have external linkage" }
+
+// { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/using-enum-2.C 
b/gcc/testsuite/g++.dg/modules/using-enum-2.C
new file mode 100644
index 000..813e2f630ab
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-enum-2.C
@@ -0,0 +1,23 @@
+// { dg-additional-options "-fmodules-ts -std=c++2a" }
+// { dg-module-cmi !bad }
+
+export module bad;
+
+namespace s {
+  namespace {
+enum e1 { x1 };  // { dg-message "declared here with internal linkage" }
+enum class e2 { x2 };  // { dg-message "declared here with internal 
linkage" }
+  }
+}
+
+namespace m {
+  enum e3 { x3 };  // { dg-message "declared here with module linkage" }
+  enum class e4 { x4 };  // { dg-message "declared here with module linkage" }
+}
+
+export using enum s::e1;  // { dg-error "does not have external linkage" }
+export using enum s::e2;  // { dg-error "does not have external linkage" }
+export using enum m::e3;  // { dg-error "does not have external linkage" }
+export using enum m::e4;  // { dg-error "does not have external linkage" }
+
+// { dg-prune-output "not writing module" }


--
Nathan Sidwell



Re: c++/modules: Emit definitions of ODR-used static members imported from modules [PR112899]

2024-01-06 Thread Nathan Sidwell
Richard Smith & I discussed whether we should use the module interface's 
capability of giving vague linkage entities a strong location. I didn't want to 
go messing with that, 'cos it was changing yet more stuff.


But, perhaps we should revisit that?  Any keyless polymorphic class in module 
purview gets its vtables etc emitted in the module's object file?  Likewise 
these kinds of entities.


cc'ing Iain, who probably knows more about Clang's state here.

nathan


On 1/4/24 21:06, Jason Merrill wrote:

On 1/4/24 18:02, Nathaniel Shead wrote:

On Thu, Jan 04, 2024 at 05:42:34PM -0500, Jason Merrill wrote:

On 1/4/24 17:24, Nathaniel Shead wrote:

On Thu, Jan 04, 2024 at 03:31:50PM -0500, Jason Merrill wrote:

On 1/2/24 17:40, Nathaniel Shead wrote:

Static data members marked 'inline' should be emitted in TUs where they
are ODR-used.  We need to make sure that statics imported from modules
are correctly added to the 'pending_statics' map so that they get
emitted if needed, otherwise the attached testcase fails to link.


Hmm, this seems wrong to me; I'd think that static data members marked
inline should be emitted in the module, and not in importers.


That's what I'd initially thought too, but this is at least consistent
with non-class inlines (variables and functions), which similarly only
get emitted in TUs that they're ODR-used rather than always (and only)
being emitted within the module.

I guess an alternative would be to change it around so that all
exported definitions are marked as needed in the module interface file
(and emitted there), and then setting some flag so that they're never
emitted in importers.


Yes, that would be my expectation.  What do other modules implementations
do?


Clang only emits ODR-used declarations (same as GCC currently).

MSVC emits all inline variables (whether exported or not) but no inline
functions.


Hmm, not a strong vote for my direction.


I'm not entirely sure what flag that would be
though, I still haven't quite wrapped my head what controls what with
regards to this, and I'm not convinced it wouldn't break template
instantiations.


I would guess avoid emitting if DECL_MODULE_IMPORT_P &&
DECL_MODULE_ATTACH_P.


Ah yup, that would make sense. I guess, thinking about it more, we
should then also ensure that all TREE_PUBLIC declarations are emitted in
the module interface even if not exported, since they may be needed in
implementation units?


That would also make sense to me; since we know the module interface unit is 
compiled to an object file, everything vague linkage in it can go there.



I wonder if this might also be related to the issue Nathan noted with
regards to block-scope class methods, which I haven't completely worked
out how to solve yet otherwise (see
https://gcc.gnu.org/pipermail/gcc-patches/2023-November/638223.html).


Indeed.


I'll give implementing this a try then, if you think that would be
sensible. (Where by "this" I mean "emit all public declarations in
module interface files, whether used or not".)


I'd like to hear Nathan's thoughts on the matter first, since he's the modules 
implementation designer.


Jason



--
Nathan Sidwell



Re: [PATCH] c++: Export usings referring to global module fragment [PR109679]

2024-01-06 Thread Nathan Sidwell

ok


On 1/3/24 05:01, Nathaniel Shead wrote:

Bootstrapped & regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

This patch stops 'add_binding_entity' from ignoring all names in the
global module fragment, since they should still be exported if named
in an exported using-declaration.

PR c++/109679

gcc/cp/ChangeLog:

* module.cc (depset::hash::add_binding_entity): Don't skip names
in the GMF if they've been exported with a using declaration.

gcc/testsuite/ChangeLog:

* g++.dg/modules/using-11.h: New test.
* g++.dg/modules/using-11_a.C: New test.
* g++.dg/modules/using-11_b.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/module.cc  | 6 --
  gcc/testsuite/g++.dg/modules/using-11.h   | 2 ++
  gcc/testsuite/g++.dg/modules/using-11_a.C | 9 +
  gcc/testsuite/g++.dg/modules/using-11_b.C | 8 
  4 files changed, 23 insertions(+), 2 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/using-11.h
  create mode 100644 gcc/testsuite/g++.dg/modules/using-11_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/using-11_b.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 82b61a2c2ad..865a4b77eca 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -12837,8 +12837,10 @@ depset::hash::add_binding_entity (tree decl, WMB_Flags 
flags, void *data_)
else if (TREE_CODE (inner) == TEMPLATE_DECL)
inner = DECL_TEMPLATE_RESULT (inner);
  
-  if (!DECL_LANG_SPECIFIC (inner) || !DECL_MODULE_PURVIEW_P (inner))

-   /* Ignore global module fragment entities.  */
+  if ((!DECL_LANG_SPECIFIC (inner) || !DECL_MODULE_PURVIEW_P (inner))
+ && !(flags & (WMB_Using | WMB_Export)))
+   /* Ignore global module fragment entities unless explicitly
+  exported with a using declaration.  */
return false;
  
if (VAR_OR_FUNCTION_DECL_P (inner)

diff --git a/gcc/testsuite/g++.dg/modules/using-11.h 
b/gcc/testsuite/g++.dg/modules/using-11.h
new file mode 100644
index 000..64c1b0ca335
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-11.h
@@ -0,0 +1,2 @@
+// PR c++/109679
+inline int foo() { return 42; }
diff --git a/gcc/testsuite/g++.dg/modules/using-11_a.C 
b/gcc/testsuite/g++.dg/modules/using-11_a.C
new file mode 100644
index 000..b846bc79203
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-11_a.C
@@ -0,0 +1,9 @@
+// PR c++/109679
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi M }
+
+module;
+#include "using-11.h"
+
+export module M;
+export using ::foo;
diff --git a/gcc/testsuite/g++.dg/modules/using-11_b.C 
b/gcc/testsuite/g++.dg/modules/using-11_b.C
new file mode 100644
index 000..736a48c98f2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-11_b.C
@@ -0,0 +1,8 @@
+// PR c++/109679
+// { dg-module-do link }
+// { dg-additional-options "-fmodules-ts" }
+
+import M;
+int main() {
+  return foo();
+}


--
Nathan Sidwell



Re: [PATCH v2] c++: Follow module grammar more closely [PR110808]

2024-01-06 Thread Nathan Sidwell

This is ok -- sorry, I thought I'd already acked this


On 12/16/23 06:03, Nathaniel Shead wrote:

Ping for https://gcc.gnu.org/pipermail/gcc-patches/2023-November/638089.html

On Fri, Nov 24, 2023 at 10:32:13PM +1100, Nathaniel Shead wrote:

On Thu, Nov 23, 2023 at 12:11:58PM -0500, Nathan Sidwell wrote:

On 11/14/23 01:24, Nathaniel Shead wrote:

I'll also note that the comments above the parsing functions here no
longer exactly match with the grammar in the standard, should they be
updated as well?


please.



As I was attempting to rewrite the comments I ended up splitting up the
work that was being done by cp_parser_module_name a lot to better match
the grammar, and also caught a few other segfaults that were occurring
along the way.

Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

This patch cleans up the parsing of module-declarations and
import-declarations to more closely follow the grammar defined by the
standard.

For instance, currently we allow declarations like 'import A:B', even
from an unrelated source file (not part of module A), which causes
errors in merging declarations. However, the syntax in [module.import]
doesn't even allow this form of import, so this patch prevents this from
parsing at all and avoids the error that way.

Additionally, we sometimes allow statements like 'import :X' or
'module :X' even when not in a named module, and this causes segfaults,
so we disallow this too.

PR c++/110808

gcc/cp/ChangeLog:

* parser.cc (cp_parser_module_name): Rewrite to handle
module-names and module-partitions independently.
(cp_parser_module_partition): New function.
(cp_parser_module_declaration): Parse module partitions
explicitly. Don't change state if parsing module decl failed.
(cp_parser_import_declaration): Handle different kinds of
import-declarations locally.

gcc/testsuite/ChangeLog:

* g++.dg/modules/part-hdr-1_c.C: Fix syntax.
* g++.dg/modules/part-mac-1_c.C: Likewise.
* g++.dg/modules/mod-invalid-1.C: New test.
* g++.dg/modules/part-8_a.C: New test.
* g++.dg/modules/part-8_b.C: New test.
* g++.dg/modules/part-8_c.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/parser.cc | 100 ---
  gcc/testsuite/g++.dg/modules/mod-invalid-1.C |   7 ++
  gcc/testsuite/g++.dg/modules/part-8_a.C  |   6 ++
  gcc/testsuite/g++.dg/modules/part-8_b.C  |   6 ++
  gcc/testsuite/g++.dg/modules/part-8_c.C  |   8 ++
  gcc/testsuite/g++.dg/modules/part-hdr-1_c.C  |   2 +-
  gcc/testsuite/g++.dg/modules/part-mac-1_c.C  |   2 +-
  7 files changed, 95 insertions(+), 36 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/mod-invalid-1.C
  create mode 100644 gcc/testsuite/g++.dg/modules/part-8_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/part-8_b.C
  create mode 100644 gcc/testsuite/g++.dg/modules/part-8_c.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index f6d088bc73f..20bd8d45a08 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -14853,58 +14853,64 @@ cp_parser_already_scoped_statement (cp_parser* 
parser, bool *if_p,
  
  /* Modules */
  
-/* Parse a module-name,

-   identifier
-   module-name . identifier
-   header-name
+/* Parse a module-name or module-partition.
  
-   Returns a pointer to module object, NULL.   */

+   module-name:
+ module-name-qualifier [opt] identifier
  
-static module_state *

-cp_parser_module_name (cp_parser *parser)
-{
-  cp_token *token = cp_lexer_peek_token (parser->lexer);
-  if (token->type == CPP_HEADER_NAME)
-{
-  cp_lexer_consume_token (parser->lexer);
+   module-partition:
+ : module-name-qualifier [opt] identifier
  
-  return get_module (token->u.value);

-}
+   module-name-qualifier:
+ identifier .
+ module-name-qualifier identifier .
  
-  module_state *parent = NULL;

-  bool partitioned = false;
-  if (token->type == CPP_COLON && named_module_p ())
-{
-  partitioned = true;
-  cp_lexer_consume_token (parser->lexer);
-}
+   Returns a pointer to the module object, or NULL on failure.
+   For PARTITION_P, PARENT is the module this is a partition of.  */
+
+static module_state *
+cp_parser_module_name (cp_parser *parser, bool partition_p = false,
+  module_state *parent = NULL)
+{
+  if (partition_p
+  && cp_lexer_consume_token (parser->lexer)->type != CPP_COLON)
+return NULL;
  
for (;;)

  {
if (cp_lexer_peek_token (parser->lexer)->type != CPP_NAME)
{
- cp_parser_error (parser, "expected module-name");
- break;
+ if (partition_p)
+   cp_parser_error (parser, "expected module-partition");
+ else
+   cp_parser_error (parser, "expected module-name");
+ return NULL;
}
  
tree name

Re: [PATCH] c++/modules: seed namespaces for bindings [PR106363]

2024-01-06 Thread Nathan Sidwell

Ok,
I think I js=ust thought this unnecessary.


On 11/11/23 20:59, Nathaniel Shead wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu. I don't have write
access.

-- >8 --

Currently the first depset for an EK_BINDING is not seeded. This breaks
the attached testcase as then the namespace is not considered referenced
yet during streaming, but we've already finished importing.

There doesn't seem to be any particular reason I could find for skipping
the first depset for bindings, and removing the condition doesn't appear
to cause any test failures, so this patch removes that check.

PR c++/106363

gcc/cp/ChangeLog:

* module.cc (module_state::write_cluster): Don't skip first
depset for bindings.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr106363_a.C: New test.
* g++.dg/modules/pr106363_b.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/module.cc  |  4 +---
  gcc/testsuite/g++.dg/modules/pr106363_a.C |  9 +
  gcc/testsuite/g++.dg/modules/pr106363_b.C | 10 ++
  3 files changed, 20 insertions(+), 3 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/pr106363_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/pr106363_b.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index c1c8c226bc1..411a3b9411c 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -14741,9 +14741,7 @@ module_state::write_cluster (elf_out *to, depset 
*scc[], unsigned size,
for (unsigned ix = 0; ix != size; ix++)
  {
depset *b = scc[ix];
-  for (unsigned jx = (b->get_entity_kind () == depset::EK_BINDING
- || b->is_special ()) ? 1 : 0;
-  jx != b->deps.length (); jx++)
+  for (unsigned jx = b->is_special (); jx != b->deps.length (); jx++)
{
  depset *dep = b->deps[jx];
  
diff --git a/gcc/testsuite/g++.dg/modules/pr106363_a.C b/gcc/testsuite/g++.dg/modules/pr106363_a.C

new file mode 100644
index 000..c18d2eef1c8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr106363_a.C
@@ -0,0 +1,9 @@
+// PR c++/106363
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi pr106363.a }
+
+export module pr106363.a;
+
+namespace ns {
+  export int x;
+}
diff --git a/gcc/testsuite/g++.dg/modules/pr106363_b.C 
b/gcc/testsuite/g++.dg/modules/pr106363_b.C
new file mode 100644
index 000..0508c0d6193
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr106363_b.C
@@ -0,0 +1,10 @@
+// PR c++/106363
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi pr106363.b }
+
+export module pr106363.b;
+import pr106363.a;
+
+namespace ns {
+  export using ns::x;
+}


--
Nathan Sidwell



Re: [PATCH RFC] c++/modules: __class_type_info and modules

2023-12-23 Thread Nathan Sidwell

On 12/18/23 17:10, Jason Merrill wrote:

On 12/18/23 16:57, Nathan Sidwell wrote:

On 12/18/23 16:31, Jason Merrill wrote:

Tested x86_64-pc-linux-gnu.  Does this make sense?  Did you have another theory
about how to merge these?


Why isn't push_abi_namespace doing the right setup here? (and I think 
get_global_binding might be similarly problematic?)


What would the right setup be?  It pushes into the global module, but before 
this change lookup doesn't find things imported into the global module, and so 
we get two independent (and so non-equivalent) declarations.


The comment for get_namespace_binding says "Users of this who, having found 
nothing, push a new decl must be prepared for that pushing to match an existing 
decl."  But if lookup_elaborated_type fails, so we pushtag a new type, 
check_module_override doesn't try to merge them because TREE_PUBLIC isn't set on 
the TYPE_DECL yet at that point, and they coexist until we complain about 
redeclaring __dynamic_cast with non-matching parameter types.


I tried setting TREE_PUBLIC on the TYPE_DECL, and then check_module_override 
called duplicate_decls, and rejected the redeclaration as a different type.


sigh, it seems that doesn't work as intended, I guess your approace is a 
pragmatic workaround, much as I dislike special-casing particular identifier. 
Perhaps comment with an appropriate FIXME?


I've realized there's problems with completeness here -- the 'invisible' type 
may be complete, but the current TU only foreward-declares it.  Our AST can't 
represent that right now.  And I'm not sure if there are template instantiation 
issues -- is the type complete or not in any particular instantiaton?


nathan




-- 8< --

Doing a dynamic_cast in both TUs broke because we were declaring a new
__class_type_info in _b that conflicted with the one imported in the global
module from _a.  lookup_elaborated_type has a comment that we probably don't
want to find such imports in general, but in this case it seems necessary to
make the artificial lazy declarations of RTTI types work.

gcc/cp/ChangeLog:

* name-lookup.cc (lookup_elaborated_type): Look for bindings
in the global namespace in the ABI namespace.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr106304_b.C: Add dynamic_cast.
---
  gcc/cp/name-lookup.cc | 10 ++
  gcc/testsuite/g++.dg/modules/pr106304_b.C |  1 +
  2 files changed, 11 insertions(+)

diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index 09dc6ef3e5a..f15b338025d 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -8092,6 +8092,16 @@ lookup_elaborated_type (tree name, TAG_how how)
    // FIXME: This isn't quite right, if we find something
    // here, from the language PoV we're not supposed to
    // know it?
+  // We at least need to do this in __cxxabiv1 to unify lazy
+  // declarations of __class_type_info in build_dynamic_cast_1.
+  if (current_namespace == abi_node)
+    {
+  tree g = (BINDING_VECTOR_CLUSTER (*slot, 0)
+    .slots[BINDING_SLOT_GLOBAL]);
+  for (ovl_iterator iter (g); iter; ++iter)
+    if (qualify_lookup (*iter, LOOK_want::TYPE))
+  return *iter;
+    }
  }
  }
  }
diff --git a/gcc/testsuite/g++.dg/modules/pr106304_b.C 
b/gcc/testsuite/g++.dg/modules/pr106304_b.C

index e8333909c8d..0d1da086176 100644
--- a/gcc/testsuite/g++.dg/modules/pr106304_b.C
+++ b/gcc/testsuite/g++.dg/modules/pr106304_b.C
@@ -5,4 +5,5 @@ module pr106304;
  void f(A& a) {
    as_b(a);
+  dynamic_cast();
  }

base-commit: 5347263b347d02e875879ca40ca6e289ac178919
prerequisite-patch-id: 66735c0c7beb22586ed4b632d10ec9094bb9920c






--
Nathan Sidwell



Re: [PATCH RFC] c++/modules: __class_type_info and modules

2023-12-18 Thread Nathan Sidwell

On 12/18/23 16:31, Jason Merrill wrote:

Tested x86_64-pc-linux-gnu.  Does this make sense?  Did you have another theory
about how to merge these?


Why isn't push_abi_namespace doing the right setup here? (and I think 
get_global_binding might be similarly problematic?)


nathan



-- 8< --

Doing a dynamic_cast in both TUs broke because we were declaring a new
__class_type_info in _b that conflicted with the one imported in the global
module from _a.  lookup_elaborated_type has a comment that we probably don't
want to find such imports in general, but in this case it seems necessary to
make the artificial lazy declarations of RTTI types work.

gcc/cp/ChangeLog:

* name-lookup.cc (lookup_elaborated_type): Look for bindings
in the global namespace in the ABI namespace.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr106304_b.C: Add dynamic_cast.
---
  gcc/cp/name-lookup.cc | 10 ++
  gcc/testsuite/g++.dg/modules/pr106304_b.C |  1 +
  2 files changed, 11 insertions(+)

diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index 09dc6ef3e5a..f15b338025d 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -8092,6 +8092,16 @@ lookup_elaborated_type (tree name, TAG_how how)
  // FIXME: This isn't quite right, if we find something
  // here, from the language PoV we're not supposed to
  // know it?
+ // We at least need to do this in __cxxabiv1 to unify lazy
+ // declarations of __class_type_info in build_dynamic_cast_1.
+ if (current_namespace == abi_node)
+   {
+ tree g = (BINDING_VECTOR_CLUSTER (*slot, 0)
+   .slots[BINDING_SLOT_GLOBAL]);
+ for (ovl_iterator iter (g); iter; ++iter)
+   if (qualify_lookup (*iter, LOOK_want::TYPE))
+ return *iter;
+   }
}
}
  }
diff --git a/gcc/testsuite/g++.dg/modules/pr106304_b.C 
b/gcc/testsuite/g++.dg/modules/pr106304_b.C
index e8333909c8d..0d1da086176 100644
--- a/gcc/testsuite/g++.dg/modules/pr106304_b.C
+++ b/gcc/testsuite/g++.dg/modules/pr106304_b.C
@@ -5,4 +5,5 @@ module pr106304;
  
  void f(A& a) {

as_b(a);
+  dynamic_cast();
  }

base-commit: 5347263b347d02e875879ca40ca6e289ac178919
prerequisite-patch-id: 66735c0c7beb22586ed4b632d10ec9094bb9920c


--
Nathan Sidwell



Re: [PATCH] c++/modules: seed namespaces for bindings [PR106363]

2023-12-16 Thread Nathan Sidwell

On 12/16/23 05:31, Nathaniel Shead wrote:

Ping for https://gcc.gnu.org/pipermail/gcc-patches/2023-November/636159.html



ok


On Sun, Nov 12, 2023 at 12:59:36PM +1100, Nathaniel Shead wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu. I don't have write
access.

-- >8 --

Currently the first depset for an EK_BINDING is not seeded. This breaks
the attached testcase as then the namespace is not considered referenced
yet during streaming, but we've already finished importing.

There doesn't seem to be any particular reason I could find for skipping
the first depset for bindings, and removing the condition doesn't appear
to cause any test failures, so this patch removes that check.

PR c++/106363

gcc/cp/ChangeLog:

* module.cc (module_state::write_cluster): Don't skip first
depset for bindings.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr106363_a.C: New test.
* g++.dg/modules/pr106363_b.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/module.cc  |  4 +---
  gcc/testsuite/g++.dg/modules/pr106363_a.C |  9 +
  gcc/testsuite/g++.dg/modules/pr106363_b.C | 10 ++
  3 files changed, 20 insertions(+), 3 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/pr106363_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/pr106363_b.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index c1c8c226bc1..411a3b9411c 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -14741,9 +14741,7 @@ module_state::write_cluster (elf_out *to, depset 
*scc[], unsigned size,
for (unsigned ix = 0; ix != size; ix++)
  {
depset *b = scc[ix];
-  for (unsigned jx = (b->get_entity_kind () == depset::EK_BINDING
- || b->is_special ()) ? 1 : 0;
-  jx != b->deps.length (); jx++)
+  for (unsigned jx = b->is_special (); jx != b->deps.length (); jx++)
{
  depset *dep = b->deps[jx];
  
diff --git a/gcc/testsuite/g++.dg/modules/pr106363_a.C b/gcc/testsuite/g++.dg/modules/pr106363_a.C

new file mode 100644
index 000..c18d2eef1c8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr106363_a.C
@@ -0,0 +1,9 @@
+// PR c++/106363
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi pr106363.a }
+
+export module pr106363.a;
+
+namespace ns {
+  export int x;
+}
diff --git a/gcc/testsuite/g++.dg/modules/pr106363_b.C 
b/gcc/testsuite/g++.dg/modules/pr106363_b.C
new file mode 100644
index 000..0508c0d6193
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr106363_b.C
@@ -0,0 +1,10 @@
+// PR c++/106363
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi pr106363.b }
+
+export module pr106363.b;
+import pr106363.a;
+
+namespace ns {
+  export using ns::x;
+}
--
2.42.0



--
Nathan Sidwell



Re: [PATCH] c++/modules: more checks for exporting names with using-declarations

2023-11-24 Thread Nathan Sidwell
auto_diagnostic_group d;
- error ("%q#D does not have external linkage", new_fn);
- inform (DECL_SOURCE_LOCATION (new_fn),
- "%q#D declared here", new_fn);
- exporting = false;
-   }
-   }
+   exporting = check_can_export_using_decl (new_fn);
  
  	  /* [namespace.udecl]
  
@@ -4938,20 +4966,26 @@ do_nonmember_using_decl (name_lookup , bool fn_scope_p,

failed = true;
  }
else if (insert_p)
-// FIXME:what if we're newly exporting lookup.value
-value = lookup.value;
+{
+  value = lookup.value;
+  if (revealing_p && module_exporting_p ())
+   check_can_export_using_decl (value);
+}

/* Now the type binding.  */

if (lookup.type && lookup.type != type)
  {
-  // FIXME: What if we're exporting lookup.type?
if (type && !decls_match (lookup.type, type))
{
  diagnose_name_conflict (lookup.type, type);
  failed = true;
}
else if (insert_p)
-   type = lookup.type;
+   {
+ type = lookup.type;
+ if (revealing_p && module_exporting_p ())
+   check_can_export_using_decl (type);
+   }
  }
  
if (insert_p)

diff --git a/gcc/testsuite/g++.dg/modules/using-10.C 
b/gcc/testsuite/g++.dg/modules/using-10.C
new file mode 100644
index 000..5735353ee21
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-10.C
@@ -0,0 +1,71 @@
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi !bad }
+
+export module bad;
+
+// internal linkage
+namespace s {
+  namespace {
+struct a1 {};  // { dg-message "declared here with internal linkage" }
+
+template 
+struct b1;  // { dg-message "declared here with internal linkage" }
+
+int x1;  // { dg-message "declared here with internal linkage" }
+
+template 
+T y1;  // { dg-message "declared here with internal linkage" }
+
+void f1();  // { dg-message "declared here with internal linkage" }
+
+template 
+void g1();  // { dg-message "declared here with internal linkage" }
+  }
+}
+
+// module linkage
+namespace m {
+  struct a2 {};  // { dg-message "declared here with module linkage" }
+
+  template 
+  struct b2;  // { dg-message "declared here with module linkage" }
+
+  int x2;  // { dg-message "declared here with module linkage" }
+
+  template 
+  T y2;  // { dg-message "declared here with module linkage" }
+
+  void f2();  // { dg-message "declared here with module linkage" }
+
+  template 
+  void g2();  // { dg-message "declared here with module linkage" }
+}
+
+export using s::a1;  // { dg-error "does not have external linkage" }
+export using s::b1;  // { dg-error "does not have external linkage" }
+export using s::x1;  // { dg-error "does not have external linkage" }
+export using s::y1;  // { dg-error "does not have external linkage" }
+export using s::f1;  // { dg-error "does not have external linkage" }
+export using s::g1;  // { dg-error "does not have external linkage" }
+
+export using m::a2;  // { dg-error "does not have external linkage" }
+export using m::b2;  // { dg-error "does not have external linkage" }
+export using m::x2;  // { dg-error "does not have external linkage" }
+export using m::y2;  // { dg-error "does not have external linkage" }
+export using m::f2;  // { dg-error "does not have external linkage" }
+export using m::g2;  // { dg-error "does not have external linkage" }
+
+namespace t {
+  using a = int;  // { dg-message "declared here with no linkage" }
+
+  template 
+  using b = int;  // { dg-message "declared here with no linkage" }
+
+  typedef int c;  // { dg-message "declared here with no linkage" }
+}
+
+export using t::a;  // { dg-error "does not have external linkage" }
+export using t::b;  // { dg-error "does not have external linkage" }
+export using t::c;  // { dg-error "does not have external linkage" }
+
+// { dg-prune-output "not writing module" }
diff --git a/gcc/testsuite/g++.dg/modules/using-enum-2.C 
b/gcc/testsuite/g++.dg/modules/using-enum-2.C
new file mode 100644
index 000..813e2f630ab
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-enum-2.C
@@ -0,0 +1,23 @@
+// { dg-additional-options "-fmodules-ts -std=c++2a" }
+// { dg-module-cmi !bad }
+
+export module bad;
+
+namespace s {
+  namespace {
+enum e1 { x1 };  // { dg-message "declared here with internal linkage" }
+enum class e2 { x2 };  // { dg-message "declared here with internal 
linkage" }
+  }
+}
+
+namespace m {
+  enum e3 { x3 };  // { dg-message "declared here with module linkage" }
+  enum class e4 { x4 };  // { dg-message "declared here with module linkage" }
+}
+
+export using enum s::e1;  // { dg-error "does not have external linkage" }
+export using enum s::e2;  // { dg-error "does not have external linkage" }
+export using enum m::e3;  // { dg-error "does not have external linkage" }
+export using enum m::e4;  // { dg-error "does not have external linkage" }
+
+// { dg-prune-output "not writing module" }


--
Nathan Sidwell



Re: [PATCH] c++: Allow exporting a typedef redeclaration [PR102341]

2023-11-24 Thread Nathan Sidwell

On 11/23/23 21:10, Nathaniel Shead wrote:

On Thu, Nov 23, 2023 at 11:45:31AM -0500, Nathan Sidwell wrote:

On 11/13/23 01:09, Nathaniel Shead wrote:

I happened to be browsing the standard a bit later and noticed that we
incorrectly reject the example given below.

Bootstrapped on x86_64-pc-linux-gnu; regtesting ongoing but modules.exp
completed with no errors.

-- >8 --

A typedef doesn't create a new entity, and thus should be allowed to be
exported even if it has been previously declared un-exported. See the
example in [module.interface] p6:


ok.  Could you put a reference to [module.interface]/p6 in the comment though?

nathan



Thanks. I've also added a new test to ensure that the redeclarations are
actually exported. Ok for trunk?


ok




-- >8 --

A typedef doesn't create a new entity, and thus should be allowed to be
exported even if it has been previously declared un-exported. See the
example in [module.interface] p6:

   export module M;
   struct S { int n; };
   typedef S S;
   export typedef S S; // OK, does not redeclare an entity

PR c++/102341

gcc/cp/ChangeLog:

* decl.cc (duplicate_decls): Allow exporting a redeclaration of
a typedef.

gcc/testsuite/ChangeLog:

* g++.dg/modules/export-1.C: Adjust test.
* g++.dg/modules/export-2_a.C: New test.
* g++.dg/modules/export-2_b.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/decl.cc|  6 +-
  gcc/testsuite/g++.dg/modules/export-1.C   |  6 +-
  gcc/testsuite/g++.dg/modules/export-2_a.C | 14 ++
  gcc/testsuite/g++.dg/modules/export-2_b.C |  7 +++
  4 files changed, 31 insertions(+), 2 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/export-2_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/export-2_b.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 16b04ebe0f8..f8324f92ca7 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -2231,7 +2231,11 @@ duplicate_decls (tree newdecl, tree olddecl, bool 
hiding, bool was_hidden)
}
  
tree not_tmpl = STRIP_TEMPLATE (olddecl);

-  if (DECL_LANG_SPECIFIC (not_tmpl) && DECL_MODULE_ATTACH_P (not_tmpl))
+  if (DECL_LANG_SPECIFIC (not_tmpl)
+ && DECL_MODULE_ATTACH_P (not_tmpl)
+ /* Typedefs are not entities and so are OK to be redeclared
+as exported: see [module.interface] p6.  */
+ && TREE_CODE (olddecl) != TYPE_DECL)
{
  if (DECL_MODULE_EXPORT_P (STRIP_TEMPLATE (newdecl))
  && !DECL_MODULE_EXPORT_P (not_tmpl))
diff --git a/gcc/testsuite/g++.dg/modules/export-1.C 
b/gcc/testsuite/g++.dg/modules/export-1.C
index 3f93814d270..598814370ec 100644
--- a/gcc/testsuite/g++.dg/modules/export-1.C
+++ b/gcc/testsuite/g++.dg/modules/export-1.C
@@ -9,8 +9,12 @@ export int x (); // { dg-error "conflicting exporting for 
declaration" }
  int y;
  export extern int y; // { dg-error "conflicting exporting for declaration" }
  
+// A typedef is not an entity so the following is OK; see [module.interface] example 4

  typedef int z;
-export typedef int z; // { dg-error "conflicting exporting for declaration" }
+export typedef int z; // { dg-bogus "conflicting exporting for declaration" }
+
+template  using w = T;
+export template  using w = T;  // { dg-error "conflicting exporting for 
declaration" }
  
  template  int f (T);

  export template  int f (T); // { dg-error "conflicting exporting for 
declaration" }
diff --git a/gcc/testsuite/g++.dg/modules/export-2_a.C 
b/gcc/testsuite/g++.dg/modules/export-2_a.C
new file mode 100644
index 000..9a201bf37c0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/export-2_a.C
@@ -0,0 +1,14 @@
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi aliases }
+
+export module aliases;
+
+typedef int x;
+export typedef int x;
+
+using y = double;
+export using y = double;
+
+struct S {};
+using T = S;
+export using T = S;
diff --git a/gcc/testsuite/g++.dg/modules/export-2_b.C 
b/gcc/testsuite/g++.dg/modules/export-2_b.C
new file mode 100644
index 000..456aa8d9ec8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/export-2_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import aliases;
+
+x a = 123;
+y b = 12.45;
+T c = T{};


--
Nathan Sidwell



Re: [PATCH] c++: Check module attachment instead of purview when necessary [PR112631]

2023-11-23 Thread Nathan Sidwell

On 11/20/23 04:47, Nathaniel Shead wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu. I don't have write
access.

-- >8 --

Block-scope declarations of functions or extern values are not allowed
when attached to a named module. Similarly, class member functions are
not inline if attached to a named module. However, in both these cases
we currently only check if the declaration is within the module purview;
it is possible for such a declaration to occur within the module purview
but not be attached to a named module (e.g. in an 'extern "C++"' block).
This patch makes the required adjustments.



Ah I'd been puzzling over the default inlinedness of  member-fns of block-scope 
structs.  Could you augment the testcase to make sure that's right too?


Something like:

// dg-module-do link
export module Mod;

export auto Get () {
  struct X { void Fn () {} };
  return X();
}


///
import Mod
void Frob () { Get().Fn(); }



PR c++/112631

gcc/cp/ChangeLog:

* cp-tree.h (named_module_attach_p): New function.
* decl.cc (start_decl): Use named_module_attach_p instead of
named_module_purview_p.
(grokmethod): Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr112631.C: New test.
---
  gcc/cp/cp-tree.h|  2 ++
  gcc/cp/decl.cc  | 10 +-
  gcc/testsuite/g++.dg/modules/pr112631.C |  8 
  3 files changed, 15 insertions(+), 5 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/pr112631.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7b0b7c6a17e..9a3981cef58 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7315,6 +7315,8 @@ inline bool module_attach_p ()
  
  inline bool named_module_purview_p ()

  { return named_module_p () && module_purview_p (); }
+inline bool named_module_attach_p ()
+{ return named_module_p () && module_attach_p (); }
  
  /* We're currently exporting declarations.  */

  inline bool module_exporting_p ()
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index e6f75d771e0..395f108aec7 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -5917,10 +5917,10 @@ start_decl (const cp_declarator *declarator,
  {
/* A function-scope decl of some namespace-scope decl.  */
DECL_LOCAL_DECL_P (decl) = true;
-  if (named_module_purview_p ())
+  if (named_module_attach_p ())
error_at (declarator->id_loc,
- "block-scope extern declaration %q#D not permitted"
- " in module purview", decl);
+ "block-scope extern declaration %q#D must not be"
+ " attached to a named module", decl);
  }
  
/* Enter this declaration into the symbol table.  Don't push the plain

@@ -18513,10 +18513,10 @@ grokmethod (cp_decl_specifier_seq *declspecs,
check_template_shadow (fndecl);
  
/* p1779 ABI-Isolation makes inline not a default for in-class

- definitions in named module purview.  If the user explicitly
+ definitions attached to a named module.  If the user explicitly
   made it inline, grokdeclarator will already have done the right
   things.  */
-  if ((!named_module_purview_p ()
+  if ((!named_module_attach_p ()
 || flag_module_implicit_inline
/* Lambda's operator function remains inline.  */
 || LAMBDA_TYPE_P (DECL_CONTEXT (fndecl)))
diff --git a/gcc/testsuite/g++.dg/modules/pr112631.C 
b/gcc/testsuite/g++.dg/modules/pr112631.C
new file mode 100644
index 000..b5e81a1041b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr112631.C
@@ -0,0 +1,8 @@
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi bla }
+
+export module bla;
+
+extern "C++" inline void fun() {
+  void oops();  // { dg-bogus "block-scope extern declaration" }
+}


--
Nathan Sidwell



Re: [PATCH] c++/modules: Allow exporting const-qualified namespace-scope variables [PR99232]

2023-11-23 Thread Nathan Sidwell

On 11/15/23 07:24, Nathaniel Shead wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu. I don't have write
access.

-- >8 --

By [basic.link] p3.2.1, a non-template non-volatile const-qualified
variable is not necessarily internal linkage in a module declaration,
and rather may have module linkage (or external linkage if it is
exported, see p4.8).


ok, but can you augment the testcase to check the address is the same in both 
TUs?  (something like an accessor in the module and a runtime-check in the 
importer?)


nathan



PR c++/99232

gcc/cp/ChangeLog:

* decl.cc (grokvardecl): Don't mark variables attached to
 modules as internal.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr99232_a.C: New test.
* g++.dg/modules/pr99232_b.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/decl.cc   | 3 ++-
  gcc/testsuite/g++.dg/modules/pr99232_a.C | 8 
  gcc/testsuite/g++.dg/modules/pr99232_b.C | 7 +++
  3 files changed, 17 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/pr99232_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/pr99232_b.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index d2ed46b1453..173dd93ef5b 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -10992,7 +10992,8 @@ grokvardecl (tree type,
&& (DECL_THIS_EXTERN (decl)
|| ! constp
|| volatilep
-   || inlinep));
+   || inlinep
+   || module_attach_p ()));
TREE_STATIC (decl) = ! DECL_EXTERNAL (decl);
  }
/* Not at top level, only `static' makes a static definition.  */
diff --git a/gcc/testsuite/g++.dg/modules/pr99232_a.C 
b/gcc/testsuite/g++.dg/modules/pr99232_a.C
new file mode 100644
index 000..33b3b783399
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr99232_a.C
@@ -0,0 +1,8 @@
+// PR c++/99232
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi pr99232 }
+
+export module pr99232;
+
+export const double lambda{ 1.3 };
+export constexpr int a = 42;
diff --git a/gcc/testsuite/g++.dg/modules/pr99232_b.C 
b/gcc/testsuite/g++.dg/modules/pr99232_b.C
new file mode 100644
index 000..98f3c52a51c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr99232_b.C
@@ -0,0 +1,7 @@
+// PR c++/99232
+// { dg-additional-options "-fmodules-ts" }
+
+import pr99232;
+
+double foo() { return lambda * 2.0; }
+static_assert(a == 42);


--
Nathan Sidwell



Re: [PATCH] c++/modules: Restrict partitions when parsing import declarations [PR110808]

2023-11-23 Thread Nathan Sidwell
+}
diff --git a/gcc/testsuite/g++.dg/modules/part-hdr-1_c.C 
b/gcc/testsuite/g++.dg/modules/part-hdr-1_c.C
index 78a53d2fda3..db57adcef44 100644
--- a/gcc/testsuite/g++.dg/modules/part-hdr-1_c.C
+++ b/gcc/testsuite/g++.dg/modules/part-hdr-1_c.C
@@ -2,4 +2,4 @@
  // { dg-module-cmi {mod} }
  
  export module mod;

-import mod:impl;
+import :impl;
diff --git a/gcc/testsuite/g++.dg/modules/part-mac-1_c.C 
b/gcc/testsuite/g++.dg/modules/part-mac-1_c.C
index 78a53d2fda3..db57adcef44 100644
--- a/gcc/testsuite/g++.dg/modules/part-mac-1_c.C
+++ b/gcc/testsuite/g++.dg/modules/part-mac-1_c.C
@@ -2,4 +2,4 @@
  // { dg-module-cmi {mod} }
  
  export module mod;

-import mod:impl;
+import :impl;


--
Nathan Sidwell



Re: [PATCH] c++/modules: Support lambdas in static template member initialisers [PR107398]

2023-11-23 Thread Nathan Sidwell

On 11/13/23 06:58, Nathaniel Shead wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu. I don't have write access.

-- >8 --

The testcase noted in the PR fails because the context of the lambda is
not in namespace scope, but rather in class scope. This patch removes
the assertion that the context must be a namespace and ensures that
lambdas in class scope still get the correct merge_kind.


ok, could you put a comment in the lambda chcking part that it's context might 
be a class, even though it's not member in the conventional sense?


nathan



PR c++/107398

gcc/cp/ChangeLog:

* module.cc (trees_out::get_merge_kind): Handle lambdas in class
scope.
(maybe_key_decl): Remove assertion and fix whitespace.

gcc/testsuite/ChangeLog:

* g++.dg/modules/lambda-6_a.C: New test.
* g++.dg/modules/lambda-6_b.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/module.cc  | 35 +--
  gcc/testsuite/g++.dg/modules/lambda-6_a.C | 16 +++
  gcc/testsuite/g++.dg/modules/lambda-6_b.C |  9 ++
  3 files changed, 45 insertions(+), 15 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/lambda-6_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/lambda-6_b.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index c1c8c226bc1..434caf22d1d 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -10412,13 +10412,13 @@ trees_out::get_merge_kind (tree decl, depset *dep)
  
  	  case RECORD_TYPE:

  case UNION_TYPE:
+ case NAMESPACE_DECL:
if (DECL_NAME (decl) == as_base_identifier)
- mk = MK_as_base;
-   else if (IDENTIFIER_ANON_P (DECL_NAME (decl)))
- mk = MK_field;
-   break;
+ {
+   mk = MK_as_base;
+   break;
+ }
  
-	  case NAMESPACE_DECL:

if (DECL_IMPLICIT_TYPEDEF_P (STRIP_TEMPLATE (decl))
&& LAMBDA_TYPE_P (TREE_TYPE (decl)))
  if (tree scope
@@ -10431,6 +10431,13 @@ trees_out::get_merge_kind (tree decl, depset *dep)
break;
  }
  
+	if (RECORD_OR_UNION_TYPE_P (ctx))

+ {
+   if (IDENTIFIER_ANON_P (DECL_NAME (decl)))
+ mk = MK_field;
+   break;
+ }
+
if (TREE_CODE (decl) == TEMPLATE_DECL
&& DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl))
  mk = MK_local_friend;
@@ -18887,18 +18894,16 @@ maybe_key_decl (tree ctx, tree decl)
if (TREE_CODE (ctx) != VAR_DECL)
  return;
  
-  gcc_checking_assert (DECL_NAMESPACE_SCOPE_P (ctx));

-
- if (!keyed_table)
+  if (!keyed_table)
  keyed_table = new keyed_map_t (EXPERIMENT (1, 400));
  
- auto  = keyed_table->get_or_insert (ctx);

- if (!vec.length ())
-   {
- retrofit_lang_decl (ctx);
- DECL_MODULE_KEYED_DECLS_P (ctx) = true;
-   }
- vec.safe_push (decl);
+  auto  = keyed_table->get_or_insert (ctx);
+  if (!vec.length ())
+{
+  retrofit_lang_decl (ctx);
+  DECL_MODULE_KEYED_DECLS_P (ctx) = true;
+}
+  vec.safe_push (decl);
  }
  
  /* Create the flat name string.  It is simplest to have it handy.  */

diff --git a/gcc/testsuite/g++.dg/modules/lambda-6_a.C 
b/gcc/testsuite/g++.dg/modules/lambda-6_a.C
new file mode 100644
index 000..28bfb358afb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-6_a.C
@@ -0,0 +1,16 @@
+// PR c++/107398
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi Lambda6 }
+
+export module Lambda6;
+
+template 
+struct R { static int x; };
+
+template 
+int R::x = []{int i; return 1;}();
+
+export int foo();
+int foo() {
+  return R::x;
+}
diff --git a/gcc/testsuite/g++.dg/modules/lambda-6_b.C 
b/gcc/testsuite/g++.dg/modules/lambda-6_b.C
new file mode 100644
index 000..ab0c4ab4805
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-6_b.C
@@ -0,0 +1,9 @@
+// PR c++/107398
+// { dg-additional-options "-fmodules-ts" }
+
+import Lambda6;
+
+int main() {
+  if (foo() != 1)
+__builtin_abort();
+}


--
Nathan Sidwell



Re: [PATCH 2/1] c++/modules: Allow exporting a typedef redeclaration

2023-11-23 Thread Nathan Sidwell

On 11/13/23 01:09, Nathaniel Shead wrote:

I happened to be browsing the standard a bit later and noticed that we
incorrectly reject the example given below.

Bootstrapped on x86_64-pc-linux-gnu; regtesting ongoing but modules.exp
completed with no errors.

-- >8 --

A typedef doesn't create a new entity, and thus should be allowed to be
exported even if it has been previously declared un-exported. See the
example in [module.interface] p6:


ok.  Could you put a reference to [module.interface]/p6 in the comment though?

nathan



   export module M;
   struct S { int n; };
   typedef S S;
   export typedef S S; // OK, does not redeclare an entity

PR c++/102341

gcc/cp/ChangeLog:

* decl.cc (duplicate_decls): Allow exporting a redeclaration of
a typedef.

gcc/testsuite/ChangeLog:

* g++.dg/modules/export-1.C: Adjust test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/decl.cc  | 5 -
  gcc/testsuite/g++.dg/modules/export-1.C | 6 +-
  2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index bde9bd79d58..5e175d3e835 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -2231,7 +2231,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool 
hiding, bool was_hidden)
}
  
tree not_tmpl = STRIP_TEMPLATE (olddecl);

-  if (DECL_LANG_SPECIFIC (not_tmpl) && DECL_MODULE_ATTACH_P (not_tmpl))
+  if (DECL_LANG_SPECIFIC (not_tmpl)
+ && DECL_MODULE_ATTACH_P (not_tmpl)
+ /* Typedefs are not entities and so can be exported later.  */
+ && TREE_CODE (olddecl) != TYPE_DECL)
{
  if (DECL_MODULE_EXPORT_P (STRIP_TEMPLATE (newdecl))
  && !DECL_MODULE_EXPORT_P (not_tmpl))
diff --git a/gcc/testsuite/g++.dg/modules/export-1.C 
b/gcc/testsuite/g++.dg/modules/export-1.C
index 3f93814d270..598814370ec 100644
--- a/gcc/testsuite/g++.dg/modules/export-1.C
+++ b/gcc/testsuite/g++.dg/modules/export-1.C
@@ -9,8 +9,12 @@ export int x (); // { dg-error "conflicting exporting for 
declaration" }
  int y;
  export extern int y; // { dg-error "conflicting exporting for declaration" }
  
+// A typedef is not an entity so the following is OK; see [module.interface] example 4

  typedef int z;
-export typedef int z; // { dg-error "conflicting exporting for declaration" }
+export typedef int z; // { dg-bogus "conflicting exporting for declaration" }
+
+template  using w = T;
+export template  using w = T;  // { dg-error "conflicting exporting for 
declaration" }
  
  template  int f (T);

  export template  int f (T); // { dg-error "conflicting exporting for 
declaration" }


--
Nathan Sidwell



Re: [PATCH] c++/modules: check mismatching exports for class tags [PR98885]

2023-11-23 Thread Nathan Sidwell

On 11/12/23 07:00, Nathaniel Shead wrote:

I think the error message is still a little bit unclear but I couldn't
come up with something clearer that was similarly concise and matching
the existing style.

(Also I noticed that the linked PR was assigned to Nathan but there
hadn't been activity for a while, and I've been looking into these kinds
of issues recently anyway so I thought I'd give it a go.)

Bootstrapped and regtested on x86_64-pc-linux-gnu. I don't have write
access.


ok



-- >8 --

Checks for exporting a declaration that was previously declared as not
exported is implemented in 'duplicate_decls', but this doesn't handle
declarations of classes. This patch adds these checks and slightly
adjusts the associated error messages for clarity.

PR c++/98885

gcc/cp/ChangeLog:

* decl.cc (duplicate_decls): Adjust error message.
(xref_tag): Adjust error message. Check exporting decl that is
already declared as non-exporting.

gcc/testsuite/ChangeLog:

* g++.dg/modules/export-1.C: Adjust error messages. Remove
xfails for working case. Add new test case.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/decl.cc  | 21 ++---
  gcc/testsuite/g++.dg/modules/export-1.C | 16 +---
  2 files changed, 27 insertions(+), 10 deletions(-)

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 4a07c7e879b..bde9bd79d58 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -2236,8 +2236,10 @@ duplicate_decls (tree newdecl, tree olddecl, bool 
hiding, bool was_hidden)
  if (DECL_MODULE_EXPORT_P (STRIP_TEMPLATE (newdecl))
  && !DECL_MODULE_EXPORT_P (not_tmpl))
{
- error ("conflicting exporting declaration %qD", newdecl);
- inform (olddecl_loc, "previous declaration %q#D here", olddecl);
+ auto_diagnostic_group d;
+ error ("conflicting exporting for declaration %qD", newdecl);
+ inform (olddecl_loc,
+ "previously declared here without exporting");
}
}
else if (DECL_MODULE_EXPORT_P (newdecl))
@@ -16249,11 +16251,24 @@ xref_tag (enum tag_types tag_code, tree name,
  tree decl = TYPE_NAME (t);
  if (!module_may_redeclare (decl))
{
+ auto_diagnostic_group d;
  error ("cannot declare %qD in a different module", decl);
- inform (DECL_SOURCE_LOCATION (decl), "declared here");
+ inform (DECL_SOURCE_LOCATION (decl), "previously declared here");
  return error_mark_node;
}
  
+	  tree not_tmpl = STRIP_TEMPLATE (decl);

+ if (DECL_LANG_SPECIFIC (not_tmpl)
+ && DECL_MODULE_ATTACH_P (not_tmpl)
+ && !DECL_MODULE_EXPORT_P (not_tmpl)
+ && module_exporting_p ())
+   {
+ auto_diagnostic_group d;
+ error ("conflicting exporting for declaration %qD", decl);
+ inform (DECL_SOURCE_LOCATION (decl),
+ "previously declared here without exporting");
+   }
+
  tree maybe_tmpl = decl;
  if (CLASS_TYPE_P (t) && CLASSTYPE_IS_TEMPLATE (t))
maybe_tmpl = CLASSTYPE_TI_TEMPLATE (t);
diff --git a/gcc/testsuite/g++.dg/modules/export-1.C 
b/gcc/testsuite/g++.dg/modules/export-1.C
index 8ca696ebee0..3f93814d270 100644
--- a/gcc/testsuite/g++.dg/modules/export-1.C
+++ b/gcc/testsuite/g++.dg/modules/export-1.C
@@ -4,19 +4,21 @@ export module frob;
  // { dg-module-cmi !frob }
  
  int x ();

-export int x (); // { dg-error "conflicting exporting declaration" }
+export int x (); // { dg-error "conflicting exporting for declaration" }
  
  int y;

-export extern int y; // { dg-error "conflicting exporting declaration" }
+export extern int y; // { dg-error "conflicting exporting for declaration" }
  
  typedef int z;

-export typedef int z; // { dg-error "conflicting exporting declaration" }
+export typedef int z; // { dg-error "conflicting exporting for declaration" }
  
  template  int f (T);

-export template  int f (T); // { dg-error "conflicting exporting 
declaration" }
+export template  int f (T); // { dg-error "conflicting exporting for 
declaration" }
  
-// doesn't go via duplicate_decls so we miss this for now

  class A;
-export class A; // { dg-error "conflicting exporting declaration" "" { xfail 
*-*-* } }
+export class A; // { dg-error "conflicting exporting for declaration" }
  
-// { dg-warning  "due to errors" "" { target *-*-* } 0 }

+template  struct B;
+export template  struct B {};  // { dg-error "conflicting exporting for 
declaration" }
+
+// { dg-warning "due to errors" "" { target *-*-* } 0 }


--
Nathan Sidwell



Re: [PATCH] c++: Set DECL_CONTEXT for __cxa_thread_atexit [PR99187]

2023-11-19 Thread Nathan Sidwell

On 11/16/23 16:39, Nathaniel Shead wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu. I don't have write
access.

-- >8 --

Modules streaming requires DECL_CONTEXT to be set on declarations that
are streamed. This ensures that __cxa_thread_atexit is given translation
unit context much like is already done with many other support
functions.

PR c++/99187

gcc/cp/ChangeLog:

* cp-tree.h (enum cp_tree_index):
(thread_atexit_node):
* decl.cc (get_thread_atexit_node):

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr99187.C: New test.

Signed-off-by: Nathaniel Shead 


thanks, I've committed it for you.

nathan

--
Nathan Sidwell



Re: [PATCH] c++/modules: fix virtual destructors [PR103499]

2023-11-09 Thread Nathan Sidwell

On 11/9/23 18:29, Nathaniel Shead wrote:

On Thu, Nov 09, 2023 at 05:57:39PM -0500, Nathan Sidwell wrote:

On 11/9/23 04:55, Nathaniel Shead wrote:

I'm not sure if this is just papering over a general issue of clones not being
exported/imported, or if this is just an exception to the general case of
clones being able to be freely regenerated with no other issues.

Alternatively, would it be better to override the DECL_VINDEX of the original
declaration after filling it in for the clones as well? I wasn't able to see
anything depending on the current behaviour (though I didn't look very hard).


I think your patch is a fine approach. IIRC just streaming out the clones
directly ran into a bunch of issues, hence the current implementation.


ok

nathan


Sorry, I don't have write access, would you be able to push? Thanks.
(And for my other patch.)


ok, no worries






Bootstrapped and regtexted on x86_64-pc-linux-gnu.

-- >8 --

Currently, cloned functions are not included in the CMI.  However, for
virtual destructors the clones must have a different DECL_VINDEX from
their base declaration: the former have an INTEGER_CST indicating the
index into the vtable, while the latter indicate the FUNCTION_DECL that
they're overriding.

As such, this patch ensures that DECL_VINDEX is properly passed on for
cloned functions as well to prevent this from causing issues.

PR c++/103499

gcc/cp/ChangeLog:

* module.cc (trees_out::decl_node): Write DECL_VINDEX for
virtual clones.
(trees_in::tree_node): Read DECL_VINDEX for virtual clones.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr103499_a.C: New test.
* g++.dg/modules/pr103499_b.C: New test.

Signed-off-by: Nathaniel Shead 
---
   gcc/cp/module.cc  |  6 ++
   gcc/testsuite/g++.dg/modules/pr103499_a.C | 12 
   gcc/testsuite/g++.dg/modules/pr103499_b.C |  8 
   3 files changed, 26 insertions(+)
   create mode 100644 gcc/testsuite/g++.dg/modules/pr103499_a.C
   create mode 100644 gcc/testsuite/g++.dg/modules/pr103499_b.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index c1c8c226bc1..416a7c414cc 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -8648,6 +8648,8 @@ trees_out::decl_node (tree decl, walk_kind ref)
 tree_node (target);
 tree_node (DECL_NAME (decl));
+  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl))
+   tree_node (DECL_VINDEX (decl));
 int tag = insert (decl);
 if (streaming_p ())
dump (dumper::TREE)
@@ -9869,6 +9871,10 @@ trees_in::tree_node (bool is_use)
}
  }
+   /* A clone might have a different vtable entry.  */
+   if (res && TREE_CODE (res) == FUNCTION_DECL && DECL_VIRTUAL_P (res))
+ DECL_VINDEX (res) = tree_node ();
+
if (!res)
  set_overrun ();
int tag = insert (res);
diff --git a/gcc/testsuite/g++.dg/modules/pr103499_a.C 
b/gcc/testsuite/g++.dg/modules/pr103499_a.C
new file mode 100644
index 000..0497c2c5504
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr103499_a.C
@@ -0,0 +1,12 @@
+// PR c++/103499
+// { dg-module-do compile }
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi pr103499 }
+
+export module pr103499;
+
+export struct base {
+  virtual ~base() = default;
+};
+
+export struct derived : base {};
diff --git a/gcc/testsuite/g++.dg/modules/pr103499_b.C 
b/gcc/testsuite/g++.dg/modules/pr103499_b.C
new file mode 100644
index 000..b7468562ba9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr103499_b.C
@@ -0,0 +1,8 @@
+// PR c++/103499
+// { dg-additional-options "-fmodules-ts" }
+
+import pr103499;
+
+void test(derived* p) {
+  delete p;
+}


--
Nathan Sidwell



--
Nathan Sidwell



Re: [PATCH] c++/modules: handle templates in exported using-declarations [PR106849]

2023-11-09 Thread Nathan Sidwell

On 11/9/23 16:06, Nathaniel Shead wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu.

-- >8 --

A TEMPLATE_DECL does not have module attachment flags associated with
it, so this patch extracts the result from the template to read the
flags from there instead.



oh yeah.  my original plan had it duplicated, but that didn't work out well. 
You can use

   tree decl = STRIP_TEMPLATE (new_fn);
btw.  ok with that change


As a drive-by fix we also group the error with its informative note.

PR c++/106849

gcc/cp/ChangeLog:

* name-lookup.cc (do_nonmember_using_decl): Handle
TEMPLATE_DECLs when checking module attachment.

gcc/testsuite/ChangeLog:

* g++.dg/modules/using-9.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/name-lookup.cc  | 14 ++
  gcc/testsuite/g++.dg/modules/using-9.C | 13 +
  2 files changed, 23 insertions(+), 4 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/using-9.C

diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index a8b9229b29e..512dc1be87f 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -4846,12 +4846,18 @@ do_nonmember_using_decl (name_lookup , bool 
fn_scope_p,
  bool exporting = revealing_p && module_exporting_p ();
  if (exporting)
{
+ /* Module flags for templates are on the template_result.  */
+ tree decl = new_fn;
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+   decl = DECL_TEMPLATE_RESULT (decl);
+
  /* If the using decl is exported, the things it refers
-to must also be exported (or not habve module attachment).  */
- if (!DECL_MODULE_EXPORT_P (new_fn)
- && (DECL_LANG_SPECIFIC (new_fn)
- && DECL_MODULE_ATTACH_P (new_fn)))
+to must also be exported (or not have module attachment).  */
+ if (!DECL_MODULE_EXPORT_P (decl)
+ && (DECL_LANG_SPECIFIC (decl)
+ && DECL_MODULE_ATTACH_P (decl)))
{
+ auto_diagnostic_group d;
  error ("%q#D does not have external linkage", new_fn);
  inform (DECL_SOURCE_LOCATION (new_fn),
  "%q#D declared here", new_fn);
diff --git a/gcc/testsuite/g++.dg/modules/using-9.C 
b/gcc/testsuite/g++.dg/modules/using-9.C
new file mode 100644
index 000..4290280d897
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/using-9.C
@@ -0,0 +1,13 @@
+// PR c++/106849
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi !lib }
+
+export module lib;
+
+namespace outer {
+  template void any_of(T) { }  // { dg-note "declared here" }
+}
+
+export using outer::any_of;  // { dg-error "does not have external linkage" }
+
+// { dg-prune-output "not writing module" }


--
Nathan Sidwell



Re: [PATCH] c++/modules: fix virtual destructors [PR103499]

2023-11-09 Thread Nathan Sidwell

On 11/9/23 04:55, Nathaniel Shead wrote:

I'm not sure if this is just papering over a general issue of clones not being
exported/imported, or if this is just an exception to the general case of
clones being able to be freely regenerated with no other issues.

Alternatively, would it be better to override the DECL_VINDEX of the original
declaration after filling it in for the clones as well? I wasn't able to see
anything depending on the current behaviour (though I didn't look very hard).


I think your patch is a fine approach. IIRC just streaming out the clones 
directly ran into a bunch of issues, hence the current implementation.



ok

nathan



Bootstrapped and regtexted on x86_64-pc-linux-gnu.

-- >8 --

Currently, cloned functions are not included in the CMI.  However, for
virtual destructors the clones must have a different DECL_VINDEX from
their base declaration: the former have an INTEGER_CST indicating the
index into the vtable, while the latter indicate the FUNCTION_DECL that
they're overriding.

As such, this patch ensures that DECL_VINDEX is properly passed on for
cloned functions as well to prevent this from causing issues.

PR c++/103499

gcc/cp/ChangeLog:

* module.cc (trees_out::decl_node): Write DECL_VINDEX for
virtual clones.
(trees_in::tree_node): Read DECL_VINDEX for virtual clones.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr103499_a.C: New test.
* g++.dg/modules/pr103499_b.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/module.cc  |  6 ++
  gcc/testsuite/g++.dg/modules/pr103499_a.C | 12 
  gcc/testsuite/g++.dg/modules/pr103499_b.C |  8 
  3 files changed, 26 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/modules/pr103499_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/pr103499_b.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index c1c8c226bc1..416a7c414cc 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -8648,6 +8648,8 @@ trees_out::decl_node (tree decl, walk_kind ref)
  
tree_node (target);

tree_node (DECL_NAME (decl));
+  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl))
+   tree_node (DECL_VINDEX (decl));
int tag = insert (decl);
if (streaming_p ())
dump (dumper::TREE)
@@ -9869,6 +9871,10 @@ trees_in::tree_node (bool is_use)
}
  }
  
+	/* A clone might have a different vtable entry.  */

+   if (res && TREE_CODE (res) == FUNCTION_DECL && DECL_VIRTUAL_P (res))
+ DECL_VINDEX (res) = tree_node ();
+
if (!res)
  set_overrun ();
int tag = insert (res);
diff --git a/gcc/testsuite/g++.dg/modules/pr103499_a.C 
b/gcc/testsuite/g++.dg/modules/pr103499_a.C
new file mode 100644
index 000..0497c2c5504
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr103499_a.C
@@ -0,0 +1,12 @@
+// PR c++/103499
+// { dg-module-do compile }
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi pr103499 }
+
+export module pr103499;
+
+export struct base {
+  virtual ~base() = default;
+};
+
+export struct derived : base {};
diff --git a/gcc/testsuite/g++.dg/modules/pr103499_b.C 
b/gcc/testsuite/g++.dg/modules/pr103499_b.C
new file mode 100644
index 000..b7468562ba9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr103499_b.C
@@ -0,0 +1,8 @@
+// PR c++/103499
+// { dg-additional-options "-fmodules-ts" }
+
+import pr103499;
+
+void test(derived* p) {
+  delete p;
+}


--
Nathan Sidwell



Re: [PATCH] c++/modules: fix up recent testcases

2023-10-25 Thread Nathan Sidwell

Patrick,

thanks for noticing this, and this is a suitable workaround for another bug.

We should either be emitting the definition of that member function in the 
object file of its containing function.  Or it should be implicitly inline.


I know in module perview the in-class defined member functions at namespace 
scope are /not/ implicitly inline.  But I can't recall what the std says about 
non-namespace scope classes.


Ah, it appears to be the former we should be doing:

[class.mfct] If a member function is attached to the global module and is 
defined (9.5) in its class definition, it is inline (9.2.8).


Notice we can get into the weird situation that the member functions of a local 
class of a module-purview inline function might not themselves be inline!



On 10/25/23 14:32, Patrick Palka wrote:

Tested on x86_64-pc-linux-gnu, does this look OK for trunk?

Declaring get() inline seems necessary to avoid link failure:

   /usr/bin/ld: /tmp/ccwdv6Co.o: in function `g3@pr105322.Decltype()':
   
decltype-1_b.C:(.text._ZW8pr105322W8Decltype2g3v[_ZW8pr105322W8Decltype2g3v]+0x18):
 undefined reference to `f@pr105322.Decltype()::A::get()'

Not sure if that's expected?

-- >8 --

This fixes some minor issues with the testcases from
r14-4806-g084addf8a700fa.

gcc/testsuite/ChangeLog:

* g++.dg/modules/decltype-1_a.C: Add missing } to dg-module-do
directive.  Declare f()::A::get() inline.
* g++.dg/modules/lambda-5_a.C: Add missing } to dg-module-do
directive.
---
  gcc/testsuite/g++.dg/modules/decltype-1_a.C | 4 ++--
  gcc/testsuite/g++.dg/modules/lambda-5_a.C   | 2 +-
  2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/gcc/testsuite/g++.dg/modules/decltype-1_a.C 
b/gcc/testsuite/g++.dg/modules/decltype-1_a.C
index ca66e8b598a..6512f151aae 100644
--- a/gcc/testsuite/g++.dg/modules/decltype-1_a.C
+++ b/gcc/testsuite/g++.dg/modules/decltype-1_a.C
@@ -1,5 +1,5 @@
  // PR c++/105322
-// { dg-module-do link
+// { dg-module-do link }
  // { dg-additional-options -fmodules-ts }
  // { dg-module-cmi pr105322.Decltype }
  
@@ -7,7 +7,7 @@ export module pr105322.Decltype;
  
  auto f() {

struct A { int m;
-int get () { return m; }
+inline int get () { return m; }
};
return A{};
  }
diff --git a/gcc/testsuite/g++.dg/modules/lambda-5_a.C 
b/gcc/testsuite/g++.dg/modules/lambda-5_a.C
index 6b589d4965c..37d0e77b1e1 100644
--- a/gcc/testsuite/g++.dg/modules/lambda-5_a.C
+++ b/gcc/testsuite/g++.dg/modules/lambda-5_a.C
@@ -1,5 +1,5 @@
  // PR c++/105322
-// { dg-module-do link
+// { dg-module-do link }
  // { dg-additional-options -fmodules-ts }
  // { dg-module-cmi pr105322.Lambda }
  


--
Nathan Sidwell



Re: [PATCH] c++/modules: ICE with lambda initializing local var [PR105322]

2023-10-20 Thread Nathan Sidwell

Thanks for looking at this, but your patch is essentially papering over the 
problem.

It took me a while to figure out, but the clue was that things like 
'decltype(f()).m' worked, but 'decltype(f()){0}' did not.  The CONSTRUCTOR node 
is the exception to the rule that required an expression node's type to be 
streamed after the node's operands.  We want the opposite for CTORS.


I'll commit this once bootstrapped.

nathan

On 10/18/23 12:28, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

-- >8 --

For a local variable initialized by a lambda:

   auto f = []{};

The corresponding BLOCK_VARS contains the variable declaration first,
followed by the closure type declaration, consistent with the
syntactical order.  This however means that a use of the closure type
appears (in the variable type/initializer) before the declaration of the
type.  This ends up causing an ICE when streaming the BLOCK_VARS of f1
below because we stream (by value) the CONSTRUCTOR initializer of g1 --
which contains components of the closure type -- before we've streamed
the declaration defining the closure type.  The following comment in
module.cc seems relevant:

   /* We want to stream the type of a expression-like nodes /after/
  we've streamed the operands.  The type often contains (bits
  of the) types of the operands, and with things like decltype
  and noexcept in play, we really want to stream the decls
  defining the type before we try and stream the type on its
  own.  Otherwise we can find ourselves trying to read in a
  decl, when we're already partially reading in a component of
  its type.  And that's bad.  */

This patch narrowly fixes this issue by special casing closure type
declarations in add_decl_to_level.  (A loop is needed since there could
be multiple variable declarations with an unprocessed initializer in
light of structured bindings.)

PR c++/105322

gcc/cp/ChangeLog:

* name-lookup.cc (add_decl_to_level): When adding a closure
type declaration to a block scope, add it before rather than
after any variable declarations whose initializer we're still
processing.

gcc/testsuite/ChangeLog:

* g++.dg/modules/lambda-5_a.C: New test.
* g++.dg/modules/lambda-5_b.C: New test.
---
  gcc/cp/name-lookup.cc | 19 ---
  gcc/testsuite/g++.dg/modules/lambda-5_a.C | 23 +++
  gcc/testsuite/g++.dg/modules/lambda-5_b.C | 10 ++
  3 files changed, 49 insertions(+), 3 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/lambda-5_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/lambda-5_b.C

diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index a8b9229b29e..bb00baaf9f4 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -391,9 +391,22 @@ add_decl_to_level (cp_binding_level *b, tree decl)
gcc_assert (b->names != decl);
  
/* We build up the list in reverse order, and reverse it later if

- necessary.  */
-  TREE_CHAIN (decl) = b->names;
-  b->names = decl;
+ necessary.  If we're adding a lambda closure type to a block
+ scope as part of a local variable initializer, then make sure
+ we declare the type before the variable; modules expects that
+ we see a type declaration before a use of the type.  */
+  tree *prev = >names;
+  if (b->kind == sk_block
+  && !processing_template_decl
+  && TREE_CODE (decl) == TYPE_DECL
+  && LAMBDA_TYPE_P (TREE_TYPE (decl)))
+while (*prev && VAR_P (*prev)
+  && !DECL_EXTERNAL (*prev)
+  && !DECL_INITIALIZED_P (*prev))
+  prev = _CHAIN (*prev);
+
+  TREE_CHAIN (decl) = *prev;
+  *prev = decl;
  
/* If appropriate, add decl to separate list of statics.  We include

   extern variables because they might turn out to be static later.
diff --git a/gcc/testsuite/g++.dg/modules/lambda-5_a.C 
b/gcc/testsuite/g++.dg/modules/lambda-5_a.C
new file mode 100644
index 000..6b54c8e3173
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-5_a.C
@@ -0,0 +1,23 @@
+// PR c++/105322
+// { dg-additional-options -fmodules-ts }
+// { dg-module-cmi pr105322 }
+
+export module pr105322;
+
+struct A { };
+
+export
+inline void f1() {
+  A a;
+  auto g1 = [a] { }; // used to ICE here during stream out
+}
+
+export
+template
+void f2() {
+  A a;
+  auto g2 = [a] { };
+}
+
+export
+inline auto g3 = [a=A{}] { };
diff --git a/gcc/testsuite/g++.dg/modules/lambda-5_b.C 
b/gcc/testsuite/g++.dg/modules/lambda-5_b.C
new file mode 100644
index 000..e25a913b726
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/lambda-5_b.C
@@ -0,0 +1,10 @@
+// PR c++/105322
+// { dg-additional-options -fmodules-ts }
+
+import pr105322;
+
+int main() {
+  f1();
+  f2();
+  g3();
+}


--
Nathan Sidwell
From fb65e961231943ecc68988f38a9ec78b0c93e5df Mon Sep 17 0

Re: [PATCH v5 4/5] c++modules: report imported CMI files as dependencies

2023-07-21 Thread Nathan Sidwell via Gcc-patches

On 7/21/23 10:57, Ben Boeckel wrote:

On Thu, Jul 20, 2023 at 17:00:32 -0400, Nathan Sidwell wrote:

On 7/19/23 20:47, Ben Boeckel wrote:

But it is inhibiting distributed builds because the distributing tool
would need to know:

- what CMIs are actually imported (here, "read the module mapper file"
(in CMake's case, this is only the modules that are needed; a single
massive mapper file for an entire project would have extra entries) or
"act as a proxy for the socket/program specified" for other
approaches);


This information is in the machine (& human) README section of the CMI.


Ok. That leaves it up to distributing build tools to figure out at
least.


- read the CMIs as it sends to the remote side to gather any other CMIs
that may be needed (recursively);

Contrast this with the MSVC and Clang (17+) mechanism where the command
line contains everything that is needed and a single bolus can be sent.


um, the build system needs to create that command line? Where does the build
system get that information?  IIUC it'll need to read some file(s) to do that.


It's chained through the P1689 information in the collator as needed. No
extra files need to be read (at least with CMake's approach); certainly
not CMI files.


It occurs to me that the model I am envisioning is similar to CMake's object 
libraries.  Object libraries are a convenient name for a bunch of object files. 
IIUC they're linked by naming the individual object files (or I think the could 
be implemented as a static lib linked with --whole-archive path/to/libfoo.a 
-no-whole-archive.  But for this conversation consider them a bunch of separate 
object files with a convenient group name.


Consider also that object libraries could themselves contain object libraries (I 
don't know of they can, but it seems like a useful concept).  Then one could 
create an object library from a collection of object files and object libraries 
(recursively).  CMake would handle the transitive gtaph.


Now, allow an object library to itself have some kind of tangible, on-disk 
representation.  *BUT* not like a static library -- it doesn't include the 
object files.



Now that immediately maps onto modules.

CMI: Object library
Direct imports: Direct object libraries of an object library

This is why I don't understand the need explicitly indicate the indirect imports 
of a CMI.  CMake knows them, because it knows the graph.





And relocatable is probably fine. How does it interact with reproducible
builds? Or are GCC CMIs not really something anyone should consider for
installation (even as a "here, maybe this can help consumers"
mechanism)?


Module CMIs should be considered a cacheable artifact.  They are neither object
files nor source files.


Sure, cachable sounds fine. What about the installation?

--Ben


--
Nathan Sidwell



Re: [PATCH v5 4/5] c++modules: report imported CMI files as dependencies

2023-07-20 Thread Nathan Sidwell via Gcc-patches

On 7/19/23 20:47, Ben Boeckel wrote:

On Wed, Jul 19, 2023 at 17:11:08 -0400, Nathan Sidwell wrote:

GCC is neither of these descriptions.  a CMI does not contain the transitive
closure of its imports.  It contains an import table.  That table lists the
transitive closure of its imports (it needs that closure to do remapping), and
that table contains the CMI pathnames of the direct imports.  Those pathnames
are absolute, if the mapper provded an absolute pathm or relative to the CMI 
repo.

The rationale here is that if you're building a CMI, Foo, which imports a bunch
of modules, those imported CMIs will have the same (relative) location in this
compilation and in compilations importing Foo (why would you move them?) Note
this is NOT inhibiting relocatable builds, because of the CMI repo.


But it is inhibiting distributed builds because the distributing tool
would need to know:

- what CMIs are actually imported (here, "read the module mapper file"
   (in CMake's case, this is only the modules that are needed; a single
   massive mapper file for an entire project would have extra entries) or
   "act as a proxy for the socket/program specified" for other
   approaches);


This information is in the machine (& human) README section of the CMI.


- read the CMIs as it sends to the remote side to gather any other CMIs
   that may be needed (recursively);

Contrast this with the MSVC and Clang (17+) mechanism where the command
line contains everything that is needed and a single bolus can be sent.


um, the build system needs to create that command line? Where does the build 
system get that information?  IIUC it'll need to read some file(s) to do that.




And relocatable is probably fine. How does it interact with reproducible
builds? Or are GCC CMIs not really something anyone should consider for
installation (even as a "here, maybe this can help consumers"
mechanism)?


Module CMIs should be considered a cacheable artifact.  They are neither object 
files nor source files.





On 7/18/23 20:01, Ben Boeckel wrote:

Maybe I'm missing how this *actually* works in GCC as I've really only
interacted with it through the command line, but I've not needed to
mention `a.cmi` when compiling `use.cppm`. Is `a.cmi` referenced and
read through some embedded information in `b.cmi` or does `b.cmi`
include enough information to not need to read it at all? If the former,
distributed builds are going to have a problem knowing what files to
send just from the command line (I'll call this "implicit thin"). If the
latter, that is the "fat" CMI that I'm thinking of.


please don't use perjorative terms like 'fat' and 'thin'.


Sorry, I was internally analogizing to "thinLTO".

--Ben


--
Nathan Sidwell



Re: [PATCH v5 4/5] c++modules: report imported CMI files as dependencies

2023-07-19 Thread Nathan Sidwell via Gcc-patches

On 7/18/23 20:01, Ben Boeckel wrote:

On Tue, Jul 18, 2023 at 16:52:44 -0400, Jason Merrill wrote:

On 6/25/23 12:36, Ben Boeckel wrote:

On Fri, Jun 23, 2023 at 08:12:41 -0400, Nathan Sidwell wrote:

On 6/22/23 22:45, Ben Boeckel wrote:

On Thu, Jun 22, 2023 at 17:21:42 -0400, Jason Merrill wrote:

On 1/25/23 16:06, Ben Boeckel wrote:

They affect the build, so report them via `-MF` mechanisms.


Why isn't this covered by the existing code in preprocessed_module?


It appears as though it is neutered in patch 3 where
`write_make_modules_deps` is used in `make_write` (or will use that name


Why do you want to record the transitive modules? I would expect just noting the
ones with imports directly in the TU would suffice (i.e check the 'outermost' 
arg)


FWIW, only GCC has "fat" modules. MSVC and Clang both require the
transitive closure to be passed. The idea there is to minimize the size
of individual module files.

If GCC only reads the "fat" modules, then only those should be recorded.
If it reads other modules, they should be recorded as well.


For clarification, given:

* a.cppm
```
export module a;
```

* b.cppm
```
export module b;
import a;
```

* use.cppm
```
import b;
```

in a "fat" module setup, `use.cppm` only needs to be told about
`b.cmi` because it contains everything that an importer needs to know
about the `a` module (reachable types, re-exported bits, whateve > With
the "thin" modules, `a.cmi` must be specified when compiling `use.cppm`
to satisfy anything that may be required transitively (e.g., a return


GCC is neither of these descriptions.  a CMI does not contain the transitive 
closure of its imports.  It contains an import table.  That table lists the 
transitive closure of its imports (it needs that closure to do remapping), and 
that table contains the CMI pathnames of the direct imports.  Those pathnames 
are absolute, if the mapper provded an absolute pathm or relative to the CMI repo.


The rationale here is that if you're building a CMI, Foo, which imports a bunch 
of modules, those imported CMIs will have the same (relative) location in this 
compilation and in compilations importing Foo (why would you move them?) Note 
this is NOT inhibiting relocatable builds, because of the CMI repo.




Maybe I'm missing how this *actually* works in GCC as I've really only
interacted with it through the command line, but I've not needed to
mention `a.cmi` when compiling `use.cppm`. Is `a.cmi` referenced and
read through some embedded information in `b.cmi` or does `b.cmi`
include enough information to not need to read it at all? If the former,
distributed builds are going to have a problem knowing what files to
send just from the command line (I'll call this "implicit thin"). If the
latter, that is the "fat" CMI that I'm thinking of.


please don't use perjorative terms like 'fat' and 'thin'.




But wouldn't the transitive modules be dependencies of the direct
imports, so (re)building the direct imports would first require building
the transitive modules anyway?  Expressing the transitive closure of
dependencies for each importer seems redundant when it can be easily
derived from the direct dependencies of each module.


I'm not concerned whether it is transitive or not, really. If a file is
read, it should be reported here regardless of the reason. Note that
caching mechanisms may skip actually *doing* the reading, but the
dependencies should still be reported from the cached results as-if the
real work had been performed.

--Ben


--
Nathan Sidwell



Re: [PATCH v5 4/5] c++modules: report imported CMI files as dependencies

2023-07-18 Thread Nathan Sidwell via Gcc-patches

On 7/18/23 16:52, Jason Merrill wrote:

On 6/25/23 12:36, Ben Boeckel wrote:

On Fri, Jun 23, 2023 at 08:12:41 -0400, Nathan Sidwell wrote:

On 6/22/23 22:45, Ben Boeckel wrote:

On Thu, Jun 22, 2023 at 17:21:42 -0400, Jason Merrill wrote:

On 1/25/23 16:06, Ben Boeckel wrote:

They affect the build, so report them via `-MF` mechanisms.


Why isn't this covered by the existing code in preprocessed_module?


It appears as though it is neutered in patch 3 where
`write_make_modules_deps` is used in `make_write` (or will use that name


Why do you want to record the transitive modules? I would expect just noting the
ones with imports directly in the TU would suffice (i.e check the 'outermost' 
arg)


FWIW, only GCC has "fat" modules. MSVC and Clang both require the
transitive closure to be passed. The idea there is to minimize the size
of individual module files.

If GCC only reads the "fat" modules, then only those should be recorded.
If it reads other modules, they should be recorded as well.


Please explain what you mean by fat modules.  There seems to be confusion.



But wouldn't the transitive modules be dependencies of the direct imports, so 
(re)building the direct imports would first require building the transitive 
modules anyway?  Expressing the transitive closure of dependencies for each 
importer seems redundant when it can be easily derived from the direct 
dependencies of each module.


Jason



--
Nathan Sidwell



Re: [PATCH v3] Introduce attribute reverse_alias

2023-07-15 Thread Nathan Sidwell via Gcc-patches
Not commenting on the semantics, but the name seems unfortunate (hello 
bikeshed).  The documentation starts with 'attribute causes @var{name} to be 
emitted as an alias to the definition'.  So not emitting a 'reverse alias', 
whatever that might be.  It doesn;t seem to mention how reverse alias differs 
from 'alias'.  Why would 'alias' not DTRT?


Is is emitting a an additiona symbol -- ie, something like 'altname'.  Or is it 
something else? Is that symbol known in the current TU, or other TUs?


nathan



On 7/14/23 21:08, Alexandre Oliva wrote:


This patch introduces an attribute to add extra aliases to a symbol
when its definition is output.  The main goal is to ease interfacing
C++ with Ada, as C++ mangled names have to be named, and in some cases
(e.g. when using stdint.h typedefs in function arguments) the symbol
names may vary across platforms.

The attribute is usable in C and C++, presumably in all C-family
languages.  It can be attached to global variables and functions.  In
C++, it can also be attached to namespace-scoped variables and
functions, static data members, member functions, explicit
instantiations and specializations of template functions, members and
classes.

When applied to constructors or destructor, additional reverse_aliases
with _Base and _Del suffixes are defined for variants other than
complete-object ones.  This changes the assumption that clones always
carry the same attributes as their abstract declarations, so there is
now a function to adjust them.

C++ also had a bug in which attributes from local extern declarations
failed to be propagated to a preexisting corresponding
namespace-scoped decl.  I've fixed that, and adjusted acc tests that
distinguished between C and C++ in this regard.

Applying the attribute to class types is only valid in C++, and the
effect is to attach the alias to the RTTI object associated with the
class type.

Regstrapped on x86_64-linux-gnu.  Ok to install?

This is refreshed and renamed from earlier versions that named the
attribute 'exalias', and that AFAICT got stuck in name bikeshedding.
https://gcc.gnu.org/pipermail/gcc-patches/2020-August/551614.html


for  gcc/ChangeLog

* attribs.cc: Include cgraph.h.
(decl_attributes): Allow late introduction of reverse_alias in
types.
(create_reverse_alias_decl, create_reverse_alias_decls): New.
* attribs.h: Declare them.
(FOR_EACH_REVERSE_ALIAS): New macro.
* cgraph.cc (cgraph_node::create): Create reverse_alias decls.
* varpool.cc (varpool_node::get_create): Create reverse_alias
decls.
* cgraph.h (symtab_node::remap_reverse_alias_target): New.
* symtab.cc (symtab_node::remap_reverse_alias_target):
Define.
* cgraphunit.cc (cgraph_node::analyze): Create alias_target
node if needed.
(analyze_functions): Fixup visibility of implicit alias only
after its node is analyzed.
* doc/extend.texi (reverse_alias): Document for variables,
functions and types.

for  gcc/ada/ChangeLog

* doc/gnat_rm/interfacing_to_other_languages.rst: Mention
attribute reverse_alias to give RTTI symbols mnemonic names.
* doc/gnat_ugn/the_gnat_compilation_model.rst: Mention
attribute reverse_alias.  Fix incorrect ref to C1 ctor variant.

for  gcc/c-family/ChangeLog

* c-ada-spec.cc (pp_asm_name): Use first reverse_alias if
available.
* c-attribs.cc (handle_reverse_alias_attribute): New.
(c_common_attribute_table): Add reverse_alias.
(handle_copy_attribute): Do not copy reverse_alias.

for  gcc/c/ChangeLog

* c-decl.cc (duplicate_decls): Remap reverse_alias target.

for  gcc/cp/ChangeLog

* class.cc (adjust_clone_attributes): New.
(copy_fndecl_with_name, build_clone): Call it.
* cp-tree.h (adjust_clone_attributes): Declare.
(update_reverse_alias_interface): Declare.
(update_tinfo_reverse_alias): Declare.
* decl.cc (duplicate_decls): Remap reverse_alias target.
Adjust clone attributes.
(grokfndecl): Tentatively create reverse_alias decls after
adding attributes in e.g. a template member function explicit
instantiation.
* decl2.cc (cplus_decl_attributes): Update tinfo
reverse_alias.
(copy_interface, update_reverse_alias_interface): New.
(determine_visibility): Update reverse_alias interface.
(tentative_decl_linkage, import_export_decl): Likewise.
* name-lookup.cc: Include target.h and cgraph.h.
(push_local_extern_decl_alias): Merge attributes with
namespace-scoped decl, and drop duplicate reverse_alias.
* optimize.cc (maybe_clone_body): Re-adjust attributes after
cloning them.  Update reverse_alias interface.
* rtti.cc: Include attribs.h and cgraph.h.
(get_tinfo_decl): Copy reverse_alias attributes from type to
tinfo decl.  Create 

Re: [WIP RFC] Add support for keyword-based attributes

2023-07-14 Thread Nathan Sidwell via Gcc-patches
 1)->type == CPP_OPEN_SQUARE))
  return false;
/* In C, '[[' must start attributes.  In Objective-C, we need to
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 560e5431636..50698439104 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -2802,6 +2802,7 @@ static const struct attribute_spec 
aarch64_attribute_table[] =
{ "arm_sve_vector_bits", 1, 1, false, true,  false, true,
  aarch64_sve::handle_arm_sve_vector_bits_attribute,
  NULL },
+  { "__arm_streaming",0, 0, false, true,  true,  true,  NULL, NULL, true },
{ "Advanced SIMD type", 1, 1, false, true,  false, true,  NULL, NULL },
{ "SVE type",   3, 3, false, true,  false, true,  NULL, NULL },
{ "SVE sizeless type",  0, 0, false, true,  false, true,  NULL, NULL },
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 668808a29d0..e6700509b9e 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -2167,6 +2167,25 @@ struct attribute_spec {
/* An array of attribute exclusions describing names of other attributes
   that this attribute is mutually exclusive with.  */
const exclusions *exclude;
+
+  /* Whether the attribute is a C/C++ "regular keyword attribute".
+ When true for an attribute "foo", this means that:
+
+ - The keyword foo can appear exactly where the standard attribute syntax
+   [[...]] can appear, but without the same minimum language requirements.
+   The link is intended to be automatic: there should be no exceptions.
+
+ - The attribute appertains to whatever a standard attribute in the
+   same location would appertain to.  There is no "sliding" from decls
+   to types, as sometimes happens for GNU-style attributes.
+
+ - When MAX_LENGTH > 0, the keyword is followed by an argument list.
+   This argument list is parsed in the same way as arguments to [[...]]
+   attributes, except that the list can be empty if MIN_LENGTH == 0.
+
+ - In C and C++, the attribute cannot appear in __attribute__ or [[...]];
+   it can only appear as a simple keyword.  */
+  bool is_keyword;
  };
  
  /* These functions allow a front-end to perform a manual layout of a


--
Nathan Sidwell



Re: [PATCH v5 4/5] c++modules: report imported CMI files as dependencies

2023-06-23 Thread Nathan Sidwell via Gcc-patches

On 6/22/23 22:45, Ben Boeckel wrote:

On Thu, Jun 22, 2023 at 17:21:42 -0400, Jason Merrill wrote:

On 1/25/23 16:06, Ben Boeckel wrote:

They affect the build, so report them via `-MF` mechanisms.


Why isn't this covered by the existing code in preprocessed_module?


It appears as though it is neutered in patch 3 where
`write_make_modules_deps` is used in `make_write` (or will use that name


Why do you want to record the transitive modules? I would expect just noting the 
ones with imports directly in the TU would suffice (i.e check the 'outermost' arg)


nathan


--
Nathan Sidwell



Fix templated conversion operator demangling

2023-06-13 Thread Nathan Sidwell via Gcc-patches
I came across this when working on the conversion operator deduction fix.  We'd 
successfully demangle an instantiation of 'template operator X & 
()', but fail for 'template operator X ()'.  The demangle printer 
was trying to specially handle the instantiation in the latter case -- seeing 
the template inst of X. That code appears to be completely unnecessary.  Added a 
bunch of conversion operator demangling tests.



nathan
--
Nathan SidwellFrom 5a897036187468d4ded330b90b2abdaff5061ed6 Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Mon, 12 Jun 2023 19:37:04 -0400
Subject: [PATCH] c++: Fix templated convertion operator demangling

Instantiations of templated conversion operators failed to demangle
for cases such as 'operator X', but worked for 'operator X
&', due to thinking the template instantiation of X was the
instantiation of the conversion operator itself.

	libiberty/
	* cp-demangle.c (d_print_conversion): Remove incorrect
	template instantiation handling.
	* testsuite/demangle-expected: Add testcases.
---
 libiberty/cp-demangle.c   | 28 +++
 libiberty/testsuite/demangle-expected | 27 ++
 2 files changed, 30 insertions(+), 25 deletions(-)

diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 18ab28fd028..3bd303a7544 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -6660,32 +6660,10 @@ d_print_conversion (struct d_print_info *dpi, int options,
   dpt.template_decl = dpi->current_template;
 }
 
-  if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE)
-{
-  d_print_comp (dpi, options, d_left (dc));
-  if (dpi->current_template != NULL)
-	dpi->templates = dpt.next;
-}
-  else
-{
-  d_print_comp (dpi, options, d_left (d_left (dc)));
+  d_print_comp (dpi, options, d_left (dc));
 
-  /* For a templated cast operator, we need to remove the template
-	 parameters from scope after printing the operator name,
-	 so we need to handle the template printing here.  */
-  if (dpi->current_template != NULL)
-	dpi->templates = dpt.next;
-
-  if (d_last_char (dpi) == '<')
-	d_append_char (dpi, ' ');
-  d_append_char (dpi, '<');
-  d_print_comp (dpi, options, d_right (d_left (dc)));
-  /* Avoid generating two consecutive '>' characters, to avoid
-	 the C++ syntactic ambiguity.  */
-  if (d_last_char (dpi) == '>')
-	d_append_char (dpi, ' ');
-  d_append_char (dpi, '>');
-}
+  if (dpi->current_template != NULL)
+dpi->templates = dpt.next;
 }
 
 /* Initialize the information structure we use to pass around
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 52dff883a18..0acd2d635db 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -1662,3 +1662,30 @@ X::F()::{lambda(int)#1}::operator()(int) const
 
 _Z1fIiEv1AIXnxtlT_EEE
 void f(A)
+
+_ZNO1Ycv1XEv
+Y::operator X() &&
+
+_ZNO1Ycv1XIT_EIvEEv
+Y::operator X() &&
+
+_ZNO1Y3bobEv
+Y::bob() &&
+
+_ZNR1Y3bobEv
+Y::bob() &
+
+_ZNKR1YcvRK1XIT_EIvEEv
+Y::operator X const&() const &
+
+_ZZN1XIiEcviEvE1y
+X::operator int()::y
+
+_ZZN1XIiEcv1ZIiEEvE1y
+X::operator Z()::y
+
+_ZZN1Xcv1ZIT_EIiEEvE1y
+X::operator Z()::y
+
+_ZZN1XIfEcv1ZIT_EIiEEvE1y
+X::operator Z()::y
-- 
2.40.1



[c++] Implement DR 976

2023-06-10 Thread Nathan Sidwell via Gcc-patches
DR 976 affects conversion operator deduction, swapping reference stripping and 
cv-qual removal.  This allows 'Y::operator P const & ()' to deduce T against a 
call wanting plain A  (previously that would fail as 'P const' cannot be deduced 
from 'A').


It also affects deductions for array- or function-producing conversions, which I 
suspect is rarer.


pushed to trunk

nathan
--
Nathan SidwellFrom 80f075b410125bddb31459428760645baba1a69f Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Sat, 10 Jun 2023 12:42:17 -0400
Subject: [PATCH] c++: Adjust conversion deduction [PR61663][DR976]

Drop the return type's reference before doing cvqual and related decays.

	gcc/cp/
	PR c++/61663
	* pt.cc (maybe_adjust_types_for_deduction): Implement DR976.
	gcc/testsuite/
	* g++.dg/template/pr61663.C: New.
---
 gcc/cp/pt.cc| 11 +++--
 gcc/testsuite/g++.dg/template/pr61663.C | 63 +
 2 files changed, 69 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/template/pr61663.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 6b20c58ce66..6a2cf2c123f 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -22725,10 +22725,16 @@ maybe_adjust_types_for_deduction (tree tparms,
   break;
 
 case DEDUCE_CONV:
+  /* [temp.deduct.conv] First remove a reference type on parm.
+	 DRs 322 & 976 affected this.  */
+  if (TYPE_REF_P (*parm))
+	*parm = TREE_TYPE (*parm);
+
   /* Swap PARM and ARG throughout the remainder of this
 	 function; the handling is precisely symmetric since PARM
 	 will initialize ARG rather than vice versa.  */
   std::swap (parm, arg);
+
   break;
 
 case DEDUCE_EXACT:
@@ -22795,11 +22801,6 @@ maybe_adjust_types_for_deduction (tree tparms,
   result |= UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
 }
 
-  /* DR 322. For conversion deduction, remove a reference type on parm
- too (which has been swapped into ARG).  */
-  if (strict == DEDUCE_CONV && TYPE_REF_P (*arg))
-*arg = TREE_TYPE (*arg);
-
   return result;
 }
 
diff --git a/gcc/testsuite/g++.dg/template/pr61663.C b/gcc/testsuite/g++.dg/template/pr61663.C
new file mode 100644
index 000..2964fa6c309
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr61663.C
@@ -0,0 +1,63 @@
+// { dg-do compile { target c++11 } }
+// PR c++/61663
+// DR 976, strip ref from conv op return type before doing
+// fn and ary decay or CV qual removal
+
+struct F 
+{
+  template
+  operator const T&();
+};
+
+void Foo () 
+{
+  F f;
+  int i = f;
+}
+
+template struct X {};
+
+struct Y
+{
+  template operator X () &&; // #3
+  template operator X const & () const &; // #4
+};
+
+void Use (X);
+Y Val ();
+Y const  ();
+
+// { dg-final { scan-assembler "_Z5Frob3v:.*_ZNO1Ycv1XIT_EIvEEv.*_Z3Use1XIvE" } }
+void Frob3 ()
+{
+  Use (Val ()); // #3
+}
+
+// { dg-final { scan-assembler "_Z5Frob4v:.*_ZNKR1YcvRK1XIT_EIvEEv.*_Z3Use1XIvE" } }
+void Frob4 ()
+{
+  Use (Ref ()); // #4
+}
+
+struct Z 
+{
+  template using FnRef = void (&) (T);
+  template using AryRef = T (&)[];
+
+  template operator FnRef ();
+  template operator AryRef ();
+};
+
+// { dg-final { scan-assembler "_Z5Frob5R1Z:.*_ZN1ZcvRFvT_EIiEEv.*_ZN1ZcvRA_T_IiEEv" } }
+void Frob5 (Z )
+{
+  void (*fnptr)(int) = z;
+  int *iptr = z;
+}
+
+// { dg-final { scan-assembler "_Z5Frob6R1Z:.*_ZN1ZcvRFvT_EIfEEv.*_ZN1ZcvRA_T_IfEEv" } }
+void Frob6 (Z )
+{
+  void ()(float) = z;
+  float ()[] = z;
+}
-- 
2.40.1



[patch] Allow plugin-specific dumps

2023-05-17 Thread Nathan Sidwell via Gcc-patches
PR 99451 is about the inability to name tree and rtl dumps by plugin name.  And 
includes a patch.  But then I worked around the problem and forgot about it. 
Here it is again, retested against trunk.


ok?

nathan
--
Nathan SidwellFrom e54518bc5e59ef5cdc21c652ceac41bd0c0f436c Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Wed, 17 May 2023 19:27:13 -0400
Subject: [PATCH] Allow plugin dumps

Defer dump option parsing until plugins are initialized.  This allows one to
use plugin names for dumps.

	PR other/99451
	gcc/
	* opts.h (handle_deferred_dump_options): Declare.
	* opts-global.cc (handle_common_deferred_options): Do not handle
	dump options here.
	(handle_deferred_dump_options): New.
	* toplev.cc (toplev::main): Call it after plugin init.
---
 gcc/opts-global.cc | 20 +++-
 gcc/opts.h |  1 +
 gcc/toplev.cc  |  4 
 3 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/gcc/opts-global.cc b/gcc/opts-global.cc
index 054169158b1..a61c701621d 100644
--- a/gcc/opts-global.cc
+++ b/gcc/opts-global.cc
@@ -401,7 +401,7 @@ handle_common_deferred_options (void)
 	  break;
 
 	case OPT_fdump_:
-	  g->get_dumps ()->dump_switch_p (opt->arg);
+	  /* Deferred until plugins initialized.  */
 	  break;
 
 case OPT_fopt_info_:
@@ -494,3 +494,21 @@ handle_common_deferred_options (void)
 	}
 }
 }
+
+/* Handle deferred dump options.  */
+
+void
+handle_deferred_dump_options (void)
+{
+  unsigned int i;
+  cl_deferred_option *opt;
+  vec v;
+
+  if (common_deferred_options)
+v = *((vec *) common_deferred_options);
+  else
+v = vNULL;
+  FOR_EACH_VEC_ELT (v, i, opt)
+if (opt->opt_index == OPT_fdump_)
+  g->get_dumps ()->dump_switch_p (opt->arg);
+}
diff --git a/gcc/opts.h b/gcc/opts.h
index 9959a440ca1..00f377f9ca7 100644
--- a/gcc/opts.h
+++ b/gcc/opts.h
@@ -425,6 +425,7 @@ extern void control_warning_option (unsigned int opt_index, int kind,
 extern char *write_langs (unsigned int mask);
 extern void print_ignored_options (void);
 extern void handle_common_deferred_options (void);
+extern void handle_deferred_dump_options (void);
 unsigned int parse_sanitizer_options (const char *, location_t, int,
   unsigned int, int, bool);
 
diff --git a/gcc/toplev.cc b/gcc/toplev.cc
index d53b5e78ae3..c606a0697b7 100644
--- a/gcc/toplev.cc
+++ b/gcc/toplev.cc
@@ -2253,6 +2253,10 @@ toplev::main (int argc, char **argv)
 
   initialize_plugins ();
 
+  /* Handle the dump options now that plugins have had a chance to install new
+ passes.  */
+  handle_deferred_dump_options ();
+
   if (version_flag)
 print_version (stderr, "", true);
 
-- 
2.40.1



Re: Ping: [PATCH] testsuite/C++: suppress filename canonicalization in module tests

2023-04-27 Thread Nathan Sidwell via Gcc-patches

On 4/25/23 11:04, Jan Beulich wrote:

On 28.06.2022 16:06, Jan Beulich wrote:

The pathname underneath gcm.cache/ is determined from the effective name
used for the main input file of a particular module. When modules are
built, no canonicalization occurs for the main input file. Hence the
module file wouldn't be found if a different (the canonicalized) file
name was used when importing that same module. (This is an effect of
importing happening in the preprocessor, just like #include handling.)

Since it doesn't look easy to make module generation use libcpp's
maybe_shorter_path() (in fact I'd consider this a layering violation,
while cloning the logic would - at least in principle - be prone to both
going out of sync), simply suppress system header path canonicalization
for the respective tests.


Ping: This still looks to apply as is.


ok -- I was unaware of this.  might be sensible to file a defect about this?



Thanks, Jan


---
Strictly speaking it could be necessary to also suppress
canonicalization when generating the modules, but for now they're self-
contained, i.e. don't include any "real" system headers. IOW at the
moment the tests aren't susceptible to the issue at generation time.

--- a/gcc/testsuite/g++.dg/modules/alias-1_b.C
+++ b/gcc/testsuite/g++.dg/modules/alias-1_b.C
@@ -1,4 +1,4 @@
-// { dg-additional-options "-fmodules-ts -fdump-lang-module -isystem [srcdir]" 
}
+// { dg-additional-options "-fmodules-ts -fdump-lang-module -isystem [srcdir] 
-fno-canonical-system-headers" }
  
  // Alias at the header file.  We have one CMI file

  import "alias-1_a.H";
--- a/gcc/testsuite/g++.dg/modules/alias-1_d.C
+++ b/gcc/testsuite/g++.dg/modules/alias-1_d.C
@@ -1,4 +1,4 @@
-// { dg-additional-options "-fmodules-ts -isystem [srcdir]" }
+// { dg-additional-options "-fmodules-ts -isystem [srcdir] 
-fno-canonical-system-headers" }
  // { dg-module-cmi kevin }
  
  export module kevin;

--- a/gcc/testsuite/g++.dg/modules/alias-1_e.C
+++ b/gcc/testsuite/g++.dg/modules/alias-1_e.C
@@ -1,4 +1,4 @@
-// { dg-additional-options "-fmodules-ts -isystem [srcdir]" }
+// { dg-additional-options "-fmodules-ts -isystem [srcdir] 
-fno-canonical-system-headers" }
  
  import bob;

  import kevin;
--- a/gcc/testsuite/g++.dg/modules/alias-1_f.C
+++ b/gcc/testsuite/g++.dg/modules/alias-1_f.C
@@ -1,4 +1,4 @@
-// { dg-additional-options "-fmodules-ts -fdump-lang-module -isystem [srcdir]" 
}
+// { dg-additional-options "-fmodules-ts -fdump-lang-module -isystem [srcdir] 
-fno-canonical-system-headers" }
  
  import kevin;

  import bob;
--- a/gcc/testsuite/g++.dg/modules/cpp-6_c.C
+++ b/gcc/testsuite/g++.dg/modules/cpp-6_c.C
@@ -1,5 +1,5 @@
  // { dg-do preprocess }
-// { dg-additional-options "-fmodules-ts -isystem [srcdir]" }
+// { dg-additional-options "-fmodules-ts -isystem [srcdir] 
-fno-canonical-system-headers" }
  
  #define empty

  #define nop(X) X
--- a/gcc/testsuite/g++.dg/modules/dir-only-2_b.C
+++ b/gcc/testsuite/g++.dg/modules/dir-only-2_b.C
@@ -1,5 +1,5 @@
  // { dg-do preprocess }
-// { dg-additional-options "-fmodules-ts -fdirectives-only -isystem [srcdir]" }
+// { dg-additional-options "-fmodules-ts -fdirectives-only -isystem [srcdir] 
-fno-canonical-system-headers" }
  // a comment
  module; // line
  frob




--
Nathan Sidwell



Re: [PATCH v2] testsuite/C++: cope with IPv6 being unavailable

2023-04-27 Thread Nathan Sidwell via Gcc-patches

On 4/25/23 11:00, Jan Beulich wrote:

When IPv6 is disabled in the kernel, the error message coming back from
Cody::OpenInet6() is different from the sole so far expected one.


ok -- i couldn't find such a system :)

---
v2: Re-base.

--- a/gcc/testsuite/g++.dg/modules/bad-mapper-3.C
+++ b/gcc/testsuite/g++.dg/modules/bad-mapper-3.C
@@ -1,6 +1,6 @@
  //  { dg-additional-options "-fmodules-ts 
-fmodule-mapper=localhost:172477262" }
  import unique3.bob;
-// { dg-error {failed (connecting|disabled) mapper 'localhost:172477262'} "" { 
target *-*-* } 0 }
+// { dg-error {failed (socket|connecting|disabled) mapper 'localhost:172477262'} 
"" { target *-*-* } 0 }
  // { dg-prune-output "fatal error:" }
  // { dg-prune-output "failed to read" }
  // { dg-prune-output "compilation terminated" }


--
Nathan Sidwell



Re: [PATCH] c++: Fix Solaris bootstraps across midnight

2023-04-11 Thread Nathan Sidwell via Gcc-patches

Jakub,
for avoidance of doubt, your version is fine.

nathan


On 4/11/23 18:06, Nathan Sidwell wrote:

On 4/11/23 04:12, Jakub Jelinek wrote:

Hi!

When working on the PR109040 fix, I wanted to test it on some
WORD_REGISTER_OPERATIONS target and tried sparc-solaris on GCC Farm.
My bootstrap failed in comparison failure on cp/module.o, because
Solaris date doesn't support the -r option and one stage's cp/module.o
was built before midnight and next stage's cp/module.o after midnight,
so they had different -DMODULE_VERSION= value.

Now, I think the advice (don't bootstrap at midnight) is something
we shouldn't have, so the following patch stores the module version
(still generated through the same way, date -r cp/module.cc
if it works, otherwise just date) into a temporary file, makes sure
that temporary file is updated when cp/module.cc source is updated
and when date -r doesn't work copies file from previous stage
if it is newer than cp/module.cc.


looks good.  one could tweak it slightly to avoid the MODULE_VERSION variable 
(but then I was the original lazy one!) Something like:



s-cp-module-version: $(srcdir)/cp/module.cc
 if date -r $(srcdir)/cp/module.cc '+%y%m%d%H%MU' \
   2>/dev/null >$@; then :; \
 elif test ../prev-gcc/$@ -nt \
   $(srcdir)/cp/module.cc; then \
   cp ../prev-gcc/$@ $@; \
 else \
   date '+%y%m%dU' 2>/dev/null >$@; \
 fi`; \


nathan



--
Nathan Sidwell



Re: [PATCH] c++: Fix Solaris bootstraps across midnight

2023-04-11 Thread Nathan Sidwell via Gcc-patches

On 4/11/23 04:12, Jakub Jelinek wrote:

Hi!

When working on the PR109040 fix, I wanted to test it on some
WORD_REGISTER_OPERATIONS target and tried sparc-solaris on GCC Farm.
My bootstrap failed in comparison failure on cp/module.o, because
Solaris date doesn't support the -r option and one stage's cp/module.o
was built before midnight and next stage's cp/module.o after midnight,
so they had different -DMODULE_VERSION= value.

Now, I think the advice (don't bootstrap at midnight) is something
we shouldn't have, so the following patch stores the module version
(still generated through the same way, date -r cp/module.cc
if it works, otherwise just date) into a temporary file, makes sure
that temporary file is updated when cp/module.cc source is updated
and when date -r doesn't work copies file from previous stage
if it is newer than cp/module.cc.


looks good.  one could tweak it slightly to avoid the MODULE_VERSION variable 
(but then I was the original lazy one!) Something like:



s-cp-module-version: $(srcdir)/cp/module.cc
if date -r $(srcdir)/cp/module.cc '+%y%m%d%H%MU' \
  2>/dev/null >$@; then :; \
elif test ../prev-gcc/$@ -nt \
  $(srcdir)/cp/module.cc; then \
  cp ../prev-gcc/$@ $@; \
else \
  date '+%y%m%dU' 2>/dev/null >$@; \
fi`; \


nathan

--
Nathan Sidwell



Re: C++ modules and AAPCS/ARM EABI clash on inline key methods

2023-02-21 Thread Nathan Sidwell via Gcc-patches

On 2/21/23 11:31, Richard Earnshaw wrote:

I started looking at this a few weeks back, but I was a bit confused by the 
testcase and then never got around to following up.


The Arm C++ binding rules normally exclude using an inline function definition 
from being chosen as the key function because this not uncommonly appears in a 
header file; instead a later function in the class is defined to take that role, 
if such a function exists (in effect an inline function is treated the same way 
as if the function definition appeared within the class definition itself).


But in this class we have only the one function, so in effect this testcase 
appears to fall back to the 'no key function' rule and as such I'd expect the 
class impedimenta to be required in all instances of the function.  That doesn't 
seem to be happening, so either there's something I'm missing, or there's 
something the compiler is doing wrong for this case.


Nathan, your insights would be appreciated here.


Right in the ARM ABI we'll be emitting the vtables etc in any TU that might need 
them.  IIUC that's any TU that creates (or destroys?) an object of type Visitor 
(or derived from there).  That source file does not do that.


I see I didn't add a testcase where the only vfunc was declared inline in the 
class itself.  Thus there's no generic-abi equivalent of ARM's behaviour.


I don't think arm's behavior should be an xfail, instead restrict the checks to 
!arm-eabi


nathan



R.




for  gcc/testsuite/ChangeLog

PR c++/105224
* g++.dg/modules/virt-2_a.C: XFAIL syms on arm*-*-*.
---
  gcc/testsuite/g++.dg/modules/virt-2_a.C |    6 +++---
  1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/gcc/testsuite/g++.dg/modules/virt-2_a.C 
b/gcc/testsuite/g++.dg/modules/virt-2_a.C

index 580552be5a0d8..b265515e2c7fd 100644
--- a/gcc/testsuite/g++.dg/modules/virt-2_a.C
+++ b/gcc/testsuite/g++.dg/modules/virt-2_a.C
@@ -22,6 +22,6 @@ export int Visit (Visitor *v)
  }
  // Emit here
-// { dg-final { scan-assembler {_ZTVW3foo7Visitor:} } }
-// { dg-final { scan-assembler {_ZTIW3foo7Visitor:} } }
-// { dg-final { scan-assembler {_ZTSW3foo7Visitor:} } }
+// { dg-final { scan-assembler {_ZTVW3foo7Visitor:} { xfail arm*-*-* } } }
+// { dg-final { scan-assembler {_ZTIW3foo7Visitor:} { xfail arm*-*-* } } }
+// { dg-final { scan-assembler {_ZTSW3foo7Visitor:} { xfail arm*-*-* } } }




--
Nathan Sidwell



Re: [PATCH] c++ modules: uninstantiated template friend class [PR104234]

2023-02-02 Thread Nathan Sidwell via Gcc-patches
That might be sufficient for this case, but temploid friends violate an 
assumption of the implementation -- namely that module A cannot create an entity 
that belongs in module B's symbol table.  This causes a bunch of excitement, 
particularly around handling (well formed) duplicatd instantions.


I'm not sure of the way to handle that, but I suspect something along the lines 
of a flag on such decls and a new hash table to hold these exceptions.


nathan

On 1/25/23 15:16, Patrick Palka wrote:

Here we're not clearing DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P for
the instantiated/injected template friend class B, which confuses a
later call to get_originating_module_decl for B.  This patch fixes this
by clearing the flag in tsubst_friend_class (as is already done for
template friend functions by r11-5730-gf7aeb823d9b0de).

After fixing that, we still fail to compile the testcase, rejecting the
later definition of B with

   friend-6_a.C:10:26: error: cannot declare ‘struct B’ in a different module

ultimately because DECL_MODULE_ATTACH_P wasn't set on the original
(injected) declaration of B.  This patch fixes this by calling
set_originating_module in tsubst_friend_class, but for that to work it
seems we need to relax the assert in this latter function since
get_originating_module_decl when called on the TYPE_DECL for B returns
the corresponding TEMPLATE_DECL.

(Alternatively we can instead call set_originating_module on the
TYPE_DECL B as soon as it's created in lookup_template_class (which is
what pushtag does), which doesn't need this assert change because at
this point the TYPE_DECL doesn't have any TEMPLATE_INFO so
get_originating_module_decl becomes a no-op.  Would that be preferable?)

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

PR c++/104234

gcc/cp/ChangeLog:

* module.cc (set_originating_module): Document default argument.
Relax assert to look through DECL_TEMPLATE_RESULT in the result
of get_originating_module_decl.
* pt.cc (tsubst_friend_class): Clear
DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P and call
set_originating_module on the instantiated template friend class.

gcc/testsuite/ChangeLog:

* g++.dg/modules/friend-6_a.C: New test.
---
  gcc/cp/module.cc  |  8 ++--
  gcc/cp/pt.cc  |  3 +++
  gcc/testsuite/g++.dg/modules/friend-6_a.C | 10 ++
  3 files changed, 19 insertions(+), 2 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/friend-6_a.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 7133009dba5..234ce43b70f 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -18843,14 +18843,18 @@ set_defining_module (tree decl)
  }
  
  void

-set_originating_module (tree decl, bool friend_p ATTRIBUTE_UNUSED)
+set_originating_module (tree decl, bool friend_p /* = false */)
  {
set_instantiating_module (decl);
  
if (!DECL_NAMESPACE_SCOPE_P (decl))

  return;
  
-  gcc_checking_assert (friend_p || decl == get_originating_module_decl (decl));

+  if (!friend_p)
+{
+  tree o = get_originating_module_decl (decl);
+  gcc_checking_assert (STRIP_TEMPLATE (o) == decl);
+}
  
if (module_attach_p ())

  {
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index cbe5898b553..f2ee74025e7 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -11520,6 +11520,9 @@ tsubst_friend_class (tree friend_tmpl, tree args)
  CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl))
= INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl)));
  
+	  DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (tmpl) = false;

+ set_originating_module (DECL_TEMPLATE_RESULT (tmpl));
+
  /* Substitute into and set the constraints on the new declaration.  */
  if (tree ci = get_constraints (friend_tmpl))
{
diff --git a/gcc/testsuite/g++.dg/modules/friend-6_a.C 
b/gcc/testsuite/g++.dg/modules/friend-6_a.C
new file mode 100644
index 000..97017e4ee78
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/friend-6_a.C
@@ -0,0 +1,10 @@
+// PR c++/104234
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi pr104234 }
+export module pr104234;
+
+template struct A {
+  template friend struct B;
+};
+A a;
+template struct B { };


--
Nathan Sidwell



Re: [PATCH] c++tools: Fix compilation of server.cc on hpux

2023-01-09 Thread Nathan Sidwell via Gcc-patches

On 1/7/23 14:12, John David Anglin wrote:

Tested on trunk and gcc-12 with hppa64-hp-hpux11.11.


ah, I see that is the use that was unprotected, ok.




Okay?

Dave
---

Fix compilation of server.cc on hpux.

Select and FD_ISSET are declared in sys/time.h on most versions
of hpux.  As a result, HAVE_PSELECT and HAVE_SELECT can be 0.

2023-01-07  John David Anglin  

c++tools/ChangeLog:

PR c++tools/107616
* server.cc (server): Don't call FD_ISSET when HAVE_PSELECT
and HAVE_SELECT are zero.

diff --git a/c++tools/server.cc b/c++tools/server.cc
index 00154a05925..693aec6820a 100644
--- a/c++tools/server.cc
+++ b/c++tools/server.cc
@@ -753,8 +753,10 @@ server (bool ipv6, int sock_fd, module_resolver *resolver)
  }
  }
  
+#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)

  if (active < 0 && sock_fd >= 0 && FD_ISSET (sock_fd, ))
active = -1;
+#endif
}
  
  	  if (active >= 0)




--
Nathan Sidwell



Re: [PATCH] c++: modules and std::source_location::current() def arg [PR100881]

2022-12-08 Thread Nathan Sidwell via Gcc-patches

On 12/7/22 16:50, Patrick Palka wrote:

We currently declare __builtin_source_location with a const void* return
type instead of the true type (const std::source_location::__impl*), and
later when folding this builtin we just obtain the true type via name
lookup.

But the below testcase demonstrates this name lookup approach seems to
interact poorly with modules, since we may import an entity that uses
std::source_location::current() in a default argument (or DMI) without
also importing , and thus the name lookup will fail
when folding the builtin at the call site unless we also import
.

This patch fixes by instead initially declaring __builtin_source_location
with an auto return type and updating it appropriately upon its first use.
Thus when folding calls to this builtin we can fish out the true return
type through the type of the CALL_EXPR and avoid needing to do name
lookup.


That's a clever approach!  LGTM

nathan

--
Nathan Sidwell



Re: PING [PATCH v3] c++: Allow module name to be a single letter on Windows

2022-11-28 Thread Nathan Sidwell via Gcc-patches

On 11/25/22 14:03, Torbjorn SVENSSON wrote:

Hi,

Ping, https://gcc.gnu.org/pipermail/gcc-patches/2022-November/606528.html


ok, thanks!



Kind regards,
Torbjörn

On 2022-11-17 14:20, Torbjörn SVENSSON wrote:

v1 -> v2:
Paths without "C:" part can still be absolute if they start with / or
\ on Windows.

v2 -> v3:
Use alternative approach by having platform specific code in module.cc.

Truth table for the new expression:
c:\foo -> true
c:/foo -> true
/foo   -> true
\foo   -> true
c:foo  -> false
foo    -> false
./foo  -> true
.\foo  -> true


Ok for trunk?

---

On Windows, the ':' character is special and when the module name is
a single character, like 'A', then the flatname would be (for
example) 'A:Foo'. On Windows, 'A:Foo' is treated as an absolute
path by the module loader and is likely not found.

Without this patch, the test case pr98944_c.C fails with:

In module imported at /src/gcc/testsuite/g++.dg/modules/pr98944_b.C:7:1,
of module A:Foo, imported at /src/gcc/testsuite/g++.dg/modules/pr98944_c.C:7:
A:Internals: error: header module expected, module 'A:Internals' found
A:Internals: error: failed to read compiled module: Bad file data
A:Internals: note: compiled module file is 'gcm.cache/A-Internals.gcm'
In module imported at /src/gcc/testsuite/g++.dg/modules/pr98944_c.C:7:8:
A:Foo: error: failed to read compiled module: Bad import dependency
A:Foo: note: compiled module file is 'gcm.cache/A-Foo.gcm'
A:Foo: fatal error: returning to the gate for a mechanical issue
compilation terminated.

gcc/cp/ChangeLog:

* module.cc: On Windows, 'A:Foo' is supposed to be a module
and not a path.

Tested on Windows with arm-none-eabi for Cortex-M3 in gcc-11 tree.

Co-Authored-By: Yvan ROUX 
Signed-off-by: Torbjörn SVENSSON 
---
  gcc/cp/module.cc | 10 +-
  1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 0e9af318ba4..fa41a86213f 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -13960,7 +13960,15 @@ get_module (tree name, module_state *parent, bool 
partition)

  static module_state *
  get_module (const char *ptr)
  {
-  if (ptr[0] == '.' ? IS_DIR_SEPARATOR (ptr[1]) : IS_ABSOLUTE_PATH (ptr))
+  /* On DOS based file systems, there is an ambiguity with A:B which can be
+ interpreted as a module Module:Partition or Drive:PATH.  Interpret strings
+ which clearly starts as pathnames as header-names and everything else is
+ treated as a (possibly malformed) named moduled.  */
+  if (IS_DIR_SEPARATOR (ptr[ptr[0] == '.']) // ./FOO or /FOO
+#if HAVE_DOS_BASED_FILE_SYSTEM
+  || (HAS_DRIVE_SPEC (ptr) && IS_DIR_SEPARATOR (ptr[2])) // A:/FOO
+#endif
+  || false)
  /* A header name.  */
  return get_module (build_string (strlen (ptr), ptr));


--
Nathan Sidwell



demangler: Templated lambda demangling

2022-11-10 Thread Nathan Sidwell via Gcc-patches

Templated lambdas have a template-head, which is part of their
signature.  GCC ABI 18 mangles that into the lambda name.  This adds
support to the demangler.  We have to introduce artificial template
parameter names, as we need to refer to them from later components of
the lambda signature. We use $T:n, $N:n and $TT:n for type, non-type
and template parameters.  Non-type parameter names are not shown in
the strictly correct location -- for instance 'int () ()' would be
shown as 'int (&) $N:n'.  That's unfortunate, but an orthogonal issue.
The 'is_lambda_arg' field is now repurposed as indicating the number
of explicit template parameters (1-based).

I'll commit in a few days.

nathan


--
Nathan SidwellFrom b7f0ba90011b8c9cae7b7278463f609ba21cd44b Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Mon, 7 Nov 2022 11:24:14 -0500
Subject: [PATCH] demangler: Templated lambda demangling

Templated lambdas have a template-head, which is part of their
signature.  GCC ABI 18 mangles that into the lambda name.  This adds
support to the demangler.  We have to introduce artificial template
parameter names, as we need to refer to them from later components of
the lambda signature. We use $T:n, $N:n and $TT:n for type, non-type
and template parameters.  Non-type parameter names are not shown in
the strictly correct location -- for instance 'int () ()' would be
shown as 'int (&) $N:n'.  That's unfortunate, but an orthogonal issue.
The 'is_lambda_arg' field is now repurposed as indicating the number
of explicit template parameters (1-based).

	include/
	* demangle.h (enum demangle_component_type): Add
	DEMANGLE_COMPONENT_TEMPLATE_HEAD,
	DEMANGLE_COMPONENT_TEMPLATE_TYPE_PARM,
	DEMANGLE_COMPONENT_TEMPLATE_NON_TYPE_PARM,
	DEMANGLE_COMPONENT_TEMPLATE_TEMPLATE_PARM,
	DEMANGLE_COMPONENT_TEMPLATE_PACK_PARM.
	libiberty/
	* cp-demangle.c (struct d_print_info): Rename is_lambda_arg to
	lambda_tpl_parms.  Augment semantics.
	(d_make_comp): Add checks for new components.
	(d_template_parm, d_template_head): New.
	(d_lambda): Add templated lambda support.
	(d_print_init): Adjust.
	(d_print_lambda_parm_name): New.
	(d_print_comp_inner): Support templated lambdas,
	* testsuite/demangle-expected: Add testcases.
---
 include/demangle.h|   6 +
 libiberty/cp-demangle.c   | 260 +++---
 libiberty/testsuite/demangle-expected |  53 ++
 3 files changed, 295 insertions(+), 24 deletions(-)

diff --git a/include/demangle.h b/include/demangle.h
index 81d4353a86f..66637ebdc16 100644
--- a/include/demangle.h
+++ b/include/demangle.h
@@ -458,6 +458,12 @@ enum demangle_component_type
   DEMANGLE_COMPONENT_MODULE_ENTITY,
   DEMANGLE_COMPONENT_MODULE_INIT,
 
+  DEMANGLE_COMPONENT_TEMPLATE_HEAD,
+  DEMANGLE_COMPONENT_TEMPLATE_TYPE_PARM,
+  DEMANGLE_COMPONENT_TEMPLATE_NON_TYPE_PARM,
+  DEMANGLE_COMPONENT_TEMPLATE_TEMPLATE_PARM,
+  DEMANGLE_COMPONENT_TEMPLATE_PACK_PARM,
+
   /* A builtin type with argument.  This holds the builtin type
  information.  */
   DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 8413dcdc785..ad533f6085e 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -347,9 +347,9 @@ struct d_print_info
   /* Number of times d_print_comp was recursively called.  Should not
  be bigger than MAX_RECURSION_COUNT.  */
   int recursion;
-  /* Non-zero if we're printing a lambda argument.  A template
- parameter reference actually means 'auto', a pack expansion means T...  */
-  int is_lambda_arg;
+  /* 1 more than the number of explicit template parms of a lambda.  Template
+ parm references >= are actually 'auto'.  */
+  int lambda_tpl_parms;
   /* The current index into any template argument packs we are using
  for printing, or -1 to print the whole pack.  */
   int pack_index;
@@ -491,6 +491,10 @@ static struct demangle_component *d_local_name (struct d_info *);
 
 static int d_discriminator (struct d_info *);
 
+static struct demangle_component *d_template_parm (struct d_info *, int *bad);
+
+static struct demangle_component *d_template_head (struct d_info *, int *bad);
+
 static struct demangle_component *d_lambda (struct d_info *);
 
 static struct demangle_component *d_unnamed_type (struct d_info *);
@@ -1028,6 +1032,10 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
 case DEMANGLE_COMPONENT_TPARM_OBJ:
 case DEMANGLE_COMPONENT_STRUCTURED_BINDING:
 case DEMANGLE_COMPONENT_MODULE_INIT:
+case DEMANGLE_COMPONENT_TEMPLATE_HEAD:
+case DEMANGLE_COMPONENT_TEMPLATE_NON_TYPE_PARM:
+case DEMANGLE_COMPONENT_TEMPLATE_TEMPLATE_PARM:
+case DEMANGLE_COMPONENT_TEMPLATE_PACK_PARM:
   if (left == NULL)
 	return NULL;
   break;
@@ -1050,6 +1058,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
 case DEMANGLE_COMPONENT_CONST:
 case DEMANGLE_COMPONENT_ARGLIST:
 case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST

Re: [PATCH] c++: Allow module name to be a single letter on Windows

2022-11-08 Thread Nathan Sidwell via Gcc-patches

On 11/8/22 05:18, Torbjorn SVENSSON wrote:

Hi Nathan,

On 2022-11-08 00:03, Nathan Sidwell wrote:




Yes, something like the above, but I think you're missing "/bob' in the 
DOS_BASED case?  shouldn't that also be a pathname?


if (IS_DIR_SEPARATOR (ptr[ptr[0] == '.']) // ./FOO or /FOO
#if HAVE_DOS_BASED_FILE_SYSTEM
 // DOS-FS IS_ABSOLUTE_PATH thinks 'A:B' is absolute, but we need to 
consider
 // that as a module:partition.
 || (HAS_DRIVE_SPEC (ptr) && IS_DIR_SEPARATOR (ptr[2])) // A:/FOO
#endif
 || false)
    return 

Does (something like) that work?


I tested it and your solution appears to work.
Are you okay with me pushing that solution or do you want me to send a v2 with 
it first?


I think it needs a better introductory comment than the one I slapped in there. 
More explanation of the drive vs partition distinction.  Something along the 
lines of 'things that clearly start as pathnames are header-names, everything 
else is treated as a (possibly malformed) named module.


Feel free to just go with it, or iterate here

nathan

--
Nathan Sidwell



Re: [PATCH] c++: Allow module name to be a single letter on Windows

2022-11-07 Thread Nathan Sidwell via Gcc-patches

On 11/3/22 11:06, Torbjorn SVENSSON wrote:



On 2022-11-03 15:17, Nathan Sidwell wrote:

On 10/28/22 05:15, Torbjörn SVENSSON wrote:

On Windows, the ':' character is special and when the module name is
a single character, like 'A', then the flatname would be (for
example) 'A:Foo'. On Windows, 'A:Foo' is treated as an absolute
path by the module loader and is likely not found.

Without this patch, the test case pr98944_c.C fails with:

In module imported at /src/gcc/testsuite/g++.dg/modules/pr98944_b.C:7:1,
of module A:Foo, imported at /src/gcc/testsuite/g++.dg/modules/pr98944_c.C:7:
A:Internals: error: header module expected, module 'A:Internals' found
A:Internals: error: failed to read compiled module: Bad file data
A:Internals: note: compiled module file is 'gcm.cache/A-Internals.gcm'
In module imported at /src/gcc/testsuite/g++.dg/modules/pr98944_c.C:7:8:
A:Foo: error: failed to read compiled module: Bad import dependency
A:Foo: note: compiled module file is 'gcm.cache/A-Foo.gcm'
A:Foo: fatal error: returning to the gate for a mechanical issue
compilation terminated.

include/ChangeLog:

* filenames.h: Added IS_REAL_ABSOLUTE_PATH macro to check if
path is absolute and not semi-absolute on Windows.


Hm, this is unfortunate.  The current IS_ABSOLUTE_PATH, is really 'not 
relative to cwd', and even then that's untrue if the drive letter there is the 
drive letter of cwd, right?


It's awkward to have a new macro for just this purpose and the new name isn't 
very indicative of the difference to the current IS_ABSOLUTE_PATH.


Would it be better to not deal with drive letters here?  How prevalent are 
they these days in windows?  Would something like


    if (IS_DIR_SEPARATOR (ptr[ptr[0] == '.'])

suffice?


I don't think you can ignore the drive letter part... see below.


#include 
#include "include/filenames.h"
#define TF(x) ((x) ? "true" : "false")
int main(int argc, char *argv[]) {
   const char *test[] = {
   /* absolute */  "c:\\foo", "c:/foo", "/foo", "\\foo",
   /* semi-absolute */ "c:foo",
   /* relative */  "foo", "./foo", ".\\foo",
   };
   for (int i = 0; i < sizeof(test) / sizeof(test[0]); i++) {
     const char *ptr = test[i];
     printf("\nptr: %s\n", ptr);
     printf("  IS_DOS_ABSOLUTE_PATH: %s\n",
    TF(IS_DOS_ABSOLUTE_PATH(ptr)));
     printf("  IS_DOS_REAL_ABSOLUTE_PATH: %s\n",
    TF(IS_DOS_REAL_ABSOLUTE_PATH(ptr)));
     printf("  IS_DIR_SEPARATOR: %s\n",
    TF(IS_DIR_SEPARATOR(ptr[ptr[0] == '.'])));
   }
   return 0;
}


The output is:

ptr: c:\foo
   IS_DOS_ABSOLUTE_PATH: true
   IS_DOS_REAL_ABSOLUTE_PATH: true
   IS_DIR_SEPARATOR: false

ptr: c:/foo
   IS_DOS_ABSOLUTE_PATH: true
   IS_DOS_REAL_ABSOLUTE_PATH: true
   IS_DIR_SEPARATOR: false

ptr: /foo
   IS_DOS_ABSOLUTE_PATH: true
   IS_DOS_REAL_ABSOLUTE_PATH: true
   IS_DIR_SEPARATOR: true

ptr: \foo
   IS_DOS_ABSOLUTE_PATH: true
   IS_DOS_REAL_ABSOLUTE_PATH: true
   IS_DIR_SEPARATOR: false

ptr: c:foo
   IS_DOS_ABSOLUTE_PATH: true
   IS_DOS_REAL_ABSOLUTE_PATH: false
   IS_DIR_SEPARATOR: false

ptr: foo
   IS_DOS_ABSOLUTE_PATH: false
   IS_DOS_REAL_ABSOLUTE_PATH: false
   IS_DIR_SEPARATOR: false

ptr: ./foo
   IS_DOS_ABSOLUTE_PATH: false
   IS_DOS_REAL_ABSOLUTE_PATH: false
   IS_DIR_SEPARATOR: true

ptr: .\foo
   IS_DOS_ABSOLUTE_PATH: false
   IS_DOS_REAL_ABSOLUTE_PATH: false
   IS_DIR_SEPARATOR: false




or, failing that perhaps put some explicit WINDOWS-specific #ifdef'd code 
there?  It's a real corner case.


Would you rather have something like this in module.cc?

if (ptr[0] == '.')
   {
     if IS_DIR_SEPARATOR (ptr[1]))
   return get_module (build_string (strlen (ptr), ptr));
   }
else
   {
#if HAVE_DOS_BASED_FILE_SYSTEM
     if (HAS_DRIVE_SPEC (ptr) && IS_DIR_SEPARATOR (ptr[2]))
#else
     if (IS_ABSOLUTE_PATH (ptr))
#endif
   return get_module (build_string (strlen (ptr), ptr));
   }


Yes, something like the above, but I think you're missing "/bob' in the 
DOS_BASED case?  shouldn't that also be a pathname?


if (IS_DIR_SEPARATOR (ptr[ptr[0] == '.']) // ./FOO or /FOO
#if HAVE_DOS_BASED_FILE_SYSTEM
// DOS-FS IS_ABSOLUTE_PATH thinks 'A:B' is absolute, but we need to consider
// that as a module:partition.
|| (HAS_DRIVE_SPEC (ptr) && IS_DIR_SEPARATOR (ptr[2])) // A:/FOO
#endif
|| false)
   return 

Does (something like) that work?

nathan




Let me know what you prefer.

Kind regards,
Torbjörn



nathan



gcc/cp/ChangeLog:

* module.cc: Use IS_REAL_ABSOLUTE_PATH macro.

Co-Authored-By: Yvan ROUX 
Signed-off-by: Torbjörn SVENSSON 
---
  gcc/cp/module.cc    | 2 +-
  include/filenames.h | 4 
  2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 9957df510e6..84680e183b7 100644
--- a/gcc/cp/module.cc
+++ b/g

C++: Template lambda mangling testcases

2022-11-07 Thread Nathan Sidwell via Gcc-patches


I found some additional cases when working on the demangler.  May as
well check their mangling.  Since I managed to confuse myself.

nathan
--
Nathan SidwellFrom 51d567d4d15e78b42d2ca83f229c98fff2aec9fa Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Mon, 7 Nov 2022 11:08:21 -0500
Subject: [PATCH] C++: Template lambda mangling testcases

I found some additional cases when working on the demangler.  May as
well check their mangling.

	gcc/testsuite/
	* g++.dg/abi/lambda-tpl1.h: Add more cases.
	* g++.dg/abi/lambda-tpl1-17.C: Add checks.
	* g++.dg/abi/lambda-tpl1-18.C: Likewise.
	* g++.dg/abi/lambda-tpl1-18vs17.C: Likewise.
---
 gcc/testsuite/g++.dg/abi/lambda-tpl1-17.C |  6 ++
 gcc/testsuite/g++.dg/abi/lambda-tpl1-18.C |  6 ++
 gcc/testsuite/g++.dg/abi/lambda-tpl1-18vs17.C |  5 +
 gcc/testsuite/g++.dg/abi/lambda-tpl1.h| 11 +++
 4 files changed, 28 insertions(+)

diff --git a/gcc/testsuite/g++.dg/abi/lambda-tpl1-17.C b/gcc/testsuite/g++.dg/abi/lambda-tpl1-17.C
index b61aaf98cd0..010f6222151 100644
--- a/gcc/testsuite/g++.dg/abi/lambda-tpl1-17.C
+++ b/gcc/testsuite/g++.dg/abi/lambda-tpl1-17.C
@@ -18,3 +18,9 @@
 // { dg-final { scan-assembler {_ZNK6l_var3MUlRT_IJXspT0__clI1XJLi1ELi2ELi3DaS1_:} } }
 // { dg-final { scan-assembler {_ZNK6l_var4MUlR1YIJDpT_EEE_clIJ1US6_EEEDaS3_:} } }
 // { dg-final { scan-assembler {_ZZ2FnILi1EEvvENKUlT_E_clIiEEDaS0_:} } }
+
+// { dg-final { scan-assembler {_ZZ1fvENKUlT_E_clIcLc0EEEDaS_:} } }
+// { dg-final { scan-assembler {_ZZ1fvENKUlT_E_clIiLi0EEEDaS_:} } }
+// { dg-final { scan-assembler {_ZZZ1fvENKUlT_E_clIcLc0EEEDaS_ENKUlcS_E_clIcEEDacS_:} } }
+// { dg-final { scan-assembler {_ZZZ1fvENKUlT_E_clIiLi0EEEDaS_ENKUliS_E_clIiEEDaiS_:} } }
+// { dg-final { scan-assembler {_ZZ1fvENKUlP1UIT_Lj0EEPS_IiLj0EEE0_clIcEEDaS2_S4_:} } }
diff --git a/gcc/testsuite/g++.dg/abi/lambda-tpl1-18.C b/gcc/testsuite/g++.dg/abi/lambda-tpl1-18.C
index dbeea407651..66cce9aa266 100644
--- a/gcc/testsuite/g++.dg/abi/lambda-tpl1-18.C
+++ b/gcc/testsuite/g++.dg/abi/lambda-tpl1-18.C
@@ -23,3 +23,9 @@
 // https://github.com/llvm/llvm-project/issues/58631
 
 // { dg-final { scan-assembler {_ZZ2FnILi1EEvvENKUlTyT_E_clIiEEDaS0_:} } }
+
+// { dg-final { scan-assembler {_ZZ1fvENKUlTyTnT_S_E_clIcLc0EEEDaS_:} } }
+// { dg-final { scan-assembler {_ZZ1fvENKUlTyTnT_S_E_clIiLi0EEEDaS_:} } }
+// { dg-final { scan-assembler {_ZZZ1fvENKUlTyTnT_S_E_clIcLc0EEEDaS_ENKUlTycS_E_clIcEEDacS_:} } }
+// { dg-final { scan-assembler {_ZZZ1fvENKUlTyTnT_S_E_clIiLi0EEEDaS_ENKUlTyiS_E_clIiEEDaiS_:} } }
+// { dg-final { scan-assembler {_ZZ1fvENKUlTyP1UIT_Lj0EEPS_IiLj0EEE_clIcEEDaS2_S4_:} } }
diff --git a/gcc/testsuite/g++.dg/abi/lambda-tpl1-18vs17.C b/gcc/testsuite/g++.dg/abi/lambda-tpl1-18vs17.C
index 8bead7393c7..6489db9e442 100644
--- a/gcc/testsuite/g++.dg/abi/lambda-tpl1-18vs17.C
+++ b/gcc/testsuite/g++.dg/abi/lambda-tpl1-18vs17.C
@@ -14,3 +14,8 @@
 // { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK10l_tpl_autoMUlT_T0_E_clIiiEEDaS_S0_'\) and '-fabi-version=18' \('_ZNK10l_tpl_autoMUlTyT_T0_E_clIiiEEDaS0_S1_'\) [^\n]*\n} }
 // { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK5l_tplMUlT_E_clIiEEDaS_'\) and '-fabi-version=18' \('_ZNK5l_tplMUlTyT_E_clIiEEDaS0_'\) [^\n]*\n} }
 // { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZNK6l_autoMUlT_E_clIiEEDaS_'\) and '-fabi-version=18' \('_ZNK6l_autoMUlT_E_clIiEEDaS0_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZ1fvENKUlT_E_clIiLi0EEEDaS_'\) and '-fabi-version=18' \('_ZZ1fvENKUlTyTnT_S_E_clIiLi0EEEDaS_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZZ1fvENKUlT_E_clIiLi0EEEDaS_ENKUliS_E_clIiEEDaiS_'\) and '-fabi-version=18' \('_ZZZ1fvENKUlTyTnT_S_E_clIiLi0EEEDaS_ENKUlTyiS_E_clIiEEDaiS_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZ1fvENKUlT_E_clIcLc0EEEDaS_'\) and '-fabi-version=18' \('_ZZ1fvENKUlTyTnT_S_E_clIcLc0EEEDaS_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZZ1fvENKUlT_E_clIcLc0EEEDaS_ENKUlcS_E_clIcEEDacS_'\) and '-fabi-version=18' \('_ZZZ1fvENKUlTyTnT_S_E_clIcLc0EEEDaS_ENKUlTycS_E_clIcEEDacS_'\) [^\n]*\n} }
+// { dg-regexp {[^\n]*lambda-tpl1.h:[:0-9]* warning: the mangled name [^\n]* \('_ZZ1fvENKUlP1UIT_Lj0EEPS_IiLj0EEE0_clIcEEDaS2_S4_'\) and '-fabi-version=18' \('_ZZ1fvENKUlTyP1UIT_Lj0EEPS_IiLj0EEE_clIcEEDaS2_S4_'\) [^\n]*\n} }
diff --git a/gcc/testsuite/g++.dg/abi/lambda-tpl1.h b/gcc/testsuite/g++.dg/abi/lambda-tpl1.h
index 5d6fe5e1d0a..376c3f6a2f4 100644
--- a/gcc/testsuite/g++.dg/abi/lambda-tpl1.h
+++ b/gcc/testsuite/g++.dg/abi/lambda-tpl1.h
@@ -56,4 +56,15 @@ void f ()
   l_var4 (y);
 
   Fn<1> ();
+
+  auto l1 = [] (T a) {
+auto l2 = [] (T a, U b) {};
+
+l2 (a, v);
+  };
+  auto l3 = [](U *, U *) {};
+
+  l1 (1);
+  

Re: [PATCH] c++: Allow module name to be a single letter on Windows

2022-11-03 Thread Nathan Sidwell via Gcc-patches

On 10/28/22 05:15, Torbjörn SVENSSON wrote:

On Windows, the ':' character is special and when the module name is
a single character, like 'A', then the flatname would be (for
example) 'A:Foo'. On Windows, 'A:Foo' is treated as an absolute
path by the module loader and is likely not found.

Without this patch, the test case pr98944_c.C fails with:

In module imported at /src/gcc/testsuite/g++.dg/modules/pr98944_b.C:7:1,
of module A:Foo, imported at /src/gcc/testsuite/g++.dg/modules/pr98944_c.C:7:
A:Internals: error: header module expected, module 'A:Internals' found
A:Internals: error: failed to read compiled module: Bad file data
A:Internals: note: compiled module file is 'gcm.cache/A-Internals.gcm'
In module imported at /src/gcc/testsuite/g++.dg/modules/pr98944_c.C:7:8:
A:Foo: error: failed to read compiled module: Bad import dependency
A:Foo: note: compiled module file is 'gcm.cache/A-Foo.gcm'
A:Foo: fatal error: returning to the gate for a mechanical issue
compilation terminated.

include/ChangeLog:

* filenames.h: Added IS_REAL_ABSOLUTE_PATH macro to check if
path is absolute and not semi-absolute on Windows.


Hm, this is unfortunate.  The current IS_ABSOLUTE_PATH, is really 'not relative 
to cwd', and even then that's untrue if the drive letter there is the drive 
letter of cwd, right?


It's awkward to have a new macro for just this purpose and the new name isn't 
very indicative of the difference to the current IS_ABSOLUTE_PATH.


Would it be better to not deal with drive letters here?  How prevalent are they 
these days in windows?  Would something like


   if (IS_DIR_SEPARATOR (ptr[ptr[0] == '.'])

suffice?

or, failing that perhaps put some explicit WINDOWS-specific #ifdef'd code there? 
 It's a real corner case.


nathan



gcc/cp/ChangeLog:

* module.cc: Use IS_REAL_ABSOLUTE_PATH macro.

Co-Authored-By: Yvan ROUX 
Signed-off-by: Torbjörn SVENSSON 
---
  gcc/cp/module.cc| 2 +-
  include/filenames.h | 4 
  2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 9957df510e6..84680e183b7 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -13958,7 +13958,7 @@ get_module (tree name, module_state *parent, bool 
partition)
  static module_state *
  get_module (const char *ptr)
  {
-  if (ptr[0] == '.' ? IS_DIR_SEPARATOR (ptr[1]) : IS_ABSOLUTE_PATH (ptr))
+  if (ptr[0] == '.' ? IS_DIR_SEPARATOR (ptr[1]) : IS_REAL_ABSOLUTE_PATH (ptr))
  /* A header name.  */
  return get_module (build_string (strlen (ptr), ptr));
  
diff --git a/include/filenames.h b/include/filenames.h

index 6c72c422edd..d04fccfed64 100644
--- a/include/filenames.h
+++ b/include/filenames.h
@@ -43,6 +43,7 @@ extern "C" {
  #  define HAS_DRIVE_SPEC(f) HAS_DOS_DRIVE_SPEC (f)
  #  define IS_DIR_SEPARATOR(c) IS_DOS_DIR_SEPARATOR (c)
  #  define IS_ABSOLUTE_PATH(f) IS_DOS_ABSOLUTE_PATH (f)
+#  define IS_REAL_ABSOLUTE_PATH(f) IS_DOS_REAL_ABSOLUTE_PATH (f)
  #else /* not DOSish */
  #  if defined(__APPLE__)
  #ifndef HAVE_CASE_INSENSITIVE_FILE_SYSTEM
@@ -52,6 +53,7 @@ extern "C" {
  #  define HAS_DRIVE_SPEC(f) (0)
  #  define IS_DIR_SEPARATOR(c) IS_UNIX_DIR_SEPARATOR (c)
  #  define IS_ABSOLUTE_PATH(f) IS_UNIX_ABSOLUTE_PATH (f)
+#  define IS_REAL_ABSOLUTE_PATH(f) IS_ABSOLUTE_PATH (f)
  #endif
  
  #define IS_DIR_SEPARATOR_1(dos_based, c)\

@@ -67,6 +69,8 @@ extern "C" {
  
  #define IS_DOS_DIR_SEPARATOR(c) IS_DIR_SEPARATOR_1 (1, c)

  #define IS_DOS_ABSOLUTE_PATH(f) IS_ABSOLUTE_PATH_1 (1, f)
+#define IS_DOS_REAL_ABSOLUTE_PATH(f) \
+  ((f)[0] && (f)[1] == ':' && ((f)[2] == '/' || (f)[2] == '\\'))
  #define HAS_DOS_DRIVE_SPEC(f) HAS_DRIVE_SPEC_1 (1, f)
  
  #define IS_UNIX_DIR_SEPARATOR(c) IS_DIR_SEPARATOR_1 (0, c)


--
Nathan Sidwell



Re: [PATCH v2] c++: Use in-process client when networking is disabled

2022-11-03 Thread Nathan Sidwell via Gcc-patches

On 11/3/22 09:48, Torbjorn SVENSSON wrote:

Hello Nathan,

On 2022-11-03 14:13, Nathan Sidwell wrote:

On 11/3/22 05:37, Torbjörn SVENSSON wrote:

v1 -> v2:
Updated expression in bad-mapper-3.C

Ok for trunk?

---

Without the patch, the output for bad-mapper-3.C would be:

/src/gcc/gcc/testsuite/g++.dg/modules/bad-mapper-3.C:2:1: error: unknown 
Compiled Module Interface: no such module


As this line is unexpected, the test case would fail.
The same problem can also be seen for g++.dg/modules/bad-mapper-2.C.

gcc/cp/ChangeLog:

* mapper-client.cc: Use in-process client when networking is
disabled.

gcc/testsuite/ChangeLog:

* g++.dg/modules/bad-mapper-3.C: Update dg-error pattern.

Tested on Windows with arm-none-eabi for Cortex-M3 in gcc-11 tree.

Co-Authored-By: Yvan ROUX 
Signed-off-by: Torbjörn SVENSSON 
---
  gcc/cp/mapper-client.cc | 4 
  gcc/testsuite/g++.dg/modules/bad-mapper-3.C | 2 +-
  2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/mapper-client.cc b/gcc/cp/mapper-client.cc
index fe9544b5ba4..4dcb3a03660 100644
--- a/gcc/cp/mapper-client.cc
+++ b/gcc/cp/mapper-client.cc
@@ -227,6 +227,8 @@ module_client::open_module_client (location_t loc, const 
char *o,

  int fd = -1;
  #if CODY_NETWORKING
  fd = Cody::OpenLocal (, name.c_str () + 1);
+#else
+    errmsg = "CODY_NETWORKING disabled";


CODY_NETWORKING is implementor speak. I think just "disabled" is sufficient 
here?


Ok for trunk if I change to just "disabled" here and in the other places below?


yes, thanks


Kind regards,
Torbjörn




  #endif
  if (fd >= 0)
    c = new module_client (fd, fd);
@@ -254,6 +256,8 @@ module_client::open_module_client (location_t loc, const 
char *o,

  int fd = -1;
  #if CODY_NETWORKING
  fd = Cody::OpenInet6 (, name.c_str (), port);
+#else
+    errmsg = "CODY_NETWORKING disabled";
  #endif
  name[colon] = ':';
diff --git a/gcc/testsuite/g++.dg/modules/bad-mapper-3.C 
b/gcc/testsuite/g++.dg/modules/bad-mapper-3.C

index 9dab332ccb2..c91bb4e260c 100644
--- a/gcc/testsuite/g++.dg/modules/bad-mapper-3.C
+++ b/gcc/testsuite/g++.dg/modules/bad-mapper-3.C
@@ -1,6 +1,6 @@
  //  { dg-additional-options "-fmodules-ts 
-fmodule-mapper=localhost:172477262" }

  import unique3.bob;
-// { dg-error {failed connecting mapper 'localhost:172477262'} "" { target 
*-*-* } 0 }
+// { dg-error {failed (connecting|CODY_NETWORKING disabled) mapper 
'localhost:172477262'} "" { target *-*-* } 0 }

  // { dg-prune-output "fatal error:" }
  // { dg-prune-output "failed to read" }
  // { dg-prune-output "compilation terminated" }




--
Nathan Sidwell



Re: [PATCH v2] c++: Use in-process client when networking is disabled

2022-11-03 Thread Nathan Sidwell via Gcc-patches

On 11/3/22 05:37, Torbjörn SVENSSON wrote:

v1 -> v2:
Updated expression in bad-mapper-3.C

Ok for trunk?

---

Without the patch, the output for bad-mapper-3.C would be:

/src/gcc/gcc/testsuite/g++.dg/modules/bad-mapper-3.C:2:1: error: unknown 
Compiled Module Interface: no such module

As this line is unexpected, the test case would fail.
The same problem can also be seen for g++.dg/modules/bad-mapper-2.C.

gcc/cp/ChangeLog:

* mapper-client.cc: Use in-process client when networking is
disabled.

gcc/testsuite/ChangeLog:

* g++.dg/modules/bad-mapper-3.C: Update dg-error pattern.

Tested on Windows with arm-none-eabi for Cortex-M3 in gcc-11 tree.

Co-Authored-By: Yvan ROUX 
Signed-off-by: Torbjörn SVENSSON 
---
  gcc/cp/mapper-client.cc | 4 
  gcc/testsuite/g++.dg/modules/bad-mapper-3.C | 2 +-
  2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/mapper-client.cc b/gcc/cp/mapper-client.cc
index fe9544b5ba4..4dcb3a03660 100644
--- a/gcc/cp/mapper-client.cc
+++ b/gcc/cp/mapper-client.cc
@@ -227,6 +227,8 @@ module_client::open_module_client (location_t loc, const 
char *o,
int fd = -1;
  #if CODY_NETWORKING
fd = Cody::OpenLocal (, name.c_str () + 1);
+#else
+   errmsg = "CODY_NETWORKING disabled";


CODY_NETWORKING is implementor speak. I think just "disabled" is sufficient 
here?


  #endif
if (fd >= 0)
  c = new module_client (fd, fd);
@@ -254,6 +256,8 @@ module_client::open_module_client (location_t loc, const 
char *o,
int fd = -1;
  #if CODY_NETWORKING
fd = Cody::OpenInet6 (, name.c_str (), port);
+#else
+   errmsg = "CODY_NETWORKING disabled";
  #endif
name[colon] = ':';
  
diff --git a/gcc/testsuite/g++.dg/modules/bad-mapper-3.C b/gcc/testsuite/g++.dg/modules/bad-mapper-3.C

index 9dab332ccb2..c91bb4e260c 100644
--- a/gcc/testsuite/g++.dg/modules/bad-mapper-3.C
+++ b/gcc/testsuite/g++.dg/modules/bad-mapper-3.C
@@ -1,6 +1,6 @@
  //  { dg-additional-options "-fmodules-ts 
-fmodule-mapper=localhost:172477262" }
  import unique3.bob;
-// { dg-error {failed connecting mapper 'localhost:172477262'} "" { target 
*-*-* } 0 }
+// { dg-error {failed (connecting|CODY_NETWORKING disabled) mapper 
'localhost:172477262'} "" { target *-*-* } 0 }
  // { dg-prune-output "fatal error:" }
  // { dg-prune-output "failed to read" }
  // { dg-prune-output "compilation terminated" }


--
Nathan Sidwell



c++: per-scope, per-signature lambda discriminators

2022-11-01 Thread Nathan Sidwell via Gcc-patches


This implements ABI-compliant lambda discriminators.  Not only do we
have per-scope counters, but we also distinguish by lambda signature.
Only lambdas with the same signature will need non-zero
discriminators.  As the discriminator is signature-dependent, we have
to process the lambda function's declaration before we can determine
it.  For templated and generic lambdas the signature is that of the
uninstantiated lambda -- not separate for each instantiation.

With this change, gcc and clang now produce the same lambda manglings
for all these testcases.

nathan

--
Nathan SidwellFrom 2b0e81d5cc2f7e1d773f6c502bd65b097f392675 Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Mon, 31 Oct 2022 06:11:28 -0400
Subject: [PATCH] c++: per-scope, per-signature lambda discriminators

This implements ABI-compliant lambda discriminators.  Not only do we
have per-scope counters, but we also distinguish by lambda signature.
Only lambdas with the same signature will need non-zero
discriminators.  As the discriminator is signature-dependent, we have
to process the lambda function's declaration before we can determine
it.  For templated and generic lambdas the signature is that of the
uninstantiated lambda -- not separate for each instantiation.

With this change, gcc and clang now produce the same lambda manglings
for all these testcases.

	gcc/cp/
	* cp-tree.h (LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR): New.
	(struct tree_lambda_expr): Add discriminator_sig bitfield.
	(recrd_lambda_scope_sig_discriminator): Declare.
	* lambda.cc (struct lambda_sig_count): New.
	(lambda_discriminator): Add signature vector.
	(start_lambda_scope): Adjust.
	(compare_lambda_template_head, compare_lambda_sig): New.
	(record_lambda_scope_sig_discriminator): New.
	* mangle.cc (write_closure_type): Use the scope-sig discriminator for
	ABI >= 18.  Emit abi mangling warning if needed.
	* module.cc (trees_out::core_vals): Stream the new discriminator.
	(trees_in::core_vals): Likewise.
	* parser.cc (cp_parser_lambda_declarator_opt): Call
	record_lambda_scope_sig_discriminator.
	* pt.cc (tsubst_lambda_expr): Likewise.
	libcc1/
	* libcp1plugin.cc (plugin_start_lambda_closure_class_type):
	Initialize the per-scope, per-signature discriminator.
	gcc/testsuite/
	* g++.dg/abi/lambda-sig1-18.C: New.
	* g++.dg/abi/lambda-sig1-18vs17.C: New.
	* g++.dg/cpp1y/lambda-mangle-1-18.C: New.
---
 gcc/cp/cp-tree.h  |   7 +-
 gcc/cp/lambda.cc  | 148 +-
 gcc/cp/mangle.cc  |   8 +-
 gcc/cp/module.cc  |   2 +
 gcc/cp/parser.cc  |   1 +
 gcc/cp/pt.cc  |   1 +
 gcc/testsuite/g++.dg/abi/lambda-sig1-18.C |  34 
 gcc/testsuite/g++.dg/abi/lambda-sig1-18vs17.C |  40 +
 .../g++.dg/cpp1y/lambda-mangle-1-18.C |  26 +++
 libcc1/libcp1plugin.cc|   1 +
 10 files changed, 265 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/abi/lambda-sig1-18.C
 create mode 100644 gcc/testsuite/g++.dg/abi/lambda-sig1-18vs17.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-18.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4c0bacb91da..d13bb3d4c0e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1501,9 +1501,12 @@ enum cp_lambda_default_capture_mode_type {
   (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->extra_scope)
 
 /* Lambdas in the same extra scope might need a discriminating count.
-   This is a single per-scope count.  */
+   For ABI 17, we have single per-scope count, for ABI 18, we have
+   per-scope, per-signature numbering.  */
 #define LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR(NODE) \
   (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator_scope)
+#define LAMBDA_EXPR_SCOPE_SIG_DISCRIMINATOR(NODE) \
+  (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator_sig)
 
 /* During parsing of the lambda, a vector of capture proxies which need
to be pushed once we're done processing a nested lambda.  */
@@ -1533,6 +1536,7 @@ struct GTY (()) tree_lambda_expr
   location_t locus;
   enum cp_lambda_default_capture_mode_type default_capture_mode : 2;
   unsigned discriminator_scope : 15; // Per-scope discriminator
+  unsigned discriminator_sig : 15; // Per-scope, per-signature discriminator
 };
 
 /* Non-zero if this template specialization has access violations that
@@ -7783,6 +7787,7 @@ extern void start_lambda_scope			(tree decl);
 extern void finish_lambda_scope			(void);
 extern void record_lambda_scope			(tree lambda);
 extern void record_lambda_scope_discriminator	(tree lambda);
+extern void record_lambda_scope_sig_discriminator (tree lambda, tree fn);
 extern tree start_lambda_function		(tree fn, tree lambda_expr);
 extern void finish_lambda_function		(tree body);
 extern bool regenerated_lambda_fn_p		(tree);
diff --git a/gcc/cp/lambda.cc b/gcc/cp/lam

c++: Reorganize per-scope lambda discriminators

2022-11-01 Thread Nathan Sidwell via Gcc-patches


We currently use a per-extra-scope counter to discriminate multiple
lambdas in a particular such scope.  This is not ABI compliant.  This
patch merely refactors the existing code to make it easier to drop in
a conformant mangling -- there's no functional change here.  I rename
the LAMBDA_EXPR_DISCIMINATOR to LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR,
foreshadowing that there'll be a new discriminator.  To provide ABI
warnings we'll need to calculate both, and that requires some
repacking of the lambda_expr's fields.  Finally, although we end up
calling the discriminator setter and the scope recorder (nearly)
always consecutively, it's clearer to handle it as two separate
operations.  That also allows us to remove the instantiation
special-case for a null extra-scope.

nathan


--
Nathan SidwellFrom 0122faae30fe1ad1dfa8c69f3d3f0428b996b600 Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Mon, 31 Oct 2022 06:11:28 -0400
Subject: [PATCH] c++: Reorganize per-scope lambda discriminators

We currently use a per-extra-scope counter to discriminate multiple
lambdas in a particular such scope.  This is not ABI compliant.  This
patch merely refactors the existing code to make it easier to drop in
a conformant mangling -- there's no functional change here.  I rename
the LAMBDA_EXPR_DISCIMINATOR to LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR,
foreshadowing that there'll be a new discriminator.  To provide ABI
warnings we'll need to calculate both, and that requires some
repacking of the lambda_expr's fields.  Finally, although we end up
calling the discriminator setter and the scope recorder (nearly)
always consecutively, it's clearer to handle it as two separate
operations.  That also allows us to remove the instantiation
special-case for a null extra-scope.

	gcc/cp/
	* cp-tree.h (LAMBDA_EXPR_DISCRIMINATOR): Rename to ...
	(LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR): ... here.
	(struct tree_lambda_expr): Make default_capture_mode &
	discriminator_scope bitfields.
	(record_null_lambda_scope) Delete.
	(record_lambda_scope_discriminator): Declare.
	* lambda.cc (struct lambda_discriminator): New struct.
	(lambda_scope, lambda_scope_stack): Adjust types.
	(lambda_count): Delete.
	(struct tree_int): Delete.
	(start_lambda_scope, finish_lambda_scope): Adjust.
	(record_lambda_scope): Only record the scope.
	(record_lambda_scope_discriminator): New.
	* mangle.cc (write_closure_type_name): Adjust.
	* module.cc (trees_out::core_vals): Likewise,
	(trees_in::core_vals): Likewise.
	* parser.cc (cp_parser_lambda_expression): Call
	record_lambda_scope_discriminator.
	* pt.cc (tsubst_lambda_expr): Adjust record_lambda_scope caling.  Call
	record_lambda_scope_discriminator. Commonize control flow on tsubsting
	the operator function.
	libcc1/
	* libcp1plugin.cc (plugin_start_closure): Adjust.
	gcc/testsuite/
	* g++.dg/abi/lambda-sig1-17.C: New.
	* g++.dg/abi/lambda-sig1.h: New.
	* g++.dg/cpp1y/lambda-mangle-1.C: Extracted to ...
	* g++.dg/cpp1y/lambda-mangle-1.h: ... here.
	* g++.dg/cpp1y/lambda-mangle-1-11.C: New
	* g++.dg/cpp1y/lambda-mangle-1-17.C
---
 gcc/cp/cp-tree.h  |  17 +--
 gcc/cp/lambda.cc  | 114 +-
 gcc/cp/mangle.cc  |   2 +-
 gcc/cp/module.cc  |   4 +-
 gcc/cp/parser.cc  |   5 +-
 gcc/cp/pt.cc  |  50 +++-
 gcc/testsuite/g++.dg/abi/lambda-sig1-17.C |  26 
 gcc/testsuite/g++.dg/abi/lambda-sig1.h|  42 +++
 .../g++.dg/cpp1y/lambda-mangle-1-11.C |  25 
 .../g++.dg/cpp1y/lambda-mangle-1-17.C |  25 
 .../{lambda-mangle-1.C => lambda-mangle-1.h}  |   3 +-
 libcc1/libcp1plugin.cc|   2 +-
 12 files changed, 208 insertions(+), 107 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/abi/lambda-sig1-17.C
 create mode 100644 gcc/testsuite/g++.dg/abi/lambda-sig1.h
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-11.C
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-mangle-1-17.C
 rename gcc/testsuite/g++.dg/cpp1y/{lambda-mangle-1.C => lambda-mangle-1.h} (98%)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 6d84514e4c0..4c0bacb91da 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1500,9 +1500,10 @@ enum cp_lambda_default_capture_mode_type {
 #define LAMBDA_EXPR_EXTRA_SCOPE(NODE) \
   (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->extra_scope)
 
-/* If EXTRA_SCOPE, this is the number of the lambda within that scope.  */
-#define LAMBDA_EXPR_DISCRIMINATOR(NODE) \
-  (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator)
+/* Lambdas in the same extra scope might need a discriminating count.
+   This is a single per-scope count.  */
+#define LAMBDA_EXPR_SCOPE_ONLY_DISCRIMINATOR(NODE) \
+  (((struct tree_lambda_expr *)LAMBDA_EXPR_CHECK (NODE))->discriminator_scope)
 
 /* During parsing of the lambda, a vector of ca

c++: Templated lambda mangling

2022-10-27 Thread Nathan Sidwell via Gcc-patches

(Explicitly) Templated lambdas have a different signature to
implicitly templated lambdas -- '[] (T) {}' is not the
same as '[](auto) {}'.  This should be reflected in the mangling.  The
ABI captures this as
https://github.com/itanium-cxx-abi/cxx-abi/issues/31, and clang has
implemented such additions.

It's relatively straight forwards to write out the non-synthetic
template parms, and note if we need to issue an ABI warning.

I did find a couple of bugs on the way -- one is a failure to parse thhe pack 
expansion in :

  inline auto l_var2 = [] (int (&...)[I]) {}

the other was clang miscounting substitutions, 
https://github.com/llvm/llvm-project/issues/58631, always a good idea to have 
multiple implementations :)


the remaining change to do is lambda sequence numbering, as that is affected by 
lambda signature.


nathan

--
Nathan SidwellFrom bf6e972b65c56c615682f712f785d0f0541ac77b Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Mon, 24 Oct 2022 17:39:55 -0400
Subject: [PATCH] c++: Templated lambda mangling

(Explicitly) Templated lambdas have a different signature to
implicitly templated lambdas -- '[] (T) {}' is not the
same as '[](auto) {}'.  This should be reflected in the mangling.  The
ABI captures this as
https://github.com/itanium-cxx-abi/cxx-abi/issues/31, and clang has
implemented such additions.

It's relatively straight forwards to write out the non-synthetic
template parms, and note if we need to issue an ABI warning.

	gcc/cp/
	* mangle.cc (write_closure_template_head): New.
	(write_closure_type_name): Call it.
	gcc/testsuite/
	* g++.dg/abi/lambda-ctx1-18.C: Adjust.
	* g++.dg/abi/lambda-ctx1-18vs17.C: Adjust.
	* g++.dg/abi/lambda-tpl1-17.C: New.
	* g++.dg/abi/lambda-tpl1-18.C: New.
	* g++.dg/abi/lambda-tpl1-18vs17.C: New.
	* g++.dg/abi/lambda-tpl1.h: New.
---
 gcc/cp/mangle.cc  | 68 +++
 gcc/testsuite/g++.dg/abi/lambda-ctx1-18.C |  4 +-
 gcc/testsuite/g++.dg/abi/lambda-ctx1-18vs17.C |  4 +-
 gcc/testsuite/g++.dg/abi/lambda-tpl1-17.C | 20 ++
 gcc/testsuite/g++.dg/abi/lambda-tpl1-18.C | 25 +++
 gcc/testsuite/g++.dg/abi/lambda-tpl1-18vs17.C | 16 +
 gcc/testsuite/g++.dg/abi/lambda-tpl1.h| 59 
 7 files changed, 192 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/abi/lambda-tpl1-17.C
 create mode 100644 gcc/testsuite/g++.dg/abi/lambda-tpl1-18.C
 create mode 100644 gcc/testsuite/g++.dg/abi/lambda-tpl1-18vs17.C
 create mode 100644 gcc/testsuite/g++.dg/abi/lambda-tpl1.h

diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 1215463089b..e39621876ef 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -1727,6 +1727,66 @@ write_unnamed_type_name (const tree type)
   write_compact_number (discriminator);
 }
 
+// A template head, for templated lambdas.
+//  ::=   Tp* Ty
+//   Tp* Tn 
+//   Tp* Tt  E
+// New in ABI=18. Returns true iff we emitted anything -- used for ABI
+// version warning.
+
+static bool
+write_closure_template_head (tree tmpl)
+{
+  bool any = false;
+
+  // We only need one level of template parms
+  tree inner = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
+
+  for (int ix = 0, len = TREE_VEC_LENGTH (inner); ix != len; ix++)
+{
+  tree parm = TREE_VEC_ELT (inner, ix);
+  if (parm == error_mark_node)
+	continue;
+  parm = TREE_VALUE (parm);
+
+  if (DECL_VIRTUAL_P (parm))
+	// A synthetic parm, we're done.
+	break;
+
+  any = true;
+  if (abi_version_at_least (18))
+	{
+	  if (TREE_CODE (parm) == PARM_DECL
+	  ? TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))
+	  : TEMPLATE_TYPE_PARAMETER_PACK (TREE_TYPE (parm)))
+	write_string ("Tp");
+
+	  switch (TREE_CODE (parm))
+	{
+	default:
+	  gcc_unreachable ();
+
+	case TYPE_DECL:
+	  write_string ("Ty");
+	  break;
+
+	case PARM_DECL:
+	  write_string ("Tn");
+	  write_type (TREE_TYPE (parm));
+	  break;
+
+	case TEMPLATE_DECL:
+	  write_string ("Tt");
+	  write_closure_template_head (parm);
+	  write_string ("E");
+	  break;
+	}
+	}
+}
+
+  return any;
+}
+
 /*  ::= Ul  E [  ] _
 ::= +  # Parameter types or "v" if the lambda has no parameters */
 
@@ -1740,6 +1800,14 @@ write_closure_type_name (const tree type)
   MANGLE_TRACE_TREE ("closure-type-name", type);
 
   write_string ("Ul");
+
+  if (auto ti = maybe_template_info (fn))
+if (write_closure_template_head (TI_TEMPLATE (ti)))
+  // If there were any explicit template parms, we may need to
+  // issue a mangling diagnostic.
+  if (abi_warn_or_compat_version_crosses (18))
+	G.need_abi_warning = true;
+
   write_method_parms (parms, /*method_p=*/1, fn);
   write_char ('E');
   write_compact_number (LAMBDA_EXPR_DISCRIMINATOR (lambda));
diff --git a/gcc/testsuite/g++.dg/abi/lambda-ctx1-18

Re: [PATCH] c++: Fix ICE on g++.dg/modules/adl-3_c.C [PR107379]

2022-10-27 Thread Nathan Sidwell via Gcc-patches

On 10/27/22 04:17, Jakub Jelinek wrote:

Hi!

As mentioned in the PR, apparently my r13-2887 P1467R9 changes
regressed these tests on powerpc64le-linux with IEEE quad by default.

I believe my changes just uncovered a latent bug.
The problem is that push_namespace calls find_namespace_slot,
which does:
   tree *slot = DECL_NAMESPACE_BINDINGS (ns)
 ->find_slot_with_hash (name, name ? IDENTIFIER_HASH_VALUE (name) : 0,
create_p ? INSERT : NO_INSERT);
In the  ns case, slot is non-NULL
above with a binding_vector in it.
Then pushdecl is called and this does:
  slot = find_namespace_slot (ns, name, ns == 
current_namespace);
where ns == current_namespace (ns is :: and name is details) is true.
So this again calls
  tree *slot = DECL_NAMESPACE_BINDINGS (ns)
->find_slot_with_hash (name, name ? IDENTIFIER_HASH_VALUE (name) : 
0,
   create_p ? INSERT : NO_INSERT);
but this time with create_p and so INSERT.
At this point we reach
  if (insert == INSERT && m_size * 3 <= m_n_elements * 4)
expand ();
and when we are unlucky and the occupancy of the hash table just reached 3/4,
expand () is called and the hash table is reallocated.  But when that happens,
it means the slot pointer in the pushdecl caller (push_namespace) points to
freed memory and so any accesses to it in make_namespace_finish will be UB.


that's unfortunate, oh well.


The following patch fixes it by calling find_namespace_slot again even if it
was non-NULL, just doesn't assert it is *slot == ns in that case (because
it often is not).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?


ok. thanks

nathan
--
Nathan Sidwell



c++: Adjust synthetic template parm creation

2022-10-25 Thread Nathan Sidwell via Gcc-patches


We intend to mark synthetic template parameters (coming from use of auto
parms), as DECL_VIRTUAL_P.  The API of process_template_parm is
awkwardly confusing, and we were marking the previous template parm
(unless this was the first parm).  process_template_parm returns the list
of parms, when most (all?) users really want the newly-added final node.
That's a bigger change, so let's not do it right now.  With this, we
correctly mark such synthetic parms DECL_VIRTUAL_P.

I fell over this trying to update template lambda mangling.  The API of 
process_template_parm is somewhat awkaward, as it returns the whole list, and we 
end up doing a lot of tree_last calls, to get to the newly added node.  I think 
all (or nearly all?) uses could be adapted to it returning the newly added list 
node, but I didn't want to go there right now.


nathan

--
Nathan SidwellFrom 43e654afeba484d75fbee080262a038c1da00ad5 Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Tue, 25 Oct 2022 09:39:00 -0400
Subject: [PATCH] c++: Adjust synthetic template parm creation

We intend to mark synthetic template parameters (coming from use of auto
parms), as DECL_VIRTUAL_P.  The API of process_template_parm is
awkwardly confusing, and we were marking the previous template parm
(unless this was the first parm).  process_template_parm returns the list
of parms, when most (all?) users really want the newly-added final node.
That's a bigger change, so let's not do it right now.  With this, we
correctly mark such synthetic parms DECL_VIRTUAL_P.

	gcc/cp/
	* parser.cc (synthesize_implicit_template_parm): Fix thinko about
	mark the new parm DECL_VIRTUAL_P.  Avoid unneccessary tree_last call.
---
 gcc/cp/parser.cc | 26 +++---
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index a39c5f0d24b..e685f190b3d 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -48996,12 +48996,11 @@ synthesize_implicit_template_parm  (cp_parser *parser, tree constr)
 
   tree proto = constr ? DECL_INITIAL (constr) : NULL_TREE;
   tree synth_id = make_generic_type_name ();
-  tree synth_tmpl_parm;
   bool non_type = false;
 
   /* Synthesize the type template parameter.  */
   gcc_assert(!proto || TREE_CODE (proto) == TYPE_DECL);
-  synth_tmpl_parm = finish_template_type_parm (class_type_node, synth_id);
+  tree synth_tmpl_parm = finish_template_type_parm (class_type_node, synth_id);
 
   if (become_template)
 current_template_parms = tree_cons (size_int (current_template_depth + 1),
@@ -49016,22 +49015,27 @@ synthesize_implicit_template_parm  (cp_parser *parser, tree constr)
 			 node,
 			 /*non_type=*/non_type,
 			 /*param_pack=*/false);
+  // Process_template_parm returns the list of parms, and
+  // parser->implicit_template_parms holds the final node of the parm
+  // list.  We really want to manipulate the newly appended element.
+  gcc_checking_assert (!parser->implicit_template_parms
+		   || parser->implicit_template_parms == new_parm);
+  if (parser->implicit_template_parms)
+new_parm = TREE_CHAIN (new_parm);
+  gcc_checking_assert (!TREE_CHAIN (new_parm));
+
+  // Record the last implicit parm node
+  parser->implicit_template_parms = new_parm;
 
   /* Mark the synthetic declaration "virtual". This is used when
  comparing template-heads to determine if whether an abbreviated
  function template is equivalent to an explicit template.
 
- Note that DECL_ARTIFICIAL is used elsewhere for template parameters.  */
+ Note that DECL_ARTIFICIAL is used elsewhere for template
+ parameters.  */
   if (TREE_VALUE (new_parm) != error_mark_node)
 DECL_VIRTUAL_P (TREE_VALUE (new_parm)) = true;
 
-  // Chain the new parameter to the list of implicit parameters.
-  if (parser->implicit_template_parms)
-parser->implicit_template_parms
-  = TREE_CHAIN (parser->implicit_template_parms);
-  else
-parser->implicit_template_parms = new_parm;
-
   tree new_decl = get_local_decls ();
   if (non_type)
 /* Return the TEMPLATE_PARM_INDEX, not the PARM_DECL.  */
@@ -49059,7 +49063,7 @@ synthesize_implicit_template_parm  (cp_parser *parser, tree constr)
 
   /* If the new parameter was constrained, we need to add that to the
  constraints in the template parameter list.  */
-  if (tree req = TEMPLATE_PARM_CONSTRAINTS (tree_last (new_parm)))
+  if (tree req = TEMPLATE_PARM_CONSTRAINTS (new_parm))
 {
   tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
   reqs = combine_constraint_expressions (reqs, req);
-- 
2.37.3



Re: [PATCH] c++ modules: verify_type failure with typedef enum [PR106848]

2022-10-24 Thread Nathan Sidwell via Gcc-patches

On 10/21/22 09:11, Patrick Palka wrote:

On Fri, 21 Oct 2022, Nathan Sidwell wrote:




Thanks for the explanation, it's a situation I didn;t anticipate and your fix
is good.  Could you add a comment about why you need to propagate the values
though?


Thanks a lot, will do.  Just to make sure since there are multiple
solutions proposed, do you prefer to go with
https://gcc.gnu.org/pipermail/gcc-patches/2022-October/603487.html
or
https://gcc.gnu.org/pipermail/gcc-patches/2022-October/603831.html ?

Both solutions fix the PR106848 issue (empty TYPE_MIN/MAX_VALUE on an
enum type variant), but the latter also fixes the related PR102600
(empty TYPE_MIN/MAX_VALUE on the main variant of an enum with no
enumerators).  (We could maybe even combine the two solutions: stream
TYPE_MIN/MAX_VALUE as part of ENUMERAL_TYPE, and also update TYPE_VALUES
of each variant during trees_in::read_enum_def)



Oh, let's go with the latter:

* module.cc (trees_out::core_vals): Stream TYPE_MAX_VALUE and
TYPE_MIN_VALUE of ENUMERAL_TYPE.
(trees_in::core_vals): Likewise.
(trees_out::write_enum_def): Don't stream them here.
(trees_in::read_enum_def): Likewise.

but, again, some comments -- at the new streaming point, and in the defn 
streamer were we no longer stream them.


thanks.





nathan






A somewhat orthogonal issue (that incidentally fixes this testcase) is
that we stream TYPE_MIN/MAX_VALUE only for enums with a definition, but
the frontend sets these fields even for opaque enums.  If we make sure
to stream these fields for all ENUMERAL_TYPEs, then we won't have to
worry about these fields being stale for variants that may have been
created before reading in the enum definition (their TYPE_VALUES field
will still be stale I guess, but verify_type doesn't worry about that
it seems, so we avoid the ICE).

patch to that effect is at
https://gcc.gnu.org/pipermail/gcc-patches/2022-October/603831.html



Richard.



 rest_of_type_compilation (type, DECL_NAMESPACE_SCOPE_P
(defn));
   }
diff --git a/gcc/testsuite/g++.dg/modules/enum-9_a.H
b/gcc/testsuite/g++.dg/modules/enum-9_a.H
new file mode 100644
index 000..fb7d10ad3b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-9_a.H
@@ -0,0 +1,5 @@
+// PR c++/106848
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+typedef enum memory_order { memory_order_seq_cst } memory_order;
diff --git a/gcc/testsuite/g++.dg/modules/enum-9_b.C
b/gcc/testsuite/g++.dg/modules/enum-9_b.C
new file mode 100644
index 000..63e81675d0a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-9_b.C
@@ -0,0 +1,6 @@
+// PR c++/106848
+// { dg-additional-options "-fmodules-ts -g" }
+
+import "enum-9_a.H";
+
+memory_order x = memory_order_seq_cst;
--
2.38.0.68.ge85701b4af













--
Nathan Sidwell






--
Nathan Sidwell



Re: [PATCH] c++ modules: verify_type failure with typedef enum [PR106848]

2022-10-21 Thread Nathan Sidwell via Gcc-patches
es/2022-October/603831.html



Richard.



rest_of_type_compilation (type, DECL_NAMESPACE_SCOPE_P (defn));
  }
diff --git a/gcc/testsuite/g++.dg/modules/enum-9_a.H 
b/gcc/testsuite/g++.dg/modules/enum-9_a.H
new file mode 100644
index 000..fb7d10ad3b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-9_a.H
@@ -0,0 +1,5 @@
+// PR c++/106848
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+typedef enum memory_order { memory_order_seq_cst } memory_order;
diff --git a/gcc/testsuite/g++.dg/modules/enum-9_b.C 
b/gcc/testsuite/g++.dg/modules/enum-9_b.C
new file mode 100644
index 000..63e81675d0a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-9_b.C
@@ -0,0 +1,6 @@
+// PR c++/106848
+// { dg-additional-options "-fmodules-ts -g" }
+
+import "enum-9_a.H";
+
+memory_order x = memory_order_seq_cst;
--
2.38.0.68.ge85701b4af













--
Nathan Sidwell



Re: [PATCH] c++ modules: handle CONCEPT_DECL in node_template_info [PR102963]

2022-10-20 Thread Nathan Sidwell via Gcc-patches

On 10/20/22 10:07, Patrick Palka wrote:

Here node_template_info is overlooking that CONCEPT_DECL has TEMPLATE_INFO
too, which makes get_originating_module_decl for the CONCEPT_DECL fail to
return the corresponding TEMPLATE_DECL, which leads to an ICE from
import_entity_index while pretty printing the CONCEPT_DECL's module
suffix as part of the failed static assert diagnostic.


ok



Tested on x86_64-pc-linux-gnu, does this look OK for trunk?

PR c++/102963

gcc/cp/ChangeLog:

* module.cc (node_template_info): Handle CONCEPT_DECL.

gcc/testsuite/ChangeLog:

* g++.dg/modules/concept-7_a.C: New test.
* g++.dg/modules/concept-7_b.C: New test.
---
  gcc/cp/module.cc   | 3 ++-
  gcc/testsuite/g++.dg/modules/concept-7_a.C | 7 +++
  gcc/testsuite/g++.dg/modules/concept-7_b.C | 7 +++
  3 files changed, 16 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/concept-7_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/concept-7_b.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index bb406a5cf01..dfed0a5ef89 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -4046,7 +4046,8 @@ node_template_info (tree decl, int )
   || TREE_CODE (decl) == TYPE_DECL
   || TREE_CODE (decl) == FUNCTION_DECL
   || TREE_CODE (decl) == FIELD_DECL
-  || TREE_CODE (decl) == TEMPLATE_DECL))
+  || TREE_CODE (decl) == TEMPLATE_DECL
+  || TREE_CODE (decl) == CONCEPT_DECL))
  {
use_tpl = DECL_USE_TEMPLATE (decl);
ti = DECL_TEMPLATE_INFO (decl);
diff --git a/gcc/testsuite/g++.dg/modules/concept-7_a.C 
b/gcc/testsuite/g++.dg/modules/concept-7_a.C
new file mode 100644
index 000..a39b31bf7f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-7_a.C
@@ -0,0 +1,7 @@
+// PR c++/102963
+// { dg-additional-options "-fmodules-ts -fconcepts" }
+// { dg-module-cmi pr102963 }
+
+export module pr102963;
+
+export template concept C = __is_same(T, int);
diff --git a/gcc/testsuite/g++.dg/modules/concept-7_b.C 
b/gcc/testsuite/g++.dg/modules/concept-7_b.C
new file mode 100644
index 000..1f81208ebd5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/concept-7_b.C
@@ -0,0 +1,7 @@
+// PR c++/102963
+// { dg-additional-options "-fmodules-ts -fconcepts" }
+
+import pr102963;
+
+static_assert(C);
+static_assert(C); // { dg-error "static assert" }


--
Nathan Sidwell



Re: [PATCH] c++ modules: stream non-trailing default targs [PR105045]

2022-10-18 Thread Nathan Sidwell via Gcc-patches

On 10/18/22 10:13, Patrick Palka wrote:

This fixes the below testcase in which we neglect to stream the default
argument for T only because the subsequent parameter U doesn't also have
a default argument.


ok



Tested on x86_64-pc-linux-gnu, does this look OK for trunk?

PR c++/105045

gcc/cp/ChangeLog:

* module.cc (trees_out::tpl_parms_fini): Don't assume default
template arguments are all trailing.
(trees_in::tpl_parms_fini): Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr105045_a.C: New test.
* g++.dg/modules/pr105045_b.C: New test.
---
  gcc/cp/module.cc  | 20 ++--
  gcc/testsuite/g++.dg/modules/pr105045_a.C |  7 +++
  gcc/testsuite/g++.dg/modules/pr105045_b.C |  6 ++
  3 files changed, 19 insertions(+), 14 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/pr105045_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/pr105045_b.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 999ff3faafc..2c2f9a9a8cb 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -10034,15 +10034,11 @@ trees_out::tpl_parms_fini (tree tmpl, unsigned 
tpl_levels)
tree vec = TREE_VALUE (parms);
  
tree_node (TREE_TYPE (vec));

-  tree dflt = error_mark_node;
for (unsigned ix = TREE_VEC_LENGTH (vec); ix--;)
{
  tree parm = TREE_VEC_ELT (vec, ix);
- if (dflt)
-   {
- dflt = TREE_PURPOSE (parm);
- tree_node (dflt);
-   }
+ tree dflt = TREE_PURPOSE (parm);
+ tree_node (dflt);
  
  	  if (streaming_p ())

{
@@ -10072,19 +10068,15 @@ trees_in::tpl_parms_fini (tree tmpl, unsigned 
tpl_levels)
 tpl_levels--; parms = TREE_CHAIN (parms))
  {
tree vec = TREE_VALUE (parms);
-  tree dflt = error_mark_node;
  
TREE_TYPE (vec) = tree_node ();

for (unsigned ix = TREE_VEC_LENGTH (vec); ix--;)
{
  tree parm = TREE_VEC_ELT (vec, ix);
- if (dflt)
-   {
- dflt = tree_node ();
- if (get_overrun ())
-   return false;
- TREE_PURPOSE (parm) = dflt;
-   }
+ tree dflt = tree_node ();
+ if (get_overrun ())
+   return false;
+ TREE_PURPOSE (parm) = dflt;
  
  	  tree decl = TREE_VALUE (parm);

  if (TREE_CODE (decl) == TEMPLATE_DECL)
diff --git a/gcc/testsuite/g++.dg/modules/pr105045_a.C 
b/gcc/testsuite/g++.dg/modules/pr105045_a.C
new file mode 100644
index 000..597f9294185
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr105045_a.C
@@ -0,0 +1,7 @@
+// PR c++/105045
+// { dg-additional-options -fmodules-ts }
+// { dg-module-cmi pr105045 }
+
+export module pr105045;
+
+export template void f(U) { }
diff --git a/gcc/testsuite/g++.dg/modules/pr105045_b.C 
b/gcc/testsuite/g++.dg/modules/pr105045_b.C
new file mode 100644
index 000..77c94d4c473
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr105045_b.C
@@ -0,0 +1,6 @@
+// PR c++/105045
+// { dg-additional-options -fmodules-ts }
+
+import pr105045;
+
+int main() { f(0); }


--
Nathan Sidwell



Re: [PATCH] c++ modules: streaming constexpr_fundef [PR101449]

2022-10-15 Thread Nathan Sidwell via Gcc-patches
00..cbf3be4fcab
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/cexpr-3_b.C
@@ -0,0 +1,7 @@
+// PR c++/101449
+// { dg-additional-options -fmodules-ts }
+
+import pr101449;
+
+static_assert(f().b);
+static_assert(g(f()));


--
Nathan Sidwell



Re: [PATCH] c++ modules: ICE with templated friend and std namespace [PR100134]

2022-10-14 Thread Nathan Sidwell via Gcc-patches

On 10/13/22 11:27, Jason Merrill wrote:

On 10/11/22 13:40, Nathan Sidwell wrote:

On 10/11/22 11:35, Patrick Palka wrote:

IIUC the function depset::hash::add_binding_entity has an assert
verifying that if a namespace contains an exported entity, then
the namespace must have been opened in the module purview:

   if (data->hash->add_namespace_entities (decl, data->partitions))
 {
   /* It contains an exported thing, so it is exported.  */
   gcc_checking_assert (DECL_MODULE_PURVIEW_P (decl));
   DECL_MODULE_EXPORT_P (decl) = true;
 }

We're tripping over this assert in the below testcase because by
instantiating and exporting std::A, we end up in turn defining
and exporting the hidden friend std::f without ever having opening
the enclosing namespace std within the module purview and thus
DECL_MODULE_PURVIEW_P (std_node) is false.

Note that it's important that the enclosing namespace is std here: if we
use a different namespace then the ICE disappears.  This probably has
something to do with the fact that we predefine std via push_namespace
from cxx_init_decl_processing (which makes it look like we've opened the
namespace in the TU), whereas with another namespace we would instead
lazily obtain the NAMESPACE_DECL from add_imported_namespace.

Since templated frined functions are special in that they give us a way
to declare a new namespace-scope function without having to explicitly
open the namespace, this patch proposes to fix this issue by propagating
DECL_MODULE_PURVIEW_P from a friend function to the enclosing namespace
when instantiating the friend.


ouch.  This is ok, but I think we have a bug -- what is the module 
ownership of the friend introduced by the instantiation?


Haha, there's a note on 13.7.5/3 -- the attachment is to the same 
module as the befriending class.


That means we end up creating and writing out entities that exist in 
the symbol table (albeit hidden) whose module ownership is neither the 
global module or the tu's module.  That's not something the module 
machinery anticipates. We'll get the mangling wrong for starters. Hmm.


I suspect we're writing out the friend definition, regardless of whether 
the class instantiation is actually referenced from a written-out 
entity.  That's wrong, but it may simply be an inefficiency, rather than 
an error.




These are probably rare.  Thinking about the right solution though ...


This seems closely connected to

  https://cplusplus.github.io/CWG/issues/2588.html



ah, I had gotten myself confused, I don't think there's an ODR[*] 
problem in the std, this is 'just' a horrible surprise.  One of the 
reasons I disliked the (original) TS's cross-module extern declaration. 
Not sure of the spelling, but something like:


extern export other.module int entity ();

was that it had the same requirements as this friend instantiation 
needs.  (this got killed when ATOM ws merged in, and thus never needed 
to be implemented)


[*] The instantiated friend definition is just as temploidy as a 
non-inline member function of the templated class.  And therefore must 
be just as well-formed to have multiple definitions reachable.  Hm, I 
thought that such in-template-class-defined friends could have no other 
declaration, but I cannot find the wording for that.



Tested on x86_64-pc-linux-gnu, does this look like the right fix?  Other
solutions that seem to work are to set DECL_MODULE_PURVIEW_P on std_node
after the fact from declare_module, or simply to suppress the assert for
std_node.

PR c++/100134

gcc/cp/ChangeLog:

* pt.cc (tsubst_friend_function): Propagate DECL_MODULE_PURVIEW_P
from the new declaration to the enclosing namespace scope.

gcc/testsuite/ChangeLog:

* g++.dg/modules/tpl-friend-8_a.H: New test.
* g++.dg/modules/tpl-friend-8_b.C: New test.
---
  gcc/cp/pt.cc  | 7 +++
  gcc/testsuite/g++.dg/modules/tpl-friend-8_a.H | 9 +
  gcc/testsuite/g++.dg/modules/tpl-friend-8_b.C | 8 
  3 files changed, 24 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/modules/tpl-friend-8_a.H
  create mode 100644 gcc/testsuite/g++.dg/modules/tpl-friend-8_b.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 5b9fc588a21..9e3085f3fa6 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -11448,6 +11448,13 @@ tsubst_friend_function (tree decl, tree args)
   by duplicate_decls.  */
    new_friend = old_decl;
  }
+
+  /* We've just added a new namespace-scope entity to the 
purview without
+ necessarily having opened the enclosing namespace, so make sure 
the

+ enclosing namespace is in the purview now too.  */
+  if (TREE_CODE (DECL_CONTEXT (new_friend)) == NAMESPACE_DECL)
+    DECL_MODULE_PURVIEW_P (DECL_CONTEXT (new_friend))
+  |= DECL_MODULE_PURVIEW_P (STRIP_TEMPLATE (new_friend));
  }
    else
  {
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-8_a.H 
b/gcc/testsuite/g++.dg/modules/tpl-friend-8_a.H

Re: [PATCH] c++ modules: ICE with dynamic_cast [PR106304]

2022-10-14 Thread Nathan Sidwell via Gcc-patches

On 10/13/22 15:04, Patrick Palka wrote:

The FUNCTION_DECL we build for __dynamic_cast has an empty DECL_CONTEXT,
but trees_out::tree_node expects all FUNCTION_DECLs to have non-empty
DECL_CONTEXT thus we crash when streaming out the dynamic_cast in the
below testcase.

This patch naively fixes this by setting DECL_CONTEXT for __dynamic_cast
appropriately.  Like for __cxa_atexit which is similarly lazily declared,
I suppose we should push it into the namespace too.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?


This is correct, there were a bunch of similar issues, surprising these 
never triggered.




PR c++/106304

gcc/cp/ChangeLog:

* constexpr.cc (cxx_dynamic_cast_fn_p): Check for abi_node
instead of global_namespace.
* rtti.cc (build_dynamic_cast_1): Set DECL_CONTEXT and
DECL_SOURCE_LOCATION on dynamic_cast_node, and push it
into the namespace.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr106304_a.C: New test.
* g++.dg/modules/pr106304_b.C: New test.
---
  gcc/cp/constexpr.cc   |  2 +-
  gcc/cp/rtti.cc|  4 
  gcc/testsuite/g++.dg/modules/pr106304_a.C | 12 
  gcc/testsuite/g++.dg/modules/pr106304_b.C |  8 
  4 files changed, 25 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/pr106304_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/pr106304_b.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 06dcd71c926..5939d2882f8 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2108,7 +2108,7 @@ cxx_dynamic_cast_fn_p (tree fndecl)
  {
return (cxx_dialect >= cxx20
  && id_equal (DECL_NAME (fndecl), "__dynamic_cast")
- && CP_DECL_CONTEXT (fndecl) == global_namespace);
+ && CP_DECL_CONTEXT (fndecl) == abi_node);
  }
  
  /* Often, we have an expression in the form of address + offset, e.g.

diff --git a/gcc/cp/rtti.cc b/gcc/cp/rtti.cc
index f5b43ec0fb2..a85c7b56409 100644
--- a/gcc/cp/rtti.cc
+++ b/gcc/cp/rtti.cc
@@ -787,6 +787,10 @@ build_dynamic_cast_1 (location_t loc, tree type, tree expr,
   NULL_TREE));
  dcast_fn = (build_library_fn_ptr
  (fn_name, fn_type, ECF_LEAF | ECF_PURE | 
ECF_NOTHROW));
+ /* As with __cxa_atexit in get_atexit_node.  */
+ DECL_CONTEXT (dcast_fn) = FROB_CONTEXT (current_namespace);
+ DECL_SOURCE_LOCATION (dcast_fn) = BUILTINS_LOCATION;
+ dcast_fn = pushdecl (dcast_fn, /*hiding=*/true);
  pop_abi_namespace (flags);
  dynamic_cast_node = dcast_fn;
}
diff --git a/gcc/testsuite/g++.dg/modules/pr106304_a.C 
b/gcc/testsuite/g++.dg/modules/pr106304_a.C
new file mode 100644
index 000..b999eeccf4a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr106304_a.C
@@ -0,0 +1,12 @@
+// PR c++/106304
+// { dg-additional-options -fmodules-ts }
+// { dg-module-cmi pr106304 }
+
+export module pr106304;
+
+struct A { virtual ~A() = default; };
+struct B : A { };
+
+inline const B* as_b(const A& a) {
+  return dynamic_cast();
+}
diff --git a/gcc/testsuite/g++.dg/modules/pr106304_b.C 
b/gcc/testsuite/g++.dg/modules/pr106304_b.C
new file mode 100644
index 000..e8333909c8d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr106304_b.C
@@ -0,0 +1,8 @@
+// PR c++/106304
+// { dg-additional-options -fmodules-ts }
+
+module pr106304;
+
+void f(A& a) {
+  as_b(a);
+}


--
Nathan Sidwell



Re: [PATCH] c++ modules: ICE with templated friend and std namespace [PR100134]

2022-10-11 Thread Nathan Sidwell via Gcc-patches

On 10/11/22 11:35, Patrick Palka wrote:

IIUC the function depset::hash::add_binding_entity has an assert
verifying that if a namespace contains an exported entity, then
the namespace must have been opened in the module purview:

   if (data->hash->add_namespace_entities (decl, data->partitions))
 {
   /* It contains an exported thing, so it is exported.  */
   gcc_checking_assert (DECL_MODULE_PURVIEW_P (decl));
   DECL_MODULE_EXPORT_P (decl) = true;
 }

We're tripping over this assert in the below testcase because by
instantiating and exporting std::A, we end up in turn defining
and exporting the hidden friend std::f without ever having opening
the enclosing namespace std within the module purview and thus
DECL_MODULE_PURVIEW_P (std_node) is false.

Note that it's important that the enclosing namespace is std here: if we
use a different namespace then the ICE disappears.  This probably has
something to do with the fact that we predefine std via push_namespace
from cxx_init_decl_processing (which makes it look like we've opened the
namespace in the TU), whereas with another namespace we would instead
lazily obtain the NAMESPACE_DECL from add_imported_namespace.

Since templated frined functions are special in that they give us a way
to declare a new namespace-scope function without having to explicitly
open the namespace, this patch proposes to fix this issue by propagating
DECL_MODULE_PURVIEW_P from a friend function to the enclosing namespace
when instantiating the friend.


ouch.  This is ok, but I think we have a bug -- what is the module 
ownership of the friend introduced by the instantiation?


Haha, there's a note on 13.7.5/3 -- the attachment is to the same module 
as the befriending class.


That means we end up creating and writing out entities that exist in the 
symbol table (albeit hidden) whose module ownership is neither the 
global module or the tu's module.  That's not something the module 
machinery anticipates. We'll get the mangling wrong for starters. Hmm.


These are probably rare.  Thinking about the right solution though ...

nathan




Tested on x86_64-pc-linux-gnu, does this look like the right fix?  Other
solutions that seem to work are to set DECL_MODULE_PURVIEW_P on std_node
after the fact from declare_module, or simply to suppress the assert for
std_node.

PR c++/100134

gcc/cp/ChangeLog:

* pt.cc (tsubst_friend_function): Propagate DECL_MODULE_PURVIEW_P
from the new declaration to the enclosing namespace scope.

gcc/testsuite/ChangeLog:

* g++.dg/modules/tpl-friend-8_a.H: New test.
* g++.dg/modules/tpl-friend-8_b.C: New test.
---
  gcc/cp/pt.cc  | 7 +++
  gcc/testsuite/g++.dg/modules/tpl-friend-8_a.H | 9 +
  gcc/testsuite/g++.dg/modules/tpl-friend-8_b.C | 8 
  3 files changed, 24 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/modules/tpl-friend-8_a.H
  create mode 100644 gcc/testsuite/g++.dg/modules/tpl-friend-8_b.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 5b9fc588a21..9e3085f3fa6 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -11448,6 +11448,13 @@ tsubst_friend_function (tree decl, tree args)
 by duplicate_decls.  */
  new_friend = old_decl;
}
+
+  /* We've just added a new namespace-scope entity to the purview without
+necessarily having opened the enclosing namespace, so make sure the
+enclosing namespace is in the purview now too.  */
+  if (TREE_CODE (DECL_CONTEXT (new_friend)) == NAMESPACE_DECL)
+   DECL_MODULE_PURVIEW_P (DECL_CONTEXT (new_friend))
+ |= DECL_MODULE_PURVIEW_P (STRIP_TEMPLATE (new_friend));
  }
else
  {
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-8_a.H 
b/gcc/testsuite/g++.dg/modules/tpl-friend-8_a.H
new file mode 100644
index 000..bd2290460b5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-8_a.H
@@ -0,0 +1,9 @@
+// PR c++/100134
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+namespace std {
+  template struct A {
+friend void f(A) { }
+  };
+}
diff --git a/gcc/testsuite/g++.dg/modules/tpl-friend-8_b.C 
b/gcc/testsuite/g++.dg/modules/tpl-friend-8_b.C
new file mode 100644
index 000..76d7447c2eb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/tpl-friend-8_b.C
@@ -0,0 +1,8 @@
+// PR c++/100134
+// { dg-additional-options -fmodules-ts }
+// { dg-module-cmi pr100134 }
+export module pr100134;
+
+import "tpl-friend-8_a.H";
+
+export std::A a;


--
Nathan Sidwell



Re: [PATCH] c++ modules: lazy loading from within template [PR99377]

2022-10-11 Thread Nathan Sidwell via Gcc-patches

On 10/11/22 10:58, Patrick Palka wrote:

On Mon, 10 Oct 2022, Nathan Sidwell wrote:


On 10/4/22 13:36, Patrick Palka wrote:

Here when lazily loading the binding for f at parse time from the
template g, processing_template_decl is set and thus the call to
note_vague_linkage_fn from module_state::read_cluster has no effect,
and we never push f onto deferred_fns and end up never emitting its
definition.

ISTM the behavior of the lazy loading machinery shouldn't be sensitive
to whether we're inside a template, and therefore we should probably be
clearing processing_template_decl somewhere e.g in lazy_load_binding.
This is sufficient to fix the testcase.


yeah, I remember hitting issues with this, but thought I'd got rid of the need
to override processing_template_decl.  Do you also need to override it in
lazy_load_pendings though? that's a lazy loader and my suspicion is it might
be susceptible to the same issues.


Hmm yeah, looks like we need to override it in lazy_load_pendings too:
I ran the testsuite with gcc_assert (!processing_template_decl) added to
module_state::read_cluster and if we don't also override it in
lazy_load_binding then the assert triggers for pr99425-2_b.X.





But it also seems the processing_template_decl test in
note_vague_linkage_fn, added by r8-7539-g977bc3ee11383e for PR84973, is
perhaps too strong: if the intent is to avoid deferring output for
uninstantiated templates, we should make sure that DECL in question is
an uninstantiated template by checking e.g. value_dependent_expression_p.
This too is sufficient to fix the testcase (since f isn't a template)
and survives bootstrap and regtest.


I think this is an orthogonal issue -- can we remove it from this patch?


Done.

-- >8 --

Subject: [PATCH] c++ modules: lazy loading from within template [PR99377]

Here when lazily loading the binding for f at parse time from the
template g, processing_template_decl is set and thus the call to
note_vague_linkage_fn from module_state::read_cluster has no effect,
and we never push f onto deferred_fns and end up never emitting its
definition.

ISTM the behavior of the lazy loading machinery shouldn't be sensitive
to whether we're inside a template, and therefore we should be clearing
processing_template_decl in the entrypoints lazy_load_binding and
lazy_load_pendings.

PR c++/99377

gcc/cp/ChangeLog:

* module.cc (lazy_load_binding): Clear processing_template_decl.
(lazy_load_pendings): Likewise.


ok, thanks



gcc/testsuite/ChangeLog:

* g++.dg/modules/pr99377-2_a.C: New test.
* g++.dg/modules/pr99377-2_b.C: New test.
---
  gcc/cp/module.cc   | 8 
  gcc/testsuite/g++.dg/modules/pr99377-2_a.C | 5 +
  gcc/testsuite/g++.dg/modules/pr99377-2_b.C | 6 ++
  3 files changed, 19 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/modules/pr99377-2_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/pr99377-2_b.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 94fbee85225..7c48602136c 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -19081,6 +19081,10 @@ lazy_load_binding (unsigned mod, tree ns, tree id, 
binding_slot *mslot)
  
timevar_start (TV_MODULE_IMPORT);
  
+  /* Make sure lazy loading from a template context behaves as if

+ from a non-template context.  */
+  processing_template_decl_sentinel ptds;
+
/* Stop GC happening, even in outermost loads (because our caller
   could well be building up a lookup set).  */
function_depth++;
@@ -19129,6 +19133,10 @@ lazy_load_binding (unsigned mod, tree ns, tree id, 
binding_slot *mslot)
  void
  lazy_load_pendings (tree decl)
  {
+  /* Make sure lazy loading from a template context behaves as if
+ from a non-template context.  */
+  processing_template_decl_sentinel ptds;
+
tree key_decl;
pending_key key;
key.ns = find_pending_key (decl, _decl);
diff --git a/gcc/testsuite/g++.dg/modules/pr99377-2_a.C 
b/gcc/testsuite/g++.dg/modules/pr99377-2_a.C
new file mode 100644
index 000..26e2bccbbbe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr99377-2_a.C
@@ -0,0 +1,5 @@
+// PR c++/99377
+// { dg-additional-options -fmodules-ts }
+// { dg-module-cmi pr99377 }
+export module pr99377;
+export inline void f() { }
diff --git a/gcc/testsuite/g++.dg/modules/pr99377-2_b.C 
b/gcc/testsuite/g++.dg/modules/pr99377-2_b.C
new file mode 100644
index 000..69571952c8a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr99377-2_b.C
@@ -0,0 +1,6 @@
+// PR c++/99377
+// { dg-additional-options -fmodules-ts }
+// { dg-do link }
+import pr99377;
+template void g() { f(); }
+int main() { g(); }


--
Nathan Sidwell



libiberty: Demangling 'M' prefixes

2022-10-11 Thread Nathan Sidwell via Gcc-patches


The grammar for a lambda context can include  'M', and we
were adding the component that generated to the substitution table
twice.  Just ignore the 'M' completely -- we'll already have done the
checks we need when we saw its predecessor.  A prefix cannot be the
last component of a nested name, so we do not need to check for that
case (although we could if we wanted to be more lenient).

nathan

--
Nathan SidwellFrom 0fa35c7e2974a22b2107fa378895c3069fe07ff3 Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Fri, 30 Sep 2022 09:43:30 -0700
Subject: [PATCH] libiberty: Demangling 'M' prefixes

The grammar for a lambda context can include  'M', and we
were adding the component that generated to the substitution table
twice.  Just ignore the 'M' completely -- we'll already have done the
checks we need when we saw its predecessor.  A prefix cannot be the
last component of a nested name, so we do not need to check for that
case (although we could if we wanted to be more lenient).

	libiberty/
	* cp-demangle.c (d_prefix): 'M' components are not
	(re-)added to the substitution table.
	* testsuite/demangle-expected: Add tests.
---
 libiberty/cp-demangle.c   |  8 +++-
 libiberty/testsuite/demangle-expected | 21 +
 2 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 303bfbf709e..4beb4d257bb 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -1609,12 +1609,10 @@ d_prefix (struct d_info *di, int substable)
 	}
   else if (peek == 'M')
 	{
-	  /* Initializer scope for a lambda.  We don't need to represent
-	 this; the normal code will just treat the variable as a type
-	 scope, which gives appropriate output.  */
-	  if (ret == NULL)
-	return NULL;
+	  /* Initializer scope for a lambda.  We already added it as a
+  	 substitution candidate, don't do that again.  */
 	  d_advance (di, 1);
+	  continue;
 	}
   else
 	{
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 90dd4a13945..bd92b12076b 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -1581,3 +1581,24 @@ void L1()::{lambda((auto:1)...)#1}::operator()(int, int*) const
 _ZZ2L1vENKUlDpT_E_clIJiPiEEEDaS0_
 auto L1()::{lambda((auto:1)...)#1}::operator()(int, int*) const
 
+_Z7captureIN4gvarMUlvE_EE7WrapperIT_EOS3_
+Wrapper capture(gvar::{lambda()#1}&&)
+
+_ZNK2L2MUlT_T0_E_clIifEEvS_S0_
+void L2::{lambda(auto:1, auto:2)#1}::operator()(L2, int) const
+
+_ZNK1C1fMUlT_E_clIMS_iEEDaS1_
+auto C::f::{lambda(auto:1)#1}::operator()(int C::*) const
+
+_ZNK2L2MUlT_T0_E_clIifEEvS0_S1_
+void L2::{lambda(auto:1, auto:2)#1}::operator()(int, float) const
+
+_ZNK1B2L3MUlT_T0_E_clIjdEEvS1_S2_
+void B::L3::{lambda(auto:1, auto:2)#1}::operator()(unsigned int, double) const
+
+_Z3fooIN1qMUlvE_ENS0_UlvE0_EEiOT_OT0_
+int foo(q::{lambda()#1}&&, q::{lambda()#2}&&)
+
+_ZNK2L1MUlDpT_E_clIJiPiEEEvS1_
+void L1::{lambda((auto:1)...)#1}::operator()(int, int*) const
+
-- 
2.30.2



Re: [PATCH] c++ modules: lazy loading from within template [PR99377]

2022-10-10 Thread Nathan Sidwell via Gcc-patches

On 10/4/22 13:36, Patrick Palka wrote:

Here when lazily loading the binding for f at parse time from the
template g, processing_template_decl is set and thus the call to
note_vague_linkage_fn from module_state::read_cluster has no effect,
and we never push f onto deferred_fns and end up never emitting its
definition.

ISTM the behavior of the lazy loading machinery shouldn't be sensitive
to whether we're inside a template, and therefore we should probably be
clearing processing_template_decl somewhere e.g in lazy_load_binding.
This is sufficient to fix the testcase.


yeah, I remember hitting issues with this, but thought I'd got rid of the need 
to override processing_template_decl.  Do you also need to override it in 
lazy_load_pendings though? that's a lazy loader and my suspicion is it might be 
susceptible to the same issues.




But it also seems the processing_template_decl test in
note_vague_linkage_fn, added by r8-7539-g977bc3ee11383e for PR84973, is
perhaps too strong: if the intent is to avoid deferring output for
uninstantiated templates, we should make sure that DECL in question is
an uninstantiated template by checking e.g. value_dependent_expression_p.
This too is sufficient to fix the testcase (since f isn't a template)
and survives bootstrap and regtest.


I think this is an orthogonal issue -- can we remove it from this patch?




Does one or the other approach look like the correct fix for this PR?

PR c++/99377

gcc/cp/ChangeLog:

* decl2.cc (note_vague_linkage_fn): Relax processing_template_decl
test to value_dependent_expression_p.
* module.cc (lazy_load_binding): Clear processing_template_decl.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr99377-2_a.C: New test.
* g++.dg/modules/pr99377-2_b.C: New test.
---
  gcc/cp/decl2.cc| 2 +-
  gcc/cp/module.cc   | 2 ++
  gcc/testsuite/g++.dg/modules/pr99377-2_a.C | 5 +
  gcc/testsuite/g++.dg/modules/pr99377-2_b.C | 6 ++
  4 files changed, 14 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/pr99377-2_a.C
  create mode 100644 gcc/testsuite/g++.dg/modules/pr99377-2_b.C

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 9f18466192f..5af4d17ee3b 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -876,7 +876,7 @@ check_classfn (tree ctype, tree function, tree 
template_parms)
  void
  note_vague_linkage_fn (tree decl)
  {
-  if (processing_template_decl)
+  if (value_dependent_expression_p (decl))
  return;
  
DECL_DEFER_OUTPUT (decl) = 1;

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 500ac06563a..79cbb346ffa 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -19074,6 +19074,8 @@ lazy_load_binding (unsigned mod, tree ns, tree id, 
binding_slot *mslot)
  
timevar_start (TV_MODULE_IMPORT);
  
+  processing_template_decl_sentinel ptds;

+
/* Stop GC happening, even in outermost loads (because our caller
   could well be building up a lookup set).  */
function_depth++;
diff --git a/gcc/testsuite/g++.dg/modules/pr99377-2_a.C 
b/gcc/testsuite/g++.dg/modules/pr99377-2_a.C
new file mode 100644
index 000..26e2bccbbbe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr99377-2_a.C
@@ -0,0 +1,5 @@
+// PR c++/99377
+// { dg-additional-options -fmodules-ts }
+// { dg-module-cmi pr99377 }
+export module pr99377;
+export inline void f() { }
diff --git a/gcc/testsuite/g++.dg/modules/pr99377-2_b.C 
b/gcc/testsuite/g++.dg/modules/pr99377-2_b.C
new file mode 100644
index 000..69571952c8a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr99377-2_b.C
@@ -0,0 +1,6 @@
+// PR c++/99377
+// { dg-additional-options -fmodules-ts }
+// { dg-do link }
+import pr99377;
+template void g() { f(); }
+int main() { g(); }


--
Nathan Sidwell



Re: [PATCH] c++ modules: ICE with bitfield member in class template

2022-10-07 Thread Nathan Sidwell via Gcc-patches

On 10/7/22 11:09, Patrick Palka wrote:

According to grokbitfield, DECL_BITFIELD_REPRESENTATIVE may "temporarily"
contain the width of the bitfield until we layout the class type (after
which it'll contain a FIELD_DECL).  But for a class template, it'll always
be the width since we don't/can't layout dependent types.

Tested on x86_64-pc-linux-gnu, does this look OK for trunk?


ok, but could you add a comment on why it might not be a decl?




gcc/cp/ChangeLog:

* module.cc (trees_out::mark_class_def): Guard against
DECL_BITFIELD_REPRESENTATIVE not being a decl.

gcc/testsuite/ChangeLog:

* g++.dg/modules/bfield-3.H: New test.
---
  gcc/cp/module.cc| 3 ++-
  gcc/testsuite/g++.dg/modules/bfield-3.H | 8 
  2 files changed, 10 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/bfield-3.H

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index cb1929bc5d5..172a72e92b9 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -11919,7 +11919,8 @@ trees_out::mark_class_def (tree defn)
mark_class_member (member);
if (TREE_CODE (member) == FIELD_DECL)
  if (tree repr = DECL_BIT_FIELD_REPRESENTATIVE (member))
-   mark_declaration (repr, false);
+   if (DECL_P (repr))
+ mark_declaration (repr, false);
}
  
/* Mark the binfo hierarchy.  */

diff --git a/gcc/testsuite/g++.dg/modules/bfield-3.H 
b/gcc/testsuite/g++.dg/modules/bfield-3.H
new file mode 100644
index 000..4fd4db7116a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/bfield-3.H
@@ -0,0 +1,8 @@
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template
+struct A {
+  int x : 1;
+  int y : N;
+};


--
Nathan Sidwell



libiberty: Demangle variadic template lambdas

2022-10-07 Thread Nathan Sidwell via Gcc-patches

Now we have templated lambdas, we can have variadic template lambdas,
and this leads to lambda signatures containing parameter packs.  But
just like 'auto' inside such a signature, we don't have a containing
template, and thus fail.  The fix is to check is_lambda_arg, just as
for a template parameter.  This allows us to demangle g++'s manglings
of such lambdas.

It's not a totally accurate demangling, because we don't mangle the
template head (that's a separate issue), but it is better than failing
to demangle.

Due to the way we print subexprs, we add an unnecessary parens around
the argument of the pack.  That's an orthogonal problem, for which the
solution is to have better knowledge of operator precedence.

nathan
--
Nathan SidwellFrom 55bd808527e8c1947cf2d2b42769528087b687ef Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Fri, 30 Sep 2022 12:11:42 -0700
Subject: [PATCH] libiberty: Demangle variadic template lambdas

Now we have templated lambdas, we can have variadic template lambdas,
and this leads to lambda signatures containing parameter packs.  But
just like 'auto' inside such a signature, we don't have a containing
template, and thus fail.  The fix is to check is_lambda_arg, just as
for a template parameter.  This allows us to demangle g++'s manglings
of such lambdas.

It's not a totally accurate demangling, because we don't mangle the
template head (that's a separate issue), but it is better than failing
to demangle.

Due to the way we print subexprs, we add an unnecessary parens around
the argument of the pack.  That's an orthogonal problem, for which the
solution is to have better knowledge of operator precedence.

	libiberty/
	* cp-demangle.c (d_print_comp_inner): Allow parameter packs
	in a lambda signature.
	* testsuite/demangle-expected: Add tests.
---
 libiberty/cp-demangle.c   | 30 +++
 libiberty/testsuite/demangle-expected |  7 +++
 2 files changed, 24 insertions(+), 13 deletions(-)

diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
index 7ff225ec1aa..303bfbf709e 100644
--- a/libiberty/cp-demangle.c
+++ b/libiberty/cp-demangle.c
@@ -348,7 +348,7 @@ struct d_print_info
  be bigger than MAX_RECURSION_COUNT.  */
   int recursion;
   /* Non-zero if we're printing a lambda argument.  A template
- parameter reference actually means 'auto'.  */
+ parameter reference actually means 'auto', a pack expansion means T...  */
   int is_lambda_arg;
   /* The current index into any template argument packs we are using
  for printing, or -1 to print the whole pack.  */
@@ -5930,9 +5930,10 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
 
 case DEMANGLE_COMPONENT_PACK_EXPANSION:
   {
-	int len;
-	int i;
-	struct demangle_component *a = d_find_pack (dpi, d_left (dc));
+	struct demangle_component *a = NULL;
+
+	if (!dpi->is_lambda_arg)
+	  a = d_find_pack (dpi, d_left (dc));
 	if (a == NULL)
 	  {
 	/* d_find_pack won't find anything if the only packs involved
@@ -5940,17 +5941,20 @@ d_print_comp_inner (struct d_print_info *dpi, int options,
 	   case, just print the pattern and "...".  */
 	d_print_subexpr (dpi, options, d_left (dc));
 	d_append_string (dpi, "...");
-	return;
 	  }
-
-	len = d_pack_length (a);
-	dc = d_left (dc);
-	for (i = 0; i < len; ++i)
+	else
 	  {
-	dpi->pack_index = i;
-	d_print_comp (dpi, options, dc);
-	if (i < len-1)
-	  d_append_string (dpi, ", ");
+	int len = d_pack_length (a);
+	int i;
+
+	dc = d_left (dc);
+	for (i = 0; i < len; ++i)
+	  {
+		if (i)
+		  d_append_string (dpi, ", ");
+		dpi->pack_index = i;
+		d_print_comp (dpi, options, dc);
+	  }
 	  }
   }
   return;
diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected
index 8fad6893ae7..90dd4a13945 100644
--- a/libiberty/testsuite/demangle-expected
+++ b/libiberty/testsuite/demangle-expected
@@ -1574,3 +1574,10 @@ initializer for module Foo.Bar
 
 _ZGIW3FooWP3BarW3Baz
 initializer for module Foo:Bar.Baz
+
+_ZZ2L1vENKUlDpT_E_clIJiPiEEEvS0_
+void L1()::{lambda((auto:1)...)#1}::operator()(int, int*) const
+
+_ZZ2L1vENKUlDpT_E_clIJiPiEEEDaS0_
+auto L1()::{lambda((auto:1)...)#1}::operator()(int, int*) const
+
-- 
2.30.2



c++: Lambda context mangling

2022-10-07 Thread Nathan Sidwell via Gcc-patches

VAR and FIELD decls can become part of a lambda context, when the
lambda is 'attached' to that entity (It's a C++20 ODR thing that was
discovered with modules, but is actually separate.)  We were not
marking those decls as substitution candidates, leading to demangling
failures and compiler variance.

The alternative I chose is to bump the ABI, and add them to the
substitution table.  I think this is the intent of the ABI.

The other alternative would be for the demangler to pop off the most
recent substitution when it saw the 'M'.  But we'd have to change [at
least] the libiberty demangler[*] and the clang demangler and the clang
mangler, which seems a bigger challenge.

I'll commit this next week, unless y'all have comments.

We have other divergence from clang, with templated lambdas.  Clang 
added new manglings [Ty, Tn, Tt] for the lambda's template head (Richard 
has a pull request, but it's not merged 
https://github.com/itanium-cxx-abi/cxx-abi/issues/31).  Without that, we 
consider all the template args to be auto when demangling (which is 
going to look odd for non-type template args).  This divergence in 
signature also affects the lambda numbering, as gcc & clang differ in 
their opinions about 'same lamda signature'.   thoughts on addressing 
that to in this cycle?


I have some demangler fixes coming up.

nathan

[*] the demangler already seems to have a bug with 'M' handling.

--
Nathan SidwellFrom 6e943ec67fbe1f2bd09325eb6a2dc6405edfc00f Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Fri, 30 Sep 2022 08:43:10 -0700
Subject: [PATCH 1/3] c++: Lambda context mangling

VAR and FIELD decls can become part of a lambda context, when the
lambda is 'attached' to that entity (It's a C++20 ODR thing that was
discovered with modules, but is actually separate.)  We were not
marking those decls as substitution candidates, leading to demangling
failures and variance from other compilers.

The alternative I chose is to bump the ABI, and add them to the
substitution table.  I think this is the intent of the ABI.

The othe alternative would be for the demangler to pop off the most
recent substitition when it saw the 'M'.  But we'd have to change [at
least] the libiberty demangler and the clang demangler and the clang
mangler, which seems a bigger challenge.

	gcc/
	* common.opt (-fabi-version=): Document 18.
	* doc/invoke.texi (-fabi-version): Document 18.
	gcc/c-family/
	* c-opts.cc (c_common_post_options): Bump abi to 18.
	gcc/cp/
	* mangle.cc (write_prefix): Add VAR_DECL & FIELD_DECL to
	substitution table under abi=18.  Note possible mismatch.
	gcc/testsuite/
	* g++.dg/abi/lambda-ctx1-17.C: New.
	* g++.dg/abi/lambda-ctx1-18.C: New.
	* g++.dg/abi/lambda-ctx1-18vs17.C: New.
	* g++.dg/abi/lambda-ctx1.h: New.
	* g++.dg/abi/lambda-vis.C: Adjust expected mangles.
	* g++.dg/abi/macro0.C: Adjust.
---
 gcc/c-family/c-opts.cc|  2 +-
 gcc/common.opt|  3 +++
 gcc/cp/mangle.cc  |  9 -
 gcc/doc/invoke.texi   |  3 +++
 gcc/testsuite/g++.dg/abi/lambda-ctx1-17.C | 10 ++
 gcc/testsuite/g++.dg/abi/lambda-ctx1-18.C | 11 ++
 gcc/testsuite/g++.dg/abi/lambda-ctx1-18vs17.C |  9 +
 gcc/testsuite/g++.dg/abi/lambda-ctx1.h| 20 +++
 gcc/testsuite/g++.dg/abi/lambda-vis.C |  8 +---
 gcc/testsuite/g++.dg/abi/macro0.C |  2 +-
 10 files changed, 71 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/abi/lambda-ctx1-17.C
 create mode 100644 gcc/testsuite/g++.dg/abi/lambda-ctx1-18.C
 create mode 100644 gcc/testsuite/g++.dg/abi/lambda-ctx1-18vs17.C
 create mode 100644 gcc/testsuite/g++.dg/abi/lambda-ctx1.h

diff --git a/gcc/c-family/c-opts.cc b/gcc/c-family/c-opts.cc
index babaa2fc157..55cebf68f9c 100644
--- a/gcc/c-family/c-opts.cc
+++ b/gcc/c-family/c-opts.cc
@@ -975,7 +975,7 @@ c_common_post_options (const char **pfilename)
 
   /* Change flag_abi_version to be the actual current ABI level, for the
  benefit of c_cpp_builtins, and to make comparison simpler.  */
-  const int latest_abi_version = 17;
+  const int latest_abi_version = 18;
   /* Generate compatibility aliases for ABI v13 (8.2) by default.  */
   const int abi_compat_default = 13;
 
diff --git a/gcc/common.opt b/gcc/common.opt
index 58dc1a0a780..c65efeeb8fc 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1004,6 +1004,9 @@ Driver Undocumented
 ; member initializers in C++14 and up.
 ; Default in G++ 12.
 ;
+; 18: Corrects errors in mangling of lambdas with additional context.
+; Default in G++ 13.
+;
 ; Additional positive integers will be assigned as new versions of
 ; the ABI become the default version of the ABI.
 fabi-version=
diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index f051e76466a..1215463089b 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -1252,7 +1252,14 @@ write_prefix (const tree node)
 	{
 	  /

Re: [PATCH] c++ modules: static var in inline function [PR104433]

2022-10-07 Thread Nathan Sidwell via Gcc-patches

On 10/6/22 12:19, Patrick Palka wrote:

The below testcase fails to link with the error

   undefined reference to `f()::y'

ultimately because during stream out for the static VAR_DECL y we
override DECL_EXTERNAL to true, which later during IPA confuses
symbol_table::remove_unreachable_nodes into thinking it's safe
to not emit the symbol.

The streaming code in question already avoids overriding DECL_EXTERNAL
here for DECL_VAR_DECLARED_INLINE_P vars, so it seems natural to do the
same for static vars from an DECL_DECLARED_INLINE_P function scope.

After this patch (and r13-3134-g09df0d8b14dda6), the following now
links:

   import ;
   int main() { std::make_shared(); }

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?


yeah, that's correct -- these are just as inline



PR c++/104433

gcc/cp/ChangeLog:

* module.cc (trees_out::core_bools): Don't override
DECL_EXTERNAL to true for static variables from an inline
function.

gcc/testsuite/ChangeLog:

* g++.dg/modules/static-2_a.H: New test.
* g++.dg/modules/static-2_b.C: New test.
---
  gcc/cp/module.cc  | 3 +++
  gcc/testsuite/g++.dg/modules/static-2_a.H | 8 
  gcc/testsuite/g++.dg/modules/static-2_b.C | 9 +
  3 files changed, 20 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/modules/static-2_a.H
  create mode 100644 gcc/testsuite/g++.dg/modules/static-2_b.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 79cbb346ffa..11f68794cd2 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -5397,6 +5397,9 @@ trees_out::core_bools (tree t)
  
  	case VAR_DECL:

  if (TREE_PUBLIC (t)
+ && !(TREE_STATIC (t)
+  && DECL_FUNCTION_SCOPE_P (t)
+  && DECL_DECLARED_INLINE_P (DECL_CONTEXT (t)))
  && !DECL_VAR_DECLARED_INLINE_P (t))
is_external = true;
  break;
diff --git a/gcc/testsuite/g++.dg/modules/static-2_a.H 
b/gcc/testsuite/g++.dg/modules/static-2_a.H
new file mode 100644
index 000..b4546932a12
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/static-2_a.H
@@ -0,0 +1,8 @@
+// PR c++/104433
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+inline int* f() {
+  static int y = 0;
+  return 
+}
diff --git a/gcc/testsuite/g++.dg/modules/static-2_b.C 
b/gcc/testsuite/g++.dg/modules/static-2_b.C
new file mode 100644
index 000..bfd35b0fc15
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/static-2_b.C
@@ -0,0 +1,9 @@
+// PR c++/104433
+// { dg-additional-options -fmodules-ts }
+// { dg-do link }
+
+import "static-2_a.H";
+
+int main() {
+  f();
+}


--
Nathan Sidwell



Re: C++ ABI

2022-09-30 Thread Nathan Sidwell via Gcc-patches

On 9/30/22 09:43, Nathan Sidwell wrote:

Hi,
I've discovered some mangling problems with lambdas.  (a) divergence 
from clang and (b) manglings that incorrectly demangle.  With #a I'm not 
yet sure who is correct.  for #b g++ is definitely wrong.


 From the docs, it doesn't appear to have been bumped this cycle.  Is 
that correct, and I should bump it to 18?


oops, 'it' == -fabi-version

nathan

--
Nathan Sidwell



C++ ABI

2022-09-30 Thread Nathan Sidwell via Gcc-patches

Hi,
I've discovered some mangling problems with lambdas.  (a) divergence 
from clang and (b) manglings that incorrectly demangle.  With #a I'm not 
yet sure who is correct.  for #b g++ is definitely wrong.


From the docs, it doesn't appear to have been bumped this cycle.  Is 
that correct, and I should bump it to 18?


nathan
--
Nathan Sidwell


Re: [PATCH] testsuite: Colon is reserved on Windows

2022-09-30 Thread Nathan Sidwell via Gcc-patches

On 9/30/22 04:18, Torbjörn SVENSSON wrote:

The ':' is reserved in filenames on Windows.
Can't find any specification for this, but when there is no filename
defined in the map file, GCC will replace the ':' with a '-' in the
generated filename for the module.


Correct (and the specification is in the source code, there's no 
requirement for any particular mapping, bu I was at least cognizant of 
windows' dislike of : :)




Without this patch, the test case failes with:
.../ben-1_a.C:4:8: error: failed to write compiled module: Invalid argument
.../ben-1_a.C:4:8: note: compiled module file is 'partitions/module:import.mod'

gcc/testsuite:

* g++.dg/modules/ben-1.map: Replace the colon with dash.
* g++.dg/modules/ben-1_a.C: Likewise


ok, thanks



Co-Authored-By: Yvan ROUX  
Signed-off-by: Torbjörn SVENSSON  
---
  gcc/testsuite/g++.dg/modules/ben-1.map | 2 +-
  gcc/testsuite/g++.dg/modules/ben-1_a.C | 2 +-
  2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/g++.dg/modules/ben-1.map 
b/gcc/testsuite/g++.dg/modules/ben-1.map
index 182183ad089..ad84c11397d 100644
--- a/gcc/testsuite/g++.dg/modules/ben-1.map
+++ b/gcc/testsuite/g++.dg/modules/ben-1.map
@@ -1,3 +1,3 @@
  $root .
-module:import partitions/module:import.mod
+module:import partitions/module-import.mod
  module module.mod
diff --git a/gcc/testsuite/g++.dg/modules/ben-1_a.C 
b/gcc/testsuite/g++.dg/modules/ben-1_a.C
index 7e9b5661026..f1562eb2c5a 100644
--- a/gcc/testsuite/g++.dg/modules/ben-1_a.C
+++ b/gcc/testsuite/g++.dg/modules/ben-1_a.C
@@ -2,7 +2,7 @@
  // { dg-additional-files ben-1.map }
  
  export module module:import;

-// { dg-module-cmi =partitions/module:import.mod }
+// { dg-module-cmi =partitions/module-import.mod }
  
  export int b() {

return 0;


--
Nathan Sidwell



c++: import/export NTTP objects

2022-09-29 Thread Nathan Sidwell via Gcc-patches


This adds smarts to the module machinery to handle NTTP object
VAR_DECLs.  Like typeinfo objects, these must be ignored in the symbol
table, streamed specially and recreated on stream in.

Patrick, thanks for the testcase, I don't know how to attribute that to 
you in the changelog anymore.


nathan

--
Nathan SidwellFrom a1f7f9541c2b20eb44750b9c15cd831c62d67f21 Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Wed, 28 Sep 2022 09:21:14 -0700
Subject: [PATCH] c++: import/export NTTP objects

This adds smarts to the module machinery to handle NTTP object
VAR_DECLs.  Like typeinfo objects, these must be ignored in the symbol
table, streamed specially and recreated on stream in.

	gcc/cp/
	PR c++/100616
	* module.cc (enum tree_tag): Add tt_nttp_var.
	(trees_out::decl_node): Handle NTTP objects.
	(trees_in::tree_node): Handle tt_nttp_var.
	(depset::hash::add_binding_entry): Skip NTTP objects.

	gcc/testsuite/
	PR c++/100616
	* g++.dg/modules/100616_a.H: New.
	* g++.dg/modules/100616_b.C: New.
	* g++.dg/modules/100616_c.C: New.
	* g++.dg/modules/100616_d.C: New.
---
 gcc/cp/module.cc| 35 +
 gcc/testsuite/g++.dg/modules/100616_a.H |  5 
 gcc/testsuite/g++.dg/modules/100616_b.C |  7 +
 gcc/testsuite/g++.dg/modules/100616_c.C |  7 +
 gcc/testsuite/g++.dg/modules/100616_d.C | 10 +++
 5 files changed, 64 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/modules/100616_a.H
 create mode 100644 gcc/testsuite/g++.dg/modules/100616_b.C
 create mode 100644 gcc/testsuite/g++.dg/modules/100616_c.C
 create mode 100644 gcc/testsuite/g++.dg/modules/100616_d.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index d965017940a..cbf3a77de01 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -2737,6 +2737,7 @@ enum tree_tag {
   tt_tinfo_var,		/* Typeinfo object. */
   tt_tinfo_typedef,	/* Typeinfo typedef.  */
   tt_ptrmem_type,	/* Pointer to member type.  */
+  tt_nttp_var,		/* NTTP_OBJECT VAR_DECL.  */
 
   tt_parm,		/* Function parameter or result.  */
   tt_enum_value,	/* An enum value.  */
@@ -8548,6 +8549,21 @@ trees_out::decl_node (tree decl, walk_kind ref)
 	}
 	  return false;
 	}
+
+  if (DECL_NTTP_OBJECT_P (decl))
+	{
+	  /* A NTTP parm object.  */
+	  if (streaming_p ())
+	i (tt_nttp_var);
+	  tree_node (tparm_object_argument (decl));
+	  tree_node (DECL_NAME (decl));
+	  int tag = insert (decl);
+	  if (streaming_p ())
+	dump (dumper::TREE)
+	  && dump ("Wrote nttp object:%d %N", tag, DECL_NAME (decl));
+	  return false;
+	}
+
   break;
 
 case TYPE_DECL:
@@ -9627,6 +9643,21 @@ trees_in::tree_node (bool is_use)
   }
   break;
 
+case tt_nttp_var:
+  /* An NTTP object. */
+  {
+	tree init = tree_node ();
+	tree name = tree_node ();
+	if (!get_overrun ())
+	  {
+	res = get_template_parm_object (init, name);
+	int tag = insert (res);
+	dump (dumper::TREE)
+	  && dump ("Created nttp object:%d %N", tag, name);
+	  }
+  }
+  break;
+
 case tt_enum_value:
   /* An enum const value.  */
   {
@@ -12760,6 +12791,10 @@ depset::hash::add_binding_entity (tree decl, WMB_Flags flags, void *data_)
 	/* Ignore TINFO things.  */
 	return false;
 
+  if (TREE_CODE (decl) == VAR_DECL && DECL_NTTP_OBJECT_P (decl))
+	/* Ignore NTTP objects.  */
+	return false;
+
   if (!(flags & WMB_Using) && CP_DECL_CONTEXT (decl) != data->ns)
 	{
 	  /* A using that lost its wrapper or an unscoped enum
diff --git a/gcc/testsuite/g++.dg/modules/100616_a.H b/gcc/testsuite/g++.dg/modules/100616_a.H
new file mode 100644
index 000..9bc42bcc05b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/100616_a.H
@@ -0,0 +1,5 @@
+// { dg-additional-options {-std=c++20 -fmodule-header} }
+// { dg-module-cmi {} }
+
+template struct C { };
+struct A { };
diff --git a/gcc/testsuite/g++.dg/modules/100616_b.C b/gcc/testsuite/g++.dg/modules/100616_b.C
new file mode 100644
index 000..416fd524b2c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/100616_b.C
@@ -0,0 +1,7 @@
+// { dg-additional-options {-std=c++20 -fmodules-ts} }
+
+export module pr100616_b;
+// { dg-module-cmi pr100616_b }
+
+import "100616_a.H";
+export C c1;
diff --git a/gcc/testsuite/g++.dg/modules/100616_c.C b/gcc/testsuite/g++.dg/modules/100616_c.C
new file mode 100644
index 000..5c79f5eef68
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/100616_c.C
@@ -0,0 +1,7 @@
+// { dg-additional-options {-std=c++20 -fmodules-ts} }
+
+export module pr100616_c;
+// { dg-module-cmi pr100616_c }
+
+import "100616_a.H";
+export C c2;
diff --git a/gcc/testsuite/g++.dg/modules/100616_d.C b/gcc/testsuite/g++.dg/modules/100616_d.C
new file mode 100644
index 000..d9515db1140
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/100616_d.C
@@ -0,0 +1,10 @@
+// { dg-additional-options {-std=c++20 -fmodules-ts} }
+
+import "100616_a.H";
+import pr

Re: [PATCH] c++ modules: ICE with class NTTP argument [PR100616]

2022-09-28 Thread Nathan Sidwell via Gcc-patches

On 9/28/22 10:42, Patrick Palka wrote:

On Tue, 27 Sep 2022, Nathan Sidwell wrote:


On 9/26/22 15:05, Patrick Palka wrote:

On Mon, 26 Sep 2022, Patrick Palka wrote:


On Mon, 26 Sep 2022, Nathan Sidwell wrote:






   return decl;
@@ -29150,9 +29151,10 @@ finish_concept_definition (cp_expr id, tree init)
   static tree
   listify (tree arg)
   {
-  tree std_init_list = get_namespace_binding (std_node,
init_list_identifier);
+  tree std_init_list = lookup_qualified_name (std_node,
init_list_identifier);
   -  if (!std_init_list || !DECL_CLASS_TEMPLATE_P (std_init_list))
+  if (std_init_list == error_mark_node
+  || !DECL_CLASS_TEMPLATE_P (std_init_list))
   {
 gcc_rich_location richloc (input_location);
 maybe_add_include_fixit (, "", false);


What do you think about this independent change to use
lookup_qualified_name instead of get_namespace_binding in listify so
that the lookup for std::initializer_list is import-aware, which seems
to fix PR102576?


Yes, that looks right to me, thanks!  (I think it'll also fix a 
potential future problem if we ever have:


namespace std {
inline namespace v2 {
template  class initializer_list {...};
}}




diff --git a/gcc/testsuite/g++.dg/modules/pr100616_a.C
b/gcc/testsuite/g++.dg/modules/pr100616_a.C
new file mode 100644
index 000..788af2eb533
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr100616_a.C
@@ -0,0 +1,8 @@
+// PR c++/100616
+// { dg-additional-options "-std=c++20 -fmodules-ts" }
+// { dg-module-cmi pr100616 }
+export module pr100616;
+
+template struct C { };
+struct A { };
+C c1;
diff --git a/gcc/testsuite/g++.dg/modules/pr100616_b.C
b/gcc/testsuite/g++.dg/modules/pr100616_b.C
new file mode 100644
index 000..fc89cd08ac5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr100616_b.C
@@ -0,0 +1,8 @@
+// PR c++/100616
+// { dg-additional-options "-std=c++20 -fmodules-ts" }
+module pr100616;
+
+C c2;
+
+using type = decltype(c1);
+using type = decltype(c2);
diff --git a/gcc/testsuite/g++.dg/modules/pr102576_a.H
b/gcc/testsuite/g++.dg/modules/pr102576_a.H
new file mode 100644
index 000..87ba9b52031
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr102576_a.H
@@ -0,0 +1,5 @@
+// PR c++/102576
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include 
diff --git a/gcc/testsuite/g++.dg/modules/pr102576_b.C
b/gcc/testsuite/g++.dg/modules/pr102576_b.C
new file mode 100644
index 000..10251ed5304
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr102576_b.C
@@ -0,0 +1,9 @@
+// PR c++/102576
+// { dg-additional-options -fmodules-ts }
+
+import "pr102576_a.H";
+
+int main() {
+  for (int i : {1, 2, 3})
+    ;
+}


--
Nathan Sidwell



--
Nathan Sidwell



c++: Add DECL_NTTP_OBJECT_P lang flag

2022-09-28 Thread Nathan Sidwell via Gcc-patches


VAR_DECLs for NTTPs need to be handled specially by module streaming,
in the same manner to type info decls.  This reworks their handling to
allow that work to drop in.  We use DECL_LANG_FLAG_5 to indicate such
decls (I didn't notice template_parm_object_p, which looks at the
mangled name -- anyway a bit flag on the node is better, IMHO).  We
break apart the creation routine, so there's now an entry point the
module machinery can use directly.

nathan
--
Nathan SidwellFrom 50888e70c984da9cd9676d3986f68222581884b3 Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Wed, 28 Sep 2022 09:20:27 -0700
Subject: [PATCH] c++: Add DECL_NTTP_OBJECT_P lang flag

VAR_DECLs for NTTPs need to be handled specially by module streaming,
in the same manner to type info decls.  This reworks their handling to
allow that work to drop in.  We use DECL_LANG_FLAG_5 to indicate such
decls (I didn't notice template_parm_object_p, which looks at the
mangled name -- anyway a bit flag on the node is better, IMHO).  We
break apart the creation routine, so there's now an entry point the
module machinery can use directly.

	gcc/cp/
	* cp-tree.h (DECL_NTTP_OBJECT_P): New.
	(template_parm_object_p): Delete.
	(build_template_parm_object): Declare.
	* cxx-pretty-print.cc (pp_cx_template_argument_list): Use DECL_NTTP_OBJECT_P.
	* error.cc (dump_simple_decl): Likewise.
	* mangle.cc (write_template_arg): Likewise.
	* pt.cc (template_parm_object_p): Delete.
	(create_template_parm_object): Separated out checking from ...
	(get_template_parm_object): ... this, new external entry point.
---
 gcc/cp/cp-tree.h   |  7 ++-
 gcc/cp/cxx-pretty-print.cc |  2 +-
 gcc/cp/error.cc|  2 +-
 gcc/cp/mangle.cc   |  2 +-
 gcc/cp/pt.cc   | 35 +--
 5 files changed, 26 insertions(+), 22 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 19bbfbc557f..d0f1b18b015 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -518,6 +518,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
   CALL_EXPR_REVERSE_ARGS (in CALL_EXPR, AGGR_INIT_EXPR)
   CONSTRUCTOR_PLACEHOLDER_BOUNDARY (in CONSTRUCTOR)
   OVL_EXPORT_P (in OVERLOAD)
+  DECL_NTTP_OBJECT_P (in VAR_DECL)
6: TYPE_MARKED_P (in _TYPE)
   DECL_NONTRIVIALLY_INITIALIZED_P (in VAR_DECL)
   RANGE_FOR_IVDEP (in RANGE_FOR_STMT)
@@ -3548,6 +3549,10 @@ struct GTY(()) lang_decl {
 #define DECL_TINFO_P(NODE)			\
   TREE_LANG_FLAG_4 (TREE_CHECK2 (NODE,VAR_DECL,TYPE_DECL))
 
+/* true iff VAR_DECL node NODE is a NTTP object decl.  */
+#define DECL_NTTP_OBJECT_P(NODE)			\
+  TREE_LANG_FLAG_5 (TREE_CHECK (NODE,VAR_DECL))
+
 /* 1 iff VAR_DECL node NODE is virtual table or VTT.  We forward to
DECL_VIRTUAL_P from the common code, as that has the semantics we
need.  But we want a more descriptive name.  */
@@ -7414,7 +7419,7 @@ extern bool alias_type_or_template_p(tree);
 enum { nt_opaque = false, nt_transparent = true };
 extern tree alias_template_specialization_p (const_tree, bool);
 extern tree dependent_alias_template_spec_p (const_tree, bool);
-extern bool template_parm_object_p		(const_tree);
+extern tree get_template_parm_object		(tree expr, tree mangle);
 extern tree tparm_object_argument		(tree);
 extern bool explicit_class_specialization_p (tree);
 extern bool push_tinst_level(tree);
diff --git a/gcc/cp/cxx-pretty-print.cc b/gcc/cp/cxx-pretty-print.cc
index e18143e39a9..bbd51bb562a 100644
--- a/gcc/cp/cxx-pretty-print.cc
+++ b/gcc/cp/cxx-pretty-print.cc
@@ -1956,7 +1956,7 @@ pp_cxx_template_argument_list (cxx_pretty_printer *pp, tree t)
 	  if (TYPE_P (arg) || (TREE_CODE (arg) == TEMPLATE_DECL
 			   && TYPE_P (DECL_TEMPLATE_RESULT (arg
 	pp->type_id (arg);
-	  else if (template_parm_object_p (arg))
+	  else if (TREE_CODE (arg) == VAR_DECL && DECL_NTTP_OBJECT_P (arg))
 	pp->expression (DECL_INITIAL (arg));
 	  else
 	pp->expression (arg);
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 0389f35d731..53904e3669d 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -1129,7 +1129,7 @@ dump_global_iord (cxx_pretty_printer *pp, tree t)
 static void
 dump_simple_decl (cxx_pretty_printer *pp, tree t, tree type, int flags)
 {
-  if (template_parm_object_p (t))
+  if (TREE_CODE (t) == VAR_DECL && DECL_NTTP_OBJECT_P (t))
 return dump_expr (pp, DECL_INITIAL (t), flags);
 
   if (flags & TFF_DECL_SPECIFIERS)
diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 00d283fff8c..1a455858827 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -3672,7 +3672,7 @@ write_template_arg (tree node)
 	}
 }
 
-  if (template_parm_object_p (node))
+  if (TREE_CODE (node) == VAR_DECL && DECL_NTTP_OBJECT_P (node))
 /* We want to mangle the argument, not the var we stored it in.  */
 node = tparm_object_argument (node);
 
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 2d83dfd6954..c7adaef997d

Re: [PATCH] c++ modules: ICE with class NTTP argument [PR100616]

2022-09-27 Thread Nathan Sidwell via Gcc-patches

On 9/26/22 15:05, Patrick Palka wrote:

On Mon, 26 Sep 2022, Patrick Palka wrote:


On Mon, 26 Sep 2022, Nathan Sidwell wrote:


On 9/26/22 10:08, Nathan Sidwell wrote:

On 9/23/22 09:32, Patrick Palka wrote:


Judging by the two commits that introduced/modified this part of
maybe_register_incomplete_var, r196852 and r214333, ISTM the code
is really only concerned with constexpr static data members (whose
initializer may contain a pointer-to-member for a currently open class).
So maybe we ought to restrict the branch like so, which effectively
disables this part of maybe_register_incomplete_var during stream-in, and
guarantees that outermost_open_class doesn't return NULL if the branch is
taken?


I think the problem is that we're streaming these VAR_DECLs as regular
VAR_DECLS, when we should be handling them as a new kind of object fished
out from the template they're instantiating. (I'm guessing that'll just be a
new tag, a type and an initializer?)

Then on stream-in we can handle them in the same way as a non-modules
compilation handles such redeclarations.  I.e. how does:

template struct C { };
struct A { };
C c1; // #1
C c2; // #2

work.  Presumably at some point #2's A{} gets unified such that we find the
instantation that occurred at #1?


This works because the lookup in get_template_parm_object for #2's A{}
finds and reuses the VAR_DECL created for #1's A{}.

But IIUC this lookup (performed via get_global_binding) isn't
import-aware, which I suppose explains why we don't find the VAR_DECL
from another TU.



I notice the template arg for C is a var decl mangled as _ZTAXtl1AEE,
which is a 'template paramete object for A{}'.  I see that's a special
mangler 'mangle_template_parm_object', called from
get_template_parm_object.  Perhaps these VAR_DECLs need an additional
in-tree flag that the streamer can check for?


I wonder if we're setting the module attachment for these variables sanely?
They should be attached to the global module.  My guess is the
pushdecl_top_level_and_finish call in get_templatE_parm_object is not doing
what is needed (as well as the other issues).


This is a bit of a shot in the dark, but the following seems to work:
when pushing the VAR_DECL, we need to call set_originating_module to
attach it to the global module, and when looking it up, we need to do so
in an import-aware way.  Hopefully something like this is sufficient
to properly handle these VAR_DECLs and we don't need to stream them
specially?


Err, rather than changing the behavior of get_namespace_binding (which
has many unrelated callers), I guess we could just use the already
import-aware lookup_qualified_name instead where appropriate.  WDYT of
the following? (testing in progress)


I'm going to have to think further.  Morally these VAR_DECLs are like 
the typeinfo objects -- which we have to handle specially.  Reminding 
myself, I see rtti.cc does the pushdecl_top_level stuff creating them -- 
so they go into the slot for the current TU.  But the streaming code 
writes tt_tinfo_var/tt_tinfo_typedef records, and recreates the typeinfo 
on stream in, using the same above pushdec_top_level path. So even 
though the tinfo decls might seem attached to the current module, that 
doesn;t confuse the streaming, nor create collisions on read back.  Nor 
do we stream out tinfo decls that are not reachable through the streamed 
AST (if we treated then as normal decls, we'd stream them cos they're 
inthe current TU in the symbol table.  I have the same fear for these 
NTTPs.)


It looks like TREE_LANG_FLAG_5 can be used to note these VAR_DECLs are 
NTTPs, and then the streaming can deal with them.  Let me look further.



@@ -7307,6 +7307,7 @@ get_template_parm_object (tree expr, tsubst_flags_t 
complain)
hash_map_safe_put (tparm_obj_values, decl, copy);
  }
  
+  set_originating_module (decl);

pushdecl_top_level_and_finish (decl, expr);


this is wrong.  You're attaching the decl to the current module. which 
will mean conflicts when reading in such VAR_DECLs for the same NTTP 
from different modules.  Your test case might be hiding that as you have 
an interface and implementation unit from the same module (but you 
should be getting some kind of multiple definition error anyway?)



  
return decl;

@@ -29150,9 +29151,10 @@ finish_concept_definition (cp_expr id, tree init)
  static tree
  listify (tree arg)
  {
-  tree std_init_list = get_namespace_binding (std_node, init_list_identifier);
+  tree std_init_list = lookup_qualified_name (std_node, init_list_identifier);
  
-  if (!std_init_list || !DECL_CLASS_TEMPLATE_P (std_init_list))

+  if (std_init_list == error_mark_node
+  || !DECL_CLASS_TEMPLATE_P (std_init_list))
  {
gcc_rich_location richloc (input_location);
maybe_add_include_fixit (, "", false);
diff --git a/gcc/testsuite/g++.dg/modules/pr100616_a.C 
b/gcc/testsuite/g++.dg/modules/pr100616_a.C
new file mode 100644
index 000..788af2eb533
---

Re: [PATCH] c++ modules: variable template partial spec fixes [PR107033]

2022-09-26 Thread Nathan Sidwell via Gcc-patches
ue;
+template constexpr bool is_reference_v = true;
+
+struct A {
+  template static constexpr bool is_reference_v = false;
+};
+
+template constexpr bool A::is_reference_v = true;
+template constexpr bool A::is_reference_v = true;
+
+#if __cpp_concepts
+namespace concepts {
+  template bool is_reference_v;
+
+  template requires __is_same(T, T&)
+  constexpr bool is_reference_v = true;
+
+  template requires __is_same(T, T&&) && (!__is_same(T, T&))
+  constexpr bool is_reference_v = true;
+
+  template requires (!__is_same(T, T&)) && (!__is_same(T, T&&))
+  constexpr bool is_reference_v = false;
+
+  struct A {
+template static bool is_reference_v;
+  };
+
+  template requires __is_same(T, T&)
+  constexpr bool A::is_reference_v = true;
+
+  template requires __is_same(T, T&&) && (!__is_same(T, T&))
+  constexpr bool A::is_reference_v = true;
+
+  template requires (!__is_same(T, T&)) && (!__is_same(T, T&&))
+  constexpr bool A::is_reference_v = false;
+}
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/partial-2_a.C 
b/gcc/testsuite/g++.dg/modules/partial-2_a.C
index 2681bb59ce8..1582f56f2d4 100644
--- a/gcc/testsuite/g++.dg/modules/partial-2_a.C
+++ b/gcc/testsuite/g++.dg/modules/partial-2_a.C
@@ -3,41 +3,4 @@
  // { dg-module-cmi pr106826 }
  export module pr106826;
  
-template constexpr bool is_reference_v = false;

-template constexpr bool is_reference_v = true;
-template constexpr bool is_reference_v = true;
-
-struct A {
-  template static constexpr bool is_reference_v = false;
-};
-
-template constexpr bool A::is_reference_v = true;
-template constexpr bool A::is_reference_v = true;
-
-#if __cpp_concepts
-namespace concepts {
-  template bool is_reference_v;
-
-  template requires __is_same(T, T&)
-  constexpr bool is_reference_v = true;
-
-  template requires __is_same(T, T&&) && (!__is_same(T, T&))
-  constexpr bool is_reference_v = true;
-
-  template requires (!__is_same(T, T&)) && (!__is_same(T, T&&))
-  constexpr bool is_reference_v = false;
-
-  struct A {
-template static bool is_reference_v;
-  };
-
-  template requires __is_same(T, T&)
-  constexpr bool A::is_reference_v = true;
-
-  template requires __is_same(T, T&&) && (!__is_same(T, T&))
-  constexpr bool A::is_reference_v = true;
-
-  template requires (!__is_same(T, T&)) && (!__is_same(T, T&&))
-  constexpr bool A::is_reference_v = false;
-}
-#endif
+#include "partial-2.h"
diff --git a/gcc/testsuite/g++.dg/modules/partial-2_b.C 
b/gcc/testsuite/g++.dg/modules/partial-2_b.C
index 0af41ef5e5e..1b0c7a53e9f 100644
--- a/gcc/testsuite/g++.dg/modules/partial-2_b.C
+++ b/gcc/testsuite/g++.dg/modules/partial-2_b.C
@@ -2,20 +2,4 @@
  // { dg-additional-options -fmodules-ts }
  module pr106826;
  
-static_assert(is_reference_v);

-static_assert(is_reference_v);
-static_assert(!is_reference_v);
-
-static_assert(A::is_reference_v);
-static_assert(A::is_reference_v);
-static_assert(!A::is_reference_v);
-
-#if __cpp_concepts
-static_assert(concepts::is_reference_v);
-static_assert(concepts::is_reference_v);
-static_assert(!concepts::is_reference_v);
-
-static_assert(concepts::A::is_reference_v);
-static_assert(concepts::A::is_reference_v);
-static_assert(!concepts::A::is_reference_v);
-#endif
+#include "partial-2.cc"
diff --git a/gcc/testsuite/g++.dg/modules/partial-2_c.H 
b/gcc/testsuite/g++.dg/modules/partial-2_c.H
new file mode 100644
index 000..bd838529ce0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/partial-2_c.H
@@ -0,0 +1,5 @@
+// PR c++/107033
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+#include "partial-2.h"
diff --git a/gcc/testsuite/g++.dg/modules/partial-2_d.C 
b/gcc/testsuite/g++.dg/modules/partial-2_d.C
new file mode 100644
index 000..ed54d3c2884
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/partial-2_d.C
@@ -0,0 +1,8 @@
+// PR c++/107033
+// { dg-additional-options -fmodules-ts }
+// { dg-module-cmi pr107033 }
+export module pr107033;
+
+import "partial-2_c.H";
+
+#include "partial-2.cc"


--
Nathan Sidwell



Re: [PATCH] c++ modules: ICE with class NTTP argument [PR100616]

2022-09-26 Thread Nathan Sidwell via Gcc-patches

On 9/26/22 10:08, Nathan Sidwell wrote:

On 9/23/22 09:32, Patrick Palka wrote:


Judging by the two commits that introduced/modified this part of
maybe_register_incomplete_var, r196852 and r214333, ISTM the code
is really only concerned with constexpr static data members (whose
initializer may contain a pointer-to-member for a currently open class).
So maybe we ought to restrict the branch like so, which effectively
disables this part of maybe_register_incomplete_var during stream-in, and
guarantees that outermost_open_class doesn't return NULL if the branch is
taken?


I think the problem is that we're streaming these VAR_DECLs as regular 
VAR_DECLS, when we should be handling them as a new kind of object 
fished out from the template they're instantiating. (I'm guessing 
that'll just be a new tag, a type and an initializer?)


Then on stream-in we can handle them in the same way as a non-modules 
compilation handles such redeclarations.  I.e. how does:


template struct C { };
struct A { };
C c1; // #1
C c2; // #2

work.  Presumably at some point #2's A{} gets unified such that we find 
the instantation that occurred at #1?


I notice the template arg for C is a var decl mangled as 
_ZTAXtl1AEE, which is a 'template paramete object for A{}'.  I see 
that's a special mangler 'mangle_template_parm_object', called from 
get_template_parm_object.  Perhaps these VAR_DECLs need an additional 
in-tree flag that the streamer can check for?


I wonder if we're setting the module attachment for these variables 
sanely? They should be attached to the global module.  My guess is the 
pushdecl_top_level_and_finish call in get_templatE_parm_object is not 
doing what is needed (as well as the other issues).



--
Nathan Sidwell



Re: [PATCH] c++ modules: ICE with class NTTP argument [PR100616]

2022-09-26 Thread Nathan Sidwell via Gcc-patches

On 9/23/22 09:32, Patrick Palka wrote:


Judging by the two commits that introduced/modified this part of
maybe_register_incomplete_var, r196852 and r214333, ISTM the code
is really only concerned with constexpr static data members (whose
initializer may contain a pointer-to-member for a currently open class).
So maybe we ought to restrict the branch like so, which effectively
disables this part of maybe_register_incomplete_var during stream-in, and
guarantees that outermost_open_class doesn't return NULL if the branch is
taken?


I think the problem is that we're streaming these VAR_DECLs as regular 
VAR_DECLS, when we should be handling them as a new kind of object 
fished out from the template they're instantiating. (I'm guessing 
that'll just be a new tag, a type and an initializer?)


Then on stream-in we can handle them in the same way as a non-modules 
compilation handles such redeclarations.  I.e. how does:


template struct C { };
struct A { };
C c1; // #1
C c2; // #2

work.  Presumably at some point #2's A{} gets unified such that we find 
the instantation that occurred at #1?


I notice the template arg for C is a var decl mangled as 
_ZTAXtl1AEE, which is a 'template paramete object for A{}'.  I see 
that's a special mangler 'mangle_template_parm_object', called from 
get_template_parm_object.  Perhaps these VAR_DECLs need an additional 
in-tree flag that the streamer can check for?


nathan
--
Nathan Sidwell



Re: [PATCH] c++ modules: ICE with class NTTP argument [PR100616]

2022-09-22 Thread Nathan Sidwell via Gcc-patches

On 9/22/22 14:25, Patrick Palka wrote:


index 80467c19254..722b64793ed 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -18235,9 +18235,11 @@ maybe_register_incomplete_var (tree var)
{
  /* When the outermost open class is complete we can resolve any
 pointers-to-members.  */
- tree context = outermost_open_class ();
- incomplete_var iv = {var, context};
- vec_safe_push (incomplete_vars, iv);
+ if (tree context = outermost_open_class ())
+   {
+ incomplete_var iv = {var, context};
+ vec_safe_push (incomplete_vars, iv);
+   }


My immediate thought here is eek!  during stream in, the 
outermost_open_class could be anything -- to do with the context that 
wanted to lookup of the thing being streamed in, right?  So, the above 
change is I think just papering over a problem in this case.


not sure how to approach this.

nathan

--
Nathan Sidwell



Re: [PATCH] c++ modules: partial variable template specializations [PR106826]

2022-09-22 Thread Nathan Sidwell via Gcc-patches
l);
  tree tmpl = TI_TEMPLATE (ti);
  tree partial = NULL_TREE;
  for (tree spec = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
diff --git a/gcc/testsuite/g++.dg/modules/partial-2_a.C 
b/gcc/testsuite/g++.dg/modules/partial-2_a.C
new file mode 100644
index 000..2681bb59ce8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/partial-2_a.C
@@ -0,0 +1,43 @@
+// PR c++/106826
+// { dg-additional-options -fmodules-ts }
+// { dg-module-cmi pr106826 }
+export module pr106826;
+
+template constexpr bool is_reference_v = false;
+template constexpr bool is_reference_v = true;
+template constexpr bool is_reference_v = true;
+
+struct A {
+  template static constexpr bool is_reference_v = false;
+};
+
+template constexpr bool A::is_reference_v = true;
+template constexpr bool A::is_reference_v = true;
+
+#if __cpp_concepts
+namespace concepts {
+  template bool is_reference_v;
+
+  template requires __is_same(T, T&)
+  constexpr bool is_reference_v = true;
+
+  template requires __is_same(T, T&&) && (!__is_same(T, T&))
+  constexpr bool is_reference_v = true;
+
+  template requires (!__is_same(T, T&)) && (!__is_same(T, T&&))
+  constexpr bool is_reference_v = false;
+
+  struct A {
+template static bool is_reference_v;
+  };
+
+  template requires __is_same(T, T&)
+  constexpr bool A::is_reference_v = true;
+
+  template requires __is_same(T, T&&) && (!__is_same(T, T&))
+  constexpr bool A::is_reference_v = true;
+
+  template requires (!__is_same(T, T&)) && (!__is_same(T, T&&))
+  constexpr bool A::is_reference_v = false;
+}
+#endif
diff --git a/gcc/testsuite/g++.dg/modules/partial-2_b.C 
b/gcc/testsuite/g++.dg/modules/partial-2_b.C
new file mode 100644
index 000..0af41ef5e5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/partial-2_b.C
@@ -0,0 +1,21 @@
+// PR c++/106826
+// { dg-additional-options -fmodules-ts }
+module pr106826;
+
+static_assert(is_reference_v);
+static_assert(is_reference_v);
+static_assert(!is_reference_v);
+
+static_assert(A::is_reference_v);
+static_assert(A::is_reference_v);
+static_assert(!A::is_reference_v);
+
+#if __cpp_concepts
+static_assert(concepts::is_reference_v);
+static_assert(concepts::is_reference_v);
+static_assert(!concepts::is_reference_v);
+
+static_assert(concepts::A::is_reference_v);
+static_assert(concepts::A::is_reference_v);
+static_assert(!concepts::A::is_reference_v);
+#endif


--
Nathan Sidwell



Re: [PATCH 2/2] c++: xtreme-header modules tests cleanups

2022-09-20 Thread Nathan Sidwell via Gcc-patches

On 9/20/22 15:54, Patrick Palka wrote:

This adds some recently implemented C++20/23 library headers to the
xtreme-header tests as appropriate.  Also, it looks like we can safely
re-add  and remove the NO_ASSOCIATED_LAMBDA workaround.

Tested on x86_64-pc-linux-gnu, does this look OK for trunk?


cool, more bits working.  thanks!



gcc/testsuite/ChangeLog:

* g++.dg/modules/xtreme-header-2.h: Include .
* g++.dg/modules/xtreme-header-6.h: Include , ,
,  and .
* g++.dg/modules/xtreme-header.h: Likewise.  Remove
NO_ASSOCIATED_LAMBDA workaround.  Include implemented C++23
library headers.
---
  .../g++.dg/modules/xtreme-header-2.h  |  3 +-
  .../g++.dg/modules/xtreme-header-6.h  | 10 ++--
  gcc/testsuite/g++.dg/modules/xtreme-header.h  | 60 +++
  3 files changed, 29 insertions(+), 44 deletions(-)

diff --git a/gcc/testsuite/g++.dg/modules/xtreme-header-2.h 
b/gcc/testsuite/g++.dg/modules/xtreme-header-2.h
index ded093e533c..dfe94aa6988 100644
--- a/gcc/testsuite/g++.dg/modules/xtreme-header-2.h
+++ b/gcc/testsuite/g++.dg/modules/xtreme-header-2.h
@@ -1,8 +1,7 @@
  // Everything that transitively includes 
  
  #include 

-// FIXME: PR 97549
-// #include 
+#include 
  #include 
  #include 
  #include 
diff --git a/gcc/testsuite/g++.dg/modules/xtreme-header-6.h 
b/gcc/testsuite/g++.dg/modules/xtreme-header-6.h
index 85894b2b20a..8d024b69bac 100644
--- a/gcc/testsuite/g++.dg/modules/xtreme-header-6.h
+++ b/gcc/testsuite/g++.dg/modules/xtreme-header-6.h
@@ -1,22 +1,22 @@
  // C++20 headers
  #if __cplusplus > 201703
  #include 
+#include 
  #include 
  #include 
  #include 
  #if __cpp_coroutines
  #include 
  #endif
+#include 
  #include 
+#include 
+#include 
  #include 
  #include 
+#include 
  #if 0
  // Unimplemented
-#include 
  #include 
-#include 
-#include 
-#include 
-#include 
  #endif
  #endif
diff --git a/gcc/testsuite/g++.dg/modules/xtreme-header.h 
b/gcc/testsuite/g++.dg/modules/xtreme-header.h
index 41302c780b5..124e2f82277 100644
--- a/gcc/testsuite/g++.dg/modules/xtreme-header.h
+++ b/gcc/testsuite/g++.dg/modules/xtreme-header.h
@@ -1,17 +1,8 @@
  // All the headers!
  
-#if __cplusplus > 201703L

-// FIXME: if we include everything, something goes wrong with location
-// information.  We used to not handle lambdas attached to global
-// vars, and this is a convienient flag to stop including everything.
-#define NO_ASSOCIATED_LAMBDA 1
-#endif
-
  // C++ 17 and below
  #if 1
-#if !NO_ASSOCIATED_LAMBDA
  #include 
-#endif
  #include 
  #include 
  #include 
@@ -26,19 +17,12 @@
  #include 
  #include 
  #include 
-#if !NO_ASSOCIATED_LAMBDA
-// FIXME: PR 97549
-//#include 
-#endif
+#include 
  #include 
  #include 
  #include 
-#if !NO_ASSOCIATED_LAMBDA
  #include 
-#endif
-#if !NO_ASSOCIATED_LAMBDA
  #include 
-#endif
  #include 
  #include 
  #include 
@@ -49,12 +33,8 @@
  #include 
  #include 
  #include 
-#if !NO_ASSOCIATED_LAMBDA
  #include 
-#endif
-#if !NO_ASSOCIATED_LAMBDA
  #include 
-#endif
  #include 
  #include 
  #include 
@@ -63,12 +43,8 @@
  #include 
  #include 
  #include 
-#if !NO_ASSOCIATED_LAMBDA
  #include 
-#endif
-#if !NO_ASSOCIATED_LAMBDA
  #include 
-#endif
  #include 
  #include 
  #include 
@@ -78,9 +54,7 @@
  #include 
  #include 
  #include 
-#if !NO_ASSOCIATED_LAMBDA
  #include 
-#endif
  #include 
  #include 
  #include 
@@ -88,9 +62,7 @@
  #include 
  #include 
  #include 
-#if !NO_ASSOCIATED_LAMBDA
  #include 
-#endif
  #include 
  #include 
  #endif
@@ -119,26 +91,40 @@
  #if __cplusplus > 201703
  #if 1
  #include 
+#include 
  #include 
  #include 
  #include 
  #if __cpp_coroutines
  #include 
  #endif
-#if !NO_ASSOCIATED_LAMBDA
-#include 
-#endif
+#include 
  #include 
+#include 
+#include 
+#include 
  #include 
  #include 
+#include 
  #if 0
  // Unimplemented
-#include 
  #include 
-#include 
-#include 
-#include 
-#include 
  #endif
  #endif
  #endif
+
+// C++23
+#if __cplusplus > 202002L
+#include 
+#include 
+#include 
+#if 0
+// Unimplemented
+#include 
+#include 
+#include 
+#include 
+#include 
+#endif
+#endif
+


--
Nathan Sidwell



Re: [PATCH 1/2] c++: modules and non-dependent auto deduction

2022-09-20 Thread Nathan Sidwell via Gcc-patches

On 9/20/22 15:54, Patrick Palka wrote:

The modules streaming code seems to rely on the invariant that a
TEMPLATE_DECL and its DECL_TEMPLATE_RESULT have the same TREE_TYPE.


It does indeed.


But for a templated VAR_DECL with deduced non-dependent type, the two
TREE_TYPEs end up diverging: cp_finish_decl deduces the type of the
initializer ahead of time and updates the TREE_TYPE of the VAR_DECL, but
neglects to update the corresponding TEMPLATE_DECL as well, which leads
to a "conflicting global module declaration" error for each of the
__phase_alignment decls in the below testcase (and for the xtreme-header
testcases if we try including ).

This patch makes cp_finish_decl update the TREE_TYPE of the corresponding
TEMPLATE_DECL so that the invariant is maintained >
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?


Ok, thanks




gcc/cp/ChangeLog:

* decl.cc (cp_finish_decl): After updating the deduced type of a
VAR_DECL, also update the corresponding TEMPLATE_DECL if there
is one.

gcc/testsuite/ChangeLog:

* g++.dg/modules/auto-3.h: New test.
* g++.dg/modules/auto-3_a.H: New test.
* g++.dg/modules/auto-3_b.C: New test.
---
  gcc/cp/decl.cc  |  6 ++
  gcc/testsuite/g++.dg/modules/auto-3.h   | 10 ++
  gcc/testsuite/g++.dg/modules/auto-3_a.H |  4 
  gcc/testsuite/g++.dg/modules/auto-3_b.C |  4 
  4 files changed, 24 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/modules/auto-3.h
  create mode 100644 gcc/testsuite/g++.dg/modules/auto-3_a.H
  create mode 100644 gcc/testsuite/g++.dg/modules/auto-3_b.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 070f673c3a2..80467c19254 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -8180,6 +8180,12 @@ cp_finish_decl (tree decl, tree init, bool 
init_const_expr_p,
  return;
}
cp_apply_type_quals_to_decl (cp_type_quals (type), decl);
+
+  /* Update the type of the corresponding TEMPLATE_DECL to match.  */
+  if (DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_INFO (decl)
+ && DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (decl)) == decl)
+   TREE_TYPE (DECL_TI_TEMPLATE (decl)) = type;
  }
  
if (ensure_literal_type_for_constexpr_object (decl) == error_mark_node)

diff --git a/gcc/testsuite/g++.dg/modules/auto-3.h 
b/gcc/testsuite/g++.dg/modules/auto-3.h
new file mode 100644
index 000..f129433cbcb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/auto-3.h
@@ -0,0 +1,10 @@
+template
+struct __tree_barrier {
+  static const auto __phase_alignment_1 = 0;
+
+  template
+  static const auto __phase_alignment_2 = 0;
+};
+
+template
+inline auto __phase_alignment_3 = 0;
diff --git a/gcc/testsuite/g++.dg/modules/auto-3_a.H 
b/gcc/testsuite/g++.dg/modules/auto-3_a.H
new file mode 100644
index 000..25a7a73e73e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/auto-3_a.H
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#include "auto-3.h"
diff --git a/gcc/testsuite/g++.dg/modules/auto-3_b.C 
b/gcc/testsuite/g++.dg/modules/auto-3_b.C
new file mode 100644
index 000..03b6d46f476
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/auto-3_b.C
@@ -0,0 +1,4 @@
+// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
+
+#include "auto-3.h"
+import "auto-3_a.H";


--
Nathan Sidwell



Re: [PATCH] c++: stream PACK_EXPANSION_EXTRA_ARGS [PR106761]

2022-09-20 Thread Nathan Sidwell via Gcc-patches

On 9/20/22 10:08, Patrick Palka wrote:

On Tue, 20 Sep 2022, Nathan Sidwell wrote:


On 9/19/22 09:52, Patrick Palka wrote:

It looks like some xtreme-header-* tests are failing after the libstdc++
change r13-2158-g02f6b405f0e9dc ultimately because we're neglecting
to stream PACK_EXPANSION_EXTRA_ARGS, which leads to false equivalences
of different partial instantiations of _TupleConstraints::__constructible.

Tested on x86_64-pc-linux-gnu, does this look OK for trunk?

PR c++/106761

gcc/cp/ChangeLog:

* module.cc (trees_out::type_node) :
Stream PACK_EXPANSION_EXTRA_ARGS.
(trees_in::tree_node) : Likewise.



Looks good, I wonder why I missed that.  (I guess extracting a testcase out of
the headers was too tricky?)


Many thanks.  I managed to produce a small testcase which mirrors the
format of the xtreme-header-2* testcase.  Does the following look OK?


yup, thanks for extracting that!

nathan


-- >8 --

PR c++/106761

gcc/cp/ChangeLog:

* module.cc (trees_out::type_node) :
Stream PACK_EXPANSION_EXTRA_ARGS.
(trees_in::tree_node) : Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr106761.h: New test.
* g++.dg/modules/pr106761_a.H: New test.
* g++.dg/modules/pr106761_b.C: New test.
---
  gcc/cp/module.cc  |  3 +++
  gcc/testsuite/g++.dg/modules/pr106761.h   | 22 ++
  gcc/testsuite/g++.dg/modules/pr106761_a.H |  5 +
  gcc/testsuite/g++.dg/modules/pr106761_b.C |  7 +++
  4 files changed, 37 insertions(+)
  create mode 100644 gcc/testsuite/g++.dg/modules/pr106761.h
  create mode 100644 gcc/testsuite/g++.dg/modules/pr106761_a.H
  create mode 100644 gcc/testsuite/g++.dg/modules/pr106761_b.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 1a1ff5be574..9a9ef4e3332 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -8922,6 +8922,7 @@ trees_out::type_node (tree type)
if (streaming_p ())
u (PACK_EXPANSION_LOCAL_P (type));
tree_node (PACK_EXPANSION_PARAMETER_PACKS (type));
+  tree_node (PACK_EXPANSION_EXTRA_ARGS (type));
break;
  
  case TYPENAME_TYPE:

@@ -9455,12 +9456,14 @@ trees_in::tree_node (bool is_use)
{
  bool local = u ();
  tree param_packs = tree_node ();
+ tree extra_args = tree_node ();
  if (!get_overrun ())
{
  tree expn = cxx_make_type (TYPE_PACK_EXPANSION);
  SET_TYPE_STRUCTURAL_EQUALITY (expn);
  PACK_EXPANSION_PATTERN (expn) = res;
  PACK_EXPANSION_PARAMETER_PACKS (expn) = param_packs;
+ PACK_EXPANSION_EXTRA_ARGS (expn) = extra_args;
  PACK_EXPANSION_LOCAL_P (expn) = local;
  res = expn;
}
diff --git a/gcc/testsuite/g++.dg/modules/pr106761.h 
b/gcc/testsuite/g++.dg/modules/pr106761.h
new file mode 100644
index 000..9f22a22a45d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr106761.h
@@ -0,0 +1,22 @@
+// PR c++/106761
+
+template
+struct __and_;
+
+template
+struct is_convertible;
+
+template
+struct _TupleConstraints {
+  template
+  using __constructible = __and_...>;
+};
+
+template
+struct tuple {
+  template
+  using __constructible
+= typename _TupleConstraints::template __constructible;
+};
+
+tuple t;
diff --git a/gcc/testsuite/g++.dg/modules/pr106761_a.H 
b/gcc/testsuite/g++.dg/modules/pr106761_a.H
new file mode 100644
index 000..8ad116412af
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr106761_a.H
@@ -0,0 +1,5 @@
+// PR c++/106761
+// { dg-additional-options -fmodule-header }
+
+// { dg-module-cmi {} }
+#include "pr106761.h"
diff --git a/gcc/testsuite/g++.dg/modules/pr106761_b.C 
b/gcc/testsuite/g++.dg/modules/pr106761_b.C
new file mode 100644
index 000..336cb12757e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr106761_b.C
@@ -0,0 +1,7 @@
+// PR c++/106761
+// { dg-additional-options -fmodules-ts }
+
+#include "pr106761.h"
+import "pr106761_a.H";
+
+tuple u = t;


--
Nathan Sidwell



Re: [PATCH] c++: stream PACK_EXPANSION_EXTRA_ARGS [PR106761]

2022-09-20 Thread Nathan Sidwell via Gcc-patches

On 9/19/22 09:52, Patrick Palka wrote:

It looks like some xtreme-header-* tests are failing after the libstdc++
change r13-2158-g02f6b405f0e9dc ultimately because we're neglecting
to stream PACK_EXPANSION_EXTRA_ARGS, which leads to false equivalences
of different partial instantiations of _TupleConstraints::__constructible.

Tested on x86_64-pc-linux-gnu, does this look OK for trunk?

PR c++/106761

gcc/cp/ChangeLog:

* module.cc (trees_out::type_node) :
Stream PACK_EXPANSION_EXTRA_ARGS.
(trees_in::tree_node) : Likewise.



Looks good, I wonder why I missed that.  (I guess extracting a testcase 
out of the headers was too tricky?)


nathan

---
  gcc/cp/module.cc | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 1a1ff5be574..9a9ef4e3332 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -8922,6 +8922,7 @@ trees_out::type_node (tree type)
if (streaming_p ())
u (PACK_EXPANSION_LOCAL_P (type));
tree_node (PACK_EXPANSION_PARAMETER_PACKS (type));
+  tree_node (PACK_EXPANSION_EXTRA_ARGS (type));
break;
  
  case TYPENAME_TYPE:

@@ -9455,12 +9456,14 @@ trees_in::tree_node (bool is_use)
{
  bool local = u ();
  tree param_packs = tree_node ();
+ tree extra_args = tree_node ();
  if (!get_overrun ())
{
  tree expn = cxx_make_type (TYPE_PACK_EXPANSION);
  SET_TYPE_STRUCTURAL_EQUALITY (expn);
  PACK_EXPANSION_PATTERN (expn) = res;
  PACK_EXPANSION_PARAMETER_PACKS (expn) = param_packs;
+ PACK_EXPANSION_EXTRA_ARGS (expn) = extra_args;
  PACK_EXPANSION_LOCAL_P (expn) = local;
  res = expn;
}


--
Nathan Sidwell



Re: [PATCH] c++: modules ICE with typename friend declaration

2022-09-17 Thread Nathan Sidwell via Gcc-patches

On 9/16/22 11:54, Patrick Palka wrote:

On Fri, 16 Sep 2022, Nathan Sidwell wrote:


Thanks, this looks right. Sigh templates can mess up ones mental invariants!
The test case should really be a foo_[ab].C kind, to test both sides of the 
streaming. Bonus points for using the template after importing.  And you need 
the dg-module-cmi annotation to check /and then
delete/ the gcm file produced.


Aha, thanks very much for the pointers, I redid the testcase using
lang-3_[abc].C as an example.  How does the following look?



yes, that's right, thanks!

nathan

--
Nathan Sidwell



Re: [PATCH] c++: modules ICE with typename friend declaration

2022-09-16 Thread Nathan Sidwell via Gcc-patches
Thanks, this looks right. Sigh templates can mess up ones mental invariants!

The test case should really be a foo_[ab].C kind, to test both sides of the
streaming. Bonus points for using the template after importing.  And you
need the dg-module-cmi annotation to check /and then delete/ the gcm file
produced.

nathan

On Thu, Sep 15, 2022, 22:16 Patrick Palka  wrote:

> A couple of xtreme-header-* modules tests began ICEing in C++23 mode
> ever since r13-2650-g5d84a4418aa962 introduced into  the
> dependently scoped friend declaration
>
>   friend /* typename */ _OuterIter::value_type;
>
> ultimately because the streaming code assumes a TYPE_P friend must
> be a class type, but here it's a TYPENAME_TYPE, which doesn't have
> a TEMPLATE_INFO or CLASSTYPE_BEFRIENDING_CLASSES.  This patch tries
> to correct this in a minimal way.
>
> Tested on x86_64-pc-linux-gnu, does this look OK for trunk?
>
> gcc/cp/ChangeLog:
>
> * module.cc (friend_from_decl_list): Don't consider
> CLASSTYPE_TEMPLATE_INFO for a TYPENAME_TYPE friend.
> (trees_in::read_class_def): Don't add to
> CLASSTYPE_BEFRIENDING_CLASSES for a TYPENAME_TYPE friend.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/modules/typename-friend.C: New test.
> ---
>  gcc/cp/module.cc   | 5 +++--
>  gcc/testsuite/g++.dg/modules/typename-friend.C | 9 +
>  2 files changed, 12 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/modules/typename-friend.C
>
> diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
> index f27f4d091e5..1a1ff5be574 100644
> --- a/gcc/cp/module.cc
> +++ b/gcc/cp/module.cc
> @@ -4734,7 +4734,8 @@ friend_from_decl_list (tree frnd)
>if (TYPE_P (frnd))
> {
>   res = TYPE_NAME (frnd);
> - if (CLASSTYPE_TEMPLATE_INFO (frnd))
> + if (CLASS_TYPE_P (frnd)
> + && CLASSTYPE_TEMPLATE_INFO (frnd))
> tmpl = CLASSTYPE_TI_TEMPLATE (frnd);
> }
>else if (DECL_TEMPLATE_INFO (frnd))
> @@ -12121,7 +12122,7 @@ trees_in::read_class_def (tree defn, tree
> maybe_template)
> {
>   tree f = TREE_VALUE (friend_classes);
>
> - if (TYPE_P (f))
> + if (CLASS_TYPE_P (f))
> {
>   CLASSTYPE_BEFRIENDING_CLASSES (f)
> = tree_cons (NULL_TREE, type,
> diff --git a/gcc/testsuite/g++.dg/modules/typename-friend.C
> b/gcc/testsuite/g++.dg/modules/typename-friend.C
> new file mode 100644
> index 000..d8faf7955c3
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/modules/typename-friend.C
> @@ -0,0 +1,9 @@
> +// { dg-additional-options "-fmodules-ts" }
> +
> +export module x;
> +
> +template
> +struct A {
> +  friend typename T::type;
> +  friend void f(A) { }
> +};
> --
> 2.37.3.662.g36f8e7ed7d
>
>


Re: Ping [PATCH V2] libcpp: Optimize #pragma once with a hash table [PR58770]

2022-08-23 Thread Nathan Sidwell via Gcc-patches

On 8/22/22 13:39, Paul Hollinsky wrote:

On Mon, Aug 22, 2022 at 09:19:29AM -0400, Nathan Sidwell wrote:

On 8/19/22 16:27, Paul Hollinsky wrote:

Hi all,

Would love some feedback on this patch!

Thanks,
Paul

On Mon, Aug 01, 2022 at 05:18:40AM +, Paul Hollinsky wrote:

Rather than traversing the all_files linked list for every include,
this factors out the quick idempotency checks (modification time
and size) to be the keys in a hash table so we can find matching
files quickly.


I'm probably confused, but why is the existing idempotency logic
insufficiently optimal?  Can it be improved directly?


The idempotency logic breaks down to a couple integer comparisons, I doubt
it can be made much faster. Usually a file will be skipped after the very
first idempotency check. The reason it's suboptimal right now is that it's
O(n^2) behavior -- for each include that's seen we follow the entire linked
list and do those integeger comparisons.


Traversing a list is O(N) -- why are you encountering N^2 here?  (Are 
you summing over all includes?)




The cost of hashing, performing a lookup against the hash table, and then
traversing the list of results (any hash collisions) is much lower than
traversing the full list of includes. I suspect that has something to do
with cache locality, or lack thereof, when accessing each member of the
linked list. It's likely also just far fewer instructions executed.


I don't see why a hash table cannot be applied to all idempotent files, 
not just #import/pragma once.






WRT using modification time as a key.  I don't see how that provides
sufficient additional randomization to file size?  Groups of headers are
often installed with the same mtime.


This is a fair point, and I was going to say something here about the
codebases being compiled, but git also doesn't preserve mtime.

The real reason mtime is because that's what was done in the previous
implementation, and I felt it best not to mess with.

But, if there are better attributes that could be used without adding
much overhead we could use those instead. I was personally worried that
reading the file to perform any sort of hash would be expensive.


doing anything other than compare the pathname is going to mean going to 
disk.  That's likely cached by the OS from the first read.  I suppose 
one could encounter horrible LRU behaviour, but you're probably going to 
lose in that case anyway.  Hm, why not just key on the inode/drive 
number? that way one even avoids the inode read (oh, I think stat isn't 
that fine grained is it)


I suppose one could have two hashtables -- one keyed by pathname, which 
one could check before the inode, which would deal with the majority of 
non-symlink-farm cases.  Then one keyed by inode/m_time or whatever to 
deal with symlinks.


nathan



In any case, thank you very much for the feedback!

--Paul





The hash table value type is a linked list, in case more than one
file matches the quick check.

The table is only built if a once-only file is seen, so include
guard performance is not affecte

My laptop would previously complete Ricardo's benchmark from the
PR in ~1.1s using #pragma once, and ~0.35s using include guards.

After this change, both benchmarks now complete in ~0.35s. I did
have to randomize the modification dates on the benchmark headers
so the files did not all end up in the same hash table list, but
that would likely not come up outside of the contrived benchmark.

I bootstrapped and ran the testsuite on x86_64 Darwin, as well as
ppc64le and aarch64 Linux.

libcpp/ChangeLog:

PR preprocessor/58770
* internal.h: Add hash table for #pragma once
* files.cc: Optimize #pragma once with the hash table

Signed-off-by: Paul Hollinsky 
---
   libcpp/files.cc   | 116 +++---
   libcpp/internal.h |   3 ++
   2 files changed, 112 insertions(+), 7 deletions(-)

diff --git a/libcpp/files.cc b/libcpp/files.cc
index 24208f7b0f8..d4ffd77578e 100644
--- a/libcpp/files.cc
+++ b/libcpp/files.cc
@@ -167,6 +167,33 @@ struct file_hash_entry_pool
 struct cpp_file_hash_entry pool[FILE_HASH_POOL_SIZE];
   };
+/* A set of attributes designed to quickly identify obviously different files
+   in a hashtable.  Just in case there are collisions, we still maintain a
+   list.  These sub-lists can then be checked for #pragma once rather than
+   interating through all_files.  */
+struct file_quick_idempotency_attrs
+{
+  file_quick_idempotency_attrs(const _cpp_file *f)
+: mtime(f->st.st_mtime), size(f->st.st_size) {}
+
+  time_t mtime;
+  off_t size;
+
+  static hashval_t hash (/* _cpp_file* */ const void *p);
+};
+
+/* Sub-list of very similar files kept in a hashtable to check for #pragma
+   once.  */
+struct file_sublist
+{
+  _cpp_file *f;
+  file_sublist *next;
+
+  static int eq (/* _cpp_file* */ const void *p,
+/* file_sublist* */ const void *q);
+  static void del (/* file_sublist* */ v

Re: Ping [PATCH V2] libcpp: Optimize #pragma once with a hash table [PR58770]

2022-08-22 Thread Nathan Sidwell via Gcc-patches
_cpp_get_file_name (file));
+}
+}
+
  /* Place the file referenced by FILE into a new buffer on the buffer
 stack if possible.  Returns true if a buffer is stacked.  Use LOC
 for any diagnostics.  */
@@ -950,6 +1009,9 @@ _cpp_stack_file (cpp_reader *pfile, _cpp_file *file, 
include_type type,
if (!has_unique_contents (pfile, file, type == IT_IMPORT, loc))
return false;
  
+  if (pfile->seen_once_only && file->once_only)

+   update_pragma_once_table (pfile, file);
+
if (pfile->buffer && file->dir)
sysp = MAX (pfile->buffer->sysp, file->dir->sysp);
  
@@ -1434,6 +1496,41 @@ nonexistent_file_hash_eq (const void *p, const void *q)

return filename_cmp ((const char *) p, (const char *) q) == 0;
  }
  
+/* Hasher for the #pragma once hash table.  */

+hashval_t
+file_quick_idempotency_attrs::hash (const void *p)
+{
+  const _cpp_file *f = static_cast (p);
+  file_quick_idempotency_attrs kh (f);
+  return iterative_hash_object (kh, 0);
+}
+
+/* Equality checker for the #pragma once hash table.  */
+int
+file_sublist::eq (const void *p, const void *q)
+{
+  /* Just check if the file q would be in the list p. Every
+ file in the list should have these attributes the same,
+ so we don't need to traverse.  */
+  const file_sublist *e = static_cast (p);
+  const _cpp_file *f = static_cast (q);
+  return f->st.st_mtime == e->f->st.st_mtime
+&& f->st.st_size == e->f->st.st_size;
+}
+
+/* Cleanup for a file sub-list. Does not free the _cpp_file
+   structures within.  */
+void
+file_sublist::del (void *p)
+{
+  file_sublist *e = static_cast (p);
+  if (e->next)
+{
+  file_sublist::del (e->next);
+  free (e->next);
+}
+}
+
  /* Initialize everything in this source file.  */
  void
  _cpp_init_files (cpp_reader *pfile)
@@ -1442,6 +1539,10 @@ _cpp_init_files (cpp_reader *pfile)
NULL, xcalloc, free);
pfile->dir_hash = htab_create_alloc (127, file_hash_hash, file_hash_eq,
NULL, xcalloc, free);
+  pfile->pragma_once_files = htab_create_alloc (127,
+   file_quick_idempotency_attrs::hash,
+   file_sublist::eq, file_sublist::del,
+   xcalloc, free);
allocate_file_hash_entries (pfile);
pfile->nonexistent_file_hash = htab_create_alloc (127, htab_hash_string,
nonexistent_file_hash_eq,
@@ -1456,6 +1557,7 @@ _cpp_cleanup_files (cpp_reader *pfile)
  {
htab_delete (pfile->file_hash);
htab_delete (pfile->dir_hash);
+  htab_delete (pfile->pragma_once_files);
htab_delete (pfile->nonexistent_file_hash);
obstack_free (>nonexistent_file_ob, 0);
free_file_hash_entries (pfile);
diff --git a/libcpp/internal.h b/libcpp/internal.h
index badfd1b40da..9c3c46df335 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -485,6 +485,9 @@ struct cpp_reader
   been used.  */
bool seen_once_only;
  
+  /* Optimization for #pragma once.  */

+  struct htab *pragma_once_files;
+
/* Multiple include optimization.  */
const cpp_hashnode *mi_cmacro;
const cpp_hashnode *mi_ind_cmacro;
--
2.34.1




--
Nathan Sidwell


Re: Where in C++ module streaming to handle a new bitfield added in "tree_decl_common"

2022-08-16 Thread Nathan Sidwell via Gcc-patches

On 8/15/22 10:03, Richard Biener wrote:

On Mon, Aug 15, 2022 at 3:29 PM Nathan Sidwell via Gcc-patches
 wrote:


On 8/2/22 10:44, Qing Zhao wrote:

Hi, Nathan,

I am adding a new bitfield “decl_not_flexarray” in “tree_decl_common”  
(gcc/tree-core.h) for the new gcc feature -fstrict-flex-arrays.


diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index ea9f281f1cc..458c6e6ceea 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1813,7 +1813,10 @@ struct GTY(()) tree_decl_common {
   TYPE_WARN_IF_NOT_ALIGN.  */
unsigned int warn_if_not_align : 6;

-  /* 14 bits unused.  */
+  /* In FIELD_DECL, this is DECL_NOT_FLEXARRAY.  */
+  unsigned int decl_not_flexarray : 1;


Is it possible to invert the meaning here -- set the flag if it /IS/ a
flexible array? negated flags can be confusing, and I see your patch
sets it to '!is_flexible_array (...)' anyway?


The issue is it's consumed by the middle-end but set by a single (or two)
frontends and the conservative setting is having the bit not set.  That works
nicely together with touching just the frontends that want stricter behavior
than currently ...


Makes sense, but is the comment incomplete?  I'm guessing this flag is 
for FIELD_DECLs /of array type/, and not just any old FIELD_DECL?  After 
all a field of type int is not a flexible array, but presumably doesn't 
need this flag setting?


nathan

--
Nathan Sidwell


c++: Fix module line no testcase

2022-08-15 Thread Nathan Sidwell via Gcc-patches


Not all systems have the same injected headers, leading to line
location table differences that are immaterial to the test.  Fix the
regexp more robustly.

nathan

--
Nathan SidwellFrom af088b32def1c56538f0f3aaea16f013e9292d64 Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Mon, 15 Aug 2022 07:19:36 -0700
Subject: [PATCH] c++: Fix module line no testcase

Not all systems have the same injected headers, leading to line
location table differences that are immaterial to the test.  Fix the
regexp more robustly.

	gcc/testsuite/
	* g++.dg/modules/loc-prune-4.C: Adjust regexp
---
 gcc/testsuite/g++.dg/modules/loc-prune-4.C | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/g++.dg/modules/loc-prune-4.C b/gcc/testsuite/g++.dg/modules/loc-prune-4.C
index 765c378e51e..aa8f248b52b 100644
--- a/gcc/testsuite/g++.dg/modules/loc-prune-4.C
+++ b/gcc/testsuite/g++.dg/modules/loc-prune-4.C
@@ -18,5 +18,5 @@ int baz (int);
 
 // { dg-final { scan-lang-dump {Ordinary maps:2 locs:12288 range_bits:5} module } }
 // { dg-final { scan-lang-dump { 1 source file names\n Source file...=[^\n]*loc-prune-4.C\n} module } }
-// { dg-final { scan-lang-dump { Span:0 ordinary \[2.\+12288,\+4096\)->\[0,\+4096\)} module } }
-// { dg-final { scan-lang-dump { Span:1 ordinary \[2.\+40960,\+8192\)->\[4096,\+8192\)} module } }
+// { dg-final { scan-lang-dump { Span:0 ordinary \[[0-9]+\+12288,\+4096\)->\[0,\+4096\)} module } }
+// { dg-final { scan-lang-dump { Span:1 ordinary \[[0-9]+\+40960,\+8192\)->\[4096,\+8192\)} module } }
-- 
2.30.2



Re: Where in C++ module streaming to handle a new bitfield added in "tree_decl_common"

2022-08-15 Thread Nathan Sidwell via Gcc-patches

On 8/2/22 10:44, Qing Zhao wrote:

Hi, Nathan,

I am adding a new bitfield “decl_not_flexarray” in “tree_decl_common”  
(gcc/tree-core.h) for the new gcc feature -fstrict-flex-arrays.


diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index ea9f281f1cc..458c6e6ceea 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -1813,7 +1813,10 @@ struct GTY(()) tree_decl_common {
  TYPE_WARN_IF_NOT_ALIGN.  */
   unsigned int warn_if_not_align : 6;

-  /* 14 bits unused.  */
+  /* In FIELD_DECL, this is DECL_NOT_FLEXARRAY.  */
+  unsigned int decl_not_flexarray : 1;


Is it possible to invert the meaning here -- set the flag if it /IS/ a 
flexible array? negated flags can be confusing, and I see your patch 
sets it to '!is_flexible_array (...)' anyway?



+
+  /* 13 bits unused.  */

   /* UID for points-to sets, stable over copying from inlining.  */
   unsigned int pt_uid;


(Please refer to the following for details:

https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598556.html
https://gcc.gnu.org/pipermail/gcc-patches/2022-July/598965.html





)

Richard mentioned the following:

"I've not seen it so you are probably missing it - the bit has to be
streamed in tree-streamer-{in,out}.cc to be usable from LTO.  Possibly
C++ module streaming also needs to handle it.”

I have figured out that where to add the handling of the bit in 
“tree-streamer-{in, out}.cc,
However, it’s quite difficult for me to locate where should I add the handling 
of this new bit in
C++ module streaming,  could you please help me on this?




add it in to trees_{in,out}::core_bools.  You could elide streaming for 
non-FIELD_DECL decls.


Hope that helps.

nathan




Thanks a lot for your help.

Qing



--
Nathan Sidwell


C++: add -std={c,gnu}++{current,future}

2022-07-13 Thread Nathan Sidwell via Gcc-patches

Inspired by a user question.  Jason, thoughts?

Since C++ is such a moving target, Microsoft have /std:c++latest
(AFAICT clang does not), to select the currently implemented version
of the working paper.  But the use of 'std:latest' is somewhat
ambiguous -- the current std is C++20 -- that's the latest std, the
next std will more than likely but not necessarily be C++23.  So this
adds:

  -std=c++current -- the current std (c++20)
  -std=c++future -- the working paper (c++2b)

also adds gnu++current and gnu++future to select the gnu-extended
variants.

nathan

--
Nathan SidwellFrom 9671f4d5e7efa130280b6d50fb4e9e8492d5b587 Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Wed, 13 Jul 2022 12:11:40 -0700
Subject: [PATCH] C++: add -std={c,gnu}++{current,future}

Since C++ is such a moving target, Microsoft have /std:c++latest
(AFAICT clang does not), to select the currently implemented version
of the working paper.  But the use of 'std:latest' is somewhat
ambiguous -- the current std is C++20 -- that's the latest std, the
next std will more than likely but not necessarily be C++23.  So this
adds:

  -std=c++current -- the current std (c++20)
  -std=c++future -- the working paper (c++2b)

also adds gnu++current and gnu++future to select the gnu-extended
variants.

	gcc/
	* doc/invoke.texi (-std=): Document new c++ current & future
	options.
	gcc/c-family/
	* c.opt (-std={c,gnu}++{current,future}: New alias options.
	gcc/testsuite/
	* g++.dg/gnu-current.C: New.
	* g++.dg/gnu-future.C: New.
	* g++.dg/std-current.C: New.
	* g++.dg/std-future.C: New.
---
 gcc/c-family/c.opt | 16 
 gcc/doc/invoke.texi| 23 +++
 gcc/testsuite/g++.dg/gnu-current.C |  7 +++
 gcc/testsuite/g++.dg/gnu-future.C  |  7 +++
 gcc/testsuite/g++.dg/std-current.C | 11 +++
 gcc/testsuite/g++.dg/std-future.C  |  8 
 6 files changed, 72 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/gnu-current.C
 create mode 100644 gcc/testsuite/g++.dg/gnu-future.C
 create mode 100644 gcc/testsuite/g++.dg/std-current.C
 create mode 100644 gcc/testsuite/g++.dg/std-future.C

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 44e1a60ce24..9292029a967 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -2321,6 +2321,14 @@ std=c++23
 C++ ObjC++ Undocumented
 Conform to the ISO 2023 C++ draft standard (experimental and incomplete support).
 
+std=c++current
+C++ ObjC++ Alias(std=c++20) Undocumented
+Conform to the current ISO C++ standard (C++20).
+
+std=c++future
+C++ ObjC++ Alias(std=c++23) Undocumented
+Conform to a future ISO C++ standard (C++2b, experimentatl and incomplete support).
+
 std=c11
 C ObjC
 Conform to the ISO 2011 C standard.
@@ -2407,6 +2415,14 @@ std=gnu++23
 C++ ObjC++ Undocumented
 Conform to the ISO 2023 C++ draft standard with GNU extensions (experimental and incomplete support).
 
+std=gnu++current
+C++ ObjC++ Alias(std=gnu++20) Undocumented
+Conform to the current ISO C++ standard with GNU extensions (C++20).
+
+std=gnu++future
+C++ ObjC++ Alias(std=gnu++23) Undocumented
+Conform to a future ISO C++ standard with GNU extensions (C++2b, experimentatl and incomplete support).
+
 std=gnu11
 C ObjC
 Conform to the ISO 2011 C standard with GNU extensions.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index d5ff1018372..1c0edb9df68 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -2462,6 +2462,17 @@ GNU dialect of @option{-std=c++17}.
 This is the default for C++ code.
 The name @samp{gnu++1z} is deprecated.
 
+@item gnu++current
+@itemx gnu++current
+GNU dialect of the current C++ standard, currently @option{-std=gnu++20}.
+The C++ version selected by this option is a moving target.
+
+@item gnu++future
+@itemx gnu++future
+GNU dialect of the next C++ standard, currently @option{-std=gnu++2b}.
+The C++ version selected by this option is a moving target (as are the
+semantics of that proposed version).
+
 @item c++20
 @itemx c++2a
 The 2020 ISO C++ standard plus amendments.
@@ -2487,6 +2498,18 @@ change in incompatible ways in future releases.
 GNU dialect of @option{-std=c++2b}.  Support is highly experimental,
 and will almost certainly change in incompatible ways in future
 releases.
+
+@item c++current
+@itemx c++current
+The current C++ standard, currently @option{-std=gnu++20}.
+The C++ version selected by this option is a moving target.
+
+@item c++future
+@itemx c++future
+The next C++ standard, currently @option{-std=gnu++2b}.
+The C++ version selected by this option is a moving target (as are the
+semantics of that proposed version).
+
 @end table
 
 @item -aux-info @var{filename}
diff --git a/gcc/testsuite/g++.dg/gnu-current.C b/gcc/testsuite/g++.dg/gnu-current.C
new file mode 100644
index 000..c95c56d3ad8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gnu-current.C
@@ -0,0 +1,7 @@
+// { dg-do compile }
+// { dg-options -std=gnu++current }
+
+static_assert (__cplusplus == 202002L, "time 

c++: Prune ordinary locations

2022-07-05 Thread Nathan Sidwell via Gcc-patches


Like macro locations, we only need to emit ordinary location
information for locations emitted into the CMI. This adds a hash table
noting which ordinary lines are needed.  These are then sorted and
(sufficiently) adjacent lines are coalesced to a single map.  There is
a tradeoff here, allowing greater separation reduces the number of
line maps, but increases the number of locations.  It appears allowing
2 or 3 intervening lines is the sweet spot, and this patch chooses 2.

Compiling a hello-world #includeing  in it's GMF gives a
reduction in number of locations of 5 fold, but an increase in number
of maps about 4 fold.  Examining one of the xtreme-header tests we
halve the number of locations and increase the number of maps by 9
fold.

Module interfaces that emit no entities (or macros, if a header-unit),
will now have no location tables.

nathan

--
Nathan SidwellFrom 47794da8d8ea61ea8f6a0e21d3c1731a56d0cff3 Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Fri, 24 Jun 2022 05:57:42 -0700
Subject: [PATCH] c++: Prune ordinary locations

Like macro locations, we only need to emit ordinary location
information for locations emitted into the CMI. This adds a hash table
noting which ordinary lines are needed.  These are then sorted and
(sufficiently) adjacent lines are coalesced to a single map.  There is
a tradeoff here, allowing greater separation reduces the number of
line maps, but increases the number of locations.  It appears allowing
2 or 3 intervening lines is the sweet spot, and this patch chooses 2.

Compiling a hello-world #includeing  in it's GMF gives a
reduction in number of locations of 5 fold, but an increase in number
of maps about 4 fold.  Examining one of the xtreme-header tests we
halve the number of locations and increase the number of maps by 9
fold.

Module interfaces that emit no entities (or macros, if a header-unit),
will now have no location tables.

	gcc/cp/
	* module.cc
	(struct ord_loc_info, ord_loc_traits): New.
	(ord_loc_tabke, ord_loc_remap): New globals.
	(struct location_map_info): Delete.
	(struct module_state_config): Rename ordinary_loc_align to
	loc_range_bits.
	(module_for_ordinary_loc): Adjust.
	(module_state::note_location): Note ordinary locations,
	return bool.
	(module_state::write_location): Adjust ordinary location
	streaming.
	(module_state::read_location): Likewise.
	(module_state::write_init_maps): Allocate ord_loc_table.
	(module_state::write_prepare_maps): Reimplement ordinary
	map preparation.
	(module_state::read_prepare_maps): Adjust.
	(module_state::write_ordinary_maps): Reimplement.
	(module_state::write_macro_maps): Adjust.
	(module_state::read_ordinary_maps): Reimplement.
	(module_state::write_macros): Adjust.
	(module_state::write_config): Adjust.
	(module_state::read_config): Adjust.
	(module_state::write_begin): Adjust.
	(module_state::read_initial): Adjust.
	gcc/testsuite/
	* g++.dg/modules/loc-prune-1.C: Adjust.
	* g++.dg/modules/loc-prune-4.C: New.
	* g++.dg/modules/pr98718_a.C: Adjust.
	* g++.dg/modules/pr98718_b.C: Adjust.
	* g++.dg/modules/pr99072.H: Adjust.
---
 gcc/cp/module.cc   | 625 -
 gcc/testsuite/g++.dg/modules/loc-prune-1.C |   2 +-
 gcc/testsuite/g++.dg/modules/loc-prune-4.C |  22 +
 gcc/testsuite/g++.dg/modules/pr98718_a.C   |   2 +-
 gcc/testsuite/g++.dg/modules/pr98718_b.C   |   2 +-
 gcc/testsuite/g++.dg/modules/pr99072.H |   4 +-
 6 files changed, 373 insertions(+), 284 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/loc-prune-4.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 238a5eb74d2..f27f4d091e5 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -3240,6 +3240,66 @@ public:
 
 static loc_spans spans;
 
+/* Information about ordinary locations we stream out.  */
+struct ord_loc_info
+{
+  const line_map_ordinary *src; // line map we're based on
+  unsigned offset;	// offset to this line
+  unsigned span;	// number of locs we span
+  unsigned remap;	// serialization
+
+  static int compare (const void *a_, const void *b_)
+  {
+auto *a = static_cast (a_);
+auto *b = static_cast (b_);
+
+if (a->src != b->src)
+  return a->src < b->src ? -1 : +1;
+
+// Ensure no overlap
+gcc_checking_assert (a->offset + a->span <= b->offset
+			 || b->offset + b->span <= a->offset);
+
+gcc_checking_assert (a->offset != b->offset);
+return a->offset < b->offset ? -1 : +1;
+  }
+};
+struct ord_loc_traits
+{
+  typedef ord_loc_info value_type;
+  typedef value_type compare_type;
+
+  static const bool empty_zero_p = false;
+
+  static hashval_t hash (const value_type )
+  {
+auto h = pointer_hash::hash (v.src);
+return iterative_hash_hashval_t (v.offset, h);
+  }
+  static bool equal (const value_type , const compare_type p)
+  {
+return v.src == p.src && v.offset == p.offset;
+  }
+
+  static void mark_empty (value_type )
+  {
+v.src = nullptr;
+  }

c++: Note macro locations

2022-06-30 Thread Nathan Sidwell via Gcc-patches


In order to prune ordinary locations, we need to note the locations of 
macros we'll be writing out.  This reaaranges the macro processing to 
achieve that.  Also drop an unneeded parameter from macro reading & writing.


Fix some it's/its errors.

nathan

--
Nathan SidwellFrom 47e36785cd2ba35a577b0678a2ac185288eb9e52 Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Mon, 27 Jun 2022 07:51:12 -0700
Subject: [PATCH] c++: Note macro locations

In order to prune ordinary locations, we need to note the locations of
macros we'll be writing out.  This rearanges the macro processing to achieve
that.  Also drop an unneeded parameter from macro reading & writing.

Fix some it's/its errors.

	gcc/cp/
	* module.cc (module_state::write_define): Drop located param.
	(module_state::read_define): Likewise.
	(module_state::prepare_macros): New, broken out of ...
	(module_state::write_macros): ... here.  Adjust.
	(module_state::write_begin): Adjust.
	gcc/testsuite/
	* g++.dg/modules/inext-1.H: Check include-next happened.
---
 gcc/cp/module.cc   | 98 +-
 gcc/testsuite/g++.dg/modules/inext-1.H |  1 +
 2 files changed, 67 insertions(+), 32 deletions(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 68a7ce53ee4..238a5eb74d2 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -2281,7 +2281,7 @@ public:
 EK_EXPLICIT_HWM,  
 EK_BINDING = EK_EXPLICIT_HWM, /* Implicitly encoded.  */
 EK_FOR_BINDING,	/* A decl being inserted for a binding.  */
-EK_INNER_DECL,	/* A decl defined outside of it's imported
+EK_INNER_DECL,	/* A decl defined outside of its imported
 			   context.  */
 EK_DIRECT_HWM = EK_PARTIAL + 1,
 
@@ -3663,9 +3663,10 @@ class GTY((chain_next ("%h.parent"), for_user)) module_state {
   bool read_macro_maps (unsigned);
 
  private:
-  void write_define (bytes_out &, const cpp_macro *, bool located = true);
-  cpp_macro *read_define (bytes_in &, cpp_reader *, bool located = true) const;
-  unsigned write_macros (elf_out *to, cpp_reader *, unsigned *crc_ptr);
+  void write_define (bytes_out &, const cpp_macro *);
+  cpp_macro *read_define (bytes_in &, cpp_reader *) const;
+  vec *prepare_macros (cpp_reader *);
+  unsigned write_macros (elf_out *to, vec *, unsigned *crc_ptr);
   bool read_macros ();
   void install_macros ();
 
@@ -7136,7 +7137,7 @@ trees_in::tree_node_vals (tree t)
 }
 
 
-/* If T is a back reference, fixed reference or NULL, write out it's
+/* If T is a back reference, fixed reference or NULL, write out its
code and return WK_none.  Otherwise return WK_value if we must write
by value, or WK_normal otherwise.  */
 
@@ -10605,7 +10606,7 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
 
 /* DECL is a new declaration that may be duplicated in OVL.  Use RET &
ARGS to find its clone, or NULL.  If DECL's DECL_NAME is NULL, this
-   has been found by a proxy.  It will be an enum type located by it's
+   has been found by a proxy.  It will be an enum type located by its
first member.
 
We're conservative with matches, so ambiguous decls will be
@@ -11615,7 +11616,7 @@ trees_in::read_var_def (tree decl, tree maybe_template)
 }
 
 /* If MEMBER doesn't have an independent life outside the class,
-   return it (or it's TEMPLATE_DECL).  Otherwise NULL.  */
+   return it (or its TEMPLATE_DECL).  Otherwise NULL.  */
 
 static tree
 member_owned_by_class (tree member)
@@ -15405,7 +15406,7 @@ module_state::read_entities (unsigned count, unsigned lwm, unsigned hwm)
sure the specified entities are loaded.
 
An optimization might be to have a flag in each key-entity saying
-   that it's top key might be in the entity table.  It's not clear to
+   that its top key might be in the entity table.  It's not clear to
me how to set that flag cheaply -- cheaper than just looking.
 
FIXME: It'd be nice to have a bit in decls to tell us whether to
@@ -16444,7 +16445,7 @@ module_state::read_macro_maps (unsigned num_macro_locs)
 /* Serialize the definition of MACRO.  */
 
 void
-module_state::write_define (bytes_out , const cpp_macro *macro, bool located)
+module_state::write_define (bytes_out , const cpp_macro *macro)
 {
   sec.u (macro->count);
 
@@ -16453,8 +16454,7 @@ module_state::write_define (bytes_out , const cpp_macro *macro, bool located
   sec.b (macro->syshdr);
   sec.bflush ();
 
-  if (located)
-write_location (sec, macro->line);
+  write_location (sec, macro->line);
   if (macro->fun_like)
 {
   sec.u (macro->paramc);
@@ -16467,8 +16467,7 @@ module_state::write_define (bytes_out , const cpp_macro *macro, bool located
   for (unsigned ix = 0; ix != macro->count; ix++)
 {
   const cpp_token *token = >exp.tokens[ix];
-  if (located)
-	write_location (sec, token->src_loc);
+  write_location (sec, token->src_loc);
   sec.u (token->type);
   sec.u (token->

c++: Rename macro location structs

2022-06-29 Thread Nathan Sidwell via Gcc-patches

The macro location tables should really mention they are about
locations.  So rename them.  Also, add a missing free of the remapping
table, and remove some now-unneeded macro checking.


nathan

--
Nathan SidwellFrom b0f25e1fdc6199725e69023a3dc49021f311ba66 Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Fri, 24 Jun 2022 05:17:24 -0700
Subject: [PATCH] c++: Rename macro location structs

The macro location tables should really mention they are about
locations.  So rename them.  Also, add a missing free of the remapping
table, and remove some now-unneeded macro checking.

	gcc/cp/
	* module.cc (macro_info, macro_traits, macro_table,
	macro_remap): Rename to ...
	(macro_loc_info, macro_loc_traits, macro_loc_table,
	macro_loc_remap): ... these.  Update all uses.
	(module_state::write_prepare_maps): Remove unneeded macro checking.
	(module_state::write_begin): Free macro_loc_remap.
---
 gcc/cp/module.cc | 73 +---
 1 file changed, 25 insertions(+), 48 deletions(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 8bb22c2b305..68a7ce53ee4 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -3241,15 +3241,15 @@ public:
 static loc_spans spans;
 
 /* Information about macro locations we stream out.  */
-struct macro_info
+struct macro_loc_info
 {
   const line_map_macro *src;// original expansion
   unsigned remap;	  // serialization
 
   static int compare (const void *a_, const void *b_)
   {
-auto *a = static_cast (a_);
-auto *b = static_cast (b_);
+auto *a = static_cast (a_);
+auto *b = static_cast (b_);
 
 gcc_checking_assert (MAP_START_LOCATION (a->src)
 			 != MAP_START_LOCATION (b->src));
@@ -3259,9 +3259,9 @@ struct macro_info
   return +1;
   }
 };
-struct macro_traits
+struct macro_loc_traits
 {
-  typedef macro_info value_type;
+  typedef macro_loc_info value_type;
   typedef const line_map_macro *compare_type;
 
   static const bool empty_zero_p = false;
@@ -3294,9 +3294,9 @@ struct macro_traits
   static void remove (value_type &) {}
 };
 /* Table keyed by line_map_macro, used for noting.  */
-static  hash_table *macro_table;
+static  hash_table *macro_loc_table;
 /* Sorted vector, used for writing.  */
-static vec *macro_remap;
+static vec *macro_loc_remap;
 
 /* Indirection to allow bsearching imports by ordinary location.  */
 static vec *ool;
@@ -15616,7 +15616,7 @@ module_state::imported_from () const
 void
 module_state::note_location (location_t loc)
 {
-  if (!macro_table)
+  if (!macro_loc_table)
 ;
   else if (loc < RESERVED_LOCATION_COUNT)
 ;
@@ -15635,9 +15635,9 @@ module_state::note_location (location_t loc)
 	{
 	  const line_map *map = linemap_lookup (line_table, loc);
 	  const line_map_macro *mac_map = linemap_check_macro (map);
-	  hashval_t hv = macro_traits::hash (mac_map);
-	  macro_info *slot
-	= macro_table->find_slot_with_hash (mac_map, hv, INSERT);
+	  hashval_t hv = macro_loc_traits::hash (mac_map);
+	  macro_loc_info *slot
+	= macro_loc_table->find_slot_with_hash (mac_map, hv, INSERT);
 	  if (!slot->src)
 	{
 	  slot->src = mac_map;
@@ -15698,11 +15698,11 @@ module_state::write_location (bytes_out , location_t loc)
 }
   else if (loc >= LINEMAPS_MACRO_LOWEST_LOCATION (line_table))
 {
-  const macro_info *info = nullptr;
+  const macro_loc_info *info = nullptr;
   unsigned offset = 0;
-  if (unsigned hwm = macro_remap->length ())
+  if (unsigned hwm = macro_loc_remap->length ())
 	{
-	  info = macro_remap->begin ();
+	  info = macro_loc_remap->begin ();
 	  while (hwm != 1)
 	{
 	  unsigned mid = hwm / 2;
@@ -15909,7 +15909,7 @@ module_state::read_location (bytes_in ) const
 void
 module_state::write_init_maps ()
 {
-  macro_table = new hash_table (EXPERIMENT (1, 400));
+  macro_loc_table = new hash_table (EXPERIMENT (1, 400));
 }
 
 location_map_info
@@ -15955,30 +15955,6 @@ module_state::write_prepare_maps (module_state_config *cfg)
 
 	  info.num_maps.first += omap - fmap;
 	}
-
-  if (span.macro.first != span.macro.second)
-	{
-	  /* Iterate over the span's macros, to elide the empty
-	 expansions.  */
-	  unsigned count = 0;
-	  for (unsigned macro
-		 = linemap_lookup_macro_index (line_table,
-	   span.macro.second - 1);
-	   macro < LINEMAPS_MACRO_USED (line_table);
-	   macro++)
-	{
-	  line_map_macro const *mmap
-		= LINEMAPS_MACRO_MAP_AT (line_table, macro);
-	  if (MAP_START_LOCATION (mmap) < span.macro.first)
-		/* Fallen out of the span.  */
-		break;
-
-	  if (mmap->n_tokens)
-		count++;
-	}
-	  dump (dumper::LOCATION) && dump ("Span:%u %u macro maps", ix, count);
-	  info.num_maps.second += count;
-	}
 }
 
   /* Adjust the maps.  Ordinary ones ascend, and we must maintain
@@ -16024,23 +16000,23 @@ module_state::write_prepare_maps (module_state_config *cfg)
   ord_off = span.ordinary.second + s

c++: Prune unneeded macro locations

2022-06-23 Thread Nathan Sidwell via Gcc-patches


This implements garbage collection on locations within macro
expansions, when streaming out a CMI.  When doing the reachability
walks, we now note which macro locations we need and then only write
those locations.  The complication here is that every macro expansion
location has an independently calculated offset.  This complicates
writing, but reading remains the same -- the macro locations of a CMI
continue to form a contiguous block.

For std headers this reduced the number of macro maps by 40% and the
number of locations by 16%.  For a GMF including iostream, it reduced
it by 80% and 60% respectively.

Ordinary locations are still transformed en-mass.  They are somewhat
more complicated to apply a similar optimization to.

nathan

--
Nathan SidwellFrom 445cc1266ff8b9b8f96eceafa3c1116da54de967 Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Wed, 22 Jun 2022 05:54:30 -0700
Subject: [PATCH] c++: Prune unneeded macro locations

This implements garbage collection on locations within macro
expansions, when streaming out a CMI.  When doing the reachability
walks, we now note which macro locations we need and then only write
those locations.  The complication here is that every macro expansion
location has an independently calculated offset.  This complicates
writing, but reading remains the same -- the macro locations of a CMI
continue to form a contiguous block.

For std headers this reduced the number of macro maps by 40% and the
number of locations by 16%.  For a GMF including iostream, it reduced
it by 80% and 60% respectively.

Ordinary locations are still transformed en-mass.  They are somewhat
more complicated to apply a similar optimization to.

	gcc/cp/
	* module.cc (struct macro_info): New.
	(struct macro_traits): New.
	(macro_remap, macro_table): New globals.
	(depset::hash::find_dependencies): Note namespace location.
	(module_for_macro_loc): Adjust.
	(module_state::note_location): New.
	(module_state::Write_location): Note location when not
	streaming. Adjust macro location streaming.
	(module_state::read_location): Adjust macro location
	streaming.
	(module_state::write_init_maps): New.
	(module_state::write_prepare_maps): Reimplement macro map
	preparation.
	(module_state::write_macro_maps): Reimplement.
	(module_state::read_macro_maps): Likewise.
	(module_state::write_begin): Adjust.
	gcc/testsuite/
	* g++.dg/modules/loc-prune-1.C: New.
	* g++.dg/modules/loc-prune-2.C: New.
	* g++.dg/modules/loc-prune-3.C: New.
	* g++.dg/modules/pr98718_a.C: Adjust.
	* g++.dg/modules/pr98718_b.C: Adjust.
---
 gcc/cp/module.cc   | 349 ++---
 gcc/testsuite/g++.dg/modules/loc-prune-1.C |  19 ++
 gcc/testsuite/g++.dg/modules/loc-prune-2.C |  14 +
 gcc/testsuite/g++.dg/modules/loc-prune-3.C |  16 +
 gcc/testsuite/g++.dg/modules/pr98718_a.C   |   4 +-
 gcc/testsuite/g++.dg/modules/pr98718_b.C   |   6 +-
 6 files changed, 290 insertions(+), 118 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/loc-prune-1.C
 create mode 100644 gcc/testsuite/g++.dg/modules/loc-prune-2.C
 create mode 100644 gcc/testsuite/g++.dg/modules/loc-prune-3.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index d735d7e8b30..7ee779d06b9 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -3238,6 +3238,65 @@ public:
 };
 
 static loc_spans spans;
+
+/* Information about macro locations we stream out.  */
+struct macro_info
+{
+  const line_map_macro *src;// original expansion
+  unsigned remap;	  // serialization
+
+  static int compare (const void *a_, const void *b_)
+  {
+auto *a = static_cast (a_);
+auto *b = static_cast (b_);
+
+gcc_checking_assert (MAP_START_LOCATION (a->src)
+			 != MAP_START_LOCATION (b->src));
+if (MAP_START_LOCATION (a->src) < MAP_START_LOCATION (b->src))
+  return -1;
+else
+  return +1;
+  }
+};
+struct macro_traits
+{
+  typedef macro_info value_type;
+  typedef const line_map_macro *compare_type;
+
+  static const bool empty_zero_p = false;
+
+  static hashval_t hash (compare_type p)
+  {
+return pointer_hash::hash (p);
+  }
+  static hashval_t hash (const value_type )
+  {
+return hash (v.src);
+  }
+  static bool equal (const value_type , const compare_type p)
+  {
+return v.src == p;
+  }
+
+  static void mark_empty (value_type )
+  {
+v.src = nullptr;
+  }
+  static bool is_empty (value_type )
+  {
+return !v.src;
+  }
+
+  static bool is_deleted (value_type &) { return false; }
+  static void mark_deleted (value_type &) { gcc_unreachable (); }
+  
+  static void remove (value_type &) {}
+};
+/* Table keyed by line_map_macro, used for noting.  */
+static  hash_table *macro_table;
+/* Sorted vector, used for writing.  */
+static vec *macro_remap;
+
 /* Indirection to allow bsearching imports by ordinary location.  */
 static vec *ool;
 
@@ -3398,7 +3457,7 @@ class GTY((chain_next ("%h.parent"), for_user)) module_state {
   /* Location ranges for this m

c++: Remove ifdefed code

2022-06-22 Thread Nathan Sidwell via Gcc-patches

The only reason I chose to use DECL_UID on this hash table was to make
it stable against ASLR and perturbations due to other allocations.
It's not required for correctness, as the comment mentions the
equality fn uses pointer identity.

nathan

--
Nathan SidwellFrom d844478ab47a16c8ae65f253fd1cdc685c7951fc Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Wed, 22 Jun 2022 07:51:44 -0700
Subject: [PATCH] c++: Remove ifdefed code

The only reason I chose to use DECL_UID on this hash table was to make
it stable against ASLR and perturbations due to other allocations.
It's not required for correctness, as the comment mentions the
equality fn uses pointer identity.

	gcc/cp/
	* module.cc (struct duplicate_hash): Remove.
	(duplicate_hash_map): Adjust.
---
 gcc/cp/module.cc | 16 +---
 1 file changed, 1 insertion(+), 15 deletions(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index b3fbd467ecb..d735d7e8b30 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -2829,24 +2829,10 @@ struct merge_key {
   }
 };
 
-struct duplicate_hash : nodel_ptr_hash
-{
-#if 0
-  /* This breaks variadic bases in the xtreme_header tests.  Since ::equal is
- the default pointer_hash::equal, let's use the default hash as well.  */
-  inline static hashval_t hash (value_type decl)
-  {
-if (TREE_CODE (decl) == TREE_BINFO)
-  decl = TYPE_NAME (BINFO_TYPE (decl));
-return hashval_t (DECL_UID (decl));
-  }
-#endif
-};
-
 /* Hashmap of merged duplicates.  Usually decls, but can contain
BINFOs.  */
 typedef hash_map >
+		 simple_hashmap_traits,uintptr_t> >
 duplicate_hash_map;
 
 /* Tree stream reader.  Note that reading a stream doesn't mark the
-- 
2.30.2



doc: Document module language-linkage supported

2022-06-21 Thread Nathan Sidwell via Gcc-patches


I missed we documented this as unimplemented, when I implemented it.


--
Nathan SidwellFrom f1fcd6e3ad911945bc3c24a3a5c7ea99b910121e Mon Sep 17 00:00:00 2001
From: Nathan Sidwell 
Date: Tue, 21 Jun 2022 06:23:11 -0700
Subject: [PATCH] doc: Document module language-linkage supported

I missed we documented this as unimplemented, when I implemented it.

	gcc/
	* doc/invoke.texi (C++ Modules): Remove language-linkage
	as missing feature.
---
 gcc/doc/invoke.texi | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 50f57877477..81d13f4e78e 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -34639,13 +34639,6 @@ Papers p1815 (@uref{https://wg21.link/p1815}) and p2003
 exported region may reference (for instance, the entities an exported
 template definition may reference).  These are not fully implemented.
 
-@item Language-linkage module attachment
-Declarations with explicit language linkage (@code{extern "C"} or
-@code{extern "C++"}) are attached to the global module, even when in
-the purview of a named module.  This is not implemented.  Such
-declarations will be attached to the module, if any, in which they are
-declared.
-
 @item Standard Library Header Units
 The Standard Library is not provided as importable header units.  If
 you want to import such units, you must explicitly build them first.
-- 
2.30.2



  1   2   3   4   5   6   7   8   9   10   >