Studying note of GCC-3.4.6 source (120)

5.12.4.1.2.1.  Process non-type parameter

After parsing this non-type template parameter, no doubt, next it needs process this parameter to finish the revelant sub-tree and insert it in the 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 a const-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-qualifiers on the template-parameter are

2199         ignored when determining its type.  */

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

2201  

2202       /* A template parameter 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     return chainon (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”. So at 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                enum decl_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     int explicit_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     enum tree_code innermost_code = ERROR_MARK;

6487     int bitfield = 0;

6488   #if 0

6489     /* See the code below that used this.  */

6490     tree decl_attr = NULL_TREE;

6491   #endif

6492  

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

6494       so that we can warn about default return values, or explicit

6495       return values which do not match 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 a declarator for the name being declared

6519       and get it as a string, for an error 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           case IDENTIFIER_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 = "<invalid operator>";

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 the decl specs and record which ones appear.

6829       Some typespecs are defined as built-in typenames.

6830       Others, the ones that are modifiers of other types,

6831       are represented by bits in SPECBITS: set the bits for

6832       the modifiers that appear. Storage class keywords are also in SPECBITS.

6833  

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

6835       This includes builtin typedefs such as `int'.

6836  

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

6838       come from a user typedef.

6839  

6840       Set LONGLONG if `long' is mentioned twice.

6841  

6842       For C++, constructors and destructors 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 parse errors 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 entire declaration is itself tagged as deprecated then

6858         suppress reports of deprecated 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 in declaration 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 a typedef 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 code below 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. Then for declspecs , it is a tree_list of only node of IDENTIFIER_NODE, which is refered by id above. Then lookup_name at line 6951 looks up this unqualified-name, and the corresponding TYPE_DECL node would be returned. Notice that for the case, the parser can recognize that it is a typedef. So variable type at line 6957 points to long_unsigned_type_node (assuming size_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       return decl;

8751     }

8752   }

 

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

(Click here for open )

Figure 107 : non-type template parameter built

Then the name must be pushed within current binding scope and let later name-lookup procedure find out the correct declaration more efficiently. Routine pushdecl runs the same code as previous template template parameter, and the parameter list after this point looks like below.

(Click here 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 within the scope.

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

(Click here for open )

Figure 109 : result of end_template_parm_list

 

 

你可能感兴趣的:(Studying note of GCC-3.4.6 source (120))