[PATCH] Suggest fix-it ':' when '=' used in for-range-declaration while initializing an auto

Ismail Pazarbasi ismail.pazarbasi at gmail.com
Mon Apr 14 13:04:42 PDT 2014


Hi dblaikie, bkramer,

I patched this during an evening at ACCU 2014 last week, but seems like I forgot to send it.

This is fix for PR19176:

  int arr[] = {1, 2, 3, 4};
  for (auto i = arr)
    (void)i;

possibly meant:
  for (auto i : arr)

This is going to be issued iff for range declaration begins with auto keyword in C++11 mode.

http://reviews.llvm.org/D3370

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  lib/Parse/ParseStmt.cpp
  test/Parser/cxx0x-for-range.cpp

Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -204,6 +204,8 @@
 def err_expected_semi_after_static_assert : Error<
   "expected ';' after static_assert">;
 def err_expected_semi_for : Error<"expected ';' in 'for' statement specifier">;
+def note_invalid_for_range : Note<
+  "range based for statement requires ':' after range declaration">;
 def warn_missing_selector_name : Warning<
   "%0 used as the name of the previous parameter rather than as part "
   "of the selector">,
Index: lib/Parse/ParseStmt.cpp
===================================================================
--- lib/Parse/ParseStmt.cpp
+++ lib/Parse/ParseStmt.cpp
@@ -1469,8 +1469,16 @@
     if (!C99orCXXorObjC)   // Use of C99-style for loops in C90 mode?
       Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
 
+    const bool RangeInitIsAuto = Tok.is(tok::kw_auto);
     // In C++0x, "for (T NS:a" might not be a typo for ::
-    bool MightBeForRangeStmt = getLangOpts().CPlusPlus;
+    const bool MightBeForRangeStmt = getLangOpts().CPlusPlus;
+    SourceLocation EqualLoc;
+    if (MightBeForRangeStmt && RangeInitIsAuto) {
+      TentativeParsingAction FindEqual(*this);
+      if (SkipUntil(tok::equal, StopAtSemi | StopBeforeMatch))
+        EqualLoc = Tok.getLocation();
+      FindEqual.Revert();
+    }
     ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt);
 
     SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
@@ -1501,6 +1509,9 @@
       Collection = ParseExpression();
     } else {
       Diag(Tok, diag::err_expected_semi_for);
+      if (getLangOpts().CPlusPlus11 && RangeInitIsAuto && EqualLoc.isValid())
+        Diag(EqualLoc, diag::note_invalid_for_range)
+            << FixItHint::CreateReplacement(EqualLoc, ":");
     }
   } else {
     ProhibitAttributes(attrs);
Index: test/Parser/cxx0x-for-range.cpp
===================================================================
--- test/Parser/cxx0x-for-range.cpp
+++ test/Parser/cxx0x-for-range.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: not %clang_cc1 -fsyntax-only -fdiagnostics-parseable-fixits -std=c++11 %s 2>&1 | FileCheck %s
 
 template<typename T, typename U>
 struct pair {};
@@ -28,3 +28,31 @@
 
   return n;
 }
+
+namespace PR19176 {
+struct Vector {
+  struct iterator {
+    int &operator*();
+    iterator &operator++();
+    iterator &operator++(int);
+    bool operator==(const iterator &) const;
+  };
+  iterator begin();
+  iterator end();
+};
+
+void f() {
+  Vector v;
+  int a[] = {1, 2, 3, 4};
+  for (auto foo = a) // expected-error {{expected ';' in 'for' statement specifier}}
+    // expected-note at -1 {{range based for statement requires ':' after range declaration}}
+    // expected-error at -2 {{expected ';' in 'for' statement specifier}}
+    // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:17-[[@LINE-3]]:18}:":"
+    (void)foo;
+  for (auto i = v)  // expected-error {{expected ';' in 'for' statement specifier}}
+    // expected-note at -1 {{range based for statement requires ':' after range declaration}}
+    // expected-error at -2 {{expected ';' in 'for' statement specifier}}
+    // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:15-[[@LINE-3]]:16}:":"
+    (void)i;
+}
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3370.1.patch
Type: text/x-patch
Size: 3376 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140414/d3ac0776/attachment.bin>


More information about the cfe-commits mailing list