This is my first patch. It's targeted at the parser/diagnostics.

The goal of the patch is to anticipate missing commas in initializer lists
and report them appropriately as errors, instead of the current "expected
'}' to match '}'" errors.

In summary, It detects missing commas only when successfully parsing the
next element in the list.

An example input/output pair are also attached for your convenience.

Please inform me of any requested changes.

Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td (revision 301985)
+++ include/clang/Basic/DiagnosticParseKinds.td (working copy)
@@ -164,6 +164,7 @@
 def err_at_defs_cxx : Error<"@defs is not supported in Objective-C++">;
 def err_at_in_class : Error<"unexpected '@' in member specification">;
 def err_unexpected_semi : Error<"unexpected ';' before %0">;
+def err_expected_comma : Error<"expected ',' before initializer">;

 def err_expected_fn_body : Error<
   "expected function body after function declarator">;
Index: include/clang/Parse/RAIIObjectsForParser.h
===================================================================
--- include/clang/Parse/RAIIObjectsForParser.h (revision 301985)
+++ include/clang/Parse/RAIIObjectsForParser.h (working copy)
@@ -440,6 +440,13 @@

       return diagnoseMissingClose();
     }
+
+    bool willClose(){
+      if (P.Tok.is(Close))
+        return false;
+      return true;
+    }
+
     void skipToEnd();
   };

Index: lib/Parse/ParseInit.cpp
===================================================================
--- lib/Parse/ParseInit.cpp (revision 301985)
+++ lib/Parse/ParseInit.cpp (working copy)
@@ -409,6 +409,8 @@
       Actions, EnterExpressionEvaluationContext::InitList);

   bool InitExprsOk = true;
+  bool maybeMissingComma = false;
+  Token startOfNextIni;

   while (1) {
     // Handle Microsoft __if_exists/if_not_exists if necessary.
@@ -427,6 +429,8 @@
     // If we know that this cannot be a designation, just parse the nested
     // initializer directly.
     ExprResult SubElt;
+    startOfNextIni = Tok;
+
     if (MayBeDesignationStart())
       SubElt = ParseInitializerWithPotentialDesignator();
     else
@@ -457,9 +461,25 @@
       }
     }

-    // If we don't have a comma continued list, we're done.
-    if (Tok.isNot(tok::comma)) break;
+    if(maybeMissingComma){
+      //Here we would have checked if InitExprsOk is true,
+      //but it's implied to be ok because of the previous break
+      //Now we know the compilee  very likely forgot the comma
+      Diag(startOfNextIni.getLocation(), diag::err_expected_comma)
+           <<
FixItHint::CreateInsertion(startOfNextIni.getLocation().getLocWithOffset(-1),
",");
+      maybeMissingComma = false;
+    }

+    // If we don't have a comma continued list, we're done (maybe).
+    if (Tok.isNot(tok::comma)){
+      if(!T.willClose()){
+        //This is a ok list, no missing commas.
+        break;
+      }
+      maybeMissingComma = true;
+      continue;
+    }
+
     // TODO: save comma locations if some client cares.
     ConsumeToken();
Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td	(revision 301985)
+++ include/clang/Basic/DiagnosticParseKinds.td	(working copy)
@@ -164,6 +164,7 @@
 def err_at_defs_cxx : Error<"@defs is not supported in Objective-C++">;
 def err_at_in_class : Error<"unexpected '@' in member specification">;
 def err_unexpected_semi : Error<"unexpected ';' before %0">;
+def err_expected_comma : Error<"expected ',' before initializer">;
 
 def err_expected_fn_body : Error<
   "expected function body after function declarator">;
Index: include/clang/Parse/RAIIObjectsForParser.h
===================================================================
--- include/clang/Parse/RAIIObjectsForParser.h	(revision 301985)
+++ include/clang/Parse/RAIIObjectsForParser.h	(working copy)
@@ -440,6 +440,13 @@
       
       return diagnoseMissingClose();
     }
+
+    bool willClose(){
+      if (P.Tok.is(Close))
+        return false;
+      return true;
+    }
+
     void skipToEnd();
   };
 
Index: lib/Parse/ParseInit.cpp
===================================================================
--- lib/Parse/ParseInit.cpp	(revision 301985)
+++ lib/Parse/ParseInit.cpp	(working copy)
@@ -409,6 +409,8 @@
       Actions, EnterExpressionEvaluationContext::InitList);
 
   bool InitExprsOk = true;
+  bool maybeMissingComma = false;
+  Token startOfNextIni;
 
   while (1) {
     // Handle Microsoft __if_exists/if_not_exists if necessary.
@@ -427,6 +429,8 @@
     // If we know that this cannot be a designation, just parse the nested
     // initializer directly.
     ExprResult SubElt;
+    startOfNextIni = Tok;
+
     if (MayBeDesignationStart())
       SubElt = ParseInitializerWithPotentialDesignator();
     else
@@ -457,9 +461,25 @@
       }
     }
 
-    // If we don't have a comma continued list, we're done.
-    if (Tok.isNot(tok::comma)) break;
+    if(maybeMissingComma){
+      //Here we would have checked if InitExprsOk is true,
+      //but it's implied to be ok because of the previous break
+      //Now we know the compilee  very likely forgot the comma
+      Diag(startOfNextIni.getLocation(), diag::err_expected_comma)
+           << FixItHint::CreateInsertion(startOfNextIni.getLocation().getLocWithOffset(-1), ",");
+      maybeMissingComma = false;
+    }
 
+    // If we don't have a comma continued list, we're done (maybe).
+    if (Tok.isNot(tok::comma)){
+      if(!T.willClose()){
+        //This is a ok list, no missing commas.
+        break;
+      }
+      maybeMissingComma = true;
+      continue;
+    }
+
     // TODO: save comma locations if some client cares.
     ConsumeToken();
 
int g(){
    return 0;
}

int main(){
    int a[] = {1 22222 33333, 4};
    int b[] = {g() g()};
    int c[3][3] = { {1 2 3},  {1,2 3} {1, 2, 3} };
    int d[] = {1,2,3};
}

Attachment: missingCommasDiag.out
Description: Binary data

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to