diff options
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r-- | gcc/cp/pt.c | 212 |
1 files changed, 185 insertions, 27 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3196d123ce3..d08a792e2e0 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -814,7 +814,13 @@ maybe_process_partial_specialization (tree type) context = TYPE_CONTEXT (type); - if (CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type)) + if ((CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type)) + /* Consider non-class instantiations of alias templates as + well. */ + || (TYPE_P (type) + && TYPE_TEMPLATE_INFO (type) + && DECL_LANG_SPECIFIC (TYPE_NAME (type)) + && DECL_USE_TEMPLATE (TYPE_NAME (type)))) { /* This is for ordinary explicit specialization and partial specialization of a template class such as: @@ -827,7 +833,8 @@ maybe_process_partial_specialization (tree type) Make sure that `C<int>' and `C<T*>' are implicit instantiations. */ - if (CLASSTYPE_IMPLICIT_INSTANTIATION (type) + if (CLASS_TYPE_P (type) + && CLASSTYPE_IMPLICIT_INSTANTIATION (type) && !COMPLETE_TYPE_P (type)) { check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type)); @@ -839,8 +846,16 @@ maybe_process_partial_specialization (tree type) return error_mark_node; } } - else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type)) + else if (CLASS_TYPE_P (type) + && CLASSTYPE_TEMPLATE_INSTANTIATION (type)) error ("specialization of %qT after instantiation", type); + + if (DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (type))) + { + error ("partial specialization of alias template %qD", + TYPE_TI_TEMPLATE (type)); + return error_mark_node; + } } else if (CLASS_TYPE_P (type) && !CLASSTYPE_USE_TEMPLATE (type) @@ -2842,8 +2857,8 @@ make_ith_pack_parameter_name (tree name, int i) return get_identifier (newname); } -/* Return true if T is a primary function - or class template instantiation. */ +/* Return true if T is a primary function, class or alias template + instantiation. */ bool primary_template_instantiation_p (const_tree t) @@ -2858,6 +2873,11 @@ primary_template_instantiation_p (const_tree t) else if (CLASS_TYPE_P (t)) return CLASSTYPE_TEMPLATE_INSTANTIATION (t) && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)); + else if (TYPE_P (t) + && TYPE_TEMPLATE_INFO (t) + && PRIMARY_TEMPLATE_P (TYPE_TI_TEMPLATE (t)) + && DECL_TEMPLATE_INSTANTIATION (TYPE_NAME (t))) + return true; return false; } @@ -4831,6 +4851,10 @@ push_template_decl_real (tree decl, bool is_friend) else if (DECL_IMPLICIT_TYPEDEF_P (decl) && CLASS_TYPE_P (TREE_TYPE (decl))) /* OK */; + else if (TREE_CODE (decl) == TYPE_DECL + && TYPE_DECL_ALIAS_P (decl)) + /* alias-declaration */ + gcc_assert (!DECL_ARTIFICIAL (decl)); else { error ("template declaration of %q#D", decl); @@ -5095,8 +5119,13 @@ template arguments to %qD do not match original template %qD", if (DECL_IMPLICIT_TYPEDEF_P (decl)) SET_TYPE_TEMPLATE_INFO (TREE_TYPE (tmpl), info); - else if (DECL_LANG_SPECIFIC (decl)) - DECL_TEMPLATE_INFO (decl) = info; + else + { + if (primary && !DECL_LANG_SPECIFIC (decl)) + retrofit_lang_decl (decl); + if (DECL_LANG_SPECIFIC (decl)) + DECL_TEMPLATE_INFO (decl) = info; + } return DECL_TEMPLATE_RESULT (tmpl); } @@ -5259,6 +5288,32 @@ fold_non_dependent_expr (tree expr) return fold_non_dependent_expr_sfinae (expr, tf_error); } +/* Return TRUE iff T is a type alias, a TEMPLATE_DECL for an alias + template declaration, or a TYPE_DECL for an alias declaration. */ + +bool +alias_type_or_template_p (tree t) +{ + if (t == NULL_TREE) + return false; + return ((TREE_CODE (t) == TYPE_DECL && TYPE_DECL_ALIAS_P (t)) + || (TYPE_P (t) + && TYPE_NAME (t) + && TYPE_DECL_ALIAS_P (TYPE_NAME (t))) + || DECL_ALIAS_TEMPLATE_P (t)); +} + +/* Return TRUE iff is a specialization of an alias template. */ + +bool +alias_template_specialization_p (tree t) +{ + if (t == NULL_TREE) + return false; + return (primary_template_instantiation_p (t) + && DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (t))); +} + /* Subroutine of convert_nontype_argument. Converts EXPR to TYPE, which must be a function or a pointer-to-function type, as specified in [temp.arg.nontype]: disambiguate EXPR if it is an overload set, @@ -7355,7 +7410,31 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, ENUM_FIXED_UNDERLYING_TYPE_P (t) = ENUM_FIXED_UNDERLYING_TYPE_P (template_type); } - else + else if (DECL_ALIAS_TEMPLATE_P (gen_tmpl)) + { + /* The user referred to a specialization of an alias + template represented by GEN_TMPL. + + [temp.alias]/2 says: + + When a template-id refers to the specialization of an + alias template, it is equivalent to the associated + type obtained by substitution of its + template-arguments for the template-parameters in the + type-id of the alias template. */ + + t = tsubst (TREE_TYPE (gen_tmpl), arglist, complain, in_decl); + /* Note that the call above (by indirectly calling + register_specialization in tsubst_decl) registers the + TYPE_DECL representing the specialization of the alias + template. So next time someone substitutes ARGLIST for + the template parms into the alias template (GEN_TMPL), + she'll get that TYPE_DECL back. */ + + if (t == error_mark_node) + return t; + } + else if (CLASS_TYPE_P (template_type)) { t = make_class_type (TREE_CODE (template_type)); CLASSTYPE_DECLARED_CLASS (t) @@ -7378,6 +7457,8 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, structural equality testing. */ SET_TYPE_STRUCTURAL_EQUALITY (t); } + else + gcc_unreachable (); /* If we called start_enum or pushtag above, this information will already be set up. */ @@ -7393,14 +7474,17 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, else type_decl = TYPE_NAME (t); - TREE_PRIVATE (type_decl) - = TREE_PRIVATE (TYPE_STUB_DECL (template_type)); - TREE_PROTECTED (type_decl) - = TREE_PROTECTED (TYPE_STUB_DECL (template_type)); - if (CLASSTYPE_VISIBILITY_SPECIFIED (template_type)) + if (CLASS_TYPE_P (template_type)) { - DECL_VISIBILITY_SPECIFIED (type_decl) = 1; - DECL_VISIBILITY (type_decl) = CLASSTYPE_VISIBILITY (template_type); + TREE_PRIVATE (type_decl) + = TREE_PRIVATE (TYPE_STUB_DECL (template_type)); + TREE_PROTECTED (type_decl) + = TREE_PROTECTED (TYPE_STUB_DECL (template_type)); + if (CLASSTYPE_VISIBILITY_SPECIFIED (template_type)) + { + DECL_VISIBILITY_SPECIFIED (type_decl) = 1; + DECL_VISIBILITY (type_decl) = CLASSTYPE_VISIBILITY (template_type); + } } /* Let's consider the explicit specialization of a member @@ -7456,7 +7540,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, ++processing_template_decl; partial_inst_args = tsubst (INNERMOST_TEMPLATE_ARGS - (CLASSTYPE_TI_ARGS (TREE_TYPE (gen_tmpl))), + (TYPE_TI_ARGS (TREE_TYPE (gen_tmpl))), arglist, complain, NULL_TREE); --processing_template_decl; TREE_VEC_LENGTH (arglist)++; @@ -7480,7 +7564,15 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, TREE_VEC_LENGTH (arglist)--; found = tsubst (gen_tmpl, arglist, complain, NULL_TREE); TREE_VEC_LENGTH (arglist)++; - found = CLASSTYPE_TI_TEMPLATE (found); + /* FOUND is either a proper class type, or an alias + template specialization. In the later case, it's a + TYPE_DECL, resulting from the substituting of arguments + for parameters in the TYPE_DECL of the alias template + done earlier. So be careful while getting the template + of FOUND. */ + found = TREE_CODE (found) == TYPE_DECL + ? TYPE_TI_TEMPLATE (TREE_TYPE (found)) + : CLASSTYPE_TI_TEMPLATE (found); } SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist)); @@ -7508,7 +7600,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context, the instantiation and exit above. */ tsubst_enum (template_type, t, arglist); - if (is_dependent_type) + if (CLASS_TYPE_P (template_type) && is_dependent_type) /* If the type makes use of template parameters, the code that generates debugging information will crash. */ DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1; @@ -8600,6 +8692,8 @@ instantiate_class_template_1 (tree type) { CLASSTYPE_VISIBILITY_SPECIFIED (type) = 1; CLASSTYPE_VISIBILITY (type) = CLASSTYPE_VISIBILITY (pattern); + /* Adjust visibility for template arguments. */ + determine_visibility (TYPE_MAIN_DECL (type)); } CLASSTYPE_FINAL (type) = CLASSTYPE_FINAL (pattern); @@ -9843,7 +9937,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) DECL_TEMPLATE_INFO (r) = build_template_info (t, args); - if (TREE_CODE (decl) == TYPE_DECL) + if (TREE_CODE (decl) == TYPE_DECL + && !TYPE_DECL_ALIAS_P (decl)) { tree new_type; ++processing_template_decl; @@ -10376,8 +10471,15 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) referencing a static data member within in its own class. We can use pointer equality, rather than same_type_p, because DECL_CONTEXT is always - canonical. */ - if (ctx == DECL_CONTEXT (t)) + canonical... */ + if (ctx == DECL_CONTEXT (t) + && (TREE_CODE (t) != TYPE_DECL + /* ... unless T is a member template; in which + case our caller can be willing to create a + specialization of that template represented + by T. */ + || !(DECL_TI_TEMPLATE (t) + && DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (t))))) spec = t; } @@ -10858,7 +10960,7 @@ tree tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) { enum tree_code code; - tree type, r; + tree type, r = NULL_TREE; if (t == NULL_TREE || t == error_mark_node || t == integer_type_node @@ -10890,10 +10992,21 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) && typedef_variant_p (t)) { tree decl = TYPE_NAME (t); - - if (DECL_CLASS_SCOPE_P (decl) - && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl)) - && uses_template_parms (DECL_CONTEXT (decl))) + + if (TYPE_DECL_ALIAS_P (decl) + && DECL_LANG_SPECIFIC (decl) + && DECL_TEMPLATE_INFO (decl) + && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))) + { + /* DECL represents an alias template and we want to + instantiate it. Let's substitute our arguments for the + template parameters into the declaration and get the + resulting type. */ + r = tsubst (decl, args, complain, decl); + } + else if (DECL_CLASS_SCOPE_P (decl) + && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl)) + && uses_template_parms (DECL_CONTEXT (decl))) { tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl)); tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl); @@ -11043,6 +11156,46 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) if (argvec == error_mark_node) return error_mark_node; + gcc_assert (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM + || TREE_CODE (arg) == TEMPLATE_DECL + || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE); + + if (TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE) + /* Consider this code: + + template <template <class> class Template> + struct Internal { + template <class Arg> using Bind = Template<Arg>; + }; + + template <template <class> class Template, class Arg> + using Instantiate = Template<Arg>; //#0 + + template <template <class> class Template, + class Argument> + using Bind = + Instantiate<Internal<Template>::template Bind, + Argument>; //#1 + + When #1 is parsed, the + BOUND_TEMPLATE_TEMPLATE_PARM representing the + parameter `Template' in #0 matches the + UNBOUND_CLASS_TEMPLATE representing the argument + `Internal<Template>::template Bind'; We then want + to assemble the type `Bind<Argument>' that can't + be fully created right now, because + `Internal<Template>' not being complete, the Bind + template cannot be looked up in that context. So + we need to "store" `Bind<Argument>' for later + when the context of Bind becomes complete. Let's + store that in a TYPENAME_TYPE. */ + return make_typename_type (TYPE_CONTEXT (arg), + build_nt (TEMPLATE_ID_EXPR, + TYPE_IDENTIFIER (arg), + argvec), + typename_type, + complain); + /* 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 @@ -17630,7 +17783,12 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain) if (! CLASS_TYPE_P (t) || ! CLASSTYPE_TEMPLATE_INFO (t)) { - error ("explicit instantiation of non-template type %qT", t); + tree tmpl = + (TYPE_TEMPLATE_INFO (t)) ? TYPE_TI_TEMPLATE (t) : NULL; + if (tmpl) + error ("explicit instantiation of non-class template %qD", tmpl); + else + error ("explicit instantiation of non-template type %qT", t); return; } |