Hi again,

I'm finishing testing this different idea, a much bigger patch but arguably more neat: add a bool parameter to cp_parser_id_expression and then to cp_parser_unqualified_id and pass down 'true' from cp_parser_decltype_expr (this is also nicely consistent with the 'true' we are passing to cp_parser_postfix_expression and cp_parser_expression).

What do you think?

Thanks,
Paolo.

//////////////////////
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<tree, va_gc> *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<typename T>
+auto foo(T x) -> decltype(~x)
+{ return ~x; }
+
+int bar()
+{ return foo(10); }

Reply via email to