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
Non-static method of the class should be METHOD_TYPE in the intermediate tree. For methods, as we know, this is the implicit argument which refers to the object the method may operate upon. Below build_pointer_type creates the implicit this . Notice that the node of FUNCTION_TYPE created at line 7601 is abandoned as side effect (it will be collected by GC later).
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 }
At line 8247, decl_funtion_context returns NULL_TREE if none of the enclosing scope of the decl is FUNCTION_DECL, or the enclosing scope of FUNCTION_DECL. Now, decl is current_class_type which is the TYPE_DECL of struct “Lock”.
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 }
During stepping over the enclosing stack, it may encounter *_TYPE besides *_DECL, then fetch enclosing context accordingly by 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 }
As result publicp at line 8248 is 1, it means the visibilty of the declaration is only determined by the containing class.
Then for the invocation of grokfndecl at line 8250, the arguments have values as: ctype (current_class_type), type (METHOD_TYPE node at line 8240), 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);
Just before invoking grokclassfn , it can get following intermediate tree.
(Click here for open )
Figure 68 : FUNCTION_DECL for ctor of “Lock” – step 1
Though it has created the METHOD_TYPE node, it may not be the exact ones required as no cv-qualifier and other attributes are considered when constructing the node. Further the implicit this argument should be a const pointer.
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 }
Argument function is the FUNCTION_DECL node created before. And TREE_TYPE returns METHOD_TYPE node from it. Though it has created this pointer for the class, however, the implicit argument should be the constant pointer – the reference can’t be changed (the non-constant pointer is also necessary, as it is the unqualified version, should appear at head of the cv-qualified type chain as required by the front-end). So cp_build_qualified_type creates the qualified type accordingly from unqualified version.
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 }
Also notice that at line 336, this_identifier is the global identifier node for this (it just the name of “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 }
Currently, processing_template_decl is still non-zero as we are still within a class template (class “SingleThreaded”), so just PARM_DECL node is created but no further handling. Again when return grokclassfn , maybe_retrofit_in_chrg does nothing as processing_template_decl is non-zero. Now the intermediate tree looks like:
(Click here for open )
Figure 69 : FUNCTION_DECL for ctor of “Lock” – step 2
Below check_explicit_specialization has no side effect for normal template declaration (e.g., non-instantiation, non-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 }
Before exiting grokfndecl , it needs some checking. For constructor, it should not take form of X(X) which if accidently does self assignment will cause infinitely recursion. At line 5867, grok_ctor_properties does the checking.
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 }
As we know, constructor having parameter can be used as conversion operator except “explict” declared. And only constructor can be declared as “explicit”, so if explicitp is 2, it indicates its using is correct. Being converting constructor, it must have at least one argument, and except the first one, all other arguments should have default value.
Now we have tree nodes for the method created, but the set is not complete yet. So in the left of start_method , it completes the set of nodes for the constructor. Notice that fndecl is the FUNCTION_DECL created by grokdeclarator .
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 }
Now we are still within the template class, so first, it still needs to check whether the declarator shadows template argument. DECL_TEMPLATE_SPECIALIZATION at line 15224 checks that if DECL_USE_TEMPLATE field equates 2 (which indicates explicit specialization). Not surprise too, the constructor here should be considered as template declaration as it is contained by template class. We have seen push_template_decl in previous sections several times, see that as not directly in the scope of sk_template_parms, local variable primary in push_template_decl_real is false. When returns from push_template_decl , the intermediate tree has following nodes added.
(Click here for open )
Figure 70 : FUNCTION_DECL for ctor of “Lock” – step 3
After successfully creating the associated TEMPLATE_DECL and pushing it within the context, some flags of the containing class should be set accordingly.
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 }
Above at line 8906, copy_fn_p checks whether decl is copy constructor or assignment operator, and returns zero if neither. Then FUNCTION_FIRST_USER_PARMTYPE fetches the first non-artificial parameter (that is skip the 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)))
Above figure explains the behavor of skip_artificial_parms_for clearly. Notice that only class derived from virtual base, DECL_HAS_IN_CHARGE_PARM_P or DECL_HAS_VTT_PARM_P may return nonzero.
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 }
Again, the parameter chain of non-variadic FUNCTION_DECL must be ended by 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 }
Then in start_method , cp_finish_decl finishes processing of a declaration by installing its line number and initial value. However, being within class template, this routine just sets FUNCTION_DECL node with flag DECL_INITIALIZED_IN_CLASS_P.
Further at line 15244, begin_scope makes the FUNCTION_DECL as the current binding scope. At this step, the intermediate tree becomes following ones:
(Click here for open )
Figure 71 : FUNCTION_DECL for ctor of “Lock” – finish