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