Studying note of GCC-3.4.6 source (100 continue)

 

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
for Policy and Practice, 2018, 17(2): 179-195. In this article, Victor Wang Chen Neo examines the implementation of school-based curriculum development (SBCD) in Singapore. SBCD is a process where schools are given greater autonomy to develop and implement their own curriculum, rather than following a standardized national curriculum. The author begins by providing an overview of the history of curriculum development in Singapore, and how the shift towards SBCD came about. He then presents the findings of a study that he conducted, which involved interviews with school leaders who had implemented SBCD in their schools. The author identifies several factors that influenced the successful implementation of SBCD in these schools. These include strong leadership, a clear vision and direction for the school, and a focus on student learning and development. The author also highlights the importance of teacher training and support, as well as collaboration and communication among all stakeholders involved in the curriculum development process. However, the author also notes some challenges that schools face when implementing SBCD. These include a lack of resources, such as time and funding, as well as the need to balance autonomy with accountability to ensure that the curriculum developed meets national standards. Overall, the author suggests that SBCD has the potential to improve the quality of education in Singapore by allowing schools to tailor their curriculum to the needs and interests of their students. However, he also calls for continued support and guidance from the government to ensure that schools are able to implement SBCD effectively.

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值