Fix a couple of bugs, add some new cool stuff.

1. Fix a todo in Parser::ParseTag, to recover better.  On code like
   that in test/Sema/decl-invalid.c it causes us to return a single
   error instead of multiple.
2. Fix an error in Sema::ParseDeclarator, where it would crash if the
   declarator didn't have an identifier.  Instead, diagnose the problem.
3. Start adding infrastructure to track the range of locations covered
   by a declspec or declarator.  This is mostly implemented for declspec,
   but could be improved, it is missing for declarator.

Thanks to Neil for pointing out this crash.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@40482 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp
new file mode 100644
index 0000000..00b606a
--- /dev/null
+++ b/Parse/ParseObjc.cpp
@@ -0,0 +1,105 @@
+//===--- ParseObjc.cpp - Objective C Parsing ------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Steve Naroff and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements the Objective-C portions of the Parser interface.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Parse/Parser.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/SmallVector.h"
+using namespace clang;
+
+
+/// ParseExternalDeclaration:
+///       external-declaration: [C99 6.9]
+/// [OBJC]  objc-class-definition
+/// [OBJC]  objc-class-declaration     [TODO]
+/// [OBJC]  objc-alias-declaration     [TODO]
+/// [OBJC]  objc-protocol-definition   [TODO]
+/// [OBJC]  objc-method-definition     [TODO]
+/// [OBJC]  '@' 'end'                  [TODO]
+void Parser::ParseObjCAtDirectives() {
+  SourceLocation AtLoc = ConsumeToken(); // the "@"
+  
+  IdentifierInfo *II = Tok.getIdentifierInfo();
+  switch (II ? II->getObjCKeywordID() : tok::objc_not_keyword) {
+    case tok::objc_class:
+      return ParseObjCAtClassDeclaration(AtLoc);
+    case tok::objc_interface:
+      return ParseObjCAtInterfaceDeclaration();
+    case tok::objc_protocol:
+      return ParseObjCAtProtocolDeclaration();
+    case tok::objc_implementation:
+      return ParseObjCAtImplementationDeclaration();
+    case tok::objc_end:
+      return ParseObjCAtEndDeclaration();
+    case tok::objc_compatibility_alias:
+      return ParseObjCAtAliasDeclaration();
+    default:
+      Diag(AtLoc, diag::err_unexpected_at);
+      SkipUntil(tok::semi);
+  }
+}
+
+///
+/// objc-class-declaration: 
+///    '@' 'class' identifier-list ';'
+///  
+void Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
+  ConsumeToken(); // the identifier "class"
+  llvm::SmallVector<IdentifierInfo *, 8> ClassNames;
+  
+  while (1) {
+    if (Tok.getKind() != tok::identifier) {
+      Diag(Tok, diag::err_expected_ident);
+      SkipUntil(tok::semi);
+      return;
+    }
+    
+    ClassNames.push_back(Tok.getIdentifierInfo());
+    ConsumeToken();
+    
+    if (Tok.getKind() != tok::comma)
+      break;
+    
+    ConsumeToken();
+  }
+  
+  // Consume the ';'.
+  if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after, "@class"))
+    return;
+  
+  Actions.ParsedObjcClassDeclaration(CurScope,
+                                     &ClassNames[0], ClassNames.size());
+}
+
+void Parser::ParseObjCAtInterfaceDeclaration() {
+  assert(0 && "Unimp");
+}
+void Parser::ParseObjCAtProtocolDeclaration() {
+  assert(0 && "Unimp");
+}
+void Parser::ParseObjCAtImplementationDeclaration() {
+  assert(0 && "Unimp");
+}
+void Parser::ParseObjCAtEndDeclaration() {
+  assert(0 && "Unimp");
+}
+void Parser::ParseObjCAtAliasDeclaration() {
+  assert(0 && "Unimp");
+}
+
+void Parser::ParseObjCInstanceMethodDeclaration() {
+  assert(0 && "Unimp");
+}
+
+void Parser::ParseObjCClassMethodDeclaration() {
+  assert(0 && "Unimp");
+}