diff options
author | Jason Merrill <jason@redhat.com> | 2010-06-04 17:21:13 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2010-06-04 17:21:13 -0400 |
commit | 0a766368bd6e51459bfd334086cc04af48f91f08 (patch) | |
tree | d5300c246ce3ea5275af264865375de418f7963e /gcc/cp | |
parent | d8a0d13e4fad752b3c3d9ff3f97b03407bf8c726 (diff) | |
download | gcc-0a766368bd6e51459bfd334086cc04af48f91f08.zip gcc-0a766368bd6e51459bfd334086cc04af48f91f08.tar.gz gcc-0a766368bd6e51459bfd334086cc04af48f91f08.tar.bz2 |
Implement noexcept operator (5.3.7)
Implement noexcept operator (5.3.7)
* c-common.c (c_common_reswords): Add noexcept.
* c-common.h (enum rid): Add RID_NOEXCEPT.
cp/
* cp-tree.def (NOEXCEPT_EXPR): New.
* except.c (check_noexcept_r, finish_noexcept_expr): New.
* cp-tree.h: Declare finish_noexcept_expr.
* parser.c (cp_parser_unary_expression): Parse noexcept-expression.
* pt.c (tsubst_copy_and_build): And tsubst it.
(type_dependent_expression_p): Handle it.
(value_dependent_expression_p): Handle it.
From-SVN: r160297
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/cp-tree.def | 1 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/except.c | 64 | ||||
-rw-r--r-- | gcc/cp/parser.c | 45 | ||||
-rw-r--r-- | gcc/cp/pt.c | 13 |
6 files changed, 133 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 190406e..0c11af7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,14 @@ 2010-06-04 Jason Merrill <jason@redhat.com> + Implement noexcept operator (5.3.7) + * cp-tree.def (NOEXCEPT_EXPR): New. + * except.c (check_noexcept_r, finish_noexcept_expr): New. + * cp-tree.h: Declare finish_noexcept_expr. + * parser.c (cp_parser_unary_expression): Parse noexcept-expression. + * pt.c (tsubst_copy_and_build): And tsubst it. + (type_dependent_expression_p): Handle it. + (value_dependent_expression_p): Handle it. + * call.c (build_conditional_expr): Never fold in unevaluated context. * tree.c (build_aggr_init_expr): Propagate TREE_NOTHROW. * semantics.c (simplify_aggr_init_expr): Likewise. diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index c71f94c..b77350f 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -247,6 +247,7 @@ DEFTREECODE (STATIC_CAST_EXPR, "static_cast_expr", tcc_unary, 1) DEFTREECODE (DYNAMIC_CAST_EXPR, "dynamic_cast_expr", tcc_unary, 1) DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", tcc_expression, 2) DEFTREECODE (TYPEID_EXPR, "typeid_expr", tcc_expression, 1) +DEFTREECODE (NOEXCEPT_EXPR, "noexcept_expr", tcc_unary, 1) /* A placeholder for an expression that is not type-dependent, but does occur in a template. When an expression that is not diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 89a3b7c..e48e469 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4820,6 +4820,7 @@ extern tree build_exc_ptr (void); extern tree build_throw (tree); extern int nothrow_libfn_p (const_tree); extern void check_handlers (tree); +extern tree finish_noexcept_expr (tree); extern void choose_personality_routine (enum languages); extern tree eh_type_info (tree); extern tree begin_eh_spec_block (void); diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 6f7f70a..76731f4 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -998,3 +998,67 @@ check_handlers (tree handlers) check_handlers_1 (handler, i); } } + +/* walk_tree helper for finish_noexcept_expr. Returns non-null if the + expression *TP causes the noexcept operator to evaluate to false. + + 5.3.7 [expr.noexcept]: The result of the noexcept operator is false if + in a potentially-evaluated context the expression would contain + * a potentially evaluated call to a function, member function, + function pointer, or member function pointer that does not have a + non-throwing exception-specification (15.4), + * a potentially evaluated throw-expression (15.1), + * a potentially evaluated dynamic_cast expression dynamic_cast<T>(v), + where T is a reference type, that requires a run-time check (5.2.7), or + * a potentially evaluated typeid expression (5.2.8) applied to a glvalue + expression whose type is a polymorphic class type (10.3). */ + +static tree +check_noexcept_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, + void *data ATTRIBUTE_UNUSED) +{ + tree t = *tp; + enum tree_code code = TREE_CODE (t); + if (code == CALL_EXPR + || code == AGGR_INIT_EXPR) + { + /* We can only use the exception specification of the called function + for determining the value of a noexcept expression; we can't use + TREE_NOTHROW, as it might have a different value in another + translation unit, creating ODR problems. + + We could use TREE_NOTHROW (t) for !TREE_PUBLIC fns, though... */ + tree fn = (code == AGGR_INIT_EXPR + ? AGGR_INIT_EXPR_FN (t) : CALL_EXPR_FN (t)); + if (TREE_CODE (fn) == ADDR_EXPR) + { + /* We do use TREE_NOTHROW for ABI internals like __dynamic_cast, + and for C library functions known not to throw. */ + tree fn2 = TREE_OPERAND (fn, 0); + if (TREE_CODE (fn2) == FUNCTION_DECL + && DECL_EXTERN_C_P (fn2) + && (DECL_ARTIFICIAL (fn2) + || nothrow_libfn_p (fn2))) + return TREE_NOTHROW (fn2) ? NULL_TREE : t; + } + fn = TREE_TYPE (TREE_TYPE (fn)); + if (!TYPE_NOTHROW_P (fn)) + return t; + } + + return NULL_TREE; +} + +/* Evaluate noexcept ( EXPR ). */ + +tree +finish_noexcept_expr (tree expr) +{ + if (processing_template_decl) + return build_min (NOEXCEPT_EXPR, boolean_type_node, expr); + + if (cp_walk_tree_without_duplicates (&expr, check_noexcept_r, 0)) + return boolean_false_node; + else + return boolean_true_node; +} diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 05d713c..32e86e9 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -5841,6 +5841,51 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p, } break; + case RID_NOEXCEPT: + { + tree expr; + const char *saved_message; + bool saved_integral_constant_expression_p; + bool saved_non_integral_constant_expression_p; + bool saved_greater_than_is_operator_p; + + cp_lexer_consume_token (parser->lexer); + cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); + + saved_message = parser->type_definition_forbidden_message; + parser->type_definition_forbidden_message + = G_("types may not be defined in %<noexcept%> expressions"); + + saved_integral_constant_expression_p + = parser->integral_constant_expression_p; + saved_non_integral_constant_expression_p + = parser->non_integral_constant_expression_p; + parser->integral_constant_expression_p = false; + + saved_greater_than_is_operator_p + = parser->greater_than_is_operator_p; + parser->greater_than_is_operator_p = true; + + ++cp_unevaluated_operand; + ++c_inhibit_evaluation_warnings; + expr = cp_parser_expression (parser, false, NULL); + --c_inhibit_evaluation_warnings; + --cp_unevaluated_operand; + + parser->greater_than_is_operator_p + = saved_greater_than_is_operator_p; + + parser->integral_constant_expression_p + = saved_integral_constant_expression_p; + parser->non_integral_constant_expression_p + = saved_non_integral_constant_expression_p; + + parser->type_definition_forbidden_message = saved_message; + + cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + return finish_noexcept_expr (expr); + } + default: break; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index dcb455b..0d58035 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -12245,6 +12245,17 @@ tsubst_copy_and_build (tree t, return cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t), complain & tf_error); + case NOEXCEPT_EXPR: + op1 = TREE_OPERAND (t, 0); + ++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; + return finish_noexcept_expr (op1); + case MODOP_EXPR: { tree r = build_x_modify_expr @@ -17577,6 +17588,7 @@ value_dependent_expression_p (tree expression) return true; else if (TYPE_P (expression)) return dependent_type_p (expression); + case NOEXCEPT_EXPR: return type_dependent_expression_p (expression); case SCOPE_REF: @@ -17680,6 +17692,7 @@ type_dependent_expression_p (tree expression) if (TREE_CODE (expression) == PSEUDO_DTOR_EXPR || TREE_CODE (expression) == SIZEOF_EXPR || TREE_CODE (expression) == ALIGNOF_EXPR + || TREE_CODE (expression) == NOEXCEPT_EXPR || TREE_CODE (expression) == TRAIT_EXPR || TREE_CODE (expression) == TYPEID_EXPR || TREE_CODE (expression) == DELETE_EXPR |