More property attribute recovery improvements.  Instead of this:

crash.m:8:12: error: type name requires a specifier or qualifier
@property (readonlyx, getter=isAwesome) int _awesome;
           ^
crash.m:8:29: error: expected ';' at end of declaration list
@property (readonlyx, getter=isAwesome) int _awesome;
                            ^
crash.m:8:39: error: expected identifier or '('
@property (readonlyx, getter=isAwesome) int _awesome;
                                      ^

we now get:

crash.m:8:12: error: unknown property attribute 'readonlyx'
@property (readonlyx, getter=isAwesome) int _awesome;
           ^

Also, we can eliminate isObjCPropertyAttribute now.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57811 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 81eacf6..c854400 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -377,7 +377,7 @@
 void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
   SourceLocation LHSLoc = ConsumeParen(); // consume '('
   
-  while (isObjCPropertyAttribute()) {
+  while (1) {
     const IdentifierInfo *II = Tok.getIdentifierInfo();
     // getter/setter require extra treatment.
     if (II == ObjCPropertyAttrs[objc_getter] || 
@@ -393,7 +393,7 @@
             loc = ConsumeToken();  // consume method name
             if (Tok.isNot(tok::colon)) {
               Diag(loc, diag::err_expected_colon);
-              SkipUntil(tok::r_paren,true,true);
+              SkipUntil(tok::r_paren);
               return;
             }
           } else {
@@ -402,13 +402,13 @@
           }
         } else {
           Diag(loc, diag::err_expected_ident);
-          SkipUntil(tok::r_paren,true,true);
+          SkipUntil(tok::r_paren);
           return;
         }
       }
       else {
         Diag(loc, diag::err_objc_expected_equal);    
-        SkipUntil(tok::r_paren,true,true);
+        SkipUntil(tok::r_paren);
         return;
       }
     } else if (II == ObjCPropertyAttrs[objc_readonly])
@@ -423,6 +423,15 @@
       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_copy);
     else if (II == ObjCPropertyAttrs[objc_nonatomic])
       DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nonatomic);
+    else if (II) {
+      Diag(Tok.getLocation(), diag::err_objc_expected_property_attr,
+           II->getName());
+      SkipUntil(tok::r_paren);
+      return;
+    } else {
+      MatchRHSPunctuation(tok::r_paren, LHSLoc);
+      return;
+    }
     
     ConsumeToken(); // consume last attribute token
     if (Tok.is(tok::comma)) {
@@ -550,18 +559,6 @@
   }
 }
 
-///  property-attrlist: one of
-///    readonly getter setter assign retain copy nonatomic
-///
-bool Parser::isObjCPropertyAttribute() {
-  if (Tok.is(tok::identifier)) {
-    const IdentifierInfo *II = Tok.getIdentifierInfo();
-    for (unsigned i = 0; i < objc_NumAttrs; ++i)
-      if (II == ObjCPropertyAttrs[i]) return true;
-  }
-  return false;
-} 
-
 ///  objc-for-collection-in: 'in'
 ///
 bool Parser::isTokIdentifier_in() const {