Studying note of GCC-3.4.6 source (120)

来源:互联网 发布:白金数据结局神乐和龙 编辑:程序博客网 时间:2024/06/05 09:37
5.12.4.1.2.1. Processnon-type parameter

After parsing this non-type template parameter, no doubt, next itneeds process this parameter to finish the revelant sub-tree and insert it inthe intermediate tree.

 

2161   tree

2162   process_template_parm(tree list, tree next)                                                      in pt.c

2163   {

2164     tree parm;

2165     tree decl = 0;

2166     tree defval;

2167     int is_type, idx;

2168  

2169     parm = next;

2170     my_friendly_assert (TREE_CODE (parm) ==TREE_LIST, 259);

2171     defval = TREE_PURPOSE (parm);

2172     parm = TREE_VALUE (parm);

2173    is_type = TREE_PURPOSE (parm) ==class_type_node;

2174  

2175     if (list)

2176     {

2177       tree p = TREE_VALUE (tree_last (list));

2178  

2179       if (TREE_CODE (p) == TYPE_DECL || TREE_CODE(p) == TEMPLATE_DECL)

2180         idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p));

2181       else

2182         idx = TEMPLATE_PARM_IDX (DECL_INITIAL(p));

2183       ++idx;

2184     }

2185     else

2186       idx = 0;

2187  

2188     if (!is_type)

2189     {

2190       my_friendly_assert (TREE_CODE (TREE_PURPOSE(parm)) == TREE_LIST, 260);

2191      /* is aconst-param */

2192       parm = grokdeclarator (TREE_VALUE (parm),TREE_PURPOSE (parm),

2193                           PARM, 0, NULL);

2194       SET_DECL_TEMPLATE_PARM_P (parm);

2195  

2196       /* [temp.param]

2197  

2198         The top-level cv-qualifierson the template-parameter are

2199         ignored when determining itstype.  */

2200       TREE_TYPE (parm) = TYPE_MAIN_VARIANT(TREE_TYPE (parm));

2201  

2202       /* A templateparameter is not modifiable.  */

2203       TREE_READONLY (parm) = TREE_CONSTANT (parm)= 1;

2204       if (invalid_nontype_parm_type_p (TREE_TYPE(parm), 1))

2205         TREE_TYPE (parm) = void_type_node;

2206       decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));

2207       TREE_CONSTANT (decl) = TREE_READONLY (decl)= 1;

2208       DECL_INITIAL (parm) = DECL_INITIAL (decl)

2209                = build_template_parm_index (idx,processing_template_decl,

2210                                         processing_template_decl,

2211                                         decl,TREE_TYPE (parm));

2212     }

2213     else

2214     {

        

2241     }

2242     DECL_ARTIFICIAL (decl) = 1;

2243     SET_DECL_TEMPLATE_PARM_P (decl);

2244     pushdecl (decl);

2245     parm = build_tree_list (defval, parm);

2246     returnchainon (list, parm);

2247   }

 

For our example: “size_t chunkSize = 4096”, the relevant sub-tree is refered by argument next of process_template_parm,then at line 2172 above, parm points to the part of “size_t chunSize”. Soat invocation of grokdeclarator, argument declarator points to tree nodes of“chunkSize”, then argument declspecs points to tree nodes “size_t”.

 

6462   tree

6463   grokdeclarator(tree declarator,                                                                 in decl.c

6464                tree declspecs,

6465                enumdecl_context decl_context,

6466                int initialized,

6467                tree* attrlist)

6468   {

6469     RID_BIT_TYPE specbits;

6470     int nclasses = 0;

6471     tree spec;

6472     tree type = NULL_TREE;

6473     int longlong = 0;

6474     int type_quals;

6475     int virtualp, explicitp, friendp, inlinep,staticp;

6476     intexplicit_int = 0;

6477    int explicit_char = 0;

6478     int defaulted_int = 0;

6479     int extern_langp = 0;

6480     tree dependant_name = NULL_TREE;

6481    

6482     tree typedef_decl = NULL_TREE;

6483     const char*name;

6484     tree typedef_type = NULL_TREE;

6485     int funcdef_flag = 0;

6486     enumtree_code innermost_code = ERROR_MARK;

6487     int bitfield = 0;

6488   #if 0

6489     /* See the codebelow that used this.  */

6490     tree decl_attr = NULL_TREE;

6491   #endif

6492  

6493     /* Keep track ofwhat sort of function is being processed

6494       so that we can warn aboutdefault return values, or explicit

6495       return values which do notmatch prescribed defaults.  */

6496     special_function_kind sfk = sfk_none;

6497  

6498     tree dname = NULL_TREE;

6499     tree ctype = current_class_type;

6500     tree ctor_return_type = NULL_TREE;

6501     enum overload_flags flags = NO_SPECIAL;

6502     tree quals = NULL_TREE;

6503     tree raises = NULL_TREE;

6504     int template_count = 0;

6505     tree in_namespace = NULL_TREE;

6506     tree returned_attrs = NULL_TREE;

6507     tree scope = NULL_TREE;

6508     tree parms = NULL_TREE;

6509  

6510     RIDBIT_RESET_ALL (specbits);

6511     if (decl_context == FUNCDEF)

6512       funcdef_flag = 1, decl_context = NORMAL;

6513     else if (decl_context == MEMFUNCDEF)

6514       funcdef_flag = -1, decl_context = FIELD;

6515     else if (decl_context == BITFIELD)

6516       bitfield = 1, decl_context = FIELD;

6517  

6518     /* Look inside adeclarator for the name being declared

6519       and get it as a string, for anerror message.  */

6520     {

6521       tree *next = &declarator;

6522       tree decl;

6523       name = NULL;

6524  

6525       while (next&& *next)

6526       {

6527         decl = *next;

6528         switch(TREE_CODE (decl))

6529         {

             

6629           caseIDENTIFIER_NODE:

6630             if (TREE_CODE (decl) ==IDENTIFIER_NODE)

6631               dname = decl;

6632  

6633             next = 0;

6634  

6635             if (C_IS_RESERVED_WORD (dname))

6636             {

6637               error ("declarator-id missing;using reserved word `%D'",

6638                     dname);

6639               name = IDENTIFIER_POINTER (dname);

6640             }

6641             else if (!IDENTIFIER_TYPENAME_P(dname))

6642               name = IDENTIFIER_POINTER (dname);

6643             else

6644             {

6645               my_friendly_assert (flags ==NO_SPECIAL, 154);

6646               flags = TYPENAME_FLAG;

6647               ctor_return_type = TREE_TYPE(dname);

6648               sfk = sfk_conversion;

6649               if (is_typename_at_global_scope(dname))

6650                 name = IDENTIFIER_POINTER(dname);

6651               else

6652                 name = "<invalidoperator>";

6653             }

6654             break;

            

6784         }

6785       }

6786     }

6787  

6788     /*A function definition's declarator must have the form of

6789       a function declarator.  */

6790  

6791     if (funcdef_flag && innermost_code !=CALL_EXPR)

6792       return 0;

       

6828     /* Look through thedecl specs and record which ones appear.

6829       Some typespecs are defined asbuilt-in typenames.

6830       Others, the ones that aremodifiers of other types,

6831       are represented by bits inSPECBITS: set the bits for

6832       the modifiers that appear. Storageclass keywords are also in SPECBITS.

6833  

6834       If there is a typedef name ora type, store the type in TYPE.

6835       This includes builtin typedefssuch as `int'.

6836  

6837       Set EXPLICIT_INT if the typeis `int' or `char' and did not

6838       come from a user typedef.

6839  

6840       Set LONGLONG if `long' ismentioned twice.

6841  

6842       For C++, constructors anddestructors have their own fast treatment. */

6843  

6844     for (spec =declspecs; spec; spec = TREE_CHAIN (spec))

6845     {

6846       int i;

6847       tree id;

6848  

6849       /* Certain parseerrors slip through. For example,

6850        `int class;' is not caught by the parser. Try

6851         weakly to recover here.  */

6852       if (TREE_CODE (spec) != TREE_LIST)

6853         return 0;

6854  

6855       id = TREE_VALUE (spec);

6856  

6857       /* If the entiredeclaration is itself tagged as deprecated then

6858        suppress reports ofdeprecated items.  */

6859       if (!adding_implicit_members && id &&TREE_DEPRECATED (id))

6860       {

6861         if (deprecated_state != DEPRECATED_SUPPRESS)

6862           warn_deprecated_use (id);

6863       }

6864  

6865       if (TREE_CODE (id) == IDENTIFIER_NODE)

6866       {

6867         if (id == ridpointers[(int) RID_INT]

6868            || id == ridpointers[(int) RID_CHAR]

6869            || id == ridpointers[(int) RID_BOOL]

6870            || id == ridpointers[(int) RID_WCHAR])

6871         {

             

6888         }

6889         /* C++ aggregate types.  */

6890         if(IDENTIFIER_HAS_TYPE_VALUE (id))

6890         {

             

6896         }

           

6947         if (type)

6948           error ("two or more data types indeclaration of `%s'", name);

6949         else if (TREE_CODE (id) ==IDENTIFIER_NODE)

6950         {

6951           tree t = lookup_name (id, 1);

6952          if (!t || TREE_CODE (t) != TYPE_DECL)

6953             error ("`%s' fails to be atypedef or built in type",

6954                  IDENTIFIER_POINTER (id));

6955           else

6956           {

6957             type = TREE_TYPE (t);

6958             typedef_decl = t;

6959           }

6960         }

          

6965       found: ;

6966       }

6967  

6968   #if 0

6969     /* See the codebelow that used this.  */

6970     if (typedef_decl)

6971       decl_attr = DECL_ATTRIBUTES (typedef_decl);

6972   #endif

6973     typedef_type = type;

 

For declarator of IDENTIFIER_NODE only literal name is retrieved,and this name is used in error message to give out a clear description. Thenfor declspecs,it is a tree_list of only node of IDENTIFIER_NODE, which is refered by idabove. Then lookup_nameat line 6951 looks up this unqualified-name, and the corresponding TYPE_DECLnode would be returned. Notice that for the case, the parser can recognize thatit is a typedef. So variable type at line 6957 points to long_unsigned_type_node (assumingsize_t is typedef as unsigned long), and typedef_decl points to the TYPE_DECL.

 

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       }

         

8750       returndecl;

8751     }

8752   }

 

Same astype-parameter, node of TEMPLATE_PARM_INDEX needs be created to stand for thisparameter. Note that template parameter chunkSize can only be constant. A nodeof CONST_DECL is created automatically by parser to indicate the fact. From thenodes built here, it can easily tell out that, it is a constant declaration ofparameter declaration of template declaration.

(Clickhere for open)

Figure 107:non-type template parameter built

Then the namemust be pushed within current binding scope and let later name-lookup procedurefind out the correct declaration more efficiently. Routine pushdecl runs the same codeas previous template template parameter, and the parameter list after thispoint looks like below.

(Clickhere for open)

Figure 108:non-type template parameter pushed

See that bindings field of IDENTIFIER_NODE of “size_t”points to the CONST_DECL now, which indicates the local binding value.Name-lookup procedure will return this binding as result of searching withinthe scope.

Then thefollowing parameter is parsed and processed exactly the same. To keep conciseas possible, we just skip the procedure, and the intermediate tree layout canbe drawn accordingly and easily. When finishing parsing the template parameters,end_template_parm_listpacks the paramters according to following figure (note that the part ofparameter of “size_t maxSmallObjectSize” is not present in figure).

(Clickhere for open)

Figure 109: result of end_template_parm_list

 

 

原创粉丝点击