Objective-C [qoi] more gracefull recovery when
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 20 Mar 2013 18:09:33 +0000 (18:09 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 20 Mar 2013 18:09:33 +0000 (18:09 +0000)
'}' is missing for the ivar declarations.
// rdar://6854840

llvm-svn: 177549

clang/include/clang/Parse/Parser.h
clang/lib/Parse/ParseObjc.cpp
clang/test/Parser/missing-closing-rbrace.m

index d8220b3..5205105 100644 (file)
@@ -1115,6 +1115,10 @@ private:
   DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc);
   Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
                                         ParsedAttributes &prefixAttrs);
+  void HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc,
+                                        BalancedDelimiterTracker &T,
+                                        SmallVectorImpl<Decl *> &AllIvarDecls,
+                                        bool RBraceMissing);
   void ParseObjCClassInstanceVariables(Decl *interfaceDecl,
                                        tok::ObjCKeywordKind visibility,
                                        SourceLocation atLoc);
index b95b41f..badbee2 100644 (file)
@@ -1228,6 +1228,22 @@ bool Parser::ParseObjCProtocolQualifiers(DeclSpec &DS) {
   return Result;
 }
 
+void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc,
+                                 BalancedDelimiterTracker &T,
+                                 SmallVectorImpl<Decl *> &AllIvarDecls,
+                                 bool RBraceMissing) {
+  if (!RBraceMissing)
+    T.consumeClose();
+  
+  Actions.ActOnObjCContainerStartDefinition(interfaceDecl);
+  Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls);
+  Actions.ActOnObjCContainerFinishDefinition();
+  // Call ActOnFields() even if we don't have any decls. This is useful
+  // for code rewriting tools that need to be aware of the empty list.
+  Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl,
+                      AllIvarDecls,
+                      T.getOpenLocation(), T.getCloseLocation(), 0);
+}
 
 ///   objc-class-instance-variables:
 ///     '{' objc-instance-variable-decl-list[opt] '}'
@@ -1260,7 +1276,6 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
 
   BalancedDelimiterTracker T(*this, tok::l_brace);
   T.consumeOpen();
-
   // While we still have something to read, read the instance variables.
   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
     // Each iteration of this loop reads one objc-instance-variable-decl.
@@ -1288,13 +1303,17 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
         visibility = Tok.getObjCKeywordID();
         ConsumeToken();
         continue;
-      case tok::objc_end:
-        Diag(Tok, diag::err_objc_unexpected_atend);
-        ConsumeToken();
-        continue;
       default:
-        Diag(Tok, diag::err_objc_illegal_visibility_spec);
-        continue;
+        Diag(Tok, (Tok.getObjCKeywordID() == tok::objc_end) ?
+             diag::err_objc_unexpected_atend :
+             diag::err_objc_illegal_visibility_spec);
+        Tok.setLocation(Tok.getLocation().getLocWithOffset(-1));
+        Tok.setKind(tok::at);
+        Tok.setLength(1);
+        PP.EnterToken(Tok);
+        HelperActionsForIvarDeclarations(interfaceDecl, atLoc,
+                                         T, AllIvarDecls, true);
+        return;
       }
     }
 
@@ -1341,16 +1360,8 @@ void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
       SkipUntil(tok::r_brace, true, true);
     }
   }
-  T.consumeClose();
-
-  Actions.ActOnObjCContainerStartDefinition(interfaceDecl);
-  Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls);
-  Actions.ActOnObjCContainerFinishDefinition();
-  // Call ActOnFields() even if we don't have any decls. This is useful
-  // for code rewriting tools that need to be aware of the empty list.
-  Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl,
-                      AllIvarDecls,
-                      T.getOpenLocation(), T.getCloseLocation(), 0);
+  HelperActionsForIvarDeclarations(interfaceDecl, atLoc,
+                                   T, AllIvarDecls, false);
   return;
 }
 
index ae1291e..89c1f18 100644 (file)
@@ -1,6 +1,12 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
 // rdar: //6854840
-@interface A {@end // expected-error {{'@end' appears where closing brace '}' is expected}}\
-                   // expected-note {{to match this '{'}}\
-                   // expected-note {{class started here}}
-                  // expected-error {{expected '}'}} expected-error {{missing '@end'}}
+@interface A {@end // expected-error {{'@end' appears where closing brace '}' is expected}}
+
+
+@interface B {
+@public
+  int ivar;
+@protected
+  id pp;
+@property (copy) id PROP; // expected-error {{illegal visibility specification}}
+@end