aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>1999-10-13 08:49:54 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>1999-10-13 08:49:54 +0000
commit356955cfb5f78224bc8c6d085d02d904ba84b4aa (patch)
tree0e448901aa69335285ee8574f6046b97ac436ba0 /gcc/cp
parenta5037588b493c6a1ca654f3acf8a5280cb614bfc (diff)
downloadgcc-356955cfb5f78224bc8c6d085d02d904ba84b4aa.zip
gcc-356955cfb5f78224bc8c6d085d02d904ba84b4aa.tar.gz
gcc-356955cfb5f78224bc8c6d085d02d904ba84b4aa.tar.bz2
cp-tree.h (build_x_va_arg): Prototype new function.
* cp-tree.h (build_x_va_arg): Prototype new function. * call.c (build_x_va_arg): Define it. * parse.y (unary_expr): Call build_x_va_arg. * cp-tree.h (convert_type_from_ellipsis): Prototype new function. * call.c (convert_type_from_ellipsis): Define it. * decl.c (init_decl_processing): Set lang_type_promotes_to. * tree.c (lvalue_p_1): Accept VA_ARG_EXPR with aggregates. From-SVN: r29942
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/call.c42
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/decl.c1
-rw-r--r--gcc/cp/parse.y2
-rw-r--r--gcc/cp/tree.c1
6 files changed, 59 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 59e0932..9bb81d0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+1999-10-13 Nathan Sidwell <nathan@acm.org>
+
+ * cp-tree.h (build_x_va_arg): Prototype new function.
+ * call.c (build_x_va_arg): Define it.
+ * parse.y (unary_expr): Call build_x_va_arg.
+
+ * cp-tree.h (convert_type_from_ellipsis): Prototype new function.
+ * call.c (convert_type_from_ellipsis): Define it.
+ * decl.c (init_decl_processing): Set lang_type_promotes_to.
+
+ * tree.c (lvalue_p_1): Accept VA_ARG_EXPR with aggregates.
+
1999-10-11 Jason Merrill <jason@yorick.cygnus.com>
* class.c (fixed_type_or_null): Always set *nonnull.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 6eaf61e..dd4e442 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -3813,6 +3813,48 @@ convert_arg_to_ellipsis (arg)
return arg;
}
+/* va_arg (EXPR, TYPE) is a builtin. Make sure it is not abused. */
+
+tree
+build_x_va_arg (expr, type)
+ tree expr;
+ tree type;
+{
+ type = complete_type_or_else (type, NULL_TREE);
+
+ if (expr == error_mark_node || !type)
+ return error_mark_node;
+
+ if (! pod_type_p (type))
+ {
+ /* Undefined behaviour [expr.call] 5.2.2/7. */
+ cp_warning ("cannot receive objects of non-POD type `%#T' through `...'",
+ type);
+ }
+
+ return build_va_arg (expr, type);
+}
+
+/* TYPE has been given to va_arg. Apply the default conversions which would
+ have happened when passed via ellipsis. Return the promoted type, or
+ NULL_TREE, if there is no change. */
+
+tree
+convert_type_from_ellipsis (type)
+ tree type;
+{
+ tree promote;
+
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ promote = build_pointer_type (TREE_TYPE (type));
+ else if (TREE_CODE (type) == FUNCTION_TYPE)
+ promote = build_pointer_type (type);
+ else
+ promote = type_promotes_to (type);
+
+ return same_type_p (type, promote) ? NULL_TREE : promote;
+}
+
/* ARG is a default argument expression being passed to a parameter of
the indicated TYPE, which is a parameter to FN. Do any required
conversions. Return the converted value. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 82ed882..3246e5a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3270,6 +3270,8 @@ extern int can_convert_arg PROTO((tree, tree, tree));
extern int enforce_access PROTO((tree, tree));
extern tree convert_default_arg PROTO((tree, tree, tree));
extern tree convert_arg_to_ellipsis PROTO((tree));
+extern tree build_x_va_arg PROTO((tree, tree));
+extern tree convert_type_from_ellipsis PROTO((tree));
extern int is_properly_derived_from PROTO((tree, tree));
extern tree initialize_reference PROTO((tree, tree));
extern tree strip_top_quals PROTO((tree));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 1554abc..60dac52 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6221,6 +6221,7 @@ init_decl_processing ()
= build_pointer_type (build_qualified_type (void_type_node,
TYPE_QUAL_CONST));
c_common_nodes_and_builtins (1, flag_no_builtin, flag_no_nonansi_builtin);
+ lang_type_promotes_to = convert_type_from_ellipsis;
void_ftype_ptr
= build_exception_variant (void_ftype_ptr, empty_except_spec);
diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y
index e9d8068..335c022 100644
--- a/gcc/cp/parse.y
+++ b/gcc/cp/parse.y
@@ -1173,7 +1173,7 @@ unary_expr:
| IMAGPART cast_expr %prec UNARY
{ $$ = build_x_unary_op (IMAGPART_EXPR, $2); }
| VA_ARG '(' expr_no_commas ',' type_id ')'
- { $$ = build_va_arg ($3, groktypename ($5.t));
+ { $$ = build_x_va_arg ($3, groktypename ($5.t));
check_for_new_type ("__builtin_va_arg", $5); }
;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index b27f9c8..0b5f843 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -145,6 +145,7 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
case CALL_EXPR:
+ case VA_ARG_EXPR:
return ((treat_class_rvalues_as_lvalues
&& IS_AGGR_TYPE (TREE_TYPE (ref)))
? clk_class : clk_none);