summaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog56
-rw-r--r--gcc/cp/call.c6
-rw-r--r--gcc/cp/decl.c3
-rw-r--r--gcc/cp/decl2.c5
-rw-r--r--gcc/cp/parser.c34
-rw-r--r--gcc/cp/semantics.c1
-rw-r--r--gcc/cp/tree.c52
-rw-r--r--gcc/cp/typeck.c9
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)