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