aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2012-10-05 21:30:39 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2012-10-05 21:30:39 +0200
commit0d23cf7a4f9609763b600a7e9edf81e78e3f7a55 (patch)
treecdaa38c550b113c61c8a82ec24f6b0febfad9e1d /gcc/cp
parent94645a02dca8b5b103278ec48b4c7e0fe82ccfbf (diff)
downloadgcc-0d23cf7a4f9609763b600a7e9edf81e78e3f7a55.zip
gcc-0d23cf7a4f9609763b600a7e9edf81e78e3f7a55.tar.gz
gcc-0d23cf7a4f9609763b600a7e9edf81e78e3f7a55.tar.bz2
cp-tree.h (SIZEOF_EXPR_TYPE_P): Define.
cp/ * cp-tree.h (SIZEOF_EXPR_TYPE_P): Define. * tree.c (cp_tree_equal): Handle SIZEOF_EXPR with SIZEOF_EXPR_TYPE_P. * mangle.c (write_expression): Likewise. * cxx-pretty-print.c (pp_cxx_unary_expression): Likewise. * error.c (dump_expr): Likewise. * parser.c (cp_parser_unary_expression): For sizeof call cxx_sizeof_or_alignof_{type,expr} just for diagnostics and return SIZEOF_EXPR with the operand. * pt.c (tsubst_copy, tsubst_copy_and_build): For SIZEOF_EXPR, call cxx_sizeof_or_alignof_{type,expr} for diagnostics, but return SIZEOF_EXPR with tsubsted operand. (value_dependent_expression_p): Handle SIZEOF_EXPR with SIZEOF_EXPR_TYPE_P. (instantiation_dependent_r): Likewise. * call.c (null_ptr_cst_p): Call maybe_constant_value for C++98. * semantics.c (finish_call_expr): Call sizeof_pointer_memaccess_warning if needed. (cxx_eval_constant_expression): Handle SIZEOF_EXPR. (potential_constant_expression_1): Remove early exit for C++98. Handle PROPERTY_REF. * decl.c (duplicate_decls): When redeclaring a builtin function, keep the merged decl builtin also if newdecl is a gnu_inline inline definition. (fold_sizeof_expr_r): New function. (compute_array_index_type): Fold SIZEOF_EXPRs in itype. * cp-gimplify.c (cp_genericize_r): Fold SIZEOF_EXPR. * typeck.c (cp_build_binary_op): For warn_for_sign_compare try harder using maybe_constant_value to get INTEGER_CSTs. * decl.c (stabilize_vla_size): Call pointer_set_destroy at the end. testsuite/ * g++.dg/torture/Wsizeof-pointer-memaccess1.C: New test. * g++.dg/torture/Wsizeof-pointer-memaccess2.C: New test. * g++.dg/warn/Wsign-compare-5.C: New test. * g++.dg/warn/Wsizeof-pointer-memaccess-1.C: New test. * g++.dg/warn/Wnull-conversion-1.C: For c++11 add dg-error. * g++.dg/ext/builtin30.C: New test. * g++.dg/ext/vla12.C: New test. * gcc.dg/builtins-85.c: New test. libstdc++-v3/ * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust line numbers. From-SVN: r192141
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog35
-rw-r--r--gcc/cp/call.c2
-rw-r--r--gcc/cp/cp-gimplify.c19
-rw-r--r--gcc/cp/cp-tree.h5
-rw-r--r--gcc/cp/cxx-pretty-print.c10
-rw-r--r--gcc/cp/decl.c102
-rw-r--r--gcc/cp/error.c4
-rw-r--r--gcc/cp/mangle.c8
-rw-r--r--gcc/cp/parser.c29
-rw-r--r--gcc/cp/pt.c98
-rw-r--r--gcc/cp/semantics.c45
-rw-r--r--gcc/cp/tree.c4
-rw-r--r--gcc/cp/typeck.c9
13 files changed, 295 insertions, 75 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index fe72a9c..458b762 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,38 @@
+2012-10-05 Jakub Jelinek <jakub@redhat.com>
+
+ * cp-tree.h (SIZEOF_EXPR_TYPE_P): Define.
+ * tree.c (cp_tree_equal): Handle SIZEOF_EXPR with
+ SIZEOF_EXPR_TYPE_P.
+ * mangle.c (write_expression): Likewise.
+ * cxx-pretty-print.c (pp_cxx_unary_expression): Likewise.
+ * error.c (dump_expr): Likewise.
+ * parser.c (cp_parser_unary_expression): For sizeof call
+ cxx_sizeof_or_alignof_{type,expr} just for diagnostics and
+ return SIZEOF_EXPR with the operand.
+ * pt.c (tsubst_copy, tsubst_copy_and_build): For SIZEOF_EXPR,
+ call cxx_sizeof_or_alignof_{type,expr} for diagnostics, but
+ return SIZEOF_EXPR with tsubsted operand.
+ (value_dependent_expression_p): Handle SIZEOF_EXPR with
+ SIZEOF_EXPR_TYPE_P.
+ (instantiation_dependent_r): Likewise.
+ * call.c (null_ptr_cst_p): Call maybe_constant_value for C++98.
+ * semantics.c (finish_call_expr): Call
+ sizeof_pointer_memaccess_warning if needed.
+ (cxx_eval_constant_expression): Handle SIZEOF_EXPR.
+ (potential_constant_expression_1): Remove early exit for
+ C++98. Handle PROPERTY_REF.
+ * decl.c (duplicate_decls): When redeclaring a builtin function,
+ keep the merged decl builtin also if newdecl is a gnu_inline
+ inline definition.
+ (fold_sizeof_expr_r): New function.
+ (compute_array_index_type): Fold SIZEOF_EXPRs in itype.
+ * cp-gimplify.c (cp_genericize_r): Fold SIZEOF_EXPR.
+ * typeck.c (cp_build_binary_op): For warn_for_sign_compare
+ try harder using maybe_constant_value to get INTEGER_CSTs.
+
+ * decl.c (stabilize_vla_size): Call pointer_set_destroy
+ at the end.
+
2012-10-04 Arnaud Charlet <charlet@adacore.com>
* decl2.c (cp_write_global_declarations): Fix handling of
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index d0492d8..006cf41 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -557,7 +557,7 @@ null_ptr_cst_p (tree t)
{
/* Core issue 903 says only literal 0 is a null pointer constant. */
if (cxx_dialect < cxx0x)
- t = integral_constant_value (t);
+ t = maybe_constant_value (t);
STRIP_NOPS (t);
if (integer_zerop (t) && !TREE_OVERFLOW (t))
return true;
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index dd2ef06..6178993 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1,6 +1,7 @@
/* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c.
- Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
+ 2012
Free Software Foundation, Inc.
Contributed by Jason Merrill <jason@redhat.com>
@@ -1119,6 +1120,22 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
genericize_break_stmt (stmt_p);
else if (TREE_CODE (stmt) == OMP_FOR)
genericize_omp_for_stmt (stmt_p, walk_subtrees, data);
+ else if (TREE_CODE (stmt) == SIZEOF_EXPR)
+ {
+ if (SIZEOF_EXPR_TYPE_P (stmt))
+ *stmt_p
+ = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (stmt, 0)),
+ SIZEOF_EXPR, false);
+ else if (TYPE_P (TREE_OPERAND (stmt, 0)))
+ *stmt_p = cxx_sizeof_or_alignof_type (TREE_OPERAND (stmt, 0),
+ SIZEOF_EXPR, false);
+ else
+ *stmt_p = cxx_sizeof_or_alignof_expr (TREE_OPERAND (stmt, 0),
+ SIZEOF_EXPR, false);
+ if (*stmt_p == error_mark_node)
+ *stmt_p = size_one_node;
+ return NULL;
+ }
pointer_set_insert (p_set, *stmt_p);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index bfe7ad7..034668d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -78,6 +78,7 @@ c-common.h, not after.
OVL_ARG_DEPENDENT (in OVERLOAD)
PACK_EXPANSION_LOCAL_P (in *_PACK_EXPANSION)
TINFO_RECHECK_ACCESS_P (in TEMPLATE_INFO)
+ SIZEOF_EXPR_TYPE_P (in SIZEOF_EXPR)
1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
@@ -4055,6 +4056,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define CONVERT_EXPR_VBASE_PATH(NODE) \
TREE_LANG_FLAG_0 (CONVERT_EXPR_CHECK (NODE))
+/* True if SIZEOF_EXPR argument is type. */
+#define SIZEOF_EXPR_TYPE_P(NODE) \
+ TREE_LANG_FLAG_0 (SIZEOF_EXPR_CHECK (NODE))
+
/* An enumeration of the kind of tags that C++ accepts. */
enum tag_types {
none_type = 0, /* Not a tag type. */
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index 03d9149..ce64a7b 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -1,6 +1,6 @@
/* Implementation of subroutines for the GNU C++ pretty-printer.
Copyright (C) 2003, 2004, 2005, 2007, 2008,
- 2009, 2010, 2011 Free Software Foundation, Inc.
+ 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
This file is part of GCC.
@@ -798,7 +798,13 @@ pp_cxx_unary_expression (cxx_pretty_printer *pp, tree t)
case ALIGNOF_EXPR:
pp_cxx_ws_string (pp, code == SIZEOF_EXPR ? "sizeof" : "__alignof__");
pp_cxx_whitespace (pp);
- if (TYPE_P (TREE_OPERAND (t, 0)))
+ if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
+ {
+ pp_cxx_left_paren (pp);
+ pp_cxx_type_id (pp, TREE_TYPE (TREE_OPERAND (t, 0)));
+ pp_cxx_right_paren (pp);
+ }
+ else if (TYPE_P (TREE_OPERAND (t, 0)))
{
pp_cxx_left_paren (pp);
pp_cxx_type_id (pp, TREE_OPERAND (t, 0));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index d0933ef..72754a9 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2160,39 +2160,40 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl);
DECL_RESULT (olddecl) = DECL_RESULT (newdecl);
}
+ /* If redeclaring a builtin function, it stays built in
+ if newdecl is a gnu_inline definition, or if newdecl is just
+ a declaration. */
+ if (DECL_BUILT_IN (olddecl)
+ && (new_defines_function ? GNU_INLINE_P (newdecl) : types_match))
+ {
+ DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
+ DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
+ /* If we're keeping the built-in definition, keep the rtl,
+ regardless of declaration matches. */
+ COPY_DECL_RTL (olddecl, newdecl);
+ if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
+ {
+ enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
+ switch (fncode)
+ {
+ /* If a compatible prototype of these builtin functions
+ is seen, assume the runtime implements it with the
+ expected semantics. */
+ case BUILT_IN_STPCPY:
+ if (builtin_decl_explicit_p (fncode))
+ set_builtin_decl_implicit_p (fncode, true);
+ break;
+ default:
+ break;
+ }
+ }
+ }
if (new_defines_function)
/* If defining a function declared with other language
linkage, use the previously declared language linkage. */
SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
else if (types_match)
{
- /* If redeclaring a builtin function, and not a definition,
- it stays built in. */
- if (DECL_BUILT_IN (olddecl))
- {
- DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
- DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
- /* If we're keeping the built-in definition, keep the rtl,
- regardless of declaration matches. */
- COPY_DECL_RTL (olddecl, newdecl);
- if (DECL_BUILT_IN_CLASS (newdecl) == BUILT_IN_NORMAL)
- {
- enum built_in_function fncode = DECL_FUNCTION_CODE (newdecl);
- switch (fncode)
- {
- /* If a compatible prototype of these builtin functions
- is seen, assume the runtime implements it with the
- expected semantics. */
- case BUILT_IN_STPCPY:
- if (builtin_decl_explicit_p (fncode))
- set_builtin_decl_implicit_p (fncode, true);
- break;
- default:
- break;
- }
- }
- }
-
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
/* Don't clear out the arguments if we're just redeclaring a
function. */
@@ -7931,6 +7932,36 @@ stabilize_vla_size (tree size)
struct pointer_set_t *pset = pointer_set_create ();
/* Break out any function calls into temporary variables. */
cp_walk_tree (&size, stabilize_save_expr_r, pset, pset);
+ pointer_set_destroy (pset);
+}
+
+/* Helper function for compute_array_index_type. Look for SIZEOF_EXPR
+ not inside of SAVE_EXPR and fold them. */
+
+static tree
+fold_sizeof_expr_r (tree *expr_p, int *walk_subtrees, void *data)
+{
+ tree expr = *expr_p;
+ if (TREE_CODE (expr) == SAVE_EXPR || TYPE_P (expr))
+ *walk_subtrees = 0;
+ else if (TREE_CODE (expr) == SIZEOF_EXPR)
+ {
+ *(bool *)data = true;
+ if (SIZEOF_EXPR_TYPE_P (expr))
+ expr = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (expr, 0)),
+ SIZEOF_EXPR, false);
+ else if (TYPE_P (TREE_OPERAND (expr, 0)))
+ expr = cxx_sizeof_or_alignof_type (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
+ false);
+ else
+ expr = cxx_sizeof_or_alignof_expr (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
+ false);
+ if (expr == error_mark_node)
+ expr = size_one_node;
+ *expr_p = expr;
+ *walk_subtrees = 0;
+ }
+ return NULL;
}
/* Given the SIZE (i.e., number of elements) in an array, compute an
@@ -8126,8 +8157,21 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
processing_template_decl = saved_processing_template_decl;
if (!TREE_CONSTANT (itype))
- /* A variable sized array. */
- itype = variable_size (itype);
+ {
+ /* A variable sized array. */
+ itype = variable_size (itype);
+ if (TREE_CODE (itype) != SAVE_EXPR)
+ {
+ /* Look for SIZEOF_EXPRs in itype and fold them, otherwise
+ they might survive till gimplification. */
+ tree newitype = itype;
+ bool found = false;
+ cp_walk_tree_without_duplicates (&newitype,
+ fold_sizeof_expr_r, &found);
+ if (found)
+ itype = variable_size (fold (newitype));
+ }
+ }
/* Make sure that there was no overflow when creating to a signed
index type. (For example, on a 32-bit machine, an array with
size 2^32 - 1 is too big.) */
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index c8b614b..e1aa938 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -2312,7 +2312,9 @@ dump_expr (tree t, int flags)
}
pp_cxx_whitespace (cxx_pp);
pp_cxx_left_paren (cxx_pp);
- if (TYPE_P (TREE_OPERAND (t, 0)))
+ if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
+ dump_type (TREE_TYPE (TREE_OPERAND (t, 0)), flags);
+ else if (TYPE_P (TREE_OPERAND (t, 0)))
dump_type (TREE_OPERAND (t, 0), flags);
else
dump_expr (TREE_OPERAND (t, 0), flags);
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 13c658b..eee44a1 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -1,6 +1,6 @@
/* Name mangling for the 3.0 C++ ABI.
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010,
- 2011 Free Software Foundation, Inc.
+ 2011, 2012 Free Software Foundation, Inc.
Written by Alex Samuel <samuel@codesourcery.com>
This file is part of GCC.
@@ -2581,6 +2581,12 @@ write_expression (tree expr)
write_char ('E');
}
else if (TREE_CODE (expr) == SIZEOF_EXPR
+ && SIZEOF_EXPR_TYPE_P (expr))
+ {
+ write_string ("st");
+ write_type (TREE_TYPE (TREE_OPERAND (expr, 0)));
+ }
+ else if (TREE_CODE (expr) == SIZEOF_EXPR
&& TYPE_P (TREE_OPERAND (expr, 0)))
{
write_string ("st");
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 155b51a..baaa809 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6383,17 +6383,19 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
case RID_ALIGNOF:
case RID_SIZEOF:
{
- tree operand;
+ tree operand, ret;
enum tree_code op;
+ location_t first_loc;
op = keyword == RID_ALIGNOF ? ALIGNOF_EXPR : SIZEOF_EXPR;
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
+ first_loc = cp_lexer_peek_token (parser->lexer)->location;
/* Parse the operand. */
operand = cp_parser_sizeof_operand (parser, keyword);
if (TYPE_P (operand))
- return cxx_sizeof_or_alignof_type (operand, op, true);
+ ret = cxx_sizeof_or_alignof_type (operand, op, true);
else
{
/* ISO C++ defines alignof only with types, not with
@@ -6404,8 +6406,29 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
"ISO C++ does not allow %<alignof%> "
"with a non-type");
- return cxx_sizeof_or_alignof_expr (operand, op, true);
+ ret = cxx_sizeof_or_alignof_expr (operand, op, true);
}
+ /* For SIZEOF_EXPR, just issue diagnostics, but keep
+ SIZEOF_EXPR with the original operand. */
+ if (op == SIZEOF_EXPR && ret != error_mark_node)
+ {
+ if (TREE_CODE (ret) != SIZEOF_EXPR || TYPE_P (operand))
+ {
+ if (!processing_template_decl && TYPE_P (operand))
+ {
+ ret = build_min (SIZEOF_EXPR, size_type_node,
+ build1 (NOP_EXPR, operand,
+ error_mark_node));
+ SIZEOF_EXPR_TYPE_P (ret) = 1;
+ }
+ else
+ ret = build_min (SIZEOF_EXPR, size_type_node, operand);
+ TREE_SIDE_EFFECTS (ret) = 0;
+ TREE_READONLY (ret) = 1;
+ }
+ SET_EXPR_LOCATION (ret, first_loc);
+ }
+ return ret;
}
case RID_NEW:
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 104d4dd..c3fb5e8 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12031,14 +12031,16 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
{
- tree expanded;
+ tree expanded, op = TREE_OPERAND (t, 0);
int len = 0;
+ if (SIZEOF_EXPR_TYPE_P (t))
+ op = TREE_TYPE (op);
+
++cp_unevaluated_operand;
++c_inhibit_evaluation_warnings;
/* We only want to compute the number of arguments. */
- expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args,
- complain, in_decl);
+ expanded = tsubst_pack_expansion (op, args, complain, in_decl);
--cp_unevaluated_operand;
--c_inhibit_evaluation_warnings;
@@ -12065,6 +12067,16 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
else
return build_int_cst (size_type_node, len);
}
+ if (SIZEOF_EXPR_TYPE_P (t))
+ {
+ r = tsubst_copy (TREE_TYPE (TREE_OPERAND (t, 0)),
+ args, complain, in_decl);
+ r = build1 (NOP_EXPR, r, error_mark_node);
+ r = build1 (SIZEOF_EXPR,
+ tsubst (TREE_TYPE (t), args, complain, in_decl), r);
+ SIZEOF_EXPR_TYPE_P (r) = 1;
+ return r;
+ }
/* Fall through */
case INDIRECT_REF:
@@ -13468,31 +13480,56 @@ tsubst_copy_and_build (tree t,
/* Fall through */
case ALIGNOF_EXPR:
- op1 = TREE_OPERAND (t, 0);
- if (!args)
- {
- /* When there are no ARGS, we are trying to evaluate a
- non-dependent expression from the parser. Trying to do
- the substitutions may not work. */
- if (!TYPE_P (op1))
- op1 = TREE_TYPE (op1);
- }
- else
- {
- ++cp_unevaluated_operand;
- ++c_inhibit_evaluation_warnings;
- op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
- /*function_p=*/false,
- /*integral_constant_expression_p=*/false);
- --cp_unevaluated_operand;
- --c_inhibit_evaluation_warnings;
- }
- if (TYPE_P (op1))
- RETURN (cxx_sizeof_or_alignof_type (op1, TREE_CODE (t),
- complain & tf_error));
- else
- RETURN (cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
- complain & tf_error));
+ {
+ tree r;
+
+ op1 = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (t))
+ op1 = TREE_TYPE (op1);
+ if (!args)
+ {
+ /* When there are no ARGS, we are trying to evaluate a
+ non-dependent expression from the parser. Trying to do
+ the substitutions may not work. */
+ if (!TYPE_P (op1))
+ op1 = TREE_TYPE (op1);
+ }
+ else
+ {
+ ++cp_unevaluated_operand;
+ ++c_inhibit_evaluation_warnings;
+ op1 = tsubst_copy_and_build (op1, args, complain, in_decl,
+ /*function_p=*/false,
+ /*integral_constant_expression_p=*/
+ false);
+ --cp_unevaluated_operand;
+ --c_inhibit_evaluation_warnings;
+ }
+ if (TYPE_P (op1))
+ r = cxx_sizeof_or_alignof_type (op1, TREE_CODE (t),
+ complain & tf_error);
+ else
+ r = cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t),
+ complain & tf_error);
+ if (TREE_CODE (t) == SIZEOF_EXPR && r != error_mark_node)
+ {
+ if (TREE_CODE (r) != SIZEOF_EXPR || TYPE_P (op1))
+ {
+ if (TYPE_P (op1))
+ {
+ r = build_min (SIZEOF_EXPR, size_type_node,
+ build1 (NOP_EXPR, op1, error_mark_node));
+ SIZEOF_EXPR_TYPE_P (r) = 1;
+ }
+ else
+ r = build_min (SIZEOF_EXPR, size_type_node, op1);
+ TREE_SIDE_EFFECTS (r) = 0;
+ TREE_READONLY (r) = 1;
+ }
+ SET_EXPR_LOCATION (r, EXPR_LOCATION (t));
+ }
+ RETURN (r);
+ }
case AT_ENCODE_EXPR:
{
@@ -19288,6 +19325,9 @@ value_dependent_expression_p (tree expression)
}
case SIZEOF_EXPR:
+ if (SIZEOF_EXPR_TYPE_P (expression))
+ return dependent_type_p (TREE_TYPE (TREE_OPERAND (expression, 0)));
+ /* FALLTHRU */
case ALIGNOF_EXPR:
case TYPEID_EXPR:
/* A `sizeof' expression is value-dependent if the operand is
@@ -19627,6 +19667,8 @@ instantiation_dependent_r (tree *tp, int *walk_subtrees,
case TRAIT_EXPR:
{
tree op = TREE_OPERAND (*tp, 0);
+ if (code == SIZEOF_EXPR && SIZEOF_EXPR_TYPE_P (*tp))
+ op = TREE_TYPE (op);
if (TYPE_P (op))
{
if (dependent_type_p (op)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 68cbb4b..17ac36f 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2170,8 +2170,25 @@ finish_call_expr (tree fn, VEC(tree,gc) **args, bool disallow_virtual,
result = resolve_overloaded_builtin (input_location, fn, *args);
if (!result)
- /* A call to a namespace-scope function. */
- result = build_new_function_call (fn, args, koenig_p, complain);
+ {
+ if (warn_sizeof_pointer_memaccess
+ && !VEC_empty(tree, *args)
+ && TREE_CODE (VEC_last(tree, *args)) == SIZEOF_EXPR
+ && !processing_template_decl)
+ {
+ tree sizeof_arg = VEC_last(tree, *args);
+ if (SIZEOF_EXPR_TYPE_P (sizeof_arg))
+ sizeof_arg = TREE_TYPE (TREE_OPERAND (sizeof_arg, 0));
+ else
+ sizeof_arg = TREE_OPERAND (sizeof_arg, 0);
+ sizeof_pointer_memaccess_warning
+ (EXPR_LOCATION (VEC_last(tree, *args)), fn, *args,
+ sizeof_arg, same_type_ignoring_top_level_qualifiers_p);
+ }
+
+ /* A call to a namespace-scope function. */
+ result = build_new_function_call (fn, args, koenig_p, complain);
+ }
}
else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR)
{
@@ -7723,6 +7740,21 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
non_constant_p);
break;
+ case SIZEOF_EXPR:
+ if (SIZEOF_EXPR_TYPE_P (t))
+ r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)),
+ SIZEOF_EXPR, false);
+ else if (TYPE_P (TREE_OPERAND (t, 0)))
+ r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR,
+ false);
+ else
+ r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR,
+ false);
+ if (r == error_mark_node)
+ r = size_one_node;
+ VERIFY_CONSTANT (r);
+ break;
+
case COMPOUND_EXPR:
{
/* check_return_expr sometimes wraps a TARGET_EXPR in a
@@ -8107,12 +8139,6 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
int i;
tree tmp;
- /* C++98 has different rules for the form of a constant expression that
- are enforced in the parser, so we can assume that anything that gets
- this far is suitable. */
- if (cxx_dialect < cxx0x)
- return true;
-
if (t == error_mark_node)
return false;
if (t == NULL_TREE)
@@ -8633,6 +8659,9 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
return false;
default:
+ if (objc_is_property_ref (t))
+ return false;
+
sorry ("unexpected AST of kind %s", tree_code_name[TREE_CODE (t)]);
gcc_unreachable();
return false;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 7dddf22..60dc549 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2602,6 +2602,10 @@ cp_tree_equal (tree t1, tree t2)
tree o1 = TREE_OPERAND (t1, 0);
tree o2 = TREE_OPERAND (t2, 0);
+ if (SIZEOF_EXPR_TYPE_P (t1))
+ o1 = TREE_TYPE (o1);
+ if (SIZEOF_EXPR_TYPE_P (t2))
+ o2 = TREE_TYPE (o2);
if (TREE_CODE (o1) != TREE_CODE (o2))
return false;
if (TYPE_P (o1))
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 884f7d0..ce77907 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4624,7 +4624,14 @@ cp_build_binary_op (location_t location,
&& !enum_cast_to_int (orig_op0)
&& !enum_cast_to_int (orig_op1))
{
- warn_for_sign_compare (location, orig_op0, orig_op1, op0, op1,
+ tree oop0 = maybe_constant_value (orig_op0);
+ tree oop1 = maybe_constant_value (orig_op1);
+
+ if (TREE_CODE (oop0) != INTEGER_CST)
+ oop0 = orig_op0;
+ if (TREE_CODE (oop1) != INTEGER_CST)
+ oop1 = orig_op1;
+ warn_for_sign_compare (location, oop0, oop1, op0, op1,
result_type, resultcode);
}
}