+2006-02-18 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/26266
+ * cp-tree.h (cp_finish_decl): Adjust declaration.
+ (grokbitfield): Likewise.
+ (finish_static_data_member_decl): Likewise.
+ * init.c (constant_value_1): Ensure processing_template_decl when
+ folding non-dependent initializers for static data members of
+ dependent types. Return error_mark_node for erroneous
+ initailizers.
+ * class.c (get_vtable_decl): Use finish_decl, not cp_finish_decl.
+ * decl.c (cp_make_fname_decl): Adjust call to cp_finish_decl.
+ (cp_finish_decl): Add init_const_expr_p parameter. Set
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P here.
+ (finish_decl): Adjust call to cp_finish_decl.
+ (compute_array_index_type): Robustify.
+ (start_method): Use finish_decl, not cp_finish_decl.
+ * rtti.c (emit_tinfo_decl): Likewise.
+ * except.c (initialize_handler_parm): Adjust call to
+ cp_finish_decl.
+ (expand_start_catch_block): Likewise.
+ * cvt.c (build_up_reference): Adjust call to cp_finish_decl.
+ * pt.c (instantiate_class_template): Adjust call to
+ finish_static_data_member_decl.
+ (tsubst_expr): Use finish_decl, not cp_finish_decl.
+ (instantiate_decl): Adjust call to cp_finish_decl.
+ * name-lookup.c (pushdecl_top_level_1): Use finish_decl, not
+ cp_finish_decl.
+ * decl2.c (finish_static_data_member_decl): Add init_const_expr_p
+ parameter.
+ (grokfield): Likewise.
+ * parser.c (cp_parser_condition): Check for constant initializers.
+ (cp_parser_init_declarator): Adjust calls to grokfield and
+ cp_finish_decl. Don't set
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P here.
+ (cp_parser_member_declaration): Likewise.
+ (cp_parser_objc_class_ivars): Likewise.
+
2006-02-14 Volker Reichelt <reichelt@igpm.rwth-aachen.de>
* call.c (standard_conversion): Return NULL instead of 0.
if (complete)
{
DECL_EXTERNAL (decl) = 1;
- cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0);
+ finish_decl (decl, NULL_TREE, NULL_TREE);
}
return decl;
extern tree groktypename (cp_decl_specifier_seq *, const cp_declarator *);
extern tree start_decl (const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree, tree *);
extern void start_decl_1 (tree);
-extern void cp_finish_decl (tree, tree, tree, int);
+extern void cp_finish_decl (tree, tree, bool, tree, int);
extern void finish_decl (tree, tree, tree);
extern int cp_complete_array_type (tree *, tree, bool);
extern tree build_ptrmemfunc_type (tree);
extern tree check_classfn (tree, tree, tree);
extern void check_member_template (tree);
extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *,
- tree, tree, tree);
+ tree, bool, tree, tree);
extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *,
tree);
extern void cplus_decl_attributes (tree *, tree, int);
extern tree build_offset_ref_call_from_tree (tree, tree);
extern void check_default_args (tree);
extern void mark_used (tree);
-extern void finish_static_data_member_decl (tree, tree, tree, int);
+extern void finish_static_data_member_decl (tree, tree, bool, tree, int);
extern tree cp_build_parm_decl (tree, tree);
extern tree get_guard (tree);
extern tree get_guard_cond (tree);
/* Process the initializer for the declaration. */
DECL_INITIAL (arg) = targ;
- cp_finish_decl (arg, targ, NULL_TREE,
+ cp_finish_decl (arg, targ, /*init_const_expr_p=*/false, NULL_TREE,
LOOKUP_ONLYCONVERTING|DIRECT_BIND);
}
else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg))
while (b->level_chain->kind != sk_function_parms)
b = b->level_chain;
pushdecl_with_scope (decl, b, /*is_friend=*/false);
- cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
+ cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
+ LOOKUP_ONLYCONVERTING);
}
else
pushdecl_top_level_and_finish (decl, init);
If the length of an array type is not known before,
it must be determined now, from the initial value, or it is an error.
- INIT holds the value of an initializer that should be allowed to escape
- the normal rules.
+ INIT is the initializer (if any) for DECL. If INIT_CONST_EXPR_P is
+ true, then INIT is an integral constant expression.
FLAGS is LOOKUP_ONLYCONVERTING if the = init syntax was used, else 0
if the (init) syntax was used. */
void
-cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
+cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
+ tree asmspec_tree, int flags)
{
tree type;
tree cleanup;
add_decl_expr (decl);
if (init && DECL_INITIAL (decl))
- DECL_INITIAL (decl) = init;
+ {
+ DECL_INITIAL (decl) = init;
+ if (init_const_expr_p)
+ {
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
+ if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
+ TREE_CONSTANT (decl) = 1;
+ }
+ }
+
if (TREE_CODE (decl) == VAR_DECL
&& !DECL_PRETTY_FUNCTION_P (decl)
&& !dependent_type_p (TREE_TYPE (decl)))
&& (!DECL_EXTERNAL (decl) || init))
{
if (init)
- DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
+ {
+ DECL_NONTRIVIALLY_INITIALIZED_P (decl) = 1;
+ if (init_const_expr_p)
+ {
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
+ if (DECL_INTEGRAL_CONSTANT_VAR_P (decl))
+ TREE_CONSTANT (decl) = 1;
+ }
+ }
init = check_initializer (decl, init, flags, &cleanup);
/* Thread-local storage cannot be dynamically initialized. */
if (DECL_THREAD_LOCAL_P (decl) && init)
void
finish_decl (tree decl, tree init, tree asmspec_tree)
{
- cp_finish_decl (decl, init, asmspec_tree, 0);
+ cp_finish_decl (decl, init, /*init_const_expr_p=*/false, asmspec_tree, 0);
}
/* Returns a declaration for a VAR_DECL as if:
library), then it is possible that our declaration will be merged
with theirs by pushdecl. */
decl = pushdecl (decl);
- cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0);
+ finish_decl (decl, NULL_TREE, NULL_TREE);
pop_from_top_level ();
return decl;
tree
compute_array_index_type (tree name, tree size)
{
- tree type = TREE_TYPE (size);
+ tree type;
tree itype;
+ if (error_operand_p (size))
+ return error_mark_node;
+
+ type = TREE_TYPE (size);
/* The array bound must be an integer type. */
if (!dependent_type_p (type) && !INTEGRAL_TYPE_P (type))
{
grok_special_member_properties (fndecl);
}
- cp_finish_decl (fndecl, NULL_TREE, NULL_TREE, 0);
+ finish_decl (fndecl, NULL_TREE, NULL_TREE);
/* Make a place for the parms. */
begin_scope (sk_function_parms, fndecl);
}
/* We have just processed the DECL, which is a static data member.
- Its initializer, if present, is INIT. The ASMSPEC_TREE, if
- present, is the assembly-language name for the data member.
- FLAGS is as for cp_finish_decl. */
+ The other parameters are as for cp_finish_decl. */
void
-finish_static_data_member_decl (tree decl, tree init, tree asmspec_tree,
+finish_static_data_member_decl (tree decl,
+ tree init, bool init_const_expr_p,
+ tree asmspec_tree,
int flags)
{
gcc_assert (TREE_PUBLIC (decl));
DECL_INITIAL (decl) = init;
DECL_IN_AGGR_P (decl) = 1;
- cp_finish_decl (decl, init, asmspec_tree, flags);
+ cp_finish_decl (decl, init, init_const_expr_p, asmspec_tree, flags);
}
-/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
- of a structure component, returning a _DECL node.
- QUALS is a list of type qualifiers for this decl (such as for declaring
- const member functions).
-
- This is done during the parsing of the struct declaration.
- The _DECL nodes are chained together and the lot of them
- are ultimately passed to `build_struct' to make the RECORD_TYPE node.
-
- If class A defines that certain functions in class B are friends, then
- the way I have set things up, it is B who is interested in permission
- granted by A. However, it is in A's context that these declarations
- are parsed. By returning a void_type_node, class A does not attempt
- to incorporate the declarations of the friends within its structure.
-
- DO NOT MAKE ANY CHANGES TO THIS CODE WITHOUT MAKING CORRESPONDING
- CHANGES TO CODE IN `start_method'. */
+/* DECLARATOR and DECLSPECS correspond to a class member. The othe
+ parameters are as for cp_finish_decl. Return the DECL for the
+ class member declared. */
tree
grokfield (const cp_declarator *declarator,
cp_decl_specifier_seq *declspecs,
- tree init, tree asmspec_tree,
+ tree init, bool init_const_expr_p,
+ tree asmspec_tree,
tree attrlist)
{
tree value;
switch (TREE_CODE (value))
{
case VAR_DECL:
- finish_static_data_member_decl (value, init, asmspec_tree,
- flags);
+ finish_static_data_member_decl (value, init, init_const_expr_p,
+ asmspec_tree, flags);
return value;
case FIELD_DECL:
error ("%<asm%> specifiers are not permitted on non-static data members");
if (DECL_INITIAL (value) == error_mark_node)
init = error_mark_node;
- cp_finish_decl (value, init, NULL_TREE, flags);
+ cp_finish_decl (value, init, /*init_const_expr_p=*/false,
+ NULL_TREE, flags);
DECL_INITIAL (value) = init;
DECL_IN_AGGR_P (value) = 1;
return value;
if (!DECL_FRIEND_P (value))
grok_special_member_properties (value);
- cp_finish_decl (value, init, asmspec_tree, flags);
+ cp_finish_decl (value, init, /*init_const_expr_p=*/false,
+ asmspec_tree, flags);
/* Pass friends back this way. */
if (DECL_FRIEND_P (value))
error ("static member %qD cannot be a bit-field", value);
return NULL_TREE;
}
- cp_finish_decl (value, NULL_TREE, NULL_TREE, 0);
+ finish_decl (value, NULL_TREE, NULL_TREE);
if (width != error_mark_node)
{
decl = pushdecl (decl);
start_decl_1 (decl);
- cp_finish_decl (decl, init, NULL_TREE,
+ cp_finish_decl (decl, init, /*init_const_expr_p=*/false, NULL_TREE,
LOOKUP_ONLYCONVERTING|DIRECT_BIND);
}
tree init = do_begin_catch ();
exp = create_temporary_var (ptr_type_node);
DECL_REGISTER (exp) = 1;
- cp_finish_decl (exp, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
+ cp_finish_decl (exp, init, /*init_const_expr=*/false,
+ NULL_TREE, LOOKUP_ONLYCONVERTING);
finish_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));
initialize_handler_parm (decl, exp);
}
tree init;
/* Static data members in template classes may have
non-dependent initializers. References to such non-static
- data members are no value-dependent, so we must retrieve the
+ data members are not value-dependent, so we must retrieve the
initializer here. The DECL_INITIAL will have the right type,
but will not have been folded because that would prevent us
from performing all appropriate semantic checks at
&& CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
&& uses_template_parms (CLASSTYPE_TI_ARGS
(DECL_CONTEXT (decl))))
- init = fold_non_dependent_expr (DECL_INITIAL (decl));
+ {
+ ++processing_template_decl;
+ init = fold_non_dependent_expr (DECL_INITIAL (decl));
+ --processing_template_decl;
+ }
else
{
/* If DECL is a static data member in a template
mark_used (decl);
init = DECL_INITIAL (decl);
}
- if (!init || init == error_mark_node
+ if (init == error_mark_node)
+ return error_mark_node;
+ if (!init
|| !TREE_TYPE (init)
|| (integral_p
? !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (init))
push_to_top_level ();
x = pushdecl_namespace_level (x, is_friend);
if (init)
- cp_finish_decl (x, *init, NULL_TREE, 0);
+ finish_decl (x, *init, NULL_TREE);
pop_from_top_level ();
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
if (cp_parser_parse_definitely (parser))
{
tree pushed_scope;
+ bool non_constant_p;
/* Create the declaration. */
decl = start_decl (declarator, &type_specifiers,
attributes, /*prefix_attributes=*/NULL_TREE,
&pushed_scope);
/* Parse the assignment-expression. */
- initializer = cp_parser_assignment_expression (parser,
- /*cast_p=*/false);
+ initializer
+ = cp_parser_constant_expression (parser,
+ /*allow_non_constant_p=*/true,
+ &non_constant_p);
+ if (!non_constant_p)
+ initializer = fold_non_dependent_expr (initializer);
/* Process the initializer. */
cp_finish_decl (decl,
- initializer,
+ initializer, !non_constant_p,
asm_specification,
LOOKUP_ONLYCONVERTING);
pushed_scope = false;
}
decl = grokfield (declarator, decl_specifiers,
- initializer, /*asmspec=*/NULL_TREE,
+ initializer, !is_non_constant_init,
+ /*asmspec=*/NULL_TREE,
prefix_attributes);
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
cp_parser_save_default_args (parser, decl);
if (!friend_p && decl && decl != error_mark_node)
{
cp_finish_decl (decl,
- initializer,
+ initializer, !is_non_constant_init,
asm_specification,
/* If the initializer is in parentheses, then this is
a direct-initialization, which means that an
if (!friend_p && pushed_scope)
pop_scope (pushed_scope);
- /* Remember whether or not variables were initialized by
- constant-expressions. */
- if (decl && TREE_CODE (decl) == VAR_DECL
- && is_initialized && !is_non_constant_init)
- DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true;
-
return decl;
}
return;
}
else
- {
- /* Create the declaration. */
- decl = grokfield (declarator, &decl_specifiers,
- initializer, asm_specification,
- attributes);
- /* Any initialization must have been from a
- constant-expression. */
- if (decl && TREE_CODE (decl) == VAR_DECL && initializer)
- DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
- }
+ /* Create the declaration. */
+ decl = grokfield (declarator, &decl_specifiers,
+ initializer, /*init_const_expr_p=*/true,
+ asm_specification,
+ attributes);
}
/* Reset PREFIX_ATTRIBUTES. */
cplus_decl_attributes (&decl, attributes, /*flags=*/0);
}
else
- decl = grokfield (declarator, &declspecs, NULL_TREE,
+ decl = grokfield (declarator, &declspecs,
+ NULL_TREE, /*init_const_expr_p=*/false,
NULL_TREE, attributes);
/* Add the instance variable. */
finish_static_data_member_decl
(r,
/*init=*/NULL_TREE,
+ /*init_const_expr_p=*/false,
/*asmspec_tree=*/NULL_TREE,
/*flags=*/0);
if (DECL_INITIALIZED_IN_CLASS_P (r))
}
else
init = tsubst_expr (init, args, complain, in_decl);
- cp_finish_decl (decl, init, NULL_TREE, 0);
+ finish_decl (decl, init, NULL_TREE);
}
}
}
args,
tf_warning_or_error, NULL_TREE);
DECL_INITIAL (d) = init;
- cp_finish_decl (d, init, /*asmspec_tree=*/NULL_TREE,
+ cp_finish_decl (d, init, /*init_const_expr_p=*/false,
+ /*asmspec_tree=*/NULL_TREE,
LOOKUP_ONLYCONVERTING);
pop_nested_class ();
pop_nested_namespace (ns);
/* Enter the scope of D so that access-checking works correctly. */
push_nested_class (DECL_CONTEXT (d));
- cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0);
+ finish_decl (d, DECL_INITIAL (d), NULL_TREE);
pop_nested_class ();
}
else if (TREE_CODE (d) == FUNCTION_DECL)
init = get_pseudo_ti_init (type, get_pseudo_ti_index (type));
DECL_INITIAL (decl) = init;
mark_used (decl);
- cp_finish_decl (decl, init, NULL_TREE, 0);
+ finish_decl (decl, init, NULL_TREE);
return true;
}
else
+2006-02-18 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/26266
+ * g++.dg/template/static22.C: New test.
+ * g++.dg/template/static23.C: New test.
+ * g++.dg/template/static24.C: New test.
+ * g++.dg/template/non-dependent13.C: New test.
+
2006-02-16 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
PR target/26255
--- /dev/null
+// PR c++/26266
+
+template <int I>
+struct S;
+
+template <int I>
+void f() {
+ if (const int i = 3) {
+ S<i>::j; // { dg-error "incomplete" }
+ }
+}
--- /dev/null
+// PR c++/26266
+
+template<typename> struct A
+{
+ static const int i = 1;
+ static const int j = i;
+ static const int k = int(j);
+ int x[k];
+};
+
+A<char> a;
--- /dev/null
+// PR c++/26266
+
+template<typename> struct A
+{
+ static const int i = 1;
+};
+
+template<typename> struct B
+{
+ static const int j = A<char>::i;
+ static const int k = int(j);
+ int x[k];
+};
+
+B<char> b;
--- /dev/null
+template<typename> struct A;
+
+template<> struct A<char>
+{
+ static const char i = 1;
+};
+
+template<typename T> struct B
+{
+ static const int j = A<T>::i;
+ static const int k = int(j);
+ int x[k];
+};
+
+B<char> b;