Studying note of GCC-3.4.6 source (121)

来源:互联网 发布:linux排行榜 编辑:程序博客网 时间:2024/06/05 10:38

5.12.4.2.             Parse class-head

The token follows thetemplate-parameter-list is “class” which denotes the definition/ declaration ofa class-template. Same as the previous example, along with the following callstack: 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 theclass-head.  */

11870   type = cp_parser_class_head (parser,

11871                           &nested_name_specifier_p,

11872                           &attributes);

 

During parsing class-specifier, access checking should be donewithout deferred in general as indicated by the new inserted node of dk_no_deferredat line 11867. However, we can see later that different access checkings may beapplied 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   enumtag_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 nonested-name-specifier will be present. */

12049   *nested_name_specifier_p = false;

12050   /* Assume notemplate parameter lists will be used in defining the

12051     type. */

12052   num_templates = 0;

12053

12054  /* Look for theclass-key.  */

12055   class_key = cp_parser_class_key (parser);

12056   if (class_key == none_type)

12057     returnerror_mark_node;

12058

12059  /* Parse theattributes.  */

12060  attributes = cp_parser_attributes_opt (parser);

12061

12062   /* If the nexttoken is `::', that is invalid -- but sometimes

12063     people do try to write:

12064

12065       struct ::S {}; 

12066

12067     Handle this gracefully by accepting theextra qualifier, and then

12068     issuing an error about it later if thisreally is a

12069     class-head. If it turns out just to be anelaborated 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 thename 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 anested-name-specifier, then there *must* be an

12085     identifier. */

12086   if (nested_name_specifier)

12087   {

         

12143   }

12144   /* Otherwise, theidentifier is optional.  */

12145   else

12146   {

12147     /* We don't know whether what comes next is atemplate-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'twork, 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 isadded in, which adjusts the accessing check rule added by cp_parser_parse_tentativelyat 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_checkscorrespondingly.

 

cp_parser_class_head (continue)

 

12259  /* Look up thetype.  */

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 classwas 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 exactthe same as that described in section Push tag of classSingleThreaded. So we just skip the detail of the handling here to avoidunneccesary duplication.

The base class must be a defined type, finding out nodes for thetype from the class name is a complex procedure, especially the base is a classtemplate. Below we first have a look at class-name lookup. But before that, wethe best see how to determine the dependency of specified name.

5.12.4.2.1.       Evaluatetype dependency
5.12.4.2.1.1. Overview

Inside a template, some constructs have semantics which may differfrom one instantiation to another. Such a construct depends on the templateparameters. In particular, types and expressions may depend on the type and/orvalue of template parameters (e.g. determined by the template arguments) and whichalso determines the context for name lookup for the names. Expressions may betype-dependent (on the type of a template parameter) or value-dependent (on thevalue of a non-type template parameter). In an expression of the form:

postfix-expression( expression-list opt )

where thepostfix-expression is an identifier, the identifier denotes a dependent name ifand only if any of the expressions in the expression-list is a type-dependentexpression (14.6.2.2). If an operand of anoperator is a type-dependent expression, the operator also denotes a dependentname. Such names are unbound and are looked up at the point of the templateinstantiation (14.6.4.1) in both the context of the template definition and thecontext of the point of instantiation.  [Example:

template<class T> struct X : B<T> {

typename T::A* pa;

voidf(B<T>* pb) {

static int i = B<T>::i;

pb->j++;

}

};

the base class nameB<T>, the type name T::A, the names B<T>::i and pb->j explicitlydepend on the template-parameter.

In thedefinition of a class template or a member of a class template, if a base classof the class template depends on a template-parameter, the base class scope isnot examined during unqualified name lookup either at the point of definitionof the class template or member or during an instantiation of the classtemplate or member. [Example:

typedef double A;

template<classT> 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 typedefname defined in the global namespace scope, not to the typedef name defined inthe base class B<T>. [Example:

struct A {

struct B { /*... */ };

int a;

int Y;

};

int a;

template<class T> structY : 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. Typedependent

Routine type_dependent_expression_p returns true ifthe expressionis type-dependent.

 

11966 bool

11967 type_dependent_expression_p (tree expression)                                                 in pt.c

11968 {

11969   if (!processing_template_decl)

11970     returnfalse;

11971

11972   if (expression ==error_mark_node)

11973     returnfalse;

11974

11975   /*An unresolved name is always dependent. */

11976   if (TREE_CODE (expression)== IDENTIFIER_NODE)

11977     returntrue;

 

As we knowwhen parser find an identifier, it always try to look it up to find out thedeclaration currently bound with the name. This declaration is the object usedin current scope. But if the identifier hasn’t visible binding in currentscope, the parser only uses the IDENTIFIER_NODE. Takes above example asinstance:

template<class T> struct X : B<T> {

typename T::A* pa;

In “T::A”, the “A” at hereshould only be IDENTIFIER_NODE.

 

type_dependent_expression_p (continue)

 

11979   /* Some expression forms are nevertype-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     returnfalse;

11988

11989   /*The types of these expressions depends only on the type to which

11990     thecast 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     returndependent_type_p (TREE_TYPE (expression));

11997

11998   /* Thetypes of these expressions depends only on the type created

11999     by theexpression.  */

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 mayappear 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         aswell.  */

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     returntrue;

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     returntrue;

12028

12029   if (TREE_CODE (expression)== TEMPLATE_DECL

12030       &&!DECL_TEMPLATE_TEMPLATE_PARM_P (expression))

12031     returnfalse;

 

Accoding to[3], following forms are never type-dependent.

literal

postfix-expression.pseduo-destructor-name

postfix-expression->pseduo-destructor-name

sizeofunary-expression

sizeof(type-id)

typeid(expression)

typeid(type-id)

::optdelete cast-expression

::optdelete[] cast-expression

throwassignment-expression opt

As types of thoseexpressions are not dependent. For example, sizeof always of type size_t. TheGNU extension operator alignof isalso within the group (it is of type size_t too).

Then an id-expression is type-dependent if itcontains:

an identifier that was declared with adependent type

a template-id that is dependent

a conversion-function-id that specifies adependent type

a nested-name-specifier that contains aclass-name that names a dependent type

Expression of the following forms are type-dependent only if thetype specified by the type-id, simple-type-specifier or new-type-id is dependent, even if anysubexpression is type-dependent:

simple-type-specifier(expression-list opt)

::optnew new-placement opt new-type-idnew-initializer opt

::optnew 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 typescontained 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 operandat 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 purposeslot and new-declarator at the valueslot. If new-declarator deriving direct-new-declarator, it is the node ofARRAY_REF, with direct-new-declaratorof sub-dimension as operand 0, and expression for the size of dimension asoperand 1. Obvious if this expression is value-dependent, new-type-id is type-dependent too.

Then dependent_type_p validates whether typepassed in is template parameter dependent.

 

11786 bool

11787 dependent_type_p (tree type)                                                                           inpt.c

11788 {

11789   /*If there are no template parameters in scope, then there can't be

11790     anydependent types.  */

11791   if (!processing_template_decl)

11792     returnfalse;

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     returntrue;

11798

11799   /* Erroneous types can be considerednon-dependent.  */

11800   if (type == error_mark_node)

11801     returnfalse;

11802

11803   /* If we have not already computed theappropriate value for TYPE,

11804     do sonow.  */

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   returnTYPE_DEPENDENT_P (type);

11812 }

 

To accelerate compiling speed, some type if has been evaluated, slotlang_flag_6of the tree type node is set (TYPE_DEPENDENT_P_VALID) and the result is set in lang_flag_0slot (TYPE_DEPENDENT_P).

A type isdependent if it is:

1) A template parameter.

2) A qualified-idwith a nested-name-specifier which contains a class-name that names a dependenttype or whose unqualified-id names a dependent type.

3) A cv-qualifiedtype where the cv-unqualified type is dependent.

4) A compound typeconstructed from any dependent type.

5) An array typeconstructed from any dependent type or whose size is specified by a constantexpression that is value-dependent.

6) A template-id inwhich either the template name is a template parameter or any of the templatearguments is a dependent type or an expression that is type-dependent orvalue-dependent.

Below, TEMPLATE_TYPE_PARMis the node for template parameter, and that parameter being template itself isthe node of TEMPLATE_TEMPLATE_PARM.

Then according to ISO-IE-14882-2003, 14.6 name resolution:

Ÿ       A name used in a templatedeclaration or definition and that is dependent on a template parameter isassumed not to name a type unless the applicable name lookup finds a type nameor the name is qualified by the keyword typename.

For example:

// no B declared here

class X;

template<classT> class Y {

        class Z;          // forwarddeclaration 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

               typedeftypename T::A TA;

               TA* a5;          // declare pointer to T’s A

               typenameT::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, novisible declaration of B and a8

        }

};

Ÿ       A qualified-name that refers toa type and that depends on a template-parameter shall be prefixed by thekeyword typenameto indicate that the qualified-name denotes a type, forming an elaborated-typespecifier.

elaborated-type-specifier:

        typename::opt nested-name-specifier identifier

        typename::opt nested-name-specifier identifer <template-argument-list>

Ÿ       The keyword typenameshall only be used in template declarations and definitions, including in thereturn type of a function template or member function template, in the returntype for the definition of a member function of a class template or of a classnested within a class template, and in the type-specifier for the definition ofa static member of a class template or of a class nested within a classtemplate. The keyword typename shall only be applied to qualifiednames, but those names need not be dependent. The keyword typename is not premitted in abase-specifier or in a mem-initializer; in these contexts a qualified-name thatdepends on a template-parameter is implicitly assumed to be a type name.

Ÿ       Within the definition of aclass template or within the definition of a member of a class template, thekeyword typenameis not required when referring to the unqualified name of a previously declaredmember of the class template that declares the type. The keyword typenameshall always be specified when the member is referred to using a qualifiedname, even if the qualifier is simply the class template name.

For example:

template<classT> struct A {

        typedefint B;

        A::B b;                   // ill-formed: typename required before A::B

        void f(A<T>::B);    // ill-formed:typename required before A<T>::B

        typenameA::B g();  // OK

};

The keyword typenameis required whether the qualified name is A or A<T> because A orA<T> are synoyms within a class template with the parameter list<T>.

With above description, if a template is declared correctly, keywordtypenamealways 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 declaredwrong, for example typename missed, error will be generated in laterparsing). Function dependent_type_p_r does the checking.

 

11686 static bool

11687 dependent_type_p_r (tree type)                                                                        inpt.c

11688 {

11689   tree scope;

11690

11691   /*[temp.dep.type]

11692

11693    A type is dependent if it is:

11694

11695    -- atemplate parameter. Template template parameters are

11696    typesfor us (since TYPE_P holds true for them) so we

11697    handlethem here.  */

11698   if (TREE_CODE (type) ==TEMPLATE_TYPE_PARM

11699       || TREE_CODE (type) ==TEMPLATE_TEMPLATE_PARM)

11700     returntrue;

11701   /*-- a qualified-id with a nested-name-specifier which contains a

11702     class-name that names a dependent type orwhose unqualified-id

11703     namesa dependent type.  */

11704   if (TREE_CODE (type) ==TYPENAME_TYPE)

11705     returntrue;

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     returndependent_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       returntrue;

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     returnfalse;

11730   }

 

Above at line 11710, TYPE_PTR_TO_MEMBER_Pis nonzero, if typeis 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 listof argument types.

 

dependent_type_p_r (continue)

 

11731   /*-- an array type constructed from any dependent type or whose

11732     sizeis 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       returntrue;

11742     returndependent_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, anarray is type dependent if its size is specified by a constant expression thatis value-dependent.

5.12.4.2.1.3. Valuedependent

Value-dependent expression should be:

Ÿ       Except as described below, aconstant expression is value-dependent if any subexpression is value-dependent.

Ÿ       An identifier isvalue-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 withan expression that is value-dependent.

Ÿ       Expression of the followingform are value-dependent if the unary-expressionis type-dependent or the type-id isdependent (even if sizeof unary-expression and sizeof (type-id) are nottype-dependent): sizeof unary-expression,sizeof (type-id).

Ÿ       Expressions of the followingform are value-dependent if either the type-idor simple-type-specifier is dependentor 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)                                                inpt.c

11853 {

11854   if (!processing_template_decl)

11855     returnfalse;

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     returntrue;

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     returntrue;

11867   /*A constant with integral or enumeration type and is initialized

11868     withan 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     returntrue;

11874   /*These expressions are value-dependent if the type to which the

11875     castoccurs 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 ofoperands.  */

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-constantexpressions.  */

11893       my_friendly_assert(INTEGRAL_OR_ENUMERATION_TYPE_P (type),

11894                       20040318);

11895

11896       returnfalse;

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       returnfalse;

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     returntype_dependent_expression_p(expression);

11921   }

11922   if (TREE_CODE (expression)== SCOPE_REF)

11923     returndependent_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 ofPREDECREMENT_EXPR, the

11948             amount to increment by may bemissing.) 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             returntrue;

11954         return false;

11955       }

11956     }

11957   }

11958

11959   /*The expression is not value-dependent. */

11960   returnfalse;

11961 }

 

Two casesderived from above rules need further consideration. At line 11922, node ofSCOPE_REF has the class (type) as operand 0, and the field as operand 1. Forexample: it is used to hold A::i below (see that the expression isvalue-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 inoperand 1. For example: it is used to hold a.i below (a.i is alsovalue-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_pverifies 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))                                   inpt.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     returntrue;

11826

11827   scope = TREE_OPERAND(expression, 0);

11828   name = TREE_OPERAND(expression, 1);

11829

11830   /* [temp.dep.expr]

11831

11832     Anid-expression is type-dependent if it contains a

11833     nested-name-specifier that contains aclass-name that names a

11834     dependent type.  */

11835   /* Thesuggested resolution to Core Issue 2 implies that if the

11836     qualifying type is the current class, thenwe must peek

11837     insideit.  */

11838   if (DECL_P (name)

11839       &&currently_open_class (scope)

11840       && !criterion(name))

11841     returnfalse;

11842   if (dependent_type_p (scope))

11843     returntrue;

11844

11845   returnfalse;

11846 }

 

Consideringcondition at line 11838, takes below example,

template<typenameT> struct A {

    int j;

};

When parsing member j withinclass A, jshould not be considered type/value dependent within the scope, but is ifviewed from outside of the class.

Further, consideringfollowing example:

template <typename T> struct A{

        typedefT innerType;

innerType j;

};

A<int>::innerTypeintType;

A<T>::innerTypeaType

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     returntrue;

11749   /*... or any of the template arguments is a dependent type or

11750     anexpression 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     returntrue;

11755   

11756   /*All TYPEOF_TYPEs are dependent; if the argument of the `typeof'

11757     expression is not type-dependent, then itshould already been

11758     haveresolved.  */

11759   if (TREE_CODE (type) ==TYPEOF_TYPE)

11760     returntrue;

11761   

11762   /*The standard does not specifically mention types that are local

11763     totemplate 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 thevalue of `I' has been

11772     determined. Therefore, `E' must beconsidered dependent.  */

11773   scope = TYPE_CONTEXT (type);

11774   if (scope && TYPE_P(scope))

11775     returndependent_type_p (scope);

11776   else if (scope &&TREE_CODE (scope) == FUNCTION_DECL)

11777     returntype_dependent_expression_p (scope);

11778

11779   /*Other types are non-dependent.  */

11780   returnfalse;

11781 }

 

For condition“a template-id in which either thetemplate name is a template parameter or any of the template arguments is adependent type or an expression that is type-dependent or value-dependent”,considers following examples:

Example 1:

template<class T> structTemp {

    int t;

};

 

template<template<classU> class T, typenameX, typename V = T<X> > struct A {

    V func;

};

 

int main() {

    A<Temp, int> a;

    a.func.t = 0;

    return1;

}

Type Temp is used as the default argument which is dependent ontemplate-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;

    return1;

}

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 definesthat:

In 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_pcan evaluate the template argument vector though here the vector only containsthe innermost arguments.

 

12116 bool

12117 any_dependent_template_arguments_p (tree args)                                              inpt.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   returnfalse;

12134 }

 

Checking whether argument is dependent or not is quite similar withtype declaration.

 

12097 static bool

12098 dependent_template_arg_p (tree arg)                                                                 inpt.c

12099 {

12100   if (!processing_template_decl)

12101     returnfalse;

12102

12103   if (TREE_CODE (arg) ==TEMPLATE_DECL

12104       || TREE_CODE (arg) ==TEMPLATE_TEMPLATE_PARM)

12105     returndependent_template_p (arg);

12106   else if (TYPE_P (arg))

12107     returndependent_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 orTEMPLATE_DECL will be handled by dependent_template_p. See that ifTEMPLATE_DECL is not used as template parameter (that is condition at line12153 is not satisfied) and it is not contained within dependent scope, theTEMPLATE_DECL is not regarded as dependent (ISO-IE-14882-2003 [temp.dep.type], a template-id in which either the template name is a templateparameter or any of the template arguments is a dependent type or an expressionthat is type-dependent or value-dependent).

 

12138 bool

12139 dependent_template_p (tree tmpl)                                                                     inpt.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     returnfalse;

12150   }

12151

12152   /*Template template parameters are dependent. */

12153   if(DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)

12154       || TREE_CODE (tmpl) ==TEMPLATE_TEMPLATE_PARM)

12155     returntrue;

12156   /*So are names that have not been looked up. */

12157   if (TREE_CODE (tmpl) ==SCOPE_REF

12158       || TREE_CODE (tmpl) ==IDENTIFIER_NODE)

12159     returntrue;

12160   /*So are member templates of dependent classes. */

12161   if (TYPE_P (CP_DECL_CONTEXT(tmpl)))

12162     returndependent_type_p (DECL_CONTEXT (tmpl));

12163   returnfalse;

12164 }

 

See that if function template is found as overloaded function, it isa tree node of OVERLOAD which wraps TEMPLATE_DECL by OVL_FUNCTION, so dependent_template_pat line 12145 will find out this function template.

Special unknown_type_node is used as type for overloadfunctions/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       returnfalse;

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, forname unsolved within an independent scope, simply regards it as independent(except the error case, I can’t think out the correct one). Otherwise, goeswith code below line 12047 continue to check the operand 1.

 

原创粉丝点击