Commit 1a048f82 by Dodji Seketeli Committed by Dodji Seketeli

Fix PRs c++/42758, c++/42634, c++/42797

... and mitigate PR c++/42336

gcc/cp/ChangeLog:
	PR c++/42758
	PR c++/42634
	PR c++/42336
	PR c++/42797
	PR c++/42880
	* cp-tree.h (NON_DEFAULT_TEMPLATE_ARGS_COUNT,
	SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT,
	GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT): New accessor macros.
	* pt.c (coerce_template_parms, type_unification_real,
	expand_template_argument_pack, coerce_template_parameter_pack):
	Set the non default template args count.
	(current_template_args): Always set non defaulted
	template args count when compiled with --enable-checking
	(tsubst_template_args, type_unification_real): Propagate the non
	defaulted template args count.
	* error.c (get_non_default_template_args_count): Renamed
	count_non_default_template_args into this. Don't calculate the
	non default template argument count anymore. Use the new
	accessor macros above to get it.
	(dump_template_argument_list, dump_type, dump_decl,
	dump_template_parms): Adjust.
	* parser.c (cp_parser_template_argument_list): Always set defaulted
	template args count when compiled with --enable-checking.

gcc/testsuite/ChangeLog:
	PR c++/42758
	PR c++/42634
	PR c++/42336
	PR c++/42797
	PR c++/42880
	* g++.dg/other/crash-5.C: New test.
	* g++.dg/other/crash-6.C: New test.
	* g++.dg/other/crash-7.C: New test.
	* g++.dg/other/crash-8.C: New test.

From-SVN: r156351
parent eb6b98c7
2010-01-29 Dodji Seketeli <dodji@redhat.com>
PR c++/42758
PR c++/42634
PR c++/42336
PR c++/42797
PR c++/42880
* cp-tree.h (NON_DEFAULT_TEMPLATE_ARGS_COUNT,
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT,
GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT): New accessor macros.
* pt.c (coerce_template_parms, type_unification_real,
expand_template_argument_pack, coerce_template_parameter_pack):
Set the non default template args count.
(current_template_args): Always set non defaulted
template args count when compiled with --enable-checking
(tsubst_template_args, type_unification_real): Propagate the non
defaulted template args count.
* error.c (get_non_default_template_args_count): Renamed
count_non_default_template_args into this. Don't calculate the
non default template argument count anymore. Use the new
accessor macros above to get it.
(dump_template_argument_list, dump_type, dump_decl,
dump_template_parms): Adjust.
* parser.c (cp_parser_template_argument_list): Always set defaulted
template args count when compiled with --enable-checking.
2010-01-29 Shujing Zhao <pearly.zhao@oracle.com>
* decl.c (redeclaration_error_message): Wrap the return messages into
......
......@@ -2497,6 +2497,23 @@ extern void decl_shadowed_for_var_insert (tree, tree);
#define TI_TEMPLATE(NODE) TREE_TYPE (TEMPLATE_INFO_CHECK (NODE))
#define TI_ARGS(NODE) TREE_CHAIN (TEMPLATE_INFO_CHECK (NODE))
#define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
/* For a given TREE_VEC containing a template argument list,
this property contains the number of arguments that are not
defaulted. */
#define NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) TREE_CHAIN (TREE_VEC_CHECK (NODE))
/* Below are the setter and getter of the NON_DEFAULT_TEMPLATE_ARGS_COUNT
property. */
#define SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE, INT_VALUE) \
NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) = build_int_cst (NULL_TREE, INT_VALUE)
#ifdef ENABLE_CHECKING
#define GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) \
int_cst_value (NON_DEFAULT_TEMPLATE_ARGS_COUNT (NODE))
#else
#define GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT(NODE) \
NON_DEFAULT_TEMPLATE_ARGS_COUNT (NODE) \
? int_cst_value (NON_DEFAULT_TEMPLATE_ARGS_COUNT (NODE)) \
: TREE_VEC_LENGTH (INNERMOST_TEMPLATE_ARGS (NODE))
#endif
/* The list of typedefs - used in the template - that need
access checking at template instantiation time. */
#define TI_TYPEDEFS_NEEDING_ACCESS_CHECKING(NODE) \
......@@ -2513,7 +2530,13 @@ extern void decl_shadowed_for_var_insert (tree, tree);
It is incorrect to ever form a template argument vector containing
only one level of arguments, but which is a TREE_VEC containing as
its only entry the TREE_VEC for that level. */
its only entry the TREE_VEC for that level.
For each TREE_VEC containing the template arguments for a single
level, it's possible to get or set the number of non defaulted
template arguments by using the accessor macros
GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT or
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT. */
/* Nonzero if the template arguments is actually a vector of vectors,
rather than just a vector. */
......
......@@ -78,14 +78,12 @@ static void dump_global_iord (tree);
static void dump_parameters (tree, int);
static void dump_exception_spec (tree, int);
static void dump_template_argument (tree, int);
static void dump_template_argument_list (tree, tree, int);
static void dump_template_argument_list (tree, int);
static void dump_template_parameter (tree, int);
static void dump_template_bindings (tree, tree, VEC(tree,gc) *);
static void dump_scope (tree, int);
static void dump_template_parms (tree, int, int);
static int count_non_default_template_args (tree, tree, int);
static int get_non_default_template_args_count (tree, int);
static const char *function_category (tree);
static void maybe_print_instantiation_context (diagnostic_context *);
static void print_instantiation_full_context (diagnostic_context *);
......@@ -147,7 +145,7 @@ static void
dump_template_argument (tree arg, int flags)
{
if (ARGUMENT_PACK_P (arg))
dump_template_argument_list (ARGUMENT_PACK_ARGS (arg), NULL_TREE, flags);
dump_template_argument_list (ARGUMENT_PACK_ARGS (arg), flags);
else if (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL)
dump_type (arg, flags & ~TFF_CLASS_KEY_OR_ENUM);
else
......@@ -163,52 +161,29 @@ dump_template_argument (tree arg, int flags)
match the (optional) default template parameter in PARAMS */
static int
count_non_default_template_args (tree args, tree params, int flags)
get_non_default_template_args_count (tree args, int flags)
{
tree inner_args = INNERMOST_TEMPLATE_ARGS (args);
int n = TREE_VEC_LENGTH (inner_args);
int last;
int n = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_ARGS (args));
if (params == NULL_TREE
/* We use this flag when generating debug information. We don't
if (/* We use this flag when generating debug information. We don't
want to expand templates at this point, for this may generate
new decls, which gets decl counts out of sync, which may in
turn cause codegen differences between compilations with and
without -g. */
|| (flags & TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS) != 0
(flags & TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS) != 0
|| !flag_pretty_templates)
return n;
for (last = n - 1; last >= 0; --last)
{
tree param = TREE_VEC_ELT (params, last);
tree def = TREE_PURPOSE (param);
if (!def)
break;
if (uses_template_parms (def))
{
++processing_template_decl;
/* This speculative substitution must not cause any classes to be
instantiated that otherwise wouldn't be. */
def = tsubst_copy_and_build (def, args, tf_no_class_instantiations,
NULL_TREE, false, true);
--processing_template_decl;
}
if (!cp_tree_equal (TREE_VEC_ELT (inner_args, last), def))
break;
}
return last + 1;
return GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (INNERMOST_TEMPLATE_ARGS (args));
}
/* Dump a template-argument-list ARGS (always a TREE_VEC) under control
of FLAGS. */
static void
dump_template_argument_list (tree args, tree parms, int flags)
dump_template_argument_list (tree args, int flags)
{
int n = count_non_default_template_args (args, parms, flags);
int n = get_non_default_template_args_count (args, flags);
int need_comma = 0;
int i;
......@@ -422,7 +397,7 @@ dump_type (tree t, int flags)
pp_cxx_cv_qualifier_seq (cxx_pp, t);
pp_cxx_tree_identifier (cxx_pp, TYPE_IDENTIFIER (t));
pp_cxx_begin_template_argument_list (cxx_pp);
dump_template_argument_list (args, NULL_TREE, flags);
dump_template_argument_list (args, flags);
pp_cxx_end_template_argument_list (cxx_pp);
}
break;
......@@ -1041,7 +1016,7 @@ dump_decl (tree t, int flags)
dump_decl (name, flags);
pp_cxx_begin_template_argument_list (cxx_pp);
if (TREE_OPERAND (t, 1))
dump_template_argument_list (TREE_OPERAND (t, 1), NULL_TREE, flags);
dump_template_argument_list (TREE_OPERAND (t, 1), flags);
pp_cxx_end_template_argument_list (cxx_pp);
}
break;
......@@ -1487,12 +1462,7 @@ dump_template_parms (tree info, int primary, int flags)
if (args && !primary)
{
int len, ix;
/* We don't know the parms for a friend template specialization. */
tree params = (TREE_CODE (TI_TEMPLATE (info)) == TEMPLATE_DECL
? DECL_INNERMOST_TEMPLATE_PARMS (TI_TEMPLATE (info))
: NULL_TREE);
len = count_non_default_template_args (args, params, flags);
len = get_non_default_template_args_count (args, flags);
args = INNERMOST_TEMPLATE_ARGS (args);
for (ix = 0; ix != len; ix++)
......
......@@ -11246,6 +11246,9 @@ cp_parser_template_argument_list (cp_parser* parser)
parser->non_integral_constant_expression_p = saved_non_ice_p;
parser->integral_constant_expression_p = saved_ice_p;
parser->in_template_argument_list_p = saved_in_template_argument_list_p;
#ifdef ENABLE_CHECKING
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (vec, TREE_VEC_LENGTH (vec));
#endif
return vec;
}
......
......@@ -3207,6 +3207,7 @@ expand_template_argument_pack (tree args)
tree result_args = NULL_TREE;
int in_arg, out_arg = 0, nargs = args ? TREE_VEC_LENGTH (args) : 0;
int num_result_args = -1;
int non_default_args_count = -1;
/* First, determine if we need to expand anything, and the number of
slots we'll need. */
......@@ -3236,6 +3237,9 @@ expand_template_argument_pack (tree args)
/* Expand arguments. */
result_args = make_tree_vec (num_result_args);
if (NON_DEFAULT_TEMPLATE_ARGS_COUNT (args))
non_default_args_count =
GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (args);
for (in_arg = 0; in_arg < nargs; ++in_arg)
{
tree arg = TREE_VEC_ELT (args, in_arg);
......@@ -3245,6 +3249,8 @@ expand_template_argument_pack (tree args)
int i, num_packed = TREE_VEC_LENGTH (packed);
for (i = 0; i < num_packed; ++i, ++out_arg)
TREE_VEC_ELT (result_args, out_arg) = TREE_VEC_ELT(packed, i);
if (non_default_args_count > 0)
non_default_args_count += num_packed;
}
else
{
......@@ -3252,7 +3258,8 @@ expand_template_argument_pack (tree args)
++out_arg;
}
}
if (non_default_args_count >= 0)
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (result_args, non_default_args_count);
return result_args;
}
......@@ -3616,6 +3623,10 @@ current_template_args (void)
/* Turn this argument into a TYPE_ARGUMENT_PACK
with a single element, which expands T. */
tree vec = make_tree_vec (1);
#ifdef ENABLE_CHECKING
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
(vec, TREE_VEC_LENGTH (vec));
#endif
TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
t = cxx_make_type (TYPE_ARGUMENT_PACK);
......@@ -3632,6 +3643,10 @@ current_template_args (void)
with a single element, which expands T. */
tree vec = make_tree_vec (1);
tree type = TREE_TYPE (TEMPLATE_PARM_DECL (t));
#ifdef ENABLE_CHECKING
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
(vec, TREE_VEC_LENGTH (vec));
#endif
TREE_VEC_ELT (vec, 0) = make_pack_expansion (t);
t = make_node (NONTYPE_ARGUMENT_PACK);
......@@ -3644,6 +3659,10 @@ current_template_args (void)
}
}
#ifdef ENABLE_CHECKING
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (a, TREE_VEC_LENGTH (a));
#endif
if (length > 1)
TREE_VEC_ELT (args, --l) = a;
else
......@@ -5736,6 +5755,10 @@ coerce_template_parameter_pack (tree parms,
}
SET_ARGUMENT_PACK_ARGS (argument_pack, packed_args);
#ifdef ENABLE_CHECKING
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (packed_args,
TREE_VEC_LENGTH (packed_args));
#endif
return argument_pack;
}
......@@ -5891,9 +5914,16 @@ coerce_template_parms (tree parms,
}
}
else if (require_all_args)
/* There must be a default arg in this case. */
arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
complain, in_decl);
{
/* There must be a default arg in this case. */
arg = tsubst_template_arg (TREE_PURPOSE (parm), new_args,
complain, in_decl);
/* The position of the first default template argument,
is also the number of non-defaulted arguments in NEW_INNER_ARGS.
Record that. */
if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args))
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args, arg_idx);
}
else
break;
......@@ -5924,6 +5954,12 @@ coerce_template_parms (tree parms,
if (lost)
return error_mark_node;
#ifdef ENABLE_CHECKING
if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args))
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_inner_args,
TREE_VEC_LENGTH (new_inner_args));
#endif
return new_inner_args;
}
......@@ -8392,6 +8428,19 @@ tsubst_template_args (tree t, tree args, tsubst_flags_t complain, tree in_decl)
/* Make space for the expanded arguments coming from template
argument packs. */
t = make_tree_vec (len + expanded_len_adjust);
/* ORIG_T can contain TREE_VECs. That happens if ORIG_T contains the
arguments for a member template.
In that case each TREE_VEC in ORIG_T represents a level of template
arguments, and ORIG_T won't carry any non defaulted argument count.
It will rather be the nested TREE_VECs that will carry one.
In other words, ORIG_T carries a non defaulted argument count only
if it doesn't contain any nested TREE_VEC. */
if (NON_DEFAULT_TEMPLATE_ARGS_COUNT (orig_t))
{
int count = GET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (orig_t);
count += expanded_len_adjust;
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (t, count);
}
for (i = 0, out = 0; i < len; i++)
{
if ((PACK_EXPANSION_P (TREE_VEC_ELT (orig_t, i))
......@@ -13247,6 +13296,10 @@ type_unification_real (tree tparms,
gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST);
gcc_assert (ntparms > 0);
/* Reset the number of non-defaulted template arguments contained
in in TARGS. */
NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs) = NULL_TREE;
switch (strict)
{
case DEDUCE_CALL:
......@@ -13425,6 +13478,11 @@ type_unification_real (tree tparms,
else
{
TREE_VEC_ELT (targs, i) = arg;
/* The position of the first default template argument,
is also the number of non-defaulted arguments in TARGS.
Record that. */
if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs))
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, i);
continue;
}
}
......@@ -13452,6 +13510,10 @@ type_unification_real (tree tparms,
return 2;
}
#ifdef ENABLE_CHECKING
if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs))
SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, TREE_VEC_LENGTH (targs));
#endif
return 0;
}
......
2010-01-29 Dodji Seketeli <dodji@redhat.com>
PR c++/42758
PR c++/42634
PR c++/42336
PR c++/42797
PR c++/42880
* g++.dg/other/crash-5.C: New test.
* g++.dg/other/crash-6.C: New test.
* g++.dg/other/crash-7.C: New test.
* g++.dg/other/crash-8.C: New test.
2010-01-29 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/42889
......
// Origin: PR c++/42758
// { dg-do compile }
template<class T> struct less {};
template<class T, typename U = less<T> > struct set {};
struct int_less_than {};
void assert_fail (const char*);
int f(const set<int, int_less_than>&)
{
assert_fail (__PRETTY_FUNCTION__);
}
// Origin: PR c++/42634
// { dg-options "-g -std=c++0x" }
// { dg-do compile }
template<typename T> T declval();
template<typename T, typename... Args> struct is_constructible {
template<typename T1, typename... Args1> static decltype(T1(declval<Args1>()...), char()) test();
static const bool value = sizeof(test<T, Args...>()) == 1;
};
template<bool> struct enable_if {
typedef void type;
};
template<class T1, class T2> struct pair {
template<class U2,
class = typename enable_if<is_constructible<T2,U2&&>::value>::type
>
pair(const T1&, U2&&) { }
};
struct string {
string() : p(0) {}
char* p;
};
struct Foo {
string s;
int i;
};
void f()
{
pair<int, Foo>(1, Foo());
}
// Origin: PR c++/42336
// { dg-options "-std=c++0x -O2 -g" }
// { dg-do compile }
struct X {
void func() {}
};
template<typename T, void (X::*P)() = &T::func>
void b(T) {}
int main() {
b(X()); /* line 9 */
X().func();
return 0;
}
// Origin: PR c++/42797
// { dg-options "-g -O2 -std=c++0x" }
template<typename _Tp, _Tp __v> struct integral_constant {
static const _Tp value = __v;
};
template<typename _Tp> _Tp declval();
template<typename _Tp, typename... _Args>
class __is_constructible_helper {
};
template<typename _Tp, typename _Arg>
class __is_constructible_helper<_Tp, _Arg> {
template<typename _Tp1, typename _Arg1>
static decltype(static_cast<_Tp1>(declval<_Arg1>()), char()) __test(int);
public:
static const bool __value = sizeof(__test<_Tp, _Arg>(0)) == 1;
};
template<typename _Tp, typename... _Args>
struct is_constructible : public integral_constant<bool,__is_constructible_helper<_Tp, _Args...>::__value> { };
template<bool, typename _Tp = void>
struct enable_if { };
template<typename _Tp>
struct enable_if<true, _Tp> {
typedef _Tp type;
};
template<class _T1, class _T2> struct pair {
_T1 first;
_T2 second;
template<class _U2, class = typename enable_if<is_constructible<_T2, _U2&&>::value>::type>
pair(const _T1& __x, _U2&& __y) : first(__x),
second(__y) { }
};
namespace __gnu_cxx {
template<typename _Tp>
class new_allocator {
public:
new_allocator() throw() { }
new_allocator(const new_allocator&) throw() { }
};
}
template<typename _Tp>
class allocator: public __gnu_cxx::new_allocator<_Tp> {
public:
template<typename _Tp1>
struct rebind {
typedef allocator<_Tp1> other;
};
};
template<typename _Tp, typename _Alloc> struct _Vector_base {
typedef typename _Alloc::template rebind<_Tp>::other _Tp_alloc_type;
struct _Vector_impl : public _Tp_alloc_type {
_Vector_impl()
{ }
};
public:
_Vector_impl _M_impl;
};
template<typename _Tp, typename _Alloc = allocator<_Tp> >
class vector : protected _Vector_base<_Tp, _Alloc> {
typedef _Alloc allocator_type;
public:
vector() { }
explicit vector(int, const allocator_type& __a = allocator_type())
{
}
};
template <typename _Key, typename _Tp>
class map {
typedef _Key key_type;
typedef _Tp mapped_type;
typedef pair<const _Key, _Tp> value_type;
public:
void insert(const value_type& __x)
{
}
mapped_type& operator[](const key_type& __k) {
insert(value_type(__k, mapped_type()));
}
};
struct Foo {
Foo() {} template<typename Tp> Foo(Tp *p) {} };
void foo() {
map <int, vector<Foo>> the_map;
the_map[1] = vector<Foo>();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment