X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcp%2Fparser.c;h=60a53c8076adcb5fb9aa23ae4835657b5a1c3e1e;hb=b4f2a57698cb7d739f6ed401d5413e149fd2427c;hp=6feb114436a4e328031f71d682d2d1cf7aee84c8;hpb=dd63dd9059200fece499159151c2905d220d88c1;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 6feb114436a..60a53c8076a 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -36,6 +36,7 @@ #include "toplev.h" #include "output.h" #include "target.h" +#include "cgraph.h" #include "c-common.h" @@ -55,10 +56,16 @@ typedef struct cp_token GTY (()) 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 system header. */ BOOL_BITFIELD in_system_header : 1; /* 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 value associated with this token, if any. */ tree value; /* The location at which this token was found. */ @@ -72,7 +79,7 @@ DEF_VEC_ALLOC_P (cp_token_position,heap); static const cp_token eof_token = { - CPP_EOF, RID_MAX, 0, 0, 0, NULL_TREE, + CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 0, 0, false, NULL_TREE, #if USE_MAPPED_LOCATION 0 #else @@ -108,11 +115,15 @@ typedef struct cp_lexer GTY (()) 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; - /* The next lexer in a linked list of lexers. */ - struct cp_lexer *next; + /* 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 @@ -162,8 +173,6 @@ static void cp_lexer_purge_token (cp_lexer *); static void cp_lexer_purge_tokens_after (cp_lexer *, cp_token_position); -static void cp_lexer_handle_pragma - (cp_lexer *); static void cp_lexer_save_tokens (cp_lexer *); static void cp_lexer_commit_tokens @@ -192,6 +201,9 @@ static void cp_lexer_stop_debugging static cp_token_cache *cp_token_cache_new (cp_token *, cp_token *); +static void cp_parser_initial_pragma + (cp_token *); + /* Manifest constants. */ #define CP_LEXER_BUFFER_SIZE 10000 #define CP_SAVED_TOKEN_STACK 5 @@ -240,17 +252,12 @@ cp_lexer_new_main (void) size_t space; cp_token *buffer; - /* It's possible that lexing the first token will load a PCH file, - which is a GC collection point. So we have to grab the first - token before allocating any memory. Pragmas must not be deferred - as -fpch-preprocess can generate a pragma to load the PCH file in - the preprocessed output used by -save-temps. */ - cp_lexer_get_preprocessor_token (NULL, &first_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 (&first_token); - /* Tell cpplib we want CPP_PRAGMA tokens. */ - cpp_get_options (parse_in)->defer_pragmas = true; - - /* Tell c_lex not to merge string constants. */ + /* Tell c_lex_with_flags not to merge string constants. */ c_lex_return_raw_strings = true; c_common_no_more_pch (); @@ -267,7 +274,7 @@ cp_lexer_new_main (void) /* Create the buffer. */ alloc = CP_LEXER_BUFFER_SIZE; - buffer = ggc_alloc (alloc * sizeof (cp_token)); + buffer = GGC_NEWVEC (cp_token, alloc); /* Put the first token in the buffer. */ space = alloc; @@ -282,7 +289,7 @@ cp_lexer_new_main (void) { space = alloc; alloc *= 2; - buffer = ggc_realloc (buffer, alloc * sizeof (cp_token)); + buffer = GGC_RESIZEVEC (cp_token, buffer, alloc); pos = buffer + space; } cp_lexer_get_preprocessor_token (lexer, pos); @@ -292,10 +299,10 @@ cp_lexer_new_main (void) lexer->last_token = pos; lexer->next_token = lexer->buffer_length ? buffer : (cp_token *)&eof_token; - /* Pragma processing (via cpp_handle_deferred_pragma) may result in - direct calls to c_lex. Those callers all expect c_lex to do - string constant concatenation. */ - c_lex_return_raw_strings = false; + /* Subsequent preprocessor diagnostics should use compiler + diagnostic functions to get the compiler source location. */ + cpp_get_options (parse_in)->client_diagnostic = true; + cpp_get_callbacks (parse_in)->error = cp_cpp_error; gcc_assert (lexer->next_token->type != CPP_PURGED); return lexer; @@ -386,6 +393,8 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED , /* Get a new token from the preprocessor. */ token->type = c_lex_with_flags (&token->value, &token->location, &token->flags); + token->keyword = RID_MAX; + token->pragma_kind = PRAGMA_NONE; token->in_system_header = in_system_header; /* On some systems, some header files are surrounded by an @@ -396,18 +405,25 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED , token->implicit_extern_c = is_extern_c > 0; /* Check to see if this token is a keyword. */ - if (token->type == CPP_NAME - && C_IS_RESERVED_WORD (token->value)) + if (token->type == CPP_NAME) { - /* Mark this token as a keyword. */ - token->type = CPP_KEYWORD; - /* Record which keyword. */ - token->keyword = C_RID_CODE (token->value); - /* Update the value. Some keywords are mapped to particular - entities, rather than simply having the value of the - corresponding IDENTIFIER_NODE. For example, `__const' is - mapped to `const'. */ - token->value = ridpointers[token->keyword]; + if (C_IS_RESERVED_WORD (token->value)) + { + /* Mark this token as a keyword. */ + token->type = CPP_KEYWORD; + /* Record which keyword. */ + token->keyword = C_RID_CODE (token->value); + /* Update the value. Some keywords are mapped to particular + entities, rather than simply having the value of the + corresponding IDENTIFIER_NODE. For example, `__const' is + mapped to `const'. */ + token->value = ridpointers[token->keyword]; + } + else + { + token->ambiguous_p = false; + token->keyword = RID_MAX; + } } /* Handle Objective-C++ keywords. */ else if (token->type == CPP_AT_NAME) @@ -426,8 +442,12 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED , default: token->keyword = C_RID_CODE (token->value); } } - else - token->keyword = RID_MAX; + else if (token->type == CPP_PRAGMA) + { + /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */ + token->pragma_kind = TREE_INT_CST_LOW (token->value); + token->value = NULL; + } } /* Update the globals input_location and in_system_header from TOKEN. */ @@ -477,12 +497,7 @@ cp_lexer_next_token_is_not (cp_lexer* lexer, enum cpp_ttype type) static inline bool cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword) { - cp_token *token; - - /* Peek at the next token. */ - token = cp_lexer_peek_token (lexer); - /* Check to see if it is the indicated keyword. */ - return token->keyword == keyword; + return cp_lexer_peek_token (lexer)->keyword == keyword; } /* Return a pointer to the Nth token in the token stream. If N is 1, @@ -537,6 +552,7 @@ cp_lexer_consume_token (cp_lexer* lexer) cp_token *token = lexer->next_token; gcc_assert (token != &eof_token); + gcc_assert (!lexer->in_pragma || token->type != CPP_PRAGMA_EOL); do { @@ -614,25 +630,6 @@ cp_lexer_purge_tokens_after (cp_lexer *lexer, cp_token *tok) } } -/* Consume and handle a pragma token. */ -static void -cp_lexer_handle_pragma (cp_lexer *lexer) -{ - cpp_string s; - cp_token *token = cp_lexer_consume_token (lexer); - gcc_assert (token->type == CPP_PRAGMA); - gcc_assert (token->value); - - s.len = TREE_STRING_LENGTH (token->value); - s.text = (const unsigned char *) TREE_STRING_POINTER (token->value); - - cpp_handle_deferred_pragma (parse_in, &s); - - /* Clearing token->value here means that we will get an ICE if we - try to process this #pragma again (which should be impossible). */ - token->value = NULL; -} - /* Begin saving tokens. All tokens consumed after this point will be preserved. */ @@ -715,7 +712,6 @@ cp_lexer_print_token (FILE * stream, cp_token *token) case CPP_STRING: case CPP_WSTRING: - case CPP_PRAGMA: fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->value)); break; @@ -756,9 +752,6 @@ cp_token_cache_new (cp_token *first, cp_token *last) /* Decl-specifiers. */ -static void clear_decl_specs - (cp_decl_specifier_seq *); - /* Set *DECL_SPECS to represent an empty decl-specifier-seq. */ static void @@ -787,7 +780,8 @@ static cp_parameter_declarator *make_parameter_declarator static cp_declarator *make_ptrmem_declarator (cp_cv_quals, tree, cp_declarator *); -cp_declarator *cp_error_declarator; +/* An erroneous declarator. */ +static cp_declarator *cp_error_declarator; /* The obstack on which declarators and related data structures are allocated. */ @@ -817,12 +811,15 @@ make_declarator (cp_declarator_kind kind) return declarator; } -/* Make a declarator for a generalized identifier. If non-NULL, the - identifier is QUALIFYING_SCOPE::UNQUALIFIED_NAME; otherwise, it is - just UNQUALIFIED_NAME. */ +/* Make a declarator for a generalized identifier. If + QUALIFYING_SCOPE is non-NULL, the identifier is + QUALIFYING_SCOPE::UNQUALIFIED_NAME; otherwise, it is just + UNQUALIFIED_NAME. SFK indicates the kind of special function this + is, if any. */ static cp_declarator * -make_id_declarator (tree qualifying_scope, tree unqualified_name) +make_id_declarator (tree qualifying_scope, tree unqualified_name, + special_function_kind sfk) { cp_declarator *declarator; @@ -839,10 +836,14 @@ make_id_declarator (tree qualifying_scope, tree unqualified_name) if (qualifying_scope && TYPE_P (qualifying_scope)) qualifying_scope = TYPE_MAIN_VARIANT (qualifying_scope); + gcc_assert (TREE_CODE (unqualified_name) == IDENTIFIER_NODE + || TREE_CODE (unqualified_name) == BIT_NOT_EXPR + || TREE_CODE (unqualified_name) == TEMPLATE_ID_EXPR); + declarator = make_declarator (cdk_id); declarator->u.id.qualifying_scope = qualifying_scope; declarator->u.id.unqualified_name = unqualified_name; - declarator->u.id.sfk = sfk_none; + declarator->u.id.sfk = sfk; return declarator; } @@ -1293,12 +1294,21 @@ typedef struct cp_parser GTY(()) /* TRUE if we are presently parsing a template-argument-list. */ bool in_template_argument_list_p; - /* TRUE if we are presently parsing the body of an - iteration-statement. */ - bool in_iteration_statement_p; - - /* TRUE if we are presently parsing the body of a switch - statement. */ + /* 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 + 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 @@ -1344,9 +1354,6 @@ typedef struct cp_parser GTY(()) unsigned num_template_parameter_lists; } cp_parser; -/* The type of a function that parses some kind of expression. */ -typedef tree (*cp_parser_expression_fn) (cp_parser *); - /* Prototypes. */ /* Constructors and destructors. */ @@ -1381,11 +1388,11 @@ static bool cp_parser_translation_unit /* Expressions [gram.expr] */ static tree cp_parser_primary_expression - (cp_parser *, bool, cp_id_kind *, tree *); + (cp_parser *, bool, bool, bool, cp_id_kind *); static tree cp_parser_id_expression - (cp_parser *, bool, bool, bool *, bool); + (cp_parser *, bool, bool, bool *, bool, bool); static tree cp_parser_unqualified_id - (cp_parser *, bool, bool, bool); + (cp_parser *, bool, bool, bool, bool); static tree cp_parser_nested_name_specifier_opt (cp_parser *, bool, bool, bool, bool); static tree cp_parser_nested_name_specifier @@ -1440,9 +1447,9 @@ static tree cp_parser_builtin_offsetof /* Statements [gram.stmt.stmt] */ static void cp_parser_statement - (cp_parser *, tree); + (cp_parser *, tree, bool); static tree cp_parser_labeled_statement - (cp_parser *, tree); + (cp_parser *, tree, bool); static tree cp_parser_expression_statement (cp_parser *, tree); static tree cp_parser_compound_statement @@ -1520,7 +1527,7 @@ static void cp_parser_linkage_specification /* Declarators [gram.dcl.decl] */ static tree cp_parser_init_declarator - (cp_parser *, cp_decl_specifier_seq *, bool, bool, int, bool *); + (cp_parser *, cp_decl_specifier_seq *, tree, bool, bool, int, bool *); static cp_declarator *cp_parser_declarator (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool); static cp_declarator *cp_parser_direct_declarator @@ -1530,7 +1537,7 @@ static enum tree_code cp_parser_ptr_operator static cp_cv_quals cp_parser_cv_qualifier_seq_opt (cp_parser *); static tree cp_parser_declarator_id - (cp_parser *); + (cp_parser *, bool); static tree cp_parser_type_id (cp_parser *); static void cp_parser_type_specifier_seq @@ -1662,6 +1669,10 @@ static bool cp_parser_extension_opt static void cp_parser_label_declaration (cp_parser *); +enum pragma_context { pragma_external, pragma_stmt, pragma_compound }; +static bool cp_parser_pragma + (cp_parser *, enum pragma_context); + /* Objective-C++ Productions */ static tree cp_parser_objc_message_receiver @@ -1694,7 +1705,7 @@ static tree cp_parser_objc_statement /* Utility Routines */ static tree cp_parser_lookup_name - (cp_parser *, tree, enum tag_types, bool, bool, bool, bool *); + (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *); static tree cp_parser_lookup_name_simple (cp_parser *, tree); static tree cp_parser_maybe_treat_template_as_class @@ -1715,8 +1726,10 @@ static tree cp_parser_function_definition_after_declarator (cp_parser *, bool); static void cp_parser_template_declaration_after_export (cp_parser *, bool); +static void cp_parser_perform_template_parameter_access_checks + (tree); static tree cp_parser_single_declaration - (cp_parser *, bool, bool *); + (cp_parser *, tree, bool, bool *); static tree cp_parser_functional_cast (cp_parser *, tree); static tree cp_parser_save_member_function_body @@ -1734,7 +1747,7 @@ static tree cp_parser_sizeof_operand static bool cp_parser_declares_only_class_p (cp_parser *); static void cp_parser_set_storage_class - (cp_decl_specifier_seq *, cp_storage_class); + (cp_parser *, cp_decl_specifier_seq *, enum rid); static void cp_parser_set_decl_spec_type (cp_decl_specifier_seq *, tree, bool); static bool cp_parser_friend_p @@ -1805,6 +1818,8 @@ static void cp_parser_skip_to_closing_brace (cp_parser *); static void cp_parser_skip_until_found (cp_parser *, enum cpp_ttype, const char *); +static void cp_parser_skip_to_pragma_eol + (cp_parser*, cp_token *); static bool cp_parser_error_occurred (cp_parser *); static bool cp_parser_allow_gnu_extensions_p @@ -1847,7 +1862,7 @@ static inline void cp_parser_warn_min_max (void) { if (warn_deprecated && !in_system_header) - warning (0, "minimum/maximum operators are deprecated"); + warning (OPT_Wdeprecated, "minimum/maximum operators are deprecated"); } /* If not parsing tentatively, issue a diagnostic of the form @@ -1865,12 +1880,14 @@ cp_parser_error (cp_parser* parser, const char* message) /* This diagnostic makes more sense if it is tagged to the line of the token we just peeked at. */ cp_lexer_set_source_position_from_token (token); + if (token->type == CPP_PRAGMA) { error ("%<#pragma%> is not allowed here"); - cp_lexer_purge_token (parser->lexer); + cp_parser_skip_to_pragma_eol (parser, token); return; } + c_parse_error (message, /* Because c_parser_error does not understand CPP_KEYWORD, keywords are treated like @@ -2047,7 +2064,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id) if (TREE_CODE (decl) == TEMPLATE_DECL) error ("invalid use of template-name %qE without an argument list", decl); - else if (!parser->scope || parser->scope == error_mark_node) + else if (!parser->scope) { /* Issue an error message. */ error ("%qE does not name a type", id); @@ -2094,7 +2111,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id) } /* Here we diagnose qualified-ids where the scope is actually correct, but the identifier does not resolve to a valid type name. */ - else + else if (parser->scope != error_mark_node) { if (TREE_CODE (parser->scope) == NAMESPACE_DECL) error ("%qE in namespace %qE does not name a type", @@ -2128,7 +2145,8 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser) /*template_keyword_p=*/false, /*check_dependency_p=*/true, /*template_p=*/NULL, - /*declarator_p=*/true); + /*declarator_p=*/true, + /*optional_p=*/false); /* After the id-expression, there should be a plain identifier, otherwise this is not a simple variable declaration. Also, if the scope is dependent, we cannot do much. */ @@ -2164,7 +2182,6 @@ cp_parser_skip_to_closing_parenthesis (cp_parser *parser, { unsigned paren_depth = 0; unsigned brace_depth = 0; - int result; if (recovering && !or_comma && cp_parser_uncommitted_to_tentative_parse_p (parser)) @@ -2172,62 +2189,55 @@ cp_parser_skip_to_closing_parenthesis (cp_parser *parser, while (true) { - cp_token *token; + cp_token * token = cp_lexer_peek_token (parser->lexer); - /* If we've run out of tokens, then there is no closing `)'. */ - if (cp_lexer_next_token_is (parser->lexer, CPP_EOF)) + switch (token->type) { - result = 0; - break; - } + case CPP_EOF: + case CPP_PRAGMA_EOL: + /* If we've run out of tokens, then there is no closing `)'. */ + return 0; - token = cp_lexer_peek_token (parser->lexer); + case CPP_SEMICOLON: + /* This matches the processing in skip_to_end_of_statement. */ + if (!brace_depth) + return 0; + break; - /* This matches the processing in skip_to_end_of_statement. */ - if (token->type == CPP_SEMICOLON && !brace_depth) - { - result = 0; + case CPP_OPEN_BRACE: + ++brace_depth; break; - } - if (token->type == CPP_OPEN_BRACE) - ++brace_depth; - if (token->type == CPP_CLOSE_BRACE) - { + case CPP_CLOSE_BRACE: if (!brace_depth--) - { - result = 0; - break; - } - } - if (recovering && or_comma && token->type == CPP_COMMA - && !brace_depth && !paren_depth) - { - result = -1; + return 0; break; - } - if (!brace_depth) - { - /* If it is an `(', we have entered another level of nesting. */ - if (token->type == CPP_OPEN_PAREN) + case CPP_COMMA: + if (recovering && or_comma && !brace_depth && !paren_depth) + return -1; + break; + + case CPP_OPEN_PAREN: + if (!brace_depth) ++paren_depth; - /* If it is a `)', then we might be done. */ - else if (token->type == CPP_CLOSE_PAREN && !paren_depth--) + break; + + case CPP_CLOSE_PAREN: + if (!brace_depth && !paren_depth--) { if (consume_paren) cp_lexer_consume_token (parser->lexer); - { - result = 1; - break; - } + return 1; } + break; + + default: + break; } /* Consume the token. */ cp_lexer_consume_token (parser->lexer); } - - return result; } /* Consume tokens until we reach the end of the current statement. @@ -2241,31 +2251,34 @@ cp_parser_skip_to_end_of_statement (cp_parser* parser) while (true) { - cp_token *token; + cp_token *token = cp_lexer_peek_token (parser->lexer); - /* Peek at the next token. */ - token = cp_lexer_peek_token (parser->lexer); - /* If we've run out of tokens, stop. */ - if (token->type == CPP_EOF) - break; - /* If the next token is a `;', we have reached the end of the - statement. */ - if (token->type == CPP_SEMICOLON && !nesting_depth) - break; - /* If the next token is a non-nested `}', then we have reached - the end of the current block. */ - if (token->type == CPP_CLOSE_BRACE) + switch (token->type) { - /* If this is a non-nested `}', stop before consuming it. + case CPP_EOF: + case CPP_PRAGMA_EOL: + /* If we've run out of tokens, stop. */ + return; + + case CPP_SEMICOLON: + /* If the next token is a `;', we have reached the end of the + statement. */ + if (!nesting_depth) + return; + break; + + case CPP_CLOSE_BRACE: + /* If this is a non-nested '}', stop before consuming it. That way, when confronted with something like: { 3 + } - we stop before consuming the closing `}', even though we + we stop before consuming the closing '}', even though we have not yet reached a `;'. */ if (nesting_depth == 0) - break; - /* If it is the closing `}' for a block that we have + return; + + /* If it is the closing '}' for a block that we have scanned, stop -- but only after consuming the token. That way given: @@ -2278,13 +2291,17 @@ cp_parser_skip_to_end_of_statement (cp_parser* parser) if (--nesting_depth == 0) { cp_lexer_consume_token (parser->lexer); - break; + return; } + + case CPP_OPEN_BRACE: + ++nesting_depth; + break; + + default: + break; } - /* If it the next token is a `{', then we are entering a new - block. Consume the entire block. */ - else if (token->type == CPP_OPEN_BRACE) - ++nesting_depth; + /* Consume the token. */ cp_lexer_consume_token (parser->lexer); } @@ -2321,15 +2338,12 @@ cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser) { cp_token *token = cp_lexer_peek_token (parser->lexer); - if (token->type == CPP_EOF) - break; - switch (token->type) { case CPP_EOF: + case CPP_PRAGMA_EOL: /* If we've run out of tokens, stop. */ - nesting_depth = -1; - continue; + return; case CPP_SEMICOLON: /* Stop if this is an unnested ';'. */ @@ -2356,7 +2370,6 @@ cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser) /* Consume the token. */ cp_lexer_consume_token (parser->lexer); - } } @@ -2370,26 +2383,67 @@ cp_parser_skip_to_closing_brace (cp_parser *parser) while (true) { - cp_token *token; + cp_token *token = cp_lexer_peek_token (parser->lexer); + + switch (token->type) + { + case CPP_EOF: + case CPP_PRAGMA_EOL: + /* If we've run out of tokens, stop. */ + return; + + case CPP_CLOSE_BRACE: + /* If the next token is a non-nested `}', then we have reached + the end of the current block. */ + if (nesting_depth-- == 0) + return; + break; + + case CPP_OPEN_BRACE: + /* If it the next token is a `{', then we are entering a new + block. Consume the entire block. */ + ++nesting_depth; + break; + + default: + break; + } - /* Peek at the next token. */ - token = cp_lexer_peek_token (parser->lexer); - /* If we've run out of tokens, stop. */ - if (token->type == CPP_EOF) - break; - /* If the next token is a non-nested `}', then we have reached - the end of the current block. */ - if (token->type == CPP_CLOSE_BRACE && nesting_depth-- == 0) - break; - /* If it the next token is a `{', then we are entering a new - block. Consume the entire block. */ - else if (token->type == CPP_OPEN_BRACE) - ++nesting_depth; /* Consume the token. */ cp_lexer_consume_token (parser->lexer); } } +/* Consume tokens until we reach the end of the pragma. The PRAGMA_TOK + parameter is the PRAGMA token, allowing us to purge the entire pragma + sequence. */ + +static void +cp_parser_skip_to_pragma_eol (cp_parser* parser, cp_token *pragma_tok) +{ + cp_token *token; + + parser->lexer->in_pragma = false; + + do + token = cp_lexer_consume_token (parser->lexer); + while (token->type != CPP_PRAGMA_EOL && token->type != CPP_EOF); + + /* Ensure that the pragma is not parsed again. */ + cp_lexer_purge_tokens_after (parser->lexer, pragma_tok); +} + +/* Require pragma end of line, resyncing with it as necessary. The + arguments are as for cp_parser_skip_to_pragma_eol. */ + +static void +cp_parser_require_pragma_eol (cp_parser *parser, cp_token *pragma_tok) +{ + parser->lexer->in_pragma = false; + if (!cp_parser_require (parser, CPP_PRAGMA_EOL, "end of line")) + cp_parser_skip_to_pragma_eol (parser, pragma_tok); +} + /* This is a simple wrapper around make_typename_type. When the id is an unresolved identifier node, we can provide a superior diagnostic using cp_parser_diagnose_invalid_type_name. */ @@ -2401,7 +2455,7 @@ cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id) if (TREE_CODE (id) == IDENTIFIER_NODE) { result = make_typename_type (scope, id, typename_type, - /*complain=*/0); + /*complain=*/tf_none); if (result == error_mark_node) cp_parser_diagnose_invalid_type_name (parser, scope, id); return result; @@ -2459,7 +2513,7 @@ cp_parser_new (void) parser->in_template_argument_list_p = false; /* We are not in an iteration statement. */ - parser->in_iteration_statement_p = false; + parser->in_statement = 0; /* We are not in a switch statement. */ parser->in_switch_statement_p = false; @@ -2656,39 +2710,34 @@ cp_parser_translation_unit (cp_parser* parser) declarator_obstack_base = obstack_next_free (&declarator_obstack); } - while (true) + cp_parser_declaration_seq_opt (parser); + + /* If there are no tokens left then all went well. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_EOF)) + { + /* Get rid of the token array; we don't need it any more. */ + cp_lexer_destroy (parser->lexer); + parser->lexer = NULL; + + /* This file might have been a context that's implicitly extern + "C". If so, pop the lang context. (Only relevant for PCH.) */ + if (parser->implicit_extern_c) + { + pop_lang_context (); + parser->implicit_extern_c = false; + } + + /* Finish up. */ + finish_translation_unit (); + + success = true; + } + else { - cp_parser_declaration_seq_opt (parser); - - /* If there are no tokens left then all went well. */ - if (cp_lexer_next_token_is (parser->lexer, CPP_EOF)) - { - /* Get rid of the token array; we don't need it any more. */ - cp_lexer_destroy (parser->lexer); - parser->lexer = NULL; - - /* This file might have been a context that's implicitly extern - "C". If so, pop the lang context. (Only relevant for PCH.) */ - if (parser->implicit_extern_c) - { - pop_lang_context (); - parser->implicit_extern_c = false; - } - - /* Finish up. */ - finish_translation_unit (); - - success = true; - break; - } - else - { - cp_parser_error (parser, "expected declaration"); - success = false; - break; - } + cp_parser_error (parser, "expected declaration"); + success = false; } - + /* Make sure the declarator obstack was fully cleaned up. */ gcc_assert (obstack_next_free (&declarator_obstack) == declarator_obstack_base); @@ -2712,6 +2761,7 @@ cp_parser_translation_unit (cp_parser* parser) primary-expression: ( compound-statement ) __builtin_va_arg ( assignment-expression , type-id ) + __builtin_offsetof ( type-id , offsetof-expression ) Objective-C++ Extension: @@ -2721,29 +2771,25 @@ cp_parser_translation_unit (cp_parser* parser) literal: __null - CAST_P is true if this primary expression is the target of a cast. - - Returns a representation of the expression. - - *IDK indicates what kind of id-expression (if any) was present. + ADDRESS_P is true iff this expression was immediately preceded by + "&" and therefore might denote a pointer-to-member. CAST_P is true + iff this expression is the target of a cast. TEMPLATE_ARG_P is + true iff this expression is a template argument. - *QUALIFYING_CLASS is set to a non-NULL value if the id-expression can be - used as the operand of a pointer-to-member. In that case, - *QUALIFYING_CLASS gives the class that is used as the qualifying - class in the pointer-to-member. */ + Returns a representation of the expression. Upon return, *IDK + indicates what kind of id-expression (if any) was present. */ static tree cp_parser_primary_expression (cp_parser *parser, + bool address_p, bool cast_p, - cp_id_kind *idk, - tree *qualifying_class) + bool template_arg_p, + cp_id_kind *idk) { cp_token *token; /* Assume the primary expression is not an id-expression. */ *idk = CP_ID_KIND_NONE; - /* And that it cannot be used as pointer-to-member. */ - *qualifying_class = NULL_TREE; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); @@ -2784,7 +2830,10 @@ cp_parser_primary_expression (cp_parser *parser, /* The end of the cast-expression. */ && next_token->type != CPP_CLOSE_PAREN /* The end of an array bound. */ - && next_token->type != CPP_CLOSE_SQUARE) + && next_token->type != CPP_CLOSE_SQUARE + /* The closing ">" in a template-argument-list. */ + && (next_token->type != CPP_GREATER + || parser->greater_than_is_operator_p)) cast_p = false; } @@ -2966,6 +3015,8 @@ cp_parser_primary_expression (cp_parser *parser, tree id_expression; tree decl; const char *error_msg; + bool template_p; + bool done; id_expression: /* Parse the id-expression. */ @@ -2973,30 +3024,38 @@ cp_parser_primary_expression (cp_parser *parser, = cp_parser_id_expression (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, - /*template_p=*/NULL, - /*declarator_p=*/false); + &template_p, + /*declarator_p=*/false, + /*optional_p=*/false); if (id_expression == error_mark_node) return error_mark_node; + token = cp_lexer_peek_token (parser->lexer); + done = (token->type != CPP_OPEN_SQUARE + && token->type != CPP_OPEN_PAREN + && token->type != CPP_DOT + && token->type != CPP_DEREF + && token->type != CPP_PLUS_PLUS + && token->type != CPP_MINUS_MINUS); /* If we have a template-id, then no further lookup is required. If the template-id was for a template-class, we will sometimes have a TYPE_DECL at this point. */ - else if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR - || TREE_CODE (id_expression) == TYPE_DECL) + if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR + || TREE_CODE (id_expression) == TYPE_DECL) decl = id_expression; /* Look up the name. */ else { - bool ambiguous_p; + tree ambiguous_decls; decl = cp_parser_lookup_name (parser, id_expression, none_type, - /*is_template=*/false, + template_p, /*is_namespace=*/false, /*check_dependency=*/true, - &ambiguous_p); + &ambiguous_decls); /* If the lookup was ambiguous, an error will already have been issued. */ - if (ambiguous_p) + if (ambiguous_decls) return error_mark_node; /* In Objective-C++, an instance variable (ivar) may be preferred @@ -3004,14 +3063,9 @@ cp_parser_primary_expression (cp_parser *parser, decl = objc_lookup_ivar (decl, id_expression); /* If name lookup gives us a SCOPE_REF, then the - qualifying scope was dependent. Just propagate the - name. */ + qualifying scope was dependent. */ if (TREE_CODE (decl) == SCOPE_REF) - { - if (TYPE_P (TREE_OPERAND (decl, 0))) - *qualifying_class = TREE_OPERAND (decl, 0); - return decl; - } + return decl; /* Check to see if DECL is a local variable in a context where that is forbidden. */ if (parser->local_variables_forbidden_p @@ -3040,12 +3094,15 @@ cp_parser_primary_expression (cp_parser *parser, } } - decl = finish_id_expression (id_expression, decl, parser->scope, - idk, qualifying_class, - parser->integral_constant_expression_p, - parser->allow_non_integral_constant_expression_p, - &parser->non_integral_constant_expression_p, - &error_msg); + decl = (finish_id_expression + (id_expression, decl, parser->scope, + idk, + parser->integral_constant_expression_p, + parser->allow_non_integral_constant_expression_p, + &parser->non_integral_constant_expression_p, + template_p, done, address_p, + template_arg_p, + &error_msg)); if (error_msg) cp_parser_error (parser, error_msg); return decl; @@ -3102,14 +3159,15 @@ cp_parser_id_expression (cp_parser *parser, bool template_keyword_p, bool check_dependency_p, bool *template_p, - bool declarator_p) + bool declarator_p, + bool optional_p) { bool global_scope_p; bool nested_name_specifier_p; /* Assume the `template' keyword was not used. */ if (template_p) - *template_p = false; + *template_p = template_keyword_p; /* Look for the optional `::' operator. */ global_scope_p @@ -3145,7 +3203,8 @@ cp_parser_id_expression (cp_parser *parser, /* Process the final unqualified-id. */ unqualified_id = cp_parser_unqualified_id (parser, *template_p, check_dependency_p, - declarator_p); + declarator_p, + /*optional_p=*/false); /* Restore the SAVED_SCOPE for our caller. */ parser->scope = saved_scope; parser->object_scope = saved_object_scope; @@ -3203,7 +3262,8 @@ cp_parser_id_expression (cp_parser *parser, else return cp_parser_unqualified_id (parser, template_keyword_p, /*check_dependency_p=*/true, - declarator_p); + declarator_p, + optional_p); } /* Parse an unqualified-id. @@ -3232,7 +3292,8 @@ static tree cp_parser_unqualified_id (cp_parser* parser, bool template_keyword_p, bool check_dependency_p, - bool declarator_p) + bool declarator_p, + bool optional_p) { cp_token *token; @@ -3402,6 +3463,15 @@ cp_parser_unqualified_id (cp_parser* parser, else if (type_decl == error_mark_node) return error_mark_node; + /* Check that destructor name and scope match. */ + if (declarator_p && scope && !check_dtor_name (scope, type_decl)) + { + if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) + error ("declaration of %<~%T%> as member of %qT", + type_decl, scope); + return error_mark_node; + } + /* [class.dtor] A typedef-name that names a class shall not be used as the @@ -3444,6 +3514,8 @@ cp_parser_unqualified_id (cp_parser* parser, /* Fall through. */ default: + if (optional_p) + return NULL_TREE; cp_parser_error (parser, "expected unqualified-id"); return error_mark_node; } @@ -3476,7 +3548,6 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, bool is_declaration) { bool success = false; - tree access_check = NULL_TREE; cp_token_position start = 0; cp_token *token; @@ -3496,9 +3567,10 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, /* Remember where the nested-name-specifier starts. */ if (cp_parser_uncommitted_to_tentative_parse_p (parser)) - start = cp_lexer_token_position (parser->lexer, false); - - push_deferring_access_checks (dk_deferred); + { + start = cp_lexer_token_position (parser->lexer, false); + push_deferring_access_checks (dk_deferred); + } while (true) { @@ -3604,16 +3676,32 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, token = cp_lexer_consume_token (parser->lexer); if (!error_p) { - tree decl; - - decl = cp_parser_lookup_name_simple (parser, token->value); - if (TREE_CODE (decl) == TEMPLATE_DECL) - error ("%qD used without template parameters", decl); - else - cp_parser_name_lookup_error - (parser, token->value, decl, - "is not a class or namespace"); - parser->scope = NULL_TREE; + if (!token->ambiguous_p) + { + tree decl; + tree ambiguous_decls; + + decl = cp_parser_lookup_name (parser, token->value, + none_type, + /*is_template=*/false, + /*is_namespace=*/false, + /*check_dependency=*/true, + &ambiguous_decls); + if (TREE_CODE (decl) == TEMPLATE_DECL) + error ("%qD used without template parameters", decl); + else if (ambiguous_decls) + { + error ("reference to %qD is ambiguous", + token->value); + print_candidates (ambiguous_decls); + decl = error_mark_node; + } + else + cp_parser_name_lookup_error + (parser, token->value, decl, + "is not a class or namespace"); + } + parser->scope = error_mark_node; error_p = true; /* Treat this as a successful nested-name-specifier due to: @@ -3629,29 +3717,38 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, } break; } - /* We've found one valid nested-name-specifier. */ success = true; - /* Make sure we look in the right scope the next time through - the loop. */ - parser->scope = (TREE_CODE (new_scope) == TYPE_DECL - ? TREE_TYPE (new_scope) - : new_scope); + /* Name lookup always gives us a DECL. */ + if (TREE_CODE (new_scope) == TYPE_DECL) + new_scope = TREE_TYPE (new_scope); + /* Uses of "template" must be followed by actual templates. */ + if (template_keyword_p + && !(CLASS_TYPE_P (new_scope) + && ((CLASSTYPE_USE_TEMPLATE (new_scope) + && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (new_scope))) + || CLASSTYPE_IS_TEMPLATE (new_scope))) + && !(TREE_CODE (new_scope) == TYPENAME_TYPE + && (TREE_CODE (TYPENAME_TYPE_FULLNAME (new_scope)) + == TEMPLATE_ID_EXPR))) + pedwarn (TYPE_P (new_scope) + ? "%qT is not a template" + : "%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. */ - if (TYPE_P (parser->scope) + if (TYPE_P (new_scope) /* Since checking types for dependency can be expensive, avoid doing it if the type is already complete. */ - && !COMPLETE_TYPE_P (parser->scope) + && !COMPLETE_TYPE_P (new_scope) /* Do not try to complete dependent types. */ - && !dependent_type_p (parser->scope)) - complete_type (parser->scope); + && !dependent_type_p (new_scope)) + new_scope = complete_type (new_scope); + /* Make sure we look in the right scope the next time through + the loop. */ + parser->scope = new_scope; } - /* Retrieve any deferred checks. Do not pop this access checks yet - so the memory will not be reclaimed during token replacing below. */ - access_check = get_deferred_access_checks (); - /* If parsing tentatively, replace the sequence of tokens that makes up the nested-name-specifier with a CPP_NESTED_NAME_SPECIFIER token. That way, should we re-parse the token stream, we will @@ -3659,19 +3756,27 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, we issue duplicate error messages. */ if (success && start) { - cp_token *token = cp_lexer_token_at (parser->lexer, start); + cp_token *token; + tree access_checks; + token = cp_lexer_token_at (parser->lexer, start); /* Reset the contents of the START token. */ token->type = CPP_NESTED_NAME_SPECIFIER; - token->value = build_tree_list (access_check, parser->scope); + /* Retrieve any deferred checks. Do not pop this access checks yet + so the memory will not be reclaimed during token replacing below. */ + access_checks = get_deferred_access_checks (); + token->value = build_tree_list (copy_list (access_checks), + parser->scope); TREE_TYPE (token->value) = parser->qualifying_scope; token->keyword = RID_MAX; /* Purge all subsequent tokens. */ cp_lexer_purge_tokens_after (parser->lexer, start); } + + if (start) + pop_to_parent_deferring_access_checks (); - pop_deferring_access_checks (); return success ? parser->scope : NULL_TREE; } @@ -3820,10 +3925,6 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) enum rid keyword; cp_id_kind idk = CP_ID_KIND_NONE; tree postfix_expression = NULL_TREE; - /* Non-NULL only if the current postfix-expression can be used to - form a pointer-to-member. In that case, QUALIFYING_CLASS is the - class used to qualify the member. */ - tree qualifying_class = NULL_TREE; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); @@ -3951,53 +4052,12 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) case RID_TYPENAME: { - bool template_p = false; - tree id; tree type; - tree scope; - - /* Consume the `typename' token. */ - cp_lexer_consume_token (parser->lexer); - /* Look for the optional `::' operator. */ - cp_parser_global_scope_opt (parser, - /*current_scope_valid_p=*/false); - /* Look for the nested-name-specifier. In case of error here, - consume the trailing id to avoid subsequent error messages - for usual cases. */ - scope = cp_parser_nested_name_specifier (parser, - /*typename_keyword_p=*/true, - /*check_dependency_p=*/true, - /*type_p=*/true, - /*is_declaration=*/true); - - /* Look for the optional `template' keyword. */ - template_p = cp_parser_optional_template_keyword (parser); - /* We don't know whether we're looking at a template-id or an - identifier. */ - cp_parser_parse_tentatively (parser); - /* Try a template-id. */ - id = cp_parser_template_id (parser, template_p, - /*check_dependency_p=*/true, - /*is_declaration=*/true); - /* If that didn't work, try an identifier. */ - if (!cp_parser_parse_definitely (parser)) - id = cp_parser_identifier (parser); - - /* Don't process id if nested name specifier is invalid. */ - if (!scope || scope == error_mark_node) - return error_mark_node; - /* If we look up a template-id in a non-dependent qualifying - scope, there's no need to create a dependent type. */ - else if (TREE_CODE (id) == TYPE_DECL - && !dependent_type_p (parser->scope)) - type = TREE_TYPE (id); - /* Create a TYPENAME_TYPE to represent the type to which the - functional cast is being performed. */ - else - type = make_typename_type (parser->scope, id, - typename_type, - /*complain=*/1); - + /* The syntax permitted here is the same permitted for an + elaborated-type-specifier. */ + type = cp_parser_elaborated_type_specifier (parser, + /*is_friend=*/false, + /*is_declaration=*/false); postfix_expression = cp_parser_functional_cast (parser, type); } break; @@ -4073,38 +4133,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p) } /* It must be a primary-expression. */ - postfix_expression = cp_parser_primary_expression (parser, - cast_p, - &idk, - &qualifying_class); + postfix_expression + = cp_parser_primary_expression (parser, address_p, cast_p, + /*template_arg_p=*/false, + &idk); } break; } - /* If we were avoiding committing to the processing of a - qualified-id until we knew whether or not we had a - pointer-to-member, we now know. */ - if (qualifying_class) - { - bool done; - - /* Peek at the next token. */ - token = cp_lexer_peek_token (parser->lexer); - done = (token->type != CPP_OPEN_SQUARE - && token->type != CPP_OPEN_PAREN - && token->type != CPP_DOT - && token->type != CPP_DEREF - && token->type != CPP_PLUS_PLUS - && token->type != CPP_MINUS_MINUS); - - postfix_expression = finish_qualified_id_expr (qualifying_class, - postfix_expression, - done, - address_p); - if (done) - return postfix_expression; - } - /* Keep looping until the postfix-expression is complete. */ while (true) { @@ -4237,7 +4273,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_NONVIRTUAL : LOOKUP_NORMAL), + /*fn_p=*/NULL)); else postfix_expression = finish_call_expr (postfix_expression, args, @@ -4392,7 +4429,6 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, { tree name; bool dependent_p; - bool template_p; bool pseudo_destructor_p; tree scope = NULL_TREE; @@ -4419,7 +4455,13 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, underlying type here. */ scope = non_reference (scope); /* The type of the POSTFIX_EXPRESSION must be complete. */ - scope = complete_type_or_else (scope, NULL_TREE); + if (scope == unknown_type_node) + { + error ("%qE does not have class type", postfix_expression); + scope = NULL_TREE; + } + else + scope = complete_type_or_else (scope, NULL_TREE); /* Let the name lookup machinery know that we are processing a class member access expression. */ parser->context->object_type = scope; @@ -4463,12 +4505,15 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, /* If the SCOPE is not a scalar type, we are looking at an ordinary class member access expression, rather than a pseudo-destructor-name. */ - template_p = cp_parser_optional_template_keyword (parser); + bool template_p; /* Parse the id-expression. */ - name = cp_parser_id_expression (parser, template_p, - /*check_dependency_p=*/true, - /*template_p=*/NULL, - /*declarator_p=*/false); + name = (cp_parser_id_expression + (parser, + cp_parser_optional_template_keyword (parser), + /*check_dependency_p=*/true, + &template_p, + /*declarator_p=*/false, + /*optional_p=*/false)); /* In general, build a SCOPE_REF if the member name is qualified. However, if the name was not dependent and has already been resolved; there is no need to build the SCOPE_REF. For example; @@ -4495,7 +4540,10 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, { if (name != error_mark_node && !BASELINK_P (name) && parser->scope) { - name = build_nt (SCOPE_REF, parser->scope, name); + name = build_qualified_name (/*type=*/NULL_TREE, + parser->scope, + name, + template_p); parser->scope = NULL_TREE; parser->qualifying_scope = NULL_TREE; parser->object_scope = NULL_TREE; @@ -4504,7 +4552,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, adjust_result_of_qualified_name_lookup (name, BINFO_TYPE (BASELINK_BINFO (name)), scope); postfix_expression - = finish_class_member_access_expr (postfix_expression, name); + = finish_class_member_access_expr (postfix_expression, name, + template_p); } } @@ -5400,7 +5449,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p) && !in_system_header && !VOID_TYPE_P (type) && current_lang_name != lang_name_c) - warning (0, "use of old-style cast"); + warning (OPT_Wold_style_cast, "use of old-style cast"); /* Only type conversions to integral or enumeration types can be used in constant-expressions. */ @@ -6010,15 +6059,20 @@ cp_parser_builtin_offsetof (cp_parser *parser) iteration-statement jump-statement declaration-statement - try-block */ + try-block + + IN_COMPOUND is true when the statement is nested inside a + cp_parser_compound_statement; this matters for certain pragmas. */ static void -cp_parser_statement (cp_parser* parser, tree in_statement_expr) +cp_parser_statement (cp_parser* parser, tree in_statement_expr, + bool in_compound) { tree statement; cp_token *token; location_t statement_location; + restart: /* There is no statement yet. */ statement = NULL_TREE; /* Peek at the next token. */ @@ -6035,8 +6089,8 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr) { case RID_CASE: case RID_DEFAULT: - statement = cp_parser_labeled_statement (parser, - in_statement_expr); + statement = cp_parser_labeled_statement (parser, in_statement_expr, + in_compound); break; case RID_IF: @@ -6082,7 +6136,8 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr) labeled-statement. */ token = cp_lexer_peek_nth_token (parser->lexer, 2); if (token->type == CPP_COLON) - statement = cp_parser_labeled_statement (parser, in_statement_expr); + statement = cp_parser_labeled_statement (parser, in_statement_expr, + in_compound); } /* Anything that starts with a `{' must be a compound-statement. */ else if (token->type == CPP_OPEN_BRACE) @@ -6091,7 +6146,20 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr) a statement all its own. */ else if (token->type == CPP_PRAGMA) { - cp_lexer_handle_pragma (parser->lexer); + /* Only certain OpenMP pragmas are attached to statements, and thus + are considered statements themselves. All others are not. In + the context of a compound, accept the pragma as a "statement" and + return so that we can check for a close brace. Otherwise we + require a real statement and must go back and read one. */ + if (in_compound) + cp_parser_pragma (parser, pragma_compound); + else if (!cp_parser_pragma (parser, pragma_stmt)) + goto restart; + return; + } + else if (token->type == CPP_EOF) + { + cp_parser_error (parser, "expected statement"); return; } @@ -6132,10 +6200,14 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr) case constant-expression ... constant-expression : statement Returns the new CASE_LABEL_EXPR, for a `case' or `default' label. - For an ordinary label, returns a LABEL_EXPR. */ + For an ordinary label, returns a LABEL_EXPR. + + IN_COMPOUND is as for cp_parser_statement: true when we're nested + inside a compound. */ static tree -cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr) +cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr, + bool in_compound) { cp_token *token; tree statement = error_mark_node; @@ -6178,20 +6250,21 @@ cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr) else expr_hi = NULL_TREE; - if (!parser->in_switch_statement_p) - error ("case label %qE not within a switch statement", expr); - else + if (parser->in_switch_statement_p) statement = finish_case_label (expr, expr_hi); + else + error ("case label %qE not within a switch statement", expr); } break; case RID_DEFAULT: /* Consume the `default' token. */ cp_lexer_consume_token (parser->lexer); - if (!parser->in_switch_statement_p) - error ("case label not within a switch statement"); - else + + if (parser->in_switch_statement_p) statement = finish_case_label (NULL_TREE, NULL_TREE); + else + error ("case label not within a switch statement"); break; default: @@ -6203,7 +6276,7 @@ cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr) /* Require the `:' token. */ cp_parser_require (parser, CPP_COLON, "`:'"); /* Parse the labeled statement. */ - cp_parser_statement (parser, in_statement_expr); + cp_parser_statement (parser, in_statement_expr, in_compound); /* Return the label, in the case of a `case' or `default' label. */ return statement; @@ -6285,13 +6358,16 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr) /* Scan statements until there aren't any more. */ while (true) { + cp_token *token = cp_lexer_peek_token (parser->lexer); + /* If we're looking at a `}', then we've run out of statements. */ - if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE) - || cp_lexer_next_token_is (parser->lexer, CPP_EOF)) + if (token->type == CPP_CLOSE_BRACE + || token->type == CPP_EOF + || token->type == CPP_PRAGMA_EOL) break; /* Parse the statement. */ - cp_parser_statement (parser, in_statement_expr); + cp_parser_statement (parser, in_statement_expr, true); } } @@ -6370,15 +6446,19 @@ cp_parser_selection_statement (cp_parser* parser) else { bool in_switch_statement_p; + unsigned char in_statement; /* Add the condition. */ finish_switch_cond (condition, statement); /* Parse the body of the switch-statement. */ in_switch_statement_p = parser->in_switch_statement_p; + in_statement = parser->in_statement; parser->in_switch_statement_p = true; + parser->in_statement |= IN_SWITCH_STMT; cp_parser_implicitly_scoped_statement (parser); parser->in_switch_statement_p = in_switch_statement_p; + parser->in_statement = in_statement; /* Now we're all done with the switch-statement. */ finish_switch_stmt (statement); @@ -6457,6 +6537,7 @@ cp_parser_condition (cp_parser* parser) if (cp_parser_parse_definitely (parser)) { tree pushed_scope; + bool non_constant_p; /* Create the declaration. */ decl = start_decl (declarator, &type_specifiers, @@ -6464,12 +6545,16 @@ cp_parser_condition (cp_parser* parser) attributes, /*prefix_attributes=*/NULL_TREE, &pushed_scope); /* Parse the assignment-expression. */ - initializer = cp_parser_assignment_expression (parser, - /*cast_p=*/false); + initializer + = cp_parser_constant_expression (parser, + /*allow_non_constant_p=*/true, + &non_constant_p); + if (!non_constant_p) + initializer = fold_non_dependent_expr (initializer); /* Process the initializer. */ cp_finish_decl (decl, - initializer, + initializer, !non_constant_p, asm_specification, LOOKUP_ONLYCONVERTING); @@ -6504,8 +6589,7 @@ cp_parser_iteration_statement (cp_parser* parser) cp_token *token; enum rid keyword; tree statement; - bool in_iteration_statement_p; - + unsigned char in_statement; /* Peek at the next token. */ token = cp_parser_require (parser, CPP_KEYWORD, "iteration-statement"); @@ -6514,7 +6598,7 @@ cp_parser_iteration_statement (cp_parser* parser) /* Remember whether or not we are already within an iteration statement. */ - in_iteration_statement_p = parser->in_iteration_statement_p; + in_statement = parser->in_statement; /* See what kind of keyword it is. */ keyword = token->keyword; @@ -6534,9 +6618,9 @@ cp_parser_iteration_statement (cp_parser* parser) /* Look for the `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); /* Parse the dependent statement. */ - parser->in_iteration_statement_p = true; + parser->in_statement = IN_ITERATION_STMT; cp_parser_already_scoped_statement (parser); - parser->in_iteration_statement_p = in_iteration_statement_p; + parser->in_statement = in_statement; /* We're done with the while-statement. */ finish_while_stmt (statement); } @@ -6549,9 +6633,9 @@ cp_parser_iteration_statement (cp_parser* parser) /* Begin the do-statement. */ statement = begin_do_stmt (); /* Parse the body of the do-statement. */ - parser->in_iteration_statement_p = true; + parser->in_statement = IN_ITERATION_STMT; cp_parser_implicitly_scoped_statement (parser); - parser->in_iteration_statement_p = in_iteration_statement_p; + parser->in_statement = in_statement; finish_do_body (statement); /* Look for the `while' keyword. */ cp_parser_require_keyword (parser, RID_WHILE, "`while'"); @@ -6596,9 +6680,9 @@ cp_parser_iteration_statement (cp_parser* parser) cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); /* Parse the body of the for-statement. */ - parser->in_iteration_statement_p = true; + parser->in_statement = IN_ITERATION_STMT; cp_parser_already_scoped_statement (parser); - parser->in_iteration_statement_p = in_iteration_statement_p; + parser->in_statement = in_statement; /* We're done with the for-statement. */ finish_for_stmt (statement); @@ -6678,25 +6762,42 @@ cp_parser_jump_statement (cp_parser* parser) switch (keyword) { case RID_BREAK: - if (!parser->in_switch_statement_p - && !parser->in_iteration_statement_p) + switch (parser->in_statement) { + case 0: error ("break statement not within loop or switch"); - statement = error_mark_node; + break; + default: + gcc_assert ((parser->in_statement & IN_SWITCH_STMT) + || parser->in_statement == IN_ITERATION_STMT); + statement = finish_break_stmt (); + break; + case IN_OMP_BLOCK: + error ("invalid exit from OpenMP structured block"); + break; + case IN_OMP_FOR: + error ("break statement used with OpenMP for loop"); + break; } - else - statement = finish_break_stmt (); cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"); break; case RID_CONTINUE: - if (!parser->in_iteration_statement_p) + switch (parser->in_statement & ~IN_SWITCH_STMT) { + case 0: error ("continue statement not within a loop"); - statement = error_mark_node; + break; + case IN_ITERATION_STMT: + case IN_OMP_FOR: + statement = finish_continue_stmt (); + break; + case IN_OMP_BLOCK: + error ("invalid exit from OpenMP structured block"); + break; + default: + gcc_unreachable (); } - else - statement = finish_continue_stmt (); cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"); break; @@ -6782,19 +6883,25 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser) { tree statement; + /* Mark if () ; with a special NOP_EXPR. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) + { + cp_lexer_consume_token (parser->lexer); + statement = add_stmt (build_empty_stmt ()); + } + /* 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); /* If the token is not a `{', then we must take special action. */ - if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)) + else { /* Create a compound-statement. */ statement = begin_compound_stmt (0); /* Parse the dependent-statement. */ - cp_parser_statement (parser, false); + cp_parser_statement (parser, NULL_TREE, false); /* Finish the dummy compound-statement. */ finish_compound_stmt (statement); } - /* Otherwise, we simply parse the statement directly. */ - else - statement = cp_parser_compound_statement (parser, NULL, false); /* Return the statement. */ return statement; @@ -6810,13 +6917,13 @@ cp_parser_already_scoped_statement (cp_parser* parser) { /* If the token is a `{', then we must take special action. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)) - cp_parser_statement (parser, false); + cp_parser_statement (parser, NULL_TREE, false); else { /* Avoid calling cp_parser_compound_statement, so that we don't create a new scope. Do everything else by hand. */ cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"); - cp_parser_statement_seq_opt (parser, false); + cp_parser_statement_seq_opt (parser, NULL_TREE); cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); } } @@ -6839,7 +6946,8 @@ cp_parser_declaration_seq_opt (cp_parser* parser) token = cp_lexer_peek_token (parser->lexer); if (token->type == CPP_CLOSE_BRACE - || token->type == CPP_EOF) + || token->type == CPP_EOF + || token->type == CPP_PRAGMA_EOL) break; if (token->type == CPP_SEMICOLON) @@ -6871,7 +6979,7 @@ cp_parser_declaration_seq_opt (cp_parser* parser) A nested declaration cannot, so this is done here and not in cp_parser_declaration. (A #pragma at block scope is handled in cp_parser_statement.) */ - cp_lexer_handle_pragma (parser->lexer); + cp_parser_pragma (parser, pragma_external); continue; } @@ -6921,7 +7029,10 @@ cp_parser_declaration (cp_parser* parser) if (token1.type != CPP_EOF) token2 = *cp_lexer_peek_nth_token (parser->lexer, 2); else - token2.type = token2.keyword = RID_MAX; + { + token2.type = CPP_EOF; + token2.keyword = RID_MAX; + } /* Get the high-water mark for the DECLARATOR_OBSTACK. */ p = obstack_alloc (&declarator_obstack, 0); @@ -6966,9 +7077,10 @@ cp_parser_declaration (cp_parser* parser) && (/* A named namespace definition. */ (token2.type == CPP_NAME && (cp_lexer_peek_nth_token (parser->lexer, 3)->type - == CPP_OPEN_BRACE)) + != CPP_EQ)) /* An unnamed namespace definition. */ - || token2.type == CPP_OPEN_BRACE)) + || token2.type == CPP_OPEN_BRACE + || token2.keyword == RID_ATTRIBUTE)) cp_parser_namespace_definition (parser); /* Objective-C++ declaration/definition. */ else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1.keyword)) @@ -7149,9 +7261,19 @@ cp_parser_simple_declaration (cp_parser* parser, bool function_definition_p; tree decl; - saw_declarator = true; + if (saw_declarator) + { + /* If we are processing next declarator, coma is expected */ + token = cp_lexer_peek_token (parser->lexer); + gcc_assert (token->type == CPP_COMMA); + cp_lexer_consume_token (parser->lexer); + } + else + saw_declarator = true; + /* Parse the init-declarator. */ decl = cp_parser_init_declarator (parser, &decl_specifiers, + /*checks=*/NULL_TREE, function_definition_allowed_p, /*member_p=*/false, declares_class_or_enum, @@ -7184,7 +7306,7 @@ cp_parser_simple_declaration (cp_parser* parser, token = cp_lexer_peek_token (parser->lexer); /* If it's a `,', there are more declarators to come. */ if (token->type == CPP_COMMA) - cp_lexer_consume_token (parser->lexer); + /* will be consumed next time around */; /* If it's a `;', we are done. */ else if (token->type == CPP_SEMICOLON) break; @@ -7268,6 +7390,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser, int* declares_class_or_enum) { bool constructor_possible_p = !parser->in_declarator_p; + cp_decl_spec ds; /* Clear DECL_SPECS. */ clear_decl_specs (decl_specs); @@ -7302,8 +7425,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser, /* decl-specifier: friend */ case RID_FRIEND: - if (decl_specs->specs[(int) ds_friend]++) - error ("duplicate %"); + ++decl_specs->specs[(int) ds_friend]; /* Consume the token. */ cp_lexer_consume_token (parser->lexer); break; @@ -7341,39 +7463,13 @@ cp_parser_decl_specifier_seq (cp_parser* parser, GNU Extension: thread */ case RID_AUTO: - /* Consume the token. */ - cp_lexer_consume_token (parser->lexer); - cp_parser_set_storage_class (decl_specs, sc_auto); - break; case RID_REGISTER: - /* Consume the token. */ - cp_lexer_consume_token (parser->lexer); - cp_parser_set_storage_class (decl_specs, sc_register); - break; case RID_STATIC: - /* Consume the token. */ - cp_lexer_consume_token (parser->lexer); - if (decl_specs->specs[(int) ds_thread]) - { - error ("%<__thread%> before %"); - decl_specs->specs[(int) ds_thread] = 0; - } - cp_parser_set_storage_class (decl_specs, sc_static); - break; case RID_EXTERN: - /* Consume the token. */ - cp_lexer_consume_token (parser->lexer); - if (decl_specs->specs[(int) ds_thread]) - { - error ("%<__thread%> before %"); - decl_specs->specs[(int) ds_thread] = 0; - } - cp_parser_set_storage_class (decl_specs, sc_extern); - break; case RID_MUTABLE: /* Consume the token. */ cp_lexer_consume_token (parser->lexer); - cp_parser_set_storage_class (decl_specs, sc_mutable); + cp_parser_set_storage_class (parser, decl_specs, token->keyword); break; case RID_THREAD: /* Consume the token. */ @@ -7469,6 +7565,42 @@ cp_parser_decl_specifier_seq (cp_parser* parser, flags |= CP_PARSER_FLAGS_OPTIONAL; } + /* Check for repeated decl-specifiers. */ + for (ds = ds_first; ds != ds_last; ++ds) + { + unsigned count = decl_specs->specs[(int)ds]; + if (count < 2) + continue; + /* The "long" specifier is a special case because of "long long". */ + if (ds == ds_long) + { + if (count > 2) + error ("% is too long for GCC"); + else if (pedantic && !in_system_header && warn_long_long) + pedwarn ("ISO C++ does not support %"); + } + else if (count > 1) + { + static const char *const decl_spec_names[] = { + "signed", + "unsigned", + "short", + "long", + "const", + "volatile", + "restrict", + "inline", + "virtual", + "explicit", + "friend", + "typedef", + "__complex", + "__thread" + }; + error ("duplicate %qs", decl_spec_names[(int)ds]); + } + } + /* Don't allow a friend specifier with a class definition. */ if (decl_specs->specs[(int) ds_friend] != 0 && (*declares_class_or_enum & 2)) @@ -7532,7 +7664,12 @@ cp_parser_function_specifier_opt (cp_parser* parser, break; case RID_VIRTUAL: - if (decl_specs) + /* 14.5.2.3 [temp.mem] + + A member function template shall not be virtual. */ + if (PROCESSING_REAL_TEMPLATE_DECL_P ()) + error ("templates may not be %"); + else if (decl_specs) ++decl_specs->specs[(int) ds_virtual]; break; @@ -7796,7 +7933,7 @@ cp_parser_mem_initializer_list (cp_parser* parser) /* Parse the mem-initializer. */ mem_initializer = cp_parser_mem_initializer (parser); /* Add it to the list, unless it was erroneous. */ - if (mem_initializer) + if (mem_initializer != error_mark_node) { TREE_CHAIN (mem_initializer) = mem_initializer_list; mem_initializer_list = mem_initializer; @@ -7825,7 +7962,8 @@ cp_parser_mem_initializer_list (cp_parser* parser) Returns a TREE_LIST. The TREE_PURPOSE is the TYPE (for a base class) or FIELD_DECL (for a non-static data member) to initialize; - the TREE_VALUE is the expression-list. */ + the TREE_VALUE is the expression-list. An empty initialization + list is represented by void_list_node. */ static tree cp_parser_mem_initializer (cp_parser* parser) @@ -7850,12 +7988,14 @@ cp_parser_mem_initializer (cp_parser* parser) = cp_parser_parenthesized_expression_list (parser, false, /*cast_p=*/false, /*non_constant_p=*/NULL); + if (expression_list == error_mark_node) + return error_mark_node; if (!expression_list) expression_list = void_type_node; in_base_initializer = 0; - return member ? build_tree_list (member, expression_list) : NULL_TREE; + return member ? build_tree_list (member, expression_list) : error_mark_node; } /* Parse a mem-initializer-id. @@ -8265,6 +8405,7 @@ cp_parser_template_parameter_list (cp_parser* parser) { tree parameter_list = NULL_TREE; + begin_template_parm_list (); while (true) { tree parameter; @@ -8287,7 +8428,7 @@ cp_parser_template_parameter_list (cp_parser* parser) cp_lexer_consume_token (parser->lexer); } - return parameter_list; + return end_template_parm_list (parameter_list); } /* Parse a template-parameter. @@ -8415,7 +8556,9 @@ cp_parser_type_parameter (cp_parser* parser) /* Consume the `=' token. */ cp_lexer_consume_token (parser->lexer); /* Parse the default-argument. */ + push_deferring_access_checks (dk_no_deferred); default_argument = cp_parser_type_id (parser); + pop_deferring_access_checks (); } else default_argument = NULL_TREE; @@ -8435,10 +8578,7 @@ cp_parser_type_parameter (cp_parser* parser) /* Look for the `<'. */ cp_parser_require (parser, CPP_LESS, "`<'"); /* Parse the template-parameter-list. */ - begin_template_parm_list (); - parameter_list - = cp_parser_template_parameter_list (parser); - parameter_list = end_template_parm_list (parameter_list); + parameter_list = cp_parser_template_parameter_list (parser); /* Look for the `>'. */ cp_parser_require (parser, CPP_GREATER, "`>'"); /* Look for the `class' keyword. */ @@ -8472,12 +8612,14 @@ cp_parser_type_parameter (cp_parser* parser) /* Consume the `='. */ cp_lexer_consume_token (parser->lexer); /* Parse the id-expression. */ + push_deferring_access_checks (dk_no_deferred); default_argument = cp_parser_id_expression (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, /*template_p=*/&is_template, - /*declarator_p=*/false); + /*declarator_p=*/false, + /*optional_p=*/false); if (TREE_CODE (default_argument) == TYPE_DECL) /* If the id-expression was a template-id that refers to a template-class, we already have the declaration here, @@ -8491,10 +8633,11 @@ cp_parser_type_parameter (cp_parser* parser) /*is_template=*/is_template, /*is_namespace=*/false, /*check_dependency=*/true, - /*ambiguous_p=*/NULL); + /*ambiguous_decls=*/NULL); /* See if the default argument is valid. */ default_argument = check_template_template_default_arg (default_argument); + pop_deferring_access_checks (); } else default_argument = NULL_TREE; @@ -8847,7 +8990,7 @@ cp_parser_template_name (cp_parser* parser, /*is_template=*/false, /*is_namespace=*/false, check_dependency_p, - /*ambiguous_p=*/NULL); + /*ambiguous_decls=*/NULL); decl = maybe_get_template_decl_from_type_decl (decl); /* If DECL is a template, then the name was a template-name. */ @@ -8905,9 +9048,19 @@ cp_parser_template_argument_list (cp_parser* parser) tree *arg_ary = fixed_args; tree vec; bool saved_in_template_argument_list_p; + bool saved_ice_p; + bool saved_non_ice_p; saved_in_template_argument_list_p = parser->in_template_argument_list_p; parser->in_template_argument_list_p = true; + /* Even if the template-id appears in an integral + constant-expression, the contents of the argument list do + not. */ + saved_ice_p = parser->integral_constant_expression_p; + 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 { tree argument; @@ -8924,11 +9077,11 @@ cp_parser_template_argument_list (cp_parser* parser) if (arg_ary == fixed_args) { - arg_ary = xmalloc (sizeof (tree) * alloced); + arg_ary = XNEWVEC (tree, alloced); memcpy (arg_ary, fixed_args, sizeof (tree) * n_args); } else - arg_ary = xrealloc (arg_ary, sizeof (tree) * alloced); + arg_ary = XRESIZEVEC (tree, arg_ary, alloced); } arg_ary[n_args++] = argument; } @@ -8941,6 +9094,8 @@ cp_parser_template_argument_list (cp_parser* parser) if (arg_ary != fixed_args) free (arg_ary); + parser->non_integral_constant_expression_p = saved_non_ice_p; + parser->integral_constant_expression_p = saved_ice_p; parser->in_template_argument_list_p = saved_in_template_argument_list_p; return vec; } @@ -8970,7 +9125,6 @@ cp_parser_template_argument (cp_parser* parser) bool maybe_type_id = false; cp_token *token; cp_id_kind idk; - tree qualifying_class; /* There's really no way to know what we're looking at, so we just try each alternative in order. @@ -9020,7 +9174,8 @@ cp_parser_template_argument (cp_parser* parser) /*template_keyword_p=*/false, /*check_dependency_p=*/true, &template_p, - /*declarator_p=*/false); + /*declarator_p=*/false, + /*optional_p=*/false); /* If the next token isn't a `,' or a `>', then this argument wasn't really finished. */ if (!cp_parser_next_token_ends_template_argument_p (parser)) @@ -9037,7 +9192,7 @@ cp_parser_template_argument (cp_parser* parser) /*is_template=*/template_p, /*is_namespace=*/false, /*check_dependency=*/true, - /*ambiguous_p=*/NULL); + /*ambiguous_decls=*/NULL); if (TREE_CODE (argument) != TEMPLATE_DECL && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE) cp_parser_error (parser, "expected template-name"); @@ -9062,9 +9217,10 @@ cp_parser_template_argument (cp_parser* parser) { cp_parser_parse_tentatively (parser); argument = cp_parser_primary_expression (parser, + /*adress_p=*/false, /*cast_p=*/false, - &idk, - &qualifying_class); + /*template_arg_p=*/true, + &idk); if (TREE_CODE (argument) != TEMPLATE_PARM_INDEX || !cp_parser_next_token_ends_template_argument_p (parser)) cp_parser_simulate_error (parser); @@ -9087,9 +9243,10 @@ cp_parser_template_argument (cp_parser* parser) { cp_parser_parse_tentatively (parser); argument = cp_parser_primary_expression (parser, + address_p, /*cast_p=*/false, - &idk, - &qualifying_class); + /*template_arg_p=*/true, + &idk); if (cp_parser_error_occurred (parser) || !cp_parser_next_token_ends_template_argument_p (parser)) cp_parser_abort_tentative_parse (parser); @@ -9101,11 +9258,11 @@ cp_parser_template_argument (cp_parser* parser) argument = TREE_OPERAND (argument, 0); } - if (qualifying_class) - argument = finish_qualified_id_expr (qualifying_class, - argument, - /*done=*/true, - address_p); + if (TREE_CODE (argument) == BASELINK) + /* We don't need the information about what class was used + to name the overloaded functions. */ + argument = BASELINK_FUNCTIONS (argument); + if (TREE_CODE (argument) == VAR_DECL) { /* A variable without external linkage might still be a @@ -9234,7 +9391,8 @@ cp_parser_explicit_instantiation (cp_parser* parser) template instantiation. */ pop_deferring_access_checks (); if (type) - do_type_instantiation (type, extension_specifier, /*complain=*/1); + do_type_instantiation (type, extension_specifier, + /*complain=*/tf_error); } else { @@ -9289,6 +9447,7 @@ cp_parser_explicit_instantiation (cp_parser* parser) static void cp_parser_explicit_specialization (cp_parser* parser) { + bool need_lang_pop; /* Look for the `template' keyword. */ cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'"); /* Look for the `<'. */ @@ -9297,9 +9456,22 @@ cp_parser_explicit_specialization (cp_parser* parser) cp_parser_require (parser, CPP_GREATER, "`>'"); /* We have processed another parameter list. */ ++parser->num_template_parameter_lists; + /* [temp] + + A template ... explicit specialization ... shall not have C + linkage. */ + if (current_lang_name == lang_name_c) + { + error ("template specialization with C linkage"); + /* Give it C++ linkage to avoid confusing other parts of the + front end. */ + push_lang_context (lang_name_cplusplus); + need_lang_pop = true; + } + else + need_lang_pop = false; /* Let the front end know that we are beginning a specialization. */ begin_specialization (); - /* If the next keyword is `template', we need to figure out whether or not we're looking a template-declaration. */ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE)) @@ -9314,11 +9486,15 @@ cp_parser_explicit_specialization (cp_parser* parser) else /* Parse the dependent declaration. */ cp_parser_single_declaration (parser, + /*checks=*/NULL_TREE, /*member_p=*/false, /*friend_p=*/NULL); - /* We're done with the specialization. */ end_specialization (); + /* For the erroneous case of a template with C linkage, we pushed an + implicit C++ linkage scope; exit that scope now. */ + if (need_lang_pop) + pop_lang_context (); /* We're done with this parameter list. */ --parser->num_template_parameter_lists; } @@ -9927,7 +10103,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, && tag_type == typename_type) type = make_typename_type (parser->scope, decl, typename_type, - /*complain=*/1); + /*complain=*/tf_error); else type = TREE_TYPE (decl); } @@ -9958,7 +10134,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, /*is_template=*/false, /*is_namespace=*/false, /*check_dependency=*/true, - /*ambiguous_p=*/NULL); + /*ambiguous_decls=*/NULL); /* If we are parsing friend declaration, DECL may be a TEMPLATE_DECL tree node here. However, we need to check @@ -10047,6 +10223,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, declaration context. */ tag_scope ts; + bool template_p; + if (is_friend) /* Friends have special name lookup rules. */ ts = ts_within_enclosing_non_class; @@ -10063,8 +10241,16 @@ cp_parser_elaborated_type_specifier (cp_parser* parser, warning (OPT_Wattributes, "type attributes are honored only at type definition"); - type = xref_tag (tag_type, identifier, ts, - parser->num_template_parameter_lists); + template_p = + (parser->num_template_parameter_lists + && (cp_parser_next_token_starts_class_definition_p (parser) + || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))); + /* An unqualified name was used to reference this type, so + there were no qualifying templates. */ + if (!cp_parser_check_template_parameters (parser, + /*num_templates=*/0)) + return error_mark_node; + type = xref_tag (tag_type, identifier, ts, template_p); } } if (tag_type != enum_type) @@ -10249,7 +10435,7 @@ cp_parser_namespace_name (cp_parser* parser) /*is_template=*/false, /*is_namespace=*/true, /*check_dependency=*/true, - /*ambiguous_p=*/NULL); + /*ambiguous_decls=*/NULL); /* If it's not a namespace, issue an error. */ if (namespace_decl == error_mark_node || TREE_CODE (namespace_decl) != NAMESPACE_DECL) @@ -10285,7 +10471,7 @@ cp_parser_namespace_name (cp_parser* parser) static void cp_parser_namespace_definition (cp_parser* parser) { - tree identifier; + tree identifier, attribs; /* Look for the `namespace' keyword. */ cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'"); @@ -10299,10 +10485,13 @@ cp_parser_namespace_definition (cp_parser* parser) else identifier = NULL_TREE; + /* Parse any specified attributes. */ + attribs = cp_parser_attributes_opt (parser); + /* Look for the `{' to start the namespace. */ cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"); /* Start the namespace. */ - push_namespace (identifier); + push_namespace_with_attribs (identifier, attribs); /* Parse the body of the namespace. */ cp_parser_namespace_body (parser); /* Finish the namespace. */ @@ -10434,11 +10623,12 @@ cp_parser_using_declaration (cp_parser* parser) identifier = cp_parser_unqualified_id (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, - /*declarator_p=*/true); + /*declarator_p=*/true, + /*optional_p=*/false); /* The function we call to handle a using-declaration is different depending on what scope we are in. */ - if (identifier == error_mark_node) + if (qscope == error_mark_node || identifier == error_mark_node) ; else if (TREE_CODE (identifier) != IDENTIFIER_NODE && TREE_CODE (identifier) != BIT_NOT_EXPR) @@ -10642,7 +10832,7 @@ cp_parser_asm_definition (cp_parser* parser) } } else - assemble_asm (string); + cgraph_add_asm_node (string); } /* Declarators [gram.dcl.decl] */ @@ -10667,10 +10857,14 @@ cp_parser_asm_definition (cp_parser* parser) function-definition: __extension__ function-definition - The DECL_SPECIFIERS and PREFIX_ATTRIBUTES apply to this declarator. - Returns a representation of the entity declared. If MEMBER_P is TRUE, - then this declarator appears in a class scope. The new DECL created - by this declarator is returned. + The DECL_SPECIFIERS apply to this declarator. Returns a + representation of the entity declared. If MEMBER_P is TRUE, then + this declarator appears in a class scope. The new DECL created by + this declarator is returned. + + The CHECKS are access checks that should be performed once we know + what entity is being declared (and, therefore, what classes have + befriended it). If FUNCTION_DEFINITION_ALLOWED_P then we handle the declarator and for a function-definition here as well. If the declarator is a @@ -10684,6 +10878,7 @@ cp_parser_asm_definition (cp_parser* parser) static tree cp_parser_init_declarator (cp_parser* parser, cp_decl_specifier_seq *decl_specifiers, + tree checks, bool function_definition_allowed_p, bool member_p, int declares_class_or_enum, @@ -10698,7 +10893,11 @@ cp_parser_init_declarator (cp_parser* parser, tree decl = NULL_TREE; tree scope; bool is_initialized; - bool is_parenthesized_init; + /* Only valid if IS_INITIALIZED is true. In that case, CPP_EQ if + initialized with "= ..", CPP_OPEN_PAREN if initialized with + "(...)". */ + enum cpp_ttype initialization_kind; + bool is_parenthesized_init = false; bool is_non_constant_init; int ctor_dtor_or_conv_p; bool friend_p; @@ -10812,16 +11011,24 @@ cp_parser_init_declarator (cp_parser* parser, } /* An `=' or an `(' indicates an initializer. */ - is_initialized = (token->type == CPP_EQ - || token->type == CPP_OPEN_PAREN); - /* If the init-declarator isn't initialized and isn't followed by a - `,' or `;', it's not a valid init-declarator. */ - if (!is_initialized - && token->type != CPP_COMMA - && token->type != CPP_SEMICOLON) + if (token->type == CPP_EQ + || token->type == CPP_OPEN_PAREN) { - cp_parser_error (parser, "expected initializer"); - return error_mark_node; + is_initialized = true; + initialization_kind = token->type; + } + else + { + /* If the init-declarator isn't initialized and isn't followed by a + `,' or `;', it's not a valid init-declarator. */ + if (token->type != CPP_COMMA + && token->type != CPP_SEMICOLON) + { + cp_parser_error (parser, "expected initializer"); + return error_mark_node; + } + is_initialized = false; + initialization_kind = CPP_EOF; } /* Because start_decl has side-effects, we should only call it if we @@ -10881,6 +11088,9 @@ cp_parser_init_declarator (cp_parser* parser, current_function_decl = decl; } + /* Perform access checks for template parameters. */ + cp_parser_perform_template_parameter_access_checks (checks); + /* Perform the access control checks for the declarator and the the decl-specifiers. */ perform_deferred_access_checks (); @@ -10891,15 +11101,19 @@ cp_parser_init_declarator (cp_parser* parser, } /* Parse the initializer. */ + initializer = NULL_TREE; + is_parenthesized_init = false; + is_non_constant_init = true; if (is_initialized) - initializer = cp_parser_initializer (parser, - &is_parenthesized_init, - &is_non_constant_init); - else { - initializer = NULL_TREE; - is_parenthesized_init = false; - is_non_constant_init = true; + if (declarator->kind == cdk_function + && declarator->declarator->kind == cdk_id + && initialization_kind == CPP_EQ) + initializer = cp_parser_pure_specifier (parser); + else + initializer = cp_parser_initializer (parser, + &is_parenthesized_init, + &is_non_constant_init); } /* The old parser allows attributes to appear after a parenthesized @@ -10921,8 +11135,9 @@ cp_parser_init_declarator (cp_parser* parser, pushed_scope = false; } decl = grokfield (declarator, decl_specifiers, - initializer, /*asmspec=*/NULL_TREE, - /*attributes=*/NULL_TREE); + initializer, !is_non_constant_init, + /*asmspec=*/NULL_TREE, + prefix_attributes); if (decl && TREE_CODE (decl) == FUNCTION_DECL) cp_parser_save_default_args (parser, decl); } @@ -10932,7 +11147,7 @@ cp_parser_init_declarator (cp_parser* parser, if (!friend_p && decl && decl != error_mark_node) { cp_finish_decl (decl, - initializer, + initializer, !is_non_constant_init, asm_specification, /* If the initializer is in parentheses, then this is a direct-initialization, which means that an @@ -10944,12 +11159,6 @@ cp_parser_init_declarator (cp_parser* parser, if (!friend_p && pushed_scope) pop_scope (pushed_scope); - /* Remember whether or not variables were initialized by - constant-expressions. */ - if (decl && TREE_CODE (decl) == VAR_DECL - && is_initialized && !is_non_constant_init) - DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true; - return decl; } @@ -11313,25 +11522,32 @@ cp_parser_direct_declarator (cp_parser* parser, { tree qualifying_scope; tree unqualified_name; + special_function_kind sfk; + bool abstract_ok; /* Parse a declarator-id */ - if (dcl_kind == CP_PARSER_DECLARATOR_EITHER) + abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER); + if (abstract_ok) cp_parser_parse_tentatively (parser); - unqualified_name = cp_parser_declarator_id (parser); + unqualified_name + = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok); qualifying_scope = parser->scope; - if (dcl_kind == CP_PARSER_DECLARATOR_EITHER) + if (abstract_ok) { if (!cp_parser_parse_definitely (parser)) unqualified_name = error_mark_node; - else if (qualifying_scope - || (TREE_CODE (unqualified_name) - != IDENTIFIER_NODE)) + else if (unqualified_name + && (qualifying_scope + || (TREE_CODE (unqualified_name) + != IDENTIFIER_NODE))) { cp_parser_error (parser, "expected unqualified-id"); unqualified_name = error_mark_node; } } + if (!unqualified_name) + return NULL; if (unqualified_name == error_mark_node) { declarator = cp_error_declarator; @@ -11370,9 +11586,7 @@ cp_parser_direct_declarator (cp_parser* parser, qualifying_scope = type; } - declarator = make_id_declarator (qualifying_scope, - unqualified_name); - declarator->id_loc = token->location; + sfk = sfk_none; if (unqualified_name) { tree class_type; @@ -11383,39 +11597,63 @@ cp_parser_direct_declarator (cp_parser* parser, else class_type = current_class_type; + if (TREE_CODE (unqualified_name) == TYPE_DECL) + { + tree name_type = TREE_TYPE (unqualified_name); + if (class_type && same_type_p (name_type, class_type)) + { + if (qualifying_scope + && CLASSTYPE_USE_TEMPLATE (name_type)) + { + error ("invalid use of constructor as a template"); + inform ("use %<%T::%D%> instead of %<%T::%D%> to " + "name the constructor in a qualified name", + class_type, + DECL_NAME (TYPE_TI_TEMPLATE (class_type)), + class_type, name_type); + declarator = cp_error_declarator; + break; + } + else + unqualified_name = constructor_name (class_type); + } + else + { + /* We do not attempt to print the declarator + here because we do not have enough + information about its original syntactic + form. */ + cp_parser_error (parser, "invalid declarator"); + declarator = cp_error_declarator; + break; + } + } + if (class_type) { if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR) - declarator->u.id.sfk = sfk_destructor; + sfk = sfk_destructor; else if (IDENTIFIER_TYPENAME_P (unqualified_name)) - declarator->u.id.sfk = sfk_conversion; + sfk = sfk_conversion; else if (/* There's no way to declare a constructor for an anonymous type, even if the type got a name for linkage purposes. */ !TYPE_WAS_ANONYMOUS (class_type) - && (constructor_name_p (unqualified_name, - class_type) - || (TREE_CODE (unqualified_name) == TYPE_DECL - && (same_type_p - (TREE_TYPE (unqualified_name), - class_type))))) - declarator->u.id.sfk = sfk_constructor; - - if (ctor_dtor_or_conv_p && declarator->u.id.sfk != sfk_none) - *ctor_dtor_or_conv_p = -1; - if (qualifying_scope - && TREE_CODE (unqualified_name) == TYPE_DECL - && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (unqualified_name))) + && constructor_name_p (unqualified_name, + class_type)) { - error ("invalid use of constructor as a template"); - inform ("use %<%T::%D%> instead of %<%T::%T%> to name " - "the constructor in a qualified name", - class_type, - DECL_NAME (TYPE_TI_TEMPLATE (class_type)), - class_type, class_type); + unqualified_name = constructor_name (class_type); + sfk = sfk_constructor; } + + if (ctor_dtor_or_conv_p && sfk != sfk_none) + *ctor_dtor_or_conv_p = -1; } } + declarator = make_id_declarator (qualifying_scope, + unqualified_name, + sfk); + declarator->id_loc = token->location; handle_declarator:; scope = get_scope_of_declarator (declarator); @@ -11523,17 +11761,23 @@ cp_parser_ptr_operator (cp_parser* parser, if (!cp_parser_error_occurred (parser) && cp_parser_require (parser, CPP_MULT, "`*'")) { - /* The type of which the member is a member is given by the - current SCOPE. */ - *type = parser->scope; - /* The next name will not be qualified. */ - parser->scope = NULL_TREE; - parser->qualifying_scope = NULL_TREE; - parser->object_scope = NULL_TREE; /* Indicate that the `*' operator was used. */ code = INDIRECT_REF; - /* Look for the optional cv-qualifier-seq. */ - *cv_quals = cp_parser_cv_qualifier_seq_opt (parser); + + if (TREE_CODE (parser->scope) == NAMESPACE_DECL) + error ("%qD is a namespace", parser->scope); + else + { + /* The type of which the member is a member is given by the + current SCOPE. */ + *type = parser->scope; + /* The next name will not be qualified. */ + parser->scope = NULL_TREE; + parser->qualifying_scope = NULL_TREE; + parser->object_scope = NULL_TREE; + /* Look for the optional cv-qualifier-seq. */ + *cv_quals = cp_parser_cv_qualifier_seq_opt (parser); + } } /* If that didn't work we don't have a ptr-operator. */ if (!cp_parser_parse_definitely (parser)) @@ -11623,8 +11867,9 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser) unqualified-id. */ static tree -cp_parser_declarator_id (cp_parser* parser) +cp_parser_declarator_id (cp_parser* parser, bool optional_p) { + tree id; /* The expression must be an id-expression. Assume that qualified names are the names of types so that: @@ -11639,11 +11884,15 @@ cp_parser_declarator_id (cp_parser* parser) int S::R::i = 3; will work, too. */ - return cp_parser_id_expression (parser, - /*template_keyword_p=*/false, - /*check_dependency_p=*/false, - /*template_p=*/NULL, - /*declarator_p=*/true); + id = cp_parser_id_expression (parser, + /*template_keyword_p=*/false, + /*check_dependency_p=*/false, + /*template_p=*/NULL, + /*declarator_p=*/true, + optional_p); + if (id && BASELINK_P (id)) + id = BASELINK_FUNCTIONS (id); + return id; } /* Parse a type-id. @@ -11762,8 +12011,6 @@ cp_parser_type_specifier_seq (cp_parser* parser, if (is_condition && !is_cv_qualifier) flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES; } - - return; } /* Parse a parameter-declaration-clause. @@ -12128,6 +12375,7 @@ cp_parser_parameter_declaration (cp_parser *parser, /* If we run out of tokens, issue an error message. */ case CPP_EOF: + case CPP_PRAGMA_EOL: error ("file ends in default argument"); done = true; break; @@ -12178,10 +12426,21 @@ cp_parser_parameter_declaration (cp_parser *parser, saved_local_variables_forbidden_p = parser->local_variables_forbidden_p; parser->local_variables_forbidden_p = true; + /* The default argument expression may cause implicitly + defined member functions to be synthesized, which will + result in garbage collection. We must treat this + situation as if we were within the body of function so as + to avoid collecting live data on the stack. */ + ++function_depth; /* Parse the assignment-expression. */ + if (template_parm_p) + push_deferring_access_checks (dk_no_deferred); default_argument = cp_parser_assignment_expression (parser, /*cast_p=*/false); + if (template_parm_p) + pop_deferring_access_checks (); /* Restore saved state. */ + --function_depth; parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; parser->local_variables_forbidden_p @@ -12485,9 +12744,13 @@ cp_parser_class_name (cp_parser *parser, if (token->type == CPP_NAME && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2)) { + cp_token *identifier_token; tree identifier; + bool ambiguous_p; /* Look for the identifier. */ + identifier_token = cp_lexer_peek_token (parser->lexer); + ambiguous_p = identifier_token->ambiguous_p; identifier = cp_parser_identifier (parser); /* If the next token isn't an identifier, we are certainly not looking at a class-name. */ @@ -12499,6 +12762,15 @@ cp_parser_class_name (cp_parser *parser, decl = identifier; else { + tree ambiguous_decls; + /* If we already know that this lookup is ambiguous, then + we've already issued an error message; there's no reason + to check again. */ + if (ambiguous_p) + { + cp_parser_simulate_error (parser); + return error_mark_node; + } /* If the next token is a `::', then the name must be a type name. @@ -12515,7 +12787,18 @@ cp_parser_class_name (cp_parser *parser, /*is_template=*/false, /*is_namespace=*/false, check_dependency_p, - /*ambiguous_p=*/NULL); + &ambiguous_decls); + if (ambiguous_decls) + { + error ("reference to %qD is ambiguous", identifier); + print_candidates (ambiguous_decls); + if (cp_parser_parsing_tentatively (parser)) + { + identifier_token->ambiguous_p = true; + cp_parser_simulate_error (parser); + } + return error_mark_node; + } } } else @@ -12533,7 +12816,8 @@ cp_parser_class_name (cp_parser *parser, /* If this is a typename, create a TYPENAME_TYPE. */ if (typename_p && decl != error_mark_node) { - decl = make_typename_type (scope, decl, typename_type, /*complain=*/1); + decl = make_typename_type (scope, decl, typename_type, + /*complain=*/tf_error); if (decl != error_mark_node) decl = TYPE_NAME (decl); } @@ -12552,15 +12836,18 @@ cp_parser_class_name (cp_parser *parser, standard does not seem to be definitive, but there is no other valid interpretation of the following `::'. Therefore, those names are considered class-names. */ - decl = TYPE_NAME (make_typename_type (scope, decl, tag_type, tf_error)); - else if (decl == error_mark_node - || TREE_CODE (decl) != TYPE_DECL - || TREE_TYPE (decl) == error_mark_node - || !IS_AGGR_TYPE (TREE_TYPE (decl))) { - cp_parser_error (parser, "expected class-name"); - return error_mark_node; + decl = make_typename_type (scope, decl, tag_type, tf_error); + if (decl != error_mark_node) + decl = TYPE_NAME (decl); } + else if (TREE_CODE (decl) != TYPE_DECL + || TREE_TYPE (decl) == error_mark_node + || !IS_AGGR_TYPE (TREE_TYPE (decl))) + decl = error_mark_node; + + if (decl == error_mark_node) + cp_parser_error (parser, "expected class-name"); return decl; } @@ -12820,7 +13107,7 @@ cp_parser_class_head (cp_parser* parser, define a class that has already been declared with this syntax. - The proposed resolution for Core Issue 180 says that whever + The proposed resolution for Core Issue 180 says that wherever you see `class T::X' you should treat `X' as a type-name. It is OK to define an inaccessible class; for example: @@ -13138,7 +13425,9 @@ cp_parser_member_specification_opt (cp_parser* parser) /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); /* If it's a `}', or EOF then we've seen all the members. */ - if (token->type == CPP_CLOSE_BRACE || token->type == CPP_EOF) + if (token->type == CPP_CLOSE_BRACE + || token->type == CPP_EOF + || token->type == CPP_PRAGMA_EOL) break; /* See if this token is a keyword. */ @@ -13160,7 +13449,7 @@ cp_parser_member_specification_opt (cp_parser* parser) /* Accept #pragmas at class scope. */ if (token->type == CPP_PRAGMA) { - cp_lexer_handle_pragma (parser->lexer); + cp_parser_pragma (parser, pragma_external); break; } @@ -13224,8 +13513,13 @@ cp_parser_member_declaration (cp_parser* parser) /* Check for a template-declaration. */ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE)) { - /* Parse the template-declaration. */ - cp_parser_template_declaration (parser, /*member_p=*/true); + /* An explicit specialization here is an error condition, and we + expect the specialization handler to detect and report this. */ + if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_LESS + && cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_GREATER) + cp_parser_explicit_specialization (parser); + else + cp_parser_template_declaration (parser, /*member_p=*/true); return; } @@ -13393,7 +13687,8 @@ cp_parser_member_declaration (cp_parser* parser) /* Create the bitfield declaration. */ decl = grokbitfield (identifier ? make_id_declarator (NULL_TREE, - identifier) + identifier, + sfk_none) : NULL, &decl_specifiers, width); @@ -13467,7 +13762,8 @@ cp_parser_member_declaration (cp_parser* parser) for a pure-specifier; otherwise, we look for a constant-initializer. When we call `grokfield', it will perform more stringent semantics checks. */ - if (declarator->kind == cdk_function) + if (declarator->kind == cdk_function + && declarator->declarator->kind == cdk_id) initializer = cp_parser_pure_specifier (parser); else /* Parse the initializer. */ @@ -13507,16 +13803,11 @@ cp_parser_member_declaration (cp_parser* parser) return; } else - { - /* Create the declaration. */ - decl = grokfield (declarator, &decl_specifiers, - initializer, asm_specification, - attributes); - /* Any initialization must have been from a - constant-expression. */ - if (decl && TREE_CODE (decl) == VAR_DECL && initializer) - DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1; - } + /* Create the declaration. */ + decl = grokfield (declarator, &decl_specifiers, + initializer, /*init_const_expr_p=*/true, + asm_specification, + attributes); } /* Reset PREFIX_ATTRIBUTES. */ @@ -13577,17 +13868,20 @@ cp_parser_pure_specifier (cp_parser* parser) return error_mark_node; /* Look for the `0' token. */ token = cp_lexer_consume_token (parser->lexer); - if (token->type != CPP_NUMBER || !integer_zerop (token->value)) + /* c_lex_with_flags marks a single digit '0' with PURE_ZERO. */ + if (token->type != CPP_NUMBER || !(token->flags & PURE_ZERO)) { - cp_parser_error (parser, + cp_parser_error (parser, "invalid pure specifier (only `= 0' is allowed)"); cp_parser_skip_to_end_of_statement (parser); return error_mark_node; } + if (PROCESSING_REAL_TEMPLATE_DECL_P ()) + { + error ("templates may not be %"); + return error_mark_node; + } - /* FIXME: Unfortunately, this will accept `0L' and `0x00' as well. - We need to get information from the lexer about how the number - was spelled in order to fix this problem. */ return integer_zero_node; } @@ -13931,6 +14225,7 @@ cp_parser_try_block (cp_parser* parser) static bool cp_parser_function_try_block (cp_parser* parser) { + tree compound_stmt; tree try_block; bool ctor_initializer_p; @@ -13938,7 +14233,7 @@ cp_parser_function_try_block (cp_parser* parser) if (!cp_parser_require_keyword (parser, RID_TRY, "`try'")) return false; /* Let the rest of the front-end know where we are. */ - try_block = begin_function_try_block (); + try_block = begin_function_try_block (&compound_stmt); /* Parse the function-body. */ ctor_initializer_p = cp_parser_ctor_initializer_opt_and_function_body (parser); @@ -13947,7 +14242,7 @@ cp_parser_function_try_block (cp_parser* parser) /* Parse the handlers. */ cp_parser_handler_seq (parser); /* We're done with the handlers. */ - finish_function_handler_sequence (try_block); + finish_function_handler_sequence (try_block, compound_stmt); return ctor_initializer_p; } @@ -14449,15 +14744,17 @@ cp_parser_label_declaration (cp_parser* parser) If CHECK_DEPENDENCY is TRUE, names are not looked up in dependent types. - If AMBIGUOUS_P is non-NULL, it is set to true if name-lookup - results in an ambiguity, and false otherwise. */ + If AMBIGUOUS_DECLS is non-NULL, *AMBIGUOUS_DECLS is set to a + TREE_LIST of candidates if name-lookup results in an ambiguity, and + NULL_TREE otherwise. */ static tree cp_parser_lookup_name (cp_parser *parser, tree name, enum tag_types tag_type, - bool is_template, bool is_namespace, + bool is_template, + bool is_namespace, bool check_dependency, - bool *ambiguous_p) + tree *ambiguous_decls) { int flags = 0; tree decl; @@ -14467,8 +14764,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name, flags |= LOOKUP_COMPLAIN; /* Assume that the lookup will be unambiguous. */ - if (ambiguous_p) - *ambiguous_p = false; + if (ambiguous_decls) + *ambiguous_decls = NULL_TREE; /* Now that we have looked up the name, the OBJECT_TYPE (if any) is no longer valid. Note that if we are parsing tentatively, and @@ -14547,15 +14844,20 @@ cp_parser_lookup_name (cp_parser *parser, tree name, A::B' should be considered a type-name, even if `A' is dependent. */ type = make_typename_type (parser->scope, name, tag_type, - /*complain=*/1); + /*complain=*/tf_error); decl = TYPE_NAME (type); } - else if (is_template) + else if (is_template + && (cp_parser_next_token_ends_template_argument_p (parser) + || cp_lexer_next_token_is (parser->lexer, + CPP_CLOSE_PAREN))) decl = make_unbound_class_template (parser->scope, name, NULL_TREE, - /*complain=*/1); + /*complain=*/tf_error); else - decl = build_nt (SCOPE_REF, parser->scope, name); + decl = build_qualified_name (/*type=*/NULL_TREE, + parser->scope, name, + is_template); } else { @@ -14620,8 +14922,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name, /* If it's a TREE_LIST, the result of the lookup was ambiguous. */ if (TREE_CODE (decl) == TREE_LIST) { - if (ambiguous_p) - *ambiguous_p = true; + if (ambiguous_decls) + *ambiguous_decls = decl; /* The error message we have to print is too complicated for cp_parser_error, so we incorporate its actions directly. */ if (!cp_parser_simulate_error (parser)) @@ -14663,7 +14965,7 @@ cp_parser_lookup_name_simple (cp_parser* parser, tree name) /*is_template=*/false, /*is_namespace=*/false, /*check_dependency=*/true, - /*ambiguous_p=*/NULL); + /*ambiguous_decls=*/NULL); } /* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in @@ -15034,7 +15336,6 @@ cp_parser_function_definition_from_specifiers_and_declarator if (!success_p) { /* Skip the entire function. */ - error ("invalid function declaration"); cp_parser_skip_to_end_of_block_or_statement (parser); fn = error_mark_node; } @@ -15073,9 +15374,15 @@ cp_parser_function_definition_after_declarator (cp_parser* parser, /* Issue an error message. */ error ("named return values are no longer supported"); /* Skip tokens until we reach the start of the function body. */ - while (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE) - && cp_lexer_next_token_is_not (parser->lexer, CPP_EOF)) - cp_lexer_consume_token (parser->lexer); + while (true) + { + cp_token *token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_OPEN_BRACE + || token->type == CPP_EOF + || token->type == CPP_PRAGMA_EOL) + break; + cp_lexer_consume_token (parser->lexer); + } } /* The `extern' in `extern "C" void f () { ... }' does not apply to anything declared inside `f'. */ @@ -15119,8 +15426,10 @@ static void cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) { tree decl = NULL_TREE; + tree checks; tree parameter_list; bool friend_p = false; + bool need_lang_pop; /* Look for the `template' keyword. */ if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'")) @@ -15129,6 +15438,24 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) /* And the `<'. */ if (!cp_parser_require (parser, CPP_LESS, "`<'")) return; + /* [temp] + + A template ... shall not have C linkage. */ + if (current_lang_name == lang_name_c) + { + error ("template with C linkage"); + /* Give it C++ linkage to avoid confusing other parts of the + front end. */ + push_lang_context (lang_name_cplusplus); + need_lang_pop = true; + } + else + need_lang_pop = false; + + /* We cannot perform access checks on the template parameter + declarations until we know what is being declared, just as we + cannot check the decl-specifier list. */ + push_deferring_access_checks (dk_deferred); /* If the next token is `>', then we have an invalid specialization. Rather than complain about an invalid template @@ -15140,12 +15467,14 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) parameter_list = NULL_TREE; } else - { - /* Parse the template parameters. */ - begin_template_parm_list (); - parameter_list = cp_parser_template_parameter_list (parser); - parameter_list = end_template_parm_list (parameter_list); - } + /* Parse the template parameters. */ + parameter_list = cp_parser_template_parameter_list (parser); + + /* Get the deferred access checks from the parameter list. These + will be checked once we know what is being declared, as for a + member template the checks must be performed in the scope of the + class containing the member. */ + checks = get_deferred_access_checks (); /* Look for the `>'. */ cp_parser_skip_until_found (parser, CPP_GREATER, "`>'"); @@ -15161,11 +15490,10 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) /* There are no access checks when parsing a template, as we do not know if a specialization will be a friend. */ push_deferring_access_checks (dk_no_check); - decl = cp_parser_single_declaration (parser, + checks, member_p, &friend_p); - pop_deferring_access_checks (); /* If this is a member template declaration, let the front @@ -15184,13 +15512,18 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) /* We are done with the current parameter list. */ --parser->num_template_parameter_lists; + pop_deferring_access_checks (); + /* Finish up. */ finish_template_decl (parameter_list); /* Register member declarations. */ if (member_p && !friend_p && decl && !DECL_CLASS_TEMPLATE_P (decl)) finish_member_declaration (decl); - + /* For the erroneous case of a template with C linkage, we pushed an + implicit C++ linkage scope; exit that scope now. */ + if (need_lang_pop) + pop_lang_context (); /* If DECL is a function template, we must return to parse it later. (Even though there is no definition, there might be default arguments that need handling.) */ @@ -15202,6 +15535,18 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) TREE_VALUE (parser->unparsed_functions_queues)); } +/* Perform the deferred access checks from a template-parameter-list. + CHECKS is a TREE_LIST of access checks, as returned by + get_deferred_access_checks. */ + +static void +cp_parser_perform_template_parameter_access_checks (tree checks) +{ + ++processing_template_parmlist; + perform_access_checks (checks); + --processing_template_parmlist; +} + /* Parse a `decl-specifier-seq [opt] init-declarator [opt] ;' or `function-definition' sequence. MEMBER_P is true, this declaration appears in a class scope. @@ -15211,6 +15556,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) static tree cp_parser_single_declaration (cp_parser* parser, + tree checks, bool member_p, bool* friend_p) { @@ -15272,6 +15618,9 @@ cp_parser_single_declaration (cp_parser* parser, decl = TYPE_NAME (decl); else decl = error_mark_node; + + /* Perform access checks for template parameters. */ + cp_parser_perform_template_parameter_access_checks (checks); } } /* If it's not a template class, try for a template function. If @@ -15284,6 +15633,7 @@ cp_parser_single_declaration (cp_parser* parser, || decl_specifiers.type != error_mark_node)) decl = cp_parser_init_declarator (parser, &decl_specifiers, + checks, /*function_definition_allowed_p=*/true, member_p, declares_class_or_enum, @@ -15331,8 +15681,10 @@ cp_parser_functional_cast (cp_parser* parser, tree type) cast = build_functional_cast (type, expression_list); /* [expr.const]/1: In an integral constant expression "only type conversions to integral or enumeration type can be used". */ - if (cast != error_mark_node && !type_dependent_expression_p (type) - && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (type))) + if (TREE_CODE (type) == TYPE_DECL) + type = TREE_TYPE (type); + if (cast != error_mark_node && !dependent_type_p (type) + && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)) { if (cp_parser_non_integral_constant_expression (parser, "a call to a constructor")) @@ -15413,6 +15765,7 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser) tree saved_qualifying_scope; tree saved_object_scope; bool saved_greater_than_is_operator_p; + bool saved_skip_evaluation; /* [temp.names] @@ -15427,6 +15780,10 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser) saved_scope = parser->scope; saved_qualifying_scope = parser->qualifying_scope; saved_object_scope = parser->object_scope; + /* We need to evaluate the template arguments, even though this + template-id may be nested within a "sizeof". */ + saved_skip_evaluation = skip_evaluation; + skip_evaluation = false; /* Parse the template-argument-list itself. */ if (cp_lexer_next_token_is (parser->lexer, CPP_GREATER)) arguments = NULL_TREE; @@ -15464,11 +15821,8 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser) "a template argument list"); } } - else if (!cp_lexer_next_token_is (parser->lexer, CPP_GREATER)) - error ("missing %<>%> to terminate the template argument list"); else - /* It's what we want, a '>'; consume it. */ - cp_lexer_consume_token (parser->lexer); + cp_parser_skip_until_found (parser, CPP_GREATER, "`>'"); /* The `>' token might be a greater-than operator again now. */ parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; @@ -15476,6 +15830,7 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser) parser->scope = saved_scope; parser->qualifying_scope = saved_qualifying_scope; parser->object_scope = saved_object_scope; + skip_evaluation = saved_skip_evaluation; return arguments; } @@ -15576,7 +15931,6 @@ cp_parser_save_default_args (cp_parser* parser, tree decl) TREE_PURPOSE (parser->unparsed_functions_queues)); break; } - return; } /* FN is a FUNCTION_DECL which may contains a parameter with an @@ -15629,6 +15983,9 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) /* Parse the assignment-expression. */ parsed_arg = cp_parser_assignment_expression (parser, /*cast_p=*/false); + 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. */ @@ -15646,6 +16003,9 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn) cp_parser_pop_lexer (parser); } + /* Make sure no default arg is missing. */ + check_default_args (fn); + /* Restore the state of local_variables_forbidden_p. */ parser->local_variables_forbidden_p = saved_local_variables_forbidden_p; @@ -15677,7 +16037,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword) saved_message = parser->type_definition_forbidden_message; /* And create the new one. */ parser->type_definition_forbidden_message - = xmalloc (strlen (format) + = XNEWVEC (const char, strlen (format) + strlen (IDENTIFIER_POINTER (ridpointers[keyword])) + 1 /* `\0' */); sprintf ((char *) parser->type_definition_forbidden_message, @@ -15761,16 +16121,56 @@ cp_parser_declares_only_class_p (cp_parser *parser) || cp_lexer_next_token_is (parser->lexer, CPP_COMMA)); } -/* Update the DECL_SPECS to reflect the STORAGE_CLASS. */ +/* Update the DECL_SPECS to reflect the storage class indicated by + KEYWORD. */ static void -cp_parser_set_storage_class (cp_decl_specifier_seq *decl_specs, - cp_storage_class storage_class) +cp_parser_set_storage_class (cp_parser *parser, + cp_decl_specifier_seq *decl_specs, + enum rid keyword) { - if (decl_specs->storage_class != sc_none) - decl_specs->multiple_storage_classes_p = true; - else - decl_specs->storage_class = storage_class; + cp_storage_class storage_class; + + if (parser->in_unbraced_linkage_specification_p) + { + error ("invalid use of %qD in linkage specification", + ridpointers[keyword]); + return; + } + else if (decl_specs->storage_class != sc_none) + { + decl_specs->multiple_storage_classes_p = true; + return; + } + + if ((keyword == RID_EXTERN || keyword == RID_STATIC) + && decl_specs->specs[(int) ds_thread]) + { + error ("%<__thread%> before %qD", ridpointers[keyword]); + decl_specs->specs[(int) ds_thread] = 0; + } + + switch (keyword) + { + case RID_AUTO: + storage_class = sc_auto; + break; + case RID_REGISTER: + storage_class = sc_register; + break; + case RID_STATIC: + storage_class = sc_static; + break; + case RID_EXTERN: + storage_class = sc_extern; + break; + case RID_MUTABLE: + storage_class = sc_mutable; + break; + default: + gcc_unreachable (); + } + decl_specs->storage_class = storage_class; } /* Update the DECL_SPECS to reflect the TYPE_SPEC. If USER_DEFINED_P @@ -15870,27 +16270,38 @@ cp_parser_skip_until_found (cp_parser* parser, { /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); - /* If we've reached the token we want, consume it and - stop. */ + + /* If we've reached the token we want, consume it and stop. */ if (token->type == type && !nesting_depth) { cp_lexer_consume_token (parser->lexer); return; } - /* If we've run out of tokens, stop. */ - if (token->type == CPP_EOF) - return; - if (token->type == CPP_OPEN_BRACE - || token->type == CPP_OPEN_PAREN - || token->type == CPP_OPEN_SQUARE) - ++nesting_depth; - else if (token->type == CPP_CLOSE_BRACE - || token->type == CPP_CLOSE_PAREN - || token->type == CPP_CLOSE_SQUARE) + + switch (token->type) { + case CPP_EOF: + case CPP_PRAGMA_EOL: + /* If we've run out of tokens, stop. */ + return; + + case CPP_OPEN_BRACE: + case CPP_OPEN_PAREN: + case CPP_OPEN_SQUARE: + ++nesting_depth; + break; + + case CPP_CLOSE_BRACE: + case CPP_CLOSE_PAREN: + case CPP_CLOSE_SQUARE: if (nesting_depth-- == 0) return; + break; + + default: + break; } + /* Consume this token. */ cp_lexer_consume_token (parser->lexer); } @@ -16109,7 +16520,9 @@ cp_parser_cache_group (cp_parser *parser, && cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) return; /* If we've reached the end of the file, stop. */ - if (cp_lexer_next_token_is (parser->lexer, CPP_EOF)) + if (cp_lexer_next_token_is (parser->lexer, CPP_EOF) + || (end != CPP_PRAGMA_EOL + && cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA_EOL))) return; /* Consume the next token. */ token = cp_lexer_consume_token (parser->lexer); @@ -16122,6 +16535,8 @@ cp_parser_cache_group (cp_parser *parser, } else if (token->type == CPP_OPEN_PAREN) cp_parser_cache_group (parser, CPP_CLOSE_PAREN, depth + 1); + else if (token->type == CPP_PRAGMA) + cp_parser_cache_group (parser, CPP_PRAGMA_EOL, depth + 1); else if (token->type == end) return; } @@ -16500,27 +16915,45 @@ cp_parser_objc_selector_expression (cp_parser* parser) cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); token = cp_lexer_peek_token (parser->lexer); - while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON) + while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON + || token->type == CPP_SCOPE) { tree selector = NULL_TREE; - if (token->type != CPP_COLON) + if (token->type != CPP_COLON + || token->type == CPP_SCOPE) selector = cp_parser_objc_selector (parser); - /* Detect if we have a unary selector. */ - if (maybe_unary_selector_p - && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)) + if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON) + && cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE)) { - sel_seq = selector; - goto finish_selector; + /* Detect if we have a unary selector. */ + if (maybe_unary_selector_p) + { + sel_seq = selector; + goto finish_selector; + } + else + { + cp_parser_error (parser, "expected %<:%>"); + } } - maybe_unary_selector_p = false; - cp_parser_require (parser, CPP_COLON, "`:'"); - - sel_seq - = chainon (sel_seq, - build_tree_list (selector, NULL_TREE)); + token = cp_lexer_consume_token (parser->lexer); + + if (token->type == CPP_SCOPE) + { + sel_seq + = chainon (sel_seq, + build_tree_list (selector, NULL_TREE)); + sel_seq + = chainon (sel_seq, + build_tree_list (NULL_TREE, NULL_TREE)); + } + else + sel_seq + = chainon (sel_seq, + build_tree_list (selector, NULL_TREE)); token = cp_lexer_peek_token (parser->lexer); } @@ -16840,7 +17273,7 @@ cp_parser_objc_interstitial_code (cp_parser* parser) cp_parser_linkage_specification (parser); /* Handle #pragma, if any. */ else if (token->type == CPP_PRAGMA) - cp_lexer_handle_pragma (parser->lexer); + cp_parser_pragma (parser, pragma_external); /* Allow stray semicolons. */ else if (token->type == CPP_SEMICOLON) cp_lexer_consume_token (parser->lexer); @@ -16980,7 +17413,8 @@ cp_parser_objc_class_ivars (cp_parser* parser) { /* Get the name of the bitfield. */ declarator = make_id_declarator (NULL_TREE, - cp_parser_identifier (parser)); + cp_parser_identifier (parser), + sfk_none); eat_colon: cp_lexer_consume_token (parser->lexer); /* Eat ':'. */ @@ -17015,7 +17449,8 @@ cp_parser_objc_class_ivars (cp_parser* parser) cplus_decl_attributes (&decl, attributes, /*flags=*/0); } else - decl = grokfield (declarator, &declspecs, NULL_TREE, + decl = grokfield (declarator, &declspecs, + NULL_TREE, /*init_const_expr_p=*/false, NULL_TREE, attributes); /* Add the instance variable. */ @@ -17332,10 +17767,1359 @@ cp_parser_objc_statement (cp_parser * parser) { return error_mark_node; } -/* The parser. */ +/* OpenMP 2.5 parsing routines. */ + +/* All OpenMP clauses. OpenMP 2.5. */ +typedef enum pragma_omp_clause { + PRAGMA_OMP_CLAUSE_NONE = 0, + + PRAGMA_OMP_CLAUSE_COPYIN, + PRAGMA_OMP_CLAUSE_COPYPRIVATE, + PRAGMA_OMP_CLAUSE_DEFAULT, + PRAGMA_OMP_CLAUSE_FIRSTPRIVATE, + PRAGMA_OMP_CLAUSE_IF, + PRAGMA_OMP_CLAUSE_LASTPRIVATE, + PRAGMA_OMP_CLAUSE_NOWAIT, + PRAGMA_OMP_CLAUSE_NUM_THREADS, + PRAGMA_OMP_CLAUSE_ORDERED, + PRAGMA_OMP_CLAUSE_PRIVATE, + PRAGMA_OMP_CLAUSE_REDUCTION, + PRAGMA_OMP_CLAUSE_SCHEDULE, + PRAGMA_OMP_CLAUSE_SHARED +} pragma_omp_clause; + +/* Returns name of the next clause. + If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and + the token is not consumed. Otherwise appropriate pragma_omp_clause is + returned and the token is consumed. */ + +static pragma_omp_clause +cp_parser_omp_clause_name (cp_parser *parser) +{ + pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE; + + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_IF)) + result = PRAGMA_OMP_CLAUSE_IF; + else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_DEFAULT)) + result = PRAGMA_OMP_CLAUSE_DEFAULT; + else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_PRIVATE)) + result = PRAGMA_OMP_CLAUSE_PRIVATE; + else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + tree id = cp_lexer_peek_token (parser->lexer)->value; + const char *p = IDENTIFIER_POINTER (id); + + switch (p[0]) + { + case 'c': + if (!strcmp ("copyin", p)) + result = PRAGMA_OMP_CLAUSE_COPYIN; + else if (!strcmp ("copyprivate", p)) + result = PRAGMA_OMP_CLAUSE_COPYPRIVATE; + break; + case 'f': + if (!strcmp ("firstprivate", p)) + result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE; + break; + case 'l': + if (!strcmp ("lastprivate", p)) + result = PRAGMA_OMP_CLAUSE_LASTPRIVATE; + break; + case 'n': + if (!strcmp ("nowait", p)) + result = PRAGMA_OMP_CLAUSE_NOWAIT; + else if (!strcmp ("num_threads", p)) + result = PRAGMA_OMP_CLAUSE_NUM_THREADS; + break; + case 'o': + if (!strcmp ("ordered", p)) + result = PRAGMA_OMP_CLAUSE_ORDERED; + break; + case 'r': + if (!strcmp ("reduction", p)) + result = PRAGMA_OMP_CLAUSE_REDUCTION; + break; + case 's': + if (!strcmp ("schedule", p)) + result = PRAGMA_OMP_CLAUSE_SCHEDULE; + else if (!strcmp ("shared", p)) + result = PRAGMA_OMP_CLAUSE_SHARED; + break; + } + } -static GTY (()) cp_parser *the_parser; + if (result != PRAGMA_OMP_CLAUSE_NONE) + cp_lexer_consume_token (parser->lexer); + return result; +} + +/* Validate that a clause of the given type does not already exist. */ + +static void +check_no_duplicate_clause (tree clauses, enum tree_code code, const char *name) +{ + tree c; + + for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) + if (OMP_CLAUSE_CODE (c) == code) + { + error ("too many %qs clauses", name); + break; + } +} + +/* OpenMP 2.5: + variable-list: + identifier + variable-list , identifier + + In addition, we match a closing parenthesis. An opening parenthesis + will have been consumed by the caller. + + If KIND is nonzero, create the appropriate node and install the decl + in OMP_CLAUSE_DECL and add the node to the head of the list. + + If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE; + return the list created. */ + +static tree +cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, + tree list) +{ + while (1) + { + tree name, decl; + + name = cp_parser_id_expression (parser, /*template_p=*/false, + /*check_dependency_p=*/true, + /*template_p=*/NULL, + /*declarator_p=*/false, + /*optional_p=*/false); + if (name == error_mark_node) + goto skip_comma; + + decl = cp_parser_lookup_name_simple (parser, name); + if (decl == error_mark_node) + cp_parser_name_lookup_error (parser, name, decl, NULL); + else if (kind != 0) + { + tree u = build_omp_clause (kind); + OMP_CLAUSE_DECL (u) = decl; + OMP_CLAUSE_CHAIN (u) = list; + list = u; + } + else + list = tree_cons (decl, NULL_TREE, list); + + get_comma: + if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) + break; + cp_lexer_consume_token (parser->lexer); + } + + if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) + { + int ending; + + /* Try to resync to an unnested comma. Copied from + cp_parser_parenthesized_expression_list. */ + skip_comma: + ending = cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/true, + /*consume_paren=*/true); + if (ending < 0) + goto get_comma; + } + + return list; +} + +/* Similarly, but expect leading and trailing parenthesis. This is a very + common case for omp clauses. */ + +static tree +cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list) +{ + if (cp_parser_require (parser, CPP_OPEN_PAREN, "`('")) + return cp_parser_omp_var_list_no_open (parser, kind, list); + return list; +} + +/* OpenMP 2.5: + default ( shared | none ) */ + +static tree +cp_parser_omp_clause_default (cp_parser *parser, tree list) +{ + enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED; + tree c; + + if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('")) + return list; + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + tree id = cp_lexer_peek_token (parser->lexer)->value; + const char *p = IDENTIFIER_POINTER (id); + + switch (p[0]) + { + case 'n': + if (strcmp ("none", p) != 0) + goto invalid_kind; + kind = OMP_CLAUSE_DEFAULT_NONE; + break; + + case 's': + if (strcmp ("shared", p) != 0) + goto invalid_kind; + kind = OMP_CLAUSE_DEFAULT_SHARED; + break; + + default: + goto invalid_kind; + } + + cp_lexer_consume_token (parser->lexer); + } + else + { + invalid_kind: + cp_parser_error (parser, "expected % or %"); + } + + if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + + if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED) + return list; + + check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default"); + c = build_omp_clause (OMP_CLAUSE_DEFAULT); + OMP_CLAUSE_CHAIN (c) = list; + OMP_CLAUSE_DEFAULT_KIND (c) = kind; + + return c; +} + +/* OpenMP 2.5: + if ( expression ) */ + +static tree +cp_parser_omp_clause_if (cp_parser *parser, tree list) +{ + tree t, c; + + if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('")) + return list; + + t = cp_parser_condition (parser); + + if (t == error_mark_node + || !cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + + check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if"); + + c = build_omp_clause (OMP_CLAUSE_IF); + OMP_CLAUSE_IF_EXPR (c) = t; + OMP_CLAUSE_CHAIN (c) = list; + + return c; +} + +/* OpenMP 2.5: + nowait */ + +static tree +cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED, tree list) +{ + tree c; + + check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait"); + + c = build_omp_clause (OMP_CLAUSE_NOWAIT); + OMP_CLAUSE_CHAIN (c) = list; + return c; +} + +/* OpenMP 2.5: + num_threads ( expression ) */ + +static tree +cp_parser_omp_clause_num_threads (cp_parser *parser, tree list) +{ + tree t, c; + + if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('")) + return list; + + t = cp_parser_expression (parser, false); + + if (t == error_mark_node + || !cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + + check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads"); + + c = build_omp_clause (OMP_CLAUSE_NUM_THREADS); + OMP_CLAUSE_NUM_THREADS_EXPR (c) = t; + OMP_CLAUSE_CHAIN (c) = list; + + return c; +} + +/* OpenMP 2.5: + ordered */ + +static tree +cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED, tree list) +{ + tree c; + + check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered"); + + c = build_omp_clause (OMP_CLAUSE_ORDERED); + OMP_CLAUSE_CHAIN (c) = list; + return c; +} + +/* OpenMP 2.5: + reduction ( reduction-operator : variable-list ) + + reduction-operator: + One of: + * - & ^ | && || */ + +static tree +cp_parser_omp_clause_reduction (cp_parser *parser, tree list) +{ + enum tree_code code; + tree nlist, c; + + if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('")) + return list; + + switch (cp_lexer_peek_token (parser->lexer)->type) + { + case CPP_PLUS: + code = PLUS_EXPR; + break; + case CPP_MULT: + code = MULT_EXPR; + break; + case CPP_MINUS: + code = MINUS_EXPR; + break; + case CPP_AND: + code = BIT_AND_EXPR; + break; + case CPP_XOR: + code = BIT_XOR_EXPR; + break; + case CPP_OR: + code = BIT_IOR_EXPR; + break; + case CPP_AND_AND: + code = TRUTH_ANDIF_EXPR; + break; + case CPP_OR_OR: + code = TRUTH_ORIF_EXPR; + break; + default: + cp_parser_error (parser, "`+', `*', `-', `&', `^', `|', `&&', or `||'"); + resync_fail: + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; + } + cp_lexer_consume_token (parser->lexer); + + if (!cp_parser_require (parser, CPP_COLON, "`:'")) + goto resync_fail; + + nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_REDUCTION, list); + for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c)) + OMP_CLAUSE_REDUCTION_CODE (c) = code; + + return nlist; +} + +/* OpenMP 2.5: + schedule ( schedule-kind ) + schedule ( schedule-kind , expression ) + + schedule-kind: + static | dynamic | guided | runtime +*/ + +static tree +cp_parser_omp_clause_schedule (cp_parser *parser, tree list) +{ + tree c, t; + + if (!cp_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>")) + return list; + + c = build_omp_clause (OMP_CLAUSE_SCHEDULE); + + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + tree id = cp_lexer_peek_token (parser->lexer)->value; + const char *p = IDENTIFIER_POINTER (id); + + switch (p[0]) + { + case 'd': + if (strcmp ("dynamic", p) != 0) + goto invalid_kind; + OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC; + break; + + case 'g': + if (strcmp ("guided", p) != 0) + goto invalid_kind; + OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED; + break; + + case 'r': + if (strcmp ("runtime", p) != 0) + goto invalid_kind; + OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME; + break; + + default: + goto invalid_kind; + } + } + else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC)) + OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC; + else + goto invalid_kind; + cp_lexer_consume_token (parser->lexer); + + if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) + { + cp_lexer_consume_token (parser->lexer); + + t = cp_parser_assignment_expression (parser, false); + + if (t == error_mark_node) + goto resync_fail; + else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME) + error ("schedule % does not take " + "a % parameter"); + else + OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t; + + if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) + goto resync_fail; + } + else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`,' or `)'")) + goto resync_fail; + + check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule"); + OMP_CLAUSE_CHAIN (c) = list; + return c; + + invalid_kind: + cp_parser_error (parser, "invalid schedule kind"); + resync_fail: + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + return list; +} + +/* Parse all OpenMP clauses. The set clauses allowed by the directive + is a bitmask in MASK. Return the list of clauses found; the result + of clause default goes in *pdefault. */ + +static tree +cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask, + const char *where, cp_token *pragma_tok) +{ + tree clauses = NULL; + + while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL)) + { + pragma_omp_clause c_kind = cp_parser_omp_clause_name (parser); + const char *c_name; + tree prev = clauses; + + switch (c_kind) + { + case PRAGMA_OMP_CLAUSE_COPYIN: + clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_COPYIN, clauses); + c_name = "copyin"; + break; + case PRAGMA_OMP_CLAUSE_COPYPRIVATE: + clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_COPYPRIVATE, + clauses); + c_name = "copyprivate"; + break; + case PRAGMA_OMP_CLAUSE_DEFAULT: + clauses = cp_parser_omp_clause_default (parser, clauses); + c_name = "default"; + break; + case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE: + clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FIRSTPRIVATE, + clauses); + c_name = "firstprivate"; + break; + case PRAGMA_OMP_CLAUSE_IF: + clauses = cp_parser_omp_clause_if (parser, clauses); + c_name = "if"; + break; + case PRAGMA_OMP_CLAUSE_LASTPRIVATE: + clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_LASTPRIVATE, + clauses); + c_name = "lastprivate"; + break; + case PRAGMA_OMP_CLAUSE_NOWAIT: + clauses = cp_parser_omp_clause_nowait (parser, clauses); + c_name = "nowait"; + break; + case PRAGMA_OMP_CLAUSE_NUM_THREADS: + clauses = cp_parser_omp_clause_num_threads (parser, clauses); + c_name = "num_threads"; + break; + case PRAGMA_OMP_CLAUSE_ORDERED: + clauses = cp_parser_omp_clause_ordered (parser, clauses); + c_name = "ordered"; + break; + case PRAGMA_OMP_CLAUSE_PRIVATE: + clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_PRIVATE, + clauses); + c_name = "private"; + break; + case PRAGMA_OMP_CLAUSE_REDUCTION: + clauses = cp_parser_omp_clause_reduction (parser, clauses); + c_name = "reduction"; + break; + case PRAGMA_OMP_CLAUSE_SCHEDULE: + clauses = cp_parser_omp_clause_schedule (parser, clauses); + c_name = "schedule"; + break; + case PRAGMA_OMP_CLAUSE_SHARED: + clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_SHARED, + clauses); + c_name = "shared"; + break; + default: + cp_parser_error (parser, "expected %<#pragma omp%> clause"); + goto saw_error; + } + + if (((mask >> c_kind) & 1) == 0) + { + /* Remove the invalid clause(s) from the list to avoid + confusing the rest of the compiler. */ + clauses = prev; + error ("%qs is not valid for %qs", c_name, where); + } + } + saw_error: + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return finish_omp_clauses (clauses); +} + +/* OpenMP 2.5: + structured-block: + statement + + In practice, we're also interested in adding the statement to an + outer node. So it is convenient if we work around the fact that + cp_parser_statement calls add_stmt. */ + +static unsigned +cp_parser_begin_omp_structured_block (cp_parser *parser) +{ + unsigned save = parser->in_statement; + + /* Only move the values to IN_OMP_BLOCK if they weren't false. + This preserves the "not within loop or switch" style error messages + for nonsense cases like + void foo() { + #pragma omp single + break; + } + */ + if (parser->in_statement) + parser->in_statement = IN_OMP_BLOCK; + + return save; +} + +static void +cp_parser_end_omp_structured_block (cp_parser *parser, unsigned save) +{ + parser->in_statement = save; +} + +static tree +cp_parser_omp_structured_block (cp_parser *parser) +{ + tree stmt = begin_omp_structured_block (); + unsigned int save = cp_parser_begin_omp_structured_block (parser); + + cp_parser_statement (parser, NULL_TREE, false); + + cp_parser_end_omp_structured_block (parser, save); + return finish_omp_structured_block (stmt); +} + +/* OpenMP 2.5: + # pragma omp atomic new-line + expression-stmt + + expression-stmt: + x binop= expr | x++ | ++x | x-- | --x + binop: + +, *, -, /, &, ^, |, <<, >> + + where x is an lvalue expression with scalar type. */ + +static void +cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok) +{ + tree lhs, rhs; + enum tree_code code; + + cp_parser_require_pragma_eol (parser, pragma_tok); + + lhs = cp_parser_unary_expression (parser, /*address_p=*/false, + /*cast_p=*/false); + switch (TREE_CODE (lhs)) + { + case ERROR_MARK: + goto saw_error; + + case PREINCREMENT_EXPR: + case POSTINCREMENT_EXPR: + lhs = TREE_OPERAND (lhs, 0); + code = PLUS_EXPR; + rhs = integer_one_node; + break; + + case PREDECREMENT_EXPR: + case POSTDECREMENT_EXPR: + lhs = TREE_OPERAND (lhs, 0); + code = MINUS_EXPR; + rhs = integer_one_node; + break; + + default: + switch (cp_lexer_peek_token (parser->lexer)->type) + { + case CPP_MULT_EQ: + code = MULT_EXPR; + break; + case CPP_DIV_EQ: + code = TRUNC_DIV_EXPR; + break; + case CPP_PLUS_EQ: + code = PLUS_EXPR; + break; + case CPP_MINUS_EQ: + code = MINUS_EXPR; + break; + case CPP_LSHIFT_EQ: + code = LSHIFT_EXPR; + break; + case CPP_RSHIFT_EQ: + code = RSHIFT_EXPR; + break; + case CPP_AND_EQ: + code = BIT_AND_EXPR; + break; + case CPP_OR_EQ: + code = BIT_IOR_EXPR; + break; + case CPP_XOR_EQ: + code = BIT_XOR_EXPR; + break; + default: + cp_parser_error (parser, + "invalid operator for %<#pragma omp atomic%>"); + goto saw_error; + } + cp_lexer_consume_token (parser->lexer); + + rhs = cp_parser_expression (parser, false); + if (rhs == error_mark_node) + goto saw_error; + break; + } + finish_omp_atomic (code, lhs, rhs); + cp_parser_consume_semicolon_at_end_of_statement (parser); + return; + + saw_error: + cp_parser_skip_to_end_of_block_or_statement (parser); +} + + +/* OpenMP 2.5: + # pragma omp barrier new-line +*/ + +static void +cp_parser_omp_barrier (cp_parser *parser, cp_token *pragma_tok) +{ + cp_parser_require_pragma_eol (parser, pragma_tok); + finish_omp_barrier (); +} + +/* OpenMP 2.5: + # pragma omp critical [(name)] new-line + structured-block +*/ + +static tree +cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok) +{ + tree stmt, name = NULL; + + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) + { + cp_lexer_consume_token (parser->lexer); + + name = cp_parser_identifier (parser); + + if (name == error_mark_node + || !cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + if (name == error_mark_node) + name = NULL; + } + cp_parser_require_pragma_eol (parser, pragma_tok); + + stmt = cp_parser_omp_structured_block (parser); + return c_finish_omp_critical (stmt, name); +} + +/* OpenMP 2.5: + # pragma omp flush flush-vars[opt] new-line + + flush-vars: + ( variable-list ) */ + +static void +cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok) +{ + if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) + (void) cp_parser_omp_var_list (parser, 0, NULL); + cp_parser_require_pragma_eol (parser, pragma_tok); + + finish_omp_flush (); +} + +/* Parse the restricted form of the for statment allowed by OpenMP. */ + +static tree +cp_parser_omp_for_loop (cp_parser *parser) +{ + tree init, cond, incr, body, decl, pre_body; + location_t loc; + + if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR)) + { + cp_parser_error (parser, "for statement expected"); + return NULL; + } + loc = cp_lexer_consume_token (parser->lexer)->location; + if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('")) + return NULL; + + init = decl = NULL; + pre_body = push_stmt_list (); + if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) + { + cp_decl_specifier_seq type_specifiers; + + /* First, try to parse as an initialized declaration. See + cp_parser_condition, from whence the bulk of this is copied. */ + + cp_parser_parse_tentatively (parser); + cp_parser_type_specifier_seq (parser, /*is_condition=*/false, + &type_specifiers); + if (!cp_parser_error_occurred (parser)) + { + tree asm_specification, attributes; + cp_declarator *declarator; + + declarator = cp_parser_declarator (parser, + CP_PARSER_DECLARATOR_NAMED, + /*ctor_dtor_or_conv_p=*/NULL, + /*parenthesized_p=*/NULL, + /*member_p=*/false); + attributes = cp_parser_attributes_opt (parser); + asm_specification = cp_parser_asm_specification_opt (parser); + + cp_parser_require (parser, CPP_EQ, "`='"); + if (cp_parser_parse_definitely (parser)) + { + tree pushed_scope; + + decl = start_decl (declarator, &type_specifiers, + /*initialized_p=*/false, attributes, + /*prefix_attributes=*/NULL_TREE, + &pushed_scope); + + init = cp_parser_assignment_expression (parser, false); + + cp_finish_decl (decl, NULL_TREE, /*init_const_expr_p=*/false, + asm_specification, LOOKUP_ONLYCONVERTING); + + if (pushed_scope) + pop_scope (pushed_scope); + } + } + else + cp_parser_abort_tentative_parse (parser); + + /* If parsing as an initialized declaration failed, try again as + a simple expression. */ + if (decl == NULL) + init = cp_parser_expression (parser, false); + } + cp_parser_require (parser, CPP_SEMICOLON, "`;'"); + pre_body = pop_stmt_list (pre_body); + + cond = NULL; + if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) + cond = cp_parser_condition (parser); + cp_parser_require (parser, CPP_SEMICOLON, "`;'"); + + incr = NULL; + if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)) + incr = cp_parser_expression (parser, false); + + if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/true); + + /* Note that we saved the original contents of this flag when we entered + the structured block, and so we don't need to re-save it here. */ + parser->in_statement = IN_OMP_FOR; + + /* Note that the grammar doesn't call for a structured block here, + though the loop as a whole is a structured block. */ + body = push_stmt_list (); + cp_parser_statement (parser, NULL_TREE, false); + body = pop_stmt_list (body); + + return finish_omp_for (loc, decl, init, cond, incr, body, pre_body); +} + +/* OpenMP 2.5: + #pragma omp for for-clause[optseq] new-line + for-loop +*/ + +#define OMP_FOR_CLAUSE_MASK \ + ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \ + | (1u << PRAGMA_OMP_CLAUSE_ORDERED) \ + | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE) \ + | (1u << PRAGMA_OMP_CLAUSE_NOWAIT)) + +static tree +cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok) +{ + tree clauses, sb, ret; + unsigned int save; + + clauses = cp_parser_omp_all_clauses (parser, OMP_FOR_CLAUSE_MASK, + "#pragma omp for", pragma_tok); + + sb = begin_omp_structured_block (); + save = cp_parser_begin_omp_structured_block (parser); + + ret = cp_parser_omp_for_loop (parser); + if (ret) + OMP_FOR_CLAUSES (ret) = clauses; + + cp_parser_end_omp_structured_block (parser, save); + add_stmt (finish_omp_structured_block (sb)); + + return ret; +} + +/* OpenMP 2.5: + # pragma omp master new-line + structured-block +*/ + +static tree +cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok) +{ + cp_parser_require_pragma_eol (parser, pragma_tok); + return c_finish_omp_master (cp_parser_omp_structured_block (parser)); +} + +/* OpenMP 2.5: + # pragma omp ordered new-line + structured-block +*/ + +static tree +cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok) +{ + cp_parser_require_pragma_eol (parser, pragma_tok); + return c_finish_omp_ordered (cp_parser_omp_structured_block (parser)); +} + +/* OpenMP 2.5: + + section-scope: + { section-sequence } + + section-sequence: + section-directive[opt] structured-block + section-sequence section-directive structured-block */ + +static tree +cp_parser_omp_sections_scope (cp_parser *parser) +{ + tree stmt, substmt; + bool error_suppress = false; + cp_token *tok; + + if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'")) + return NULL_TREE; + + stmt = push_stmt_list (); + + if (cp_lexer_peek_token (parser->lexer)->pragma_kind != PRAGMA_OMP_SECTION) + { + unsigned save; + + substmt = begin_omp_structured_block (); + save = cp_parser_begin_omp_structured_block (parser); + + while (1) + { + cp_parser_statement (parser, NULL_TREE, false); + + tok = cp_lexer_peek_token (parser->lexer); + if (tok->pragma_kind == PRAGMA_OMP_SECTION) + break; + if (tok->type == CPP_CLOSE_BRACE) + break; + if (tok->type == CPP_EOF) + break; + } + + cp_parser_end_omp_structured_block (parser, save); + substmt = finish_omp_structured_block (substmt); + substmt = build1 (OMP_SECTION, void_type_node, substmt); + add_stmt (substmt); + } + + while (1) + { + tok = cp_lexer_peek_token (parser->lexer); + if (tok->type == CPP_CLOSE_BRACE) + break; + if (tok->type == CPP_EOF) + break; + + if (tok->pragma_kind == PRAGMA_OMP_SECTION) + { + cp_lexer_consume_token (parser->lexer); + cp_parser_require_pragma_eol (parser, tok); + error_suppress = false; + } + else if (!error_suppress) + { + cp_parser_error (parser, "expected %<#pragma omp section%> or %<}%>"); + error_suppress = true; + } + + substmt = cp_parser_omp_structured_block (parser); + substmt = build1 (OMP_SECTION, void_type_node, substmt); + add_stmt (substmt); + } + cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); + + substmt = pop_stmt_list (stmt); + + stmt = make_node (OMP_SECTIONS); + TREE_TYPE (stmt) = void_type_node; + OMP_SECTIONS_BODY (stmt) = substmt; + + add_stmt (stmt); + return stmt; +} + +/* OpenMP 2.5: + # pragma omp sections sections-clause[optseq] newline + sections-scope +*/ + +#define OMP_SECTIONS_CLAUSE_MASK \ + ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \ + | (1u << PRAGMA_OMP_CLAUSE_NOWAIT)) + +static tree +cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok) +{ + tree clauses, ret; + + clauses = cp_parser_omp_all_clauses (parser, OMP_SECTIONS_CLAUSE_MASK, + "#pragma omp sections", pragma_tok); + + ret = cp_parser_omp_sections_scope (parser); + if (ret) + OMP_SECTIONS_CLAUSES (ret) = clauses; + + return ret; +} + +/* OpenMP 2.5: + # pragma parallel parallel-clause new-line + # pragma parallel for parallel-for-clause new-line + # pragma parallel sections parallel-sections-clause new-line +*/ + +#define OMP_PARALLEL_CLAUSE_MASK \ + ( (1u << PRAGMA_OMP_CLAUSE_IF) \ + | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \ + | (1u << PRAGMA_OMP_CLAUSE_SHARED) \ + | (1u << PRAGMA_OMP_CLAUSE_COPYIN) \ + | (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \ + | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS)) + +static tree +cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok) +{ + enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL; + const char *p_name = "#pragma omp parallel"; + tree stmt, clauses, par_clause, ws_clause, block; + unsigned int mask = OMP_PARALLEL_CLAUSE_MASK; + unsigned int save; + + if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR)) + { + cp_lexer_consume_token (parser->lexer); + p_kind = PRAGMA_OMP_PARALLEL_FOR; + p_name = "#pragma omp parallel for"; + mask |= OMP_FOR_CLAUSE_MASK; + mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT); + } + else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + tree id = cp_lexer_peek_token (parser->lexer)->value; + const char *p = IDENTIFIER_POINTER (id); + if (strcmp (p, "sections") == 0) + { + cp_lexer_consume_token (parser->lexer); + p_kind = PRAGMA_OMP_PARALLEL_SECTIONS; + p_name = "#pragma omp parallel sections"; + mask |= OMP_SECTIONS_CLAUSE_MASK; + mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT); + } + } + + clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok); + block = begin_omp_parallel (); + save = cp_parser_begin_omp_structured_block (parser); + + switch (p_kind) + { + case PRAGMA_OMP_PARALLEL: + cp_parser_already_scoped_statement (parser); + par_clause = clauses; + break; + + case PRAGMA_OMP_PARALLEL_FOR: + c_split_parallel_clauses (clauses, &par_clause, &ws_clause); + stmt = cp_parser_omp_for_loop (parser); + if (stmt) + OMP_FOR_CLAUSES (stmt) = ws_clause; + break; + + case PRAGMA_OMP_PARALLEL_SECTIONS: + c_split_parallel_clauses (clauses, &par_clause, &ws_clause); + stmt = cp_parser_omp_sections_scope (parser); + if (stmt) + OMP_SECTIONS_CLAUSES (stmt) = ws_clause; + break; + + default: + gcc_unreachable (); + } + + cp_parser_end_omp_structured_block (parser, save); + stmt = finish_omp_parallel (par_clause, block); + if (p_kind != PRAGMA_OMP_PARALLEL) + OMP_PARALLEL_COMBINED (stmt) = 1; + return stmt; +} + +/* OpenMP 2.5: + # pragma omp single single-clause[optseq] new-line + structured-block +*/ + +#define OMP_SINGLE_CLAUSE_MASK \ + ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \ + | (1u << PRAGMA_OMP_CLAUSE_NOWAIT)) + +static tree +cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok) +{ + tree stmt = make_node (OMP_SINGLE); + TREE_TYPE (stmt) = void_type_node; + + OMP_SINGLE_CLAUSES (stmt) + = cp_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK, + "#pragma omp single", pragma_tok); + OMP_SINGLE_BODY (stmt) = cp_parser_omp_structured_block (parser); + + return add_stmt (stmt); +} + +/* OpenMP 2.5: + # pragma omp threadprivate (variable-list) */ + +static void +cp_parser_omp_threadprivate (cp_parser *parser, cp_token *pragma_tok) +{ + tree vars; + + vars = cp_parser_omp_var_list (parser, 0, NULL); + cp_parser_require_pragma_eol (parser, pragma_tok); + + if (!targetm.have_tls) + sorry ("threadprivate variables not supported in this target"); + + finish_omp_threadprivate (vars); +} + +/* Main entry point to OpenMP statement pragmas. */ + +static void +cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok) +{ + tree stmt; + + switch (pragma_tok->pragma_kind) + { + case PRAGMA_OMP_ATOMIC: + cp_parser_omp_atomic (parser, pragma_tok); + return; + case PRAGMA_OMP_CRITICAL: + stmt = cp_parser_omp_critical (parser, pragma_tok); + break; + case PRAGMA_OMP_FOR: + stmt = cp_parser_omp_for (parser, pragma_tok); + break; + case PRAGMA_OMP_MASTER: + stmt = cp_parser_omp_master (parser, pragma_tok); + break; + case PRAGMA_OMP_ORDERED: + stmt = cp_parser_omp_ordered (parser, pragma_tok); + break; + case PRAGMA_OMP_PARALLEL: + stmt = cp_parser_omp_parallel (parser, pragma_tok); + break; + case PRAGMA_OMP_SECTIONS: + stmt = cp_parser_omp_sections (parser, pragma_tok); + break; + case PRAGMA_OMP_SINGLE: + stmt = cp_parser_omp_single (parser, pragma_tok); + break; + default: + gcc_unreachable (); + } + + if (stmt) + SET_EXPR_LOCATION (stmt, pragma_tok->location); +} + +/* The parser. */ + +static GTY (()) cp_parser *the_parser; + + +/* Special handling for the first token or line in the file. The first + thing in the file might be #pragma GCC pch_preprocess, which loads a + PCH file, which is a GC collection point. So we need to handle this + first pragma without benefit of an existing lexer structure. + + Always returns one token to the caller in *FIRST_TOKEN. This is + either the true first token of the file, or the first token after + the initial pragma. */ + +static void +cp_parser_initial_pragma (cp_token *first_token) +{ + tree name = NULL; + + cp_lexer_get_preprocessor_token (NULL, first_token); + if (first_token->pragma_kind != PRAGMA_GCC_PCH_PREPROCESS) + return; + + cp_lexer_get_preprocessor_token (NULL, first_token); + if (first_token->type == CPP_STRING) + { + name = first_token->value; + + cp_lexer_get_preprocessor_token (NULL, first_token); + if (first_token->type != CPP_PRAGMA_EOL) + error ("junk at end of %<#pragma GCC pch_preprocess%>"); + } + else + error ("expected string literal"); + + /* Skip to the end of the pragma. */ + while (first_token->type != CPP_PRAGMA_EOL && first_token->type != CPP_EOF) + cp_lexer_get_preprocessor_token (NULL, first_token); + + /* Read one more token to return to our caller. */ + cp_lexer_get_preprocessor_token (NULL, first_token); + + /* Now actually load the PCH file. */ + if (name) + c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name)); +} + +/* Normal parsing of a pragma token. Here we can (and must) use the + regular lexer. */ + +static bool +cp_parser_pragma (cp_parser *parser, enum pragma_context context) +{ + cp_token *pragma_tok; + unsigned int id; + + pragma_tok = cp_lexer_consume_token (parser->lexer); + gcc_assert (pragma_tok->type == CPP_PRAGMA); + parser->lexer->in_pragma = true; + + id = pragma_tok->pragma_kind; + switch (id) + { + case PRAGMA_GCC_PCH_PREPROCESS: + error ("%<#pragma GCC pch_preprocess%> must be first"); + break; + + case PRAGMA_OMP_BARRIER: + switch (context) + { + case pragma_compound: + cp_parser_omp_barrier (parser, pragma_tok); + return false; + case pragma_stmt: + error ("%<#pragma omp barrier%> may only be " + "used in compound statements"); + break; + default: + goto bad_stmt; + } + break; + + case PRAGMA_OMP_FLUSH: + switch (context) + { + case pragma_compound: + cp_parser_omp_flush (parser, pragma_tok); + return false; + case pragma_stmt: + error ("%<#pragma omp flush%> 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; + + case PRAGMA_OMP_ATOMIC: + case PRAGMA_OMP_CRITICAL: + case PRAGMA_OMP_FOR: + case PRAGMA_OMP_MASTER: + case PRAGMA_OMP_ORDERED: + case PRAGMA_OMP_PARALLEL: + case PRAGMA_OMP_SECTIONS: + case PRAGMA_OMP_SINGLE: + if (context == pragma_external) + goto bad_stmt; + cp_parser_omp_construct (parser, pragma_tok); + return true; + + case PRAGMA_OMP_SECTION: + error ("%<#pragma omp section%> may only be used in " + "%<#pragma omp sections%> construct"); + break; + + default: + gcc_assert (id >= PRAGMA_FIRST_EXTERNAL); + c_invoke_pragma_handler (id); + break; + + bad_stmt: + cp_parser_error (parser, "expected declaration specifiers"); + break; + } + + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + return false; +} + +/* The interface the pragma parsers have to the lexer. */ + +enum cpp_ttype +pragma_lex (tree *value) +{ + cp_token *tok; + enum cpp_ttype ret; + + tok = cp_lexer_peek_token (the_parser->lexer); + + ret = tok->type; + *value = tok->value; + + if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF) + ret = CPP_EOF; + else if (ret == CPP_STRING) + *value = cp_parser_string_literal (the_parser, false, false); + else + { + cp_lexer_consume_token (the_parser->lexer); + if (ret == CPP_KEYWORD) + ret = CPP_NAME; + } + + return ret; +} + + /* External interface. */ /* Parse one entire translation unit. */