c++: header unit purview [PR 99283]
authorNathan Sidwell <nathan@acm.org>
Fri, 2 Apr 2021 13:28:29 +0000 (06:28 -0700)
committerNathan Sidwell <nathan@acm.org>
Fri, 2 Apr 2021 16:08:28 +0000 (09:08 -0700)
This case occurs due to some equivocation about module_purview.
Header-unit building is treated as a module-purview, but we should not
treat entities imported from that as module purview.  (header units
were not a thing when I started).  The testcase didn't understand we
had a local textual definition, but it was (incorrectly) marked as
module-purview, because we'd read in a declaration from a header unit
too.

gcc/cp/
* cp-tree.h (lang_decl_base): Correct module flag comment.
* module.cc (trees_in::assert_definition): Break out
not_tmpl var.
(trees_out::lang_decl_bools): Do not write purview for header units.
gcc/testsuite/
* g++.dg/modules/pr99283-6_d.H: New.
* g++.dg/modules/pr99283-7-swap.h: New.
* g++.dg/modules/pr99283-7-traits.h: New.
* g++.dg/modules/pr99283-7_a.H: New.
* g++.dg/modules/pr99283-7_b.H: New.
* g++.dg/modules/pr99283-7_c.C: New.
* g++.dg/modules/pr99283-7_d.H: New.

gcc/cp/cp-tree.h
gcc/cp/module.cc
gcc/testsuite/g++.dg/modules/pr99283-6_d.H [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/pr99283-7-swap.h [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/pr99283-7-traits.h [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/pr99283-7_a.H [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/pr99283-7_b.H [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/pr99283-7_c.C [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/pr99283-7_d.H [new file with mode: 0644]

index 9535910..66bba7b 100644 (file)
@@ -2756,8 +2756,8 @@ struct GTY(()) lang_decl_base {
   unsigned var_declared_inline_p : 1;     /* var */
   unsigned dependent_init_p : 1;          /* var */
 
-  /* The following apply to VAR, FUNCTION, TYPE, CONCEPT, TEMPLATE,
-     NAMESPACE decls.  */
+  /* The following apply to VAR, FUNCTION, TYPE, CONCEPT, & NAMESPACE
+     decls.  */
   unsigned module_purview_p : 1;          /* in module purview (not GMF) */
   unsigned module_import_p : 1;           /* from an import */
   unsigned module_entity_p : 1;                   /* is in the entitity ary &
index c87ddd1..d5b7d28 100644 (file)
@@ -4477,6 +4477,7 @@ trees_in::assert_definition (tree decl ATTRIBUTE_UNUSED,
 {
 #if CHECKING_P
   tree *slot = note_defs->find_slot (decl, installing ? INSERT : NO_INSERT);
+  tree not_tmpl = STRIP_TEMPLATE (decl);
   if (installing)
     {
       /* We must be inserting for the first time.  */
@@ -4492,13 +4493,13 @@ trees_in::assert_definition (tree decl ATTRIBUTE_UNUSED,
     gcc_assert (!is_duplicate (decl)
                ? !slot
                : (slot
-                  || !DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
-                  || !DECL_MODULE_PURVIEW_P (STRIP_TEMPLATE (decl))
-                  || (!DECL_MODULE_IMPORT_P (STRIP_TEMPLATE (decl))
+                  || !DECL_LANG_SPECIFIC (not_tmpl)
+                  || !DECL_MODULE_PURVIEW_P (not_tmpl)
+                  || (!DECL_MODULE_IMPORT_P (not_tmpl)
                       && header_module_p ())));
 
-  if (TREE_CODE (decl) == TEMPLATE_DECL)
-    gcc_assert (!note_defs->find_slot (DECL_TEMPLATE_RESULT (decl), NO_INSERT));
+  if (not_tmpl != decl)
+    gcc_assert (!note_defs->find_slot (not_tmpl, NO_INSERT));
 #endif
 }
 
@@ -5519,7 +5520,9 @@ trees_out::lang_decl_bools (tree t)
   WB (lang->u.base.concept_p);
   WB (lang->u.base.var_declared_inline_p);
   WB (lang->u.base.dependent_init_p);
-  WB (lang->u.base.module_purview_p);
+  /* When building a header unit, everthing is marked as purview, but
+     that's the GM purview, so not what the importer will mean  */
+  WB (lang->u.base.module_purview_p && !header_module_p ());
   if (VAR_OR_FUNCTION_DECL_P (t))
     WB (lang->u.base.module_attached_p);
   switch (lang->u.base.selector)
@@ -11304,7 +11307,7 @@ trees_in::register_duplicate (tree decl, tree existing)
 /* We've read a definition of MAYBE_EXISTING.  If not a duplicate,
    return MAYBE_EXISTING (into which the definition should be
    installed).  Otherwise return NULL if already known bad, or the
-   duplicate we read (for ODR checking, or extracting addtional merge
+   duplicate we read (for ODR checking, or extracting additional merge
    information).  */
 
 tree
diff --git a/gcc/testsuite/g++.dg/modules/pr99283-6_d.H b/gcc/testsuite/g++.dg/modules/pr99283-6_d.H
new file mode 100644 (file)
index 0000000..e811471
--- /dev/null
@@ -0,0 +1,10 @@
+// { dg-additional-options {-std=c++2a -fmodule-header} }
+
+import  "pr99283-6_b.H";
+
+template<typename _Alloc>
+struct __allocated_ptr
+{
+  using value_type = allocator_traits<_Alloc>;
+};
+
diff --git a/gcc/testsuite/g++.dg/modules/pr99283-7-swap.h b/gcc/testsuite/g++.dg/modules/pr99283-7-swap.h
new file mode 100644 (file)
index 0000000..d725fea
--- /dev/null
@@ -0,0 +1,17 @@
+template<typename _Tp>
+constexpr typename remove_reference<_Tp>::type&&
+  move(_Tp&& __t) noexcept;
+
+template<typename _Tp>
+constexpr inline
+typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>,
+                         is_move_constructible<_Tp>,
+                         is_move_assignable<_Tp>>::value>::type
+  swap(_Tp& __a, _Tp& __b)
+  noexcept(__and_<is_nothrow_move_constructible<_Tp>,
+          is_nothrow_move_assignable<_Tp>>::value)
+{
+  _Tp __tmp = move(__a);
+  __a = move(__b);
+  __b = move(__tmp);
+}
diff --git a/gcc/testsuite/g++.dg/modules/pr99283-7-traits.h b/gcc/testsuite/g++.dg/modules/pr99283-7-traits.h
new file mode 100644 (file)
index 0000000..8f6bce0
--- /dev/null
@@ -0,0 +1,41 @@
+template<typename...>
+struct __and_;
+
+template<typename _Pp>
+struct __not_;
+
+template<typename _Tp>
+struct is_move_constructible;
+
+template<typename _Tp>
+struct is_nothrow_move_constructible;
+
+template<typename _Tp>
+struct is_move_assignable;
+
+template<typename _Tp>
+struct is_nothrow_move_assignable;
+
+template<typename _Tp>
+struct remove_reference;
+
+template<bool, typename _Tp = void>
+struct enable_if;
+
+template<bool _Cond, typename _Tp = void>
+using __enable_if_t = typename enable_if<_Cond, _Tp>::type;
+
+template<typename... _Cond>
+using _Require = __enable_if_t<__and_<_Cond...>::value>;
+
+template<typename _Tp>
+struct __is_tuple_like;
+
+template<typename _Tp>
+constexpr inline
+  _Require<__not_<__is_tuple_like<_Tp>>,
+          is_move_constructible<_Tp>,
+          is_move_assignable<_Tp>>
+swap(_Tp&, _Tp&)
+  noexcept(__and_<is_nothrow_move_constructible<_Tp>,
+          is_nothrow_move_assignable<_Tp>>::value);
diff --git a/gcc/testsuite/g++.dg/modules/pr99283-7_a.H b/gcc/testsuite/g++.dg/modules/pr99283-7_a.H
new file mode 100644 (file)
index 0000000..b52d44d
--- /dev/null
@@ -0,0 +1,97 @@
+// PR 99283,
+// { dg-additional-options "-std=c++2a -fmodule-header" }
+// { dg-module-cmi {} }
+
+#include "pr99283-7-traits.h"
+
+template<class _CharT>
+struct char_traits;
+
+template<typename _CharT, typename _Traits = char_traits<_CharT>>
+class basic_string;
+
+typedef basic_string<char> string;
+
+template<typename _Tp, _Tp __v>
+struct integral_constant
+{
+  static constexpr _Tp value = __v;
+  typedef _Tp value_type;
+  typedef integral_constant<_Tp, __v> type;
+  constexpr operator value_type() const noexcept { return value; }
+  constexpr value_type operator()() const noexcept { return value; }
+};
+
+template<typename _Tp, _Tp __v>
+constexpr _Tp integral_constant<_Tp, __v>::value;
+
+typedef integral_constant<bool, true> true_type;
+
+typedef integral_constant<bool, false> false_type;
+
+template<bool __v>
+using __bool_constant = integral_constant<bool, __v>;
+
+template<typename _Tp, typename _Up = _Tp&&>
+_Up __declval(int);
+
+template<typename _Tp>
+_Tp __declval(long);
+
+template<typename _Tp>
+auto declval() noexcept -> decltype(__declval<_Tp>(0));
+
+struct __do_is_nothrow_swappable_impl
+{
+  template<typename _Tp>
+  static __bool_constant<
+    noexcept(swap(declval<_Tp&>(), declval<_Tp&>()))
+    > __test(int);
+};
+
+
+
+template<typename _Tp>
+struct __is_nothrow_swappable_impl
+  : public __do_is_nothrow_swappable_impl
+{
+  typedef decltype(__test<_Tp>(0)) type;
+};
+
+template<typename _Tp>
+struct __is_nothrow_swappable
+  : public __is_nothrow_swappable_impl<_Tp>::type
+{ };
+
+#include "pr99283-7-swap.h"
+
+class partial_ordering
+{
+public:
+  friend constexpr bool
+    operator==(partial_ordering, partial_ordering) noexcept = default;
+};
+
+class strong_ordering
+{
+public:
+  constexpr operator partial_ordering() const noexcept;
+};
+
+template<typename _T1, typename _T2>
+struct pair
+{
+  constexpr void
+    swap(pair& __p)
+    noexcept(__is_nothrow_swappable<_T1>::value);
+};
+
+template<typename _T1, typename _T2>
+inline constexpr bool
+  operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y);
+       
+template<typename _CharT>
+struct char_traits
+{
+  using comparison_category = strong_ordering;
+};
diff --git a/gcc/testsuite/g++.dg/modules/pr99283-7_b.H b/gcc/testsuite/g++.dg/modules/pr99283-7_b.H
new file mode 100644 (file)
index 0000000..50c780e
--- /dev/null
@@ -0,0 +1,4 @@
+// { dg-additional-options "-std=c++2a -fmodule-header" }
+// { dg-module-cmi {} }
+
+#include "pr99283-7-traits.h"
diff --git a/gcc/testsuite/g++.dg/modules/pr99283-7_c.C b/gcc/testsuite/g++.dg/modules/pr99283-7_c.C
new file mode 100644 (file)
index 0000000..195bc68
--- /dev/null
@@ -0,0 +1,8 @@
+// { dg-additional-options "-std=c++2a -fmodules-ts" }
+import  "pr99283-7_b.H";
+
+#include "pr99283-7-swap.h"
+
+import  "pr99283-7_a.H";
+
+void Xlocale(const string& __s);
diff --git a/gcc/testsuite/g++.dg/modules/pr99283-7_d.H b/gcc/testsuite/g++.dg/modules/pr99283-7_d.H
new file mode 100644 (file)
index 0000000..ef4934b
--- /dev/null
@@ -0,0 +1,8 @@
+// { dg-additional-options "-std=c++2a -fmodule-header" }
+import  "pr99283-7_b.H";
+
+#include "pr99283-7-swap.h"
+
+import  "pr99283-7_a.H";
+
+void Xlocale(const string& __s);