aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2021-03-18 05:12:59 -0700
committerNathan Sidwell <nathan@acm.org>2021-03-22 08:26:57 -0700
commit87e3c2ef682e2ba7692ee56142a4eb5b6441c4d3 (patch)
tree81c3b97add2b26466f93f5a2fa226b30258d91aa
parent150a829accd76ddd73c20628774cb0781f6e8bfe (diff)
downloadgcc-87e3c2ef682e2ba7692ee56142a4eb5b6441c4d3.zip
gcc-87e3c2ef682e2ba7692ee56142a4eb5b6441c4d3.tar.gz
gcc-87e3c2ef682e2ba7692ee56142a4eb5b6441c4d3.tar.bz2
c++: duplicate alias templates with decltype [PR 99425]
This failure was ultimately from incorrect handling of alias templates, but required a specific set of occurrences to happen in the specialization hash table. This cleans up the specialization streaming to add alias instantiations at the same point as other instantiations. I also removed some unneeded global variables dealing with mapping of duplicate decl contexts. PR c++/99425 gcc/cp/ * cp-tree.h (map_context_from, map_context_to): Delete. (add_mergeable_specialization): Add is_alias parm. * pt.c (add_mergeable_specialization): Add is_alias parm, add them. * module.cc (map_context_from, map_context_to): Delete. (trees_in::decl_value): Add specializations later, adjust call. Drop useless alias lookup. Set duplicate fn parm context. (check_mergeable_decl): Drop context mapping. (trees_in::is_matching_decl): Likewise. (trees_in::read_function_def): Drop parameter context adjustment here. gcc/testsuite/ * g++.dg/modules/pr99425-1.h: New. * g++.dg/modules/pr99425-1_a.H: New. * g++.dg/modules/pr99425-1_b.H: New. * g++.dg/modules/pr99425-1_c.C: New. * g++.dg/modules/pr99425-2_a.X: New. * g++.dg/modules/pr99425-2_b.X: New. * g++.dg/template/pr99425.C: New.
-rw-r--r--gcc/cp/cp-tree.h7
-rw-r--r--gcc/cp/module.cc82
-rw-r--r--gcc/cp/pt.c38
-rw-r--r--gcc/testsuite/g++.dg/modules/pr99425-1.h11
-rw-r--r--gcc/testsuite/g++.dg/modules/pr99425-1_a.H4
-rw-r--r--gcc/testsuite/g++.dg/modules/pr99425-1_b.H19
-rw-r--r--gcc/testsuite/g++.dg/modules/pr99425-1_c.C11
-rw-r--r--gcc/testsuite/g++.dg/modules/pr99425-2_a.X7
-rw-r--r--gcc/testsuite/g++.dg/modules/pr99425-2_b.X4
-rw-r--r--gcc/testsuite/g++.dg/template/pr99425.C45
10 files changed, 159 insertions, 69 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 81ff375..e68e390 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5444,10 +5444,6 @@ extern int comparing_specializations;
FIXME we should always do this except during deduction/ordering. */
extern int comparing_dependent_aliases;
-/* When comparing specializations permit context _FROM to match _TO. */
-extern tree map_context_from;
-extern tree map_context_to;
-
/* In parser.c. */
/* Nonzero if we are parsing an unevaluated operand: an operand to
@@ -7241,7 +7237,8 @@ extern void walk_specializations (bool,
void *);
extern tree match_mergeable_specialization (bool is_decl, spec_entry *);
extern unsigned get_mergeable_specialization_flags (tree tmpl, tree spec);
-extern void add_mergeable_specialization (bool is_decl, spec_entry *,
+extern void add_mergeable_specialization (bool is_decl, bool is_alias,
+ spec_entry *,
tree outer, unsigned);
extern tree add_outermost_template_args (tree, tree);
extern tree add_extra_args (tree, tree);
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 551cb66..ad3b7d5 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -279,11 +279,6 @@ static inline tree identifier (const cpp_hashnode *node)
return HT_IDENT_TO_GCC_IDENT (HT_NODE (const_cast<cpp_hashnode *> (node)));
}
-/* During duplicate detection we need to tell some comparators that
- these are equivalent. */
-tree map_context_from;
-tree map_context_to;
-
/* Id for dumping module information. */
int module_dump_id;
@@ -8074,16 +8069,6 @@ trees_in::decl_value ()
if (spec.spec)
set_constraints (decl, spec.spec);
- if (mk & MK_template_mask
- || mk == MK_partial)
- {
- /* Add to specialization tables now that constraints etc are
- added. */
- bool is_type = mk == MK_partial || !(mk & MK_tmpl_decl_mask);
-
- spec.spec = is_type ? type : mk & MK_tmpl_tmpl_mask ? inner : decl;
- add_mergeable_specialization (!is_type, &spec, decl, spec_flags);
- }
if (TREE_CODE (decl) == INTEGER_CST && !TREE_OVERFLOW (decl))
{
@@ -8111,28 +8096,25 @@ trees_in::decl_value ()
/* Set the TEMPLATE_DECL's type. */
TREE_TYPE (decl) = TREE_TYPE (inner);
+ if (mk & MK_template_mask
+ || mk == MK_partial)
+ {
+ /* Add to specialization tables now that constraints etc are
+ added. */
+ bool is_type = mk == MK_partial || !(mk & MK_tmpl_decl_mask);
+
+ spec.spec = is_type ? type : mk & MK_tmpl_tmpl_mask ? inner : decl;
+ add_mergeable_specialization (!is_type,
+ !is_type && mk & MK_tmpl_alias_mask,
+ &spec, decl, spec_flags);
+ }
+
if (NAMESPACE_SCOPE_P (decl)
&& (mk == MK_named || mk == MK_unique
|| mk == MK_enum || mk == MK_friend_spec)
&& !(VAR_OR_FUNCTION_DECL_P (decl) && DECL_LOCAL_DECL_P (decl)))
add_module_namespace_decl (CP_DECL_CONTEXT (decl), decl);
- /* The late insertion of an alias here or an implicit member
- (next block), is ok, because we ensured that all imports were
- loaded up before we started this cluster. Thus an insertion
- from some other import cannot have happened between the
- merged insertion above and these insertions down here. */
- if (mk == MK_alias_spec)
- {
- /* Insert into type table. */
- tree ti = DECL_TEMPLATE_INFO (inner);
- spec_entry elt =
- {TI_TEMPLATE (ti), TI_ARGS (ti), TREE_TYPE (inner)};
- tree texist = match_mergeable_specialization (false, &elt);
- if (texist)
- set_overrun ();
- }
-
if (DECL_ARTIFICIAL (decl)
&& TREE_CODE (decl) == FUNCTION_DECL
&& !DECL_TEMPLATE_INFO (decl)
@@ -8176,6 +8158,14 @@ trees_in::decl_value ()
if (!is_matching_decl (existing, decl, is_typedef))
unmatched_duplicate (existing);
+ if (inner && TREE_CODE (inner) == FUNCTION_DECL)
+ {
+ tree e_inner = STRIP_TEMPLATE (existing);
+ for (auto parm = DECL_ARGUMENTS (inner);
+ parm; parm = DECL_CHAIN (parm))
+ DECL_CONTEXT (parm) = e_inner;
+ }
+
/* And our result is the existing node. */
decl = existing;
}
@@ -8186,7 +8176,7 @@ trees_in::decl_value ()
if (!e)
{
spec.spec = inner;
- add_mergeable_specialization (true, &spec, decl, spec_flags);
+ add_mergeable_specialization (true, false, &spec, decl, spec_flags);
}
else if (e != existing)
set_overrun ();
@@ -10378,8 +10368,9 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
{
if (mk & MK_tmpl_alias_mask)
/* It should be in both tables. */
- gcc_assert (match_mergeable_specialization (false, entry)
- == TREE_TYPE (existing));
+ gcc_checking_assert
+ (match_mergeable_specialization (false, entry)
+ == TREE_TYPE (existing));
else if (mk & MK_tmpl_tmpl_mask)
existing = DECL_TI_TEMPLATE (existing);
}
@@ -10392,7 +10383,7 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
}
/* The walkabout should have found ourselves. */
- gcc_assert (existing == decl);
+ gcc_checking_assert (existing == decl);
}
}
else if (mk != MK_unique)
@@ -10622,8 +10613,6 @@ check_mergeable_decl (merge_kind mk, tree decl, tree ovl, merge_key const &key)
break;
case FUNCTION_DECL:
- map_context_from = d_inner;
- map_context_to = m_inner;
if (tree m_type = TREE_TYPE (m_inner))
if ((!key.ret
|| same_type_p (key.ret, fndecl_declared_return_type (m_inner)))
@@ -10647,7 +10636,6 @@ check_mergeable_decl (merge_kind mk, tree decl, tree ovl, merge_key const &key)
if (cp_tree_equal (key.constraints, m_reqs))
found = match;
}
- map_context_from = map_context_to = NULL_TREE;
break;
case TYPE_DECL:
@@ -11022,12 +11010,6 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
gcc_checking_assert (TREE_CODE (e_inner) == TREE_CODE (d_inner));
}
- gcc_checking_assert (!map_context_from);
- /* This mapping requres the new decl on the lhs and the existing
- entity on the rhs of the comparitors below. */
- map_context_from = d_inner;
- map_context_to = e_inner;
-
if (TREE_CODE (d_inner) == FUNCTION_DECL)
{
tree e_ret = fndecl_declared_return_type (existing);
@@ -11104,7 +11086,6 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
else if (!cp_tree_equal (TREE_TYPE (decl), TREE_TYPE (existing)))
{
mismatch:
- map_context_from = map_context_to = NULL_TREE;
if (DECL_IS_UNDECLARED_BUILTIN (existing))
/* Just like duplicate_decls, presum the user knows what
they're doing in overriding a builtin. */
@@ -11121,8 +11102,6 @@ trees_in::is_matching_decl (tree existing, tree decl, bool is_typedef)
}
}
- map_context_from = map_context_to = NULL_TREE;
-
if (DECL_IS_UNDECLARED_BUILTIN (existing)
&& !DECL_IS_UNDECLARED_BUILTIN (decl))
{
@@ -11463,10 +11442,6 @@ trees_in::read_function_def (tree decl, tree maybe_template)
tree maybe_dup = odr_duplicate (maybe_template, DECL_SAVED_TREE (decl));
bool installing = maybe_dup && !DECL_SAVED_TREE (decl);
- if (maybe_dup)
- for (auto parm = DECL_ARGUMENTS (maybe_dup); parm; parm = DECL_CHAIN (parm))
- DECL_CONTEXT (parm) = decl;
-
if (int wtag = i ())
{
int tag = 1;
@@ -12881,10 +12856,11 @@ specialization_add (bool decl_p, spec_entry *entry, void *data_)
|| DECL_CLASS_TEMPLATE_P (entry->tmpl));
/* Only alias templates can appear in both tables (and
- if they're in the type table they must also be in the decl table). */
+ if they're in the type table they must also be in the decl
+ table). */
gcc_checking_assert
(!match_mergeable_specialization (true, entry)
- == (decl_p || !DECL_ALIAS_TEMPLATE_P (entry->tmpl)));
+ == !DECL_ALIAS_TEMPLATE_P (entry->tmpl));
}
else if (VAR_OR_FUNCTION_DECL_P (entry->spec))
gcc_checking_assert (!DECL_LOCAL_DECL_P (entry->spec));
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 933dfc3..2736bb4 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -30009,25 +30009,41 @@ get_mergeable_specialization_flags (tree tmpl, tree decl)
get_mergeable_specialization_flags. */
void
-add_mergeable_specialization (bool decl_p, spec_entry *elt,
+add_mergeable_specialization (bool decl_p, bool alias_p, spec_entry *elt,
tree decl, unsigned flags)
{
- hash_table<spec_hasher> *specializations
- = decl_p ? decl_specializations : type_specializations;
-
hashval_t hash = spec_hasher::hash (elt);
- auto *slot = specializations->find_slot_with_hash (elt, hash, INSERT);
-
- /* We don't distinguish different constrained partial type
- specializations, so there could be duplicates. Everything else
- must be new. */
- if (!(flags & 2 && *slot))
+ if (decl_p)
{
- gcc_checking_assert (!*slot);
+ auto *slot = decl_specializations->find_slot_with_hash (elt, hash, INSERT);
+ gcc_checking_assert (!*slot);
auto entry = ggc_alloc<spec_entry> ();
*entry = *elt;
*slot = entry;
+
+ if (alias_p)
+ {
+ elt->spec = TREE_TYPE (elt->spec);
+ gcc_checking_assert (elt->spec);
+ }
+ }
+
+ if (!decl_p || alias_p)
+ {
+ auto *slot = type_specializations->find_slot_with_hash (elt, hash, INSERT);
+
+ /* We don't distinguish different constrained partial type
+ specializations, so there could be duplicates. Everything else
+ must be new. */
+ if (!(flags & 2 && *slot))
+ {
+ gcc_checking_assert (!*slot);
+
+ auto entry = ggc_alloc<spec_entry> ();
+ *entry = *elt;
+ *slot = entry;
+ }
}
if (flags & 1)
diff --git a/gcc/testsuite/g++.dg/modules/pr99425-1.h b/gcc/testsuite/g++.dg/modules/pr99425-1.h
new file mode 100644
index 0000000..de167a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr99425-1.h
@@ -0,0 +1,11 @@
+template<typename T>
+struct make_signed
+{
+ using type = int;
+};
+
+template<typename S>
+using make_signed_t = typename make_signed<S>::type;
+
+template<typename U>
+auto ssize (U &parm) -> make_signed_t<decltype(parm.call())>;
diff --git a/gcc/testsuite/g++.dg/modules/pr99425-1_a.H b/gcc/testsuite/g++.dg/modules/pr99425-1_a.H
new file mode 100644
index 0000000..6117d4a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr99425-1_a.H
@@ -0,0 +1,4 @@
+// PR 99425 alias dependent specializations
+// { dg-additional-options {-fmodule-header} }
+// { dg-module-cmi {} }
+#include "pr99425-1.h"
diff --git a/gcc/testsuite/g++.dg/modules/pr99425-1_b.H b/gcc/testsuite/g++.dg/modules/pr99425-1_b.H
new file mode 100644
index 0000000..98303a0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr99425-1_b.H
@@ -0,0 +1,19 @@
+// { dg-additional-options {-fmodule-header -fdump-lang-module-alias} }
+// { dg-module-cmi {} }
+
+#include "pr99425-1.h"
+
+import "pr99425-1_a.H";
+
+struct Cont
+{
+ int call ();
+};
+
+inline void widget (Cont parm)
+{
+ ssize (parm);
+}
+
+// { dg-final { scan-lang-dump {Read:-[0-9]*'s alias spec merge key \(new\) type_decl:'::make_signed_t'\n ... Read:-[0-9]*'s type spec merge key \(new\) type_decl:'::make_signed'\n Read:-1's named merge key \(matched\) template_decl:'::template ssize'} module } }
+
diff --git a/gcc/testsuite/g++.dg/modules/pr99425-1_c.C b/gcc/testsuite/g++.dg/modules/pr99425-1_c.C
new file mode 100644
index 0000000..28ef3a1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr99425-1_c.C
@@ -0,0 +1,11 @@
+// { dg-additional-options {-fmodules-ts -fdump-lang-module-alias} }
+import "pr99425-1_a.H";
+import "pr99425-1_b.H";
+
+void frob (Cont parm)
+{
+ ssize (parm);
+}
+
+// { dg-final { scan-lang-dump {Read:-1's named merge key \(new\) template_decl:'::template ssize'} module } }
+// { dg-final { scan-lang-dump {Read:-1's named merge key \(matched\) template_decl:'::template ssize'} module } }
diff --git a/gcc/testsuite/g++.dg/modules/pr99425-2_a.X b/gcc/testsuite/g++.dg/modules/pr99425-2_a.X
new file mode 100644
index 0000000..9a44dc3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr99425-2_a.X
@@ -0,0 +1,7 @@
+// PR 99425 template aliases can cause equivalences in the hash
+// tables, and for extra excitement be reordered on rehash.
+
+// { dg-additional-options {-x c++-system-header stdexcept -fmodules-ts} }
+// { dg-prune-output {linker input file unused} }
+
+No! DO NOT COMPILE;
diff --git a/gcc/testsuite/g++.dg/modules/pr99425-2_b.X b/gcc/testsuite/g++.dg/modules/pr99425-2_b.X
new file mode 100644
index 0000000..5e45354
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr99425-2_b.X
@@ -0,0 +1,4 @@
+// { dg-additional-options {-x c++-system-header mutex -fmodules-ts} }
+// { dg-prune-output {linker input file unused} }
+
+No! DO NOT COMPILE;
diff --git a/gcc/testsuite/g++.dg/template/pr99425.C b/gcc/testsuite/g++.dg/template/pr99425.C
new file mode 100644
index 0000000..fd49c86
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/pr99425.C
@@ -0,0 +1,45 @@
+// { dg-do compile { target c++20 } }
+// a potential fix for 99425 generated an ICE here.
+
+template<typename _Tp>
+struct is_nothrow_destructible;
+
+template<typename _Tp>
+struct common_reference;
+
+template<typename _Tp>
+concept same_as
+ = true;
+
+template<typename _Sent, typename _Iter>
+concept sentinel_for
+ = same_as<common_reference<_Sent>>
+ && is_nothrow_destructible<_Iter>::value;
+
+template<typename _Tp>
+concept __member_end
+ = requires (_Tp& __t)
+ {
+ { true }
+ -> sentinel_for<decltype(__t)>;
+ };
+
+template<typename _Tp>
+concept __adl_end
+ = requires (_Tp& __t)
+ {
+ { true }
+ -> sentinel_for<decltype(__t)>;
+ };
+
+template<typename _Tp>
+requires __member_end<_Tp> || __adl_end<_Tp>
+ void
+ Bar (_Tp&& __t)
+{
+}
+
+void test03 ()
+{
+ Bar (1); // { dg-error "no matching function" }
+}