Index: cp/parser.c =================================================================== --- cp/parser.c (revision 224575) +++ cp/parser.c (working copy) @@ -1953,9 +1953,10 @@ static bool cp_parser_translation_unit static tree cp_parser_primary_expression (cp_parser *, bool, bool, bool, cp_id_kind *); static tree cp_parser_id_expression - (cp_parser *, bool, bool, bool *, bool, bool); + (cp_parser *, bool, bool, bool * = NULL, + bool = false, bool = false, bool = false); static tree cp_parser_unqualified_id - (cp_parser *, bool, bool, bool, bool); + (cp_parser *, bool, 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 @@ -3095,8 +3096,7 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp /*template_keyword_p=*/false, /*check_dependency_p=*/true, /*template_p=*/NULL, - /*declarator_p=*/true, - /*optional_p=*/false); + /*declarator_p=*/true); /* If the next token is a (, this is a function with no explicit return type, i.e. constructor, destructor or conversion op. */ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN) @@ -4637,9 +4637,7 @@ cp_parser_primary_expression (cp_parser *parser, = cp_parser_id_expression (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, - &template_p, - /*declarator_p=*/false, - /*optional_p=*/false); + &template_p); if (id_expression == error_mark_node) return error_mark_node; id_expr_token = token; @@ -4821,7 +4819,8 @@ cp_parser_id_expression (cp_parser *parser, bool check_dependency_p, bool *template_p, bool declarator_p, - bool optional_p) + bool optional_p, + bool decltype_p) { bool global_scope_p; bool nested_name_specifier_p; @@ -4865,7 +4864,8 @@ cp_parser_id_expression (cp_parser *parser, unqualified_id = cp_parser_unqualified_id (parser, *template_p, check_dependency_p, declarator_p, - /*optional_p=*/false); + /*optional_p=*/false, + decltype_p); /* Restore the SAVED_SCOPE for our caller. */ parser->scope = saved_scope; parser->object_scope = saved_object_scope; @@ -4925,7 +4925,8 @@ cp_parser_id_expression (cp_parser *parser, return cp_parser_unqualified_id (parser, template_keyword_p, /*check_dependency_p=*/true, declarator_p, - optional_p); + optional_p, + decltype_p); } /* Parse an unqualified-id. @@ -4955,7 +4956,8 @@ cp_parser_unqualified_id (cp_parser* parser, bool template_keyword_p, bool check_dependency_p, bool declarator_p, - bool optional_p) + bool optional_p, + bool decltype_p) { cp_token *token; @@ -5161,7 +5163,13 @@ cp_parser_unqualified_id (cp_parser* parser, && ! cp_parser_parse_definitely (parser)) { /* We couldn't find a type with this name, so just accept - it and check for a match at instantiation time. */ + it and check for a match at instantiation time. However + don't do that if we are parsing the immediate operand of + a decltype as an id-expression, because definitely the + production ~ class-name isn't ok and we want to look for + a complement expression (c++/65091). */ + if (decltype_p) + return error_mark_node; type_decl = cp_parser_identifier (parser); if (type_decl != error_mark_node) type_decl = build_nt (BIT_NOT_EXPR, type_decl); @@ -6709,9 +6717,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser (parser, cp_parser_optional_template_keyword (parser), /*check_dependency_p=*/true, - &template_p, - /*declarator_p=*/false, - /*optional_p=*/false)); + &template_p)); /* 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; @@ -12250,7 +12256,8 @@ cp_parser_decltype_expr (cp_parser *parser, /*check_dependency_p=*/true, /*template_p=*/NULL, /*declarator_p=*/false, - /*optional_p=*/false); + /*optional_p=*/false, + /*decltype_p=*/true); if (!cp_parser_error_occurred (parser) && expr != error_mark_node) { @@ -13629,9 +13636,7 @@ cp_parser_type_parameter (cp_parser* parser, bool = cp_parser_id_expression (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, - /*template_p=*/&is_template, - /*declarator_p=*/false, - /*optional_p=*/false); + /*template_p=*/&is_template); 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, @@ -14273,9 +14278,7 @@ cp_parser_template_argument (cp_parser* parser) argument = cp_parser_id_expression (parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, - &template_p, - /*declarator_p=*/false, - /*optional_p=*/false); + &template_p); /* 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)) @@ -16441,7 +16444,8 @@ cp_parser_using_declaration (cp_parser* parser, /*template_keyword_p=*/false, /*check_dependency_p=*/true, /*declarator_p=*/true, - /*optional_p=*/false); + /*optional_p=*/false, + /*decltype_p=*/false); if (access_declaration_p) { @@ -23253,7 +23257,8 @@ cp_parser_constructor_declarator_p (cp_parser *par /*template_keyword_p=*/false, /*check_dependency_p=*/false, /*declarator_p=*/true, - /*optional_p=*/false); + /*optional_p=*/false, + /*decltype_p=*/false); if (is_overloaded_fn (id)) id = DECL_NAME (get_first_fn (id)); if (!constructor_name_p (id, nested_name_specifier)) @@ -27823,10 +27828,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, token = cp_lexer_peek_token (parser->lexer); name = cp_parser_id_expression (parser, /*template_p=*/false, - /*check_dependency_p=*/true, - /*template_p=*/NULL, - /*declarator_p=*/false, - /*optional_p=*/false); + /*check_dependency_p=*/true); if (name == error_mark_node) goto skip_comma; @@ -28529,10 +28531,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; parser->colon_corrects_to_scope_p = false; id = cp_parser_id_expression (parser, /*template_p=*/false, - /*check_dependency_p=*/true, - /*template_p=*/NULL, - /*declarator_p=*/false, - /*optional_p=*/false); + /*check_dependency_p=*/true); parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; if (identifier_p (id)) { @@ -32166,10 +32165,7 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl { cp_parser_parse_tentatively (parser); tree fn_name = cp_parser_id_expression (parser, /*template_p=*/false, - /*check_dependency_p=*/true, - /*template_p=*/NULL, - /*declarator_p=*/false, - /*optional_p=*/false); + /*check_dependency_p=*/true); vec *args; if (fn_name == error_mark_node || cp_parser_error_occurred (parser) @@ -33347,8 +33343,7 @@ cp_parser_cilk_simd_linear (cp_parser *parser, tre break; } - tree var_name = cp_parser_id_expression (parser, false, true, NULL, - false, false); + tree var_name = cp_parser_id_expression (parser, false, true); tree decl = cp_parser_lookup_name_simple (parser, var_name, token->location); if (decl == error_mark_node) Index: testsuite/g++.dg/cpp0x/decltype63.C =================================================================== --- testsuite/g++.dg/cpp0x/decltype63.C (revision 0) +++ testsuite/g++.dg/cpp0x/decltype63.C (working copy) @@ -0,0 +1,9 @@ +// PR c++/65091 +// { dg-do compile { target c++11 } } + +template +auto foo(T x) -> decltype(~x) +{ return ~x; } + +int bar() +{ return foo(10); }