]> granicus.if.org Git - clang/commitdiff
refactor a bunch of code:
authorChris Lattner <sabre@nondot.org>
Mon, 20 Oct 2008 06:10:06 +0000 (06:10 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 20 Oct 2008 06:10:06 +0000 (06:10 +0000)
Check for @end in ParseObjCInterfaceDeclList instead of in each caller
Handle @required and @optional with the same code

Add some fixmes about some apparently objc2 code that is being accepted
in objc1.

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

include/clang/Basic/DiagnosticKinds.def
lib/Parse/ParseObjc.cpp
test/SemaObjC/protocol-test-1.m

index f409df465b1bc9699bf59caf04c755a99d5c7830..3ec005855570e90c51caa86a3862ae025b848892 100644 (file)
@@ -430,10 +430,8 @@ DIAG(warn_objc_property_default_assign_on_object, WARNING,
      "default property attribute 'assign' not appropriate for non-gc object")
 DIAG(err_objc_property_requires_object, ERROR,
      "property with '%0' attribute must be of object type")
-DIAG(err_objc_protocol_required, ERROR,
-     "@required may be specified in protocols only")
-DIAG(err_objc_protocol_optional, ERROR,
-     "@optional may be specified in protocols only")
+DIAG(err_objc_directive_only_in_protocol, ERROR,
+     "directive may only be specified in protocols only")
 DIAG(err_missing_catch_finally, ERROR,
      "@try statement without a @catch and @finally clause")
 DIAG(err_objc_concat_string, ERROR,
index 52d52bde7e3df381368ce7fc02e30f9b10982106..6369817ad5467b40cb45612fdb6d8ee8fa8abf9c 100644 (file)
@@ -163,14 +163,7 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
                                      EndProtoLoc);
     
     ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword);
-
-    // The @ sign was already consumed by ParseObjCInterfaceDeclList().
-    if (Tok.isObjCAtKeyword(tok::objc_end)) {
-      ConsumeToken(); // the "end" identifier
-      return CategoryType;
-    }
-    Diag(Tok, diag::err_objc_missing_end);
-    return 0;
+    return CategoryType;
   }
   // Parse a class interface.
   IdentifierInfo *superClassId = 0;
@@ -202,14 +195,7 @@ Parser::DeclTy *Parser::ParseObjCAtInterfaceDeclaration(
     ParseObjCClassInstanceVariables(ClsType, atLoc);
 
   ParseObjCInterfaceDeclList(ClsType, tok::objc_interface);
-
-  // The @ sign was already consumed by ParseObjCInterfaceDeclList().
-  if (Tok.isObjCAtKeyword(tok::objc_end)) {
-    ConsumeToken(); // the "end" identifier
-    return ClsType;
-  }
-  Diag(Tok, diag::err_objc_missing_end);
-  return 0;
+  return ClsType;
 }
 
 /// constructSetterName - Return the setter name for the given
@@ -246,8 +232,9 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
   llvm::SmallVector<DeclTy*, 32> allMethods;
   llvm::SmallVector<DeclTy*, 16> allProperties;
   tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;
-  SourceLocation AtEndLoc;
   
+  SourceLocation AtEndLoc;
+
   while (1) {
     // If this is a method prototype, parse it.
     if (Tok.is(tok::minus) || Tok.is(tok::plus)) {
@@ -266,8 +253,7 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
       continue;
     }
     
-    // If we got to the end of the file, pretend that we saw an @end.
-    // FIXME: Should this be a warning?
+    // If we got to the end of the file, exit the loop.
     if (Tok.is(tok::eof))
       break;
     
@@ -286,37 +272,34 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
     if (DirectiveKind == tok::objc_end) { // @end -> terminate list
       AtEndLoc = AtLoc;
       break;
-    } 
+    }
     
+    // Eat the identifier.
+    ConsumeToken();
+
     switch (DirectiveKind) {
     default:
+      // FIXME: If someone forgets an @end on a protocol, this loop will
+      // continue to eat up tons of stuff and spew lots of nonsense errors.  It
+      // would probably be better to bail out if we saw an @class or @interface
+      // or something like that.
       Diag(Tok, diag::err_objc_illegal_interface_qual);
-      ConsumeToken();
-      // Skip until we see an @ or } or ;
+      // Skip until we see an '@' or '}' or ';'.
       SkipUntil(tok::r_brace, tok::at);
       break;
       
     case tok::objc_required:
-      ConsumeToken();
-      // This is only valid on protocols.
-      if (contextKey != tok::objc_protocol)
-        Diag(AtLoc, diag::err_objc_protocol_required);
-      else
-        MethodImplKind = tok::objc_required;
-      break;
-        
     case tok::objc_optional:
-      ConsumeToken();
       // This is only valid on protocols.
+      // FIXME: Should this check for ObjC2 being enabled?
       if (contextKey != tok::objc_protocol)
-        Diag(AtLoc, diag::err_objc_protocol_optional);
+        Diag(AtLoc, diag::err_objc_directive_only_in_protocol);
       else
-        MethodImplKind = tok::objc_optional;
+        MethodImplKind = DirectiveKind;
       break;
         
     case tok::objc_property:
       ObjCDeclSpec OCDS;
-      ConsumeToken(); // the "property" identifier
       // Parse property attribute list, if any. 
       if (Tok.is(tok::l_paren)) {
         // property has attribute list.
@@ -356,9 +339,16 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
       break;
     }
   }
+
+  // We break out of the big loop in two cases: when we see @end or when we see
+  // EOF.  In the former case, eat the @end.  In the later case, emit an error.
+  if (Tok.isObjCAtKeyword(tok::objc_end))
+    ConsumeToken(); // the "end" identifier
+  else
+    Diag(Tok, diag::err_objc_missing_end);
+  
   // Insert collected methods declarations into the @interface object.
-  // FIXME: This passes in an invalid SourceLocation for AtEndLoc when EOF is
-  // hit.
+  // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
   Actions.ActOnAtEnd(AtEndLoc, interfaceDecl,
                      allMethods.empty() ? 0 : &allMethods[0],
                      allMethods.size(), 
@@ -1006,14 +996,7 @@ Parser::DeclTy *Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
                                         &ProtocolRefs[0], ProtocolRefs.size(),
                                         EndProtoLoc, attrList);
   ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol);
-
-  // The @ sign was already consumed by ParseObjCInterfaceDeclList().
-  if (Tok.isObjCAtKeyword(tok::objc_end)) {
-    ConsumeToken(); // the "end" identifier
-    return ProtoType;
-  }
-  Diag(Tok, diag::err_objc_missing_end);
-  return 0;
+  return ProtoType;
 }
 
 ///   objc-implementation:
index 6fb28b533cf7721f7dff8179e05b3cfb5188ee79..c8e4080c5e3b41bf7d447552169ad8c8d8d6a4bf 100644 (file)
@@ -9,11 +9,11 @@
 @end
 
 @interface INTF1
-@required  // expected-error {{@required may be specified in protocols only}}
+@required  // expected-error {{directive may only be specified in protocols only}}
 - (int) FooBar;
 - (int) FooBar1;
 - (int) FooBar2;
-@optional  // expected-error {{@optional may be specified in protocols only}}
+@optional  // expected-error {{directive may only be specified in protocols only}}
 + (int) C;
 
 - (int)I;