From fa8d6e85a759f80f8c75bbd045e18950b99c8001 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Mon, 19 Apr 1999 12:23:55 +0000 Subject: [PATCH] cp-tree.h (finish_static_data_member_decl): New function. * cp-tree.h (finish_static_data_member_decl): New function. * decl2.c (finish_static_data_member_decl): Split out from ... (grokfield): Here. * pt.c (instantiate_class_template): Use it here instead of trying to fake it. (tsubst_decl): Don't set DECL_ASSEMBLER_NAME; finish_static_data_member_decl will do that. Explicit set DECL_EXTERNAL to match non-template processing. From-SVN: r26548 --- gcc/cp/ChangeLog | 11 +++ gcc/cp/cp-tree.h | 1 + gcc/cp/decl2.c | 94 +++++++++++++-------- gcc/cp/pt.c | 29 ++++--- gcc/testsuite/g++.old-deja/g++.pt/static7.C | 14 +++ 5 files changed, 100 insertions(+), 49 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/static7.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 470c9cfca6c..d8bdb2c35af 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +1999-04-19 Mark Mitchell + + * cp-tree.h (finish_static_data_member_decl): New function. + * decl2.c (finish_static_data_member_decl): Split out from ... + (grokfield): Here. + * pt.c (instantiate_class_template): Use it here instead of + trying to fake it. + (tsubst_decl): Don't set DECL_ASSEMBLER_NAME; + finish_static_data_member_decl will do that. Explicit set + DECL_EXTERNAL to match non-template processing. + 1999-04-18 Mark Mitchell * cp-tree.h (finish_class_definition): Add parameter. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 3eb8550697e..21392cebbba 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2947,6 +2947,7 @@ extern void check_default_args PROTO((tree)); extern void mark_used PROTO((tree)); extern tree handle_class_head PROTO((tree, tree, tree)); extern tree lookup_arg_dependent PROTO((tree, tree, tree)); +extern void finish_static_data_member_decl PROTO((tree, tree, tree, int, int)); /* in errfn.c */ /* The cp_* functions aren't suitable for ATTRIBUTE_PRINTF. */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index c68e25a76b2..744baae1f20 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1456,6 +1456,61 @@ check_classfn (ctype, function) return NULL_TREE; } +/* 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. + NEED_POP and FLAGS are as for cp_finish_decl. */ + +void +finish_static_data_member_decl (decl, init, asmspec_tree, need_pop, flags) + tree decl; + tree init; + tree asmspec_tree; + int need_pop; + int flags; +{ + char* asmspec = 0; + + if (asmspec_tree) + asmspec = TREE_STRING_POINTER (asmspec_tree); + + my_friendly_assert (TREE_PUBLIC (decl), 0); + + /* We cannot call pushdecl here, because that would fill in the + decl of our TREE_CHAIN. Instead, we modify cp_finish_decl to do + the right thing, namely, to put this decl out straight away. */ + /* current_class_type can be NULL_TREE in case of error. */ + if (!asmspec && current_class_type) + { + DECL_INITIAL (decl) = error_mark_node; + DECL_ASSEMBLER_NAME (decl) + = build_static_name (current_class_type, DECL_NAME (decl)); + } + if (! processing_template_decl) + pending_statics = perm_tree_cons (NULL_TREE, decl, pending_statics); + + /* Static consts need not be initialized in the class definition. */ + if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))) + { + static int explanation = 0; + + error ("initializer invalid for static member with constructor"); + if (explanation++ == 0) + error ("(you really want to initialize it separately)"); + init = 0; + } + /* Force the compiler to know when an uninitialized static const + member is being used. */ + if (CP_TYPE_CONST_P (TREE_TYPE (decl)) && init == 0) + TREE_USED (decl) = 1; + DECL_INITIAL (decl) = init; + DECL_IN_AGGR_P (decl) = 1; + DECL_CONTEXT (decl) = current_class_type; + DECL_CLASS_CONTEXT (decl) = current_class_type; + + cp_finish_decl (decl, init, asmspec_tree, need_pop, flags); +} + /* Process the specs, declarator (NULL if omitted) and width (NULL if omitted) of a structure component, returning a FIELD_DECL node. QUALS is a list of type qualifiers for this decl (such as for declaring @@ -1635,43 +1690,8 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist) if (TREE_CODE (value) == VAR_DECL) { - my_friendly_assert (TREE_PUBLIC (value), 0); - - /* We cannot call pushdecl here, because that would - fill in the value of our TREE_CHAIN. Instead, we - modify cp_finish_decl to do the right thing, namely, to - put this decl out straight away. */ - /* current_class_type can be NULL_TREE in case of error. */ - if (asmspec == 0 && current_class_type) - { - TREE_PUBLIC (value) = 1; - DECL_INITIAL (value) = error_mark_node; - DECL_ASSEMBLER_NAME (value) - = build_static_name (current_class_type, DECL_NAME (value)); - } - if (! processing_template_decl) - pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics); - - /* Static consts need not be initialized in the class definition. */ - if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (value))) - { - static int explanation = 0; - - error ("initializer invalid for static member with constructor"); - if (explanation++ == 0) - error ("(you really want to initialize it separately)"); - init = 0; - } - /* Force the compiler to know when an uninitialized static - const member is being used. */ - if (CP_TYPE_CONST_P (TREE_TYPE (value)) && init == 0) - TREE_USED (value) = 1; - DECL_INITIAL (value) = init; - DECL_IN_AGGR_P (value) = 1; - DECL_CONTEXT (value) = current_class_type; - DECL_CLASS_CONTEXT (value) = current_class_type; - - cp_finish_decl (value, init, asmspec_tree, 1, flags); + finish_static_data_member_decl (value, init, asmspec_tree, + /*need_pop=*/1, flags); return value; } if (TREE_CODE (value) == FIELD_DECL) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b26b88a4dcc..f2e40b32242 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -4982,16 +4982,19 @@ instantiate_class_template (type) r = tsubst (t, args, /*complain=*/1, NULL_TREE); if (TREE_CODE (r) == VAR_DECL) { - pending_statics = perm_tree_cons (NULL_TREE, r, pending_statics); - /* Perhaps we should do more of grokfield here. */ + tree init; + if (DECL_DEFINED_IN_CLASS_P (r)) - /* Set up DECL_INITIAL, since tsubst doesn't. */ - DECL_INITIAL (r) = tsubst_expr (DECL_INITIAL (t), args, - /*complain=*/1, NULL_TREE); - start_decl_1 (r); - DECL_IN_AGGR_P (r) = 1; - DECL_EXTERNAL (r) = 1; - cp_finish_decl (r, DECL_INITIAL (r), NULL_TREE, 0, 0); + init = tsubst_expr (DECL_INITIAL (t), args, + /*complain=*/1, NULL_TREE); + else + init = NULL_TREE; + + finish_static_data_member_decl (r, init, + /*asmspec_tree=*/NULL_TREE, + /*need_pop=*/0, + /*flags=*/0); + if (DECL_DEFINED_IN_CLASS_P (r)) check_static_variable_definition (r, TREE_TYPE (r)); } @@ -5825,9 +5828,6 @@ tsubst_decl (t, args, type, in_decl) TREE_TYPE (r) = type; c_apply_type_quals_to_decl (CP_TYPE_QUALS (type), r); DECL_CONTEXT (r) = ctx; - if (TREE_STATIC (r)) - DECL_ASSEMBLER_NAME (r) - = build_static_name (DECL_CONTEXT (r), DECL_NAME (r)); /* Don't try to expand the initializer until someone tries to use this variable; otherwise we run into circular dependencies. */ @@ -5837,6 +5837,11 @@ tsubst_decl (t, args, type, in_decl) copy_lang_decl (r); DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r); + /* A static data member declaration is always marked external + when it is declared in-class, even if an initializer is + present. We mimic the non-template processing here. */ + DECL_EXTERNAL (r) = 1; + DECL_TEMPLATE_INFO (r) = perm_tree_cons (tmpl, argvec, NULL_TREE); SET_DECL_IMPLICIT_INSTANTIATION (r); register_specialization (r, gen_tmpl, argvec); diff --git a/gcc/testsuite/g++.old-deja/g++.pt/static7.C b/gcc/testsuite/g++.old-deja/g++.pt/static7.C new file mode 100644 index 00000000000..282f78fe8f8 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/static7.C @@ -0,0 +1,14 @@ +// Build don't link: +// Origin: Mark Mitchell + +template +struct S { + S() {} + + static S s; +}; + +template +S S::s; + +S si; -- 2.30.2