/* C++ Parser.
- Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Written by Mark Mitchell <mark@codesourcery.com>.
- This file is part of GNU CC.
+ This file is part of GCC.
- GNU CC is free software; you can redistribute it and/or modify it
+ GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
- GNU CC is distributed in the hope that it will be useful, but
+ GCC is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to the Free
+ along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
#include "decl.h"
#include "flags.h"
#include "diagnostic.h"
-#include "ggc.h"
#include "toplev.h"
#include "output.h"
/* Prototypes. */
-static cp_lexer *cp_lexer_new
- PARAMS ((bool));
+static cp_lexer *cp_lexer_new_main
+ (void);
static cp_lexer *cp_lexer_new_from_tokens
- PARAMS ((struct cp_token_cache *));
+ (struct cp_token_cache *);
static int cp_lexer_saving_tokens
- PARAMS ((const cp_lexer *));
+ (const cp_lexer *);
static cp_token *cp_lexer_next_token
- PARAMS ((cp_lexer *, cp_token *));
-static ptrdiff_t cp_lexer_token_difference
- PARAMS ((cp_lexer *, cp_token *, cp_token *));
+ (cp_lexer *, cp_token *);
+static ptrdiff_t cp_lexer_token_difference
+ (cp_lexer *, cp_token *, cp_token *);
static cp_token *cp_lexer_read_token
- PARAMS ((cp_lexer *));
+ (cp_lexer *);
static void cp_lexer_maybe_grow_buffer
- PARAMS ((cp_lexer *));
+ (cp_lexer *);
static void cp_lexer_get_preprocessor_token
- PARAMS ((cp_lexer *, cp_token *));
+ (cp_lexer *, cp_token *);
static cp_token *cp_lexer_peek_token
- PARAMS ((cp_lexer *));
+ (cp_lexer *);
static cp_token *cp_lexer_peek_nth_token
- PARAMS ((cp_lexer *, size_t));
-static bool cp_lexer_next_token_is
- PARAMS ((cp_lexer *, enum cpp_ttype));
+ (cp_lexer *, size_t);
+static inline bool cp_lexer_next_token_is
+ (cp_lexer *, enum cpp_ttype);
static bool cp_lexer_next_token_is_not
- PARAMS ((cp_lexer *, enum cpp_ttype));
+ (cp_lexer *, enum cpp_ttype);
static bool cp_lexer_next_token_is_keyword
- PARAMS ((cp_lexer *, enum rid));
-static cp_token *cp_lexer_consume_token
- PARAMS ((cp_lexer *));
+ (cp_lexer *, enum rid);
+static cp_token *cp_lexer_consume_token
+ (cp_lexer *);
static void cp_lexer_purge_token
(cp_lexer *);
static void cp_lexer_purge_tokens_after
(cp_lexer *, cp_token *);
static void cp_lexer_save_tokens
- PARAMS ((cp_lexer *));
+ (cp_lexer *);
static void cp_lexer_commit_tokens
- PARAMS ((cp_lexer *));
+ (cp_lexer *);
static void cp_lexer_rollback_tokens
- PARAMS ((cp_lexer *));
-static void cp_lexer_set_source_position_from_token
- PARAMS ((cp_lexer *, const cp_token *));
+ (cp_lexer *);
+static inline void cp_lexer_set_source_position_from_token
+ (cp_lexer *, const cp_token *);
static void cp_lexer_print_token
- PARAMS ((FILE *, cp_token *));
-static bool cp_lexer_debugging_p
- PARAMS ((cp_lexer *));
+ (FILE *, cp_token *);
+static inline bool cp_lexer_debugging_p
+ (cp_lexer *);
static void cp_lexer_start_debugging
- PARAMS ((cp_lexer *)) ATTRIBUTE_UNUSED;
+ (cp_lexer *) ATTRIBUTE_UNUSED;
static void cp_lexer_stop_debugging
- PARAMS ((cp_lexer *)) ATTRIBUTE_UNUSED;
+ (cp_lexer *) ATTRIBUTE_UNUSED;
/* Manifest constants. */
/* The stream to which debugging output should be written. */
static FILE *cp_lexer_debug_stream;
-/* Create a new C++ lexer. If MAIN_LEXER_P is true the new lexer is
- the main lexer -- i.e, the lexer that gets tokens from the
- preprocessor. Otherwise, it is a lexer that uses a cache of stored
- tokens. */
+/* Create a new main C++ lexer, the lexer that gets tokens from the
+ preprocessor. */
static cp_lexer *
-cp_lexer_new (bool main_lexer_p)
+cp_lexer_new_main (void)
{
cp_lexer *lexer;
+ cp_token first_token;
+
+ /* It's possible that lexing the first token will load a PCH file,
+ which is a GC collection point. So we have to grab the first
+ token before allocating any memory. */
+ cp_lexer_get_preprocessor_token (NULL, &first_token);
+ cpp_get_callbacks (parse_in)->valid_pch = NULL;
/* Allocate the memory. */
lexer = (cp_lexer *) ggc_alloc_cleared (sizeof (cp_lexer));
/* Create the circular buffer. */
lexer->buffer = ((cp_token *)
- ggc_alloc (CP_TOKEN_BUFFER_SIZE * sizeof (cp_token)));
+ ggc_calloc (CP_TOKEN_BUFFER_SIZE, sizeof (cp_token)));
lexer->buffer_end = lexer->buffer + CP_TOKEN_BUFFER_SIZE;
- /* There are no tokens in the buffer. */
- lexer->last_token = lexer->buffer;
+ /* There is one token in the buffer. */
+ lexer->last_token = lexer->buffer + 1;
+ lexer->first_token = lexer->buffer;
+ lexer->next_token = lexer->buffer;
+ memcpy (lexer->buffer, &first_token, sizeof (cp_token));
/* This lexer obtains more tokens by calling c_lex. */
- lexer->main_lexer_p = main_lexer_p;
+ lexer->main_lexer_p = true;
/* Create the SAVED_TOKENS stack. */
VARRAY_INT_INIT (lexer->saved_tokens, CP_SAVED_TOKENS_SIZE, "saved_tokens");
cp_token_block *block;
ptrdiff_t num_tokens;
- /* Create the lexer. */
- lexer = cp_lexer_new (/*main_lexer_p=*/false);
+ /* Allocate the memory. */
+ lexer = (cp_lexer *) ggc_alloc_cleared (sizeof (cp_lexer));
/* Create a new buffer, appropriately sized. */
num_tokens = 0;
for (block = tokens->first; block != NULL; block = block->next)
num_tokens += block->num_tokens;
- lexer->buffer = ((cp_token *)
- ggc_alloc (num_tokens * sizeof (cp_token)));
+ lexer->buffer = ((cp_token *) ggc_alloc (num_tokens * sizeof (cp_token)));
lexer->buffer_end = lexer->buffer + num_tokens;
/* Install the tokens. */
/* The buffer is full. */
lexer->last_token = lexer->first_token;
+ /* This lexer doesn't obtain more tokens. */
+ lexer->main_lexer_p = false;
+
+ /* Create the SAVED_TOKENS stack. */
+ VARRAY_INT_INIT (lexer->saved_tokens, CP_SAVED_TOKENS_SIZE, "saved_tokens");
+
+ /* Create the STRINGS array. */
+ VARRAY_TREE_INIT (lexer->string_tokens, 32, "strings");
+
+ /* Assume we are not debugging. */
+ lexer->debugging_p = false;
+
return lexer;
}
-/* Non-zero if we are presently saving tokens. */
+/* Returns non-zero if debugging information should be output. */
-static int
-cp_lexer_saving_tokens (lexer)
- const cp_lexer *lexer;
+static inline bool
+cp_lexer_debugging_p (cp_lexer *lexer)
{
- return VARRAY_ACTIVE_SIZE (lexer->saved_tokens) != 0;
+ return lexer->debugging_p;
+}
+
+/* Set the current source position from the information stored in
+ TOKEN. */
+
+static inline void
+cp_lexer_set_source_position_from_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
+ const cp_token *token)
+{
+ /* Ideally, the source position information would not be a global
+ variable, but it is. */
+
+ /* Update the line number. */
+ if (token->type != CPP_EOF)
+ {
+ lineno = token->line_number;
+ input_filename = token->file_name;
+ }
}
/* TOKEN points into the circular token buffer. Return a pointer to
the next token in the buffer. */
-static cp_token *
-cp_lexer_next_token (lexer, token)
- cp_lexer *lexer;
- cp_token *token;
+static inline cp_token *
+cp_lexer_next_token (cp_lexer* lexer, cp_token* token)
{
token++;
if (token == lexer->buffer_end)
return token;
}
+/* Non-zero if we are presently saving tokens. */
+
+static int
+cp_lexer_saving_tokens (const cp_lexer* lexer)
+{
+ return VARRAY_ACTIVE_SIZE (lexer->saved_tokens) != 0;
+}
+
/* Return a pointer to the token that is N tokens beyond TOKEN in the
buffer. */
to reach FINISH. If START and FINISH are the same, returns zero. */
static ptrdiff_t
-cp_lexer_token_difference (lexer, start, finish)
- cp_lexer *lexer;
- cp_token *start;
- cp_token *finish;
+cp_lexer_token_difference (cp_lexer* lexer, cp_token* start, cp_token* finish)
{
if (finish >= start)
return finish - start;
token buffer. Returns the newly read token. */
static cp_token *
-cp_lexer_read_token (lexer)
- cp_lexer *lexer;
+cp_lexer_read_token (cp_lexer* lexer)
{
cp_token *token;
/* If the circular buffer is full, make it bigger. */
static void
-cp_lexer_maybe_grow_buffer (lexer)
- cp_lexer *lexer;
+cp_lexer_maybe_grow_buffer (cp_lexer* lexer)
{
/* If the buffer is full, enlarge it. */
if (lexer->last_token == lexer->first_token)
/* Store the next token from the preprocessor in *TOKEN. */
static void
-cp_lexer_get_preprocessor_token (lexer, token)
- cp_lexer *lexer ATTRIBUTE_UNUSED;
- cp_token *token;
+cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
+ cp_token *token)
{
bool done;
/* If this not the main lexer, return a terminating CPP_EOF token. */
- if (!lexer->main_lexer_p)
+ if (lexer != NULL && !lexer->main_lexer_p)
{
token->type = CPP_EOF;
token->line_number = 0;
consume it. */
static cp_token *
-cp_lexer_peek_token (lexer)
- cp_lexer *lexer;
+cp_lexer_peek_token (cp_lexer* lexer)
{
cp_token *token;
/* Return true if the next token has the indicated TYPE. */
static bool
-cp_lexer_next_token_is (lexer, type)
- cp_lexer *lexer;
- enum cpp_ttype type;
+cp_lexer_next_token_is (cp_lexer* lexer, enum cpp_ttype type)
{
cp_token *token;
/* Return true if the next token does not have the indicated TYPE. */
static bool
-cp_lexer_next_token_is_not (lexer, type)
- cp_lexer *lexer;
- enum cpp_ttype type;
+cp_lexer_next_token_is_not (cp_lexer* lexer, enum cpp_ttype type)
{
return !cp_lexer_next_token_is (lexer, type);
}
/* Return true if the next token is the indicated KEYWORD. */
static bool
-cp_lexer_next_token_is_keyword (lexer, keyword)
- cp_lexer *lexer;
- enum rid keyword;
+cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword)
{
cp_token *token;
then this is precisely equivalent to cp_lexer_peek_token. */
static cp_token *
-cp_lexer_peek_nth_token (lexer, n)
- cp_lexer *lexer;
- size_t n;
+cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n)
{
cp_token *token;
time. */
static cp_token *
-cp_lexer_consume_token (lexer)
- cp_lexer *lexer;
+cp_lexer_consume_token (cp_lexer* lexer)
{
cp_token *token;
preserved. */
static void
-cp_lexer_save_tokens (lexer)
- cp_lexer *lexer;
+cp_lexer_save_tokens (cp_lexer* lexer)
{
/* Provide debugging output. */
if (cp_lexer_debugging_p (lexer))
/* Commit to the portion of the token stream most recently saved. */
static void
-cp_lexer_commit_tokens (lexer)
- cp_lexer *lexer;
+cp_lexer_commit_tokens (cp_lexer* lexer)
{
/* Provide debugging output. */
if (cp_lexer_debugging_p (lexer))
to the token stream. Stop saving tokens. */
static void
-cp_lexer_rollback_tokens (lexer)
- cp_lexer *lexer;
+cp_lexer_rollback_tokens (cp_lexer* lexer)
{
size_t delta;
lexer->next_token = cp_lexer_advance_token (lexer,
lexer->first_token,
delta);
- /* It might be the case that there wer no tokens when we started
+ /* It might be the case that there were no tokens when we started
saving tokens, but that there are some tokens now. */
if (!lexer->next_token && lexer->first_token)
lexer->next_token = lexer->first_token;
VARRAY_POP (lexer->saved_tokens);
}
-/* Set the current source position from the information stored in
- TOKEN. */
-
-static void
-cp_lexer_set_source_position_from_token (lexer, token)
- cp_lexer *lexer ATTRIBUTE_UNUSED;
- const cp_token *token;
-{
- /* Ideally, the source position information would not be a global
- variable, but it is. */
-
- /* Update the line number. */
- if (token->type != CPP_EOF)
- {
- lineno = token->line_number;
- input_filename = token->file_name;
- }
-}
-
/* Print a representation of the TOKEN on the STREAM. */
static void
-cp_lexer_print_token (stream, token)
- FILE *stream;
- cp_token *token;
+cp_lexer_print_token (FILE * stream, cp_token* token)
{
const char *token_type = NULL;
fprintf (stream, " %s", IDENTIFIER_POINTER (token->value));
}
-/* Returns non-zero if debugging information should be output. */
-
-static bool
-cp_lexer_debugging_p (lexer)
- cp_lexer *lexer;
-{
- return lexer->debugging_p;
-}
-
/* Start emitting debugging information. */
static void
-cp_lexer_start_debugging (lexer)
- cp_lexer *lexer;
+cp_lexer_start_debugging (cp_lexer* lexer)
{
++lexer->debugging_p;
}
/* Stop emitting debugging information. */
static void
-cp_lexer_stop_debugging (lexer)
- cp_lexer *lexer;
+cp_lexer_stop_debugging (cp_lexer* lexer)
{
--lexer->debugging_p;
}
CP_PARSER_ID_KIND_QUALIFIED
} cp_parser_id_kind;
+/* The different kinds of declarators we want to parse. */
+
+typedef enum cp_parser_declarator_kind
+{
+ /* We want an abstract declartor. */
+ CP_PARSER_DECLARATOR_ABSTRACT,
+ /* We want a named declarator. */
+ CP_PARSER_DECLARATOR_NAMED,
+ /* We don't mind, but the name must be an unqualified-id */
+ CP_PARSER_DECLARATOR_EITHER
+} cp_parser_declarator_kind;
+
/* A mapping from a token type to a corresponding tree node type. */
typedef struct cp_parser_token_tree_map_node
scope given by OBJECT_TYPE (the type of `x' or `*x') and also in
the context of the containing expression. */
tree object_type;
- /* A TREE_LIST representing name-lookups for which we have deferred
- checking access controls. We cannot check the accessibility of
- names used in a decl-specifier-seq until we know what is being
- declared because code like:
-
- class A {
- class B {};
- B* f();
- }
-
- A::B* A::f() { return 0; }
-
- is valid, even though `A::B' is not generally accessible.
-
- The TREE_PURPOSE of each node is the scope used to qualify the
- name being looked up; the TREE_VALUE is the DECL to which the
- name was resolved. */
- tree deferred_access_checks;
- /* TRUE iff we are deferring access checks. */
- bool deferring_access_checks_p;
/* The next parsing context in the stack. */
struct cp_parser_context *next;
} cp_parser_context;
/* Constructors and destructors. */
static cp_parser_context *cp_parser_context_new
- PARAMS ((cp_parser_context *));
+ (cp_parser_context *);
+
+/* Class variables. */
+
+static GTY((deletable (""))) cp_parser_context* cp_parser_context_free_list;
/* Constructors and destructors. */
is given by NEXT. */
static cp_parser_context *
-cp_parser_context_new (next)
- cp_parser_context *next;
+cp_parser_context_new (cp_parser_context* next)
{
cp_parser_context *context;
/* Allocate the storage. */
- context = ((cp_parser_context *)
- ggc_alloc_cleared (sizeof (cp_parser_context)));
+ if (cp_parser_context_free_list != NULL)
+ {
+ /* Pull the first entry from the free list. */
+ context = cp_parser_context_free_list;
+ cp_parser_context_free_list = context->next;
+ memset ((char *)context, 0, sizeof (*context));
+ }
+ else
+ context = ((cp_parser_context *)
+ ggc_alloc_cleared (sizeof (cp_parser_context)));
/* No errors have occurred yet in this context. */
context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
/* If this is not the bottomost context, copy information that we
/* If, in the NEXT context, we are parsing an `x->' or `x.'
expression, then we are parsing one in this context, too. */
context->object_type = next->object_type;
- /* We are deferring access checks here if we were in the NEXT
- context. */
- context->deferring_access_checks_p
- = next->deferring_access_checks_p;
/* Thread the stack. */
context->next = next;
}
issued as an error message if a type is defined. */
const char *type_definition_forbidden_message;
- /* List of FUNCTION_TYPEs which contain unprocessed DEFAULT_ARGs
- during class parsing, and are not FUNCTION_DECLs. G++ has an
- awkward extension allowing default args on pointers to functions
- etc. */
- tree default_arg_types;
-
/* A TREE_LIST of queues of functions whose bodies have been lexed,
but may not have been parsed. These functions are friends of
members defined within a class-specification; they are not
front of the list.
Within each queue, functions appear in the reverse order that
- they appeared in the source. The TREE_PURPOSE of each node is
- the class in which the function was defined or declared; the
- TREE_VALUE is the FUNCTION_DECL itself. */
+ they appeared in the source. Each TREE_VALUE is a
+ FUNCTION_DECL of TEMPLATE_DECL corresponding to a member
+ function. */
tree unparsed_functions_queues;
/* The number of classes whose definitions are currently in
} cp_parser;
/* The type of a function that parses some kind of expression */
-typedef tree (*cp_parser_expression_fn) PARAMS ((cp_parser *));
+typedef tree (*cp_parser_expression_fn) (cp_parser *);
/* Prototypes. */
/* Constructors and destructors. */
static cp_parser *cp_parser_new
- PARAMS ((void));
+ (void);
/* Routines to parse various constructs.
/* Lexical conventions [gram.lex] */
static tree cp_parser_identifier
- PARAMS ((cp_parser *));
+ (cp_parser *);
/* Basic concepts [gram.basic] */
static bool cp_parser_translation_unit
- PARAMS ((cp_parser *));
+ (cp_parser *);
/* Expressions [gram.expr] */
static tree cp_parser_primary_expression
(cp_parser *, cp_parser_id_kind *, tree *);
static tree cp_parser_id_expression
- PARAMS ((cp_parser *, bool, bool, bool *));
+ (cp_parser *, bool, bool, bool *);
static tree cp_parser_unqualified_id
- PARAMS ((cp_parser *, bool, bool));
+ (cp_parser *, bool, bool);
static tree cp_parser_nested_name_specifier_opt
(cp_parser *, bool, bool, bool);
static tree cp_parser_nested_name_specifier
static tree cp_parser_postfix_expression
(cp_parser *, bool);
static tree cp_parser_expression_list
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_pseudo_destructor_name
- PARAMS ((cp_parser *, tree *, tree *));
+ (cp_parser *, tree *, tree *);
static tree cp_parser_unary_expression
(cp_parser *, bool);
static enum tree_code cp_parser_unary_operator
- PARAMS ((cp_token *));
+ (cp_token *);
static tree cp_parser_new_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_new_placement
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_new_type_id
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_new_declarator_opt
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_direct_new_declarator
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_new_initializer
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_delete_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_cast_expression
(cp_parser *, bool);
static tree cp_parser_pm_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_multiplicative_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_additive_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_shift_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_relational_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_equality_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_and_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_exclusive_or_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_inclusive_or_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_logical_and_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_logical_or_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_conditional_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_question_colon_clause
- PARAMS ((cp_parser *, tree));
+ (cp_parser *, tree);
static tree cp_parser_assignment_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static enum tree_code cp_parser_assignment_operator_opt
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_constant_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
/* Statements [gram.stmt.stmt] */
static void cp_parser_statement
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_labeled_statement
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_expression_statement
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_compound_statement
(cp_parser *);
static void cp_parser_statement_seq_opt
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_selection_statement
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_condition
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_iteration_statement
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_for_init_statement
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_jump_statement
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_declaration_statement
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_implicitly_scoped_statement
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_already_scoped_statement
- PARAMS ((cp_parser *));
+ (cp_parser *);
/* Declarations [gram.dcl.dcl] */
static void cp_parser_declaration_seq_opt
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_declaration
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_block_declaration
- PARAMS ((cp_parser *, bool));
+ (cp_parser *, bool);
static void cp_parser_simple_declaration
- PARAMS ((cp_parser *, bool));
+ (cp_parser *, bool);
static tree cp_parser_decl_specifier_seq
- PARAMS ((cp_parser *, cp_parser_flags, tree *, bool *));
+ (cp_parser *, cp_parser_flags, tree *, bool *);
static tree cp_parser_storage_class_specifier_opt
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_function_specifier_opt
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_type_specifier
- (cp_parser *, cp_parser_flags, bool, bool, bool *, bool *);
+ (cp_parser *, cp_parser_flags, bool, bool, bool *, bool *);
static tree cp_parser_simple_type_specifier
- PARAMS ((cp_parser *, cp_parser_flags));
+ (cp_parser *, cp_parser_flags);
static tree cp_parser_type_name
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_elaborated_type_specifier
- PARAMS ((cp_parser *, bool, bool));
+ (cp_parser *, bool, bool);
static tree cp_parser_enum_specifier
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_enumerator_list
- PARAMS ((cp_parser *, tree));
+ (cp_parser *, tree);
static void cp_parser_enumerator_definition
- PARAMS ((cp_parser *, tree));
+ (cp_parser *, tree);
static tree cp_parser_namespace_name
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_namespace_definition
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_namespace_body
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_qualified_namespace_specifier
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_namespace_alias_definition
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_using_declaration
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_using_directive
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_asm_definition
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_linkage_specification
- PARAMS ((cp_parser *));
+ (cp_parser *);
/* Declarators [gram.dcl.decl] */
static tree cp_parser_init_declarator
- PARAMS ((cp_parser *, tree, tree, tree, bool, bool, bool *));
+ (cp_parser *, tree, tree, bool, bool, bool *);
static tree cp_parser_declarator
- PARAMS ((cp_parser *, bool, bool *));
+ (cp_parser *, cp_parser_declarator_kind, bool *);
static tree cp_parser_direct_declarator
- PARAMS ((cp_parser *, bool, bool *));
+ (cp_parser *, cp_parser_declarator_kind, bool *);
static enum tree_code cp_parser_ptr_operator
- PARAMS ((cp_parser *, tree *, tree *));
+ (cp_parser *, tree *, tree *);
static tree cp_parser_cv_qualifier_seq_opt
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_cv_qualifier_opt
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_declarator_id
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_type_id
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_type_specifier_seq
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_parameter_declaration_clause
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_parameter_declaration_list
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_parameter_declaration
- PARAMS ((cp_parser *, bool));
+ (cp_parser *, bool);
static tree cp_parser_function_definition
- PARAMS ((cp_parser *, bool *));
+ (cp_parser *, bool *);
static void cp_parser_function_body
(cp_parser *);
static tree cp_parser_initializer
- PARAMS ((cp_parser *, bool *));
+ (cp_parser *, bool *);
static tree cp_parser_initializer_clause
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_initializer_list
- PARAMS ((cp_parser *));
+ (cp_parser *);
static bool cp_parser_ctor_initializer_opt_and_function_body
(cp_parser *);
static tree cp_parser_class_name
(cp_parser *, bool, bool, bool, bool, bool, bool);
static tree cp_parser_class_specifier
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_class_head
- PARAMS ((cp_parser *, bool *, bool *, tree *));
+ (cp_parser *, bool *);
static enum tag_types cp_parser_class_key
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_member_specification_opt
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_member_declaration
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_pure_specifier
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_constant_initializer
- PARAMS ((cp_parser *));
+ (cp_parser *);
/* Derived classes [gram.class.derived] */
static tree cp_parser_base_clause
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_base_specifier
- PARAMS ((cp_parser *));
+ (cp_parser *);
/* Special member functions [gram.special] */
static tree cp_parser_conversion_function_id
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_conversion_type_id
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_conversion_declarator_opt
- PARAMS ((cp_parser *));
+ (cp_parser *);
static bool cp_parser_ctor_initializer_opt
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_mem_initializer_list
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_mem_initializer
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_mem_initializer_id
- PARAMS ((cp_parser *));
+ (cp_parser *);
/* Overloading [gram.over] */
static tree cp_parser_operator_function_id
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_operator
- PARAMS ((cp_parser *));
+ (cp_parser *);
/* Templates [gram.temp] */
static void cp_parser_template_declaration
- PARAMS ((cp_parser *, bool));
+ (cp_parser *, bool);
static tree cp_parser_template_parameter_list
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_template_parameter
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_type_parameter
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_template_id
- PARAMS ((cp_parser *, bool, bool));
+ (cp_parser *, bool, bool);
static tree cp_parser_template_name
- PARAMS ((cp_parser *, bool, bool));
+ (cp_parser *, bool, bool);
static tree cp_parser_template_argument_list
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_template_argument
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_explicit_instantiation
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_explicit_specialization
- PARAMS ((cp_parser *));
+ (cp_parser *);
/* Exception handling [gram.exception] */
static tree cp_parser_try_block
- PARAMS ((cp_parser *));
+ (cp_parser *);
static bool cp_parser_function_try_block
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_handler_seq
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_handler
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_exception_declaration
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_throw_expression
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_exception_specification_opt
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_type_id_list
- PARAMS ((cp_parser *));
+ (cp_parser *);
/* GNU Extensions */
static tree cp_parser_asm_specification_opt
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_asm_operand_list
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_asm_clobber_list
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_attributes_opt
- PARAMS ((cp_parser *));
+ (cp_parser *);
static tree cp_parser_attribute_list
- PARAMS ((cp_parser *));
+ (cp_parser *);
static bool cp_parser_extension_opt
- PARAMS ((cp_parser *, int *));
+ (cp_parser *, int *);
static void cp_parser_label_declaration
- PARAMS ((cp_parser *));
+ (cp_parser *);
/* Utility Routines */
static tree cp_parser_lookup_name
- PARAMS ((cp_parser *, tree, bool, bool, bool));
+ (cp_parser *, tree, bool, bool, bool, bool);
static tree cp_parser_lookup_name_simple
- PARAMS ((cp_parser *, tree));
+ (cp_parser *, tree);
static tree cp_parser_resolve_typename_type
- PARAMS ((cp_parser *, tree));
+ (cp_parser *, tree);
static tree cp_parser_maybe_treat_template_as_class
(tree, bool);
static bool cp_parser_check_declarator_template_parameters
- PARAMS ((cp_parser *, tree));
+ (cp_parser *, tree);
static bool cp_parser_check_template_parameters
- PARAMS ((cp_parser *, unsigned));
+ (cp_parser *, unsigned);
static tree cp_parser_binary_expression
- PARAMS ((cp_parser *,
- cp_parser_token_tree_map,
- cp_parser_expression_fn));
+ (cp_parser *, const cp_parser_token_tree_map, cp_parser_expression_fn);
static tree cp_parser_global_scope_opt
- PARAMS ((cp_parser *, bool));
+ (cp_parser *, bool);
static bool cp_parser_constructor_declarator_p
(cp_parser *, bool);
static tree cp_parser_function_definition_from_specifiers_and_declarator
- PARAMS ((cp_parser *, tree, tree, tree, tree));
+ (cp_parser *, tree, tree, tree);
static tree cp_parser_function_definition_after_declarator
- PARAMS ((cp_parser *, bool));
+ (cp_parser *, bool);
static void cp_parser_template_declaration_after_export
- PARAMS ((cp_parser *, bool));
+ (cp_parser *, bool);
static tree cp_parser_single_declaration
- PARAMS ((cp_parser *, bool, bool *));
+ (cp_parser *, bool, bool *);
static tree cp_parser_functional_cast
- PARAMS ((cp_parser *, tree));
+ (cp_parser *, tree);
static void cp_parser_late_parsing_for_member
- PARAMS ((cp_parser *, tree));
+ (cp_parser *, tree);
static void cp_parser_late_parsing_default_args
- PARAMS ((cp_parser *, tree));
+ (cp_parser *, tree);
static tree cp_parser_sizeof_operand
- PARAMS ((cp_parser *, enum rid));
+ (cp_parser *, enum rid);
static bool cp_parser_declares_only_class_p
- PARAMS ((cp_parser *));
+ (cp_parser *);
static bool cp_parser_friend_p
- PARAMS ((tree));
+ (tree);
static cp_token *cp_parser_require
- PARAMS ((cp_parser *, enum cpp_ttype, const char *));
+ (cp_parser *, enum cpp_ttype, const char *);
static cp_token *cp_parser_require_keyword
- PARAMS ((cp_parser *, enum rid, const char *));
+ (cp_parser *, enum rid, const char *);
static bool cp_parser_token_starts_function_definition_p
- PARAMS ((cp_token *));
+ (cp_token *);
static bool cp_parser_next_token_starts_class_definition_p
(cp_parser *);
static enum tag_types cp_parser_token_is_class_key
- PARAMS ((cp_token *));
+ (cp_token *);
static void cp_parser_check_class_key
(enum tag_types, tree type);
static bool cp_parser_optional_template_keyword
(cp_parser *);
+static void cp_parser_pre_parsed_nested_name_specifier
+ (cp_parser *);
static void cp_parser_cache_group
(cp_parser *, cp_token_cache *, enum cpp_ttype, unsigned);
static void cp_parser_parse_tentatively
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_commit_to_tentative_parse
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_abort_tentative_parse
- PARAMS ((cp_parser *));
+ (cp_parser *);
static bool cp_parser_parse_definitely
- PARAMS ((cp_parser *));
-static bool cp_parser_parsing_tentatively
- PARAMS ((cp_parser *));
+ (cp_parser *);
+static inline bool cp_parser_parsing_tentatively
+ (cp_parser *);
static bool cp_parser_committed_to_tentative_parse
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_error
- PARAMS ((cp_parser *, const char *));
-static void cp_parser_simulate_error
- PARAMS ((cp_parser *));
+ (cp_parser *, const char *);
+static bool cp_parser_simulate_error
+ (cp_parser *);
static void cp_parser_check_type_definition
- PARAMS ((cp_parser *));
+ (cp_parser *);
+static bool cp_parser_diagnose_invalid_type_name
+ (cp_parser *);
static bool cp_parser_skip_to_closing_parenthesis
- PARAMS ((cp_parser *));
+ (cp_parser *);
static bool cp_parser_skip_to_closing_parenthesis_or_comma
(cp_parser *);
static void cp_parser_skip_to_end_of_statement
- PARAMS ((cp_parser *));
+ (cp_parser *);
+static void cp_parser_consume_semicolon_at_end_of_statement
+ (cp_parser *);
static void cp_parser_skip_to_end_of_block_or_statement
- PARAMS ((cp_parser *));
+ (cp_parser *);
static void cp_parser_skip_to_closing_brace
(cp_parser *);
static void cp_parser_skip_until_found
- PARAMS ((cp_parser *, enum cpp_ttype, const char *));
+ (cp_parser *, enum cpp_ttype, const char *);
static bool cp_parser_error_occurred
- PARAMS ((cp_parser *));
+ (cp_parser *);
static bool cp_parser_allow_gnu_extensions_p
- PARAMS ((cp_parser *));
+ (cp_parser *);
static bool cp_parser_is_string_literal
- PARAMS ((cp_token *));
+ (cp_token *);
static bool cp_parser_is_keyword
- PARAMS ((cp_token *, enum rid));
-static bool cp_parser_dependent_type_p
- (tree);
-static bool cp_parser_value_dependent_expression_p
- (tree);
-static bool cp_parser_type_dependent_expression_p
- (tree);
-static bool cp_parser_dependent_template_arg_p
- (tree);
-static bool cp_parser_dependent_template_id_p
- (tree, tree);
-static bool cp_parser_dependent_template_p
- (tree);
-static void cp_parser_defer_access_check
- (cp_parser *, tree, tree);
-static void cp_parser_start_deferring_access_checks
- (cp_parser *);
-static tree cp_parser_stop_deferring_access_checks
- PARAMS ((cp_parser *));
-static void cp_parser_perform_deferred_access_checks
- PARAMS ((tree));
+ (cp_token *, enum rid);
static tree cp_parser_scope_through_which_access_occurs
(tree, tree, tree);
-/* Returns non-zero if TOKEN is a string literal. */
-
-static bool
-cp_parser_is_string_literal (token)
- cp_token *token;
-{
- return (token->type == CPP_STRING || token->type == CPP_WSTRING);
-}
-
-/* Returns non-zero if TOKEN is the indicated KEYWORD. */
-
-static bool
-cp_parser_is_keyword (token, keyword)
- cp_token *token;
- enum rid keyword;
-{
- return token->keyword == keyword;
-}
-
-/* Returns TRUE if TYPE is dependent, in the sense of
- [temp.dep.type]. */
-
-static bool
-cp_parser_dependent_type_p (type)
- tree type;
-{
- tree scope;
-
- if (!processing_template_decl)
- return false;
-
- /* If the type is NULL, we have not computed a type for the entity
- in question; in that case, the type is dependent. */
- if (!type)
- return true;
-
- /* Erroneous types can be considered non-dependent. */
- if (type == error_mark_node)
- return false;
-
- /* [temp.dep.type]
-
- A type is dependent if it is:
-
- -- a template parameter. */
- if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
- return true;
- /* -- a qualified-id with a nested-name-specifier which contains a
- class-name that names a dependent type or whose unqualified-id
- names a dependent type. */
- if (TREE_CODE (type) == TYPENAME_TYPE)
- return true;
- /* -- a cv-qualified type where the cv-unqualified type is
- dependent. */
- type = TYPE_MAIN_VARIANT (type);
- /* -- a compound type constructed from any dependent type. */
- if (TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
- return (cp_parser_dependent_type_p (TYPE_PTRMEM_CLASS_TYPE (type))
- || cp_parser_dependent_type_p (TYPE_PTRMEM_POINTED_TO_TYPE
- (type)));
- else if (TREE_CODE (type) == POINTER_TYPE
- || TREE_CODE (type) == REFERENCE_TYPE)
- return cp_parser_dependent_type_p (TREE_TYPE (type));
- else if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == METHOD_TYPE)
- {
- tree arg_type;
-
- if (cp_parser_dependent_type_p (TREE_TYPE (type)))
- return true;
- for (arg_type = TYPE_ARG_TYPES (type);
- arg_type;
- arg_type = TREE_CHAIN (arg_type))
- if (cp_parser_dependent_type_p (TREE_VALUE (arg_type)))
- return true;
- return false;
- }
- /* -- an array type constructed from any dependent type or whose
- size is specified by a constant expression that is
- value-dependent. */
- if (TREE_CODE (type) == ARRAY_TYPE)
- {
- if (TYPE_DOMAIN (TREE_TYPE (type))
- && ((cp_parser_value_dependent_expression_p
- (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
- || (cp_parser_type_dependent_expression_p
- (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))))
- return true;
- return cp_parser_dependent_type_p (TREE_TYPE (type));
- }
- /* -- a template-id in which either the template name is a template
- parameter or any of the template arguments is a dependent type or
- an expression that is type-dependent or value-dependent.
-
- This language seems somewhat confused; for example, it does not
- discuss template template arguments. Therefore, we use the
- definition for dependent template arguments in [temp.dep.temp]. */
- if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_INFO (type)
- && (cp_parser_dependent_template_id_p
- (CLASSTYPE_TI_TEMPLATE (type),
- CLASSTYPE_TI_ARGS (type))))
- return true;
- else if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
- return true;
- /* All TYPEOF_TYPEs are dependent; if the argument of the `typeof'
- expression is not type-dependent, then it should already been
- have resolved. */
- if (TREE_CODE (type) == TYPEOF_TYPE)
- return true;
- /* The standard does not specifically mention types that are local
- to template functions or local classes, but they should be
- considered dependent too. For example:
-
- template <int I> void f() {
- enum E { a = I };
- S<sizeof (E)> s;
- }
-
- The size of `E' cannot be known until the value of `I' has been
- determined. Therefore, `E' must be considered dependent. */
- scope = TYPE_CONTEXT (type);
- if (scope && TYPE_P (scope))
- return cp_parser_dependent_type_p (scope);
- else if (scope && TREE_CODE (scope) == FUNCTION_DECL)
- return cp_parser_type_dependent_expression_p (scope);
-
- /* Other types are non-dependent. */
- return false;
-}
-
-/* Returns TRUE if the EXPRESSION is value-dependent. */
-
-static bool
-cp_parser_value_dependent_expression_p (tree expression)
-{
- if (!processing_template_decl)
- return false;
-
- /* A name declared with a dependent type. */
- if (DECL_P (expression)
- && cp_parser_dependent_type_p (TREE_TYPE (expression)))
- return true;
- /* A non-type template parameter. */
- if ((TREE_CODE (expression) == CONST_DECL
- && DECL_TEMPLATE_PARM_P (expression))
- || TREE_CODE (expression) == TEMPLATE_PARM_INDEX)
- return true;
- /* A constant with integral or enumeration type and is initialized
- with an expression that is value-dependent. */
- if (TREE_CODE (expression) == VAR_DECL
- && DECL_INITIAL (expression)
- && (CP_INTEGRAL_TYPE_P (TREE_TYPE (expression))
- || TREE_CODE (TREE_TYPE (expression)) == ENUMERAL_TYPE)
- && cp_parser_value_dependent_expression_p (DECL_INITIAL (expression)))
- return true;
- /* These expressions are value-dependent if the type to which the
- cast occurs is dependent. */
- if ((TREE_CODE (expression) == DYNAMIC_CAST_EXPR
- || TREE_CODE (expression) == STATIC_CAST_EXPR
- || TREE_CODE (expression) == CONST_CAST_EXPR
- || TREE_CODE (expression) == REINTERPRET_CAST_EXPR
- || TREE_CODE (expression) == CAST_EXPR)
- && cp_parser_dependent_type_p (TREE_TYPE (expression)))
- return true;
- /* A `sizeof' expression where the sizeof operand is a type is
- value-dependent if the type is dependent. If the type was not
- dependent, we would no longer have a SIZEOF_EXPR, so any
- SIZEOF_EXPR is dependent. */
- if (TREE_CODE (expression) == SIZEOF_EXPR)
- return true;
- /* A constant expression is value-dependent if any subexpression is
- value-dependent. */
- if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expression))))
- {
- switch (TREE_CODE_CLASS (TREE_CODE (expression)))
- {
- case '1':
- return (cp_parser_value_dependent_expression_p
- (TREE_OPERAND (expression, 0)));
- case '<':
- case '2':
- return ((cp_parser_value_dependent_expression_p
- (TREE_OPERAND (expression, 0)))
- || (cp_parser_value_dependent_expression_p
- (TREE_OPERAND (expression, 1))));
- case 'e':
- {
- int i;
- for (i = 0;
- i < TREE_CODE_LENGTH (TREE_CODE (expression));
- ++i)
- if (cp_parser_value_dependent_expression_p
- (TREE_OPERAND (expression, i)))
- return true;
- return false;
- }
- }
- }
-
- /* The expression is not value-dependent. */
- return false;
-}
-
-/* Returns TRUE if the EXPRESSION is type-dependent, in the sense of
- [temp.dep.expr]. */
-
-static bool
-cp_parser_type_dependent_expression_p (expression)
- tree expression;
-{
- if (!processing_template_decl)
- return false;
-
- /* Some expression forms are never type-dependent. */
- if (TREE_CODE (expression) == PSEUDO_DTOR_EXPR
- || TREE_CODE (expression) == SIZEOF_EXPR
- || TREE_CODE (expression) == ALIGNOF_EXPR
- || TREE_CODE (expression) == TYPEID_EXPR
- || TREE_CODE (expression) == DELETE_EXPR
- || TREE_CODE (expression) == VEC_DELETE_EXPR
- || TREE_CODE (expression) == THROW_EXPR)
- return false;
-
- /* The types of these expressions depends only on the type to which
- the cast occurs. */
- if (TREE_CODE (expression) == DYNAMIC_CAST_EXPR
- || TREE_CODE (expression) == STATIC_CAST_EXPR
- || TREE_CODE (expression) == CONST_CAST_EXPR
- || TREE_CODE (expression) == REINTERPRET_CAST_EXPR
- || TREE_CODE (expression) == CAST_EXPR)
- return cp_parser_dependent_type_p (TREE_TYPE (expression));
- /* The types of these expressions depends only on the type created
- by the expression. */
- else if (TREE_CODE (expression) == NEW_EXPR
- || TREE_CODE (expression) == VEC_NEW_EXPR)
- return cp_parser_dependent_type_p (TREE_OPERAND (expression, 1));
-
- if (TREE_CODE (expression) == FUNCTION_DECL
- && DECL_LANG_SPECIFIC (expression)
- && DECL_TEMPLATE_INFO (expression)
- && (cp_parser_dependent_template_id_p
- (DECL_TI_TEMPLATE (expression),
- INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (expression)))))
- return true;
-
- return (cp_parser_dependent_type_p (TREE_TYPE (expression)));
-}
-
-/* Returns TRUE if the ARG (a template argument) is dependent. */
+/* Returns non-zero if we are parsing tentatively. */
-static bool
-cp_parser_dependent_template_arg_p (tree arg)
+static inline bool
+cp_parser_parsing_tentatively (cp_parser* parser)
{
- if (!processing_template_decl)
- return false;
-
- if (TREE_CODE (arg) == TEMPLATE_DECL
- || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
- return cp_parser_dependent_template_p (arg);
- else if (TYPE_P (arg))
- return cp_parser_dependent_type_p (arg);
- else
- return (cp_parser_type_dependent_expression_p (arg)
- || cp_parser_value_dependent_expression_p (arg));
+ return parser->context->next != NULL;
}
-/* Returns TRUE if the specialization TMPL<ARGS> is dependent. */
+/* Returns non-zero if TOKEN is a string literal. */
static bool
-cp_parser_dependent_template_id_p (tree tmpl, tree args)
+cp_parser_is_string_literal (cp_token* token)
{
- int i;
-
- if (cp_parser_dependent_template_p (tmpl))
- return true;
- for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
- if (cp_parser_dependent_template_arg_p (TREE_VEC_ELT (args, i)))
- return true;
- return false;
+ return (token->type == CPP_STRING || token->type == CPP_WSTRING);
}
-/* Returns TRUE if the template TMPL is dependent. */
+/* Returns non-zero if TOKEN is the indicated KEYWORD. */
static bool
-cp_parser_dependent_template_p (tree tmpl)
-{
- /* Template template parameters are dependent. */
- if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)
- || TREE_CODE (tmpl) == TEMPLATE_TEMPLATE_PARM)
- return true;
- /* So are member templates of dependent classes. */
- if (TYPE_P (CP_DECL_CONTEXT (tmpl)))
- return cp_parser_dependent_type_p (DECL_CONTEXT (tmpl));
- return false;
-}
-
-/* Defer checking the accessibility of DECL, when looked up in
- CLASS_TYPE. */
-
-static void
-cp_parser_defer_access_check (cp_parser *parser,
- tree class_type,
- tree decl)
-{
- tree check;
-
- /* If we are not supposed to defer access checks, just check now. */
- if (!parser->context->deferring_access_checks_p)
- {
- enforce_access (class_type, decl);
- return;
- }
-
- /* See if we are already going to perform this check. */
- for (check = parser->context->deferred_access_checks;
- check;
- check = TREE_CHAIN (check))
- if (TREE_VALUE (check) == decl
- && same_type_p (TREE_PURPOSE (check), class_type))
- return;
- /* If not, record the check. */
- parser->context->deferred_access_checks
- = tree_cons (class_type, decl, parser->context->deferred_access_checks);
-}
-
-/* Start deferring access control checks. */
-
-static void
-cp_parser_start_deferring_access_checks (cp_parser *parser)
-{
- parser->context->deferring_access_checks_p = true;
-}
-
-/* Stop deferring access control checks. Returns a TREE_LIST
- representing the deferred checks. The TREE_PURPOSE of each node is
- the type through which the access occurred; the TREE_VALUE is the
- declaration named. */
-
-static tree
-cp_parser_stop_deferring_access_checks (parser)
- cp_parser *parser;
-{
- tree access_checks;
-
- parser->context->deferring_access_checks_p = false;
- access_checks = parser->context->deferred_access_checks;
- parser->context->deferred_access_checks = NULL_TREE;
-
- return access_checks;
-}
-
-/* Perform the deferred ACCESS_CHECKS, whose representation is as
- documented with cp_parser_stop_deferrring_access_checks. */
-
-static void
-cp_parser_perform_deferred_access_checks (access_checks)
- tree access_checks;
+cp_parser_is_keyword (cp_token* token, enum rid keyword)
{
- tree deferred_check;
-
- /* Look through all the deferred checks. */
- for (deferred_check = access_checks;
- deferred_check;
- deferred_check = TREE_CHAIN (deferred_check))
- /* Check access. */
- enforce_access (TREE_PURPOSE (deferred_check),
- TREE_VALUE (deferred_check));
+ return token->keyword == keyword;
}
/* Returns the scope through which DECL is being accessed, or
NESTED_NAME_SPECIFIER is `A'. */
tree
-cp_parser_scope_through_which_access_occurs (decl,
- object_type,
- nested_name_specifier)
- tree decl;
- tree object_type;
- tree nested_name_specifier;
+cp_parser_scope_through_which_access_occurs (tree decl,
+ tree object_type,
+ tree nested_name_specifier)
{
tree scope;
tree qualifying_type = NULL_TREE;
if (!TYPE_P (scope))
return NULL_TREE;
/* Figure out the type through which DECL is being accessed. */
- if (object_type && DERIVED_FROM_P (scope, object_type))
+ if (object_type
+ /* OBJECT_TYPE might not be a class type; consider:
+
+ class A { typedef int I; };
+ I *p;
+ p->A::I::~I();
+
+ In this case, we will have "A::I" as the DECL, but "I" as the
+ OBJECT_TYPE. */
+ && CLASS_TYPE_P (object_type)
+ && DERIVED_FROM_P (scope, object_type))
/* If we are processing a `->' or `.' expression, use the type of the
left-hand side. */
qualifying_type = object_type;
/* Issue the indicated error MESSAGE. */
static void
-cp_parser_error (parser, message)
- cp_parser *parser;
- const char *message;
+cp_parser_error (cp_parser* parser, const char* message)
{
- /* Remember that we have issued an error. */
- cp_parser_simulate_error (parser);
/* Output the MESSAGE -- unless we're parsing tentatively. */
- if (!cp_parser_parsing_tentatively (parser)
- || cp_parser_committed_to_tentative_parse (parser))
+ if (!cp_parser_simulate_error (parser))
error (message);
}
/* If we are parsing tentatively, remember that an error has occurred
- during this tentative parse. */
+ during this tentative parse. Returns true if the error was
+ simulated; false if a messgae should be issued by the caller. */
-static void
-cp_parser_simulate_error (parser)
- cp_parser *parser;
+static bool
+cp_parser_simulate_error (cp_parser* parser)
{
if (cp_parser_parsing_tentatively (parser)
&& !cp_parser_committed_to_tentative_parse (parser))
- parser->context->status = CP_PARSER_STATUS_KIND_ERROR;
+ {
+ parser->context->status = CP_PARSER_STATUS_KIND_ERROR;
+ return true;
+ }
+ return false;
}
/* This function is called when a type is defined. If type
issued. */
static void
-cp_parser_check_type_definition (parser)
- cp_parser *parser;
+cp_parser_check_type_definition (cp_parser* parser)
{
/* If types are forbidden here, issue a message. */
if (parser->type_definition_forbidden_message)
error ("%s", parser->type_definition_forbidden_message);
}
+/* Check for a common situation where a type-name should be present,
+ but is not, and issue a sensible error message. Returns true if an
+ invalid type-name was detected. */
+
+static bool
+cp_parser_diagnose_invalid_type_name (cp_parser *parser)
+{
+ /* If the next two tokens are both identifiers, the code is
+ erroneous. The usual cause of this situation is code like:
+
+ T t;
+
+ where "T" should name a type -- but does not. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+ && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME)
+ {
+ tree name;
+
+ /* If parsing tenatively, we should commit; we really are
+ looking at a declaration. */
+ /* Consume the first identifier. */
+ name = cp_lexer_consume_token (parser->lexer)->value;
+ /* Issue an error message. */
+ error ("`%s' does not name a type", IDENTIFIER_POINTER (name));
+ /* If we're in a template class, it's possible that the user was
+ referring to a type from a base class. For example:
+
+ template <typename T> struct A { typedef T X; };
+ template <typename T> struct B : public A<T> { X x; };
+
+ The user should have said "typename A<T>::X". */
+ if (processing_template_decl && current_class_type)
+ {
+ tree b;
+
+ for (b = TREE_CHAIN (TYPE_BINFO (current_class_type));
+ b;
+ b = TREE_CHAIN (b))
+ {
+ tree base_type = BINFO_TYPE (b);
+ if (CLASS_TYPE_P (base_type)
+ && dependent_type_p (base_type))
+ {
+ tree field;
+ /* Go from a particular instantiation of the
+ template (which will have an empty TYPE_FIELDs),
+ to the main version. */
+ if (CLASSTYPE_USE_TEMPLATE (base_type))
+ base_type = (TREE_TYPE
+ (DECL_TEMPLATE_RESULT
+ (DECL_PRIMARY_TEMPLATE
+ (CLASSTYPE_TI_TEMPLATE (base_type)))));
+ for (field = TYPE_FIELDS (base_type);
+ field;
+ field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == TYPE_DECL
+ && DECL_NAME (field) == name)
+ {
+ error ("(perhaps `typename %T::%s' was intended)",
+ BINFO_TYPE (b), IDENTIFIER_POINTER (name));
+ break;
+ }
+ if (field)
+ break;
+ }
+ }
+ }
+ /* Skip to the end of the declaration; there's no point in
+ trying to process it. */
+ cp_parser_skip_to_end_of_statement (parser);
+
+ return true;
+ }
+
+ return false;
+}
+
/* Consume tokens up to, and including, the next non-nested closing `)'.
Returns TRUE iff we found a closing `)'. */
non-nested `}' comes first, then we stop before consuming that. */
static void
-cp_parser_skip_to_end_of_statement (parser)
- cp_parser *parser;
+cp_parser_skip_to_end_of_statement (cp_parser* parser)
{
unsigned nesting_depth = 0;
}
}
+/* This function is called at the end of a statement or declaration.
+ If the next token is a semicolon, it is consumed; otherwise, error
+ recovery is attempted. */
+
+static void
+cp_parser_consume_semicolon_at_end_of_statement (cp_parser *parser)
+{
+ /* Look for the trailing `;'. */
+ if (!cp_parser_require (parser, CPP_SEMICOLON, "`;'"))
+ {
+ /* If there is additional (erroneous) input, skip to the end of
+ the statement. */
+ cp_parser_skip_to_end_of_statement (parser);
+ /* If the next token is now a `;', consume it. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ cp_lexer_consume_token (parser->lexer);
+ }
+}
+
/* Skip tokens until we have consumed an entire block, or until we
have consumed a non-nested `;'. */
static void
-cp_parser_skip_to_end_of_block_or_statement (parser)
- cp_parser *parser;
+cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser)
{
unsigned nesting_depth = 0;
/* Create a new C++ parser. */
static cp_parser *
-cp_parser_new ()
+cp_parser_new (void)
{
cp_parser *parser;
+ cp_lexer *lexer;
+
+ /* cp_lexer_new_main is called before calling ggc_alloc because
+ cp_lexer_new_main might load a PCH file. */
+ lexer = cp_lexer_new_main ();
parser = (cp_parser *) ggc_alloc_cleared (sizeof (cp_parser));
- parser->lexer = cp_lexer_new (/*main_lexer_p=*/true);
+ parser->lexer = lexer;
parser->context = cp_parser_context_new (NULL);
/* For now, we always accept GNU extensions. */
/* We are not processing a declarator. */
parser->in_declarator_p = false;
- /* There are no default args to process. */
- parser->default_arg_types = NULL;
-
/* The unparsed function queue is empty. */
parser->unparsed_functions_queues = build_tree_list (NULL_TREE, NULL_TREE);
identifier. */
static tree
-cp_parser_identifier (parser)
- cp_parser *parser;
+cp_parser_identifier (cp_parser* parser)
{
cp_token *token;
Returns TRUE if all went well. */
static bool
-cp_parser_translation_unit (parser)
- cp_parser *parser;
+cp_parser_translation_unit (cp_parser* parser)
{
while (true)
{
}
}
- /* If unqualified name lookup fails while processing a
- template, that just means that we need to do name
- lookup again when the template is instantiated. */
if (!parser->scope
&& decl == error_mark_node
&& processing_template_decl)
{
+ /* Unqualified name lookup failed while processing a
+ template. */
*idk = CP_PARSER_ID_KIND_UNQUALIFIED;
- return build_min_nt (LOOKUP_EXPR, id_expression);
+ /* If the next token is a parenthesis, assume that
+ Koenig lookup will succeed when instantiating the
+ template. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+ return build_min_nt (LOOKUP_EXPR, id_expression);
+ /* If we're not doing Koenig lookup, issue an error. */
+ error ("`%D' has not been declared", id_expression);
+ return error_mark_node;
}
else if (decl == error_mark_node
&& !processing_template_decl)
/* If we didn't find anything, or what we found was a type,
then this wasn't really an id-expression. */
- if (TREE_CODE (decl) == TYPE_DECL
- || TREE_CODE (decl) == NAMESPACE_DECL
- || (TREE_CODE (decl) == TEMPLATE_DECL
- && !DECL_FUNCTION_TEMPLATE_P (decl)))
+ if (TREE_CODE (decl) == TEMPLATE_DECL
+ && !DECL_FUNCTION_TEMPLATE_P (decl))
+ {
+ cp_parser_error (parser, "missing template arguments");
+ return error_mark_node;
+ }
+ else if (TREE_CODE (decl) == TYPE_DECL
+ || TREE_CODE (decl) == NAMESPACE_DECL)
{
cp_parser_error (parser,
"expected primary-expression");
its type. */
else if (!is_overloaded_fn (decl))
dependent_p
- = cp_parser_dependent_type_p (TREE_TYPE (decl));
+ = dependent_type_p (TREE_TYPE (decl));
/* For a set of overloaded functions, check each of the
functions. */
else
{
while (args)
{
- if (cp_parser_dependent_template_arg_p
- (TREE_VALUE (args)))
+ if (dependent_template_arg_p (TREE_VALUE (args)))
{
dependent_p = true;
break;
{
int i;
for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
- if (cp_parser_dependent_template_arg_p
- (TREE_VEC_ELT (args, i)))
+ if (dependent_template_arg_p (TREE_VEC_ELT (args, i)))
{
dependent_p = true;
break;
/* Member functions of dependent classes are
dependent. */
if (TREE_CODE (fn) == FUNCTION_DECL
- && cp_parser_type_dependent_expression_p (fn))
+ && type_dependent_expression_p (fn))
dependent_p = true;
else if (TREE_CODE (fn) == TEMPLATE_DECL
- && cp_parser_dependent_template_p (fn))
+ && dependent_template_p (fn))
dependent_p = true;
fns = OVL_NEXT (fns);
if (TREE_CODE (decl) == FIELD_DECL || BASELINK_P (decl))
*qualifying_class = parser->scope;
}
- /* Resolve references to variables of anonymous unions
- into COMPONENT_REFs. */
- else if (TREE_CODE (decl) == ALIAS_DECL)
- decl = DECL_INITIAL (decl);
else
/* Transform references to non-static data members into
COMPONENT_REFs. */
decl = hack_identifier (decl, id_expression);
+
+ /* Resolve references to variables of anonymous unions
+ into COMPONENT_REFs. */
+ if (TREE_CODE (decl) == ALIAS_DECL)
+ decl = DECL_INITIAL (decl);
}
if (TREE_DEPRECATED (decl))
function does not do this in order to avoid wastefully creating
SCOPE_REFs when they are not required.
- If ASSUME_TYPENAME_P is true then we assume that qualified names
- are typenames. This flag is set when parsing a declarator-id;
- for something like:
-
- template <class T>
- int S<T>::R::i = 3;
-
- we are supposed to assume that `S<T>::R' is a class.
-
If TEMPLATE_KEYWORD_P is true, then we have just seen the
`template' keyword.
If CHECK_DEPENDENCY_P is false, then names are looked up inside
uninstantiated templates.
- If *TEMPLATE_KEYWORD_P is non-NULL, it is set to true iff the
+ If *TEMPLATE_P is non-NULL, it is set to true iff the
`template' keyword is used to explicitly indicate that the entity
named is a template. */
cp_token *token;
tree id;
- /* We don't know yet whether or not this will be a
- template-id. */
+ /* Peek at the next token. */
+ token = cp_lexer_peek_token (parser->lexer);
+
+ /* If it's an identifier, and the next token is not a "<", then
+ we can avoid the template-id case. This is an optimization
+ for this common case. */
+ if (token->type == CPP_NAME
+ && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_LESS)
+ return cp_parser_identifier (parser);
+
cp_parser_parse_tentatively (parser);
/* Try a template-id. */
id = cp_parser_template_id (parser,
if (cp_parser_parse_definitely (parser))
return id;
- /* Peek at the next token. */
+ /* Peek at the next token. (Changes in the token buffer may
+ have invalidated the pointer obtained above.) */
token = cp_lexer_peek_token (parser->lexer);
switch (token->type)
names are looked up in uninstantiated templates. */
static tree
-cp_parser_unqualified_id (parser, template_keyword_p,
- check_dependency_p)
- cp_parser *parser;
- bool template_keyword_p;
- bool check_dependency_p;
+cp_parser_unqualified_id (cp_parser* parser,
+ bool template_keyword_p,
+ bool check_dependency_p)
{
cp_token *token;
bool success = false;
tree access_check = NULL_TREE;
ptrdiff_t start;
+ cp_token* token;
/* If the next token corresponds to a nested name specifier, there
- is no need to reparse it. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_NESTED_NAME_SPECIFIER))
- {
- tree value;
- tree check;
-
- /* Get the stored value. */
- value = cp_lexer_consume_token (parser->lexer)->value;
- /* Perform any access checks that were deferred. */
- for (check = TREE_PURPOSE (value); check; check = TREE_CHAIN (check))
- cp_parser_defer_access_check (parser,
- TREE_PURPOSE (check),
- TREE_VALUE (check));
- /* Set the scope from the stored value. */
- parser->scope = TREE_VALUE (value);
- parser->qualifying_scope = TREE_TYPE (value);
- parser->object_scope = NULL_TREE;
+ is no need to reparse it. However, if CHECK_DEPENDENCY_P is
+ false, it may have been true before, in which case something
+ like `A<X>::B<Y>::C' may have resulted in a nested-name-specifier
+ of `A<X>::', where it should now be `A<X>::B<Y>::'. So, when
+ CHECK_DEPENDENCY_P is false, we have to fall through into the
+ main loop. */
+ if (check_dependency_p
+ && cp_lexer_next_token_is (parser->lexer, CPP_NESTED_NAME_SPECIFIER))
+ {
+ cp_parser_pre_parsed_nested_name_specifier (parser);
return parser->scope;
}
if (cp_parser_parsing_tentatively (parser)
&& !cp_parser_committed_to_tentative_parse (parser))
{
- cp_token *next_token = cp_lexer_peek_token (parser->lexer);
+ token = cp_lexer_peek_token (parser->lexer);
start = cp_lexer_token_difference (parser->lexer,
parser->lexer->first_token,
- next_token);
- access_check = parser->context->deferred_access_checks;
+ token);
}
else
start = -1;
+ push_deferring_access_checks (true);
+
while (true)
{
tree new_scope;
tree old_scope;
tree saved_qualifying_scope;
- cp_token *token;
bool template_keyword_p;
/* Spot cases that cannot be the beginning of a
+ nested-name-specifier. */
+ token = cp_lexer_peek_token (parser->lexer);
+
+ /* If the next token is CPP_NESTED_NAME_SPECIFIER, just process
+ the already parsed nested-name-specifier. */
+ if (token->type == CPP_NESTED_NAME_SPECIFIER)
+ {
+ /* Grab the nested-name-specifier and continue the loop. */
+ cp_parser_pre_parsed_nested_name_specifier (parser);
+ success = true;
+ continue;
+ }
+
+ /* Spot cases that cannot be the beginning of a
nested-name-specifier. On the second and subsequent times
through the loop, we look for the `template' keyword. */
- if (success
- && cp_lexer_next_token_is_keyword (parser->lexer,
- RID_TEMPLATE))
+ if (success && token->keyword == RID_TEMPLATE)
;
/* A template-id can start a nested-name-specifier. */
- else if (cp_lexer_next_token_is (parser->lexer, CPP_TEMPLATE_ID))
+ else if (token->type == CPP_TEMPLATE_ID)
;
else
{
/* If the next token is not an identifier, then it is
definitely not a class-or-namespace-name. */
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+ if (token->type != CPP_NAME)
break;
/* If the following token is neither a `<' (to begin a
template-id), nor a `::', then we are not looking at a
token->value);
parser->scope = NULL_TREE;
error_p = true;
+ /* Treat this as a successful nested-name-specifier
+ due to:
+
+ [basic.lookup.qual]
+
+ If the name found is not a class-name (clause
+ _class_) or namespace-name (_namespace.def_), the
+ program is ill-formed. */
+ success = true;
}
cp_lexer_consume_token (parser->lexer);
}
: new_scope);
/* If it is a class scope, try to complete it; we are about to
be looking up names inside the class. */
- if (TYPE_P (parser->scope))
+ if (TYPE_P (parser->scope)
+ /* Since checking types for dependency can be expensive,
+ avoid doing it if the type is already complete. */
+ && !COMPLETE_TYPE_P (parser->scope)
+ /* Do not try to complete dependent types. */
+ && !dependent_type_p (parser->scope))
complete_type (parser->scope);
}
+ /* Retrieve any deferred checks. Do not pop this access checks yet
+ so the memory will not be reclaimed during token replacing below. */
+ access_check = get_deferred_access_checks ();
+
/* If parsing tentatively, replace the sequence of tokens that makes
up the nested-name-specifier with a CPP_NESTED_NAME_SPECIFIER
token. That way, should we re-parse the token stream, we will
we issue duplicate error messages. */
if (success && start >= 0)
{
- cp_token *token;
- tree c;
-
/* Find the token that corresponds to the start of the
template-id. */
token = cp_lexer_advance_token (parser->lexer,
parser->lexer->first_token,
start);
- /* Remember the access checks associated with this
- nested-name-specifier. */
- c = parser->context->deferred_access_checks;
- if (c == access_check)
- access_check = NULL_TREE;
- else
- {
- while (TREE_CHAIN (c) != access_check)
- c = TREE_CHAIN (c);
- access_check = parser->context->deferred_access_checks;
- parser->context->deferred_access_checks = TREE_CHAIN (c);
- TREE_CHAIN (c) = NULL_TREE;
- }
-
/* Reset the contents of the START token. */
token->type = CPP_NESTED_NAME_SPECIFIER;
token->value = build_tree_list (access_check, parser->scope);
cp_lexer_purge_tokens_after (parser->lexer, token);
}
+ pop_deferring_access_checks ();
return success ? parser->scope : NULL_TREE;
}
scope.
Returns the class (TYPE_DECL) or namespace (NAMESPACE_DECL)
- specified by the class-or-namespace-name. */
+ specified by the class-or-namespace-name. If neither is found the
+ ERROR_MARK_NODE is returned. */
static tree
cp_parser_class_or_namespace_name (cp_parser *parser,
tree saved_qualifying_scope;
tree saved_object_scope;
tree scope;
+ bool only_class_p;
/* If the next token is the `template' keyword, we know that we are
looking at a class-name. */
saved_scope = parser->scope;
saved_qualifying_scope = parser->qualifying_scope;
saved_object_scope = parser->object_scope;
- /* Try for a class-name first. */
- cp_parser_parse_tentatively (parser);
+ /* Try for a class-name first. If the SAVED_SCOPE is a type, then
+ there is no need to look for a namespace-name. */
+ only_class_p = saved_scope && TYPE_P (saved_scope);
+ if (!only_class_p)
+ cp_parser_parse_tentatively (parser);
scope = cp_parser_class_name (parser,
typename_keyword_p,
template_keyword_p,
check_dependency_p,
/*class_head_p=*/false);
/* If that didn't work, try for a namespace-name. */
- if (!cp_parser_parse_definitely (parser))
+ if (!only_class_p && !cp_parser_parse_definitely (parser))
{
/* Restore the saved scope. */
parser->scope = saved_scope;
parser->qualifying_scope = saved_qualifying_scope;
parser->object_scope = saved_object_scope;
- /* Now look for a namespace-name. */
+ /* If we are not looking at an identifier followed by the scope
+ resolution operator, then this is not part of a
+ nested-name-specifier. (Note that this function is only used
+ to parse the components of a nested-name-specifier.) */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME)
+ || cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_SCOPE)
+ return error_mark_node;
scope = cp_parser_namespace_name (parser);
}
Do Koenig lookup -- unless any of the arguments are
type-dependent. */
for (arg = args; arg; arg = TREE_CHAIN (arg))
- if (cp_parser_type_dependent_expression_p (TREE_VALUE (arg)))
+ if (type_dependent_expression_p (TREE_VALUE (arg)))
break;
if (!arg)
{
postfix_expression = (build_offset_ref_call_from_tree
(postfix_expression, args));
else if (idk == CP_PARSER_ID_KIND_QUALIFIED)
- {
- /* A call to a static class member, or a
- namespace-scope function. */
- postfix_expression
- = finish_call_expr (postfix_expression, args,
- /*disallow_virtual=*/true);
- }
+ /* A call to a static class member, or a namespace-scope
+ function. */
+ postfix_expression
+ = finish_call_expr (postfix_expression, args,
+ /*disallow_virtual=*/true);
else
- {
- /* All other function calls. */
- postfix_expression
- = finish_call_expr (postfix_expression, args,
- /*disallow_virtual=*/false);
- }
+ /* All other function calls. */
+ postfix_expression
+ = finish_call_expr (postfix_expression, args,
+ /*disallow_virtual=*/false);
/* The POSTFIX_EXPRESSION is certainly no longer an id. */
idk = CP_PARSER_ID_KIND_NONE;
postfix_expression = build_x_arrow (postfix_expression);
/* Check to see whether or not the expression is
type-dependent. */
- dependent_p = (cp_parser_type_dependent_expression_p
- (postfix_expression));
+ dependent_p = (type_dependent_expression_p (postfix_expression));
/* The identifier following the `->' or `.' is not
qualified. */
parser->scope = NULL_TREE;
is returned even if there is only a single expression in the list. */
static tree
-cp_parser_expression_list (parser)
- cp_parser *parser;
+cp_parser_expression_list (cp_parser* parser)
{
tree expression_list = NULL_TREE;
or ERROR_MARK_NODE if no type-name is present. */
static void
-cp_parser_pseudo_destructor_name (parser, scope, type)
- cp_parser *parser;
- tree *scope;
- tree *type;
+cp_parser_pseudo_destructor_name (cp_parser* parser,
+ tree* scope,
+ tree* type)
{
bool nested_name_specifier_p;
/* If the type of the operand cannot be determined build a
SIZEOF_EXPR. */
if (TYPE_P (operand)
- ? cp_parser_dependent_type_p (operand)
- : cp_parser_type_dependent_expression_p (operand))
+ ? dependent_type_p (operand)
+ : type_dependent_expression_p (operand))
return build_min (SIZEOF_EXPR, size_type_node, operand);
/* Otherwise, compute the constant value. */
else
unary-operator, the corresponding tree code is returned. */
static enum tree_code
-cp_parser_unary_operator (token)
- cp_token *token;
+cp_parser_unary_operator (cp_token* token)
{
switch (token->type)
{
Returns a representation of the expression. */
static tree
-cp_parser_new_expression (parser)
- cp_parser *parser;
+cp_parser_new_expression (cp_parser* parser)
{
bool global_scope_p;
tree placement;
Returns the same representation as for an expression-list. */
static tree
-cp_parser_new_placement (parser)
- cp_parser *parser;
+cp_parser_new_placement (cp_parser* parser)
{
tree expression_list;
and whose TREE_VALUE is the new-declarator. */
static tree
-cp_parser_new_type_id (parser)
- cp_parser *parser;
+cp_parser_new_type_id (cp_parser* parser)
{
tree type_specifier_seq;
tree declarator;
cp_parser_declarator for the representations used. */
static tree
-cp_parser_new_declarator_opt (parser)
- cp_parser *parser;
+cp_parser_new_declarator_opt (cp_parser* parser)
{
enum tree_code code;
tree type;
documented for cp_parser_direct_declarator. */
static tree
-cp_parser_direct_new_declarator (parser)
- cp_parser *parser;
+cp_parser_direct_new_declarator (cp_parser* parser)
{
tree declarator = NULL_TREE;
expression-list, VOID_ZERO_NODE is returned. */
static tree
-cp_parser_new_initializer (parser)
- cp_parser *parser;
+cp_parser_new_initializer (cp_parser* parser)
{
tree expression_list;
Returns a representation of the expression. */
static tree
-cp_parser_delete_expression (parser)
- cp_parser *parser;
+cp_parser_delete_expression (cp_parser* parser)
{
bool global_scope_p;
bool array_p;
Returns a representation of the expression. */
static tree
-cp_parser_pm_expression (parser)
- cp_parser *parser;
+cp_parser_pm_expression (cp_parser* parser)
{
tree cast_expr;
tree pm_expr;
Returns a representation of the expression. */
static tree
-cp_parser_multiplicative_expression (parser)
- cp_parser *parser;
+cp_parser_multiplicative_expression (cp_parser* parser)
{
- static cp_parser_token_tree_map map = {
+ static const cp_parser_token_tree_map map = {
{ CPP_MULT, MULT_EXPR },
{ CPP_DIV, TRUNC_DIV_EXPR },
{ CPP_MOD, TRUNC_MOD_EXPR },
Returns a representation of the expression. */
static tree
-cp_parser_additive_expression (parser)
- cp_parser *parser;
+cp_parser_additive_expression (cp_parser* parser)
{
- static cp_parser_token_tree_map map = {
+ static const cp_parser_token_tree_map map = {
{ CPP_PLUS, PLUS_EXPR },
{ CPP_MINUS, MINUS_EXPR },
{ CPP_EOF, ERROR_MARK }
Returns a representation of the expression. */
static tree
-cp_parser_shift_expression (parser)
- cp_parser *parser;
+cp_parser_shift_expression (cp_parser* parser)
{
- static cp_parser_token_tree_map map = {
+ static const cp_parser_token_tree_map map = {
{ CPP_LSHIFT, LSHIFT_EXPR },
{ CPP_RSHIFT, RSHIFT_EXPR },
{ CPP_EOF, ERROR_MARK }
Returns a representation of the expression. */
static tree
-cp_parser_relational_expression (parser)
- cp_parser *parser;
+cp_parser_relational_expression (cp_parser* parser)
{
- static cp_parser_token_tree_map map = {
+ static const cp_parser_token_tree_map map = {
{ CPP_LESS, LT_EXPR },
{ CPP_GREATER, GT_EXPR },
{ CPP_LESS_EQ, LE_EXPR },
Returns a representation of the expression. */
static tree
-cp_parser_equality_expression (parser)
- cp_parser *parser;
+cp_parser_equality_expression (cp_parser* parser)
{
- static cp_parser_token_tree_map map = {
+ static const cp_parser_token_tree_map map = {
{ CPP_EQ_EQ, EQ_EXPR },
{ CPP_NOT_EQ, NE_EXPR },
{ CPP_EOF, ERROR_MARK }
Returns a representation of the expression. */
static tree
-cp_parser_and_expression (parser)
- cp_parser *parser;
+cp_parser_and_expression (cp_parser* parser)
{
- static cp_parser_token_tree_map map = {
+ static const cp_parser_token_tree_map map = {
{ CPP_AND, BIT_AND_EXPR },
{ CPP_EOF, ERROR_MARK }
};
Returns a representation of the expression. */
static tree
-cp_parser_exclusive_or_expression (parser)
- cp_parser *parser;
+cp_parser_exclusive_or_expression (cp_parser* parser)
{
- static cp_parser_token_tree_map map = {
+ static const cp_parser_token_tree_map map = {
{ CPP_XOR, BIT_XOR_EXPR },
{ CPP_EOF, ERROR_MARK }
};
Returns a representation of the expression. */
static tree
-cp_parser_inclusive_or_expression (parser)
- cp_parser *parser;
+cp_parser_inclusive_or_expression (cp_parser* parser)
{
- static cp_parser_token_tree_map map = {
+ static const cp_parser_token_tree_map map = {
{ CPP_OR, BIT_IOR_EXPR },
{ CPP_EOF, ERROR_MARK }
};
Returns a representation of the expression. */
static tree
-cp_parser_logical_and_expression (parser)
- cp_parser *parser;
+cp_parser_logical_and_expression (cp_parser* parser)
{
- static cp_parser_token_tree_map map = {
+ static const cp_parser_token_tree_map map = {
{ CPP_AND_AND, TRUTH_ANDIF_EXPR },
{ CPP_EOF, ERROR_MARK }
};
Returns a representation of the expression. */
static tree
-cp_parser_logical_or_expression (parser)
- cp_parser *parser;
+cp_parser_logical_or_expression (cp_parser* parser)
{
- static cp_parser_token_tree_map map = {
+ static const cp_parser_token_tree_map map = {
{ CPP_OR_OR, TRUTH_ORIF_EXPR },
{ CPP_EOF, ERROR_MARK }
};
Returns a representation of the expression. */
static tree
-cp_parser_conditional_expression (parser)
- cp_parser *parser;
+cp_parser_conditional_expression (cp_parser* parser)
{
tree logical_or_expr;
? : assignment-expression */
static tree
-cp_parser_question_colon_clause (parser, logical_or_expr)
- cp_parser *parser;
- tree logical_or_expr;
+cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
{
tree expr;
tree assignment_expr;
Returns a representation for the expression. */
static tree
-cp_parser_assignment_expression (parser)
- cp_parser *parser;
+cp_parser_assignment_expression (cp_parser* parser)
{
tree expr;
operator, ERROR_MARK is returned. */
static enum tree_code
-cp_parser_assignment_operator_opt (parser)
- cp_parser *parser;
+cp_parser_assignment_operator_opt (cp_parser* parser)
{
enum tree_code op;
cp_token *token;
Returns a representation of the expression. */
static tree
-cp_parser_expression (parser)
- cp_parser *parser;
+cp_parser_expression (cp_parser* parser)
{
tree expression = NULL_TREE;
bool saw_comma_p = false;
conditional-expression */
static tree
-cp_parser_constant_expression (parser)
- cp_parser *parser;
+cp_parser_constant_expression (cp_parser* parser)
{
bool saved_constant_expression_p;
tree expression;
try-block */
static void
-cp_parser_statement (parser)
- cp_parser *parser;
+cp_parser_statement (cp_parser* parser)
{
tree statement;
cp_token *token;
an ordinary label, returns a LABEL_STMT. */
static tree
-cp_parser_labeled_statement (parser)
- cp_parser *parser;
+cp_parser_labeled_statement (cp_parser* parser)
{
cp_token *token;
tree statement = NULL_TREE;
statement consists of nothing more than an `;'. */
static tree
-cp_parser_expression_statement (parser)
- cp_parser *parser;
+cp_parser_expression_statement (cp_parser* parser)
{
tree statement;
statement = NULL_TREE;
}
/* Consume the final `;'. */
- if (!cp_parser_require (parser, CPP_SEMICOLON, "`;'"))
- {
- /* If there is additional (erroneous) input, skip to the end of
- the statement. */
- cp_parser_skip_to_end_of_statement (parser);
- /* If the next token is now a `;', consume it. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
- cp_lexer_consume_token (parser->lexer);
- }
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
return statement;
}
statement-seq [opt] statement */
static void
-cp_parser_statement_seq_opt (parser)
- cp_parser *parser;
+cp_parser_statement_seq_opt (cp_parser* parser)
{
/* Scan statements until there aren't any more. */
while (true)
Returns the new IF_STMT or SWITCH_STMT. */
static tree
-cp_parser_selection_statement (parser)
- cp_parser *parser;
+cp_parser_selection_statement (cp_parser* parser)
{
cp_token *token;
enum rid keyword;
Returns the expression that should be tested. */
static tree
-cp_parser_condition (parser)
- cp_parser *parser;
+cp_parser_condition (cp_parser* parser)
{
tree type_specifiers;
const char *saved_message;
tree initializer = NULL_TREE;
/* Parse the declarator. */
- declarator = cp_parser_declarator (parser,
- /*abstract_p=*/false,
+ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
/*ctor_dtor_or_conv_p=*/NULL);
/* Parse the attributes. */
attributes = cp_parser_attributes_opt (parser);
Returns the new WHILE_STMT, DO_STMT, or FOR_STMT. */
static tree
-cp_parser_iteration_statement (parser)
- cp_parser *parser;
+cp_parser_iteration_statement (cp_parser* parser)
{
cp_token *token;
enum rid keyword;
simple-declaration */
static void
-cp_parser_for_init_statement (parser)
- cp_parser *parser;
+cp_parser_for_init_statement (cp_parser* parser)
{
/* If the next token is a `;', then we have an empty
expression-statement. Gramatically, this is also a
GOTO_STMT. */
static tree
-cp_parser_jump_statement (parser)
- cp_parser *parser;
+cp_parser_jump_statement (cp_parser* parser)
{
tree statement = error_mark_node;
cp_token *token;
block-declaration */
static void
-cp_parser_declaration_statement (parser)
- cp_parser *parser;
+cp_parser_declaration_statement (cp_parser* parser)
{
/* Parse the block-declaration. */
cp_parser_block_declaration (parser, /*statement_p=*/true);
Returns the new statement. */
static tree
-cp_parser_implicitly_scoped_statement (parser)
- cp_parser *parser;
+cp_parser_implicitly_scoped_statement (cp_parser* parser)
{
tree statement;
scope. */
static void
-cp_parser_already_scoped_statement (parser)
- cp_parser *parser;
+cp_parser_already_scoped_statement (cp_parser* parser)
{
/* If the token is not a `{', then we must take special action. */
if (cp_lexer_next_token_is_not(parser->lexer, CPP_OPEN_BRACE))
declaration-seq declaration */
static void
-cp_parser_declaration_seq_opt (parser)
- cp_parser *parser;
+cp_parser_declaration_seq_opt (cp_parser* parser)
{
while (true)
{
continue;
}
+ /* The C lexer modifies PENDING_LANG_CHANGE when it wants the
+ parser to enter or exit implict `extern "C"' blocks. */
+ while (pending_lang_change > 0)
+ {
+ push_lang_context (lang_name_c);
+ --pending_lang_change;
+ }
+ while (pending_lang_change < 0)
+ {
+ pop_lang_context ();
+ ++pending_lang_change;
+ }
+
+ /* Parse the declaration itself. */
cp_parser_declaration (parser);
}
}
explicit-instantiation
explicit-specialization
linkage-specification
- namespace-definition */
+ namespace-definition
+
+ GNU extension:
+
+ declaration:
+ __extension__ declaration */
static void
-cp_parser_declaration (parser)
- cp_parser *parser;
+cp_parser_declaration (cp_parser* parser)
{
cp_token token1;
cp_token token2;
+ int saved_pedantic;
+
+ /* Check for the `__extension__' keyword. */
+ if (cp_parser_extension_opt (parser, &saved_pedantic))
+ {
+ /* Parse the qualified declaration. */
+ cp_parser_declaration (parser);
+ /* Restore the PEDANTIC flag. */
+ pedantic = saved_pedantic;
+
+ return;
+ }
/* Try to figure out what kind of declaration is present. */
token1 = *cp_lexer_peek_token (parser->lexer);
function-definition as a simple-declaration. */
static void
-cp_parser_simple_declaration (parser, function_definition_allowed_p)
- cp_parser *parser;
- bool function_definition_allowed_p;
+cp_parser_simple_declaration (cp_parser* parser,
+ bool function_definition_allowed_p)
{
tree decl_specifiers;
tree attributes;
- tree access_checks;
bool declares_class_or_enum;
bool saw_declarator;
/* Defer access checks until we know what is being declared; the
checks for names appearing in the decl-specifier-seq should be
done as if we were in the scope of the thing being declared. */
- cp_parser_start_deferring_access_checks (parser);
+ push_deferring_access_checks (true);
+
/* Parse the decl-specifier-seq. We have to keep track of whether
or not the decl-specifier-seq declares a named class or
enumeration type, since that is the only case in which the
&attributes,
&declares_class_or_enum);
/* We no longer need to defer access checks. */
- access_checks = cp_parser_stop_deferring_access_checks (parser);
+ stop_deferring_access_checks ();
+
+ /* If the next two tokens are both identifiers, the code is
+ erroneous. The usual cause of this situation is code like:
+
+ T t;
+
+ where "T" should name a type -- but does not. */
+ if (cp_parser_diagnose_invalid_type_name (parser))
+ {
+ /* If parsing tenatively, we should commit; we really are
+ looking at a declaration. */
+ cp_parser_commit_to_tentative_parse (parser);
+ /* Give up. */
+ return;
+ }
/* Keep going until we hit the `;' at the end of the simple
declaration. */
saw_declarator = true;
/* Parse the init-declarator. */
cp_parser_init_declarator (parser, decl_specifiers, attributes,
- access_checks,
function_definition_allowed_p,
/*member_p=*/false,
&function_definition_p);
+ /* If an error occurred while parsing tentatively, exit quickly.
+ (That usually happens when in the body of a function; each
+ statement is treated as a declaration-statement until proven
+ otherwise.) */
+ if (cp_parser_error_occurred (parser))
+ {
+ pop_deferring_access_checks ();
+ return;
+ }
/* Handle function definitions specially. */
if (function_definition_p)
{
error ("mixing declarations and function-definitions is forbidden");
/* Otherwise, we're done with the list of declarators. */
else
- return;
+ {
+ pop_deferring_access_checks ();
+ return;
+ }
}
/* The next token should be either a `,' or a `;'. */
token = cp_lexer_peek_token (parser->lexer);
cp_parser_error (parser, "expected `,' or `;'");
/* Skip tokens until we reach the end of the statement. */
cp_parser_skip_to_end_of_statement (parser);
+ pop_deferring_access_checks ();
return;
}
/* After the first time around, a function-definition is not
if (cp_parser_declares_only_class_p (parser))
shadow_tag (decl_specifiers);
/* Perform any deferred access checks. */
- cp_parser_perform_deferred_access_checks (access_checks);
+ perform_deferred_access_checks ();
}
+ pop_deferring_access_checks ();
+
/* Consume the `;'. */
cp_parser_require (parser, CPP_SEMICOLON, "`;'");
friendship is granted might not be a class. */
static tree
-cp_parser_decl_specifier_seq (parser, flags, attributes,
- declares_class_or_enum)
- cp_parser *parser;
- cp_parser_flags flags;
- tree *attributes;
- bool *declares_class_or_enum;
+cp_parser_decl_specifier_seq (cp_parser* parser,
+ cp_parser_flags flags,
+ tree* attributes,
+ bool* declares_class_or_enum)
{
tree decl_specs = NULL_TREE;
bool friend_p = false;
+ bool constructor_possible_p = true;
/* Assume no class or enumeration type is declared. */
*declares_class_or_enum = false;
decl_spec = token->value;
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
+ /* A constructor declarator cannot appear in a typedef. */
+ constructor_possible_p = false;
+ /* The "typedef" keyword can only occur in a declaration; we
+ may as well commit at this point. */
+ cp_parser_commit_to_tentative_parse (parser);
break;
/* storage-class-specifier:
/* Constructors are a special case. The `S' in `S()' is not a
decl-specifier; it is the beginning of the declarator. */
constructor_p = (!decl_spec
+ && constructor_possible_p
&& cp_parser_constructor_declarator_p (parser,
friend_p));
error message later. */
if (decl_spec && !is_cv_qualifier)
flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
+ /* A constructor declarator cannot follow a type-specifier. */
+ if (decl_spec)
+ constructor_possible_p = false;
}
/* If we still do not have a DECL_SPEC, then there are no more
Returns an IDENTIFIER_NODE corresponding to the keyword used. */
static tree
-cp_parser_storage_class_specifier_opt (parser)
- cp_parser *parser;
+cp_parser_storage_class_specifier_opt (cp_parser* parser)
{
switch (cp_lexer_peek_token (parser->lexer)->keyword)
{
Returns an IDENTIFIER_NODE corresponding to the keyword used. */
static tree
-cp_parser_function_specifier_opt (parser)
- cp_parser *parser;
+cp_parser_function_specifier_opt (cp_parser* parser)
{
switch (cp_lexer_peek_token (parser->lexer)->keyword)
{
extern string-literal declaration */
static void
-cp_parser_linkage_specification (parser)
- cp_parser *parser;
+cp_parser_linkage_specification (cp_parser* parser)
{
cp_token *token;
tree linkage;
Returns an IDENTIFIER_NODE representing the operator. */
static tree
-cp_parser_conversion_function_id (parser)
- cp_parser *parser;
+cp_parser_conversion_function_id (cp_parser* parser)
{
tree type;
tree saved_scope;
Returns the TYPE specified. */
static tree
-cp_parser_conversion_type_id (parser)
- cp_parser *parser;
+cp_parser_conversion_type_id (cp_parser* parser)
{
tree attributes;
tree type_specifiers;
cp_parser_declarator for details. */
static tree
-cp_parser_conversion_declarator_opt (parser)
- cp_parser *parser;
+cp_parser_conversion_declarator_opt (cp_parser* parser)
{
enum tree_code code;
tree class_type;
Returns TRUE iff the ctor-initializer was actually present. */
static bool
-cp_parser_ctor_initializer_opt (parser)
- cp_parser *parser;
+cp_parser_ctor_initializer_opt (cp_parser* parser)
{
/* If the next token is not a `:', then there is no
ctor-initializer. */
mem-initializer , mem-initializer-list */
static void
-cp_parser_mem_initializer_list (parser)
- cp_parser *parser;
+cp_parser_mem_initializer_list (cp_parser* parser)
{
tree mem_initializer_list = NULL_TREE;
the TREE_VALUE is the expression-list. */
static tree
-cp_parser_mem_initializer (parser)
- cp_parser *parser;
+cp_parser_mem_initializer (cp_parser* parser)
{
tree mem_initializer_id;
tree expression_list;
to be initialized for the second production. */
static tree
-cp_parser_mem_initializer_id (parser)
- cp_parser *parser;
+cp_parser_mem_initializer_id (cp_parser* parser)
{
bool global_scope_p;
bool nested_name_specifier_p;
human-readable spelling of the identifier, e.g., `operator +'. */
static tree
-cp_parser_operator_function_id (parser)
- cp_parser *parser;
+cp_parser_operator_function_id (cp_parser* parser)
{
/* Look for the `operator' keyword. */
if (!cp_parser_require_keyword (parser, RID_OPERATOR, "`operator'"))
human-readable spelling of the identifier, e.g., `operator +'. */
static tree
-cp_parser_operator (parser)
- cp_parser *parser;
+cp_parser_operator (cp_parser* parser)
{
tree id = NULL_TREE;
cp_token *token;
template < template-parameter-list > */
static void
-cp_parser_template_declaration (parser, member_p)
- cp_parser *parser;
- bool member_p;
+cp_parser_template_declaration (cp_parser* parser, bool member_p)
{
/* Check for `export'. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_EXPORT))
The nodes are connected via their TREE_CHAINs. */
static tree
-cp_parser_template_parameter_list (parser)
- cp_parser *parser;
+cp_parser_template_parameter_list (cp_parser* parser)
{
tree parameter_list = NULL_TREE;
TREE_PURPOSE is the default value, if any. */
static tree
-cp_parser_template_parameter (parser)
- cp_parser *parser;
+cp_parser_template_parameter (cp_parser* parser)
{
cp_token *token;
of the template parameter-list rather than a greater-than
operator. */
return
- cp_parser_parameter_declaration (parser,
- /*greater_than_is_operator_p=*/false);
+ cp_parser_parameter_declaration (parser, /*template_parm_p=*/true);
}
/* Parse a type-parameter.
the declaration of the parameter. */
static tree
-cp_parser_type_parameter (parser)
- cp_parser *parser;
+cp_parser_type_parameter (cp_parser* parser)
{
cp_token *token;
tree parameter;
bool saved_greater_than_is_operator_p;
ptrdiff_t start_of_id;
tree access_check = NULL_TREE;
+ cp_token *next_token;
/* If the next token corresponds to a template-id, there is no need
to reparse it. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_TEMPLATE_ID))
+ next_token = cp_lexer_peek_token (parser->lexer);
+ if (next_token->type == CPP_TEMPLATE_ID)
{
tree value;
tree check;
value = cp_lexer_consume_token (parser->lexer)->value;
/* Perform any access checks that were deferred. */
for (check = TREE_PURPOSE (value); check; check = TREE_CHAIN (check))
- cp_parser_defer_access_check (parser,
- TREE_PURPOSE (check),
- TREE_VALUE (check));
+ perform_or_defer_access_check (TREE_PURPOSE (check),
+ TREE_VALUE (check));
/* Return the stored value. */
return TREE_VALUE (value);
}
+ /* Avoid performing name lookup if there is no possibility of
+ finding a template-id. */
+ if ((next_token->type != CPP_NAME && next_token->keyword != RID_OPERATOR)
+ || (next_token->type == CPP_NAME
+ && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_LESS))
+ {
+ cp_parser_error (parser, "expected template-id");
+ return error_mark_node;
+ }
+
/* Remember where the template-id starts. */
if (cp_parser_parsing_tentatively (parser)
&& !cp_parser_committed_to_tentative_parse (parser))
{
- cp_token *next_token = cp_lexer_peek_token (parser->lexer);
+ next_token = cp_lexer_peek_token (parser->lexer);
start_of_id = cp_lexer_token_difference (parser->lexer,
parser->lexer->first_token,
next_token);
- access_check = parser->context->deferred_access_checks;
}
else
start_of_id = -1;
+ push_deferring_access_checks (true);
+
/* Parse the template-name. */
template = cp_parser_template_name (parser, template_keyword_p,
check_dependency_p);
if (template == error_mark_node)
- return error_mark_node;
+ {
+ pop_deferring_access_checks ();
+ return error_mark_node;
+ }
/* Look for the `<' that starts the template-argument-list. */
if (!cp_parser_require (parser, CPP_LESS, "`<'"))
- return error_mark_node;
+ {
+ pop_deferring_access_checks ();
+ return error_mark_node;
+ }
/* [temp.names]
template_id = lookup_template_function (template, arguments);
}
+ /* Retrieve any deferred checks. Do not pop this access checks yet
+ so the memory will not be reclaimed during token replacing below. */
+ access_check = get_deferred_access_checks ();
+
/* If parsing tentatively, replace the sequence of tokens that makes
up the template-id with a CPP_TEMPLATE_ID token. That way,
should we re-parse the token stream, we will not have to repeat
if (start_of_id >= 0)
{
cp_token *token;
- tree c;
/* Find the token that corresponds to the start of the
template-id. */
parser->lexer->first_token,
start_of_id);
- /* Remember the access checks associated with this
- nested-name-specifier. */
- c = parser->context->deferred_access_checks;
- if (c == access_check)
- access_check = NULL_TREE;
- else
- {
- while (TREE_CHAIN (c) != access_check)
- c = TREE_CHAIN (c);
- access_check = parser->context->deferred_access_checks;
- parser->context->deferred_access_checks = TREE_CHAIN (c);
- TREE_CHAIN (c) = NULL_TREE;
- }
-
/* Reset the contents of the START_OF_ID token. */
token->type = CPP_TEMPLATE_ID;
token->value = build_tree_list (access_check, template_id);
cp_lexer_purge_tokens_after (parser->lexer, token);
}
+ pop_deferring_access_checks ();
return template_id;
}
names are looked up inside uninstantiated templates. */
static tree
-cp_parser_template_name (parser, template_keyword_p, check_dependency_p)
- cp_parser *parser;
- bool template_keyword_p;
- bool check_dependency_p;
+cp_parser_template_name (cp_parser* parser,
+ bool template_keyword_p,
+ bool check_dependency_p)
{
tree identifier;
tree decl;
decl = cp_parser_lookup_name (parser, identifier,
/*check_access=*/true,
/*is_type=*/false,
+ /*is_namespace=*/false,
check_dependency_p);
decl = maybe_get_template_decl_from_type_decl (decl);
if (DECL_FUNCTION_TEMPLATE_P (decl) || !DECL_P (decl))
{
tree scope = CP_DECL_CONTEXT (get_first_fn (decl));
- if (TYPE_P (scope) && cp_parser_dependent_type_p (scope))
+ if (TYPE_P (scope) && dependent_type_p (scope))
return identifier;
}
argument. */
static tree
-cp_parser_template_argument_list (parser)
- cp_parser *parser;
+cp_parser_template_argument_list (cp_parser* parser)
{
tree arguments = NULL_TREE;
OVERLOAD. */
static tree
-cp_parser_template_argument (parser)
- cp_parser *parser;
+cp_parser_template_argument (cp_parser* parser)
{
tree argument;
bool template_p;
Therefore, we try a type-id first. */
cp_parser_parse_tentatively (parser);
- /* Otherwise, try a type-id. */
argument = cp_parser_type_id (parser);
/* If the next token isn't a `,' or a `>', then this argument wasn't
really finished. */
decl-specifier-seq [opt] declarator [opt] ; */
static void
-cp_parser_explicit_instantiation (parser)
- cp_parser *parser;
+cp_parser_explicit_instantiation (cp_parser* parser)
{
bool declares_class_or_enum;
tree decl_specifiers;
/* Parse the declarator. */
declarator
- = cp_parser_declarator (parser,
- /*abstract_p=*/false,
+ = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
/*ctor_dtor_or_conv_p=*/NULL);
decl = grokdeclarator (declarator, decl_specifiers,
NORMAL, 0, NULL);
/* Trun access control back on. */
scope_chain->check_access = flag_access_control;
- /* Look for the trailing `;'. */
- cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+ cp_parser_consume_semicolon_at_end_of_statement (parser);
}
/* Parse an explicit-specialization.
template <> template-declaration */
static void
-cp_parser_explicit_specialization (parser)
- cp_parser *parser;
+cp_parser_explicit_specialization (cp_parser* parser)
{
/* Look for the `template' keyword. */
cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'");
is set to FALSE. */
static tree
-cp_parser_type_specifier (parser,
- flags,
- is_friend,
- is_declaration,
- declares_class_or_enum,
- is_cv_qualifier)
- cp_parser *parser;
- cp_parser_flags flags;
- bool is_friend;
- bool is_declaration;
- bool *declares_class_or_enum;
- bool *is_cv_qualifier;
+cp_parser_type_specifier (cp_parser* parser,
+ cp_parser_flags flags,
+ bool is_friend,
+ bool is_declaration,
+ bool* declares_class_or_enum,
+ bool* is_cv_qualifier)
{
tree type_spec = NULL_TREE;
cp_token *token;
productions, the value returned is the indicated TYPE_DECL. */
static tree
-cp_parser_simple_type_specifier (parser, flags)
- cp_parser *parser;
- cp_parser_flags flags;
+cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags)
{
tree type = NULL_TREE;
cp_token *token;
Returns a TYPE_DECL for the the type. */
static tree
-cp_parser_type_name (parser)
- cp_parser *parser;
+cp_parser_type_name (cp_parser* parser)
{
tree type_decl;
tree identifier;
Returns the TYPE specified. */
static tree
-cp_parser_elaborated_type_specifier (parser, is_friend, is_declaration)
- cp_parser *parser;
- bool is_friend;
- bool is_declaration;
+cp_parser_elaborated_type_specifier (cp_parser* parser,
+ bool is_friend,
+ bool is_declaration)
{
enum tag_types tag_type;
tree identifier;
/*current_scope_valid_p=*/false);
/* Look for the nested-name-specifier. */
if (tag_type == typename_type)
- cp_parser_nested_name_specifier (parser,
- /*typename_keyword_p=*/true,
- /*check_dependency_p=*/true,
- /*type_p=*/true);
+ {
+ if (cp_parser_nested_name_specifier (parser,
+ /*typename_keyword_p=*/true,
+ /*check_dependency_p=*/true,
+ /*type_p=*/true)
+ == error_mark_node)
+ return error_mark_node;
+ }
else
/* Even though `typename' is not present, the proposed resolution
to Core Issue 180 says that in `class A<T>::B', `B' should be
decl = cp_parser_lookup_name (parser, identifier,
/*check_access=*/true,
/*is_type=*/true,
+ /*is_namespace=*/false,
/*check_dependency=*/true);
decl = (cp_parser_maybe_treat_template_as_class
(decl, /*tag_name_p=*/is_friend));
Returns an ENUM_TYPE representing the enumeration. */
static tree
-cp_parser_enum_specifier (parser)
- cp_parser *parser;
+cp_parser_enum_specifier (cp_parser* parser)
{
cp_token *token;
tree identifier = NULL_TREE;
enumerator-list , enumerator-definition */
static void
-cp_parser_enumerator_list (parser, type)
- cp_parser *parser;
- tree type;
+cp_parser_enumerator_list (cp_parser* parser, tree type)
{
while (true)
{
identifier */
static void
-cp_parser_enumerator_definition (parser, type)
- cp_parser *parser;
- tree type;
+cp_parser_enumerator_definition (cp_parser* parser, tree type)
{
cp_token *token;
tree identifier;
Returns the NAMESPACE_DECL for the namespace. */
static tree
-cp_parser_namespace_name (parser)
- cp_parser *parser;
+cp_parser_namespace_name (cp_parser* parser)
{
tree identifier;
tree namespace_decl;
if (identifier == error_mark_node)
return error_mark_node;
- /* Look up the identifier in the currently active scope. */
- namespace_decl = cp_parser_lookup_name_simple (parser, identifier);
+ /* Look up the identifier in the currently active scope. Look only
+ for namespaces, due to:
+
+ [basic.lookup.udir]
+
+ When looking up a namespace-name in a using-directive or alias
+ definition, only namespace names are considered.
+
+ And:
+
+ [basic.lookup.qual]
+
+ During the lookup of a name preceding the :: scope resolution
+ operator, object, function, and enumerator names are ignored.
+
+ (Note that cp_parser_class_or_namespace_name only calls this
+ function if the token after the name is the scope resolution
+ operator.) */
+ namespace_decl = cp_parser_lookup_name (parser, identifier,
+ /*check_access=*/true,
+ /*is_type=*/false,
+ /*is_namespace=*/true,
+ /*check_dependency=*/true);
/* If it's not a namespace, issue an error. */
if (namespace_decl == error_mark_node
|| TREE_CODE (namespace_decl) != NAMESPACE_DECL)
namespace { namespace-body } */
static void
-cp_parser_namespace_definition (parser)
- cp_parser *parser;
+cp_parser_namespace_definition (cp_parser* parser)
{
tree identifier;
declaration-seq [opt] */
static void
-cp_parser_namespace_body (parser)
- cp_parser *parser;
+cp_parser_namespace_body (cp_parser* parser)
{
cp_parser_declaration_seq_opt (parser);
}
namespace identifier = qualified-namespace-specifier ; */
static void
-cp_parser_namespace_alias_definition (parser)
- cp_parser *parser;
+cp_parser_namespace_alias_definition (cp_parser* parser)
{
tree identifier;
tree namespace_specifier;
namespace. */
static tree
-cp_parser_qualified_namespace_specifier (parser)
- cp_parser *parser;
+cp_parser_qualified_namespace_specifier (cp_parser* parser)
{
/* Look for the optional `::'. */
cp_parser_global_scope_opt (parser,
using :: unqualified-id ; */
static void
-cp_parser_using_declaration (parser)
- cp_parser *parser;
+cp_parser_using_declaration (cp_parser* parser)
{
cp_token *token;
bool typename_p = false;
else
{
decl = cp_parser_lookup_name_simple (parser, identifier);
- if (scope)
+ if (decl == error_mark_node)
+ {
+ if (parser->scope && parser->scope != global_namespace)
+ error ("`%D::%D' has not been declared",
+ parser->scope, identifier);
+ else
+ error ("`::%D' has not been declared", identifier);
+ }
+ else if (scope)
do_local_using_decl (decl);
else
do_toplevel_using_decl (decl);
namespace-name ; */
static void
-cp_parser_using_directive (parser)
- cp_parser *parser;
+cp_parser_using_directive (cp_parser* parser)
{
tree namespace_decl;
: asm-operand-list [opt] ) ; */
static void
-cp_parser_asm_definition (parser)
- cp_parser *parser;
+cp_parser_asm_definition (cp_parser* parser)
{
cp_token *token;
tree string;
if (cp_lexer_next_token_is_not (parser->lexer,
CPP_COLON)
&& cp_lexer_next_token_is_not (parser->lexer,
- CPP_SCOPE))
+ CPP_SCOPE)
+ && cp_lexer_next_token_is_not (parser->lexer,
+ CPP_CLOSE_PAREN))
outputs = cp_parser_asm_operand_list (parser);
}
/* If the next token is `::', there are no outputs, and the
if (cp_lexer_next_token_is_not (parser->lexer,
CPP_COLON)
&& cp_lexer_next_token_is_not (parser->lexer,
- CPP_SCOPE))
+ CPP_SCOPE)
+ && cp_lexer_next_token_is_not (parser->lexer,
+ CPP_CLOSE_PAREN))
inputs = cp_parser_asm_operand_list (parser);
}
else if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
/* Consume the `:'. */
cp_lexer_consume_token (parser->lexer);
/* Parse the clobbers. */
- clobbers = cp_parser_asm_clobber_list (parser);
+ if (cp_lexer_next_token_is_not (parser->lexer,
+ CPP_CLOSE_PAREN))
+ clobbers = cp_parser_asm_clobber_list (parser);
}
}
/* Look for the closing `)'. */
declarator asm-specification [opt] attributes [opt] initializer [opt]
The DECL_SPECIFIERS and PREFIX_ATTRIBUTES apply to this declarator.
- Returns a reprsentation of the entity declared. The ACCESS_CHECKS
- represent deferred access checks from the decl-specifier-seq. If
- MEMBER_P is TRUE, then this declarator appears in a class scope.
- The new DECL created by this declarator is returned.
+ Returns a reprsentation of the entity declared. If MEMBER_P is TRUE,
+ then this declarator appears in a class scope. The new DECL created
+ by this declarator is returned.
If FUNCTION_DEFINITION_ALLOWED_P then we handle the declarator and
for a function-definition here as well. If the declarator is a
is FALSE. */
static tree
-cp_parser_init_declarator (parser,
- decl_specifiers,
- prefix_attributes,
- access_checks,
- function_definition_allowed_p,
- member_p,
- function_definition_p)
- cp_parser *parser;
- tree decl_specifiers;
- tree prefix_attributes;
- tree access_checks;
- bool function_definition_allowed_p;
- bool member_p;
- bool *function_definition_p;
+cp_parser_init_declarator (cp_parser* parser,
+ tree decl_specifiers,
+ tree prefix_attributes,
+ bool function_definition_allowed_p,
+ bool member_p,
+ bool* function_definition_p)
{
cp_token *token;
tree declarator;
tree initializer;
tree decl = NULL_TREE;
tree scope;
- tree declarator_access_checks;
bool is_initialized;
bool is_parenthesized_init;
bool ctor_dtor_or_conv_p;
/* Defer access checks while parsing the declarator; we cannot know
what names are accessible until we know what is being
declared. */
- cp_parser_start_deferring_access_checks (parser);
+ resume_deferring_access_checks ();
+
/* Parse the declarator. */
declarator
- = cp_parser_declarator (parser,
- /*abstract_p=*/false,
+ = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
&ctor_dtor_or_conv_p);
/* Gather up the deferred checks. */
- declarator_access_checks
- = cp_parser_stop_deferring_access_checks (parser);
+ stop_deferring_access_checks ();
/* If the DECLARATOR was erroneous, there's no need to go
further. */
}
else
{
- tree *ac;
-
/* Neither attributes nor an asm-specification are allowed
on a function-definition. */
if (asm_specification)
/* This is a function-definition. */
*function_definition_p = true;
- /* Thread the access checks together. */
- ac = &access_checks;
- while (*ac)
- ac = &TREE_CHAIN (*ac);
- *ac = declarator_access_checks;
-
/* Parse the function definition. */
decl = (cp_parser_function_definition_from_specifiers_and_declarator
- (parser, decl_specifiers, prefix_attributes, declarator,
- access_checks));
-
- /* Pull the access-checks apart again. */
- *ac = NULL_TREE;
+ (parser, decl_specifiers, prefix_attributes, declarator));
return decl;
}
current_function_decl = decl;
}
- /* Perform the access control checks for the decl-specifiers. */
- cp_parser_perform_deferred_access_checks (access_checks);
- /* And for the declarator. */
- cp_parser_perform_deferred_access_checks (declarator_access_checks);
+ /* Perform the access control checks for the declarator and the
+ the decl-specifiers. */
+ perform_deferred_access_checks ();
/* Restore the saved value. */
if (TREE_CODE (decl) == FUNCTION_DECL)
expression, not a declaration.) */
static tree
-cp_parser_declarator (parser, abstract_p, ctor_dtor_or_conv_p)
- cp_parser *parser;
- bool abstract_p;
- bool *ctor_dtor_or_conv_p;
+cp_parser_declarator (cp_parser* parser,
+ cp_parser_declarator_kind dcl_kind,
+ bool* ctor_dtor_or_conv_p)
{
cp_token *token;
tree declarator;
{
/* The dependent declarator is optional if we are parsing an
abstract-declarator. */
- if (abstract_p)
+ if (dcl_kind != CP_PARSER_DECLARATOR_NAMED)
cp_parser_parse_tentatively (parser);
/* Parse the dependent declarator. */
- declarator = cp_parser_declarator (parser, abstract_p,
+ declarator = cp_parser_declarator (parser, dcl_kind,
/*ctor_dtor_or_conv_p=*/NULL);
/* If we are parsing an abstract-declarator, we must handle the
case where the dependent declarator is absent. */
- if (abstract_p && !cp_parser_parse_definitely (parser))
+ if (dcl_kind != CP_PARSER_DECLARATOR_NAMED
+ && !cp_parser_parse_definitely (parser))
declarator = NULL_TREE;
/* Build the representation of the ptr-operator. */
/* Everything else is a direct-declarator. */
else
declarator = cp_parser_direct_declarator (parser,
- abstract_p,
+ dcl_kind,
ctor_dtor_or_conv_p);
if (attributes && declarator != error_mark_node)
direct-abstract-declarator:
direct-abstract-declarator [opt]
- ( parameter-declaration-clause )
- cv-qualifier-seq [opt]
- exception-specification [opt]
- direct-abstract-declarator [opt] [ constant-expression [opt] ]
- ( abstract-declarator )
-
- Returns a representation of the declarator. ABSTRACT_P is TRUE if
- we are parsing a direct-abstract-declarator; FALSE if we are
- parsing a direct-declarator. CTOR_DTOR_OR_CONV_P is as for
- cp_parser_declarator.
-
- For the declarator-id production, the representation is as for an
- id-expression, except that a qualified name is represented as a
- SCOPE_REF. A function-declarator is represented as a CALL_EXPR;
- see the documentation of the FUNCTION_DECLARATOR_* macros for
- information about how to find the various declarator components.
- An array-declarator is represented as an ARRAY_REF. The
- direct-declarator is the first operand; the constant-expression
- indicating the size of the array is the second operand. */
-
-static tree
-cp_parser_direct_declarator (parser, abstract_p, ctor_dtor_or_conv_p)
- cp_parser *parser;
- bool abstract_p;
- bool *ctor_dtor_or_conv_p;
-{
- cp_token *token;
- tree declarator;
- tree scope = NULL_TREE;
- bool saved_default_arg_ok_p = parser->default_arg_ok_p;
- bool saved_in_declarator_p = parser->in_declarator_p;
-
- /* Peek at the next token. */
- token = cp_lexer_peek_token (parser->lexer);
- /* Find the initial direct-declarator. It might be a parenthesized
- declarator. */
- if (token->type == CPP_OPEN_PAREN)
- {
- /* For an abstract declarator we do not know whether we are
- looking at the beginning of a parameter-declaration-clause,
- or at a parenthesized abstract declarator. For example, if
- we see `(int)', we are looking at a
- parameter-declaration-clause, and the
- direct-abstract-declarator has been omitted. If, on the
- other hand we are looking at `((*))' then we are looking at a
- parenthesized abstract-declarator. There is no easy way to
- tell which situation we are in. */
- if (abstract_p)
- cp_parser_parse_tentatively (parser);
-
- /* Consume the `('. */
- cp_lexer_consume_token (parser->lexer);
- /* Parse the nested declarator. */
- declarator
- = cp_parser_declarator (parser, abstract_p, ctor_dtor_or_conv_p);
- /* Expect a `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
-
- /* If parsing a parenthesized abstract declarator didn't work,
- try a parameter-declaration-clause. */
- if (abstract_p && !cp_parser_parse_definitely (parser))
- declarator = NULL_TREE;
- /* If we were not parsing an abstract declarator, but failed to
- find a satisfactory nested declarator, then an error has
- occurred. */
- else if (!abstract_p && declarator == error_mark_node)
- return error_mark_node;
- /* Default args cannot appear in an abstract decl. */
- parser->default_arg_ok_p = false;
- }
- /* Otherwise, for a non-abstract declarator, there should be a
- declarator-id. */
- else if (!abstract_p)
- {
- declarator = cp_parser_declarator_id (parser);
-
- if (TREE_CODE (declarator) == SCOPE_REF)
- {
- scope = TREE_OPERAND (declarator, 0);
-
- /* In the declaration of a member of a template class
- outside of the class itself, the SCOPE will sometimes be
- a TYPENAME_TYPE. For example, given:
-
- template <typename T>
- int S<T>::R::i = 3;
-
- the SCOPE will be a TYPENAME_TYPE for `S<T>::R'. In this
- context, we must resolve S<T>::R to an ordinary type,
- rather than a typename type.
-
- The reason we normally avoid resolving TYPENAME_TYPEs is
- that a specialization of `S' might render `S<T>::R' not a
- type. However, if `S' is specialized, then this `i' will
- not be used, so there is no harm in resolving the types
- here. */
- if (TREE_CODE (scope) == TYPENAME_TYPE)
- {
- /* Resolve the TYPENAME_TYPE. */
- scope = cp_parser_resolve_typename_type (parser, scope);
- /* If that failed, the declarator is invalid. */
- if (scope == error_mark_node)
- return error_mark_node;
- /* Build a new DECLARATOR. */
- declarator = build_nt (SCOPE_REF,
- scope,
- TREE_OPERAND (declarator, 1));
- }
- }
- else if (TREE_CODE (declarator) != IDENTIFIER_NODE)
- /* Default args can only appear for a function decl. */
- parser->default_arg_ok_p = false;
-
- /* Check to see whether the declarator-id names a constructor,
- destructor, or conversion. */
- if (ctor_dtor_or_conv_p
- && ((TREE_CODE (declarator) == SCOPE_REF
- && CLASS_TYPE_P (TREE_OPERAND (declarator, 0)))
- || (TREE_CODE (declarator) != SCOPE_REF
- && at_class_scope_p ())))
- {
- tree unqualified_name;
- tree class_type;
-
- /* Get the unqualified part of the name. */
- if (TREE_CODE (declarator) == SCOPE_REF)
- {
- class_type = TREE_OPERAND (declarator, 0);
- unqualified_name = TREE_OPERAND (declarator, 1);
- }
- else
- {
- class_type = current_class_type;
- unqualified_name = declarator;
- }
+ ( parameter-declaration-clause )
+ cv-qualifier-seq [opt]
+ exception-specification [opt]
+ direct-abstract-declarator [opt] [ constant-expression [opt] ]
+ ( abstract-declarator )
- /* See if it names ctor, dtor or conv. */
- if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR
- || IDENTIFIER_TYPENAME_P (unqualified_name)
- || constructor_name_p (unqualified_name, class_type))
- {
- *ctor_dtor_or_conv_p = true;
- /* We would have cleared the default arg flag above, but
- they are ok. */
- parser->default_arg_ok_p = saved_default_arg_ok_p;
- }
- }
- }
- /* But for an abstract declarator, the initial direct-declarator can
- be omitted. */
- else
- {
- declarator = NULL_TREE;
- parser->default_arg_ok_p = false;
- }
+ Returns a representation of the declarator. DCL_KIND is
+ CP_PARSER_DECLARATOR_ABSTRACT, if we are parsing a
+ direct-abstract-declarator. It is CP_PARSER_DECLARATOR_NAMED, if
+ we are parsing a direct-declarator. It is
+ CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case
+ of ambiguity we prefer an abstract declarator, as per
+ [dcl.ambig.res]. CTOR_DTOR_OR_CONV_P is as for
+ cp_parser_declarator.
- scope = get_scope_of_declarator (declarator);
- if (scope)
- /* Any names that appear after the declarator-id for a member
- are looked up in the containing scope. */
- push_scope (scope);
- else
- scope = NULL_TREE;
- parser->in_declarator_p = true;
+ For the declarator-id production, the representation is as for an
+ id-expression, except that a qualified name is represented as a
+ SCOPE_REF. A function-declarator is represented as a CALL_EXPR;
+ see the documentation of the FUNCTION_DECLARATOR_* macros for
+ information about how to find the various declarator components.
+ An array-declarator is represented as an ARRAY_REF. The
+ direct-declarator is the first operand; the constant-expression
+ indicating the size of the array is the second operand. */
- /* Now, parse function-declarators and array-declarators until there
- are no more. */
+static tree
+cp_parser_direct_declarator (cp_parser* parser,
+ cp_parser_declarator_kind dcl_kind,
+ bool* ctor_dtor_or_conv_p)
+{
+ cp_token *token;
+ tree declarator = NULL_TREE;
+ tree scope = NULL_TREE;
+ bool saved_default_arg_ok_p = parser->default_arg_ok_p;
+ bool saved_in_declarator_p = parser->in_declarator_p;
+ bool first = true;
+
while (true)
{
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
- /* If it's a `[', we're looking at an array-declarator. */
- if (token->type == CPP_OPEN_SQUARE)
+ if (token->type == CPP_OPEN_PAREN)
{
- tree bounds;
-
- /* Consume the `['. */
- cp_lexer_consume_token (parser->lexer);
- /* Peek at the next token. */
- token = cp_lexer_peek_token (parser->lexer);
- /* If the next token is `]', then there is no
- constant-expression. */
- if (token->type != CPP_CLOSE_SQUARE)
- bounds = cp_parser_constant_expression (parser);
- else
- bounds = NULL_TREE;
- /* Look for the closing `]'. */
- cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+ /* This is either a parameter-declaration-clause, or a
+ parenthesized declarator. When we know we are parsing a
+ named declarator, it must be a paranthesized declarator
+ if FIRST is true. For instance, `(int)' is a
+ parameter-declaration-clause, with an omitted
+ direct-abstract-declarator. But `((*))', is a
+ parenthesized abstract declarator. Finally, when T is a
+ template parameter `(T)' is a
+ paremeter-declaration-clause, and not a parenthesized
+ named declarator.
+
+ We first try and parse a parameter-declaration-clause,
+ and then try a nested declarator (if FIRST is true).
- declarator = build_nt (ARRAY_REF, declarator, bounds);
- }
- /* If it's a `(', we're looking at a function-declarator. */
- else if (token->type == CPP_OPEN_PAREN)
- {
- /* A function-declarator. Or maybe not. Consider, for
- example:
+ It is not an error for it not to be a
+ parameter-declaration-clause, even when FIRST is
+ false. Consider,
int i (int);
int i (3);
The former is a function-declaration; the latter is a
variable initialization.
- First, we attempt to parse a parameter-declaration
- clause. If this works, then we continue; otherwise, we
- replace the tokens consumed in the process and continue. */
- tree params;
+ Thus again, we try a parameter-declation-clause, and if
+ that fails, we back out and return. */
- /* We are now parsing tentatively. */
- cp_parser_parse_tentatively (parser);
+ if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
+ {
+ tree params;
+
+ cp_parser_parse_tentatively (parser);
+
+ /* Consume the `('. */
+ cp_lexer_consume_token (parser->lexer);
+ if (first)
+ {
+ /* If this is going to be an abstract declarator, we're
+ in a declarator and we can't have default args. */
+ parser->default_arg_ok_p = false;
+ parser->in_declarator_p = true;
+ }
- /* Consume the `('. */
- cp_lexer_consume_token (parser->lexer);
- /* Parse the parameter-declaration-clause. */
- params = cp_parser_parameter_declaration_clause (parser);
+ /* Parse the parameter-declaration-clause. */
+ params = cp_parser_parameter_declaration_clause (parser);
+
+ /* If all went well, parse the cv-qualifier-seq and the
+ exception-specfication. */
+ if (cp_parser_parse_definitely (parser))
+ {
+ tree cv_qualifiers;
+ tree exception_specification;
+
+ first = false;
+ /* Consume the `)'. */
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+ /* Parse the cv-qualifier-seq. */
+ cv_qualifiers = cp_parser_cv_qualifier_seq_opt (parser);
+ /* And the exception-specification. */
+ exception_specification
+ = cp_parser_exception_specification_opt (parser);
+
+ /* Create the function-declarator. */
+ declarator = make_call_declarator (declarator,
+ params,
+ cv_qualifiers,
+ exception_specification);
+ /* Any subsequent parameter lists are to do with
+ return type, so are not those of the declared
+ function. */
+ parser->default_arg_ok_p = false;
+
+ /* Repeat the main loop. */
+ continue;
+ }
+ }
- /* If all went well, parse the cv-qualifier-seq and the
- exception-specification. */
- if (cp_parser_parse_definitely (parser))
+ /* If this is the first, we can try a parenthesized
+ declarator. */
+ if (first)
{
- tree cv_qualifiers;
- tree exception_specification;
-
- /* Consume the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
-
- /* Parse the cv-qualifier-seq. */
- cv_qualifiers = cp_parser_cv_qualifier_seq_opt (parser);
- /* And the exception-specification. */
- exception_specification
- = cp_parser_exception_specification_opt (parser);
-
- /* Create the function-declarator. */
- declarator = make_call_declarator (declarator,
- params,
- cv_qualifiers,
- exception_specification);
+ parser->default_arg_ok_p = saved_default_arg_ok_p;
+ parser->in_declarator_p = saved_in_declarator_p;
+
+ /* Consume the `('. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Parse the nested declarator. */
+ declarator
+ = cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p);
+ first = false;
+ /* Expect a `)'. */
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+ declarator = error_mark_node;
+ if (declarator == error_mark_node)
+ break;
+
+ goto handle_declarator;
}
- /* Otherwise, we must be done with the declarator. */
+ /* Otherwise, we must be done. */
+ else
+ break;
+ }
+ else if ((!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
+ && token->type == CPP_OPEN_SQUARE)
+ {
+ /* Parse an array-declarator. */
+ tree bounds;
+
+ first = false;
+ parser->default_arg_ok_p = false;
+ parser->in_declarator_p = true;
+ /* Consume the `['. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Peek at the next token. */
+ token = cp_lexer_peek_token (parser->lexer);
+ /* If the next token is `]', then there is no
+ constant-expression. */
+ if (token->type != CPP_CLOSE_SQUARE)
+ bounds = cp_parser_constant_expression (parser);
else
+ bounds = NULL_TREE;
+ /* Look for the closing `]'. */
+ if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"))
+ {
+ declarator = error_mark_node;
+ break;
+ }
+
+ declarator = build_nt (ARRAY_REF, declarator, bounds);
+ }
+ else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
+ {
+ /* Parse a declarator_id */
+ if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
+ cp_parser_parse_tentatively (parser);
+ declarator = cp_parser_declarator_id (parser);
+ if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
+ {
+ if (!cp_parser_parse_definitely (parser))
+ declarator = error_mark_node;
+ else if (TREE_CODE (declarator) != IDENTIFIER_NODE)
+ {
+ cp_parser_error (parser, "expected unqualified-id");
+ declarator = error_mark_node;
+ }
+ }
+
+ if (declarator == error_mark_node)
break;
+
+ if (TREE_CODE (declarator) == SCOPE_REF)
+ {
+ tree scope = TREE_OPERAND (declarator, 0);
+
+ /* In the declaration of a member of a template class
+ outside of the class itself, the SCOPE will sometimes
+ be a TYPENAME_TYPE. For example, given:
+
+ template <typename T>
+ int S<T>::R::i = 3;
+
+ the SCOPE will be a TYPENAME_TYPE for `S<T>::R'. In
+ this context, we must resolve S<T>::R to an ordinary
+ type, rather than a typename type.
+
+ The reason we normally avoid resolving TYPENAME_TYPEs
+ is that a specialization of `S' might render
+ `S<T>::R' not a type. However, if `S' is
+ specialized, then this `i' will not be used, so there
+ is no harm in resolving the types here. */
+ if (TREE_CODE (scope) == TYPENAME_TYPE)
+ {
+ /* Resolve the TYPENAME_TYPE. */
+ scope = cp_parser_resolve_typename_type (parser, scope);
+ /* If that failed, the declarator is invalid. */
+ if (scope == error_mark_node)
+ return error_mark_node;
+ /* Build a new DECLARATOR. */
+ declarator = build_nt (SCOPE_REF,
+ scope,
+ TREE_OPERAND (declarator, 1));
+ }
+ }
+
+ /* Check to see whether the declarator-id names a constructor,
+ destructor, or conversion. */
+ if (declarator && ctor_dtor_or_conv_p
+ && ((TREE_CODE (declarator) == SCOPE_REF
+ && CLASS_TYPE_P (TREE_OPERAND (declarator, 0)))
+ || (TREE_CODE (declarator) != SCOPE_REF
+ && at_class_scope_p ())))
+ {
+ tree unqualified_name;
+ tree class_type;
+
+ /* Get the unqualified part of the name. */
+ if (TREE_CODE (declarator) == SCOPE_REF)
+ {
+ class_type = TREE_OPERAND (declarator, 0);
+ unqualified_name = TREE_OPERAND (declarator, 1);
+ }
+ else
+ {
+ class_type = current_class_type;
+ unqualified_name = declarator;
+ }
+
+ /* See if it names ctor, dtor or conv. */
+ if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR
+ || IDENTIFIER_TYPENAME_P (unqualified_name)
+ || constructor_name_p (unqualified_name, class_type))
+ *ctor_dtor_or_conv_p = true;
+ }
+
+ handle_declarator:;
+ scope = get_scope_of_declarator (declarator);
+ if (scope)
+ /* Any names that appear after the declarator-id for a member
+ are looked up in the containing scope. */
+ push_scope (scope);
+ parser->in_declarator_p = true;
+ if ((ctor_dtor_or_conv_p && *ctor_dtor_or_conv_p)
+ || (declarator
+ && (TREE_CODE (declarator) == SCOPE_REF
+ || TREE_CODE (declarator) == IDENTIFIER_NODE)))
+ /* Default args are only allowed on function
+ declarations. */
+ parser->default_arg_ok_p = saved_default_arg_ok_p;
+ else
+ parser->default_arg_ok_p = false;
+
+ first = false;
}
- /* Otherwise, we're done with the declarator. */
+ /* We're done. */
else
break;
- /* Any subsequent parameter lists are to do with return type, so
- are not those of the declared function. */
- parser->default_arg_ok_p = false;
}
/* For an abstract declarator, we might wind up with nothing at this
cv-qualifiers. Returns ERROR_MARK if an error occurred. */
static enum tree_code
-cp_parser_ptr_operator (parser, type, cv_qualifier_seq)
- cp_parser *parser;
- tree *type;
- tree *cv_qualifier_seq;
+cp_parser_ptr_operator (cp_parser* parser,
+ tree* type,
+ tree* cv_qualifier_seq)
{
enum tree_code code = ERROR_MARK;
cp_token *token;
representation of a cv-qualifier. */
static tree
-cp_parser_cv_qualifier_seq_opt (parser)
- cp_parser *parser;
+cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
{
tree cv_qualifiers = NULL_TREE;
__restrict__ */
static tree
-cp_parser_cv_qualifier_opt (parser)
- cp_parser *parser;
+cp_parser_cv_qualifier_opt (cp_parser* parser)
{
cp_token *token;
tree cv_qualifier = NULL_TREE;
unqualified-id. */
static tree
-cp_parser_declarator_id (parser)
- cp_parser *parser;
+cp_parser_declarator_id (cp_parser* parser)
{
tree id_expression;
Returns the TYPE specified. */
static tree
-cp_parser_type_id (parser)
- cp_parser *parser;
+cp_parser_type_id (cp_parser* parser)
{
tree type_specifier_seq;
tree abstract_declarator;
cp_parser_parse_tentatively (parser);
/* Look for the declarator. */
abstract_declarator
- = cp_parser_declarator (parser, /*abstract_p=*/true, NULL);
+ = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL);
/* Check to see if there really was a declarator. */
if (!cp_parser_parse_definitely (parser))
abstract_declarator = NULL_TREE;
type-specifier, or the TREE_PURPOSE is a list of attributes. */
static tree
-cp_parser_type_specifier_seq (parser)
- cp_parser *parser;
+cp_parser_type_specifier_seq (cp_parser* parser)
{
bool seen_type_specifier = false;
tree type_specifier_seq = NULL_TREE;
parameter-declaration-clause consisting only of an ellipsis. */
static tree
-cp_parser_parameter_declaration_clause (parser)
- cp_parser *parser;
+cp_parser_parameter_declaration_clause (cp_parser* parser)
{
tree parameters;
cp_token *token;
}
else if (token->type == CPP_CLOSE_PAREN)
/* There are no parameters. */
- return void_list_node;
+ {
+#ifndef NO_IMPLICIT_EXTERN_C
+ if (in_system_header && current_class_type == NULL
+ && current_lang_name == lang_name_c)
+ return NULL_TREE;
+ else
+#endif
+ return void_list_node;
+ }
/* Check for `(void)', too, which is a special case. */
else if (token->keyword == RID_VOID
&& (cp_lexer_peek_nth_token (parser->lexer, 2)->type
`void_list_node' is never appended to the list. */
static tree
-cp_parser_parameter_declaration_list (parser)
- cp_parser *parser;
+cp_parser_parameter_declaration_list (cp_parser* parser)
{
tree parameters = NULL_TREE;
tree parameter;
/* Parse the parameter. */
parameter
- = cp_parser_parameter_declaration (parser,
- /*greater_than_is_operator_p=*/true);
+ = cp_parser_parameter_declaration (parser, /*template_parm_p=*/false);
+
/* If a parse error ocurred parsing the parameter declaration,
then the entire parameter-declaration-list is erroneous. */
if (parameter == error_mark_node)
decl-specifier-seq abstract-declarator [opt]
decl-specifier-seq abstract-declarator [opt] = assignment-expression
- If GREATER_THAN_IS_OPERATOR_P is FALSE, then a non-nested `>' token
- encountered during the parsing of the assignment-expression is not
- interpreted as a greater-than operator.
+ If TEMPLATE_PARM_P is TRUE, then this parameter-declaration
+ declares a template parameter. (In that case, a non-nested `>'
+ token encountered during the parsing of the assignment-expression
+ is not interpreted as a greater-than operator.)
Returns a TREE_LIST representing the parameter-declaration. The
TREE_VALUE is a representation of the decl-specifier-seq and
TREE_VALUE represents the declarator. */
static tree
-cp_parser_parameter_declaration (parser, greater_than_is_operator_p)
- cp_parser *parser;
- bool greater_than_is_operator_p;
+cp_parser_parameter_declaration (cp_parser *parser,
+ bool template_parm_p)
{
bool declares_class_or_enum;
+ bool greater_than_is_operator_p;
tree decl_specifiers;
tree attributes;
tree declarator;
cp_token *token;
const char *saved_message;
+ /* In a template parameter, `>' is not an operator.
+
+ [temp.param]
+
+ When parsing a default template-argument for a non-type
+ template-parameter, the first non-nested `>' is taken as the end
+ of the template parameter-list rather than a greater-than
+ operator. */
+ greater_than_is_operator_p = !template_parm_p;
+
/* Type definitions may not appear in parameter types. */
saved_message = parser->type_definition_forbidden_message;
parser->type_definition_forbidden_message
bool saved_default_arg_ok_p = parser->default_arg_ok_p;
parser->default_arg_ok_p = false;
- /* We don't know whether the declarator will be abstract or
- not. So, first we try an ordinary declarator. */
- cp_parser_parse_tentatively (parser);
declarator = cp_parser_declarator (parser,
- /*abstract_p=*/false,
+ CP_PARSER_DECLARATOR_EITHER,
/*ctor_dtor_or_conv_p=*/NULL);
- /* If that didn't work, look for an abstract declarator. */
- if (!cp_parser_parse_definitely (parser))
- declarator = cp_parser_declarator (parser,
- /*abstract_p=*/true,
- /*ctor_dtor_or_conv_p=*/NULL);
parser->default_arg_ok_p = saved_default_arg_ok_p;
+ /* After the declarator, allow more attributes. */
+ attributes = chainon (attributes, cp_parser_attributes_opt (parser));
}
- /* The restriction on definining new types applies only to the type
+ /* The restriction on defining new types applies only to the type
of the parameter, not to the default argument. */
parser->type_definition_forbidden_message = saved_message;
/* If we are defining a class, then the tokens that make up the
default argument must be saved and processed later. */
- if (at_class_scope_p () && TYPE_BEING_DEFINED (current_class_type))
+ if (!template_parm_p && at_class_scope_p ()
+ && TYPE_BEING_DEFINED (current_class_type))
{
unsigned depth = 0;
be a `friend'. */
static tree
-cp_parser_function_definition (parser, friend_p)
- cp_parser *parser;
- bool *friend_p;
+cp_parser_function_definition (cp_parser* parser, bool* friend_p)
{
tree decl_specifiers;
tree attributes;
tree declarator;
tree fn;
- tree access_checks;
cp_token *token;
bool declares_class_or_enum;
bool member_p;
function is being defined. There is no need to do this for the
definition of member functions; we cannot be defining a member
from another class. */
- if (!member_p)
- cp_parser_start_deferring_access_checks (parser);
+ push_deferring_access_checks (!member_p);
+
/* Parse the decl-specifier-seq. */
decl_specifiers
= cp_parser_decl_specifier_seq (parser,
*friend_p = cp_parser_friend_p (decl_specifiers);
/* Parse the declarator. */
- declarator = cp_parser_declarator (parser,
- /*abstract_p=*/false,
+ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
/*ctor_dtor_or_conv_p=*/NULL);
/* Gather up any access checks that occurred. */
- if (!member_p)
- access_checks = cp_parser_stop_deferring_access_checks (parser);
- else
- access_checks = NULL_TREE;
+ stop_deferring_access_checks ();
/* If something has already gone wrong, we may as well stop now. */
if (declarator == error_mark_node)
like a function-definition, to a `;' in the hopes of finding
a sensible place from which to continue parsing. */
cp_parser_skip_to_end_of_block_or_statement (parser);
+ pop_deferring_access_checks ();
return error_mark_node;
}
/* Skip to the next `;'. */
cp_parser_skip_to_end_of_block_or_statement (parser);
+ pop_deferring_access_checks ();
return error_mark_node;
}
if (cp_parser_token_starts_function_definition_p
(cp_lexer_peek_token (parser->lexer)))
cp_parser_skip_to_end_of_block_or_statement (parser);
+ pop_deferring_access_checks ();
return error_mark_node;
}
/* Add FN to the queue of functions to be parsed later. */
TREE_VALUE (parser->unparsed_functions_queues)
- = tree_cons (current_class_type, fn,
+ = tree_cons (NULL_TREE, fn,
TREE_VALUE (parser->unparsed_functions_queues));
+ pop_deferring_access_checks ();
return fn;
}
declarator))
{
cp_parser_skip_to_end_of_block_or_statement (parser);
+ pop_deferring_access_checks ();
return error_mark_node;
}
- return (cp_parser_function_definition_from_specifiers_and_declarator
- (parser, decl_specifiers, attributes, declarator, access_checks));
+ fn = cp_parser_function_definition_from_specifiers_and_declarator
+ (parser, decl_specifiers, attributes, declarator);
+ pop_deferring_access_checks ();
+ return fn;
}
/* Parse a function-body.
set to FALSE if there is no initializer present. */
static tree
-cp_parser_initializer (parser, is_parenthesized_init)
- cp_parser *parser;
- bool *is_parenthesized_init;
+cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init)
{
cp_token *token;
tree init;
trailing `,' was provided. */
static tree
-cp_parser_initializer_clause (parser)
- cp_parser *parser;
+cp_parser_initializer_clause (cp_parser* parser)
{
tree initializer;
IDENTIFIER_NODE naming the field to initialize. */
static tree
-cp_parser_initializer_list (parser)
- cp_parser *parser;
+cp_parser_initializer_list (cp_parser* parser)
{
tree initializers = NULL_TREE;
tree decl;
tree scope;
bool typename_p;
-
+ cp_token *token;
+
+ /* All class-names start with an identifier. */
+ token = cp_lexer_peek_token (parser->lexer);
+ if (token->type != CPP_NAME && token->type != CPP_TEMPLATE_ID)
+ {
+ cp_parser_error (parser, "expected class-name");
+ return error_mark_node;
+ }
+
/* PARSER->SCOPE can be cleared when parsing the template-arguments
to a template-id, so we save it here. */
scope = parser->scope;
/* Any name names a type if we're following the `typename' keyword
in a qualified name where the enclosing scope is type-dependent. */
typename_p = (typename_keyword_p && scope && TYPE_P (scope)
- && cp_parser_dependent_type_p (scope));
-
- /* We don't know whether what comes next is a template-id or
- not. */
- cp_parser_parse_tentatively (parser);
- /* Try a template-id. */
- decl = cp_parser_template_id (parser, template_keyword_p,
- check_dependency_p);
- if (cp_parser_parse_definitely (parser))
- {
- if (decl == error_mark_node)
- return error_mark_node;
- }
- else
+ && dependent_type_p (scope));
+ /* Handle the common case (an identifier, but not a template-id)
+ efficiently. */
+ if (token->type == CPP_NAME
+ && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_LESS)
{
- /* If it wasn't a template-id, try a simple identifier. */
tree identifier;
/* Look for the identifier. */
decl = cp_parser_lookup_name (parser, identifier,
check_access_p,
type_p,
+ /*is_namespace=*/false,
check_dependency_p);
}
}
+ else
+ {
+ /* Try a template-id. */
+ decl = cp_parser_template_id (parser, template_keyword_p,
+ check_dependency_p);
+ if (decl == error_mark_node)
+ return error_mark_node;
+ }
decl = cp_parser_maybe_treat_template_as_class (decl, class_head_p);
Returns the TREE_TYPE representing the class. */
static tree
-cp_parser_class_specifier (parser)
- cp_parser *parser;
+cp_parser_class_specifier (cp_parser* parser)
{
cp_token *token;
tree type;
tree attributes = NULL_TREE;
int has_trailing_semicolon;
bool nested_name_specifier_p;
- bool deferring_access_checks_p;
- tree saved_access_checks;
unsigned saved_num_template_parameter_lists;
+ push_deferring_access_checks (false);
+
/* Parse the class-head. */
type = cp_parser_class_head (parser,
- &nested_name_specifier_p,
- &deferring_access_checks_p,
- &saved_access_checks);
+ &nested_name_specifier_p);
/* If the class-head was a semantic disaster, skip the entire body
of the class. */
if (!type)
{
cp_parser_skip_to_end_of_block_or_statement (parser);
+ pop_deferring_access_checks ();
return error_mark_node;
}
+
/* Look for the `{'. */
if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
- return error_mark_node;
+ {
+ pop_deferring_access_checks ();
+ return error_mark_node;
+ }
+
/* Issue an error message if type-definitions are forbidden here. */
cp_parser_check_type_definition (parser);
/* Remember that we are defining one more class. */
if (--parser->num_classes_being_defined == 0)
{
tree last_scope = NULL_TREE;
+ tree queue_entry;
+ tree fn;
- /* Process non FUNCTION_DECL related DEFAULT_ARGs. */
- for (parser->default_arg_types = nreverse (parser->default_arg_types);
- parser->default_arg_types;
- parser->default_arg_types = TREE_CHAIN (parser->default_arg_types))
- cp_parser_late_parsing_default_args
- (parser, TREE_PURPOSE (parser->default_arg_types));
-
/* Reverse the queue, so that we process it in the order the
functions were declared. */
TREE_VALUE (parser->unparsed_functions_queues)
= nreverse (TREE_VALUE (parser->unparsed_functions_queues));
- /* Loop through all of the functions. */
+ /* In a first pass, parse default arguments to the functions.
+ Then, in a second pass, parse the bodies of the functions.
+ This two-phased approach handles cases like:
+
+ struct S {
+ void f() { g(); }
+ void g(int i = 3);
+ };
+
+ */
+ for (queue_entry = TREE_VALUE (parser->unparsed_functions_queues);
+ queue_entry;
+ queue_entry = TREE_CHAIN (queue_entry))
+ {
+ fn = TREE_VALUE (queue_entry);
+ if (DECL_FUNCTION_TEMPLATE_P (fn))
+ fn = DECL_TEMPLATE_RESULT (fn);
+ /* Make sure that any template parameters are in scope. */
+ maybe_begin_member_template_processing (fn);
+ /* If there are default arguments that have not yet been processed,
+ take care of them now. */
+ cp_parser_late_parsing_default_args (parser, fn);
+ /* Remove any template parameters from the symbol table. */
+ maybe_end_member_template_processing ();
+ }
+ /* Now parse the body of the functions. */
while (TREE_VALUE (parser->unparsed_functions_queues))
{
- tree fn;
- tree fn_scope;
- tree queue_entry;
-
/* Figure out which function we need to process. */
queue_entry = TREE_VALUE (parser->unparsed_functions_queues);
- fn_scope = TREE_PURPOSE (queue_entry);
fn = TREE_VALUE (queue_entry);
/* Parse the function. */
}
/* Put back any saved access checks. */
- if (deferring_access_checks_p)
- {
- cp_parser_start_deferring_access_checks (parser);
- parser->context->deferred_access_checks = saved_access_checks;
- }
+ pop_deferring_access_checks ();
/* Restore the count of active template-parameter-lists. */
parser->num_template_parameter_lists
Returns the TYPE of the indicated class. Sets
*NESTED_NAME_SPECIFIER_P to TRUE iff one of the productions
involving a nested-name-specifier was used, and FALSE otherwise.
- Sets *DEFERRING_ACCESS_CHECKS_P to TRUE iff we were deferring
- access checks before this class-head. In that case,
- *SAVED_ACCESS_CHECKS is set to the current list of deferred access
- checks.
Returns NULL_TREE if the class-head is syntactically valid, but
semantically invalid in a way that means we should skip the entire
body of the class. */
static tree
-cp_parser_class_head (parser,
- nested_name_specifier_p,
- deferring_access_checks_p,
- saved_access_checks)
- cp_parser *parser;
- bool *nested_name_specifier_p;
- bool *deferring_access_checks_p;
- tree *saved_access_checks;
+cp_parser_class_head (cp_parser* parser,
+ bool* nested_name_specifier_p)
{
cp_token *token;
tree nested_name_specifier;
Handle this gracefully by accepting the extra qualifier, and then
issuing an error about it later if this really is a
- class-header. If it turns out just to be an elaborated type
+ class-head. If it turns out just to be an elaborated type
specifier, remain silent. */
if (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false))
qualified_p = true;
if (TYPE_P (scope)
&& CLASS_TYPE_P (scope)
&& CLASSTYPE_TEMPLATE_INFO (scope)
- && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope)))
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope))
+ && !CLASSTYPE_TEMPLATE_SPECIALIZATION (scope))
++num_templates;
}
}
process the class-definition. */
return NULL_TREE;
- /* We do not need to defer access checks for entities declared
- within the class. But, we do need to save any access checks that
- are currently deferred and restore them later, in case we are in
- the middle of something else. */
- *deferring_access_checks_p = parser->context->deferring_access_checks_p;
- if (*deferring_access_checks_p)
- *saved_access_checks = cp_parser_stop_deferring_access_checks (parser);
-
/* Look up the type. */
if (template_id_p)
{
}
else
{
- int new_type_p;
+ bool new_type_p;
tree class_type;
/* Given:
nested_name_specifier,
type,
attributes,
- /*defn_p=*/1,
+ /*defn_p=*/true,
&new_type_p));
if (type != error_mark_node)
{
error. */
static enum tag_types
-cp_parser_class_key (parser)
- cp_parser *parser;
+cp_parser_class_key (cp_parser* parser)
{
cp_token *token;
enum tag_types tag_type;
access-specifier : member-specification [opt] */
static void
-cp_parser_member_specification_opt (parser)
- cp_parser *parser;
+cp_parser_member_specification_opt (cp_parser* parser)
{
while (true)
{
/* Otherwise, the next construction must be a
member-declaration. */
cp_parser_member_declaration (parser);
- reset_type_access_control ();
}
}
}
identifier [opt] attributes [opt] : constant-expression */
static void
-cp_parser_member_declaration (parser)
- cp_parser *parser;
+cp_parser_member_declaration (cp_parser* parser)
{
tree decl_specifiers;
tree prefix_attributes;
CP_PARSER_FLAGS_OPTIONAL,
&prefix_attributes,
&declares_class_or_enum);
+ /* Check for an invalid type-name. */
+ if (cp_parser_diagnose_invalid_type_name (parser))
+ return;
/* If there is no declarator, then the decl-specifier-seq should
specify a type. */
if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
/* Parse the declarator. */
declarator
- = cp_parser_declarator (parser,
- /*abstract_p=*/false,
+ = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
&ctor_dtor_or_conv_p);
/* If something went wrong parsing the declarator, make sure
there might be default arguments that need handling.) */
if (TREE_CODE (decl) == FUNCTION_DECL)
TREE_VALUE (parser->unparsed_functions_queues)
- = tree_cons (current_class_type, decl,
+ = tree_cons (NULL_TREE, decl,
TREE_VALUE (parser->unparsed_functions_queues));
}
}
Otherwiser, ERROR_MARK_NODE is returned. */
static tree
-cp_parser_pure_specifier (parser)
- cp_parser *parser;
+cp_parser_pure_specifier (cp_parser* parser)
{
cp_token *token;
Returns a representation of the constant-expression. */
static tree
-cp_parser_constant_initializer (parser)
- cp_parser *parser;
+cp_parser_constant_initializer (cp_parser* parser)
{
/* Look for the `=' token. */
if (!cp_parser_require (parser, CPP_EQ, "`='"))
NULL_TREE, not ERROR_MARK_NODE. */
static tree
-cp_parser_base_clause (parser)
- cp_parser *parser;
+cp_parser_base_clause (cp_parser* parser)
{
tree bases = NULL_TREE;
(or the ERROR_MARK_NODE) indicating the type that was specified. */
static tree
-cp_parser_base_specifier (parser)
- cp_parser *parser;
+cp_parser_base_specifier (cp_parser* parser)
{
cp_token *token;
bool done = false;
TREE_VALUE of each node is a type. */
static tree
-cp_parser_exception_specification_opt (parser)
- cp_parser *parser;
+cp_parser_exception_specification_opt (cp_parser* parser)
{
cp_token *token;
tree type_id_list;
in the order that the types were presented. */
static tree
-cp_parser_type_id_list (parser)
- cp_parser *parser;
+cp_parser_type_id_list (cp_parser* parser)
{
tree types = NULL_TREE;
try compound-statement handler-seq */
static tree
-cp_parser_try_block (parser)
- cp_parser *parser;
+cp_parser_try_block (cp_parser* parser)
{
tree try_block;
try ctor-initializer [opt] function-body handler-seq */
static bool
-cp_parser_function_try_block (parser)
- cp_parser *parser;
+cp_parser_function_try_block (cp_parser* parser)
{
tree try_block;
bool ctor_initializer_p;
handler handler-seq [opt] */
static void
-cp_parser_handler_seq (parser)
- cp_parser *parser;
+cp_parser_handler_seq (cp_parser* parser)
{
while (true)
{
catch ( exception-declaration ) compound-statement */
static void
-cp_parser_handler (parser)
- cp_parser *parser;
+cp_parser_handler (cp_parser* parser)
{
tree handler;
tree declaration;
ellipsis variant is used. */
static tree
-cp_parser_exception_declaration (parser)
- cp_parser *parser;
+cp_parser_exception_declaration (cp_parser* parser)
{
tree type_specifiers;
tree declarator;
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
declarator = NULL_TREE;
else
- {
- /* Otherwise, we can't be sure whether we are looking at a
- direct, or an abstract, declarator. */
- cp_parser_parse_tentatively (parser);
- /* Try an ordinary declarator. */
- declarator = cp_parser_declarator (parser,
- /*abstract_p=*/false,
- /*ctor_dtor_or_conv_p=*/NULL);
- /* If that didn't work, try an abstract declarator. */
- if (!cp_parser_parse_definitely (parser))
- declarator = cp_parser_declarator (parser,
- /*abstract_p=*/true,
- /*ctor_dtor_or_conv_p=*/NULL);
- }
+ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER,
+ /*ctor_dtor_or_conv_p=*/NULL);
/* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message;
Returns a THROW_EXPR representing the throw-expression. */
static tree
-cp_parser_throw_expression (parser)
- cp_parser *parser;
+cp_parser_throw_expression (cp_parser* parser)
{
tree expression;
NULL_TREE. */
static tree
-cp_parser_asm_specification_opt (parser)
- cp_parser *parser;
+cp_parser_asm_specification_opt (cp_parser* parser)
{
cp_token *token;
tree asm_specification;
is a STRING_CST for the string literal before the parenthesis. */
static tree
-cp_parser_asm_operand_list (parser)
- cp_parser *parser;
+cp_parser_asm_operand_list (cp_parser* parser)
{
tree asm_operands = NULL_TREE;
appeared. The TREE_VALUE of each node is a STRING_CST. */
static tree
-cp_parser_asm_clobber_list (parser)
- cp_parser *parser;
+cp_parser_asm_clobber_list (cp_parser* parser)
{
tree clobbers = NULL_TREE;
The return value is as for cp_parser_attribute_list. */
static tree
-cp_parser_attributes_opt (parser)
- cp_parser *parser;
+cp_parser_attributes_opt (cp_parser* parser)
{
tree attributes = NULL_TREE;
any. */
static tree
-cp_parser_attribute_list (parser)
- cp_parser *parser;
+cp_parser_attribute_list (cp_parser* parser)
{
tree attribute_list = NULL_TREE;
for restoring the value of the PEDANTIC flag. */
static bool
-cp_parser_extension_opt (parser, saved_pedantic)
- cp_parser *parser;
- int *saved_pedantic;
+cp_parser_extension_opt (cp_parser* parser, int* saved_pedantic)
{
/* Save the old value of the PEDANTIC flag. */
*saved_pedantic = pedantic;
identifier */
static void
-cp_parser_label_declaration (parser)
- cp_parser *parser;
+cp_parser_label_declaration (cp_parser* parser)
{
/* Look for the `__label__' keyword. */
cp_parser_require_keyword (parser, RID_LABEL, "`__label__'");
If IS_TYPE is TRUE, bindings that do not refer to types are
ignored.
+ If IS_NAMESPACE is TRUE, bindings that do not refer to namespaces
+ are ignored.
+
If CHECK_DEPENDENCY is TRUE, names are not looked up in dependent
types. */
static tree
-cp_parser_lookup_name (parser, name, check_access, is_type,
- check_dependency)
- cp_parser *parser;
- tree name;
- bool check_access;
- bool is_type;
- bool check_dependency;
+cp_parser_lookup_name (cp_parser *parser, tree name, bool check_access,
+ bool is_type, bool is_namespace, bool check_dependency)
{
tree decl;
tree object_type = parser->context->object_type;
/* Perform the lookup. */
if (parser->scope)
{
- bool dependent_type_p;
+ bool dependent_p;
if (parser->scope == error_mark_node)
return error_mark_node;
looking up names in uninstantiated templates. Even then, we
cannot look up the name if the scope is not a class type; it
might, for example, be a template type parameter. */
- dependent_type_p = (TYPE_P (parser->scope)
- && !(parser->in_declarator_p
- && currently_open_class (parser->scope))
- && cp_parser_dependent_type_p (parser->scope));
+ dependent_p = (TYPE_P (parser->scope)
+ && !(parser->in_declarator_p
+ && currently_open_class (parser->scope))
+ && dependent_type_p (parser->scope));
if ((check_dependency || !CLASS_TYPE_P (parser->scope))
- && dependent_type_p)
+ && dependent_p)
{
if (!is_type)
decl = build_nt (SCOPE_REF, parser->scope, name);
otherwise, we would have processed this lookup above. So
that PARSER->SCOPE is not considered a dependent base by
lookup_member, we must enter the scope here. */
- if (dependent_type_p)
+ if (dependent_p)
push_scope (parser->scope);
/* If the PARSER->SCOPE is a a template specialization, it
may be instantiated during name lookup. In that case,
tentative parse, those errors are valid. */
decl = lookup_qualified_name (parser->scope, name, is_type,
/*flags=*/0);
- if (dependent_type_p)
+ if (dependent_p)
pop_scope (parser->scope);
}
parser->qualifying_scope = parser->scope;
/*protect=*/0, is_type);
/* Look it up in the enclosing context, too. */
decl = lookup_name_real (name, is_type, /*nonclass=*/0,
- /*namespaces_only=*/0,
+ is_namespace,
/*flags=*/0);
parser->object_scope = object_type;
parser->qualifying_scope = NULL_TREE;
else
{
decl = lookup_name_real (name, is_type, /*nonclass=*/0,
- /*namespaces_only=*/0,
+ is_namespace,
/*flags=*/0);
parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE;
{
/* The error message we have to print is too complicated for
cp_parser_error, so we incorporate its actions directly. */
- cp_parser_simulate_error (parser);
- if (!cp_parser_parsing_tentatively (parser)
- || cp_parser_committed_to_tentative_parse (parser))
+ if (!cp_parser_simulate_error (parser))
{
error ("reference to `%D' is ambiguous", name);
print_candidates (decl);
object_type,
parser->scope);
if (qualifying_type)
- {
- /* If we are supposed to defer access checks, just record
- the information for later. */
- if (parser->context->deferring_access_checks_p)
- cp_parser_defer_access_check (parser, qualifying_type, decl);
- /* Otherwise, check accessibility now. */
- else
- enforce_access (qualifying_type, decl);
- }
+ perform_or_defer_access_check (qualifying_type, decl);
}
return decl;
TRUE. */
static tree
-cp_parser_lookup_name_simple (parser, name)
- cp_parser *parser;
- tree name;
+cp_parser_lookup_name_simple (cp_parser* parser, tree name)
{
return cp_parser_lookup_name (parser, name,
/*check_access=*/true,
- /*is_type=*/false,
+ /*is_type=*/false,
+ /*is_namespace=*/false,
/*check_dependency=*/true);
}
extremely limited situations. */
static tree
-cp_parser_resolve_typename_type (parser, type)
- cp_parser *parser;
- tree type;
+cp_parser_resolve_typename_type (cp_parser* parser, tree type)
{
tree scope;
tree name;
20010702);
scope = TYPE_CONTEXT (type);
- name = DECL_NAME (TYPE_NAME (type));
+ name = TYPE_IDENTIFIER (type);
/* If the SCOPE is itself a TYPENAME_TYPE, then we need to resolve
it first before we can figure out what NAME refers to. */
scope = cp_parser_resolve_typename_type (parser, scope);
/* If we don't know what SCOPE refers to, then we cannot resolve the
TYPENAME_TYPE. */
- if (scope == error_mark_node)
+ if (scope == error_mark_node || TREE_CODE (scope) == TYPENAME_TYPE)
return error_mark_node;
/* If the SCOPE is a template type parameter, we have no way of
resolving the name. */
and FALSE otherwise. */
static bool
-cp_parser_check_declarator_template_parameters (parser, declarator)
- cp_parser *parser;
- tree declarator;
+cp_parser_check_declarator_template_parameters (cp_parser* parser,
+ tree declarator)
{
unsigned num_templates;
return TRUE. */
static bool
-cp_parser_check_template_parameters (parser, num_templates)
- cp_parser *parser;
- unsigned num_templates;
+cp_parser_check_template_parameters (cp_parser* parser,
+ unsigned num_templates)
{
/* If there are more template classes than parameter lists, we have
something like:
the two sub-expressions. */
static tree
-cp_parser_binary_expression (parser, token_tree_map, fn)
- cp_parser *parser;
- cp_parser_token_tree_map token_tree_map;
- cp_parser_expression_fn fn;
+cp_parser_binary_expression (cp_parser* parser,
+ const cp_parser_token_tree_map token_tree_map,
+ cp_parser_expression_fn fn)
{
tree lhs;
while (true)
{
cp_token *token;
- cp_parser_token_tree_map_node *map_node;
+ const cp_parser_token_tree_map_node *map_node;
tree rhs;
/* Peek at the next token. */
present, and NULL_TREE otherwise. */
static tree
-cp_parser_global_scope_opt (parser, current_scope_valid_p)
- cp_parser *parser;
- bool current_scope_valid_p;
+cp_parser_global_scope_opt (cp_parser* parser, bool current_scope_valid_p)
{
cp_token *token;
bool constructor_p;
tree type_decl = NULL_TREE;
bool nested_name_p;
+ cp_token *next_token;
+
+ /* The common case is that this is not a constructor declarator, so
+ try to avoid doing lots of work if at all possible. It's not
+ valid declare a constructor at function scope. */
+ if (at_function_scope_p ())
+ return false;
+ /* And only certain tokens can begin a constructor declarator. */
+ next_token = cp_lexer_peek_token (parser->lexer);
+ if (next_token->type != CPP_NAME
+ && next_token->type != CPP_SCOPE
+ && next_token->type != CPP_NESTED_NAME_SPECIFIER
+ && next_token->type != CPP_TEMPLATE_ID)
+ return false;
/* Parse tentatively; we are going to roll back all of the tokens
consumed here. */
{
/* If we have:
- template <typename T> struct S { S(); }
+ template <typename T> struct S { S(); };
template <typename T> S<T>::S ();
we must recognize that the nested `S' names a class.
&& cp_lexer_next_token_is_not (parser->lexer, CPP_ELLIPSIS)
&& !cp_parser_storage_class_specifier_opt (parser))
{
- if (current_class_type
- && !same_type_p (current_class_type, TREE_TYPE (type_decl)))
- /* The constructor for one class cannot be declared inside
- another. */
- constructor_p = false;
+ tree type;
+
+ /* Names appearing in the type-specifier should be looked up
+ in the scope of the class. */
+ if (current_class_type)
+ type = NULL_TREE;
else
{
- tree type;
-
- /* Names appearing in the type-specifier should be looked up
- in the scope of the class. */
- if (current_class_type)
- type = NULL_TREE;
- else
- {
- type = TREE_TYPE (type_decl);
- if (TREE_CODE (type) == TYPENAME_TYPE)
- type = cp_parser_resolve_typename_type (parser, type);
- push_scope (type);
- }
- /* Look for the type-specifier. */
- cp_parser_type_specifier (parser,
- CP_PARSER_FLAGS_NONE,
- /*is_friend=*/false,
- /*is_declarator=*/true,
- /*declares_class_or_enum=*/NULL,
- /*is_cv_qualifier=*/NULL);
- /* Leave the scope of the class. */
- if (type)
- pop_scope (type);
-
- constructor_p = !cp_parser_error_occurred (parser);
+ type = TREE_TYPE (type_decl);
+ if (TREE_CODE (type) == TYPENAME_TYPE)
+ type = cp_parser_resolve_typename_type (parser, type);
+ push_scope (type);
}
+ /* Look for the type-specifier. */
+ cp_parser_type_specifier (parser,
+ CP_PARSER_FLAGS_NONE,
+ /*is_friend=*/false,
+ /*is_declarator=*/true,
+ /*declares_class_or_enum=*/NULL,
+ /*is_cv_qualifier=*/NULL);
+ /* Leave the scope of the class. */
+ if (type)
+ pop_scope (type);
+
+ constructor_p = !cp_parser_error_occurred (parser);
}
}
else
}
/* Parse the definition of the function given by the DECL_SPECIFIERS,
- ATTRIBUTES, and DECLARATOR. The ACCESS_CHECKS have been deferred;
+ ATTRIBUTES, and DECLARATOR. The access checks have been deferred;
they must be performed once we are in the scope of the function.
Returns the function defined. */
static tree
cp_parser_function_definition_from_specifiers_and_declarator
- (parser, decl_specifiers, attributes, declarator, access_checks)
- cp_parser *parser;
- tree decl_specifiers;
- tree attributes;
- tree declarator;
- tree access_checks;
+ (cp_parser* parser,
+ tree decl_specifiers,
+ tree attributes,
+ tree declarator)
{
tree fn;
bool success_p;
did not check, check them now. We must wait until we are in the
scope of the function to perform the checks, since the function
might be a friend. */
- cp_parser_perform_deferred_access_checks (access_checks);
+ perform_deferred_access_checks ();
if (!success_p)
{
Returns the function defined. */
static tree
-cp_parser_function_definition_after_declarator (parser,
- inline_p)
- cp_parser *parser;
- bool inline_p;
+cp_parser_function_definition_after_declarator (cp_parser* parser,
+ bool inline_p)
{
tree fn;
bool ctor_initializer_p = false;
is as for cp_parser_template_declaration. */
static void
-cp_parser_template_declaration_after_export (parser, member_p)
- cp_parser *parser;
- bool member_p;
+cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
{
tree decl = NULL_TREE;
tree parameter_list;
&& (TREE_CODE (decl) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (decl)))
TREE_VALUE (parser->unparsed_functions_queues)
- = tree_cons (current_class_type, decl,
+ = tree_cons (NULL_TREE, decl,
TREE_VALUE (parser->unparsed_functions_queues));
}
*FRIEND_P is set to TRUE iff the declaration is a friend. */
static tree
-cp_parser_single_declaration (parser,
- member_p,
- friend_p)
- cp_parser *parser;
- bool member_p;
- bool *friend_p;
+cp_parser_single_declaration (cp_parser* parser,
+ bool member_p,
+ bool* friend_p)
{
bool declares_class_or_enum;
tree decl = NULL_TREE;
tree decl_specifiers;
tree attributes;
- tree access_checks;
/* Parse the dependent declaration. We don't know yet
whether it will be a function-definition. */
cp_parser_parse_tentatively (parser);
/* Defer access checks until we know what is being declared. */
- cp_parser_start_deferring_access_checks (parser);
+ push_deferring_access_checks (true);
+
/* Try the `decl-specifier-seq [opt] init-declarator [opt]'
alternative. */
decl_specifiers
&declares_class_or_enum);
/* Gather up the access checks that occurred the
decl-specifier-seq. */
- access_checks = cp_parser_stop_deferring_access_checks (parser);
+ stop_deferring_access_checks ();
+
/* Check for the declaration of a template class. */
if (declares_class_or_enum)
{
decl = cp_parser_init_declarator (parser,
decl_specifiers,
attributes,
- access_checks,
/*function_definition_allowed_p=*/false,
member_p,
/*function_definition_p=*/NULL);
+
+ pop_deferring_access_checks ();
+
/* Clear any current qualification; whatever comes next is the start
of something new. */
parser->scope = NULL_TREE;
representing the cast. */
static tree
-cp_parser_functional_cast (parser, type)
- cp_parser *parser;
- tree type;
+cp_parser_functional_cast (cp_parser* parser, tree type)
{
tree expression_list;
parse them now. */
static void
-cp_parser_late_parsing_for_member (parser, member_function)
- cp_parser *parser;
- tree member_function;
+cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
{
cp_lexer *saved_lexer;
/* Make sure that any template parameters are in scope. */
maybe_begin_member_template_processing (member_function);
- /* If there are default arguments that have not yet been processed,
- take care of them now. */
- if (DECL_FUNCTION_MEMBER_P (member_function))
- push_nested_class (DECL_CONTEXT (member_function), 1);
- cp_parser_late_parsing_default_args (parser, TREE_TYPE (member_function));
- if (DECL_FUNCTION_MEMBER_P (member_function))
- pop_nested_class ();
-
/* If the body of the function has not yet been parsed, parse it
now. */
if (DECL_PENDING_INLINE_P (member_function))
/* Set the current source position to be the location of the first
token in the saved inline body. */
- cp_lexer_set_source_position_from_token
- (parser->lexer,
- cp_lexer_peek_token (parser->lexer));
+ cp_lexer_peek_token (parser->lexer);
/* Let the front end know that we going to be defining this
function. */
= TREE_CHAIN (parser->unparsed_functions_queues);
}
-/* TYPE is a FUNCTION_TYPE or METHOD_TYPE which contains a parameter
- with an unparsed DEFAULT_ARG. Parse those default args now. */
+/* FN is a FUNCTION_DECL which may contains a parameter with an
+ unparsed DEFAULT_ARG. Parse the default args now. */
static void
-cp_parser_late_parsing_default_args (parser, type)
- cp_parser *parser;
- tree type;
+cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
{
cp_lexer *saved_lexer;
cp_token_cache *tokens;
bool saved_local_variables_forbidden_p;
tree parameters;
-
- for (parameters = TYPE_ARG_TYPES (type);
+
+ for (parameters = TYPE_ARG_TYPES (TREE_TYPE (fn));
parameters;
parameters = TREE_CHAIN (parameters))
{
/* Set the current source position to be the location of the
first token in the default argument. */
- cp_lexer_set_source_position_from_token
- (parser->lexer, cp_lexer_peek_token (parser->lexer));
+ cp_lexer_peek_token (parser->lexer);
/* Local variable names (and the `this' keyword) may not appear
in a default argument. */
saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
parser->local_variables_forbidden_p = true;
/* Parse the assignment-expression. */
+ if (DECL_CONTEXT (fn))
+ push_nested_class (DECL_CONTEXT (fn), 1);
TREE_PURPOSE (parameters) = cp_parser_assignment_expression (parser);
+ if (DECL_CONTEXT (fn))
+ pop_nested_class ();
/* Restore saved state. */
parser->lexer = saved_lexer;
encountered. */
static tree
-cp_parser_sizeof_operand (parser, keyword)
- cp_parser *parser;
- enum rid keyword;
+cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
{
static const char *format;
tree expr = NULL_TREE;
saved_constant_expression_p = parser->constant_expression_p;
parser->constant_expression_p = false;
+ /* Do not actually evaluate the expression. */
+ ++skip_evaluation;
/* If it's a `(', then we might be looking at the type-id
construction. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
looking at the unary-expression production. */
if (!expr)
expr = cp_parser_unary_expression (parser, /*address_p=*/false);
+ /* Go back to evaluating expressions. */
+ --skip_evaluation;
/* Free the message we created. */
free ((char *) parser->type_definition_forbidden_message);
Returns TRUE iff `friend' appears among the DECL_SPECIFIERS. */
static bool
-cp_parser_friend_p (decl_specifiers)
- tree decl_specifiers;
+cp_parser_friend_p (tree decl_specifiers)
{
while (decl_specifiers)
{
Otherwise, returns NULL. */
static cp_token *
-cp_parser_require (parser, type, token_desc)
- cp_parser *parser;
- enum cpp_ttype type;
- const char *token_desc;
+cp_parser_require (cp_parser* parser,
+ enum cpp_ttype type,
+ const char* token_desc)
{
if (cp_lexer_next_token_is (parser->lexer, type))
return cp_lexer_consume_token (parser->lexer);
else
{
- dyn_string_t error_msg;
-
- /* Format the error message. */
- error_msg = dyn_string_new (0);
- dyn_string_append_cstr (error_msg, "expected ");
- dyn_string_append_cstr (error_msg, token_desc);
- cp_parser_error (parser, error_msg->s);
- dyn_string_delete (error_msg);
+ /* Output the MESSAGE -- unless we're parsing tentatively. */
+ if (!cp_parser_simulate_error (parser))
+ error ("expected %s", token_desc);
return NULL;
}
}
the next token is not as expected. */
static void
-cp_parser_skip_until_found (parser, type, token_desc)
- cp_parser *parser;
- enum cpp_ttype type;
- const char *token_desc;
+cp_parser_skip_until_found (cp_parser* parser,
+ enum cpp_ttype type,
+ const char* token_desc)
{
cp_token *token;
unsigned nesting_depth = 0;
Otherwise, returns NULL. */
static cp_token *
-cp_parser_require_keyword (parser, keyword, token_desc)
- cp_parser *parser;
- enum rid keyword;
- const char *token_desc;
+cp_parser_require_keyword (cp_parser* parser,
+ enum rid keyword,
+ const char* token_desc)
{
cp_token *token = cp_parser_require (parser, CPP_KEYWORD, token_desc);
function-definition. */
static bool
-cp_parser_token_starts_function_definition_p (token)
- cp_token *token;
+cp_parser_token_starts_function_definition_p (cp_token* token)
{
return (/* An ordinary function-body begins with an `{'. */
token->type == CPP_OPEN_BRACE
or none_type otherwise. */
static enum tag_types
-cp_parser_token_is_class_key (token)
- cp_token *token;
+cp_parser_token_is_class_key (cp_token* token)
{
switch (token->keyword)
{
return false;
}
+/* The next token is a CPP_NESTED_NAME_SPECIFIER. Consume the token,
+ set PARSER->SCOPE, and perform other related actions. */
+
+static void
+cp_parser_pre_parsed_nested_name_specifier (cp_parser *parser)
+{
+ tree value;
+ tree check;
+
+ /* Get the stored value. */
+ value = cp_lexer_consume_token (parser->lexer)->value;
+ /* Perform any access checks that were deferred. */
+ for (check = TREE_PURPOSE (value); check; check = TREE_CHAIN (check))
+ perform_or_defer_access_check (TREE_PURPOSE (check), TREE_VALUE (check));
+ /* Set the scope from the stored value. */
+ parser->scope = TREE_VALUE (value);
+ parser->qualifying_scope = TREE_TYPE (value);
+ parser->object_scope = NULL_TREE;
+}
+
/* Add tokens to CACHE until an non-nested END token appears. */
static void
tokens. */
static void
-cp_parser_parse_tentatively (parser)
- cp_parser *parser;
+cp_parser_parse_tentatively (cp_parser* parser)
{
/* Enter a new parsing context. */
parser->context = cp_parser_context_new (parser->context);
/* In order to avoid repetitive access control error messages,
access checks are queued up until we are no longer parsing
tentatively. */
- cp_parser_start_deferring_access_checks (parser);
+ push_deferring_access_checks (true);
}
/* Commit to the currently active tentative parse. */
static void
-cp_parser_commit_to_tentative_parse (parser)
- cp_parser *parser;
+cp_parser_commit_to_tentative_parse (cp_parser* parser)
{
cp_parser_context *context;
cp_lexer *lexer;
will be rolled back, and no diagnostics will be issued. */
static void
-cp_parser_abort_tentative_parse (parser)
- cp_parser *parser;
+cp_parser_abort_tentative_parse (cp_parser* parser)
{
cp_parser_simulate_error (parser);
/* Now, pretend that we want to see if the construct was
Returns true if no error occurred; false otherwise. */
static bool
-cp_parser_parse_definitely (parser)
- cp_parser *parser;
+cp_parser_parse_definitely (cp_parser* parser)
{
bool error_occurred;
cp_parser_context *context;
already done. */
if (context->status != CP_PARSER_STATUS_KIND_COMMITTED)
cp_lexer_commit_tokens (parser->lexer);
- if (!parser->context->deferring_access_checks_p)
- /* If in the parent context we are not deferring checks, then
- these perform these checks now. */
- (cp_parser_perform_deferred_access_checks
- (context->deferred_access_checks));
- else
- /* Any lookups that were deferred during the tentative parse are
- still deferred. */
- parser->context->deferred_access_checks
- = chainon (parser->context->deferred_access_checks,
- context->deferred_access_checks);
- return true;
+
+ pop_to_parent_deferring_access_checks ();
}
/* Otherwise, if errors occurred, roll back our state so that things
are just as they were before we began the tentative parse. */
else
{
cp_lexer_rollback_tokens (parser->lexer);
- return false;
+ pop_deferring_access_checks ();
}
-}
-
-/* Returns non-zero if we are parsing tentatively. */
+ /* Add the context to the front of the free list. */
+ context->next = cp_parser_context_free_list;
+ cp_parser_context_free_list = context;
-static bool
-cp_parser_parsing_tentatively (parser)
- cp_parser *parser;
-{
- return parser->context->next != NULL;
+ return !error_occurred;
}
/* Returns true if we are parsing tentatively -- but have decided that
we will stick with this tentative parse, even if errors occur. */
static bool
-cp_parser_committed_to_tentative_parse (parser)
- cp_parser *parser;
+cp_parser_committed_to_tentative_parse (cp_parser* parser)
{
return (cp_parser_parsing_tentatively (parser)
&& parser->context->status == CP_PARSER_STATUS_KIND_COMMITTED);
tentative parse. */
static bool
-cp_parser_error_occurred (parser)
- cp_parser *parser;
+cp_parser_error_occurred (cp_parser* parser)
{
return (cp_parser_parsing_tentatively (parser)
&& parser->context->status == CP_PARSER_STATUS_KIND_ERROR);
/* Returns non-zero if GNU extensions are allowed. */
static bool
-cp_parser_allow_gnu_extensions_p (parser)
- cp_parser *parser;
+cp_parser_allow_gnu_extensions_p (cp_parser* parser)
{
return parser->allow_gnu_extensions_p;
}
/* Parse the entire translation unit. */
int
-yyparse ()
+yyparse (void)
{
bool error_occurred;
the_parser = cp_parser_new ();
+ push_deferring_access_checks (false);
error_occurred = cp_parser_translation_unit (the_parser);
the_parser = NULL;
+
+ finish_file ();
return error_occurred;
}
/* Clean up after parsing the entire translation unit. */
void
-free_parser_stacks ()
+free_parser_stacks (void)
{
/* Nothing to do. */
}