Studying note of GCC-3.4.6 source (152)
来源:互联网 发布:sql substr 编辑:程序博客网 时间:2024/06/08 00:01
5.12.5.2.2.2.2. Default arguments
If argexhausted, but parmdoesn’t, parmmust contain default arguments, for which the list should be terminated by thespecial void_list_node.Then in corresponding node, TREE_VALUE holds the type, and TREE_PURPOSE is theexpression of the default argument.
4258 tree
4259 convert_default_arg (tree type, tree arg, tree fn, int parmnum) in call.c
4260 {
4261 /*If the ARG is an unparsed default argument expression, the
4262 conversion cannot be performed. */
4263 if (TREE_CODE (arg) ==DEFAULT_ARG)
4264 {
4265 error ("the defaultargument for parameter %d of `%D' has "
4266 "not yet beenparsed",
4267 parmnum, fn);
4268 returnerror_mark_node;
4269 }
4270
4271 if (fn &&DECL_TEMPLATE_INFO (fn))
4272 arg =tsubst_default_argument (fn, type, arg);
4273
4274 arg = break_out_target_exprs (arg);
4275
4276 if (TREE_CODE (arg) ==CONSTRUCTOR)
4277 {
4278 arg = digest_init(type, arg, 0);
4279 arg =convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
4280 "defaultargument", fn, parmnum);
4281 }
4282 else
4283 {
4284 /*This could get clobbered by the following call. */
4285 if (TREE_HAS_CONSTRUCTOR(arg))
4286 arg = copy_node (arg);
4287
4288 arg =convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
4289 "defaultargument", fn, parmnum);
4290 arg = convert_for_arg_passing (type, arg);
4291 }
4292
4293 returnarg;
4294 }
Node of DEFAULT_ARG is created for unparsed default argument.Remember during parsing class definition, any default argument is cached byDEFAULT_ARG, which will be parsed after the parsing. So DEFAULT_ARG should notbe present here (if so, it may be missing “};” in the class definition), and atthis point, the front-end doesn’t know how to handle node of this kind.
Then argpassed for below function at line 4274, is the default argument shared by allinvocations of the function. However, as [3] defines, “Default arguments are evaluated each time thefunction is called”, so before really evaluate the expression of thedefault argument, it needs prepare appropriate copy of arg and update this localtemparories acclaimed as below.
1259 tree
1260 break_out_target_exprs (tree t) incp/tree.c
1261 {
1262 staticint target_remap_count;
1263 staticsplay_tree target_remap;
1264
1265 if (!target_remap_count++)
1266 target_remap =splay_tree_new (splay_tree_compare_pointers,
1267 /*splay_tree_delete_key_fn=*/NULL,
1268 /*splay_tree_delete_value_fn=*/NULL);
1269 walk_tree(&t, bot_manip, target_remap, NULL);
1270 walk_tree(&t, bot_replace, target_remap, NULL);
1271
1272 if (!--target_remap_count)
1273 {
1274 splay_tree_delete(target_remap);
1275 target_remap = NULL;
1276 }
1277
1278 returnt;
1279 }
Above walk_tree traverses the subtree rooted by t andexecutes provided function upon nodes selected by the code of t. Infirst traversal, below function is used. Note that the function always returnsNULL (copy_tree_rbelow returns NULL) to force walk_tree to do full traversal with depthfirst (i.e. tpmaybe a tree_list, in which node can contain operands which in turn can betree_list again and so on, the visit should be from bottom up); however whetherstepping into the sub-tree (i.e. operand) is controlled by local variable walk_subtrees(which is passes as argument walk_subtrees in below function). Beforeprocessing the tree node with the specified function, walk_subtrees is set as 1; it isthe specified function to decide whether the node is of interesting and needsto be stepped into if no result gotten.
1182 static tree
1183 bot_manip (tree* tp, int* walk_subtrees, void* data) in cp/tree.c
1184 {
1185 splay_tree target_remap =((splay_tree) data);
1186 tree t = *tp;
1187
1188 if (TREE_CONSTANT (t))
1189 {
1190 /*There can't be any TARGET_EXPRs or their slot variables below
1191 thispoint. We used to check !TREE_SIDE_EFFECTS, but then we
1192 failed to copy an ADDR_EXPR of the slotVAR_DECL. */
1193 *walk_subtrees = 0;
1194 returnNULL_TREE;
1195 }
1196 if (TREE_CODE (t) ==TARGET_EXPR)
1197 {
1198 tree u;
1199
1200 if (TREE_CODE(TREE_OPERAND (t, 1)) == AGGR_INIT_EXPR)
1201 {
1202 mark_used(TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 1), 0), 0));
1203 u = build_cplus_new
1204 (TREE_TYPE (t),break_out_target_exprs (TREE_OPERAND (t, 1)));
1205 }
1206 else
1207 {
1208 u = build_target_expr_with_type
1209 (break_out_target_exprs (TREE_OPERAND (t,1)), TREE_TYPE (t));
1210 }
1211
1212 /* Map the old variable to the new one. */
1213 splay_tree_insert(target_remap,
1214 (splay_tree_key)TREE_OPERAND (t, 0),
1215 (splay_tree_value)TREE_OPERAND (u, 0));
1216
1217 /*Replace the old expression with the new version. */
1218 *tp = u;
1219 /*We don't have to go below this point; the recursive call to
1220 break_out_target_exprs will have handledanything below this
1221 point. */
1222 *walk_subtrees = 0;
1223 returnNULL_TREE;
1224 }
1225 else if (TREE_CODE (t) ==CALL_EXPR)
1226 mark_used(TREE_OPERAND (TREE_OPERAND (t, 0), 0));
1227
1228 /*Make a copy of this node. */
1229 returncopy_tree_r (tp, walk_subtrees, NULL);
1230 }
For node other than constant or TRAGET_EXPR, copy_tree_r copies the nodeif it is either *_CST (see it is filtered out by TREE_CONSTANT above) orexpression or TREE_LIST or TREE_VEC or OVERLOAD (told by C++ hook of tree_chain_matters_pbelow, and note that walk_subtrees is unchanged here, walk_treewill step into the sub-nodes of the node and continues copying the structureaccordingly).
1966 tree
1967 copy_tree_r (tree *tp, int*walk_subtrees, void *data ATTRIBUTE_UNUSED) in tree-inline.c
1968 {
1969 enumtree_code code = TREE_CODE (*tp);
1970
1971 /* We make copies of most nodes. */
1972 if (IS_EXPR_CODE_CLASS(TREE_CODE_CLASS (code))
1973 || TREE_CODE_CLASS(code) == 'c'
1974 || code == TREE_LIST
1975 || code == TREE_VEC
1976 || (*lang_hooks.tree_inlining.tree_chain_matters_p)(*tp))
1977 {
1978 /* Because the chain gets clobbered when wemake a copy, we save it
1979 here. */
1980 tree chain = TREE_CHAIN(*tp);
1981
1982 /*Copy the node. */
1983 *tp = copy_node (*tp);
1984
1985 /*Now, restore the chain, if appropriate. That will cause
1986 walk_tree to walk into the chain aswell. */
1987 if (code == PARM_DECL ||code == TREE_LIST
1988 #ifndef INLINER_FOR_JAVA
1989 || (*lang_hooks.tree_inlining.tree_chain_matters_p)(*tp)
1990 || STATEMENT_CODE_P (code))
1991 TREE_CHAIN (*tp) = chain;
1992
1993 /* For now, we don't update BLOCKs when wemake copies. So, we
1994 haveto nullify all scope-statements. */
1995 if (TREE_CODE (*tp) ==SCOPE_STMT)
1996 SCOPE_STMT_BLOCK (*tp) =NULL_TREE;
1997 #else/* INLINER_FOR_JAVA */
1998 || (*lang_hooks.tree_inlining.tree_chain_matters_p)(*tp))
1999 TREE_CHAIN (*tp) =chain;
2000 #endif /*INLINER_FOR_JAVA */
2001 }
2002 else if (TREE_CODE_CLASS(code) == 't')
2003 *walk_subtrees = 0;
2004
2005 returnNULL_TREE;
2006 }
A TARGET_EXPR represents a temporary object. The first operand is aVAR_DECL for the temporary variable. The second operand is the initializer forthe temporary. The initializer is evaluated, and copied (bitwise) into thetemporary.
An AGGR_INIT_EXPR represents the initialization as the return valueof a function call, or as the result of a constructor. An AGGR_INIT_EXPR willonly appear as the second operand of a TARGET_EXPR. The first operand to theAGGR_INIT_EXPR is the address of a function to call, just as in a CALL_EXPR.The second operand are the arguments to pass that function, as a TREE_LIST,again in a manner similar to that of a CALL_EXPR. The value of the expressionis that returned by the function.
Then if AGGR_INIT_EXPR is used in TRAGET_EXPR, it recurses break_out_target_exprsto copy this node. With the copied expression, build_cplus_new generatescode for the initialization.
2007 tree
2008 build_cplus_new (tree type, tree init) incp/tree.c
2009 {
2010 tree fn;
2011 tree slot;
2012 tree rval;
2013 int is_ctor;
2014
2015 /*Make sure that we're not trying to create an instance of an
2016 abstract class. */
2017 abstract_virtuals_error (NULL_TREE, type);
2018
2019 if (TREE_CODE (init) != CALL_EXPR &&TREE_CODE (init) != AGGR_INIT_EXPR)
2020 returnconvert (type, init);
2021
2022 fn = TREE_OPERAND (init, 0);
2023 is_ctor = (TREE_CODE (fn) ==ADDR_EXPR
2024 &&TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
2025 &&DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
2026
2027 slot = build_local_temp (type);
2028
2029 /*We split the CALL_EXPR into its function and its arguments here.
2030 Then,in expand_expr, we put them back together. The reason for
2031 thisis that this expression might be a default argument
2032 expression. In that case, we need a newtemporary every time the
2033 expression is used. That's whatbreak_out_target_exprs does; it
2034 replaces every AGGR_INIT_EXPR with a copythat uses a fresh
2035 temporary slot. Then, expand_expr builds upa call-expression
2036 usingthe new slot. */
2037
2038 /*If we don't need to use a constructor to create an object of this
2039 type,don't mess with AGGR_INIT_EXPR. */
2040 if (is_ctor ||TREE_ADDRESSABLE (type))
2041 {
2042 rval = build(AGGR_INIT_EXPR, type, fn, TREE_OPERAND (init, 1), slot);
2043 TREE_SIDE_EFFECTS (rval) =1;
2044 AGGR_INIT_VIA_CTOR_P(rval) = is_ctor;
2045 }
2046 else
2047 rval = init;
2048
2049 rval = build_target_expr (slot, rval);
2050
2051 returnrval;
2052 }
Now it needs update the temporary in the TARGET_EXPR, as we are notwithin the context generating the original TARGET_EXPR. See it makes thetemporary as local by forcing its DECL_CONTEXT by current_function_decl.
253 static tree
254 build_local_temp (tree type) incp/tree.c
255 {
256 tree slot = build_decl(VAR_DECL, NULL_TREE, type);
257 DECL_ARTIFICIAL (slot) = 1;
258 DECL_CONTEXT (slot) = current_function_decl;
259 layout_decl (slot,0);
260 return slot;
261 }
Note if AGGR_INIT_VIA_CTOR_P holds for the AGGR_INIT_EXPR, then theinitialization is via a constructor call. AGGR_INIT_EXPR constructed at line 2042will have this temporary as its third operand, which is always a VAR_DECL. And init isthe AGGR_INIT_EXPR in the original TARGET_EXPR (the address of the thirdoperand of the AGGR_INIT_EXPR is taken, and this value replaces the firstargument in the argument list. In this case, the value of the expression is theVAR_DECL given by the third operand to the AGGR_INIT_EXPR; constructors do notreturn a value).
Finally, this new generated TARGET_EXPR is retuned by build_cplus_new.
While for second operand in TARGET_EXPR other than AGGR_INIT_EXPR,the operand is handled by build_target_expr_with_type instead. Here if init isTARGET_EXPR, it must be one that built by break_out_target_exprs at line 1209 in bot_manip, which is the node we expect.
320 tree
321 build_target_expr_with_type (tree init,tree type) incp/tree.c
322 {
323 tree slot;
324
325 if (TREE_CODE (init) == TARGET_EXPR)
326 returninit;
327 else if (CLASS_TYPE_P (type) &&!TYPE_HAS_TRIVIAL_INIT_REF (type)
328 && TREE_CODE (init) !=COND_EXPR
329 && TREE_CODE (init) !=CONSTRUCTOR
330 && TREE_CODE (init) !=VA_ARG_EXPR)
331 /* We need tobuild up a copy constructor call. COND_EXPR is a special
332 case because wealready have copies on the arms and we don't want
333 another onehere. A CONSTRUCTOR is aggregate initialization, which
334 is handledseparately. A VA_ARG_EXPR is magic creation of an
335 aggregate;there's no additional work to be done. */
336 return force_rvalue (init);
337
338 slot = build_local_temp(type);
339 return build_target_expr (slot, init);
340 }
Above if TYPE_HAS_TRIVIAL_INIT_REF is nonzero, it means that copyinitialization of the type can use a bitwise copy. For which case, it cansimply build TARGET_EXPR; otherwise, it needs perform an lvalue-to-rvalueconversion, including invoking the copy ctor as below.
590 tree
591 force_rvalue (tree expr) incvt.c
592 {
593 if (IS_AGGR_TYPE (TREE_TYPE(expr)) && TREE_CODE (expr) != TARGET_EXPR)
594 expr = ocp_convert (TREE_TYPE (expr), expr,
595 CONV_IMPLICIT|CONV_FORCE_TEMP, LOOKUP_NORMAL);
596 else
597 expr = decay_conversion(expr);
598
599 return expr;
600 }
We will see the detail of ocp_convert in short later. As summary here,the function will generate code for invoking the appropriate copy ctor and theninvoking build_cplus_newto create the temporary with its initialization. Before leaving bot_manip,it worthes a look of build_target_expr.
234 static tree
235 build_target_expr (tree decl, treevalue) incp/tree.c
236 {
237 tree t;
238
239 t = build (TARGET_EXPR,TREE_TYPE (decl), decl, value,
240 cxx_maybe_build_cleanup(decl), NULL_TREE);
241 /* We always setTREE_SIDE_EFFECTS so that expand_expr does not
242 ignore the TARGET_EXPR. If there really turnout to be no
243 side-effects,then the optimizer should be able to get rid of
244 whatever code isgenerated anyhow. */
245 TREE_SIDE_EFFECTS (t) = 1;
246
247 return t;
248 }
For temporary with non-trivial destructor, the compiler needsgenerate code to destory the temporary at exitting its scope by invoking thedestructor. So at line 240, cxx_maybe_build_cleanup generates this codeif necessary.
Now at line 1213 inbot_manip,u isthe TARGET_EXPR built corresponding to t. It maps the new version temporary with the oldone. Then, we immediately replace the old one with it. However, it is possiblesome sub-nodes within node handled by break_out_target_exprs, still hold thereference to this old version, which needs be updated as below.
1236 static tree
1237 bot_replace (tree* t, incp/tree.c
1238 int* walk_subtreesATTRIBUTE_UNUSED ,
1239 void* data)
1240 {
1241 splay_tree target_remap =((splay_tree) data);
1242
1243 if (TREE_CODE (*t) ==VAR_DECL)
1244 {
1245 splay_tree_node n =splay_tree_lookup (target_remap,
1246 (splay_tree_key)*t);
1247 if (n)
1248 *t = (tree) n->value;
1249 }
1250
1251 returnNULL_TREE;
1252 }
Back convert_default_arg, it gets the updated arg atline 4274 from break_out_target_exprs, then the following functions are usedto generate code for the initialization.
5.12.5.2.2.2.3. Ellipsis arguments
The last possibility is the ellipsis arguments, note that ellipsisargument can’t coexist with default argument. In front-end to tell out functiondeclaration containing ellipsis arguments, the list of parameters is terminatedby NULL instead of void_list_node.
4161 tree
4162 convert_arg_to_ellipsis (tree arg) incall.c
4163 {
4164 /*[expr.call]
4165
4166 Thelvalue-to-rvalue, array-to-pointer, and function-to-pointer
4167 standard conversions are performed. */
4168 arg = decay_conversion (arg);
4169 /* [expr.call]
4170
4171 If theargument has integral or enumeration type that is subject
4172 to theintegral promotions (_conv.prom_), or a floating point
4173 typethat is subject to the floating point promotion
4174 (_conv.fpprom_), the value of the argumentis converted to the
4175 promoted type before the call. */
4176 if (TREE_CODE (TREE_TYPE(arg)) == REAL_TYPE
4177 &&(TYPE_PRECISION (TREE_TYPE (arg))
4178 < TYPE_PRECISION(double_type_node)))
4179 arg = convert_to_real (double_type_node,arg);
4180 else if(INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (arg)))
4181 arg =perform_integral_promotions (arg);
4182
4183 arg = require_complete_type(arg);
4184
4185 if (arg != error_mark_node
4186 && !pod_type_p(TREE_TYPE (arg)))
4187 {
4188 /*Undefined behavior [expr.call] 5.2.2/7. We usedto just warn
4189 hereand do a bitwise copy, but now cp_expr_size will abort if we
4190 tryto do that.
4191 Ifthe call appears in the context of a sizeof expression,
4192 there is no need to emit a warning, sincethe expression won't be
4193 evaluated. We keep the builtin_trap justas a safety check. */
4194 if (!skip_evaluation)
4195 warning ("cannotpass objects of non-POD type `%#T' through `...'; "
4196 "call willabort at runtime", TREE_TYPE (arg));
4197 arg = call_builtin_trap ();
4198 arg = build(COMPOUND_EXPR, integer_type_node, arg,
4199 integer_zero_node);
4200 }
4201
4202 returnarg;
4203 }
[3], clause 5.2.2“Function call”, terms 7 defines the behavior of compiler upon ellipsisargument as below.
7. When there is no parameter for a given argument, the argument is passed in such a way that the receiving function can obtain the value of the argument by invoking va_arg (18.7). The lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are performed on the argument expression. After these conversions, if the argument does not have arithmetic, enumeration, pointer, pointer to member, or class type, the program is ill-formed. If the argument has a non-POD class type (clause 9), the behavior is undefined. If the argument has integral or enumeration type that is subject to the integral promotions (4.5), or a floating point type that is subject to the floating point promotion (4.6), the value of the argument is converted to the promoted type before the call. These promotions are referred to as the default argument promotions.
Function decay_conversionperforms the conversions in exp, which are used when an lvalue appears in anrvalue context, and include lvalue-to-rvalue, array-to-pointer, and function-to-pointerconversion.
1335 tree
1336 decay_conversion (tree exp) ntypeck.c
1337 {
1338 tree type;
1339 enumtree_code code;
1340
1341 type = TREE_TYPE (exp);
1342 code = TREE_CODE (type);
1343
1344 if (code == REFERENCE_TYPE)
1345 {
1346 exp = convert_from_reference (exp);
1347 type = TREE_TYPE (exp);
1348 code = TREE_CODE (type);
1349 }
1350
1351 if (type == error_mark_node)
1352 returnerror_mark_node;
1353
1354 if (type_unknown_p (exp))
1355 {
1356 cxx_incomplete_type_error(exp, TREE_TYPE (exp));
1357 returnerror_mark_node;
1358 }
1359
1360 /*Constants can be used directly unless they're not loadable. */
1361 if (TREE_CODE (exp) ==CONST_DECL)
1362 exp = DECL_INITIAL (exp);
1363 /*Replace a nonvolatile const static variable with its value. We
1364 don'tdo this for arrays, though; we want the address of the
1365 firstelement of the array, not the address of the first element
1366 of itsinitializing constant. */
1367 else if (code != ARRAY_TYPE)
1368 {
1369 exp = decl_constant_value(exp);
1370 type = TREE_TYPE (exp);
1371 }
1372
1373 /* build_c_cast puts on a NOP_EXPR to make theresult not an lvalue.
1374 Leavesuch NOP_EXPRs, since RHS is being used in non-lvalue context. */
1375
1376 if (code == VOID_TYPE)
1377 {
1378 error ("void valuenot ignored as it ought to be");
1379 returnerror_mark_node;
1380 }
1381 if (invalid_nonstatic_memfn_p(exp))
1382 returnerror_mark_node;
1383 if (code == FUNCTION_TYPE ||is_overloaded_fn (exp))
1384 returnbuild_unary_op (ADDR_EXPR, exp, 0);
1385 if (code == ARRAY_TYPE)
1386 {
1387 tree adr;
1388 tree ptrtype;
1389
1390 if (TREE_CODE (exp) ==INDIRECT_REF)
1391 returnbuild_nop (build_pointer_type (TREE_TYPE(type)),
1392 TREE_OPERAND (exp, 0));
1393
1394 if (TREE_CODE (exp) ==COMPOUND_EXPR)
1395 {
1396 tree op1 = decay_conversion (TREE_OPERAND (exp, 1));
1397 returnbuild (COMPOUND_EXPR, TREE_TYPE (op1),
1398 TREE_OPERAND(exp, 0), op1);
1399 }
1400
1401 if (!lvalue_p (exp)
1402 && ! (TREE_CODE(exp) == CONSTRUCTOR && TREE_STATIC (exp)))
1403 {
1404 error ("invalid useof non-lvalue array");
1405 returnerror_mark_node;
1406 }
1407
1408 ptrtype = build_pointer_type (TREE_TYPE (type));
1409
1410 if (TREE_CODE (exp) ==VAR_DECL)
1411 {
1412 if(!cxx_mark_addressable (exp))
1413 return error_mark_node;
1414 adr = build_nop(ptrtype, build_address (exp));
1415 TREE_SIDE_EFFECTS (adr)= 0; /*Default would be, same as EXP. */
1416 returnadr;
1417 }
1418 /*This way is better for a COMPONENT_REF since it can
1419 simplify the offset for a component. */
1420 adr = build_unary_op(ADDR_EXPR, exp, 1);
1421 returncp_convert (ptrtype, adr);
1422 }
1423
1424 /*[basic.lval]: Class rvalues can have cv-qualified types; non-class
1425 rvalues always have cv-unqualifiedtypes. */
1426 if (! CLASS_TYPE_P (type))
1427 exp = cp_convert(TYPE_MAIN_VARIANT (type), exp);
1428
1429 returnexp;
1430 }
First for REFERENCE_TYPE, it is a lvalue, to change it to rvalue, itshould uses the value referred instead of holding reference any more. Infront-end, INDIRECT_REF is built for the purpose (it because reference alwayshas its address passed just like pointer, and in compiler, the mode ofreference is the same as pointer, both are ptr_mode, see build_reference_type).
566 tree
567 convert_from_reference (tree val) incvt.c
568 {
569 if (TREE_CODE (TREE_TYPE (val)) ==REFERENCE_TYPE)
570 return build_indirect_ref (val, NULL);
571 return val;
572 }
Remember pointer is rvalue. When handling ARRAY_TYPE, condition atline 1390 is satisfied, if we are using expression like: int *a[i] (a is arrayhaving dimensions more than 1, for example, int A[2][2]), so it builds typelike: int**, and see converting pointer of “int *a[i]” to “int**” needesn’tgenerate any code, NOP_EXPR is built for such conversion.
Further if exp simply is a declaration of an array, forexmaple: int a[8], rvalue of this declaration is just “int*”. It can build thisrvalue directly. However, for other cases, for example: tempA.a (it is a treerooted by SCOPE_REF), it is not a simple rule we can use directly, so it asks build_unary_opand cp_convertto do the appropriate conversion.
As comment at line 4188 inconvert_arg_to_ellipsismentions, for the undefined behavior of non-POD class type, GCC once usesbitwise copy, but this behavior will cause later invocation of cp_expr_sizetriggering abort in current version. This abort is triggered by belowinvocation of “__builtin_trap”, which is included in arg of COMPOUND_EXPR at line 4198.
4148 c tree
4149 call_builtin_trap (void) incall.c
4150 {
4151 tree fn =IDENTIFIER_GLOBAL_VALUE (get_identifier ("__builtin_trap"));
4152
4153 my_friendly_assert (fn !=NULL, 20030927);
4154 fn = build_call (fn,NULL_TREE);
4155 returnfn;
4156 }
The behavior of the builtin trap will use trap if the target machinedefines it; otherwise the compiler will call abort() (see expand_builtin_trap).
Below is aninteresting test for the behavior of non-POD class type:
#include <stdarg.h>
class A {
public: virtual void func() {}
};
int func (int a, ...) {
va_list ap;
va_start(ap, a);
va_arg(ap, A);
va_end(ap);
return 1;
}
int main() {
A a;
func (1, a); // sizeof (func (1, a))
}
The compiler will give outfollowing warning:
test2.cpp: In function ‘int func(int, ...)’:
test2.cpp:11: warning: cannot receive objects ofnon-POD type ‘class A’ through ‘...’; call will abort at runtime
test2.cpp: In function ‘int main()’:
test2.cpp:19: warning: cannot pass objects of non-PODtype ‘class A’ through ’...’; call will abort at runtime
When execute the program, it gets error: Illegal instruction.
However, if we use statement in comment instead, the compiler thengives warning as:
test2.cpp: In function ‘int func(int, ...)’:
test2.cpp:11: warning: cannot receive objects ofnon-POD type ‘class A’ through ‘...’; call will abort at runtime
And at execution, no error will be output, as func(1, a) will not beevaluated except its returned value.
- Studying note of GCC-3.4.6 source (152)
- Studying note of GCC-3.4.6 source (6)
- Studying note of GCC-3.4.6 source (1)
- Studying note of GCC-3.4.6 source (2)
- Studying note of GCC-3.4.6 source (3)
- Studying note of GCC-3.4.6 source (4)
- Studying note of GCC-3.4.6 source (5)
- Studying note of GCC-3.4.6 source (7)
- Studying note of GCC-3.4.6 source (8)
- Studying note of GCC-3.4.6 source (9)
- Studying note of GCC-3.4.6 source (10)
- Studying note of GCC-3.4.6 source (10 cont1)
- Studying note of GCC-3.4.6 source (10 cont2)
- Studying note of GCC-3.4.6 source (10 cont3)
- Studying note of GCC-3.4.6 source (10 cont4)
- Studying note of GCC-3.4.6 source (11)
- Studying note of GCC-3.4.6 source (12)
- Studying note of GCC-3.4.6 source (13)
- Studying note of GCC-3.4.6 source (151)
- 我为什么写博客
- java高手释疑:package 与 import 【转载:java联机版】
- GCC-3.4.6源代码学习笔记(152)
- asp.net获取html内容中的指定标签下的某个属性值
- Studying note of GCC-3.4.6 source (152)
- GCC-3.4.6源代码学习笔记(153)
- Studying note of GCC-3.4.6 source (153)
- 有趣的智力题
- 简单的操作通信
- 现在就开始
- VHD文件的压缩和转化
- 智力风暴(经典智力题)
- 第一次来到这里啊,求罩啊