下面的 DECL_MAIN_P 返回非 0 值来表示遇到 “ main ”函数,对于该函数一些有趣的限制。看到 main 函数不能被声明为 inline ,而且永远是公有可访问的。
grokfndecl (continue)
5642 if (ctype == NULL_TREE && DECL_MAIN_P (decl))
5643 {
5644 if (processing_template_decl)
5645 error ("cannot declare `::main' to be a template");
5646 if (inlinep)
5647 error ("cannot declare `::main' to be inline");
5648 if (!publicp)
5649 error ("cannot declare `::main' to be static");
5650 if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
5651 integer_type_node))
5652 error ("`main' must return `int'");
5653 inlinep = 0;
5654 publicp = 1;
5655 }
5656
5657 /* Members of anonymous types and local classes have no linkage; make
5658 them internal. */
5659 /* FIXME what if it gets a name from typedef? */
5660 if (ctype && (TYPE_ANONYMOUS_P (ctype)
5661 || decl_function_context (TYPE_MAIN_DECL (ctype))))
5662 publicp = 0;
5663
5664 if (publicp)
5665 {
5666 /* [basic.link]: A name with no linkage (notably, the name of a class
5667 or enumeration declared in a local scope) shall not be used to
5668 declare an entity with linkage.
5669
5670 Only check this for public decls for now. See core 319, 389. */
5671 t = no_linkage_check (TREE_TYPE (decl));
5672 if (t)
5673 {
5674 if (TYPE_ANONYMOUS_P (t))
5675 {
5676 if (DECL_EXTERN_C_P (decl))
5677 /* Allow this; it's pretty common in C. */;
5678 else
5679 {
5680 pedwarn ("non-local function `%#D' uses anonymous type",
5681 decl);
5682 if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
5683 cp_pedwarn_at ("/
5684 `%#D' does not refer to the unqualified type, so it is not used for linkage",
5685 TYPE_NAME (t));
5686 }
5687 }
5688 else
5689 pedwarn ("non-local function `%#D' uses local type `%T'",
5690 decl, t);
5691 }
5692 }
5693
5694 TREE_PUBLIC (decl) = publicp;
...
5710 DECL_EXTERNAL (decl) = 1;
...
5870 if (ctype == NULL_TREE || check)
5871 return decl;
...
5877 }
【 3 】的 [basic.link] 一节给出了关于实体链接性的详细描述。
一个程序包含了一个或多个链接起来的编译单元。
一个名字被认为有链接性,当它可能代表,作为在另一个域中的声明所引入名字的,一个对象、引用、函数、类型、模板、名字空间或值:
— 当一个名字具有外部链接性时,其代表的实体可以被其他编译单元中的名字,或同一编译单元不同域中的名字所引用。
— 当一个名字具有内部链接性时,其代表的实体可以被同一编译单元不同域中的名字所引用。
— 当一个名字没有链接性时,其代表的实体不能被其他域中的名字所引用。
一个具有名字空间作用域( 3.3.5 )的名字具有内部链接性,如果它是如下的名字
— 一个显式声明为静态( static )的对象、引用、函数或函数模板,或者
— 一个显式声明为常量( const ),但没有声明为外部( extern ),或先前也没有声明为具有外部链接性的对象、引用;或者
— 匿名 union 的数据成员。
一个具有名字空间作用域的名字具有外部链接性,如果它是如下的名字
— 一个对象、引用,除非它具有内部链接性;或者
— 一个函数,除非它具有内部链接性;或者
— 一个具名类(条款 9 ),一个定义在 typedef 声明中的匿名类,在该声明中该类具有用于链接目的( 7.1.3 )的 typedef 名字;或者
— 一个具名枚举类型( 7.2 ),或者一个定义在 typedef 声明中的匿名枚举类型,在该声明中该枚举类型具有用于链接目的( 7.1.3 )的 typedef 名字;或者
— 一个从属域一个枚举类型的枚举值具有外部链接性;或者
— 一个模板,除非它是一个具有内部链接性(条款 14 )的函数模板;或者
— 一个名字空间( 7.3 ),除非它被声明在一个匿名名字空间中。
另外,类域中的成员函数、静态数据成员、类或枚举类型具有外部链接性,如果该类名具有外部链接性。
在一个块域中声明的函数名,及一个由块域中 extern 声明所声明的对象名,具有链接性。如果存在与一个具有链接性的实体的名字、类型相同的一个可见声明,忽略在最里层封闭名字空间作用域之外声明的实体,该块域中的声明声明了相同的实体,并且接受这个可见声明的链接性。如果存在多于一个匹配的实体,程序是错误的。否则,如果没有找到匹配的实体,块域中的实体接受外部链接性。【例如:
static void f();
static int i = 0; //1
void g() {
extern void f(); // internal linkage
int i; //2: i has no linkage
{
extern void f(); // internal linkage
extern int i; //3: external linkage
}
}
在这个程序中有 3 个对象被命名为 i 。具有内部链接性的对象被在全局作用域中的声明所引入(行 //1 ),具有自动存储周期且不具有链接性的对象由行 //2 的声明引入,而具有静态存储周期且具有外部链接性的对象由行 //3 的声明引入。】
当一个块域中一个具有链接性的实体没有发现引用其他声明,那么该实体是最里层封闭名字空间的一个成员。不过这样的声明不能在其名字空间作用域中引入成员名字。【例如:
namespace X {
void p() {
q(); //error: q not yet declared
extern void q(); // q is a member of namespace X
}
void middle() {
q(); //error: q not yet declared
}
void q() { /* ... */ } // definition of X::q
}
void q() { /* ... */ } // some other, unrelated q
不被这些规则所覆盖的名字不具有链接性。此外,除非另有说明,在一个局部域( 3.3.2 )中声明的名字不具有链接性。一个不具有链接性的名字(尤其是,在一个局部域中声明的一个类或枚举类型名)不应该用于声明一个具有链接性的实体。如果一个声明使用了一个 typedef 名,使用的链接性则来自 typedef 所引用的类型名【例如:
void f() {
struct A { int x; }; // no linkage
extern A a; // ill-formed
typedef A B;
extern B b; // ill-formed
}
这意味着不具有链接性的名字不能用作模板参数( 14.3 )。
两个相同的名字(条款 3 ),并且声明在不同的作用域中,应该代表相同的对象、引用、函数、类型、枚举类型、模板或名字空间,如果
— 两者具有外部链接性,或者两者具有内部链接性并声明在同一个编译单元中;而且
— 两者指向相同名字空间中的成员,或者同一个类的成员(不是通过继承);并且
— 当两者代表函数时,对于重载的目的,函数类型是相同的;并且
— 当两者代表函数模板,其签名( signatures 14.5.5.1 )是相同的。
在所有的类型调整之后(其中 typedef ( 7.1.3 )为其定义所替代),所有引用一个给定对象或函数的声明所指定的类型都应该相同,除了数组对象的声明可以指定有或没有主要数组边界( a major array bound 8.3.4 )的数组类型。对该规则的违反,不要求诊断。
在 5659 行的注释在 V4.3.0 中被移去,但没有改变代码。因为条款 8 (这个版本在这个规则被制定前完成)指出, typedef 名字应该遵循相同的规则;在前面关于处理 typedef 声明的章节中,我们可以看到有一个 TYPE_DECL 节点将为 typedef 声明所构建,并且将被置于同一个作用域中,代表被 typedef 的类型。随后当看到这个 typedef 名字时,我们使用这个 TYPE_DECL 节点,而且函数中的条件依然工作。在上面的 5661 行, decl_function_context 返回最里层的封闭函数作用域,如果没有这样的作用域返回 null 。
grokdeclarator (continue)
8550 my_friendly_assert (!RIDBIT_SETP (RID_MUTABLE, specbits), 19990927);
8551
8552 /* Record `register' declaration for warnings on &
8553 and in case doing stupid register allocation. */
8554
8555 if (RIDBIT_SETP (RID_REGISTER, specbits))
8556 DECL_REGISTER (decl) = 1;
8557
8558 if (RIDBIT_SETP (RID_EXTERN, specbits))
8559 DECL_THIS_EXTERN (decl) = 1;
8560
8561 if (RIDBIT_SETP (RID_STATIC, specbits))
8562 DECL_THIS_STATIC (decl) = 1;
8563
8564 /* Record constancy and volatility. There's no need to do this
8565 when processing a template; we'll do this for the instantiated
8566 declaration based on the type of DECL. */
8567 if (!processing_template_decl)
8568 c_apply_type_quals_to_decl (type_quals, decl);
8569
8570 return decl;
8571 }
8572 }
看到在下面 decl 被返回给 decl1 ,这是对应的 FUNCTION_DECL 。因此下面的 fntype 指向这个 FUNCTION_TYPE 节点,而 restype 指向 integer_type_node 节点。
start_function(continue)
10229 /* If the declarator is not suitable for a function definition,
10230 cause a syntax error. */
10231 if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
10232 return 0;
10233
10234 cplus_decl_attributes (&decl1, attrs, 0);
10235
10236 /* If #pragma weak was used, mark the decl weak now. */
10237 if (global_scope_p ( current_binding_level ))
10238 maybe_apply_pragma_weak (decl1);
10239
10240 fntype = TREE_TYPE (decl1);
10241
10242 restype = TREE_TYPE (fntype);
10243
10244 if (TREE_CODE (fntype) == METHOD_TYPE)
10245 ctype = TYPE_METHOD_BASETYPE (fntype);
10246 else if (DECL_MAIN_P (decl1))
10247 {
10248 /* If this doesn't return integer_type, or a typedef to
10249 integer_type, complain. */
10250 if (!same_type_p (TREE_TYPE (TREE_TYPE (decl1)), integer_type_node))
10251 {
10252 if (pedantic || warn_return_type )
10253 pedwarn ("return type for `main' changed to `int'");
10254 TREE_TYPE (decl1) = fntype = default_function_type;
10255 }
10256 }
10257 }
…
10306 /* Make the init_value nonzero so pushdecl knows this is not tentative.
10307 error_mark_node is replaced below (in poplevel) with the BLOCK. */
10308 if (!DECL_INITIAL (decl1))
10309 DECL_INITIAL (decl1) = error_mark_node;
10310
10311 /* This function exists in static storage.
10312 (This does not mean `static' in the C sense!) */
10313 TREE_STATIC (decl1) = 1;
…
10326 /* We are now in the scope of the function being defined. */
10327 current_function_decl = decl1;
10328
10329 /* Save the parm names or decls from this function's declarator
10330 where store_parm_decls will find them. */
10331 current_function_parms = DECL_ARGUMENTS (decl1);
10332
10333 /* Make sure the parameter and return types are reasonable. When
10334 you declare a function, these types can be incomplete, but they
10335 must be complete when you define the function. */
10336 if (!processing_template_decl )
10337 check_function_type (decl1, current_function_parms);
10338 /* Make sure no default arg is missing. */
10339 check_default_args (decl1);
现在对应的 FUNCTION_DECL 节点及相应的引用更新如下图。
对于我们的 “ main ” 函数 , check_function_type 只是检查参数类型及返回类型是否是完整的类型 ( 而不仅是声明 ) 。而 check_default_args 不做任何事情 , 因为我们没有缺省参数。
start_function(continue)
10341 /* Build the return declaration for the function. */
10342 restype = TREE_TYPE (fntype);
10343 /* Promote the value to int before returning it. */
10344 if (c_promoting_integer_type_p (restype))
10345 restype = type_promotes_to (restype);
10346 if (DECL_RESULT (decl1) == NULL_TREE)
10347 {
10348 DECL_RESULT (decl1)
10349 = build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
10350 c_apply_type_quals_to_decl (cp_type_quals (restype),
10351 DECL_RESULT (decl1));
10352 }
10353
10354 /* Initialize RTL machinery. We cannot do this until
10355 CURRENT_FUNCTION_DECL and DECL_RESULT are set up. We do this
10356 even when processing a template; this is how we get
10357 CFUN set up, and our per-function variables initialized.
10358 FIXME factor out the non-RTL stuff. */
10359 bl = current_binding_level;
10360 allocate_struct_function (decl1);
10361 current_binding_level = bl;
10362
10363 /* Even though we're inside a function body, we still don't want to
10364 call expand_expr to calculate the size of a variable-sized array.
10365 We haven't necessarily assigned RTL to all variables yet, so it's
10366 not safe to try to expand expressions involving them. */
10367 immediate_size_expand = 0;
10368 cfun ->x_dont_save_pending_sizes_p = 1;
10369
10370 /* Start the statement-tree, start the tree now. */
10371 begin_stmt_tree (&DECL_SAVED_TREE (decl1));
10372
10373 /* Let the user know we're compiling this function. */
10374 announce_function (decl1);
在 5.12.3.2.1.2.1.1.开始函数处理 一节中我们已经看过上面的函数,关于这些函数的细节参考该节内容。简而言之,在继续处理之前,我们得到以下子树。注:在该图中,“ (0) ”或“ (1) ”表示该域包含“ 0 ”或“ 1 ”,而“ [0] ”表示 tree_vec 的第 0 个成员,这个规则适用于所有的图形。
( 点此打开 )
start_function(continue)
10376 /* Record the decl so that the function name is defined.
10377 If we already have a decl for this name, and it is a FUNCTION_DECL,
10378 use the old decl. */
10379 if (!processing_template_decl && !(flags & SF_PRE_PARSED))
10380 {
10381 /* A specialization is not used to guide overload resolution. */
10382 if (!DECL_FUNCTION_MEMBER_P (decl1)
10383 && !(DECL_USE_TEMPLATE (decl1) &&
10384 PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl1))))
10385 {
10386 tree olddecl = pushdecl (decl1);
10387
10388 if (olddecl == error_mark_node)
10389 /* If something went wrong when registering the declaration,
10390 use DECL1; we have to have a FUNCTION_DECL to use when
10391 parsing the body of the function. */
10392 ;
10393 else
10394 /* Otherwise, OLDDECL is either a previous declaration of
10395 the same function or DECL1 itself. */
10396 decl1 = olddecl;
10397 }
10398 else
10399 {
10400 /* We need to set the DECL_CONTEXT. */
10401 if (!DECL_CONTEXT (decl1) && DECL_TEMPLATE_INFO (decl1))
10402 DECL_CONTEXT (decl1) = DECL_CONTEXT (DECL_TI_TEMPLATE (decl1));
10403 }
10404 fntype = TREE_TYPE (decl1);
10405 }
10406
10407 /* Reset these in case the call to pushdecl changed them. */
10408 current_function_decl = decl1;
10409 cfun ->decl = decl1;
因为在 10327 行, current_function_decl 指向 decl1 ,而 main 函数在全局名字空间中是新定义, pushdecl 把对应的 FUNCTION_DECL 链接入全局名字空间的 cxx_scope 节点的 name 域。在 10386 行, olddecl 与 decl1 相同。
start_function(continue)
10411 /* If we are (erroneously) defining a function that we have already
10412 defined before, wipe out what we knew before. */
10413 if (!DECL_PENDING_INLINE_P (decl1))
10414 DECL_SAVED_FUNCTION_DATA (decl1) = NULL;
10415
10416 if (ctype && !doing_friend && !DECL_STATIC_FUNCTION_P (decl1))
10417 {
...
10447 }
10448
10449 if (DECL_INTERFACE_KNOWN (decl1))
10450 {
...
10461 }
10462 /* If this function belongs to an interface, it is public.
10463 If it belongs to someone else's interface, it is also external.
10464 This only affects inlines and template instantiations. */
10465 else if (interface_unknown == 0
10466 && ! DECL_TEMPLATE_INSTANTIATION (decl1))
10467 {
...
10485 }
10486 else if (interface_unknown && interface_only
10487 && ! DECL_TEMPLATE_INSTANTIATION (decl1))
10488 {
...
10498 }
10499 else
10500 {
10501 /* This is a definition, not a reference.
10502 So clear DECL_EXTERNAL. */
10503 DECL_EXTERNAL (decl1) = 0;
10504
10505 if ((DECL_DECLARED_INLINE_P (decl1)
10506 || DECL_TEMPLATE_INSTANTIATION (decl1))
10507 && ! DECL_INTERFACE_KNOWN (decl1)
10508 /* Don't try to defer nested functions for now. */
10509 && ! decl_function_context (decl1))
10510 DECL_DEFER_OUTPUT (decl1) = 1;
10511 else
10512 DECL_INTERFACE_KNOWN (decl1) = 1;
10513 }
10514
10515 begin_scope (sk_function_parms, decl1);
10516
10517 ++function_depth ;
10518
10519 if (DECL_DESTRUCTOR_P (decl1))
10520 {
10521 dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
10522 DECL_CONTEXT (dtor_label) = current_function_decl ;
10523 }
10524
10525 start_fname_decls ();
10526
10527 store_parm_decls (current_function_parms);
10528
10529 return 1;
10530 }
当我们从 start_function , 返回时,我们得到以下的节点。
( 点此打开 )