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 &¤tly_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.
- Studying note of GCC-3.4.6 source (121)
- Studying note of GCC-3.4.6 source (6)
- Studying note of GCC-3.4.6 source (1)
- Studying note of GCC-3.4.6 source (2)
- Studying note of GCC-3.4.6 source (3)
- Studying note of GCC-3.4.6 source (4)
- Studying note of GCC-3.4.6 source (5)
- Studying note of GCC-3.4.6 source (7)
- Studying note of GCC-3.4.6 source (8)
- Studying note of GCC-3.4.6 source (9)
- Studying note of GCC-3.4.6 source (10)
- Studying note of GCC-3.4.6 source (10 cont1)
- Studying note of GCC-3.4.6 source (10 cont2)
- Studying note of GCC-3.4.6 source (10 cont3)
- Studying note of GCC-3.4.6 source (10 cont4)
- Studying note of GCC-3.4.6 source (11)
- Studying note of GCC-3.4.6 source (12)
- Studying note of GCC-3.4.6 source (13)
- GCC-3.4.6源代码学习笔记(120)
- Studying note of GCC-3.4.6 source (120)
- 窗口刷新时的问题
- GCC-3.4.6源代码学习笔记(121)
- 喜欢羽球
- Studying note of GCC-3.4.6 source (121)
- 最后一个人可以挽救360和QQ的——马云
- VirtualBox安装Fedora后的相关设置1——全屏显示
- visibility 属性
- Ext JavaScript 运行机制
- oracle数据库使用odbc导出到access失败
- c#俄罗斯方块程序
- ASP 操作ADO 读写Excel文件
- GCC-3.4.6源代码学习笔记(122)