From ae58fa02be510bc8a7bb014a5f3f511594848d22 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Fri, 7 Aug 1998 16:33:34 +0000 Subject: [PATCH] typeck.c (require_complete_type): Use complete_type_or_else. * typeck.c (require_complete_type): Use complete_type_or_else. (complete_type_or_else): Always return NULL_TREE on failure, as documented. * pt.c (tsubst_aggr_type): Prototype. (tsubst_decl): New function, split out from tsubst. Set input_filename and lineno as appropriate. (pop_tinst_level): Restore the file and line number saved in push_tinst_level. (instantiate_class_template): Set input_filename and lineno as appropriate. (tsubst): Move _DECL processing to tsubst_decl. Make sure the context for a TYPENAME_TYPE is complete. * decl2.c (grokbitfield): Issue errors on bitfields declared with function type. (do_dtors): As in do_ctors, pretend to be a member of the same class as a static data member while generating a call to its destructor. From-SVN: r21627 --- gcc/cp/ChangeLog | 22 +- gcc/cp/decl2.c | 35 ++ gcc/cp/pt.c | 541 ++++++++++-------- gcc/cp/typeck.c | 16 +- .../g++.old-deja/g++.bugs/900402_01.C | 2 +- .../g++.old-deja/g++.law/visibility13.C | 4 +- gcc/testsuite/g++.old-deja/g++.other/dtor2.C | 13 + gcc/testsuite/g++.old-deja/g++.pt/friend23.C | 4 +- gcc/testsuite/g++.old-deja/g++.pt/t05.C | 8 +- gcc/testsuite/g++.old-deja/g++.pt/typename8.C | 27 + .../g++.old-deja/g++.robertl/eb109.C | 2 +- .../g++.old-deja/g++.robertl/eb128.C | 4 +- 12 files changed, 423 insertions(+), 255 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.other/dtor2.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/typename8.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f1957d80cd3..4a1c42ab060 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,6 +1,26 @@ 1998-08-07 Mark Mitchell - * cvt.c (cp_convert_to_pointer): Handle a NULL pointer + * typeck.c (require_complete_type): Use complete_type_or_else. + (complete_type_or_else): Always return NULL_TREE on failure, as + documented. + + * pt.c (tsubst_aggr_type): Prototype. + (tsubst_decl): New function, split out from tsubst. Set + input_filename and lineno as appropriate. + (pop_tinst_level): Restore the file and line number saved in + push_tinst_level. + (instantiate_class_template): Set input_filename and lineno as + appropriate. + (tsubst): Move _DECL processing to tsubst_decl. Make sure the + context for a TYPENAME_TYPE is complete. + + * decl2.c (grokbitfield): Issue errors on bitfields declared with + function type. + (do_dtors): As in do_ctors, pretend to be a member of the same + class as a static data member while generating a call to its + destructor. + + * cvt.c (cp_convert_to_pointer): Handle NULL pointer conversions, even in complex virtual base class hierarchies. 1998-08-06 Mark Mitchell diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 998b3463197..d8bc74f4779 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -1845,6 +1845,17 @@ grokbitfield (declarator, declspecs, width) return NULL_TREE; } + /* Usually, finish_struct_1 catches bitifields with invalid types. + But, in the case of bitfields with function type, we confuse + ourselves into thinking they are member functions, so we must + check here. */ + if (TREE_CODE (value) == FUNCTION_DECL) + { + cp_error ("cannot declare bitfield `%D' with funcion type", + DECL_NAME (value)); + return NULL_TREE; + } + if (IS_SIGNATURE (current_class_type)) { error ("field declaration not allowed in signature"); @@ -3001,6 +3012,25 @@ do_dtors () if (! current_function_decl) start_objects ('D'); + /* Because of: + + [class.access.spec] + + Access control for implicit calls to the constructors, + the conversion functions, or the destructor called to + create and destroy a static data member is per- formed as + if these calls appeared in the scope of the member's + class. + + we must convince enforce_access to let us access the + DECL. */ + if (member_p (decl)) + { + DECL_CLASS_CONTEXT (current_function_decl) + = DECL_CONTEXT (decl); + DECL_STATIC_FUNCTION_P (current_function_decl) = 1; + } + temp = build_cleanup (decl); if (protect) @@ -3015,6 +3045,11 @@ do_dtors () if (protect) expand_end_cond (); + + /* Now that we're done with DECL we don't need to pretend to + be a member of its class any longer. */ + DECL_CLASS_CONTEXT (current_function_decl) = NULL_TREE; + DECL_STATIC_FUNCTION_P (current_function_decl) = 0; } } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3071f1e3715..f664caa9bc6 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -122,6 +122,8 @@ static tree most_specialized_class PROTO((tree, tree)); static tree most_general_template PROTO((tree)); static void set_mangled_name_for_template_decl PROTO((tree)); static int template_class_depth_real PROTO((tree, int)); +static tree tsubst_aggr_type PROTO((tree, tree, tree, int)); +static tree tsubst_decl PROTO((tree, tree, tree, tree)); /* We use TREE_VECs to hold template arguments. If there is only one level of template arguments, then the TREE_VEC contains the @@ -3779,6 +3781,11 @@ pop_tinst_level () { struct tinst_level *old = current_tinst_level; + /* Restore the filename and line number stashed away when we started + this instantiation. */ + lineno = old->line; + input_filename = old->file; + current_tinst_level = old->next; old->next = free_tinst_level; free_tinst_level = old; @@ -4291,7 +4298,15 @@ instantiate_class_template (type) for (t = TYPE_FIELDS (pattern); t; t = TREE_CHAIN (t)) if (TREE_CODE (t) != CONST_DECL) { - tree r = tsubst (t, args, NULL_TREE); + tree r; + + /* The the file and line for this declaration, to assist in + error message reporting. Since we called push_tinst_level + above, we don't need to restore these. */ + lineno = DECL_SOURCE_LINE (t); + input_filename = DECL_SOURCE_FILE (t); + + r = tsubst (t, args, NULL_TREE); if (TREE_CODE (r) == VAR_DECL) { pending_statics = perm_tree_cons (NULL_TREE, r, pending_statics); @@ -4619,204 +4634,34 @@ tsubst_aggr_type (t, args, in_decl, entering_scope) } } -/* Take the tree structure T and replace template parameters used therein - with the argument vector ARGS. IN_DECL is an associated decl for - diagnostics. - - tsubst is used for dealing with types, decls and the like; for - expressions, use tsubst_expr or tsubst_copy. */ +/* Substitute the ARGS into the T, which is a _DECL. TYPE is the + (already computed) substitution of ARGS into TREE_TYPE (T), if + appropriate. Return the result of the substitution. IN_DECL is as + for tsubst. */ tree -tsubst (t, args, in_decl) - tree t, args; +tsubst_decl (t, args, type, in_decl) + tree t; + tree args; + tree type; tree in_decl; { - tree type; - - if (t == NULL_TREE || t == error_mark_node - || t == integer_type_node - || t == void_type_node - || t == char_type_node - || TREE_CODE (t) == NAMESPACE_DECL) - return t; - - if (TREE_CODE (t) == IDENTIFIER_NODE) - type = IDENTIFIER_TYPE_VALUE (t); - else - type = TREE_TYPE (t); - if (type == unknown_type_node) - my_friendly_abort (42); + int saved_lineno; + char* saved_filename; + tree r; - if (type && TREE_CODE (t) != FUNCTION_DECL - && TREE_CODE (t) != TYPENAME_TYPE - && TREE_CODE (t) != TEMPLATE_DECL - && TREE_CODE (t) != IDENTIFIER_NODE) - type = tsubst (type, args, in_decl); + /* Set the filename and linenumber to improve error-reporting. */ + saved_lineno = lineno; + saved_filename = input_filename; + lineno = DECL_SOURCE_LINE (t); + input_filename = DECL_SOURCE_FILE (t); switch (TREE_CODE (t)) { - case RECORD_TYPE: - case UNION_TYPE: - case ENUMERAL_TYPE: - return tsubst_aggr_type (t, args, in_decl, /*entering_scope=*/0); - - case ERROR_MARK: - case IDENTIFIER_NODE: - case OP_IDENTIFIER: - case VOID_TYPE: - case REAL_TYPE: - case COMPLEX_TYPE: - case BOOLEAN_TYPE: - case INTEGER_CST: - case REAL_CST: - case STRING_CST: - case NAMESPACE_DECL: - return t; - - case INTEGER_TYPE: - if (t == integer_type_node) - return t; - - if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST - && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST) - return t; - - { - tree max = TREE_OPERAND (TYPE_MAX_VALUE (t), 0); - max = tsubst_expr (max, args, in_decl); - if (processing_template_decl) - { - tree itype = make_node (INTEGER_TYPE); - TYPE_MIN_VALUE (itype) = size_zero_node; - TYPE_MAX_VALUE (itype) = build_min (MINUS_EXPR, sizetype, max, - integer_one_node); - return itype; - } - - max = fold (build_binary_op (MINUS_EXPR, max, integer_one_node, 1)); - return build_index_2_type (size_zero_node, max); - } - - case TEMPLATE_TYPE_PARM: - case TEMPLATE_TEMPLATE_PARM: - case TEMPLATE_PARM_INDEX: - { - int idx; - int level; - int levels; - tree r = NULL_TREE; - - if (TREE_CODE (t) == TEMPLATE_TYPE_PARM - || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM) - { - idx = TEMPLATE_TYPE_IDX (t); - level = TEMPLATE_TYPE_LEVEL (t); - } - else - { - idx = TEMPLATE_PARM_IDX (t); - level = TEMPLATE_PARM_LEVEL (t); - } - - if (TREE_VEC_LENGTH (args) > 0) - { - tree arg = NULL_TREE; - - levels = TMPL_ARGS_DEPTH (args); - if (level <= levels) - arg = TMPL_ARG (args, level, idx); - - if (arg != NULL_TREE) - { - if (TREE_CODE (t) == TEMPLATE_TYPE_PARM) - { - my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg)) - == 't', 0); - return cp_build_type_variant - (arg, TYPE_READONLY (arg) || TYPE_READONLY (t), - TYPE_VOLATILE (arg) || TYPE_VOLATILE (t)); - } - else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM) - { - if (CLASSTYPE_TEMPLATE_INFO (t)) - { - /* We are processing a type constructed from - a template template parameter */ - tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), - args, in_decl); - tree r; - - /* We can get a TEMPLATE_TEMPLATE_PARM here when - we are resolving nested-types in the signature of - a member function templates. - Otherwise ARG is a TEMPLATE_DECL and is the real - template to be instantiated. */ - if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM) - arg = TYPE_NAME (arg); - - r = lookup_template_class (DECL_NAME (arg), - argvec, in_decl, - DECL_CONTEXT (arg), - /*entering_scope=*/0); - return cp_build_type_variant (r, TYPE_READONLY (t), - TYPE_VOLATILE (t)); - } - else - /* We are processing a template argument list. */ - return arg; - } - else - return arg; - } - } - - if (level == 1) - /* This can happen during the attempted tsubst'ing in - unify. This means that we don't yet have any information - about the template parameter in question. */ - return t; - - /* If we get here, we must have been looking at a parm for a - more deeply nested template. Make a new version of this - template parameter, but with a lower level. */ - switch (TREE_CODE (t)) - { - case TEMPLATE_TYPE_PARM: - case TEMPLATE_TEMPLATE_PARM: - r = copy_node (t); - TEMPLATE_TYPE_PARM_INDEX (r) - = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t), - r, levels); - TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r); - TYPE_MAIN_VARIANT (r) = r; - TYPE_POINTER_TO (r) = NULL_TREE; - TYPE_REFERENCE_TO (r) = NULL_TREE; - - if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM - && CLASSTYPE_TEMPLATE_INFO (t)) - { - tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl); - CLASSTYPE_TEMPLATE_INFO (r) - = perm_tree_cons (TYPE_NAME (t), argvec, NULL_TREE); - } - break; - - case TEMPLATE_PARM_INDEX: - r = reduce_template_parm_level (t, type, levels); - break; - - default: - my_friendly_abort (0); - } - - return r; - } - case TEMPLATE_DECL: { /* We can get here when processing a member template function of a template class. */ - tree tmpl; tree decl = DECL_TEMPLATE_RESULT (t); tree parms; tree* new_parms; @@ -4841,7 +4686,10 @@ tsubst (t, args, in_decl) spec = retrieve_specialization (t, full_args); if (spec != NULL_TREE) - return spec; + { + r = spec; + break; + } } /* Make a new template decl. It will be similar to the @@ -4849,60 +4697,60 @@ tsubst (t, args, in_decl) We also create a new function declaration, which is just like the old one, but points to this new template, rather than the old one. */ - tmpl = copy_node (t); - copy_lang_decl (tmpl); - my_friendly_assert (DECL_LANG_SPECIFIC (tmpl) != 0, 0); - TREE_CHAIN (tmpl) = NULL_TREE; + r = copy_node (t); + copy_lang_decl (r); + my_friendly_assert (DECL_LANG_SPECIFIC (r) != 0, 0); + TREE_CHAIN (r) = NULL_TREE; if (is_template_template_parm) { tree new_decl = tsubst (decl, args, in_decl); - DECL_RESULT (tmpl) = new_decl; - TREE_TYPE (tmpl) = TREE_TYPE (new_decl); - return tmpl; + DECL_RESULT (r) = new_decl; + TREE_TYPE (r) = TREE_TYPE (new_decl); + break; } - DECL_CONTEXT (tmpl) + DECL_CONTEXT (r) = tsubst_aggr_type (DECL_CONTEXT (t), args, in_decl, /*entering_scope=*/1); - DECL_CLASS_CONTEXT (tmpl) + DECL_CLASS_CONTEXT (r) = tsubst_aggr_type (DECL_CLASS_CONTEXT (t), args, in_decl, /*entering_scope=*/1); - DECL_TEMPLATE_INFO (tmpl) = build_tree_list (t, args); + DECL_TEMPLATE_INFO (r) = build_tree_list (t, args); if (TREE_CODE (decl) == TYPE_DECL) { tree new_type = tsubst (TREE_TYPE (t), args, in_decl); - TREE_TYPE (tmpl) = new_type; - CLASSTYPE_TI_TEMPLATE (new_type) = tmpl; - DECL_RESULT (tmpl) = TYPE_MAIN_DECL (new_type); - DECL_TI_ARGS (tmpl) = CLASSTYPE_TI_ARGS (new_type); + TREE_TYPE (r) = new_type; + CLASSTYPE_TI_TEMPLATE (new_type) = r; + DECL_RESULT (r) = TYPE_MAIN_DECL (new_type); + DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type); } else { tree new_decl = tsubst (decl, args, in_decl); - DECL_RESULT (tmpl) = new_decl; - DECL_TI_TEMPLATE (new_decl) = tmpl; - TREE_TYPE (tmpl) = TREE_TYPE (new_decl); - DECL_TI_ARGS (tmpl) = DECL_TI_ARGS (new_decl); + DECL_RESULT (r) = new_decl; + DECL_TI_TEMPLATE (new_decl) = r; + TREE_TYPE (r) = TREE_TYPE (new_decl); + DECL_TI_ARGS (r) = DECL_TI_ARGS (new_decl); } - SET_DECL_IMPLICIT_INSTANTIATION (tmpl); - DECL_TEMPLATE_INSTANTIATIONS (tmpl) = NULL_TREE; - DECL_TEMPLATE_SPECIALIZATIONS (tmpl) = NULL_TREE; + SET_DECL_IMPLICIT_INSTANTIATION (r); + DECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE; + DECL_TEMPLATE_SPECIALIZATIONS (r) = NULL_TREE; /* The template parameters for this new template are all the template parameters for the old template, except the outermost level of parameters. */ - DECL_TEMPLATE_PARMS (tmpl) + DECL_TEMPLATE_PARMS (r) = tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args); if (PRIMARY_TEMPLATE_P (t)) - DECL_PRIMARY_TEMPLATE (tmpl) = tmpl; + DECL_PRIMARY_TEMPLATE (r) = r; /* We don't partially instantiate partial specializations. */ if (TREE_CODE (decl) == TYPE_DECL) - return tmpl; + break; for (spec = DECL_TEMPLATE_SPECIALIZATIONS (t); spec != NULL_TREE; @@ -4953,20 +4801,19 @@ tsubst (t, args, in_decl) new_fn = tsubst (DECL_RESULT (most_general_template (fn)), spec_args, in_decl); DECL_TI_TEMPLATE (new_fn) = fn; - register_specialization (new_fn, tmpl, + register_specialization (new_fn, r, innermost_args (spec_args)); } /* Record this partial instantiation. */ - register_specialization (tmpl, t, - DECL_TI_ARGS (DECL_RESULT (tmpl))); + register_specialization (r, t, + DECL_TI_ARGS (DECL_RESULT (r))); - return tmpl; } + break; case FUNCTION_DECL: { - tree r = NULL_TREE; tree ctx; tree argvec; tree gen_tmpl; @@ -4988,7 +4835,10 @@ tsubst (t, args, in_decl) /* Check to see if we already have this specialization. */ spec = retrieve_specialization (gen_tmpl, argvec); if (spec) - return spec; + { + r = spec; + break; + } } else { @@ -5113,13 +4963,12 @@ tsubst (t, args, in_decl) == NULL_TREE)) SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r); } - - return r; } + break; case PARM_DECL: { - tree r = copy_node (t); + r = copy_node (t); TREE_TYPE (r) = type; if (TREE_CODE (DECL_INITIAL (r)) != TEMPLATE_PARM_INDEX) DECL_INITIAL (r) = TREE_TYPE (r); @@ -5135,12 +4984,12 @@ tsubst (t, args, in_decl) #endif if (TREE_CHAIN (t)) TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, TREE_CHAIN (t)); - return r; } + break; case FIELD_DECL: { - tree r = copy_node (t); + r = copy_node (t); TREE_TYPE (r) = type; copy_lang_decl (r); #if 0 @@ -5150,21 +4999,20 @@ tsubst (t, args, in_decl) TREE_CHAIN (r) = NULL_TREE; if (TREE_CODE (type) == VOID_TYPE) cp_error_at ("instantiation of `%D' as type void", r); - return r; } + break; case USING_DECL: { - tree r = copy_node (t); + r = copy_node (t); DECL_INITIAL (r) = tsubst_copy (DECL_INITIAL (t), args, in_decl); TREE_CHAIN (r) = NULL_TREE; - return r; } + break; case VAR_DECL: { - tree r; tree argvec; tree gen_tmpl; tree spec; @@ -5183,7 +5031,10 @@ tsubst (t, args, in_decl) spec = retrieve_specialization (gen_tmpl, argvec); if (spec) - return spec; + { + r = spec; + break; + } r = copy_node (t); TREE_TYPE (r) = type; @@ -5207,20 +5058,227 @@ tsubst (t, args, in_decl) TREE_CHAIN (r) = NULL_TREE; if (TREE_CODE (type) == VOID_TYPE) cp_error_at ("instantiation of `%D' as type void", r); - return r; } + break; case TYPE_DECL: if (t == TYPE_NAME (TREE_TYPE (t))) - return TYPE_NAME (type); + r = TYPE_NAME (type); + else + { + r = copy_node (t); + TREE_TYPE (r) = type; + DECL_CONTEXT (r) = current_class_type; + TREE_CHAIN (r) = NULL_TREE; + } + break; + + default: + my_friendly_abort (0); + } + + /* Restore the file and line information. */ + lineno = saved_lineno; + input_filename = saved_filename; + + return r; +} + + +/* Take the tree structure T and replace template parameters used therein + with the argument vector ARGS. IN_DECL is an associated decl for + diagnostics. + + tsubst is used for dealing with types, decls and the like; for + expressions, use tsubst_expr or tsubst_copy. */ + +tree +tsubst (t, args, in_decl) + tree t, args; + tree in_decl; +{ + tree type; + + if (t == NULL_TREE || t == error_mark_node + || t == integer_type_node + || t == void_type_node + || t == char_type_node + || TREE_CODE (t) == NAMESPACE_DECL) + return t; + + if (TREE_CODE (t) == IDENTIFIER_NODE) + type = IDENTIFIER_TYPE_VALUE (t); + else + type = TREE_TYPE (t); + if (type == unknown_type_node) + my_friendly_abort (42); + + if (type && TREE_CODE (t) != FUNCTION_DECL + && TREE_CODE (t) != TYPENAME_TYPE + && TREE_CODE (t) != TEMPLATE_DECL + && TREE_CODE (t) != IDENTIFIER_NODE) + type = tsubst (type, args, in_decl); + + if (TREE_CODE_CLASS (TREE_CODE (t)) == 'd') + return tsubst_decl (t, args, type, in_decl); + + switch (TREE_CODE (t)) + { + case RECORD_TYPE: + case UNION_TYPE: + case ENUMERAL_TYPE: + return tsubst_aggr_type (t, args, in_decl, /*entering_scope=*/0); + + case ERROR_MARK: + case IDENTIFIER_NODE: + case OP_IDENTIFIER: + case VOID_TYPE: + case REAL_TYPE: + case COMPLEX_TYPE: + case BOOLEAN_TYPE: + case INTEGER_CST: + case REAL_CST: + case STRING_CST: + return t; + + case INTEGER_TYPE: + if (t == integer_type_node) + return t; + + if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST + && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST) + return t; { - tree r = copy_node (t); - TREE_TYPE (r) = type; - DECL_CONTEXT (r) = current_class_type; - TREE_CHAIN (r) = NULL_TREE; + tree max = TREE_OPERAND (TYPE_MAX_VALUE (t), 0); + max = tsubst_expr (max, args, in_decl); + if (processing_template_decl) + { + tree itype = make_node (INTEGER_TYPE); + TYPE_MIN_VALUE (itype) = size_zero_node; + TYPE_MAX_VALUE (itype) = build_min (MINUS_EXPR, sizetype, max, + integer_one_node); + return itype; + } + + max = fold (build_binary_op (MINUS_EXPR, max, integer_one_node, 1)); + return build_index_2_type (size_zero_node, max); + } + + case TEMPLATE_TYPE_PARM: + case TEMPLATE_TEMPLATE_PARM: + case TEMPLATE_PARM_INDEX: + { + int idx; + int level; + int levels; + tree r = NULL_TREE; + + if (TREE_CODE (t) == TEMPLATE_TYPE_PARM + || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM) + { + idx = TEMPLATE_TYPE_IDX (t); + level = TEMPLATE_TYPE_LEVEL (t); + } + else + { + idx = TEMPLATE_PARM_IDX (t); + level = TEMPLATE_PARM_LEVEL (t); + } + + if (TREE_VEC_LENGTH (args) > 0) + { + tree arg = NULL_TREE; + + levels = TMPL_ARGS_DEPTH (args); + if (level <= levels) + arg = TMPL_ARG (args, level, idx); + + if (arg != NULL_TREE) + { + if (TREE_CODE (t) == TEMPLATE_TYPE_PARM) + { + my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (arg)) + == 't', 0); + return cp_build_type_variant + (arg, TYPE_READONLY (arg) || TYPE_READONLY (t), + TYPE_VOLATILE (arg) || TYPE_VOLATILE (t)); + } + else if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM) + { + if (CLASSTYPE_TEMPLATE_INFO (t)) + { + /* We are processing a type constructed from + a template template parameter */ + tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), + args, in_decl); + tree r; + + /* We can get a TEMPLATE_TEMPLATE_PARM here when + we are resolving nested-types in the signature of + a member function templates. + Otherwise ARG is a TEMPLATE_DECL and is the real + template to be instantiated. */ + if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM) + arg = TYPE_NAME (arg); + + r = lookup_template_class (DECL_NAME (arg), + argvec, in_decl, + DECL_CONTEXT (arg), + /*entering_scope=*/0); + return cp_build_type_variant (r, TYPE_READONLY (t), + TYPE_VOLATILE (t)); + } + else + /* We are processing a template argument list. */ + return arg; + } + else + return arg; + } + } + + if (level == 1) + /* This can happen during the attempted tsubst'ing in + unify. This means that we don't yet have any information + about the template parameter in question. */ + return t; + + /* If we get here, we must have been looking at a parm for a + more deeply nested template. Make a new version of this + template parameter, but with a lower level. */ + switch (TREE_CODE (t)) + { + case TEMPLATE_TYPE_PARM: + case TEMPLATE_TEMPLATE_PARM: + r = copy_node (t); + TEMPLATE_TYPE_PARM_INDEX (r) + = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t), + r, levels); + TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r); + TYPE_MAIN_VARIANT (r) = r; + TYPE_POINTER_TO (r) = NULL_TREE; + TYPE_REFERENCE_TO (r) = NULL_TREE; + + if (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM + && CLASSTYPE_TEMPLATE_INFO (t)) + { + tree argvec = tsubst (CLASSTYPE_TI_ARGS (t), args, in_decl); + CLASSTYPE_TEMPLATE_INFO (r) + = perm_tree_cons (TYPE_NAME (t), argvec, NULL_TREE); + } + break; + + case TEMPLATE_PARM_INDEX: + r = reduce_template_parm_level (t, type, levels); + break; + + default: + my_friendly_abort (0); + } + return r; - } + } case TREE_LIST: { @@ -5439,6 +5497,19 @@ tsubst (t, args, in_decl) tree ctx = tsubst_aggr_type (TYPE_CONTEXT (t), args, in_decl, /*entering_scope=*/1); tree f = tsubst_copy (TYPENAME_TYPE_FULLNAME (t), args, in_decl); + + /* Normally, make_typename_type does not require that the CTX + have complete type in order to allow things like: + + template struct S { typename S::X Y; }; + + But, such constructs have already been resolved by this + point, so here CTX really should have complete type, unless + it's a partial instantiation. */ + if (!uses_template_parms (ctx) + && !complete_type_or_else (ctx)) + return error_mark_node; + f = make_typename_type (ctx, f); return cp_build_type_variant (f, TYPE_READONLY (f) || TYPE_READONLY (t), diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 3e4fd0ab7b2..008a3157a52 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -80,7 +80,9 @@ target_type (type) } /* Do `exp = require_complete_type (exp);' to make sure exp - does not have an incomplete type. (That includes void types.) */ + does not have an incomplete type. (That includes void types.) + Returns the error_mark_node if the VALUE does not have + complete type when this function returns. */ tree require_complete_type (value) @@ -120,13 +122,10 @@ require_complete_type (value) return require_complete_type (value); } - if (TYPE_SIZE (complete_type (type))) + if (complete_type_or_else (type)) return value; else - { - incomplete_type_error (value, type); - return error_mark_node; - } + return error_mark_node; } /* Try to complete TYPE, if it is incomplete. For example, if TYPE is @@ -170,7 +169,10 @@ complete_type_or_else (type) tree type; { type = complete_type (type); - if (type != error_mark_node && !TYPE_SIZE (type)) + if (type == error_mark_node) + /* We already issued an error. */ + return NULL_TREE; + else if (!TYPE_SIZE (type)) { incomplete_type_error (NULL_TREE, type); return NULL_TREE; diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900402_01.C b/gcc/testsuite/g++.old-deja/g++.bugs/900402_01.C index 4e636b5ece9..946e6d1e0d3 100644 --- a/gcc/testsuite/g++.old-deja/g++.bugs/900402_01.C +++ b/gcc/testsuite/g++.old-deja/g++.bugs/900402_01.C @@ -9,7 +9,7 @@ typedef void (func_type) (); struct s { - func_type f:32; // ERROR - XFAIL *-*-* + func_type f:32; // ERROR - bitified with function type }; int main () { return 0; } diff --git a/gcc/testsuite/g++.old-deja/g++.law/visibility13.C b/gcc/testsuite/g++.old-deja/g++.law/visibility13.C index 6e53fc739c5..8bd6a851b71 100644 --- a/gcc/testsuite/g++.old-deja/g++.law/visibility13.C +++ b/gcc/testsuite/g++.old-deja/g++.law/visibility13.C @@ -14,7 +14,7 @@ const int ArraySize = 12; template -class Array { +class Array { // ERROR - .struct Array_RC redecl.* friend class Array_RC; public: Array(const Type *ar, int sz) { init(ar,sz); } @@ -97,7 +97,7 @@ try_array( Array_RC &rc ) main() { static int ia[10] = { 12, 7, 14, 9, 128, 17, 6, 3, 27, 5 }; - Array_RC iA(ia, 10);// ERROR - .struct Array_RC redecl.* + Array_RC iA(ia, 10);// ERROR - instantiated from here cout << "template Array_RC class" << endl; try_array(iA); diff --git a/gcc/testsuite/g++.old-deja/g++.other/dtor2.C b/gcc/testsuite/g++.old-deja/g++.other/dtor2.C new file mode 100644 index 00000000000..201068c415b --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/dtor2.C @@ -0,0 +1,13 @@ +// Build don't link: + +class K { +public: + friend class C; + +private: + static K qwe; + K(); + ~K(); +}; + +K K::qwe; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend23.C b/gcc/testsuite/g++.old-deja/g++.pt/friend23.C index efb24b1d551..21065f1cac1 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/friend23.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/friend23.C @@ -2,9 +2,9 @@ template // ERROR - original definition struct S -{ +{ // ERROR - redefinition of default arg template friend class S; }; -template struct S; // ERROR - redefinition of default arg +template struct S; // ERROR - instantiated from here diff --git a/gcc/testsuite/g++.old-deja/g++.pt/t05.C b/gcc/testsuite/g++.old-deja/g++.pt/t05.C index 888f1de95ea..6dab744b357 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/t05.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/t05.C @@ -1,9 +1,9 @@ // Build don't link: -template class B { - A a; +template class B { // ERROR - candidates + A a; public: - B(A&aa); // ERROR - + B(A&aa); // ERROR - near match ~B(); }; -static B b_int (3); // ERROR - +static B b_int (3); // ERROR - no matching function diff --git a/gcc/testsuite/g++.old-deja/g++.pt/typename8.C b/gcc/testsuite/g++.old-deja/g++.pt/typename8.C new file mode 100644 index 00000000000..d2eb4cede91 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/typename8.C @@ -0,0 +1,27 @@ +// Build don't link: + +template < class T > class A +{ +public: + typedef typename T::myT anotherT; // ERROR - undefined type + + anotherT t; // ERROR - undefined type + + A(anotherT _t) { // ERROR - undefined type + t=_t; + } + + anotherT getT() { + return t; + } +}; + +class B : public A< B > +{ +public: + typedef int myT; +}; + +int main() { + B b; +} diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C index dd9e0e53f84..94141548687 100644 --- a/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C +++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb109.C @@ -17,7 +17,7 @@ inline istream& operator>>(istream& is, Empty& ) { return is;} template class Graph -{ +{ // ERROR - candidates public: // public type interface typedef map Successor; diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb128.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb128.C index ae4fc6683eb..d056e39012e 100644 --- a/gcc/testsuite/g++.old-deja/g++.robertl/eb128.C +++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb128.C @@ -1,11 +1,11 @@ template struct A { - typedef T* iterator; + typedef T* iterator; // ERROR - pointer to reference public: A(){} }; void f() { - A a; // ERROR - pointer to reference + A a; // ERROR - instantiated from here } -- 2.30.2