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
This commit is contained in:
parent
7ecb00a6e2
commit
d3a79fcc3c
@ -1,3 +1,13 @@
|
||||
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>
|
||||
|
||||
PR c++/44682
|
||||
|
48
gcc/cp/pt.c
48
gcc/cp/pt.c
@ -4880,6 +4880,36 @@ check_valid_ptrmem_cst_expr (tree type, tree expr)
|
||||
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
|
||||
indicated TYPE. If the conversion is successful, return the
|
||||
converted value. If the conversion is unsuccessful, return
|
||||
@ -4918,6 +4948,11 @@ convert_nontype_argument (tree type, tree expr)
|
||||
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
|
||||
have a syntactic, rather than semantic, form. For example, EXPR
|
||||
might be a SCOPE_REF, rather than the VAR_DECL to which the
|
||||
@ -4925,7 +4960,11 @@ convert_nontype_argument (tree type, tree expr)
|
||||
so that access checking can be performed when the template is
|
||||
instantiated -- but here we need the resolved form so that we can
|
||||
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))
|
||||
return error_mark_node;
|
||||
expr_type = TREE_TYPE (expr);
|
||||
@ -17638,6 +17677,13 @@ value_dependent_expression_p (tree expression)
|
||||
return ((value_dependent_expression_p (TREE_OPERAND (expression, 0)))
|
||||
|| (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:
|
||||
/* A constant expression is value-dependent if any subexpression is
|
||||
value-dependent. */
|
||||
|
@ -3097,7 +3097,13 @@ finish_id_expression (tree id_expression,
|
||||
{
|
||||
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),
|
||||
scope, decl,
|
||||
template_p);
|
||||
|
@ -1,3 +1,9 @@
|
||||
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>
|
||||
|
||||
PR fortran/44696
|
||||
|
27
gcc/testsuite/g++.dg/template/qualified-id2.C
Normal file
27
gcc/testsuite/g++.dg/template/qualified-id2.C
Normal file
@ -0,0 +1,27 @@
|
||||
// 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);
|
||||
}
|
14
gcc/testsuite/g++.dg/template/qualified-id3.C
Normal file
14
gcc/testsuite/g++.dg/template/qualified-id3.C
Normal file
@ -0,0 +1,14 @@
|
||||
// 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
|
||||
};
|
Loading…
Reference in New Issue
Block a user