GCC-3.4.6源代码学习笔记(92)

5.12.3.2.              解析模板声明的decl-specifier-seq部分

在解析过程中,我们可能会遇到错误的语句,为了尽可能的继续解析,最好前进到最近的“>”(显然,如果语句是正确的,下一个符号应该是“>”)。接下来为了解析如下类模板的成员模板函数:

 

template<class T> class string {

public:

template<class T2> int compare(const T2&);

template<class T2> string(const string<T2>& s) { /* ... */ }

// ...

};

template<class T> template<class T2> int string<T>::compare(const T2& s) {}

 

14458行检查方法的“template<class T2>”部分,并在14460处的递归对其进行处理。

 

cp_parser_template_declaration_after_export (continue)

 

14452   /* Look for the `>'.  */

14453   cp_parser_skip_until_found (parser, CPP_GREATER, "`>'");

14454   /* We just processed one more parameter list.  */

14455   ++parser->num_template_parameter_lists;

14456   /* If the next token is `template', there are more template

14457     parameters.  */

14458   if (cp_lexer_next_token_is_keyword (parser->lexer,

14459                                  RID_TEMPLATE))

14460     cp_parser_template_declaration_after_export (parser, member_p);

14461   else

14462   {

14463     decl = cp_parser_single_declaration (parser,

14464                                   member_p,

14465                                   &friend_p);

14466

14467     /* If this is a member template declaration, let the front

14468       end know.  */

14469     if (member_p && !friend_p && decl)

14470     {

14471       if (TREE_CODE (decl) == TYPE_DECL)

14472         cp_parser_check_access_in_redeclaration (decl);

14473

14474       decl = finish_member_template_decl (decl);

14475     }

14476     else if (friend_p && decl && TREE_CODE (decl) == TYPE_DECL)

14477       make_friend_class (current_class_type, TREE_TYPE (decl),

14478                       /*complain=*/true);

14479   }

 

在我们这个贯穿整章的例子的语句中,现在未解析的部分是“class SingleThreaded {…”,根据语法规则,它应该是decl-specifier-seqdecl-specifier-seq结构包含了decl-specifier序列,decl-specifier是如下的一个复杂结构。

 

 

14508 static tree

14509 cp_parser_single_declaration (cp_parser* parser,                                        in parser.c

14510                          bool member_p,

14511                          bool* friend_p)

14512 {

14513   int declares_class_or_enum;

14514   tree decl = NULL_TREE;

14515   tree decl_specifiers;

14516   tree attributes;

14517   bool function_definition_p = false;

14518

14519   /* This function is only used when processing a template

14520     declaration.  */

14521   if (innermost_scope_kind () != sk_template_parms

14522       && innermost_scope_kind () != sk_template_spec)

14523     abort ();

14524

14525   /* Defer access checks until we know what is being declared.  */

14526   push_deferring_access_checks (dk_deferred);

14527

14528   /* Try the `decl-specifier-seq [opt] init-declarator [opt]'

14529     alternative.  */

14530   decl_specifiers

14531     = cp_parser_decl_specifier_seq (parser,

14532                               CP_PARSER_FLAGS_OPTIONAL,

14533                               &attributes,

14534                               &declares_class_or_enum);

14535   if (friend_p)

14536     *friend_p = cp_parser_friend_p (decl_specifiers);

14537

14538   /* There are no template typedefs.  */

14539   if (cp_parser_typedef_p (decl_specifiers))

14540   {

14541     error ("template declaration of `typedef'");

14542    decl = error_mark_node;

14543   }

14544

14545   /* Gather up the access checks that occurred the

14546     decl-specifier-seq.  */

14547   stop_deferring_access_checks ();

 

在下面的函数中,如果declares_class_or_enum非空,*declares_class_or_enum被按位设置为以下标记:

1:其中一个decl-specifierselaborated-type-specifier(即一个类型声明)。

2:其中一个decl-specifiersenum-specifierclass-specifier(一个类型定义)。

 

6642 static tree

6643 cp_parser_decl_specifier_seq (cp_parser* parser,                                          in parser.c

6644                          cp_parser_flags flags,

6645                          tree* attributes,

6646                          int* declares_class_or_enum)

6647 {

6648   tree decl_specs = NULL_TREE;

6649   bool friend_p = false;

6650   bool constructor_possible_p = !parser->in_declarator_p;

6651  

6652   /* Assume no class or enumeration type is declared.  */

6653   *declares_class_or_enum = 0;

6654

6655   /* Assume there are no attributes.  */

6656   *attributes = NULL_TREE;

6657

6658  /* Keep reading specifiers until there are no more to read.  */

6659   while (true)

6660   {

6661     tree decl_spec = NULL_TREE;

6662     bool constructor_p;

6663     cp_token *token;

6664

6665     /* Peek at the next token.  */

6666     token = cp_lexer_peek_token (parser->lexer);

6667     /* Handle attributes.  */

6668     if (token->keyword == RID_ATTRIBUTE)

6669     {

6670       /* Parse the attributes.  */

6671       decl_spec = cp_parser_attributes_opt (parser);

6672       /* Add them to the list.  */

6673       *attributes = chainon (*attributes, decl_spec);

6674       continue;

6675     }

 

我们跳过上面的GCC扩展的属性。继续除type-specifier以外的decl-specifier的解析。 看到在这些项中friendfunction-specifiertypedefstorage-class-specifier都必须在后面跟有type-specifier注意break语句。局部变量decl_spec记录这些项的信息。

 

cp_parser_decl_specifier_seq (continue)

 

6676     /* If the next token is an appropriate keyword, we can simply

6677       add it to the list.  */

6678     switch (token->keyword)

6679     {

6680       case RID_FRIEND:

6681         /* decl-specifier:

6682           friend  */

6683         if (friend_p)

6684           error ("duplicate `friend'");

6685         else

6686           friend_p = true;

6687         /* The representation of the specifier is simply the

6688           appropriate TREE_IDENTIFIER node.  */

6689         decl_spec = token->value;

6690         /* Consume the token.  */

6691         cp_lexer_consume_token (parser->lexer);

6692         break;

6693

6694       /* function-specifier:

6695         inline

6696         virtual

6697         explicit  */

6698       case RID_INLINE:

6699       case RID_VIRTUAL:

6700       case RID_EXPLICIT:

6701         decl_spec = cp_parser_function_specifier_opt (parser);

6702         break;

6703    

6704       /* decl-specifier:

6705         typedef  */

6706       case RID_TYPEDEF:

6707         /* The representation of the specifier is simply the

6708           appropriate TREE_IDENTIFIER node.  */

6709         decl_spec = token->value;

6710         /* Consume the token.  */

6711         cp_lexer_consume_token (parser->lexer);

6712         /* A constructor declarator cannot appear in a typedef.  */

6713         constructor_possible_p = false;

6714         /* The "typedef" keyword can only occur in a declaration; we

6715           may as well commit at this point.  */

6716         cp_parser_commit_to_tentative_parse (parser);

6717         break;

6718

6719       /* storage-class-specifier:

6720         auto

6721         register

6722         static

6723         extern

6724         mutable 

6725

6726         GNU Extension:

6727         thread  */

6728       case RID_AUTO:

6729       case RID_REGISTER:

6730       case RID_STATIC:

6731       case RID_EXTERN:

6732       case RID_MUTABLE:

6733       case RID_THREAD:

6734         decl_spec = cp_parser_storage_class_specifier_opt (parser);

6735         break;

6736    

6737       default:

6738         break;

6739     }

 

例程cp_parser_function_specifier_optcp_parser_storage_class_specifier_opt只是再次确认以获取期望的符号。

C++中,decl-specifier-seq指出如何解释名字,而一个声明符(declarator)则在声明中声明了一个对象,函数或者类型。例如,考虑构造函数:

class A {

public:

   A();

};

在语句“A();”中,A不应该被按decl-specifier来解析,它不是声明,而是声明符。注意到A()simple-declaration的格式相符,它没有decl-specifier部分。因为它是一个特殊的情况,需要特殊的处理。显然,在解析声明符的过程中,这不是一个问题,注意到在6713行,constructor_possible_pparserin_declarator_p域的取反,在解析声明符的过程中,in_declarator_ptrue

 

cp_parser_decl_specifier_seq (continue)

 

6741     /* Constructors are a special case. The `S' in `S()' is not a

6742       decl-specifier; it is the beginning of the declarator.  */

6743     constructor_p = (!decl_spec

6744                   && constructor_possible_p

6745                   && cp_parser_constructor_declarator_p (parser,

6746                                                     friend_p));

 

同样注意到解析构造函数,不管成功与否,都不“消化”符号,因为构造函数不是decl-specifier而是声明符。而找到构造函数意味着错误。为了不至于离开我们的例子太远,我们暂时跳过对构造函数的解析。

5.12.3.2.1.        解析type-specifier

如果上面的情形都未能发现,那么现在我们可以在下面尝试按type-specifier解析之。Type-specifierdecl-specifier-seq的关键部分,它是声明的主体。

 

cp_parser_decl_specifier_seq (continue)

 

6748     /* If we don't have a DECL_SPEC yet, then we must be looking at

6749       a type-specifier.  */

6750     if (!decl_spec && !constructor_p)

6751     {

6752       int decl_spec_declares_class_or_enum;

6753       bool is_cv_qualifier;

6754

6755       decl_spec

6756          = cp_parser_type_specifier (parser, flags,

6757                                 friend_p,

6758                                 /*is_declaration=*/true,

6759                                 &decl_spec_declares_class_or_enum,

6760                                 &is_cv_qualifier);

6761

6762       *declares_class_or_enum |= decl_spec_declares_class_or_enum;

6763

6764        /* If this type-specifier referenced a user-defined type

6765          (a typedef, class-name, etc.), then we can't allow any

6766          more such type-specifiers henceforth.

6767

6768          [dcl.spec]

6769

6770          The longest sequence of decl-specifiers that could

6771          possibly be a type name is taken as the

6772          decl-specifier-seq of a declaration. The sequence shall

6773          be self-consistent as described below.

6774

6775          [dcl.type]

6776

6777          As a general rule, at most one type-specifier is allowed

6778          in the complete decl-specifier-seq of a declaration. The

6779          only exceptions are the following:

6780

6781          -- const or volatile can be combined with any other

6782            type-specifier.

6783

6784          -- signed or unsigned can be combined with char, long,

6785            short, or int.

6786

6787          -- ..

6788

6789          Example:

6790

6791            typedef char* Pc;

6792            void g (const int Pc);

6793

6794          Here, Pc is *not* part of the decl-specifier seq; it's

6795          the declarator. Therefore, once we see a type-specifier

6796          (other than a cv-qualifier), we forbid any additional

6797          user-defined types. We *do* still allow things like `int

6798          int' to be considered a decl-specifier-seq, and issue the

6799          error message later.  */

6800        if (decl_spec && !is_cv_qualifier)

6801          flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;

6802        /* A constructor declarator cannot follow a type-specifier.  */

6803        if (decl_spec)

6804          constructor_possible_p = false;

6805     }

 

type-specifier的简要语法树显示如下。

type-specifier

simple-type-specifier

├ class-specifier

├ enum-specifier

├ elaborated-type-specifier

├ cv-qualifier

GUN ext __complex__

在下面的函数中参数declares_class_or_enum如果非空并且type-specifier是一个class-specifierenum-specifier或者elaborated-type-specifier那么*declares_class_or_enum被设置为一个非0如果声明一个类型其值为1如果定义一个类型其值则为2。否则,它被设置为0。而如果is_cv_qualifier非空,并且type-specifier是一个cv-qualifier,那么*is_cv_qualifier被设为true,否则设为false

 

8713 static tree

8714 cp_parser_type_specifier (cp_parser* parser,                                                in parser.c

8715                      cp_parser_flags flags,

8716                      bool is_friend,

8717                      bool is_declaration,

8718                      int* declares_class_or_enum,

8719                      bool* is_cv_qualifier)

8720 {

8721   tree type_spec = NULL_TREE;

8722   cp_token *token;

8723   enum rid keyword;

8724

8725  /* Assume this type-specifier does not declare a new type.  */

8726   if (declares_class_or_enum)

8727     *declares_class_or_enum = 0;

8728   /* And that it does not specify a cv-qualifier.  */

8729   if (is_cv_qualifier)

8730     *is_cv_qualifier = false;

8731  /* Peek at the next token.  */

8732   token = cp_lexer_peek_token (parser->lexer);

8733

8734  /* If we're looking at a keyword, we can use that to guide the

8735     production we choose.  */

8736   keyword = token->keyword;

8737   switch (keyword)

8738   {

8739     case RID_ENUM:

            ...

8763     /* Any of these indicate either a class-specifier, or an

8764       elaborated-type-specifier.  */

8765     case RID_CLASS:

8766     case RID_STRUCT:

8767     case RID_UNION:

8768       /* Parse tentatively so that we can back up if we don't find a

8769         class-specifier or enum-specifier.  */

8770       cp_parser_parse_tentatively (parser);

8771       /* Look for the class-specifier.  */

8772       type_spec = cp_parser_class_specifier (parser);

8773       /* If that worked, we're done.  */

8774       if (cp_parser_parse_definitely (parser))

8775       {

8776         if (declares_class_or_enum)

8777           *declares_class_or_enum = 2;

8778         return type_spec;

8779       }

 

我们例子的第二条语句剩下的符号构成了class-specifier。它们进一步由cp_parser_class_specifier处理。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值