The token follows the template-parameter-list is “class” which denotes the definition/ declaration of a class-template. Same as the previous example, along with the following call stack: cp_parser_template_declaration_after_export à cp_parser_single_declaration à cp_parser_decl_specifier_seq à cp_parser_type_specifier , keyword “class” leads the parser to the routine cp_parser_class_specifier .
11855 static tree
11856 cp_parser_class_specifier (cp_parser* parser) in parser.c
11857 {
11858 cp_token *token;
11859 tree type;
11860 tree attributes;
11861 int has_trailing_semicolon;
11862 bool nested_name_specifier_p;
11863 unsigned saved_num_template_parameter_lists;
11864 bool pop_p = false;
11865 tree scope = NULL_TREE;
11866
11867 push_deferring_access_checks (dk_no_deferred);
11868
11869 /* Parse the class-head. */
11870 type = cp_parser_class_head (parser,
11871 &nested_name_specifier_p,
11872 &attributes);
During parsing class-specifier, access checking should be done without deferred in general as indicated by the new inserted node of dk_no_deferred at line 11867. However, we can see later that different access checkings may be applied locally.
12030 static tree
12031 cp_parser_class_head (cp_parser* parser, in parser.c
12032 bool* nested_name_specifier_p,
12033 tree *attributes_p)
12034 {
12035 cp_token *token;
12036 tree nested_name_specifier;
12037 enum tag_types class_key;
12038 tree id = NULL_TREE;
12039 tree type = NULL_TREE;
12040 tree attributes;
12041 bool template_id_p = false;
12042 bool qualified_p = false;
12043 bool invalid_nested_name_p = false;
12044 bool invalid_explicit_specialization_p = false;
12045 bool pop_p = false;
12046 unsigned num_templates;
12047
12048 /* Assume no nested-name-specifier will be present. */
12049 *nested_name_specifier_p = false;
12050 /* Assume no template parameter lists will be used in defining the
12051 type. */
12052 num_templates = 0;
12053
12054 /* Look for the class-key. */
12055 class_key = cp_parser_class_key (parser);
12056 if (class_key == none_type)
12057 return error_mark_node;
12058
12059 /* Parse the attributes. */
12060 attributes = cp_parser_attributes_opt (parser);
12061
12062 /* If the next token is `::', that is invalid -- but sometimes
12063 people do try to write:
12064
12065 struct ::S {};
12066
12067 Handle this gracefully by accepting the extra qualifier, and then
12068 issuing an error about it later if this really is a
12069 class-head. If it turns out just to be an elaborated type
12070 specifier, remain silent. */
12071 if (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/ false))
12072 qualified_p = true;
12073
12074 push_deferring_access_checks (dk_no_check);
12075
12076 /* Determine the name of the class. Begin by looking for an
12077 optional nested-name-specifier. */
12078 nested_name_specifier
12079 = cp_parser_nested_name_specifier_opt (parser,
12080 /*typename_keyword_p=*/ false,
12081 /*check_dependency_p=*/ false,
12082 /*type_p=*/ false,
12083 /*is_declaration=*/ false);
12084 /* If there was a nested-name-specifier, then there *must* be an
12085 identifier. */
12086 if (nested_name_specifier)
12087 {
…
12143 }
12144 /* Otherwise, the identifier is optional. */
12145 else
12146 {
12147 /* We don't know whether what comes next is a template-id,
12148 an identifier, or nothing at all. */
12149 cp_parser_parse_tentatively (parser);
12150 /* Check for a template-id. */
12151 id = cp_parser_template_id (parser,
12152 /*template_keyword_p=*/ false,
12153 /*check_dependency_p=*/ true,
12154 /*is_declaration=*/ true);
12155 /* If that didn't work, it could still be an identifier. */
12156 if (!cp_parser_parse_definitely (parser))
12157 {
12158 if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
12159 id = cp_parser_identifier (parser);
12160 else
12161 id = NULL_TREE;
12162 }
12163 else
12164 {
12165 template_id_p = true;
12166 ++num_templates;
12167 }
12168 }
12169
12170 pop_deferring_access_checks ();
Here, can see that at line 12074, rule of no accessing check is added in, which adjusts the accessing check rule added by cp_parser_parse_tentatively at line 12149 into dk_no_check too. Here token after the keyword “class” is “SmallObject” which is an identifier and handled at line 12159 by cp_parser_identifier .
Notice that pop_deferring_access_checks pops the node of dk_no_checks correspondingly.
cp_parser_class_head (continue)
12259 /* Look up the type. */
12260 if (template_id_p)
12261 {
12262 type = TREE_TYPE (id);
12263 maybe_process_partial_specialization (type);
12264 }
12265 else if (!nested_name_specifier)
12266 {
12267 /* If the class was unnamed, create a dummy name. */
12268 if (!id)
12269 id = make_anon_name ();
12270 type = xref_tag (class_key, id, /*globalize=*/ false,
12271 parser->num_template_parameter_lists);
12272 }
The processing of tokens “class SmallObject” as a class tag is exact the same as that described in section Push tag of class SingleThreaded . So we just skip the detail of the handling here to avoid unneccesary duplication.
The base class must be a defined type, finding out nodes for the type from the class name is a complex procedure, especially the base is a class template. Below we first have a look at class-name lookup. But before that, we the best see how to determine the dependency of specified name.
Inside a template, some constructs have semantics which may differ from one instantiation to another. Such a construct depends on the template parameters. In particular, types and expressions may depend on the type and/or value of template parameters (e.g. determined by the template arguments) and which also determines the context for name lookup for the names. Expressions may be type-dependent (on the type of a template parameter) or value-dependent (on the value of a non-type template parameter). In an expression of the form:
postfix-expression ( expression-list opt )
where the postfix-expression is an identifier, the identifier denotes a dependent name if and only if any of the expressions in the expression-list is a type-dependent expression (14.6.2.2). If an operand of an operator is a type-dependent expression, the operator also denotes a dependent name. Such names are unbound and are looked up at the point of the template instantiation (14.6.4.1) in both the context of the template definition and the context of the point of instantiation. [Example:
template <class T> struct X : B<T> {
typename T::A* pa;
void f(B<T>* pb) {
static int i = B<T>::i;
pb->j++;
}
};
the base class name B<T>, the type name T::A, the names B<T>::i and pb->j explicitly depend on the template-parameter.
In the definition of a class template or a member of a class template, if a base class of the class template depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member. [Example:
typedef double A;
template <class T> class B {
typedef int A;
};
template <class T> struct X : B<T> {
A a; // a has type double
};
The type name A in the definition of X<T> binds to the typedef name defined in the global namespace scope, not to the typedef name defined in the base class B<T>. [Example:
struct A {
struct B { /* ... */ };
int a;
int Y;
};
int a;
template <class T> struct Y : T {
struct B { /* ... */ };
B b; // The B defined in Y
void f(int i) { a = i; } // ::a
Y* p; // Y<T>
};
Y<A> ya;
The members A::B, A::a, and A::Y of the template argument A do not affect the binding of names in Y<A>.
Routine type_dependent_expression_p returns true if the expression is type-dependent.
11966 bool
11967 type_dependent_expression_p (tree expression) in pt.c
11968 {
11969 if (!processing_template_decl )
11970 return false;
11971
11972 if (expression == error_mark_node)
11973 return false;
11974
11975 /* An unresolved name is always dependent. */
11976 if (TREE_CODE (expression) == IDENTIFIER_NODE)
11977 return true;
As we know when parser find an identifier, it always try to look it up to find out the declaration currently bound with the name. This declaration is the object used in current scope. But if the identifier hasn’t visible binding in current scope, the parser only uses the IDENTIFIER_NODE. Takes above example as instance:
template <class T> struct X : B<T> {
typename T::A* pa;
In “T::A”, the “A” at here should only be IDENTIFIER_NODE.
type_dependent_expression_p (continue)
11979 /* Some expression forms are never type-dependent. */
11980 if (TREE_CODE (expression) == PSEUDO_DTOR_EXPR
11981 || TREE_CODE (expression) == SIZEOF_EXPR
11982 || TREE_CODE (expression) == ALIGNOF_EXPR
11983 || TREE_CODE (expression) == TYPEID_EXPR
11984 || TREE_CODE (expression) == DELETE_EXPR
11985 || TREE_CODE (expression) == VEC_DELETE_EXPR
11986 || TREE_CODE (expression) == THROW_EXPR)
11987 return false;
11988
11989 /* The types of these expressions depends only on the type to which
11990 the cast occurs. */
11991 if (TREE_CODE (expression) == DYNAMIC_CAST_EXPR
11992 || TREE_CODE (expression) == STATIC_CAST_EXPR
11993 || TREE_CODE (expression) == CONST_CAST_EXPR
11994 || TREE_CODE (expression) == REINTERPRET_CAST_EXPR
11995 || TREE_CODE (expression) == CAST_EXPR)
11996 return dependent_type_p (TREE_TYPE (expression));
11997
11998 /* The types of these expressions depends only on the type created
11999 by the expression. */
12000 if (TREE_CODE (expression) == NEW_EXPR
12001 || TREE_CODE (expression) == VEC_NEW_EXPR)
12002 {
12003 /* For NEW_EXPR tree nodes created inside a template, either
12004 the object type itself or a TREE_LIST may appear as the
12005 operand 1. */
12006 tree type = TREE_OPERAND (expression, 1);
12007 if (TREE_CODE (type) == TREE_LIST)
12008 /* This is an array type. We need to check array dimensions
12009 as well. */
12010 return dependent_type_p (TREE_VALUE (TREE_PURPOSE (type)))
12011 || value_dependent_expression_p
12012 (TREE_OPERAND (TREE_VALUE (type), 1));
12013 else
12014 return dependent_type_p (type);
12015 }
12016
12017 if (TREE_CODE (expression) == SCOPE_REF
12018 && dependent_scope_ref_p (expression,
12019 type_dependent_expression_p))
12020 return true;
12021
12022 if (TREE_CODE (expression) == FUNCTION_DECL
12023 && DECL_LANG_SPECIFIC (expression)
12024 && DECL_TEMPLATE_INFO (expression)
12025 && (any_dependent_template_arguments_p
12026 (INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)))))
12027 return true;
12028
12029 if (TREE_CODE (expression) == TEMPLATE_DECL
12030 && !DECL_TEMPLATE_TEMPLATE_PARM_P (expression))
12031 return false;
Accoding to [3], following forms are never type-dependent.
literal
postfix-expression.pseduo-destructor-name
postfix-expression->pseduo-destructor-name
sizeof unary-expression
sizeof (type-id)
typeid (expression)
typeid (type-id)
::opt delete cast-expression
::opt delete[] cast-expression
throw assignment-expression opt
As types of those expressions are not dependent. For example, sizeof always of type size_t. The GNU extension operator alignof is also within the group (it is of type size_t too).
Then an id-expression is type-dependent if it contains:
an identifier that was declared with a dependent type
a template-id that is dependent
a conversion-function-id that specifies a dependent type
a nested-name-specifier that contains a class-name that names a dependent type
Expression of the following forms are type-dependent only if the type specified by the type-id , simple-type-specifier or new-type-id is dependent, even if any subexpression is type-dependent:
simple-type-specifier (expression-list opt )
::opt new new-placement opt new-type-id new-initializer opt
::opt new new-placement opt (type-id ) new-initializer opt
dynamic_cast <type-id > (expression)
static_cast <type-id > (expression)
const_cast <type-id > (expression)
reinterpret_cast <type-id > (expression)
(type-id ) cast-expression
The core of above rules is to check type-dependence of types contained by the expression. Above at line 12000, note that for new-type-id , the grammar for it is:
new-type-id
type-specifier-seq new-declarator opt
new-declarator:
ptr-operator new-declarator opt
direct-new-declarator
direct-new-declarator:
[expression]
direct-new-declarator [constant-expression]
For this case, the operand at position 1 (starts from 0) of tree node of NEW_EXPR/ VEC_NEW_EXPR is the new-type-id which is a tree_list , with type-specifier-seq at the purpose slot and new-declarator at the value slot. If new-declarator deriving direct-new-declarator , it is the node of ARRAY_REF, with direct-new-declarator of sub-dimension as operand 0, and expression for the size of dimension as operand 1. Obvious if this expression is value-dependent, new-type-id is type-dependent too.
Then dependent_type_p validates whether type passed in is template parameter dependent.
11786 bool
11787 dependent_type_p (tree type) in pt.c
11788 {
11789 /* If there are no template parameters in scope, then there can't be
11790 any dependent types. */
11791 if (!processing_template_decl )
11792 return false;
11793
11794 /* If the type is NULL, we have not computed a type for the entity
11795 in question; in that case, the type is dependent. */
11796 if (!type)
11797 return true;
11798
11799 /* Erroneous types can be considered non-dependent. */
11800 if (type == error_mark_node)
11801 return false;
11802
11803 /* If we have not already computed the appropriate value for TYPE,
11804 do so now. */
11805 if (!TYPE_DEPENDENT_P_VALID (type))
11806 {
11807 TYPE_DEPENDENT_P (type) = dependent_type_p_r (type);
11808 TYPE_DEPENDENT_P_VALID (type) = 1;
11809 }
11810
11811 return TYPE_DEPENDENT_P (type);
11812 }
To accelerate compiling speed, some type if has been evaluated, slot lang_flag_6 of the tree type node is set (TYPE_DEPENDENT_P_VALID) and the result is set in lang_flag_0 slot (TYPE_DEPENDENT_P).
A type is dependent if it is:
1) A template parameter.
2) A qualified-id with a nested-name-specifier which contains a class-name that names a dependent type or whose unqualified-id names a dependent type.
3) A cv-qualified type where the cv-unqualified type is dependent.
4) A compound type constructed from any dependent type.
5) An array type constructed from any dependent type or whose size is specified by a constant expression that is value-dependent.
6) A template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent.
Below, TEMPLATE_TYPE_PARM is the node for template parameter, and that parameter being template itself is the node of TEMPLATE_TEMPLATE_PARM.
Then according to ISO-IE-14882-2003, 14.6 name resolution:
A name used in a template declaration or definition and that is dependent on a template parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.
For example:
// no B declared here
class X;
template <class T> class Y {
class Z; // forward declaration of member class
void f() {
X* a1; // declare pointer to X
T* a2; // declare pointer to T
Y* a3; // declare pointer to Y
Z* a4; // declare pointer to Z
typedef typename T::A TA;
TA* a5; // declare pointer to T’s A
typename T::A* a6; // declare pointer to T’s A
T::A* a7; // T::A is not a type name: mulitply T::A by a7;
// ill-formed, no visible declaration of a7
B* a8; // multiply B by a8; ill-formed, no visible declaration of B and a8
}
};
A qualified-name that refers to a type and that depends on a template-parameter shall be prefixed by the keyword typename to indicate that the qualified-name denotes a type, forming an elaborated-type specifier.
elaborated-type-specifier:
typename ::opt nested-name-specifier identifier
typename ::opt nested-name-specifier identifer <template-argument-list>
The keyword typename shall only be used in template declarations and definitions, including in the return type of a function template or member function template, in the return type for the definition of a member function of a class template or of a class nested within a class template, and in the type-specifier for the definition of a static member of a class template or of a class nested within a class template. The keyword typename shall only be applied to qualified names, but those names need not be dependent. The keyword typename is not premitted in a base-specifier or in a mem-initializer; in these contexts a qualified-name that depends on a template-parameter is implicitly assumed to be a type name.
Within the definition of a class template or within the definition of a member of a class template, the keyword typename is not required when referring to the unqualified name of a previously declared member of the class template that declares the type. The keyword typename shall always be specified when the member is referred to using a qualified name, even if the qualifier is simply the class template name.
For example:
template <class T> struct A {
typedef int B;
A::B b; // ill-formed: typename required before A::B
void f(A<T>::B); // ill-formed: typename required before A<T>::B
typename A::B g(); // OK
};
The keyword typename is required whether the qualified name is A or A<T> because A or A<T> are synoyms within a class template with the parameter list <T>.
With above description, if a template is declared correctly, keyword typename always indicates a dependent type. So below at line 11704, if we see typename , we can assume type dependency safely and vice versa (if the template declared wrong, for example typename missed, error will be generated in later parsing). Function dependent_type_p_r does the checking.
11686 static bool
11687 dependent_type_p_r (tree type) in pt.c
11688 {
11689 tree scope;
11690
11691 /* [temp.dep.type]
11692
11693 A type is dependent if it is:
11694
11695 -- a template parameter. Template template parameters are
11696 types for us (since TYPE_P holds true for them) so we
11697 handle them here. */
11698 if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
11699 || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
11700 return true;
11701 /* -- a qualified-id with a nested-name-specifier which contains a
11702 class-name that names a dependent type or whose unqualified-id
11703 names a dependent type. */
11704 if (TREE_CODE (type) == TYPENAME_TYPE)
11705 return true;
11706 /* -- a cv-qualified type where the cv-unqualified type is
11707 dependent. */
11708 type = TYPE_MAIN_VARIANT (type);
11709 /* -- a compound type constructed from any dependent type. */
11710 if (TYPE_PTR_TO_MEMBER_P (type))
11711 return (dependent_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
11712 || dependent_type_p (TYPE_PTRMEM_POINTED_TO_TYPE
11713 (type)));
11714 else if (TREE_CODE (type) == POINTER_TYPE
11715 || TREE_CODE (type) == REFERENCE_TYPE)
11716 return dependent_type_p (TREE_TYPE (type));
11717 else if (TREE_CODE (type) == FUNCTION_TYPE
11718 || TREE_CODE (type) == METHOD_TYPE)
11719 {
11720 tree arg_type;
11721
11722 if (dependent_type_p (TREE_TYPE (type)))
11723 return true;
11724 for (arg_type = TYPE_ARG_TYPES (type);
11725 arg_type;
11726 arg_type = TREE_CHAIN (arg_type))
11727 if (dependent_type_p (TREE_VALUE (arg_type)))
11728 return true;
11729 return false;
11730 }
Above at line 11710, TYPE_PTR_TO_MEMBER_P is nonzero, if type is a pointer to data member or method of a class. While for type T X::* , TYPE_PTRMEM_CLASS_TYPE returns X , and TYPE_PTRMEM_CLASS_TYPE returns T.
For FUNCTION_DECL (function) or METHOD_DECL (method of class), TREE_TYPE returns the returned type, and TREE_ARG_TYPE returns the list of argument types.
dependent_type_p_r (continue)
11731 /* -- an array type constructed from any dependent type or whose
11732 size is specified by a constant expression that is
11733 value-dependent. */
11734 if (TREE_CODE (type) == ARRAY_TYPE)
11735 {
11736 if (TYPE_DOMAIN (type)
11737 && ((value_dependent_expression_p
11738 (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
11739 || (type_dependent_expression_p
11740 (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))))
11741 return true;
11742 return dependent_type_p (TREE_TYPE (type));
11743 }
The type of boundary of an array is accessed by TYPE_DOMAIN , and the upper and lower bounds can be visited by TYPE_MAX_VALUE and TYPE_MIN_VALUE respectively.
In above type dependent condition, by 5th clause, an array is type dependent if its size is specified by a constant expression that is value-dependent.
Value-dependent expression should be:
Except as described below, a constant expression is value-dependent if any subexpression is value-dependent.
An identifier is value-dependent if it is:
A name declared with a dependent type.
The name of a non-type template parameter.
A constant with integral or enumeration type and is initialized with an expression that is value-dependent.
Expression of the following form are value-dependent if the unary-expression is type-dependent or the type-id is dependent (even if sizeof unary-expression and sizeof (type-id) are not type-dependent): sizeof unary-expression, sizeof (type-id) .
Expressions of the following form are value-dependent if either the type-id or simple-type-specifier is dependent or the expression or cast-expression is value-dependent:
simple-type-specifier (expression-list opt )
static_cast <type-id> (expression)
const_cast <type-id> (expression)
reinterpret_cast <type-id> (expression)
(type-id) cast-expression
11851 bool
11852 value_dependent_expression_p (tree expression) in pt.c
11853 {
11854 if (!processing_template_decl )
11855 return false;
11856
11857 /* A name declared with a dependent type. */
11858 if (TREE_CODE (expression) == IDENTIFIER_NODE
11859 || (DECL_P (expression)
11860 && type_dependent_expression_p (expression)))
11861 return true;
11862 /* A non-type template parameter. */
11863 if ((TREE_CODE (expression) == CONST_DECL
11864 && DECL_TEMPLATE_PARM_P (expression))
11865 || TREE_CODE (expression) == TEMPLATE_PARM_INDEX)
11866 return true;
11867 /* A constant with integral or enumeration type and is initialized
11868 with an expression that is value-dependent. */
11869 if (TREE_CODE (expression) == VAR_DECL
11870 && DECL_INITIAL (expression)
11871 && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (expression))
11872 && value_dependent_expression_p (DECL_INITIAL (expression)))
11873 return true;
11874 /* These expressions are value-dependent if the type to which the
11875 cast occurs is dependent or the expression being casted is
11876 value-dependent. */
11877 if (TREE_CODE (expression) == DYNAMIC_CAST_EXPR
11878 || TREE_CODE (expression) == STATIC_CAST_EXPR
11879 || TREE_CODE (expression) == CONST_CAST_EXPR
11880 || TREE_CODE (expression) == REINTERPRET_CAST_EXPR
11881 || TREE_CODE (expression) == CAST_EXPR)
11882 {
11883 tree type = TREE_TYPE (expression);
11884 if (dependent_type_p (type))
11885 return true;
11886 /* A functional cast has a list of operands. */
11887 expression = TREE_OPERAND (expression, 0);
11888 if (!expression)
11889 {
11890 /* If there are no operands, it must be an expression such
11891 as "int()". This should not happen for aggregate types
11892 because it would form non-constant expressions. */
11893 my_friendly_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type),
11894 20040318);
11895
11896 return false;
11897 }
11898 if (TREE_CODE (expression) == TREE_LIST)
11899 {
11900 do
11901 {
11902 if (value_dependent_expression_p (TREE_VALUE (expression)))
11903 return true;
11904 expression = TREE_CHAIN (expression);
11905 }
11906 while (expression);
11907 return false;
11908 }
11909 else
11910 return value_dependent_expression_p (expression);
11911 }
11912 /* A `sizeof' expression is value-dependent if the operand is
11913 type-dependent. */
11914 if (TREE_CODE (expression) == SIZEOF_EXPR
11915 || TREE_CODE (expression) == ALIGNOF_EXPR)
11916 {
11917 expression = TREE_OPERAND (expression, 0);
11918 if (TYPE_P (expression))
11919 return dependent_type_p (expression);
11920 return type_dependent_expression_p (expression);
11921 }
11922 if (TREE_CODE (expression) == SCOPE_REF)
11923 return dependent_scope_ref_p (expression, value_dependent_expression_p );
11924 if (TREE_CODE (expression) == COMPONENT_REF)
11925 return (value_dependent_expression_p (TREE_OPERAND (expression, 0))
11926 || value_dependent_expression_p (TREE_OPERAND (expression, 1)));
11927 /* A constant expression is value-dependent if any subexpression is
11928 value-dependent. */
11929 if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expression))))
11930 {
11931 switch (TREE_CODE_CLASS (TREE_CODE (expression)))
11932 {
11933 case '1':
11934 return (value_dependent_expression_p
11935 (TREE_OPERAND (expression, 0)));
11936 case '<':
11937 case '2':
11938 return ((value_dependent_expression_p
11939 (TREE_OPERAND (expression, 0)))
11940 || (value_dependent_expression_p
11941 (TREE_OPERAND (expression, 1))));
11942 case 'e':
11943 {
11944 int i;
11945 for (i = 0; i < first_rtl_op (TREE_CODE (expression)); ++i)
11946 /* In some cases, some of the operands may be missing.
11947 (For example, in the case of PREDECREMENT_EXPR, the
11948 amount to increment by may be missing.) That doesn't
11949 make the expression dependent. */
11950 if (TREE_OPERAND (expression, i)
11951 && (value_dependent_expression_p
11952 (TREE_OPERAND (expression, i))))
11953 return true;
11954 return false;
11955 }
11956 }
11957 }
11958
11959 /* The expression is not value-dependent. */
11960 return false;
11961 }
Two cases derived from above rules need further consideration. At line 11922, node of SCOPE_REF has the class (type) as operand 0, and the field as operand 1. For example: it is used to hold A::i below (see that the expression is value-dependent).
template <typename T> struct A {
static const int i = sizeof (T);
};
A::i;
While COMPONENT_REF has the object in operand 0, and field in operand 1. For example: it is used to hold a.i below (a.i is also value-dependent as i is declared with dependent type).
template <typename T> struct A {
T i;
};
template <typename V> void f (A<V>& a, V value) {
a.i = value;
}
For node of SCOPE_REF, dependent_scope_ref_p verifies it being dependent or not. Notice that argument criterion refers to value_dependent_expression_p .
11816 static bool
11817 dependent_scope_ref_p (tree expression, bool criterion (tree)) in pt.c
11818 {
11819 tree scope;
11820 tree name;
11821
11822 my_friendly_assert (TREE_CODE (expression) == SCOPE_REF, 20030714);
11823
11824 if (!TYPE_P (TREE_OPERAND (expression, 0)))
11825 return true;
11826
11827 scope = TREE_OPERAND (expression, 0);
11828 name = TREE_OPERAND (expression, 1);
11829
11830 /* [temp.dep.expr]
11831
11832 An id-expression is type-dependent if it contains a
11833 nested-name-specifier that contains a class-name that names a
11834 dependent type. */
11835 /* The suggested resolution to Core Issue 2 implies that if the
11836 qualifying type is the current class, then we must peek
11837 inside it. */
11838 if (DECL_P (name)
11839 && currently_open_class (scope)
11840 && !criterion (name))
11841 return false;
11842 if (dependent_type_p (scope))
11843 return true;
11844
11845 return false;
11846 }
Considering condition at line 11838, takes below example,
template <typename T> struct A {
int j;
};
When parsing member j within class A, j should not be considered type/value dependent within the scope, but is if viewed from outside of the class.
Further, considering following example:
template <typename T> struct A{
typedef T innerType;
innerType j;
};
A<int>::innerType intType;
A<T>::innerType aType
intType (A<int>::innerType) is not value-dependent. But aType (A<T>::innerType) is.
dependent_type_p_r (continue)
11745 /* -- a template-id in which either the template name is a template
11746 parameter ... */
11747 if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
11748 return true;
11749 /* ... or any of the template arguments is a dependent type or
11750 an expression that is type-dependent or value-dependent. */
11751 else if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INFO (type)
11752 && (any_dependent_template_arguments_p
11753 (INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)))))
11754 return true;
11755
11756 /* All TYPEOF_TYPEs are dependent; if the argument of the `typeof'
11757 expression is not type-dependent, then it should already been
11758 have resolved. */
11759 if (TREE_CODE (type) == TYPEOF_TYPE)
11760 return true;
11761
11762 /* The standard does not specifically mention types that are local
11763 to template functions or local classes, but they should be
11764 considered dependent too. For example:
11765
11766 template <int I> void f() {
11767 enum E { a = I };
11768 S<sizeof (E)> s;
11769 }
11770
11771 The size of `E' cannot be known until the value of `I' has been
11772 determined. Therefore, `E' must be considered dependent. */
11773 scope = TYPE_CONTEXT (type);
11774 if (scope && TYPE_P (scope))
11775 return dependent_type_p (scope);
11776 else if (scope && TREE_CODE (scope) == FUNCTION_DECL)
11777 return type_dependent_expression_p (scope);
11778
11779 /* Other types are non-dependent. */
11780 return false;
11781 }
For condition “a template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent ”, considers following examples:
Example 1:
template <class T> struct Temp {
int t;
};
template <template <class U> class T, typename X, typename V = T<X> > struct A {
V func;
};
int main() {
A<Temp, int> a;
a.func.t = 0;
return 1;
}
Type Temp is used as the default argument which is dependent on template-parameter X (it is the case template name is a template parameter).
Example 2:
template <class T> struct Temp {
T t;
};
template<typename T> struct A {
Temp<T> func;
};
int main() {
A<int> a;
a.func.t = 0;
return 1;
}
Template Temp being a class member of A, accepts dependent type T. In this case, Temp’s definition contains one level of template argument (T). For template related tree nodes, refers to macros accessing template definition . It just tests innermost template argument because ISO-IE-14882-2003 defines that:
I n an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well. In such explicit specialization declaration, the keyword template followed by a template-parameter-list shall be provided instead of the template<> preceding the explicit specialization declaration of the member. The types of the template-parameters in the template-parameter-list shall be the same as those specified in the primary template definition. [Example: template <class T1> class A { template <class T2> class B { template <class T3> void mf1(T3); void mf2(); }; };
template <> template <class X> class A<int>::B { }; template <> template <> template <class T> void A<int>::B<double>::mf1(T t) { } template <class Y> template <> void A<Y>::B<double>::mf2() { } // ill-formed; B<double> is specialized but // its enclosing class template A is not |
Routine any_dependent_tempalte_arguments_p can evaluate the template argument vector though here the vector only contains the innermost arguments.
12116 bool
12117 any_dependent_template_arguments_p (tree args) in pt.c
12118 {
12119 int i;
12120 int j;
12121
12122 if (!args)
12123 return false;
12124
12125 for (i = 0; i < TMPL_ARGS_DEPTH (args); ++i)
12126 {
12127 tree level = TMPL_ARGS_LEVEL (args, i + 1);
12128 for (j = 0; j < TREE_VEC_LENGTH (level); ++j)
12129 if (dependent_template_arg_p (TREE_VEC_ELT (level, j)))
12130 return true;
12131 }
12132
12133 return false;
12134 }
Checking whether argument is dependent or not is quite similar with type declaration.
12097 static bool
12098 dependent_template_arg_p (tree arg) in pt.c
12099 {
12100 if (!processing_template_decl )
12101 return false;
12102
12103 if (TREE_CODE (arg) == TEMPLATE_DECL
12104 || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
12105 return dependent_template_p (arg);
12106 else if (TYPE_P (arg))
12107 return dependent_type_p (arg);
12108 else
12109 return (type_dependent_expression_p (arg)
12110 || value_dependent_expression_p (arg));
12111 }
Here notice that only node of TEMPLATE_TEMPLATE_PARM or TEMPLATE_DECL will be handled by dependent_template_p . See that if TEMPLATE_DECL is not used as template parameter (that is condition at line 12153 is not satisfied) and it is not contained within dependent scope, the TEMPLATE_DECL is not regarded as dependent (ISO-IE-14882-2003 [temp.dep.type], a template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent).
12138 bool
12139 dependent_template_p (tree tmpl) in pt.c
12140 {
12141 if (TREE_CODE (tmpl) == OVERLOAD)
12142 {
12143 while (tmpl)
12144 {
12145 if (dependent_template_p (OVL_FUNCTION (tmpl)))
12146 return true;
12147 tmpl = OVL_CHAIN (tmpl);
12148 }
12149 return false;
12150 }
12151
12152 /* Template template parameters are dependent. */
12153 if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)
12154 || TREE_CODE (tmpl) == TEMPLATE_TEMPLATE_PARM)
12155 return true;
12156 /* So are names that have not been looked up. */
12157 if (TREE_CODE (tmpl) == SCOPE_REF
12158 || TREE_CODE (tmpl) == IDENTIFIER_NODE)
12159 return true;
12160 /* So are member templates of dependent classes. */
12161 if (TYPE_P (CP_DECL_CONTEXT (tmpl)))
12162 return dependent_type_p (DECL_CONTEXT (tmpl));
12163 return false;
12164 }
See that if function template is found as overloaded function, it is a tree node of OVERLOAD which wraps TEMPLATE_DECL by OVL_FUNCTION, so dependent_template_p at line 12145 will find out this function template.
Special unknown_type_node is used as type for overload functions/methods.
type_dependent_expression_p (continue)
12033 if (TREE_TYPE (expression) == unknown_type_node)
12034 {
12035 if (TREE_CODE (expression) == ADDR_EXPR)
12035 return type_dependent_expression_p (TREE_OPERAND (expression, 0));
12037 if (TREE_CODE (expression) == COMPONENT_REF
12038 || TREE_CODE (expression) == OFFSET_REF)
12039 {
12040 if (type_dependent_expression_p (TREE_OPERAND (expression, 0)))
12041 return true;
12042 expression = TREE_OPERAND (expression, 1);
12043 if (TREE_CODE (expression) == IDENTIFIER_NODE)
12044 return false;
12045 }
12046 /* SCOPE_REF with non-null TREE_TYPE is always non-dependent. */
12047 if (TREE_CODE (expression) == SCOPE_REF)
12048 return false;
12049
12050 if (TREE_CODE (expression) == BASELINK)
12051 expression = BASELINK_FUNCTIONS (expression);
12052 if (TREE_CODE (expression) == TEMPLATE_ID_EXPR)
12053 {
12054 if (any_dependent_template_arguments_p
12055 (TREE_OPERAND (expression, 1)))
12056 return true;
12057 expression = TREE_OPERAND (expression, 0);
12058 }
12059 if (TREE_CODE (expression) == OVERLOAD
12060 || TREE_CODE (expression) == FUNCTION_DECL)
12061 {
12062 while (expression)
12063 {
12064 if (type_dependent_expression_p (OVL_CURRENT (expression)))
12065 return true;
12066 expression = OVL_NEXT (expression);
12067 }
12068 return false;
12069 }
12070 abort ();
12071 }
12072
12073 my_friendly_assert (TREE_CODE (expression) != TYPE_DECL, 20051116);
12074
12075 return (dependent_type_p (TREE_TYPE (expression)));
12076 }
Above code continue to check type-dependency. See line 12043, for name unsolved within an independent scope, simply regards it as independent (except the error case, I can’t think out the correct one). Otherwise, goes with code below line 12047 continue to check the operand 1.