The problem in this testcase was that we were initially tentatively parsing int(A) as a parameter declaration, then complaining about using that parameter as a template-argument. We should treat it as a parse error rather than a semantic error until we know how we really want to parse things.

The second patch fixes the diagnostic location of the pedwarn about using list-initialization in C++98 mode.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 4c3bf0de12cf730edf673cddedf43f8bdc8ef7ff
Author: Jason Merrill <ja...@redhat.com>
Date:   Mon Mar 3 15:41:03 2014 -0500

    	PR c++/60361
    	* parser.c (cp_parser_template_id): Don't set up a CPP_TEMPLATE_ID
    	if re-parsing might succeed.
    	* semantics.c (finish_id_expression): Use of a parameter outside
    	the function body is a parse error.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 5b3e489..b56870d 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -13466,7 +13466,12 @@ cp_parser_template_id (cp_parser *parser,
      the effort required to do the parse, nor will we issue duplicate
      error messages about problems during instantiation of the
      template.  */
-  if (start_of_id)
+  if (start_of_id
+      /* Don't do this if we had a parse error in a declarator; re-parsing
+	 might succeed if a name changes meaning (60361).  */
+      && !(cp_parser_error_occurred (parser)
+	   && cp_parser_parsing_tentatively (parser)
+	   && parser->in_declarator_p))
     {
       cp_token *token = cp_lexer_token_at (parser->lexer, start_of_id);
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 787eab8..4081e0e 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3246,7 +3246,7 @@ finish_id_expression (tree id_expression,
 	  && DECL_CONTEXT (decl) == NULL_TREE
 	  && !cp_unevaluated_operand)
 	{
-	  error ("use of parameter %qD outside function body", decl);
+	  *error_msg = "use of parameter outside function body";
 	  return error_mark_node;
 	}
     }
diff --git a/gcc/testsuite/g++.dg/parse/ambig7.C b/gcc/testsuite/g++.dg/parse/ambig7.C
new file mode 100644
index 0000000..9a5b879
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/ambig7.C
@@ -0,0 +1,16 @@
+// PR c++/60361
+
+struct Helper
+{
+  Helper(int a, void (*pfunc)());
+};
+
+template <int I> void function();
+
+const int A = 1;
+const int B = 2;
+
+Helper testOk(A, function<A>);
+Helper testOk2(int(A), function<B>);
+Helper testOk3((int(A)), function<A>);
+Helper testFail(int(A), function<A>);
diff --git a/gcc/testsuite/g++.dg/parse/parameter-declaration-2.C b/gcc/testsuite/g++.dg/parse/parameter-declaration-2.C
index 6116630..3c983cc 100644
--- a/gcc/testsuite/g++.dg/parse/parameter-declaration-2.C
+++ b/gcc/testsuite/g++.dg/parse/parameter-declaration-2.C
@@ -1,2 +1,2 @@
-void f (int i, int p[i]); // { dg-error "use of parameter .i. outside function body" }
+void f (int i, int p[i]); // { dg-error "use of parameter.*outside function body" }
 // { dg-prune-output "array bound" }
diff --git a/gcc/testsuite/g++.dg/parse/typename7.C b/gcc/testsuite/g++.dg/parse/typename7.C
index 6ec7696..e49a1ec 100644
--- a/gcc/testsuite/g++.dg/parse/typename7.C
+++ b/gcc/testsuite/g++.dg/parse/typename7.C
@@ -7,10 +7,9 @@
 
 struct A
 {
-  template<typename>   void foo(int); // { dg-message "note" }
-  template<typename T> void bar(T t) { // { dg-message "note" }
+  template<typename>   void foo(int);
+  template<typename T> void bar(T t) {
     this->foo<typename T>(t); } // { dg-error "expected|parse error|no matching" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 12 }
   template<typename T> void bad(T t) {
     foo<typename T>(t); } // { dg-error "expected|parse error|no matching" }
 };
@@ -20,7 +19,6 @@ struct B
 {
   void bar(T t) {
     A().bar<typename T>(t); } // { dg-error "expected|parse error|no matching" }
-  // { dg-message "candidate" "candidate note" { target *-*-* } 22 }
   void bad(T t) {
     B<typename T>::bar(t); } // { dg-error "invalid|qualified-id|not a template" }
 };
commit 575a4d70513faec5d8a66fe818a48a6abcf91500
Author: Jason Merrill <ja...@redhat.com>
Date:   Mon Mar 3 16:39:46 2014 -0500

    	* parser.c (cp_parser_mem_initializer): Set input_location
    	properly for init-list warning.
    	(cp_parser_postfix_open_square_expression): Likewise.
    	(cp_parser_parenthesized_expression_list): Likewise.
    	(cp_parser_new_initializer): Likewise.
    	(cp_parser_jump_statement): Likewise.
    	(cp_parser_initializer): Likewise.
    	(cp_parser_functional_cast): Likewise.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index bb7d268..5b3e489 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6359,6 +6359,8 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
       if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
 	{
 	  bool expr_nonconst_p;
+	  cp_token *token = cp_lexer_peek_token (parser->lexer);
+	  cp_lexer_set_source_position_from_token (token);
 	  maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
 	  index = cp_parser_braced_list (parser, &expr_nonconst_p);
 	  if (flag_cilkplus
@@ -6671,6 +6673,8 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
 	    if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
 	      {
 		/* A braced-init-list.  */
+		cp_token *token = cp_lexer_peek_token (parser->lexer);
+		cp_lexer_set_source_position_from_token (token);
 		maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
 		expr = cp_parser_braced_list (parser, &expr_non_constant_p);
 		if (non_constant_p && expr_non_constant_p)
@@ -7519,6 +7523,8 @@ cp_parser_new_initializer (cp_parser* parser)
     {
       tree t;
       bool expr_non_constant_p;
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      cp_lexer_set_source_position_from_token (token);
       maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
       t = cp_parser_braced_list (parser, &expr_non_constant_p);
       CONSTRUCTOR_IS_DIRECT_INIT (t) = 1;
@@ -10675,6 +10681,8 @@ cp_parser_jump_statement (cp_parser* parser)
 
 	if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
 	  {
+	    cp_token *token = cp_lexer_peek_token (parser->lexer);
+	    cp_lexer_set_source_position_from_token (token);
 	    maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
 	    expr = cp_parser_braced_list (parser, &expr_non_constant_p);
 	  }
@@ -12353,6 +12361,8 @@ cp_parser_mem_initializer (cp_parser* parser)
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
     {
       bool expr_non_constant_p;
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      cp_lexer_set_source_position_from_token (token);
       maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
       expression_list = cp_parser_braced_list (parser, &expr_non_constant_p);
       CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
@@ -18801,6 +18811,8 @@ cp_parser_initializer (cp_parser* parser, bool* is_direct_init,
     }
   else if (token->type == CPP_OPEN_BRACE)
     {
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      cp_lexer_set_source_position_from_token (token);
       maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
       init = cp_parser_braced_list (parser, non_constant_p);
       CONSTRUCTOR_IS_DIRECT_INIT (init) = 1;
@@ -23236,6 +23248,8 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
     {
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      cp_lexer_set_source_position_from_token (token);
       maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
       expression_list = cp_parser_braced_list (parser, &nonconst_p);
       CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
diff --git a/gcc/testsuite/g++.dg/template/crash90.C b/gcc/testsuite/g++.dg/template/crash90.C
index 6fe247c..4cfc408 100644
--- a/gcc/testsuite/g++.dg/template/crash90.C
+++ b/gcc/testsuite/g++.dg/template/crash90.C
@@ -4,5 +4,4 @@ template < unsigned >
 struct A ;
 template < typename >
 struct B ;
-template < typename T , A < B < T > // { dg-error "initializer|parse error|valid type|expected" }
-{ }
+template < typename T , A < B < T > {}// { dg-error "initializer|parse error|type|expected" }

Reply via email to