[cfe-commits] r151137 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Sema/DeclSpec.h lib/Parse/ParseExprCXX.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp test/Parser/cxx-condition.cpp test/Parser/cxx0x-condition.cpp test/SemaCXX/cxx0x-initializer-scalars.cpp

Richard Smith richard-llvm at metafoo.co.uk
Tue Feb 21 22:49:10 PST 2012


Author: rsmith
Date: Wed Feb 22 00:49:09 2012
New Revision: 151137

URL: http://llvm.org/viewvc/llvm-project?rev=151137&view=rev
Log:
Accept braced-init-lists in conditions, and, in passing, dramatically improve
the diagnostic for using a parenthesized direct-initializer in a condition.

Added:
    cfe/trunk/test/Parser/cxx0x-condition.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Sema/DeclSpec.h
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp
    cfe/trunk/test/Parser/cxx-condition.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=151137&r1=151136&r2=151137&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Wed Feb 22 00:49:09 2012
@@ -381,8 +381,10 @@
   "function definition does not declare parameters">;
 def err_expected_lparen_after_type : Error<
   "expected '(' for function-style cast or type construction">;
-def err_expected_equal_after_declarator : Error<
-  "expected '=' after declarator">;
+def err_expected_init_in_condition : Error<
+  "variable declaration in condition must have an initializer">;
+def err_expected_init_in_condition_lparen : Error<
+  "variable declaration in condition cannot have a parenthesized initializer">;
 def warn_parens_disambiguated_as_function_decl : Warning<
   "parentheses were disambiguated as a function declarator">,
   InGroup<VexingParse>;

Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=151137&r1=151136&r2=151137&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Wed Feb 22 00:49:09 2012
@@ -1645,9 +1645,14 @@
     case ForContext:
       return true;
 
+    case ConditionContext:
+      // This may not be followed by a direct initializer, but it can't be a
+      // function declaration either, and we'd prefer to perform a tentative
+      // parse in order to produce the right diagnostic.
+      return true;
+
     case KNRTypeListContext:
     case MemberContext:
-    case ConditionContext:
     case PrototypeContext:
     case ObjCParameterContext:
     case ObjCResultContext:

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=151137&r1=151136&r2=151137&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Wed Feb 22 00:49:09 2012
@@ -1271,6 +1271,8 @@
 ///       condition:
 ///         expression
 ///         type-specifier-seq declarator '=' assignment-expression
+/// [C++11] type-specifier-seq declarator '=' initializer-clause
+/// [C++11] type-specifier-seq declarator braced-init-list
 /// [GNU]   type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
 ///             '=' assignment-expression
 ///
@@ -1342,17 +1344,34 @@
 
   // '=' assignment-expression
   // If a '==' or '+=' is found, suggest a fixit to '='.
-  if (isTokenEqualOrEqualTypo()) {
+  bool CopyInitialization = isTokenEqualOrEqualTypo();
+  if (CopyInitialization)
     ConsumeToken();
-    ExprResult AssignExpr(ParseAssignmentExpression());
-    if (!AssignExpr.isInvalid()) 
-      Actions.AddInitializerToDecl(DeclOut, AssignExpr.take(), false,
-                                   DS.getTypeSpecType() == DeclSpec::TST_auto);
+
+  ExprResult InitExpr = ExprError();
+  if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) {
+    Diag(Tok.getLocation(),
+         diag::warn_cxx98_compat_generalized_initializer_lists);
+    InitExpr = ParseBraceInitializer();
+  } else if (CopyInitialization) {
+    InitExpr = ParseAssignmentExpression();
+  } else if (Tok.is(tok::l_paren)) {
+    // This was probably an attempt to initialize the variable.
+    SourceLocation LParen = ConsumeParen(), RParen = LParen;
+    if (SkipUntil(tok::r_paren, true, /*DontConsume=*/true))
+      RParen = ConsumeParen();
+    Diag(DeclOut ? DeclOut->getLocation() : LParen,
+         diag::err_expected_init_in_condition_lparen)
+      << SourceRange(LParen, RParen);
   } else {
-    // FIXME: C++0x allows a braced-init-list
-    Diag(Tok, diag::err_expected_equal_after_declarator);
+    Diag(DeclOut ? DeclOut->getLocation() : Tok.getLocation(),
+         diag::err_expected_init_in_condition);
   }
-  
+
+  if (!InitExpr.isInvalid())
+    Actions.AddInitializerToDecl(DeclOut, InitExpr.take(), !CopyInitialization,
+                                 DS.getTypeSpecType() == DeclSpec::TST_auto);
+
   // FIXME: Build a reference to this declaration? Convert it to bool?
   // (This is currently handled by Sema).
 

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp?rev=151137&r1=151136&r2=151137&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3.cpp Wed Feb 22 00:49:09 2012
@@ -13,9 +13,9 @@
   
   auto *b; // expected-error{{declaration of variable 'b' with type 'auto *' requires an initializer}}
 
-  if (auto b) {} // expected-error {{expected '='}}
-  for (;auto b;) {} // expected-error {{expected '='}}
-  while (auto b) {} // expected-error {{expected '='}}
+  if (auto b) {} // expected-error {{must have an initializer}}
+  for (;auto b;) {} // expected-error {{must have an initializer}}
+  while (auto b) {} // expected-error {{must have an initializer}}
   if (auto b = true) { (void)b; }
 }
 

Modified: cfe/trunk/test/Parser/cxx-condition.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-condition.cpp?rev=151137&r1=151136&r2=151137&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx-condition.cpp (original)
+++ cfe/trunk/test/Parser/cxx-condition.cpp Wed Feb 22 00:49:09 2012
@@ -1,11 +1,15 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 
+struct S { S(int); operator bool(); };
+
 void f() {
   int a;
   while (a) ;
-  while (int x) ; // expected-error {{expected '=' after declarator}}
+  while (int x) ; // expected-error {{variable declaration in condition must have an initializer}}
   while (float x = 0) ;
   if (const int x = a) ; // expected-warning{{empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
   switch (int x = a+10) {}
   for (; int x = ++a; ) ;
+
+  if (S a(42)) {} // expected-error {{variable declaration in condition cannot have a parenthesized initializer}}
 }

Added: cfe/trunk/test/Parser/cxx0x-condition.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-condition.cpp?rev=151137&view=auto
==============================================================================
--- cfe/trunk/test/Parser/cxx0x-condition.cpp (added)
+++ cfe/trunk/test/Parser/cxx0x-condition.cpp Wed Feb 22 00:49:09 2012
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+struct S { S(int); operator bool(); };
+
+void f() {
+  int a;
+  typedef int n;
+
+  while (a) ;
+  while (int x) ; // expected-error {{variable declaration in condition must have an initializer}}
+  while (float x = 0) ;
+  if (const int x = a) ; // expected-warning{{empty body}} expected-note{{put the semicolon on a separate line to silence this warning}}
+  switch (int x = a+10) {}
+  for (; int x = ++a; ) ;
+
+  if (S(a)) {} // ok
+  if (S(a) = 0) {} // ok
+  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-error {{unexpected type name 'n': expected expression}}
+
+  if (S b(a)) {} // expected-error {{variable declaration in condition cannot have a parenthesized initializer}}
+
+  if (S b(n)) {} // expected-error {{a function type is not allowed here}} expected-error {{must have an initializer}}
+  if (S b(n) = 0) {} // expected-error {{a function type is not allowed here}}
+  if (S b(n) == 0) {} // expected-error {{a function type is not allowed here}} expected-error {{did you mean '='?}}
+
+  // FIXME: this is legal, and incorrectly rejected, because tentative parsing
+  // does not yet know about braced function-style casts.
+  if (S{a}) {} // unexpected-error{{unqualified-id}}
+
+  if (S a{a}) {} // ok
+  if (S a = {a}) {} // ok
+  if (S a == {a}) {} // expected-error {{did you mean '='?}}
+}

Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp?rev=151137&r1=151136&r2=151137&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-scalars.cpp Wed Feb 22 00:49:09 2012
@@ -15,6 +15,8 @@
     // FIXME: Redundant warnings.
     { const short a{100000}; } // expected-error {{cannot be narrowed}} expected-note {{inserting an explicit cast}} expected-warning {{changes value}}
     { const short a = {100000}; } // expected-error {{cannot be narrowed}} expected-note {{inserting an explicit cast}} expected-warning {{changes value}}
+    { if (const int a{1}) static_assert(a == 1, ""); }
+    { if (const int a = {1}) static_assert(a == 1, ""); }
   }
 
   int direct_usage() {





More information about the cfe-commits mailing list