[C++ Patch/RFC] PR 65091

Paolo Carlini paolo.carlini@oracle.com
Wed Jun 17 23:38:00 GMT 2015


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.

//////////////////////
-------------- next part --------------
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); }


More information about the Gcc-patches mailing list