mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-23 09:40:54 +08:00
cp-tree.def (STATIC_ASSERT): New.
2006-11-21 Douglas Gregor <doug.gregor@gmail.com> * cp-tree.def (STATIC_ASSERT): New. * cp-objcp-common.c (cp_tree_size): Handle STATIC_ASSERT. * error.c (dump_decl): Handle STATIC_ASSERT. * cp-tree.h (STATIC_ASSERT_CONDITION): New. (STATIC_ASSERT_MESSAGE): New. (STATIC_ASSERT_SOURCE_LOCATION): New. (struct tree_static_assert): New. (enum cp_tree_node_structure_enum): Add TS_CP_STATIC_ASSERT. (union lang_tree_node): Add static_assertion. (finish_static_assert): Declare. * cxx-pretty-print.c (pp_cxx_statement): Handle STATIC_ASSERT. (pp_cxx_declaration): Handle STATIC_ASSERT. * pt.c (instantiate_class_template): Handle STATIC_ASSERT members. (tsubst_expr): Handle STATIC_ASSERT statements. * semantics.c (finish_static_assert): New. * lex.c (D_CPP0X): New. (reswords): Add static_assert keyword. (init_reswords): If not flag_cpp0x, mask out C++0x keywords. * parser.c (cp_parser_block_declaration): Parse static assertions. (cp_parser_static_assert): New. (cp_parser_member_declaration): Parse static assertions. From-SVN: r119066
This commit is contained in:
parent
218f00156c
commit
55a3debe44
@ -1,3 +1,29 @@
|
||||
2006-11-21 Douglas Gregor <doug.gregor@gmail.com>
|
||||
|
||||
* cp-tree.def (STATIC_ASSERT): New.
|
||||
* cp-objcp-common.c (cp_tree_size): Handle STATIC_ASSERT.
|
||||
* error.c (dump_decl): Handle STATIC_ASSERT.
|
||||
* cp-tree.h (STATIC_ASSERT_CONDITION): New.
|
||||
(STATIC_ASSERT_MESSAGE): New.
|
||||
(STATIC_ASSERT_SOURCE_LOCATION): New.
|
||||
(struct tree_static_assert): New.
|
||||
(enum cp_tree_node_structure_enum): Add TS_CP_STATIC_ASSERT.
|
||||
(union lang_tree_node): Add static_assertion.
|
||||
(finish_static_assert): Declare.
|
||||
* cxx-pretty-print.c (pp_cxx_statement): Handle STATIC_ASSERT.
|
||||
(pp_cxx_declaration): Handle STATIC_ASSERT.
|
||||
* pt.c (instantiate_class_template): Handle
|
||||
STATIC_ASSERT members.
|
||||
(tsubst_expr): Handle STATIC_ASSERT statements.
|
||||
* semantics.c (finish_static_assert): New.
|
||||
* lex.c (D_CPP0X): New.
|
||||
(reswords): Add static_assert keyword.
|
||||
(init_reswords): If not flag_cpp0x, mask out C++0x keywords.
|
||||
* parser.c (cp_parser_block_declaration): Parse static
|
||||
assertions.
|
||||
(cp_parser_static_assert): New.
|
||||
(cp_parser_member_declaration): Parse static assertions.
|
||||
|
||||
2006-11-21 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/29570
|
||||
|
@ -123,6 +123,7 @@ cp_tree_size (enum tree_code code)
|
||||
case TEMPLATE_PARM_INDEX: return sizeof (template_parm_index);
|
||||
case DEFAULT_ARG: return sizeof (struct tree_default_arg);
|
||||
case OVERLOAD: return sizeof (struct tree_overload);
|
||||
case STATIC_ASSERT: return sizeof (struct tree_static_assert);
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
@ -342,6 +342,14 @@ DEFTREECODE (STMT_EXPR, "stmt_expr", tcc_expression, 1)
|
||||
is applied. */
|
||||
DEFTREECODE (UNARY_PLUS_EXPR, "unary_plus_expr", tcc_unary, 1)
|
||||
|
||||
/** C++0x extensions. */
|
||||
|
||||
/* A static assertion. This is a C++0x extension.
|
||||
STATIC_ASSERT_CONDITION contains the condition that is being
|
||||
checked. STATIC_ASSERT_MESSAGE contains the message (a string
|
||||
literal) to be displayed if the condition fails to hold. */
|
||||
DEFTREECODE (STATIC_ASSERT, "static_assert", tcc_exceptional, 0)
|
||||
|
||||
/*
|
||||
Local variables:
|
||||
mode:c
|
||||
|
@ -446,6 +446,29 @@ struct tree_default_arg GTY (())
|
||||
VEC(tree,gc) *instantiations;
|
||||
};
|
||||
|
||||
/* The condition associated with the static assertion. This must be
|
||||
an integral constant expression. */
|
||||
#define STATIC_ASSERT_CONDITION(NODE) \
|
||||
(((struct tree_static_assert *)STATIC_ASSERT_CHECK (NODE))->condition)
|
||||
|
||||
/* The message associated with the static assertion. This must be a
|
||||
string constant, which will be emitted as an error message when the
|
||||
static assert condition is false. */
|
||||
#define STATIC_ASSERT_MESSAGE(NODE) \
|
||||
(((struct tree_static_assert *)STATIC_ASSERT_CHECK (NODE))->message)
|
||||
|
||||
/* Source location information for a static assertion. */
|
||||
#define STATIC_ASSERT_SOURCE_LOCATION(NODE) \
|
||||
(((struct tree_static_assert *)STATIC_ASSERT_CHECK (NODE))->location)
|
||||
|
||||
struct tree_static_assert GTY (())
|
||||
{
|
||||
struct tree_common common;
|
||||
tree condition;
|
||||
tree message;
|
||||
location_t location;
|
||||
};
|
||||
|
||||
enum cp_tree_node_structure_enum {
|
||||
TS_CP_GENERIC,
|
||||
TS_CP_IDENTIFIER,
|
||||
@ -457,6 +480,7 @@ enum cp_tree_node_structure_enum {
|
||||
TS_CP_BASELINK,
|
||||
TS_CP_WRAPPER,
|
||||
TS_CP_DEFAULT_ARG,
|
||||
TS_CP_STATIC_ASSERT,
|
||||
LAST_TS_CP_ENUM
|
||||
};
|
||||
|
||||
@ -473,6 +497,8 @@ union lang_tree_node GTY((desc ("cp_tree_node_structure (&%h)"),
|
||||
struct tree_baselink GTY ((tag ("TS_CP_BASELINK"))) baselink;
|
||||
struct tree_default_arg GTY ((tag ("TS_CP_DEFAULT_ARG"))) default_arg;
|
||||
struct lang_identifier GTY ((tag ("TS_CP_IDENTIFIER"))) identifier;
|
||||
struct tree_static_assert GTY ((tag ("TS_CP_STATIC_ASSERT")))
|
||||
static_assertion;
|
||||
};
|
||||
|
||||
|
||||
@ -4326,6 +4352,8 @@ extern tree cxx_omp_clause_assign_op (tree, tree, tree);
|
||||
extern tree cxx_omp_clause_dtor (tree, tree);
|
||||
extern bool cxx_omp_privatize_by_reference (tree);
|
||||
extern tree baselink_for_fns (tree);
|
||||
extern void finish_static_assert (tree, tree, location_t,
|
||||
bool);
|
||||
|
||||
/* in tree.c */
|
||||
extern void lang_check_failed (const char *, int,
|
||||
|
@ -1711,6 +1711,10 @@ pp_cxx_statement (cxx_pretty_printer *pp, tree t)
|
||||
pp_newline_and_indent (pp, -2);
|
||||
break;
|
||||
|
||||
case STATIC_ASSERT:
|
||||
pp_cxx_declaration (pp, t);
|
||||
break;
|
||||
|
||||
default:
|
||||
pp_c_statement (pp_c_base (pp), t);
|
||||
break;
|
||||
@ -1906,11 +1910,21 @@ pp_cxx_explicit_instantiation (cxx_pretty_printer *pp, tree t)
|
||||
asm-definition
|
||||
namespace-alias-definition
|
||||
using-declaration
|
||||
using-directive */
|
||||
using-directive
|
||||
static_assert-declaration */
|
||||
void
|
||||
pp_cxx_declaration (cxx_pretty_printer *pp, tree t)
|
||||
{
|
||||
if (!DECL_LANG_SPECIFIC (t))
|
||||
if (TREE_CODE (t) == STATIC_ASSERT)
|
||||
{
|
||||
pp_cxx_identifier (pp, "static_assert");
|
||||
pp_cxx_left_paren (pp);
|
||||
pp_cxx_expression (pp, STATIC_ASSERT_CONDITION (t));
|
||||
pp_cxx_separate_with (pp, ',');
|
||||
pp_cxx_expression (pp, STATIC_ASSERT_MESSAGE (t));
|
||||
pp_cxx_right_paren (pp);
|
||||
}
|
||||
else if (!DECL_LANG_SPECIFIC (t))
|
||||
pp_cxx_simple_declaration (pp, t);
|
||||
else if (DECL_USE_TEMPLATE (t))
|
||||
switch (DECL_USE_TEMPLATE (t))
|
||||
|
@ -886,6 +886,10 @@ dump_decl (tree t, int flags)
|
||||
dump_decl (DECL_NAME (t), flags);
|
||||
break;
|
||||
|
||||
case STATIC_ASSERT:
|
||||
pp_cxx_declaration (cxx_pp, t);
|
||||
break;
|
||||
|
||||
case BASELINK:
|
||||
dump_decl (BASELINK_FUNCTIONS (t), flags);
|
||||
break;
|
||||
|
@ -176,6 +176,7 @@ struct resword
|
||||
#define D_EXT 0x01 /* GCC extension */
|
||||
#define D_ASM 0x02 /* in C99, but has a switch to turn it off */
|
||||
#define D_OBJC 0x04 /* Objective C++ only */
|
||||
#define D_CPP0X 0x08 /* C++0x only */
|
||||
|
||||
CONSTRAINT(ridbits_fit, RID_LAST_MODIFIER < sizeof(unsigned long) * CHAR_BIT);
|
||||
|
||||
@ -259,6 +260,7 @@ static const struct resword reswords[] =
|
||||
{ "signed", RID_SIGNED, 0 },
|
||||
{ "sizeof", RID_SIZEOF, 0 },
|
||||
{ "static", RID_STATIC, 0 },
|
||||
{ "static_assert", RID_STATIC_ASSERT, D_CPP0X },
|
||||
{ "static_cast", RID_STATCAST, 0 },
|
||||
{ "struct", RID_STRUCT, 0 },
|
||||
{ "switch", RID_SWITCH, 0 },
|
||||
@ -314,7 +316,8 @@ init_reswords (void)
|
||||
tree id;
|
||||
int mask = ((flag_no_asm ? D_ASM : 0)
|
||||
| D_OBJC
|
||||
| (flag_no_gnu_keywords ? D_EXT : 0));
|
||||
| (flag_no_gnu_keywords ? D_EXT : 0)
|
||||
| (flag_cpp0x ? 0 : D_CPP0X));
|
||||
|
||||
ridpointers = GGC_CNEWVEC (tree, (int) RID_MAX);
|
||||
for (i = 0; i < ARRAY_SIZE (reswords); i++)
|
||||
|
@ -1589,6 +1589,8 @@ static void cp_parser_asm_definition
|
||||
(cp_parser *);
|
||||
static void cp_parser_linkage_specification
|
||||
(cp_parser *);
|
||||
static void cp_parser_static_assert
|
||||
(cp_parser *, bool);
|
||||
|
||||
/* Declarators [gram.dcl.decl] */
|
||||
|
||||
@ -7211,6 +7213,11 @@ cp_parser_declaration (cp_parser* parser)
|
||||
__extension__ block-declaration
|
||||
label-declaration
|
||||
|
||||
C++0x Extension:
|
||||
|
||||
block-declaration:
|
||||
static_assert-declaration
|
||||
|
||||
If STATEMENT_P is TRUE, then this block-declaration is occurring as
|
||||
part of a declaration-statement. */
|
||||
|
||||
@ -7272,6 +7279,9 @@ cp_parser_block_declaration (cp_parser *parser,
|
||||
cp_parser_commit_to_tentative_parse (parser);
|
||||
cp_parser_label_declaration (parser);
|
||||
}
|
||||
/* If the next token is `static_assert' we have a static assertion. */
|
||||
else if (token1->keyword == RID_STATIC_ASSERT)
|
||||
cp_parser_static_assert (parser, /*member_p=*/false);
|
||||
/* Anything else must be a simple-declaration. */
|
||||
else
|
||||
cp_parser_simple_declaration (parser, !statement_p);
|
||||
@ -7825,6 +7835,68 @@ cp_parser_linkage_specification (cp_parser* parser)
|
||||
pop_lang_context ();
|
||||
}
|
||||
|
||||
/* Parse a static_assert-declaration.
|
||||
|
||||
static_assert-declaration:
|
||||
static_assert ( constant-expression , string-literal ) ;
|
||||
|
||||
If MEMBER_P, this static_assert is a class member. */
|
||||
|
||||
static void
|
||||
cp_parser_static_assert(cp_parser *parser, bool member_p)
|
||||
{
|
||||
tree condition;
|
||||
tree message;
|
||||
cp_token *token;
|
||||
location_t saved_loc;
|
||||
|
||||
/* Peek at the `static_assert' token so we can keep track of exactly
|
||||
where the static assertion started. */
|
||||
token = cp_lexer_peek_token (parser->lexer);
|
||||
saved_loc = token->location;
|
||||
|
||||
/* Look for the `static_assert' keyword. */
|
||||
if (!cp_parser_require_keyword (parser, RID_STATIC_ASSERT,
|
||||
"`static_assert'"))
|
||||
return;
|
||||
|
||||
/* We know we are in a static assertion; commit to any tentative
|
||||
parse. */
|
||||
if (cp_parser_parsing_tentatively (parser))
|
||||
cp_parser_commit_to_tentative_parse (parser);
|
||||
|
||||
/* Parse the `(' starting the static assertion condition. */
|
||||
cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
|
||||
|
||||
/* Parse the constant-expression. */
|
||||
condition =
|
||||
cp_parser_constant_expression (parser,
|
||||
/*allow_non_constant_p=*/false,
|
||||
/*non_constant_p=*/NULL);
|
||||
|
||||
/* Parse the separating `,'. */
|
||||
cp_parser_require (parser, CPP_COMMA, "`,'");
|
||||
|
||||
/* Parse the string-literal message. */
|
||||
message = cp_parser_string_literal (parser,
|
||||
/*translate=*/false,
|
||||
/*wide_ok=*/true);
|
||||
|
||||
/* A `)' completes the static assertion. */
|
||||
if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
|
||||
cp_parser_skip_to_closing_parenthesis (parser,
|
||||
/*recovering=*/true,
|
||||
/*or_comma=*/false,
|
||||
/*consume_paren=*/true);
|
||||
|
||||
/* A semicolon terminates the declaration. */
|
||||
cp_parser_require (parser, CPP_SEMICOLON, "`;'");
|
||||
|
||||
/* Complete the static assertion, which may mean either processing
|
||||
the static assert now or saving it for template instantiation. */
|
||||
finish_static_assert (condition, message, saved_loc, member_p);
|
||||
}
|
||||
|
||||
/* Special member functions [gram.special] */
|
||||
|
||||
/* Parse a conversion-function-id.
|
||||
@ -13624,7 +13696,12 @@ cp_parser_member_specification_opt (cp_parser* parser)
|
||||
member-declarator:
|
||||
declarator attributes [opt] pure-specifier [opt]
|
||||
declarator attributes [opt] constant-initializer [opt]
|
||||
identifier [opt] attributes [opt] : constant-expression */
|
||||
identifier [opt] attributes [opt] : constant-expression
|
||||
|
||||
C++0x Extensions:
|
||||
|
||||
member-declaration:
|
||||
static_assert-declaration */
|
||||
|
||||
static void
|
||||
cp_parser_member_declaration (cp_parser* parser)
|
||||
@ -13687,6 +13764,13 @@ cp_parser_member_declaration (cp_parser* parser)
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the next token is `static_assert' we have a static assertion. */
|
||||
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC_ASSERT))
|
||||
{
|
||||
cp_parser_static_assert (parser, /*member_p=*/true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cp_parser_using_declaration (parser, /*access_declaration=*/true))
|
||||
return;
|
||||
|
||||
|
28
gcc/cp/pt.c
28
gcc/cp/pt.c
@ -5886,8 +5886,18 @@ instantiate_class_template (tree type)
|
||||
else
|
||||
{
|
||||
/* Build new TYPE_FIELDS. */
|
||||
|
||||
if (TREE_CODE (t) != CONST_DECL)
|
||||
if (TREE_CODE (t) == STATIC_ASSERT)
|
||||
{
|
||||
tree condition =
|
||||
tsubst_expr (STATIC_ASSERT_CONDITION (t), args,
|
||||
tf_warning_or_error, NULL_TREE,
|
||||
/*integral_constant_expression_p=*/true);
|
||||
finish_static_assert (condition,
|
||||
STATIC_ASSERT_MESSAGE (t),
|
||||
STATIC_ASSERT_SOURCE_LOCATION (t),
|
||||
/*member_p=*/true);
|
||||
}
|
||||
else if (TREE_CODE (t) != CONST_DECL)
|
||||
{
|
||||
tree r;
|
||||
|
||||
@ -8716,6 +8726,20 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
|
||||
tsubst (TREE_TYPE (t), args, complain, NULL_TREE);
|
||||
break;
|
||||
|
||||
case STATIC_ASSERT:
|
||||
{
|
||||
tree condition =
|
||||
tsubst_expr (STATIC_ASSERT_CONDITION (t),
|
||||
args,
|
||||
complain, in_decl,
|
||||
/*integral_constant_expression_p=*/true);
|
||||
finish_static_assert (condition,
|
||||
STATIC_ASSERT_MESSAGE (t),
|
||||
STATIC_ASSERT_SOURCE_LOCATION (t),
|
||||
/*member_p=*/false);
|
||||
}
|
||||
break;
|
||||
|
||||
case OMP_PARALLEL:
|
||||
tmp = tsubst_omp_clauses (OMP_PARALLEL_CLAUSES (t),
|
||||
args, complain, in_decl);
|
||||
|
@ -3914,5 +3914,57 @@ void
|
||||
init_cp_semantics (void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Build a STATIC_ASSERT for a static assertion with the condition
|
||||
CONDITION and the message text MESSAGE. LOCATION is the location
|
||||
of the static assertion in the source code. When MEMBER_P, this
|
||||
static assertion is a member of a class. */
|
||||
void
|
||||
finish_static_assert (tree condition, tree message, location_t location,
|
||||
bool member_p)
|
||||
{
|
||||
if (type_dependent_expression_p (condition)
|
||||
|| value_dependent_expression_p (condition))
|
||||
{
|
||||
/* We're in a template; build a STATIC_ASSERT and put it in
|
||||
the right place. */
|
||||
tree assertion;
|
||||
|
||||
assertion = make_node (STATIC_ASSERT);
|
||||
STATIC_ASSERT_CONDITION (assertion) = condition;
|
||||
STATIC_ASSERT_MESSAGE (assertion) = message;
|
||||
STATIC_ASSERT_SOURCE_LOCATION (assertion) = location;
|
||||
|
||||
if (member_p)
|
||||
maybe_add_class_template_decl_list (current_class_type,
|
||||
assertion,
|
||||
/*friend_p=*/0);
|
||||
else
|
||||
add_stmt (assertion);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fold the expression and convert it to a boolean value. */
|
||||
condition = fold_non_dependent_expr (condition);
|
||||
condition = cp_convert (boolean_type_node, condition);
|
||||
|
||||
if (TREE_CODE (condition) == INTEGER_CST && !integer_zerop (condition))
|
||||
/* Do nothing; the condition is satisfied. */
|
||||
;
|
||||
else
|
||||
{
|
||||
location_t saved_loc = input_location;
|
||||
|
||||
input_location = location;
|
||||
if (TREE_CODE (condition) == INTEGER_CST
|
||||
&& integer_zerop (condition))
|
||||
/* Report the error. */
|
||||
error ("static assertion failed: %E", message);
|
||||
else if (condition && condition != error_mark_node)
|
||||
error ("non-constant condition for static assertion");
|
||||
input_location = saved_loc;
|
||||
}
|
||||
}
|
||||
|
||||
#include "gt-cp-semantics.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user