Add a "vexing parse" warning for ambiguity between a variable declaration and a
function-style cast.

This fires for cases such as

  T(x);

... where 'x' was previously declared and T is a type. This construct declares
a variable named 'x' rather than the (probably expected) interpretation of a
function-style cast of 'x' to T.

llvm-svn: 314570
diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
index 18b1883..cf58a85 100644
--- a/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
+++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.qual/class.qual/p2.cpp
@@ -73,6 +73,7 @@
   int a;
   {
     X0::X0(a); // expected-error{{qualified reference to 'X0' is a constructor name rather than a type in this context}}
+    // expected-warning@-1 {{redundant parentheses around declaration of variable named 'a'}} expected-note@-1 2{{}}
   }
 }
 
diff --git a/clang/test/FixIt/fixit-vexing-parse.cpp b/clang/test/FixIt/fixit-vexing-parse.cpp
index 71d3eff..973c696 100644
--- a/clang/test/FixIt/fixit-vexing-parse.cpp
+++ b/clang/test/FixIt/fixit-vexing-parse.cpp
@@ -106,3 +106,24 @@
     wchar_t wc(); // expected-warning {{function declaration}} expected-note {{replace parentheses with an initializer}}
   }
 }
+
+namespace RedundantParens {
+struct Y {
+  Y();
+  Y(int);
+  ~Y();
+};
+int n;
+
+void test() {
+  // CHECK: add a variable name
+  // CHECK: fix-it:"{{.*}}":{[[@LINE+7]]:4-[[@LINE+7]]:4}:" varname"
+  // CHECK: add enclosing parentheses
+  // CHECK: fix-it:"{{.*}}":{[[@LINE+5]]:3-[[@LINE+5]]:3}:"("
+  // CHECK: fix-it:"{{.*}}":{[[@LINE+4]]:7-[[@LINE+4]]:7}:")"
+  // CHECK: remove parentheses
+  // CHECK: fix-it:"{{.*}}":{[[@LINE+2]]:4-[[@LINE+2]]:5}:" "
+  // CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:6-[[@LINE+1]]:7}:""
+  Y(n); // expected-warning {{declaration of variable named 'n'}} expected-note 3{{}}
+}
+}
diff --git a/clang/test/Parser/cxx0x-condition.cpp b/clang/test/Parser/cxx0x-condition.cpp
index 071e09e..19d5a73 100644
--- a/clang/test/Parser/cxx0x-condition.cpp
+++ b/clang/test/Parser/cxx0x-condition.cpp
@@ -14,11 +14,11 @@
   for (; int x = ++a; ) ;
 
   if (S(a)) {} // ok
-  if (S(a) = 0) {} // ok
+  if (S(a) = 0) {} // expected-warning {{redundant parentheses}} expected-note 2{{}}
   if (S(a) == 0) {} // ok
 
   if (S(n)) {} // expected-error {{unexpected type name 'n': expected expression}}
-  if (S(n) = 0) {} // ok
+  if (S(n) = 0) {} // expected-warning {{redundant parentheses}} expected-note 2{{}}
   if (S(n) == 0) {} // expected-error {{unexpected type name 'n': expected expression}}
 
   if (S b(a)) {} // expected-error {{variable declaration in condition cannot have a parenthesized initializer}}
diff --git a/clang/test/Parser/cxx1z-class-template-argument-deduction.cpp b/clang/test/Parser/cxx1z-class-template-argument-deduction.cpp
index dac17df..b8f5a82 100644
--- a/clang/test/Parser/cxx1z-class-template-argument-deduction.cpp
+++ b/clang/test/Parser/cxx1z-class-template-argument-deduction.cpp
@@ -180,6 +180,7 @@
     {(void)(typename T::A)(0);} // expected-error{{refers to class template member}}
     {(void)(typename T::A){0};} // expected-error{{refers to class template member}}
     {typename T::A (parens) = 0;} // expected-error {{refers to class template member in 'typename_specifier::X'; argument deduction not allowed here}}
+    // expected-warning@-1 {{disambiguated as redundant parentheses around declaration of variable named 'parens'}} expected-note@-1 {{add a variable name}} expected-note@-1{{remove parentheses}} expected-note@-1 {{add enclosing parentheses}}
     {typename T::A *p = 0;} // expected-error {{refers to class template member}}
     {typename T::A &r = *p;} // expected-error {{refers to class template member}}
     {typename T::A arr[3] = 0;} // expected-error {{refers to class template member}}
diff --git a/clang/test/SemaCXX/decl-expr-ambiguity.cpp b/clang/test/SemaCXX/decl-expr-ambiguity.cpp
index 1b1f7dc..1e31d70 100644
--- a/clang/test/SemaCXX/decl-expr-ambiguity.cpp
+++ b/clang/test/SemaCXX/decl-expr-ambiguity.cpp
@@ -48,13 +48,20 @@
 
 struct RAII {
   RAII();
+  RAII(int);
   ~RAII();
 };
 
+struct NotRAII {
+  NotRAII();
+  NotRAII(int);
+};
+
 void func();
 void func2(short);
 namespace N {
   struct S;
+  int n;
 
   void emptyParens() {
     RAII raii(); // expected-warning {{function declaration}} expected-note {{remove parentheses to declare a variable}}
@@ -69,6 +76,23 @@
   void nonEmptyParens() {
     int f = 0, // g = 0; expected-note {{change this ',' to a ';' to call 'func2'}}
     func2(short(f)); // expected-warning {{function declaration}} expected-note {{add a pair of parentheses}}
+
+    RAII(n); // expected-warning {{parentheses were disambiguated as redundant parentheses around declaration of variable named 'n'}}
+    // expected-note@-1 {{add a variable name to declare a 'RAII' initialized with 'n'}}
+    // expected-note@-2 {{add enclosing parentheses to perform a function-style cast}}
+    // expected-note@-3 {{remove parentheses to silence this warning}}
+
+    RAII(undeclared1);
+#pragma clang diagnostic push
+#pragma clang diagnostic warning "-Wredundant-parens"
+    RAII(undeclared2); // expected-warning {{redundant parentheses surrounding declarator}}
+#pragma clang diagnostic pop
+
+    {
+      NotRAII(n); // expected-warning {{parentheses were disambiguated as redundant parentheses around declaration of variable named 'n'}}
+      // expected-note@-1 {{add enclosing parentheses to perform a function-style cast}}
+      // expected-note@-2 {{remove parentheses to silence this warning}}
+    }
   }
 }