summaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c153
1 files changed, 119 insertions, 34 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 4a50b556f46..e8f10a4d000 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -27,7 +27,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree.h"
#include "cp-tree.h"
#include "intl.h"
-#include "c-pragma.h"
+#include "c-family/c-pragma.h"
#include "decl.h"
#include "flags.h"
#include "diagnostic-core.h"
@@ -35,7 +35,7 @@ along with GCC; see the file COPYING3. If not see
#include "output.h"
#include "target.h"
#include "cgraph.h"
-#include "c-common.h"
+#include "c-family/c-common.h"
#include "plugin.h"
@@ -393,7 +393,7 @@ cp_lexer_new_main (void)
c_common_no_more_pch ();
/* Allocate the memory. */
- lexer = GGC_CNEW (cp_lexer);
+ lexer = ggc_alloc_cleared_cp_lexer ();
#ifdef ENABLE_CHECKING
/* Initially we are not debugging. */
@@ -404,7 +404,7 @@ cp_lexer_new_main (void)
/* Create the buffer. */
alloc = CP_LEXER_BUFFER_SIZE;
- buffer = GGC_NEWVEC (cp_token, alloc);
+ buffer = ggc_alloc_vec_cp_token (alloc);
/* Put the first token in the buffer. */
space = alloc;
@@ -445,7 +445,7 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
{
cp_token *first = cache->first;
cp_token *last = cache->last;
- cp_lexer *lexer = GGC_CNEW (cp_lexer);
+ cp_lexer *lexer = ggc_alloc_cleared_cp_lexer ();
/* We do not own the buffer. */
lexer->buffer = NULL;
@@ -946,7 +946,7 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
static cp_token_cache *
cp_token_cache_new (cp_token *first, cp_token *last)
{
- cp_token_cache *cache = GGC_NEW (cp_token_cache);
+ cp_token_cache *cache = ggc_alloc_cp_token_cache ();
cache->first = first;
cache->last = last;
return cache;
@@ -1496,7 +1496,7 @@ cp_parser_context_new (cp_parser_context* next)
memset (context, 0, sizeof (*context));
}
else
- context = GGC_CNEW (cp_parser_context);
+ context = ggc_alloc_cleared_cp_parser_context ();
/* No errors have occurred yet in this context. */
context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
@@ -3093,7 +3093,7 @@ cp_parser_new (void)
cp_lexer *lexer;
unsigned i;
- /* cp_lexer_new_main is called before calling ggc_alloc because
+ /* cp_lexer_new_main is called before doing GC allocation because
cp_lexer_new_main might load a PCH file. */
lexer = cp_lexer_new_main ();
@@ -3102,7 +3102,7 @@ cp_parser_new (void)
for (i = 0; i < sizeof (binops) / sizeof (binops[0]); i++)
binops_by_token[binops[i].token_type] = binops[i];
- parser = GGC_CNEW (cp_parser);
+ parser = ggc_alloc_cleared_cp_parser ();
parser->lexer = lexer;
parser->context = cp_parser_context_new (NULL);
@@ -4605,7 +4605,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
token->type = CPP_NESTED_NAME_SPECIFIER;
/* Retrieve any deferred checks. Do not pop this access checks yet
so the memory will not be reclaimed during token replacing below. */
- token->u.tree_check_value = GGC_CNEW (struct tree_check);
+ token->u.tree_check_value = ggc_alloc_cleared_tree_check ();
token->u.tree_check_value->value = parser->scope;
token->u.tree_check_value->checks = get_deferred_access_checks ();
token->u.tree_check_value->qualifying_scope =
@@ -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, tf_warning_or_error);
+ }
+
default:
break;
}
@@ -6770,15 +6815,20 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
{
tree expr;
tree assignment_expr;
+ struct cp_token *token;
/* Consume the `?' token. */
cp_lexer_consume_token (parser->lexer);
+ token = cp_lexer_peek_token (parser->lexer);
if (cp_parser_allow_gnu_extensions_p (parser)
- && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ && token->type == CPP_COLON)
{
+ pedwarn (token->location, OPT_pedantic,
+ "ISO C++ does not allow ?: with omitted middle operand");
/* Implicit true clause. */
expr = NULL_TREE;
c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_true_node;
+ warn_for_omitted_condop (token->location, logical_or_expr);
}
else
{
@@ -10136,7 +10186,7 @@ cp_parser_mem_initializer_list (cp_parser* parser)
mem-initializer-list. */
if (!DECL_CONSTRUCTOR_P (current_function_decl))
error_at (token->location,
- "only constructors take base initializers");
+ "only constructors take member initializers");
/* Loop through the list. */
while (true)
@@ -11230,7 +11280,7 @@ cp_parser_template_id (cp_parser *parser,
token->type = CPP_TEMPLATE_ID;
/* Retrieve any deferred checks. Do not pop this access checks yet
so the memory will not be reclaimed during token replacing below. */
- token->u.tree_check_value = GGC_CNEW (struct tree_check);
+ token->u.tree_check_value = ggc_alloc_cleared_tree_check ();
token->u.tree_check_value->value = template_id;
token->u.tree_check_value->checks = get_deferred_access_checks ();
token->keyword = RID_MAX;
@@ -17489,13 +17539,50 @@ cp_parser_exception_specification_opt (cp_parser* parser)
{
cp_token *token;
tree type_id_list;
+ const char *saved_message;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
+
+ /* Is it a noexcept-specification? */
+ if (cp_parser_is_keyword (token, RID_NOEXCEPT))
+ {
+ tree expr;
+ cp_lexer_consume_token (parser->lexer);
+
+ if (cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN)
+ {
+ cp_lexer_consume_token (parser->lexer);
+
+ /* Types may not be defined in an exception-specification. */
+ saved_message = parser->type_definition_forbidden_message;
+ parser->type_definition_forbidden_message
+ = G_("types may not be defined in an exception-specification");
+
+ expr = cp_parser_constant_expression (parser, false, NULL);
+
+ /* Restore the saved message. */
+ parser->type_definition_forbidden_message = saved_message;
+
+ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+ }
+ else
+ expr = boolean_true_node;
+
+ return build_noexcept_spec (expr, tf_warning_or_error);
+ }
+
/* If it's not `throw', then there's no exception-specification. */
if (!cp_parser_is_keyword (token, RID_THROW))
return NULL_TREE;
+#if 0
+ /* Enable this once a lot of code has transitioned to noexcept? */
+ if (cxx_dialect == cxx0x && !in_system_header)
+ warning (OPT_Wdeprecated, "dynamic exception specifications are "
+ "deprecated in C++0x; use %<noexcept%> instead.");
+#endif
+
/* Consume the `throw'. */
cp_lexer_consume_token (parser->lexer);
@@ -17507,8 +17594,6 @@ cp_parser_exception_specification_opt (cp_parser* parser)
/* If it's not a `)', then there is a type-id-list. */
if (token->type != CPP_CLOSE_PAREN)
{
- const char *saved_message;
-
/* Types may not be defined in an exception-specification. */
saved_message = parser->type_definition_forbidden_message;
parser->type_definition_forbidden_message
@@ -18285,6 +18370,14 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
if (dependent_p)
pushed_scope = push_scope (parser->scope);
+ /* If the PARSER->SCOPE is a template specialization, it
+ may be instantiated during name lookup. In that case,
+ errors may be issued. Even if we rollback the current
+ tentative parse, those errors are valid. */
+ decl = lookup_qualified_name (parser->scope, name,
+ tag_type != none_type,
+ /*complain=*/true);
+
/* 3.4.3.1: In a lookup in which the constructor is an acceptable
lookup result and the nested-name-specifier nominates a class C:
* if the name specified after the nested-name-specifier, when
@@ -18300,17 +18393,11 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
shall be used only in the declarator-id of a declaration that
names a constructor or in a using-declaration. */
if (tag_type == none_type
- && CLASS_TYPE_P (parser->scope)
- && constructor_name_p (name, parser->scope))
- name = ctor_identifier;
-
- /* If the PARSER->SCOPE is a template specialization, it
- may be instantiated during name lookup. In that case,
- errors may be issued. Even if we rollback the current
- tentative parse, those errors are valid. */
- decl = lookup_qualified_name (parser->scope, name,
- tag_type != none_type,
- /*complain=*/true);
+ && DECL_SELF_REFERENCE_P (decl)
+ && same_type_p (DECL_CONTEXT (decl), parser->scope))
+ decl = lookup_qualified_name (parser->scope, ctor_identifier,
+ tag_type != none_type,
+ /*complain=*/true);
/* If we have a single function from a using decl, pull it out. */
if (TREE_CODE (decl) == OVERLOAD
@@ -22618,11 +22705,12 @@ static tree
cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
{
tree init, cond, incr, body, decl, pre_body = NULL_TREE, ret;
- tree for_block = NULL_TREE, real_decl, initv, condv, incrv, declv;
+ tree real_decl, initv, condv, incrv, declv;
tree this_pre_body, cl;
location_t loc_first;
bool collapse_err = false;
int i, collapse = 1, nbraces = 0;
+ VEC(tree,gc) *for_block = make_tree_vector ();
for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
@@ -22741,8 +22829,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
LOOKUP_ONLYCONVERTING);
if (CLASS_TYPE_P (TREE_TYPE (decl)))
{
- for_block
- = tree_cons (NULL, this_pre_body, for_block);
+ VEC_safe_push (tree, gc, for_block, this_pre_body);
init = NULL_TREE;
}
else
@@ -22996,11 +23083,9 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
}
}
- while (for_block)
- {
- add_stmt (pop_stmt_list (TREE_VALUE (for_block)));
- for_block = TREE_CHAIN (for_block);
- }
+ while (!VEC_empty (tree, for_block))
+ add_stmt (pop_stmt_list (VEC_pop (tree, for_block)));
+ release_tree_vector (for_block);
return ret;
}