Commit 1ad8aeeb by Douglas Gregor Committed by Doug Gregor

re PR c++/31439 (ICE with variadic template and broken specialization)

2007-11-06  Douglas Gregor  <doug.gregor@gmail.com>

	PR c++/31439
	PR c++/32114
	PR c++/32115
	PR c++/32125
	PR c++/32126
	PR c++/32127
	PR c++/32128
	PR c++/32253
	PR c++/32566
	* typeck.c (check_return_expr): Pass address of retval to
	check_for_bare_parameter_packs.
	* class.c (build_base_field): Tolerate bases that have no layout
	due to errors.
	(end_of_base): Ditto.
	* tree.c (canonical_type_variant): Be careful with
	ERROR_MARK_NODE.
	* cp-tree.h (check_for_bare_parameter_packs): Now accepts a
	tree*.
	* pt.c (find_parameter_pack_data): Add set_packs_to_error field,
	which states whether parameter packs should be replaced with
	ERROR_MARK_NODE.
	(find_parameter_packs_r): Pass addresses to cp_walk_tree wherever
	possible. If set_packs_to_error is set true, replace the parameter
	pack with ERROR_MARK_NODE. Manage our own pointer sets.
	(uses_parameter_packs): Don't set parameter packs to
	ERROR_MARK_NODE.
	(check_for_bare_parameter_packs): Now takes a pointer to a tree,
	which may be modified (if it is a parameter pack). Instructs
	find_parameter_packs_r to replace parameter packs with
	ERROR_MARK_NODE (so that they won't cause errors later on).
	(process_template_parm): Pass pointer to
	check_for_bare_parameter_packs.
	(process_partial_specialization): Replace pack expansions before
	the end of the template argument list with ERROR_MARK_NODE.
	(push_template_decl_real): Pass pointer to
	check_for_bare_parameter_packs. Replace parameter packs not at the
	end of the template parameter list with ERROR_MARK_NODE.
	(convert_template_argument): Be more careful about using DECL_NAME
	on only declarations.
	(unify): Can't unify against ERROR_MARK_NODE.
	* semantics.c (finish_cond): Pass pointer to
	check_for_bare_parameter_packs.
	(finish_expr_stmt): Ditto.
	(finish_for_expr): Ditto.
	(finish_switch_cond): Pass pointer to
	check_for_bare_parameter_packs, and call it before we put the
	condition into the statement.
	(finish_mem_initializers): Pass pointer to
	check_for_bare_parameter_packs.
	(finish_member_declaration): Ditto.
	* parser.c (cp_parser_base_clause): Ditto.
	
2007-11-06  Douglas Gregor  <doug.gregor@gmail.com>

	* testsuite/g++.dg/parser/crash36.C: Tweak expected errors.
	* testsuite/g++.dg/cpp0x/pr31439.C: New.
	* testsuite/g++.dg/cpp0x/pr32114.C: New.
	* testsuite/g++.dg/cpp0x/pr32115.C: New.
	* testsuite/g++.dg/cpp0x/pr32125.C: New.
	* testsuite/g++.dg/cpp0x/pr32126.C: New.
	* testsuite/g++.dg/cpp0x/pr32127.C: New.
	* testsuite/g++.dg/cpp0x/pr32128.C: New.
	* testsuite/g++.dg/cpp0x/pr32253.C: New.
	* testsuite/g++.dg/cpp0x/pr32566.C: New.
	* testsuite/g++.dg/cpp0x/pr31445.C: Tweak expected errors.
	* testsuite/g++.dg/cpp0x/pr31438.C: Ditto.
	* testsuite/g++.dg/cpp0x/variadic81.C: Ditto.
	* testsuite/g++.dg/cpp0x/pr31432.C: Ditto.
	* testsuite/g++.dg/cpp0x/pr31442.C: Ditto.

From-SVN: r129928
parent 3de36a09
2007-11-06 Douglas Gregor <doug.gregor@gmail.com>
PR c++/31439
PR c++/32114
PR c++/32115
PR c++/32125
PR c++/32126
PR c++/32127
PR c++/32128
PR c++/32253
PR c++/32566
* typeck.c (check_return_expr): Pass address of retval to
check_for_bare_parameter_packs.
* class.c (build_base_field): Tolerate bases that have no layout
due to errors.
(end_of_base): Ditto.
* tree.c (canonical_type_variant): Be careful with
ERROR_MARK_NODE.
* cp-tree.h (check_for_bare_parameter_packs): Now accepts a
tree*.
* pt.c (find_parameter_pack_data): Add set_packs_to_error field,
which states whether parameter packs should be replaced with
ERROR_MARK_NODE.
(find_parameter_packs_r): Pass addresses to cp_walk_tree wherever
possible. If set_packs_to_error is set true, replace the parameter
pack with ERROR_MARK_NODE. Manage our own pointer sets.
(uses_parameter_packs): Don't set parameter packs to
ERROR_MARK_NODE.
(check_for_bare_parameter_packs): Now takes a pointer to a tree,
which may be modified (if it is a parameter pack). Instructs
find_parameter_packs_r to replace parameter packs with
ERROR_MARK_NODE (so that they won't cause errors later on).
(process_template_parm): Pass pointer to
check_for_bare_parameter_packs.
(process_partial_specialization): Replace pack expansions before
the end of the template argument list with ERROR_MARK_NODE.
(push_template_decl_real): Pass pointer to
check_for_bare_parameter_packs. Replace parameter packs not at the
end of the template parameter list with ERROR_MARK_NODE.
(convert_template_argument): Be more careful about using DECL_NAME
on only declarations.
(unify): Can't unify against ERROR_MARK_NODE.
* semantics.c (finish_cond): Pass pointer to
check_for_bare_parameter_packs.
(finish_expr_stmt): Ditto.
(finish_for_expr): Ditto.
(finish_switch_cond): Pass pointer to
check_for_bare_parameter_packs, and call it before we put the
condition into the statement.
(finish_mem_initializers): Pass pointer to
check_for_bare_parameter_packs.
(finish_member_declaration): Ditto.
* parser.c (cp_parser_base_clause): Ditto.
2007-11-06 Jakub Jelinek <jakub@redhat.com>
PR target/33168
......
......@@ -3613,21 +3613,24 @@ build_base_field (record_layout_info rli, tree binfo,
DECL_ARTIFICIAL (decl) = 1;
DECL_IGNORED_P (decl) = 1;
DECL_FIELD_CONTEXT (decl) = t;
DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
DECL_MODE (decl) = TYPE_MODE (basetype);
DECL_FIELD_IS_BASE (decl) = 1;
/* Try to place the field. It may take more than one try if we
have a hard time placing the field without putting two
objects of the same type at the same address. */
layout_nonempty_base_or_field (rli, decl, binfo, offsets);
/* Add the new FIELD_DECL to the list of fields for T. */
TREE_CHAIN (decl) = *next_field;
*next_field = decl;
next_field = &TREE_CHAIN (decl);
if (CLASSTYPE_AS_BASE (basetype))
{
DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
DECL_MODE (decl) = TYPE_MODE (basetype);
DECL_FIELD_IS_BASE (decl) = 1;
/* Try to place the field. It may take more than one try if we
have a hard time placing the field without putting two
objects of the same type at the same address. */
layout_nonempty_base_or_field (rli, decl, binfo, offsets);
/* Add the new FIELD_DECL to the list of fields for T. */
TREE_CHAIN (decl) = *next_field;
*next_field = decl;
next_field = &TREE_CHAIN (decl);
}
}
else
{
......@@ -4423,7 +4426,9 @@ end_of_base (tree binfo)
{
tree size;
if (is_empty_class (BINFO_TYPE (binfo)))
if (!CLASSTYPE_AS_BASE (BINFO_TYPE (binfo)))
size = TYPE_SIZE_UNIT (char_type_node);
else if (is_empty_class (BINFO_TYPE (binfo)))
/* An empty class has zero CLASSTYPE_SIZE_UNIT, but we need to
allocate some space for it. It cannot have virtual bases, so
TYPE_SIZE_UNIT is fine. */
......
......@@ -4435,7 +4435,7 @@ extern int comp_template_parms (const_tree, const_tree);
extern bool uses_parameter_packs (tree);
extern bool template_parameter_pack_p (const_tree);
extern tree make_pack_expansion (tree);
extern bool check_for_bare_parameter_packs (tree);
extern bool check_for_bare_parameter_packs (tree*);
extern tree get_template_info (tree);
extern int template_class_depth (tree);
extern int is_specialization_of (tree, tree);
......
......@@ -15248,7 +15248,7 @@ cp_parser_base_clause (cp_parser* parser)
/* Make this a pack expansion type. */
TREE_VALUE (base) = make_pack_expansion (TREE_VALUE (base));
else
check_for_bare_parameter_packs (TREE_VALUE (base));
check_for_bare_parameter_packs (&TREE_VALUE (base));
TREE_CHAIN (base) = bases;
bases = base;
......
......@@ -508,7 +508,7 @@ finish_cond (tree *cond_p, tree expr)
if (TREE_CODE (cond) == DECL_EXPR)
expr = cond;
check_for_bare_parameter_packs (expr);
check_for_bare_parameter_packs (&expr);
}
*cond_p = expr;
}
......@@ -618,7 +618,7 @@ finish_expr_stmt (tree expr)
else if (!type_dependent_expression_p (expr))
convert_to_void (build_non_dependent_expr (expr), "statement");
check_for_bare_parameter_packs (expr);
check_for_bare_parameter_packs (&expr);
/* Simplification of inner statement expressions, compound exprs,
etc can result in us already having an EXPR_STMT. */
......@@ -875,7 +875,7 @@ finish_for_expr (tree expr, tree for_stmt)
else if (!type_dependent_expression_p (expr))
convert_to_void (build_non_dependent_expr (expr), "3rd expression in for");
expr = maybe_cleanup_point_expr_void (expr);
check_for_bare_parameter_packs (expr);
check_for_bare_parameter_packs (&expr);
FOR_EXPR (for_stmt) = expr;
}
......@@ -971,12 +971,12 @@ finish_switch_cond (tree cond, tree switch_stmt)
cond = index;
}
}
check_for_bare_parameter_packs (&cond);
finish_cond (&SWITCH_STMT_COND (switch_stmt), cond);
SWITCH_STMT_TYPE (switch_stmt) = orig_type;
add_stmt (switch_stmt);
push_switch (switch_stmt);
SWITCH_STMT_BODY (switch_stmt) = push_stmt_list ();
check_for_bare_parameter_packs (cond);
}
/* Finish the body of a switch-statement, which may be given by
......@@ -1389,7 +1389,7 @@ finish_mem_initializers (tree mem_inits)
bound as part of the TREE_PURPOSE. See
make_pack_expansion for more information. */
if (TREE_CODE (TREE_PURPOSE (mem)) != TYPE_PACK_EXPANSION)
check_for_bare_parameter_packs (TREE_VALUE (mem));
check_for_bare_parameter_packs (&TREE_VALUE (mem));
}
add_stmt (build_min_nt (CTOR_INITIALIZER, mem_inits));
......@@ -2306,9 +2306,8 @@ finish_member_declaration (tree decl)
DECL_CONTEXT (decl) = current_class_type;
/* Check for bare parameter packs in the member variable declaration. */
if (TREE_CODE (decl) == FIELD_DECL
&& !check_for_bare_parameter_packs (TREE_TYPE (decl)))
TREE_TYPE (decl) = error_mark_node;
if (TREE_CODE (decl) == FIELD_DECL)
check_for_bare_parameter_packs (&TREE_TYPE (decl));
/* [dcl.link]
......
......@@ -846,6 +846,9 @@ cp_build_qualified_type_real (tree type,
tree
canonical_type_variant (tree t)
{
if (t == error_mark_node)
return error_mark_node;
return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t));
}
......
......@@ -6613,7 +6613,7 @@ check_return_expr (tree retval, bool *no_warning)
if (processing_template_decl)
{
current_function_returns_value = 1;
check_for_bare_parameter_packs (retval);
check_for_bare_parameter_packs (&retval);
return retval;
}
......
2007-11-06 Douglas Gregor <doug.gregor@gmail.com>
* testsuite/g++.dg/parser/crash36.C: Tweak expected errors.
* testsuite/g++.dg/cpp0x/pr31439.C: New.
* testsuite/g++.dg/cpp0x/pr32114.C: New.
* testsuite/g++.dg/cpp0x/pr32115.C: New.
* testsuite/g++.dg/cpp0x/pr32125.C: New.
* testsuite/g++.dg/cpp0x/pr32126.C: New.
* testsuite/g++.dg/cpp0x/pr32127.C: New.
* testsuite/g++.dg/cpp0x/pr32128.C: New.
* testsuite/g++.dg/cpp0x/pr32253.C: New.
* testsuite/g++.dg/cpp0x/pr32566.C: New.
* testsuite/g++.dg/cpp0x/pr31445.C: Tweak expected errors.
* testsuite/g++.dg/cpp0x/pr31438.C: Ditto.
* testsuite/g++.dg/cpp0x/variadic81.C: Ditto.
* testsuite/g++.dg/cpp0x/pr31432.C: Ditto.
* testsuite/g++.dg/cpp0x/pr31442.C: Ditto.
2007-11-06 Jakub Jelinek <jakub@redhat.com>
PR target/33168
......@@ -4,5 +4,5 @@ template<typename..., typename> struct A // { dg-error "parameter pack" }
static int i;
};
A<int, int> a; // { dg-error "invalid type" }
A<char,int> b; // { dg-error "invalid type" }
A<int, int> a; // { dg-error "mismatch|expected|invalid type" }
A<char,int> b; // { dg-error "mismatch|expected|invalid type" }
// { dg-options "-std=gnu++0x" }
template<typename> struct A; // { dg-error "candidates" }
template<typename T, typename... U> struct A<T(U)> // { dg-error "parameter packs|U" }
{ // { dg-error "parameter packs|U" }
template<typename X> A(X); // { dg-error "parameter packs|U" }
template<typename> struct A;
template<typename T, typename... U> struct A<T(U)> // { dg-error "parameter packs|U|not used|U" }
{
template<typename X> A(X);
};
A<void(int)> a(0); // { dg-error "no matching" }
A<void(int)> a(0); // { dg-error "incomplete type" }
// { dg-options "-std=c++0x" }
template<typename...> struct A;
template<char> struct A<> {}; // { dg-error "not used in partial specialization|anonymous" }
template<typename T, typename... U> struct A<T, U...> : A<U...> {};
A<int> a;
// { dg-options "-std=gnu++0x" }
template<typename... T, T = 0> struct A {}; // { dg-error "parameter packs|T|the end" }
template<typename... T, T = 0> struct A {}; // { dg-error "parameter packs|T|the end|parameter packs|anonymous" }
struct B
{
template <template <typename...> class C> B(C<int>);
};
B b = A<int>();
B b = A<int>(); // { dg-error "mismatch|expected" }
// { dg-options "-std=gnu++0x" }
template <typename... T> struct A
{
void foo(T...); // { dg-error "candidates" }
A(T... t) { foo(t); } // { dg-error "parameter packs|t|no matching" }
void foo(T...);
A(T... t) { foo(t); } // { dg-error "parameter packs|t" }
};
A<int> a(0);
// { dg-options "-std=c++0x" }
template<typename ...T> struct A
{
typedef typename T::X Y; // { dg-error "not expanded|T" }
};
A<int> a;
// { dg-options "-std=c++0x" }
template<typename ...T, int = 0> struct A {}; // { dg-error "end of" }
A<int> a; // { dg-error "mismatch|expected|invalid" }
// { dg-options "-std=c++0x" }
template<typename...> struct A;
template<typename...T> struct A<T*> // { dg-error "not expanded|T|not used|T" }
{
A();
A(T); // { dg-error "not expanded|T" }
};
// { dg-options "-std=c++0x" }
template<typename...> struct A;
template<typename...T> struct A<T> // { dg-error "not expanded|T|not used|T" }
{
static int i;
};
A<char> a; // { dg-error "incomplete" }
A<int> b; // { dg-error "incomplete" }
// { dg-options "-std=c++0x" }
template<typename...T> struct A
{
static T i; // { dg-error "parameter packs|T" }
};
int j = A<int>::i; // { dg-error "not a member" }
// { dg-options "-std=c++0x" }
template<typename...> struct A;
template<typename...T, typename...U>
struct A<T..., U...> {}; // { dg-error "must be at the end" }
A<int> a; // { dg-error "incomplete" }
// { dg-options "-std=c++0x" }
template<void (*... fp)()> struct A
{
A() { fp(); } // { dg-error "not expanded|fp" }
};
void foo();
A<foo> a;
// { dg-options "-std=c++0x" }
template<int...> struct A;
template<template<int> class... T> struct A<T...> {}; // { dg-error "mismatch|expected" }
......@@ -3,9 +3,9 @@
template<typename> struct A;
template<typename... T> struct A<T*> // { dg-error "not expanded|note" }
{ // { dg-error "not expanded|note" }
template<typename... T> struct A<T*> // { dg-error "not expanded|T|not used|T" }
{
struct B;
};
A<void*> a;
A<void*> a; // { dg-error "incomplete" }
......@@ -5,7 +5,7 @@
template <typename... T> struct A // { dg-error "does not include variadic templates" }
{
static T &t; // { dg-error "not expanded with|T" }
static const int i = sizeof (++t); // { dg-error "invalid use of template type parameter" }
static const int i = sizeof (++t);
};
int x[A <int>::i]; // { dg-error "is not an integral constant-expression" }
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