diff options
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r-- | gcc/cp/parser.c | 359 |
1 files changed, 221 insertions, 138 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 27e73cb..19f55f4 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1651,6 +1651,8 @@ static tree cp_parser_sizeof_operand (cp_parser *, enum rid); static bool cp_parser_declares_only_class_p (cp_parser *); +static tree cp_parser_fold_non_dependent_expr + (tree); static bool cp_parser_friend_p (tree); static cp_token *cp_parser_require @@ -1661,6 +1663,8 @@ static bool cp_parser_token_starts_function_definition_p (cp_token *); static bool cp_parser_next_token_starts_class_definition_p (cp_parser *); +static bool cp_parser_next_token_ends_template_argument_p + (cp_parser *); static enum tag_types cp_parser_token_is_class_key (cp_token *); static void cp_parser_check_class_key @@ -2381,7 +2385,6 @@ cp_parser_primary_expression (cp_parser *parser, cp_parser_error (parser, "expected primary-expression"); return error_mark_node; } - /* Fall through. */ /* An id-expression can start with either an identifier, a `::' as the beginning of a qualified-id, or the "operator" @@ -2600,30 +2603,7 @@ cp_parser_primary_expression (cp_parser *parser, if (TREE_CODE (fns) == TEMPLATE_ID_EXPR) { tree args = TREE_OPERAND (fns, 1); - - if (args && TREE_CODE (args) == TREE_LIST) - { - while (args) - { - if (dependent_template_arg_p (TREE_VALUE (args))) - { - dependent_p = true; - break; - } - args = TREE_CHAIN (args); - } - } - else if (args && TREE_CODE (args) == TREE_VEC) - { - int i; - for (i = 0; i < TREE_VEC_LENGTH (args); ++i) - if (dependent_template_arg_p (TREE_VEC_ELT (args, i))) - { - dependent_p = true; - break; - } - } - + dependent_p = any_dependent_template_arguments_p (args); /* The functions are those referred to by the template-id. */ fns = TREE_OPERAND (fns, 0); @@ -2687,27 +2667,34 @@ cp_parser_primary_expression (cp_parser *parser, /* Only certain kinds of names are allowed in constant expression. Enumerators have already been handled above. */ - if (parser->constant_expression_p + if (parser->constant_expression_p) + { /* Non-type template parameters of integral or - enumeration type. */ - && !(TREE_CODE (decl) == TEMPLATE_PARM_INDEX - && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))) + enumeration type are OK. */ + if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX + && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))) + ; /* Const variables or static data members of integral or enumeration types initialized with constant - expressions (or dependent expressions - in this case - the check will be done at instantiation time). */ - && !(TREE_CODE (decl) == VAR_DECL - && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)) - && DECL_INITIAL (decl) - && (TREE_CONSTANT (DECL_INITIAL (decl)) - || type_dependent_expression_p - (DECL_INITIAL (decl)) - || value_dependent_expression_p - (DECL_INITIAL (decl))))) - { - if (!parser->allow_non_constant_expression_p) - return cp_parser_non_constant_id_expression (decl); - parser->non_constant_expression_p = true; + expressions are OK. We also accept dependent + initializers; they may turn out to be constant at + instantiation-time. */ + else if (TREE_CODE (decl) == VAR_DECL + && CP_TYPE_CONST_P (TREE_TYPE (decl)) + && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)) + && DECL_INITIAL (decl) + && (TREE_CONSTANT (DECL_INITIAL (decl)) + || type_dependent_expression_p (DECL_INITIAL + (decl)) + || value_dependent_expression_p (DECL_INITIAL + (decl)))) + ; + else + { + if (!parser->allow_non_constant_expression_p) + return cp_parser_non_constant_id_expression (decl); + parser->non_constant_expression_p = true; + } } if (parser->scope) @@ -3792,7 +3779,6 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p) || TREE_CODE (postfix_expression) == IDENTIFIER_NODE) && args) { - tree arg; tree identifier = NULL_TREE; tree functions = NULL_TREE; @@ -3815,10 +3801,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p) Do Koenig lookup -- unless any of the arguments are type-dependent. */ - for (arg = args; arg; arg = TREE_CHAIN (arg)) - if (type_dependent_expression_p (TREE_VALUE (arg))) - break; - if (!arg) + if (!any_type_dependent_arguments_p (args)) { postfix_expression = lookup_arg_dependent (identifier, functions, args); @@ -3827,14 +3810,12 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p) /* The unqualified name could not be resolved. */ unqualified_name_lookup_error (identifier); postfix_expression = error_mark_node; + break; } - postfix_expression - = build_call_from_tree (postfix_expression, args, - /*diallow_virtual=*/false); - break; } - postfix_expression = build_min_nt (LOOKUP_EXPR, - identifier); + else + postfix_expression = build_min_nt (LOOKUP_EXPR, + identifier); } else if (idk == CP_PARSER_ID_KIND_UNQUALIFIED && TREE_CODE (postfix_expression) == IDENTIFIER_NODE) @@ -3845,25 +3826,31 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p) break; } - /* In the body of a template, no further processing is - required. */ - if (processing_template_decl) + if (TREE_CODE (postfix_expression) == COMPONENT_REF) { - postfix_expression = build_nt (CALL_EXPR, - postfix_expression, - args); - break; + tree instance = TREE_OPERAND (postfix_expression, 0); + tree fn = TREE_OPERAND (postfix_expression, 1); + + if (processing_template_decl + && (type_dependent_expression_p (instance) + || (!BASELINK_P (fn) + && TREE_CODE (fn) != FIELD_DECL) + || any_type_dependent_arguments_p (args))) + { + postfix_expression + = build_min_nt (CALL_EXPR, postfix_expression, args); + break; + } + + postfix_expression + = (build_new_method_call + (instance, fn, args, NULL_TREE, + (idk == CP_PARSER_ID_KIND_QUALIFIED + ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL))); } - - if (TREE_CODE (postfix_expression) == COMPONENT_REF) - postfix_expression - = (build_new_method_call - (TREE_OPERAND (postfix_expression, 0), - TREE_OPERAND (postfix_expression, 1), - args, NULL_TREE, - (idk == CP_PARSER_ID_KIND_QUALIFIED - ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL))); - else if (TREE_CODE (postfix_expression) == OFFSET_REF) + else if (TREE_CODE (postfix_expression) == OFFSET_REF + || TREE_CODE (postfix_expression) == MEMBER_REF + || TREE_CODE (postfix_expression) == DOTSTAR_EXPR) postfix_expression = (build_offset_ref_call_from_tree (postfix_expression, args)); else if (idk == CP_PARSER_ID_KIND_QUALIFIED) @@ -3967,8 +3954,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p) struct X { void f(); }; template <typename T> void f(T* t) { t->X::f(); } - Even though "t" is dependent, "X::f" is not and has - except that for a BASELINK there is no need to + Even though "t" is dependent, "X::f" is not and has + been resolved to a BASELINK; there is no need to include scope information. */ /* But we do need to remember that there was an explicit @@ -4336,7 +4323,8 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p) return build_x_indirect_ref (cast_expression, "unary *"); case ADDR_EXPR: - return build_x_unary_op (ADDR_EXPR, cast_expression); + case BIT_NOT_EXPR: + return build_x_unary_op (unary_operator, cast_expression); case PREINCREMENT_EXPR: case PREDECREMENT_EXPR: @@ -4354,9 +4342,6 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p) case TRUTH_NOT_EXPR: return finish_unary_op_expr (unary_operator, cast_expression); - case BIT_NOT_EXPR: - return build_x_unary_op (BIT_NOT_EXPR, cast_expression); - default: abort (); return error_mark_node; @@ -5293,7 +5278,6 @@ static tree cp_parser_expression (cp_parser* parser) { tree expression = NULL_TREE; - bool saw_comma_p = false; while (true) { @@ -5306,45 +5290,23 @@ cp_parser_expression (cp_parser* parser) save it away. */ if (!expression) expression = assignment_expression; - /* Otherwise, chain the expressions together. It is unclear why - we do not simply build COMPOUND_EXPRs as we go. */ else - expression = tree_cons (NULL_TREE, - assignment_expression, - expression); + expression = build_x_compound_expr (expression, + assignment_expression); /* If the next token is not a comma, then we are done with the expression. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) break; /* Consume the `,'. */ cp_lexer_consume_token (parser->lexer); - /* The first time we see a `,', we must take special action - because the representation used for a single expression is - different from that used for a list containing the single - expression. */ - if (!saw_comma_p) - { - /* Remember that this expression has a `,' in it. */ - saw_comma_p = true; - /* Turn the EXPRESSION into a TREE_LIST so that we can link - additional expressions to it. */ - expression = build_tree_list (NULL_TREE, expression); - } - } - - /* Build a COMPOUND_EXPR to represent the entire expression, if - necessary. We built up the list in reverse order, so we must - straighten it out here. */ - if (saw_comma_p) - { /* A comma operator cannot appear in a constant-expression. */ if (parser->constant_expression_p) { if (!parser->allow_non_constant_expression_p) - return cp_parser_non_constant_expression ("a comma operator"); + expression + = cp_parser_non_constant_expression ("a comma operator"); parser->non_constant_expression_p = true; } - expression = build_x_compound_expr (nreverse (expression)); } return expression; @@ -5356,8 +5318,9 @@ cp_parser_expression (cp_parser* parser) conditional-expression If ALLOW_NON_CONSTANT_P a non-constant expression is silently - accepted. In that case *NON_CONSTANT_P is set to TRUE. If - ALLOW_NON_CONSTANT_P is false, NON_CONSTANT_P should be NULL. */ + accepted. If ALLOW_NON_CONSTANT_P is true and the expression is not + constant, *NON_CONSTANT_P is set to TRUE. If ALLOW_NON_CONSTANT_P + is false, NON_CONSTANT_P should be NULL. */ static tree cp_parser_constant_expression (cp_parser* parser, @@ -5547,7 +5510,7 @@ cp_parser_labeled_statement (cp_parser* parser) cp_lexer_consume_token (parser->lexer); /* Parse the constant-expression. */ expr = cp_parser_constant_expression (parser, - /*allow_non_constant=*/false, + /*allow_non_constant_p=*/false, NULL); /* Create the label. */ statement = finish_case_label (expr, NULL_TREE); @@ -8051,13 +8014,21 @@ cp_parser_template_argument_list (cp_parser* parser) The representation is that of an assignment-expression, type-id, or id-expression -- except that the qualified id-expression is evaluated, so that the value returned is either a DECL or an - OVERLOAD. */ + OVERLOAD. + + Although the standard says "assignment-expression", it forbids + throw-expressions or assignments in the template argument. + Therefore, we use "conditional-expression" instead. */ static tree cp_parser_template_argument (cp_parser* parser) { tree argument; bool template_p; + bool address_p; + cp_token *token; + cp_parser_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. @@ -8073,8 +8044,7 @@ cp_parser_template_argument (cp_parser* parser) argument = cp_parser_type_id (parser); /* If the next token isn't a `,' or a `>', then this argument wasn't really finished. */ - if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA) - && cp_lexer_next_token_is_not (parser->lexer, CPP_GREATER)) + if (!cp_parser_next_token_ends_template_argument_p (parser)) cp_parser_error (parser, "expected template-argument"); /* If that worked, we're done. */ if (cp_parser_parse_definitely (parser)) @@ -8088,8 +8058,7 @@ cp_parser_template_argument (cp_parser* parser) &template_p); /* If the next token isn't a `,' or a `>', then this argument wasn't really finished. */ - if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA) - && cp_lexer_next_token_is_not (parser->lexer, CPP_GREATER)) + if (!cp_parser_next_token_ends_template_argument_p (parser)) cp_parser_error (parser, "expected template-argument"); if (!cp_parser_error_occurred (parser)) { @@ -8104,8 +8073,101 @@ cp_parser_template_argument (cp_parser* parser) } if (cp_parser_parse_definitely (parser)) return argument; - /* It must be an assignment-expression. */ - return cp_parser_assignment_expression (parser); + /* It must be a non-type argument. There permitted cases are given + in [temp.arg.nontype]: + + -- an integral constant-expression of integral or enumeration + type; or + + -- the name of a non-type template-parameter; or + + -- the name of an object or function with external linkage... + + -- the address of an object or function with external linkage... + + -- a pointer to member... */ + /* Look for a non-type template parameter. */ + if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)) + { + cp_parser_parse_tentatively (parser); + argument = cp_parser_primary_expression (parser, + &idk, + &qualifying_class); + if (TREE_CODE (argument) != TEMPLATE_PARM_INDEX + || !cp_parser_next_token_ends_template_argument_p (parser)) + cp_parser_simulate_error (parser); + if (cp_parser_parse_definitely (parser)) + return argument; + } + /* If the next token is "&", the argument must be the address of an + object or function with external linkage. */ + address_p = cp_lexer_next_token_is (parser->lexer, CPP_AND); + if (address_p) + cp_lexer_consume_token (parser->lexer); + /* See if we might have an id-expression. */ + token = cp_lexer_peek_token (parser->lexer); + if (token->type == CPP_NAME + || token->keyword == RID_OPERATOR + || token->type == CPP_SCOPE + || token->type == CPP_TEMPLATE_ID + || token->type == CPP_NESTED_NAME_SPECIFIER) + { + cp_parser_parse_tentatively (parser); + argument = cp_parser_primary_expression (parser, + &idk, + &qualifying_class); + if (cp_parser_error_occurred (parser) + || !cp_parser_next_token_ends_template_argument_p (parser)) + cp_parser_abort_tentative_parse (parser); + else + { + if (qualifying_class) + argument = finish_qualified_id_expr (qualifying_class, + argument, + /*done=*/true, + address_p); + if (TREE_CODE (argument) == VAR_DECL) + { + /* A variable without external linkage might still be a + valid constant-expression, so no error is issued here + if the external-linkage check fails. */ + if (!DECL_EXTERNAL_LINKAGE_P (argument)) + cp_parser_simulate_error (parser); + } + else if (is_overloaded_fn (argument)) + /* All overloaded functions are allowed; if the external + linkage test does not pass, an error will be issued + later. */ + ; + else if (address_p + && (TREE_CODE (argument) == OFFSET_REF + || TREE_CODE (argument) == SCOPE_REF)) + /* A pointer-to-member. */ + ; + else + cp_parser_simulate_error (parser); + + if (cp_parser_parse_definitely (parser)) + { + if (address_p) + argument = build_x_unary_op (ADDR_EXPR, argument); + return argument; + } + } + } + /* If the argument started with "&", there are no other valid + alternatives at this point. */ + if (address_p) + { + cp_parser_error (parser, "invalid non-type template argument"); + return error_mark_node; + } + /* The argument must be a constant-expression. */ + argument = cp_parser_constant_expression (parser, + /*allow_non_constant_p=*/false, + /*non_constant_p=*/NULL); + /* If it's non-dependent, simplify it. */ + return cp_parser_fold_non_dependent_expr (argument); } /* Parse an explicit-instantiation. @@ -8914,7 +8976,7 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type) cp_lexer_consume_token (parser->lexer); /* Parse the value. */ value = cp_parser_constant_expression (parser, - /*allow_non_constant=*/false, + /*allow_non_constant_p=*/false, NULL); } else @@ -9919,29 +9981,8 @@ cp_parser_direct_declarator (cp_parser* parser, = cp_parser_constant_expression (parser, /*allow_non_constant=*/true, &non_constant_p); - /* If we're in a template, but the constant-expression - isn't value dependent, simplify it. We're supposed - to treat: - - template <typename T> void f(T[1 + 1]); - template <typename T> void f(T[2]); - - as two declarations of the same function, for - example. */ - if (processing_template_decl - && !non_constant_p - && !value_dependent_expression_p (bounds)) - { - HOST_WIDE_INT saved_processing_template_decl; - - saved_processing_template_decl = processing_template_decl; - processing_template_decl = 0; - bounds = tsubst_copy_and_build (bounds, - /*args=*/NULL_TREE, - tf_error, - /*in_decl=*/NULL_TREE); - processing_template_decl = saved_processing_template_decl; - } + if (!non_constant_p) + bounds = cp_parser_fold_non_dependent_expr (bounds); } else bounds = NULL_TREE; @@ -14129,6 +14170,36 @@ cp_parser_declares_only_class_p (cp_parser *parser) || cp_lexer_next_token_is (parser->lexer, CPP_COMMA)); } +/* Simplify EXPR if it is a non-dependent expression. Returns the + (possibly simplified) expression. */ + +static tree +cp_parser_fold_non_dependent_expr (tree expr) +{ + /* If we're in a template, but EXPR isn't value dependent, simplify + it. We're supposed to treat: + + template <typename T> void f(T[1 + 1]); + template <typename T> void f(T[2]); + + as two declarations of the same function, for example. */ + if (processing_template_decl + && !type_dependent_expression_p (expr) + && !value_dependent_expression_p (expr)) + { + HOST_WIDE_INT saved_processing_template_decl; + + saved_processing_template_decl = processing_template_decl; + processing_template_decl = 0; + expr = tsubst_copy_and_build (expr, + /*args=*/NULL_TREE, + tf_error, + /*in_decl=*/NULL_TREE); + processing_template_decl = saved_processing_template_decl; + } + return expr; +} + /* DECL_SPECIFIERS is the representation of a decl-specifier-seq. Returns TRUE iff `friend' appears among the DECL_SPECIFIERS. */ @@ -14274,6 +14345,18 @@ cp_parser_next_token_starts_class_definition_p (cp_parser *parser) return (token->type == CPP_OPEN_BRACE || token->type == CPP_COLON); } +/* Returns TRUE iff the next token is the "," or ">" ending a + template-argument. */ + +static bool +cp_parser_next_token_ends_template_argument_p (cp_parser *parser) +{ + cp_token *token; + + token = cp_lexer_peek_token (parser->lexer); + return (token->type == CPP_COMMA || token->type == CPP_GREATER); +} + /* Returns the kind of tag indicated by TOKEN, if it is a class-key, or none_type otherwise. */ |