Studying note of GCC-3.4.6 source (104)
2010-09-20 11:49
288 查看
5.12.3.2.1.1.3.5.3.
Finish
With returned arg_types
and parms
,
at line 7601 in grokdeclarator
, build_function_type
creates
node of FUNCTION_TYPE as following.
(Click
here for open
)
Figure 81
:
FUNCTION_TYPE created
Now nodes
related to CALL_EXPR are useless, as no reference to CALL_EXPR node. Then at
line 8240 in grokdeclarator
,
build_method_type_directly
creates node of METHOD_TYPE as following.
(Click
here for open
)
Figure 82
:
METHOD_TYPE created
Immediately at
line 8250 in grokdeclarator
,
grokfndecl
creates node of FUNCTION_DECL as below.
(Click
here for open
)
Figure 83
:
FUNCTION_DECL created
When returns
back start_method
,
after pushing corresponding nodes of template declaration, it gets following
intermediate tree.
(Click
here for open
)
Figure 84
:
TEMPLATE_DECL created
Next at line 11087 in start_method
and within grok_special_member_properties
,
copy_fn_p
returns value to indicate the characteristics of the constructor or assignment
operator.
Assuming D is a constructor or overloaded `operator='. Let T be the
class in which D is declared. Then, this function returns:
-1, if D's is an ill-formed constructor or copy assignment operator whose
first parameter is of type `T'.
0, if D is not a copy constructor or copy assignment operator.
1, if D is a copy constructor or copy assignment operator whose
first parameter is a reference to const qualified T.
2, if D is a copy constructor or copy assignment operator whose
first parameter is a reference to non-const qualified T.
8853
int
8854
copy_fn_p
(tree d)
in decl.c
8855
{
8856
tree args;
8857
tree arg_type;
8858
int result = 1;
8859
8860
my_friendly_assert
(DECL_FUNCTION_MEMBER_P (d), 20011208);
8861
8862
if (DECL_TEMPLATE_INFO (d) &&
is_member_template (DECL_TI_TEMPLATE (d)))
8863
/*
Instantiations of template member functions are never copy
8864
functions. Note that member functions of templated classes are
8865
represented as template functions
internally, and we must
8866
accept those as copy functions.
*/
8867
return
0;
8868
8869
args = FUNCTION_FIRST_USER_PARMTYPE
(d);
8870
if (!args)
8871
return
0;
8872
8873
arg_type = TREE_VALUE
(args);
8874
8875
if (TYPE_MAIN_VARIANT
(arg_type) == DECL_CONTEXT (d))
8876
{
8877
/*
Pass by value copy assignment operator.
*/
8878
result = -1;
8879
}
8880
else if (TREE_CODE
(arg_type) == REFERENCE_TYPE
8881
&&
TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)) == DECL_CONTEXT (d))
8882
{
8883
if (CP_TYPE_CONST_P
(TREE_TYPE (arg_type)))
8884
result = 2;
8885
}
8886
else
8887
return
0;
8888
8889
args = TREE_CHAIN (args);
8890
8891
if (args && args !=
void_list_node && !TREE_PURPOSE (args))
8892
/*
There are more non-optional args.
*/
8893
return
0;
8894
8895
return
result;
8896
}
No doubt, for our copy constructor, result will be 0, as the
parameter is not of type “Lock”. So nothing is done in grok_special_member_properties
.
5.12.3.2.1.1.3.1.
Finish
parsing
After parsing the non-default constructor, we come to the end of the
class. It must be “};” to ending the definition. As GNU extension allows
declaring attributes for the class after token “}” and before “;”, it needs try
parsing this optional attributes.
cp_parser_class_specifier (continue)
11913
cp_parser_require
(parser, CPP_CLOSE_BRACE, "`}'");
11914
/*
We get better error messages by noticing a common problem: a
11915
missing trailing `;'.
*/
11916
token = cp_lexer_peek_token
(parser->lexer);
11917
has_trailing_semicolon =
(token->type == CPP_SEMICOLON);
11918
/*
Look for trailing attributes to apply to this class.
*/
11919
if
(cp_parser_allow_gnu_extensions_p (parser))
11920
{
11921
tree sub_attr =
cp_parser_attributes_opt (parser);
11922
attributes = chainon
(attributes, sub_attr);
11923
}
11924
if (type !=
error_mark_node)
11925
type = finish_struct
(type, attributes);
11926
if (pop_p)
11927
pop_scope (scope);
If everything runs smoothly, it can finialize the parsing of the
class, and install the attributes for the class at the same time.
5228
tree
5229
finish_struct
(tree t, tree attributes)
in class.c
5230
{
5231
location_t saved_loc = input_location
;
5232
5233
/* Now that we've
got all the field declarations, reverse everything
5234
as necessary.
*/
5235
unreverse_member_declarations
(t);
5236
5237
cplus_decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
5238
5239
/* Nadger the
current location so that diagnostics point to the start of
5240
the struct, not the end.
*/
5241
input_location
= DECL_SOURCE_LOCATION (TYPE_NAME
(t));
As we have seen before, the nodes for declarator of the methods are
chained in the reverse order of the declaration, so it now restore the order
back now by reversing again.
5197
void
5198
unreverse_member_declarations
(tree t)
in class.c
5199
{
5200
tree next;
5201
tree prev;
5202
tree x;
5203
5204
/* The following
lists are all in reverse order. Put them in
5205
declaration order now.
*/
5206
TYPE_METHODS (t) = nreverse (TYPE_METHODS
(t));
5207
CLASSTYPE_DECL_LIST (t) = nreverse
(CLASSTYPE_DECL_LIST (t));
5208
5209
/* Actually, for
the TYPE_FIELDS, only the non TYPE_DECLs are in
5210
reverse order, so we can't
just use nreverse.
*/
5211
prev = NULL_TREE;
5212
for
(x =
TYPE_FIELDS (t);
5213
x && TREE_CODE (x) != TYPE_DECL;
5214
x = next)
5215
{
5216
next = TREE_CHAIN (x);
5217
TREE_CHAIN (x) = prev;
5218
prev = x;
5219
}
5220
if (prev)
5221
{
5222
TREE_CHAIN (TYPE_FIELDS (t)) = x;
5223
if (prev)
5224
TYPE_FIELDS (t) = prev;
5225
}
5226
}
At line 5237, cplus_decl_attributes
installs the optional
attributes of the class, for the struct Lock, class level attribute is absent.
finish_struct (continue)
5243
if (processing_template_decl
)
5244
{
5245
finish_struct_methods
(t);
5246
TYPE_SIZE (t) = bitsize_zero_node;
5247
TYPE_SIZE_UNIT (t) = size_zero_node;
5248
}
5249
else
5250
finish_struct_1 (t);
5251
5252
input_location
= saved_loc;
5253
5254
TYPE_BEING_DEFINED (t) = 0;
5255
5256
if (current_class_type
)
5257
popclass
();
5258
else
5259
error ("trying to finish struct, but
kicked out due to previous parse errors");
5260
5261
if (processing_template_decl
&& at_function_scope_p ())
5262
add_stmt
(build_min (TAG_DEFN, t));
5263
5264
return
t;
5265
}
If we are handling class-template, the details of the class which
will be determined at point of instantiation (for example, if it inherits from
a class-template, the derivation can only be known at point of instantiation).
So only limited operation needs be taken by finish_struct_methods
, and see that even the
size of the class is temperary declared as zero at line 5246 and 5247.
1718
static
void
1719
finish_struct_methods
(tree t)
in class.c
1720
{
1721
tree fn_fields;
1722
tree method_vec;
1723
int slot, len;
1724
1725
if (!TYPE_METHODS (t))
1726
{
1727
/* Clear these
for safety; perhaps some parsing error could set
1728
these incorrectly.
*/
1729
TYPE_HAS_CONSTRUCTOR (t) = 0;
1730
TYPE_HAS_DESTRUCTOR (t) = 0;
1731
CLASSTYPE_METHOD_VEC (t) = NULL_TREE;
1732
return
;
1733
}
1734
1735
method_vec = CLASSTYPE_METHOD_VEC (t);
1736
my_friendly_assert (method_vec != NULL_TREE,
19991215);
1737
len = TREE_VEC_LENGTH (method_vec);
1738
1739
/* First fill in
entry 0 with the constructors, entry 1 with destructors,
1740
and the next few with type
conversion operators (if any).
*/
1741
for
(fn_fields = TYPE_METHODS (t); fn_fields;
1742
fn_fields = TREE_CHAIN (fn_fields))
1743
/* Clear out this
flag.
*/
1744
DECL_IN_AGGR_P (fn_fields) = 0;
1745
1746
if (TYPE_HAS_DESTRUCTOR (t) &&
!CLASSTYPE_DESTRUCTORS (t))
1747
/* We thought there was a destructor, but
there wasn't. Some
1748
parse errors cause this
anomalous situation.
*/
1749
TYPE_HAS_DESTRUCTOR (t) = 0;
1750
1751
/* Issue warnings
about private constructors and such. If there are
1752
no methods, then some public
defaults are generated.
*/
1753
maybe_warn_about_overly_private_class (t);
1754
1755
/* Now sort the
methods.
*/
1756
while
(len
> 2 && TREE_VEC_ELT (method_vec, len-1) == NULL_TREE)
1757
len--;
1758
TREE_VEC_LENGTH (method_vec) = len;
1759
1760
/* The type
conversion ops have to live at the front of the vec, so we
1761
can't sort them.
*/
1762
for
(slot =
2; slot < len; ++slot)
1763
{
1764
tree fn = TREE_VEC_ELT (method_vec, slot);
1765
1766
if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
1767
break
;
1768
}
1769
if (len - slot > 1)
1770
qsort (&TREE_VEC_ELT (method_vec,
slot), len-slot, sizeof
(tree),
1771
method_name_cmp);
1772
}
Seeing that this limited handling just includes correcting flags
incorrectly set by error statements encountered by parser. Sometimes, when
writing a simple class like “Lock” here, it may be mistakenly written as:
cass
Lock {
Lock();
Lock(const
Host&);
};
As it missing the access-specifier “public”, the constructors can’t
be invoked. The parser can give out warning about it. However, when the class
has friend, or has other public methods (static or non-static), it is diffcult
to tell whether the constructors can be invoked outside. The parser just
assumes that them can, and will issue error if them can’t be invoked later in
code. At line 1753, maybe_warn_about_overly_private_class
does
the checking.
And now all methods of the class are known, to accelerate the
searching speed for the method, the methods must be sorted so binary search can
be applied (line 1770).
Finish
With returned arg_types
and parms
,
at line 7601 in grokdeclarator
, build_function_type
creates
node of FUNCTION_TYPE as following.
(Click
here for open
)
Figure 81
:
FUNCTION_TYPE created
Now nodes
related to CALL_EXPR are useless, as no reference to CALL_EXPR node. Then at
line 8240 in grokdeclarator
,
build_method_type_directly
creates node of METHOD_TYPE as following.
(Click
here for open
)
Figure 82
:
METHOD_TYPE created
Immediately at
line 8250 in grokdeclarator
,
grokfndecl
creates node of FUNCTION_DECL as below.
(Click
here for open
)
Figure 83
:
FUNCTION_DECL created
When returns
back start_method
,
after pushing corresponding nodes of template declaration, it gets following
intermediate tree.
(Click
here for open
)
Figure 84
:
TEMPLATE_DECL created
Next at line 11087 in start_method
and within grok_special_member_properties
,
copy_fn_p
returns value to indicate the characteristics of the constructor or assignment
operator.
Assuming D is a constructor or overloaded `operator='. Let T be the
class in which D is declared. Then, this function returns:
-1, if D's is an ill-formed constructor or copy assignment operator whose
first parameter is of type `T'.
0, if D is not a copy constructor or copy assignment operator.
1, if D is a copy constructor or copy assignment operator whose
first parameter is a reference to const qualified T.
2, if D is a copy constructor or copy assignment operator whose
first parameter is a reference to non-const qualified T.
8853
int
8854
copy_fn_p
(tree d)
in decl.c
8855
{
8856
tree args;
8857
tree arg_type;
8858
int result = 1;
8859
8860
my_friendly_assert
(DECL_FUNCTION_MEMBER_P (d), 20011208);
8861
8862
if (DECL_TEMPLATE_INFO (d) &&
is_member_template (DECL_TI_TEMPLATE (d)))
8863
/*
Instantiations of template member functions are never copy
8864
functions. Note that member functions of templated classes are
8865
represented as template functions
internally, and we must
8866
accept those as copy functions.
*/
8867
return
0;
8868
8869
args = FUNCTION_FIRST_USER_PARMTYPE
(d);
8870
if (!args)
8871
return
0;
8872
8873
arg_type = TREE_VALUE
(args);
8874
8875
if (TYPE_MAIN_VARIANT
(arg_type) == DECL_CONTEXT (d))
8876
{
8877
/*
Pass by value copy assignment operator.
*/
8878
result = -1;
8879
}
8880
else if (TREE_CODE
(arg_type) == REFERENCE_TYPE
8881
&&
TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)) == DECL_CONTEXT (d))
8882
{
8883
if (CP_TYPE_CONST_P
(TREE_TYPE (arg_type)))
8884
result = 2;
8885
}
8886
else
8887
return
0;
8888
8889
args = TREE_CHAIN (args);
8890
8891
if (args && args !=
void_list_node && !TREE_PURPOSE (args))
8892
/*
There are more non-optional args.
*/
8893
return
0;
8894
8895
return
result;
8896
}
No doubt, for our copy constructor, result will be 0, as the
parameter is not of type “Lock”. So nothing is done in grok_special_member_properties
.
5.12.3.2.1.1.3.1.
Finish
parsing
After parsing the non-default constructor, we come to the end of the
class. It must be “};” to ending the definition. As GNU extension allows
declaring attributes for the class after token “}” and before “;”, it needs try
parsing this optional attributes.
cp_parser_class_specifier (continue)
11913
cp_parser_require
(parser, CPP_CLOSE_BRACE, "`}'");
11914
/*
We get better error messages by noticing a common problem: a
11915
missing trailing `;'.
*/
11916
token = cp_lexer_peek_token
(parser->lexer);
11917
has_trailing_semicolon =
(token->type == CPP_SEMICOLON);
11918
/*
Look for trailing attributes to apply to this class.
*/
11919
if
(cp_parser_allow_gnu_extensions_p (parser))
11920
{
11921
tree sub_attr =
cp_parser_attributes_opt (parser);
11922
attributes = chainon
(attributes, sub_attr);
11923
}
11924
if (type !=
error_mark_node)
11925
type = finish_struct
(type, attributes);
11926
if (pop_p)
11927
pop_scope (scope);
If everything runs smoothly, it can finialize the parsing of the
class, and install the attributes for the class at the same time.
5228
tree
5229
finish_struct
(tree t, tree attributes)
in class.c
5230
{
5231
location_t saved_loc = input_location
;
5232
5233
/* Now that we've
got all the field declarations, reverse everything
5234
as necessary.
*/
5235
unreverse_member_declarations
(t);
5236
5237
cplus_decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
5238
5239
/* Nadger the
current location so that diagnostics point to the start of
5240
the struct, not the end.
*/
5241
input_location
= DECL_SOURCE_LOCATION (TYPE_NAME
(t));
As we have seen before, the nodes for declarator of the methods are
chained in the reverse order of the declaration, so it now restore the order
back now by reversing again.
5197
void
5198
unreverse_member_declarations
(tree t)
in class.c
5199
{
5200
tree next;
5201
tree prev;
5202
tree x;
5203
5204
/* The following
lists are all in reverse order. Put them in
5205
declaration order now.
*/
5206
TYPE_METHODS (t) = nreverse (TYPE_METHODS
(t));
5207
CLASSTYPE_DECL_LIST (t) = nreverse
(CLASSTYPE_DECL_LIST (t));
5208
5209
/* Actually, for
the TYPE_FIELDS, only the non TYPE_DECLs are in
5210
reverse order, so we can't
just use nreverse.
*/
5211
prev = NULL_TREE;
5212
for
(x =
TYPE_FIELDS (t);
5213
x && TREE_CODE (x) != TYPE_DECL;
5214
x = next)
5215
{
5216
next = TREE_CHAIN (x);
5217
TREE_CHAIN (x) = prev;
5218
prev = x;
5219
}
5220
if (prev)
5221
{
5222
TREE_CHAIN (TYPE_FIELDS (t)) = x;
5223
if (prev)
5224
TYPE_FIELDS (t) = prev;
5225
}
5226
}
At line 5237, cplus_decl_attributes
installs the optional
attributes of the class, for the struct Lock, class level attribute is absent.
finish_struct (continue)
5243
if (processing_template_decl
)
5244
{
5245
finish_struct_methods
(t);
5246
TYPE_SIZE (t) = bitsize_zero_node;
5247
TYPE_SIZE_UNIT (t) = size_zero_node;
5248
}
5249
else
5250
finish_struct_1 (t);
5251
5252
input_location
= saved_loc;
5253
5254
TYPE_BEING_DEFINED (t) = 0;
5255
5256
if (current_class_type
)
5257
popclass
();
5258
else
5259
error ("trying to finish struct, but
kicked out due to previous parse errors");
5260
5261
if (processing_template_decl
&& at_function_scope_p ())
5262
add_stmt
(build_min (TAG_DEFN, t));
5263
5264
return
t;
5265
}
If we are handling class-template, the details of the class which
will be determined at point of instantiation (for example, if it inherits from
a class-template, the derivation can only be known at point of instantiation).
So only limited operation needs be taken by finish_struct_methods
, and see that even the
size of the class is temperary declared as zero at line 5246 and 5247.
1718
static
void
1719
finish_struct_methods
(tree t)
in class.c
1720
{
1721
tree fn_fields;
1722
tree method_vec;
1723
int slot, len;
1724
1725
if (!TYPE_METHODS (t))
1726
{
1727
/* Clear these
for safety; perhaps some parsing error could set
1728
these incorrectly.
*/
1729
TYPE_HAS_CONSTRUCTOR (t) = 0;
1730
TYPE_HAS_DESTRUCTOR (t) = 0;
1731
CLASSTYPE_METHOD_VEC (t) = NULL_TREE;
1732
return
;
1733
}
1734
1735
method_vec = CLASSTYPE_METHOD_VEC (t);
1736
my_friendly_assert (method_vec != NULL_TREE,
19991215);
1737
len = TREE_VEC_LENGTH (method_vec);
1738
1739
/* First fill in
entry 0 with the constructors, entry 1 with destructors,
1740
and the next few with type
conversion operators (if any).
*/
1741
for
(fn_fields = TYPE_METHODS (t); fn_fields;
1742
fn_fields = TREE_CHAIN (fn_fields))
1743
/* Clear out this
flag.
*/
1744
DECL_IN_AGGR_P (fn_fields) = 0;
1745
1746
if (TYPE_HAS_DESTRUCTOR (t) &&
!CLASSTYPE_DESTRUCTORS (t))
1747
/* We thought there was a destructor, but
there wasn't. Some
1748
parse errors cause this
anomalous situation.
*/
1749
TYPE_HAS_DESTRUCTOR (t) = 0;
1750
1751
/* Issue warnings
about private constructors and such. If there are
1752
no methods, then some public
defaults are generated.
*/
1753
maybe_warn_about_overly_private_class (t);
1754
1755
/* Now sort the
methods.
*/
1756
while
(len
> 2 && TREE_VEC_ELT (method_vec, len-1) == NULL_TREE)
1757
len--;
1758
TREE_VEC_LENGTH (method_vec) = len;
1759
1760
/* The type
conversion ops have to live at the front of the vec, so we
1761
can't sort them.
*/
1762
for
(slot =
2; slot < len; ++slot)
1763
{
1764
tree fn = TREE_VEC_ELT (method_vec, slot);
1765
1766
if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
1767
break
;
1768
}
1769
if (len - slot > 1)
1770
qsort (&TREE_VEC_ELT (method_vec,
slot), len-slot, sizeof
(tree),
1771
method_name_cmp);
1772
}
Seeing that this limited handling just includes correcting flags
incorrectly set by error statements encountered by parser. Sometimes, when
writing a simple class like “Lock” here, it may be mistakenly written as:
cass
Lock {
Lock();
Lock(const
Host&);
};
As it missing the access-specifier “public”, the constructors can’t
be invoked. The parser can give out warning about it. However, when the class
has friend, or has other public methods (static or non-static), it is diffcult
to tell whether the constructors can be invoked outside. The parser just
assumes that them can, and will issue error if them can’t be invoked later in
code. At line 1753, maybe_warn_about_overly_private_class
does
the checking.
And now all methods of the class are known, to accelerate the
searching speed for the method, the methods must be sorted so binary search can
be applied (line 1770).
相关文章推荐
- Studying note of GCC-3.4.6 source (137)
- Studying note of GCC-3.4.6 source (4)
- Studying note of GCC-3.4.6 source (10)
- Studying note of GCC-3.4.6 source (141)
- Studying note of GCC-3.4.6 source (148)
- Studying note of GCC-3.4.6 source (19)
- Studying note of GCC-3.4.6 source (161)
- Studying note of GCC-3.4.6 source (29)
- Studying note of GCC-3.4.6 source (34)
- Studying note of GCC-3.4.6 source (171)
- Studying note of GCC-3.4.6 source (178)
- Studying note of GCC-3.4.6 source (61)
- Studying note of GCC-3.4.6 source (79)
- Studying note of GCC-3.4.6 source (93)
- Studying note of GCC-3.4.6 source (106)
- Studying note of GCC-3.4.6 source (112)
- Studying note of GCC-3.4.6 source (118)
- Studying note of GCC-3.4.6 source (132)
- Studying note of GCC-3.4.6 source (140)
- Studying note of GCC-3.4.6 source (145)