5.12.4.2.2.2.3. 完成 template-id
如果模板名是一个 IDENTIFER_NODE ,它可能是一个成员模板;而如果它是应该类模板的 TEMPLATE_DECL , template-id 本身是一个类名;而如果是 FUNCTION_DECL , OVERLOAD 或 METHOD_DECL , template-id 就是一个函数名。
因此如果模板名是一个类模板, template-id 可能代表一个新的类,对此我们需要通过 finish_template_type 来构建相应的类型。它是应该非常复杂的过程,在后面的章节中将给出一个例子来浏览这一过程。
cp_parser_template_id (continue)
7991 /* Build a representation of the specialization. */
7992 if (TREE_CODE (template) == IDENTIFIER_NODE)
7993 template_id = build_min_nt (TEMPLATE_ID_EXPR, template, arguments);
7994 else if (DECL_CLASS_TEMPLATE_P (template)
7995 || DECL_TEMPLATE_TEMPLATE_PARM_P (template))
7996 template_id
7997 = finish_template_type (template, arguments,
7998 cp_lexer_next_token_is (parser->lexer,
7999 CPP_SCOPE));
8000 else
8001 {
8002 /* If it's not a class-template or a template-template, it should be
8003 a function-template. */
8004 my_friendly_assert ((DECL_FUNCTION_TEMPLATE_P (template)
8005 || TREE_CODE (template) == OVERLOAD
8006 || BASELINK_P (template)),
8007 20010716);
8008
8009 template_id = lookup_template_function (template, arguments);
8010 }
8011
8012 /* Retrieve any deferred checks. Do not pop this access checks yet
8013 so the memory will not be reclaimed during token replacing below. */
8014 access_check = get_deferred_access_checks ();
如果模板名是一个 IDNETIFIER_NODE ,所形成的 TEMPLATE_ID_EXPR 由 build_min_nt 来构建。该函数构建的是一个 tree_exp 节点。
4069 tree
4070 build_min_nt (enum tree_code code, ...) in tree.c
4071 {
4072 tree t;
4073 int length;
4074 int i;
4075 va_list p;
4076
4077 va_start (p, code);
4078
4079 t = make_node (code);
4080 length = TREE_CODE_LENGTH (code);
4081 TREE_COMPLEXITY (t) = input_line;
4082
4083 for (i = 0; i < length; i++)
4084 {
4085 tree x = va_arg (p, tree);
4086 TREE_OPERAND (t, i) = x;
4087 }
4088
4089 va_end (p);
4090 return t;
4091 }
如果模板名是一个函数模板,所对应的 TEMPLATE_ID_EXPR 节点则是由 lookup_template_function 来构建。一个 BASEL INK 节点表示从基类对成员函数或成员函数集(因为重载)的引用。注意在这个情形下,在所产生的 TEMPLATE_ID_EXPR 节点中,其类型是 unknonw_type_node ,这将强制前端在后面调用 instantiate_type 来解析其类型。
4069 tree
4070 lookup_template_function (tree fns, tree arglist) in pt.c
4071 {
4072 tree type;
4073
4074 if (fns == error_mark_node || arglist == error_mark_node)
4075 return error_mark_node;
4076
4077 my_friendly_assert (!arglist || TREE_CODE (arglist) == TREE_VEC, 20030726);
4078 my_friendly_assert (fns && (is_overloaded_fn (fns)
4079 || TREE_CODE (fns) == IDENTIFIER_NODE),
4080 20050608);
4081
4082 if (BASELINK_P (fns))
4083 {
4084 BASELINK_FUNCTIONS (fns) = build (TEMPLATE_ID_EXPR,
4085 unknown_type_node,
4086 BASELINK_FUNCTIONS (fns),
4087 arglist);
4088 return fns;
4089 }
4090
4091 type = TREE_TYPE (fns);
4092 if (TREE_CODE (fns) == OVERLOAD || !type)
4093 type = unknown_type_node;
4094
4095 return build (TEMPLATE_ID_EXPR, type, fns, arglist);
4096 }
然后对应的符号被捆绑成 CPP_TEMPLATE_ID ;类似的符号组还有 NESTED_NAME_SPECFIER 。
cp_parser_template_id (continue)
8016 /* If parsing tentatively, replace the sequence of tokens that makes
8017 up the template-id with a CPP_TEMPLATE_ID token. That way,
8018 should we re-parse the token stream, we will not have to repeat
8019 the effort required to do the parse, nor will we issue duplicate
8020 error messages about problems during instantiation of the
8021 template. */
8022 if (start_of_id >= 0)
8023 {
8024 cp_token *token;
8025
8026 /* Find the token that corresponds to the start of the
8027 template-id. */
8028 token = cp_lexer_advance_token (parser->lexer,
8029 parser->lexer->first_token,
8030 start_of_id);
8031
8032 /* Reset the contents of the START_OF_ID token. */
8033 token->type = CPP_TEMPLATE_ID;
8034 token->value = build_tree_list (access_check, template_id);
8035 token->keyword = RID_MAX;
8036 /* Purge all subsequent tokens. */
8037 cp_lexer_purge_tokens_after (parser->lexer, token);
8038
8039 /* ??? Can we actually assume that, if template_id ==
8040 error_mark_node, we will have issued a diagnostic to the
8041 user, as opposed to simply marking the tentative parse as
8042 failed? */
8043 if (cp_parser_error_occurred (parser) && template_id != error_mark_node)
8044 error ("parse error in template argument list");
8045 }
8046
8047 pop_deferring_access_checks ();
8048 return template_id;
8049 }
当为 identifier 获得 decl 时,根据语法,它必须是一个标识符或 template-id 。如果参数 typename_p 是 true ,这表示已经看到关键字 typename 。因此调用 make_typename_type 来解析“ typename CONTEXT::NAME ”,并返回合适的类型。
cp_parser_class_name (continue)
11812 decl = cp_parser_maybe_treat_template_as_class (decl, class_head_p);
11813
11814 /* If this is a typename, create a TYPENAME_TYPE. */
11815 if (typename_p && decl != error_mark_node)
11816 {
11817 decl = make_typename_type (scope, decl, /*complain=* /1);
11818 if (decl != error_mark_node)
11819 decl = TYPE_NAME (decl);
11820 }
11821
11822 /* Check to see that it is really the name of a class. */
11823 if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
11824 && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE
11825 && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
11826 /* Situations like this:
11827
11828 template <typename T> struct A {
11829 typename T::template X<int>::I i;
11830 };
11831
11832 are problematic. Is `T::template X<int>' a class-name? The
11833 standard does not seem to be definitive, but there is no other
11834 valid interpretation of the following `::'. Therefore, those
11835 names are considered class-names. */
11836 decl = TYPE_NAME (make_typename_type (scope, decl, tf_error));
11837 else if (decl == error_mark_node
11838 || TREE_CODE (decl) != TYPE_DECL
11839 || !IS_AGGR_TYPE (TREE_TYPE (decl)))
11840 {
11841 cp_parser_error (parser, "expected class-name");
11842 return error_mark_node;
11843 }
11844
11845 return decl;
11846 }
参考在 cp_parser_template_id 中调用的 maybe_get_template_decl_from_type_decl 来帮助更好地理解 cp_parser_maybe_treat_template_as_class 。参数 tag_name_p 为 true 时, decl 表示的类正在 class-head 中定义,或声明在一个 elaborated-type-specifier 中。
13901 static tree
13902 cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p) in parser.c
13903 {
13904 /* If the TEMPLATE_DECL is being declared as part of a class-head,
13905 the translation from TEMPLATE_DECL to TYPE_DECL occurs:
13906
13907 struct A {
13908 template <typename T> struct B;
13909 };
13910
13911 template <typename T> struct A::B {};
13912
13913 Similarly, in a elaborated-type-specifier:
13914
13915 namespace N { struct X{}; }
13916
13917 struct A {
13918 template <typename T> friend struct N::X;
13919 };
13920
13921 However, if the DECL refers to a class type, and we are in
13922 the scope of the class, then the name lookup automatically
13923 finds the TYPE_DECL created by build_self_reference rather
13924 than a TEMPLATE_DECL. For example, in:
13925
13926 template <class T> struct S {
13927 S s;
13928 };
13929
13930 there is no need to handle such case. */
13931
13932 if (DECL_CLASS_TEMPLATE_P (decl) && tag_name_p)
13933 return DECL_TEMPLATE_RESULT (decl);
13934
13935 return decl;
13936 }
函数的作用是,如果 decl 是一个可以在当前上下文中按 TYPE_DECL 处理的 TEMPLATE_DECL ,返回其对应的 TYPE_DECL 。
下面如果 name 是一个类模板(由 CLASSTYPE_IS_TEMPLATE )或者一个模板的具现或特化( 由 CLASSTYPE_USE_TEMPLATE ),一个 TMEPLATE_ID_EXPR 被构建。其处理涉及函数 lookup_template_class ,我们在后面再结合例子来看这个复杂的函数。
2608 tree
2609 make_typename_type (tree context, tree name, tsubst_flags_t complain) in decl.c
2610 {
2611 tree fullname;
2612
2613 if (name == error_mark_node
2614 || context == NULL_TREE
2615 || context == error_mark_node)
2616 return error_mark_node;
2617
2618 if (TYPE_P (name))
2619 {
2620 if (!(TYPE_LANG_SPECIFIC (name)
2621 && (CLASSTYPE_IS_TEMPLATE (name)
2622 || CLASSTYPE_USE_TEMPLATE (name))))
2623 name = TYPE_IDENTIFIER (name);
2624 else
2625 /* Create a TEMPLATE_ID_EXPR for the type. */
2626 name = build_nt (TEMPLATE_ID_EXPR,
2627 CLASSTYPE_TI_TEMPLATE (name),
2628 CLASSTYPE_TI_ARGS (name));
2629 }
2630 else if (TREE_CODE (name) == TYPE_DECL)
2631 name = DECL_NAME (name);
2632
2633 fullname = name;
2634
2635 if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
2636 {
2637 name = TREE_OPERAND (name, 0);
2638 if (TREE_CODE (name) == TEMPLATE_DECL)
2639 name = TREE_OPERAND (fullname, 0) = DECL_NAME (name);
2640 }
2641 if (TREE_CODE (name) == TEMPLATE_DECL)
2642 {
2643 error ("`%D' used without template parameters", name);
2644 return error_mark_node;
2645 }
2646 my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 20030802);
2647 my_friendly_assert (TYPE_P (context), 20050905);
2648
2649 if (!dependent_type_p (context)
2650 || currently_open_class (context))
2651 {
2652 if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
2653 {
2654 tree tmpl = NULL_TREE;
2655 if (IS_AGGR_TYPE (context))
2656 tmpl = lookup_field (context, name, 0, false);
2657 if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
2658 {
2659 if (complain & tf_error)
2660 error ("no class template named `%#T' in `%#T'",
2661 name, context);
2662 return error_mark_node;
2663 }
2664
2665 if (complain & tf_error)
2666 perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
2667
2668 return lookup_template_class (tmpl,
2669 TREE_OPERAND (fullname, 1),
2670 NULL_TREE, context,
2671 /*entering_scope=*/ 0,
2672 tf_error | tf_warning | tf_user);
2673 }
2674 else
2675 {
2676 tree t;
2677
2678 if (!IS_AGGR_TYPE (context))
2679 {
2680 if (complain & tf_error)
2681 error ("no type named `%#T' in `%#T'", name, context);
2682 return error_mark_node;
2683 }
2684
2685 t = lookup_field (context, name, 0, true);
2686 if (t)
2687 {
2688 if (TREE_CODE (t) != TYPE_DECL)
2689 {
2690 if (complain & tf_error)
2691 error ("no type named `%#T' in `%#T'", name, context);
2692 return error_mark_node;
2693 }
2694
2695 if (complain & tf_error)
2696 perform_or_defer_access_check (TYPE_BINFO (context), t);
2697
2698 if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
2699 t = TREE_TYPE (t);
2700
2701 return t;
2702 }
2703 }
2704 }
2705
2706 /* If the CONTEXT is not a template type, then either the field is
2707 there now or its never going to be. */
2708 if (!dependent_type_p (context))
2709 {
2710 if (complain & tf_error)
2711 error ("no type named `%#T' in `%#T'", name, context);
2712 return error_mark_node;
2713 }
2714
2715 return build_typename_type (context, name, fullname);
2716 }
而对于表达式“ typename CONTEXT::NAME ”,如果 CONTEXT 不具有依赖性,或者它是当前打开的类, NAME 首先通过 lookup_field 在该类中查找。
1372 tree
1373 lookup_field (tree xbasetype, tree name, int protect, bool want_type) in search.c
1374 {
1375 tree rval = lookup_member (xbasetype, name, protect, want_type);
1376
1377 /* Ignore functions. */
1378 if (rval && BASELINK_P (rval))
1379 return NULL_TREE;
1380
1381 return rval;
1382 }
看到参数 want_type 在 2656 行的调用中,对于 template-id 是 false ;而在 2685 行的调用中对普通类型是 true 。而 want_type 是 true ,表示我们只接受 TYPE_DECL 。
如果找不到该名字,而且该上下文具有依赖性,就必须为这个类型构建一个占位符。这就是 TYPENAME_TYPE 节点。
2566 static tree
2567 build_typename_type (tree context, tree name, tree fullname) in decl.c
2568 {
2569 tree t;
2570 tree d;
2571 void **e;
2572
2573 if (typename_htab == NULL)
2574 {
2575 typename_htab = htab_create_ggc (61, &typename_hash,
2576 &typename_compare, NULL);
2577 }
2578
2579 /* Build the TYPENAME_TYPE. */
2580 t = make_aggr_type (TYPENAME_TYPE);
2581 TYPE_CONTEXT (t) = FROB_CONTEXT (context);
2582 TYPENAME_TYPE_FULLNAME (t) = fullname;
2583
2584 /* Build the corresponding TYPE_DECL. */
2585 d = build_decl (TYPE_DECL, name, t);
2586 TYPE_NAME (TREE_TYPE (d)) = d;
2587 TYPE_STUB_DECL (TREE_TYPE (d)) = d;
2588 DECL_CONTEXT (d) = FROB_CONTEXT (context);
2589 DECL_ARTIFICIAL (d) = 1;
2590
2591 /* See if we already have this type. */
2592 e = htab_find_slot (typename_htab , t, INSERT);
2593 if (*e)
2594 t = (tree) *e;
2595 else
2596 *e = t;
2597
2598 return t;
2599 }
TYPENAME_TYPE 节点表示 “ typename T::t ”这样的结构。在这个节点中,其 TYPE_CONTEXT 是‘ T ’, TYPE_NAME 是代表‘ t ’的一个 IDENTIFIER_NODE 。如果该类型来自 template-id , TYPENAME_TYPE_FULLNAME 将保存这个 TEMPLATE_ID_EXPR 。
注意这里对“ typename T::t ”的处理,‘ T ’在前一步中已经被解析,它可能是一个模板或模板参数,其子树已经构建。因此事实上,在不同的上下文‘ T ’中,“ typename T::t ”代表不同的结构。为了确保在编译单元中,代表这些结构的节点的唯一性,这些节点都被保存在哈希表 typename_htab 中。