c++: header unit purview [PR 99283]

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.
This commit is contained in:
Nathan Sidwell 2021-04-02 06:28:29 -07:00
parent c844918279
commit f4e05eebd6
9 changed files with 197 additions and 9 deletions

View 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 &

View 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

View File

@ -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>;
};

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
};

View File

@ -0,0 +1,4 @@
// { dg-additional-options "-std=c++2a -fmodule-header" }
// { dg-module-cmi {} }
#include "pr99283-7-traits.h"

View File

@ -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);

View File

@ -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);