您的位置:首页 > 编程语言

GCC-3.4.6源代码学习笔记 (100 续)

2010-09-10 11:45 381 查看
grokdeclarator (continue)

8163

{

8164

tree decl;

8165

8166

if (decl_context == PARM)

8167

{

8168

decl =
cp_build_parm_decl (declarator, type);

8169

8170

bad_specifiers (decl,
"parameter", virtualp, quals != NULL_TREE,

8171

inlinep,
friendp, raises != NULL_TREE);

8172

}

8173

else if (decl_context ==
FIELD)

8174

{

8175

/*
The C99 flexible array extension.
*/

8176

if (!staticp &&
TREE_CODE (type) == ARRAY_TYPE

8177

&& TYPE_DOMAIN
(type) == NULL_TREE)

8178

{

8179

tree itype =
compute_array_index_type (dname, integer_zero_node);

8180

type = build_cplus_array_type
(TREE_TYPE (type), itype);

8181

}

8182

8183

if (type ==
error_mark_node)

8184

{

8185

/* Happens when declaring arrays of sizes which

8186

are error_mark_node, for example.
*/

8187

decl = NULL_TREE;

8188

}

8189

else if (in_namespace
&& !friendp)

8190

{

8191

/* Something like struct S { int N::j; };
*/

8192

error ("invalid
use of `::'");

8193

decl = NULL_TREE;

8194

}

8195

else if (TREE_CODE
(type) == FUNCTION_TYPE)

8196

{

8197

int publicp = 0;

8198

tree function_context;

8199

8200

/* We catch the others as conflicts with the builtin

8201

typedefs.
*/

8202

if (friendp &&
declarator == ridpointers

[(int)
RID_SIGNED])

8203

{

8204

error
("function `%D' cannot be declared friend",

8205

declarator);

8206

friendp = 0;

8207

}

8208

8209

if (friendp == 0)

8210

{

8211

if (ctype == NULL_TREE)

8212

ctype = current_class_type

;

8213

8214

if (ctype ==
NULL_TREE)

8215

{

8216

error ("can't
make `%D' into a method -- not in a class",

8217

declarator);

8218

return
void_type_node;

8219

}

8220

8221

/*
``A union may [ ... ] not [ have ] virtual functions.''

8222

ARM 9.5 */

8223

if (virtualp
&& TREE_CODE (ctype) == UNION_TYPE)

8224

{

8225

error
("function `%D' declared virtual inside a union",

8226

declarator);

8227

return
void_type_node;

8228

}

8229

8230

if
(NEW_DELETE_OPNAME_P (declarator))

8231

{

8232

if (virtualp)

8233

{

8234

error ("`%D' cannot be declared
virtual, since it is always static",

8235

declarator);

8236

virtualp = 0;

8237

}

8238

}

8239

else if (staticp
< 2)

8240

type = build_method_type_directly
(ctype,

8241

TREE_TYPE (type),

8242

TYPE_ARG_TYPES (type));

8243

}

8244

8245

/* Tell grokfndecl if it needs to set TREE_PUBLIC on the
node.
*/

8246

function_context =
(ctype != NULL_TREE) ?

8247

decl_function_context
(TYPE_MAIN_DECL
(ctype)) : NULL_TREE;

8248

publicp = (! friendp
|| ! staticp)

8249

&&
function_context == NULL_TREE;

8250

decl = grokfndecl
(ctype, type,

8251

TREE_CODE (declarator) != TEMPLATE_ID_EXPR

8252

?
declarator : dname,

8253

parms,

8254

declarator,

8255

virtualp, flags, quals, raises,

8256

friendp
? -1 : 0, friendp, publicp, inlinep,

8257

funcdef_flag, template_count, in_namespace);

8258

if (decl == NULL_TREE)

8259

return
decl;

8260

#if
0

8261

/* This clobbers the attrs stored in `decl' from
`attrlist'.
*/

8262

/* The decl and setting of decl_attr is also turned off.
*/

8263

decl =
build_decl_attribute_variant (decl, decl_attr);

8264

#endif

在中间树中,该类的非静态方法应该是
METHOD_TYPE
。对于方法,正如我们所了解的,
this

是隐含的参数指向这个方法所要操纵的对象。下面的
build_pointer_type

则是创建这个隐含的
this

。注意到,作为副作用,在
7601
行所构建的
FUNCTION_TYPE
节点被丢弃(它将随后被
GC
回收)。

3902

tree

3903

build_method_type_directly

(tree basetype,
in
tree.c

3904

tree
rettype,

3905

tree
argtypes)

3906

{

3907

tree t;

3908

tree ptype;

3909

int hashcode;

3910

3911

/*
Make a node of the sort we want.
*/

3912

t = make_node
(METHOD_TYPE);

3913

3914

TYPE_METHOD_BASETYPE (t) =
TYPE_MAIN_VARIANT (basetype);

3915

TREE_TYPE (t) = rettype;

3916

ptype = build_pointer_type
(basetype);

3917

3918

/*
The actual arglist for this function includes a "hidden" argument

3919

which
is "this". Put it into the list of argument types.
*/

3920

argtypes = tree_cons
(NULL_TREE, ptype, argtypes);

3921

TYPE_ARG_TYPES (t) =
argtypes;

3922

3923

/*
If we already have such a type, use the old one and free this one.

3924

Note
that it also frees up the above cons cell if found.
*/

3925

hashcode = TYPE_HASH
(basetype) + TYPE_HASH (rettype) +

3926

type_hash_list (argtypes);

3927

3928

t = type_hash_canon
(hashcode, t);

3929

3930

if (!COMPLETE_TYPE_P (t))

3931

layout_type
(t);

3932

3933

return
t;

3934

}


8247
行,如果
decl

的封闭(
enclosing
)域不是
FUNCTION_DECL

decl_funtion_context

返回
NULL_TREE
,否则就是这个
FUNCTION_DECL
。而现在
decl


current_class_type

,它是结构体“
Lock
”的
TYPE_DECL


4392

tree

4393

decl_function_context

(tree decl)
in
tree.c

4394

{

4395

tree context;

4396

4397

if (TREE_CODE (decl) ==
ERROR_MARK)

4398

return
0;

4399

4400

if (TREE_CODE (decl) ==
SAVE_EXPR)

4401

context =
SAVE_EXPR_CONTEXT (decl);

4402

4403

/*
C++ virtual functions use DECL_CONTEXT for the class of the vtable

4404

where
we look up the function at runtime. Such functions always take

4405

a
first argument of type 'pointer to real context'.

4406

4407

C++
should really be fixed to use DECL_CONTEXT for the real context,

4408

and
use something else for the "virtual context".
*/

4409

else if (TREE_CODE (decl) ==
FUNCTION_DECL && DECL_VINDEX (decl))

4410

context

4411

= TYPE_MAIN_VARIANT

4412

(TREE_TYPE
(TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));

4413

else

4414

context = DECL_CONTEXT
(decl);

4415

4416

while
(context && TREE_CODE (context) != FUNCTION_DECL)

4417

{

4418

if (TREE_CODE (context) ==
BLOCK)

4419

context =
BLOCK_SUPERCONTEXT (context);

4420

else

4421

context = get_containing_scope
(context);

4422

}

4423

4424

return
context;

4425

}

而在进入封闭域栈时,除了
*_DECL
可能还会遇到
*_TYPE
,通过
get_containing_scope

获取相应的封闭上下文。

4383

tree

4384

get_containing_scope

(tree t)
in
tree.c

4385

{

4386

return
(TYPE_P (t) ? TYPE_CONTEXT (t) : DECL_CONTEXT
(t));

4387

}

结果在
8248
行,
publicp


1
,它表示该声明的可见性仅取决于包含它的类。

那么对于
8250

grokfndecl

的调用,其参数的值为:
ctype


current_class_type
),
type

(在
8240
行的
METHOD_TYPE
节点),
parms


NULL_TREE
),
virtualp


0
),
flags


NO_SPECIAL
),
quals


NULL_TREE
),
raises


NULL_TREE
),
check


0
),
friendp


0
),
publicp


1
),
inlinep


0
),
funcdef_flag


-1
),
template_count


0
),
in_namespace


NULL_TREE)


5582

static
tree

5583

grokfndecl

(tree ctype,
in
decl.c

5584

tree type,

5585

tree declarator,

5586

tree parms,

5587

tree orig_declarator,

5588

int virtualp,

5589

enum
overload_flags
flags,

5590

tree quals,

5591

tree raises,

5592

int check,

5593

int friendp,

5594

int publicp,

5595

int inlinep,

5596

int funcdef_flag,

5597

int template_count,

5598

tree in_namespace)

5599

{

5600

tree decl;

5601

int staticp = ctype
&& TREE_CODE (type) == FUNCTION_TYPE;

5602

int has_default_arg = 0;

5603

tree t;

5604

5605

if (raises)

5606

type =
build_exception_variant (type, raises);

5607

5608

decl =
build_lang_decl

(FUNCTION_DECL, declarator, type);

5609

DECL_ARGUMENTS (decl) =
parms;

5610

/*
Propagate volatile out from type to decl.

*/

5611

if (TYPE_VOLATILE (type))

5612

TREE_THIS_VOLATILE (decl)
= 1;

5613

5614

/*
If this decl has namespace scope, set that up.

*/

5615

if (in_namespace)

5616

set_decl_namespace (decl,
in_namespace, friendp);

5617

else if (!ctype)

5618

DECL_CONTEXT (decl) =
FROB_CONTEXT (current_namespace);

5619

5620

/*
`main' and builtins have implicit 'C' linkage.

*/

5621

if ((MAIN_NAME_P
(declarator)

5622

|| (IDENTIFIER_LENGTH
(declarator) > 10

5623

&& IDENTIFIER_POINTER
(declarator)[0] == '_'

5624

&&
IDENTIFIER_POINTER (declarator)[1] == '_'

5625

&& strncmp
(IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0))

5626

&&
current_lang_name == lang_name_cplusplus

5627

&& ctype ==
NULL_TREE

5628

/* NULL_TREE means global namespace.

*/

5629

&& DECL_CONTEXT
(decl) == NULL_TREE)

5630

SET_DECL_LANGUAGE (decl,
lang_c);

5631

5632

/*
Should probably propagate const out from type to decl I bet (mrs).
*/

5633

if (staticp)

5634

{

5635

DECL_STATIC_FUNCTION_P
(decl) = 1;

5636

DECL_CONTEXT (decl) =
ctype;

5637

}

5638

5639

if (ctype)

5640

DECL_CONTEXT (decl) =
ctype;

5641

5642

if (ctype == NULL_TREE
&& DECL_MAIN_P (decl))

5643

{

5644

if
(processing_template_decl)

5645

error ("cannot
declare `::main' to be a template");

5646

if (inlinep)

5647

error ("cannot
declare `::main' to be inline");

5648

if (!publicp)

5649

error ("cannot
declare `::main' to be static");

5650

if (!same_type_p
(TREE_TYPE (TREE_TYPE (decl)),

5651

integer_type_node))

5652

error ("`main' must
return `int'");

5653

inlinep = 0;

5654

publicp = 1;

5655

}

5656

5657

/*
Members of anonymous types and local classes have no linkage; make

5658

them
internal.
*/

5659

/*
FIXME what if it gets a name from typedef?

*/

5660

if (ctype &&
(TYPE_ANONYMOUS_P (ctype)

5661

|| decl_function_context
(TYPE_MAIN_DECL (ctype))))

5662

publicp = 0;

5663

5664

if (publicp)

5665

{

5666

/*
[basic.link]: A name with no linkage (notably, the name of a class

5667

or enumeration declared in a local scope)
shall not be used to

5668

declare an entity with linkage.

5669

5670

Only check this for public decls for now. See
core 319, 389.
*/

5671

t = no_linkage_check
(TREE_TYPE (decl));

5672

if (t)

5673

{

5674

if (TYPE_ANONYMOUS_P
(t))

5675

{

5676

if (DECL_EXTERN_C_P
(decl))

5677

/*
Allow this; it's pretty common in C.
*/;

5678

else

5679

{

5680

pedwarn
("non-local function `%#D' uses anonymous type",

5681

decl);

5682

if
(DECL_ORIGINAL_TYPE (TYPE_NAME (t)))

5683

cp_pedwarn_at
("/

5684

`%#D' does not refer to the
unqualified type, so it is not used for linkage",

5685

TYPE_NAME (t));

5686

}

5687

}

5688

else

5689

pedwarn
("non-local function `%#D' uses local type `%T'",

5690

decl, t);

5691

}

5692

}

5693

5694

TREE_PUBLIC (decl) =
publicp;

5695

if (! publicp)

5696

{

5697

DECL_INTERFACE_KNOWN
(decl) = 1;

5698

DECL_NOT_REALLY_EXTERN
(decl) = 1;

5699

}

5700

5701

/*
If the declaration was declared inline, mark it as such.
*/

5702

if (inlinep)

5703

DECL_DECLARED_INLINE_P
(decl) = 1;

5704

/*
We inline functions that are explicitly declared inline, or, when

5705

the
user explicitly asks us to, all functions.

*/

5706

if (DECL_DECLARED_INLINE_P
(decl)

5707

|| (flag_inline_trees ==
2 && !DECL_INLINE (decl) && funcdef_flag))

5708

DECL_INLINE (decl) = 1;

5709

5710

DECL_EXTERNAL (decl) = 1;

5711

if (quals != NULL_TREE && TREE_CODE
(type) == FUNCTION_TYPE)

5712

{

5713

error ("%smember
function `%D' cannot have `%T' method qualifier",

5714

(ctype ?
"static " : "non-"), decl, TREE_VALUE (quals));

5715

quals = NULL_TREE;

5716

}

5717

5718

if (IDENTIFIER_OPNAME_P
(DECL_NAME (decl)))

5719

grok_op_properties (decl, /*complain=*/
true);

5720

5721

if (ctype && decl_function_context
(decl))

5722

DECL_NO_STATIC_CHAIN
(decl) = 1;

5723

5724

for
(t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t =
TREE_CHAIN (t))

5725

if (TREE_PURPOSE (t)

5726

&& TREE_CODE
(TREE_PURPOSE (t)) == DEFAULT_ARG)

5727

{

5728

has_default_arg = 1;

5729

break
;

5730

}

5731

5732

if (friendp

5733

&& TREE_CODE
(orig_declarator) == TEMPLATE_ID_EXPR)

5734

{

...

5786

}

5787

5788

if (funcdef_flag)

5789

/* Make the
init_value nonzero so pushdecl knows this is not

5790

tentative.
error_mark_node is replaced later with the BLOCK.
*/

5791

DECL_INITIAL (decl) = error_mark_node;

5792

5793

if (TYPE_NOTHROW_P (type) || nothrow_libfn_p
(decl))

5794

TREE_NOTHROW (decl) = 1;

5795

5796

/* Caller will do the rest of this.
*/

5797

if (check < 0)

5798

return
decl;

5799

5800

if (flags == NO_SPECIAL && ctype
&& constructor_name_p (declarator, ctype))

5801

DECL_CONSTRUCTOR_P (decl) = 1;

5802

5803

/* Function gets
the ugly name, field gets the nice one. This call

5804

may change the
type of the function (because of default

5805

parameters)!
*/

5806

if (ctype != NULL_TREE)

5807

grokclassfn
(ctype, decl, flags, quals);

在调用
grokclassfn

之前,中间树对应的部分如下。


点此打开




68

:“
Lock
”构造函数的
FUNCTION_DECL
—第一步

虽然已经创建了
METHOD_TYPE
节点,但它可能不完全是所要求的,因为这个类型节点没有考虑限定词及属性。而且那个隐含的
this

参数应该是一个指针常量。

303

void

304

grokclassfn

(tree ctype, tree function, enum
overload_flags flags, tree quals)
in decl2.c

305

{

306

tree fn_name = DECL_NAME
(function);

307

int this_quals =
TYPE_UNQUALIFIED;

308

309

/*
Even within an `extern "C"' block, members get C++ linkage.
See

310

[dcl.link] for details.
*/

311

SET_DECL_LANGUAGE (function,
lang_cplusplus);

312

313

if (fn_name == NULL_TREE)

314

{

315

error ("name missing
for member function");

316

fn_name = get_identifier
("<anonymous>");

317

DECL_NAME (function) =
fn_name;

318

}

319

320

if (quals)

321

this_quals =
grok_method_quals (ctype, function, quals);

322

323

if (TREE_CODE (TREE_TYPE
(function)) == METHOD_TYPE)

324

{

325

/*
Must add the class instance variable up front.

*/

326

/*
Right now we just make this a pointer.

But later

327

we may wish to make it special.
*/

328

tree type = TREE_VALUE
(TYPE_ARG_TYPES (TREE_TYPE (function)));

329

tree qual_type;

330

tree parm;

331

332

/*
The `this' parameter is implicitly `const'; it cannot be

333

assigned to.

*/

334

this_quals |=
TYPE_QUAL_CONST;

335

qual_type =
cp_build_qualified_type (type, this_quals);

336

parm = build_artificial_parm
(this_identifier,
qual_type);

337

c_apply_type_quals_to_decl
(this_quals, parm);

338

TREE_CHAIN (parm) =
DECL_ARGUMENTS (function);

339

DECL_ARGUMENTS (function)
= parm;

340

}

341

342

DECL_CONTEXT (function) =
ctype;

343

344

if (flags == DTOR_FLAG)

345

DECL_DESTRUCTOR_P
(function) = 1;

346

347

if (flags == DTOR_FLAG ||
DECL_CONSTRUCTOR_P (function))

348

maybe_retrofit_in_chrg
(function);

349

}

上面的参数
function

是先前所创建的
FUNCTION_DECL
节点。而
TREE_TYPE
从这个节点返回对应的
METHOD_TYPE
节点。虽然已经为类构建了
this

指针,不过这个隐含的参数应该是一个指针常量—其引用对象不能更换(这个非常量指针也是需要的,作为非限定类型,前端要求它出现在限定类型链表的头部)。因此
cp_build_qualified_type

从非限定类型构建要求的限定类型。

196

tree

197

build_artificial_parm

(tree name, tree type)
in
decl2.c

198

{

199

tree parm = cp_build_parm_decl
(name, type);

200

DECL_ARTIFICIAL (parm) = 1;

201

/*
All our artificial parms are implicitly `const'; they cannot be

202

avsigned
to.
*/

203

TREE_READONLY (parm) = 1;

204

return
parm;

205

}

同样注意在
336
行,
this_identifier

是表示
this

指针的全局标识符(它仅是名字“
this
”)。

182

tree

183

cp_build_parm_decl

(tree name, tree type)
in
decl2.c

184

{

185

tree parm =
build_decl

(PARM_DECL, name, type);

186

/*
DECL_ARG_TYPE is only used by the back end and the back end never

187

sees
templates.
*/

188

if (!processing_template_decl
)

189

DECL_ARG_TYPE (parm) = type_passed_as
(type);

190

return
parm;

191

}

在这里,
processing_template_decl

仍然为非
0
值,因为我们还在一个类模板里(
class

SingleThreaded
”),因此仅创建了
PARM_DECL
节点,但没有进一步的处理。同样当从
grokclassfn

返回,
maybe_retrofit_in_chrg

不做任何事,因为
processing_template_decl

是非
0
值。现在中间树看起来就像:


点此打开




69

:“
Lock
”构造函数的
FUNCTION_DECL
—第二步

下面,对于普通的模板声明(即,非具现,非特化),函数
check_explicit_specialization

不做实质的事情。

grokfndecl (continue)

5809

decl =
check_explicit_specialization (orig_declarator, decl,

5810

template_count,

5811

2 * (funcdef_flag != 0) +

5812

4 * (friendp != 0));

5813

if (decl == error_mark_node)

5814

return
NULL_TREE;

5815

5816

if (ctype != NULL_TREE

5817

&& (!
TYPE_FOR_JAVA (ctype) || check_java_method (decl))

5818

&& check)

5819

{



5865

}

5866

5867

if (DECL_CONSTRUCTOR_P
(decl) && !grok_ctor_properties (ctype, decl))

5868

return
NULL_TREE;

5869

5870

if (ctype == NULL_TREE ||
check)

5871

return
decl;

5872

5873

if (virtualp)

5874

DECL_VIRTUAL_P (decl) = 1;

5875

5876

return
decl;

5877

}

在离开
grokfndecl

之前,还需要一些检查。对于构造函数,它不能是
X(X)
的形式,因为如果不慎对自己赋值将导致无限递归。在
5867
行,
grok_ctor_properties

进行这个检查。

grokdeclarator (continue)

8266

/* [class.conv.ctor]

8267

8268

A constructor declared without the
function-specifier

8269

explicit that can be called with a single
parameter

8270

specifies
a conversion from the type of its first

8271

parameter to the type of its class. Such
a constructor

8272

is called a converting constructor.
*/

8273

if (explicitp == 2)

8274

DECL_NONCONVERTING_P
(decl) = 1;

8275

else if
(DECL_CONSTRUCTOR_P (decl))

8276

{

8277

/* The constructor can be called with exactly one

8278

parameter if there is at least one parameter,
and

8279

any
subsequent parameters have default arguments.

8280

Ignore any compiler-added parms.
*/

8281

tree arg_types =
FUNCTION_FIRST_USER_PARMTYPE (decl);

8282

8283

if (arg_types ==
void_list_node

8284

|| (arg_types

8285

&&
TREE_CHAIN (arg_types)

8286

&&
TREE_CHAIN (arg_types) != void_list_node

8287

&&
!TREE_PURPOSE (TREE_CHAIN (arg_types))))

8288

DECL_NONCONVERTING_P
(decl) = 1;

8289

}

8290

}



8548

}

8549

8550

my_friendly_assert
(!RIDBIT_SETP (RID_MUTABLE, specbits), 19990927);

8551

8552

/*
Record `register' declaration for warnings on &

8553

and
in case doing stupid register allocation.

*/

8554

8555

if (RIDBIT_SETP
(RID_REGISTER, specbits))

8556

DECL_REGISTER (decl) =
1;

8557

8558

if (RIDBIT_SETP
(RID_EXTERN, specbits))

8559

DECL_THIS_EXTERN (decl)
= 1;

8560

8561

if (RIDBIT_SETP
(RID_STATIC, specbits))

8562

DECL_THIS_STATIC (decl)
= 1;

8563

8564

/*
Record constancy and volatility. There's no need to do this

8565

when
processing a template; we'll do this for the instantiated

8566

declaration based on the type of DECL.

*/

8567

if (!processing_template_decl
)

8568

c_apply_type_quals_to_decl (type_quals, decl);

8569

8570

return
decl;

8571

}

8572

}

我们知道,带有参数的构造函数可以被用作转换操作符,除非它被声明为“
explict
”。而且只有构造函数可被声明为“
explicit
”,如果
explicitp


2
,则表示其使用没问题。能用作转换构造函数的构造函数必须带有至少一个参数,而且除第一个参数外,其他参数需要具有缺省值。

现在我们已经构建了方法的树节点,但其设置尚未完成。因此在
start_method

的余下部分,它为构造函数完成节点的设置。注意
fndecl

是由
grokdeclarator

构建的
FUNCTION_DECL
节点。

start_method (continue)

11051

if (fndecl ==
error_mark_node)

11052

return
error_mark_node;

11053

11054

if (fndecl == NULL ||
TREE_CODE (fndecl) != FUNCTION_DECL)

11055

{

11056

error ("invalid
member function declaration");

11057

return
error_mark_node;

11058

}

11059

11060

if (attrlist)

11061

cplus_decl_attributes
(&fndecl, attrlist, 0);

11062

11063

/*
Pass friends other than inline friend functions back.
*/

11064

if (fndecl ==
void_type_node)

11065

return
fndecl;

11066

11067

if (DECL_IN_AGGR_P (fndecl))

11068

{

11069

if (IDENTIFIER_ERROR_LOCUS
(DECL_ASSEMBLER_NAME (fndecl)) != current_class_type

)

11070

{

11071

if (DECL_CONTEXT
(fndecl)

11072

&& TREE_CODE(
DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)

11073

error ("`%D' is
already defined in class `%T'", fndecl,

11074

DECL_CONTEXT
(fndecl));

11075

}

11076

return
void_type_node;

11077

}

11078

11079

check_template_shadow
(fndecl);

11080

11081

DECL_DECLARED_INLINE_P
(fndecl) = 1;

11082

if (flag_default_inline)

11083

DECL_INLINE (fndecl) = 1;

11084

11085

/*
We process method specializations in finish_struct_1.
*/

11086

if (processing_template_decl
&&
!DECL_TEMPLATE_SPECIALIZATION (fndecl))

11087

{

11088

fndecl = push_template_decl
(fndecl);

11089

if (fndecl ==
error_mark_node)

11090

return
fndecl;

11091

}

11092

11093

if (! DECL_FRIEND_P
(fndecl))

11094

{

11095

if (TREE_CHAIN (fndecl))

11096

{

11097

fndecl = copy_node
(fndecl);

11098

TREE_CHAIN (fndecl) =
NULL_TREE;

11099

}

11100

grok_special_member_properties
(fndecl);

11101

}

11102

11103

cp_finish_decl (fndecl,
NULL_TREE, NULL_TREE, 0);

11104

11105

/*
Make a place for the parms.
*/

11106

begin_scope

(sk_function_parms, fndecl);

11107

11108

DECL_IN_AGGR_P (fndecl) = 1;

11109

return
fndecl;

11110

}

因为我们仍然在类模板中,所以它需要检查该声明符是否会屏蔽模板参数。在
15224
行的
DECL_TEMPLATE_SPECIALIZATION
检查
DECL_USE_TEMPLATE
域是否等于
2
(这表示显式特化)。毫无疑问,在这里,这个构造函数也被视为一个模板声明,因为它被包含在一个类模板中。在前面的章节中我们多次看过
push_template_decl

,注意到因为不是直接包含在域
sk_template_parms
中,在
push_template_decl_real

的局部变量
primary


false
。当从
push_template_decl

返回时,中间树加入了以下的节点。


点此打开




70

:“
Lock
”构造函数的
FUNCTION_DECL
—第三步

在成功地创建了相应的
TEMPLATE_DECL
并把它加入到上下文环境中,包含类节点的某些标记需要相应地设置。

8900

void grok_special_member_properties
(tree decl)
in
decl.c

8901

{

8902

if
(!DECL_NONSTATIC_MEMBER_FUNCTION_P(decl))

8903

; /*
Not special.
*/

8904

else if (DECL_CONSTRUCTOR_P
(decl))

8905

{

8906

int ctor = copy_fn_p
(decl);

8907

8908

if (ctor > 0)

8909

{

8910

/*
[class.copy]

8911

8912

A non-template constructor for class X is a
copy

8913

constructor if its first parameter is of
type X&, const

8914

X&, volatile X& or const volatile
X&, and either there

8915

are no other parameters or else all other
parameters have

8916

default arguments.
*/

8917

TYPE_HAS_INIT_REF
(DECL_CONTEXT (decl)) = 1;

8918

if (ctor > 1)

8919

TYPE_HAS_CONST_INIT_REF (DECL_CONTEXT (decl)) = 1;

8920

}

8921

else if (sufficient_parms_p
(FUNCTION_FIRST_USER_PARMTYPE
(decl)))

8922

TYPE_HAS_DEFAULT_CONSTRUCTOR (DECL_CONTEXT (decl)) = 1;

8923

}

8924

else if
(DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)

8925

{



8942

}

8943

}

上面在
8906
行,
copy_fn_p

检查
decl

是否是拷贝构造函数或赋值操作符,如果它都不是,则返回
0
。那么
FUNCTION_FIRST_USER_PARMTYPE
获取第一个非人造的参数(也即跳过参数
const this*

)。

983

#define
FUNCTION_FIRST_USER_PARMTYPE
(NODE) /
in cp-tree.h

984

skip_artificial_parms_for
((NODE),
TYPE_ARG_TYPES (TREE_TYPE (NODE)))

上面的图清除地解释了
skip_artificial_parms_for

的行为。注意到只有从虚基类派生的类,

DECL_HAS_IN_CHARGE_PARM_P

DECL_HAS_VTT_PARM_P
才可能返回非
0
值。

1061

tree

1062

skip_artificial_parms_for

(tree fn, tree list)
in
method.c

1063

{

1064

if
(DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))

1065

list = TREE_CHAIN (list);

1066

else

1067

return
list;

1068

1069

if
(DECL_HAS_IN_CHARGE_PARM_P (fn))

1070

list = TREE_CHAIN (list);

1071

if (DECL_HAS_VTT_PARM_P
(fn))

1072

list = TREE_CHAIN (list);

1073

return
list;

1074

}

注意,非可变参数的
FUNCTION_DECL
的参数链表必须由
void_list_node

结尾。

398

bool

399

sufficient_parms_p

(tree parmlist)
in
call.c

400

{

401

for
(; parmlist && parmlist != void_list_node;

402

parmlist = TREE_CHAIN
(parmlist))

403

if (!TREE_PURPOSE
(parmlist))

404

return
false;

405

return
true;

406

}

然后在
start_method

中,
cp_finish_decl

通过向节点中置入行号及初始值(如果有的话)完成对声明的处理。不过,因为在类模板中,该函数仅设置了
FUNCTION_DECL
节点的标记
DECL_INITIALIZED_IN_CLASS_P


另外,在
15244
行,
begin_scope

使得
FUNCTION_DECL
成为了当前的作用域(绑定域)。在这一步,中间树看起来如下:


点此打开




71

:“
Lock
”构造函数的
FUNCTION_DECL
—完成
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: