re PR c++/30759 (initializer-list accepted for object of non-POD type)

gcc/

2007-06-07  Simon Martin  <simartin@users.sourceforge.net>

	PR c++/30759
	* c-common.h (flag_cpp0x): Replaced by...
	(cxx_dialect): ... this new variable specifying the C++ dialect that
	is used.
	* c-common.c (flag_cpp0x): Removed.
	(cxx_dialect): Defined.
	* c-cppbuiltin.c (c_cpp_builtins): flag_cpp0x rewritten in terms of
	cxx_dialect.
	* c-opts.c (c_common_post_options): Likewise.
	(set_std_cxx98): Set cxx_dialect to cxx98.
	(set_std_cxx0x): Set cxx_dialect to cxx0x.

gcc/cp/

2007-06-07  Simon Martin  <simartin@users.sourceforge.net>

	PR c++/30759
	* decl.c (check_initializer): Report an error when a brace enclosed
	initializer is used for a non-aggregate type in C++98.
	(redeclaration_error_message): Rewrote flag_cpp0x in terms of
	cxx_dialect.
	(grokdeclarator): Likewise.
	(move_fn_p): Likewise.
	* typeck.c (check_return_expr): Likewise.
	* call.c (reference_binding): Likewise.
	* error.c (cp_cpp_error): Likewise.
	* pt.c (check_default_tmpl_args): Likewise.
	(tsubst): Likewise.
	* lex.c (init_reswords): Likewise.
	* parser.c (p_parser_primary_expression): Likewise.
	(TOKEN_PRECEDENCE): Likewise.
	(cp_parser_init_declarator): Likewise.
	(cp_parser_ptr_operator): Likewise.
	(cp_parser_parameter_declaration): Likewise.
	(cp_parser_enclosed_template_argument_list): Likewise.
	(cp_parser_skip_to_end_of_template_parameter_list): Likewise.
	(cp_parser_next_token_ends_template_argument_p): Likewise.

gcc/testsuite/

2007-06-07  Simon Martin  <simartin@users.sourceforge.net>

	PR c++/30759
	* g++.dg/init/brace6.C: New test.

From-SVN: r125539
This commit is contained in:
Simon Martin 2007-06-07 19:59:33 +00:00 committed by Simon Martin
parent 20967296dc
commit c1ae8be51f
15 changed files with 136 additions and 43 deletions

View File

@ -1,3 +1,17 @@
2007-06-07 Simon Martin <simartin@users.sourceforge.net>
PR c++/30759
* c-common.h (flag_cpp0x): Replaced by...
(cxx_dialect): ... this new variable specifying the C++ dialect that
is used.
* c-common.c (flag_cpp0x): Removed.
(cxx_dialect): Defined.
* c-cppbuiltin.c (c_cpp_builtins): flag_cpp0x rewritten in terms of
cxx_dialect.
* c-opts.c (c_common_post_options): Likewise.
(set_std_cxx98): Set cxx_dialect to cxx98.
(set_std_cxx0x): Set cxx_dialect to cxx0x.
2007-06-06 Geoffrey Keating <geoffk@apple.com> 2007-06-06 Geoffrey Keating <geoffk@apple.com>
Hui-May Chang <hm.chang@apple.com> Hui-May Chang <hm.chang@apple.com>

View File

@ -406,10 +406,9 @@ int flag_access_control = 1;
int flag_check_new; int flag_check_new;
/* Nonzero if we want to allow the use of experimental features that /* The C++ dialect being used. C++98 is the default. */
are likely to become part of C++0x. */
int flag_cpp0x = 0; enum cxx_dialect cxx_dialect = cxx98;
/* Nonzero if we want the new ISO rules for pushing a new scope for `for' /* Nonzero if we want the new ISO rules for pushing a new scope for `for'
initialization variables. initialization variables.

View File

@ -543,10 +543,18 @@ extern int flag_access_control;
extern int flag_check_new; extern int flag_check_new;
/* Nonzero if we want to allow the use of experimental features that /* The supported C++ dialects. */
are likely to become part of C++0x. */
extern int flag_cpp0x; enum cxx_dialect {
/* C++98 */
cxx98,
/* Experimental features that are likely to become part of
C++0x. */
cxx0x
};
/* The C++ dialect being used. C++98 is the default. */
extern enum cxx_dialect cxx_dialect;
/* Nonzero if we want the new ISO rules for pushing a new scope for `for' /* Nonzero if we want the new ISO rules for pushing a new scope for `for'
initialization variables. initialization variables.

View File

@ -419,7 +419,7 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__GXX_WEAK__=0"); cpp_define (pfile, "__GXX_WEAK__=0");
if (warn_deprecated) if (warn_deprecated)
cpp_define (pfile, "__DEPRECATED"); cpp_define (pfile, "__DEPRECATED");
if (flag_cpp0x) if (cxx_dialect == cxx0x)
cpp_define (pfile, "__GXX_EXPERIMENTAL_CXX0X__"); cpp_define (pfile, "__GXX_EXPERIMENTAL_CXX0X__");
} }
/* Note that we define this for C as well, so that we know if /* Note that we define this for C as well, so that we know if

View File

@ -1145,7 +1145,7 @@ c_common_post_options (const char **pfilename)
/* If we're allowing C++0x constructs, don't warn about C++0x /* If we're allowing C++0x constructs, don't warn about C++0x
compatibility problems. */ compatibility problems. */
if (flag_cpp0x) if (cxx_dialect == cxx0x)
warn_cxx0x_compat = 0; warn_cxx0x_compat = 0;
if (flag_preprocess_only) if (flag_preprocess_only)
@ -1610,6 +1610,7 @@ set_std_cxx98 (int iso)
flag_no_gnu_keywords = iso; flag_no_gnu_keywords = iso;
flag_no_nonansi_builtin = iso; flag_no_nonansi_builtin = iso;
flag_iso = iso; flag_iso = iso;
cxx_dialect = cxx98;
} }
/* Set the C++ 0x working draft "standard" (without GNU extensions if ISO). */ /* Set the C++ 0x working draft "standard" (without GNU extensions if ISO). */
@ -1620,7 +1621,7 @@ set_std_cxx0x (int iso)
flag_no_gnu_keywords = iso; flag_no_gnu_keywords = iso;
flag_no_nonansi_builtin = iso; flag_no_nonansi_builtin = iso;
flag_iso = iso; flag_iso = iso;
flag_cpp0x = 1; cxx_dialect = cxx0x;
} }
/* Handle setting implicit to ON. */ /* Handle setting implicit to ON. */

View File

@ -1,3 +1,27 @@
2007-06-07 Simon Martin <simartin@users.sourceforge.net>
PR c++/30759
* decl.c (check_initializer): Report an error when a brace enclosed
initializer is used for a non-aggregate type in C++98.
(redeclaration_error_message): Rewrote flag_cpp0x in terms of
cxx_dialect.
(grokdeclarator): Likewise.
(move_fn_p): Likewise.
* typeck.c (check_return_expr): Likewise.
* call.c (reference_binding): Likewise.
* error.c (cp_cpp_error): Likewise.
* pt.c (check_default_tmpl_args): Likewise.
(tsubst): Likewise.
* lex.c (init_reswords): Likewise.
* parser.c (p_parser_primary_expression): Likewise.
(TOKEN_PRECEDENCE): Likewise.
(cp_parser_init_declarator): Likewise.
(cp_parser_ptr_operator): Likewise.
(cp_parser_parameter_declaration): Likewise.
(cp_parser_enclosed_template_argument_list): Likewise.
(cp_parser_skip_to_end_of_template_parameter_list): Likewise.
(cp_parser_next_token_ends_template_argument_p): Likewise.
2007-06-04 Simon Baldwin <simonb@google.com> 2007-06-04 Simon Baldwin <simonb@google.com>
* decl.c (grokdeclarator): Readability change. Moved case labels * decl.c (grokdeclarator): Readability change. Moved case labels

View File

@ -1160,7 +1160,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
DR391. */ DR391. */
if (compatible_p if (compatible_p
&& (lvalue_p && (lvalue_p
|| (flag_cpp0x || ((cxx_dialect != cxx98)
&& (CP_TYPE_CONST_NON_VOLATILE_P(to) || TYPE_REF_IS_RVALUE (rto)) && (CP_TYPE_CONST_NON_VOLATILE_P(to) || TYPE_REF_IS_RVALUE (rto))
&& CLASS_TYPE_P (from)))) && CLASS_TYPE_P (from))))
{ {

View File

@ -2161,7 +2161,7 @@ redeclaration_error_message (tree newdecl, tree olddecl)
default template-argument, that declaration shall be a default template-argument, that declaration shall be a
definition and shall be the only declaration of the definition and shall be the only declaration of the
function template in the translation unit. */ function template in the translation unit. */
if (flag_cpp0x if ((cxx_dialect != cxx98)
&& TREE_CODE (ot) == FUNCTION_DECL && DECL_FRIEND_P (ot) && TREE_CODE (ot) == FUNCTION_DECL && DECL_FRIEND_P (ot)
&& !check_default_tmpl_args (nt, DECL_TEMPLATE_PARMS (newdecl), && !check_default_tmpl_args (nt, DECL_TEMPLATE_PARMS (newdecl),
/*is_primary=*/1, /*is_partial=*/0, /*is_primary=*/1, /*is_partial=*/0,
@ -4777,14 +4777,29 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
else else
/* There is no way to make a variable-sized class type in GNU C++. */ /* There is no way to make a variable-sized class type in GNU C++. */
gcc_assert (TREE_CONSTANT (TYPE_SIZE (type))); gcc_assert (TREE_CONSTANT (TYPE_SIZE (type)));
if (!CP_AGGREGATE_TYPE_P (type) if (init && BRACE_ENCLOSED_INITIALIZER_P (init))
&& init && BRACE_ENCLOSED_INITIALIZER_P (init)
&& VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)) != 1)
{ {
error ("scalar object %qD requires one element in initializer", decl); int init_len = VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init));
TREE_TYPE (decl) = error_mark_node; if (SCALAR_TYPE_P (type))
return NULL_TREE; {
if (init_len != 1)
{
error ("scalar object %qD requires one element in initializer",
decl);
TREE_TYPE (decl) = error_mark_node;
return NULL_TREE;
}
}
else if ((cxx_dialect == cxx98) && !CP_AGGREGATE_TYPE_P (type))
{
/* A non-aggregate that is not a scalar cannot be initialized
via an initializer-list in C++98. */
error ("braces around initializer for non-aggregate type %qT",
type);
TREE_TYPE (decl) = error_mark_node;
return NULL_TREE;
}
} }
if (TREE_CODE (decl) == CONST_DECL) if (TREE_CODE (decl) == CONST_DECL)
@ -7871,7 +7886,7 @@ grokdeclarator (const cp_declarator *declarator,
are still forbidden, occurs below. Reasoning behind the change are still forbidden, occurs below. Reasoning behind the change
can be found in DR106, DR540, and the rvalue reference can be found in DR106, DR540, and the rvalue reference
proposals. */ proposals. */
else if (!flag_cpp0x) else if (cxx_dialect == cxx98)
{ {
error ("cannot declare reference to %q#T", type); error ("cannot declare reference to %q#T", type);
type = TREE_TYPE (type); type = TREE_TYPE (type);
@ -9217,8 +9232,8 @@ move_fn_p (tree d)
gcc_assert (DECL_FUNCTION_MEMBER_P (d)); gcc_assert (DECL_FUNCTION_MEMBER_P (d));
if (!flag_cpp0x) if (cxx_dialect == cxx98)
/* There are no move constructors if we aren't in C++0x mode. */ /* There are no move constructors if we are in C++98 mode. */
return false; return false;
if (TREE_CODE (d) == TEMPLATE_DECL if (TREE_CODE (d) == TEMPLATE_DECL

View File

@ -2549,7 +2549,7 @@ cp_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level,
void void
maybe_warn_variadic_templates (void) maybe_warn_variadic_templates (void)
{ {
if (!flag_cpp0x && !in_system_header) if ((cxx_dialect == cxx98) && !in_system_header)
/* We really want to suppress this warning in system headers, /* We really want to suppress this warning in system headers,
because libstdc++ uses variadic templates even when we aren't because libstdc++ uses variadic templates even when we aren't
in C++0x mode. */ in C++0x mode. */

View File

@ -334,7 +334,7 @@ init_reswords (void)
int mask = ((flag_no_asm ? D_ASM : 0) int mask = ((flag_no_asm ? D_ASM : 0)
| D_OBJC | D_OBJC
| (flag_no_gnu_keywords ? D_EXT : 0) | (flag_no_gnu_keywords ? D_EXT : 0)
| (flag_cpp0x ? 0 : D_CXX0X)); | ((cxx_dialect == cxx0x) ? 0 : D_CXX0X));
ridpointers = GGC_CNEWVEC (tree, (int) RID_MAX); ridpointers = GGC_CNEWVEC (tree, (int) RID_MAX);
for (i = 0; i < ARRAY_SIZE (reswords); i++) for (i = 0; i < ARRAY_SIZE (reswords); i++)

View File

@ -3109,7 +3109,7 @@ cp_parser_primary_expression (cp_parser *parser,
/* C++0x only: A ">>" treated like two ">" tokens, /* C++0x only: A ">>" treated like two ">" tokens,
in a template-argument-list. */ in a template-argument-list. */
&& (next_token->type != CPP_RSHIFT && (next_token->type != CPP_RSHIFT
|| !flag_cpp0x || (cxx_dialect == cxx98)
|| parser->greater_than_is_operator_p)) || parser->greater_than_is_operator_p))
cast_p = false; cast_p = false;
} }
@ -5887,11 +5887,11 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
The binops_by_token map is used to get the tree codes for each <token> type. The binops_by_token map is used to get the tree codes for each <token> type.
binary-expressions are associated according to a precedence table. */ binary-expressions are associated according to a precedence table. */
#define TOKEN_PRECEDENCE(token) \ #define TOKEN_PRECEDENCE(token) \
(((token->type == CPP_GREATER \ (((token->type == CPP_GREATER \
|| (flag_cpp0x && token->type == CPP_RSHIFT)) \ || ((cxx_dialect != cxx98) && token->type == CPP_RSHIFT)) \
&& !parser->greater_than_is_operator_p) \ && !parser->greater_than_is_operator_p) \
? PREC_NOT_OPERATOR \ ? PREC_NOT_OPERATOR \
: binops_by_token[token->type].prec) : binops_by_token[token->type].prec)
static tree static tree
@ -11974,7 +11974,8 @@ cp_parser_init_declarator (cp_parser* parser,
((is_parenthesized_init || !is_initialized) ((is_parenthesized_init || !is_initialized)
? 0 : LOOKUP_ONLYCONVERTING)); ? 0 : LOOKUP_ONLYCONVERTING));
} }
else if (flag_cpp0x && friend_p && decl && TREE_CODE (decl) == FUNCTION_DECL) else if ((cxx_dialect != cxx98) && friend_p
&& decl && TREE_CODE (decl) == FUNCTION_DECL)
/* Core issue #226 (C++0x only): A default template-argument /* Core issue #226 (C++0x only): A default template-argument
shall not be specified in a friend class template shall not be specified in a friend class template
declaration. */ declaration. */
@ -12590,7 +12591,8 @@ cp_parser_ptr_operator (cp_parser* parser,
code = INDIRECT_REF; code = INDIRECT_REF;
else if (token->type == CPP_AND) else if (token->type == CPP_AND)
code = ADDR_EXPR; code = ADDR_EXPR;
else if (flag_cpp0x && token->type == CPP_AND_AND) /* C++0x only */ else if ((cxx_dialect != cxx98) &&
token->type == CPP_AND_AND) /* C++0x only */
code = NON_LVALUE_EXPR; code = NON_LVALUE_EXPR;
if (code != ERROR_MARK) if (code != ERROR_MARK)
@ -13273,7 +13275,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
break; break;
case CPP_RSHIFT: case CPP_RSHIFT:
if (!flag_cpp0x) if (cxx_dialect == cxx98)
break; break;
/* Fall through for C++0x, which treats the `>>' /* Fall through for C++0x, which treats the `>>'
operator like two `>' tokens in certain operator like two `>' tokens in certain
@ -16808,7 +16810,7 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
a '>>' instead, it's probably just a typo. */ a '>>' instead, it's probably just a typo. */
if (cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT)) if (cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT))
{ {
if (flag_cpp0x) if (cxx_dialect != cxx98)
{ {
/* In C++0x, a `>>' in a template argument list or cast /* In C++0x, a `>>' in a template argument list or cast
expression is considered to be two separate `>' expression is considered to be two separate `>'
@ -17338,7 +17340,7 @@ cp_parser_skip_to_end_of_template_parameter_list (cp_parser* parser)
break; break;
case CPP_RSHIFT: case CPP_RSHIFT:
if (!flag_cpp0x) if (cxx_dialect == cxx98)
/* C++0x views the `>>' operator as two `>' tokens, but /* C++0x views the `>>' operator as two `>' tokens, but
C++98 does not. */ C++98 does not. */
break; break;
@ -17460,7 +17462,7 @@ cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
return (token->type == CPP_COMMA return (token->type == CPP_COMMA
|| token->type == CPP_GREATER || token->type == CPP_GREATER
|| token->type == CPP_ELLIPSIS || token->type == CPP_ELLIPSIS
|| (flag_cpp0x && token->type == CPP_RSHIFT)); || ((cxx_dialect != cxx98) && token->type == CPP_RSHIFT));
} }
/* Returns TRUE iff the n-th token is a "<", or the n-th is a "[" and the /* Returns TRUE iff the n-th token is a "<", or the n-th is a "[" and the

View File

@ -3447,7 +3447,7 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary,
/* Core issue 226 (C++0x only): the following only applies to class /* Core issue 226 (C++0x only): the following only applies to class
templates. */ templates. */
if (!flag_cpp0x || TREE_CODE (decl) != FUNCTION_DECL) if ((cxx_dialect == cxx98) || TREE_CODE (decl) != FUNCTION_DECL)
{ {
/* [temp.param] /* [temp.param]
@ -3482,7 +3482,7 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary,
} }
} }
if ((!flag_cpp0x && TREE_CODE (decl) != TYPE_DECL) if (((cxx_dialect == cxx98) && TREE_CODE (decl) != TYPE_DECL)
|| is_partial || is_partial
|| !is_primary || !is_primary
|| is_friend_decl) || is_friend_decl)
@ -3510,7 +3510,7 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary,
msg = "default template arguments may not be used in function template friend re-declaration"; msg = "default template arguments may not be used in function template friend re-declaration";
else if (is_friend_decl) else if (is_friend_decl)
msg = "default template arguments may not be used in function template friend declarations"; msg = "default template arguments may not be used in function template friend declarations";
else if (TREE_CODE (decl) == FUNCTION_DECL && !flag_cpp0x) else if (TREE_CODE (decl) == FUNCTION_DECL && (cxx_dialect == cxx98))
msg = "default template arguments may not be used in function templates"; msg = "default template arguments may not be used in function templates";
else if (is_partial) else if (is_partial)
msg = "default template arguments may not be used in partial specializations"; msg = "default template arguments may not be used in partial specializations";
@ -8736,7 +8736,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
during instantiation is no longer a cause for failure. We during instantiation is no longer a cause for failure. We
only enforce this check in strict C++98 mode. */ only enforce this check in strict C++98 mode. */
if ((TREE_CODE (type) == REFERENCE_TYPE if ((TREE_CODE (type) == REFERENCE_TYPE
&& ((!flag_cpp0x && flag_iso) || code != REFERENCE_TYPE)) && (((cxx_dialect == cxx98) && flag_iso) || code != REFERENCE_TYPE))
|| (code == REFERENCE_TYPE && TREE_CODE (type) == VOID_TYPE)) || (code == REFERENCE_TYPE && TREE_CODE (type) == VOID_TYPE))
{ {
static location_t last_loc; static location_t last_loc;
@ -11537,9 +11537,9 @@ type_unification_real (tree tparms,
If a template argument has not been deduced, its If a template argument has not been deduced, its
default template argument, if any, is used. default template argument, if any, is used.
When we are not in C++0x mode (i.e., !flag_cpp0x), When we are in C++98 mode, TREE_PURPOSE will either
TREE_PURPOSE will either be NULL_TREE or ERROR_MARK_NODE, be NULL_TREE or ERROR_MARK_NODE, so we do not need
so we do not need to explicitly check flag_cpp0x here. */ to explicitly check cxx_dialect here. */
if (TREE_PURPOSE (TREE_VEC_ELT (tparms, i))) if (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)))
{ {
tree arg = tsubst (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)), tree arg = tsubst (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)),

View File

@ -6733,7 +6733,7 @@ check_return_expr (tree retval, bool *no_warning)
/* Under C++0x [12.8/16 class.copy], a returned lvalue is sometimes /* Under C++0x [12.8/16 class.copy], a returned lvalue is sometimes
treated as an rvalue for the purposes of overload resolution to treated as an rvalue for the purposes of overload resolution to
favor move constructors over copy constructors. */ favor move constructors over copy constructors. */
if (flag_cpp0x if ((cxx_dialect != cxx98)
&& named_return_value_okay_p && named_return_value_okay_p
/* The variable must not have the `volatile' qualifier. */ /* The variable must not have the `volatile' qualifier. */
&& !(cp_type_quals (TREE_TYPE (retval)) & TYPE_QUAL_VOLATILE) && !(cp_type_quals (TREE_TYPE (retval)) & TYPE_QUAL_VOLATILE)

View File

@ -1,3 +1,8 @@
2007-06-07 Simon Martin <simartin@users.sourceforge.net>
PR c++/30759
* g++.dg/init/brace6.C: New test.
2007-06-07 Geoffrey Keating <geoffk@apple.com> 2007-06-07 Geoffrey Keating <geoffk@apple.com>
* gcc.dg/attr-weakref-1-darwin.c: Run on all Darwin platforms. * gcc.dg/attr-weakref-1-darwin.c: Run on all Darwin platforms.

View File

@ -0,0 +1,25 @@
/* PR c++/30759 */
/* { dg-do "compile" } */
struct A {
A(int) { }
};
struct B {
B(const B&);
int b;
};
struct C {};
struct D { int c; };
int main()
{
int i = { 1 };
int j = { 1, 2 }; /* { dg-error "requires one element" } */
A a = { 6 }; /* { dg-error "initializer for non" } */
B b = { 6 }; /* { dg-error "initializer for non" } */
C c = { 6 }; /* { dg-error "too many initializers" } */
D d = { 6 };
}