diff options
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r-- | gcc/cp/pt.c | 248 |
1 files changed, 165 insertions, 83 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 152ac0e3820..b751ad49e74 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -134,6 +134,7 @@ static tree build_template_decl PARAMS ((tree, tree)); static int mark_template_parm PARAMS ((tree, void *)); static tree tsubst_friend_function PARAMS ((tree, tree)); static tree tsubst_friend_class PARAMS ((tree, tree)); +static int can_complete_type_without_circularity PARAMS ((tree)); static tree get_bindings_real PARAMS ((tree, tree, tree, int, int, int)); static int template_decl_level PARAMS ((tree)); static tree maybe_get_template_decl_from_type_decl PARAMS ((tree)); @@ -3302,17 +3303,12 @@ convert_template_argument (parm, arg, args, complain, i, in_decl) && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL) || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE); - else if (CLASSTYPE_TEMPLATE_INFO (arg) && !CLASSTYPE_USE_TEMPLATE (arg) - && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (arg))) - { - if (is_base_of_enclosing_class (arg, current_class_type)) - /* This is a template name used within the scope of the - template. It could be the template, or it could be the - instantiation. Choose whichever makes sense. */ - is_tmpl_type = requires_tmpl_type; - else - is_tmpl_type = 1; - } + else if (CLASSTYPE_IS_TEMPLATE (arg) + && is_base_of_enclosing_class (arg, current_class_type)) + /* This is a template name used within the scope of the + template. It could be the template, or it could be the + instantiation. Choose whichever makes sense. */ + is_tmpl_type = requires_tmpl_type; else /* It is a non-template class, or a specialization of a template class, or a non-template member of a template class. */ @@ -3429,6 +3425,16 @@ convert_template_argument (parm, arg, args, complain, i, in_decl) val, t); return error_mark_node; } + + /* In order to avoid all sorts of complications, we do + not allow variably-modified types as template + arguments. */ + if (variably_modified_type_p (val)) + { + error ("template-argument `%T' is a variably modified type", + val); + return error_mark_node; + } } } } @@ -3942,10 +3948,16 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain) The template parameter level of T and U are one level larger than of TT. To proper process the default argument of U, say when an instantiation `TT<int>' is seen, we need to build the full - arguments containing {int} as the innermost level. Outer levels - can be obtained from `current_template_args ()'. */ + arguments containing {int} as the innermost level. Outer levels, + available when not appearing as default template argument, can be + obtained from `current_template_args ()'. - if (processing_template_decl) + Suppose that TT is later substituted with std::vector. The above + instantiation is `TT<int, std::allocator<T> >' with TT at + level 1, and T at level 2, while the template arguments at level 1 + becomes {std::vector} and the inner level 2 is {int}. */ + + if (current_template_parms) arglist = add_to_template_args (current_template_args (), arglist); arglist2 = coerce_template_parms (parmlist, arglist, template, @@ -4588,7 +4600,7 @@ tsubst_friend_function (decl, args) tree template_id, arglist, fns; tree new_args; tree tmpl; - tree ns = CP_DECL_CONTEXT (TYPE_MAIN_DECL (current_class_type)); + tree ns = decl_namespace_context (TYPE_MAIN_DECL (current_class_type)); /* Friend functions are looked up in the containing namespace scope. We must enter that scope, to avoid finding member functions of the @@ -4796,16 +4808,27 @@ tsubst_friend_class (friend_tmpl, args) { tree friend_type; tree tmpl; + tree context; + + context = DECL_CONTEXT (friend_tmpl); + + if (context) + { + if (TREE_CODE (context) == NAMESPACE_DECL) + push_nested_namespace (context); + else + push_nested_class (tsubst (context, args, tf_none, NULL_TREE), 2); + } /* First, we look for a class template. */ tmpl = lookup_name (DECL_NAME (friend_tmpl), /*prefer_type=*/0); - + /* But, if we don't find one, it might be because we're in a situation like this: template <class T> struct S { - template <class U> + template <class U> friend struct S; }; @@ -4825,12 +4848,15 @@ tsubst_friend_class (friend_tmpl, args) of course. We only need the innermost template parameters because that is all that redeclare_class_template will look at. */ - tree parms - = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_tmpl), - args, tf_error | tf_warning); - if (!parms) - return error_mark_node; - redeclare_class_template (TREE_TYPE (tmpl), parms); + if (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (friend_tmpl)) + > TMPL_ARGS_DEPTH (args)) + { + tree parms; + parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_tmpl), + args, tf_error | tf_warning); + redeclare_class_template (TREE_TYPE (tmpl), parms); + } + friend_type = TREE_TYPE (tmpl); } else @@ -4852,9 +4878,36 @@ tsubst_friend_class (friend_tmpl, args) friend_type = TREE_TYPE (pushdecl_top_level (tmpl)); } + if (context) + { + if (TREE_CODE (context) == NAMESPACE_DECL) + pop_nested_namespace (context); + else + pop_nested_class (); + } + return friend_type; } +/* Returns zero if TYPE cannot be completed later due to circularity. + Otherwise returns one. */ + +static int +can_complete_type_without_circularity (type) + tree type; +{ + if (type == NULL_TREE || type == error_mark_node) + return 0; + else if (COMPLETE_TYPE_P (type)) + return 1; + else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type)) + return can_complete_type_without_circularity (TREE_TYPE (type)); + else if (CLASS_TYPE_P (type) && TYPE_BEING_DEFINED (TYPE_MAIN_VARIANT (type))) + return 0; + else + return 1; +} + tree instantiate_class_template (type) tree type; @@ -5175,7 +5228,20 @@ instantiate_class_template (type) if (DECL_INITIALIZED_IN_CLASS_P (r)) check_static_variable_definition (r, TREE_TYPE (r)); } - + else if (TREE_CODE (r) == FIELD_DECL) + { + /* Determine whether R has a valid type and can be + completed later. If R is invalid, then it is replaced + by error_mark_node so that it will not be added to + TYPE_FIELDS. */ + tree rtype = TREE_TYPE (r); + if (!can_complete_type_without_circularity (rtype)) + { + incomplete_type_error (r, rtype); + r = error_mark_node; + } + } + /* R will have a TREE_CHAIN if and only if it has already been processed by finish_member_declaration. This can happen if, for example, it is a TYPE_DECL for a class-scoped @@ -5256,6 +5322,8 @@ instantiate_class_template (type) --processing_template_decl; } + /* Now that TYPE_FIELDS and TYPE_METHODS are set up. We can + instantiate templates used by this class. */ for (t = TYPE_FIELDS (type); t; t = TREE_CHAIN (t)) if (TREE_CODE (t) == FIELD_DECL) { @@ -6016,6 +6084,8 @@ tsubst_decl (t, args, type, complain) } r = copy_decl (t); + if (TREE_CODE (r) == VAR_DECL) + type = complete_type (type); TREE_TYPE (r) = type; c_apply_type_quals_to_decl (cp_type_quals (type), r); DECL_CONTEXT (r) = ctx; @@ -6029,15 +6099,6 @@ tsubst_decl (t, args, type, complain) SET_DECL_RTL (r, NULL_RTX); DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0; - /* For __PRETTY_FUNCTION__ we have to adjust the initializer. */ - if (DECL_PRETTY_FUNCTION_P (r)) - { - const char *const name = (*decl_printable_name) - (current_function_decl, 2); - DECL_INITIAL (r) = cp_fname_init (name); - TREE_TYPE (r) = TREE_TYPE (DECL_INITIAL (r)); - } - /* Even if the original location is out of scope, the newly substituted one is not. */ if (TREE_CODE (r) == VAR_DECL) @@ -6061,6 +6122,8 @@ tsubst_decl (t, args, type, complain) TREE_CHAIN (r) = NULL_TREE; if (TREE_CODE (r) == VAR_DECL && VOID_TYPE_P (type)) cp_error_at ("instantiation of `%D' as type `%T'", r, type); + /* Compute the size, alignment, etc. of R. */ + layout_decl (r, 0); } break; @@ -7080,9 +7143,10 @@ tsubst_copy (t, args, complain, in_decl) { tree base = tsubst_copy (TREE_OPERAND (name, 0), args, complain, in_decl); - name = TREE_OPERAND (name, 1); - name = tsubst_copy (TREE_OPERAND (name, 0), args, - complain, in_decl); + name = TREE_OPERAND (TREE_OPERAND (name, 1), 0); + if (TREE_CODE (name) == TYPE_DECL) + name = TREE_TYPE (name); + name = tsubst_copy (name, args, complain, in_decl); name = build1 (BIT_NOT_EXPR, NULL_TREE, name); name = build_nt (SCOPE_REF, base, name); } @@ -7318,15 +7382,8 @@ tsubst_expr (t, args, complain, in_decl) { init = DECL_INITIAL (decl); decl = tsubst (decl, args, complain, in_decl); - if (DECL_PRETTY_FUNCTION_P (decl)) - init = DECL_INITIAL (decl); - else - init = tsubst_expr (init, args, complain, in_decl); if (decl != error_mark_node) { - if (TREE_CODE (decl) != TYPE_DECL) - /* Make sure the type is instantiated now. */ - complete_type (TREE_TYPE (decl)); if (init) DECL_INITIAL (decl) = error_mark_node; /* By marking the declaration as instantiated, we avoid @@ -7336,8 +7393,26 @@ tsubst_expr (t, args, complain, in_decl) do. */ if (TREE_CODE (decl) == VAR_DECL) DECL_TEMPLATE_INSTANTIATED (decl) = 1; - maybe_push_decl (decl); - cp_finish_decl (decl, init, NULL_TREE, 0); + if (TREE_CODE (decl) == VAR_DECL + && ANON_AGGR_TYPE_P (TREE_TYPE (decl))) + /* Anonymous aggregates are a special case. */ + finish_anon_union (decl); + else + { + maybe_push_decl (decl); + if (DECL_PRETTY_FUNCTION_P (decl)) + { + /* For __PRETTY_FUNCTION__ we have to adjust the + initializer. */ + const char *const name + = (*decl_printable_name) (current_function_decl, 2); + init = cp_fname_init (name); + TREE_TYPE (decl) = TREE_TYPE (init); + } + else + init = tsubst_expr (init, args, complain, in_decl); + cp_finish_decl (decl, init, NULL_TREE, 0); + } } } @@ -7467,6 +7542,11 @@ tsubst_expr (t, args, complain, in_decl) finish_label_stmt (DECL_NAME (LABEL_STMT_LABEL (t))); break; + case FILE_STMT: + input_filename = FILE_STMT_FILENAME (t); + add_stmt (build_nt (FILE_STMT, FILE_STMT_FILENAME_NODE (t))); + break; + case GOTO_STMT: prep_stmt (t); tmp = GOTO_DESTINATION (t); @@ -7482,12 +7562,13 @@ tsubst_expr (t, args, complain, in_decl) case ASM_STMT: prep_stmt (t); - finish_asm_stmt (ASM_CV_QUAL (t), - tsubst_expr (ASM_STRING (t), args, complain, in_decl), - tsubst_expr (ASM_OUTPUTS (t), args, complain, in_decl), - tsubst_expr (ASM_INPUTS (t), args, complain, in_decl), - tsubst_expr (ASM_CLOBBERS (t), args, complain, - in_decl)); + tmp = finish_asm_stmt + (ASM_CV_QUAL (t), + tsubst_expr (ASM_STRING (t), args, complain, in_decl), + tsubst_expr (ASM_OUTPUTS (t), args, complain, in_decl), + tsubst_expr (ASM_INPUTS (t), args, complain, in_decl), + tsubst_expr (ASM_CLOBBERS (t), args, complain, in_decl)); + ASM_INPUT_P (tmp) = ASM_INPUT_P (t); break; case TRY_BLOCK: @@ -8477,9 +8558,7 @@ check_cv_quals_for_unify (strict, arg, parm) { /* If the cvr quals of parm will not unify with ARG, they'll be ignored in instantiation, so we have to do the same here. */ - if (TREE_CODE (arg) == REFERENCE_TYPE - || TREE_CODE (arg) == FUNCTION_TYPE - || TREE_CODE (arg) == METHOD_TYPE) + if (TREE_CODE (arg) == REFERENCE_TYPE) parm_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE); if (!POINTER_TYPE_P (arg) && TREE_CODE (arg) != TEMPLATE_TYPE_PARM) @@ -8704,21 +8783,17 @@ unify (tparms, targs, parm, arg, strict) return 0; else if (targ) return 1; - } - /* Make sure that ARG is not a variable-sized array. (Note that - were talking about variable-sized arrays (like `int[n]'), - rather than arrays of unknown size (like `int[]').) We'll - get very confused by such a type since the bound of the array - will not be computable in an instantiation. Besides, such - types are not allowed in ISO C++, so we can do as we please - here. */ - if (TREE_CODE (arg) == ARRAY_TYPE - && !uses_template_parms (arg) - && TYPE_DOMAIN (arg) - && (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (arg))) - != INTEGER_CST)) - return 1; + /* Make sure that ARG is not a variable-sized array. (Note + that were talking about variable-sized arrays (like + `int[n]'), rather than arrays of unknown size (like + `int[]').) We'll get very confused by such a type since + the bound of the array will not be computable in an + instantiation. Besides, such types are not allowed in + ISO C++, so we can do as we please here. */ + if (variably_modified_type_p (arg)) + return 1; + } TREE_VEC_ELT (targs, idx) = arg; return 0; @@ -9481,12 +9556,16 @@ do_decl_instantiation (declspecs, declarator, storage) if (DECL_TEMPLATE_SPECIALIZATION (result)) { - /* [temp.spec] + /* DR 259 [temp.spec]. - No program shall both explicitly instantiate and explicitly - specialize a template. */ - pedwarn ("explicit instantiation of `%#D' after", result); - cp_pedwarn_at ("explicit specialization here", result); + Both an explicit instantiation and a declaration of an explicit + specialization shall not appear in a program unless the explicit + instantiation follows a declaration of the explicit specialization. + + For a given set of template parameters, if an explicit + instantiation of a template appears after a declaration of an + explicit specialization for that template, the explicit + instantiation has no effect. */ return; } else if (DECL_EXPLICIT_INSTANTIATION (result)) @@ -9616,15 +9695,16 @@ do_type_instantiation (t, storage, complain) if (CLASSTYPE_TEMPLATE_SPECIALIZATION (t)) { - /* [temp.spec] + /* DR 259 [temp.spec]. - No program shall both explicitly instantiate and explicitly - specialize a template. */ - if (complain & tf_error) - { - error ("explicit instantiation of `%#T' after", t); - cp_error_at ("explicit specialization here", t); - } + Both an explicit instantiation and a declaration of an explicit + specialization shall not appear in a program unless the explicit + instantiation follows a declaration of the explicit specialization. + + For a given set of template parameters, if an explicit + instantiation of a template appears after a declaration of an + explicit specialization for that template, the explicit + instantiation has no effect. */ return; } else if (CLASSTYPE_EXPLICIT_INSTANTIATION (t)) @@ -10202,8 +10282,10 @@ tsubst_initializer_list (t, argvec) else init = convert_from_reference (init); - *p = build_tree_list (decl, init); - p = &TREE_CHAIN (*p); + *p = expand_member_init (current_class_ref, decl, + init ? init : void_type_node); + if (*p) + p = &TREE_CHAIN (*p); } return first; } |