diff options
author | Jakub Jelinek <jakub@redhat.com> | 2012-10-05 21:30:39 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2012-10-05 21:30:39 +0200 |
commit | 0d23cf7a4f9609763b600a7e9edf81e78e3f7a55 (patch) | |
tree | cdaa38c550b113c61c8a82ec24f6b0febfad9e1d /gcc/cp | |
parent | 94645a02dca8b5b103278ec48b4c7e0fe82ccfbf (diff) | |
download | gcc-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/ChangeLog | 35 | ||||
-rw-r--r-- | gcc/cp/call.c | 2 | ||||
-rw-r--r-- | gcc/cp/cp-gimplify.c | 19 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 5 | ||||
-rw-r--r-- | gcc/cp/cxx-pretty-print.c | 10 | ||||
-rw-r--r-- | gcc/cp/decl.c | 102 | ||||
-rw-r--r-- | gcc/cp/error.c | 4 | ||||
-rw-r--r-- | gcc/cp/mangle.c | 8 | ||||
-rw-r--r-- | gcc/cp/parser.c | 29 | ||||
-rw-r--r-- | gcc/cp/pt.c | 98 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 45 | ||||
-rw-r--r-- | gcc/cp/tree.c | 4 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 9 |
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); } } |