Commit 49bb4bbe by Jason Merrill Committed by Jason Merrill

re PR c++/50852 (ICE: internal compiler error: in tsubst, at cp/pt.c:11030)

	PR c++/50852
	PR c++/53039
	* tree.c (strip_typedefs_expr): New.
	* cp-tree.h: Declare it.
	* pt.c (convert_template_argument, unify): Use it.
	* parser.c (cp_parser_template_declaration_after_export): Don't call
	fixup_template_parms.

From-SVN: r189298
parent 40264d66
2012-07-05 Jason Merrill <jason@redhat.com>
PR c++/50852
PR c++/53039
* tree.c (strip_typedefs_expr): New.
* cp-tree.h: Declare it.
* pt.c (convert_template_argument, unify): Use it.
* parser.c (cp_parser_template_declaration_after_export): Don't call
fixup_template_parms.
2012-07-04 Jason Merrill <jason@redhat.com>
PR c++/53848
......
......@@ -5692,6 +5692,7 @@ extern bool type_has_nontrivial_copy_init (const_tree);
extern bool class_tmpl_impl_spec_p (const_tree);
extern int zero_init_p (const_tree);
extern tree strip_typedefs (tree);
extern tree strip_typedefs_expr (tree);
extern tree copy_binfo (tree, tree, tree,
tree *, int);
extern int member_p (const_tree);
......
......@@ -21207,7 +21207,6 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
{
/* Parse the template parameters. */
parameter_list = cp_parser_template_parameter_list (parser);
fixup_template_parms ();
}
/* Get the deferred access checks from the parameter list. These
......
......@@ -6600,7 +6600,7 @@ convert_template_argument (tree parm,
argument specification is valid. */
val = convert_nontype_argument (t, orig_arg, complain);
else
val = orig_arg;
val = strip_typedefs_expr (orig_arg);
if (val == NULL_TREE)
val = error_mark_node;
......@@ -16598,6 +16598,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
&& !TEMPLATE_PARM_PARAMETER_PACK (parm))
return unify_parameter_pack_mismatch (explain_p, parm, arg);
arg = strip_typedefs_expr (arg);
TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
return unify_success (explain_p);
......
......@@ -1094,7 +1094,7 @@ cv_unqualified (tree type)
* If T is a type that needs structural equality
its TYPE_CANONICAL (T) will be NULL.
* TYPE_CANONICAL (T) desn't carry type attributes
and looses template parameter names. */
and loses template parameter names. */
tree
strip_typedefs (tree t)
......@@ -1184,6 +1184,16 @@ strip_typedefs (tree t)
TYPENAME_TYPE_FULLNAME (t),
typename_type, tf_none);
break;
case DECLTYPE_TYPE:
result = strip_typedefs_expr (DECLTYPE_TYPE_EXPR (t));
if (result == DECLTYPE_TYPE_EXPR (t))
return t;
else
result = (finish_decltype_type
(result,
DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t),
tf_none));
break;
default:
break;
}
......@@ -1205,6 +1215,186 @@ strip_typedefs (tree t)
return cp_build_qualified_type (result, cp_type_quals (t));
}
/* Like strip_typedefs above, but works on expressions, so that in
template<class T> struct A
{
typedef T TT;
B<sizeof(TT)> b;
};
sizeof(TT) is replaced by sizeof(T). */
tree
strip_typedefs_expr (tree t)
{
unsigned i,n;
tree r, type, *ops;
enum tree_code code;
if (t == NULL_TREE || t == error_mark_node)
return t;
if (DECL_P (t) || CONSTANT_CLASS_P (t))
return t;
/* Some expressions have type operands, so let's handle types here rather
than check TYPE_P in multiple places below. */
if (TYPE_P (t))
return strip_typedefs (t);
code = TREE_CODE (t);
switch (code)
{
case IDENTIFIER_NODE:
case TEMPLATE_PARM_INDEX:
case OVERLOAD:
case BASELINK:
case ARGUMENT_PACK_SELECT:
return t;
case TRAIT_EXPR:
{
tree type1 = strip_typedefs (TRAIT_EXPR_TYPE1 (t));
tree type2 = strip_typedefs (TRAIT_EXPR_TYPE2 (t));
if (type1 == TRAIT_EXPR_TYPE1 (t)
&& type2 == TRAIT_EXPR_TYPE2 (t))
return t;
r = copy_node (t);
TRAIT_EXPR_TYPE1 (t) = type1;
TRAIT_EXPR_TYPE2 (t) = type2;
return r;
}
case TREE_LIST:
{
VEC(tree,gc) *vec = make_tree_vector ();
bool changed = false;
tree it;
for (it = t; it; it = TREE_CHAIN (it))
{
tree val = strip_typedefs_expr (TREE_VALUE (t));
VEC_safe_push (tree, gc, vec, val);
if (val != TREE_VALUE (t))
changed = true;
gcc_assert (TREE_PURPOSE (it) == NULL_TREE);
}
if (changed)
{
r = NULL_TREE;
FOR_EACH_VEC_ELT_REVERSE (tree, vec, i, it)
r = tree_cons (NULL_TREE, it, r);
}
else
r = t;
release_tree_vector (vec);
return r;
}
case TREE_VEC:
{
bool changed = false;
VEC(tree,gc)* vec = make_tree_vector ();
n = TREE_VEC_LENGTH (t);
VEC_reserve (tree, gc, vec, n);
for (i = 0; i < n; ++i)
{
tree op = strip_typedefs_expr (TREE_VEC_ELT (t, i));
VEC_quick_push (tree, vec, op);
if (op != TREE_VEC_ELT (t, i))
changed = true;
}
if (changed)
{
r = copy_node (t);
for (i = 0; i < n; ++i)
TREE_VEC_ELT (r, i) = VEC_index (tree, vec, i);
}
else
r = t;
release_tree_vector (vec);
return r;
}
case CONSTRUCTOR:
{
bool changed = false;
VEC(constructor_elt,gc) *vec
= VEC_copy (constructor_elt, gc, CONSTRUCTOR_ELTS (t));
n = CONSTRUCTOR_NELTS (t);
type = strip_typedefs (TREE_TYPE (t));
for (i = 0; i < n; ++i)
{
constructor_elt *e = VEC_index (constructor_elt, vec, i);
tree op = strip_typedefs_expr (e->value);
if (op != e->value)
{
changed = true;
e->value = op;
}
gcc_checking_assert (e->index == strip_typedefs_expr (e->index));
}
if (!changed && type == TREE_TYPE (t))
{
VEC_free (constructor_elt, gc, vec);
return t;
}
else
{
r = copy_node (t);
TREE_TYPE (r) = type;
CONSTRUCTOR_ELTS (r) = vec;
return r;
}
}
case LAMBDA_EXPR:
gcc_unreachable ();
default:
break;
}
gcc_assert (EXPR_P (t));
n = TREE_OPERAND_LENGTH (t);
ops = XALLOCAVEC (tree, n);
type = TREE_TYPE (t);
switch (code)
{
CASE_CONVERT:
case IMPLICIT_CONV_EXPR:
case DYNAMIC_CAST_EXPR:
case STATIC_CAST_EXPR:
case CONST_CAST_EXPR:
case REINTERPRET_CAST_EXPR:
case CAST_EXPR:
case NEW_EXPR:
type = strip_typedefs (type);
/* fallthrough */
default:
for (i = 0; i < n; ++i)
ops[i] = strip_typedefs_expr (TREE_OPERAND (t, i));
break;
}
/* If nothing changed, return t. */
for (i = 0; i < n; ++i)
if (ops[i] != TREE_OPERAND (t, i))
break;
if (i == n && type == TREE_TYPE (t))
return t;
r = copy_node (t);
TREE_TYPE (r) = type;
for (i = 0; i < n; ++i)
TREE_OPERAND (r, i) = ops[i];
return r;
}
/* Makes a copy of BINFO and TYPE, which is to be inherited into a
graph dominated by T. If BINFO is NULL, TYPE is a dependent base,
and we do a shallow copy. If BINFO is non-NULL, we do a deep copy.
......
2012-07-05 Jason Merrill <jason@redhat.com>
PR c++/50852
* g++.dg/template/typedef39.C: New.
PR c++/53039
* g++.dg/cpp0x/variadic133.C: New.
* g++.dg/template/param1.C: Adjust.
2012-07-05 Ramana Radhakrishnan <ramana.radhakrishnan@linaro.org>
PR target/48941
......
// PR c++/53039
// { dg-do compile { target c++11 } }
template <class, class>
struct is_convertible
{
static const bool value = true;
};
template<bool, class T>
struct enable_if
{
typedef T type;
};
template <bool...>
struct Xs
{
static const bool value = true;
};
template<typename... BTs>
class BType
{
template <typename... BUs,
typename enable_if<
Xs<is_convertible<BUs, BTs>::value...>::value,
bool>::type = false>
void fooX(BUs&&...);
};
template <typename... ATs>
struct AType
{
template <typename... AUs,
typename enable_if<
Xs<is_convertible<AUs, ATs>::value...>::value,
bool>::type = false>
void foo(AUs&&...);
};
int main()
{
AType<int, int> t;
t.foo(1, 1);
}
......@@ -2,11 +2,11 @@
// Origin: Volker Reichelt <reichelt@igpm.rwth-aachen.de>
// { dg-do compile }
template<int> struct A // { dg-error "declaration" }
template<int> struct A
{
A();
};
template<int N, char> A<N>::A() {} // { dg-error "invalid use of incomplete type" }
template<int N, char> A<N>::A() {} // { dg-error "got 2 template parameters|1 required" }
A<0> a;
// PR c++/50852
template<int d> class A;
template<class T> struct B {typedef int K;typedef int L;};
template<class U,class V> struct C
{
typedef typename U::L X;
typedef A<X::a-1> W; // { dg-error "not a member" }
};
template<class U,int d> struct D
{
typedef typename U::L X;
typedef A<X::a-1> W; // the error should really be on this line
};
template class D<B<A<1> >,3>;
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