re PR c++/23099 (ICE in build_simple_base_path, at cp/class.c:460)
PR c++/23099 * cp-tree.h (saved_scope): Add skip_evaluation. * decl.c (start_decl): Use DECL_INITIALIZED_IN_CLASS_P, not DECL_INITIAL, to determine whether or not a static data member was initialized in the class-specifier. (cp_finish_decl): Add comment. * init.c (integral_constant_value): Subtitute into the initializers for static data members in templates. * name-lookup.c (push_to_top_level): Save skip_evaluation. (pop_from_top_level): Restore it. * pt.c (instantiate_class_template): Do not substitute into the intializers of static data members when instantiating a class. (regenerate_decl_from_template): Simplify. (instantiate_decl): Tidy. Substitute into the initializer for a static data member even when the definition of the data member is not available. PR c++/23099 * g++.dg/init/member1.C: Make sure erroneous static data member definitions are required. * g++.dg/template/static13.C: New test. * g++.dg/template/static14.C: Likewise. From-SVN: r103604
This commit is contained in:
parent
3a6ebcdcee
commit
b794e321c1
@ -1,3 +1,22 @@
|
||||
2005-08-28 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/23099
|
||||
* cp-tree.h (saved_scope): Add skip_evaluation.
|
||||
* decl.c (start_decl): Use DECL_INITIALIZED_IN_CLASS_P, not
|
||||
DECL_INITIAL, to determine whether or not a static data member was
|
||||
initialized in the class-specifier.
|
||||
(cp_finish_decl): Add comment.
|
||||
* init.c (integral_constant_value): Subtitute into the
|
||||
initializers for static data members in templates.
|
||||
* name-lookup.c (push_to_top_level): Save skip_evaluation.
|
||||
(pop_from_top_level): Restore it.
|
||||
* pt.c (instantiate_class_template): Do not substitute into the
|
||||
intializers of static data members when instantiating a class.
|
||||
(regenerate_decl_from_template): Simplify.
|
||||
(instantiate_decl): Tidy. Substitute into the initializer for a
|
||||
static data member even when the definition of the data member is
|
||||
not available.
|
||||
|
||||
2005-08-26 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/19004
|
||||
|
@ -655,6 +655,7 @@ struct saved_scope GTY(())
|
||||
int x_processing_specialization;
|
||||
bool x_processing_explicit_instantiation;
|
||||
int need_pop_function_context;
|
||||
bool skip_evaluation;
|
||||
|
||||
struct stmt_tree_s x_stmt_tree;
|
||||
|
||||
|
@ -3716,7 +3716,8 @@ start_decl (const cp_declarator *declarator,
|
||||
declaration will have DECL_EXTERNAL set, but will have an
|
||||
initialization. Thus, duplicate_decls won't warn
|
||||
about this situation, and so we check here. */
|
||||
if (DECL_INITIAL (decl) && DECL_INITIAL (field))
|
||||
if (DECL_INITIAL (decl)
|
||||
&& DECL_INITIALIZED_IN_CLASS_P (field))
|
||||
error ("duplicate initialization of %qD", decl);
|
||||
if (duplicate_decls (decl, field))
|
||||
decl = field;
|
||||
@ -4921,10 +4922,20 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
|
||||
"initialized", decl);
|
||||
init = NULL_TREE;
|
||||
}
|
||||
|
||||
/* Check that the initializer for a static data member was a
|
||||
constant. Althouh we check in the parser that the
|
||||
initializer is an integral constant expression, we do not
|
||||
simplify division-by-zero at the point at which it
|
||||
occurs. Therefore, in:
|
||||
|
||||
struct S { static const int i = 7 / 0; };
|
||||
|
||||
we issue an error at this point. It would
|
||||
probably be better to forbid division by zero in
|
||||
integral constant expressions. */
|
||||
if (DECL_EXTERNAL (decl) && init)
|
||||
{
|
||||
/* The static data member cannot be initialized by a
|
||||
non-constant when being declared. */
|
||||
error ("%qD cannot be initialized by a non-constant expression"
|
||||
" when being declared", decl);
|
||||
DECL_INITIALIZED_IN_CLASS_P (decl) = 0;
|
||||
|
@ -1572,12 +1572,25 @@ integral_constant_value (tree decl)
|
||||
/* And so are variables with a 'const' type -- unless they
|
||||
are also 'volatile'. */
|
||||
&& CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl))
|
||||
&& DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)))
|
||||
&& DECL_INITIAL (decl)
|
||||
&& DECL_INITIAL (decl) != error_mark_node
|
||||
&& TREE_TYPE (DECL_INITIAL (decl))
|
||||
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (DECL_INITIAL (decl))))
|
||||
decl = DECL_INITIAL (decl);
|
||||
&& DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))))
|
||||
{
|
||||
tree init;
|
||||
/* If DECL is a static data member in a template class, we must
|
||||
instantiate it here. The initializer for the static data
|
||||
member is not processed until needed; we need it now. */
|
||||
mark_used (decl);
|
||||
init = DECL_INITIAL (decl);
|
||||
/* If we are currently processing a template, the
|
||||
initializer for a static data member may not be dependent,
|
||||
but it is not folded until instantiation time. */
|
||||
if (init)
|
||||
init = fold_non_dependent_expr (init);
|
||||
if (!(init || init == error_mark_node)
|
||||
|| !TREE_TYPE (init)
|
||||
|| !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (init)))
|
||||
break;
|
||||
decl = init;
|
||||
}
|
||||
return decl;
|
||||
}
|
||||
|
||||
|
@ -4872,12 +4872,14 @@ push_to_top_level (void)
|
||||
s->bindings = b;
|
||||
s->need_pop_function_context = need_pop;
|
||||
s->function_decl = current_function_decl;
|
||||
s->skip_evaluation = skip_evaluation;
|
||||
|
||||
scope_chain = s;
|
||||
current_function_decl = NULL_TREE;
|
||||
current_lang_base = VEC_alloc (tree, gc, 10);
|
||||
current_lang_name = lang_name_cplusplus;
|
||||
current_namespace = global_namespace;
|
||||
skip_evaluation = 0;
|
||||
timevar_pop (TV_NAME_LOOKUP);
|
||||
}
|
||||
|
||||
@ -4909,6 +4911,7 @@ pop_from_top_level (void)
|
||||
if (s->need_pop_function_context)
|
||||
pop_function_context_from (NULL_TREE);
|
||||
current_function_decl = s->function_decl;
|
||||
skip_evaluation = s->skip_evaluation;
|
||||
timevar_pop (TV_NAME_LOOKUP);
|
||||
}
|
||||
|
||||
|
67
gcc/cp/pt.c
67
gcc/cp/pt.c
@ -5699,17 +5699,22 @@ instantiate_class_template (tree type)
|
||||
--processing_template_decl;
|
||||
if (TREE_CODE (r) == VAR_DECL)
|
||||
{
|
||||
tree init;
|
||||
/* In [temp.inst]:
|
||||
|
||||
if (DECL_INITIALIZED_IN_CLASS_P (r))
|
||||
init = tsubst_expr (DECL_INITIAL (t), args,
|
||||
tf_error | tf_warning, NULL_TREE);
|
||||
else
|
||||
init = NULL_TREE;
|
||||
|
||||
finish_static_data_member_decl
|
||||
(r, init, /*asmspec_tree=*/NULL_TREE, /*flags=*/0);
|
||||
[t]he initialization (and any associated
|
||||
side-effects) of a static data member does
|
||||
not occur unless the static data member is
|
||||
itself used in a way that requires the
|
||||
definition of the static data member to
|
||||
exist.
|
||||
|
||||
Therefore, we do not substitute into the
|
||||
initialized for the static data member here. */
|
||||
finish_static_data_member_decl
|
||||
(r,
|
||||
/*init=*/NULL_TREE,
|
||||
/*asmspec_tree=*/NULL_TREE,
|
||||
/*flags=*/0);
|
||||
if (DECL_INITIALIZED_IN_CLASS_P (r))
|
||||
check_static_variable_definition (r, TREE_TYPE (r));
|
||||
}
|
||||
@ -11278,13 +11283,9 @@ regenerate_decl_from_template (tree decl, tree tmpl)
|
||||
DECL_INLINE (decl) = 1;
|
||||
}
|
||||
else if (TREE_CODE (decl) == VAR_DECL)
|
||||
{
|
||||
if (!DECL_INITIALIZED_IN_CLASS_P (decl)
|
||||
&& DECL_INITIAL (code_pattern))
|
||||
DECL_INITIAL (decl) =
|
||||
tsubst_expr (DECL_INITIAL (code_pattern), args,
|
||||
tf_error, DECL_TI_TEMPLATE (decl));
|
||||
}
|
||||
DECL_INITIAL (decl) =
|
||||
tsubst_expr (DECL_INITIAL (code_pattern), args,
|
||||
tf_error, DECL_TI_TEMPLATE (decl));
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
@ -11367,7 +11368,7 @@ instantiate_decl (tree d, int defer_ok,
|
||||
tree code_pattern;
|
||||
tree spec;
|
||||
tree gen_tmpl;
|
||||
int pattern_defined;
|
||||
bool pattern_defined;
|
||||
int need_push;
|
||||
location_t saved_loc = input_location;
|
||||
|
||||
@ -11415,9 +11416,6 @@ instantiate_decl (tree d, int defer_ok,
|
||||
|
||||
timevar_push (TV_PARSE);
|
||||
|
||||
/* We may be in the middle of deferred access check. Disable it now. */
|
||||
push_deferring_access_checks (dk_no_deferred);
|
||||
|
||||
/* Set TD to the template whose DECL_TEMPLATE_RESULT is the pattern
|
||||
for the instantiation. */
|
||||
td = template_for_substitution (d);
|
||||
@ -11437,6 +11435,10 @@ instantiate_decl (tree d, int defer_ok,
|
||||
pattern_defined = (DECL_SAVED_TREE (code_pattern) != NULL_TREE);
|
||||
else
|
||||
pattern_defined = ! DECL_IN_AGGR_P (code_pattern);
|
||||
|
||||
/* We may be in the middle of deferred access check. Disable it now. */
|
||||
push_deferring_access_checks (dk_no_deferred);
|
||||
|
||||
/* Unless an explicit instantiation directive has already determined
|
||||
the linkage of D, remember that a definition is available for
|
||||
this entity. */
|
||||
@ -11486,12 +11488,6 @@ instantiate_decl (tree d, int defer_ok,
|
||||
pop_access_scope (d);
|
||||
}
|
||||
|
||||
/* We should have set up DECL_INITIAL in instantiate_class_template
|
||||
for in-class definitions of static data members. */
|
||||
gcc_assert (!(TREE_CODE (d) == VAR_DECL
|
||||
&& DECL_INITIALIZED_IN_CLASS_P (d)
|
||||
&& DECL_INITIAL (d) == NULL_TREE));
|
||||
|
||||
/* Do not instantiate templates that we know will be defined
|
||||
elsewhere. */
|
||||
if (DECL_INTERFACE_KNOWN (d)
|
||||
@ -11504,6 +11500,20 @@ instantiate_decl (tree d, int defer_ok,
|
||||
because it's used by add_pending_template. */
|
||||
else if (! pattern_defined || defer_ok)
|
||||
{
|
||||
/* The definition of the static data member is now required so
|
||||
we must substitute the initializer. */
|
||||
if (TREE_CODE (d) == VAR_DECL
|
||||
&& !DECL_INITIAL (d)
|
||||
&& DECL_INITIAL (code_pattern))
|
||||
{
|
||||
push_nested_class (DECL_CONTEXT (d));
|
||||
DECL_INITIAL (d)
|
||||
= tsubst_expr (DECL_INITIAL (code_pattern),
|
||||
args,
|
||||
tf_error | tf_warning, NULL_TREE);
|
||||
pop_nested_class ();
|
||||
}
|
||||
|
||||
input_location = saved_loc;
|
||||
|
||||
if (at_eof && !pattern_defined
|
||||
@ -11570,10 +11580,7 @@ instantiate_decl (tree d, int defer_ok,
|
||||
|
||||
/* Enter the scope of D so that access-checking works correctly. */
|
||||
push_nested_class (DECL_CONTEXT (d));
|
||||
cp_finish_decl (d,
|
||||
(!DECL_INITIALIZED_IN_CLASS_P (d)
|
||||
? DECL_INITIAL (d) : NULL_TREE),
|
||||
NULL_TREE, 0);
|
||||
cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0);
|
||||
pop_nested_class ();
|
||||
}
|
||||
else if (TREE_CODE (d) == FUNCTION_DECL)
|
||||
|
@ -1,3 +1,11 @@
|
||||
2005-08-28 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/23099
|
||||
* g++.dg/init/member1.C: Make sure erroneous static data member
|
||||
definitions are required.
|
||||
* g++.dg/template/static13.C: New test.
|
||||
* g++.dg/template/static14.C: Likewise.
|
||||
|
||||
2005-08-29 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* gcc.target/i386/pr23575.c: Use -msse2 instead of
|
||||
|
@ -11,8 +11,11 @@ template<int> struct B {};
|
||||
template<typename T> struct C
|
||||
{
|
||||
static const int i = A<T>::i; // { dg-error "incomplete" }
|
||||
static const int j = i; // { dg-error "initialized by a non-const" }
|
||||
static const int j = i;
|
||||
B<j> b; // { dg-error "not a valid template arg" }
|
||||
};
|
||||
|
||||
C<int> c;
|
||||
|
||||
int i = C<int>::i;
|
||||
int j = C<int>::j;
|
||||
|
14
gcc/testsuite/g++.dg/template/static13.C
Normal file
14
gcc/testsuite/g++.dg/template/static13.C
Normal file
@ -0,0 +1,14 @@
|
||||
// PR c++/23099
|
||||
|
||||
struct Base {
|
||||
int x;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct A {
|
||||
static const int N = sizeof(static_cast<Base*>(T()));
|
||||
};
|
||||
|
||||
struct Derived : Base {
|
||||
A<Derived*> a;
|
||||
};
|
13
gcc/testsuite/g++.dg/template/static14.C
Normal file
13
gcc/testsuite/g++.dg/template/static14.C
Normal file
@ -0,0 +1,13 @@
|
||||
struct Base {
|
||||
int x;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct A {
|
||||
static const int N = sizeof(static_cast<Base*>(T()));
|
||||
int a[N];
|
||||
};
|
||||
|
||||
struct Derived : Base {
|
||||
A<Derived*> a;
|
||||
};
|
Loading…
Reference in New Issue
Block a user