From 8905b21458329471de04b288cc01b35cec7f311b Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Fri, 27 Jul 2018 12:32:44 -0400
Subject: [PATCH 16/18] FIXME: WIP on -Wvexing-parse

---
 gcc/c-family/c.opt                          |   4 +
 gcc/cp/parser.c                             |  50 ++++++-
 gcc/testsuite/g++.dg/warn/Wvexing-parse-1.C | 219 ++++++++++++++++++++++++++++
 3 files changed, 272 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/Wvexing-parse-1.C

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index d614838..fe3cc3d 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1157,6 +1157,10 @@ Wvarargs
 C ObjC C++ ObjC++ Warning Var(warn_varargs) Init(1)
 Warn about questionable usage of the macros used to retrieve variable arguments.
 
+Wvexing-parse
+C++ Var(warn_vexing_parse) Warning LangEnabledBy(C++,Wall)
+FIXME
+
 Wvla
 C ObjC C++ ObjC++ Var(warn_vla) Init(-1) Warning
 Warn if a variable length array is used.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index da475bd..c3ec0af 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1089,6 +1089,8 @@ cp_lexer_consume_token (cp_lexer* lexer)
   gcc_assert (token != &eof_token);
   gcc_assert (!lexer->in_pragma || token->type != CPP_PRAGMA_EOL);
 
+  //inform (token->location, "consuming token");
+
   do
     {
       lexer->next_token++;
@@ -1201,6 +1203,11 @@ cp_lexer_rollback_tokens (cp_lexer* lexer)
     fprintf (cp_lexer_debug_stream, "cp_lexer: restoring tokens\n");
 
   lexer->next_token = lexer->saved_tokens.pop ();
+
+#if 0
+  inform (lexer->next_token->location,
+	  "rolling back tokens; this one is now next");
+#endif
 }
 
 /* RAII wrapper around the above functions, with sanity checking.  Creating
@@ -19737,6 +19744,10 @@ cp_parser_init_declarator (cp_parser* parser,
       initialization_kind = CPP_EOF;
     }
 
+#if 0
+  inform (token->location, "init-declarator");
+#endif
+
   /* Because start_decl has side-effects, we should only call it if we
      know we're going ahead.  By this point, we know that we cannot
      possibly be looking at any other construct.  */
@@ -20121,6 +20132,7 @@ cp_parser_direct_declarator (cp_parser* parser,
 
 	     Thus again, we try a parameter-declaration-clause, and if
 	     that fails, we back out and return.  */
+	  // inform (token->location, "-Wvexing-parse here? %i %i", dcl_kind, first);
 
 	  if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
 	    {
@@ -20151,16 +20163,45 @@ cp_parser_direct_declarator (cp_parser* parser,
 
 	      begin_scope (sk_function_parms, NULL_TREE);
 
+#if 0
+	      inform (token->location, "parameter-declaration-clause");
+#endif
+
 	      /* Parse the parameter-declaration-clause.  */
 	      params = cp_parser_parameter_declaration_clause (parser);
 
 	      /* Consume the `)'.  */
-	      parens.require_close (parser);
+	      cp_token *close_paren = parens.require_close (parser);
 
 	      /* If all went well, parse the cv-qualifier-seq,
 		 ref-qualifier and the exception-specification.  */
 	      if (member_p || cp_parser_parse_definitely (parser))
 		{
+#if 0
+		  inform (token->location,
+			  "successfully parsed as a parameter-declaration-clause");
+#endif
+		  // maybe -Wvexing-parse here?
+		  // presumably only if there are no params, which is an empty TREE_LIST
+		  if (params == void_list_node && close_paren)
+		    {
+		      // FIXME: but this is giving false positives: we only want to
+		      // emit this warning for that case where it could be a decl.
+		      location_t parens_loc
+			= make_location (token->location, token->location,
+					 close_paren->location);
+		      // FIXME: but what about "(void)"?
+		      if (warning_at (parens_loc, OPT_Wvexing_parse,
+				      "empty parentheses interpreted as a"
+				      " function declaration"))
+			{
+			  gcc_rich_location richloc (parens_loc);
+			  richloc.add_fixit_remove ();
+			  inform (&richloc,
+				  "remove parentheses to declare a variable");
+			}
+		    }
+		  // 
 		  cp_cv_quals cv_quals;
 		  cp_virt_specifiers virt_specifiers;
 		  cp_ref_qualifier ref_qual;
@@ -20232,6 +20273,10 @@ cp_parser_direct_declarator (cp_parser* parser,
 	    {
 	      bool saved_in_type_id_in_expr_p;
 
+#if 0
+	      inform (token->location, "try a declarator?");
+#endif
+
 	      parser->default_arg_ok_p = saved_default_arg_ok_p;
 	      parser->in_declarator_p = saved_in_declarator_p;
 
@@ -21696,6 +21741,9 @@ cp_parser_parameter_declaration (cp_parser *parser,
 	cp_parser_commit_to_tentative_parse (parser);
       /* Parse the declarator.  */
       declarator_token_start = token;
+#if 0
+      inform (input_location, "got here");
+#endif
       declarator = cp_parser_declarator (parser,
 					 CP_PARSER_DECLARATOR_EITHER,
 					 /*ctor_dtor_or_conv_p=*/NULL,
diff --git a/gcc/testsuite/g++.dg/warn/Wvexing-parse-1.C b/gcc/testsuite/g++.dg/warn/Wvexing-parse-1.C
new file mode 100644
index 0000000..45dbf84
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wvexing-parse-1.C
@@ -0,0 +1,219 @@
+// { dg-do compile }
+// { dg-warning "-Wvexing-parse" }
+
+
+// Taken from Scott Meyer's "Effective STL":
+#if 1
+int f(double d);
+int f(double (d));
+int f(double);
+int g(double (*pf)());
+int g(double pf());
+int g(double ());
+#endif
+
+// Taken from cp/parser.c:
+#if 1
+int t1 (int);
+#endif
+#if 1
+int t2 (3);
+#endif
+#if 1
+int t3 (int (a));
+int t4 (int (3));
+#endif
+
+
+/*
+
+For both t1 and t2, it tries a parameter-declaration-clause
+But this only appears to succeed for t1; it fails for t2.
+
+t1:
+  |-declaration 0x432bb00 <16:1-16:13>
+  |  |:          0         0         0         0         0         0         0         0         0         1         1         1         1
+  |  |:          1         2         3         4         5         6         7         8         9         0         1         2         3
+  |  |: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+  |  |: int t1 (int);
+  |  |: ^~~~~~~~~~~~~
+  |  `-block-declaration 0x432b740 <16:1-16:13>
+  |    `-simple-declaration 0x432c730 <16:1-16:13>
+  |      |-decl-specifier-seq 0x432c780 <16:1-16:3>
+  |      |  |:          0         0         0         0         0         0         0         0         0         1         1         1         1
+  |      |  |:          1         2         3         4         5         6         7         8         9         0         1         2         3
+  |      |  |: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+  |      |  |: int t1 (int);
+  |      |  |: ^~~
+  |      |  |-type-specifier 0x439e4c0 <16:1-16:3>
+  |      |  `-type-specifier 0x439e510 <16:5-16:3>
+  |      |    |:          0         0         0         0         0         0         0         0         0         1         1         1         1
+  |      |    |:          1         2         3         4         5         6         7         8         9         0         1         2         3
+  |      |    |: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+  |      |    |: int t1 (int);
+  |      |    |:      
+  |      |-declarator 0x432d7c0 <16:5-16:12>
+  |      |  |:          0         0         0         0         0         0         0         0         0         1         1         1         1
+  |      |  |:          1         2         3         4         5         6         7         8         9         0         1         2         3
+  |      |  |: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+  |      |  |: int t1 (int);
+  |      |  |:     ^~~~~~~~
+  |      |  `-direct-declarator 0x432d810 <16:5-16:12>
+  |      |    |-id-expression 0x432d860 <16:5-16:6>
+  |      |    |  |:          0         0         0         0         0         0         0         0         0         1         1         1         1
+  |      |    |  |:          1         2         3         4         5         6         7         8         9         0         1         2         3
+  |      |    |  |: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+  |      |    |  |: int t1 (int);
+  |      |    |  |:     ^~
+  |      |    |  `-unqualified-id 0x432d9f0 <16:5-16:6>
+  |      |    |    `-identifier 0x432da40 <16:5-16:6>
+  |      |    |      `-NAME-token 0x432da90 <16:5-16:6>
+  |      |    |-(-token 0x432b9c0 <16:8>
+  |      |    |  |:          0         0         0         0         0         0         0         0         0         1         1         1         1
+  |      |    |  |:          1         2         3         4         5         6         7         8         9         0         1         2         3
+  |      |    |  |: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+  |      |    |  |: int t1 (int);
+  |      |    |  |:        ^
+  |      |    |-parameter-declaration-clause 0x432ba10 <16:9-16:11>
+  |      |    |  |: int t1 (int);
+  |      |    |  |:         ^~~
+  |      |    |  `-parameter-declaration-list 0x432ba60 <16:9-16:11>
+  |      |    |    `-parameter-declaration 0x432fb50 <16:9-16:11>
+  |      |    |      `-decl-specifier-seq 0x432fba0 <16:9-16:11>
+  |      |    |        |-type-specifier 0x432fbf0 <16:9-16:11>
+  |      |    |        `-type-specifier 0x432bc40 <16:12-16:11>
+
+t2:
+
+  |-declaration 0x432c660 <17:1-17:11>
+  |  |:          0         0         0         0         0         0         0         0         0         1         1         1         1
+  |  |:          1         2         3         4         5         6         7         8         9         0         1         2         3
+  |  |: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+  |  |: int t2 (3);
+  |  |: ^~~~~~~~~~~
+  |  `-block-declaration 0x432bd20 <17:1-17:11>
+  |    `-simple-declaration 0x432c820 <17:1-17:11>
+  |      |-decl-specifier-seq 0x432c870 <17:1-17:3>
+  |      |  |:          0         0         0         0         0         0         0         0         0         1         1         1         1
+  |      |  |:          1         2         3         4         5         6         7         8         9         0         1         2         3
+  |      |  |: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+  |      |  |: int t2 (3);
+  |      |  |: ^~~
+  |      |  |-type-specifier 0x432c8c0 <17:1-17:3>
+  |      |  `-type-specifier 0x432c910 <17:5-17:3>
+  |      |    |:          0         0         0         0         0         0         0         0         0         1         1         1         1
+  |      |    |:          1         2         3         4         5         6         7         8         9         0         1         2         3
+  |      |    |: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+  |      |    |: int t2 (3);
+  |      |    |:      
+  |      |-declarator 0x432ccd0 <17:5-17:6>
+  |      |  |:          0         0         0         0         0         0         0         0         0         1         1         1         1
+  |      |  |:          1         2         3         4         5         6         7         8         9         0         1         2         3
+  |      |  |: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+  |      |  |: int t2 (3);
+  |      |  |:     ^~
+  |      |  `-direct-declarator 0x432cd20 <17:5-17:6>
+  |      |    |-id-expression 0x432cd70 <17:5-17:6>
+  |      |    |  `-unqualified-id 0x432cdc0 <17:5-17:6>
+  |      |    |    `-identifier 0x432d040 <17:5-17:6>
+  |      |    |      `-NAME-token 0x432d090 <17:5-17:6>
+  |      |    |-(-token 0x432d0e0 <17:8>
+  |      |    |  |:          0         0         0         0         0         0         0         0         0         1         1         1         1
+  |      |    |  |:          1         2         3         4         5         6         7         8         9         0         1         2         3
+  |      |    |  |: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+  |      |    |  |: int t2 (3);
+  |      |    |  |:        ^
+  |      |    `-parameter-declaration-clause 0x432d130 <17:9-17:8>
+  |      |      |:          0         0         0         0         0         0         0         0         0         1         1         1         1
+  |      |      |:          1         2         3         4         5         6         7         8         9         0         1         2         3
+  |      |      |: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+  |      |      |: int t2 (3);
+  |      |      |:          
+  |      |      `-parameter-declaration-list 0x432d270 <17:9-17:8>
+  |      |        `-parameter-declaration 0x432d2c0 <17:9-17:8>
+  |      |          `-decl-specifier-seq 0x432d310 <17:9-17:8>
+  |      |            |-type-specifier 0x432d360 <17:9-17:8>
+  |      |            |  `-identifier 0x432d450 <17:9-17:8>
+  |      |            `-type-specifier 0x432d4a0 <17:9-17:8>
+  |      |-expression-list 0x432d4f0 <17:8-17:10>
+  |      |  |:          0         0         0         0         0         0         0         0         0         1         1         1         1
+  |      |  |:          1         2         3         4         5         6         7         8         9         0         1         2         3
+  |      |  |: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+  |      |  |: int t2 (3);
+  |      |  |:        ^~~
+  |      |  |-(-token 0x432d540 <17:8>
+  |      |  |  |:          0         0         0         0         0         0         0         0         0         1         1         1         1
+  |      |  |  |:          1         2         3         4         5         6         7         8         9         0         1         2         3
+  |      |  |  |: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+  |      |  |  |: int t2 (3);
+  |      |  |  |:        ^
+  |      |  |-assignment-expression 0x432eb20 <17:9>
+  |      |  |  |:          0         0         0         0         0         0         0         0         0         1         1         1         1
+  |      |  |  |:          1         2         3         4         5         6         7         8         9         0         1         2         3
+  |      |  |  |: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+  |      |  |  |: int t2 (3);
+  |      |  |  |:         ^
+  |      |  |  `-unary-expression 0x432eb70 <17:9>
+  |      |  |    `-postfix-expression 0x432ebc0 <17:9>
+  |      |  |      |-identifier 0x432ec10 <17:9-17:8>
+  |      |  |      |  |:          0         0         0         0         0         0         0         0         0         1         1         1         1
+  |      |  |      |  |:          1         2         3         4         5         6         7         8         9         0         1         2         3
+  |      |  |      |  |: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
+  |      |  |      |  |: int t2 (3);
+  |      |  |      |  |:          
+  |      |  |      `-primary-expression 0x432ec60 <17:9>
+  |      |  `-)-token 0x4378d40 <17:10>
+*/
+
+
+
+// Adapted from PR c++/52960:
+struct s1 {};
+s1 fn_1();
+
+#if 1
+s1 test_1() {
+  s1 foo,
+    fn_1();
+  return foo;
+}
+#endif
+
+#if 1
+s1 test_2() {
+  s1 foo;
+  s1 fn_1();
+  return foo;
+}
+#endif
+
+#if 1
+s1 test_3() {
+  s1 foo,
+    unknown_2();
+  return foo;
+}
+#endif
+
+s1 test_4() {
+  //s1 foo;
+  s1 unknown_2();
+  //return foo;
+  return unknown_2;
+}
+
+// From PR c++/9217:
+
+#if 1
+struct A { A(char const*); };
+struct B { B(A const&); };
+struct C { C(B const&); };
+
+void f()
+{
+  char const* const str = "t";
+  static C c1(  B("t")  );      // Works.
+  static C c2( (B(str)) );      // Works.
+  static C c3(  B(str)  );      // Fails.
+}
+#endif
-- 
1.8.5.3

