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         /* Declaring a function type.

7440           Make sure we have a valid type for the function to return.  */

7441  

7442         /* We now know that the TYPE_QUALS don't apply to the

7443           decl, but to its return type.  */

7444         type_quals = TYPE_UNQUALIFIED;

7445  

7446         /* Warn about some types functions can't return.  */

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         /* Pick up type qualifiers which should be applied to `this'.  */

7466         quals = CALL_DECLARATOR_QUALS (declarator);

7467  

7468         /* Pick up the exception specifications.  */

7469         raises = CALL_DECLARATOR_EXCEPTION_SPEC (declarator);

7470  

7471         /* Say it's a definition only for the CALL_EXPR

7472           closest to the identifier.  */

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            /* We are within a class's scope. If our declarator name

7490             is the same as the class name, and we are defining

7491             a function, then it is a constructor/destructor, and

7492             therefore returns a void type.  */

7493  

7494           if (flags == DTOR_FLAG)

7495           {

7496              /* ISO C++ 12.4/2. A destructor may not be

7497               declared const or volatile. A destructor may

7498                not be static.  */

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            /* It's a constructor.  */

7516           {

7517             if (explicitp == 1)

7518                explicitp = 2;

7519             /* ISO C++ 12.1. A constructor may not be

7520               declared const or volatile. A constructor may

7521               not be virtual. A constructor may not be

7522               static.  */

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             /* Cannot be both friend and virtual.  */

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          /* Construct the function type and go to the next

7577           inner layer of declarator.  */

7578  

7579         declarator = TREE_OPERAND (declarator, 0);

7580  

7581         arg_types = grokparms (inner_parms, &parms);

7582  

7583         if (declarator && flags == DTOR_FLAG)

7584         {

7585           /* A destructor declared in the body of a class will

7586             be represented as a BIT_NOT_EXPR. But, we just

7587             want the underlying IDENTIFIER.  */

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         /* ANSI says that `const int foo ();'

7600           does not make the function foo const.  */

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       /* @@ weak defense against parse errors.  */

8742       if (TREE_CODE (decl) != VOID_TYPE

8743          && TREE_CODE (decl) != TREE_LIST)

8744       {

8745         /* Give various messages as the need arises.  */

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     /* 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         {

6530           case TREE_LIST:

6531              /* For attributes.  */

6532             next = &TREE_VALUE (decl);

6533             break ;

              …

6582           case ADDR_EXPR:     /* C++ reference declaration */

6583           /* Fall through.  */

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     /* 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         {

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         /* C++ aggregate types.  */

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             /* Diagnose "__thread extern" or "__thread static".   */

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               /* This extern was part of a language linkage.  */

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         /* Can't change CLASS nodes into RECORD nodes here!  */

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     /* We might have ignored or rejected some of the qualifiers.  */

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      /* A reference, function or method type shall not be cv qualified.

496        [dcl.ref], [dct.fct]  */

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      /* A restrict-qualified type must be a pointer (or reference)

507        to object or incomplete type.  */

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        /*OK*/ ;

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          /* We're not going to warn about constifying things that can't

525            be constified.  */

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      /* Retrieve (or create) the appropriately qualified variant.  */

538      result = build_qualified_type (type, type_quals);

539   

540      /* If this was a pointer-to-method type, and we just made a copy,

541        then we need to unshare the record that holds the cached

542        pointer-to-member-function type, because these will be distinct

543        between the unqualified and qualified types.  */

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     /* Now figure out the structure of the declarator proper.

7340       Descend through it, creating more complex types, until we reach

7341       the declared identifier (or NULL_TREE, in an abstract declarator).  */

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           /* We encode a declarator with embedded attributes using

7397             a TREE_LIST.  */

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           /* Filter out pointers-to-references and references-to-references.

7608             We can get these if a TYPE_DECL is used.  */

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           /* Merge any constancy or volatility into the target type

7623             for the pointer.  */

7624  

7625           /* We now know that the TYPE_QUALS don't apply to the decl,

7626             but to the target of the pointer.  */

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           /* Process a list of type modifier keywords (such as

7642             const or volatile) that were given inside the `*' or `&'.  */

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           /* this is a parmlist of `(void)', which is ok.  */

8771           break ;

8772         cxx_incomplete_type_error (decl, type);

8773         /* It's not a good idea to actually create parameters of

8774           type `void'; other parts of the compiler assume that a

8775           void type terminates the parameter list.  */

8776         type = error_mark_node;

8777         TREE_TYPE (decl) = error_mark_node;

8778       }

8779  

8780       if (type != error_mark_node)

8781       {

8782         /* Top-level qualifiers on the parameters are

8783           ignored for function types.  */

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;  /* Seems like a good idea.  */

8793         else if (POINTER_TYPE_P (type))

8794         {

8795           /* [dcl.fct]/6, parameter types cannot contain pointers

8796             (references) to arrays of unknown bound.  */

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>