天天看點

GCC-3.4.6源代碼學習筆記 (103)

5.12.3.2.1.1.3.5.2.            為參數建構 DECL 節點

在解析完參數清單後,在 cp_parser_direct_declarator 的 10492 行, make_call_declarator 建立如下的樹節點。

( 點此打開 )

圖 76 :非預設構造函數的 CALL_EXPR

沿着和預設構造函數相同的路徑,然後在 grokdeclarator 中,以下對該聲明符的處理有所不同。下面的 CALL_DECLARATOR_PARMS 通路 declarator (它就是上圖的 CALL_EXPR )的第二個操作數的 TREE_PURPOSE 域,這個域儲存該函數的參數。而第一個操作數則指向包含這個函數的類的 TYPE_DECL 。

grokdeclarator (continue)

7432       case CALL_EXPR:

7433       {

7434         tree arg_types;

7435         int funcdecl_p;

7436         tree inner_parms = CALL_DECLARATOR_PARMS (declarator);

7437         tree inner_decl = TREE_OPERAND (declarator, 0);

7438  

7439        

7441  

7442        

7444         type_quals = TYPE_UNQUALIFIED;

7445  

7446        

7447  

7448         if (TREE_CODE (type) == FUNCTION_TYPE)

7449         {

7450           error ("`%s' declared as function returning a function", name);

7451           type = integer_type_node;

7452         }

7453         if (TREE_CODE (type) == ARRAY_TYPE)

7454         {

7455           error ("`%s' declared as function returning an array", name);

7456           type = integer_type_node;

7457         }

7458  

7459         if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF)

7460           inner_decl = TREE_OPERAND (inner_decl, 1);

7461  

7462         if (inner_decl && TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR)

7463           inner_decl = dname;

7464  

7465        

7466         quals = CALL_DECLARATOR_QUALS (declarator);

7467  

7468        

7469         raises = CALL_DECLARATOR_EXCEPTION_SPEC (declarator);

7470  

7471        

7473         funcdecl_p

7474            = inner_decl

7475                && (TREE_CODE (inner_decl) == IDENTIFIER_NODE

7476                     || TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR

7477                     || TREE_CODE (inner_decl) == BIT_NOT_EXPR);

7478  

7479         if (ctype == NULL_TREE

7480            && decl_context == FIELD

7481            && funcdecl_p

7482            && (friendp == 0 || dname == current_class_name))

7483           ctype = current_class_type ;

7484  

7485         if (ctype && sfk == sfk_conversion)

7486           TYPE_HAS_CONVERSION (ctype) = 1;

7487         if (ctype && constructor_name_p (dname, ctype))

7488         {

7489           

7493  

7494           if (flags == DTOR_FLAG)

7495           {

7496             

7499             if (staticp == 2)

7500               error ("destructor cannot be static member function");

7501             if (quals)

7502             {

7503               error ("destructors may not be `%s'",

7504                     IDENTIFIER_POINTER (TREE_VALUE (quals)));

7505               quals = NULL_TREE;

7506             }

7507             if (decl_context == FIELD)

7508             {

7509               if (! member_function_or_else (ctype,

7510                                         current_class_type ,

7511                                         flags))

7512                 return void_type_node;

7513             }

7514           }

7515           else           

7516           {

7517             if (explicitp == 1)

7518                explicitp = 2;

7519            

7523             if (staticp == 2)

7524               error ("constructor cannot be static member function");

7525             if (virtualp)

7526             {

7527               pedwarn ("constructors cannot be declared virtual");

7528               virtualp = 0;

7529             }

7530              if (quals)

7531             {

7532               error ("constructors may not be `%s'",

7533                     IDENTIFIER_POINTER (TREE_VALUE (quals)));

7534               quals = NULL_TREE;

7535             }

7536             {

7537               RID_BIT_TYPE tmp_bits;

7538               memcpy (&tmp_bits, &specbits, sizeof (RID_BIT_TYPE));

7539               RIDBIT_RESET (RID_INLINE, tmp_bits);

7540               RIDBIT_RESET (RID_STATIC, tmp_bits);

7541               if (RIDBIT_ANY_SET (tmp_bits))

7542                 error ("return value type specifier for constructor ignored");

7543             }

7544             if (decl_context == FIELD)

7545             {

7546               if (! member_function_or_else (ctype,

7547                                         current_class_type ,

7548                                         flags))

7549                 return void_type_node;

7550               TYPE_HAS_CONSTRUCTOR (ctype) = 1;

7551               if (sfk != sfk_constructor)

7552                 return NULL_TREE;

7553             }

7554           }

7555           if (decl_context == FIELD)

7556             staticp = 0;

7557         }

7558         else if (friendp)

7559         {

7560           if (initialized)

7561             error ("can't initialize friend function `%s'", name);

7562           if (virtualp)

7563            {

7564            

7565             error ("virtual functions cannot be friends");

7566             RIDBIT_RESET (RID_FRIEND, specbits);

7567             friendp = 0;

7568           }

7569           if (decl_context == NORMAL)

7570             error ("friend declaration not in class definition");

7571           if (current_function_decl && funcdef_flag)

7572             error ("can't define friend function `%s' in a local class definition",

7573                   name);

7574         }

7575  

7576         

7578  

7579         declarator = TREE_OPERAND (declarator, 0);

7580  

7581         arg_types = grokparms (inner_parms, &parms);

7582  

7583         if (declarator && flags == DTOR_FLAG)

7584         {

7585          

7588           if (TREE_CODE (declarator) == BIT_NOT_EXPR)

7589             declarator = TREE_OPERAND (declarator, 0);

7590  

7591           if (arg_types != void_list_node)

7592           {

7593             error ("destructors may not have parameters");

7594              arg_types = void_list_node;

7595             parms = NULL_TREE;

7596           }

7597         }

7598  

7599        

7601         type = build_function_type (type, arg_types);

7602       }

7603       break ;

上面在 7473 行, funcdecl_p 是 true 。那麼如果聲明符是有效的,就可以處理其參數。

8722   static tree

8723   grokparms (tree first_parm, tree *parms)                                                          in decl.c

8724   {

8725     tree result = NULL_TREE;

8726     tree decls = NULL_TREE;

8727     int ellipsis = !first_parm || PARMLIST_ELLIPSIS_P (first_parm);

8728     tree parm, chain;

8729     int any_error = 0;

8730  

8731     my_friendly_assert (!first_parm || TREE_PARMLIST (first_parm), 20001115);

8732  

8733     for (parm = first_parm; parm != NULL_TREE; parm = chain)

8734     {

8735       tree type = NULL_TREE;

8736       tree decl = TREE_VALUE (parm);

8737       tree init = TREE_PURPOSE (parm);

8738       tree specs, attrs;

8739  

8740       chain = TREE_CHAIN (parm);

8741      

8742       if (TREE_CODE (decl) != VOID_TYPE

8743          && TREE_CODE (decl) != TREE_LIST)

8744       {

8745        

8746         if (TREE_CODE (decl) == STRING_CST)

8747           error ("invalid string constant `%E'", decl);

8748         else if (TREE_CODE (decl) == INTEGER_CST)

8749           error ("invalid integer constant in parameter list, did you forget to give parameter name?");

8750         continue ;

8751       }

8752  

8753       if (parm == void_list_node)

8754         break ;

8755  

8756       split_specs_attrs (TREE_PURPOSE (decl), &specs, &attrs);

8757       decl = grokdeclarator (TREE_VALUE (decl), specs,

8758                          PARM, init != NULL_TREE, &attrs);

8759       if (! decl || TREE_TYPE (decl) == error_mark_node)

8760         continue ;

這裡在 8756 行的 attrs 是 NULL_TREE ,是以 split_specs_attrs 隻是傳回 decl 的 TREE_PURPOSE 域的子樹。從上圖所建立的 CALL_EXPR 節點中,看到 decl 的 TREE_VALUE 域指向該聲明符。

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    

6490     tree decl_attr = NULL_TREE;

6491   #endif

6492  

6493    

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    

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         {

6530           case TREE_LIST:

6531             

6532             next = &TREE_VALUE (decl);

6533             break ;

              …

6582           case ADDR_EXPR:    

6583          

6584           case ARRAY_REF:

6585           case INDIRECT_REF:

6586             ctype = NULL_TREE;

6587             innermost_code = TREE_CODE (decl);

6588             next = &TREE_OPERAND (decl, 0);

6589             break ;

      …

6784         }

6785       }

6786     }

首先是對聲明符的預先處理。實際上,對于這個參數,其預先處理僅僅是進行有效性驗證(比較前面對方法的處理,期間為 CALL_EXPR 節點建構了 FUNCTION_DECL 節點)。是以在下面, name 是 NULL 因為該聲明符是匿名的,并最終作為“ parameter “進行指派。

grokdeclarator (continue)

6825     if (name == NULL)

6826       name = decl_context == PARM ? "parameter" : "type name";

6827  

6828    

6843  

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

6845     {

6846       int i;

6847       tree id;

6848  

6849      

6852       if (TREE_CODE (spec) != TREE_LIST)

6853         return 0;

6854  

6855       id = TREE_VALUE (spec);

6856  

6857      

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         {

6872           if (type)

6873           {

6874             if (id == ridpointers [(int) RID_BOOL])

6875               error ("`bool' is now a keyword");

6876             else

6877               error ("extraneous `%T' ignored", id);

6878           }

6879           else

6880           {

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

6882                explicit_int = 1;

6883             else if (id == ridpointers [(int) RID_CHAR])

6884               explicit_char = 1;

6885             type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));

6886           }

6887           goto found;

6888         }

6889        

6890         if (IDENTIFIER_HAS_TYPE_VALUE (id))

6891         {

6892           if (type)

6893             error ("multiple declarations `%T' and `%T'", type, id);

6894           else

6895             type = IDENTIFIER_TYPE_VALUE (id);

6896           goto found;

6897         }

6898  

6899         for (i = (int) RID_FIRST_MODIFIER; i <= (int) RID_LAST_MODIFIER; i++)

6900         {

6901           if (ridpointers [i] == id)

6902           {

6903             if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits))

6904              {

6905               if (pedantic && ! in_system_header && warn_long_long )

6906                 pedwarn ("ISO C++ does not support `long long'");

6907               if (longlong)

6908                 error ("`long long long' is too long for GCC");

6909                else

6910                 longlong = 1;

6911             }

6912             else if (RIDBIT_SETP (i, specbits))

6913               pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));

6914  

6915            

6916             if (RIDBIT_SETP (RID_THREAD, specbits))

6917             {

6918               if (i == (int)RID_EXTERN)

6919                 error ("`__thread' before `extern'");

6920               else if (i == (int)RID_STATIC)

6921                 error ("`__thread' before `static'");

6922             }

6923  

6924             if (i == (int)RID_EXTERN

6925                && TREE_PURPOSE (spec) == error_mark_node)

6926              

6927               extern_langp = 1;

6928  

6929             RIDBIT_SET (i, specbits);

6930             goto found;

6931           }

6932         }

6933       }

6934       else if (TREE_CODE (id) == TYPE_DECL)

6935       {

6936         if (type)

6937           error ("multiple declarations `%T' and `%T'", type,

6938                 TREE_TYPE (id));

6939         else

6940         {

6941           type = TREE_TYPE (id);

6942           TREE_VALUE (spec) = type;

6943           typedef_decl = id;

6944         }

6945         goto found;

6946       }

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       }

6961       else if (id != error_mark_node)

6962        

6963         type = id;

6964  

6965   found: ;

6966     }

構成 decl-specifier-seq 部分的節點,如果有效,應該早已被定義。第一個節點是關鍵字“ const ”,在 6899 行的 FOR 循環體中被識别出來,并且其 cv-qualifier 資訊被儲存在 6929 行的 specbits 内。每個聲明符隻能指定一個類型,是以當看到一個 TYPE_DECL 時, type 必須是 NULL 。

grokdeclarator (continue)

7161     type_quals = TYPE_UNQUALIFIED;

7162     if (RIDBIT_SETP (RID_CONST, specbits))

7163       type_quals |= TYPE_QUAL_CONST;

        …

7172     type_quals |= cp_type_quals (type);

7173     type = cp_build_qualified_type_real

7174        (type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl)

7175                        ? tf_ignore_bad_quals : 0) | tf_error | tf_warning));

7176    

7177     type_quals = cp_type_quals (type);

考慮代碼:

       typedef const int A;

       void func (A&);

雖然參數 A 被聲明為非 constant ,它本身是一個常量類型。為了産生正确的代碼,前端必須能夠找出确切使用的那個類型。這就是 cp_build_qualified_type_real 的任務。

427    tree

428    cp_build_qualified_type_real (tree type,                                                           in tree.c

429                             int type_quals,

430                             tsubst_flags_t complain)

431    {

432      tree result;

433      int bad_quals = TYPE_UNQUALIFIED;

434   

435      if (type == error_mark_node)

436        return type;

437   

438      if (type_quals == cp_type_quals (type))

439        return type;

440   

441      if (TREE_CODE (type) == ARRAY_TYPE)

442      {

         …

481      }

482      else if (TYPE_PTRMEMFUNC_P (type))

483      {

         …

493      }

494     

495     

497      if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)

498         && (TREE_CODE (type) == REFERENCE_TYPE

499              || TREE_CODE (type) == FUNCTION_TYPE

500              || TREE_CODE (type) == METHOD_TYPE))

501      {

502        bad_quals |= type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);

503        type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);

504      }

505     

506     

508      if ((type_quals & TYPE_QUAL_RESTRICT)

509          && TREE_CODE (type) != TEMPLATE_TYPE_PARM

510          && TREE_CODE (type) != TYPENAME_TYPE

511           && !POINTER_TYPE_P (type))

512      {

513        bad_quals |= TYPE_QUAL_RESTRICT;

514        type_quals &= ~TYPE_QUAL_RESTRICT;

515      }

516   

517      if (bad_quals == TYPE_UNQUALIFIED)

518        ;

519      else if (!(complain & (tf_error | tf_ignore_bad_quals)))

520        return error_mark_node;

521      else

522      {

523        if (complain & tf_ignore_bad_quals)

524         

526          bad_quals &= ~TYPE_QUAL_CONST;

527        if (bad_quals)

528        {

529          tree bad_type = build_qualified_type (ptr_type_node, bad_quals);

530   

531          if (!(complain & tf_ignore_bad_quals))

532            error ("`%V' qualifiers cannot be applied to `%T'",

533                 bad_type, type);

534        }

535      }

536     

537     

538      result = build_qualified_type (type, type_quals);

539   

540     

544      if (result != type

545         && TREE_CODE (type) == POINTER_TYPE

546         && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)

547        TYPE_LANG_SPECIFIC (result) = NULL;

548   

549      return result;

550    }

注意到 438 行,如果類型所傳回的 cv-qualifier 标記與期望的 cv-qualifier 相同,那個參數就是我們要的。不過,在這裡 type 指向原始的“ Host ”,“ const Host ”的節點需要由 build_qualified_type 來建構。那麼得到如下的中間樹:

( 點此打開 )

圖 77 :建構的 cv-qualified 參數

處理了 decl-specifier-seq 部分後,可以把這個 type-specifier 應用到聲明符上。下面的 WHILE 循環體逐個處理構成聲明符的連結清單節點,連結清單中的第一個節點在 TREE_PURPOSE 域儲存了指定的屬性。例如:“ void func (const int) const ; ”第二個“ const ”是聲明符“ func ”的屬性,并且到達此處。并且在這個語句中, type 應該指向“ func ”的傳回類型,是以 attr_flags 的域 ATTR_FLAG_FUNCTION_NEXT 被設定,它使得屬性“ const ”在 decl_attributes 中不經過安裝而被傳回。

grokdeclarator (continue)

7339    

7342  

7343     while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE

7344          && TREE_CODE (declarator) != TEMPLATE_ID_EXPR)

7345     {

          …

7392       switch (TREE_CODE (declarator))

7393       {

7394         case TREE_LIST:

7395         {

7396          

7398           tree attrs = TREE_PURPOSE (declarator);

7399           tree inner_decl;

7400           int attr_flags;

7401  

7402           declarator = TREE_VALUE (declarator);

7403           inner_decl = declarator;

7404           while (inner_decl != NULL_TREE

7405                 && TREE_CODE (inner_decl) == TREE_LIST)

7406             inner_decl = TREE_VALUE (inner_decl);

7407           attr_flags = 0;

7408           if (inner_decl == NULL_TREE

7409               || TREE_CODE (inner_decl) == IDENTIFIER_NODE)

7410             attr_flags |= (int) ATTR_FLAG_DECL_NEXT;

7411           if (TREE_CODE (inner_decl) == CALL_EXPR)

7412             attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;

7413           if (TREE_CODE (inner_decl) == ARRAY_REF)

7414             attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;

7415           returned_attrs = decl_attributes (&type,

7416                                      chainon (returned_attrs, attrs),

7417                                      attr_flags);

7418         }

7419         break ;

           …

7605         case ADDR_EXPR:

7606         case INDIRECT_REF:

7607          

7609  

7610           if (TREE_CODE (type) == REFERENCE_TYPE)

7611           {

7612             error (TREE_CODE (declarator) == ADDR_EXPR

7613                  ? "cannot declare reference to `%#T'"

7614                  : "cannot declare pointer to `%#T'", type);

7615             type = TREE_TYPE (type);

7616           }

7617           else if (VOID_TYPE_P (type)

7618                 && (ctype || TREE_CODE (declarator) == ADDR_EXPR))

7619             error (ctype ? "cannot declare pointer to `%#T' member"

7620                  : "cannot declare reference to `%#T'", type);

7621  

7622          

7624  

7625          

7627           type_quals = TYPE_UNQUALIFIED;

7628  

7629           if (TREE_CODE (declarator) == ADDR_EXPR)

7630           {

7631             if (!VOID_TYPE_P (type))

7632               type = build_reference_type (type);

7633           }

7634           else if (TREE_CODE (type) == METHOD_TYPE)

7635             type = build_ptrmemfunc_type (build_pointer_type (type));

7636           else if (ctype)

7637             type = build_ptrmem_type (ctype, type);

7638           else

7639             type = build_pointer_type (type);

7640  

7641          

7643  

7644           if (TREE_TYPE (declarator))

7645            {

7646             tree typemodlist;

7647             int erred = 0;

7648             int constp = 0;

7649             int volatilep = 0;

7650             int restrictp = 0;

7651             

7652             for (typemodlist = TREE_TYPE (declarator); typemodlist;

7653                 typemodlist = TREE_CHAIN (typemodlist))

7654             {

7655               tree qualifier = TREE_VALUE (typemodlist);

7656  

7657               if (qualifier == ridpointers [(int) RID_CONST])

7658               {

7659                 constp++;

7660                 type_quals |= TYPE_QUAL_CONST;

7661               }

7662               else if (qualifier == ridpointers [(int) RID_VOLATILE])

7663               {

7664                 volatilep++;

7665                 type_quals |= TYPE_QUAL_VOLATILE;

7666               }

7667               else if (qualifier == ridpointers [(int) RID_RESTRICT])

7668               {

7669                 restrictp++;

7670                 type_quals |= TYPE_QUAL_RESTRICT;

7671               }

7672               else if (!erred)

7673               {

7674                 erred = 1;

7675                 error ("invalid type modifier within pointer declarator");

7676               }

7677             }

7678             if (constp > 1)

7679               pedwarn ("duplicate `const'");

7680             if (volatilep > 1)

7681               pedwarn ("duplicate `volatile'");

7682             if (restrictp > 1)

7683               pedwarn ("duplicate `restrict'");

7684             type = cp_build_qualified_type (type, type_quals);

7685             type_quals = cp_type_quals (type);

7686            }

7687           declarator = TREE_OPERAND (declarator, 0);

7688           ctype = NULL_TREE;

7689           break ;

             ...

7839         }

7840       }

看到上面的 7402 行,從 declarator 擷取了 ADDR_EXPR 節點,并且由于 type 指向“ const Host ”,語言所期盼的 REFERENCE_TYPE 節點被産生出來。注意到在 declarator 中,域 TREE_TYPE 記錄了 cv-qualifier 如果有的話。例如:“ const int * const a; ”第二個“ const ”将出現在這裡,它限定了聲明符“ a ”。并且看到對于這個例子,在 7684 行的 type 代表“ const int* ”,而這個類型的常量版本(即“ const int* const ”)由 cp_build_qualified_type 建構(它隻是 cp_build_qualified_type_real 的簡單的封裝)。

這裡因為是“ const Host& ”,是以 declarator 的 TREE_TYPE 域是 NULL_TREE 。連同新建構的節點,中間樹看起來如下:

( 點此打開 )

圖 78 :建構的引用節點

現在 type 指向剛建立的 REFERENCE_TYPE 節點。而 declarator 被更新為 ADDR_EXPR 節點的第一個操作數,這裡它是 NULL_TREE 。

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       }

          …

8570       return decl;

8571     }

8572   }

那麼在下圖中的 PARM_DECL 節點由 grokdeclarator 傳回。下面的 decl 正好指向這個建立的 PARM_DECL 節點。

( 點此打開 )

圖 79 :建構的 PARM_DECL 節點

grokparms (continue)

8762       if (attrs)

8763         cplus_decl_attributes (&decl, attrs, 0);

8764  

8765       type = TREE_TYPE (decl);

8766       if (VOID_TYPE_P (type))

8767       {

8768         if (same_type_p (type, void_type_node)

8769            && !DECL_NAME (decl) && !result && !chain && !ellipsis)

8770          

8771           break ;

8772         cxx_incomplete_type_error (decl, type);

8773        

8776         type = error_mark_node;

8777         TREE_TYPE (decl) = error_mark_node;

8778       }

8779  

8780       if (type != error_mark_node)

8781       {

8782        

8784         type = cp_build_qualified_type (type, 0);

8785         if (TREE_CODE (type) == METHOD_TYPE)

8786         {

8787           error ("parameter `%D' invalidly declared method type", decl);

8788           type = build_pointer_type (type);

8789           TREE_TYPE (decl) = type;

8790         }

8791         else if (abstract_virtuals_error (decl, type))

8792            any_error = 1; 

8793         else if (POINTER_TYPE_P (type))

8794         {

8795          

8797           tree t = TREE_TYPE (type);

8798           int ptr = TYPE_PTR_P (type);

8799  

8800           while (1)

8801           {

8802             if (TYPE_PTR_P (t))

8803               ptr = 1;

8804             else if (TREE_CODE (t) != ARRAY_TYPE)

8805               break ;

8806             else if (!TYPE_DOMAIN (t))

8807               break ;

8808             t = TREE_TYPE (t);

8809           }

8810           if (TREE_CODE (t) == ARRAY_TYPE)

8811             error ("parameter `%D' includes %s to array of unknown bound `%T'",

8812                   decl, ptr ? "pointer" : "reference", t);

8813         }

8814  

8815         if (!any_error && init)

8816           init = check_default_argument (decl, init);

8817         else

8818           init = NULL_TREE;

8819       }

8820  

8821       TREE_CHAIN (decl) = decls;

8822       decls = decl;

8823       result = tree_cons (init, type, result);

8824     }

8825     decls = nreverse (decls);

8826     result = nreverse (result);

8827     if (!ellipsis)

8828       result = chainon (result, void_list_node);

8829     *parms = decls;

8830  

8831     return result;

8832   }

當為 identifier 擷取 decl 時,根據文法,它必須是一個辨別符或者 template-id 。再次考慮前一個例子:

typedef const int A;

void func(A&);

對于這個例子,在 8784 行的 type 将指向類型“ const int ”,不過“ const ”沒有出現在“ func ”的聲明中;為了産生函數聲明的正确的表示,沒有“ const ”需要被考慮。在 8784 行, cp_build_qualified_type 找出該類型的非限定版本。那麼在下圖中, result 及 parms 就是由 grokparms 傳回的。

( 點此打開 )

圖 80 : grokparms 由傳回的 result 及 parms

繼續閱讀