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

 

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 —完成

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值