您的位置:首页 > 其它

Studying note of GCC-3.4.6 source (121)

2010-11-05 08:56 351 查看

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.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: