+2020-04-20 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/94628
+ * cp-tree.h (lss_policy::lss_nop): New enumerator.
+ * pt.c (local_specialization_stack::local_specialization_stack): Handle
+ an lss_nop policy.
+ (local_specialization_stack::~local_specialization_stack): Likewise.
+ (tsubst_pack_expansion): Use a local_specialization_stack instead of
+ manually saving and restoring local_specializations. Conditionally
+ replace local_specializations sooner, before the handling of the
+ unsubstituted_packs case.
+
2020-04-20 Marek Polacek <polacek@redhat.com>
PR c++/94505 - bogus -Wparentheses warning with fold-expression.
local_specialization_stack::local_specialization_stack (lss_policy policy)
: saved (local_specializations)
{
- if (policy == lss_blank || !saved)
+ if (policy == lss_nop)
+ ;
+ else if (policy == lss_blank || !saved)
local_specializations = new hash_map<tree, tree>;
else
local_specializations = new hash_map<tree, tree>(*saved);
local_specialization_stack::~local_specialization_stack ()
{
- delete local_specializations;
- local_specializations = saved;
+ if (local_specializations != saved)
+ {
+ delete local_specializations;
+ local_specializations = saved;
+ }
}
/* True if we've recursed into fn_type_unification too many times. */
bool unsubstituted_fn_pack = false;
int i, len = -1;
tree result;
- hash_map<tree, tree> *saved_local_specializations = NULL;
bool need_local_specializations = false;
int levels;
= build_extra_args (pattern, args, complain);
return t;
}
- else if (unsubstituted_packs)
+
+ /* If NEED_LOCAL_SPECIALIZATIONS then we're in a late-specified return
+ type, so create our own local specializations map; the current map is
+ either NULL or (in the case of recursive unification) might have
+ bindings that we don't want to use or alter. */
+ local_specialization_stack lss (need_local_specializations
+ ? lss_blank : lss_nop);
+
+ if (unsubstituted_packs)
{
/* There were no real arguments, we're just replacing a parameter
pack with another version of itself. Substitute into the
gcc_assert (len >= 0);
- if (need_local_specializations)
- {
- /* We're in a late-specified return type, so create our own local
- specializations map; the current map is either NULL or (in the
- case of recursive unification) might have bindings that we don't
- want to use or alter. */
- saved_local_specializations = local_specializations;
- local_specializations = new hash_map<tree, tree>;
- }
-
/* For each argument in each argument pack, substitute into the
pattern. */
result = make_tree_vec (len);
}
}
- if (need_local_specializations)
- {
- delete local_specializations;
- local_specializations = saved_local_specializations;
- }
-
/* If the dependent pack arguments were such that we end up with only a
single pack expansion again, there's no need to keep it in a TREE_VEC. */
if (len == 1 && TREE_CODE (result) == TREE_VEC
--- /dev/null
+// PR c++/94628
+// A variant of variadic101.C where the recursive call to deref
+// has its first template argument explicitly provided.
+// { dg-do compile { target c++11 } }
+
+template<class T>
+struct Container
+{ T f() const; };
+
+template<class T>
+T deref(const T& t)
+{ return t; }
+
+
+template <class T, class... Args>
+auto
+deref(const T& u, int r, Args... args)
+-> decltype(deref(u.f(), args...))
+{ return deref<decltype(u.f())>(u.f(), args...); }
+
+int main(void)
+{
+ Container<Container<int>> v;
+ deref(v,1,2);
+}