]> granicus.if.org Git - clang/commitdiff
PR11297: Provide a better diagnostic for code which contains a
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 20 Dec 2011 22:56:20 +0000 (22:56 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 20 Dec 2011 22:56:20 +0000 (22:56 +0000)
reasonable-looking but ill-formed for-range statement of the form:

  for (expression : expression)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147006 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticParseKinds.td
lib/Parse/ParseStmt.cpp
test/Parser/cxx0x-for-range.cpp [new file with mode: 0644]

index 0f5fb58ac7decab2e36c897f716d8e2a5611efcc..74c4418ce6e5660004b8d8f3d9df2c827a32113f 100644 (file)
@@ -244,6 +244,8 @@ def ext_for_range : ExtWarn<
 def warn_cxx98_compat_for_range : Warning<
   "range-based for loop is incompatible with C++98">,
   InGroup<CXX98Compat>, DefaultIgnore;
+def err_for_range_expected_decl : Error<
+  "for range declaration must declare a variable">;
 def err_argument_required_after_attribute : Error<
   "argument required after attribute">;
 def err_missing_param : Error<"expected parameter declarator">;
index 435bde33753c424cc66419c7097ae3d7efaaa158..13b3bdaf7495efe63022ce1b7204c00794ae07c2 100644 (file)
@@ -1371,6 +1371,14 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) {
         return StmtError();
       }
       Collection = ParseExpression();
+    } else if (getLang().CPlusPlus0x && Tok.is(tok::colon) &&
+               !FirstPart.isInvalid()) {
+      // User tried to write the reasonable, but ill-formed, for-range-statement
+      //   for (expr : expr) { ... }
+      Diag(Tok, diag::err_for_range_expected_decl)
+        << FirstPart.get()->getSourceRange();
+      SkipUntil(tok::r_paren, false, true);
+      SecondPartIsInvalid = true;
     } else {
       if (!Value.isInvalid()) {
         Diag(Tok, diag::err_expected_semi_for);
diff --git a/test/Parser/cxx0x-for-range.cpp b/test/Parser/cxx0x-for-range.cpp
new file mode 100644 (file)
index 0000000..f920ef9
--- /dev/null
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+template<typename T, typename U>
+struct pair {};
+
+template<typename T, typename U>
+struct map {
+  typedef pair<T,U> *iterator;
+  iterator begin();
+  iterator end();
+};
+
+template<typename T, typename U>
+pair<T,U> &tie(T &, U &);
+
+int foo(map<char*,int> &m) {
+  char *p;
+  int n;
+
+  for (pair<char*,int> x : m) {
+    (void)x;
+  }
+
+  for (tie(p, n) : m) { // expected-error {{for range declaration must declare a variable}}
+    (void)p;
+    (void)n;
+  }
+
+  return n;
+}