Studying note of GCC-3.4.6 source (121)

5.12.4.2.              Parse class-head

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.

5.12.4.2.1.        Evaluate type dependency
5.12.4.2.1.1.  Overview

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>.

5.12.4.2.1.2.  Type dependent

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.

5.12.4.2.1.3.  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.

 

你可能感兴趣的:(struct,tree,Class,templates,nested,attributes)