X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=gcc%2Fcp%2Fparser.c;h=e543e870550c4bdde4b0071d3b6bc6eb51308a51;hb=8fbf5688fb7314c59ccd2774fd16f8d91ef56dd4;hp=e63d9765c58d1bbbe0e764aa09f583d7a5a3a5b1;hpb=d853ee42d2bd96a3d589e349c57a2e71e4ace38f;p=gcc.git diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index e63d9765c58..e543e870550 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1,6 +1,6 @@ /* C++ Parser. Copyright (C) 2000, 2001, 2002, 2003, 2004, - 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Mark Mitchell . This file is part of GCC. @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" +#include "timevar.h" #include "cpplib.h" #include "tree.h" #include "cp-tree.h" @@ -37,6 +38,8 @@ along with GCC; see the file COPYING3. If not see #include "c-family/c-common.h" #include "c-family/c-objc.h" #include "plugin.h" +#include "tree-pretty-print.h" +#include "parser.h" /* The lexer. */ @@ -44,110 +47,11 @@ along with GCC; see the file COPYING3. If not see /* The cp_lexer_* routines mediate between the lexer proper (in libcpp and c-lex.c) and the C++ parser. */ -/* A token's value and its associated deferred access checks and - qualifying scope. */ - -struct GTY(()) tree_check { - /* The value associated with the token. */ - tree value; - /* The checks that have been associated with value. */ - VEC (deferred_access_check, gc)* checks; - /* The token's qualifying scope (used when it is a - CPP_NESTED_NAME_SPECIFIER). */ - tree qualifying_scope; -}; - -/* A C++ token. */ - -typedef struct GTY (()) cp_token { - /* The kind of token. */ - ENUM_BITFIELD (cpp_ttype) type : 8; - /* If this token is a keyword, this value indicates which keyword. - Otherwise, this value is RID_MAX. */ - ENUM_BITFIELD (rid) keyword : 8; - /* Token flags. */ - unsigned char flags; - /* Identifier for the pragma. */ - ENUM_BITFIELD (pragma_kind) pragma_kind : 6; - /* True if this token is from a context where it is implicitly extern "C" */ - BOOL_BITFIELD implicit_extern_c : 1; - /* True for a CPP_NAME token that is not a keyword (i.e., for which - KEYWORD is RID_MAX) iff this name was looked up and found to be - ambiguous. An error has already been reported. */ - BOOL_BITFIELD ambiguous_p : 1; - /* The location at which this token was found. */ - location_t location; - /* The value associated with this token, if any. */ - union cp_token_value { - /* Used for CPP_NESTED_NAME_SPECIFIER and CPP_TEMPLATE_ID. */ - struct tree_check* GTY((tag ("1"))) tree_check_value; - /* Use for all other tokens. */ - tree GTY((tag ("0"))) value; - } GTY((desc ("(%1.type == CPP_TEMPLATE_ID) || (%1.type == CPP_NESTED_NAME_SPECIFIER)"))) u; -} cp_token; - -/* We use a stack of token pointer for saving token sets. */ -typedef struct cp_token *cp_token_position; -DEF_VEC_P (cp_token_position); -DEF_VEC_ALLOC_P (cp_token_position,heap); - static cp_token eof_token = { - CPP_EOF, RID_MAX, 0, PRAGMA_NONE, false, 0, 0, { NULL } + CPP_EOF, RID_MAX, 0, PRAGMA_NONE, false, false, false, 0, { NULL } }; -/* The cp_lexer structure represents the C++ lexer. It is responsible - for managing the token stream from the preprocessor and supplying - it to the parser. Tokens are never added to the cp_lexer after - it is created. */ - -typedef struct GTY (()) cp_lexer { - /* The memory allocated for the buffer. NULL if this lexer does not - own the token buffer. */ - cp_token * GTY ((length ("%h.buffer_length"))) buffer; - /* If the lexer owns the buffer, this is the number of tokens in the - buffer. */ - size_t buffer_length; - - /* A pointer just past the last available token. The tokens - in this lexer are [buffer, last_token). */ - cp_token_position GTY ((skip)) last_token; - - /* The next available token. If NEXT_TOKEN is &eof_token, then there are - no more available tokens. */ - cp_token_position GTY ((skip)) next_token; - - /* A stack indicating positions at which cp_lexer_save_tokens was - called. The top entry is the most recent position at which we - began saving tokens. If the stack is non-empty, we are saving - tokens. */ - VEC(cp_token_position,heap) *GTY ((skip)) saved_tokens; - - /* The next lexer in a linked list of lexers. */ - struct cp_lexer *next; - - /* True if we should output debugging information. */ - bool debugging_p; - - /* True if we're in the context of parsing a pragma, and should not - increment past the end-of-line marker. */ - bool in_pragma; -} cp_lexer; - -/* cp_token_cache is a range of tokens. There is no need to represent - allocate heap memory for it, since tokens are never removed from the - lexer's array. There is also no need for the GC to walk through - a cp_token_cache, since everything in here is referenced through - a lexer. */ - -typedef struct GTY(()) cp_token_cache { - /* The beginning of the token range. */ - cp_token * GTY((skip)) first; - - /* Points immediately after the last token in the range. */ - cp_token * GTY ((skip)) last; -} cp_token_cache; - /* The various kinds of non integral constant we encounter. */ typedef enum non_integral_constant { NIC_NONE, @@ -280,8 +184,6 @@ static void cp_lexer_destroy (cp_lexer *); static int cp_lexer_saving_tokens (const cp_lexer *); -static cp_token_position cp_lexer_token_position - (cp_lexer *, bool); static cp_token *cp_lexer_token_at (cp_lexer *, cp_token_position); static void cp_lexer_get_preprocessor_token @@ -308,7 +210,6 @@ static void cp_lexer_commit_tokens (cp_lexer *); static void cp_lexer_rollback_tokens (cp_lexer *); -#ifdef ENABLE_CHECKING static void cp_lexer_print_token (FILE *, cp_token *); static inline bool cp_lexer_debugging_p @@ -317,15 +218,6 @@ static void cp_lexer_start_debugging (cp_lexer *) ATTRIBUTE_UNUSED; static void cp_lexer_stop_debugging (cp_lexer *) ATTRIBUTE_UNUSED; -#else -/* If we define cp_lexer_debug_stream to NULL it will provoke warnings - about passing NULL to functions that require non-NULL arguments - (fputs, fprintf). It will never be used, so all we need is a value - of the right type that's guaranteed not to be NULL. */ -#define cp_lexer_debug_stream stdout -#define cp_lexer_print_token(str, tok) (void) 0 -#define cp_lexer_debugging_p(lexer) 0 -#endif /* ENABLE_CHECKING */ static cp_token_cache *cp_token_cache_new (cp_token *, cp_token *); @@ -333,107 +225,389 @@ static cp_token_cache *cp_token_cache_new static void cp_parser_initial_pragma (cp_token *); +static tree cp_literal_operator_id + (const char *); + /* Manifest constants. */ #define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token)) #define CP_SAVED_TOKEN_STACK 5 -/* A token type for keywords, as opposed to ordinary identifiers. */ -#define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1)) - -/* A token type for template-ids. If a template-id is processed while - parsing tentatively, it is replaced with a CPP_TEMPLATE_ID token; - the value of the CPP_TEMPLATE_ID is whatever was returned by - cp_parser_template_id. */ -#define CPP_TEMPLATE_ID ((enum cpp_ttype) (CPP_KEYWORD + 1)) - -/* A token type for nested-name-specifiers. If a - nested-name-specifier is processed while parsing tentatively, it is - replaced with a CPP_NESTED_NAME_SPECIFIER token; the value of the - CPP_NESTED_NAME_SPECIFIER is whatever was returned by - cp_parser_nested_name_specifier_opt. */ -#define CPP_NESTED_NAME_SPECIFIER ((enum cpp_ttype) (CPP_TEMPLATE_ID + 1)) - -/* A token type for tokens that are not tokens at all; these are used - to represent slots in the array where there used to be a token - that has now been deleted. */ -#define CPP_PURGED ((enum cpp_ttype) (CPP_NESTED_NAME_SPECIFIER + 1)) - -/* The number of token types, including C++-specific ones. */ -#define N_CP_TTYPES ((int) (CPP_PURGED + 1)) - /* Variables. */ -#ifdef ENABLE_CHECKING /* The stream to which debugging output should be written. */ static FILE *cp_lexer_debug_stream; -#endif /* ENABLE_CHECKING */ /* Nonzero if we are parsing an unevaluated operand: an operand to sizeof, typeof, or alignof. */ int cp_unevaluated_operand; -/* Create a new main C++ lexer, the lexer that gets tokens from the - preprocessor. */ +/* Dump up to NUM tokens in BUFFER to FILE starting with token + START_TOKEN. If START_TOKEN is NULL, the dump starts with the + first token in BUFFER. If NUM is 0, dump all the tokens. If + CURR_TOKEN is set and it is one of the tokens in BUFFER, it will be + highlighted by surrounding it in [[ ]]. */ + +static void +cp_lexer_dump_tokens (FILE *file, VEC(cp_token,gc) *buffer, + cp_token *start_token, unsigned num, + cp_token *curr_token) +{ + unsigned i, nprinted; + cp_token *token; + bool do_print; + + fprintf (file, "%u tokens\n", VEC_length (cp_token, buffer)); + + if (buffer == NULL) + return; + + if (num == 0) + num = VEC_length (cp_token, buffer); + + if (start_token == NULL) + start_token = VEC_address (cp_token, buffer); + + if (start_token > VEC_address (cp_token, buffer)) + { + cp_lexer_print_token (file, VEC_index (cp_token, buffer, 0)); + fprintf (file, " ... "); + } + + do_print = false; + nprinted = 0; + for (i = 0; VEC_iterate (cp_token, buffer, i, token) && nprinted < num; i++) + { + if (token == start_token) + do_print = true; + + if (!do_print) + continue; + + nprinted++; + if (token == curr_token) + fprintf (file, "[["); + + cp_lexer_print_token (file, token); + + if (token == curr_token) + fprintf (file, "]]"); + + switch (token->type) + { + case CPP_SEMICOLON: + case CPP_OPEN_BRACE: + case CPP_CLOSE_BRACE: + case CPP_EOF: + fputc ('\n', file); + break; + + default: + fputc (' ', file); + } + } + + if (i == num && i < VEC_length (cp_token, buffer)) + { + fprintf (file, " ... "); + cp_lexer_print_token (file, VEC_index (cp_token, buffer, + VEC_length (cp_token, buffer) - 1)); + } + + fprintf (file, "\n"); +} + + +/* Dump all tokens in BUFFER to stderr. */ + +void +cp_lexer_debug_tokens (VEC(cp_token,gc) *buffer) +{ + cp_lexer_dump_tokens (stderr, buffer, NULL, 0, NULL); +} + + +/* Dump the cp_parser tree field T to FILE if T is non-NULL. DESC is the + description for T. */ + +static void +cp_debug_print_tree_if_set (FILE *file, const char *desc, tree t) +{ + if (t) + { + fprintf (file, "%s: ", desc); + print_node_brief (file, "", t, 0); + } +} + + +/* Dump parser context C to FILE. */ + +static void +cp_debug_print_context (FILE *file, cp_parser_context *c) +{ + const char *status_s[] = { "OK", "ERROR", "COMMITTED" }; + fprintf (file, "{ status = %s, scope = ", status_s[c->status]); + print_node_brief (file, "", c->object_type, 0); + fprintf (file, "}\n"); +} + + +/* Print the stack of parsing contexts to FILE starting with FIRST. */ + +static void +cp_debug_print_context_stack (FILE *file, cp_parser_context *first) +{ + unsigned i; + cp_parser_context *c; + + fprintf (file, "Parsing context stack:\n"); + for (i = 0, c = first; c; c = c->next, i++) + { + fprintf (file, "\t#%u: ", i); + cp_debug_print_context (file, c); + } +} + + +/* Print the value of FLAG to FILE. DESC is a string describing the flag. */ + +static void +cp_debug_print_flag (FILE *file, const char *desc, bool flag) +{ + if (flag) + fprintf (file, "%s: true\n", desc); +} + + +/* Print an unparsed function entry UF to FILE. */ + +static void +cp_debug_print_unparsed_function (FILE *file, cp_unparsed_functions_entry *uf) +{ + unsigned i; + cp_default_arg_entry *default_arg_fn; + tree fn; + + fprintf (file, "\tFunctions with default args:\n"); + for (i = 0; + VEC_iterate (cp_default_arg_entry, uf->funs_with_default_args, i, + default_arg_fn); + i++) + { + fprintf (file, "\t\tClass type: "); + print_node_brief (file, "", default_arg_fn->class_type, 0); + fprintf (file, "\t\tDeclaration: "); + print_node_brief (file, "", default_arg_fn->decl, 0); + fprintf (file, "\n"); + } + + fprintf (file, "\n\tFunctions with definitions that require " + "post-processing\n\t\t"); + for (i = 0; VEC_iterate (tree, uf->funs_with_definitions, i, fn); i++) + { + print_node_brief (file, "", fn, 0); + fprintf (file, " "); + } + fprintf (file, "\n"); + + fprintf (file, "\n\tNon-static data members with initializers that require " + "post-processing\n\t\t"); + for (i = 0; VEC_iterate (tree, uf->nsdmis, i, fn); i++) + { + print_node_brief (file, "", fn, 0); + fprintf (file, " "); + } + fprintf (file, "\n"); +} + + +/* Print the stack of unparsed member functions S to FILE. */ + +static void +cp_debug_print_unparsed_queues (FILE *file, + VEC(cp_unparsed_functions_entry, gc) *s) +{ + unsigned i; + cp_unparsed_functions_entry *uf; + + fprintf (file, "Unparsed functions\n"); + for (i = 0; VEC_iterate (cp_unparsed_functions_entry, s, i, uf); i++) + { + fprintf (file, "#%u:\n", i); + cp_debug_print_unparsed_function (file, uf); + } +} + + +/* Dump the tokens in a window of size WINDOW_SIZE around the next_token for + the given PARSER. If FILE is NULL, the output is printed on stderr. */ + +static void +cp_debug_parser_tokens (FILE *file, cp_parser *parser, int window_size) +{ + cp_token *next_token, *first_token, *start_token; + + if (file == NULL) + file = stderr; + + next_token = parser->lexer->next_token; + first_token = VEC_address (cp_token, parser->lexer->buffer); + start_token = (next_token > first_token + window_size / 2) + ? next_token - window_size / 2 + : first_token; + cp_lexer_dump_tokens (file, parser->lexer->buffer, start_token, window_size, + next_token); +} + + +/* Dump debugging information for the given PARSER. If FILE is NULL, + the output is printed on stderr. */ + +void +cp_debug_parser (FILE *file, cp_parser *parser) +{ + const size_t window_size = 20; + cp_token *token; + expanded_location eloc; + + if (file == NULL) + file = stderr; + + fprintf (file, "Parser state\n\n"); + fprintf (file, "Number of tokens: %u\n", + VEC_length (cp_token, parser->lexer->buffer)); + cp_debug_print_tree_if_set (file, "Lookup scope", parser->scope); + cp_debug_print_tree_if_set (file, "Object scope", + parser->object_scope); + cp_debug_print_tree_if_set (file, "Qualifying scope", + parser->qualifying_scope); + cp_debug_print_context_stack (file, parser->context); + cp_debug_print_flag (file, "Allow GNU extensions", + parser->allow_gnu_extensions_p); + cp_debug_print_flag (file, "'>' token is greater-than", + parser->greater_than_is_operator_p); + cp_debug_print_flag (file, "Default args allowed in current " + "parameter list", parser->default_arg_ok_p); + cp_debug_print_flag (file, "Parsing integral constant-expression", + parser->integral_constant_expression_p); + cp_debug_print_flag (file, "Allow non-constant expression in current " + "constant-expression", + parser->allow_non_integral_constant_expression_p); + cp_debug_print_flag (file, "Seen non-constant expression", + parser->non_integral_constant_expression_p); + cp_debug_print_flag (file, "Local names and 'this' forbidden in " + "current context", + parser->local_variables_forbidden_p); + cp_debug_print_flag (file, "In unbraced linkage specification", + parser->in_unbraced_linkage_specification_p); + cp_debug_print_flag (file, "Parsing a declarator", + parser->in_declarator_p); + cp_debug_print_flag (file, "In template argument list", + parser->in_template_argument_list_p); + cp_debug_print_flag (file, "Parsing an iteration statement", + parser->in_statement & IN_ITERATION_STMT); + cp_debug_print_flag (file, "Parsing a switch statement", + parser->in_statement & IN_SWITCH_STMT); + cp_debug_print_flag (file, "Parsing a structured OpenMP block", + parser->in_statement & IN_OMP_BLOCK); + cp_debug_print_flag (file, "Parsing a an OpenMP loop", + parser->in_statement & IN_OMP_FOR); + cp_debug_print_flag (file, "Parsing an if statement", + parser->in_statement & IN_IF_STMT); + cp_debug_print_flag (file, "Parsing a type-id in an expression " + "context", parser->in_type_id_in_expr_p); + cp_debug_print_flag (file, "Declarations are implicitly extern \"C\"", + parser->implicit_extern_c); + cp_debug_print_flag (file, "String expressions should be translated " + "to execution character set", + parser->translate_strings_p); + cp_debug_print_flag (file, "Parsing function body outside of a " + "local class", parser->in_function_body); + cp_debug_print_flag (file, "Auto correct a colon to a scope operator", + parser->colon_corrects_to_scope_p); + if (parser->type_definition_forbidden_message) + fprintf (file, "Error message for forbidden type definitions: %s\n", + parser->type_definition_forbidden_message); + cp_debug_print_unparsed_queues (file, parser->unparsed_queues); + fprintf (file, "Number of class definitions in progress: %u\n", + parser->num_classes_being_defined); + fprintf (file, "Number of template parameter lists for the current " + "declaration: %u\n", parser->num_template_parameter_lists); + cp_debug_parser_tokens (file, parser, window_size); + token = parser->lexer->next_token; + fprintf (file, "Next token to parse:\n"); + fprintf (file, "\tToken: "); + cp_lexer_print_token (file, token); + eloc = expand_location (token->location); + fprintf (file, "\n\tFile: %s\n", eloc.file); + fprintf (file, "\tLine: %d\n", eloc.line); + fprintf (file, "\tColumn: %d\n", eloc.column); +} + + +/* Allocate memory for a new lexer object and return it. */ static cp_lexer * -cp_lexer_new_main (void) +cp_lexer_alloc (void) { - cp_token first_token; cp_lexer *lexer; - cp_token *pos; - size_t alloc; - size_t space; - cp_token *buffer; - - /* It's possible that parsing the first pragma will load a PCH file, - which is a GC collection point. So we have to do that before - allocating any memory. */ - cp_parser_initial_pragma (&first_token); c_common_no_more_pch (); /* Allocate the memory. */ lexer = ggc_alloc_cleared_cp_lexer (); -#ifdef ENABLE_CHECKING /* Initially we are not debugging. */ lexer->debugging_p = false; -#endif /* ENABLE_CHECKING */ + lexer->saved_tokens = VEC_alloc (cp_token_position, heap, CP_SAVED_TOKEN_STACK); /* Create the buffer. */ - alloc = CP_LEXER_BUFFER_SIZE; - buffer = ggc_alloc_vec_cp_token (alloc); + lexer->buffer = VEC_alloc (cp_token, gc, CP_LEXER_BUFFER_SIZE); + + return lexer; +} + + +/* Create a new main C++ lexer, the lexer that gets tokens from the + preprocessor. */ + +static cp_lexer * +cp_lexer_new_main (void) +{ + cp_lexer *lexer; + cp_token token; + + /* It's possible that parsing the first pragma will load a PCH file, + which is a GC collection point. So we have to do that before + allocating any memory. */ + cp_parser_initial_pragma (&token); + + lexer = cp_lexer_alloc (); /* Put the first token in the buffer. */ - space = alloc; - pos = buffer; - *pos = first_token; + VEC_quick_push (cp_token, lexer->buffer, &token); /* Get the remaining tokens from the preprocessor. */ - while (pos->type != CPP_EOF) + while (token.type != CPP_EOF) { - pos++; - if (!--space) - { - space = alloc; - alloc *= 2; - buffer = GGC_RESIZEVEC (cp_token, buffer, alloc); - pos = buffer + space; - } - cp_lexer_get_preprocessor_token (lexer, pos); + cp_lexer_get_preprocessor_token (lexer, &token); + VEC_safe_push (cp_token, gc, lexer->buffer, &token); } - lexer->buffer = buffer; - lexer->buffer_length = alloc - space; - lexer->last_token = pos; - lexer->next_token = lexer->buffer_length ? buffer : &eof_token; + + lexer->last_token = VEC_address (cp_token, lexer->buffer) + + VEC_length (cp_token, lexer->buffer) + - 1; + lexer->next_token = VEC_length (cp_token, lexer->buffer) + ? VEC_address (cp_token, lexer->buffer) + : &eof_token; /* Subsequent preprocessor diagnostics should use compiler diagnostic functions to get the compiler source location. */ done_lexing = true; - gcc_assert (lexer->next_token->type != CPP_PURGED); + gcc_assert (!lexer->next_token->purged_p); return lexer; } @@ -449,19 +623,16 @@ cp_lexer_new_from_tokens (cp_token_cache *cache) /* We do not own the buffer. */ lexer->buffer = NULL; - lexer->buffer_length = 0; lexer->next_token = first == last ? &eof_token : first; lexer->last_token = last; lexer->saved_tokens = VEC_alloc (cp_token_position, heap, CP_SAVED_TOKEN_STACK); -#ifdef ENABLE_CHECKING /* Initially we are not debugging. */ lexer->debugging_p = false; -#endif - gcc_assert (lexer->next_token->type != CPP_PURGED); + gcc_assert (!lexer->next_token->purged_p); return lexer; } @@ -470,23 +641,19 @@ cp_lexer_new_from_tokens (cp_token_cache *cache) static void cp_lexer_destroy (cp_lexer *lexer) { - if (lexer->buffer) - ggc_free (lexer->buffer); + VEC_free (cp_token, gc, lexer->buffer); VEC_free (cp_token_position, heap, lexer->saved_tokens); ggc_free (lexer); } /* Returns nonzero if debugging information should be output. */ -#ifdef ENABLE_CHECKING - static inline bool cp_lexer_debugging_p (cp_lexer *lexer) { return lexer->debugging_p; } -#endif /* ENABLE_CHECKING */ static inline cp_token_position cp_lexer_token_position (cp_lexer *lexer, bool previous_p) @@ -549,6 +716,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token) lexer == NULL ? 0 : C_LEX_STRING_NO_JOIN); token->keyword = RID_MAX; token->pragma_kind = PRAGMA_NONE; + token->purged_p = false; /* On some systems, some header files are surrounded by an implicit extern "C" block. Set a flag in the token if it @@ -576,7 +744,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token) /* Warn about the C++0x keyword (but still treat it as an identifier). */ warning (OPT_Wc__0x_compat, - "identifier %qE will become a keyword in C++0x", + "identifier %qE is a keyword in C++11", token->u.value); /* Clear out the C_RID_CODE so we don't warn about this @@ -723,6 +891,7 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer) case RID_TYPEOF: /* C++0x extensions. */ case RID_DECLTYPE: + case RID_UNDERLYING_TYPE: return true; default: @@ -730,6 +899,24 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer) } } +/* Returns TRUE iff the token T begins a decltype type. */ + +static bool +token_is_decltype (cp_token *t) +{ + return (t->keyword == RID_DECLTYPE + || t->type == CPP_DECLTYPE); +} + +/* Returns TRUE iff the next token begins a decltype type. */ + +static bool +cp_lexer_next_token_is_decltype (cp_lexer *lexer) +{ + cp_token *t = cp_lexer_peek_token (lexer); + return token_is_decltype (t); +} + /* Return a pointer to the Nth token in the token stream. If N is 1, then this is precisely equivalent to cp_lexer_peek_token (except that it is not inline). One would like to disallow that case, but @@ -760,7 +947,7 @@ cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n) break; } - if (token->type != CPP_PURGED) + if (!token->purged_p) --n; } @@ -794,7 +981,7 @@ cp_lexer_consume_token (cp_lexer* lexer) } } - while (lexer->next_token->type == CPP_PURGED); + while (lexer->next_token->purged_p); cp_lexer_set_source_position_from_token (token); @@ -819,7 +1006,7 @@ cp_lexer_purge_token (cp_lexer *lexer) cp_token *tok = lexer->next_token; gcc_assert (tok != &eof_token); - tok->type = CPP_PURGED; + tok->purged_p = true; tok->location = UNKNOWN_LOCATION; tok->u.value = NULL_TREE; tok->keyword = RID_MAX; @@ -833,7 +1020,7 @@ cp_lexer_purge_token (cp_lexer *lexer) break; } } - while (tok->type == CPP_PURGED); + while (tok->purged_p); lexer->next_token = tok; } @@ -853,7 +1040,7 @@ cp_lexer_purge_tokens_after (cp_lexer *lexer, cp_token *tok) for ( tok += 1; tok != peek; tok += 1) { - tok->type = CPP_PURGED; + tok->purged_p = true; tok->location = UNKNOWN_LOCATION; tok->u.value = NULL_TREE; tok->keyword = RID_MAX; @@ -901,8 +1088,6 @@ cp_lexer_rollback_tokens (cp_lexer* lexer) /* Print a representation of the TOKEN on the STREAM. */ -#ifdef ENABLE_CHECKING - static void cp_lexer_print_token (FILE * stream, cp_token *token) { @@ -919,14 +1104,8 @@ cp_lexer_print_token (FILE * stream, cp_token *token) "KEYWORD", "TEMPLATE_ID", "NESTED_NAME_SPECIFIER", - "PURGED" }; - /* If we have a name for the token, print it out. Otherwise, we - simply give the numeric code. */ - gcc_assert (token->type < ARRAY_SIZE(token_names)); - fputs (token_names[token->type], stream); - /* For some tokens, print the associated data. */ switch (token->type) { @@ -948,7 +1127,17 @@ cp_lexer_print_token (FILE * stream, cp_token *token) fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->u.value)); break; + case CPP_NUMBER: + print_generic_expr (stream, token->u.value, 0); + break; + default: + /* If we have a name for the token, print it out. Otherwise, we + simply give the numeric code. */ + if (token->type < ARRAY_SIZE(token_names)) + fputs (token_names[token->type], stream); + else + fprintf (stream, "[%d]", token->type); break; } } @@ -959,6 +1148,7 @@ static void cp_lexer_start_debugging (cp_lexer* lexer) { lexer->debugging_p = true; + cp_lexer_debug_stream = stderr; } /* Stop emitting debugging information. */ @@ -967,10 +1157,9 @@ static void cp_lexer_stop_debugging (cp_lexer* lexer) { lexer->debugging_p = false; + cp_lexer_debug_stream = NULL; } -#endif /* ENABLE_CHECKING */ - /* Create a new cp_token_cache, representing a range of tokens. */ static cp_token_cache * @@ -1001,7 +1190,7 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs) VAR_DECLs or FUNCTION_DECLs) should do that directly. */ static cp_declarator *make_call_declarator - (cp_declarator *, tree, cp_cv_quals, tree, tree); + (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, tree, tree); static cp_declarator *make_array_declarator (cp_declarator *, tree); static cp_declarator *make_pointer_declarator @@ -1166,6 +1355,7 @@ cp_declarator * make_call_declarator (cp_declarator *target, tree parms, cp_cv_quals cv_qualifiers, + cp_virt_specifiers virt_specifiers, tree exception_specification, tree late_return_type) { @@ -1175,6 +1365,7 @@ make_call_declarator (cp_declarator *target, declarator->declarator = target; declarator->u.function.parameters = parms; declarator->u.function.qualifiers = cv_qualifiers; + declarator->u.function.virt_specifiers = virt_specifiers; declarator->u.function.exception_specification = exception_specification; declarator->u.function.late_return_type = late_return_type; if (target) @@ -1413,19 +1604,6 @@ typedef struct cp_parser_binary_operations_map_node enum cp_parser_prec prec; } cp_parser_binary_operations_map_node; -/* The status of a tentative parse. */ - -typedef enum cp_parser_status_kind -{ - /* No errors have occurred. */ - CP_PARSER_STATUS_KIND_NO_ERROR, - /* An error has occurred. */ - CP_PARSER_STATUS_KIND_ERROR, - /* We are committed to this tentative parse, whether or not an error - has occurred. */ - CP_PARSER_STATUS_KIND_COMMITTED -} cp_parser_status_kind; - typedef struct cp_parser_expression_stack_entry { /* Left hand side of the binary operation we are currently @@ -1446,21 +1624,6 @@ typedef struct cp_parser_expression_stack_entry typedef struct cp_parser_expression_stack_entry cp_parser_expression_stack[NUM_PREC_VALUES]; -/* Context that is saved and restored when parsing tentatively. */ -typedef struct GTY (()) cp_parser_context { - /* If this is a tentative parsing context, the status of the - tentative parse. */ - enum cp_parser_status_kind status; - /* If non-NULL, we have just seen a `x->' or `x.' expression. Names - that are looked up in this context must be looked up both in the - scope given by OBJECT_TYPE (the type of `x' or `*x') and also in - the context of the containing expression. */ - tree object_type; - - /* The next parsing context in the stack. */ - struct cp_parser_context *next; -} cp_parser_context; - /* Prototypes. */ /* Constructors and destructors. */ @@ -1551,183 +1714,14 @@ cp_parser_context_new (cp_parser_context* next) return context; } -/* An entry in a queue of function arguments that require post-processing. */ - -typedef struct GTY(()) cp_default_arg_entry_d { - /* The current_class_type when we parsed this arg. */ - tree class_type; - - /* The function decl itself. */ - tree decl; -} cp_default_arg_entry; - -DEF_VEC_O(cp_default_arg_entry); -DEF_VEC_ALLOC_O(cp_default_arg_entry,gc); - -/* An entry in a stack for member functions of local classes. */ - -typedef struct GTY(()) cp_unparsed_functions_entry_d { - /* Functions with default arguments that require post-processing. - Functions appear in this list in declaration order. */ - VEC(cp_default_arg_entry,gc) *funs_with_default_args; - - /* Functions with defintions that require post-processing. Functions - appear in this list in declaration order. */ - VEC(tree,gc) *funs_with_definitions; -} cp_unparsed_functions_entry; - -DEF_VEC_O(cp_unparsed_functions_entry); -DEF_VEC_ALLOC_O(cp_unparsed_functions_entry,gc); - -/* The cp_parser structure represents the C++ parser. */ - -typedef struct GTY(()) cp_parser { - /* The lexer from which we are obtaining tokens. */ - cp_lexer *lexer; - - /* The scope in which names should be looked up. If NULL_TREE, then - we look up names in the scope that is currently open in the - source program. If non-NULL, this is either a TYPE or - NAMESPACE_DECL for the scope in which we should look. It can - also be ERROR_MARK, when we've parsed a bogus scope. - - This value is not cleared automatically after a name is looked - up, so we must be careful to clear it before starting a new look - up sequence. (If it is not cleared, then `X::Y' followed by `Z' - will look up `Z' in the scope of `X', rather than the current - scope.) Unfortunately, it is difficult to tell when name lookup - is complete, because we sometimes peek at a token, look it up, - and then decide not to consume it. */ - tree scope; - - /* OBJECT_SCOPE and QUALIFYING_SCOPE give the scopes in which the - last lookup took place. OBJECT_SCOPE is used if an expression - like "x->y" or "x.y" was used; it gives the type of "*x" or "x", - respectively. QUALIFYING_SCOPE is used for an expression of the - form "X::Y"; it refers to X. */ - tree object_scope; - tree qualifying_scope; - - /* A stack of parsing contexts. All but the bottom entry on the - stack will be tentative contexts. - - We parse tentatively in order to determine which construct is in - use in some situations. For example, in order to determine - whether a statement is an expression-statement or a - declaration-statement we parse it tentatively as a - declaration-statement. If that fails, we then reparse the same - token stream as an expression-statement. */ - cp_parser_context *context; - - /* True if we are parsing GNU C++. If this flag is not set, then - GNU extensions are not recognized. */ - bool allow_gnu_extensions_p; - - /* TRUE if the `>' token should be interpreted as the greater-than - operator. FALSE if it is the end of a template-id or - template-parameter-list. In C++0x mode, this flag also applies to - `>>' tokens, which are viewed as two consecutive `>' tokens when - this flag is FALSE. */ - bool greater_than_is_operator_p; - - /* TRUE if default arguments are allowed within a parameter list - that starts at this point. FALSE if only a gnu extension makes - them permissible. */ - bool default_arg_ok_p; - - /* TRUE if we are parsing an integral constant-expression. See - [expr.const] for a precise definition. */ - bool integral_constant_expression_p; - - /* TRUE if we are parsing an integral constant-expression -- but a - non-constant expression should be permitted as well. This flag - is used when parsing an array bound so that GNU variable-length - arrays are tolerated. */ - bool allow_non_integral_constant_expression_p; - - /* TRUE if ALLOW_NON_CONSTANT_EXPRESSION_P is TRUE and something has - been seen that makes the expression non-constant. */ - bool non_integral_constant_expression_p; - - /* TRUE if local variable names and `this' are forbidden in the - current context. */ - bool local_variables_forbidden_p; - - /* TRUE if the declaration we are parsing is part of a - linkage-specification of the form `extern string-literal - declaration'. */ - bool in_unbraced_linkage_specification_p; - - /* TRUE if we are presently parsing a declarator, after the - direct-declarator. */ - bool in_declarator_p; - - /* TRUE if we are presently parsing a template-argument-list. */ - bool in_template_argument_list_p; - - /* Set to IN_ITERATION_STMT if parsing an iteration-statement, - to IN_OMP_BLOCK if parsing OpenMP structured block and - IN_OMP_FOR if parsing OpenMP loop. If parsing a switch statement, - this is bitwise ORed with IN_SWITCH_STMT, unless parsing an - iteration-statement, OpenMP block or loop within that switch. */ -#define IN_SWITCH_STMT 1 -#define IN_ITERATION_STMT 2 -#define IN_OMP_BLOCK 4 -#define IN_OMP_FOR 8 -#define IN_IF_STMT 16 - unsigned char in_statement; - - /* TRUE if we are presently parsing the body of a switch statement. - Note that this doesn't quite overlap with in_statement above. - The difference relates to giving the right sets of error messages: - "case not in switch" vs "break statement used with OpenMP...". */ - bool in_switch_statement_p; - - /* TRUE if we are parsing a type-id in an expression context. In - such a situation, both "type (expr)" and "type (type)" are valid - alternatives. */ - bool in_type_id_in_expr_p; - - /* TRUE if we are currently in a header file where declarations are - implicitly extern "C". */ - bool implicit_extern_c; - - /* TRUE if strings in expressions should be translated to the execution - character set. */ - bool translate_strings_p; - - /* TRUE if we are presently parsing the body of a function, but not - a local class. */ - bool in_function_body; - - /* TRUE if we can auto-correct a colon to a scope operator. */ - bool colon_corrects_to_scope_p; - - /* If non-NULL, then we are parsing a construct where new type - definitions are not permitted. The string stored here will be - issued as an error message if a type is defined. */ - const char *type_definition_forbidden_message; - - /* A stack used for member functions of local classes. The lists - contained in an individual entry can only be processed once the - outermost class being defined is complete. */ - VEC(cp_unparsed_functions_entry,gc) *unparsed_queues; - - /* The number of classes whose definitions are currently in - progress. */ - unsigned num_classes_being_defined; - - /* The number of template parameter lists that apply directly to the - current declaration. */ - unsigned num_template_parameter_lists; -} cp_parser; - /* Managing the unparsed function queues. */ #define unparsed_funs_with_default_args \ VEC_last (cp_unparsed_functions_entry, parser->unparsed_queues)->funs_with_default_args #define unparsed_funs_with_definitions \ VEC_last (cp_unparsed_functions_entry, parser->unparsed_queues)->funs_with_definitions +#define unparsed_nsdmis \ + VEC_last (cp_unparsed_functions_entry, parser->unparsed_queues)->nsdmis static void push_unparsed_function_queues (cp_parser *parser) @@ -1736,6 +1730,7 @@ push_unparsed_function_queues (cp_parser *parser) parser->unparsed_queues, NULL); unparsed_funs_with_default_args = NULL; unparsed_funs_with_definitions = make_tree_vector (); + unparsed_nsdmis = NULL; } static void @@ -1770,6 +1765,12 @@ static tree cp_parser_identifier (cp_parser *); static tree cp_parser_string_literal (cp_parser *, bool, bool); +static tree cp_parser_userdef_char_literal + (cp_parser *); +static tree cp_parser_userdef_string_literal + (cp_token *); +static tree cp_parser_userdef_numeric_literal + (cp_parser *); /* Basic concepts [gram.basic] */ @@ -1840,7 +1841,7 @@ static tree cp_parser_lambda_expression (cp_parser *); static void cp_parser_lambda_introducer (cp_parser *, tree); -static void cp_parser_lambda_declarator_opt +static bool cp_parser_lambda_declarator_opt (cp_parser *, tree); static void cp_parser_lambda_body (cp_parser *, tree); @@ -1854,7 +1855,7 @@ static void cp_parser_label_for_labeled_statement static tree cp_parser_expression_statement (cp_parser *, tree); static tree cp_parser_compound_statement - (cp_parser *, tree, bool); + (cp_parser *, tree, bool, bool); static void cp_parser_statement_seq_opt (cp_parser *, tree); static tree cp_parser_selection_statement @@ -1863,12 +1864,20 @@ static tree cp_parser_condition (cp_parser *); static tree cp_parser_iteration_statement (cp_parser *); -static void cp_parser_for_init_statement - (cp_parser *); -static tree cp_parser_c_for - (cp_parser *); -static tree cp_parser_range_for +static bool cp_parser_for_init_statement + (cp_parser *, tree *decl); +static tree cp_parser_for (cp_parser *); +static tree cp_parser_c_for + (cp_parser *, tree, tree); +static tree cp_parser_range_for + (cp_parser *, tree, tree, tree); +static void do_range_for_auto_deduction + (tree, tree); +static tree cp_parser_perform_range_for_lookup + (tree, tree *, tree *); +static tree cp_parser_range_for_member_function + (tree, tree); static tree cp_parser_jump_statement (cp_parser *); static void cp_parser_declaration_statement @@ -1888,7 +1897,7 @@ static void cp_parser_declaration static void cp_parser_block_declaration (cp_parser *, bool); static void cp_parser_simple_declaration - (cp_parser *, bool); + (cp_parser *, bool, tree *); static void cp_parser_decl_specifier_seq (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, int *); static tree cp_parser_storage_class_specifier_opt @@ -1938,7 +1947,7 @@ static tree cp_parser_decltype /* Declarators [gram.dcl.decl] */ static tree cp_parser_init_declarator - (cp_parser *, cp_decl_specifier_seq *, VEC (deferred_access_check,gc)*, bool, bool, int, bool *); + (cp_parser *, cp_decl_specifier_seq *, VEC (deferred_access_check,gc)*, bool, bool, int, bool *, tree *); static cp_declarator *cp_parser_declarator (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool); static cp_declarator *cp_parser_direct_declarator @@ -1947,8 +1956,10 @@ static enum tree_code cp_parser_ptr_operator (cp_parser *, tree *, cp_cv_quals *); static cp_cv_quals cp_parser_cv_qualifier_seq_opt (cp_parser *); -static tree cp_parser_late_return_type_opt +static cp_virt_specifiers cp_parser_virt_specifier_seq_opt (cp_parser *); +static tree cp_parser_late_return_type_opt + (cp_parser *, cp_cv_quals); static tree cp_parser_declarator_id (cp_parser *, bool); static tree cp_parser_type_id @@ -2168,12 +2179,18 @@ static tree cp_parser_functional_cast (cp_parser *, tree); static tree cp_parser_save_member_function_body (cp_parser *, cp_decl_specifier_seq *, cp_declarator *, tree); +static tree cp_parser_save_nsdmi + (cp_parser *); static tree cp_parser_enclosed_template_argument_list (cp_parser *); static void cp_parser_save_default_args (cp_parser *, tree); static void cp_parser_late_parsing_for_member (cp_parser *, tree); +static tree cp_parser_late_parse_one_default_arg + (cp_parser *, tree, tree, tree); +static void cp_parser_late_parsing_nsdmi + (cp_parser *, tree); static void cp_parser_late_parsing_default_args (cp_parser *, tree); static tree cp_parser_sizeof_operand @@ -2262,6 +2279,8 @@ static bool cp_parser_error_occurred (cp_parser *); static bool cp_parser_allow_gnu_extensions_p (cp_parser *); +static bool cp_parser_is_pure_string_literal + (cp_token *); static bool cp_parser_is_string_literal (cp_token *); static bool cp_parser_is_keyword @@ -2282,7 +2301,7 @@ cp_parser_parsing_tentatively (cp_parser* parser) /* Returns nonzero if TOKEN is a string literal. */ static bool -cp_parser_is_string_literal (cp_token* token) +cp_parser_is_pure_string_literal (cp_token* token) { return (token->type == CPP_STRING || token->type == CPP_STRING16 || @@ -2291,6 +2310,20 @@ cp_parser_is_string_literal (cp_token* token) token->type == CPP_UTF8STRING); } +/* Returns nonzero if TOKEN is a string literal + of a user-defined string literal. */ + +static bool +cp_parser_is_string_literal (cp_token* token) +{ + return (cp_parser_is_pure_string_literal (token) || + token->type == CPP_STRING_USERDEF || + token->type == CPP_STRING16_USERDEF || + token->type == CPP_STRING32_USERDEF || + token->type == CPP_WSTRING_USERDEF || + token->type == CPP_UTF8STRING_USERDEF); +} + /* Returns nonzero if TOKEN is the indicated KEYWORD. */ static bool @@ -2697,6 +2730,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, location_t location) { tree decl, old_scope; + cp_parser_commit_to_tentative_parse (parser); /* Try to lookup the identifier. */ old_scope = parser->scope; parser->scope = scope; @@ -2725,8 +2759,8 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, The user should have said "typename A::X". */ if (cxx_dialect < cxx0x && id == ridpointers[(int)RID_CONSTEXPR]) - inform (location, "C++0x % only available with " - "-std=c++0x or -std=gnu++0x"); + inform (location, "C++11 % only available with " + "-std=c++11 or -std=gnu++11"); else if (processing_template_decl && current_class_type && TYPE_BINFO (current_class_type)) { @@ -2785,12 +2819,11 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, "%qT is a dependent scope", parser->scope, id, parser->scope); else if (TYPE_P (parser->scope)) - error_at (location, "%qE in class %qT does not name a type", + error_at (location, "%qE in %q#T does not name a type", id, parser->scope); else gcc_unreachable (); } - cp_parser_commit_to_tentative_parse (parser); } /* Check for a common situation where a type-name should be present, @@ -3330,7 +3363,11 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok) struct obstack str_ob; cpp_string str, istr, *strs; cp_token *tok; - enum cpp_ttype type; + enum cpp_ttype type, curr_type; + int have_suffix_p = 0; + tree string_tree; + tree suffix_id = NULL_TREE; + bool curr_tok_is_userdef_p = false; tok = cp_lexer_peek_token (parser->lexer); if (!cp_parser_is_string_literal (tok)) @@ -3339,7 +3376,18 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok) return error_mark_node; } - type = tok->type; + if (cpp_userdef_string_p (tok->type)) + { + string_tree = USERDEF_LITERAL_VALUE (tok->u.value); + curr_type = cpp_userdef_string_remove_type (tok->type); + curr_tok_is_userdef_p = true; + } + else + { + string_tree = tok->u.value; + curr_type = tok->type; + } + type = curr_type; /* Try to avoid the overhead of creating and destroying an obstack for the common case of just one string. */ @@ -3348,10 +3396,19 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok) { cp_lexer_consume_token (parser->lexer); - str.text = (const unsigned char *)TREE_STRING_POINTER (tok->u.value); - str.len = TREE_STRING_LENGTH (tok->u.value); + str.text = (const unsigned char *)TREE_STRING_POINTER (string_tree); + str.len = TREE_STRING_LENGTH (string_tree); count = 1; + if (curr_tok_is_userdef_p) + { + suffix_id = USERDEF_LITERAL_SUFFIX_ID (tok->u.value); + have_suffix_p = 1; + curr_type = cpp_userdef_string_remove_type (tok->type); + } + else + curr_type = tok->type; + strs = &str; } else @@ -3363,14 +3420,35 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok) { cp_lexer_consume_token (parser->lexer); count++; - str.text = (const unsigned char *)TREE_STRING_POINTER (tok->u.value); - str.len = TREE_STRING_LENGTH (tok->u.value); + str.text = (const unsigned char *)TREE_STRING_POINTER (string_tree); + str.len = TREE_STRING_LENGTH (string_tree); - if (type != tok->type) + if (curr_tok_is_userdef_p) + { + tree curr_suffix_id = USERDEF_LITERAL_SUFFIX_ID (tok->u.value); + if (have_suffix_p == 0) + { + suffix_id = curr_suffix_id; + have_suffix_p = 1; + } + else if (have_suffix_p == 1 + && curr_suffix_id != suffix_id) + { + error ("inconsistent user-defined literal suffixes" + " %qD and %qD in string literal", + suffix_id, curr_suffix_id); + have_suffix_p = -1; + } + curr_type = cpp_userdef_string_remove_type (tok->type); + } + else + curr_type = tok->type; + + if (type != curr_type) { if (type == CPP_STRING) - type = tok->type; - else if (tok->type != CPP_STRING) + type = curr_type; + else if (curr_type != CPP_STRING) error_at (tok->location, "unsupported non-standard concatenation " "of string literals"); @@ -3379,6 +3457,18 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok) obstack_grow (&str_ob, &str, sizeof (cpp_string)); tok = cp_lexer_peek_token (parser->lexer); + if (cpp_userdef_string_p (tok->type)) + { + string_tree = USERDEF_LITERAL_VALUE (tok->u.value); + curr_type = cpp_userdef_string_remove_type (tok->type); + curr_tok_is_userdef_p = true; + } + else + { + string_tree = tok->u.value; + curr_type = tok->type; + curr_tok_is_userdef_p = false; + } } while (cp_parser_is_string_literal (tok)); @@ -3416,15 +3506,203 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok) } value = fix_string_type (value); + + if (have_suffix_p) + { + tree literal = build_userdef_literal (suffix_id, value, NULL_TREE); + tok->u.value = literal; + return cp_parser_userdef_string_literal (tok); + } + } + else + /* cpp_interpret_string has issued an error. */ + value = error_mark_node; + + if (count > 1) + obstack_free (&str_ob, 0); + + return value; +} + +/* Parse a user-defined char constant. Returns a call to a user-defined + literal operator taking the character as an argument. */ + +static tree +cp_parser_userdef_char_literal (cp_parser *parser) +{ + cp_token *token = NULL; + tree literal, suffix_id, value; + tree name, decl; + tree result; + VEC(tree,gc) *vec; + + token = cp_lexer_consume_token (parser->lexer); + literal = token->u.value; + suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal); + value = USERDEF_LITERAL_VALUE (literal); + name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id)); + + /* Build up a call to the user-defined operator */ + /* Lookup the name we got back from the id-expression. */ + vec = make_tree_vector (); + VEC_safe_push (tree, gc, vec, value); + decl = lookup_function_nonclass (name, vec, /*block_p=*/false); + if (!decl || decl == error_mark_node) + { + error ("unable to find user-defined character literal operator %qD", + name); + release_tree_vector (vec); + return error_mark_node; + } + result = finish_call_expr (decl, &vec, false, true, tf_warning_or_error); + release_tree_vector (vec); + + return result; +} + +/* A subroutine of cp_parser_userdef_numeric_literal to + create a char... template parameter pack from a string node. */ + +static tree +make_char_string_pack (tree value) +{ + tree charvec; + tree argpack = make_node (NONTYPE_ARGUMENT_PACK); + const char *str = TREE_STRING_POINTER (value); + int i, len = TREE_STRING_LENGTH (value) - 1; + tree argvec = make_tree_vec (1); + + /* Fill in CHARVEC with all of the parameters. */ + charvec = make_tree_vec (len); + for (i = 0; i < len; ++i) + TREE_VEC_ELT (charvec, i) = build_int_cst (char_type_node, str[i]); + + /* Build the argument packs. */ + SET_ARGUMENT_PACK_ARGS (argpack, charvec); + TREE_TYPE (argpack) = char_type_node; + + TREE_VEC_ELT (argvec, 0) = argpack; + + return argvec; +} + +/* Parse a user-defined numeric constant. returns a call to a user-defined + literal operator. */ + +static tree +cp_parser_userdef_numeric_literal (cp_parser *parser) +{ + cp_token *token = NULL; + tree literal, suffix_id, value, num_string; + tree name, decl; + tree result = error_mark_node; + VEC(tree,gc) *args; + + token = cp_lexer_consume_token (parser->lexer); + literal = token->u.value; + suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal); + value = USERDEF_LITERAL_VALUE (literal); + num_string = USERDEF_LITERAL_NUM_STRING (literal); + name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id)); + + /* Build up a call to the user-defined operator */ + /* Lookup the name we got back from the id-expression. */ + /* Try to find the literal operator by finishing the call expression + with the numeric argument. */ + args = make_tree_vector (); + VEC_safe_push (tree, gc, args, value); + decl = lookup_function_nonclass (name, args, /*block_p=*/false); + if (decl && decl != error_mark_node) + { + result = finish_call_expr (decl, &args, false, true, tf_none); + if (result != error_mark_node) + { + release_tree_vector (args); + return result; + } + } + release_tree_vector (args); + + /* If the numeric argument didn't work, look for a raw literal + operator taking a const char* argument consisting of the number + in string format. */ + args = make_tree_vector (); + VEC_safe_push (tree, gc, args, num_string); + decl = lookup_function_nonclass (name, args, /*block_p=*/false); + if (decl && decl != error_mark_node) + { + result = finish_call_expr (decl, &args, false, true, tf_none); + if (result != error_mark_node) + { + release_tree_vector (args); + return result; + } + } + release_tree_vector (args); + + /* If the raw literal didn't work, look for a non-type template + function with parameter pack char.... Call the function with + template parameter characters representing the number. */ + args = make_tree_vector (); + decl = lookup_function_nonclass (name, args, /*block_p=*/false); + if (decl && decl != error_mark_node) + { + tree tmpl_args = make_char_string_pack (num_string); + decl = lookup_template_function (decl, tmpl_args); + result = finish_call_expr (decl, &args, false, true, tf_none); + if (result != error_mark_node) + { + release_tree_vector (args); + return result; + } + } + release_tree_vector (args); + + if (result == error_mark_node) + error ("unable to find user-defined numeric literal operator %qD", name); + + return result; +} + +/* Parse a user-defined string constant. Returns a call to a user-defined + literal operator taking a character pointer and the length of the string + as arguments. */ + +static tree +cp_parser_userdef_string_literal (cp_token *token) +{ + tree literal, suffix_id, value; + tree name, decl; + tree result; + VEC(tree,gc) *vec; + int len; + + literal = token->u.value; + suffix_id = USERDEF_LITERAL_SUFFIX_ID (literal); + name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id)); + value = USERDEF_LITERAL_VALUE (literal); + len = TREE_STRING_LENGTH (value) - 1; + + /* Build up a call to the user-defined operator */ + /* Lookup the name we got back from the id-expression. */ + vec = make_tree_vector (); + VEC_safe_push (tree, gc, vec, value); + VEC_safe_push (tree, gc, vec, build_int_cst (size_type_node, len)); + decl = lookup_function_nonclass (name, vec, /*block_p=*/false); + if (!decl || decl == error_mark_node) + { + error ("unable to find user-defined string literal operator %qD", name); + release_tree_vector (vec); + return error_mark_node; } - else - /* cpp_interpret_string has issued an error. */ - value = error_mark_node; - - if (count > 1) - obstack_free (&str_ob, 0); + result = finish_call_expr (decl, &vec, false, true, tf_none); + if (result == error_mark_node) + error ("unable to find valid user-defined string literal operator %qD." + " Possible missing length argument in string literal operator.", + name); + release_tree_vector (vec); - return value; + return result; } @@ -3526,8 +3804,11 @@ cp_parser_translation_unit (cp_parser* parser) __is_convertible_to ( type-id , type-id ) __is_empty ( type-id ) __is_enum ( type-id ) + __is_literal_type ( type-id ) __is_pod ( type-id ) __is_polymorphic ( type-id ) + __is_std_layout ( type-id ) + __is_trivial ( type-id ) __is_union ( type-id ) Objective-C++ Extension: @@ -3567,12 +3848,16 @@ cp_parser_primary_expression (cp_parser *parser, character-literal floating-literal string-literal - boolean-literal */ + boolean-literal + pointer-literal + user-defined-literal */ case CPP_CHAR: case CPP_CHAR16: case CPP_CHAR32: case CPP_WCHAR: case CPP_NUMBER: + if (TREE_CODE (token->u.value) == USERDEF_LITERAL) + return cp_parser_userdef_numeric_literal (parser); token = cp_lexer_consume_token (parser->lexer); if (TREE_CODE (token->u.value) == FIXED_CST) { @@ -3626,11 +3911,22 @@ cp_parser_primary_expression (cp_parser *parser, } return token->u.value; + case CPP_CHAR_USERDEF: + case CPP_CHAR16_USERDEF: + case CPP_CHAR32_USERDEF: + case CPP_WCHAR_USERDEF: + return cp_parser_userdef_char_literal (parser); + case CPP_STRING: case CPP_STRING16: case CPP_STRING32: case CPP_WSTRING: case CPP_UTF8STRING: + case CPP_STRING_USERDEF: + case CPP_STRING16_USERDEF: + case CPP_STRING32_USERDEF: + case CPP_WSTRING_USERDEF: + case CPP_UTF8STRING_USERDEF: /* ??? Should wide strings be allowed when parser->translate_strings_p is false (i.e. in attributes)? If not, we can kill the third argument to cp_parser_string_literal. */ @@ -3679,7 +3975,7 @@ cp_parser_primary_expression (cp_parser *parser, /* Start the statement-expression. */ expr = begin_stmt_expr (); /* Parse the compound-statement. */ - cp_parser_compound_statement (parser, expr, false); + cp_parser_compound_statement (parser, expr, false, false); /* Finish up. */ expr = finish_stmt_expr (expr, false); } @@ -3694,6 +3990,12 @@ cp_parser_primary_expression (cp_parser *parser, `&A::B' might be a pointer-to-member, but `&(A::B)' is not. */ finish_parenthesized_expr (expr); + /* DR 705: Wrapping an unqualified name in parentheses + suppresses arg-dependent lookup. We want to pass back + CP_ID_KIND_QUALIFIED for suppressing vtable lookup + (c++/37862), but none of the others. */ + if (*idk != CP_ID_KIND_QUALIFIED) + *idk = CP_ID_KIND_NONE; } /* The `>' token might be the end of a template-id or template-parameter-list now. */ @@ -3710,8 +4012,14 @@ cp_parser_primary_expression (cp_parser *parser, if (c_dialect_objc ()) /* We have an Objective-C++ message. */ return cp_parser_objc_expression (parser); - maybe_warn_cpp0x (CPP0X_LAMBDA_EXPR); - return cp_parser_lambda_expression (parser); + { + tree lam = cp_parser_lambda_expression (parser); + /* Don't warn about a failed tentative parse. */ + if (cp_parser_error_occurred (parser)) + return error_mark_node; + maybe_warn_cpp0x (CPP0X_LAMBDA_EXPR); + return lam; + } case CPP_OBJC_STRING: if (c_dialect_objc ()) @@ -3841,12 +4149,12 @@ cp_parser_primary_expression (cp_parser *parser, case RID_IS_CONVERTIBLE_TO: case RID_IS_EMPTY: case RID_IS_ENUM: + case RID_IS_LITERAL_TYPE: case RID_IS_POD: case RID_IS_POLYMORPHIC: case RID_IS_STD_LAYOUT: case RID_IS_TRIVIAL: case RID_IS_UNION: - case RID_IS_LITERAL_TYPE: return cp_parser_trait_expr (parser, token->keyword); /* Objective-C++ expressions. */ @@ -4306,7 +4614,8 @@ cp_parser_unqualified_id (cp_parser* parser, && (cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_LESS) && (token->u.value == TYPE_IDENTIFIER (scope) - || constructor_name_p (token->u.value, scope))) + || (CLASS_TYPE_P (scope) + && constructor_name_p (token->u.value, scope)))) { cp_lexer_consume_token (parser->lexer); return build_nt (BIT_NOT_EXPR, scope); @@ -4453,6 +4762,14 @@ cp_parser_unqualified_id (cp_parser* parser, /* If that didn't work, try a conversion-function-id. */ if (!cp_parser_parse_definitely (parser)) id = cp_parser_conversion_function_id (parser); + else if (UDLIT_OPER_P (id)) + { + /* 17.6.3.3.5 */ + const char *name = UDLIT_OP_SUFFIX (id); + if (name[0] != '_' && !in_system_header) + warning (0, "literal operator suffixes not preceded by %<_%>" + " are reserved for future standardization"); + } return id; } @@ -4549,6 +4866,9 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, /* A template-id can start a nested-name-specifier. */ else if (token->type == CPP_TEMPLATE_ID) ; + /* DR 743: decltype can be used in a nested-name-specifier. */ + else if (token_is_decltype (token)) + ; else { /* If the next token is not an identifier, then it is @@ -4622,6 +4942,28 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, class-or-namespace-name. */ parser->scope = old_scope; parser->qualifying_scope = saved_qualifying_scope; + + /* If the next token is a decltype, and the one after that is a + `::', then the decltype has failed to resolve to a class or + enumeration type. Give this error even when parsing + tentatively since it can't possibly be valid--and we're going + to replace it with a CPP_NESTED_NAME_SPECIFIER below, so we + won't get another chance.*/ + if (cp_lexer_next_token_is (parser->lexer, CPP_DECLTYPE) + && (cp_lexer_peek_nth_token (parser->lexer, 2)->type + == CPP_SCOPE)) + { + token = cp_lexer_consume_token (parser->lexer); + error_at (token->location, "decltype evaluates to %qT, " + "which is not a class or enumeration type", + token->u.value); + parser->scope = error_mark_node; + error_p = true; + /* As below. */ + success = true; + cp_lexer_consume_token (parser->lexer); + } + if (cp_parser_uncommitted_to_tentative_parse_p (parser)) break; /* If the next token is an identifier, and the one after @@ -4703,8 +5045,8 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, && (TREE_CODE (TYPENAME_TYPE_FULLNAME (new_scope)) == TEMPLATE_ID_EXPR))) permerror (input_location, TYPE_P (new_scope) - ? "%qT is not a template" - : "%qD is not a template", + ? G_("%qT is not a template") + : G_("%qD is not a template"), new_scope); /* If it is a class scope, try to complete it; we are about to be looking up names inside the class. */ @@ -4821,6 +5163,21 @@ cp_parser_qualifying_entity (cp_parser *parser, bool only_class_p; bool successful_parse_p; + /* DR 743: decltype can appear in a nested-name-specifier. */ + if (cp_lexer_next_token_is_decltype (parser->lexer)) + { + scope = cp_parser_decltype (parser); + if (TREE_CODE (scope) != ENUMERAL_TYPE + && !MAYBE_CLASS_TYPE_P (scope)) + { + cp_parser_simulate_error (parser); + return error_mark_node; + } + if (TYPE_NAME (scope)) + scope = TYPE_NAME (scope); + return scope; + } + /* Before we try to parse the class-name, we must save away the current PARSER->SCOPE since cp_parser_class_name will destroy it. */ @@ -5055,7 +5412,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, /* Restore the saved message. */ parser->type_definition_forbidden_message = saved_message; /* `typeid' may not appear in an integral constant expression. */ - if (cp_parser_non_integral_constant_expression(parser, NIC_TYPEID)) + if (cp_parser_non_integral_constant_expression (parser, NIC_TYPEID)) return error_mark_node; } break; @@ -5153,7 +5510,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, postfix_expression = (finish_compound_literal (type, build_constructor (init_list_type_node, - initializer_list))); + initializer_list), + tf_warning_or_error)); break; } } @@ -5255,7 +5613,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, if (!any_type_dependent_arguments_p (args)) postfix_expression = perform_koenig_lookup (postfix_expression, args, - /*include_std=*/false); + /*include_std=*/false, + tf_warning_or_error); } else postfix_expression @@ -5280,7 +5639,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, if (!any_type_dependent_arguments_p (args)) postfix_expression = perform_koenig_lookup (postfix_expression, args, - /*include_std=*/false); + /*include_std=*/false, + tf_warning_or_error); } } } @@ -5309,7 +5669,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, = (build_new_method_call (instance, fn, &args, NULL_TREE, (idk == CP_ID_KIND_QUALIFIED - ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL), + ? LOOKUP_NORMAL|LOOKUP_NONVIRTUAL + : LOOKUP_NORMAL), /*fn_p=*/NULL, tf_warning_or_error)); } @@ -5513,7 +5874,11 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, postfix_expression); scope = NULL_TREE; } - else + /* Unlike the object expression in other contexts, *this is not + required to be of complete type for purposes of class member + access (5.2.5) outside the member function body. */ + else if (scope != current_class_ref + && !(processing_template_decl && scope == current_class_type)) scope = complete_type_or_else (scope, NULL_TREE); /* Let the name lookup machinery know that we are processing a class member access expression. */ @@ -5874,6 +6239,11 @@ cp_parser_pseudo_destructor_name (cp_parser* parser, /* Look for the `~'. */ cp_parser_require (parser, CPP_COMPL, RT_COMPL); + + /* Once we see the ~, this has to be a pseudo-destructor. */ + if (!processing_template_decl && !cp_parser_error_occurred (parser)) + cp_parser_commit_to_tentative_parse (parser); + /* Look for the type-name again. We are not responsible for checking that it matches the first type-name. */ *type = cp_parser_nonclass_name (parser); @@ -6544,7 +6914,8 @@ cp_parser_delete_expression (cp_parser* parser) if (cp_parser_non_integral_constant_expression (parser, NIC_DEL)) return error_mark_node; - return delete_sanity (expression, NULL_TREE, array_p, global_scope_p); + return delete_sanity (expression, NULL_TREE, array_p, global_scope_p, + tf_warning_or_error); } /* Returns true if TOKEN may start a cast-expression and false @@ -6811,7 +7182,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, cp_token *token; enum tree_code tree_type, lhs_type, rhs_type; enum cp_parser_prec new_prec, lookahead_prec; - bool overloaded_p; + tree overload; /* Parse the first expression. */ lhs = cp_parser_cast_expression (parser, /*address_p=*/false, cast_p, pidk); @@ -6827,8 +7198,8 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, && !parser->greater_than_is_operator_p) { if (warning_at (token->location, OPT_Wc__0x_compat, - "%<>>%> operator will be treated as" - " two right angle brackets in C++0x")) + "%<>>%> operator is treated as" + " two right angle brackets in C++11")) inform (token->location, "suggest parentheses around %<>>%> expression"); } @@ -6914,7 +7285,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, else if (tree_type == TRUTH_ORIF_EXPR) c_inhibit_evaluation_warnings -= lhs == truthvalue_true_node; - overloaded_p = false; + overload = NULL; /* ??? Currently we pass lhs_type == ERROR_MARK and rhs_type == ERROR_MARK for everything that is not a binary expression. This makes warn_about_parentheses miss some warnings that @@ -6929,7 +7300,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, lhs = build2 (tree_type, boolean_type_node, lhs, rhs); else lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type, - &overloaded_p, tf_warning_or_error); + &overload, tf_warning_or_error); lhs_type = tree_type; /* If the binary operator required the use of an overloaded operator, @@ -6938,7 +7309,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p, otherwise permissible in an integral constant-expression if at least one of the operands is of enumeration type. */ - if (overloaded_p + if (overload && cp_parser_non_integral_constant_expression (parser, NIC_OVERLOADED)) return error_mark_node; @@ -7264,11 +7635,18 @@ cp_parser_constant_expression (cp_parser* parser, = saved_integral_constant_expression_p; parser->allow_non_integral_constant_expression_p = saved_allow_non_integral_constant_expression_p; + if (cxx_dialect >= cxx0x) + { + /* Require an rvalue constant expression here; that's what our + callers expect. Reference constant expressions are handled + separately in e.g. cp_parser_template_argument. */ + bool is_const = potential_rvalue_constant_expression (expression); + parser->non_integral_constant_expression_p = !is_const; + if (!is_const && !allow_non_constant_p) + require_potential_rvalue_constant_expression (expression); + } if (allow_non_constant_p) *non_constant_p = parser->non_integral_constant_expression_p; - else if (parser->non_integral_constant_expression_p - && cxx_dialect < cxx0x) - expression = error_mark_node; parser->non_integral_constant_expression_p = saved_non_integral_constant_expression_p; @@ -7370,7 +7748,10 @@ cp_parser_builtin_offsetof (cp_parser *parser) return expr; } -/* Parse a trait expression. */ +/* Parse a trait expression. + + Returns a representation of the expression, the underlying type + of the type at issue when KEYWORD is RID_UNDERLYING_TYPE. */ static tree cp_parser_trait_expr (cp_parser* parser, enum rid keyword) @@ -7426,6 +7807,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) case RID_IS_ENUM: kind = CPTK_IS_ENUM; break; + case RID_IS_LITERAL_TYPE: + kind = CPTK_IS_LITERAL_TYPE; + break; case RID_IS_POD: kind = CPTK_IS_POD; break; @@ -7441,8 +7825,14 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) case RID_IS_UNION: kind = CPTK_IS_UNION; break; - case RID_IS_LITERAL_TYPE: - kind = CPTK_IS_LITERAL_TYPE; + case RID_UNDERLYING_TYPE: + kind = CPTK_UNDERLYING_TYPE; + break; + case RID_BASES: + kind = CPTK_BASES; + break; + case RID_DIRECT_BASES: + kind = CPTK_DIRECT_BASES; break; default: gcc_unreachable (); @@ -7488,7 +7878,17 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword) /* Complete the trait expression, which may mean either processing the trait expr now or saving it for template instantiation. */ - return finish_trait_expr (kind, type1, type2); + switch(kind) + { + case CPTK_UNDERLYING_TYPE: + return finish_underlying_type (type1); + case CPTK_BASES: + return finish_bases (type1, false); + case CPTK_DIRECT_BASES: + return finish_bases (type1, true); + default: + return finish_trait_expr (kind, type1, type2); + } } /* Lambdas that appear in variable initializer or default argument scope @@ -7556,6 +7956,7 @@ cp_parser_lambda_expression (cp_parser* parser) { tree lambda_expr = build_lambda_expr (); tree type; + bool ok; LAMBDA_EXPR_LOCATION (lambda_expr) = cp_lexer_peek_token (parser->lexer)->location; @@ -7585,15 +7986,22 @@ cp_parser_lambda_expression (cp_parser* parser) /* Inside the class, surrounding template-parameter-lists do not apply. */ unsigned int saved_num_template_parameter_lists = parser->num_template_parameter_lists; + unsigned char in_statement = parser->in_statement; + bool in_switch_statement_p = parser->in_switch_statement_p; parser->num_template_parameter_lists = 0; + parser->in_statement = 0; + parser->in_switch_statement_p = false; /* By virtue of defining a local class, a lambda expression has access to the private variables of enclosing classes. */ - cp_parser_lambda_declarator_opt (parser, lambda_expr); + ok = cp_parser_lambda_declarator_opt (parser, lambda_expr); - cp_parser_lambda_body (parser, lambda_expr); + if (ok) + cp_parser_lambda_body (parser, lambda_expr); + else if (cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE)) + cp_parser_skip_to_end_of_block_or_statement (parser); /* The capture list was built up in reverse order; fix that now. */ { @@ -7603,40 +8011,37 @@ cp_parser_lambda_expression (cp_parser* parser) for (elt = LAMBDA_EXPR_CAPTURE_LIST (lambda_expr); elt; elt = next) { - tree field = TREE_PURPOSE (elt); - char *buf; - next = TREE_CHAIN (elt); TREE_CHAIN (elt) = newlist; newlist = elt; - - /* Also add __ to the beginning of the field name so that code - outside the lambda body can't see the captured name. We could - just remove the name entirely, but this is more useful for - debugging. */ - if (field == LAMBDA_EXPR_THIS_CAPTURE (lambda_expr)) - /* The 'this' capture already starts with __. */ - continue; - - buf = (char *) alloca (IDENTIFIER_LENGTH (DECL_NAME (field)) + 3); - buf[1] = buf[0] = '_'; - memcpy (buf + 2, IDENTIFIER_POINTER (DECL_NAME (field)), - IDENTIFIER_LENGTH (DECL_NAME (field)) + 1); - DECL_NAME (field) = get_identifier (buf); } LAMBDA_EXPR_CAPTURE_LIST (lambda_expr) = newlist; } - maybe_add_lambda_conv_op (type); + if (ok) + maybe_add_lambda_conv_op (type); type = finish_struct (type, /*attributes=*/NULL_TREE); parser->num_template_parameter_lists = saved_num_template_parameter_lists; + parser->in_statement = in_statement; + parser->in_switch_statement_p = in_switch_statement_p; } pop_deferring_access_checks (); - return build_lambda_object (lambda_expr); + /* This field is only used during parsing of the lambda. */ + LAMBDA_EXPR_THIS_CAPTURE (lambda_expr) = NULL_TREE; + + /* This lambda shouldn't have any proxies left at this point. */ + gcc_assert (LAMBDA_EXPR_PENDING_PROXIES (lambda_expr) == NULL); + /* And now that we're done, push proxies for an enclosing lambda. */ + insert_pending_capture_proxies (); + + if (ok) + return build_lambda_object (lambda_expr); + else + return error_mark_node; } /* Parse the beginning of a lambda expression. @@ -7697,9 +8102,13 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) /* Possibly capture `this'. */ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_THIS)) { + location_t loc = cp_lexer_peek_token (parser->lexer)->location; + if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_COPY) + pedwarn (loc, 0, "explicit by-copy capture of % redundant " + "with by-copy capture default"); cp_lexer_consume_token (parser->lexer); add_capture (lambda_expr, - /*id=*/get_identifier ("__this"), + /*id=*/this_identifier, /*initializer=*/finish_this_expr(), /*by_reference_p=*/false, explicit_init_p); @@ -7759,6 +8168,31 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) /*ambiguous_decls=*/NULL, capture_token->location); + if (capture_init_expr == error_mark_node) + { + unqualified_name_lookup_error (capture_id); + continue; + } + else if (DECL_P (capture_init_expr) + && (TREE_CODE (capture_init_expr) != VAR_DECL + && TREE_CODE (capture_init_expr) != PARM_DECL)) + { + error_at (capture_token->location, + "capture of non-variable %qD ", + capture_init_expr); + inform (0, "%q+#D declared here", capture_init_expr); + continue; + } + if (TREE_CODE (capture_init_expr) == VAR_DECL + && decl_storage_duration (capture_init_expr) != dk_auto) + { + pedwarn (capture_token->location, 0, "capture of variable " + "%qD with non-automatic storage duration", + capture_init_expr); + inform (0, "%q+#D declared here", capture_init_expr); + continue; + } + capture_init_expr = finish_id_expression (capture_id, @@ -7776,9 +8210,20 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) capture_token->location); } - if (TREE_CODE (capture_init_expr) == IDENTIFIER_NODE) - capture_init_expr - = unqualified_name_lookup_error (capture_init_expr); + if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE + && !explicit_init_p) + { + if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_COPY + && capture_kind == BY_COPY) + pedwarn (capture_token->location, 0, "explicit by-copy capture " + "of %qD redundant with by-copy capture default", + capture_id); + if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_REFERENCE + && capture_kind == BY_REFERENCE) + pedwarn (capture_token->location, 0, "explicit by-reference " + "capture of %qD redundant with by-reference capture " + "default", capture_id); + } add_capture (lambda_expr, capture_id, @@ -7801,7 +8246,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr) LAMBDA_EXPR is the current representation of the lambda expression. */ -static void +static bool cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) { /* 5.1.1.4 of the standard says: @@ -7889,6 +8334,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) quals = (LAMBDA_EXPR_MUTABLE_P (lambda_expr) ? TYPE_UNQUALIFIED : TYPE_QUAL_CONST); declarator = make_call_declarator (declarator, param_list, quals, + VIRT_SPEC_UNSPECIFIED, exception_spec, /*late_return_type=*/NULL_TREE); declarator->id_loc = LAMBDA_EXPR_LOCATION (lambda_expr); @@ -7896,12 +8342,19 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr) fco = grokmethod (&return_type_specs, declarator, attributes); - DECL_INITIALIZED_IN_CLASS_P (fco) = 1; - DECL_ARTIFICIAL (fco) = 1; + if (fco != error_mark_node) + { + DECL_INITIALIZED_IN_CLASS_P (fco) = 1; + DECL_ARTIFICIAL (fco) = 1; + /* Give the object parameter a different name. */ + DECL_NAME (DECL_ARGUMENTS (fco)) = get_identifier ("__closure"); + } finish_member_declaration (fco); obstack_free (&declarator_obstack, p); + + return (fco != error_mark_node); } } @@ -7916,8 +8369,15 @@ static void cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) { bool nested = (current_function_decl != NULL_TREE); + bool local_variables_forbidden_p = parser->local_variables_forbidden_p; if (nested) push_function_context (); + else + /* Still increment function_depth so that we don't GC in the + middle of an expression. */ + ++function_depth; + /* Clear this in case we're in the middle of a default argument. */ + parser->local_variables_forbidden_p = false; /* Finish the function call operator - class_specifier @@ -7928,6 +8388,8 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) tree fco = lambda_function (lambda_expr); tree body; bool done = false; + tree compound_stmt; + tree cap; /* Let the front end know that we are going to be defining this function. */ @@ -7938,6 +8400,16 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) start_lambda_scope (fco); body = begin_function_body (); + if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE)) + goto out; + + /* Push the proxies for any explicit captures. */ + for (cap = LAMBDA_EXPR_CAPTURE_LIST (lambda_expr); cap; + cap = TREE_CHAIN (cap)) + build_capture_proxy (TREE_PURPOSE (cap)); + + compound_stmt = begin_compound_stmt (0); + /* 5.1.1.4 of the standard says: If a lambda-expression does not include a trailing-return-type, it is as if the trailing-return-type denotes the following type: @@ -7954,11 +8426,9 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) in the body. Since we used void as the placeholder return type, parsing the body as usual will give such desired behavior. */ if (!LAMBDA_EXPR_RETURN_TYPE (lambda_expr) - && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE) - && cp_lexer_peek_nth_token (parser->lexer, 2)->keyword == RID_RETURN - && cp_lexer_peek_nth_token (parser->lexer, 3)->type != CPP_SEMICOLON) + && cp_lexer_peek_nth_token (parser->lexer, 1)->keyword == RID_RETURN + && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_SEMICOLON) { - tree compound_stmt; tree expr = NULL_TREE; cp_id_kind idk = CP_ID_KIND_NONE; @@ -7966,7 +8436,6 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) statement. */ cp_parser_parse_tentatively (parser); - cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE); cp_parser_require_keyword (parser, RID_RETURN, RT_RETURN); expr = cp_parser_expression (parser, /*cast_p=*/false, &idk); @@ -7978,10 +8447,8 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) { apply_lambda_return_type (lambda_expr, lambda_return_type (expr)); - compound_stmt = begin_compound_stmt (0); /* Will get error here if type not deduced yet. */ finish_return_stmt (expr); - finish_compound_stmt (compound_stmt); done = true; } @@ -7991,12 +8458,16 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) { if (!LAMBDA_EXPR_RETURN_TYPE (lambda_expr)) LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda_expr) = true; - /* TODO: does begin_compound_stmt want BCS_FN_BODY? - cp_parser_compound_stmt does not pass it. */ - cp_parser_function_body (parser); + while (cp_lexer_next_token_is_keyword (parser->lexer, RID_LABEL)) + cp_parser_label_declaration (parser); + cp_parser_statement_seq_opt (parser, NULL_TREE); + cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda_expr) = false; } + finish_compound_stmt (compound_stmt); + + out: finish_function_body (body); finish_lambda_scope (); @@ -8004,8 +8475,11 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr) expand_or_defer_fn (finish_function (/*inline*/2)); } + parser->local_variables_forbidden_p = local_variables_forbidden_p; if (nested) pop_function_context(); + else + --function_depth; } /* Statements [gram.stmt.stmt] */ @@ -8120,7 +8594,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, } /* Anything that starts with a `{' must be a compound-statement. */ else if (token->type == CPP_OPEN_BRACE) - statement = cp_parser_compound_statement (parser, NULL, false); + statement = cp_parser_compound_statement (parser, NULL, false, false); /* CPP_PRAGMA is a #pragma inside a function body, which constitutes a statement all its own. */ else if (token->type == CPP_PRAGMA) @@ -8352,13 +8826,17 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr) static tree cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr, - bool in_try) + bool in_try, bool function_body) { tree compound_stmt; /* Consume the `{'. */ if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE)) return error_mark_node; + if (DECL_DECLARED_CONSTEXPR_P (current_function_decl) + && !function_body) + pedwarn (input_location, OPT_pedantic, + "compound-statement in constexpr function"); /* Begin the compound-statement. */ compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0); /* If the next keyword is `__label__' we have a label declaration. */ @@ -8670,9 +9148,6 @@ cp_parser_condition (cp_parser* parser) if (BRACE_ENCLOSED_INITIALIZER_P (initializer)) maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS); - if (!non_constant_p) - initializer = fold_non_dependent_expr (initializer); - /* Process the initializer. */ cp_finish_decl (decl, initializer, !non_constant_p, @@ -8694,21 +9169,38 @@ cp_parser_condition (cp_parser* parser) return cp_parser_expression (parser, /*cast_p=*/false, NULL); } -/* Parses a traditional for-statement until the closing ')', not included. */ +/* Parses a for-statement or range-for-statement until the closing ')', + not included. */ static tree -cp_parser_c_for (cp_parser *parser) +cp_parser_for (cp_parser *parser) { - /* Normal for loop */ - tree stmt; - tree condition = NULL_TREE; - tree expression = NULL_TREE; + tree init, scope, decl; + bool is_range_for; /* Begin the for-statement. */ - stmt = begin_for_stmt (); + scope = begin_for_scope (&init); /* Parse the initialization. */ - cp_parser_for_init_statement (parser); + is_range_for = cp_parser_for_init_statement (parser, &decl); + + if (is_range_for) + return cp_parser_range_for (parser, scope, init, decl); + else + return cp_parser_c_for (parser, scope, init); +} + +static tree +cp_parser_c_for (cp_parser *parser, tree scope, tree init) +{ + /* Normal for loop */ + tree condition = NULL_TREE; + tree expression = NULL_TREE; + tree stmt; + + stmt = begin_for_stmt (scope, init); + /* The for-init-statement has already been parsed in + cp_parser_for_init_statement, so no work is needed here. */ finish_for_init_stmt (stmt); /* If there's a condition, process it. */ @@ -8729,60 +9221,18 @@ cp_parser_c_for (cp_parser *parser) /* Tries to parse a range-based for-statement: range-based-for: - type-specifier-seq declarator : expression - - If succesful, assigns to *DECL the DECLARATOR and to *EXPR the - expression. Note that the *DECL is returned unfinished, so - later you should call cp_finish_decl(). + decl-specifier-seq declarator : expression - Returns TRUE iff a range-based for is parsed. */ + The decl-specifier-seq declarator and the `:' are already parsed by + cp_parser_for_init_statement. If processing_template_decl it returns a + newly created RANGE_FOR_STMT; if not, it is converted to a + regular FOR_STMT. */ static tree -cp_parser_range_for (cp_parser *parser) +cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl) { - tree stmt, range_decl, range_expr; - cp_decl_specifier_seq type_specifiers; - cp_declarator *declarator; - const char *saved_message; - tree attributes, pushed_scope; - bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; - - parser->colon_corrects_to_scope_p = false; - cp_parser_parse_tentatively (parser); - /* New types are not allowed in the type-specifier-seq for a - range-based for loop. */ - saved_message = parser->type_definition_forbidden_message; - parser->type_definition_forbidden_message - = G_("types may not be defined in range-based for loops"); - /* Parse the type-specifier-seq. */ - cp_parser_type_specifier_seq (parser, /*is_declaration==*/true, - /*is_trailing_return=*/false, - &type_specifiers); - /* Restore the saved message. */ - parser->type_definition_forbidden_message = saved_message; - /* If all is well, we might be looking at a declaration. */ - if (cp_parser_error_occurred (parser)) - { - cp_parser_abort_tentative_parse (parser); - stmt = NULL_TREE; - goto out; - } - /* Parse the declarator. */ - declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, - /*ctor_dtor_or_conv_p=*/NULL, - /*parenthesized_p=*/NULL, - /*member_p=*/false); - /* Parse the attributes. */ - attributes = cp_parser_attributes_opt (parser); - /* The next token should be `:'. */ - if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)) - cp_parser_simulate_error (parser); - - /* Check if it is a range-based for */ - if (!cp_parser_parse_definitely (parser)) - return NULL_TREE; + tree stmt, range_expr; - cp_parser_require (parser, CPP_COLON, RT_COLON); if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) { bool expr_non_constant_p; @@ -8791,32 +9241,71 @@ cp_parser_range_for (cp_parser *parser) else range_expr = cp_parser_expression (parser, /*cast_p=*/false, NULL); - /* If in template, STMT is converted to a normal for-statements + /* If in template, STMT is converted to a normal for-statement at instantiation. If not, it is done just ahead. */ if (processing_template_decl) - stmt = begin_range_for_stmt (); - else - stmt = begin_for_stmt (); - - /* Create the declaration. It must be after begin{,_range}_for_stmt(). */ - range_decl = start_decl (declarator, &type_specifiers, - /*initialized_p=*/SD_INITIALIZED, - attributes, /*prefix_attributes=*/NULL_TREE, - &pushed_scope); - /* No scope allowed here */ - pop_scope (pushed_scope); - - if (TREE_CODE (stmt) == RANGE_FOR_STMT) - finish_range_for_decl (stmt, range_decl, range_expr); + { + stmt = begin_range_for_stmt (scope, init); + finish_range_for_decl (stmt, range_decl, range_expr); + if (!type_dependent_expression_p (range_expr) + /* do_auto_deduction doesn't mess with template init-lists. */ + && !BRACE_ENCLOSED_INITIALIZER_P (range_expr)) + do_range_for_auto_deduction (range_decl, range_expr); + } else - /* Convert the range-based for loop into a normal for-statement. */ - stmt = cp_convert_range_for (stmt, range_decl, range_expr); - - out: - parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; + { + stmt = begin_for_stmt (scope, init); + stmt = cp_convert_range_for (stmt, range_decl, range_expr); + } return stmt; } +/* Subroutine of cp_convert_range_for: given the initializer expression, + builds up the range temporary. */ + +static tree +build_range_temp (tree range_expr) +{ + tree range_type, range_temp; + + /* Find out the type deduced by the declaration + `auto &&__range = range_expr'. */ + range_type = cp_build_reference_type (make_auto (), true); + range_type = do_auto_deduction (range_type, range_expr, + type_uses_auto (range_type)); + + /* Create the __range variable. */ + range_temp = build_decl (input_location, VAR_DECL, + get_identifier ("__for_range"), range_type); + TREE_USED (range_temp) = 1; + DECL_ARTIFICIAL (range_temp) = 1; + + return range_temp; +} + +/* Used by cp_parser_range_for in template context: we aren't going to + do a full conversion yet, but we still need to resolve auto in the + type of the for-range-declaration if present. This is basically + a shortcut version of cp_convert_range_for. */ + +static void +do_range_for_auto_deduction (tree decl, tree range_expr) +{ + tree auto_node = type_uses_auto (TREE_TYPE (decl)); + if (auto_node) + { + tree begin_dummy, end_dummy, range_temp, iter_type, iter_decl; + range_temp = convert_from_reference (build_range_temp (range_expr)); + iter_type = (cp_parser_perform_range_for_lookup + (range_temp, &begin_dummy, &end_dummy)); + iter_decl = build_decl (input_location, VAR_DECL, NULL_TREE, iter_type); + iter_decl = build_x_indirect_ref (iter_decl, RO_NULL, + tf_warning_or_error); + TREE_TYPE (decl) = do_auto_deduction (TREE_TYPE (decl), + iter_decl, auto_node); + } +} + /* Converts a range-based for-statement into a normal for-statement, as per the definition. @@ -8837,83 +9326,46 @@ cp_parser_range_for (cp_parser *parser) } If RANGE_EXPR is an array: - BEGIN_EXPR = __range - END_EXPR = __range + ARRAY_SIZE(__range) + BEGIN_EXPR = __range + END_EXPR = __range + ARRAY_SIZE(__range) + Else if RANGE_EXPR has a member 'begin' or 'end': + BEGIN_EXPR = __range.begin() + END_EXPR = __range.end() Else: BEGIN_EXPR = begin(__range) END_EXPR = end(__range); - When calling begin()/end() we must use argument dependent - lookup, but always considering 'std' as an associated namespace. */ + If __range has a member 'begin' but not 'end', or vice versa, we must + still use the second alternative (it will surely fail, however). + When calling begin()/end() in the third alternative we must use + argument dependent lookup, but always considering 'std' as an associated + namespace. */ tree cp_convert_range_for (tree statement, tree range_decl, tree range_expr) { - tree range_type, range_temp; tree begin, end; tree iter_type, begin_expr, end_expr; tree condition, expression; - /* Find out the type deduced by the declaration - * `auto &&__range = range_expr' */ - range_type = cp_build_reference_type (make_auto (), true); - range_type = do_auto_deduction (range_type, range_expr, - type_uses_auto (range_type)); - - /* Create the __range variable */ - range_temp = build_decl (input_location, VAR_DECL, - get_identifier ("__for_range"), range_type); - TREE_USED (range_temp) = 1; - DECL_ARTIFICIAL (range_temp) = 1; - pushdecl (range_temp); - cp_finish_decl (range_temp, range_expr, - /*is_constant_init*/false, NULL_TREE, - LOOKUP_ONLYCONVERTING); - - range_temp = convert_from_reference (range_temp); - - if (TREE_CODE (TREE_TYPE (range_temp)) == ARRAY_TYPE) - { - /* If RANGE_TEMP is an array we will use pointer arithmetic */ - iter_type = build_pointer_type (TREE_TYPE (TREE_TYPE (range_temp))); - begin_expr = range_temp; - end_expr - = build_binary_op (input_location, PLUS_EXPR, - range_temp, - array_type_nelts_top (TREE_TYPE (range_temp)), 0); - } + if (range_decl == error_mark_node || range_expr == error_mark_node) + /* If an error happened previously do nothing or else a lot of + unhelpful errors would be issued. */ + begin_expr = end_expr = iter_type = error_mark_node; else { - /* If it is not an array, we must call begin(__range)/end__range() */ - VEC(tree,gc) *vec; - - begin_expr = get_identifier ("begin"); - vec = make_tree_vector (); - VEC_safe_push (tree, gc, vec, range_temp); - begin_expr = perform_koenig_lookup (begin_expr, vec, - /*include_std=*/true); - begin_expr = finish_call_expr (begin_expr, &vec, false, true, - tf_warning_or_error); - release_tree_vector (vec); - - end_expr = get_identifier ("end"); - vec = make_tree_vector (); - VEC_safe_push (tree, gc, vec, range_temp); - end_expr = perform_koenig_lookup (end_expr, vec, - /*include_std=*/true); - end_expr = finish_call_expr (end_expr, &vec, false, true, - tf_warning_or_error); - release_tree_vector (vec); + tree range_temp = build_range_temp (range_expr); + pushdecl (range_temp); + cp_finish_decl (range_temp, range_expr, + /*is_constant_init*/false, NULL_TREE, + LOOKUP_ONLYCONVERTING); - /* The unqualified type of the __begin and __end temporaries should - * be the same as required by the multiple auto declaration */ - iter_type = cv_unqualified (TREE_TYPE (begin_expr)); - if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (end_expr)))) - error ("inconsistent begin/end types in range-based for: %qT and %qT", - TREE_TYPE (begin_expr), TREE_TYPE (end_expr)); + range_temp = convert_from_reference (range_temp); + iter_type = cp_parser_perform_range_for_lookup (range_temp, + &begin_expr, &end_expr); } - /* The new for initialization statement */ + /* The new for initialization statement. */ begin = build_decl (input_location, VAR_DECL, get_identifier ("__for_begin"), iter_type); TREE_USED (begin) = 1; @@ -8934,18 +9386,18 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr) finish_for_init_stmt (statement); -/* The new for condition */ + /* The new for condition. */ condition = build_x_binary_op (NE_EXPR, begin, ERROR_MARK, end, ERROR_MARK, NULL, tf_warning_or_error); finish_for_cond (condition, statement); - /* The new increment expression */ + /* The new increment expression. */ expression = finish_unary_op_expr (PREINCREMENT_EXPR, begin); finish_for_expr (expression, statement); - /* The declaration is initialized with *__begin inside the loop body */ + /* The declaration is initialized with *__begin inside the loop body. */ cp_finish_decl (range_decl, build_x_indirect_ref (begin, RO_NULL, tf_warning_or_error), /*is_constant_init*/false, NULL_TREE, @@ -8954,6 +9406,132 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr) return statement; } +/* Solves BEGIN_EXPR and END_EXPR as described in cp_convert_range_for. + We need to solve both at the same time because the method used + depends on the existence of members begin or end. + Returns the type deduced for the iterator expression. */ + +static tree +cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end) +{ + if (error_operand_p (range)) + { + *begin = *end = error_mark_node; + return error_mark_node; + } + + if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (range)))) + { + error ("range-based % expression of type %qT " + "has incomplete type", TREE_TYPE (range)); + *begin = *end = error_mark_node; + return error_mark_node; + } + if (TREE_CODE (TREE_TYPE (range)) == ARRAY_TYPE) + { + /* If RANGE is an array, we will use pointer arithmetic. */ + *begin = range; + *end = build_binary_op (input_location, PLUS_EXPR, + range, + array_type_nelts_top (TREE_TYPE (range)), + 0); + return build_pointer_type (TREE_TYPE (TREE_TYPE (range))); + } + else + { + /* If it is not an array, we must do a bit of magic. */ + tree id_begin, id_end; + tree member_begin, member_end; + + *begin = *end = error_mark_node; + + id_begin = get_identifier ("begin"); + id_end = get_identifier ("end"); + member_begin = lookup_member (TREE_TYPE (range), id_begin, + /*protect=*/2, /*want_type=*/false); + member_end = lookup_member (TREE_TYPE (range), id_end, + /*protect=*/2, /*want_type=*/false); + + if (member_begin != NULL_TREE || member_end != NULL_TREE) + { + /* Use the member functions. */ + if (member_begin != NULL_TREE) + *begin = cp_parser_range_for_member_function (range, id_begin); + else + error ("range-based % expression of type %qT has an " + "% member but not a %", TREE_TYPE (range)); + + if (member_end != NULL_TREE) + *end = cp_parser_range_for_member_function (range, id_end); + else + error ("range-based % expression of type %qT has a " + "% member but not an %", TREE_TYPE (range)); + } + else + { + /* Use global functions with ADL. */ + VEC(tree,gc) *vec; + vec = make_tree_vector (); + + VEC_safe_push (tree, gc, vec, range); + + member_begin = perform_koenig_lookup (id_begin, vec, + /*include_std=*/true, + tf_warning_or_error); + *begin = finish_call_expr (member_begin, &vec, false, true, + tf_warning_or_error); + member_end = perform_koenig_lookup (id_end, vec, + /*include_std=*/true, + tf_warning_or_error); + *end = finish_call_expr (member_end, &vec, false, true, + tf_warning_or_error); + + release_tree_vector (vec); + } + + /* Last common checks. */ + if (*begin == error_mark_node || *end == error_mark_node) + { + /* If one of the expressions is an error do no more checks. */ + *begin = *end = error_mark_node; + return error_mark_node; + } + else + { + tree iter_type = cv_unqualified (TREE_TYPE (*begin)); + /* The unqualified type of the __begin and __end temporaries should + be the same, as required by the multiple auto declaration. */ + if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (*end)))) + error ("inconsistent begin/end types in range-based % " + "statement: %qT and %qT", + TREE_TYPE (*begin), TREE_TYPE (*end)); + return iter_type; + } + } +} + +/* Helper function for cp_parser_perform_range_for_lookup. + Builds a tree for RANGE.IDENTIFIER(). */ + +static tree +cp_parser_range_for_member_function (tree range, tree identifier) +{ + tree member, res; + VEC(tree,gc) *vec; + + member = finish_class_member_access_expr (range, identifier, + false, tf_warning_or_error); + if (member == error_mark_node) + return error_mark_node; + + vec = make_tree_vector (); + res = finish_call_expr (member, &vec, + /*disallow_virtual=*/false, + /*koenig_p=*/false, + tf_warning_or_error); + release_tree_vector (vec); + return res; +} /* Parse an iteration-statement. @@ -9039,12 +9617,7 @@ cp_parser_iteration_statement (cp_parser* parser) /* Look for the `('. */ cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); - if (cxx_dialect == cxx0x) - statement = cp_parser_range_for (parser); - else - statement = NULL_TREE; - if (statement == NULL_TREE) - statement = cp_parser_c_for (parser); + statement = cp_parser_for (parser); /* Look for the `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); @@ -9068,14 +9641,15 @@ cp_parser_iteration_statement (cp_parser* parser) return statement; } -/* Parse a for-init-statement. +/* Parse a for-init-statement or the declarator of a range-based-for. + Returns true if a range-based-for declaration is seen. for-init-statement: expression-statement simple-declaration */ -static void -cp_parser_for_init_statement (cp_parser* parser) +static bool +cp_parser_for_init_statement (cp_parser* parser, tree *decl) { /* If the next token is a `;', then we have an empty expression-statement. Grammatically, this is also a @@ -9085,19 +9659,45 @@ cp_parser_for_init_statement (cp_parser* parser) declaration. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) { + bool is_range_for = false; + bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; + + parser->colon_corrects_to_scope_p = false; + /* We're going to speculatively look for a declaration, falling back to an expression, if necessary. */ cp_parser_parse_tentatively (parser); /* Parse the declaration. */ cp_parser_simple_declaration (parser, - /*function_definition_allowed_p=*/false); + /*function_definition_allowed_p=*/false, + decl); + parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; + if (cp_lexer_next_token_is (parser->lexer, CPP_COLON)) + { + /* It is a range-for, consume the ':' */ + cp_lexer_consume_token (parser->lexer); + is_range_for = true; + if (cxx_dialect < cxx0x) + { + error_at (cp_lexer_peek_token (parser->lexer)->location, + "range-based % loops are not allowed " + "in C++98 mode"); + *decl = error_mark_node; + } + } + else + /* The ';' is not consumed yet because we told + cp_parser_simple_declaration not to. */ + cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); + + if (cp_parser_parse_definitely (parser)) + return is_range_for; /* If the tentative parse failed, then we shall need to look for an expression-statement. */ - if (cp_parser_parse_definitely (parser)) - return; } - + /* If we are here, it is an expression-statement. */ cp_parser_expression_statement (parser, NULL_TREE); + return false; } /* Parse a jump-statement. @@ -9278,7 +9878,7 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p) } /* if a compound is opened, we simply parse the statement directly. */ else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) - statement = cp_parser_compound_statement (parser, NULL, false); + statement = cp_parser_compound_statement (parser, NULL, false, false); /* If the token is not a `{', then we must take special action. */ else { @@ -9432,7 +10032,7 @@ cp_parser_declaration (cp_parser* parser) /* If the next token is `extern' and the following token is a string literal, then we have a linkage specification. */ if (token1.keyword == RID_EXTERN - && cp_parser_is_string_literal (&token2)) + && cp_parser_is_pure_string_literal (&token2)) cp_parser_linkage_specification (parser); /* If the next token is `template', then we have either a template declaration, an explicit instantiation, or an explicit @@ -9584,7 +10184,8 @@ cp_parser_block_declaration (cp_parser *parser, cp_parser_static_assert (parser, /*member_p=*/false); /* Anything else must be a simple-declaration. */ else - cp_parser_simple_declaration (parser, !statement_p); + cp_parser_simple_declaration (parser, !statement_p, + /*maybe_range_for_decl*/NULL); } /* Parse a simple-declaration. @@ -9597,16 +10198,25 @@ cp_parser_block_declaration (cp_parser *parser, init-declarator-list , init-declarator If FUNCTION_DEFINITION_ALLOWED_P is TRUE, then we also recognize a - function-definition as a simple-declaration. */ + function-definition as a simple-declaration. + + If MAYBE_RANGE_FOR_DECL is not NULL, the pointed tree will be set to the + parsed declaration if it is an uninitialized single declarator not followed + by a `;', or to error_mark_node otherwise. Either way, the trailing `;', + if present, will not be consumed. */ static void cp_parser_simple_declaration (cp_parser* parser, - bool function_definition_allowed_p) + bool function_definition_allowed_p, + tree *maybe_range_for_decl) { cp_decl_specifier_seq decl_specifiers; int declares_class_or_enum; bool saw_declarator; + if (maybe_range_for_decl) + *maybe_range_for_decl = NULL_TREE; + /* 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. */ @@ -9681,6 +10291,8 @@ cp_parser_simple_declaration (cp_parser* parser, token = cp_lexer_peek_token (parser->lexer); gcc_assert (token->type == CPP_COMMA); cp_lexer_consume_token (parser->lexer); + if (maybe_range_for_decl) + *maybe_range_for_decl = error_mark_node; } else saw_declarator = true; @@ -9691,7 +10303,8 @@ cp_parser_simple_declaration (cp_parser* parser, function_definition_allowed_p, /*member_p=*/false, declares_class_or_enum, - &function_definition_p); + &function_definition_p, + maybe_range_for_decl); /* 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 @@ -9721,13 +10334,15 @@ cp_parser_simple_declaration (cp_parser* parser, return; } } + if (maybe_range_for_decl && *maybe_range_for_decl == NULL_TREE) + *maybe_range_for_decl = decl; /* The next token should be either a `,' or a `;'. */ token = cp_lexer_peek_token (parser->lexer); /* If it's a `,', there are more declarators to come. */ if (token->type == CPP_COMMA) /* will be consumed next time around */; /* If it's a `;', we are done. */ - else if (token->type == CPP_SEMICOLON) + else if (token->type == CPP_SEMICOLON || maybe_range_for_decl) break; /* Anything else is an error. */ else @@ -9765,7 +10380,8 @@ cp_parser_simple_declaration (cp_parser* parser, } /* Consume the `;'. */ - cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); + if (!maybe_range_for_decl) + cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); done: pop_deferring_access_checks (); @@ -9912,7 +10528,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser, /* Complain about `auto' as a storage specifier, if we're complaining about C++0x compatibility. */ warning_at (token->location, OPT_Wc__0x_compat, "%" - " will change meaning in C++0x; please remove it"); + " changes meaning in C++11; please remove it"); /* Set the storage class anyway. */ cp_parser_set_storage_class (parser, decl_specs, RID_AUTO, @@ -10200,6 +10816,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) tree message; cp_token *token; location_t saved_loc; + bool dummy; /* Peek at the `static_assert' token so we can keep track of exactly where the static assertion started. */ @@ -10219,11 +10836,12 @@ cp_parser_static_assert(cp_parser *parser, bool member_p) /* Parse the `(' starting the static assertion condition. */ cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); - /* Parse the constant-expression. */ + /* Parse the constant-expression. Allow a non-constant expression + here in order to give better diagnostics in finish_static_assert. */ condition = cp_parser_constant_expression (parser, - /*allow_non_constant_p=*/false, - /*non_constant_p=*/NULL); + /*allow_non_constant_p=*/true, + /*non_constant_p=*/&dummy); /* Parse the separating `,'. */ cp_parser_require (parser, CPP_COMMA, RT_COMMA); @@ -10262,6 +10880,14 @@ cp_parser_decltype (cp_parser *parser) bool saved_integral_constant_expression_p; bool saved_non_integral_constant_expression_p; cp_token *id_expr_start_token; + cp_token *start_token = cp_lexer_peek_token (parser->lexer); + + if (start_token->type == CPP_DECLTYPE) + { + /* Already parsed. */ + cp_lexer_consume_token (parser->lexer); + return start_token->u.value; + } /* Look for the `decltype' token. */ if (!cp_parser_require_keyword (parser, RID_DECLTYPE, RT_DECLTYPE)) @@ -10415,14 +11041,6 @@ cp_parser_decltype (cp_parser *parser) parser->non_integral_constant_expression_p = saved_non_integral_constant_expression_p; - if (expr == error_mark_node) - { - /* Skip everything up to the closing `)'. */ - cp_parser_skip_to_closing_parenthesis (parser, true, false, - /*consume_paren=*/true); - return error_mark_node; - } - /* Parse to the closing `)'. */ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) { @@ -10431,7 +11049,17 @@ cp_parser_decltype (cp_parser *parser) return error_mark_node; } - return finish_decltype_type (expr, id_expression_or_member_access_p); + expr = finish_decltype_type (expr, id_expression_or_member_access_p, + tf_warning_or_error); + + /* Replace the decltype with a CPP_DECLTYPE so we don't need to parse + it again. */ + start_token->type = CPP_DECLTYPE; + start_token->u.value = expr; + start_token->keyword = RID_MAX; + cp_lexer_purge_tokens_after (parser->lexer, start_token); + + return expr; } /* Special member functions [gram.special] */ @@ -10835,6 +11463,22 @@ cp_parser_operator_function_id (cp_parser* parser) return cp_parser_operator (parser); } +/* Return an identifier node for a user-defined literal operator. + The suffix identifier is chained to the operator name identifier. */ + +static tree +cp_literal_operator_id (const char* name) +{ + tree identifier; + char *buffer = XNEWVEC (char, strlen (UDLIT_OP_ANSI_PREFIX) + + strlen (name) + 10); + sprintf (buffer, UDLIT_OP_ANSI_FORMAT, name); + identifier = get_identifier (buffer); + /*IDENTIFIER_UDLIT_OPNAME_P (identifier) = 1; If we get a flag someday. */ + + return identifier; +} + /* Parse an operator. operator: @@ -11054,6 +11698,37 @@ cp_parser_operator (cp_parser* parser) cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); return ansi_opname (ARRAY_REF); + case CPP_STRING: + if (cxx_dialect == cxx98) + maybe_warn_cpp0x (CPP0X_USER_DEFINED_LITERALS); + if (TREE_STRING_LENGTH (token->u.value) > 2) + { + error ("expected empty string after % keyword"); + return error_mark_node; + } + /* Consume the string. */ + cp_lexer_consume_token (parser->lexer); + /* Look for the suffix identifier. */ + token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_NAME) + { + id = cp_parser_identifier (parser); + if (id != error_mark_node) + { + const char *name = IDENTIFIER_POINTER (id); + return cp_literal_operator_id (name); + } + } + else + { + error ("expected suffix identifier"); + return error_mark_node; + } + + case CPP_STRING_USERDEF: + error ("missing space between %<\"\"%> and suffix identifier"); + return error_mark_node; + default: /* Anything else is an error. */ break; @@ -11285,9 +11960,7 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type, user may try to do so, so we'll parse them and give an appropriate diagnostic here. */ - /* Consume the `='. */ cp_token *start_token = cp_lexer_peek_token (parser->lexer); - cp_lexer_consume_token (parser->lexer); /* Find the name of the parameter pack. */ id_declarator = parameter_declarator->declarator; @@ -11952,6 +12625,7 @@ cp_parser_template_argument_list (cp_parser* parser) parser->integral_constant_expression_p = false; saved_non_ice_p = parser->non_integral_constant_expression_p; parser->non_integral_constant_expression_p = false; + /* Parse the arguments. */ do { @@ -12279,6 +12953,8 @@ cp_parser_explicit_instantiation (cp_parser* parser) cp_decl_specifier_seq decl_specifiers; tree extension_specifier = NULL_TREE; + timevar_push (TV_TEMPLATE_INST); + /* Look for an (optional) storage-class-specifier or function-specifier. */ if (cp_parser_allow_gnu_extensions_p (parser)) @@ -12362,6 +13038,8 @@ cp_parser_explicit_instantiation (cp_parser* parser) end_explicit_instantiation (); cp_parser_consume_semicolon_at_end_of_statement (parser); + + timevar_pop (TV_TEMPLATE_INST); } /* Parse an explicit-specialization. @@ -12515,7 +13193,7 @@ cp_parser_type_specifier (cp_parser* parser, cp_parser_set_decl_spec_type (decl_specs, type_spec, token->location, - /*user_defined_p=*/true); + /*type_definition_p=*/true); return type_spec; } else @@ -12544,7 +13222,7 @@ cp_parser_type_specifier (cp_parser* parser, cp_parser_set_decl_spec_type (decl_specs, type_spec, token->location, - /*user_defined_p=*/true); + /*type_definition_p=*/true); return type_spec; } @@ -12566,7 +13244,7 @@ cp_parser_type_specifier (cp_parser* parser, cp_parser_set_decl_spec_type (decl_specs, type_spec, token->location, - /*user_defined_p=*/true); + /*type_definition_p=*/false); return type_spec; case RID_CONST: @@ -12648,6 +13326,7 @@ cp_parser_type_specifier (cp_parser* parser, decltype ( expression ) char16_t char32_t + __underlying_type ( type-id ) GNU Extension: @@ -12738,15 +13417,13 @@ cp_parser_simple_type_specifier (cp_parser* parser, break; case RID_DECLTYPE: - /* Parse the `decltype' type. */ - type = cp_parser_decltype (parser); - - if (decl_specs) - cp_parser_set_decl_spec_type (decl_specs, type, - token->location, - /*user_defined_p=*/true); - - return type; + /* Since DR 743, decltype can either be a simple-type-specifier by + itself or begin a nested-name-specifier. Parsing it will replace + it with a CPP_DECLTYPE, so just rewind and let the CPP_DECLTYPE + handling below decide what to do. */ + cp_parser_decltype (parser); + cp_lexer_set_token_position (parser->lexer, token); + break; case RID_TYPEOF: /* Consume the `typeof' token. */ @@ -12760,14 +13437,45 @@ cp_parser_simple_type_specifier (cp_parser* parser, if (decl_specs) cp_parser_set_decl_spec_type (decl_specs, type, token->location, - /*user_defined_p=*/true); + /*type_definition_p=*/false); + + return type; + + case RID_UNDERLYING_TYPE: + type = cp_parser_trait_expr (parser, RID_UNDERLYING_TYPE); + if (decl_specs) + cp_parser_set_decl_spec_type (decl_specs, type, + token->location, + /*type_definition_p=*/false); return type; + case RID_BASES: + case RID_DIRECT_BASES: + type = cp_parser_trait_expr (parser, token->keyword); + if (decl_specs) + cp_parser_set_decl_spec_type (decl_specs, type, + token->location, + /*type_definition_p=*/false); + return type; default: break; } + /* If token is an already-parsed decltype not followed by ::, + it's a simple-type-specifier. */ + if (token->type == CPP_DECLTYPE + && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_SCOPE) + { + type = token->u.value; + if (decl_specs) + cp_parser_set_decl_spec_type (decl_specs, type, + token->location, + /*type_definition_p=*/false); + cp_lexer_consume_token (parser->lexer); + return type; + } + /* If the type-specifier was for a built-in type, we're done. */ if (type) { @@ -12780,7 +13488,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_set_decl_spec_type (decl_specs, type, token->location, - /*user_defined=*/false); + /*type_definition_p=*/false); if (decl_specs) decl_specs->any_specifiers_p = true; @@ -12855,7 +13563,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, if (type && decl_specs) cp_parser_set_decl_spec_type (decl_specs, type, token->location, - /*user_defined=*/true); + /*type_definition_p=*/false); } /* If we didn't get a type-name, issue an error message. */ @@ -13331,7 +14039,13 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, } if (tag_type != enum_type) - cp_parser_check_class_key (tag_type, type); + { + /* Indicate whether this class was declared as a `class' or as a + `struct'. */ + if (TREE_CODE (type) == RECORD_TYPE) + CLASSTYPE_DECLARED_CLASS (type) = (tag_type == class_type); + cp_parser_check_class_key (tag_type, type); + } /* A "<" cannot follow an elaborated type specifier. If that happens, the user was probably trying to form a template-id. */ @@ -13562,6 +14276,7 @@ cp_parser_enum_specifier (cp_parser* parser) elaborated-type-specifier. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) { + timevar_push (TV_PARSE_ENUM); if (nested_name_specifier) { /* The following catches invalid code such as: @@ -13623,6 +14338,7 @@ cp_parser_enum_specifier (cp_parser* parser) if (scoped_enum_p) finish_scope (); + timevar_pop (TV_PARSE_ENUM); } else { @@ -13751,6 +14467,10 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type) if (check_for_bare_parameter_packs (value)) value = error_mark_node; + /* integral_constant_value will pull out this expression, so make sure + it's folded as appropriate. */ + value = fold_non_dependent_expr (value); + /* Create the enumerator. */ build_enumerator (identifier, value, type, loc); } @@ -14378,7 +15098,13 @@ cp_parser_asm_definition (cp_parser* parser) have been completely parsed. FUNCTION_DEFINITION_P may be NULL if FUNCTION_DEFINITION_ALLOWED_P - is FALSE. */ + is FALSE. + + If MAYBE_RANGE_FOR_DECL is not NULL, the pointed tree will be set to the + parsed declaration if it is an uninitialized single declarator not followed + by a `;', or to error_mark_node otherwise. Either way, the trailing `;', + if present, will not be consumed. If returned, this declarator will be + created with SD_INITIALIZED but will not call cp_finish_decl. */ static tree cp_parser_init_declarator (cp_parser* parser, @@ -14387,7 +15113,8 @@ cp_parser_init_declarator (cp_parser* parser, bool function_definition_allowed_p, bool member_p, int declares_class_or_enum, - bool* function_definition_p) + bool* function_definition_p, + tree* maybe_range_for_decl) { cp_token *token = NULL, *asm_spec_start_token = NULL, *attributes_start_token = NULL; @@ -14407,7 +15134,8 @@ cp_parser_init_declarator (cp_parser* parser, bool is_non_constant_init; int ctor_dtor_or_conv_p; bool friend_p; - tree pushed_scope = NULL; + tree pushed_scope = NULL_TREE; + bool range_for_decl_p = false; /* Gather the attributes that were provided with the decl-specifiers. */ @@ -14429,7 +15157,7 @@ cp_parser_init_declarator (cp_parser* parser, = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, &ctor_dtor_or_conv_p, /*parenthesized_p=*/NULL, - /*member_p=*/false); + member_p); /* Gather up the deferred checks. */ stop_deferring_access_checks (); @@ -14551,6 +15279,8 @@ cp_parser_init_declarator (cp_parser* parser, { is_initialized = SD_INITIALIZED; initialization_kind = token->type; + if (maybe_range_for_decl) + *maybe_range_for_decl = error_mark_node; if (token->type == CPP_EQ && function_declarator_p (declarator)) @@ -14569,8 +15299,13 @@ cp_parser_init_declarator (cp_parser* parser, if (token->type != CPP_COMMA && token->type != CPP_SEMICOLON) { - cp_parser_error (parser, "expected initializer"); - return error_mark_node; + if (maybe_range_for_decl && *maybe_range_for_decl != error_mark_node) + range_for_decl_p = true; + else + { + cp_parser_error (parser, "expected initializer"); + return error_mark_node; + } } is_initialized = SD_UNINITIALIZED; initialization_kind = CPP_EOF; @@ -14603,7 +15338,8 @@ cp_parser_init_declarator (cp_parser* parser, if (parser->in_unbraced_linkage_specification_p) decl_specifiers->storage_class = sc_extern; decl = start_decl (declarator, decl_specifiers, - is_initialized, attributes, prefix_attributes, + range_for_decl_p? SD_INITIALIZED : is_initialized, + attributes, prefix_attributes, &pushed_scope); /* Adjust location of decl if declarator->id_loc is more appropriate: set, and decl wasn't merged with another decl, in which case its @@ -14705,7 +15441,7 @@ cp_parser_init_declarator (cp_parser* parser, if (pushed_scope) { pop_scope (pushed_scope); - pushed_scope = false; + pushed_scope = NULL_TREE; } decl = grokfield (declarator, decl_specifiers, initializer, !is_non_constant_init, @@ -14715,9 +15451,9 @@ cp_parser_init_declarator (cp_parser* parser, cp_parser_save_default_args (parser, decl); } - /* Finish processing the declaration. But, skip friend + /* Finish processing the declaration. But, skip member declarations. */ - if (!friend_p && decl && decl != error_mark_node) + if (!member_p && decl && decl != error_mark_node && !range_for_decl_p) { cp_finish_decl (decl, initializer, !is_non_constant_init, @@ -14978,11 +15714,15 @@ cp_parser_direct_declarator (cp_parser* parser, parser->num_template_parameter_lists = saved_num_template_parameter_lists; + /* Consume the `)'. */ + cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + /* If all went well, parse the cv-qualifier-seq and the exception-specification. */ if (member_p || cp_parser_parse_definitely (parser)) { cp_cv_quals cv_quals; + cp_virt_specifiers virt_specifiers; tree exception_specification; tree late_return; @@ -14991,22 +15731,23 @@ cp_parser_direct_declarator (cp_parser* parser, if (ctor_dtor_or_conv_p) *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0; first = false; - /* Consume the `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); /* Parse the cv-qualifier-seq. */ cv_quals = cp_parser_cv_qualifier_seq_opt (parser); /* And the exception-specification. */ exception_specification = cp_parser_exception_specification_opt (parser); + /* Parse the virt-specifier-seq. */ + virt_specifiers = cp_parser_virt_specifier_seq_opt (parser); - late_return - = cp_parser_late_return_type_opt (parser); + late_return = (cp_parser_late_return_type_opt + (parser, member_p ? cv_quals : -1)); /* Create the function-declarator. */ declarator = make_call_declarator (declarator, params, cv_quals, + virt_specifiers, exception_specification, late_return); /* Any subsequent parameter lists are to do with @@ -15083,7 +15824,7 @@ cp_parser_direct_declarator (cp_parser* parser, = cp_parser_constant_expression (parser, /*allow_non_constant=*/true, &non_constant_p); - if (!non_constant_p || cxx_dialect >= cxx0x) + if (!non_constant_p) /* OK */; /* Normally, the array bound must be an integral constant expression. However, as an extension, we allow VLAs @@ -15514,17 +16255,103 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser) return cv_quals; } +/* Parse an (optional) virt-specifier-seq. + + virt-specifier-seq: + virt-specifier virt-specifier-seq [opt] + + virt-specifier: + override + final + + Returns a bitmask representing the virt-specifiers. */ + +static cp_virt_specifiers +cp_parser_virt_specifier_seq_opt (cp_parser* parser) +{ + cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED; + + while (true) + { + cp_token *token; + cp_virt_specifiers virt_specifier; + + /* Peek at the next token. */ + token = cp_lexer_peek_token (parser->lexer); + /* See if it's a virt-specifier-qualifier. */ + if (token->type != CPP_NAME) + break; + if (!strcmp (IDENTIFIER_POINTER(token->u.value), "override")) + { + maybe_warn_cpp0x (CPP0X_OVERRIDE_CONTROLS); + virt_specifier = VIRT_SPEC_OVERRIDE; + } + else if (!strcmp (IDENTIFIER_POINTER(token->u.value), "final")) + { + maybe_warn_cpp0x (CPP0X_OVERRIDE_CONTROLS); + virt_specifier = VIRT_SPEC_FINAL; + } + else if (!strcmp (IDENTIFIER_POINTER(token->u.value), "__final")) + { + virt_specifier = VIRT_SPEC_FINAL; + } + else + break; + + if (virt_specifiers & virt_specifier) + { + error_at (token->location, "duplicate virt-specifier"); + cp_lexer_purge_token (parser->lexer); + } + else + { + cp_lexer_consume_token (parser->lexer); + virt_specifiers |= virt_specifier; + } + } + return virt_specifiers; +} + +/* Used by handling of trailing-return-types and NSDMI, in which 'this' + is in scope even though it isn't real. */ + +static void +inject_this_parameter (tree ctype, cp_cv_quals quals) +{ + tree this_parm; + + if (current_class_ptr) + { + /* We don't clear this between NSDMIs. Is it already what we want? */ + tree type = TREE_TYPE (TREE_TYPE (current_class_ptr)); + if (same_type_ignoring_top_level_qualifiers_p (ctype, type) + && cp_type_quals (type) == quals) + return; + } + + this_parm = build_this_parm (ctype, quals); + /* Clear this first to avoid shortcut in cp_build_indirect_ref. */ + current_class_ptr = NULL_TREE; + current_class_ref + = cp_build_indirect_ref (this_parm, RO_NULL, tf_warning_or_error); + current_class_ptr = this_parm; +} + /* Parse a late-specified return type, if any. This is not a separate non-terminal, but part of a function declarator, which looks like -> trailing-type-specifier-seq abstract-declarator(opt) - Returns the type indicated by the type-id. */ + Returns the type indicated by the type-id. + + QUALS is either a bitmask of cv_qualifiers or -1 for a non-member + function. */ static tree -cp_parser_late_return_type_opt (cp_parser* parser) +cp_parser_late_return_type_opt (cp_parser* parser, cp_cv_quals quals) { cp_token *token; + tree type; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); @@ -15535,7 +16362,19 @@ cp_parser_late_return_type_opt (cp_parser* parser) /* Consume the ->. */ cp_lexer_consume_token (parser->lexer); - return cp_parser_trailing_type_id (parser); + if (quals >= 0) + { + /* DR 1207: 'this' is in scope in the trailing return type. */ + gcc_assert (current_class_ptr == NULL_TREE); + inject_this_parameter (current_class_type, quals); + } + + type = cp_parser_trailing_type_id (parser); + + if (quals >= 0) + current_class_ptr = current_class_ref = NULL_TREE; + + return type; } /* Parse a declarator-id. @@ -15639,7 +16478,13 @@ static tree cp_parser_type_id (cp_parser *parser) static tree cp_parser_template_type_arg (cp_parser *parser) { - return cp_parser_type_id_1 (parser, true, false); + tree r; + const char *saved_message = parser->type_definition_forbidden_message; + parser->type_definition_forbidden_message + = G_("types may not be defined in template arguments"); + r = cp_parser_type_id_1 (parser, true, false); + parser->type_definition_forbidden_message = saved_message; + return r; } static tree cp_parser_trailing_type_id (cp_parser *parser) @@ -15870,7 +16715,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) { cp_parameter_declarator *parameter; tree decl = error_mark_node; - bool parenthesized_p; + bool parenthesized_p = false; /* Parse the parameter. */ parameter = cp_parser_parameter_declaration (parser, @@ -15910,6 +16755,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error) { retrofit_lang_decl (decl); DECL_PARM_INDEX (decl) = ++index; + DECL_PARM_LEVEL (decl) = function_parm_depth (); } /* Add the new parameter to the list. */ @@ -16072,6 +16918,7 @@ cp_parser_parameter_declaration (cp_parser *parser, of some object of type "char" to "int". */ && !parser->in_type_id_in_expr_p && cp_parser_uncommitted_to_tentative_parse_p (parser) + && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE) && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)) cp_parser_commit_to_tentative_parse (parser); /* Parse the declarator. */ @@ -16126,9 +16973,6 @@ cp_parser_parameter_declaration (cp_parser *parser, /* If the next token is `=', then process a default argument. */ if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)) { - /* Consume the `='. */ - cp_lexer_consume_token (parser->lexer); - /* If we are defining a class, then the tokens that make up the default argument must be saved and processed later. */ if (!template_parm_p && at_class_scope_p () @@ -16306,17 +17150,20 @@ cp_parser_parameter_declaration (cp_parser *parser, if (id_declarator && id_declarator->kind == cdk_id) error_at (declarator_token_start->location, - template_parm_p - ? "template parameter pack %qD" - " cannot have a default argument" - : "parameter pack %qD cannot have a default argument", + template_parm_p + ? G_("template parameter pack %qD " + "cannot have a default argument") + : G_("parameter pack %qD cannot have " + "a default argument"), id_declarator->u.id.unqualified_name); else error_at (declarator_token_start->location, - template_parm_p - ? "template parameter pack cannot have a default argument" - : "parameter pack cannot have a default argument"); - + template_parm_p + ? G_("template parameter pack cannot have " + "a default argument") + : G_("parameter pack cannot have a " + "default argument")); + default_argument = NULL_TREE; } } @@ -16338,6 +17185,7 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p) tree default_argument = NULL_TREE; bool saved_greater_than_is_operator_p; bool saved_local_variables_forbidden_p; + bool non_constant_p, is_direct_init; /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is set correctly. */ @@ -16351,7 +17199,9 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p) if (template_parm_p) push_deferring_access_checks (dk_no_deferred); default_argument - = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL); + = cp_parser_initializer (parser, &is_direct_init, &non_constant_p); + if (BRACE_ENCLOSED_INITIALIZER_P (default_argument)) + maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS); if (template_parm_p) pop_deferring_access_checks (); parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; @@ -16368,7 +17218,7 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p) static void cp_parser_function_body (cp_parser *parser) { - cp_parser_compound_statement (parser, NULL, false); + cp_parser_compound_statement (parser, NULL, false, true); } /* Parse a ctor-initializer-opt followed by a function-body. Return @@ -16509,16 +17359,6 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p) = cp_parser_constant_expression (parser, /*allow_non_constant_p=*/true, non_constant_p); - if (!*non_constant_p) - { - /* We only want to fold if this is really a constant - expression. FIXME Actually, we don't want to fold here, but in - cp_finish_decl. */ - tree folded = fold_non_dependent_expr (initializer); - folded = maybe_constant_value (folded); - if (TREE_CONSTANT (folded)) - initializer = folded; - } } else initializer = cp_parser_braced_list (parser, non_constant_p); @@ -16573,8 +17413,13 @@ cp_parser_braced_list (cp_parser* parser, bool* non_constant_p) GNU Extension: initializer-list: - identifier : initializer-clause - initializer-list, identifier : initializer-clause + designation initializer-clause ...[opt] + initializer-list , designation initializer-clause ...[opt] + + designation: + . identifier = + identifier : + [ constant-expression ] = Returns a VEC of constructor_elt. The VALUE of each elt is an expression for the initializer. If the INDEX of the elt is non-NULL, it is the @@ -16593,7 +17438,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) while (true) { cp_token *token; - tree identifier; + tree designator; tree initializer; bool clause_non_constant_p; @@ -16608,12 +17453,38 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) pedwarn (input_location, OPT_pedantic, "ISO C++ does not allow designated initializers"); /* Consume the identifier. */ - identifier = cp_lexer_consume_token (parser->lexer)->u.value; + designator = cp_lexer_consume_token (parser->lexer)->u.value; /* Consume the `:'. */ cp_lexer_consume_token (parser->lexer); } + /* Also handle the C99 syntax, '. id ='. */ + else if (cp_parser_allow_gnu_extensions_p (parser) + && cp_lexer_next_token_is (parser->lexer, CPP_DOT) + && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME + && cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_EQ) + { + /* Warn the user that they are using an extension. */ + pedwarn (input_location, OPT_pedantic, + "ISO C++ does not allow C99 designated initializers"); + /* Consume the `.'. */ + cp_lexer_consume_token (parser->lexer); + /* Consume the identifier. */ + designator = cp_lexer_consume_token (parser->lexer)->u.value; + /* Consume the `='. */ + cp_lexer_consume_token (parser->lexer); + } + /* Also handle C99 array designators, '[ const ] ='. */ + else if (cp_parser_allow_gnu_extensions_p (parser) + && !c_dialect_objc () + && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE)) + { + cp_lexer_consume_token (parser->lexer); + designator = cp_parser_constant_expression (parser, false, NULL); + cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); + cp_parser_require (parser, CPP_EQ, RT_EQ); + } else - identifier = NULL_TREE; + designator = NULL_TREE; /* Parse the initializer. */ initializer = cp_parser_initializer_clause (parser, @@ -16634,7 +17505,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p) } /* Add it to the vector. */ - CONSTRUCTOR_APPEND_ELT(v, identifier, initializer); + CONSTRUCTOR_APPEND_ELT (v, designator, initializer); /* If the next token is not a comma, we have reached the end of the list. */ @@ -16831,17 +17702,20 @@ cp_parser_class_name (cp_parser *parser, Returns the TREE_TYPE representing the class. */ static tree -cp_parser_class_specifier (cp_parser* parser) +cp_parser_class_specifier_1 (cp_parser* parser) { tree type; tree attributes = NULL_TREE; bool nested_name_specifier_p; unsigned saved_num_template_parameter_lists; bool saved_in_function_body; + unsigned char in_statement; + bool in_switch_statement_p; bool saved_in_unbraced_linkage_specification_p; tree old_scope = NULL_TREE; tree scope = NULL_TREE; tree bases; + cp_token *closing_brace; push_deferring_access_checks (dk_no_deferred); @@ -16890,6 +17764,12 @@ cp_parser_class_specifier (cp_parser* parser) /* We are not in a function body. */ saved_in_function_body = parser->in_function_body; parser->in_function_body = false; + /* Or in a loop. */ + in_statement = parser->in_statement; + parser->in_statement = 0; + /* Or in a switch. */ + in_switch_statement_p = parser->in_switch_statement_p; + parser->in_switch_statement_p = false; /* We are not immediately inside an extern "lang" block. */ saved_in_unbraced_linkage_specification_p = parser->in_unbraced_linkage_specification_p; @@ -16911,7 +17791,7 @@ cp_parser_class_specifier (cp_parser* parser) cp_parser_member_specification_opt (parser); /* Look for the trailing `}'. */ - cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); + closing_brace = cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); /* Look for trailing attributes to apply to this class. */ if (cp_parser_allow_gnu_extensions_p (parser)) attributes = cp_parser_attributes_opt (parser); @@ -16970,18 +17850,15 @@ cp_parser_class_specifier (cp_parser* parser) class Z { } static const var = ...; */ case CPP_KEYWORD: - if (keyword_is_storage_class_specifier (token->keyword) - || keyword_is_type_qualifier (token->keyword)) + if (keyword_is_decl_specifier (token->keyword)) { cp_token *lookahead = cp_lexer_peek_nth_token (parser->lexer, 2); - if (lookahead->type == CPP_KEYWORD - && !keyword_begins_type_specifier (lookahead->keyword)) - want_semicolon = false; - else if (lookahead->type == CPP_NAME) - /* Handling user-defined types here would be nice, but - very tricky. */ - want_semicolon = false; + /* Handling user-defined types here would be nice, but very + tricky. */ + want_semicolon + = (lookahead->type == CPP_KEYWORD + && keyword_begins_type_specifier (lookahead->keyword)); } break; default: @@ -16989,8 +17866,9 @@ cp_parser_class_specifier (cp_parser* parser) } /* If we don't have a type, then something is very wrong and we - shouldn't try to do anything clever. */ - if (TYPE_P (type) && want_semicolon) + shouldn't try to do anything clever. Likewise for not seeing the + closing brace. */ + if (closing_brace && TYPE_P (type) && want_semicolon) { cp_token_position prev = cp_lexer_previous_token_position (parser->lexer); @@ -17037,11 +17915,12 @@ cp_parser_class_specifier (cp_parser* parser) there is no need to delay the parsing of `A::B::f'. */ if (--parser->num_classes_being_defined == 0) { - tree fn; + tree decl; tree class_type = NULL_TREE; tree pushed_scope = NULL_TREE; unsigned ix; cp_default_arg_entry *e; + tree save_ccp, save_ccr; /* In a first pass, parse default arguments to the functions. Then, in a second pass, parse the bodies of the functions. @@ -17056,7 +17935,7 @@ cp_parser_class_specifier (cp_parser* parser) FOR_EACH_VEC_ELT (cp_default_arg_entry, unparsed_funs_with_default_args, ix, e) { - fn = e->decl; + decl = e->decl; /* If there are default arguments that have not yet been processed, take care of them now. */ if (class_type != e->class_type) @@ -17067,18 +17946,36 @@ cp_parser_class_specifier (cp_parser* parser) pushed_scope = push_scope (class_type); } /* Make sure that any template parameters are in scope. */ - maybe_begin_member_template_processing (fn); + maybe_begin_member_template_processing (decl); /* Parse the default argument expressions. */ - cp_parser_late_parsing_default_args (parser, fn); + cp_parser_late_parsing_default_args (parser, decl); /* Remove any template parameters from the symbol table. */ maybe_end_member_template_processing (); } + VEC_truncate (cp_default_arg_entry, unparsed_funs_with_default_args, 0); + /* Now parse any NSDMIs. */ + save_ccp = current_class_ptr; + save_ccr = current_class_ref; + FOR_EACH_VEC_ELT (tree, unparsed_nsdmis, ix, decl) + { + if (class_type != DECL_CONTEXT (decl)) + { + if (pushed_scope) + pop_scope (pushed_scope); + class_type = DECL_CONTEXT (decl); + pushed_scope = push_scope (class_type); + } + inject_this_parameter (class_type, TYPE_UNQUALIFIED); + cp_parser_late_parsing_nsdmi (parser, decl); + } + VEC_truncate (tree, unparsed_nsdmis, 0); + current_class_ptr = save_ccp; + current_class_ref = save_ccr; if (pushed_scope) pop_scope (pushed_scope); - VEC_truncate (cp_default_arg_entry, unparsed_funs_with_default_args, 0); /* Now parse the body of the functions. */ - FOR_EACH_VEC_ELT (tree, unparsed_funs_with_definitions, ix, fn) - cp_parser_late_parsing_for_member (parser, fn); + FOR_EACH_VEC_ELT (tree, unparsed_funs_with_definitions, ix, decl) + cp_parser_late_parsing_for_member (parser, decl); VEC_truncate (tree, unparsed_funs_with_definitions, 0); } @@ -17086,6 +17983,8 @@ cp_parser_class_specifier (cp_parser* parser) pop_deferring_access_checks (); /* Restore saved state. */ + parser->in_switch_statement_p = in_switch_statement_p; + parser->in_statement = in_statement; parser->in_function_body = saved_in_function_body; parser->num_template_parameter_lists = saved_num_template_parameter_lists; @@ -17095,14 +17994,27 @@ cp_parser_class_specifier (cp_parser* parser) return type; } +static tree +cp_parser_class_specifier (cp_parser* parser) +{ + tree ret; + timevar_push (TV_PARSE_STRUCT); + ret = cp_parser_class_specifier_1 (parser); + timevar_pop (TV_PARSE_STRUCT); + return ret; +} + /* Parse a class-head. class-head: class-key identifier [opt] base-clause [opt] - class-key nested-name-specifier identifier base-clause [opt] + class-key nested-name-specifier identifier class-virt-specifier [opt] base-clause [opt] class-key nested-name-specifier [opt] template-id base-clause [opt] + class-virt-specifier: + final + GNU Extensions: class-key attributes identifier [opt] base-clause [opt] class-key attributes nested-name-specifier identifier base-clause [opt] @@ -17134,6 +18046,7 @@ cp_parser_class_head (cp_parser* parser, tree id = NULL_TREE; tree type = NULL_TREE; tree attributes; + cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED; bool template_id_p = false; bool qualified_p = false; bool invalid_nested_name_p = false; @@ -17277,8 +18190,11 @@ cp_parser_class_head (cp_parser* parser, pop_deferring_access_checks (); if (id) - cp_parser_check_for_invalid_template_id (parser, id, - type_start_token->location); + { + cp_parser_check_for_invalid_template_id (parser, id, + type_start_token->location); + } + virt_specifiers = cp_parser_virt_specifier_seq_opt (parser); /* If it's not a `:' or a `{' then we can't really be looking at a class-head, since a class-head only appears as part of a @@ -17294,6 +18210,13 @@ cp_parser_class_head (cp_parser* parser, /* At this point, we're going ahead with the class-specifier, even if some other problem occurs. */ cp_parser_commit_to_tentative_parse (parser); + if (virt_specifiers & VIRT_SPEC_OVERRIDE) + { + cp_parser_error (parser, + "cannot specify % for a class"); + type = error_mark_node; + goto out; + } /* Issue the error about the overly-qualified name now. */ if (qualified_p) { @@ -17510,6 +18433,8 @@ cp_parser_class_head (cp_parser* parser, if (type) DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location; *attributes_p = attributes; + if (type && (virt_specifiers & VIRT_SPEC_FINAL)) + CLASSTYPE_FINAL (type) = 1; out: parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; return type; @@ -17750,9 +18675,10 @@ cp_parser_member_declaration (cp_parser* parser) { /* If the `friend' keyword was present, the friend must be introduced with a class-key. */ - if (!declares_class_or_enum) - error_at (decl_spec_token_start->location, - "a class-key must be used when declaring a friend"); + if (!declares_class_or_enum && cxx_dialect < cxx0x) + pedwarn (decl_spec_token_start->location, OPT_pedantic, + "in C++03 a class-key must be used " + "when declaring a friend"); /* In this case: template struct A { @@ -17761,10 +18687,12 @@ cp_parser_member_declaration (cp_parser* parser) A::B will be represented by a TYPENAME_TYPE, and therefore not recognized by check_tag_decl. */ - if (!type - && decl_specifiers.type - && TYPE_P (decl_specifiers.type)) - type = decl_specifiers.type; + if (!type) + { + type = decl_specifiers.type; + if (type && TREE_CODE (type) == TYPE_DECL) + type = TREE_TYPE (type); + } if (!type || !TYPE_P (type)) error_at (decl_spec_token_start->location, "friend declaration does not name a class or " @@ -17926,12 +18854,38 @@ cp_parser_member_declaration (cp_parser* parser) constant-initializer. When we call `grokfield', it will perform more stringent semantics checks. */ initializer_token_start = cp_lexer_peek_token (parser->lexer); - if (function_declarator_p (declarator)) + if (function_declarator_p (declarator) + || (decl_specifiers.type + && TREE_CODE (decl_specifiers.type) == TYPE_DECL + && (TREE_CODE (TREE_TYPE (decl_specifiers.type)) + == FUNCTION_TYPE))) initializer = cp_parser_pure_specifier (parser); + else if (decl_specifiers.storage_class != sc_static) + initializer = cp_parser_save_nsdmi (parser); + else if (cxx_dialect >= cxx0x) + { + bool nonconst; + /* Don't require a constant rvalue in C++11, since we + might want a reference constant. We'll enforce + constancy later. */ + cp_lexer_consume_token (parser->lexer); + /* Parse the initializer. */ + initializer = cp_parser_initializer_clause (parser, + &nonconst); + } else /* Parse the initializer. */ initializer = cp_parser_constant_initializer (parser); } + else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE) + && !function_declarator_p (declarator)) + { + bool x; + if (decl_specifiers.storage_class != sc_static) + initializer = cp_parser_save_nsdmi (parser); + else + initializer = cp_parser_initializer (parser, &x, &x); + } /* Otherwise, there is no initializer. */ else initializer = NULL_TREE; @@ -18016,6 +18970,11 @@ cp_parser_member_declaration (cp_parser* parser) if (TREE_CODE (decl) == FUNCTION_DECL) cp_parser_save_default_args (parser, decl); + else if (TREE_CODE (decl) == FIELD_DECL + && !DECL_C_BIT_FIELD (decl) + && DECL_INITIAL (decl)) + /* Add DECL to the queue of NSDMI to be parsed later. */ + VEC_safe_push (tree, gc, unparsed_nsdmis, decl); } if (assume_semicolon) @@ -18161,12 +19120,11 @@ cp_parser_base_clause (cp_parser* parser) } /* Add BASE to the front of the list. */ - if (base != error_mark_node) + if (base && base != error_mark_node) { if (pack_expansion_p) /* Make this a pack expansion type. */ TREE_VALUE (base) = make_pack_expansion (TREE_VALUE (base)); - if (!check_for_bare_parameter_packs (TREE_VALUE (base))) { @@ -18308,19 +19266,27 @@ cp_parser_base_specifier (cp_parser* parser) class_scope_p = (parser->scope && TYPE_P (parser->scope)); template_p = class_scope_p && cp_parser_optional_template_keyword (parser); - /* Finally, look for the class-name. */ - type = cp_parser_class_name (parser, - class_scope_p, - template_p, - typename_type, - /*check_dependency_p=*/true, - /*class_head_p=*/false, - /*is_declaration=*/true); + if (!parser->scope + && cp_lexer_next_token_is_decltype (parser->lexer)) + /* DR 950 allows decltype as a base-specifier. */ + type = cp_parser_decltype (parser); + else + { + /* Otherwise, look for the class-name. */ + type = cp_parser_class_name (parser, + class_scope_p, + template_p, + typename_type, + /*check_dependency_p=*/true, + /*class_head_p=*/false, + /*is_declaration=*/true); + type = TREE_TYPE (type); + } if (type == error_mark_node) return error_mark_node; - return finish_base_specifier (TREE_TYPE (type), access, virtual_p); + return finish_base_specifier (type, access, virtual_p); } /* Exception handling [gram.exception] */ @@ -18467,7 +19433,7 @@ cp_parser_try_block (cp_parser* parser) cp_parser_require_keyword (parser, RID_TRY, RT_TRY); try_block = begin_try_block (); - cp_parser_compound_statement (parser, NULL, true); + cp_parser_compound_statement (parser, NULL, true, false); finish_try_block (try_block); cp_parser_handler_seq (parser); finish_handler_sequence (try_block); @@ -18544,7 +19510,7 @@ cp_parser_handler (cp_parser* parser) declaration = cp_parser_exception_declaration (parser); finish_handler_parms (declaration, handler); cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); - cp_parser_compound_statement (parser, NULL, false); + cp_parser_compound_statement (parser, NULL, false, false); finish_handler (handler); } @@ -19310,6 +20276,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name, if (DECL_P (decl)) check_accessibility_of_qualified_id (decl, object_type, parser->scope); + maybe_record_typedef_use (decl); + return decl; } @@ -19583,7 +20551,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p) /* If we have a class scope, this is easy; DR 147 says that S::S always names the constructor, and no other qualified name could. */ if (constructor_p && nested_name_specifier - && TYPE_P (nested_name_specifier)) + && CLASS_TYPE_P (nested_name_specifier)) { tree id = cp_parser_unqualified_id (parser, /*template_keyword_p=*/false, @@ -19740,8 +20708,17 @@ cp_parser_function_definition_from_specifiers_and_declarator pop_nested_class (); } else - fn = cp_parser_function_definition_after_declarator (parser, + { + timevar_id_t tv; + if (DECL_DECLARED_INLINE_P (current_function_decl)) + tv = TV_PARSE_INLINE; + else + tv = TV_PARSE_FUNC; + timevar_push (tv); + fn = cp_parser_function_definition_after_declarator (parser, /*inline_p=*/false); + timevar_pop (tv); + } return fn; } @@ -19891,8 +20868,11 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) parameter_list = NULL_TREE; } else - /* Parse the template parameters. */ - parameter_list = cp_parser_template_parameter_list (parser); + { + /* Parse the template parameters. */ + parameter_list = cp_parser_template_parameter_list (parser); + fixup_template_parms (); + } /* Get the deferred access checks from the parameter list. These will be checked once we know what is being declared, as for a @@ -19943,6 +20923,33 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) /* Finish up. */ finish_template_decl (parameter_list); + /* Check the template arguments for a literal operator template. */ + if (decl + && (TREE_CODE (decl) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (decl)) + && UDLIT_OPER_P (DECL_NAME (decl))) + { + bool ok = true; + if (parameter_list == NULL_TREE) + ok = false; + else + { + int num_parms = TREE_VEC_LENGTH (parameter_list); + if (num_parms != 1) + ok = false; + else + { + tree parm_list = TREE_VEC_ELT (parameter_list, 0); + tree parm = INNERMOST_TEMPLATE_PARMS (parm_list); + if (TREE_TYPE (parm) != char_type_node + || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))) + ok = false; + } + } + if (!ok) + error ("literal operator template %qD has invalid parameter list." + " Expected non-type template argument pack ", + decl); + } /* Register member declarations. */ if (member_p && !friend_p && decl && !DECL_CLASS_TEMPLATE_P (decl)) finish_member_declaration (decl); @@ -20053,8 +21060,15 @@ cp_parser_single_declaration (cp_parser* parser, } /* Complain about missing 'typename' or other invalid type names. */ - if (!decl_specifiers.any_type_specifiers_p) - cp_parser_parse_and_diagnose_invalid_type_name (parser); + if (!decl_specifiers.any_type_specifiers_p + && cp_parser_parse_and_diagnose_invalid_type_name (parser)) + { + /* cp_parser_parse_and_diagnose_invalid_type_name calls + cp_parser_skip_to_end_of_block_or_statement, so don't try to parse + the rest of this declaration. */ + decl = error_mark_node; + goto out; + } /* If it's not a template class, try for a template function. If the next token is a `;', then this declaration does not declare @@ -20071,7 +21085,8 @@ cp_parser_single_declaration (cp_parser* parser, /*function_definition_allowed_p=*/true, member_p, declares_class_or_enum, - &function_definition_p); + &function_definition_p, + NULL); /* 7.1.1-1 [dcl.stc] @@ -20087,6 +21102,13 @@ cp_parser_single_declaration (cp_parser* parser, } } + /* Look for a trailing `;' after the declaration. */ + if (!function_definition_p + && (decl == error_mark_node + || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))) + cp_parser_skip_to_end_of_block_or_statement (parser); + + out: pop_deferring_access_checks (); /* Clear any current qualification; whatever comes next is the start @@ -20094,11 +21116,6 @@ cp_parser_single_declaration (cp_parser* parser, parser->scope = NULL_TREE; parser->qualifying_scope = NULL_TREE; parser->object_scope = NULL_TREE; - /* Look for a trailing `;' after the declaration. */ - if (!function_definition_p - && (decl == error_mark_node - || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))) - cp_parser_skip_to_end_of_block_or_statement (parser); return decl; } @@ -20130,7 +21147,8 @@ cp_parser_functional_cast (cp_parser* parser, tree type) CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1; if (TREE_CODE (type) == TYPE_DECL) type = TREE_TYPE (type); - return finish_compound_literal (type, expression_list); + return finish_compound_literal (type, expression_list, + tf_warning_or_error); } @@ -20216,23 +21234,48 @@ cp_parser_save_member_function_body (cp_parser* parser, cp_parser_cache_group (parser, CPP_CLOSE_BRACE, /*depth=*/0); last = parser->lexer->next_token; - /* Save away the inline definition; we will process it when the - class is complete. */ - DECL_PENDING_INLINE_INFO (fn) = cp_token_cache_new (first, last); - DECL_PENDING_INLINE_P (fn) = 1; + /* Save away the inline definition; we will process it when the + class is complete. */ + DECL_PENDING_INLINE_INFO (fn) = cp_token_cache_new (first, last); + DECL_PENDING_INLINE_P (fn) = 1; + + /* We need to know that this was defined in the class, so that + friend templates are handled correctly. */ + DECL_INITIALIZED_IN_CLASS_P (fn) = 1; + + /* Add FN to the queue of functions to be parsed later. */ + VEC_safe_push (tree, gc, unparsed_funs_with_definitions, fn); + + return fn; +} + +/* Save the tokens that make up the in-class initializer for a non-static + data member. Returns a DEFAULT_ARG. */ + +static tree +cp_parser_save_nsdmi (cp_parser* parser) +{ + /* Save away the tokens that make up the body of the + function. */ + cp_token *first = parser->lexer->next_token; + cp_token *last; + tree node; + + /* Save tokens until the next comma or semicolon. */ + cp_parser_cache_group (parser, CPP_COMMA, /*depth=*/0); - /* We need to know that this was defined in the class, so that - friend templates are handled correctly. */ - DECL_INITIALIZED_IN_CLASS_P (fn) = 1; + last = parser->lexer->next_token; - /* Add FN to the queue of functions to be parsed later. */ - VEC_safe_push (tree, gc, unparsed_funs_with_definitions, fn); + node = make_node (DEFAULT_ARG); + DEFARG_TOKENS (node) = cp_token_cache_new (first, last); + DEFARG_INSTANTIATIONS (node) = NULL; - return fn; + return node; } + /* Parse a template-argument-list, as well as the trailing ">" (but - not the opening ">"). See cp_parser_template_argument_list for the + not the opening "<"). See cp_parser_template_argument_list for the return value. */ static tree @@ -20344,6 +21387,7 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser) static void cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function) { + timevar_push (TV_PARSE_INMETH); /* If this member is a template, get the underlying FUNCTION_DECL. */ if (DECL_FUNCTION_TEMPLATE_P (member_function)) @@ -20410,6 +21454,7 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function) /* Restore the queue. */ pop_unparsed_function_queues (parser); + timevar_pop (TV_PARSE_INMETH); } /* If DECL contains any default args, remember it on the unparsed @@ -20434,6 +21479,83 @@ cp_parser_save_default_args (cp_parser* parser, tree decl) } } +/* DEFAULT_ARG contains the saved tokens for the initializer of DECL, + which is either a FIELD_DECL or PARM_DECL. Parse it and return + the result. For a PARM_DECL, PARMTYPE is the corresponding type + from the parameter-type-list. */ + +static tree +cp_parser_late_parse_one_default_arg (cp_parser *parser, tree decl, + tree default_arg, tree parmtype) +{ + cp_token_cache *tokens; + tree parsed_arg; + bool dummy; + + /* Push the saved tokens for the default argument onto the parser's + lexer stack. */ + tokens = DEFARG_TOKENS (default_arg); + cp_parser_push_lexer_for_tokens (parser, tokens); + + start_lambda_scope (decl); + + /* Parse the default argument. */ + parsed_arg = cp_parser_initializer (parser, &dummy, &dummy); + if (BRACE_ENCLOSED_INITIALIZER_P (parsed_arg)) + maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS); + + finish_lambda_scope (); + + if (!processing_template_decl) + { + /* In a non-template class, check conversions now. In a template, + we'll wait and instantiate these as needed. */ + if (TREE_CODE (decl) == PARM_DECL) + parsed_arg = check_default_argument (parmtype, parsed_arg); + else + { + int flags = LOOKUP_IMPLICIT; + if (BRACE_ENCLOSED_INITIALIZER_P (parsed_arg) + && CONSTRUCTOR_IS_DIRECT_INIT (parsed_arg)) + flags = LOOKUP_NORMAL; + parsed_arg = digest_init_flags (TREE_TYPE (decl), parsed_arg, flags); + } + } + + /* If the token stream has not been completely used up, then + there was extra junk after the end of the default + argument. */ + if (!cp_lexer_next_token_is (parser->lexer, CPP_EOF)) + { + if (TREE_CODE (decl) == PARM_DECL) + cp_parser_error (parser, "expected %<,%>"); + else + cp_parser_error (parser, "expected %<;%>"); + } + + /* Revert to the main lexer. */ + cp_parser_pop_lexer (parser); + + return parsed_arg; +} + +/* FIELD is a non-static data member with an initializer which we saved for + later; parse it now. */ + +static void +cp_parser_late_parsing_nsdmi (cp_parser *parser, tree field) +{ + tree def; + + push_unparsed_function_queues (parser); + def = cp_parser_late_parse_one_default_arg (parser, field, + DECL_INITIAL (field), + NULL_TREE); + pop_unparsed_function_queues (parser); + + DECL_INITIAL (field) = def; +} + /* FN is a FUNCTION_DECL which may contains a parameter with an unparsed DEFAULT_ARG. Parse the default args now. This function assumes that the current scope is the scope in which the default @@ -20456,13 +21578,14 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) saved_local_variables_forbidden_p = parser->local_variables_forbidden_p; parser->local_variables_forbidden_p = true; + push_defarg_context (fn); + for (parm = TYPE_ARG_TYPES (TREE_TYPE (fn)), parmdecl = DECL_ARGUMENTS (fn); parm && parm != void_list_node; parm = TREE_CHAIN (parm), parmdecl = DECL_CHAIN (parmdecl)) { - cp_token_cache *tokens; tree default_arg = TREE_PURPOSE (parm); tree parsed_arg; VEC(tree,gc) *insts; @@ -20477,43 +21600,25 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) already declared with default arguments. */ continue; - /* Push the saved tokens for the default argument onto the parser's - lexer stack. */ - tokens = DEFARG_TOKENS (default_arg); - cp_parser_push_lexer_for_tokens (parser, tokens); - - start_lambda_scope (parmdecl); - - /* Parse the assignment-expression. */ - parsed_arg = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL); + parsed_arg + = cp_parser_late_parse_one_default_arg (parser, parmdecl, + default_arg, + TREE_VALUE (parm)); if (parsed_arg == error_mark_node) { - cp_parser_pop_lexer (parser); continue; } - if (!processing_template_decl) - parsed_arg = check_default_argument (TREE_VALUE (parm), parsed_arg); - TREE_PURPOSE (parm) = parsed_arg; /* Update any instantiations we've already created. */ for (insts = DEFARG_INSTANTIATIONS (default_arg), ix = 0; VEC_iterate (tree, insts, ix, copy); ix++) TREE_PURPOSE (copy) = parsed_arg; - - finish_lambda_scope (); - - /* If the token stream has not been completely used up, then - there was extra junk after the end of the default - argument. */ - if (!cp_lexer_next_token_is (parser->lexer, CPP_EOF)) - cp_parser_error (parser, "expected %<,%>"); - - /* Revert to the main lexer. */ - cp_parser_pop_lexer (parser); } + pop_defarg_context (); + /* Make sure no default arg is missing. */ check_default_args (fn); @@ -20706,15 +21811,14 @@ cp_parser_set_storage_class (cp_parser *parser, decl_specs->conflicting_specifiers_p = true; } -/* Update the DECL_SPECS to reflect the TYPE_SPEC. If USER_DEFINED_P - is true, the type is a user-defined type; otherwise it is a - built-in type specified by a keyword. */ +/* Update the DECL_SPECS to reflect the TYPE_SPEC. If TYPE_DEFINITION_P + is true, the type is a class or enum definition. */ static void cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs, tree type_spec, location_t location, - bool user_defined_p) + bool type_definition_p) { decl_specs->any_specifiers_p = true; @@ -20724,7 +21828,7 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs, declarations so that G++ can work with system headers that are not C++-safe. */ if (decl_specs->specs[(int) ds_typedef] - && !user_defined_p + && !type_definition_p && (type_spec == boolean_type_node || type_spec == char16_type_node || type_spec == char32_type_node @@ -20739,7 +21843,7 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs, if (!decl_specs->type) { decl_specs->type = type_spec; - decl_specs->user_defined_type_p = false; + decl_specs->type_definition_p = false; decl_specs->type_location = location; } } @@ -20748,7 +21852,7 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs, else { decl_specs->type = type_spec; - decl_specs->user_defined_type_p = user_defined_p; + decl_specs->type_definition_p = type_definition_p; decl_specs->redefined_builtin_type = NULL_TREE; decl_specs->type_location = location; } @@ -21260,6 +22364,12 @@ cp_parser_cache_group (cp_parser *parser, kind of syntax error. */ return true; + /* If we're caching something finished by a comma (or semicolon), + such as an NSDMI, don't consume the comma. */ + if (end == CPP_COMMA + && (token->type == CPP_SEMICOLON || token->type == CPP_COMMA)) + return false; + /* Consume the token. */ cp_lexer_consume_token (parser->lexer); /* See if it starts a new group. */ @@ -21329,6 +22439,8 @@ cp_parser_commit_to_tentative_parse (cp_parser* parser) static void cp_parser_abort_tentative_parse (cp_parser* parser) { + gcc_assert (parser->context->status != CP_PARSER_STATUS_KIND_COMMITTED + || errorcount > 0); cp_parser_simulate_error (parser); /* Now, pretend that we want to see if the construct was successfully parsed. */ @@ -21475,7 +22587,7 @@ cp_parser_objc_message_expression (cp_parser* parser) messageargs = cp_parser_objc_message_args (parser); cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); - return objc_build_message_expr (build_tree_list (receiver, messageargs)); + return objc_build_message_expr (receiver, messageargs); } /* Parse an objc-message-receiver. @@ -21801,7 +22913,21 @@ static void cp_parser_objc_class_declaration (cp_parser* parser) { cp_lexer_consume_token (parser->lexer); /* Eat '@class'. */ - objc_declare_class (cp_parser_objc_identifier_list (parser)); + while (true) + { + tree id; + + id = cp_parser_identifier (parser); + if (id == error_mark_node) + break; + + objc_declare_class (id); + + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + cp_lexer_consume_token (parser->lexer); + else + break; + } cp_parser_consume_semicolon_at_end_of_statement (parser); } @@ -22132,7 +23258,8 @@ cp_parser_objc_interstitial_code (cp_parser* parser) /* If the next token is `extern' and the following token is a string literal, then we have a linkage specification. */ if (token->keyword == RID_EXTERN - && cp_parser_is_string_literal (cp_lexer_peek_nth_token (parser->lexer, 2))) + && cp_parser_is_pure_string_literal + (cp_lexer_peek_nth_token (parser->lexer, 2))) cp_parser_linkage_specification (parser); /* Handle #pragma, if any. */ else if (token->type == CPP_PRAGMA) @@ -22284,7 +23411,8 @@ cp_parser_objc_method_definition_list (cp_parser* parser) token = cp_lexer_peek_token (parser->lexer); continue; } - objc_start_method_definition (is_class_method, sig, attribute); + objc_start_method_definition (is_class_method, sig, attribute, + NULL_TREE); /* For historical reasons, we accept an optional semicolon. */ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) @@ -22442,7 +23570,8 @@ cp_parser_objc_class_ivars (cp_parser* parser) NULL_TREE, attributes); /* Add the instance variable. */ - objc_add_instance_variable (decl); + if (decl != error_mark_node && decl != NULL_TREE) + objc_add_instance_variable (decl); /* Reset PREFIX_ATTRIBUTES. */ while (attributes && TREE_CHAIN (attributes) != first_attribute) @@ -22490,7 +23619,8 @@ cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes) { tok = cp_lexer_peek_token (parser->lexer); error_at (tok->location, "identifier expected after %<@protocol%>"); - goto finish; + cp_parser_consume_semicolon_at_end_of_statement (parser); + return; } /* See if we have a forward declaration or a definition. */ @@ -22499,9 +23629,21 @@ cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes) /* Try a forward declaration first. */ if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON) { - objc_declare_protocols (cp_parser_objc_identifier_list (parser), - attributes); - finish: + while (true) + { + tree id; + + id = cp_parser_identifier (parser); + if (id == error_mark_node) + break; + + objc_declare_protocol (id, attributes); + + if(cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + cp_lexer_consume_token (parser->lexer); + else + break; + } cp_parser_consume_semicolon_at_end_of_statement (parser); } @@ -22726,7 +23868,7 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) /* NB: The @try block needs to be wrapped in its own STATEMENT_LIST node, lest it get absorbed into the surrounding block. */ stmt = push_stmt_list (); - cp_parser_compound_statement (parser, NULL, false); + cp_parser_compound_statement (parser, NULL, false, false); objc_begin_try_stmt (location, pop_stmt_list (stmt)); while (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_CATCH)) @@ -22782,7 +23924,7 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) forget about the closing parenthesis and keep going. */ } objc_begin_catch_clause (parameter_declaration); - cp_parser_compound_statement (parser, NULL, false); + cp_parser_compound_statement (parser, NULL, false, false); objc_finish_catch_clause (); } if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_FINALLY)) @@ -22792,7 +23934,7 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) /* NB: The @finally block needs to be wrapped in its own STATEMENT_LIST node, lest it get absorbed into the surrounding block. */ stmt = push_stmt_list (); - cp_parser_compound_statement (parser, NULL, false); + cp_parser_compound_statement (parser, NULL, false, false); objc_build_finally_clause (location, pop_stmt_list (stmt)); } @@ -22823,7 +23965,7 @@ cp_parser_objc_synchronized_statement (cp_parser *parser) /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST node, lest it get absorbed into the surrounding block. */ stmt = push_stmt_list (); - cp_parser_compound_statement (parser, NULL, false); + cp_parser_compound_statement (parser, NULL, false, false); return objc_build_synchronized (location, lock, pop_stmt_list (stmt)); } @@ -23097,7 +24239,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser) break; } cp_lexer_consume_token (parser->lexer); /* eat the = */ - if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME)) + if (!cp_parser_objc_selector_p (cp_lexer_peek_token (parser->lexer)->type)) { cp_parser_error (parser, "expected identifier"); syntax_error = true; @@ -23106,10 +24248,12 @@ cp_parser_objc_at_property_declaration (cp_parser *parser) if (keyword == RID_SETTER) { if (property_setter_ident != NULL_TREE) - cp_parser_error (parser, "the % attribute may only be specified once"); + { + cp_parser_error (parser, "the % attribute may only be specified once"); + cp_lexer_consume_token (parser->lexer); + } else - property_setter_ident = cp_lexer_peek_token (parser->lexer)->u.value; - cp_lexer_consume_token (parser->lexer); + property_setter_ident = cp_parser_objc_selector (parser); if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)) cp_parser_error (parser, "setter name must terminate with %<:%>"); else @@ -23118,10 +24262,12 @@ cp_parser_objc_at_property_declaration (cp_parser *parser) else { if (property_getter_ident != NULL_TREE) - cp_parser_error (parser, "the % attribute may only be specified once"); + { + cp_parser_error (parser, "the % attribute may only be specified once"); + cp_lexer_consume_token (parser->lexer); + } else - property_getter_ident = cp_lexer_peek_token (parser->lexer)->u.value; - cp_lexer_consume_token (parser->lexer); + property_getter_ident = cp_parser_objc_selector (parser); } break; default: @@ -23316,13 +24462,19 @@ cp_parser_omp_clause_name (cp_parser *parser) result = PRAGMA_OMP_CLAUSE_COPYPRIVATE; break; case 'f': - if (!strcmp ("firstprivate", p)) + if (!strcmp ("final", p)) + result = PRAGMA_OMP_CLAUSE_FINAL; + else if (!strcmp ("firstprivate", p)) result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE; break; case 'l': if (!strcmp ("lastprivate", p)) result = PRAGMA_OMP_CLAUSE_LASTPRIVATE; break; + case 'm': + if (!strcmp ("mergeable", p)) + result = PRAGMA_OMP_CLAUSE_MERGEABLE; + break; case 'n': if (!strcmp ("nowait", p)) result = PRAGMA_OMP_CLAUSE_NOWAIT; @@ -23552,6 +24704,34 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list, location_t location) return c; } +/* OpenMP 3.1: + final ( expression ) */ + +static tree +cp_parser_omp_clause_final (cp_parser *parser, tree list, location_t location) +{ + tree t, c; + + if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) + return list; + + t = cp_parser_condition (parser); + + if (t == error_mark_node + || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN)) + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + + check_no_duplicate_clause (list, OMP_CLAUSE_FINAL, "final", location); + + c = build_omp_clause (location, OMP_CLAUSE_FINAL); + OMP_CLAUSE_FINAL_EXPR (c) = t; + OMP_CLAUSE_CHAIN (c) = list; + + return c; +} + /* OpenMP 2.5: if ( expression ) */ @@ -23580,6 +24760,23 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location) return c; } +/* OpenMP 3.1: + mergeable */ + +static tree +cp_parser_omp_clause_mergeable (cp_parser *parser ATTRIBUTE_UNUSED, + tree list, location_t location) +{ + tree c; + + check_no_duplicate_clause (list, OMP_CLAUSE_MERGEABLE, "mergeable", + location); + + c = build_omp_clause (location, OMP_CLAUSE_MERGEABLE); + OMP_CLAUSE_CHAIN (c) = list; + return c; +} + /* OpenMP 2.5: nowait */ @@ -23647,7 +24844,12 @@ cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED, reduction ( reduction-operator : variable-list ) reduction-operator: - One of: + * - & ^ | && || */ + One of: + * - & ^ | && || + + OpenMP 3.1: + + reduction-operator: + One of: + * - & ^ | && || min max */ static tree cp_parser_omp_clause_reduction (cp_parser *parser, tree list) @@ -23684,9 +24886,26 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list) case CPP_OR_OR: code = TRUTH_ORIF_EXPR; break; + case CPP_NAME: + { + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + const char *p = IDENTIFIER_POINTER (id); + + if (strcmp (p, "min") == 0) + { + code = MIN_EXPR; + break; + } + if (strcmp (p, "max") == 0) + { + code = MAX_EXPR; + break; + } + } + /* FALLTHROUGH */ default: cp_parser_error (parser, "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, " - "%<|%>, %<&&%>, or %<||%>"); + "%<|%>, %<&&%>, %<||%>, % or %"); resync_fail: cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, /*or_comma=*/false, @@ -23859,6 +25078,10 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask, token->location); c_name = "default"; break; + case PRAGMA_OMP_CLAUSE_FINAL: + clauses = cp_parser_omp_clause_final (parser, clauses, token->location); + c_name = "final"; + break; case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE: clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FIRSTPRIVATE, clauses); @@ -23873,6 +25096,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask, clauses); c_name = "lastprivate"; break; + case PRAGMA_OMP_CLAUSE_MERGEABLE: + clauses = cp_parser_omp_clause_mergeable (parser, clauses, + token->location); + c_name = "mergeable"; + break; case PRAGMA_OMP_CLAUSE_NOWAIT: clauses = cp_parser_omp_clause_nowait (parser, clauses, token->location); c_name = "nowait"; @@ -23983,34 +25211,140 @@ cp_parser_omp_structured_block (cp_parser *parser) binop: +, *, -, /, &, ^, |, <<, >> - where x is an lvalue expression with scalar type. */ + where x is an lvalue expression with scalar type. + + OpenMP 3.1: + # pragma omp atomic new-line + update-stmt + + # pragma omp atomic read new-line + read-stmt + + # pragma omp atomic write new-line + write-stmt + + # pragma omp atomic update new-line + update-stmt + + # pragma omp atomic capture new-line + capture-stmt + + # pragma omp atomic capture new-line + capture-block + + read-stmt: + v = x + write-stmt: + x = expr + update-stmt: + expression-stmt | x = x binop expr + capture-stmt: + v = x binop= expr | v = x++ | v = ++x | v = x-- | v = --x + capture-block: + { v = x; update-stmt; } | { update-stmt; v = x; } + + where x and v are lvalue expressions with scalar type. */ static void cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok) { - tree lhs, rhs; - enum tree_code code; + tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, lhs1 = NULL_TREE; + tree rhs1 = NULL_TREE, orig_lhs; + enum tree_code code = OMP_ATOMIC, opcode = NOP_EXPR; + bool structured_block = false; + + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + tree id = cp_lexer_peek_token (parser->lexer)->u.value; + const char *p = IDENTIFIER_POINTER (id); + if (!strcmp (p, "read")) + code = OMP_ATOMIC_READ; + else if (!strcmp (p, "write")) + code = NOP_EXPR; + else if (!strcmp (p, "update")) + code = OMP_ATOMIC; + else if (!strcmp (p, "capture")) + code = OMP_ATOMIC_CAPTURE_NEW; + else + p = NULL; + if (p) + cp_lexer_consume_token (parser->lexer); + } cp_parser_require_pragma_eol (parser, pragma_tok); + switch (code) + { + case OMP_ATOMIC_READ: + case NOP_EXPR: /* atomic write */ + v = cp_parser_unary_expression (parser, /*address_p=*/false, + /*cast_p=*/false, NULL); + if (v == error_mark_node) + goto saw_error; + if (!cp_parser_require (parser, CPP_EQ, RT_EQ)) + goto saw_error; + if (code == NOP_EXPR) + lhs = cp_parser_expression (parser, /*cast_p=*/false, NULL); + else + lhs = cp_parser_unary_expression (parser, /*address_p=*/false, + /*cast_p=*/false, NULL); + if (lhs == error_mark_node) + goto saw_error; + if (code == NOP_EXPR) + { + /* atomic write is represented by OMP_ATOMIC with NOP_EXPR + opcode. */ + code = OMP_ATOMIC; + rhs = lhs; + lhs = v; + v = NULL_TREE; + } + goto done; + case OMP_ATOMIC_CAPTURE_NEW: + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) + { + cp_lexer_consume_token (parser->lexer); + structured_block = true; + } + else + { + v = cp_parser_unary_expression (parser, /*address_p=*/false, + /*cast_p=*/false, NULL); + if (v == error_mark_node) + goto saw_error; + if (!cp_parser_require (parser, CPP_EQ, RT_EQ)) + goto saw_error; + } + default: + break; + } + +restart: lhs = cp_parser_unary_expression (parser, /*address_p=*/false, /*cast_p=*/false, NULL); + orig_lhs = lhs; switch (TREE_CODE (lhs)) { case ERROR_MARK: goto saw_error; - case PREINCREMENT_EXPR: case POSTINCREMENT_EXPR: + if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block) + code = OMP_ATOMIC_CAPTURE_OLD; + /* FALLTHROUGH */ + case PREINCREMENT_EXPR: lhs = TREE_OPERAND (lhs, 0); - code = PLUS_EXPR; + opcode = PLUS_EXPR; rhs = integer_one_node; break; - case PREDECREMENT_EXPR: case POSTDECREMENT_EXPR: + if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block) + code = OMP_ATOMIC_CAPTURE_OLD; + /* FALLTHROUGH */ + case PREDECREMENT_EXPR: lhs = TREE_OPERAND (lhs, 0); - code = MINUS_EXPR; + opcode = MINUS_EXPR; rhs = integer_one_node; break; @@ -24028,48 +25362,123 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok) case MODIFY_EXPR: if (TREE_CODE (lhs) == MODIFY_EXPR && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE) - { - /* Undo effects of boolean_increment. */ - if (integer_onep (TREE_OPERAND (lhs, 1))) - { - /* This is pre or post increment. */ - rhs = TREE_OPERAND (lhs, 1); - lhs = TREE_OPERAND (lhs, 0); - code = NOP_EXPR; - break; - } - } + { + /* Undo effects of boolean_increment. */ + if (integer_onep (TREE_OPERAND (lhs, 1))) + { + /* This is pre or post increment. */ + rhs = TREE_OPERAND (lhs, 1); + lhs = TREE_OPERAND (lhs, 0); + opcode = NOP_EXPR; + if (code == OMP_ATOMIC_CAPTURE_NEW + && !structured_block + && TREE_CODE (orig_lhs) == COMPOUND_EXPR) + code = OMP_ATOMIC_CAPTURE_OLD; + break; + } + } /* FALLTHRU */ default: switch (cp_lexer_peek_token (parser->lexer)->type) { case CPP_MULT_EQ: - code = MULT_EXPR; + opcode = MULT_EXPR; break; case CPP_DIV_EQ: - code = TRUNC_DIV_EXPR; + opcode = TRUNC_DIV_EXPR; break; case CPP_PLUS_EQ: - code = PLUS_EXPR; + opcode = PLUS_EXPR; break; case CPP_MINUS_EQ: - code = MINUS_EXPR; + opcode = MINUS_EXPR; break; case CPP_LSHIFT_EQ: - code = LSHIFT_EXPR; + opcode = LSHIFT_EXPR; break; case CPP_RSHIFT_EQ: - code = RSHIFT_EXPR; + opcode = RSHIFT_EXPR; break; case CPP_AND_EQ: - code = BIT_AND_EXPR; + opcode = BIT_AND_EXPR; break; case CPP_OR_EQ: - code = BIT_IOR_EXPR; + opcode = BIT_IOR_EXPR; break; case CPP_XOR_EQ: - code = BIT_XOR_EXPR; + opcode = BIT_XOR_EXPR; break; + case CPP_EQ: + if (structured_block || code == OMP_ATOMIC) + { + enum cp_parser_prec oprec; + cp_token *token; + cp_lexer_consume_token (parser->lexer); + rhs1 = cp_parser_unary_expression (parser, /*address_p=*/false, + /*cast_p=*/false, NULL); + if (rhs1 == error_mark_node) + goto saw_error; + token = cp_lexer_peek_token (parser->lexer); + switch (token->type) + { + case CPP_SEMICOLON: + if (code == OMP_ATOMIC_CAPTURE_NEW) + { + code = OMP_ATOMIC_CAPTURE_OLD; + v = lhs; + lhs = NULL_TREE; + lhs1 = rhs1; + rhs1 = NULL_TREE; + cp_lexer_consume_token (parser->lexer); + goto restart; + } + cp_parser_error (parser, + "invalid form of %<#pragma omp atomic%>"); + goto saw_error; + case CPP_MULT: + opcode = MULT_EXPR; + break; + case CPP_DIV: + opcode = TRUNC_DIV_EXPR; + break; + case CPP_PLUS: + opcode = PLUS_EXPR; + break; + case CPP_MINUS: + opcode = MINUS_EXPR; + break; + case CPP_LSHIFT: + opcode = LSHIFT_EXPR; + break; + case CPP_RSHIFT: + opcode = RSHIFT_EXPR; + break; + case CPP_AND: + opcode = BIT_AND_EXPR; + break; + case CPP_OR: + opcode = BIT_IOR_EXPR; + break; + case CPP_XOR: + opcode = BIT_XOR_EXPR; + break; + default: + cp_parser_error (parser, + "invalid operator for %<#pragma omp atomic%>"); + goto saw_error; + } + oprec = TOKEN_PRECEDENCE (token); + gcc_assert (oprec != PREC_NOT_OPERATOR); + if (commutative_tree_code (opcode)) + oprec = (enum cp_parser_prec) (oprec - 1); + cp_lexer_consume_token (parser->lexer); + rhs = cp_parser_binary_expression (parser, false, false, + oprec, NULL); + if (rhs == error_mark_node) + goto saw_error; + goto stmt_done; + } + /* FALLTHROUGH */ default: cp_parser_error (parser, "invalid operator for %<#pragma omp atomic%>"); @@ -24082,12 +25491,46 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok) goto saw_error; break; } - finish_omp_atomic (code, lhs, rhs); - cp_parser_consume_semicolon_at_end_of_statement (parser); +stmt_done: + if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW) + { + if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)) + goto saw_error; + v = cp_parser_unary_expression (parser, /*address_p=*/false, + /*cast_p=*/false, NULL); + if (v == error_mark_node) + goto saw_error; + if (!cp_parser_require (parser, CPP_EQ, RT_EQ)) + goto saw_error; + lhs1 = cp_parser_unary_expression (parser, /*address_p=*/false, + /*cast_p=*/false, NULL); + if (lhs1 == error_mark_node) + goto saw_error; + } + if (structured_block) + { + cp_parser_consume_semicolon_at_end_of_statement (parser); + cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE); + } +done: + finish_omp_atomic (code, opcode, lhs, rhs, v, lhs1, rhs1); + if (!structured_block) + cp_parser_consume_semicolon_at_end_of_statement (parser); return; saw_error: cp_parser_skip_to_end_of_block_or_statement (parser); + if (structured_block) + { + if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)) + cp_lexer_consume_token (parser->lexer); + else if (code == OMP_ATOMIC_CAPTURE_NEW) + { + cp_parser_skip_to_end_of_block_or_statement (parser); + if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)) + cp_lexer_consume_token (parser->lexer); + } + } } @@ -24153,8 +25596,6 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl) { tree cond = cp_parser_binary_expression (parser, false, true, PREC_NOT_OPERATOR, NULL); - bool overloaded_p; - if (cond == error_mark_node || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) { @@ -24183,7 +25624,7 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl) return build_x_binary_op (TREE_CODE (cond), TREE_OPERAND (cond, 0), ERROR_MARK, TREE_OPERAND (cond, 1), ERROR_MARK, - &overloaded_p, tf_warning_or_error); + /*overload=*/NULL, tf_warning_or_error); } /* Helper function, to parse omp for increment expression. */ @@ -24391,7 +25832,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses) &is_direct_init, &is_non_constant_init); - if (auto_node && describable_type (init)) + if (auto_node) { TREE_TYPE (decl) = do_auto_deduction (TREE_TYPE (decl), init, @@ -24566,7 +26007,8 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses) /* If decl is an iterator, preserve the operator on decl until finish_omp_for. */ if (decl - && (type_dependent_expression_p (decl) + && ((type_dependent_expression_p (decl) + && !POINTER_TYPE_P (TREE_TYPE (decl))) || CLASS_TYPE_P (TREE_TYPE (decl)))) incr = cp_parser_omp_for_incr (parser, decl); else @@ -24950,7 +26392,9 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok) | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \ | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \ | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ - | (1u << PRAGMA_OMP_CLAUSE_SHARED)) + | (1u << PRAGMA_OMP_CLAUSE_SHARED) \ + | (1u << PRAGMA_OMP_CLAUSE_FINAL) \ + | (1u << PRAGMA_OMP_CLAUSE_MERGEABLE)) static tree cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok) @@ -24977,6 +26421,16 @@ cp_parser_omp_taskwait (cp_parser *parser, cp_token *pragma_tok) finish_omp_taskwait (); } +/* OpenMP 3.1: + # pragma omp taskyield new-line */ + +static void +cp_parser_omp_taskyield (cp_parser *parser, cp_token *pragma_tok) +{ + cp_parser_require_pragma_eol (parser, pragma_tok); + finish_omp_taskyield (); +} + /* OpenMP 2.5: # pragma omp threadprivate (variable-list) */ @@ -25152,6 +26606,22 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context) } break; + case PRAGMA_OMP_TASKYIELD: + switch (context) + { + case pragma_compound: + cp_parser_omp_taskyield (parser, pragma_tok); + return false; + case pragma_stmt: + error_at (pragma_tok->location, + "%<#pragma omp taskyield%> may only be " + "used in compound statements"); + break; + default: + goto bad_stmt; + } + break; + case PRAGMA_OMP_THREADPRIVATE: cp_parser_omp_threadprivate (parser, pragma_tok); return false;