diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 56 | ||||
-rw-r--r-- | gcc/cp/call.c | 6 | ||||
-rw-r--r-- | gcc/cp/decl.c | 3 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 5 | ||||
-rw-r--r-- | gcc/cp/parser.c | 34 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 1 | ||||
-rw-r--r-- | gcc/cp/tree.c | 52 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 9 |
8 files changed, 130 insertions, 36 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 391407fb9da..2dcdb770ea3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,59 @@ +2012-05-30 Jason Merrill <jason@redhat.com> + + PR c++/53356 + * tree.c (stabilize_init): Handle stabilizing a TARGET_EXPR + representing a bitwise copy of a glvalue. + + * tree.c (stabilize_expr): Tweak logic. + + PR c++/53356 + * tree.c (stabilize_init): Side effects make the init unstable. + +2012-05-28 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/53503 + * semantics.c (potential_constant_expression_1): Handle LTGT_EXPR. + +2012-05-26 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/53491 + * tree.c (stabilize_expr): Handle exp of void type. + +2012-05-26 Jason Merrill <jason@redhat.com> + + PR c++/53220 + * call.c (convert_like_real) [ck_list]: Take array address directly. + * typeck.c (decay_conversion): Reject decay of an array compound + literal. + +2012-05-25 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/32054 + * parser.c (cp_parser_member_declaration): A storage class is not + allowed in a declaration of an anonymous aggregate in a class scope. + +2012-05-24 Uros Bizjak <ubizjak@gmail.com> + + PR obj-c++/53441 + * decl.c (grokdeclarator): Check that current_class_type is non-NULL + before calling constructor_name_p. + +2012-05-24 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/32080 + * parser.c (cp_parser_ctor_initializer_opt_and_function_body, + cp_parser_function_body): Add a bool parameter, true when parsing + a function-try-block. + (cp_parser_function_try_block): Pass true to the above. + (cp_parser_function_definition_after_declarator, + cp_parser_function_transaction): Adjust. + +2012-05-23 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/29185 + * decl2.c (delete_sanity): Extend 'deleting array' warning to + any array type. + 2012-05-21 Paolo Carlini <paolo.carlini@oracle.com> PR c++/51184 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 29fb195f131..4c99068587c 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5868,11 +5868,15 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, (elttype, cp_type_quals (elttype) | TYPE_QUAL_CONST); array = build_array_of_n_type (elttype, len); array = finish_compound_literal (array, new_ctor, complain); + /* Take the address explicitly rather than via decay_conversion + to avoid the error about taking the address of a temporary. */ + array = cp_build_addr_expr (array, complain); + array = cp_convert (build_pointer_type (elttype), array); /* Build up the initializer_list object. */ totype = complete_type (totype); field = next_initializable_field (TYPE_FIELDS (totype)); - CONSTRUCTOR_APPEND_ELT (vec, field, decay_conversion (array, complain)); + CONSTRUCTOR_APPEND_ELT (vec, field, array); field = next_initializable_field (DECL_CHAIN (field)); CONSTRUCTOR_APPEND_ELT (vec, field, size_int (len)); new_ctor = build_constructor (totype, vec); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 85f5c4b9e05..4d02f547719 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -9912,7 +9912,8 @@ grokdeclarator (const cp_declarator *declarator, clones. */ DECL_ABSTRACT (decl) = 1; } - else if (constructor_name_p (unqualified_id, current_class_type)) + else if (current_class_type + && constructor_name_p (unqualified_id, current_class_type)) permerror (input_location, "ISO C++ forbids nested type %qD with same name " "as enclosing class", unqualified_id); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 34d26bcad23..b6fb623b794 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -438,9 +438,8 @@ delete_sanity (tree exp, tree size, bool doing_vec, int use_global_delete, } /* An array can't have been allocated by new, so complain. */ - if (TREE_CODE (exp) == VAR_DECL - && TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE) - warning (0, "deleting array %q#D", exp); + if (TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE) + warning (0, "deleting array %q#E", exp); t = build_expr_type_conversion (WANT_POINTER, exp, true); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c99020f36d6..f2275023a26 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2028,7 +2028,7 @@ static cp_parameter_declarator *cp_parser_parameter_declaration static tree cp_parser_default_argument (cp_parser *, bool); static void cp_parser_function_body - (cp_parser *); + (cp_parser *, bool); static tree cp_parser_initializer (cp_parser *, bool *, bool *); static tree cp_parser_initializer_clause @@ -2039,7 +2039,7 @@ static VEC(constructor_elt,gc) *cp_parser_initializer_list (cp_parser *, bool *); static bool cp_parser_ctor_initializer_opt_and_function_body - (cp_parser *); + (cp_parser *, bool); /* Classes [gram.class] */ @@ -18004,16 +18004,18 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p) compound_statement */ static void -cp_parser_function_body (cp_parser *parser) +cp_parser_function_body (cp_parser *parser, bool in_function_try_block) { - cp_parser_compound_statement (parser, NULL, false, true); + cp_parser_compound_statement (parser, NULL, in_function_try_block, true); } /* Parse a ctor-initializer-opt followed by a function-body. Return - true if a ctor-initializer was present. */ + true if a ctor-initializer was present. When IN_FUNCTION_TRY_BLOCK + is true we are parsing a function-try-block. */ static bool -cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser) +cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser, + bool in_function_try_block) { tree body, list; bool ctor_initializer_p; @@ -18040,7 +18042,7 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser) last = STATEMENT_LIST_TAIL (list)->stmt; } /* Parse the function-body. */ - cp_parser_function_body (parser); + cp_parser_function_body (parser, in_function_try_block); if (check_body_p) check_constexpr_ctor_body (last, list); /* Finish the function body. */ @@ -19519,6 +19521,12 @@ cp_parser_member_declaration (cp_parser* parser) particular type), as opposed to a nested class. */ else if (ANON_AGGR_TYPE_P (type)) { + /* C++11 9.5/6. */ + if (decl_specifiers.storage_class != sc_none) + error_at (decl_spec_token_start->location, + "a storage class on an anonymous aggregate " + "in class scope is not allowed"); + /* Remove constructors and such from TYPE, now that we know it is an anonymous aggregate. */ fixup_anonymous_aggr (type); @@ -20318,8 +20326,8 @@ cp_parser_function_try_block (cp_parser* parser) /* Let the rest of the front end know where we are. */ try_block = begin_function_try_block (&compound_stmt); /* Parse the function-body. */ - ctor_initializer_p - = cp_parser_ctor_initializer_opt_and_function_body (parser); + ctor_initializer_p = cp_parser_ctor_initializer_opt_and_function_body + (parser, /*in_function_try_block=*/true); /* We're done with the `try' part. */ finish_function_try_block (try_block); /* Parse the handlers. */ @@ -21666,8 +21674,8 @@ cp_parser_function_definition_after_declarator (cp_parser* parser, else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TRY)) ctor_initializer_p = cp_parser_function_try_block (parser); else - ctor_initializer_p - = cp_parser_ctor_initializer_opt_and_function_body (parser); + ctor_initializer_p = cp_parser_ctor_initializer_opt_and_function_body + (parser, /*in_function_try_block=*/false); finish_lambda_scope (); @@ -27843,8 +27851,8 @@ cp_parser_function_transaction (cp_parser *parser, enum rid keyword) if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TRY)) ctor_initializer_p = cp_parser_function_try_block (parser); else - ctor_initializer_p - = cp_parser_ctor_initializer_opt_and_function_body (parser); + ctor_initializer_p = cp_parser_ctor_initializer_opt_and_function_body + (parser, /*in_function_try_block=*/false); parser->in_transaction = old_in; diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index a2f8f0ece89..5bc0ee2a4a4 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -8545,6 +8545,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case UNGT_EXPR: case UNGE_EXPR: case UNEQ_EXPR: + case LTGT_EXPR: case RANGE_EXPR: case COMPLEX_EXPR: want_rval = true; diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index c7223fb3c98..df98bc3b00c 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -3285,6 +3285,11 @@ stabilize_expr (tree exp, tree* initp) if (!TREE_SIDE_EFFECTS (exp)) init_expr = NULL_TREE; + else if (VOID_TYPE_P (TREE_TYPE (exp))) + { + init_expr = exp; + exp = void_zero_node; + } /* There are no expressions with REFERENCE_TYPE, but there can be call arguments with such a type; just treat it as a pointer. */ else if (TREE_CODE (TREE_TYPE (exp)) == REFERENCE_TYPE @@ -3388,7 +3393,7 @@ stabilize_aggr_init (tree call, tree *initp) takes care not to introduce additional temporaries. Returns TRUE iff the expression was successfully pre-evaluated, - i.e., if INIT is now side-effect free, except for, possible, a + i.e., if INIT is now side-effect free, except for, possibly, a single call to a constructor. */ bool @@ -3401,21 +3406,37 @@ stabilize_init (tree init, tree *initp) if (t == error_mark_node || processing_template_decl) return true; - if (TREE_CODE (t) == INIT_EXPR - && TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR - && TREE_CODE (TREE_OPERAND (t, 1)) != CONSTRUCTOR - && TREE_CODE (TREE_OPERAND (t, 1)) != AGGR_INIT_EXPR) - { - TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp); - return true; - } - if (TREE_CODE (t) == INIT_EXPR) t = TREE_OPERAND (t, 1); if (TREE_CODE (t) == TARGET_EXPR) t = TARGET_EXPR_INITIAL (t); - if (TREE_CODE (t) == COMPOUND_EXPR) - t = expr_last (t); + + /* If the RHS can be stabilized without breaking copy elision, stabilize + it. We specifically don't stabilize class prvalues here because that + would mean an extra copy, but they might be stabilized below. */ + if (TREE_CODE (init) == INIT_EXPR + && TREE_CODE (t) != CONSTRUCTOR + && TREE_CODE (t) != AGGR_INIT_EXPR + && (SCALAR_TYPE_P (TREE_TYPE (t)) + || lvalue_or_rvalue_with_address_p (t))) + { + TREE_OPERAND (init, 1) = stabilize_expr (t, initp); + return true; + } + + if (TREE_CODE (t) == COMPOUND_EXPR + && TREE_CODE (init) == INIT_EXPR) + { + tree last = expr_last (t); + /* Handle stabilizing the EMPTY_CLASS_EXPR pattern. */ + if (!TREE_SIDE_EFFECTS (last)) + { + *initp = t; + TREE_OPERAND (init, 1) = last; + return true; + } + } + if (TREE_CODE (t) == CONSTRUCTOR) { /* Aggregate initialization: stabilize each of the field @@ -3438,11 +3459,6 @@ stabilize_init (tree init, tree *initp) return good; } - /* If the initializer is a COND_EXPR, we can't preevaluate - anything. */ - if (TREE_CODE (t) == COND_EXPR) - return false; - if (TREE_CODE (t) == CALL_EXPR) { stabilize_call (t, initp); @@ -3457,7 +3473,7 @@ stabilize_init (tree init, tree *initp) /* The initialization is being performed via a bitwise copy -- and the item copied may have side effects. */ - return TREE_SIDE_EFFECTS (init); + return !TREE_SIDE_EFFECTS (init); } /* Like "fold", but should be used whenever we might be processing the diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index e67d1b12c25..0a322e3356b 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1887,6 +1887,15 @@ decay_conversion (tree exp, tsubst_flags_t complain) return error_mark_node; } + /* Don't let an array compound literal decay to a pointer. It can + still be used to initialize an array or bind to a reference. */ + if (TREE_CODE (exp) == TARGET_EXPR) + { + if (complain & tf_error) + error_at (loc, "taking address of temporary array"); + return error_mark_node; + } + ptrtype = build_pointer_type (TREE_TYPE (type)); if (TREE_CODE (exp) == VAR_DECL) |