c++: header unit purview [PR 99283]

Message ID e347ba01-13bf-0e57-8722-63131c47c661@acm.org
State New
Headers show
Series
  • c++: header unit purview [PR 99283]
Related show

Commit Message

Nathan Sidwell April 2, 2021, 4:07 p.m.
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.
         * gcc/cp/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.
-- 
Nathan Sidwell

Patch

diff --git c/gcc/cp/cp-tree.h w/gcc/cp/cp-tree.h
index 9535910fd4e..66bba7b4d43 100644
--- c/gcc/cp/cp-tree.h
+++ w/gcc/cp/cp-tree.h
@@ -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 &
diff --git c/gcc/cp/module.cc w/gcc/cp/module.cc
index c87ddd16a80..d5b7d28ded5 100644
--- c/gcc/cp/module.cc
+++ w/gcc/cp/module.cc
@@ -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 c/gcc/testsuite/g++.dg/modules/pr99283-6_d.H w/gcc/testsuite/g++.dg/modules/pr99283-6_d.H
new file mode 100644
index 00000000000..e8114711f38
--- /dev/null
+++ w/gcc/testsuite/g++.dg/modules/pr99283-6_d.H
@@ -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 c/gcc/testsuite/g++.dg/modules/pr99283-7-swap.h w/gcc/testsuite/g++.dg/modules/pr99283-7-swap.h
new file mode 100644
index 00000000000..d725fea9ee5
--- /dev/null
+++ w/gcc/testsuite/g++.dg/modules/pr99283-7-swap.h
@@ -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 c/gcc/testsuite/g++.dg/modules/pr99283-7-traits.h w/gcc/testsuite/g++.dg/modules/pr99283-7-traits.h
new file mode 100644
index 00000000000..8f6bce04bee
--- /dev/null
+++ w/gcc/testsuite/g++.dg/modules/pr99283-7-traits.h
@@ -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 c/gcc/testsuite/g++.dg/modules/pr99283-7_a.H w/gcc/testsuite/g++.dg/modules/pr99283-7_a.H
new file mode 100644
index 00000000000..b52d44d5c26
--- /dev/null
+++ w/gcc/testsuite/g++.dg/modules/pr99283-7_a.H
@@ -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 c/gcc/testsuite/g++.dg/modules/pr99283-7_b.H w/gcc/testsuite/g++.dg/modules/pr99283-7_b.H
new file mode 100644
index 00000000000..50c780e096e
--- /dev/null
+++ w/gcc/testsuite/g++.dg/modules/pr99283-7_b.H
@@ -0,0 +1,4 @@ 
+// { dg-additional-options "-std=c++2a -fmodule-header" }
+// { dg-module-cmi {} }
+
+#include "pr99283-7-traits.h"
diff --git c/gcc/testsuite/g++.dg/modules/pr99283-7_c.C w/gcc/testsuite/g++.dg/modules/pr99283-7_c.C
new file mode 100644
index 00000000000..195bc684e40
--- /dev/null
+++ w/gcc/testsuite/g++.dg/modules/pr99283-7_c.C
@@ -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 c/gcc/testsuite/g++.dg/modules/pr99283-7_d.H w/gcc/testsuite/g++.dg/modules/pr99283-7_d.H
new file mode 100644
index 00000000000..ef4934beac0
--- /dev/null
+++ w/gcc/testsuite/g++.dg/modules/pr99283-7_d.H
@@ -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);