Commit d3a79fcc by Jason Merrill Committed by Jason Merrill

re PR c++/44587 (ICE in instantiate_decl)

	PR c++/44587
	* pt.c (has_value_dependent_address): New.
	(value_dependent_expression_p): Check it.
	(convert_nontype_argument): Likewise.  Call decay_conversion before
	folding if we want a pointer.
	* semantics.c (finish_id_expression): Don't add SCOPE_REF if the
	scope is the current instantiation.

From-SVN: r161559
parent 7ecb00a6
2010-06-29 Jason Merrill <jason@redhat.com>
PR c++/44587
* pt.c (has_value_dependent_address): New.
(value_dependent_expression_p): Check it.
(convert_nontype_argument): Likewise. Call decay_conversion before
folding if we want a pointer.
* semantics.c (finish_id_expression): Don't add SCOPE_REF if the
scope is the current instantiation.
2010-06-28 Jakub Jelinek <jakub@redhat.com> 2010-06-28 Jakub Jelinek <jakub@redhat.com>
PR c++/44682 PR c++/44682
......
...@@ -4880,6 +4880,36 @@ check_valid_ptrmem_cst_expr (tree type, tree expr) ...@@ -4880,6 +4880,36 @@ check_valid_ptrmem_cst_expr (tree type, tree expr)
return false; return false;
} }
/* Returns TRUE iff the address of OP is value-dependent.
14.6.2.4 [temp.dep.temp]:
A non-integral non-type template-argument is dependent if its type is
dependent or it has either of the following forms
qualified-id
& qualified-id
and contains a nested-name-specifier which specifies a class-name that
names a dependent type.
We generalize this to just say that the address of a member of a
dependent class is value-dependent; the above doesn't cover the
address of a static data member named with an unqualified-id. */
static bool
has_value_dependent_address (tree op)
{
/* We could use get_inner_reference here, but there's no need;
this is only relevant for template non-type arguments, which
can only be expressed as &id-expression. */
if (DECL_P (op))
{
tree ctx = CP_DECL_CONTEXT (op);
if (TYPE_P (ctx) && dependent_type_p (ctx))
return true;
}
return false;
}
/* Attempt to convert the non-type template parameter EXPR to the /* Attempt to convert the non-type template parameter EXPR to the
indicated TYPE. If the conversion is successful, return the indicated TYPE. If the conversion is successful, return the
converted value. If the conversion is unsuccessful, return converted value. If the conversion is unsuccessful, return
...@@ -4918,6 +4948,11 @@ convert_nontype_argument (tree type, tree expr) ...@@ -4918,6 +4948,11 @@ convert_nontype_argument (tree type, tree expr)
return NULL_TREE; return NULL_TREE;
} }
/* Add the ADDR_EXPR now for the benefit of
value_dependent_expression_p. */
if (TYPE_PTROBV_P (type))
expr = decay_conversion (expr);
/* If we are in a template, EXPR may be non-dependent, but still /* If we are in a template, EXPR may be non-dependent, but still
have a syntactic, rather than semantic, form. For example, EXPR have a syntactic, rather than semantic, form. For example, EXPR
might be a SCOPE_REF, rather than the VAR_DECL to which the might be a SCOPE_REF, rather than the VAR_DECL to which the
...@@ -4925,7 +4960,11 @@ convert_nontype_argument (tree type, tree expr) ...@@ -4925,7 +4960,11 @@ convert_nontype_argument (tree type, tree expr)
so that access checking can be performed when the template is so that access checking can be performed when the template is
instantiated -- but here we need the resolved form so that we can instantiated -- but here we need the resolved form so that we can
convert the argument. */ convert the argument. */
expr = fold_non_dependent_expr (expr); if (TYPE_REF_OBJ_P (type)
&& has_value_dependent_address (expr))
/* If we want the address and it's value-dependent, don't fold. */;
else
expr = fold_non_dependent_expr (expr);
if (error_operand_p (expr)) if (error_operand_p (expr))
return error_mark_node; return error_mark_node;
expr_type = TREE_TYPE (expr); expr_type = TREE_TYPE (expr);
...@@ -17638,6 +17677,13 @@ value_dependent_expression_p (tree expression) ...@@ -17638,6 +17677,13 @@ value_dependent_expression_p (tree expression)
return ((value_dependent_expression_p (TREE_OPERAND (expression, 0))) return ((value_dependent_expression_p (TREE_OPERAND (expression, 0)))
|| (value_dependent_expression_p (TREE_OPERAND (expression, 2)))); || (value_dependent_expression_p (TREE_OPERAND (expression, 2))));
case ADDR_EXPR:
{
tree op = TREE_OPERAND (expression, 0);
return (value_dependent_expression_p (op)
|| has_value_dependent_address (op));
}
default: default:
/* A constant expression is value-dependent if any subexpression is /* A constant expression is value-dependent if any subexpression is
value-dependent. */ value-dependent. */
......
...@@ -3097,7 +3097,13 @@ finish_id_expression (tree id_expression, ...@@ -3097,7 +3097,13 @@ finish_id_expression (tree id_expression,
{ {
tree r = convert_from_reference (decl); tree r = convert_from_reference (decl);
if (processing_template_decl && TYPE_P (scope)) /* In a template, return a SCOPE_REF for most qualified-ids
so that we can check access at instantiation time. But if
we're looking at a member of the current instantiation, we
know we have access and building up the SCOPE_REF confuses
non-type template argument handling. */
if (processing_template_decl && TYPE_P (scope)
&& !currently_open_class (scope))
r = build_qualified_name (TREE_TYPE (r), r = build_qualified_name (TREE_TYPE (r),
scope, decl, scope, decl,
template_p); template_p);
......
2010-06-29 Jason Merrill <jason@redhat.com>
PR c++/44587
* g++.dg/template/qualified-id2.C: New.
* g++.dg/template/qualified-id3.C: New.
2010-06-29 Janus Weil <janus@gcc.gnu.org> 2010-06-29 Janus Weil <janus@gcc.gnu.org>
PR fortran/44696 PR fortran/44696
......
// PR c++/44587
// { dg-do run }
template <const char *N> struct A { static const char *p; };
template <const char *N> const char *A<N>::p = N;
template <class T> struct B { static const char c[1]; typedef A<B<T>::c> C; };
template <class T> const char B<T>::c[1] = "";
template <class T> struct D { static const char c[1]; typedef A<c> C; };
template <class T> const char D<T>::c[1] = "";
template <int& I> struct E { static int *ip; };
template <int& I> int* E<I>::ip = &I;
template <class T> struct F { static int i; typedef E<F<T>::i> C; };
template <class T> int F<T>::i;
template <class T> struct G { static int i; typedef E<i> C; };
template <class T> int G<T>::i;
#define AS(X) if (!(X)) return 1;
int main()
{
AS(B<int>::C::p == B<int>::c);
AS(B<float>::C::p == B<float>::c);
AS(B<float>::C::p != B<int>::c);
AS(D<int>::C::p == D<int>::c);
AS(D<float>::C::p == D<float>::c);
AS(D<float>::C::p != D<int>::c);
}
// PR c++/44587
template <const int N> struct A { };
template <class T> struct B {
static const int c;
typedef A<B<T>::c> C; // { dg-error "non-constant" }
};
template <class T> const int B<T>::c = sizeof (T);
template <const int N> struct D { };
template <class T> struct E {
static const int c = sizeof (T);
typedef D<E<T>::c> F; // OK
};
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